# Copyright (c) Facebook, Inc. and its affiliates.
#
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.
import logging
from asyncio.log import logger
logger = logging.getLogger(__name__)
import math
from typing import Dict, List, Optional
from collections import OrderedDict
import torch
import torch.nn as nn
from torch import Tensor
from fairseq import utils
from fairseq.distributed import fsdp_wrap
from fairseq.models import FairseqEncoder
from fairseq.modules.checkpoint_activations import checkpoint_wrapper
from fairseq.modules.quant_noise import quant_noise as apply_quant_noise_
from fairseq.models.contrastive_model.embeding import PositionEmbeddingSine, BoxRelationalEmbedding
from fairseq.modules import (
    FairseqDropout,
    LayerDropModuleList,
    LayerNorm,
    PositionalEmbedding,
    SinusoidalPositionalEmbedding,
    transformer_layer,
)
from fairseq.modules import PositionalEmbedding

class Bottleneck(nn.Module):
    expansion = 4

    def __init__(self, inplanes, planes, stride=1, downsample=None):
        super(Bottleneck, self).__init__()
        self.conv1 = nn.Conv2d(inplanes, planes, kernel_size=1, bias=False)
        self.bn1 = nn.BatchNorm2d(planes)
        self.conv2 = nn.Conv2d(planes, planes, kernel_size=3, stride=stride,
                            padding=1, bias=False)
        self.bn2 = nn.BatchNorm2d(planes)
        self.conv3 = nn.Conv2d(planes, planes * 4, kernel_size=1, bias=False)
        self.bn3 = nn.BatchNorm2d(planes * 4)
        self.relu = nn.ReLU(inplace=True)
        self.downsample = downsample
        self.stride = stride

    def forward(self,x):
        residual = x

        out = self.conv1(x)
        out = self.bn1(out)
        out = self.relu(out)

        out = self.conv2(out)
        out = self.bn2(out)
        out = self.relu(out)

        out = self.conv3(out)
        out = self.bn3(out)

        if self.downsample is not None:
            residual = self.downsample(x)

        out += residual
        out = self.relu(out)

        return out
class CnnEncoderBase(FairseqEncoder):
    """
    Transformer encoder consisting of *cfg.encoder.layers* layers. Each layer
    is a :class:`TransformerEncoderLayer`.

    Args:
        args (argparse.Namespace): parsed command-line arguments
        dictionary (~fairseq.data.Dictionary): encoding dictionary
        embed_tokens (torch.nn.Embedding): input embedding
    """

    def __init__(self, cfg, dictionary, layers):
        self.cfg = cfg
        super().__init__(dictionary)
        self.register_buffer("version", torch.Tensor([3]))
        self.max_source_positions = cfg.max_source_positions
        self.inplanes = 64
        self.conv1 = nn.Conv2d(3, self.inplanes, kernel_size=7, stride=2, padding=3,
                            bias=False)
        self.bn1 = nn.BatchNorm2d(self.inplanes)
        self.relu = nn.ReLU(inplace=True)
        self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, padding=1)
        self.layer1 = self._make_layer(Bottleneck, 64, layers[0])
        self.layer2 = self._make_layer(Bottleneck, 128, layers[1], stride=2)
        self.layer3 = self._make_layer(Bottleneck, 256, layers[2], stride=2)
        self.layer4 = self._make_layer(Bottleneck, 512, layers[3], stride=2)
        # self.avgpool = nn.AvgPool2d(1, stride=1)
        self.avgpool = nn.AvgPool2d(2, stride=2)
        self.linear = nn.Linear(2048,256)
        self.encoder_layerdrop = cfg.encoder.layerdrop

        # self.grid_embedding = PositionEmbeddingSine(cfg.decoder.embed_dim // 2, normalize=True)
        if self.encoder_layerdrop > 0.0:
            self.layers = LayerDropModuleList(p=self.encoder_layerdrop)
        else:
            self.layers = nn.ModuleList([])
        self.layers.extend(
            [self.build_encoder_layer(cfg) for i in range(cfg.encoder.layers)]
        )

        # self.embed_positions = (
        #     PositionalEmbedding(
        #         cfg.max_source_positions,
        #         2048,
        #         0,
        #         learned=cfg.encoder.learned_pos,
        #     )
        # )
        self.embed_positions = None

        for m in self.modules():
            if isinstance(m, nn.Conv2d):
                # n = m.kernel_size[0] * m.kernel_size[1] * m.out_channels
                # m.weight.data.normal_(0, math.sqrt(2. / n))
                torch.nn.init.xavier_normal_(m.weight, gain=1)
            elif isinstance(m, nn.BatchNorm2d):
                m.weight.data.fill_(1)
                m.bias.data.zero_()
                # print(self.training)
        # self.dnn = DnCNN()

        # self.craft = CRAFT()#检测网络
        # if self.training:#如果是训练，就加载预训练模型
        #     self.craft.load_state_dict(copyStateDict(torch.load(cfg.pre_model_path, map_location='cuda')))

    def _make_layer(self, block, planes, blocks, stride=1):
        downsample = None
        if stride != 1 or self.inplanes != planes * block.expansion:
            downsample = nn.Sequential(
                nn.Conv2d(self.inplanes, planes * block.expansion,
                        kernel_size=1, stride=stride, bias=False),
                nn.BatchNorm2d(planes * block.expansion),
            )

        layers = []
        layers.append(block(self.inplanes, planes, stride, downsample))
        self.inplanes = planes * block.expansion
        for i in range(1, blocks):
            layers.append(block(self.inplanes, planes))

        return nn.Sequential(*layers)

    def get_pos_embedding(self, grids):
        bs = grids.shape[0]
        grid_embed = self.grid_embedding(grids)#这里不需要reshape，因为我们的cnn已经处理好格式了
        return grid_embed

    def forward(
        self,
        img_source,
        src_token = None,
        src_lengths = None,
    ):
        return self.forward_scriptable(img_source)

    # TorchScript doesn't support super() method so that the scriptable Subclass
    # can't access the base class model in Torchscript.
    # Current workaround is to add a helper function with different name and
    # call the helper function from scriptable Subclass.
    def forward_scriptable(self, img_source):
        # print('https://github.com/Yang-Liu1082/FDN.git',self.inplanes)
        img_source = img_source.permute(0,3,1,2)
        # res_img = img_source - img_mask_source#已有图片减去背景图片
        # x = self.dnn(res_img)
        # res_x = x

        # polys_list = get_boxes(self.craft,img_source)
        # batch_img_tensor_list,batch_img_white_tensor_list = batch_process_box(polys_list,img_source,img_white_source)
        # batch_img_tensor_list = shared_dnn(batch_img_tensor_list,self.dnn)

        #Resnet101
        x = self.conv1(img_source) # B x C x H x W
        x = self.bn1(x)
        x = self.relu(x)
        x = self.maxpool(x)
        x = self.layer1(x)
        x = self.layer2(x)
        x = self.layer3(x)
        x = self.layer4(x)

        x = self.avgpool(x) # (B, C, H, W)

        #变形
        bz, channel, height, width = x.shape
        time_step = height * width
        x = x.view(bz, channel, time_step).permute(2,0,1).contiguous() # T x B x C
        x = self.linear(x)
        src_lengths = torch.ones(bz, device=x.device) * time_step
        padding_mask = torch.zeros((bz, time_step), device=x.device)

        #transformer
        for layer in self.layers:
            lr = layer(
                x,None
            )

            if isinstance(lr, tuple) and len(lr) == 2:
                x, fc_result = lr
            else:
                x = lr
                fc_result = None

        # dummy_tokens = torch.ones((bz, time_step), device=img_source.device).int()
        # pos_embed = self.embed_positions(dummy_tokens).transpose(0,1).contiguous() # T x B x C
        # x = x #+ pos_embed
        return {
            "encoder_out": [x],  # T x B x C
            "encoder_padding_mask": [padding_mask],  # B x T
            "src_lengths": [src_lengths], # B
        }

    def build_encoder_layer(self, cfg):
        layer = transformer_layer.TransformerEncoderLayerBase(
            cfg, return_fc=False
        )
        checkpoint = cfg.checkpoint_activations
        if checkpoint:
            offload_to_cpu = cfg.offload_activations
            layer = checkpoint_wrapper(layer, offload_to_cpu=offload_to_cpu)
        # if we are checkpointing, enforce that FSDP always wraps the
        # checkpointed layer, regardless of layer size
        min_params_to_wrap = cfg.min_params_to_wrap if not checkpoint else 0
        layer = fsdp_wrap(layer, min_num_params=min_params_to_wrap)
        return layer

    @torch.jit.export
    def reorder_encoder_out(self, encoder_out: Dict[str, List[Tensor]], new_order):
        """
        Reorder encoder output according to *new_order*.

        Args:
            encoder_out: output from the ``forward()`` method
            new_order (LongTensor): desired order

        Returns:
            *encoder_out* rearranged according to *new_order*
        """
        if len(encoder_out["encoder_out"]) == 0:
            new_encoder_out = []
        else:
            new_encoder_out = [encoder_out["encoder_out"][0].index_select(1, new_order)]

        if len(encoder_out["src_lengths"]) == 0:
            src_lengths = []
        else:
            src_lengths = [(encoder_out["src_lengths"][0]).index_select(0, new_order)]

        if len(encoder_out["encoder_padding_mask"]) == 0:
            new_padding_mask = []
        else:
            new_padding_mask = [(encoder_out["encoder_padding_mask"][0]).index_select(0, new_order)]

        return {
            "encoder_out": new_encoder_out,  # T x B x C
            "encoder_padding_mask": new_padding_mask,
            "src_lengths": src_lengths,  # B x 1
        }

    @torch.jit.export
    def _reorder_encoder_out(self, encoder_out: Dict[str, List[Tensor]], new_order):
        """Dummy re-order function for beamable enc-dec attention"""
        return encoder_out

    def max_positions(self):
        """Maximum input length supported by the encoder."""
        if self.embed_positions is None:
            return self.max_source_positions
        return min(self.max_source_positions, self.embed_positions.max_positions)

    def upgrade_state_dict_named(self, state_dict, name):
        pass

def copyStateDict(state_dict):
    if list(state_dict.keys())[0].startswith("module"):
        start_idx = 1
    else:
        start_idx = 0
    new_state_dict = OrderedDict()
    for k, v in state_dict.items():
        name = ".".join(k.split(".")[start_idx:])
        new_state_dict[name] = v
    return new_state_dict


def format_name(f_name,l_name):
    """This function is used to join first and last name and
    return in title case"""
    if f_name == "" or l_name == "":
        return "You didn't provide the inputs"
    formated_fname =f_name.title()
    formated_lname = l_name.title()
    return f"{formated_fname} {formated_lname}"

f_name = input("Enter you first name:")
l_name = input("Enter you last name:")
final_output = format_name(f_name,l_name)
print(final_output)


v1 = int(input('Primeiro valor: '))
v2 = int(input('Segundo valor: '))
v3 = int(input('Terceiro valor: '))

list = [v1, v2, v3]

max = max(list)
print(f'O Maior valor é: {max}')

min = min(list)
print(f'O menor vaor é: {min}')


import unittest

import numpy as np

from ms_peak_picker import FittedPeak
from brainpy._c.isotopic_distribution import TheoreticalPeak as Peak

from ms_deisotope.scoring import (
        PenalizedMSDeconVFitter, MSDeconVFitter, DotProductFitter, ScaledGTestFitter,
        GTestFitter, LeastSquaresFitter)

experimental = [
    FittedPeak(mz=739.920, intensity=8356.829, signal_to_noise=100.000,
               peak_count=30, index=30588, full_width_at_half_max=0.050, area=425.445),
    FittedPeak(mz=740.255, intensity=8006.456, signal_to_noise=100.000,
               peak_count=31, index=30622, full_width_at_half_max=0.051, area=416.640),
    FittedPeak(mz=740.589, intensity=4970.605, signal_to_noise=100.000,
               peak_count=32, index=30655, full_width_at_half_max=0.050, area=253.103),
    FittedPeak(mz=740.923, intensity=2215.961, signal_to_noise=100.000,
               peak_count=33, index=30688, full_width_at_half_max=0.051, area=118.020)
]

theoretical = [
    Peak(mz=739.920306, intensity=8310.933747, charge=-3),
    Peak(mz=740.254733, intensity=8061.025466, charge=-3),
    Peak(mz=740.588994, intensity=4926.998052, charge=-3),
    Peak(mz=740.923235, intensity=2250.893651, charge=-3)
]

class IsotopicFitScoringTests(unittest.TestCase):

    def test_penalized_msdeconv(self):
        scorer = PenalizedMSDeconVFitter(20, 2.0)
        # score = scorer.evaluate(None, experimental, theoretical)
        scores = [scorer.evaluate(None, experimental, theoretical) for i in range(10)]
        score = scores[0]
        assert all([np.isclose(s, score) for s in scores[1:]]), scores
        self.assertAlmostEqual(score, 293.47483621051316, 3)
        score = scorer(None, experimental, theoretical)
        self.assertAlmostEqual(score, 293.47483621051316, 3)

    def test_msdeconv(self):
        scorer = MSDeconVFitter()
        score = scorer.evaluate(None, experimental, theoretical)
        self.assertAlmostEqual(score, 293.5135479544602, 3)
        score = scorer(None, experimental, theoretical)
        self.assertAlmostEqual(score, 293.5135479544602, 3)

    def test_dotproduct(self):
        scorer = DotProductFitter()
        score = scorer.evaluate(None, experimental, theoretical)
        self.assertAlmostEqual(score, 163471351.56044182, 3)
        score = scorer(None, experimental, theoretical)
        self.assertAlmostEqual(score, 163471351.56044182, 3)

    def test_scaled_g_test(self):
        scorer = ScaledGTestFitter()
        score = scorer.evaluate(None, experimental, theoretical)
        self.assertAlmostEqual(score, 6.59454124295588e-05, 3)
        score = scorer(None, experimental, theoretical)
        self.assertAlmostEqual(score, 6.59454124295588e-05, 3)

    def test_g_test(self):
        scorer = GTestFitter()
        score = scorer.evaluate(None, experimental, theoretical)
        self.assertAlmostEqual(score, 1.5531726368555354, 3)
        score = scorer(None, experimental, theoretical)
        self.assertAlmostEqual(score, 1.5531726368555354, 3)

    def test_least_squares(self):
        scorer = LeastSquaresFitter()
        score = scorer.evaluate(None, experimental, theoretical)
        self.assertAlmostEqual(score, 7.463484119741042e-05, 3)
        score = scorer(None, experimental, theoretical)
        self.assertAlmostEqual(score, 7.463484119741042e-05, 3)

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


#!/usr/bin/env python

from setuptools import setup, find_packages

with open('README.md') as f:
    long_description = f.read()

setup(
    name='harvest_api_client',
    version='1.1.3',
    description='A client for the Harvest API (getharvest.com)',
    license='MIT',
    author='Alex Maslakov',
    author_email='Alex Maslakov<me@gildedhonour.com>, Alex Maslakov<gilded.honour@gmail.com>',
    url='https://github.com/GildedHonour/harvest-api-client',
    packages=['harvest_api_client'],
    long_description=long_description,
    keywords = ['harvest-api', 'api', 'harvest.com', 'getharvest.com', 'harvest', 'api client'],
    classifiers = [
        'Development Status :: 5 - Production/Stable',
        'Intended Audience :: Developers',
        'Topic :: Software Development :: Libraries',
        'Topic :: Internet :: WWW/HTTP :: Site Management',
        'Topic :: Utilities',
        'License :: OSI Approved :: MIT License',
        'Programming Language :: Python :: 3.4',
    ],
)


from konlpy.tag import Komoran
import pandas as pd

k = Komoran()

df = pd.read_csv('articles.tsv', sep='\t')

nouns = k.nouns(df.iloc[123860, 0])

words = [word for word in nouns if len(word) > 1]

print(words)

texts = df.iloc[123860, 0].split(' ')
from krwordrank.word import summarize_with_keywords

stopwords = {'기자'}
keywords = summarize_with_keywords(texts, min_count=3, max_length=12,
                                   beta=0.85, max_iter=10, stopwords=stopwords, verbose=True)
print(keywords)


"""empty message

Revision ID: 93bc89d93405
Revises: 0b447827b2dc
Create Date: 2020-02-27 18:51:30.129522

"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import postgresql

# revision identifiers, used by Alembic.
revision = '93bc89d93405'
down_revision = '0b447827b2dc'
branch_labels = None
depends_on = None

def upgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.add_column('Artist', sa.Column('genres', sa.ARRAY(sa.String()), nullable=True))
    op.drop_column('Artist', 'genress')
    # ### end Alembic commands ###

def downgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.add_column('Artist', sa.Column('genress', postgresql.ARRAY(sa.VARCHAR()), autoincrement=False, nullable=True))
    op.drop_column('Artist', 'genres')
    # ### end Alembic commands ###


import pandas as pd
from Bio import SeqIO, pairwise2
from Bio.Align import substitution_matrices
from tqdm import tqdm
import logging

blosum62 = substitution_matrices.load("BLOSUM62")

def get_gene_name(seq_id, lookup=None):
    if lookup is None:
        return seq_id.split(":")[0]
    return lookup[seq_id.split(":")[0]]

def p_identity(alignemnt):
    n = len(alignemnt.seqA)
    return sum([alignemnt.seqA[i] == alignemnt.seqB[i] for i in range(n)]) / n

if __name__ == "__main__":
    try:
        snakemake
    except NameError:
        snakemake = None
    if snakemake is not None:
        motif_df = pd.read_csv(snakemake.input["motif_table"])
        reference_dbds = SeqIO.parse(snakemake.input["ensembl_fa"], "fasta")
        records = SeqIO.parse(snakemake.input["tf_fa"], "fasta")
        lookup = (
            pd.read_csv(snakemake.input["id2name"])
            .set_index("gene_id")
            .to_dict()["name"]
        )
        logging.basicConfig(filename=snakemake.log[0], level=logging.WARNING)
        query_dbds = {}
        for each in records:
            gene = get_gene_name(each.id, lookup)
            if gene not in query_dbds:
                query_dbds[gene] = [each]
            else:
                query_dbds[gene].append(each)
        reference_ids = []
        motif_ids = []
        query_ids = []
        percent_identities = []
        missed_genes = []
        for dbd in tqdm(reference_dbds):
            ensembl_id = get_gene_name(dbd.id)
            possible_motifs = motif_df.query("gene_id == @ensembl_id")
            related_motifs = possible_motifs.motif.values.tolist()
            unique_genes = possible_motifs.gene.unique()
            for ref_gene in unique_genes:
                try:
                    to_query = query_dbds[ref_gene]
                except KeyError:
                    to_query = []
                    missed_genes.append(ref_gene)

                for query_seq in to_query:
                    # default blast parameters
                    try:
                        alignment = pairwise2.align.globalds(
                            dbd.seq, query_seq.seq, blosum62, -11, -1
                        )
                    except SystemError:
                        continue
                    if len(alignment) > 0:
                        reference_ids += [dbd.id] * len(related_motifs)
                        motif_ids += related_motifs
                        query_ids += [query_seq.id] * len(related_motifs)
                        percent_identities += [p_identity(alignment[0])] * len(
                            related_motifs
                        )

        pd.DataFrame(
            {
                "ensembl_dbd": reference_ids,
                "motif_id": motif_ids,
                "query_dbd": query_ids,
                "pident": percent_identities,
            }
        ).assign(
            gene_id=lambda df_: [x.split(":")[0] for x in df_.ensembl_dbd],
            query_id=lambda df_: [x.split(":")[0] for x in df_.query_dbd],
        ).to_csv(
            snakemake.output["csv"]
        )
        logging.warning("Missed Sequences: %s", ", ".join(set(missed_genes)))


#사용자로부터 두 개의 정수를 입력받아서 둘중에서 큰수를 출력하는 프로그램
a = int(input("a입력 : "))
b = int(input("b입력 : "))

answer = 0
if a > b:
    answer = a
    print("a가 더큽니다")
else:
    answer = b
    print("b가 더큽니다")


import argparse
parser = argparse.ArgumentParser(prog='map2gtexv8.py', description='''
    Map variant to SNP ID system given in the lookup table
    (by position and filter out ones with confilct reference/alternative alleles)
    It will report the number of :
      1. exact map;
      2. filpped strand;
      3. filpped ref/alt;
      4. filpped strand and ref/alt
    CAUTION: it only works for SNV but NOT indel!
''')
parser.add_argument('--input', help='''
    input variant list (it should have header!)
''')
parser.add_argument('--chr_col', type = int, help='''
    column index of chromosome (start from 1) in --input
''')
parser.add_argument('--pos_col', type = int, help='''
    column index of position (start from 1) in --input
''')
parser.add_argument('--ref_col', type = int, help='''
    column index of reference allele (start from 1) in --input
''')
parser.add_argument('--alt_col', type = int, help='''
    column index of alternative allele (start from 1) in --input
''')
parser.add_argument('--effect_col', type = str, help='''
    column index of effect (start from 1) in --input which may need to flip the sign.
    separated by ','
''')
parser.add_argument('--lookup_table', help='''
    SNP system lookup table,
    It will be interpreted as by chromosome
    if it used something like path/chr@.gz
''')
parser.add_argument('--lookup_chr_col', type = int, help='''
    column index of chromosome (start from 1) in --lookup_table
''')
parser.add_argument('--lookup_pos_col', type = int, help='''
    column index of position (start from 1) in --lookup_table
''')
parser.add_argument('--lookup_ref_col', type = int, help='''
    column index of reference allele (start from 1) in --lookup_table
''')
parser.add_argument('--lookup_alt_col', type = int, help='''
    column index of alternative allele (start from 1) in --lookup_table
''')
parser.add_argument('--lookup_snpid_col', type = int, help='''
    column index of SNP ID (start from 1) in --lookup_table
''')
parser.add_argument('--out_txtgz', help='''
    output txt.gz file name
''')
parser.add_argument('--include_ambiguious', action = 'store_true', help='''
    output txt.gz file name
''')
args = parser.parse_args()

import gzip
from lib import ref_alt_to_code
from lib import my_read
from lib import read_in_file_name_allowing_by_chromosome

import gzip

# first go through lookup table and get save position info for each snp with ref/alt info (see ref_alt_to_code in lib.py for detail)

var_dic = {}

for lookup_file in read_in_file_name_allowing_by_chromosome(args.lookup_table):
    with my_read(lookup_file) as f:
        next(f)
        for i in f:
            i = i.strip().split('\t')
            chr = i[args.lookup_chr_col - 1]
            start = i[args.lookup_pos_col - 1]
            ref = i[args.lookup_ref_col - 1]
            alt = i[args.lookup_alt_col - 1]
            if len(ref) > 1 or len(alt) > 1:
                continue
            ref_alt_code = ref_alt_to_code(ref, alt)
            v = '*'.join([chr, start, str(ref_alt_code)])
            # print(ref_alt_code, ref, alt)
            v_ambiguious = '*'.join([chr, start, str(-1 * ref_alt_code)])
            if v_ambiguious in var_dic or v in var_dic:
                print('Wrong lookup: same snp has already been included: ', '\t'.join(i))
                continue
            var_dic[v] = ( i[args.lookup_snpid_col - 1], ref, alt )
    print('Finished scanning lookup table: ', lookup_file, flush = True)

meta_dic = {
    'other invalid (long ref or alt)': 0,
    'not shown': 0,
    'exact match': 0,
    'flipped strand': 0,
    'flipped ref/alt': 0,
    'flipped strand and ref/alt': 0,
    'Ambiguious SNP (T/A or G/C SNP)': 0
}
# print(meta_dic)

flip_cols = [ int(i) for i in args.effect_col.split(',') ]

o = gzip.open(args.out_txtgz, 'wt')
with my_read(args.input) as f:
    o.write(next(f).strip() + '\t' + 'annotated_snpid' + '\n')
    for i in f:
        i = i.strip().split('\t')
        chr = i[args.chr_col - 1]
        start = i[args.pos_col - 1]
        ref = i[args.ref_col - 1]
        alt = i[args.alt_col - 1]
        if len(ref) > 1 or len(alt) > 1:
            meta_dic['other invalid (long ref or alt)'] += 1
            continue
        ref_alt_code = ref_alt_to_code(ref, alt)
        if ref_alt_code is 1 or ref_alt_code is 4:
            meta_dic['Ambiguious SNP (T/A or G/C SNP)'] += 1
            if args.include_ambiguious is False:
                continue
        v = '*'.join([chr, start, str(ref_alt_code)])
        v_ambiguious = '*'.join([chr, start, str(-1 * ref_alt_code)])
        if v in var_dic:
            info = var_dic[v]
            newid = info[0]
            if info[1] == ref:
                meta_dic['exact match'] += 1
            else:
                meta_dic['flipped strand'] += 1
                i[args.ref_col - 1] = info[1]
                i[args.alt_col - 1] = info[2]
            i.append(newid)
            o.write('\t'.join(i) + '\n')
        elif v_ambiguious in var_dic:
            info = var_dic[v_ambiguious]
            newid = info[0]
            if info[2] == ref:
                meta_dic['flipped ref/alt'] += 1
            else:
                meta_dic['flipped strand and ref/alt'] += 1
            i.append(newid)
            i[args.ref_col - 1] = info[1]
            i[args.alt_col - 1] = info[2]
            for ff in flip_cols:
                i[ff - 1] = str(-1 * float(i[ff - 1]))
            o.write('\t'.join(i) + '\n')
        else:
            meta_dic['not shown'] += 1
o.close()

for i in list(meta_dic.keys()):
    print('{}\t{}'.format(i, meta_dic[i]))


import os
import time
import warnings

import cv2
import numpy as np

from sedna.common.config import Context
from sedna.common.file_ops import FileOps
from sedna.core.incremental_learning import IncrementalLearning
from interface import Estimator

he_saved_url = Context.get_parameters("HE_SAVED_URL", '/tmp')
rsl_saved_url = Context.get_parameters("RESULT_SAVED_URL", '/tmp')
class_names = ['person', 'helmet', 'helmet_on', 'helmet_off']

FileOps.clean_folder([he_saved_url, rsl_saved_url], clean=False)

def draw_boxes(img, labels, scores, bboxes, class_names, colors):
    line_type = 2
    text_thickness = 1
    box_thickness = 1
    #  get color code
    colors = colors.split(",")
    colors_code = []
    for color in colors:
        if color == 'green':
            colors_code.append((0, 255, 0))
        elif color == 'blue':
            colors_code.append((255, 0, 0))
        elif color == 'yellow':
            colors_code.append((0, 255, 255))
        else:
            colors_code.append((0, 0, 255))
    label_dict = {i: label for i, label in enumerate(class_names)}
    for i in range(bboxes.shape[0]):
        bbox = bboxes[i]
        if float("inf") in bbox or float("-inf") in bbox:
            continue
        label = int(labels[i])
        score = "%.2f" % round(scores[i], 2)
        text = label_dict.get(label) + ":" + score
        p1 = (int(bbox[0]), int(bbox[1]))
        p2 = (int(bbox[2]), int(bbox[3]))
        if (p2[0] - p1[0] < 1) or (p2[1] - p1[1] < 1):
            continue
        try:
            cv2.rectangle(img, p1[::-1], p2[::-1],
                          colors_code[labels[i]], box_thickness)
            cv2.putText(img, text, (p1[1], p1[0] + 20 * (label + 1)),
                        cv2.FONT_HERSHEY_SIMPLEX, 0.6, (255, 0, 0),
                        text_thickness, line_type)
        except TypeError as err:
            warnings.warn(f"Draw box fail: {err}")
    return img

def output_deal(is_hard_example, infer_result, nframe, img_rgb):
    # save and show image
    img_rgb = np.array(img_rgb)
    img_rgb = cv2.cvtColor(img_rgb, cv2.COLOR_RGB2BGR)
    colors = 'yellow,blue,green,red'

    lables, scores, bbox_list_pred = infer_result
    img = draw_boxes(img_rgb, lables, scores, bbox_list_pred, class_names,
                     colors)
    if is_hard_example:
        cv2.imwrite(f"{he_saved_url}/{nframe}.jpeg", img)
    cv2.imwrite(f"{rsl_saved_url}/{nframe}.jpeg", img)

def mkdir(path):
    path = path.strip()
    path = path.rstrip()
    is_exists = os.path.exists(path)
    if not is_exists:
        os.makedirs(path)

def deal_infer_rsl(model_output):
    all_classes, all_scores, all_bboxes = model_output
    rsl = []
    for c, s, bbox in zip(all_classes, all_scores, all_bboxes):
        bbox[0], bbox[1], bbox[2], bbox[3] = bbox[1], bbox[0], bbox[3], bbox[2]
        rsl.append(bbox.tolist() + [s, c])
    return rsl

def run():
    camera_address = Context.get_parameters('video_url')

    # get hard exmaple mining algorithm from config
    hard_example_mining = IncrementalLearning.get_hem_algorithm_from_config(
        threshold_img=0.9
    )

    input_shape_str = Context.get_parameters("input_shape")
    input_shape = tuple(int(v) for v in input_shape_str.split(","))
    # create Incremental Learning instance
    incremental_instance = IncrementalLearning(
        estimator=Estimator, hard_example_mining=hard_example_mining
    )
    # use video streams for testing
    camera = cv2.VideoCapture(camera_address)
    fps = 10
    nframe = 0
    # the input of video stream
    while 1:
        ret, input_yuv = camera.read()
        if not ret:
            time.sleep(5)
            camera = cv2.VideoCapture(camera_address)
            continue

        if nframe % fps:
            nframe += 1
            continue

        img_rgb = cv2.cvtColor(input_yuv, cv2.COLOR_BGR2RGB)
        nframe += 1
        if nframe % 1000 == 1:  # logs every 1000 frames
            warnings.warn(f"camera is open, current frame index is {nframe}")
        results, _, is_hard_example = incremental_instance.inference(
            img_rgb, post_process=deal_infer_rsl, input_shape=input_shape)
        output_deal(is_hard_example, results, nframe, img_rgb)

if __name__ == "__main__":
    run()


import copy
import glob
import json
import os
import tkinter
from collections import deque

from PIL import Image, ImageTk

class App(tkinter.Frame):
    class Face:
        def __init__(self, a):
            self.ind = 0
            self.face_parts = {
                'eye_side': a.FacePart(2, 'green'),
                'mouth_side': a.FacePart(2, 'green'),
                'nose_side': a.FacePart(2, 'green'),
                'l_eye_w': a.FacePart(2, 'red'),
                'l_eye_h': a.FacePart(2, 'red'),
                'r_eye_w': a.FacePart(2, 'red'),
                'r_eye_h': a.FacePart(2, 'red'),
                'mouth_w': a.FacePart(2, 'blue'),
                'mouth_h': a.FacePart(2, 'blue'),
                'jaw': a.FacePart(1, 'yellow'),
                'nose_w': a.FacePart(2, 'yellow'),
                'nose_h': a.FacePart(2, 'yellow')
            }
            self.part = self.face_parts['eye_side']

        def point(self, p):
            self.part.list.append((p.x, p.y))
            if self.part.is_full() and self.ind < len(self.face_parts) - 1:
                self.ind += 1
                key = list(self.face_parts)[self.ind]
                self.part = self.face_parts[key]
                print(f'part={key}')

        def is_completed(self):
            return self.part.is_full() and self.ind == len(self.face_parts) - 1

    class FacePart:
        def __init__(self, max_len, color):
            self.max_len = max_len
            self.list = []
            self.color = color

        def is_full(self):
            return len(self.list) == self.max_len

    class Point:
        def __init__(self, a, x, y, color):
            self.r = 3
            self.app = a
            self.x = x
            self.y = y
            x1 = x - self.r
            y1 = y - self.r
            x2 = x + self.r
            y2 = y + self.r
            app.canvas.create_oval(x1, y1, x2, y2, tag='circle', fill=color, outline='')

    def __init__(self, master=None):
        super().__init__(master)
        self.master = master
        self.pack()
        self.files = deque(glob.glob("./images/*"))
        self.file = self.files.pop()
        self.face = self.Face(self)

        self.width = 800
        self.height = 800
        self.master.geometry(f'{self.width}x{self.height}')
        self.master.resizable(False, False)

        img = Image.open(self.file)
        w, h = img.size

        im_w = self.width if w > h else self.height * w / h
        im_h = self.height if h > w else self.width * h / w
        print(im_w)
        print(im_h)
        img = img.resize((int(im_w), int(im_h)))
        self.img = ImageTk.PhotoImage(img, master=self)

        self.canvas = tkinter.Canvas(self.master, width=self.width, height=self.height)
        self.canvas.place(x=0, y=0)

        self.item = self.canvas.create_image(0, 0, image=self.img, anchor=tkinter.NW)
        self.canvas.bind('<ButtonPress-1>', self.detect)

    def sw_img(self, source):
        w, h = source.size
        im_w = self.width if w > h else self.height * w / h
        im_h = self.height if h > w else self.width * h / w

        img = source.resize((int(im_w), int(im_h)))
        self.img = ImageTk.PhotoImage(img)
        self.canvas.itemconfig(self.item, image=self.img)

    def detect(self, event):
        print(f'x={event.x}, y={event.y}')
        p = self.Point(self, event.x, event.y, self.face.part.color)
        self.face.point(p)
        if self.face.is_completed():
            self.output()
            self.canvas.delete('circle')
            if len(self.files) == 0:
                self.master.destroy()
            else:
                self.file = self.files.pop()
                self.sw_img(Image.open(self.file))
                self.face = self.Face(self)
                print('switched')

    def output(self):
        data = copy.copy(self.face.face_parts)
        for k, v in data.items():
            data[k] = v.list

        filename = os.path.splitext(os.path.basename(self.file))[0]
        file = open(f'./data/{filename}.json', mode='w')
        json.dump(data, file, ensure_ascii=False)
        file.close()

if __name__ == '__main__':
    root = tkinter.Tk()
    app = App(master=root)
    app.mainloop()


import torch
from torch.autograd import grad
import numpy as np
import matplotlib.pyplot as plt
from utilities import get_derivative

device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')

class PhysicsInformedContinuous:
    """A class used for the definition of Physics Informed Models for one dimensional bars."""

    def __init__(self, layers, t0, x0, t_lb, x_lb, t_ub, x_ub, t_f, x_f, u0,):
        """Construct a PhysicsInformedBar model"""

        self.t0 = t0
        self.x0 = x0
        self.t_lb = t_lb
        self.x_lb = x_lb
        self.t_ub = t_ub
        self.x_ub = x_ub
        self.t_f = t_f
        self.x_f = x_f
        self.u0 = u0
        self.model = self.build_model(layers[0], layers[1:-1], layers[-1])
        self.train_cost_history = []

    def build_model(self, input_dimension, hidden_dimension, output_dimension):
        """Build a neural network of given dimensions."""

        nonlinearity = torch.nn.Tanh()
        modules = []
        modules.append(torch.nn.Linear(input_dimension, hidden_dimension[0]))
        modules.append(nonlinearity)
        for i in range(len(hidden_dimension)-1):
            modules.append(torch.nn.Linear(hidden_dimension[i], hidden_dimension[i+1]))
            modules.append(nonlinearity)

        modules.append(torch.nn.Linear(hidden_dimension[-1], output_dimension))

        model = torch.nn.Sequential(*modules).to(device)
        print(model)
        print('model parameters on gpu:', next(model.parameters()).is_cuda)
        return model

    def u_nn(self, t, x):
        """Predict temperature at (t,x)."""

        u = self.model(torch.cat((t,x),1))
        return u

    def f_nn(self, t, x):
        """Compute differential equation."""

        u = self.u_nn(t, x)
        u_t = get_derivative(u, t, 1)
        u_x = get_derivative(u, x, 1)
        u_xx = get_derivative(u, x, 2)

        k = 0.01 * u + 7
        k_u = 0.01
        c = 0.0005 * u ** 2 + 500
        s = self.source_term(t,x)

        f = c * u_t - k_u * u_x * u_x - k * u_xx - s
        return f

    def source_term(self, t, x):
        """Compute source term."""

        t_max = 0.5
        sigma = 0.02
        u_max = 1

        p = 0.25 * torch.cos(2 * np.pi * t / t_max) + 0.5
        p_t = -0.5 * torch.sin(2 * np.pi * t / t_max) * np.pi / t_max
        u_sol = u_max * torch.exp(-(x - p) ** 2 / (2 * sigma ** 2))
        k_sol = 0.01 * u_sol + 7
        k_u_sol = 0.01
        c_sol = 0.0005 * u_sol ** 2 + 500
        factor = 1/(sigma ** 2)

        s = factor * k_sol * u_sol + u_sol * (x - p) * factor * (c_sol * p_t - (x - p) * factor * (k_sol + u_sol * k_u_sol))
        return s

    def cost_function(self):
        """Compute cost function."""

        u0_pred = self.u_nn(self.t0, self.x0)
        u_lb_pred = self.u_nn(self.t_lb, self.x_lb)
        u_x_lb_pred = get_derivative(u_lb_pred, self.x_lb, 1)
        u_ub_pred = self.u_nn(self.t_ub, self.x_ub)
        u_x_ub_pred = get_derivative(u_ub_pred, self.x_ub, 1)
        f_pred = self.f_nn(self.t_f, self.x_f)

        mse_0 = torch.mean((self.u0 - u0_pred)**2)
        mse_b = torch.mean(u_x_lb_pred**2) + torch.mean(u_x_ub_pred**2)
        mse_f = torch.mean((5e-4*f_pred)**2)  # 5e-4 is a good value for balancing

        return mse_0, mse_b, mse_f

    def train(self, epochs, optimizer='Adam', **kwargs):
        """Train the model."""

        # Select optimizer
        if optimizer=='Adam':
            self.optimizer = torch.optim.Adam(self.model.parameters(), **kwargs)

        ########################################################################
        elif optimizer=='L-BFGS':
            self.optimizer = torch.optim.LBFGS(self.model.parameters())

            def closure():
                self.optimizer.zero_grad()
                mse_0, mse_b, mse_f = self.cost_function()
                cost = mse_0 + mse_b + mse_f
                cost.backward(retain_graph=True)
                return cost
        ########################################################################

        # Training loop
        for epoch in range(epochs):
            mse_0, mse_b, mse_f = self.cost_function()
            cost = mse_0 + mse_b + mse_f
            self.train_cost_history.append([cost.cpu().detach(), mse_0.cpu().detach(), mse_b.cpu().detach(), mse_f.cpu().detach()])

            if optimizer=='Adam':
                # Set gradients to zero.
                self.optimizer.zero_grad()

                # Compute gradient (backwardpropagation)
                cost.backward(retain_graph=True)

                # Update parameters
                self.optimizer.step()

            ########################################################################
            elif optimizer=='L-BFGS':
                self.optimizer.step(closure)
            ########################################################################

            if epoch % 100 == 0:
                # print("Cost function: " + cost.detach().numpy())
                print(f'Epoch ({optimizer}): {epoch}, Cost: {cost.detach().cpu().numpy()}')

    def plot_training_history(self, yscale='log'):
        """Plot the training history."""

        train_cost_history = np.asarray(self.train_cost_history, dtype=np.float32)

        # Set up plot
        fig, ax = plt.subplots(figsize=(4,3))
        ax.set_title("Cost function history")
        ax.set_xlabel("Epochs")
        ax.set_ylabel("Cost function $C$")
        plt.yscale(yscale)

        # Plot data
        mse_0, mse_b, mse_f = ax.plot(train_cost_history[:,1:4])
        mse_0.set(color='r', linestyle='dashed', linewidth=2)
        mse_b.set(color='k', linestyle='dotted', linewidth=2)
        mse_f.set(color='silver', linewidth=2)
        plt.legend([mse_0, mse_b, mse_f], ['$MSE_0$', '$MSE_b$', '$MSE_f$'], loc='lower left')
        plt.tight_layout()
        # plt.savefig('plots/cost-function-history.png')
        plt.show()


import matplotlib.pyplot as plt
import numpy as np
import scipy.io as sio
from sklearn import svm
from plotData import*
from visualizeBoundary import*
from gaussianKernel import*
from visualizeBoundaryLinear import *
plt.ion()
np.set_printoptions(formatter={'float': '{: 0.6f}'.format})

print('Loading and Visualizing data ... ')

data = sio.loadmat('ex6data1.mat')
X = data['X']
y = data['y'].flatten()

plotData(X, y)

input('Program paused. Press ENTER to continue')

print('Training Linear SVM')

c = 1
#通过C=1000或者等于1使得其考虑是否忽略数据坐标图中的特殊点
clf = svm.SVC(c, kernel='linear', tol=1e-3,max_iter=200)
model=clf.fit(X, y)

plotData(X, y)
visualizeBoundaryLinear(X,y,model)

input('Program paused. Press ENTER to continue')

print('Evaluating the Gaussian Kernel')

x1 = np.array([1, 2, 1])
x2 = np.array([0, 4, -1])
sigma = 2
sim = gaussianKernel(x1, x2, sigma)

print('Gaussian kernel between x1 = [1, 2, 1], x2 = [0, 4, -1], sigma = {} : {:0.6f}\n'
      '(for sigma = 2, this value should be about 0.324652'.format(sigma, sim))

input('Program paused. Press ENTER to continue')

print('Loading and Visualizing Data ...')

data = sio.loadmat('ex6data2.mat')
X = data['X']
y = data['y'].flatten()
m = y.size

plotData(X, y)

input('Program paused. Press ENTER to continue')

print('Training SVM with RFB(Gaussian) Kernel (this may take 1 to 2 minutes) ...')

#参数设置
c = 1
sigma = 0.1
ga=1.0/(2*sigma**2)
#调用自己写的高斯核函数  返回新的特征向量矩阵
def gaussian_kernel(x_1, x_2):
    n1 = x_1.shape[0]
    n2 = x_2.shape[0]
    result = np.zeros((n1, n2))

    for i in range(n1):
        for j in range(n2):
            result[i, j] = gaussianKernel(x_1[i], x_2[j], sigma)

    return result

#

clf = svm.SVC(c, kernel='rbf', gamma=ga,tol=1e-3,max_iter=200)
model=clf.fit(X, y)
print('Training complete!')

plotData(X, y)
visualizeBoundary_old(clf,X,y,model)

input('Program paused. Press ENTER to continue')

print('Loading and Visualizing Data ...')

data = sio.loadmat('ex6data3.mat')
X = data['X']
y = data['y'].flatten()
m = y.size

plotData(X, y)

input('Program paused. Press ENTER to continue')

# ===================== Part 7: Visualizing Dataset 3 =====================

clf = svm.SVC(c, kernel='rbf', gamma=ga,tol=1e-3,max_iter=200)
model=clf.fit(X, y)
print(clf)
plotData(X, y)
visualizeBoundary_old(clf,X,y,model)

input('ex6 Finished. Press ENTER to exit')


from FunctionScanner import FunctionScanner

class NumericalMethod:
    def __init__(self, precision, eps, alpha, max_iterations, function, derivative,
                 function_x_values, graph):
        self.precision = precision
        self.eps = eps
        self.alpha = alpha
        self.max_iterations = max_iterations
        self.function = function
        self.derivative = derivative
        self.function_x_values = function_x_values
        self.graph = graph

        scanner = FunctionScanner()
        self.intervals = scanner.scan(f=self.function, start_x=self.function_x_values[0],
                                      end_x=self.function_x_values[-1])

    def simple_iteration_method(self):
        self.table_header('Paprastųjų iteracijų metodas')

        self.graph.clear_graph()
        self.graph.show_function(self.function_x_values,
                                 [x + (self.function(x) / self.alpha) for x in self.function_x_values],
                                 'b', 'f(x)')
        self.graph.show_function(self.function_x_values, self.function_x_values, 'r', 'y')
        self.graph.show_function(self.function_x_values[0], 0, color='ro')
        self.graph.show_function(self.function_x_values[-1], 0, color='ro')

        for interval in self.intervals:
            x = interval[0]
            iteration = 0  # Iteration count
            prec = self.precision
            while prec > self.eps and x >= self.function_x_values[0]:
                iteration += 1
                if iteration == self.max_iterations:
                    print("Reached max iterations limit")
                    return

                if x > self.function_x_values[-1]:
                    print('X out of bounds')
                    return

                next_x = (self.function(x) / self.alpha) + x
                self.graph.show_function([x, x, next_x], [x, next_x, next_x], 'g-')

                prec = abs(x - next_x)
                x = next_x
            self.table_content(interval[0], interval[1], prec, iteration, x)

        self.table_footer()

    def scanning_method(self):
        self.table_header('Skenavimo su mažėjančiu žingsniu')

        self.graph.clear_graph()
        self.graph.show_function(self.function_x_values, [self.function(x) for x in self.function_x_values], 'b',
                                 'f(x)')
        self.graph.show_function(self.function_x_values[0], 0, color='ro')
        self.graph.show_function(self.function_x_values[-1], 0, color='ro')

        for interval in self.intervals:
            prec = 0.1
            step = 0.1

            current = interval[0]
            is_positive = self.function(current) > 0
            changed = False
            current_iteration = 0
            iteration_counter = 0

            while prec > self.eps:
                if current_iteration >= self.max_iterations:
                    print("Reached max iterations limit")
                    return
                y = self.function(current)
                if is_positive is not (y > 0):
                    current -= step
                    step /= 2
                    self.graph.show_function(current, 0, color='bo')
                    changed = True
                else:
                    # time.sleep(0.1)
                    if changed is False:
                        self.graph.show_function(current, 0, color='yo')

                    changed = False
                    current += step

                prec = abs(y)
                iteration_counter += 1
                is_positive = y > 0

            self.table_content(interval[0], interval[1], prec, iteration_counter, current)

        self.table_footer()

    def newton_method(self):
        self.table_header('Niutono (liestinių) metodas')

        self.graph.clear_graph()
        self.graph.show_function(self.function_x_values, [self.function(x) for x in self.function_x_values], 'b',
                                 'f(x)')
        self.graph.show_function(self.function_x_values[0], 0, color='ro')
        self.graph.show_function(self.function_x_values[-1], 0, color='ro')

        for interval in self.intervals:

            prec = 0.1
            x = (interval[0] + interval[-1]) / 2
            current_iteration = 0

            while prec > self.eps:
                if current_iteration >= self.max_iterations:
                    print("Reached max iterations limit")
                    return

                next_x = (x - self.function(x) / self.derivative(x))
                prec = abs(next_x - x)

                x = next_x
                current_iteration += 1

            self.table_content(interval[0], interval[1], prec, current_iteration, x)

        self.table_footer()

    @staticmethod
    def table_header(title):
        print('-' * 129)
        print('-' * 45 + '{0:^40}'.format(title) + '-' * 44)
        print('-' * 129)
        print(
            '|                    INTERVALAS                  |          TIKSLUMAS          |   ITERACIJŲ SKAIČIUS  | '
            '       ŠAKNIS          |')
        print('-' * 129)

    @staticmethod
    def table_content(start, end, prec, iteration_counter, root):
        print('|  [{0:^20}, {1:^20}]  |  {2:^25}  |  {3:^19}  |  {4:^20}  |'.format(start, end, prec,
                                                                                iteration_counter, root))

    @staticmethod
    def table_footer():
        print('-' * 129)


# from sys import stdin, setrecursionlimit
# setrecursionlimit(10 ** 6)
# input = stdin.readline
from collections import list

N, M = map(int, input().split())
graph = [list(map(int, input())) for _ in range(N)]
queue = list()
# (상, 하, 좌, 우)
dx = [-1, 1, 0, 0]
dy = [0, 0, -1, 1]

def bfs(x, y):
    queue.append((x, y))
    while queue:
        x, y = queue.popleft()

        for i in range(4):
            nx = x + dx[i]
            ny = y + dy[i]

            if 0 <= nx < N and 0 <= ny < M:
                if graph[nx][ny] == 1:
                    graph[nx][ny] = graph[x][y] + 1
                    queue.append((nx, ny))
                else:
                    continue

    print(graph[N-1][M-1])

bfs(0, 0)


import growPinConfig
from utime import sleep_ms
import machine
import math

FREQ = 1000 # Frequency for PWM machine.Pins

def init():
    for pin in growPinConfig.LEDPINS:
        myPin = machine.Pin(pin, machine.Pin.OUT)
        myPin.off()

    soilPwr = machine.Pin(growPinConfig.SOILPWR, machine.Pin.OUT)
    soilPwr.off()

    global alertPin
    alertPin = machine.PWM(machine.Pin(growPinConfig.ALERTPIN), FREQ)
    #===========================================================================
    # global mcr, mcg, mcb
    # mcr = machine.PWM(machine.Pin(growPinConfig.MC_RED), FREQ)
    # mcg = machine.PWM(machine.Pin(growPinConfig.MC_GREEN), FREQ)
    # mcb = machine.PWM(machine.Pin(growPinConfig.MC_BLUE), FREQ)
    #===========================================================================

def ledControl (pin, onoff):
    myPin = machine.Pin(pin, machine.Pin.OUT)
    if onoff == 'on':
        myPin.on()
    else:
        myPin.off()

def blink (pin):
    myPin = machine.Pin(pin, machine.Pin.OUT)
    myPin.value(not bool(myPin.value())) # convert 0 and 1 to true and false and toggle it
    sleep_ms(100)
    myPin.value(not bool(myPin.value()))

def alert(toggle):
    if toggle:
        t=30
        for a in range(3):             # repeat the pulsing
            for i in range(19):         # perform the pulse
                alertPin.duty(int(math.sin(i / 10 * math.pi) * 500 + 500))
                sleep_ms(t)
        alertPin.duty(0) # turn off LED
#===============================================================================
#
# def pulse(color, t=30):
#     print("Callback executed, color: " + color)
#
#     if color in growPinConfig.COLORS:
#         for a in range(10):             # repeat the pulsing
#             for i in range(20):         # perform the pulse
#                 if color == 'red':
#                     mcr.duty(int(math.sin(i / 10 * math.pi) * 500 + 500))
#                     mcb.duty(0)
#                     mcg.duty(0)
#
#                 elif color == 'green':
#                     mcr.duty(0)
#                     mcb.duty(0)
#                     mcg.duty(int(math.sin(i / 10 * math.pi) * 500 + 500))
#
#                 elif color == 'blue':
#                     mcr.duty(0)
#                     mcb.duty(int(math.sin(i / 10 * math.pi) * 500 + 500))
#                     mcg.duty(0)
#
#                 elif color == 'yellow':
#                     mcr.duty(int(math.sin(i / 10 * math.pi) * 500 + 500))
#                     mcb.duty(0)
#                     mcg.duty(int(math.sin(i / 10 * math.pi) * 500 + 500))
#
#                 elif color == 'purple':
#                     mcr.duty(int(math.sin(i / 10 * math.pi) * 500 + 500))
#                     mcb.duty(int(math.sin(i / 10 * math.pi) * 500 + 500))
#                     mcg.duty(0)
#
#                 elif color == 'aqua':
#                     mcr.duty(0)
#                     mcb.duty(int(math.sin(i / 10 * math.pi) * 500 + 500))
#                     mcg.duty(int(math.sin(i / 10 * math.pi) * 500 + 500))
#
#                 sleep_ms(t)
#     mcr.duty(0)
#     mcg.duty(0)
#     mcb.duty(0)
#===============================================================================


import numpy as np
import pandas as pd
import pytest

from feature_engine.timeseries.forecasting import LagFeatures

@pytest.mark.parametrize("_periods", [1, [1, 2, 3]])
def test_permitted_param_periods(_periods):
    transformer = LagFeatures(periods=_periods)
    assert transformer.periods == _periods

@pytest.mark.parametrize(
    "_periods", [-1, 0, None, [-1, 2, 3], [0.1, 1], 0.5, [0, 1], [1, 1, 2]]
)
def test_error_when_non_permitted_param_periods(_periods):
    with pytest.raises(ValueError):
        LagFeatures(periods=_periods)

def test_error_when_non_permitted_param_freq():
    with pytest.raises(ValueError):
        LagFeatures(freq=["2h", "2h", "3h"])

@pytest.mark.parametrize("_sort_index", [True, False])
def test_permitted_param_sort_index(_sort_index):
    transformer = LagFeatures(sort_index=_sort_index)
    assert transformer.sort_index == _sort_index

@pytest.mark.parametrize("_sort_index", [-1, None, "hola"])
def test_error_when_non_permitted_param_sort_index(_sort_index):
    with pytest.raises(ValueError):
        LagFeatures(sort_index=_sort_index)

def test_get_feature_names_out(df_time):
    # input features
    original_features = ["ambient_temp", "module_temp", "irradiation", "color"]

    # When freq is a string:
    tr = LagFeatures(freq="1D")
    tr.fit(df_time)

    # Expected
    out = ["ambient_temp_lag_1D", "module_temp_lag_1D", "irradiation_lag_1D"]
    out = original_features + out
    assert tr.get_feature_names_out(input_features=None) == out
    assert tr.get_feature_names_out(input_features=original_features) == out
    assert tr.get_feature_names_out(input_features=df_time.columns) == out

    with pytest.raises(ValueError):
        # assert error when user passes a string instead of list
        tr.get_feature_names_out(input_features=original_features[0])

    with pytest.raises(ValueError):
        # assert error when uses passes features that were not lagged
        tr.get_feature_names_out(input_features=["color"])

    # When period is an int:
    tr = LagFeatures(periods=2)
    tr.fit(df_time)

    # Expected
    out = ["ambient_temp_lag_2", "module_temp_lag_2", "irradiation_lag_2"]
    out = original_features + out
    assert tr.get_feature_names_out(input_features=None) == out
    assert tr.get_feature_names_out(input_features=original_features) == out
    assert tr.get_feature_names_out(input_features=df_time.columns) == out

    # When freq is a list:
    tr = LagFeatures(freq=["3D", "2D"])
    tr.fit(df_time)

    # Expected
    out = [
        "ambient_temp_lag_3D",
        "module_temp_lag_3D",
        "irradiation_lag_3D",
        "ambient_temp_lag_2D",
        "module_temp_lag_2D",
        "irradiation_lag_2D",
    ]
    out = original_features + out

    assert tr.get_feature_names_out(input_features=None) == out
    assert tr.get_feature_names_out(input_features=df_time.columns) == out

    # When periods is a list:
    tr = LagFeatures(periods=[2, 3])
    tr.fit(df_time)

    # Expected
    out = [
        "ambient_temp_lag_2",
        "module_temp_lag_2",
        "irradiation_lag_2",
        "ambient_temp_lag_3",
        "module_temp_lag_3",
        "irradiation_lag_3",
    ]
    out = original_features + out

    assert tr.get_feature_names_out(input_features=None) == out
    assert tr.get_feature_names_out(input_features=original_features) == out

    # When drop original is true.
    tr = LagFeatures(freq="1D", drop_original=True)
    tr.fit(df_time)

    # Expected
    out = ["ambient_temp_lag_1D", "module_temp_lag_1D", "irradiation_lag_1D"]
    assert tr.get_feature_names_out(input_features=None) == ["color"] + out
    assert tr.get_feature_names_out(input_features=original_features) == ["color"] + out

def test_correct_lag_when_using_periods(df_time):
    # Expected
    date_time = [
        pd.Timestamp("2020-05-15 12:00:00"),
        pd.Timestamp("2020-05-15 12:15:00"),
        pd.Timestamp("2020-05-15 12:30:00"),
        pd.Timestamp("2020-05-15 12:45:00"),
        pd.Timestamp("2020-05-15 13:00:00"),
    ]
    expected_results = {
        "ambient_temp": [31.31, 31.51, 32.15, 32.39, 32.62],
        "module_temp": [49.18, 49.84, 52.35, 50.63, 49.61],
        "irradiation": [0.51, 0.79, 0.65, 0.76, 0.42],
        "color": ["blue"] * 5,
        "ambient_temp_lag_3": [np.nan, np.nan, np.nan, 31.31, 31.51],
        "module_temp_lag_3": [np.nan, np.nan, np.nan, 49.18, 49.84],
        "ambient_temp_lag_2": [np.nan, np.nan, 31.31, 31.51, 32.15],
        "module_temp_lag_2": [np.nan, np.nan, 49.18, 49.84, 52.35],
    }
    expected_results_df = pd.DataFrame(data=expected_results, index=date_time)

    # When period is an int.
    transformer = LagFeatures(variables=["ambient_temp", "module_temp"], periods=3)
    df_tr = transformer.fit_transform(df_time)
    assert df_tr.head(5).equals(
        expected_results_df.drop(["ambient_temp_lag_2", "module_temp_lag_2"], axis=1)
    )

    # When period is list.
    transformer = LagFeatures(variables=["ambient_temp", "module_temp"], periods=[3, 2])
    df_tr = transformer.fit_transform(df_time)
    assert df_tr.head(5).equals(expected_results_df)

    # When drop original is True
    transformer = LagFeatures(
        variables=["ambient_temp", "module_temp"], periods=[3, 2], drop_original=True
    )
    df_tr = transformer.fit_transform(df_time)
    assert df_tr.head(5).equals(
        expected_results_df.drop(["ambient_temp", "module_temp"], axis=1)
    )

def test_correct_lag_when_using_freq(df_time):
    # Expected
    date_time = [
        pd.Timestamp("2020-05-15 12:00:00"),
        pd.Timestamp("2020-05-15 12:15:00"),
        pd.Timestamp("2020-05-15 12:30:00"),
        pd.Timestamp("2020-05-15 12:45:00"),
        pd.Timestamp("2020-05-15 13:00:00"),
    ]
    expected_results = {
        "ambient_temp": [31.31, 31.51, 32.15, 32.39, 32.62],
        "module_temp": [49.18, 49.84, 52.35, 50.63, 49.61],
        "irradiation": [0.51, 0.79, 0.65, 0.76, 0.42],
        "color": ["blue"] * 5,
        "ambient_temp_lag_1h": [np.nan, np.nan, np.nan, np.nan, 31.31],
        "module_temp_lag_1h": [np.nan, np.nan, np.nan, np.nan, 49.18],
        "irradiation_lag_1h": [np.nan, np.nan, np.nan, np.nan, 0.51],
        "ambient_temp_lag_15min": [np.nan, 31.31, 31.51, 32.15, 32.39],
        "module_temp_lag_15min": [np.nan, 49.18, 49.84, 52.35, 50.63],
        "irradiation_lag_15min": [np.nan, 0.51, 0.79, 0.65, 0.76],
    }
    expected_results_df = pd.DataFrame(
        data=expected_results,
        index=date_time,
    )

    # When freq is a string
    transformer = LagFeatures(freq="1h")
    df_tr = transformer.fit_transform(df_time)
    assert df_tr.head(5).equals(
        expected_results_df.drop(
            [
                "ambient_temp_lag_15min",
                "module_temp_lag_15min",
                "irradiation_lag_15min",
            ],
            axis=1,
        )
    )

    # When freq is a list
    transformer = LagFeatures(freq=["1h", "15min"])
    df_tr = transformer.fit_transform(df_time)
    assert df_tr.head(5).equals(expected_results_df)

    # When drop original is True
    transformer = LagFeatures(freq=["1h"], drop_original=True)
    df_tr = transformer.fit_transform(df_time)
    assert df_tr.head(5).equals(
        expected_results_df[
            ["color", "ambient_temp_lag_1h", "module_temp_lag_1h", "irradiation_lag_1h"]
        ]
    )

def test_sort_index(df_time):
    X = df_time.copy()

    # Shuffle dataframe
    Xs = X.sample(len(df_time)).copy()

    transformer = LagFeatures(sort_index=True)
    X_tr = transformer.fit_transform(Xs)

    A = X[transformer.variables_].iloc[0:4].values
    B = X_tr[transformer._get_new_features_name()].iloc[1:5].values
    assert (A == B).all()

    transformer = LagFeatures(sort_index=False)
    X_tr = transformer.fit_transform(Xs)

    A = Xs[transformer.variables_].iloc[0:4].values
    B = X_tr[transformer._get_new_features_name()].iloc[1:5].values
    assert (A == B).all()


#  Licensed under a 3-clause BSD style license - see LICENSE.rst

import logging
from astropy import units as u
from matplotlib import figure as mpf
from matplotlib import gridspec
from matplotlib import backend_bases as mpb
import pytest
import pytestqt.exceptions as pe

from sofia_redux.visualization.display import figure, gallery, blitting, pane
from sofia_redux.visualization.models import high_model, reference_model
from sofia_redux.visualization import signals
from sofia_redux.visualization.utils import eye_error

PyQt5 = pytest.importorskip('PyQt5')

class TestFigure(object):

    def test_init(self, fig_widget, qtbot):
        sigs = signals.Signals()

        correct_flags = {'gs': None, 'block_current_pane_signal': False,
                         'highlight_pane': True, 'show_markers': False,
                         'show_grid': False, 'show_error': True,
                         'dark_mode': False, '_cursor_mode': None,
                         '_cursor_pane': None}
        correct_types = {'fig': mpf.Figure, 'gallery': gallery.Gallery,
                         'blitter': blitting.BlitManager, 'panes': list,
                         '_cursor_locations': list, '_fit_params': list,
                         '_current_pane': list}
        correct_values = {'layout': 'grid',
                          'color_cycle': 'Accessible', 'plot_type': 'Step'}

        obj = figure.Figure(figure_widget=fig_widget, signals=sigs)

        assert isinstance(obj, figure.Figure)
        assert obj.signals == sigs
        assert obj.widget == fig_widget

        for field, flag in correct_flags.items():
            assert getattr(obj, field) is flag
        for field, value in correct_types.items():
            assert isinstance(getattr(obj, field), value)
        for field, value in correct_values.items():
            assert getattr(obj, field) == value

    @pytest.mark.parametrize('state', [True, False, None])
    def test_set_pane_highlight_flag(self, blank_figure, mocker, state, qtbot):

        art_mock = mocker.patch.object(gallery.Gallery,
                                       'set_pane_highlight_flag')
        blank_figure.set_pane_highlight_flag(state)

        assert blank_figure.highlight_pane is state
        assert art_mock.called_with({'state': state})

    @pytest.mark.parametrize('value', [True, False, None])
    def test_set_block_current_pane_signal(self, blank_figure, value):
        blank_figure.set_block_current_pane_signal(value)
        assert blank_figure.block_current_pane_signal is value

        blank_figure.set_block_current_pane_signal()
        assert blank_figure.block_current_pane_signal is True

    @pytest.mark.parametrize('value', ['grid', 'columns'])
    def test_set_layout_style(self, blank_figure, value):
        blank_figure.set_layout_style(value)
        assert blank_figure.layout == value

        blank_figure.set_layout_style()
        assert blank_figure.layout == 'grid'

    def test_populated(self, blank_figure):
        value = blank_figure.populated()
        assert not value

        panes = ['one', 'two', 'three']
        blank_figure.panes = panes
        value = blank_figure.populated()
        assert value

    def test_current_pane_setting(self, blank_figure, qtbot, mocker):
        value = 5
        with qtbot.wait_signal(blank_figure.signals.current_pane_changed):
            blank_figure.current_pane = value
        assert blank_figure.current_pane == list()

        mocker.patch.object(blank_figure, 'valid_pane', return_value=True)
        with qtbot.wait_signal(blank_figure.signals.current_pane_changed):
            blank_figure.current_pane = value
        assert blank_figure.current_pane == [value]

    def test_pane_count(self, blank_figure):
        length = 4
        blank_figure.panes = ['a'] * length

        assert blank_figure.pane_count() == length

    def test_pane_layout(self, blank_figure):
        gs = blank_figure.pane_layout()
        assert gs is None

        shape = (2, 3)
        blank_figure.gs = gridspec.GridSpec(shape[0], shape[1],
                                            figure=blank_figure.fig)
        gs = blank_figure.pane_layout()
        assert gs == shape

    def test_add_panes_two_dim(self, blank_figure, mocker):
        methods = ['set_plot_type', 'set_markers', 'set_grid',
                   'set_error', 'create_artists_from_current_models']
        for method in methods:
            mocker.patch.object(pane.TwoDimPane, method)
        assert len(blank_figure.panes) == 0
        n_panes = 2
        blank_figure.add_panes(n_dims=2, n_panes=n_panes)
        assert len(blank_figure.panes) == n_panes
        assert all([isinstance(p, pane.TwoDimPane)
                    for p in blank_figure.panes])

    def test_add_panes_failures(self, blank_figure):
        count = blank_figure.pane_count()

        blank_figure.add_panes(None, 0)
        new_count = blank_figure.pane_count()

        assert new_count == count

        with pytest.raises(RuntimeError) as e:
            blank_figure.add_panes([1, 1, 1], 1)
        assert 'Length of pane dimensions' in str(e)

        with pytest.raises(RuntimeError) as e:
            blank_figure.add_panes([3, 1, 1], 3)
        assert 'Invalid number of dimensions' in str(e)

    def test_remove_artists(self, blank_figure, mocker):
        mock = mocker.patch.object(gallery.Gallery,
                                   'reset_artists')

        blank_figure.remove_artists()

        assert mock.called_with({'selection': 'all'})

    def test_reset_artists_fail(self, blank_figure, mocker, caplog):
        sigs = signals.Signals()
        caplog.set_level(logging.DEBUG)
        mocker.patch.object(pane.OneDimPane,
                            'create_artists_from_current_models',
                            return_value=[1, 2])
        mocker.patch.object(gallery.Gallery, 'add_drawings',
                            return_value=0)
        mocker.patch.object(figure.Figure, '_add_pane_artists')

        blank_figure.panes = [pane.OneDimPane(sigs)]

        blank_figure.reset_artists()

        assert 'Error encountered while creating artists' in caplog.text

    def test_add_pane_artists(self, blank_figure, mocker):
        sigs = signals.Signals()
        add_mock = mocker.patch.object(gallery.Gallery, 'add_patches')
        blank_figure.panes = [pane.OneDimPane(sigs)]
        blank_figure._current_pane = list()
        expected = {'pane_0': {'kind': 'border',
                               'artist': None,
                               'visible': True}}

        # test show, no current: visible
        blank_figure.highlight_pane = True
        blank_figure._add_pane_artists()
        assert add_mock.called_with(expected)

        # test show, None current: visible
        blank_figure._current_pane = None
        blank_figure._add_pane_artists()
        assert add_mock.called_with(expected)

        # test show, current matches: visible
        blank_figure._current_pane = [0]
        blank_figure._add_pane_artists()
        assert add_mock.called_with(expected)

        # test show, current does not match: not visible
        expected['pane_0']['visible'] = False
        blank_figure._current_pane = [1]
        blank_figure._add_pane_artists()
        assert add_mock.called_with(expected)

        # test no show, current does match: not visible
        blank_figure.highlight_pane = False
        blank_figure._current_pane = [0]
        blank_figure._add_pane_artists()
        assert add_mock.called_with(expected)

        # test no show, current does not match: not visible
        blank_figure._current_pane = [1]
        blank_figure._add_pane_artists()
        assert add_mock.called_with(expected)

    def test_add_crosshair(self, blank_figure, mocker):

        m1 = mocker.patch.object(blank_figure.gallery, 'add_crosshairs')

        # no lines added for no panes
        expected = list()
        blank_figure._add_crosshair()
        m1.assert_called_with(expected)

        # 1 pane => 2 lines added
        blank_figure.add_panes(n_dims=0, n_panes=1)
        blank_figure._add_crosshair()
        assert len(m1.call_args[0][0]) == 2

    def test_pane_details(self, blank_figure):
        expected = dict()
        assert blank_figure.pane_details() == expected

        blank_figure.add_panes(1, 2)
        expected = {'pane_0': {}, 'pane_1': {}}
        assert blank_figure.pane_details() == expected

    def test_change_current_pane(self, blank_figure):
        blank_figure.panes = [0, 1, 2, 3, 4, 5]
        blank_figure.current_pane = [0]
        assert not blank_figure.change_current_pane([0])
        assert blank_figure.current_pane == [0]

        assert blank_figure.change_current_pane(list())
        assert blank_figure.current_pane == list()

        blank_figure.current_pane = [0, 1, 2, 3]
        assert blank_figure.change_current_pane([1, 2])
        assert blank_figure.current_pane == [1, 2]

        assert not blank_figure.change_current_pane([6])
        assert blank_figure.current_pane == [1, 2]

    def test_determine_selected_pane(self, blank_figure):
        n_panes = 3
        fig = mpf.Figure()
        axes = fig.subplots(1, n_panes)
        sigs = signals.Signals()
        blank_figure.panes = [pane.OneDimPane(sigs, ax) for ax in axes]

        for i, ax in enumerate(axes):
            found = blank_figure.determine_selected_pane(ax)
            assert found == [i]

        found = blank_figure.determine_selected_pane(all_ax=True)
        assert found == [0, 1, 2]

        ax = fig.add_subplot()
        found = blank_figure.determine_selected_pane(ax)
        assert isinstance(found, list) and len(found) == 0

    def test_determine_pane_from_model(self, blank_figure, mocker):
        sigs = signals.Signals()

        count = 3
        blank_figure.panes = [pane.OneDimPane(sigs) for _ in range(count)]

        mocker.patch.object(pane.OneDimPane, 'contains_model',
                            return_value=True)
        matching = blank_figure.determine_pane_from_model('test')
        assert len(matching) == count
        assert isinstance(matching[0][1], pane.OneDimPane)

    def test_get_current_pane(self, blank_figure):
        assert blank_figure.get_current_pane() is None

        blank_figure.panes = ['a', 'b', 'c', 'd', 'e']
        blank_figure.current_pane = [2, 3]
        assert blank_figure.get_current_pane() == ['c', 'd']

        blank_figure.panes = ['a', 'b', 'c', 'd', 'e']
        blank_figure.current_pane = None
        assert blank_figure.get_current_pane() == list()

    def test_assign_models_split(self, grism_hdul, blank_figure):
        blank_figure.add_panes(n_dims=1, n_panes=2)
        model_1 = high_model.Grism(grism_hdul)
        model_2 = high_model.Grism(grism_hdul)
        models = {model_1.id: model_1, model_2.id: model_2}

        blank_figure.assign_models('split', models)

        assert all([len(p.models) == 1 for p in blank_figure.panes])

    def test_assign_models_bad(self, blank_figure):
        models = dict()
        with pytest.raises(RuntimeError) as msg:
            blank_figure.assign_models(mode='default', models=models)

        assert 'Invalid mode' in str(msg)

    @pytest.mark.parametrize('mode', ['split', 'first', 'last', 'assigned'])
    def test_assign_models_errors(self, mode, blank_figure, mocker,
                                  grism_hdul):
        mocker.patch.object(blank_figure, 'add_model_to_pane',
                            side_effect=eye_error.EyeError)

        blank_figure.add_panes(n_dims=1, n_panes=2)
        model_1 = high_model.Grism(grism_hdul)
        model_2 = high_model.Grism(grism_hdul)
        models = {model_1.id: model_1, model_2.id: model_2}
        indicies = [0, 1]

        result = blank_figure.assign_models(mode, models, indicies)
        assert result == 2

    @pytest.mark.parametrize('layout,shape', [('rows', (3, 1)),
                                              ('columns', (1, 3)),
                                              ('grid', (2, 2))])
    def test_add_model_to_pane_different(self, blank_figure, mocker,
                                         caplog, grism_hdul, layout, shape):
        caplog.set_level(logging.DEBUG)
        mocker.patch.object(figure.Figure, 'model_matches_pane',
                            return_value=False)

        blank_figure.set_layout_style(layout)

        model = high_model.Grism(grism_hdul)
        blank_figure.add_panes(n_dims=1, n_panes=1)
        assert blank_figure.pane_count() == 1

        blank_figure.add_model_to_pane(model)
        assert blank_figure.pane_count() == 2

        assert 'Added model to panes' in caplog.text

        blank_figure.add_panes(n_dims=0, n_panes=1)
        assert blank_figure.pane_count() == 3
        assert blank_figure.pane_layout() == shape

        # setting overplot state should reassign axes
        blank_figure.set_overplot_state(True, 'all')
        assert blank_figure.pane_count() == 3
        for pane_ in blank_figure.panes:
            assert pane_.show_overplot

    @pytest.mark.parametrize('matches', [True, False])
    def test_add_model_to_pane_bad(self, blank_figure, mocker, grism_hdul,
                                   caplog, matches):
        caplog.set_level(logging.INFO)
        mocker.patch.object(pane.OneDimPane, 'add_model',
                            side_effect=eye_error.EyeError)
        mocker.patch.object(figure.Figure, 'model_matches_pane',
                            return_value=matches)
        remove_mock = mocker.patch.object(pane.OneDimPane, 'remove_model')

        with pytest.raises(eye_error.EyeError):
            blank_figure.add_model_to_pane(high_model.Grism(grism_hdul))

        assert 'Added model to panes' not in caplog.text
        assert remove_mock.called_once

    def test_remove_model_from_pane(self, blank_figure, mocker):

        remove = mocker.patch.object(pane.OneDimPane, 'remove_model')
        sigs = signals.Signals()
        with pytest.raises(RuntimeError) as msg:
            blank_figure.remove_model_from_pane()
        assert 'Must specify which model' in str(msg)

        count = 4
        panes = [pane.OneDimPane(sigs) for i in range(count)]
        blank_figure.panes = panes

        blank_figure.remove_model_from_pane(filename='test',
                                            panes=panes[0])
        assert remove.call_count == 1

        # good call with int
        blank_figure.remove_model_from_pane(model_id='test',
                                            panes=0)
        assert remove.call_count == 2

        # good call with None
        blank_figure.remove_model_from_pane(model_id='test',
                                            panes=None)
        assert remove.call_count == 6

        # bad call with int
        blank_figure.remove_model_from_pane(filename='test',
                                            panes=42)
        assert remove.call_count == 6

        # bad call with non-int
        blank_figure.remove_model_from_pane(filename='test',
                                            panes='bad')
        assert remove.call_count == 6

        mock = mocker.patch.object(figure.Figure, 'end_cursor_records')
        blank_figure.recording = False
        blank_figure.remove_model_from_pane(filename='test',
                                            panes=panes[0])
        assert mock.call_count == 0

        blank_figure.recording = True
        blank_figure.remove_model_from_pane(filename='test',
                                            panes=panes[0])
        assert mock.call_count == 1

    def test_remove_all_panes(self, blank_figure):
        count = 4
        sigs = signals.Signals()
        panes = [pane.OneDimPane(sigs) for i in range(count)]
        blank_figure.panes = panes

        blank_figure.remove_all_panes()
        assert blank_figure.pane_count() == 0

        blank_figure.add_panes(0, 1)
        assert blank_figure.pane_count() == 1

    @pytest.mark.parametrize('flags, pane_count, ax_val',
                             [(None, 1, ''),
                              ('all', 4, ''),
                              ([1, 3], 2, ''),
                              ({'pane': 'all'}, 4, ''),
                              ({'pane': 'all', 'axis': 'test'}, 4, 'test'),
                              ({'pane': 'current'}, 1, ''),
                              ({'pane': 'current', 'axis': 'alt'}, 1, 'alt')])
    def test_parse_pane_flag(self, blank_figure, flags, pane_count, ax_val):
        # set a list of 4 panes
        sigs = signals.Signals()
        blank_figure.panes = [pane.OneDimPane(sigs) for _ in range(4)]
        blank_figure.current_pane = [0]

        panes, axis = blank_figure.parse_pane_flag(flags)
        assert len(panes) == pane_count
        assert axis == ax_val

        panes, axis = blank_figure.parse_pane_flag([blank_figure.panes[0]])
        assert len(panes) == 1
        assert panes[0] is blank_figure.panes[0]

        panes, axis = blank_figure.parse_pane_flag(
            {'pane': [blank_figure.panes[1]]})
        assert len(panes) == 1
        assert panes[0] is blank_figure.panes[1]

    def test_parse_pane_flag_fail(self, blank_figure, capsys):
        panes = [2.5, 'bad']
        with pytest.raises(TypeError) as msg:
            blank_figure.parse_pane_flag(panes)
        assert 'only contain integers or Pane' in str(msg)

        panes = {'bad_key': 'bad'}
        with pytest.raises(eye_error.EyeError) as msg:
            blank_figure.parse_pane_flag(panes)
        assert 'Unable to parse pane flag' in str(msg)

        panes = {'pane': 'bad'}
        with pytest.raises(eye_error.EyeError) as msg:
            blank_figure.parse_pane_flag(panes)
        assert 'Unable to parse pane flag' in str(msg)
        capsys.readouterr()

        blank_figure.parse_pane_flag(4)
        assert 'Invalid index' in capsys.readouterr().out

        blank_figure.parse_pane_flag({'pane': [4]})
        assert 'Invalid pane flag: 4' in capsys.readouterr().out

        blank_figure.parse_pane_flag({'pane': ['a']})
        assert 'Invalid pane flag: a' in capsys.readouterr().out

    def test_set_enabled(self, blank_figure, mocker, qtbot):
        model_mock = mocker.patch.object(pane.OneDimPane,
                                         'set_model_enabled')
        art_mock = mocker.patch.object(gallery.Gallery,
                                       'update_artist_options')
        vis_mock = mocker.patch.object(pane.OneDimPane,
                                       'update_visibility')
        pid = 0
        mid = 1
        state = True
        sigs = signals.Signals()

        blank_figure.panes = [pane.OneDimPane(sigs), pane.OneDimPane(sigs)]
        with qtbot.wait_signal(blank_figure.signals.atrophy):
            blank_figure.set_enabled(pid, mid, state)

        assert model_mock.called_with({'model_id': mid, 'state': state})
        assert art_mock.called_with({'pane': pid})
        assert vis_mock.called_once()

    def test_set_all_enabled(self, blank_figure, mocker, qtbot):
        model_mock = mocker.patch.object(pane.OneDimPane,
                                         'set_all_models_enabled')
        art_mock = mocker.patch.object(gallery.Gallery,
                                       'update_artist_options')
        vis_mock = mocker.patch.object(pane.OneDimPane,
                                       'update_visibility')
        pid = 0
        state = True
        sigs = signals.Signals()

        blank_figure.panes = [pane.OneDimPane(sigs), pane.OneDimPane(sigs)]
        with qtbot.wait_signal(blank_figure.signals.atrophy):
            blank_figure.set_all_enabled(pid, state)

        assert model_mock.called_with({'state': state})
        assert art_mock.called_with({'pane': pid})
        assert vis_mock.called_once()

    def test_get_markers(self, blank_figure, grism_hdul):
        model = high_model.Grism(grism_hdul)
        blank_figure.add_model_to_pane(model)

        assert blank_figure.get_markers(model.id, 0) == ['x']

    def test_get_colors(self, blank_figure, grism_hdul):
        model = high_model.Grism(grism_hdul)
        blank_figure.add_model_to_pane(model)

        colors = blank_figure.get_colors(model.id, 0)
        assert len(colors) == 1
        assert isinstance(colors[0], list)
        assert len(colors[0]) == 1
        assert isinstance(colors[0][0], str)

    @pytest.mark.parametrize('panes_list', [[0, 1, 2], 0, [0], []])
    def test_crosshair(self, blank_figure, mocker, qtbot, panes_list):
        direction = 'v'
        mocker.patch.object(figure.Figure, 'determine_selected_pane',
                            return_value=panes_list)
        art_mock = mocker.patch.object(gallery.Gallery, 'update_crosshair')
        cross_mock = mocker.patch.object(figure.Figure,
                                         '_parse_cursor_direction',
                                         return_value=direction)
        sigs = signals.Signals()

        blank_figure.panes = [pane.OneDimPane(sigs)]
        blank_figure._cursor_pane = [0]
        event = mpb.MouseEvent(x=2, y=3, canvas=blank_figure.widget.canvas,
                               name='motion_notify_event')
        event.xdata = 2
        event.ydata = 3

        if isinstance(panes_list, list) and len(panes_list) == 0:
            blank_figure.crosshair(event)
            assert art_mock.call_count == 0
            assert cross_mock.call_count == 0
        else:
            with qtbot.wait_signal(blank_figure.signals.atrophy):
                blank_figure.crosshair(event)

            assert art_mock.called_with({'data_point': (2, 3),
                                         'direction': direction})
            assert cross_mock.called_with({'mode': 'crosshair'})

    def test_reset_data_points_empty(self, blank_figure, mocker):
        mock = mocker.patch.object(gallery.Gallery, 'hide_cursor_markers')

        blank_figure.reset_data_points()

        assert mock.call_count == 0

    def test_reset_zoom_empty(self, blank_figure, mocker, qtbot):
        with pytest.raises(pe.TimeoutError):
            with qtbot.wait_signal(blank_figure.signals.atrophy_bg_partial):
                blank_figure.reset_zoom()
        sigs = signals.Signals()

        n_panes = 4
        blank_figure.panes = [pane.OneDimPane(sigs) for i in range(n_panes)]
        blank_figure.current_pane = [0]
        zoom_mock = mocker.patch.object(pane.OneDimPane, 'reset_zoom')
        with qtbot.wait_signal(blank_figure.signals.atrophy_bg_partial):
            blank_figure.reset_zoom(all_panes=True)

        assert zoom_mock.call_count == n_panes

        # test without all panes - should call once more
        with qtbot.wait_signal(blank_figure.signals.atrophy_bg_partial):
            blank_figure.reset_zoom(all_panes=False)
        assert zoom_mock.call_count == n_panes + 1

    @pytest.mark.parametrize('cursor,result',
                             [('fit', 'v'), ('y_zoom', 'h'), ('other', 'hv')])
    def test_parse_cursor_direction_crosshair(self, blank_figure, cursor,
                                              result):
        blank_figure._cursor_mode = cursor
        direction = blank_figure._parse_cursor_direction('crosshair')

        assert direction == result

    def test_clear_lines_all(self, blank_figure, mocker):
        reset_mock = mocker.patch.object(gallery.Gallery,
                                         'reset_artists')
        sigs = signals.Signals()
        panes = [pane.OneDimPane(sigs) for i in range(3)]
        blank_figure.panes = panes

        blank_figure.clear_lines(flags='v', all_panes=True)
        assert reset_mock.called_with({'panes': panes})
        assert reset_mock.call_count == 1

        blank_figure.clear_lines(flags='v', all_panes=False)
        assert reset_mock.called_with({'panes': [panes[0]]})
        assert reset_mock.call_count == 2

    def test_add_remove_pane(self, blank_figure, qtbot):
        blank_figure.add_panes(1, 3)
        assert blank_figure.current_pane is not None
        assert len(blank_figure.current_pane) == 1

        # remove first
        blank_figure.remove_pane([0])
        assert len(blank_figure.current_pane) == 1

        # remove last
        blank_figure.remove_pane([2])
        assert len(blank_figure.current_pane) == 1

        # remove none
        blank_figure.remove_pane(None)
        assert len(blank_figure.current_pane) == 1

        # remove final
        blank_figure.remove_pane([0])
        assert len(blank_figure.current_pane) == 0

    def test_change_axis_field(self, blank_figure, mocker):
        set_mock = mocker.patch.object(pane.OneDimPane, 'set_fields')
        fields = {'x': 'wavepos', 'y': 'spectral_flux'}
        f1 = fields.copy()
        f2 = {'x': 'wavepos', 'y_alt': 'spectral_flux'}
        f3 = {'x': 'wavepos', 'y': 'spectral_flux',
              'y_alt': 'spectral_flux'}

        # no panes
        mocker.patch.object(blank_figure, 'parse_pane_flag',
                            return_value=(None, None))
        blank_figure.change_axis_field(fields)
        assert set_mock.call_count == 0
        assert fields == f1
        sigs = signals.Signals()

        # a valid pane, primary axes
        mocker.patch.object(blank_figure, 'parse_pane_flag',
                            return_value=([pane.OneDimPane(sigs)], 'primary'))
        blank_figure.change_axis_field(fields)
        assert set_mock.call_count == 1
        assert fields == f1

        # secondary axis
        mocker.patch.object(blank_figure, 'parse_pane_flag',
                            return_value=([pane.OneDimPane(sigs)], 'alt'))
        blank_figure.change_axis_field(fields)
        assert set_mock.call_count == 2
        assert fields == f2

        # both axes
        fields = f1.copy()
        mocker.patch.object(blank_figure, 'parse_pane_flag',
                            return_value=([pane.OneDimPane(sigs)], 'both'))
        blank_figure.change_axis_field(fields)
        assert set_mock.call_count == 3
        assert fields == f3

    def test_set_orders(self, blank_figure, mocker):
        orders = {0: {'id': [1, 2, 3]}}
        set_patch = mocker.patch.object(pane.OneDimPane, 'set_orders')

        # pane is None, nothing happens
        mocker.patch.object(blank_figure, 'parse_pane_flag',
                            return_value=(None, None))
        sigs = signals.Signals()
        blank_figure.set_orders(orders)
        assert set_patch.call_count == 0

        # pane is single valued, set is called
        mocker.patch.object(blank_figure, 'parse_pane_flag',
                            return_value=(pane.OneDimPane(sigs), None))
        blank_figure.set_orders(orders)
        assert set_patch.call_count == 1

        # pane is list, only the first is called
        mocker.patch.object(blank_figure, 'parse_pane_flag',
                            return_value=([pane.OneDimPane(sigs),
                                          pane.OneDimPane(sigs)], None))
        blank_figure.set_orders(orders)
        assert set_patch.call_count == 2

    def test_set_scales(self, blank_figure, mocker):
        sigs = signals.Signals()
        scales = {'x': 'linear', 'y': 'log'}
        s1 = scales.copy()
        s2 = {'x': 'linear', 'y_alt': 'log'}
        s3 = {'x': 'linear', 'y': 'log', 'y_alt': 'log'}
        set_patch = mocker.patch.object(pane.OneDimPane, 'set_scales')

        # pane is None, nothing happens
        mocker.patch.object(blank_figure, 'parse_pane_flag',
                            return_value=(None, 'all'))
        blank_figure.set_scales(scales)
        assert set_patch.call_count == 0
        assert scales == s1

        # pane is list, set is called for primary on all
        mocker.patch.object(blank_figure, 'parse_pane_flag',
                            return_value=([pane.OneDimPane(sigs),
                                          pane.OneDimPane(sigs)], 'primary'))
        blank_figure.set_scales(scales)
        assert set_patch.call_count == 2
        assert scales == s1

        # call for alt
        mocker.patch.object(blank_figure, 'parse_pane_flag',
                            return_value=([pane.OneDimPane(sigs),
                                          pane.OneDimPane(sigs)], 'alt'))
        blank_figure.set_scales(scales)
        assert set_patch.call_count == 4
        assert scales == s2

        # call for both
        scales = s1.copy()
        mocker.patch.object(blank_figure, 'parse_pane_flag',
                            return_value=([pane.OneDimPane(sigs),
                                           pane.OneDimPane(sigs)], 'all'))
        blank_figure.set_scales(scales)
        assert set_patch.call_count == 6
        assert scales == s3

    def test_end_fit(self, blank_figure, mocker):
        sigs = signals.Signals()
        blank_figure.panes = [pane.OneDimPane(sigs)]
        fit_mock = mocker.patch.object(pane.OneDimPane, 'perform_fit',
                                       return_value=({}, list()))

        # one location - does nothing
        blank_figure._cursor_locations = [[0, 1]]
        blank_figure._end_fit(0)
        assert fit_mock.call_count == 0

        # two locations - should perform fit
        blank_figure._cursor_locations = [[0, 1], [2, 3]]
        blank_figure._end_fit(0)
        assert fit_mock.call_count == 1

        # same if locations are reversed
        blank_figure._cursor_locations = [[2, 3], [0, 1]]
        blank_figure._end_fit(0)
        assert fit_mock.call_count == 2

    def test_toggle_fits_visibility(self, blank_figure, gauss_model_fit,
                                    moffat_model_fit, grism_hdul):
        # no fits, nothing happens
        fits = list()
        blank_figure.toggle_fits_visibility(fits)
        assert len(blank_figure.gallery.arts['fit']) == 0

        # with fit, no panes, nothing happens
        fits = [gauss_model_fit]
        blank_figure.toggle_fits_visibility(fits)
        assert len(blank_figure.gallery.arts['fit']) == 0

        # with fit and pane and matching fields, fit gallery
        # are attempted to be regenerated, but fail because
        # there's no model in the pane
        blank_figure.add_panes(1)
        gauss_model_fit.fields = {'x': 'wavepos', 'y': 'spectral_flux'}
        gauss_model_fit.order = 0
        blank_figure.toggle_fits_visibility(fits)
        assert len(blank_figure.gallery.arts['fit']) == 0

        # add a model to the pane
        model = high_model.Grism(grism_hdul)
        blank_figure.add_model_to_pane(model)
        gauss_model_fit.model_id = model.id
        blank_figure.toggle_fits_visibility(fits)
        assert len(blank_figure.gallery.arts['fit']) == 2
        art1 = blank_figure.gallery.arts['fit'][0].get_artist()

        # remake when axis matches: artist is updated in place
        gauss_model_fit.axis = blank_figure.panes[0].axes()[0]
        blank_figure.toggle_fits_visibility(fits)
        assert len(blank_figure.gallery.arts['fit']) == 2
        art2 = blank_figure.gallery.arts['fit'][0].get_artist()
        assert art2 == art1

        # remake when original artist has been lost: replaces with new artist
        blank_figure.gallery.arts['fit'] = list()
        blank_figure.toggle_fits_visibility(fits)
        assert len(blank_figure.gallery.arts['fit']) == 2
        art3 = blank_figure.gallery.arts['fit'][0].get_artist()
        assert art3 != art1

        # stale_fit_artists should do the same: reset and replace
        blank_figure.stale_fit_artists(fits)
        assert len(blank_figure.gallery.arts['fit']) == 2
        art4 = blank_figure.gallery.arts['fit'][0].get_artist()
        assert art4 != art1

        # with another fit artist added to the same pane:
        # should add the gallery and not reset in between
        moffat_model_fit.fields = {'x': 'wavepos', 'y': 'spectral_flux'}
        moffat_model_fit.order = 0
        moffat_model_fit.model_id = model.id
        moffat_model_fit.axis = blank_figure.panes[0].axes()[0]
        fits.append(moffat_model_fit)
        blank_figure.stale_fit_artists(fits)
        assert len(blank_figure.gallery.arts['fit']) == 4

    def test_update_reference_lines(self, caplog, qtbot, blank_figure,
                                    grism_hdul):
        caplog.set_level(logging.DEBUG)

        # only reset for empty reference/panes
        ref = reference_model.ReferenceData()
        with qtbot.wait_signal(blank_figure.signals.atrophy_bg_partial):
            blank_figure.update_reference_lines(ref)
        assert 'Resetting reference artists' in caplog.text
        assert 'Updated reference' not in caplog.text

        # add data and lines
        model = high_model.Grism(grism_hdul)
        blank_figure.add_model_to_pane(model)
        ref.line_list = {'1': [5.1], '2': [6.3], '3': [7.4]}
        ref.line_unit = u.um
        ref.set_visibility('all', True)

        # reference lines added
        with qtbot.wait_signal(blank_figure.signals.atrophy_bg_partial):
            blank_figure.update_reference_lines(ref)
        assert 'Resetting reference artists' in caplog.text
        assert 'Updated reference' in caplog.text

    def test_model_extensions(self, mocker, blank_figure, grism_hdul):
        model = high_model.Grism(grism_hdul)
        blank_figure.add_model_to_pane(model)

        ext = blank_figure.model_extensions(model.id)
        assert ext == list()
        ext = blank_figure.model_extensions(model.id, pane_index=0)
        assert 'SPECTRAL_FLUX' in ext

    def test_unload_reference_model(self, mocker, blank_figure, grism_hdul):
        ref = reference_model.ReferenceData()

        # no op if no panes
        blank_figure.unload_reference_model(ref)

        # add a pane: calls unload_ref_model
        model = high_model.Grism(grism_hdul)
        blank_figure.add_model_to_pane(model)

        m1 = mocker.patch.object(blank_figure.panes[0], 'unload_ref_model')
        blank_figure.unload_reference_model(ref)
        m1.assert_called_once()

    def test_change_axis_limits(self, mocker, blank_figure, grism_hdul):
        # add data and lines
        model = high_model.Grism(grism_hdul)
        blank_figure.add_model_to_pane(model)
        ref = reference_model.ReferenceData()
        ref.line_list = {'1': [5.1], '2': [6.3], '3': [7.4]}
        ref.line_unit = u.um
        ref.set_visibility('all', True)
        blank_figure.update_reference_lines(ref)

        m1 = mocker.patch.object(blank_figure.gallery,
                                 'update_reference_data')

        # change limits
        blank_figure.change_axis_limits({'x': [4, 6]})
        assert m1.call_count == 1

        # reset zoom: update called again
        blank_figure.reset_zoom()
        assert m1.call_count == 2

        # zoom by mouse: also calls update
        blank_figure._cursor_locations = [[4, 4], [6, 4]]
        blank_figure._end_zoom(0, 'x')
        assert m1.call_count == 3

    def test_end_zoom_bad_call(self, blank_figure, mocker, caplog, grism_hdul):
        caplog.set_level(logging.DEBUG)
        model = high_model.Grism(grism_hdul)
        blank_figure.add_model_to_pane(model)

        blank_figure._cursor_locations = [(2, 4)]
        blank_figure._cursor_mode = 'x-zoom'

        blank_figure._end_zoom(0)

        assert 'Cancelling zoom' in caplog.text
        assert len(blank_figure._cursor_locations) == 0


from pprint import pprint
import pytest
from graphql_relay import to_global_id

INGEST_RUN = """
query ($id: ID!) {
    ingestRun(id: $id) {
        id
        name
        inputHash
        startedAt
        stoppedAt
        versions {
          edges {
            node {
              kfId
            }
          }
        }
    }
}
"""

ALL_INGEST_RUNS = """
query {
    allIngestRuns {
     edges {
       node {
         id
         name
         inputHash
         startedAt
         stoppedAt
         versions {
           edges {
             node {
               kfId
             }
           }
         }
       }
     }
  }
}
"""

FILTER_ALL_INGEST_RUNS = """
query ($name: String!){
    allIngestRuns(name_Icontains: $name) {
     edges {
       node {
         id
         name
         startedAt
         stoppedAt
         versions {
           edges {
             node {
               kfId
             }
           }
         }
       }
     }
  }
}
"""

@pytest.mark.parametrize(
    "user_group,allowed",
    [
        ("Administrators", True),
        ("Services", False),
        ("Developers", False),
        ("Investigators", False),
        ("Bioinformatics", False),
        (None, False),
    ],
)
def test_query_ingest_run(db, clients, ingest_runs, user_group, allowed):
    client = clients.get(user_group)

    ingest_run = ingest_runs(n=1)[0]

    variables = {"id": to_global_id("IngestRunNode", ingest_run.id)}

    resp = client.post(
        "/graphql",
        data={"query": INGEST_RUN, "variables": variables},
        content_type="application/json",
    )

    if allowed:
        node = resp.json()["data"]["ingestRun"]
        assert node["id"] == to_global_id("IngestRunNode", ingest_run.id)
        assert node["name"]
        assert node["versions"]
    else:
        assert resp.json()["errors"][0]["message"] == "Not allowed"

@pytest.mark.parametrize(
    "user_group,allowed",
    [
        ("Administrators", True),
        ("Services", False),
        ("Developers", False),
        ("Investigators", False),
        ("Bioinformatics", False),
        (None, False),
    ],
)
def test_query_all_ingest_runs(db, clients, ingest_runs, user_group, allowed):
    client = clients.get(user_group)

    # Create an ingest run for each file
    n = 2
    ingest_runs(n=n)

    resp = client.post(
        "/graphql",
        data={"query": ALL_INGEST_RUNS},
        content_type="application/json",
    )

    if allowed:
        pprint(resp.json())
        edges = resp.json()["data"]["allIngestRuns"]["edges"]
        assert len(edges) == n
        for edge in edges:
            assert "id" in edge["node"]
            assert "name" in edge["node"]
            assert "versions" in edge["node"]
    else:
        assert resp.json()["errors"][0]["message"] == "Not allowed"

@pytest.mark.parametrize(
    "user_group,allowed",
    [
        ("Administrators", True),
        ("Services", False),
        ("Developers", False),
        ("Investigators", False),
        ("Bioinformatics", False),
        (None, False),
    ],
)
def test_filter_query_all_ingest_runs(
    db, clients, ingest_runs, user_group, allowed
):
    client = clients.get(user_group)

    # Create an ingest run for each file
    ingest_runs = ingest_runs(n=2)
    version_id_filter = ingest_runs[0].versions.first().kf_id

    resp = client.post(
        "/graphql",
        data={
            "query": FILTER_ALL_INGEST_RUNS,
            "variables": {"name": version_id_filter},
        },
        content_type="application/json",
    )

    if allowed:
        edges = resp.json()["data"]["allIngestRuns"]["edges"]
        assert len(edges) == 1
        assert version_id_filter in edges[0]["node"]["name"]
    else:
        assert resp.json()["errors"][0]["message"] == "Not allowed"