"""Test methods for `zcode/math/math_core.py`.

Can be run with:
    $ nosetests math/tests/test_math_core.py
    $ nosetests math/tests/test_math_core.py:TestMathCore.test_around
    $ python math/tests/test_math_core.py

"""
from __future__ import absolute_import, division, print_function, unicode_literals

import numpy as np
from numpy.testing import run_module_suite
import scipy as sp
import scipy.stats  # noqa
from nose.tools import assert_true, assert_false, assert_equal, assert_raises, assert_almost_equal

from zcode.math import math_core, interpolate

class TestMathCore(object):

    @classmethod
    def setup_class(cls):
        np.random.seed(9865)
        cls.SIZE = 100
        cls.r1 = np.random.random(cls.SIZE)
        cls.r2 = np.random.uniform(-1.0, 1.0, size=cls.SIZE)

    def test_argnearest_ordered(self):
        from zcode.math.math_core import argnearest
        edges = np.array([0.2, 0.8, 1.3, 1.5, 2.0, 3.1, 3.8, 3.9, 4.5, 5.1, 5.5])
        vals = np.array([-1, 0.2, 1, 1.4, 2, 3, 4, 5, 5.5, 10])
        correct = [0, 0, 1, 2, 4, 5, 7, 9, 10, 10]
        retval = argnearest(edges, vals, assume_sorted=True)
        assert_true(np.all(correct == retval))
        print("Edges = {}".format(edges))
        print("Vals = {}".format(vals))
        print("retval  = {}".format(retval))
        print("correct = {}".format(correct))
        return

    def test_argnearest_ordered_left_right(self):
        from zcode.math.math_core import argnearest
        #                 0    1    2    3    4    5    6    7    8    9    10
        edges = np.array([0.2, 0.8, 1.3, 1.5, 2.0, 3.1, 3.8, 3.9, 4.5, 5.1, 5.5])
        vals    = np.array([-1, 0.2, 1, 1.4, 2, 3, 4, 5, 5.5, 10])
        correct = np.array([-1, -1 , 1, 2  , 3, 4, 7, 8, 9  , 10])
        print("LEFT")
        retval = argnearest(edges, vals, assume_sorted=True, side='left')
        print("Edges = {}".format(edges))
        print("Vals = {}".format(vals))
        print("retval  = {}".format(retval))
        print("correct = {}".format(correct))
        print(correct == retval)
        print(np.all(correct == retval))
        assert_true(np.all(correct == retval))

        correct += 1
        for ee in edges:
            correct[vals == ee] += 1

        print("RIGHT")
        retval = argnearest(edges, vals, assume_sorted=True, side='right')
        print("Edges = {}".format(edges))
        print("Vals = {}".format(vals))
        print("retval  = {}".format(retval))
        print("correct = {}".format(correct))
        assert_true(np.all(correct == retval))

        return

    def test_argnearest_unordered_x(self):
        from zcode.math.math_core import argnearest
        edges = np.array([0.2, 0.8, 1.3, 1.5, 2.0, 3.1, 3.8, 3.9, 4.5, 5.1, 5.5])
        vals = np.array([-1, 0.2, 1, 1.4, 2, 3, 4, 5, 5.5, 10])
        correct = np.array([2, 2, 8, 7, 0, 6, 9, 3, 4, 4])

        # ix = np.random.permutation(edges.size)
        ix = np.array([4,  3,  0,  9, 10,  8,  5,  2,  1,  7,  6])
        edges = edges[ix]

        retval = argnearest(edges, vals, assume_sorted=False)
        print("Edges = {}".format(edges))
        print("Vals = {}".format(vals))
        print("retval  = {}".format(retval))
        print("nearest = {}".format(edges[retval]))
        print("Vals = {}".format(vals))
        print("retval  = {}".format(retval))
        print("correct = {}".format(correct))
        assert_true(np.all(correct == retval))
        return

    def test_argnearest_unordered_xy(self):
        from zcode.math.math_core import argnearest
        edges = np.array([0.2, 0.8, 1.3, 1.5, 2.0, 3.1, 3.8, 3.9, 4.5, 5.1, 5.5])
        vals = np.array([-1, 0.2, 1, 1.4, 2, 3, 4, 5, 5.5, 10])
        correct = np.array([0, 7, 6, 3, 4, 9, 2, 4, 2, 8])

        # ix = np.random.permutation(edges.size)
        ix = np.array([4,  3,  0,  9, 10,  8,  5,  2,  1,  7,  6])
        edges = edges[ix]
        iy = np.array([4, 3, 5, 7, 9, 6, 0, 8, 1, 2])
        vals = vals[iy]

        retval = argnearest(edges, vals, assume_sorted=False)
        print("Edges = {}".format(edges))
        print("Vals = {}".format(vals))
        print("retval  = {}".format(retval))
        print("nearest = {}".format(edges[retval]))
        print("Vals = {}".format(vals))
        print("retval  = {}".format(retval))
        print("correct = {}".format(correct))
        assert_true(np.all(correct == retval))
        return

    def test_spacing(self):
        from zcode.math.math_core import spacing

        # Linear Spacing
        ref1 = np.linspace(0.0, 1.0, num=20)
        spc1 = spacing([0.0, 1.0], scale='lin', num=20)
        assert_true(np.allclose(ref1, spc1))

        # Logarithmic Spacing
        ref2 = np.logspace(0.0, 2.5, num=20)
        spc2 = spacing([np.power(10.0, 0.0), np.power(10.0, 2.5)], scale='log', num=20)
        assert_true(np.allclose(ref2, spc2))

        # Automatically selects appropriate Range
        ref3 = np.logspace(1.0, 2.0, num=13)
        spc3 = spacing([-10.0, 100.0, 0.0, 10.0], scale='log', num=13)
        assert_true(np.allclose(ref3, spc3))

        # Manually selects appropraite range
        ref4 = np.linspace(-5.0, -2.5, num=27)
        spc4 = spacing([3.0, -2.5, -5.0, 0.0], scale='lin', num=27, filter='<')
        assert_true(np.allclose(ref4, spc4))

        # Only integral (whole number) values
        # log spacing
        vals = [2.34, 365.23]
        res = np.array([2., 3., 4., 5., 6., 7., 8., 9., 10.,
                        20., 30., 40., 50., 60., 70., 80., 90., 100.,
                        200., 300., 400.])
        retvals = spacing(vals, 'log', integers=True)
        print("integers, log\n", vals, "\n\t", res, "\n\t", retvals)
        print(retvals)
        print(np.allclose(retvals, res))
        assert_true(np.allclose(retvals, res))

        # lin spacing
        vals = [2.34, 11.23]
        res = np.arange(2, 13)
        retvals = spacing(vals, 'lin', integers=True)
        print("integers, lin\n", vals, "\n\t", res, "\n\t", retvals)
        print(np.allclose(retvals, res))
        assert_true(np.allclose(retvals, res))

        return

    def test_mono(self):
        arr_g = [-1.0, 1.0, 2.0, 3.0]
        arr_ge = [-1.0, 1.0, 1.0, 2.0, 2.5]
        arr_l = [11.5, 9.2, -2.0, -301.0]
        arr_le = [11.5, 9.2, -2.0, -2.0, -301.0]
        arr_e = 11*[1.0]

        assert_true(math_core.mono(arr_g, 'g'))
        assert_true(math_core.mono(arr_ge, 'ge'))
        assert_true(math_core.mono(arr_g, 'ge'))
        assert_false(math_core.mono(arr_ge, 'g'))

        assert_true(math_core.mono(arr_l, 'l'))
        assert_true(math_core.mono(arr_le, 'le'))
        assert_true(math_core.mono(arr_l, 'le'))
        assert_false(math_core.mono(arr_le, 'l'))

        assert_true(math_core.mono(arr_e, 'e'))
        assert_false(math_core.mono(arr_le, 'e'))

    def test_ordered_groups(self):
        arr = np.array([99, 77, 14, 21, 71, 64, 98, 38, 66, 25])
        sinds = np.argsort(arr)
        targets = [40, 77]
        print("arr = {}, targets = {}, sorted arr = {}".format(arr, targets, arr[sinds]))

        # Group into elements below targets
        #    Exclusively
        print("Below, exclusive:")
        locs, isort = math_core.ordered_groups(arr, targets, inds=None, dir='b', include=False)
        assert_true(np.all(sinds == isort))
        #    Check subsets from each target location
        for ll, tt in zip(locs, targets):
            print("target = {}, loc = {}".format(tt, ll))
            print(set(arr[isort[:ll]]), set(arr[sinds][arr[sinds] < tt]))
            assert_true(set(arr[isort[:ll]]) == set(arr[sinds][arr[sinds] < tt]))
        #    Inclusively
        print("Below, inclusive:")
        locs, isort = math_core.ordered_groups(arr, targets, inds=None, dir='b', include=True)
        assert_true(np.all(sinds == isort))
        #    Check subsets from each target location
        for ll, tt in zip(locs, targets):
            print("target = {}, loc = {}".format(tt, ll))
            print(set(arr[isort[:ll]]), set(arr[sinds][arr[sinds] <= tt]))
            assert_true(set(arr[isort[:ll]]) == set(arr[sinds][arr[sinds] <= tt]))

        # Group into elements above targets
        #    Exclusive
        print("Above, exclusive:")
        locs, isort = math_core.ordered_groups(arr, targets, inds=None, dir='a', include=False)
        assert_true(np.all(sinds[::-1] == isort))
        # Check subsets from each target location
        for ll, tt in zip(locs, targets):
            print("target = {}, loc = {}".format(tt, ll))
            print(set(arr[isort[:ll]]), set(arr[sinds][arr[sinds] > tt]))
            assert_true(set(arr[isort[:ll]]) == set(arr[sinds][arr[sinds] > tt]))

        #    Exclusive
        print("Above, inclusive:")
        locs, isort = math_core.ordered_groups(arr, targets, inds=None, dir='a', include=True)
        assert_true(np.all(sinds[::-1] == isort))
        # Check subsets from each target location
        for ll, tt in zip(locs, targets):
            print("target = {}, loc = {}".format(tt, ll))
            print(set(arr[isort[:ll]]), set(arr[sinds][arr[sinds] >= tt]))
            assert_true(set(arr[isort[:ll]]) == set(arr[sinds][arr[sinds] >= tt]))

        # Should raise error for unsorted `targets`
        assert_raises(ValueError, math_core.ordered_groups, arr, targets[::-1])

        # Should raise error for `dir` not starting with 'a' or 'b'
        assert_raises(ValueError, math_core.ordered_groups, arr, targets, None, 'c')
        return

    def test_really1d(self):
        from zcode.math import really1d
        assert_true(really1d([1, 2, 3]))
        assert_true(really1d([1]))
        assert_true(really1d([]))
        assert_true(really1d(np.arange(10)))

        assert_false(really1d(1))
        assert_false(really1d([[1]]))
        assert_false(really1d([[1, 2], [2, 3]]))
        assert_false(really1d([[1, 2, 3], [4, 5]]))
        assert_false(really1d(np.random.random((4, 3))))
        assert_false(really1d([[]]))

    def test_argextrema(self):
        # Basic usage without filtering
        assert_equal(math_core.argextrema([-1, -5, 2, 10], 'min'), 1)
        assert_equal(math_core.argextrema([-1, -5, 2, 10], 'max'), 3)

        # Filtering
        #    min
        assert_equal(math_core.argextrema([-1, -5, 2, 10, 0], 'min', 'g'), 2)
        assert_equal(math_core.argextrema([-1, -5, 2, 10, 0], 'min', 'ge'), 4)
        assert_equal(math_core.argextrema([-1, -5, 0, 2, 10], 'min', 'l'), 1)
        assert_equal(math_core.argextrema([-1, -5, 0, 2, 10], 'min', 'le'), 1)
        #    max
        assert_equal(math_core.argextrema([-1, -5, 2, 10, 0], 'max', 'g'), 3)
        assert_equal(math_core.argextrema([-1, -5, 2, 10, 0], 'max', 'ge'), 3)
        assert_equal(math_core.argextrema([-1, -5, 0, 2, 10], 'max', 'l'), 0)
        assert_equal(math_core.argextrema([-1, -5, 0, 2, 10], 'max', 'le'), 2)

        # Raises appropriate errors
        #    Incorrect shape input array
        assert_raises(ValueError, math_core.argextrema, np.arange(4).reshape(2, 2), 'max')
        assert_raises(ValueError, math_core.argextrema, 0.0, 'max')
        #    Invalid `type` argument
        assert_raises(ValueError, math_core.argextrema, [1, 2], 'mex')
        #    Invalid `filter` argument
        assert_raises(ValueError, math_core.argextrema, [1, 2], 'max', 'e')
        #    Invalid `filter` argument
        assert_raises(ValueError, math_core.argextrema, [1, 2], 'max', 'greater')

    def test_asBinEdges_1d(self):
        print("TestMathCore.test_asBinEdges_1d")
        from zcode.math import asBinEdges, spacing

        data_1d = np.random.random(40)
        bins_1d = np.arange(20)
        # Preserves valid bins
        assert_true(np.allclose(bins_1d, asBinEdges(bins_1d, data_1d)))

        # Constructs valid bins
        #    lin
        lin_1d = spacing(data_1d, scale='lin', num=8+1)
        lin_edges_1d = asBinEdges(8, data_1d, scale='lin')
        assert_true(np.allclose(lin_1d, lin_edges_1d))
        #    log
        log_1d = spacing(data_1d, scale='log', num=7+1)
        log_edges_1d = asBinEdges(7, data_1d, scale='log')
        assert_true(np.allclose(log_1d, log_edges_1d))

        # Raises appropriate errors
        data_2d = data_1d.reshape(8, 5)
        bins_2d = bins_1d.reshape(4, 5)
        #    1D bins, 2D data
        assert_raises(ValueError, asBinEdges, bins_1d, data_2d)
        #    2D bins, 1D data
        assert_raises(ValueError, asBinEdges, bins_2d, data_1d)

    def test_asBinEdges_nd(self):
        print("TestMathCore.test_asBinEdges_nd")
        from zcode.math import asBinEdges

        data_2d = np.random.random((8, 2))
        bins_2d = np.arange(8).reshape(2, 4)
        bins_2d2 = [[0.0, 1.0], [0.0, 0.5, 1.0]]

        # Preserves valid bins
        edges_2d = asBinEdges(bins_2d, data_2d)
        assert_true(np.allclose(bins_2d, edges_2d))
        edges_2d2 = asBinEdges(bins_2d2, data_2d)
        assert_true(np.allclose(bins_2d2[0], edges_2d2[0]))
        assert_true(np.allclose(bins_2d2[1], edges_2d2[1]))

        # Constructs valid bins
        #    lin
        lin_2d1 = sp.stats.binned_statistic_dd(data_2d, None, 'count', bins=4).bin_edges
        lin_edges_2d1 = asBinEdges(4, data_2d, scale='lin')
        assert_true(np.allclose(lin_2d1, lin_edges_2d1))
        lin_2d2 = sp.stats.binned_statistic_dd(data_2d, None, 'count', bins=[4, 3]).bin_edges
        lin_edges_2d2 = asBinEdges([4, 3], data_2d, scale='lin')
        assert_true(np.allclose(lin_2d2[0], lin_edges_2d2[0]))
        assert_true(np.allclose(lin_2d2[1], lin_edges_2d2[1]))

        # Raises appropriate errors
        #    1D bins, 2D data
        assert_raises(ValueError, asBinEdges, [4], data_2d)
        #    2D bins, 1D data
        assert_raises(ValueError, asBinEdges, [4, 3, 2], data_2d)

    def test_comparison_function(self):
        from zcode.math.math_core import _comparison_function

        comp = ['g', '>']
        arr = [0.5, 1.5, -0.5, 0.0]
        res = [True, True, False, False]
        for cc in comp:
            func = _comparison_function(cc, value=0.0)
            assert_true(np.all(np.equal(func(arr), res)))

        comp = ['ge', '>=']
        arr = [0.5, 1.5, -0.5, 0.0]
        res = [True, True, False, True]
        for cc in comp:
            func = _comparison_function(cc, value=0.0)
            assert_true(np.all(np.equal(func(arr), res)))

        comp = ['l', '<']
        arr = [-10.5, -1.5, 0.5, 0.0]
        res = [True, True, False, False]
        for cc in comp:
            func = _comparison_function(cc, value=0.0)
            assert_true(np.all(np.equal(func(arr), res)))

        comp = ['le', '<=']
        arr = [-10.5, -1.5, 0.5, 0.0]
        res = [True, True, False, True]
        for cc in comp:
            func = _comparison_function(cc, value=0.0)
            assert_true(np.all(np.equal(func(arr), res)))

        comp = ['e', '=', '==']
        arr = [-10.5, 0.5, 0.0]
        res = [False, False, True]
        for cc in comp:
            func = _comparison_function(cc, value=0.0)
            assert_true(np.all(np.equal(func(arr), res)))

        comp = ['ne', '!=']
        arr = [-10.5, 0.5, 0.0]
        res = [True, True, False]
        for cc in comp:
            func = _comparison_function(cc, value=0.0)
            assert_true(np.all(np.equal(func(arr), res)))

        return

    def test_comparison_filter(self):
        from zcode.math.math_core import comparison_filter

        comp = ['g', '>']
        arr = [0.5, -1.0, 1.5, -0.5, 0.0]
        res = [0.5, 1.5]
        inds = [0, 2]

        arr = np.array(arr)
        for cc in comp:
            vals = comparison_filter(arr, cc, value=0.0)
            assert_true(np.all(np.equal(vals, res)))
            val_inds = comparison_filter(arr, cc, inds=True, value=0.0)
            assert_true(np.all(np.equal(arr[val_inds], arr[inds])))

        comp = ['le', '<=']
        arr = [0.5, -1.0, 1.5, -0.5, 0.0]
        res = [-1.0, -0.5, 0.0]
        inds = [1, 3, 4]

        arr = np.array(arr)
        for cc in comp:
            vals = comparison_filter(arr, cc, value=0.0)
            assert_true(np.all(np.equal(vals, res)))
            vals = comparison_filter(arr, cc, inds=True, value=0.0)
            assert_true(np.all(np.equal(arr[vals], arr[inds])))

        return

    def test_around(self):
        from zcode.math.math_core import around
        vals = [
            # Nearest
            #    linear
            [[123.4678, 0, 'lin', 'near'], 123.00],
            [[123.4678, 1, 'linear', 'nearest'], 123.50],
            [[123.4678, 2, 'lin', 'n'], 123.47],
            #    logarithmic
            [[123.4678, 0, 'log', 'nearest'], 100.0],
            [[123.4678, 1, 'logarithmic', 'nearest'], 120.0],
            [[123.4678, 2, 'log', 'nearest'], 123.0],
            [[123.4678, 3, 'log', 'nearest'], 123.5],
            #       Negative decimals (order-of-magnitude rounding)
            [[213.4678, -1, 'log', 'nearest'], 100.0],
            # Ceiling (up)
            #    linear
            [[123.4678, 0, 'lin', 'c'], 124.0],
            [[123.4678, 1, 'linear', 'ceiling'], 123.5],
            [[123.4678, 2, 'lin', 'ceil'], 123.47],
            #    logarithmic
            [[123.4678, 0, 'log', 'c'], 200.0],
            [[123.4678, 1, 'logarithmic', 'c'], 130.0],
            [[123.4678, 2, 'log', 'c'], 124.0],
            [[123.4678, 3, 'log', 'c'], 123.5],
            #       Negative decimals (order-of-magnitude rounding)
            [[213.4678, -1, 'log', 'c'], 1000.0],
            # Floor (down)
            #    linear
            [[123.4678, 0, 'lin', 'f'], 123.0],
            [[123.4678, 1, 'linear', 'fl'], 123.4],
            [[123.4678, 2, 'lin', 'floor'], 123.46],
            #    logarithmic
            [[123.4678, 0, 'log', 'f'], 100.0],
            [[123.4678, 1, 'logarithmic', 'f'], 120.0],
            [[123.4678, 2, 'log', 'f'], 123.0],
            [[123.4678, 3, 'log', 'f'], 123.4],
            #       Negative decimals (order-of-magnitude rounding)
            [[213.4678, -1, 'log', 'f'], 100.0],
        ]
        for vv in vals:
            print(vv)
            res = around(*vv[0])
            print("\t", res)
            assert_true(np.isclose(vv[1], res))

        # Invalid 'scaling'
        assert_raises(ValueError, around, 1234.567, 1, 'symlog', 'n')
        # Invalid 'dir'ection
        assert_raises(ValueError, around, 1234.567, 1, 'log', 'm')
        return

    def test_str_array(self):
        from zcode.math.math_core import str_array
        print("TestMathCore.test_str_array()")

        arr = np.linspace(0, 10.0, 6)
        correct = '[0.00, 2.00, 4.00, 6.00, 8.00, 10.00]'
        sa = str_array(arr)
        print("'({})' ==> '{}', should be '{}'".format(arr, sa, correct))
        assert_true(sa == correct)

        sa = str_array(arr, (2, 2))
        print("'({}, (2, 2))' ==> '{}'".format(arr, sa))
        assert_true(sa == '[0.00, 2.00... 8.00, 10.00]')

        sa = str_array(arr, None)
        print("'({}, None)' ==> '{}'".format(arr, sa))
        assert_true(sa == '[0.00, 2.00, 4.00, 6.00, 8.00, 10.00]')

        sa = str_array(arr, 1)
        print("'({}, 1)' ==> '{}'".format(arr, sa))
        assert_true(sa == '[0.00... 10.00]')

        sa = str_array(arr, (1, 3))
        print("'({}, (1, 3))' ==> '{}'".format(arr, sa))
        assert_true(sa == '[0.00... 6.00, 8.00, 10.00]')

        sa = str_array(arr, (12, 10))
        print("'({}, (12, 10))' ==> '{}'".format(arr, sa))
        assert_true(sa == '[0.00, 2.00, 4.00, 6.00, 8.00, 10.00]')

        sa = str_array(arr, (2, 1), delim=' ')
        print("'({}, (2, 1), delim=' ')' ==> '{}'".format(arr, sa))
        assert_true(sa == '[0.00 2.00... 10.00]')

        sa = str_array(arr, (2, 1), format=':.1e')
        print("'({}, (2, 1), format=':.1e')' ==> '{}'".format(arr, sa))
        assert_true(sa == '[0.0e+00, 2.0e+00... 1.0e+01]')

        return

    def test_broadcast(self):
        from zcode.math.math_core import broadcast

        def check_in_ot(din, check):
            dot = broadcast(*din)
            print("input:  {}".format(din))
            print("output: {} ({})".format(dot, check))
            assert_true(np.all([dd == cc for dd, cc in zip(dot, check)]))
            assert_true(np.all([np.shape(dd) == np.shape(cc) for dd, cc in zip(dot, check)]))
            return

        # Normal broadcast (1,) (2,) ==> (2,) (2,)
        din = [[1.0], [2.0, 3.0]]
        check = [[[1.0, 1.0]], [[2.0, 3.0]]]
        check_in_ot(din, check)

        # Scalar-only broadcast () () ==> () ()
        din = [1.0, 2.0]
        check = din
        check_in_ot(din, check)

        # Mixed scalar and array
        din = [1.5, [1.0, 2.0], [1.0, 2.0, 3.0]]
        check = [
            [[1.5, 1.5, 1.5], [1.5, 1.5, 1.5]],
            [[1.0, 1.0, 1.0], [2.0, 2.0, 2.0]],
            [[1.0, 2.0, 3.0], [1.0, 2.0, 3.0]]
        ]
        check_in_ot(din, check)

        din = [[1.0], [2.0, 3.0]]
        check = [[[1.0, 1.0]], [[2.0, 3.0]]]
        dot = broadcast(*din)
        check_in_ot(din, check)

        sh_in = np.random.randint(1, 5, 3)
        sh_ot = [sh_in for ii in range(len(sh_in))]
        din = [np.random.normal(size=sh) for sh in sh_in]
        dot = broadcast(*din)
        print("Input shapes: '{}'".format(sh_in))
        print("Output shapes: '{}' ({})".format([dd.shape for dd in dot], sh_ot))
        assert_true(np.all([dd.shape == sh for dd, sh in zip(dot, sh_ot)]))
        return

class Test_Interp(object):

    def test_interp_lin_lin(self):
        print("\ntest_interp_lin_lin()")
        kw = dict(xlog=False, ylog=False, valid=False, left=np.nan, right=100.0)

        xo = [1.0, 2.0, 3.0]
        yo = [10.0, 20.0, 30.0]

        tests = [1.5, 2.5, 0.5, 3.5]
        truth = [15.0, 25.0, np.nan, 100.0]

        for xx, zz in zip(tests, truth):
            yy = interpolate.interp(xx, xo, yo, **kw)
            print("{} ==> {}, should be {}".format(xx, yy, zz))
            if np.isnan(zz):
                assert_true(np.isnan(yy))
            else:
                assert_almost_equal(yy, zz)

        return

    def test_interp_lin_log(self):
        print("\ntest_interp_lin_log()")
        kw = dict(xlog=False, ylog=True, valid=False, left=100.0, right=np.nan)

        xo = [1.0, 2.0, 3.0]
        yo = [1.0e1, 1.0e3, 1.0e5]

        tests = [1.5, 2.5, 0.5, 3.5]
        truth = [1.0e2, 1.0e4, 100.0, np.nan]

        for xx, zz in zip(tests, truth):
            yy = interpolate.interp(xx, xo, yo, **kw)
            print("{} ==> {}, should be {}".format(xx, yy, zz))
            if np.isnan(zz):
                assert_true(np.isnan(yy))
            else:
                assert_almost_equal(yy, zz)

        return

    def test_interp_log_lin(self):
        print("\ntest_interp_log_lin()")
        kw = dict(xlog=True, ylog=False, valid=False, left=100.0, right=np.nan)

        xo = [2.0e-5, 2.0e-3, 2.0e-1]
        yo = [-10.0, -20.0, -30.0]

        tests = [2.0e-4, 2.0e-2, 1.0e-8, 1.0e8]
        truth = [-15.0, -25.0, 100.0, np.nan]

        for xx, zz in zip(tests, truth):
            yy = interpolate.interp(xx, xo, yo, **kw)
            print("{} ==> {}, should be {}".format(xx, yy, zz))
            if np.isnan(zz):
                assert_true(np.isnan(yy))
            else:
                assert_almost_equal(yy, zz)

        return

    def test_interp_log_log(self):
        print("\ntest_interp_log_log()")
        kw = dict(xlog=True, ylog=True, valid=False, left=np.nan, right=100.0)

        xo = [1.0e-1, 1.0e1, 1.0e5]
        yo = [3.0e0, 3.0e-2, 3.0e6]

        tests = [1.0, 1.0e3, 1.0e-8, 1.0e8]
        truth = [3.0e-1, 3.0e2, np.nan, 100.0]

        for xx, zz in zip(tests, truth):
            yy = interpolate.interp(xx, xo, yo, **kw)
            print("{} ==> {}, should be {}".format(xx, yy, zz))
            if np.isnan(zz):
                assert_true(np.isnan(yy))
            else:
                assert_almost_equal(yy, zz)

        return

class Test_Interp_Func_Linear(object):

    KW = dict(kind='linear', bounds_error=False)

    def test_interp_func(self):
        print("\n|test_interp_func()|")
        options = [True, False]
        TRIES = 10
        SAMPS = 40
        TESTS = 100
        LOG_RANGE = [-8.0, 8.0]

        for xlog in options:
            for ylog in options:
                kw = dict(xlog=xlog, ylog=ylog)
                print("xlog = {}, ylog = {}".format(xlog, ylog))

                for kk in range(TRIES):
                    xo = np.random.uniform(*LOG_RANGE, SAMPS)
                    xo = np.sort(xo)
                    yo = np.random.uniform(*LOG_RANGE, SAMPS)

                    xx = np.random.uniform(*math_core.minmax(xo), TESTS)

                    if xlog:
                        xo = np.power(10.0, xo)
                        xx = np.power(10.0, xx)
                    if ylog:
                        yo = np.power(10.0, yo)

                    y1 = interpolate.interp(xx, xo, yo, valid=False, **kw)
                    y2 = interpolate.interp_func(xo, yo, kind='linear', bounds_error=False, **kw)(xx)
                    assert_true(np.allclose(y1, y2))

        return

    def test_interp_func_lin_lin(self):
        print("\n|test_interp_func_lin_lin()|")
        kw = dict(xlog=False, ylog=False, fill_value=(np.nan, 100.0))
        kw.update(self.KW)

        xo = [1.0, 2.0, 3.0]
        yo = [10.0, 20.0, 30.0]

        tests = [1.5, 2.5, 0.5, 3.5]
        truth = [15.0, 25.0, np.nan, 100.0]

        for xx, zz in zip(tests, truth):
            yy = interpolate.interp_func(xo, yo, **kw)(xx)
            print("{} ==> {}, should be {}".format(xx, yy, zz))
            if np.isnan(zz):
                assert_true(np.isnan(yy))
            else:
                assert_almost_equal(yy, zz)

        return

    def test_interp_func_lin_log(self):
        print("\n|test_interp_func_lin_log()|")
        kw = dict(xlog=False, ylog=True, fill_value=(100.0, np.nan))
        kw.update(self.KW)

        xo = [1.0, 2.0, 3.0]
        yo = [1.0e1, 1.0e3, 1.0e5]

        tests = [1.5, 2.5, 0.5, 3.5]
        truth = [1.0e2, 1.0e4, 100.0, np.nan]

        for xx, zz in zip(tests, truth):
            yy = interpolate.interp_func(xo, yo, **kw)(xx)
            print("{} ==> {}, should be {}".format(xx, yy, zz))
            if np.isnan(zz):
                assert_true(np.isnan(yy))
            else:
                assert_almost_equal(yy, zz)

        return

    def test_interp_func_log_lin(self):
        print("\n|test_interp_func_log_lin()|")
        kw = dict(xlog=True, ylog=False, fill_value=(100.0, np.nan))
        kw.update(self.KW)

        xo = [2.0e-5, 2.0e-3, 2.0e-1]
        yo = [-10.0, -20.0, -30.0]

        tests = [2.0e-4, 2.0e-2, 1.0e-8, 1.0e8]
        truth = [-15.0, -25.0, 100.0, np.nan]

        for xx, zz in zip(tests, truth):
            yy = interpolate.interp_func(xo, yo, **kw)(xx)
            print("{} ==> {}, should be {}".format(xx, yy, zz))
            if np.isnan(zz):
                assert_true(np.isnan(yy))
            else:
                assert_almost_equal(yy, zz)

        return

    def test_interp_func_log_log(self):
        print("\n|test_interp_func_log_log()|")
        kw = dict(xlog=True, ylog=True, fill_value=(np.nan, 100.0))
        kw.update(self.KW)

        xo = [1.0e-1, 1.0e1, 1.0e5]
        yo = [3.0e0, 3.0e-2, 3.0e6]

        tests = [1.0, 1.0e3, 1.0e-8, 1.0e8]
        truth = [3.0e-1, 3.0e2, np.nan, 100.0]

        for xx, zz in zip(tests, truth):
            yy = interpolate.interp_func(xo, yo, **kw)(xx)
            print("{} ==> {}, should be {}".format(xx, yy, zz))
            if np.isnan(zz):
                assert_true(np.isnan(yy))
            else:
                assert_almost_equal(yy, zz)

        return

class Test_Interp_Func_Mono(object):

    KW = dict(kind='mono')

    def test_interp_func(self):
        print("\n|test_interp_func()|")

        xo = [0.1, 1.0, 2.0, 3.0, 4.0, 5.0]
        yo = [100.0, 100.0, 90.0, 0.1, 2.0, 2.0]
        NUM = len(xo)

        xn = np.linspace(xo[1], xo[-2], 1000)

        def test_within(xx, yy):
            vals = []
            for ii in range(NUM-1):
                xl = xo[ii]
                xh = xo[ii+1]
                yl = yo[ii]
                yh = yo[ii+1]

                inds = (xl <= xx) & (xx <= xh)
                rv1 = math_core.within(yy[inds], [yl, yh], all=True, close=True)
                rv2 = math_core.mono(yy[inds], 'ge') or math_core.mono(yy[inds], 'le')
                rv = (rv1 and rv2)
                vals.append(rv)

            return np.all(vals)

        options = [True, False]
        for xlog in options:
            for ylog in options:
                func = interpolate.interp_func(xo, yo, xlog=xlog, ylog=ylog, kind='mono')
                yn = func(xn)
                print("xlog = {}, ylog = {}".format(xlog, ylog))
                assert_true(test_within(xn, yn))

                # 'cubic' should be NON-monotonic, make sure test shows that
                func = interpolate.interp_func(xo, yo, xlog=xlog, ylog=ylog, kind='cubic')
                yn = func(xn)
                assert_false(test_within(xn, yn))

        return

class Test_Edges_From_Cents(object):

    def test_lin_spacing(self):
        print("\n|test_lin_spacing()|")

        edges_true = [
            np.linspace(0.0, 1.0, 20),
            np.linspace(1.0, 0.0, 20),
            np.linspace(-100, 100, 100)
        ]

        for true in edges_true:
            cents = math_core.midpoints(true, log=False)
            edges = math_core.edges_from_cents(cents, log=False)

            print("truth = {}".format(math_core.str_array(true)))
            print("recov = {}".format(math_core.str_array(edges)))
            assert_true(np.allclose(edges, true))

        return

    def test_log_spacing(self):
        print("\n|test_log_spacing()|")

        true_pars = [
            [0.0, 1.0, 20],
            [1.0, 0.0, 20],
            [2.0, -2.0, 100]
        ]

        for pars in true_pars:
            true = np.logspace(*pars)
            cents = math_core.midpoints(true, log=True)
            edges = math_core.edges_from_cents(cents, log=True)
            print("pars = ", pars)
            print("truth = {}".format(math_core.str_array(true)))
            print("recov = {}".format(math_core.str_array(edges)))
            assert_true(np.allclose(edges, true))

        return

    def test_irr_spacing(self):
        print("\n|test_irr_spacing()|")

        NUM = 10
        xx = np.arange(NUM)
        widths = 1.5 + 0.4*xx + 0.1*(xx**2)

        true = np.zeros(NUM+1)
        true[0] = 4.0
        for ii in range(1, NUM+1):
            true[ii] = true[ii-1] + widths[ii-1]

        cents = math_core.midpoints(true, log=False)
        edges = math_core.edges_from_cents(cents, log=False)
        print("truth = {}".format(math_core.str_array(true)))
        print("recov = {}".format(math_core.str_array(edges)))
        assert_true(np.allclose(edges, true, rtol=1e-1))

        return

# Run all methods as if with `nosetests ...`
if __name__ == "__main__":
    run_module_suite()


import numpy as np
import pandas as pd

from keras.callbacks import EarlyStopping
from keras.callbacks import ModelCheckpoint

from keras.models import Sequential
from keras.layers.core import Dense, Dropout, Activation, Flatten
from keras.layers.convolutional import Conv2D, MaxPooling2D
from keras.optimizers import SGD, Adam
from keras import backend as K
K.set_image_data_format('channels_first')

class Classifier(object):
    """Plain-vanilla classifier

    Inputs
    ------
    input_shape : list-like of int (length 2 or 3)
        - shape of each input image. e.g. `(3, 50, 50)`

    num_conv_filters: Optional(list-like of int)
         - List of `filters` parameters for `keras.layers.convolutional.Conv2D`
         - Length of this parameter should match the number of conv layers desired

    conv_kernel_sizes: Optional(list-like of int)
         - List of `kernel_size` parameters for `keras.layers.convolutional.Conv2D`
         - Length of this parameter should match the number of conv layers desired

    padding: Optional(str)
        - parameter for `keras.layers.convolutional.Conv2D`

    pool_size: Optional(ist-like of int [length 2])
        - the parameter for `keras.layers.convolutional.MaxPooling2D`

    dropout_fraction: Optional(float)
        - parameter for `keras.layers.core.Dropout` after each conv layer

    activation: Optional(str)
        - parameter for `keras.layers.core.Activation` between each layer
          (but not after the final dense layer)

    activation_final: Optional(str)
        - the final activation of the output layer

    num_neurons_dense: Optional(list-like of int)
         - Number of dense layers set by length of this parameter
         - `num_neurons_dense[-1]` sets the number of outputs from the network

    loss_function_name: Optional(str)
        - the loss function which the optimizer tries to minimize

    batch_size: Optional(int)
        - batch the training into `batch_size` amount of images

    """
    def __init__(self,
                 input_shape,
                 num_conv_filters=(16, 16, 16),
                 conv_kernel_sizes=(4, 8, 16),
                 padding="same",
                 pool_size=(2, 2),
                 dropout_fraction=0.25,
                 activation="relu",
                 activation_final="sigmoid",
                 num_neurons_dense=(128, 64, 1),
                 loss_function_name="binary_crossentropy",
                 batch_size=64):

        assert(len(num_conv_filters) == len(conv_kernel_sizes))

        self.input_shape = input_shape
        self.num_conv_filters = num_conv_filters
        self.conv_kernel_sizes = conv_kernel_sizes
        self.padding = padding
        self.pool_size = pool_size
        self.dropout_fraction = dropout_fraction
        self.activation = activation
        self.activation_final = activation_final
        self.num_neurons_dense = num_neurons_dense
        self.loss_function_name = loss_function_name
        self.batch_size = batch_size

    def configure_optimizer(self, lr=0.001, **kwargs):
        """Configure an `Adam` optimizer
        """
        kwargs["lr"] = lr
        self.optimizer = Adam(**kwargs)

    def configure_early_stopping(self,
                                 monitor="loss",
                                 patience=35,
                                 verbose=1,
                                 mode="auto",
                                 **kwargs):
        """Configure patience-based early stopping on our optimizer
        """
        self.early_stopping = EarlyStopping(monitor=monitor,
                                            patience=patience,
                                            verbose=verbose,
                                            mode=mode,
                                            **kwargs,
                                            )

    def build_model(self):
        model = Sequential()

        # # # Convolutional Layers
        num_conv_layers = len(self.num_conv_filters)
        for i in range(num_conv_layers):
            model.add(Conv2D(self.num_conv_filters[i],
                             self.conv_kernel_sizes[i],
                             padding=self.padding,
                             input_shape=self.input_shape,
                             ))
            model.add(Activation(self.activation))
            model.add(MaxPooling2D(pool_size=self.pool_size))
            model.add(Dropout(self.dropout_fraction))

        model.add(Flatten())

        # # # Dense / Fully-Connected Layers
        number_of_dense_layers = len(self.num_neurons_dense)
        for i, num_neurons in enumerate(self.num_neurons_dense):
            if (i+1) != number_of_dense_layers:
                activation = self.activation
            else:
                activation = self.activation_final
            model.add(Dense(num_neurons, activation=activation))

        model.compile(loss=self.loss_function_name,
                      optimizer=self.optimizer)

        self.model = model

    def fit_model(self,
                  X,
                  Y,
                  training_set_indices,
                  testing_set_indices,
                  data_iterator,
                  verbose=1,
                  max_epochs=100):

        batches_per_epoch = training_set_indices.size//self.batch_size

        if verbose:
            print("batches_per_epoch: ", batches_per_epoch)
            print("batch_size: ", self.batch_size)

        history = self.model \
                      .fit_generator(data_iterator,
                                     steps_per_epoch=batches_per_epoch,
                                     epochs=max_epochs,
                                     validation_data=(X[testing_set_indices],
                                                      Y[testing_set_indices]),
                                     verbose=verbose,
                                     callbacks=[self.early_stopping],
                                     )

        return history


#!/usr/bin/python

import numpy as np
import matplotlib.pyplot as plt
from math import floor, log
import os
from datetime import date
import signal

# my library
from common_library import *
from particle_filter import *
from cascadeLPBN import *
from print_library import *

import time

def generate_folder(path):
  if not os.path.exists(path):
      os.makedirs(path)

# Close the generation data
def handler(signum, frame):
    res = input("Ctrl-c was pressed. Do you really want to exit? y/n ")
    if res == 'y':
        exit(1)

signal.signal(signal.SIGINT, handler)

# The simulation "time"
steps = 300
# When appling the damage
damage_time = 200
end_damage_time = steps

# The network to simulate
namefile="edkcbr_sano"
# The network with the cancer-typed error
error_file="edkcbr_cancer"

# The PBN network to use
exec(open("../networks/"+namefile+".json").read())
# The PBNc (PBN of the cancer) network to use
exec(open("../networks/"+error_file+".json").read())

generation = 160

while True:
  print("Generation "+str(generation))
  # Generte an initial state
  x01 = getRandState(PBN['x,u,y'][0])
  x02 = getRandState(PBN['x,u,y'][0])
  x0 = np.concatenate((x01,getXD(x01,x02)))
  u = getRandState(PBN['x,u,y'][1])
  # x0 = np.array([0,1,0,0,0,1])
  # u = np.array([0,1])
  # print("Models creation...")
  pc1 = cascadeLPBN(PBN, u,namefile)
  pc_cancer = cascadeLPBN(PBNc, u,error_file)
  # pc1.gel() # generate the estimated matrix for the normal behaviur
  # print("Done")
  # y time 0, u time 0, x time 1
  # print("System inizialization...")
  xc,yc  = pc1.updateSystem(x0,u)
  # print("Done")

  # Inizialize the state vectors
  ax = []
  au = []
  ay = []

  ax.append(x0)
  au.append(u)
  ay.append(yc)

  print("xc:"+str(x0))
  print("yc:"+str(yc))

  tin = time.time()

  # Do the first simulation
  print("---")
  for i in range(steps):
      # Simulate the system
      # print("time :"+str(i))
      u = getRandState(PBN['x,u,y'][1])
      ax.append(xc)
      au.append(u)
      #ts = time.time()

      if (i > damage_time and i < end_damage_time):
          # Broken network
          xc,yc  = pc_cancer.updateSystem(xc,u,True)
      else:
          # Normal network
          xc,yc  = pc1.updateSystem(xc,u,True)
      ay.append(yc)
      if (i % 10 == 0):
        print("time :"+str(i))

  tfin = time.time()
  print("Simulation time ="+str(tfin-tin))

  data_str = "data/"+str(date.today())+"_"+str(generation)
  generate_folder(data_str)
  np.save(data_str+"/ax", ax)
  np.save(data_str+"/au", au)
  np.save(data_str+"/ay", ay)

  print(ax)

  plt.figure(figsize=(15,6))
  print_evolution_state(ax, PBN['x,u,y'][0])
  plt.savefig(data_str+"/states.png")

  generation = generation+1


import torch
from tqdm import tqdm
from scipy.integrate import trapz

def to_np(tensor: torch.Tensor):
    return tensor.detach().cpu().numpy()

def eval_func_on_grid(
    density_func,
    interval=(-10, 10),
    num_samples=200,
    device="cpu",
    dimensions=2,
    batch_size=10_000,
    dtype=torch.float32,
):
    interp = torch.linspace(*interval, num_samples)
    grid_coords = torch.meshgrid(*[interp for _ in range(dimensions)])
    grid = torch.stack([coords.reshape(-1) for coords in grid_coords], 1).to(dtype)

    vals = []
    for samples in tqdm(torch.split(grid, batch_size)):
        vals.append(density_func(samples.to(device)).cpu())
    vals = torch.cat(vals)
    return grid_coords, vals

def estimate_normalizing_constant(
    density_func,
    interval=(-10, 10),
    num_samples=200,
    device="cpu",
    dimensions=2,
    batch_size=10_000,
    dtype=torch.float32,
):
    """
    Numerically integrate a funtion in the specified interval.
    """
    with torch.no_grad():
        _, p_x = eval_func_on_grid(
            density_func, interval, num_samples, device, dimensions, batch_size, dtype
        )

        dx = (abs(interval[0]) + abs(interval[1])) / num_samples
        # Integrate one dimension after another
        grid_vals = to_np(p_x).reshape(*[num_samples for _ in range(dimensions)])
        for _ in range(dimensions):
            grid_vals = trapz(grid_vals, dx=dx, axis=-1)

        return torch.tensor(grid_vals)

def sum_except_batch(x, num_batch_dims=1):
    """Sums all elements of `x` except for the first `num_batch_dims` dimensions."""
    if x.ndimension() == 1:
        return x
    reduce_dims = list(range(num_batch_dims, x.ndimension()))
    return torch.sum(x, dim=reduce_dims)

def split_leading_dim(x, shape):
    """Reshapes the leading dim of `x` to have the given shape."""
    new_shape = torch.Size(shape) + x.shape[1:]
    return torch.reshape(x, new_shape)

if __name__ == "__main__":
    dims = 2
    samples = 100
    print(
        estimate_normalizing_constant(
            lambda x: torch.empty(x.shape[0]).fill_(1 / (samples ** dims)),
            num_samples=samples,
            dimensions=dims,
        )
    )


import pygame.sprite
from pygame.surface import Surface

from core.animate import Animation
from core.sprite import BaseSprite
from settings import DEFAULT_CONTROLS

class Fisher(BaseSprite):
    def __init__(
        self,
        x: int,
        y: int,
        animations: dict[str, Animation],
        *groups
    ):
        self.animations = animations

        self.controls = DEFAULT_CONTROLS
        self.speed = 1.1

        self.animation = "normal"
        super().__init__((x, y), (60.8, 57.6), *groups)

    def catch_animation(self):
        self.animation = "catch"

    def update(self, now, *args):
        if self.animation == "catch" and self.get_anim().done:
            self.get_anim().reset()
            self.animation = "normal"

        self.image = self.get_anim().get_next_frame(now)
        width, height = self.image.get_size()
        self.image = pygame.transform.scale(self.image, (width * 1.6, height * 1.6))

    def get_anim(self):
        return self.animations[self.animation]


# Uses python3
import sys
from itertools import chain

def fast_count_segments(starts, ends, points):
    count = [0] * len(points)

    starts = zip(starts, [float('-inf')]*len(starts))
    ends = zip(ends, [float('inf')]*len(ends))
    points = zip(points, range(len(points)))

    sorted_list = sorted(chain(starts, ends, points), key=lambda starts: (starts[0], starts[1]))
    stack = []

    for i, j in sorted_list:
        if j == float('-inf'):
            stack.append(j)
        elif j == float('inf'):
            stack.pop()
        else:
            count[j] = len(stack)

    return count

def naive_count_segments(starts, ends, points):
    count = [0] * len(points)
    for i in range(len(points)):
        for j in range(len(starts)):
            if starts[j] <= points[i] <= ends[j]:
                count[i] += 1
    return count

if __name__ == '__main__':
    input = sys.stdin.read()
    data = list(map(int, input.split()))
    n = data[0]
    m = data[1]
    starts = data[2:2 * n + 2:2]
    ends   = data[3:2 * n + 2:2]
    points = data[2 * n + 2:]
    #use fast_count_segments
    count = fast_count_segments(starts, ends, points)
    for x in count:
        print(x, end=' ')


import os
import csv
import re

try:
    import xlrd
except ImportError as exc:
    print(exc)
    print(f"The module {exc.name} is required!")
try:
    import openpyxl
except ImportError as exc:
    print(exc)
    print(f"The module {exc.name} is required!")

def xl_export(filepath, sheet, start_row=2):
    """Hämtar data från en excelfil och returnerar en lista som kan användas
    i funktionen mssql_insert. Är det många rader så är den seg. Skulle vara
    interssant att jämföra denna i kombination med mssql_insert med.
    För alternativ se xl_to_csv"""
    try:
        wb = openpyxl.load_workbook(filename=filepath, data_only=True, read_only=True)
        sheet = wb[sheet]
        data = []
        for row in sheet.iter_rows():
            data_row = []
            for cell in row:
                data_row += [cell.value]
            data += [data_row]
        start_row = start_row - 1
        result_list = [tuple(l) for l in data[start_row:]]
        return result_list
    except Exception as exc:
        print(exc)
        raise

def xl_to_csv(inFile, outFile, sheet):
    """write docstring"""
    try:
        # print("xlsxToCsv")
        wb = xlrd.open_workbook(inFile)
        sh = wb.sheet_by_name(sheet)
        your_csv_file = open(outFile, "w", encoding="utf-8", newline="")
        wr = csv.writer(your_csv_file, delimiter="|")
        # print('xlsxToCsv')
        for rownum in range(sh.nrows):
            wr.writerow(sh.row_values(rownum))
        your_csv_file.close()
    except Exception as exc:
        print(exc)
        raise

def change_enc_one_file(outFile, s_decode="utf-8", d_encode="utf-16"):
    """write docstring"""
    print("changeEnc")
    with open(outFile, "rb") as source_file:
        target_file_name = outFile
        with open(target_file_name, "w+b") as dest_file:
            contents = source_file.read()
            dest_file.write(contents.decode(s_decode).encode(d_encode))

def change_enc_multiple_files(path, s_decode="utf-8", d_encode="utf-16"):
    """write docstring"""

    for file in os.listdir(path):
        # print("denc_utf16_Kör: "+file)
        filepath = os.path.join(path, file)
        # filename = os.path.splitext(file)[0]
        with open(filepath, "rb") as source_file:
            contents = source_file.read()
            try:
                os.remove(filepath)
            except OSError:
                pass
            target_file_name = filepath
            with open(target_file_name, "w+b") as dest_file:
                dest_file.write(contents.decode(s_decode).encode(d_encode))

def txt_to_csv(
    path,
    delete_original_file="Yes",
    encoding="utf-8",
    delimiter_outfile=";",
    delimiter_infile="",
):
    """
    This function loops through a chosen folder and changes a txt file to a
    csv file. Optinal changes to teh file is delieting the original file,
    reencoding, and change of the delimiter\n
    path = path of the txt file/s that should be converted to csv.\n
    delete_original_file = if yes the original file is deleted, default is yes\n
    encoding = encoding of the csvfile, default=utf-8.\n
    delimiter_outfile = delimiter of the csv file, default is ';'.\n
    delimiter_infile = if the delimiter of the txt file is known it can be
    specified here. Although it is not necassary if the delimiter is equal
    to one of the following: [',',';','\t','|']. If the delimiter not is one of
    these 4 then the function will throw an exception.
    """
    # add delete of originalfile

    file_list = os.listdir(path)
    for file in file_list:
        if os.path.splitext(file)[1] != ".txt":
            continue
        filename = os.path.splitext(file)[0]
        filepath_in = path + file
        filepath_out = path + filename + ".csv"
        with open(filepath_in, "r") as fin:
            if delimiter_infile == "":
                dialect = csv.Sniffer().sniff(fin.readline(), [",", ";", "\t", "|"])
                fin.seek(0)
            else:
                dialect = delimiter_infile
            in_file = csv.reader(fin, dialect)
            with open(filepath_out, "w", newline="", encoding=encoding) as fout:
                out_file = csv.writer(fout, delimiter=delimiter_outfile)
                out_file.writerows(in_file)
        if str.upper(delete_original_file).startswith("Y") or str.upper(
            delete_original_file
        ).startswith("J"):
            os.remove(filepath_in)

def list_to_csv(fullFilePath, result_list, csvType="w"):
    """ """
    try:
        if csvType == "w":
            with open(fullFilePath, "w", newline="\n") as f:
                writer = csv.writer(f, delimiter="|")
                writer.writerows(result_list)
        if csvType == "a":
            with open(fullFilePath, "a", newline="\n") as f:
                writer = csv.writer(f, delimiter="|")
                writer.writerows(result_list)
    except TypeError:
        pass

def checkDataForFaultyDelimiters(
    data, expected_number_of_delimiters, delimiter=";", start_row=0, end_row="LAST_ROW"
):
    """Checks if there are any rows that has to many delimiters and returns
    the total number of "bad rows".\n
    return: int\n
    Inputs:\n
    data = list of lists\n
    expected_number_of_delimiters = int\n
    delimiter = string. Default is ";"\n
    start_row = int. Default is the first row, i.e. index 0.\n
    end_row = int. Default is the last row, i.e. len(data)
    """
    ex = expected_number_of_delimiters
    d = delimiter
    st = start_row
    if end_row == "LAST_ROW":
        end = len(data)
    else:
        end = end_row
    count = 0
    for row in data[st:end]:
        for l in row:
            if len(re.findall(d, l)) > ex:
                count += 1
    return count

def correctFaultyDelimiter(data, position_of_faulty_delimiter, delimiter, replacement):
    """Byter endast ut en felaktig delimiter"""
    corrected_bad_rows = []
    n = position_of_faulty_delimiter
    d = delimiter
    rep = replacement
    for rows in data:
        r = str(rows).replace("[", "").replace("]", "")
        where = [m.start() for m in re.finditer(d, r)][n - 1]
        before = r[:where]
        # print(before)
        after = r[where:]
        # print(after)
        x = after.replace(d, rep, 1)
        newString = (before + x).replace("'", "")
        # print(newString)
        corrected_bad_rows.append(newString.split(d))
    return corrected_bad_rows

def correctMultipleFaultyDelimiters(
    data,
    position_of_faulty_delimiter,
    delimiter,
    replacement,
    columns,
    start_row=0,
    end_row="LAST_ROW",
):
    """ Finds and replaces faulty delimiters in list of lists.
    When to use: E.g. if there should be 5 columns in the data but there is
    more than four (4) delimiters the data is impossible to insert into a
    database. This function replaces the faulty delimiters and makes the
    data ok.\n
    return: list of lists\n
    Inputs:\n
    data = list of lists\n
    position_of_faulty_delimiter = integer, the position of the faulty
    delimiter, occurs in textfields\n
    delimiter = string. Default is ";"\n
    replacement = string, e.g. "_"\n
    columns = int, numnber of columns in the data.
    start_row = int. Default is the first row, i.e. index 0.\n
    end_row = int. Default is the last roe, i.e. len(data)
    """
    corrected_data = []
    n = position_of_faulty_delimiter
    d = delimiter
    rep = replacement
    col = columns - 1
    st = start_row
    if end_row == "LAST_ROW":
        end = len(data)
    else:
        end = end_row
    for row in data[st:end]:
        count = len(re.findall(d, str(row)))
        if count > col:
            while count > col:
                r = str(row).replace("[", "").replace("]", "")
                where = [m.start() for m in re.finditer(d, r)][n - 1]
                before = r[:where]
                after = r[where:]
                after = after.replace(d, rep, 1)
                row = (before + after).replace("'", "")
                count = len(re.findall(d, row))
        else:
            row = str(row).replace("[", "").replace("]", "").replace("'", "")
        corrected_data.append(row.split(d))
    return corrected_data


import matplotlib.pyplot as plt
import numpy as np

# Suponiendo que tus datos están en el siguiente formato:
# {"network_name": {"vanilla": latency, "TRT_fp32": latency, "TRT_fp16": latency, "TRT_int8": latency}, ...}

data = {
    "resnet18": {"Vanilla": 1.9, "TRT_fp32": 1.3, "TRT_fp16": 0.8 , "TRT_int8": 0.7},
    "resnet34": {"Vanilla": 3.1, "TRT_fp32": 2.1 , "TRT_fp16": 1.0 , "TRT_int8": 0.8},
    "resnet50": {"Vanilla": 3.7, "TRT_fp32": 2.2  , "TRT_fp16": 1.0 , "TRT_int8": 0.9},
    "resnet101": {"Vanilla": 5.8, "TRT_fp32": 3.8  , "TRT_fp16": 1.7 , "TRT_int8": 1.2 },
    "resnet152": {"Vanilla": 8.1 , "TRT_fp32": 5.5   , "TRT_fp16": 2.2  , "TRT_int8": 1.5 },
    "mobilenet": {"Vanilla": 2.8, "TRT_fp32": 1.0, "TRT_fp16": 0.8 , "TRT_int8": 0.8},
    "yolon": {"Vanilla": 1.9, "TRT_fp32": 0.9, "TRT_fp16": 0.8, "TRT_int8": 0.8},
    "yolox": {"Vanilla": 5.9, "TRT_fp32": 4.3, "TRT_fp16": 1.8 , "TRT_int8": 1.4}
    #... [Similar data for other networks]
}

# Configuraciones del gráfico
barWidth = 0.2
labels = list(data.keys())
vanilla = [values["Vanilla"] for values in data.values()]
TRT_fp32 = [values["TRT_fp32"] for values in data.values()]
TRT_fp16 = [values["TRT_fp16"] for values in data.values()]
TRT_int8 = [values["TRT_int8"] for values in data.values()]

# Configurando la posición de las barras en X
r1 = np.arange(len(vanilla))
r2 = [x + barWidth for x in r1]
r3 = [x + barWidth for x in r2]
r4 = [x + barWidth for x in r3]

# Creando el gráfico de barras
plt.bar(r1, vanilla,  width=barWidth, edgecolor='white', label='vanilla')
plt.bar(r2, TRT_fp32,  width=barWidth, edgecolor='white', label='TRT_fp32')
plt.bar(r3, TRT_fp16,  width=barWidth, edgecolor='white', label='TRT_fp16')
plt.bar(r4, TRT_int8,  width=barWidth, edgecolor='white', label='TRT_int8')

# Añadiendo etiquetas al gráfico
plt.xlabel('networks', fontweight='bold')
plt.xticks([r + barWidth for r in range(len(vanilla))], labels, rotation=20)
plt.ylabel('Latency ms' , fontweight='bold')

# Creando la leyenda y mostrando el gráfico
plt.legend()
plt.title('Latencia promedio por Red para Batch Size 1')
plt.grid()
plt.savefig('inference_time_bar_all.png')
plt.show()


import Chemins
from Utils import UTILS_Adaptations
from Utils.UTILS_Traduction import _
import wx
from Ctrl import CTRL_Bouton_image
import datetime
import GestionDB

from Utils import UTILS_Interface
from Ctrl.CTRL_ObjectListView import FastObjectListView, ColumnDefn, Filter, CTRL_Outils

from Utils import UTILS_Utilisateurs

class Track(object):
    def __init__(self, donnees, dictModeles):
        self.IDutilisateur = donnees[0]
        self.sexe = donnees[1]
        self.nom = donnees[2]
        self.prenom = donnees[3]
        self.mdp = donnees[4]
        self.profil = donnees[5]
        self.actif = donnees[6]
        if self.actif == 1 :
            self.texteActif = "Oui"
        else :
            self.texteActif = "Non"
        self.nomImage = donnees[7]

        # Droits
        if self.profil.startswith("modele:") :
            IDmodele = int(self.profil.replace("modele:", ""))
            if IDmodele in dictModeles :
                self.texteDroits = dictModeles[IDmodele]
            else :
                self.texteDroits = _(u"Modèle de droits inconnu")

        elif self.profil == "perso" :
            self.texteDroits = _(u"Droits personnalisés")

        else :
            self.texteDroits = _(u"Administrateur")

        # Image
        if self.nomImage == None or self.nomImage == "Automatique" :
            if self.sexe == "M" :
                self.image = wx.Bitmap(Chemins.GetStaticPath("Images/Avatars/16x16/Homme.png"), wx.BITMAP_TYPE_PNG)
            else:
                self.image = wx.Bitmap(Chemins.GetStaticPath("Images/Avatars/16x16/Femme.png"), wx.BITMAP_TYPE_PNG)
        else :
            self.image = wx.Bitmap(Chemins.GetStaticPath("Images/Avatars/16x16/%s.png" % self.nomImage), wx.BITMAP_TYPE_PNG)

class ListView(FastObjectListView):
    def __init__(self, *args, **kwds):
        # Récupération des paramètres perso
        self.selectionID = None
        self.selectionTrack = None
        self.criteres = ""
        self.itemSelected = False
        self.popupIndex = -1
        self.listeFiltres = []
        # Initialisation du listCtrl
        self.nom_fichier_liste = __file__
        FastObjectListView.__init__(self, *args, **kwds)
        # Binds perso
        self.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.OnItemActivated)
        self.Bind(wx.EVT_CONTEXT_MENU, self.OnContextMenu)

    def OnItemActivated(self,event):
        self.Modifier(None)

    def InitModel(self):
        self.donnees = self.GetTracks()

    def GetTracks(self):
        """ Récupération des données """
        listeID = None
        DB = GestionDB.DB()

        # Liste des modèles
        req = """SELECT IDmodele, nom
        FROM modeles_droits;"""
        DB.ExecuterReq(req)
        listeModeles = DB.ResultatReq()
        dictModeles = {}
        for IDmodele, nom in listeModeles :
            dictModeles[IDmodele] = nom

        # Liste des utilisateurs
        req = """SELECT IDutilisateur, sexe, nom, prenom, mdp, profil, actif, image
        FROM utilisateurs;"""
        DB.ExecuterReq(req)
        listeDonnees = DB.ResultatReq()
        DB.Close()

        listeListeView = []
        for item in listeDonnees :
            valide = True
            if listeID != None :
                if item[0] not in listeID :
                    valide = False
            if valide == True :
                track = Track(item, dictModeles)
                listeListeView.append(track)
                if self.selectionID == item[0] :
                    self.selectionTrack = track
        return listeListeView

    def InitObjectListView(self):
        # Couleur en alternance des lignes
        self.oddRowsBackColor = UTILS_Interface.GetValeur("couleur_tres_claire", wx.Colour(240, 251, 237))
        self.evenRowsBackColor = wx.Colour(255, 255, 255)
        self.useExpansionColumn = True

        # Préparation de la listeImages
        imgActif = self.AddNamedImages("actif", wx.Bitmap(Chemins.GetStaticPath("Images/16x16/Ok.png"), wx.BITMAP_TYPE_PNG))
        imgInactif = self.AddNamedImages("inactif", wx.Bitmap(Chemins.GetStaticPath("Images/16x16/Interdit.png"), wx.BITMAP_TYPE_PNG))

        for track in self.donnees :
            self.AddNamedImages(str(track.IDutilisateur), track.image)

        # Formatage des données
        def GetImageActif(track):
            if track.actif == 1 : return "actif"
            else: return "inactif"

        def GetImageAvatar(track):
            return str(track.IDutilisateur)

        liste_Colonnes = [

            ColumnDefn(u"", 'left', 22, "IDutilisateur", typeDonnee="entier", imageGetter=GetImageAvatar),
            ColumnDefn(_(u"Nom"), 'left', 150, "nom", typeDonnee="texte"),
            ColumnDefn(_(u"Prénom"), 'left', 150, "prenom", typeDonnee="texte"),
            ColumnDefn(_(u"Actif"), "left", 60, "texteActif", typeDonnee="texte", imageGetter=GetImageActif),
            ColumnDefn(_(u"Droits"), 'left', 200, "texteDroits", typeDonnee="texte"),
            ]

        self.SetColumns(liste_Colonnes)
        self.SetEmptyListMsg(_(u"Aucun utilisateur"))
        self.SetEmptyListMsgFont(wx.FFont(11, wx.DEFAULT, False, "Tekton"))
        self.SetSortColumn(self.columns[1])
        self.SetObjects(self.donnees)

    def MAJ(self, ID=None):
        if ID != None :
            self.selectionID = ID
            self.selectionTrack = None
        else:
            self.selectionID = None
            self.selectionTrack = None
        self.InitModel()
        self.InitObjectListView()
        # Sélection d'un item
        if self.selectionTrack != None :
            self.SelectObject(self.selectionTrack, deselectOthers=True, ensureVisible=True)
        self.selectionID = None
        self.selectionTrack = None

    def Selection(self):
        return self.GetSelectedObjects()

    def OnContextMenu(self, event):
        """Ouverture du menu contextuel """
        if len(self.Selection()) == 0:
            noSelection = True
        else:
            noSelection = False
            ID = self.Selection()[0].IDutilisateur

        # Création du menu contextuel
        menuPop = UTILS_Adaptations.Menu()

        # Item Modifier
        item = wx.MenuItem(menuPop, 10, _(u"Ajouter"))
        bmp = wx.Bitmap(Chemins.GetStaticPath("Images/16x16/Ajouter.png"), wx.BITMAP_TYPE_PNG)
        item.SetBitmap(bmp)
        menuPop.AppendItem(item)
        self.Bind(wx.EVT_MENU, self.Ajouter, id=10)

        menuPop.AppendSeparator()

        # Item Ajouter
        item = wx.MenuItem(menuPop, 20, _(u"Modifier"))
        bmp = wx.Bitmap(Chemins.GetStaticPath("Images/16x16/Modifier.png"), wx.BITMAP_TYPE_PNG)
        item.SetBitmap(bmp)
        menuPop.AppendItem(item)
        self.Bind(wx.EVT_MENU, self.Modifier, id=20)
        if noSelection == True : item.Enable(False)

        # Item Supprimer
        item = wx.MenuItem(menuPop, 30, _(u"Supprimer"))
        bmp = wx.Bitmap(Chemins.GetStaticPath("Images/16x16/Supprimer.png"), wx.BITMAP_TYPE_PNG)
        item.SetBitmap(bmp)
        menuPop.AppendItem(item)
        self.Bind(wx.EVT_MENU, self.Supprimer, id=30)
        if noSelection == True : item.Enable(False)

        menuPop.AppendSeparator()

        # Item Historique
        item = wx.MenuItem(menuPop, 60, _(u"Historique"))
        bmp = wx.Bitmap(Chemins.GetStaticPath("Images/16x16/Horloge3.png"), wx.BITMAP_TYPE_PNG)
        item.SetBitmap(bmp)
        menuPop.AppendItem(item)
        self.Bind(wx.EVT_MENU, self.Historique, id=60)
        if noSelection == True : item.Enable(False)

        menuPop.AppendSeparator()

        # Item Apercu avant impression
        item = wx.MenuItem(menuPop, 40, _(u"Aperçu avant impression"))
        bmp = wx.Bitmap(Chemins.GetStaticPath("Images/16x16/Apercu.png"), wx.BITMAP_TYPE_PNG)
        item.SetBitmap(bmp)
        menuPop.AppendItem(item)
        self.Bind(wx.EVT_MENU, self.Apercu, id=40)

        # Item Imprimer
        item = wx.MenuItem(menuPop, 50, _(u"Imprimer"))
        bmp = wx.Bitmap(Chemins.GetStaticPath("Images/16x16/Imprimante.png"), wx.BITMAP_TYPE_PNG)
        item.SetBitmap(bmp)
        menuPop.AppendItem(item)
        self.Bind(wx.EVT_MENU, self.Imprimer, id=50)

        self.PopupMenu(menuPop)
        menuPop.Destroy()

    def Apercu(self, event):
        from Utils import UTILS_Printer
        prt = UTILS_Printer.ObjectListViewPrinter(self, titre=_(u"Liste des utilisateurs"), format="A", orientation=wx.PORTRAIT)
        prt.Preview()

    def Imprimer(self, event):
        from Utils import UTILS_Printer
        prt = UTILS_Printer.ObjectListViewPrinter(self, titre=_(u"Liste des utilisateurs"), format="A", orientation=wx.PORTRAIT)
        prt.Print()

    def Ajouter(self, event):
        if UTILS_Utilisateurs.VerificationDroitsUtilisateurActuel("parametrage_utilisateurs", "creer") == False : return
        from Dlg import DLG_Saisie_utilisateur
        dlg = DLG_Saisie_utilisateur.Dialog(self, IDutilisateur=None)
        if dlg.ShowModal() == wx.ID_OK:
            IDutilisateur = dlg.GetIDutilisateur()
            self.MAJ(IDutilisateur)
        dlg.Destroy()

    def Modifier(self, event):
        if len(self.Selection()) == 0 :
            dlg = wx.MessageDialog(self, _(u"Vous n'avez sélectionné aucun utilisateur à modifier dans la liste !"), _(u"Erreur de saisie"), wx.OK | wx.ICON_EXCLAMATION)
            dlg.ShowModal()
            dlg.Destroy()
            return
        if UTILS_Utilisateurs.VerificationDroitsUtilisateurActuel("parametrage_utilisateurs", "modifier") == False : return
        IDutilisateur = self.Selection()[0].IDutilisateur
        from Dlg import DLG_Saisie_utilisateur
        dlg = DLG_Saisie_utilisateur.Dialog(self, IDutilisateur=IDutilisateur)
        if dlg.ShowModal() == wx.ID_OK:
            self.MAJ(IDutilisateur)
        dlg.Destroy()

    def Supprimer(self, event):
        if len(self.Selection()) == 0 :
            dlg = wx.MessageDialog(self, _(u"Vous n'avez sélectionné aucun utilisateur à supprimer dans la liste !"), _(u"Erreur de saisie"), wx.OK | wx.ICON_EXCLAMATION)
            dlg.ShowModal()
            dlg.Destroy()
            return
        if UTILS_Utilisateurs.VerificationDroitsUtilisateurActuel("parametrage_utilisateurs", "supprimer") == False : return
        IDutilisateur = self.Selection()[0].IDutilisateur
        profil = self.Selection()[0].profil
        # Vérifie que cet utilisateur n'est pas déjà attribué à d'autres tables de données

        # Table Consommations
        DB = GestionDB.DB()
        req = """SELECT COUNT(IDconso)
        FROM consommations
        WHERE IDutilisateur=%d
        ;""" % IDutilisateur
        DB.ExecuterReq(req)
        nbreConso = int(DB.ResultatReq()[0][0])
        DB.Close()
        if nbreConso > 0 :
            dlg = wx.MessageDialog(self, _(u"Cet utilisateur a déjà été attribué à %d consommation(s).\n\nVous ne pouvez donc pas le supprimer !") % nbreConso, _(u"Suppression impossible"), wx.OK | wx.ICON_EXCLAMATION)
            dlg.ShowModal()
            dlg.Destroy()
            return

        # Table Règlements
        DB = GestionDB.DB()
        req = """SELECT COUNT(IDreglement)
        FROM reglements
        WHERE IDutilisateur=%d
        ;""" % IDutilisateur
        DB.ExecuterReq(req)
        nbreReglements = int(DB.ResultatReq()[0][0])
        DB.Close()
        if nbreReglements > 0 :
            dlg = wx.MessageDialog(self, _(u"Cet utilisateur a déjà été attribué à %d règlement(s).\n\nVous ne pouvez donc pas le supprimer !") % nbreReglements, _(u"Suppression impossible"), wx.OK | wx.ICON_EXCLAMATION)
            dlg.ShowModal()
            dlg.Destroy()
            return

        # Vérifie qu'il reste au moins un administrateur
        if profil == "administrateur" :
            nbreAdmin = 0
            for track in self.donnees :
                if track.profil == "administrateur" and track.IDutilisateur != IDutilisateur :
                    nbreAdmin += 1
            if nbreAdmin == 0 :
                dlg = wx.MessageDialog(self, _(u"Vous ne pouvez pas supprimer le seul administrateur !"), _(u"Erreur de saisie"), wx.OK | wx.ICON_EXCLAMATION)
                dlg.ShowModal()
                dlg.Destroy()
                return

        # Suppression
        dlg = wx.MessageDialog(self, _(u"Souhaitez-vous vraiment supprimer cet utilisateur ?"), _(u"Suppression"), wx.YES_NO|wx.NO_DEFAULT|wx.CANCEL|wx.ICON_INFORMATION)
        if dlg.ShowModal() == wx.ID_YES :
            DB = GestionDB.DB()
            DB.ReqDEL("utilisateurs", "IDutilisateur", IDutilisateur)
            DB.ReqDEL("droits", "IDutilisateur", IDutilisateur)
            DB.Close()
            self.MAJ()
        dlg.Destroy()

    def Historique(self, event):
        """ Affiche l'historique de l'utilisateur """
        if len(self.Selection()) == 0 :
            dlg = wx.MessageDialog(self, _(u"Vous n'avez sélectionné aucun utilisateur dans la liste !"), _(u"Erreur de saisie"), wx.OK | wx.ICON_EXCLAMATION)
            dlg.ShowModal()
            dlg.Destroy()
            return
        IDutilisateur = self.Selection()[0].IDutilisateur
        from Dlg import DLG_Historique
        dlg = DLG_Historique.Dialog(self, IDutilisateur=IDutilisateur)
        dlg.ShowModal()
        dlg.Destroy()

# -------------------------------------------------------------------------------------------------------------------------------------------

class BarreRecherche(wx.SearchCtrl):
    def __init__(self, parent):
        wx.SearchCtrl.__init__(self, parent, size=(-1, -1), style=wx.TE_PROCESS_ENTER)
        self.parent = parent
        self.rechercheEnCours = False

        self.SetDescriptiveText(_(u"Rechercher un utilisateur..."))
        self.ShowSearchButton(True)

        self.listView = self.parent.ctrl_listview
        nbreColonnes = self.listView.GetColumnCount()
        self.listView.SetFilter(Filter.TextSearch(self.listView, self.listView.columns[0:nbreColonnes]))

        self.SetCancelBitmap(wx.Bitmap(Chemins.GetStaticPath("Images/16x16/Interdit.png"), wx.BITMAP_TYPE_PNG))
        self.SetSearchBitmap(wx.Bitmap(Chemins.GetStaticPath("Images/16x16/Loupe.png"), wx.BITMAP_TYPE_PNG))

        self.Bind(wx.EVT_SEARCHCTRL_SEARCH_BTN, self.OnSearch)
        self.Bind(wx.EVT_SEARCHCTRL_CANCEL_BTN, self.OnCancel)
        self.Bind(wx.EVT_TEXT_ENTER, self.OnDoSearch)
        self.Bind(wx.EVT_TEXT, self.OnDoSearch)

    def OnSearch(self, evt):
        self.Recherche()

    def OnCancel(self, evt):
        self.SetValue("")
        self.Recherche()

    def OnDoSearch(self, evt):
        self.Recherche()

    def Recherche(self):
        txtSearch = self.GetValue()
        self.ShowCancelButton(len(txtSearch))
        self.listView.GetFilter().SetText(txtSearch)
        self.listView.RepopulateList()
        self.Refresh()

# -------------------------------------------------------------------------------------------------------------------------------------------

class MyFrame(wx.Frame):
    def __init__(self, *args, **kwds):
        wx.Frame.__init__(self, *args, **kwds)
        panel = wx.Panel(self, -1, name="test1")
        sizer_1 = wx.BoxSizer(wx.VERTICAL)
        sizer_1.Add(panel, 1, wx.ALL|wx.EXPAND)
        self.SetSizer(sizer_1)
        self.myOlv = ListView(panel, id=-1, name="OL_test", style=wx.LC_REPORT|wx.SUNKEN_BORDER|wx.LC_SINGLE_SEL|wx.LC_HRULES|wx.LC_VRULES)
        self.myOlv.MAJ()
        sizer_2 = wx.BoxSizer(wx.VERTICAL)
        sizer_2.Add(self.myOlv, 1, wx.ALL|wx.EXPAND, 4)
        panel.SetSizer(sizer_2)
        self.Layout()

if __name__ == '__main__':
    app = wx.App(0)
    #wx.InitAllImageHandlers()
    frame_1 = MyFrame(None, -1, "OL TEST")
    app.SetTopWindow(frame_1)
    frame_1.Show()
    app.MainLoop()

{'UTILS_Printer': 'Utils.UTILS_Printer', 'DLG_Saisie_utilisateur': 'Dlg.DLG_Saisie_utilisateur', 'DLG_Historique': 'Dlg.DLG_Historique'}


import gdown, json
from os import makedirs
from os.path import exists, dirname

if __name__ == "__main__":
    with open('data/default_parameters.json', 'r') as defaults_file:
        files = json.load(defaults_file)['default_files']

    required = 0
    for file in files.values():
        if not exists(file['output_file']): required += 1

    if required > 0:
        print("{0} (of {1}) required files must be downloaded.".format(required, len(files.keys())))

        for file in files.values():
            if not exists(file['output_file']):
                print('\n'+file['name'].upper()+":")

                if not exists(dirname(file['output_file'])):
                    makedirs(dirname(file['output_file']))

                gdown.download(file['gdrive_link'], file['output_file'], quiet=False)

        print('All required files have finished downloaded!')
    else:
        print("All required files have already been downloaded!")

    print("  ↳ Run 'redistricter.py' to start the model.")


# -*- coding: utf-8 -*-

import aiohttp
import asyncio

VALIDATION_ENDPOINT = 'https://id.twitch.tv/oauth2/validate'
TOKEN_ENDPOINT = 'https://id.twitch.tv/oauth2/token'
REVOKE_ENDPOINT = 'https://id.twitch.tv/oauth2/revoke'

async def validate(session, access_token):
    header = {'Authorization': f'OAuth {access_token}'}

    async with session.get(VALIDATION_ENDPOINT, headers=header) as response:
        return await response.json()

async def client_credentials_flow(session, client_id, client_secret, scopes=None):
    if scopes is None:
        scope = {}
    else:
        scope = {'scope': " ".join(scopes)}

    params = {**{'client_id': client_id, 'client_secret': client_secret, 'grant_type': 'client_credentials'}, **scope}

    async with session.post(TOKEN_ENDPOINT, params=params) as response:
        return await response.json()

async def revoke(session, client_id, access_token):
    params = {'client_id': client_id, 'token': access_token}

    async with session.post(REVOKE_ENDPOINT, params=params) as response:
        return response.status

async def main():
    async with aiohttp.ClientSession() as session:
        response = await validate(session, "xxx")
        print(response)
        response = await client_credentials_flow(session, 'xxx', 'xxx', ['channel:read:subscriptions', 'channel:manage:broadcast'])
        print(response)

        response = await validate(session, "xxx")
        print(response)

if __name__ == "__main__":
    asyncio.run(main())


from cms.plugin_base import CMSPluginBase
from cms.plugin_pool import plugin_pool
import json

from .models import TawkPlugin, CalendlyPlugin
from .forms import CalendlyPluginForm

@plugin_pool.register_plugin
class TawkAddonPlugin(CMSPluginBase):
    model = TawkPlugin
    render_template = 'addons_plugin/plugin/tawk-addons.html'
    cache = True

    def render(self, context, instance, placeholder):
        context = super(TawkAddonPlugin, self).render(context, instance, placeholder)
        instance = context['instance']

        tawk_object = {
            'tawk_embedded_url': instance.tawk_embedded_url,
            'name': instance.name
        }
        context['tawk_object'] = json.dumps(tawk_object)

        return context

@plugin_pool.register_plugin
class CalendlyAddonPlugin(CMSPluginBase):
    model = CalendlyPlugin
    render_template = 'addons_plugin/plugin/calendly-addons.html'
    cache = True
    form = CalendlyPluginForm

    def render(self, context, instance, placeholder):
        context = super(CalendlyAddonPlugin, self).render(context, instance, placeholder)
        instance = context['instance']

        calendly_object = {
            'calendly_embedded_url': instance.calendly_embedded_url,
            'text_message': instance.text_message,
            'color': instance.color
        }
        context['calendly_object'] = json.dumps(calendly_object)

        return context

@plugin_pool.register_plugin
class CalendlyMenuAddonPlugin(CMSPluginBase):
    model = CalendlyPlugin
    render_template = 'addons_plugin/plugin/calendly-addon-menu-component.html'
    cache = True
    form = CalendlyPluginForm

    def render(self, context, instance, placeholder):
        context = super(CalendlyMenuAddonPlugin, self).render(context, instance, placeholder)
        instance = context['instance']

        calendly_object = {
            'calendly_embedded_url': instance.calendly_embedded_url,
            'text_message': instance.text_message,
            'color': instance.color
        }
        context['calendly_object'] = json.dumps(calendly_object)

        return context


import os
from setuptools import setup, find_packages

# Utility function to read the README file.
# Used for the long_description.  It's nice, because now 1) we have a top level
# README file and 2) it's easier to type in the README file than to put a raw
# string in below ...
def read(fname):
    return open(os.path.join(os.path.dirname(__file__), fname)).read()

setup(
    # Includes all other files that are within your project folder
    include_package_data=True,

    # Name of your Package
    name='radiobuenavia',
    # Project Version
    version='1.0',

    # Description of your Package
    description='automate the download, mixing and upload of tracks',

    # Website for your Project or Github repo
    url="https://github.com/finn-ball/radiobuenavia",

    # Name of the Creator
    author='Finn Ball',

    # Creator's mail address
    author_email='finn.ball@codificasolutions.com',

    # Projects you want to include in your Package
    packages=find_packages(),

    # Dependencies/Other modules required for your package to work
    install_requires=['dropbox', 'toml', "pywin32;  os_name=='win32'", "pydub"],

    # Detailed description of your package
    long_description=read("README.md"),

    # Format of your Detailed Description
    long_description_content_type="text/markdown",

    entry_points={"console_scripts": ["rbv = radiobuenavia.cli:cli"]},
)


"""Main module."""
import sys
import os
import pyexcel
import logging
import datetime

def check_dir_and_files(component_position_file, bom_file, output_folder, basename, dir_exist_ok):
    # basic file verification
    if not os.path.isfile(component_position_file):
        logging.error("{} is not an existing file".format(component_position_file))
        sys.exit(-1)

    if not os.path.isfile(bom_file):
        logging.error("{} is not an existing file".format(component_position_file))
        sys.exit(-1)

    if output_folder is None:
        basepath = os.path.dirname(os.path.abspath(component_position_file))
    else:
        basepath = output_folder

    if os.path.isdir(basepath) and not dir_exist_ok:
        logging.warning("{} is an existing dir, cancelling,".format(basepath))
        sys.exit(0)

    os.makedirs(os.path.join(basepath), exist_ok=dir_exist_ok)

    if basename is None:
        basename = "{date}-{basename}".format(date=datetime.datetime.now().strftime("%Y%m%d-%H%M%S"), basename=os.path.splitext(os.path.basename(bom_file))[0])

    return basepath, basename

def extract_bom(bom_file):
    bom_content = pyexcel.get_sheet(file_name=bom_file, start_row=0, delimiter=",")
    return bom_content

def extract_feeders_data(feeders_file):
    """
    returns data of the form
    [
        {"alias":["ALIAS", ...], feeder_index:X},
    ]
    """
    feeeders_data = []
    first_row = True
    for row in pyexcel.get_array(file_name=feeders_file):
        if first_row:
            first_row = False
            continue
        cmp = row[2]
        alias = row[15]
        index = row[1]

        alias = [cmp] + alias.split(":")

        if(row[0] != "Stop"):
            feeeders_data.append({"alias":alias, "feeder_index":index})

        else:
            break

    return feeeders_data

def extract_tape_data(feeders_file):
    """
    returns data of the form
    [
        {"alias":["ALIAS", ...], feeder_index:X},
    ]
    """
    feeeders_data = []

    first_row = True
    for row in pyexcel.get_array(file_name=feeders_file): # skip header
        if first_row:
            first_row = False
            continue

        cmp = row[2]
        alias = row[16]
        index = row[1]

        alias = [cmp] + alias.split(":")

        if(row[0] != "Stop"):
            feeeders_data.append({"alias":alias, "feeder_index":index})

        else:
            break

    return feeeders_data

def extract_machine_config(feeders_file, cuttape_config_files):
    machine_config = {}

    machine_config['feeders'] = extract_feeders_data(feeders_file)

    machine_config['cuttapes'] = {}
    if cuttape_config_files is not None:
        for cuttape_file in cuttape_config_files:
            cuttape = os.path.splitext(os.path.basename(cuttape_file))[0]
            machine_config['cuttapes'][cuttape] = extract_tape_data(cuttape_file)

    return machine_config

def tag_bom(bom_sheet, machine_conf):
    ID=0
    DES=3
    PACKAGE=5
    QUANTITY=6
    DESIGNATION=4

    auto_mounted_cmps = ""
    nm_cmp = ""

    append_col = bom_sheet.number_of_columns()

    assembly_mode_index = append_col
    bom_sheet.column += ["Assembly Mode"]
    cuttape_job_name = append_col + 1
    bom_sheet.column += ["Cuttape Job"]
    feeder_index_index = append_col + 2
    bom_sheet.column += ["Feeder Index"]

    def find_comp(c, confs):
        # return ID or None

        d = map(lambda feeder: feeder['feeder_index'] if cmp in feeder['alias'] else None, confs)
        fis = list(filter(lambda x: x is not None, d))

        if len(fis) > 1:
            raise Exception(f"More than one feeder found for {c}")

        elif len(fis) == 1:
            return fis[0]

        return None

    first_row = True
    for row in bom_sheet:
        if first_row:
            first_row = False
            continue

        if not isinstance(row[ID], int):
            break

        cmp = row[DESIGNATION] + "-" + row[PACKAGE]

        row[assembly_mode_index] = 'Manual'

        fid = find_comp(cmp, machine_conf['feeders'])
        if fid is not None:
            row[assembly_mode_index] = 'Feeder'
            row[feeder_index_index] = fid

        else:
            l = [(ct, find_comp(cmp, machine_conf['cuttapes'][ct])) for ct in machine_conf['cuttapes']]
            l = filter(lambda  t: t[1] is not None, l)
            l = list(l)
            if len(l) > 1:
                raise Exception(f"More than one CutTape found for {cmp}")

            elif len(l) == 1:
                ct, fid = l[0]

                row[assembly_mode_index] = 'Cut Tape'
                row[cuttape_job_name] = ct
                row[feeder_index_index] = fid

        if row[assembly_mode_index] != 'Manual':
            auto_mounted_cmps += ','.join(row[DES].split(' ')) + ','

        if row[DESIGNATION].find("/NM") != -1:
            row[assembly_mode_index] = 'NotMounted'
            nm_cmp += ','.join(row[DES].split(' ')) + ','

    return bom_sheet, auto_mounted_cmps, nm_cmp


from django.urls import path
from apiSaveIt.views import ProfileViewSet, CategoriaViewSet, SubCategoriaViewSet, PlaneamentoViewSet
from rest_framework.routers import DefaultRouter
from drf_yasg.views import get_schema_view
from drf_yasg import openapi
from rest_framework import permissions
from django.urls import re_path
from django.conf.urls import url
from . import views

schema_view = get_schema_view(
   openapi.Info(
      title="SaveIt API yasg swagger",
      default_version='v1',
      description="SaveIt API",
      terms_of_service="https://www.google.com/policies/terms/",
      contact=openapi.Contact(email="ljsgmg@google.com"),
      license=openapi.License(name="BSD License"),
   ),
   public=True,
   permission_classes=(permissions.AllowAny,),
)

#app_name = 'apiSaveIt'

router = DefaultRouter()
router.register(r'', ProfileViewSet, basename='utilizador')
urlpatterns = [
    path('perfis/', views.criar_perfil),
    path('perfis/<int:perfil_id>/', views.perfil_detalhe),
    path('categorias/', views.criar_categoria),
    path('categorias/<int:categoria_id>/', views.categoria_detalhe),
    path('sub_categorias/', views.criar_subcategoria),
    path('planeamentos/', views.criar_planeamento),
    path('planeamentos/<int:planeamento_id>/', views.planeamento_detalhe),
    re_path('swagger/', schema_view.with_ui('swagger', cache_timeout=0), name='schema-swagger-ui'),
]

from rest_framework.routers import DefaultRouter
from .views import ProfileViewSet
router = DefaultRouter()
router.register('perfis', ProfileViewSet, basename='perfil_viewsets')
router.register('categorias', CategoriaViewSet, basename='categoria_viewsets')
router.register('sub_categorias', SubCategoriaViewSet, basename='sub_categoria_viewsets')
router.register('planeamentos', PlaneamentoViewSet, basename='planeamento_viewsets')
urlpatterns += router.urls


# -*- coding: utf-8 -*-
"""
Created on Wed Aug 16 12:02:48 2023

@author: nikhilve

Here the customer has asked us to build a clustering algo only based upon Annual Income and spending score.
The mall owner has no idea on how many groups to be formed.

It is Unsupervised Learning

"""

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import pickle

#Reading the CSV data
data = pd.read_csv('Mall_Customers.csv')

#Here x is the matrix of column. Science it is Unsupervised learning
x=data.iloc[:,[3,4]].values

#Elbow method using WCSS.
from sklearn.cluster import KMeans

#Creating a empty list to hold the values of wcss.
wcss=[]
#WCSS= within cluster sum of squares.
#k-means++ helps to overcome random allocation trap.
#n_init means how many times we want to reinitialize the centroids from the starting
#n_clusters is the no of clusters we want to begin with initially.
#max_iter is the maximum no of times the centroids are getting reassigned when the data points are changing groups.
for i in range(1,11):
    kmeans= KMeans(n_clusters=i, init='k-means++', max_iter=300, n_init=10 )
    #final formation of the clusters is taken as the iteration where there was least movement of data points in any initialization(n_iter).
    #i.e. the cluster at max_iter=300(will be taken) from each initialization n_init and then compared, cluster with the least movent of centroids will be selected as final cluster.
    kmeans.fit(x)
    wcss.append(kmeans.inertia_)#Here the inertia method is used to give the wcss value and append it in wcss[](empty list).

#Plotting the graph of no of clusters vs WCSS-values to get the elbow angle.

plt.figure(figsize=(8,5))
plt.subplot(1,2,1)#This plots the graph of wcss vs no of clusters. Here 1=no of rows, 2= no of columns and 1= 1st plot i.e. elbow graph

plt.plot(range(1,11), wcss)
plt.xlabel("Number of clusters")
plt.ylabel("wcss-values")
plt.title("Graph of WCSS vs no of clusters")

#Implementing K-Means algorithm with K=5, using this value from elbow graph.
kmeans= KMeans(n_clusters=5, init='k-means++', max_iter=300, n_init=10 )

#Fitting and predicting the clusters for each customer
y_means = kmeans.fit_predict(x)

#Visual representation of the cluster-formation
plt.subplot(1,2,2)#to print the scatter plot of salary vs income.Here 1=no of rows, 2= no of columns and 2= 2nd plot i.e. income vs spending

plt.scatter(x[y_means==0,0], x[y_means==0,1], s=50, c='red', label="cluster1")
plt.scatter(x[y_means==1,0], x[y_means==1,1], s=50, c='blue', label="cluster2")
plt.scatter(x[y_means==2,0], x[y_means==2,1], s=50, c='green', label="cluster3")
plt.scatter(x[y_means==3,0], x[y_means==3,1], s=50, c='yellow', label="cluster4")
plt.scatter(x[y_means==4,0], x[y_means==4,1], s=50, c='pink', label="cluster5")
#We can rename the labels as per our requirment.

#Plotting Centroids by using the average values of x-coordinate(here annual salary) and y-coordinate(Here Purchase score)
plt.scatter(kmeans.cluster_centers_[:,0], kmeans.cluster_centers_[:,1], s=200, c="cyan", label="Centroids")
plt.xlabel("Annual Income")
plt.ylabel("Spending Score")
plt.title("Clusters of Customers")
plt.legend()
plt.tight_layout()
plt.show()


from rest_framework import status
from rest_framework.response import Response
from rest_framework.decorators import api_view
from .serializers import RegisterSerializer

# Create your views here.
@api_view(['GET'])
def getRoutes(request):
    routes = [
        '/api/token',
        '/api/token/refresh',
        '/api/register'
    ]

    return Response(routes)

@api_view(['POST'])
def RegisterView(request):
    serializer = RegisterSerializer(data=request.data)

    print(serializer.error_messages)
    if serializer.is_valid() is False:
        return Response(status=status.HTTP_400_BAD_REQUEST, data=serializer.errors)

    serializer.save()
    return Response()


"""empty message

Revision ID: 7a2f6511abeb
Revises: 6d6f17e54e67
Create Date: 2020-07-26 15:32:40.707885

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

# revision identifiers, used by Alembic.
revision = '7a2f6511abeb'
down_revision = '6d6f17e54e67'
branch_labels = None
depends_on = None

def upgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.add_column('Venue', sa.Column('genres', postgresql.ARRAY(sa.String()), nullable=True))
    op.add_column('Venue', sa.Column('seeking_description', sa.String(), nullable=True))
    op.add_column('Venue', sa.Column('seeking_talent', sa.Boolean(), nullable=True))
    op.add_column('Venue', sa.Column('website', sa.String(), nullable=True))
    # ### end Alembic commands ###

def downgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.drop_column('Venue', 'website')
    op.drop_column('Venue', 'seeking_talent')
    op.drop_column('Venue', 'seeking_description')
    op.drop_column('Venue', 'genres')
    # ### end Alembic commands ###


"""
The Python implementation of the GRPC helloworld.MultiGreeter client
Programmed by David G Messerschmitt
27 Jan 2018
"""

import grpc
import hellostreamingworld_pb2
import hellostreamingworld_pb2_grpc

# Configuration
_user_name = 'Dave'
_number = 20 # number of streaming responses
_net_addr = 'localhost:50052'

def invoke(user_name,number):
    return hellostreamingworld_pb2.HelloRequest(
        name=user_name,
        num_greetings=number
        )

def run():
  channel = grpc.insecure_channel(_net_addr)
  stub = hellostreamingworld_pb2_grpc.MultiGreeterStub(channel)
  responses = stub.SayHello(
      invoke(_user_name,_number)
      )
  for response in responses:
      print(response.greeting)

if __name__ == '__main__':
  run()


import pytest
import tardis.montecarlo.montecarlo_numba.macro_atom as macro_atom
import numpy as np

@pytest.mark.parametrize(
    ["seed", "expected"],
    [(1963, 10015), (1, 9993), (2111963, 17296), (10000, 9993)],
)
def test_macro_atom(
    static_packet,
    verysimple_numba_plasma,
    verysimple_numba_model,
    set_seed_fixture,
    seed,
    expected,
):
    set_seed_fixture(seed)
    static_packet.initialize_line_id(
        verysimple_numba_plasma, verysimple_numba_model
    )
    result = macro_atom.macro_atom(static_packet, verysimple_numba_plasma)
    assert result == expected


import long_range_compare

from long_range_compare.data_paths import get_trendytukan_drive_path, get_abailoni_hci_home_path
import numpy as np
import os

from imageio import imread

dataset_path = os.path.join(get_abailoni_hci_home_path(), "projects/GASP_on_BSD/images")

def compute_affs(image):
    img = imread(os.path.join(dataset_path, image))
    img = img[..., 0] / 255.

    # Decide if to rotate the image:
    rotate = img.shape[0] > img.shape[1]
    if rotate:
        img = np.rot90(img, -1)

    eps = 0.01

    affinities = np.ones((2, int(img.shape[0] / 2), int(img.shape[1] / 2)))

    import scipy.ndimage
    filtered = scipy.ndimage.uniform_filter(img, size=(1, 2), origin=(0, -1))
    l1, l2 = filtered[::2, ::2], filtered[1::2, ::2]
    affinities[0] = np.maximum(l1, l2)

    filtered = scipy.ndimage.uniform_filter(img, size=(2, 1), origin=(-1, 0))
    l1, l2 = filtered[::2, ::2], filtered[::2, 1::2]
    affinities[1] = np.maximum(l1, l2)

    affinities = np.clip(affinities, eps, 1. - eps)
    return affinities, rotate

nb_collected = []
affs_collected = []
rotated_collected = []
for filename in os.listdir(dataset_path):
    if filename.endswith(".ppm"):
        nb_collected.append(int(filename.replace(".jpg_edges.ppm", "")))
        # print(nb_collected[-1])
        affs, rotated = compute_affs(filename)
        affs_collected.append(affs)
        rotated_collected.append(rotated)
        print(affs_collected[-1].shape)

    # offsets = [
    #     [1, 0],
    #     [0, 1]
    # ]
    #
    # def convert_to_weights(edges, bias=0.5):
    #     beta = np.log(bias / (1 - bias))
    #     z = np.log(edges / (1 - edges))
    #     return 1. / (1. + np.exp(-z - beta))
    #
    # convert_to_weights(0.5, 0.9)

from segmfriends.utils import writeHDF5

output_dataset = os.path.join(dataset_path, "affinites.h5")
writeHDF5(np.stack(affs_collected), output_dataset, "affs")
writeHDF5(np.stack(nb_collected), output_dataset, "numbers")
writeHDF5(np.stack(rotated_collected), output_dataset, "rotated")

# filtered = scipy.ndimage.uniform_filter(img, size=(2,1))
# l1, l2, l3, l4 = filtered[::2,:-2:4], filtered[::2, 1:-2:4], filtered[::2, 2::4], filtered[::2, 3::4]
# print(np.where(l3>l4,l3,0).shape)
# check = eps + np.maximum(np.where(l1<l2,l2,0), np.where(l3>l4,l3,0))
# print(check.max())
# print(check.min())
# print(check.shape)
# import imageio
# imageio.imwrite("100007_x.png", biased_affs[0])
# imageio.imwrite("100007_y.png", biased_affs[1])


# This script is example code from this blog post:
# http://www.voidynullness.net/blog/2013/07/25/gmail-email-with-python-via-imap/
#
# This is an updated version of the original -- modified to work with Python 3.4.
#
import sys
import os
import imaplib
import email
import quopri
import email
import email.header
import datetime
from bot_db_interface import *
from send_message import send_question_assign, send_answer, send_notification, send_attachment
import time
from email_params import get_config
from bot_db_interface import cut_domain
import glob

# Поиск идет в INBOX
EMAIL_FOLDER = "INBOX"

#обрабатывет непрочитанные входящие письма от IT departament(в настройках Spiceworks так указано имя отправителя)
def process_mailbox(M):
    try:
        rv, data = M.search(None, '(UNSEEN)','(FROM "IT department")')
        #закончить выполнение при отсутствии писем
        if rv != 'OK':
            print("Empty")
            return
    except imaplib.IMAP4.error:
        print("ERROR: search failed")
        return
    for num in data[0].split():
        try:
            rv, data = M.fetch(num, '(RFC822)')
            if rv != 'OK':
                print("ERROR getting message", num)
                return
        except imaplib.IMAP4.error:
            print("ERROR: fetch failed")
            return
        #  msg кладется содержимое письма в виде строки
        try:
            msg = email.message_from_bytes(data[0][1])
            # передает ключевую информацию из письма на вход #send_to_user
            parse_and_send(msg)
        except imaplib.IMAP4.error:
            print("ERROR: email parsing failed")
            return

def parse_and_send(message):
    counter = 0
    attachments = []
    #запоминаем текущую директорию
    start_path = os.getcwd() + '\\'
    path = start_path + 'attachments'+ '\\'
    #переходим в %start_path\attachments\
    os.chdir(path)
    # удаляем все старые файлы в папке
    files = glob.glob(path+'*')
    for f in files:
        os.remove(f)
    # собираем все новые файлы в список, сохраняя их временно в папку
    for part in message.walk():
        #обрабатываем вложения
        if(part.get_content_disposition()=='attachment'):
                #получаем полный путь к новому файлу
                filepath = '{}'+part.get_filename()
                filepath = filepath.format(path)
                attachments.append(filepath)
                #создаем файл
                f = open(part.get_filename(), 'wb')
                f.write(part.get_payload(decode=True))
                f.close()
    os.chdir(start_path)
    string = quopri.decodestring(str(message))
    string = string.decode('utf-8','ignore')
    user_add = get_config('outgoing_email.txt')[0]
    user_add = user_add[0:len(user_add)-1]
    to = get_from_email(string, "to")
    ticket_id = get_from_email(string, "id")
    ticket_body = get_from_email(string, "ticket_body")
    url = get_from_email(string, "url")
    #индекс подстроки, содержащей информацию по следующему событию
    prev_event = 0
    #в цикле обрабатывается ближайшее новое событие
    while(string.find("", last_ind)].replace('
','\n'),'!')
    return (text[text.find("", last_ind)]).replace('
', '\n')

#запуск процесса, который обрабатывает сообщения, отправленные на указанный адрес
#второй аргумент - пароль от почты
def check_mailbox(email_account,password, host, port):
    try:
        M = imaplib.IMAP4_SSL(host, port)
        rv, data = M.login(email_account, password)
    except imaplib.IMAP4.error:
        print ("LOGIN FAILED!!! ")
        return
    try:
        rv, mailboxes = M.list()
        rv, data = M.select(EMAIL_FOLDER)
    except imaplib.IMAP4.error:
        print("ERROR: Unable to select email from mailbox")
        return
    if rv == 'OK':
        #запускает обработку сообщений в EMAIL_FOLDER
        process_mailbox(M)
        M.close()
    else:
        print("ERROR: Unable to open mailbox ", rv)
    M.logout()

# Запускаем проверку уведомлений, задержка 10 секунд
#считываем данные для подключения из файла, переданного на вход get_config
email_account, password, host, port = get_config('cc_mailbox.txt')
while True:
    try:
        check_mailbox(email_account, password, host, port)
    except Exception as e:
        print(e)
        print("Error occured, retry in 10 seconds")
    time.sleep(10)


from django import forms
from ssig_site.base import models

class TextInput(forms.TextInput):
    template_name = 'forms/widgets/input.html'

class Textarea(forms.Textarea):
    template_name = 'forms/widgets/textarea.html'

class SplitDateTimeWidget(forms.SplitDateTimeWidget):
    template_name = 'forms/widgets/splitdatetime.html'

class NumberInput(forms.NumberInput):
    template_name = 'forms/widgets/input.html'

class Select(forms.Select):
    template_name = 'forms/widgets/select.html'

class EventForm(forms.ModelForm):

    class Meta:
        model = models.Event
        fields = '__all__'
        field_classes = {
            'start_datetime': forms.SplitDateTimeField,
            'end_datetime': forms.SplitDateTimeField,
        }
        widgets = {
            'group': forms.HiddenInput(),
            'title': TextInput(),
            'restricted_to': Select(),
            'short_description': Textarea(),
            'long_description': Textarea(),
            'start_datetime': SplitDateTimeWidget(),
            'end_datetime': SplitDateTimeWidget(),
            'location': TextInput(),
            'latitude': NumberInput(),
            'longitude': NumberInput(),
        }

class AttendanceForm(forms.Form):
    upi = forms.CharField(widget=TextInput())