from rest_framework import status
from rest_framework.test import APITestCase
from user.tests.test_apis import AuthMixin

from gallery.models import File, FilePreview
from django.conf import settings

import os
import tempfile

class GalleryTests(AuthMixin, APITestCase):
    """
    Gallery Tests
    """
    def setUp(self):
        """
        Get HTTP_AUTHORIZATION header
        Create temp file
        """
        self.auth = self.get_auth()
        tmp_file = tempfile.NamedTemporaryFile(delete=False)
        tmp_file.write(b'Hello world')
        tmp_file.close()

        path = os.path.join(settings.TEST_DIR, 'documents')
        self.supported_file = os.path.join(path, 'doc.docx')
        self.unsupported_file = tmp_file.name

    def tearDown(self):
        """
        Delete test file
        """
        os.unlink(self.unsupported_file)

    def test_upload_supported_file(self):
        """
        Test if file uploads successfully
        """

        last_count = File.objects.count()
        url = '/api/v1/files/'

        data = {
            'title': 'Test file',
            'file': open(self.supported_file, 'rb'),
            'isPublic': True,
        }

        response = self.client.post(url, data,
                                    HTTP_AUTHORIZATION=self.auth,
                                    format='multipart')
        self.assertEqual(response.status_code, status.HTTP_201_CREATED)
        self.assertEqual(File.objects.count(), last_count + 1)
        self.assertEqual(response.data['title'], data['title'])

        # Let's delete the file from the filesystem to keep
        # things clean
        last = File.objects.last()
        if os.path.isfile(last.file.path):
            os.unlink(last.file.path)

        # TODO Retrive contents from url data['file'] and assert
        # the text data.

    def test_upload_unsupported_file(self):
        """
        Test if file uploads unsuccessfully
        """

        last_count = File.objects.count()
        url = '/api/v1/files/'

        data = {
            'title': 'Test file',
            'file': open(self.unsupported_file, 'rb'),
            'isPublic': True,
        }

        response = self.client.post(url, data,
                                    HTTP_AUTHORIZATION=self.auth,
                                    format='multipart')
        self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
        self.assertEqual(File.objects.count(), last_count)

    def test_trigger_api(self):
        """
        Test if file preview is triggered and gives proper response
        Actual task is tested in test_tasks
        """
        url = '/api/v1/file-extraction-trigger/'
        data = {
            'file_ids': [1],
        }
        response = self.client.post(url, data,
                                    format='json',
                                    HTTP_AUTHORIZATION=self.auth)
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertTrue(FilePreview.objects.filter(
            id=response.data['extraction_triggered']
        ).exists())

    def test_duplicate_trigger_api(self):
        """
        Test if preview with same file ids is returned as is and not triggered
        again
        """
        preview = FilePreview.objects.create(file_ids=[1, 2], text='dummy')
        url = '/api/v1/file-extraction-trigger/'
        data = {
            'file_ids': [2, 1],
        }
        response = self.client.post(url, data,
                                    format='json',
                                    HTTP_AUTHORIZATION=self.auth)
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertEqual(response.data['extraction_triggered'], preview.id)

    def test_preview_api(self):
        """
        Test the preview api to get previously triggered preview
        """
        preview = FilePreview.objects.create(file_ids=[], text='dummy')

        url = '/api/v1/file-previews/{}/'.format(preview.id)
        response = self.client.get(url, HTTP_AUTHORIZATION=self.auth)
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertEqual(response.data['text'], preview.text)


from gnuradio import gr
from gnuradio import digital
from gnuradio import blocks
from gnuradio import analog
from gnuradio import filter
from gnuradio.filter import firdes
import ecss
import sys

class demodulator(gr.hier_block2):
    """
    docstring for block demodulator
    """
    def __init__(self, k, cl_loop_bandwidth, cl_order, cl_freq_sub, ss_sps, ss_loop_bandwidth, ss_ted_gain, ss_damping, ss_max_dev, ss_out_ss, ss_interpolation, ss_ted_type, ss_constellation, ss_nfilter, ss_pfb_mf_taps, sel_costas, sel_spl, samp_rate):
        gr.hier_block2.__init__(self,
            "demodulator",
            gr.io_signature(1, 1, gr.sizeof_float),  # Input signature
            gr.io_signature(1, 1, gr.sizeof_char)) # Output signature

        ##################################################
        # Variables
        ##################################################
        self.k = k
        self.cl_loop_bandwidth = cl_loop_bandwidth
        self.cl_order = cl_order
        self.cl_freq_sub = cl_freq_sub

        self.ss_sps = ss_sps
        self.ss_loop_bandwidth = ss_loop_bandwidth
        self.ss_ted_gain = ss_ted_gain
        self.ss_damping = ss_damping
        self.ss_max_dev = ss_max_dev
        self.ss_out_ss = ss_out_ss
        self.ss_interpolation = ss_interpolation
        self.ss_ted_type = ss_ted_type
        self.ss_constellation = ss_constellation
        self.ss_nfilter = ss_nfilter
        self.ss_pfb_mf_taps = ss_pfb_mf_taps

        self.sel_costas = sel_costas
        self.sel_spl = sel_spl
        self.samp_rate = samp_rate

        ##################################################
        # Blocks
        ##################################################

        self.digital_sync = digital.symbol_sync_ff(self.ss_ted_type, self.ss_sps, self.ss_loop_bandwidth, self.ss_damping, self.ss_ted_gain, self.ss_max_dev, self.ss_out_ss, self.ss_constellation, self.ss_interpolation, self.ss_nfilter, (self.ss_pfb_mf_taps))

        self.spl_decoder = ecss.spl_decoder()

        self.costas_loop_cc = digital.costas_loop_cc(self.cl_loop_bandwidth, self.cl_order, False)
        self.signal_gen = analog.sig_source_c(samp_rate, analog.GR_SIN_WAVE, self.cl_freq_sub , 1, 0)
        self.multiply = blocks.multiply_vcc(1)

        self.hilbert = filter.hilbert_fc(65, firdes.WIN_HAMMING, 6.76)
        self.null_complex = blocks.null_sink(gr.sizeof_gr_complex*1)
        self.null_float = blocks.null_sink(gr.sizeof_float*1)
        self.to_char = blocks.float_to_uchar()
        self.unpack = blocks.unpack_k_bits_bb(k)

        ##################################################
        # Connections
        ##################################################

        if (sel_costas == 0):
            # if (type == 0):
            #     self.connect(self, (self.multiply, 0))
            # else:
            self.connect(self, self.hilbert,(self.multiply, 0))

            self.connect(self.signal_gen, (self.multiply, 1))
            self.connect(self.multiply, self.costas_loop_cc)
            self.connect((self.costas_loop_cc, 0), self.null_complex)
            self.connect((self.costas_loop_cc, 1), self.null_float)
            self.connect((self.costas_loop_cc, 2), self.digital_sync)
        else:
            self.connect(self, self.digital_sync)

        if (sel_spl == 0):
            self.connect(self.digital_sync, self.spl_decoder, self.unpack, self)
        else:
            self.connect(self.digital_sync, self.to_char, self.unpack, self)


class Node:
    def __init__(self,val=0):
        self.val=val
        self.next=None
class sll:
    def __init__(self):
        self.head=None
    def insertatbegin(self,data):
        if self.head==None:
            self.head=Node(data)
        else:
            new=Node(data)
            new.next=self.head
            self.head=new
    def deleteatend(self):
        if self.head==None:
            return
        temp=self.head
        while(temp.next.next):
            temp=temp.next
        temp.next=None
    def printing(self):
        temp=self.head
        while(temp!=None):
            print(temp.val)
            temp=temp.next
l=[2,4,6,8,9]
c=sll()
for i in l:
    c.insertatbegin(i)

print("Deleted Element:",c.deleteatend())
print("After Deleting at end the list is:")
c.printing()


from troposphere import Tags, Tag, Template
from troposphere.s3 import (
    Bucket,
    NotificationConfiguration,
    EventBridgeConfiguration,
    LifecycleConfiguration,
    LifecycleRule,
    LifecycleRuleTransition,
)

from troposphere.ecr import Repository

t = Template()
t.set_version("2010-09-09")

bucket = t.add_resource(
    Bucket(
        'DataScienceBucket',
        NotificationConfiguration=NotificationConfiguration(
            EventBridgeConfiguration=EventBridgeConfiguration(
                EventBridgeEnabled=True
            )
        ),
        LifecycleConfiguration=LifecycleConfiguration(
            Rules=[
                LifecycleRule(
                    Id='DataRule',
                    Prefix='data',
                    Status='Enabled',
                    Transitions=[
                        LifecycleRuleTransition(
                            TransitionInDays=180,
                            StorageClass='STANDARD_IA'
                        )
                    ]
                ),
                LifecycleRule(
                    Id='MetadataRule',
                    Prefix='preprocessing',
                    Status='Enabled',
                    ExpirationInDays=7
                )
            ]
        ),
        DeletionPolicy='Retain',
        UpdateReplacePolicy='Retain',
        Tags=Tags(Name="Bucket - Data Science", CreatedBy='data-science-pipeline'),
    )
)

repository = t.add_resource(
    Repository(
        "DataSciencePreprocessing",
        RepositoryName="data-science-preprocessing",
        Tags=Tags(Name="ECR - Data Science Preprocessing", CreatedBy='data-science-pipeline')
    )
)

repository = t.add_resource(
    Repository(
        "DataScienceTraining",
        RepositoryName="data-science-training",
        Tags=Tags(Name="ECR - Data Science Training", CreatedBy='data-science-pipeline'),
    )
)

repository = t.add_resource(
    Repository(
        "DataScienceInference",
        RepositoryName="data-science-inference",
        Tags=Tags(Name="ECR - Data Science Inference", CreatedBy='data-science-pipeline')
    )
)

with open('bootstrap.yml', 'w') as f:
    f.write(t.to_yaml())


# -*- coding: utf-8 -*-
"""
Created on Thu Oct 10 21:28:13 2019

@author: Danylo.Rusyn
"""

import cv2
camera = cv2.VideoCapture(0)
ret, image = camera.read()
cv2.imwrite('Photo.png', image)
camera.release()
cv2.imshow('My_Photo', image)
image = cv2.imread('Photo.png')
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
image = cv2.cvtColor(image, cv2.COLOR_GRAY2BGR)
cv2.line(image, (0, 0), (image.shape[1], image.shape[0]) , (255,0 , 190), 8)
cv2.rectangle(image, (12, 12), (365, 355), (0, 100, 255), 8)
cv2.imwrite('Photo.png', image)
cv2.imshow('My_Photo', image)
cv2.waitKey(0)
cv2.destroyAllWindows()


def rule1(min,max,letter,pwd):
    letter_count = pwd.count(letter)
    if (letter_count <= max) and (letter_count >= min):
        return True
    else:
        return False

def rule2(min,max,letter,pwd):

    check1 = (pwd[min - 1] == letter)
    check2 = (pwd[max - 1] == letter)
    if check1:
        if check2:
            return False
        else:
            return True

    else:
        if check2:
            return True

    return False

def run(file_path,rule=rule2):

    lines = open(file_path).readlines()
    valid = 0
    for line in lines:
        line = line.split()
        min , max = tuple(line[0].split('-'))
        min, max = int(min), int(max)
        letter = line[1].replace(':', '')

        if rule(min,max,letter,line[2]):
            valid += 1

    print(f"Num valid = {valid}")

if __name__ == '__main__':
    path = 'data/day2.txt'

    print("Running part 1")
    run(path,rule1)
    print("Running part 2")
    run(path, rule2)


import tensorflow as tf
from tensorflow.python.keras.layers import LeakyReLU

from optimization import create_optimizer

product_dim = 150
new_product_dim = 34

def get_model():
    training = tf.placeholder(tf.bool)  # Can be any computed boolean expression.

    birth_date = tf.placeholder(tf.float32, [None], name="birth_date")
    history = tf.placeholder(tf.float32, [None, product_dim], name="history")
    consumer_product = tf.placeholder(tf.float32, [None], name="current_products")
    business_product = tf.placeholder(tf.float32, [None], name="current_products")
    current_products = tf.placeholder(tf.float32, [None, product_dim], name="current_products")
    new_product = tf.placeholder(tf.float32, [None, new_product_dim], name="new_product")

    from tensorflow.contrib import slim

    hidden = tf.concat(
        [
            slim.fully_connected(tf.expand_dims(birth_date, axis=1), 2, activation_fn=LeakyReLU(),
                                 weights_initializer=tf.truncated_normal_initializer(mean=0.0, stddev=.1)),
            slim.fully_connected(history, 20, activation_fn=LeakyReLU(),
                                 weights_initializer=tf.truncated_normal_initializer(mean=0.0, stddev=.1)),
            slim.fully_connected(current_products, 20, activation_fn=LeakyReLU(),
                                 weights_initializer=tf.truncated_normal_initializer(mean=0.0, stddev=.1)),
            slim.fully_connected(tf.expand_dims(consumer_product, axis=1), 1, activation_fn=LeakyReLU(),
                                 weights_initializer=tf.truncated_normal_initializer(mean=0.0, stddev=.1)),
            slim.fully_connected(tf.expand_dims(business_product, axis=1), 1, activation_fn=LeakyReLU(),
                                 weights_initializer=tf.truncated_normal_initializer(mean=0.0, stddev=.1))
        ]
        , axis=1)

    hidden = slim.fully_connected(hidden, 20, activation_fn=LeakyReLU(), weights_initializer=tf.truncated_normal_initializer(mean=0.0, stddev=.1))
    hidden = slim.fully_connected(hidden, 20, activation_fn=LeakyReLU(), weights_initializer=tf.truncated_normal_initializer(mean=0.0, stddev=.1))
    hidden = tf.layers.dropout(hidden, rate=.5, training=training)  # DROP-OUT here

    out = slim.fully_connected(hidden, new_product_dim, activation_fn=LeakyReLU(), weights_initializer=tf.truncated_normal_initializer(mean=0.0, stddev=.1))
    out = out
    #out = tf.Print(out, [out, tf.shape(out)], "out: ", summarize=100)
    loss = tf.losses.mean_squared_error(new_product, out)

    #optimizer = tf.train.AdamOptimizer(learning_rate=.00001).minimize(loss)
    optimizer = create_optimizer(loss, .001, 100000, 100, False)
    return birth_date, history, current_products, consumer_product, business_product, new_product, loss, optimizer, out, training


import random
import numpy as np

class cell:
    def __init__(self, r, c):
        self.options = [i for i in range(1, 10)]
        self.value = 0
        self.n_row = r
        self.n_column = c
        self.group = []
        self.row = []
        self.column = []

    def __repr__(self):
        return str(self.value)

    def collapse(self):
        choice = random.choice(self.options)

        for item in self.group:
            item.remove_choice(choice)
        for item in self.row:
            item.remove_choice(choice)
        for item in self.column:
            item.remove_choice(choice)

        self.value = choice

    def remove_choice(self, choice):
        if choice in self.options:
            self.options.remove(choice)

    def option_count(self):
        return len(self.options)

    def add_group(self, c):
        if c not in self.group:
            self.group.append(c)

        if self not in c.group:
            c.group.append(self)

    def add_row(self, c):
        if c not in self.row:
            self.row.append(c)

        if self not in c.row:
            c.row.append(self)

    def add_column(self, c):
        if c not in self.column:
            self.column.append(c)

        if self not in c.column:
            c.column.append(self)

def make_board():
    board = np.empty((9, 9), dtype=cell)
    for i in range(9):
        for j in range(9):
            board[i][j] = cell(i, j)

    for i in range(9):
        for item in board[i]:
            for other in board[i]:
                item.add_row(other)

    for i in range(9):
        for j in range(9):
            for k in range(9):
                board[i][j].add_column(board[k][j])

    for gi in range(3):
        for gj in range(3):
            for i in range(3):
                for j in range(3):
                    for ci in range(3):
                        for cj in range(3):
                            board[ci + 3 * gi][cj + 3 * gj].add_group(board[i + 3 * gi][j + 3 * gj])

    flat_board = board.flatten()
    un_collapsed = [item for item in flat_board]
    while un_collapsed:
        flat_board = board.flatten()
        min_entropy = random.choice(un_collapsed)
        for item in flat_board:
            if item.option_count() < min_entropy.option_count():
                if item.value == 0:
                    min_entropy = item
        try:
            min_entropy.collapse()
            un_collapsed.remove(min_entropy)
        except:
            break
    flat_board.resize(9, 9)
    return flat_board

def new_board():
    board = make_board()
    while 0 in board:
        board = make_board()
    return board

def new_play_board(difficulty):
    board = new_board().flatten()
    play = board.flatten()
    for i in range(difficulty):
        item = random.choice(board)
        np.delete(board, np.where(board == item))
        play[np.where(play == item)] = 0
    play.resize(9, 9)
    return play

if __name__ == "__main__":
    print(new_play_board(90))


import scrapy
import pandas as pd
import re

from DiveSiteScraping.items import AquanautDiveClubItems

class DiveClubsGermanySpider(scrapy.Spider):
    name = "dive_clubs_germany"
    allowed_domains = ["dive-centers.net"]
    start_urls = ["http://dive-centers.net/dive_clubs-germany-20.html"]

    def parse(self, response):

        htmls = response.css('table .a')

        for i in range(19, 30):
            url = 'http://www.dive-centers.net' + htmls[i].css('a').attrib['href']

            yield response.follow(url, self.parse_dive_club_page)

    def parse_dive_club_page(self, response):

        club_items = AquanautDiveClubItems()

        tables = pd.read_html(response.url)

        country = tables[6][tables[6][0] == 'Country:'][1][0]
        city = tables[6][tables[6][0] == 'Region:'][1].iloc[0]
        phone_number_row = [row for row in tables[6][0] if 'phone' in str(row)]
        if len(phone_number_row) > 0:
            phone_number = tables[6][tables[6][0] == phone_number_row[0]][1].iloc[0]
        else:
            phone_number = None

        text = response.xpath('tr//text()').getall()
        text = ' '.join(text)
        email = re.findall(r'[\w.+-]+@[\w-]+\.[\w.-]+', text)
        email = None if len(email) == 0 else email

        club_url = response.css('td .a a::text')[2].get()

        if 'www.' not in club_url:
            try:
                club_url = response.css('td .a a::text')[3].get()
            except:
                pass

        club_items['url'] = response.url
        club_items['tag'] = None
        club_items['date'] = None
        club_items['club_name'] = response.css('h2::text')[0].get()
        club_items['building'] = None
        club_items['city'] = city
        club_items['country'] = country
        club_items['club_url'] = club_url
        club_items['contact'] = None
        club_items['phone'] = phone_number
        club_items['email'] = email

        yield club_items


#!/usr/bin/env python2

from flask import Flask, render_template, request
from flask_bootstrap import Bootstrap
import sys
sys.path.append("../lib")
from madras import MADRASClient

# Needed because of unicode strings
import locale
locale.setlocale(locale.LC_ALL, '')

# Uses flask-bootstrap:
# https://pythonhosted.org/Flask-Bootstrap/basic-usage.html
# sudo pip2 install flask-bootstrap

app = Flask(__name__)
mclient = MADRASClient("http://localhost:8080")

@app.route('/')
def index(editing=None, settings=None):
    # Get a list of plugins we can add
    new_plugins = [str(x) for x in mclient.listPlugins().keys()]
    new_plugins = sorted(new_plugins, key=str.lower)

    plugin_chain = mclient.viewChain()
    if plugin_chain == None: plugin_chain = {}
    # Plugin chain is a dict which maps an index to a plugin obj
    # Want to have it as 0, Chorus as a tuple
    pchain_lst = []
    for k in plugin_chain.keys():
        pchain_lst.append((k, plugin_chain[k]['type']))
    pchain_lst = sorted(pchain_lst, key=lambda x: x[0])

    return render_template('index.html',
                           plugins = new_plugins,
                           plugin_chain = pchain_lst,
                           editing = editing,
                           settings = settings)

@app.route('/add/<plugin>')
def add(plugin):
    mclient.addPlugin(plugin)
    return index()

@app.route('/edit/<id>')
def edit(id):
    settings = mclient.getPlugin(id)

    # Get rid of trailing zeros on floats
    for p in settings['parameters']:
        val = str(settings['parameters'][p]['value'])
        val = val.rstrip('0').rstrip('.')
        settings['parameters'][p]['value'] = val

    return index(editing = id, settings = settings)

@app.route('/delete/<id>')
def delete(id):
    mclient.removePlugin(id)
    return index()

@app.route('/update', methods=['POST'])
def update():
    id = request.form['_plugin_id']
    newSettings = {}
    for k, v in request.form.iteritems():
        if k == "_plugin_id":
            continue
        else:
            # Update each value with the API
            mclient.updatePlugin(id, k, v)

    return edit(id)

def bootstrap_app():
    Bootstrap(app)
    return app

if __name__ == '__main__':
    bootstrap_app().run(debug=True, host='0.0.0.0')


class Solution:
    # @param A : integer
    # @param B : integer
    # @param C : integer
    # @return an integer
    def pow(self, A, B, C):

        if A == 0:
            return 0
        elif B == 0:
            return 1

        ans = self.pow(A, B // 2, C) % C
        ans = (ans * ans) % C
        if B % 2 == 1:
            ans = (ans * A) % C

        return (ans + C) % C

Advanced/06 Advanced DSA : Maths - Modular Arithmetic/Assignment/Q3. Implement Power Function/Implement Power Function.py


from quspin.basis import spin_basis_1d
from quspin.operators import hamiltonian
from numpy.random import default_rng
from numpy import float64, array
from numpy.linalg import eigvalsh, eigh
from scipy.special import binom
from scipy.sparse.linalg import eigsh

class SpinChain:

    def __init__(self,L,N_up,W,Delta,pbc=True,J=[1.0,1.0],seed=None,dtype=float64):
        """
        Creates a Chain object representing a 1d Heisenberg chain.
        Args:
            L: int
                The length of the chain
            N_up: int
                The number of "up" spins. If None, the whole Fock space (ie, all S_z sectors)
                    is included.
            W: float
                The disorder strength. The (random) on-site potential is sampled from a
                    the uniform distribution [-W/2 , W/2].
            Delta: float
                The interaction strength (e.g. coefficient of the nearest-neighbor S_z-S_z term)
            use_pbc: Bool, optional
                Whether or not to use periodic boundary conditions. Defaults to True
            J: array or float, optional
                The X and Y coupling strengths. Can either be a float (in which case X and Y strengths are
                    are the same and equal to the given value), or a 2-component array-like. Defaults to [1.0,1.0]
            seed: int/unsigned int/etc, optional
                Seed for the random number generator used to generate the on-site potential. Defaults
                    to None, in which case a seed is randomly generated by the RNG
            dtype: dtype, optional
                Data type to use for internal storage of matrix elements. Defaults to numpy.float64
        """
        self.L = L
        self.W = W
        self.Delta = Delta
        self.J = J
        self.N_up = N_up
        self.pbc = pbc
        if type(J) == float:
            self.J = [J,J]
        else:
            self.J = J

        self._rng = default_rng(seed)
        self.on_site = 2*self.W*self._rng.random(self.L) - self.W

        self.dtype = dtype

        self.basis = spin_basis_1d(L=self.L,Nup=self.N_up)

        #Initialize the random on-site potential and nearest-neighbor interaction terms
        self.interactions = [[self.Delta,i,i+1] for i in range(self.L-1)]
        if self.pbc:
            self.interactions.append([self.Delta,self.L-1,0])

        self.on_site_pot = [[self.on_site[i] , i] for i in range(self.L)]

        self.diags = [["zz" , self.interactions] , ["z" , self.on_site_pot]]

        #Initialize the spin flip terms
        self._X = [[self.J[0],i,i+1] for i in range(self.L-1)]
        self._Y = [[self.J[1],i,i+1] for i in range(self.L-1)]
        if self.pbc:
            self._X.append([self.J[0],L-1,0])
            self._Y.append([self.J[1],L-1,0])

        self.off_diags = [['xx', self._X],['yy',self._Y]]

        #Construct the Hamiltonian from the above terms
        self._Ham = hamiltonian(self.diags+self.off_diags,[],dtype=self.dtype,basis=self.basis,check_symm=False,check_herm=False,check_pcon=False)
        self.H = self._Ham.static

        self.energies= None
        self.eigenvectors = None

    #### ****                                           **** ####
    ####     HAMILTONIAN CREATION/MANIPULATION FUNCTIONS     ####
    #### ****                                           **** ####

    def create_H(self):
        """
        Create the Hamiltonian for this Chain.
        """
        self._Ham = hamiltonian(self.diags+self.off_diags,[],dtype=self.dtype,basis=self.basis,check_symm=False,check_herm=False,check_pcon=False)
        self.H = self._Ham.static

    def make_diag(self):
        """
        Update the diagonal terms of this Hamiltonian, and call create_H() to make the Hamiltonian
            matrix.
        """
        self.interactions = [[self.Delta,i,i+1] for i in range(self.L-1)]
        if self.pbc:
            self.interactions.append([self.Delta,self.L-1,0])
        self.on_site_pot = [[self.on_site[i] , i] for i in range(self.L)]
        self.diags = [["zz" , interactions] , ["z" , on_site_pot]]
        self.create_H()

    def new_disorder(self,disorder=None):
        """
        Generates a new disorder realization, or sets it to a user-supplied realization, and updates
            the Hamiltonian.

        Args:
            disorder: array, optional
                The new disorder realization. If None, then generates a new one automatically. Defaults
                    to None
        """
        if disorder is not None:
            self.on_site = disorder
        else:
            self.on_site = 2*self.W*self._rng.random(self.L) - self.W
        self.make_diag()

    #### ****                                     **** ####
    ####     HAMILTONIAN DIAGONALIZATION FUNCTIONS     ####
    #### ****                                     **** ####

    def spectrum(self):
        """
        Compute and return the spectrum of eigenvalues for the current Hamiltonian.
        """
        return eigvalsh(self.H.todense())

    def all_states(self):
        """
        Compute and return the spectrum of eigenvalues - and their associated eigenvectors - for
            the current Hamiltonian.
        """
        return eigh(self.H.todense())

    def spectrum_extrema(self,k,mode='LM',sigma=None):
        """
        Use sparse diagonalization to return the extrema of the spectrum for the current Hamiltonian.
        """
        return eigsh(self.H,k=k,sigma=sigma,which=mode,return_eigenvectors=False)

    def states_extrema(self,k,mode='LM',sigma=None):
        """
        Use sparse diagonalization to return the extrema of the spectrum for the current Hamiltonian.
        Returns the eigenvectors as well
        """
        return eigsh(self.H,k=k,sigma=sigma,which=mode,return_eigenvectors=True)

    #### ****              **** ####
    ####     MISC FUNCTIONS     ####
    #### ****              **** ####

    def dimension(self):
        """
        Return the size of the Hamiltonian matrix for this chain.
        """
        if self.N_up is not None:
            return int(binom(self.L,self.N_up))
        else:
            return 1 << L

    def get_H(self,dense=False):
        """
        Return the Hamiltonian matrix.

        Args:
            dense: Bool, optional
                Whether to return the dense (True) or sparse (False) version of the
                    Hamiltonian matrix. Defaults to False

        Returns:
            H: array or scipy sparse matrix
                The Hamiltonian matrix
        """
        if dense:
            return self.H.todense()
        else:
            return self.H


from PyQt4 import QtGui
from threading import Thread

import cv2
from PyQt4.QtCore import QObject, SIGNAL

class Emitter(QObject, Thread):

    def __init__(self, transport, parent=None):
        QObject.__init__(self,parent)
        Thread.__init__(self)
        self.transport = transport

    def _emit(self, signature, args=None):
        # print("emit ",signature, args)
        if args:
            self.emit(SIGNAL(signature), args)
        else:
            self.emit(SIGNAL(signature))

    def run(self):
        while True:
            try:
                signature, data = self.transport.recv()
                if signature == 'data(QImage)':
                    color_swapped_image = cv2.cvtColor(data, cv2.COLOR_BGR2RGB)

                    height, width, _ = color_swapped_image.shape

                    qt_image = QtGui.QImage(color_swapped_image.data,
                                            width,
                                            height,
                                            color_swapped_image.strides[0],
                                            QtGui.QImage.Format_RGB888)
                    self._emit('data(QImage)',qt_image)

            except EOFError:
                break
            # else:
                # self._emit(*signature)


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

# # Running Mangoes predictions locally

# In[ ]:

# In house mangoes pred (using mangoes as a lib)
import os
import sys
from pathlib import Path

sys.path.append(str(Path(os.path.abspath(os.curdir)).parent))

# In[ ]:

import numpy as np
import glob
import torch
from collections import Counter
from mangoes.modeling import BERTForCoreferenceResolution, MangoesCoreferenceDataset
from transformers import BertTokenizerFast
from tqdm.auto import trange
from pathlib import Path
import pickle
from scipy.optimize import linear_sum_assignment as linear_assignment

# In[ ]:

from config import ROOT_LOC

# In[ ]:

def normalize_word(word, language):
    if language == "arabic":
        word = word[:word.find("#")]
    if word == "/." or word == "/?" or word == "/-":
        return word[1:]
    else:
        return word

print('here')
def parse_document(path, language="english"):
    """
    returns:
        words: Lists of Lists of Lists of strings. list of sentences. One sentence is a list of words.
        cluster_ids: List of Lists of List(int, int).
        speaker_ids: Lists of Lists of Lists of ints.
    """
    doc_keys = []
    doc_sents = []
    doc_speaker_ids = []
    doc_clusters = []
    sentences = []
    sentence_speaker_ids = []
    clusters = {}
    cur_sentence_words = []
    cur_sentence_speaker_ids = []
    docs = 0
    with open(path, "r") as input_file:
        for line in input_file:
            if line.startswith("#begin document"):
                doc_key = line.split()[2][:-1]
                doc_keys.append(doc_key[1:-1])
                num_words = 0
                docs += 1
            elif line.startswith("#end document"):
                assert len(sentences) == len(sentence_speaker_ids)
                assert cur_sentence_words == []
                doc_sents.append(sentences)
                merged_clusters = []
                for c1 in clusters.values():
                    existing = None
                    for m in c1:
                        for c2 in merged_clusters:
                            if tuple(m) in c2:
                                existing = c2
                                break
                        if existing is not None:
                            break
                    if existing is not None:
                        print("Merging clusters (shouldn't happen very often.)")
                        existing.update([tuple(x) for x in c1])
                    else:
                        merged_clusters.append(set([tuple(x) for x in c1]))
                merged_clusters = [list(c) for c in merged_clusters]
                doc_clusters.append(merged_clusters)
                doc_speaker_ids.append(sentence_speaker_ids)
                sentences = []
                sentence_speaker_ids = []
                clusters = {}
            else:
                data = line.split()
                sentence_end = len(data) == 0
                if sentence_end:
                    sentences.append(cur_sentence_words)
                    sentence_speaker_ids.append(cur_sentence_speaker_ids)
                    cur_sentence_words = []
                    cur_sentence_speaker_ids = []
                else:
                    cur_sentence_words.append(normalize_word(data[3], language))
                    cur_sentence_speaker_ids.append(data[9])
                    # get cluster id
                    raw_cluster_id = data[-1]
                    for part in raw_cluster_id.split("|"):
                        if "(" in part:
                            clus_id = part[1:-1] if ")" in part else part[1:]
                            if clus_id not in clusters:
                                clusters[clus_id] = []
                            clusters[clus_id].append([num_words])
                    for part in raw_cluster_id.split("|"):
                        if ")" in part:
                            clus_id = part[1:-1] if "(" in part else part[:-1]
                            for i in range(len(clusters[clus_id]) - 1, -1, -1):
                                if len(clusters[clus_id][i]) == 1:
                                    clusters[clus_id][i].append(num_words)
                                    break
                    num_words += 1
        assert len(doc_sents) == docs
        for i in range(docs):
            doc_keys[i] += f"_{i}"
        return doc_sents, doc_clusters, doc_speaker_ids, doc_keys

def parse_dataset(path):
    dataset_sents = []
    dataset_clusters_words = []
    dataset_speakers = []
    dataset_genres = []
    dataset_doc_keys = []
    for path in glob.iglob(path):

        genre = path.split("/")[-4]
        doc_sents, doc_clusters, doc_speaker_ids, doc_keys = parse_document(path)
        assert len(doc_sents) == len(doc_speaker_ids) == len(doc_keys) == len(doc_clusters)
        dataset_sents += doc_sents
        dataset_genres += [genre] * len(doc_sents)
        dataset_doc_keys += doc_keys
        dataset_clusters_words += doc_clusters
        for d in range(len(doc_speaker_ids)):
            speakers = doc_speaker_ids[d]
            speakers_to_ids = {speaker: i for i, speaker in
                               enumerate(list(set([item for sublist in speakers for item in sublist])))}
            for i in range(len(speakers)):
                for j in range(len(speakers[i])):
                    speakers[i][j] = speakers_to_ids[speakers[i][j]] + 1
            dataset_speakers.append(speakers)
    gen_to_id = {g: i for i, g in enumerate(set(dataset_genres))}
    return dataset_sents, dataset_clusters_words, dataset_speakers, dataset_genres, dataset_doc_keys, gen_to_id

# In[ ]:

model = BERTForCoreferenceResolution.load("bert-base-cased", "SpanBERT/spanbert-base-cased",
                                          max_top_antecendents=50, max_training_segments=3, top_span_ratio=0.4,
                                          ffnn_hidden_size=3000, coref_dropout=0.3, coref_depth=2,
                                          use_metadata=False)

tok = BertTokenizerFast.from_pretrained("bert-base-cased")

# In[ ]:

# In[ ]:

train_path = ROOT_LOC / 'data/raw/ontonotes/conll-2012/v5/data/train/data/english/annotations/*/*/*/*gold_conll'
valid_path = ROOT_LOC / 'data/raw/ontonotes/conll-2012/v5/data/development/data/english/annotations/*/*/*/*gold_conll'

# change this path to point to where the data is
train_sents, train_clusters, train_speakers, train_genres, train_doc_keys, _ = parse_dataset(str(train_path))

# Filter out useless ones
valid_indices = [i for i, x in enumerate(train_clusters) if x]

# In[ ]:

train_sents = [train_sents[i] for i in valid_indices]
train_clusters = [train_clusters[i] for i in valid_indices]
train_speakers = [train_speakers[i] for i in valid_indices]
train_genres = [train_genres[i] for i in valid_indices]
train_doc_keys = [train_doc_keys[i] for i in valid_indices]

# In[ ]:

train_dataset = MangoesCoreferenceDataset(tok, use_metadata=False, max_segment_len=384, max_segments=3,
                                          documents=train_sents, cluster_ids=train_clusters,
                                          speaker_ids=train_speakers, genres=train_genres,
                                          genre_to_id=model.model.genres)

print(len(train_dataset))

# In[ ]:

eval_sents, eval_clusters, eval_speakers, eval_genres, eval_doc_keys, _ = parse_dataset(str(valid_path))

eval_dataset = MangoesCoreferenceDataset(tok, use_metadata=False, max_segment_len=384, max_segments=3,
                                         documents=eval_sents, cluster_ids=eval_clusters,
                                         speaker_ids=eval_speakers, genres=eval_genres,
                                         genre_to_id=model.model.genres)

print(len(eval_dataset))

# In[ ]:

writefl = Path(ROOT_LOC / 'temp/mangoespred')
writefl.mkdir(exist_ok=True, parents=True)
print(writefl.absolute())

# In[ ]:

def f1(p_num, p_den, r_num, r_den, beta=1):
    p = 0 if p_den == 0 else p_num / float(p_den)
    r = 0 if r_den == 0 else r_num / float(r_den)
    return 0 if p + r == 0 else (1 + beta * beta) * p * r / (beta * beta * p + r)

class CorefEvaluator(object):
    def __init__(self):
        self.evaluators = [Evaluator(m) for m in (muc, b_cubed, ceafe)]

    def update(self, predicted, gold, mention_to_predicted, mention_to_gold):
        for e in self.evaluators:
            e.update(predicted, gold, mention_to_predicted, mention_to_gold)

    def get_f1(self):
        return sum(e.get_f1() for e in self.evaluators) / len(self.evaluators)

    def get_recall(self):
        return sum(e.get_recall() for e in self.evaluators) / len(self.evaluators)

    def get_precision(self):
        return sum(e.get_precision() for e in self.evaluators) / len(self.evaluators)

    def get_prf(self):
        return self.get_precision(), self.get_recall(), self.get_f1()

class Evaluator(object):
    def __init__(self, metric, beta=1):
        self.p_num = 0
        self.p_den = 0
        self.r_num = 0
        self.r_den = 0
        self.metric = metric
        self.beta = beta

    def update(self, predicted, gold, mention_to_predicted, mention_to_gold):
        if self.metric == ceafe:
            pn, pd, rn, rd = self.metric(predicted, gold)
        else:
            pn, pd = self.metric(predicted, mention_to_gold)
            rn, rd = self.metric(gold, mention_to_predicted)
        self.p_num += pn
        self.p_den += pd
        self.r_num += rn
        self.r_den += rd

    def get_f1(self):
        return f1(self.p_num, self.p_den, self.r_num, self.r_den, beta=self.beta)

    def get_recall(self):
        return 0 if self.r_num == 0 else self.r_num / float(self.r_den)

    def get_precision(self):
        return 0 if self.p_num == 0 else self.p_num / float(self.p_den)

    def get_prf(self):
        return self.get_precision(), self.get_recall(), self.get_f1()

    def get_counts(self):
        return self.p_num, self.p_den, self.r_num, self.r_den

def b_cubed(clusters, mention_to_gold):
    num, dem = 0, 0

    for c in clusters:
        if len(c) == 1:
            continue

        gold_counts = Counter()
        correct = 0
        for m in c:
            if m in mention_to_gold:
                gold_counts[tuple(mention_to_gold[m])] += 1
        for c2, count in gold_counts.items():
            if len(c2) != 1:
                correct += count * count

        num += correct / float(len(c))
        dem += len(c)

    return num, dem

def muc(clusters, mention_to_gold):
    tp, p = 0, 0
    for c in clusters:
        p += len(c) - 1
        tp += len(c)
        linked = set()
        for m in c:
            if m in mention_to_gold:
                linked.add(mention_to_gold[m])
            else:
                tp -= 1
        tp -= len(linked)
    return tp, p

def phi4(c1, c2):
    return 2 * len([m for m in c1 if m in c2]) / float(len(c1) + len(c2))

def ceafe(clusters, gold_clusters):
    clusters = [c for c in clusters if len(c) != 1]
    scores = np.zeros((len(gold_clusters), len(clusters)))
    for i in range(len(gold_clusters)):
        for j in range(len(clusters)):
            scores[i, j] = phi4(gold_clusters[i], clusters[j])
    matching = linear_assignment(-scores)
    similarity = sum(scores[matching[0], matching[1]])

    # similarity = sum(scores[matching[:, 0], matching[:, 1]])
    return similarity, len(clusters), similarity, len(gold_clusters)

# In[ ]:

coref_evaluator = CorefEvaluator()

# Dumping outputs
for example_index in trange(len(eval_dataset)):
    with torch.no_grad():
        example = eval_dataset[example_index]
        example = {name: tensor.to(model.model_device) for name, tensor in example.items()}
        outputs = model.model.forward(example["input_ids"],
                                      example["attention_mask"],
                                      example["sentence_map"],
                                      #                               speaker_ids=example["speaker_ids"],
                                      #                               genre=example["genre"],
                                      gold_starts=example["gold_starts"],
                                      gold_ends=example["gold_ends"],
                                      cluster_ids=example["cluster_ids"],
                                      return_dict=True)

        gold_clusters = {}
        for i in range(len(example["cluster_ids"])):
            assert len(example["cluster_ids"]) == len(
                example["gold_starts"]) == len(example["gold_ends"])
            cid = example["cluster_ids"][i].item()
            if cid in gold_clusters:
                gold_clusters[cid].append((example["gold_starts"][i].item(),
                                           example["gold_ends"][i].item()))
            else:
                gold_clusters[cid] = [(example["gold_starts"][i].item(),
                                       example["gold_ends"][i].item())]

        gold_clusters = [tuple(v) for v in gold_clusters.values()]
        mention_to_gold = {}
        for c in gold_clusters:
            for mention in c:
                mention_to_gold[mention] = c

        top_indices = torch.argmax(outputs["top_antecedents_score"], dim=-1, keepdim=False)
        ids = outputs["flattened_ids"]
        top_span_starts = outputs["top_span_starts"]
        top_span_ends = outputs["top_span_ends"]
        top_antecedents = outputs["top_antecedents"]
        mention_indices = []
        antecedent_indices = []
        predicted_antecedents = []
        for i in range(len(outputs["top_span_ends"])):
            if top_indices[i] > 0:
                mention_indices.append(i)
                antecedent_indices.append(top_antecedents[i][top_indices[i] - 1].item())
                predicted_antecedents.append(top_indices[i] - 1)

        cluster_sets = []
        for i in range(len(mention_indices)):
            new_cluster = True
            for j in range(len(cluster_sets)):
                if mention_indices[i] in cluster_sets[j] or antecedent_indices[i] in cluster_sets[j]:
                    cluster_sets[j].add(mention_indices[i])
                    cluster_sets[j].add(antecedent_indices[i])
                    new_cluster = False
                    break
            if new_cluster:
                cluster_sets.append({mention_indices[i], antecedent_indices[i]})

        cluster_dicts = []
        clusters = []
        for i in range(len(cluster_sets)):
            cluster_mentions = sorted(list(cluster_sets[i]))
            current_ids = []
            current_start_end = []
            for mention_index in cluster_mentions:
                current_ids.append(ids[top_span_starts[mention_index]:top_span_ends[mention_index] + 1])
                current_start_end.append((top_span_starts[mention_index].item(), top_span_ends[mention_index].item()))
            cluster_dicts.append({"cluster_ids": current_ids})
            clusters.append(tuple(current_start_end))

        mention_to_predicted = {}
        for c in clusters:
            for mention in c:
                mention_to_predicted[mention] = c

        coref_evaluator.update(clusters, gold_clusters, mention_to_predicted, mention_to_gold)

        outputs['_clusters'] = clusters
        outputs['_gold_clusters'] = gold_clusters
        outputs['_mention_to_predicted'] = mention_to_predicted
        outputs['_mention_to_gold'] = mention_to_gold

        # dump to disk
        with (writefl / (str(example_index) + '.pkl')).open('wb+') as f:
            pickle.dump({'input': example, 'output': outputs}, f)

        del example
        del outputs

summary_dict = {}
p, r, f = coref_evaluator.get_prf()
summary_dict["Average F1 (py)"] = f
print("Average F1 (py): {:.2f}% on {} docs".format(f * 100, len(eval_dataset)))
summary_dict["Average precision (py)"] = p
print("Average precision (py): {:.2f}%".format(p * 100))
summary_dict["Average recall (py)"] = r
print("Average recall (py): {:.2f}%".format(r * 100))


import os
import glob
import numpy as np
from scipy import ndimage, misc, optimize, special
import skimage as sk
from skimage.transform import rotate
from tifffile import imread, imsave, imwrite
from roifile import ImagejRoi
import pims
import yaml
import re
from tqdm import trange
from . import io
from scipy.spatial import distance as dist
from matplotlib import pyplot as plt
from PyQt5.QtWidgets import QMessageBox

# ---------------------------------------------------------------------
def get_rect_params(rect, printing=False):
    length = int(np.sqrt((rect[0][0] - rect[3][0])**2 + (rect[0][1] - rect[3][1])**2))
    width = int(np.sqrt((rect[0][0] - rect[1][0])**2 + (rect[0][1] - rect[1][1])**2))
    dy = rect[3][1] - rect[0][1]
    dx = rect[3][0] - rect[0][0]
    if dx == 0 or dy == 0:
        angle = 0
    else:
        m1 = (dy/dx);   # tan(A)
        A = np.arctan(m1) * 180 / np.pi
        angle = 270-A#-(A-90)
    x_cent = int((rect[0, :][0] + rect[2, :][0])/2)
    y_cent = int((rect[0, :][1] + rect[2, :][1])/2)
    if printing:
        print('length:', length, ', width:', width, ', angle:', angle)
    rect_params = {
        'length': length,
        'width' : width,
        'angle' : int(angle),
        'x_cent' : x_cent,
        'y_cent' : y_cent,}
    return rect_params

# ---------------------------------------------------------------------
def crop_rect(img, rect, angle=0):
    # rect : array for rectanglular roi as in napari
    rect_params = get_rect_params(rect)
    if rect_params['angle'] != 0 or angle!=0:
        img_rot = rotate(img, angle=rect_params['angle']+angle)
    else:
        img_rot = img
    x = int(rect_params['x_cent'] - rect_params['width']/2)
    y = int(rect_params['y_cent'] - rect_params['length']/2)
    img_cropped = img_rot[x:x+rect_params['width'], y:y+rect_params['length']]
    return sk.util.img_as_uint(img_cropped)

# ---------------------------------------------------------------------
def rect_shape_to_roi(arr_from_napari):
    arr_from_napari = np.flip(arr_from_napari)
    roi_coord = np.array([arr_from_napari[0], arr_from_napari[3],
                          arr_from_napari[2], arr_from_napari[1]], dtype=np.float32)
    return roi_coord

# ---------------------------------------------------------------------
def save_rectshape_as_imageJroi(shape_layer, folder_to_save=None, label=None, defaultShape=None):
    if folder_to_save is None:
        folder_to_save = io.FileDialog().openDirectoryDialog()
    if not os.path.isdir(folder_to_save):
        os.makedirs(folder_to_save)
    label = cleanLabel(label)

    rect_shape = np.rint(shape_layer.data)
    if len(rect_shape)==0:
        return
    numShapes = len(rect_shape)
    # remove column with all 0 entries
    rect_shape = [rect_shape[i][:,(rect_shape[i]!=0).any(axis=0)] for i in range(len(rect_shape))]
    names = []
    for iRect in range(numShapes):
        if (rect_shape[iRect]==defaultShape).all():
            continue
        rect = np.array(rect_shape[iRect])
        rect = order_points(rect)

        rect_0 = rect[0].astype(int)

        dy = rect[3][1] - rect[0][1]
        dx = rect[3][0] - rect[0][0]
        if dx == 0 or dy == 0:
            angle_roi = int(0)
        else:
            angle_roi = int(np.arctan(dy/dx) * 180 / np.pi)
        width_x = int( np.ceil( np.sqrt(np.sum((rect[3,:]-rect[2,:])**2)) ) )
        height_y = int( np.ceil( np.sqrt(np.sum((rect[2,:]-rect[1,:])**2)) ) )
        nam = 'x' + str(rect_0[0]) + '-y' + str(rect_0[1]) +\
            '-l' + str(height_y) + '-w' + str(width_x) +\
            '-a' + str(angle_roi) + label.lower()
        roi_ij = ImagejRoi.frompoints(rect_shape_to_roi(rect))
        roi_ij.tofile(os.path.join(folder_to_save, nam+'.roi'))
        names.append(nam)

    return names

# ---------------------------------------------------------------------
def roi_to_rect_shape(roi_imagej):
    roi = ImagejRoi.fromfile(roi_imagej)
    roi_coord = np.flip(roi.coordinates())
    arr_rect_napari = np.array([roi_coord[2], roi_coord[1], roi_coord[0], roi_coord[3]], dtype=np.float32)
    return arr_rect_napari

# ---------------------------------------------------------------------
def addroi_to_shapelayer(shape_layer, roi_file_list):
    roi_arr_list = []
    for roi_file in roi_file_list:
        roi_arr = roi_to_rect_shape(roi_file)
        roi_arr_list.append(roi_arr)
    shape_layer.data = roi_arr_list
    return roi_arr_list

# ---------------------------------------------------------------------
def cleanLabel(label):
    if label is not None:
        label = label.replace(' ', '_')
        label = label.replace('-', '_')
        label = label.replace(']', '')
        label = label.replace('[', '')
        if '_' in label:
            fractions = label.rsplit("_")
            label = label.replace('_'+fractions[-1],'') # the last entry is the number of the layer. we remove this
        # in case the last entry was not actually a number, then we have now nothing left
        if len(label) == 0:
            label = fractions[-1]
        if label == 'Shapes': # 'Shapes' is the default name when the user creates a new layer manually
            label = 'ROI'
        # if label dont have a leading underscore, add it
        if label[0] != '_':
            label = '_' + label
    else:
        label = ''
    return label

# ---------------------------------------------------------------------
def readROIassociatedYamlFile(roi_file, num_colors):
    # for all colors in the yaml file
    # if we cannot find it, set all to zero
    yamlFileName = roi_file[:-4] + '.yaml'
    shift_yaml = LoadShiftYamlFile(yamlFileName, 0, 0, 0, num_colors)
    angle = []
    shift_x = []
    shift_y = []
    file_corrected = False

    for col in range(shift_yaml['numColors']):
            if not 'col'+str(int(col)) in shift_yaml['angle'] \
                or not 'col'+str(int(col)) in shift_yaml['x'] \
                or not 'col'+str(int(col)) in shift_yaml['y']:
                shift_yaml['numColors'] = col
                file_corrected = True
                continue
            if "angle" in shift_yaml:
                angle.append(shift_yaml['angle']['col'+str(int(col))])
            else:
                angle.append(0)
            shift_x.append(shift_yaml['x']['col'+str(int(col))])
            shift_y.append(shift_yaml['y']['col'+str(int(col))])

    if file_corrected:
        shift_yaml = io.to_dict_walk(shift_yaml)
        os.makedirs(os.path.dirname(yamlFileName), exist_ok=True)
        with open(yamlFileName, "w") as shift_file:
            yaml.dump(dict(shift_yaml), shift_file, default_flow_style=False)
    return angle, shift_x, shift_y, shift_yaml['numColors']

# ---------------------------------------------------------------------
def LoadShiftYamlFile(yamlFileName, xShift, yShift, angle, numColors):
    if os.path.isfile(yamlFileName): # if it exists, load it. assume there is only one such file
        try:
            yaml_file = open(yamlFileName, "r")
        except FileNotFoundError:
            print('Not found: '+yamlFileName)
            shift_yaml = MakeShiftYamlFile(xShift, yShift, angle, numColors)
            return shift_yaml
        try:
            shift_yaml = yaml.load(yaml_file, Loader=yaml.FullLoader)
            yaml_file.close()
            shift_yaml = io.AutoDict(shift_yaml)
        except:
            print('Found but not readable: '+yamlFileName)
            # it might be here that yaml files are corrupt. This is especially crucial for cropping.
            # If we encounter such a file in a posXX_analysis folder, try to look at the corresponding folder with '_analysis'
            # our folders have usually the names pos or default since we use micromanager
            pos_analysis_folder = re.search("pos\d+_analysis", yamlFileName.lower())
            default_analysis_folder = re.search("default\d+_analysis", yamlFileName.lower())
            if (pos_analysis_folder is not None) or (default_analysis_folder is not None):
                yamlFileInImageFolder = os.path.join(os.path.dirname(yamlFileName)[:-len('_analysis')], 'shift.yaml')
                try:
                    yaml_file = open(yamlFileInImageFolder, "r")
                except FileNotFoundError:
                    print('Alternative yaml file not found: '+yamlFileInImageFolder)
                    shift_yaml = MakeShiftYamlFile(xShift, yShift, angle, numColors)
                try:
                    shift_yaml = yaml.load(yaml_file, Loader=yaml.FullLoader)
                    yaml_file.close()
                    shift_yaml = io.AutoDict(shift_yaml)
                    print('Alternative yaml file loaded: '+yamlFileInImageFolder)
                except:
                    print('Alternative yaml file found but not readable: '+yamlFileInImageFolder)
                    shift_yaml = MakeShiftYamlFile(xShift, yShift, angle, numColors)
            else:
                print('No potential alternative yaml file present.')
                shift_yaml = MakeShiftYamlFile(xShift, yShift, angle, numColors)
    else: # if is doesnt exist, we create all structures from scratch
        print('Given file does not exist: '+yamlFileName)
        shift_yaml = MakeShiftYamlFile(xShift, yShift, angle, numColors)
    return shift_yaml

# ---------------------------------------------------------------------
def MakeShiftYamlFile(xShift, yShift, angle, numColors):
    shift_yaml = {}
    shift_yaml["x"] = {}
    shift_yaml["y"] = {}
    shift_yaml["angle"] = {}
    shift_yaml["numColors"] = numColors
    for nColor in range(numColors):
        shift_yaml["x"]["col"+str(int(nColor))] = xShift
        shift_yaml["y"]["col"+str(int(nColor))] = yShift
        shift_yaml["angle"]["col"+str(int(nColor))] = angle
    return shift_yaml

# ---------------------------------------------------------------
def ShiftROI(coord, dy, dx):

    y = np.array( [x[0] for x in coord] )
    x = np.array( [x[1] for x in coord] )
    return np.array( [[y[i]+dy, x[i]+dx] for i in range(len(coord))] )

# ---------------------------------------------------------------------
def order_points(pts):
    # sorts points clockwise
    # sort the points based on their x-coordinates
    xSorted = pts[np.argsort(pts[:, 0]), :]
    # grab the left-most and right-most points from the sorted
    # x-roodinate points
    leftMost = xSorted[:2, :]
    rightMost = xSorted[2:, :]
    # now, sort the left-most coordinates according to their
    # y-coordinates so we can grab the top-left and bottom-left
    # points, respectively
    leftMost = leftMost[np.argsort(leftMost[:, 1]), :]
    (tl, bl) = leftMost
    # now that we have the top-left coordinate, use it as an
    # anchor to calculate the Euclidean distance between the
    # top-left and right-most points; by the Pythagorean
    # theorem, the point with the largest distance will be
    # our bottom-right point
    D = dist.cdist(tl[np.newaxis], rightMost, "euclidean")[0]
    (br, tr) = rightMost[np.argsort(D)[::-1], :]
    # return the coordinates in top-left, top-right,
    # bottom-right, and bottom-left order
    return np.array([tl, tr, br, bl])

# ---------------------------------------------------------------------
def rotatePoint(point, centerPoint, angleDeg):
    angleRad = angleDeg * np.pi/180
    return np.array([(point[0]-centerPoint[0]) * np.cos(angleRad) - (point[1]-centerPoint[1]) * np.sin(angleRad),
    (point[0]-centerPoint[0]) * np.sin(angleRad) + (point[1]-centerPoint[1]) * np.cos(angleRad)]) + centerPoint

# ---------------------------------------------------------------------
def rotateShiftROI(rect, img, imgSize, shift_x, shift_y, angle, fixedShape=None):
    rect = order_points(rect) # toplleft, topright, bottomrrigt, bottomleft

    # compute angle of the ROI which the user defined (not the angle by whcih the image is rotated)
    # angle between rect and surrounding_rect. surrounding_rect is straight.
    # We measure COUNTERCLOCKWISE since skimage.transform.rotate rotates counter-clockwise
    dy = rect[3][1] - rect[0][1]
    dx = rect[3][0] - rect[0][0]
    if dx == 0 or dy == 0:
        angle_rect_surrounding_rect = 0
    else:
        angle_rect_surrounding_rect = np.arctan(dy/dx) * 180 / np.pi

    # we first rotate the ROI according to the rotation of the image
    if angle != 0:
        centerPoint = np.array(imgSize)/2
        rect = np.array([
            rotatePoint(rect[0], centerPoint, -angle),
            rotatePoint(rect[1], centerPoint, -angle),
            rotatePoint(rect[2], centerPoint, -angle),
            rotatePoint(rect[3], centerPoint, -angle)
        ])

    # plt.figure()
    # plt.imshow(img)
    # # plt.plot(surrounding_rect[:,1], surrounding_rect[:,0])
    # plt.plot(rect[:,1], rect[:,0])
    # # plt.plot(rot_rect[:,1], rot_rect[:,0])
    # # plt.show()

    # plt.figure()
    # plt.imshow(rotate(img, angle=angle))
    # # plt.plot(surrounding_rect[:,1], surrounding_rect[:,0])
    # plt.plot(rect[:,1], rect[:,0])
    # plt.plot(rot_rect[:,1], rot_rect[:,0])
    # plt.show()

    if (shift_y!=0 or shift_x!=0):
        rect[:,0] = rect[:,0]-shift_y
        rect[:,1] = rect[:,1]-shift_x
    rect = np.round(rect)

    # rect[rect<0] = 0
    # rect[:,0][rect[:,0]>imgSize[0]] = imgSize[0]
    # rect[:,1][rect[:,1]>imgSize[1]] = imgSize[1]
    # if col==0 and i==0: # check again if dimensions are > 0. otherwise skip
    #     if not (np.sqrt(np.sum((rect[3,:]-rect[2,:])**2))>0) and not (np.sqrt(np.sum((rect[2,:]-rect[1,:])**2))>0):
    #         print('Skipping ROI ['+str(iRect+1)+'/'+str(len(rect_shape))+']')
    #         continue

    # obtain min and max values of the surrounding rectangle
    minx = np.min(rect[:,0], axis=0)
    maxx = np.max(rect[:,0], axis=0)
    miny = np.min(rect[:,1], axis=0)
    maxy = np.max(rect[:,1], axis=0)
    surrounding_rect = np.array([
        [minx, miny], \
        [maxx, miny], \
        [maxx, maxy], \
        [minx, maxy], \
        ]) # topleft, topright, bottomrrigt, bottomleft
        # the centers of the rectangle and surrounding rectangle are the same

    # plt.figure()
    # plt.imshow(img)
    # plt.plot(surrounding_rect[:,1], surrounding_rect[:,0])
    # plt.plot(rect[:,1], rect[:,0])
    # plt.show()

    # now we cropped the surrounding rectangle, let's take away this rotation from the ROI again to leave only with the rotation that the user defined on the ROI itself, not on the image
    # if angle != 0:
    #     centerPoint = np.mean(rect,axis=0) # we rotate the ROI around its center
    #     rect = np.array([
    #         rotatePoint(rect[0], centerPoint, angle), # note that we rotate by -angle above
    #         rotatePoint(rect[1], centerPoint, angle),
    #         rotatePoint(rect[2], centerPoint, angle),
    #         rotatePoint(rect[3], centerPoint, angle)
    #     ])

    # plt.figure()
    # plt.imshow(img)
    # plt.plot(surrounding_rect[:,1], surrounding_rect[:,0])
    # plt.plot(rect[:,1], rect[:,0])
    # plt.show()

    # angle between rect and surrounding_rect. surrounding_rect is straight.
    # We measure COUNTERCLOCKWISE since skimage.transform.rotate rotates counter-clockwise
    dy = rect[3][1] - rect[0][1]
    dx = rect[3][0] - rect[0][0]
    if dx == 0 or dy == 0:
        angle_rect_surrounding_rect = 0
    else:
        angle_rect_surrounding_rect = np.arctan(dy/dx) * 180 / np.pi

    minx_backup = minx
    miny_backup = miny
    minx_append = 0
    miny_append = 0
    maxx_append = 0
    maxy_append = 0
    if maxx>img.shape[0]:
        if minx>img.shape[0]: # if the ROI is entirely out of the image
            maxx_append = int( maxx-minx )
        else:
            maxx_append =int( maxx-img.shape[0] )
            maxx = img.shape[0]
    if maxy>img.shape[1]:
        if miny>img.shape[1]: # if the ROI is entirely out of the image
            maxy_append = int( maxy-miny )
        else:
            maxy_append = int( maxy-img.shape[1] )
            maxy = img.shape[1]
    if minx<0:
        if maxx<0:
            minx_append = int( maxx-minx )
            minx = img.shape[0]+1
            maxx = minx+minx_append
        else:
            minx_append = int( np.abs(minx) )
            minx = 0
    if miny<0:
        if maxy<0:
            miny_append = int( maxy-miny )
            miny = img.shape[1]+1
            maxy = miny+miny_append
        else:
            miny_append = int( np.abs(miny) )
            miny = 0

    img_surrounding = img[int(minx):int(maxx), int(miny):int(maxy)]
    # rotationCenter  = ((int(maxy)-int(miny)) / 2 - 0.5, (int(maxx)-int(minx)) / 2 - 0.5)
    dtype = np.dtype(img[0][0])
    if minx_append>0:
        img_surrounding = np.concatenate( (np.zeros((minx_append, img_surrounding.shape[1]), dtype=dtype), img_surrounding), axis=0)
    if maxx_append>0:
        img_surrounding = np.concatenate( (img_surrounding, np.zeros((maxx_append, img_surrounding.shape[1]), dtype=dtype)), axis=0)
    if miny_append>0:
        img_surrounding = np.concatenate( (np.zeros((img_surrounding.shape[0], miny_append), dtype=dtype), img_surrounding), axis=1)
    if maxy_append>0:
        img_surrounding = np.concatenate( (img_surrounding, np.zeros((img_surrounding.shape[0], maxy_append), dtype=dtype)), axis=1)

    if angle_rect_surrounding_rect != 0 and angle_rect_surrounding_rect!=360:
        img_surrounding_rot = rotate(img_surrounding, angle=360-angle_rect_surrounding_rect) # we have to rotate the other way as the ROI is

        rect_straight = rect
        rect_straight[:,0] = rect_straight[:,0]-minx_backup
        rect_straight[:,1] = rect_straight[:,1]-miny_backup
        centerPoint = np.mean(rect_straight,axis=0) # we rotate the ROI around its center
        rect_straight = np.array([
            rotatePoint(rect_straight[0], centerPoint, -angle_rect_surrounding_rect), # now the rectangle is straight again
            rotatePoint(rect_straight[1], centerPoint, -angle_rect_surrounding_rect),
            rotatePoint(rect_straight[2], centerPoint, -angle_rect_surrounding_rect),
            rotatePoint(rect_straight[3], centerPoint, -angle_rect_surrounding_rect)
        ])

        # plt.figure()
        # plt.imshow(img_surrounding_rot)
        # plt.plot(rect_straight[:,1], rect_straight[:,0])
        # plt.show()
        tranposeImage = False
        minx = np.min(rect_straight[:,0], axis=0)
        maxx = np.max(rect_straight[:,0], axis=0)
        miny = np.min(rect_straight[:,1], axis=0)
        maxy = np.max(rect_straight[:,1], axis=0)
        if minx<0:
            minx = 0
        if miny<0:
            miny = 0
        if maxx>img_surrounding_rot.shape[0]:
            maxx = img_surrounding_rot.shape[0]
        if maxy>img_surrounding_rot.shape[1]:
            maxy = img_surrounding_rot.shape[1]
        if fixedShape is not None:
            currentShape = np.array([int(maxx)-int(minx), int(maxy)-int(miny)])
            if (currentShape != fixedShape).all():
                if sum(np.abs(currentShape-fixedShape)) > sum(np.abs(currentShape[-1::-1]-fixedShape)):
                    fixedShape = fixedShape[-1::-1]
                    tranposeImage = True

                maxx = minx + fixedShape[0]
                maxy = miny + fixedShape[1]
                maxx = int(maxx)
                maxy = int(maxy)
                if img_surrounding_rot.shape[0]<maxx: # if the image is too small, extend it with zeros
                    img_surrounding_rot = np.concatenate((img_surrounding_rot, \
                        np.zeros((maxx-img_surrounding_rot.shape[0], img_surrounding_rot.shape[1]))), axis=0)
                if img_surrounding_rot.shape[1]<maxy: # if the image is too small, extend it with zeros
                    img_surrounding_rot = np.concatenate((img_surrounding_rot, \
                        np.zeros((img_surrounding_rot.shape[0], maxy-img_surrounding_rot.shape[1]))), axis=1)
        img_crop = img_surrounding_rot[int(minx):int(maxx), int(miny):int(maxy)]
        if tranposeImage:
            img_crop = np.transpose(img_crop)

        # plt.figure()
        # plt.imshow(img_crop)
        # plt.show()
        # plt.close("all")
    else:
        img_crop = img_surrounding
    if fixedShape is not None:
        if (img_crop.shape != fixedShape):
            a=1
    if (img_crop.shape[0]==0) or (img_crop.shape[1]==0):
        a=1
    return sk.util.img_as_uint(img_crop)

# ---------------------------------------------------------------------
def crop_rect_shapes(image_meta, shape_layers, dir_to_save=None,
                     frame_start=None, frame_end=None,
                     shift_x=0, shift_y=0, angle=0, label=None,
                     defaultShape=None, numColors=0):
    '''
    shape_layer should be a shape object from napari viewer
    '''

    if frame_start is None: frame_start = 0
    if frame_end is None: frame_end = image_meta['num_frames']  // image_meta['num_colors']
    num_frames_update = image_meta['num_colors'] * ((frame_end - frame_start) // image_meta['num_colors'])
    frame_end = frame_start + num_frames_update

    if type(shape_layers) is not list: # if only a single layer was supplied
        shape_layers = [shape_layers]
    if type(label) is not list: # if only a single layer was supplied
        label = [label]

    # loop through layers and extract rect_shape's
    numLayers = len(shape_layers)
    rect_shape = []
    labels     = []
    for nLayer in range(numLayers):
        # first see if there is any shape in the layer. if not, continue
        rect_shape_temp = np.rint(shape_layers[nLayer].data)
        if len(rect_shape_temp)==0:
            continue

        # first get the label and clean up
        label[nLayer] = cleanLabel(label[nLayer])

        # now get the rect_shape
        # in case the shape was added by the user manually, it contains by default a
        # third (z) dimension which is all 0 for 2D images. We need to remove this
        # in order not to confuse ImagejRoi.frompoints
        # for layers and shapes we added ourselves, layer.data is empty. we need a special case for that
        if len(rect_shape_temp) == 1: # check if we have a rectangle
            if rect_shape_temp[0].shape[0] != 4:
                print('The shape is not rectangular, please only give rectngular shapes')
            else:
                # remove column with all 0 entries
                rect_shape_temp = [rect_shape_temp[i][:,(rect_shape_temp[i]!=0).any(axis=0)] for i in range(len(rect_shape_temp))]#rect_shape_temp[0][:,(rect_shape_temp[0]!=0).any(axis=0)]
                if not (rect_shape_temp[0]==defaultShape).all():
                    rect_shape.append(rect_shape_temp[0])
                    labels.append(label[nLayer])
        else:
            # remove column with all 0 entries
            rect_shape_temp = [rect_shape_temp[i][:,(rect_shape_temp[i]!=0).any(axis=0)] for i in range(len(rect_shape_temp))]
            for i in range(len(rect_shape_temp)):
                if rect_shape_temp[i].shape[0] == 4:
                    # check if the current shape is the default shape. if so, skip
                    if (rect_shape_temp[i]==defaultShape).all():
                        continue
                    rect_shape.append(rect_shape_temp[i])
                    labels.append(label[nLayer])

    # now labels and rect_shape have the same length
    # if there are none to process => only shapes with the default position, return without doing anything
    if len(labels) == 0:
        print('Found only ROIs at the default position. Move ROIs before cropping')
        return

    folderpath = image_meta['folderpath']
    if dir_to_save is None:
        dir_to_save = os.path.join(folderpath+'_analysis')
        if not os.path.isdir(dir_to_save):
            os.makedirs(dir_to_save)

    names_roi_tosave = []
    img_array_all    = {}
    for col in range(image_meta['num_colors']):
        imgseq = pims.ImageSequence(image_meta['filenames_color_'+str(col)])[frame_start:frame_end]
        for i in trange(num_frames_update, desc='Cropping color: {} '.format(col)):
            # load image
            img = np.array(imgseq[i], dtype=np.uint16)
            imgSize = img.shape

            ## first determine if all crops are valid or if some lie outside the image region after applying all shifts/rotations
            if i == 0:
                numRectanglesOutside = 0
                for col2 in range(image_meta['num_colors']):
                    for iRect in range(len(rect_shape)):
                        # rectangle shape
                        rect = np.array(rect_shape[iRect])
                        rect = order_points(rect) # toplleft, topright, bottomrrigt, bottomleft

                        if angle[col] != 0:
                            centerPoint = np.array(imgSize)/2 # np.array([0, 0])#
                            rect = np.array([
                                rotatePoint(rect[0], centerPoint, -angle[col]),
                                rotatePoint(rect[1], centerPoint, -angle[col]),
                                rotatePoint(rect[2], centerPoint, -angle[col]),
                                rotatePoint(rect[3], centerPoint, -angle[col])
                            ])

                        if (shift_y[col]!=0 or shift_x[col]!=0):
                            rect[:,0] = rect[:,0]-shift_y[col]
                            rect[:,1] = rect[:,1]-shift_x[col]
                        rect = np.round(rect)

            ## all crops are valid, thus proceed
            for iRect in range(len(rect_shape)):
                # rectangle shape
                rect = np.array(rect_shape[iRect])
                # for the first image, we'll do it for all colors and see if the shapes for all colors are the same
                # in order to add them all to the same array later
                if i==0:
                    for col2 in range(image_meta['num_colors']):
                        if col2 == 0:
                            img_crop = rotateShiftROI(rect, img, imgSize, shift_x[col2], shift_y[col2], angle[col2])
                            img_crop_shape = img_crop.shape
                        else:
                            img_crop = rotateShiftROI(rect, img, imgSize, shift_x[col2], shift_y[col2], angle[col2], fixedShape=img_crop_shape)

                    # construct names of ROIs to save
                    rect = order_points(rect) # toplleft, topright, bottomrrigt, bottomleft
                    rect_0 = rect[0].astype(int)

                    dy = rect[3][1] - rect[0][1]
                    dx = rect[3][0] - rect[0][0]
                    if dx == 0 or dy == 0:
                        angle_roi = int(0)
                    else:
                        angle_roi = int(np.arctan(dy/dx) * 180 / np.pi)
                    width_x = int( np.ceil( np.sqrt(np.sum((rect[3,:]-rect[2,:])**2)) ) )
                    height_y = int( np.ceil( np.sqrt(np.sum((rect[2,:]-rect[1,:])**2)) ) )
                    nam = 'x' + str(rect_0[0]) + '-y' + str(rect_0[1]) +\
                          '-l' + str(height_y) + '-w' + str(width_x) +\
                          '-a' + str(angle_roi) + labels[i].lower()
                    names_roi_tosave.append(nam) # without the -f flags

                key = 'arr' + str(iRect)
                if col == 0:
                    img_crop = rotateShiftROI(rect, img, imgSize, shift_x[col], shift_y[col], angle[col])
                else:
                    img_crop = rotateShiftROI(rect, img, imgSize, shift_x[col], shift_y[col], angle[col], fixedShape=img_array_all[key].shape[2:4])

                # initialize the array holding all crops based on the size of the just cropped crop
                if col==0 and i==0:
                    img_array_all[key] = np.zeros((num_frames_update, image_meta['num_colors'],
                                                img_crop.shape[0], img_crop.shape[1]),
                                                dtype=np.uint16)

                # write crop into img_array_all
                img_array_all[key][i, col, :, :] = img_crop

    # save ROIs and associated yaml files
    rect_keys = list(img_array_all.keys())
    yamlFileName = os.path.join(folderpath, 'shift.yaml')
    shift_yaml = LoadShiftYamlFile(yamlFileName, shift_x, shift_y, angle, image_meta['num_colors'])
    shift_yaml["numColors"] = image_meta['num_colors']
    for nColor in range(image_meta['num_colors']):
        shift_yaml["x"]["col"+str(int(nColor))] = shift_x[nColor]
        shift_yaml["y"]["col"+str(int(nColor))] = shift_y[nColor]
        shift_yaml["angle"]["col"+str(int(nColor))] = angle[nColor]
    # save the yaml file
    shift_yaml = io.to_dict_walk(shift_yaml)
    for i in range(len(rect_shape)):
        roi_ij = ImagejRoi.frompoints(rect_shape_to_roi(rect_shape[i]))
        roi_ij.tofile(os.path.join(dir_to_save, names_roi_tosave[i]+'.roi'))
        imwrite(os.path.join(dir_to_save, names_roi_tosave[i]+'.tif'),
                img_array_all[rect_keys[i]], imagej=True,
                metadata={'axis': 'TCYX', 'channels': image_meta['num_colors'],
                'mode': 'composite',})

        yamlFileName = os.path.join(dir_to_save, names_roi_tosave[i]+'.yaml')
        with open(yamlFileName, "w") as shift_file:
            yaml.dump(dict(shift_yaml), shift_file, default_flow_style=False)
    return

from skimage.io import imread
from skimage.io.collection import alphanumeric_key
from dask import delayed
import dask.array as da
import random
folderpath = ''
# ---------------------------------------------------------------------
def daskread_img_seq(num_colors=1, bkg_subtraction=False, mean_subtraction=False, path="", RotationAngle=None):
    '''
    Import image sequences (saved individually in a folder)
    num_colors : integer
    returns: dask arrays and
    # 20210330: mean subtraction currently without function. The reason is that the mean image has to be computed over
    every n'th image only for n colors, while dask arrays only allow the same operation on each element in the array
    '''
    image_meta = {}
    image_meta['num_colors'] = num_colors
    global folderpath
    if path:
        folderpath = path
        for file in os.listdir(folderpath):
            if file.endswith(".tif") or file.endswith(".tiff"):
                filepath = file
                break
    else:
        settings = io.load_user_settings()
        try:
            folderpath = settings["crop"]["PWD"]
            if os.path.isfile(folderpath):
                folderpath = os.path.dirname(folderpath)
            folderpath = os.path.dirname(folderpath)
            # filepath = io.FileDialog(folderpath, "Select a folder with tif",
            #                      "Tif File (*.tif *.tiff)").openFileNameDialog()
            filepath = io.FileDialog(folderpath, "Select a folder containing .tif files",).openFolderNameDialog()
        except Exception as e:
            print(e)
            # filepath = io.FileDialog(None, "open a tif file stack",
            #                      "Tif File (*.tif *.tiff)").openFileNameDialog()
            filepath = io.FileDialog(None, "Select a folder containing .tif files",).openFolderNameDialog()
            pass
        if not filepath:
            image_meta = {}
            return image_meta
        if os.path.isfile(filepath):
            folderpath = os.path.dirname(filepath)
        else:
            folderpath = filepath
    image_meta['folderpath'] = folderpath
    if filepath.endswith('tif'):
        filenames = sorted(glob.glob(folderpath + "/*.tif"), key=alphanumeric_key)
    elif filepath.endswith('tiff'):
        filenames = sorted(glob.glob(folderpath + "/*.tiff"), key=alphanumeric_key)
    else:
        filenames = sorted(glob.glob(folderpath + "/*.tif"), key=alphanumeric_key)
        if len(filenames)==0:
            filenames = sorted(glob.glob(folderpath + "/*.tiff"), key=alphanumeric_key)
    image_meta['filenames'] = filenames
    # read the first file to get the shape and dtype
    # ASSUMES THAT ALL FILES SHARE THE SAME SHAPE/TYPE
    sample = imread(filenames[0])

    lazy_imread = delayed(imread)  # lazy reader
    lazy_arrays = [lazy_imread(fn) for fn in filenames] # read delayed images for all filenames
    dask_arrays = [
        da.from_delayed(delayed_reader, shape=sample.shape, dtype=sample.dtype)
        for delayed_reader in lazy_arrays
    ]

    # save current folderpath for the next time when the dialog is opened
    settings = io.load_user_settings()
    if folderpath is not None:
        settings["crop"]["PWD"] = folderpath
    io.save_user_settings(settings)

    # Stack into one large dask.array
    stack = da.stack(dask_arrays, axis=0)

    # background subtraction
    if bkg_subtraction:
        stack = stack.map_blocks(bkgSubtraction)
    # if mean_subtraction:
    #     stackMean = stack.mean(axis=0).persist()
    #     stack = stack - stackMean
        # stack.map_blocks(meanSubtraction)

    # apply rotation. For that, see if we can load an already existing yaml file from which we read the previously applied rotation angle
    if len(folderpath)==0:
        yamlFileName = ''
    else:
        yamlFileName = os.path.join(folderpath, 'shift.yaml')
    shift_yaml = LoadShiftYamlFile(yamlFileName, 0, 0, 0, num_colors)
    RotationAngle = [0] * shift_yaml["numColors"]
    for nColor in range(shift_yaml["numColors"]):
        try:
            RotationAngle[nColor] = shift_yaml["angle"]["col"+str(int(nColor))]
        except:
            RotationAngle[nColor] = 0
    if (RotationAngle[:-1] != RotationAngle[1:]):
        print('Not all read rotation angles are equal. Not applying any rotation.')
        RotationAngle = None

    if RotationAngle is not None:
        if any([x != 0 for x in RotationAngle]):
            stack = stack.map_blocks(applyRotation, RotationAngle=RotationAngle, num_colors=num_colors)

    num_frames = num_colors * (len(filenames)//num_colors)
    image_meta['num_frames'] = num_frames
    minVal = []; maxVal = []
    minCon = []; maxCon = []
    sampling = random.choices(range(0, num_frames, num_colors), k=10)
    for i in range(num_colors):
        image_meta['filenames_color_'+str(i)] = filenames[i:num_frames:num_colors]
        image_meta['stack_color_'+str(i)] = stack[i:num_frames:num_colors]
        for k in sampling:
            sample = imread(filenames[k+i])
            if bkg_subtraction:
                sample = bkgSubtraction(sample)
            # if mean_subtraction:
            #     sample -= sample
            minVal.append(sample.min())
            maxVal.append(sample.max())
            minConTemp, maxConTemp = AutoAdjustContrastIJ(sample)
            minCon.append(minConTemp)
            maxCon.append(maxConTemp)
        image_meta['min_int_color_'+str(i)] = np.mean(minVal)
        image_meta['max_int_color_'+str(i)] = np.mean(maxVal)
        image_meta['min_contrast_color_'+str(i)] = np.mean(minCon)#AutoAdjustContrastSorting(sample)#
        image_meta['max_contrast_color_'+str(i)] = np.mean(maxCon)
        # print('Channel {}: adjusted min intensity {}, adjusted max intensity {}'.format(i, round(np.mean(minCon)), round(np.mean(maxCon))))

    return image_meta

# ---------------------------------------------------------------------
def applyRotation(txy_array, RotationAngle=[0], num_colors=1):
    array_processed = np.zeros_like(txy_array)
    if array_processed.ndim > 2:
        for i in range(txy_array.shape[0]):
            img = txy_array[i]
            ### i tried here to compute which channel we are currently pocessing, but
            ### this function gets only fed one image at a time, so I dont know
            ### how to decide which image from the series is shown and, respectively,
            ### which color it is
            # col = np.mod(i,num_colors)
            img_rot = ndimage.rotate(img, RotationAngle[0], reshape=False)
            array_processed[i, :, :] = img_rot
    else:
        array_processed = ndimage.rotate(txy_array, RotationAngle[0], reshape=False)
        # imutils.rotate(txy_array, angle=RotationAngle)
    return array_processed

# ---------------------------------------------------------------------
def AutoAdjustContrastIJ(img):
    size = img.shape
    pixelCount = size[0]*size[1]
    limit = pixelCount/10
    AUTO_THRESHOLD = 5000/2
    threshold = pixelCount/AUTO_THRESHOLD
    hist = np.histogram(img, bins=255, range=(img.min(), img.max()))
    i = -1
    found = False
    while (not found) and (i<255):
        i = i+1
        count = hist[0][i] #hist[0] are histogram counts
        if count>limit: count = 0
        found = count>threshold
    hmin = i
    found = False
    i = 255
    while (not found) and (i>0):
        i = i-1
        count = hist[0][i]
        if (count>limit): count = 0
        found = count > threshold
    hmax = i
    if (hmax<hmin):
        hmin = img.min()
        hmax = img.max()
    else: # map back to real pixel values
        hmin = hist[1][hmin]
        hmax = hist[1][hmax]
    return hmin, hmax

# ---------------------------------------------------------------------
def invnormcdf(x, mu, sigma):
    # noise model: mu is the mean value, sigma is the sigma of the gaussian noise
    return np.real(mu+sigma*np.sqrt(2)*special.erfinv(x))

# ---------------------------------------------------------------------
def AutoAdjustContrastSorting(img):
    img = img.astype('float')
    size = img.shape
    img_bckg = bkgSubtraction(img)
    img_bckg_flat = img_bckg.flatten()
    # get rid of zeros, that messes with the fitting once the intensity values are sorted
    if (img_bckg_flat==0).any():
        img_bckg_flat[img_bckg_flat==0] = np.nan
        sumNaNs = np.sum(np.isnan(img_bckg_flat))
        N = size[0]*size[1] - sumNaNs
    else:
        sumNaNs = 0
        N = size[0]*size[1]
    x = np.linspace(-0.999, 0.999, N)

    # sort intensity values
    sort_ind = np.argsort(img_bckg_flat)
    img_bckg_sorted = img_bckg_flat[sort_ind]

    # if there are nan's, take them away now
    if sumNaNs > 0:
        img_bckg_sorted = img_bckg_sorted[~np.isnan(img_bckg_sorted)]

    # subtract mean value and normalize data
    img_bckg_sorted -= np.mean(img_bckg_sorted)
    img_bckg_sorted /= max(img_bckg_sorted)

    # fit to noise model
    initial_guess = np.array([0, 0.2])
    LB = np.array([-0.2, 0.001])
    UB = np.array([0.2, 0.35])

    popt, pcov = optimize.curve_fit(invnormcdf, x[0:int(np.round(N/2))], \
        img_bckg_sorted[0:int(np.round(N/2))], p0=initial_guess, bounds=(LB, UB))

    noise_subtracted = img_bckg_sorted - invnormcdf(x, popt[0], popt[1])
    noise_subtracted /= np.max(noise_subtracted.flatten())

    ind = np.argmax(noise_subtracted > 0.01)
    sorted_im = np.sort(img.flatten())
    threshold = sorted_im[ind]

    # from matplotlib import pyplot as plt
    # plt.figure()
    # plt.plot(x, img_bckg_sorted)
    # plt.plot(x, invnormcdf(x, popt[0], popt[1]))
    # # plt.show()
    # plt.savefig('foo.png')

    return threshold

# ---------------------------------------------------------------------
from scipy.ndimage import white_tophat, black_tophat
def bkgSubtraction(txy_array, size_bgs=50, light_bg=False):
    array_processed = np.zeros_like(txy_array)
    if array_processed.ndim>2:
        for i in range(txy_array.shape[0]):
            img = txy_array[i]
            if light_bg:
                img_bgs = black_tophat(img, size=size_bgs)
            else:
                img_bgs = white_tophat(img, size=size_bgs)
            array_processed[i, :, :] = img_bgs
    else:
        if light_bg:
            array_processed = black_tophat(txy_array, size=size_bgs)
        else:
            array_processed = white_tophat(txy_array, size=size_bgs)
    return array_processed

# ---------------------------------------------------------------------
# def meanSubtraction(txy_array):
#     array_processed = np.zeros_like(txy_array)
#     if array_processed.ndim>2:
#         for i in range(txy_array.shape[0]):
#             img = txy_array[i]
#             if light_bg:
#                 img_bgs = black_tophat(img, size=size_bgs)
#             else:
#                 img_bgs = white_tophat(img, size=size_bgs)
#             array_processed[i, :, :] = img_bgs
#     else:
#         if light_bg:
#             array_processed = black_tophat(txy_array, size=size_bgs)
#         else:
#             array_processed = white_tophat(txy_array, size=size_bgs)
#     return array_processed
# def meanSubtraction(txy_array):
#     array_processed = np.zeros_like(txy_array)
#     if array_processed.ndim>2:
#         # meanImage = np.nanmean(txy_array, axis=0, keepdims=True)
#         meanImage = sum(txy_array) / len(txy_array)
#         if np.isnan(meanImage.flatten()).any():
#             return txy_array
#         # plt.figure(), plt.imshow(meanImage), plt.show()
#         for i in range(txy_array.shape[0]):
#             array_processed[i, :, :] = txy_array[i] - meanImage
#     # for i in range(txy_array.shape[0]):
#         # array_processed = txy_array - meanImage
#         # array_processed[array_processed<0] = 0
#         print('shape: ')
#         print(txy_array.shape)
#         print('meanImage: ')
#         print(meanImage)
#         asdkjgasd
#         print(np.nanmean(meanImage.flatten()))
#     return array_processed

# ---------------------------------------------------------------------
def geometric_shift(image2d, angle, shift_x, shift_y):
    if angle!=0:
        image2d = ndimage.rotate(image2d, angle, reshape=False)
    if float(shift_y)!=0 or float(shift_x)!=0:
        image2d = ndimage.shift(image2d, (float(shift_y), float(shift_x)))
    return image2d


###########################################
######### FUNCTIONS

## Normal
def sum(a, b):
    c = a+b
    print(c)

sum(1, 2)

## Using the rest parameter

def sum(a, *b):     # Baaki saare bache hue param b me le lo😏
    sum = a

    for i in b:
        sum += i

    print(sum)

sum(1, 2, 3, 4)

## Returning multiple values from a function

from array import *

def count_even_odd(lst):
    even = 0
    odd = 0

    for i in lst:
        if i%2 == 0:
            even += 1
        else:
            odd += 1

    return even, odd

n = int(input('Enter list size: '))

arr = array('i', [])  # New array creation
for i in range(n):
    x = int(input('Number: '))
    arr.append(i)  # Adding values to the array

print(count_even_odd(arr)) ## 2 Even 3 Odd


import lib.module as module
from lib import numeric

from lib.error import NameInUseError, NoSuchTargetError

class KillMod(module.Module):

	command = "KILL"

	@module.min_params(1)
	def handle_client(self, source, message):
		nick = message['params'][0]

		try:

			# generate QUIT event
			message = {
				'prefix' : None,
				'command' : 'QUIT',
				'params' : ['Disconnected by %s.' % source]
			}

			self.server.generate_client_event(nick, message)

		except NameInUseError as err:
			self.server.numeric_message_client(self.server.name,
											   numeric.ERR_NICKNAMEINUSE,
											   source,
											   ":Nickname already in use.")
		except NoSuchTargetError as err:
			self.server.numeric_message_client(self.server.name,
											   numeric.ERR_NOSUCHNICK,
											   source,
											   ":No such nickname.")


import re
from openpyxl.descriptors import (
    Strict,
    Integer,
    String,
    Typed,
)
from openpyxl.utils import quote_sheetname, absolute_coordinate
from openpyxl.utils.cell import SHEET_TITLE, SHEETRANGE_RE, RANGE_EXPR

from .cell_range import MultiCellRange

COL_RANGE = r"""(?P<cols>[$]?(?P<min_col>[a-zA-Z]{1,3}):[$]?(?P<max_col>[a-zA-Z]{1,3}))"""
COL_RANGE_RE = re.compile(COL_RANGE)
ROW_RANGE = r"""(?P<rows>[$]?(?P<min_row>\d+):[$]?(?P<max_row>\d+))"""
ROW_RANGE_RE = re.compile(ROW_RANGE)
TITLES_REGEX = re.compile("""{0}{1}?,?{2}?,?""".format(SHEET_TITLE, ROW_RANGE, COL_RANGE),
                          re.VERBOSE)
PRINT_AREA_RE = re.compile(f"({SHEET_TITLE})?(?P<cells>{RANGE_EXPR})", re.VERBOSE)

class ColRange(Strict):
    """
    Represent a range of at least one column
    """

    min_col = String()
    max_col = String()

    def __init__(self, range_string=None, min_col=None, max_col=None):
        if range_string is not None:
            match = COL_RANGE_RE.match(range_string)
            if not match:
                raise ValueError(f"{range_string} is not a valid column range")
            min_col, max_col = match.groups()[1:]
        self.min_col = min_col
        self.max_col = max_col

    def __eq__(self, other):
        if isinstance(other, self.__class__):
            return (self.min_col == other.min_col
                    and
                    self.max_col == other.max_col)
        elif isinstance(other, str):
            return (str(self) == other
                    or
                    f"{self.min_col}:{self.max_col}")
        return False

    def __repr__(self):
        return f"Range of columns from '{self.min_col}' to '{self.max_col}'"

    def __str__(self):
        return f"${self.min_col}:${self.max_col}"

class RowRange(Strict):
    """
    Represent a range of at least one row
    """

    min_row = Integer()
    max_row = Integer()

    def __init__(self, range_string=None, min_row=None, max_row=None):
        if range_string is not None:
            match = ROW_RANGE_RE.match(range_string)
            if not match:
                raise ValueError(f"{range_string} is not a valid row range")
            min_row, max_row = match.groups()[1:]
        self.min_row = min_row
        self.max_row = max_row

    def __eq__(self, other):
        if isinstance(other, self.__class__):
            return (self.min_row == other.min_row
                    and
                    self.max_row == other.max_row)
        elif isinstance(other, str):
            return (str(self) == other
                    or
                    f"{self.min_row}:{self.max_row}")
        return False

    def __repr__(self):
        return f"Range of rows from '{self.min_row}' to '{self.max_row}'"

    def __str__(self):
        return f"${self.min_row}:${self.max_row}"

class PrintTitles(Strict):
    """
    Contains at least either a range of rows or columns
    """

    cols = Typed(expected_type=ColRange, allow_none=True)
    rows = Typed(expected_type=RowRange, allow_none=True)
    title = String()

    def __init__(self, cols=None, rows=None, title=""):
        self.cols = cols
        self.rows = rows
        self.title = title

    @classmethod
    def from_string(cls, value):
        kw = dict((k, v) for match in TITLES_REGEX.finditer(value)
                  for k, v in match.groupdict().items() if v)

        if not kw:
            raise ValueError(f"{value} is not a valid print titles definition")

        cols = rows = None

        if "cols" in kw:
            cols = ColRange(kw["cols"])
        if "rows" in kw:
            rows = RowRange(kw["rows"])

        title = kw.get("quoted") or kw.get("notquoted")

        return cls(cols=cols, rows=rows, title=title)

    def __eq__(self, other):
        if isinstance(other, self.__class__):
            return (self.cols == other.cols
                    and
                    self.rows == other.rows
                    and
                    self.title == other.title)
        elif isinstance(other, str):
            return str(self) == other
        return False

    def __repr__(self):
        return f"Print titles for sheet {self.title} cols {self.rows}, rows {self.cols}"

    def __str__(self):
        title = quote_sheetname(self.title)
        titles = ",".join([f"{title}!{value}" for value in (self.rows, self.cols) if value])
        return titles or ""

class PrintArea(MultiCellRange):

    @classmethod
    def from_string(cls, value):
        new = []
        for m in PRINT_AREA_RE.finditer(value): # can be multiple
            coord = m.group("cells")
            if coord:
                new.append(coord)
        return cls(new)

    def __init__(self, ranges=(), title=""):
        self.title = ""
        super().__init__(ranges)

    def __str__(self):
        if self.ranges:
            return ",".join([f"{quote_sheetname(self.title)}!{absolute_coordinate(str(range))}"
                             for range in self.sorted()])
        return ""

    def __eq__(self, other):
        super().__eq__(other)
        if isinstance(other, str):
            return str(self) == other


from typing import *
import sys

input = sys.stdin.readline

point = [list(map(int , input().split())) for _ in range(3)]

len_ab = (abs(point[0][0] - point[1][0])**2 + abs(point[0][1] - point[1][1])**2)
len_bc = (abs(point[1][0] - point[2][0])**2 + abs(point[1][1] - point[2][1])**2)
len_ac = (abs(point[0][0] - point[2][0])**2 + abs(point[0][1] - point[2][1])**2)

length = [len_ab , len_bc , len_ac]
length_r = [len_ab**0.5 , len_bc**0.5 , len_ac**0.5]

length.sort()
length_r.sort()

d = (length[0] + length[1])

result = []

if length_r[2] >= length_r[0] + length_r[1]:
    result.append('X')
else:
    if length_r[0] == length_r[1] and length_r[1] == length_r[2]:
        result.append('Jung')
    elif length_r[0] == length_r[1] or length_r[1] == length_r[2] or length_r[2] == length_r[0]:
        if d < length[2]:
            result.append('Dunkak')
        elif d == length[2]:
            result.append('Jikkak')
        else:
            result.append('Yeahkak')
        result.append('2')
    else:
        if d < length[2]:
            result.append('Dunkak')
        elif d == length[2]:
            result.append('Jikkak')
        else:
            result.append('Yeahkak')

    result.append('Triangle')

print(''.join(result))