from pathlib import Path
from typing import Callable, Iterable, Iterator, List

from prospector.exceptions import PermissionMissing
from prospector.pathutils import is_python_module, is_python_package, is_virtualenv

_SKIP_DIRECTORIES = (".git", ".tox", ".mypy_cache", ".pytest_cache", ".venv", "__pycache__", "node_modules")

class FileFinder:
    """
    This class is responsible for taking a combination of command-line arguments
    and configuration loaded from a profile to discover all files and modules which
    should be inspected.

    Individual tools can be told to ignore certain files, so the job of this class
    is basically to know which files to pass to which tools to be inspected.
    """

    def __init__(self, *provided_paths: Path, exclusion_filters: Iterable[Callable] = None):
        """
        :param provided_paths:
            A list of Path objects to search for files and modules - can be either directories or files
        :param exclusion_filters:
            An optional list of filters. All paths will be checked against this list - if any return True,
            the path is excluded.
        """
        self._provided_files = []
        self._provided_dirs = []
        self._exclusion_filters = [
            # we always want to ignore some things
            lambda _path: _path.is_dir() and _path.name in _SKIP_DIRECTORIES,
            is_virtualenv,
        ] + list(exclusion_filters or [])

        for path in provided_paths:
            if not path.exists():
                raise FileNotFoundError(path)
            # ensure all paths from now one are absolute paths; they can be converted
            # to relative paths for output purposes later
            path = path.absolute()
            if path.is_file():
                self._provided_files.append(path)
            if path.is_dir():
                self._provided_dirs.append(path)

    def make_syspath(self) -> List[Path]:
        paths = set()
        for path in self._provided_dirs:
            paths.add(path)
        for module in self.python_modules:
            paths.add(module.parent)
        return sorted(paths)

    def is_excluded(self, path: Path) -> bool:
        return any(filt(path) for filt in self._exclusion_filters)

    def _filter(self, paths: Iterable[Path]) -> List[Path]:
        return [path for path in paths if not self.is_excluded(path)]

    def _walk(self, directory: Path) -> Iterator[Path]:
        if not self.is_excluded(directory):
            yield directory

        for path in directory.iterdir():
            if self.is_excluded(path):
                continue
            if path.is_dir():
                yield from self._walk(path)
            else:
                yield path

    @property
    def files(self) -> List[Path]:
        """
        List every individual file found from the given configuration.

        This method is useful for tools which require an explicit list of files to check.
        """
        files = set()
        for path in self._provided_files:
            files.add(path)

        for directory in self.directories:
            for path in self._walk(directory):
                if path.is_file():
                    files.add(path)

        return self._filter(files)

    @property
    def python_packages(self) -> List[Path]:
        """
        Lists every directory found in the given configuration which is a python module (that is,
        contains an `__init__.py` file).

        This method is useful for passing to tools which will do their own discovery of python files.
        """
        return self._filter(d for d in self.directories if is_python_package(d))

    @property
    def python_modules(self) -> List[Path]:
        """
        Lists every directory found in the given configuration which is a python module (that is,
        contains an `__init__.py` file).

        This method is useful for passing to tools which will do their own discovery of python files.
        """
        return self._filter(f for f in self.files if is_python_module(f))

    @property
    def directories(self) -> List[Path]:
        """
        Lists every directory found from the given configuration, regardless of its contents.

        This method is useful for passing to tools which will do their own discovery of python files.
        """
        dirs = set()
        for directory in self._provided_dirs:
            dirs.add(directory)
            try:
                for obj in self._walk(directory):
                    if obj.is_dir():
                        dirs.add(obj)
            except PermissionError as err:
                raise PermissionMissing(obj) from err

        return self._filter(dirs)


import sqlite3

# Povezivanje sa bazom podataka (kreiranje nove baze ako ne postoji)
conn = sqlite3.connect('ski_baza.db')

# Kreiranje objekta kursora za interakciju sa bazom
cursor = conn.cursor()

# Kreiranje tabele za ski-centre
cursor.execute('''
    CREATE TABLE IF NOT EXISTS ski_centri (
        id INTEGER PRIMARY KEY,
        ime TEXT,
        lokacija TEXT,
        tezina TEXT,
        broj_staza INTEGER,
        sezona_otvaranja TEXT
    )
''')

# Ubacivanje ski centara u tabelu
cursor.execute('''
    INSERT INTO ski_centri (ime, lokacija, tezina, broj_staza, sezona_otvaranja)
    VALUES ('Aspen Mountain', 'Aspen, Kolorado', 'Napredno', 76, 'Novembar - April')
''')
cursor.execute('''
    INSERT INTO ski_centri (ime, lokacija, tezina, broj_staza, sezona_otvaranja)
    VALUES ('Whistler Blackcomb', 'Whistler, Britanska Kolumbija', 'Napredno', 200, 'Novembar - Maj')
''')
cursor.execute('''
    INSERT INTO ski_centri (ime, lokacija, tezina, broj_staza, sezona_otvaranja)
    VALUES ('St. Anton am Arlberg', 'St. Anton, Austrija', 'Ekspert', 340, 'Decembar - April')
''')

conn.commit()

def izaberi_ski_centre():
    """Izaberi sve ski-centre iz tabele ski_centri."""
    cursor.execute("SELECT * FROM ski_centri")
    centri = cursor.fetchall()
    return centri

def azuriraj_ime_ski_centra(id_centra, novo_ime):
    """Azuriraj ime ski-centra sa datim ID-jem."""
    cursor.execute("UPDATE ski_centri SET ime = ? WHERE id = ?", (novo_ime, id_centra))
    conn.commit()

def obrisi_ski_centar(id_centra):
    """Obrisi ski-centar sa datim ID-jem iz tabele ski_centri."""
    cursor.execute("DELETE FROM ski_centri WHERE id = ?", (id_centra,))
    conn.commit()

def prikazi_ski_centre(centri):
    """Prikazi detalje o ski-centrima."""
    print("Ski Centri:")
    for centar in centri:
        print(centar)
    print()

# Glavna petlja za interakciju sa korisnikom
while True:
    print("Opcije:")
    print("1. Prikazi ski centre")
    print("2. Azuriraj ime ski centra")
    print("3. Obrisi ski centar")
    print("4. Izlaz")

    izbor = input("Unesite izbor: ")

    if izbor == "1":
        centri = izaberi_ski_centre()
        prikazi_ski_centre(centri)

    elif izbor == "2":
        centri = izaberi_ski_centre()
        prikazi_ski_centre(centri)

        id_centra = input("Unesite ID ski centra koji želite ažurirati: ")
        novo_ime = input("Unesite novo ime za ski centar: ")

        azuriraj_ime_ski_centra(id_centra, novo_ime)
        print("Ime ski centra uspješno ažurirano.")

        centri = izaberi_ski_centre()
        prikazi_ski_centre(centri)

    elif izbor == "3":
        centri = izaberi_ski_centre()
        prikazi_ski_centre(centri)

        id_centra = input("Unesite ID ski centra koji želite obrisati: ")

        obrisi_ski_centar(id_centra)
        print("Ski centar uspešno obrisan.")

        centri = izaberi_ski_centre()
        prikazi_ski_centre(centri)

    elif izbor == "4":
        break

    else:
        print("Nevažeći izbor. Molimo pokušajte ponovo.")


import subprocess
from datetime import datetime, timedelta, timezone

from dateutil.tz import tzutc

import pytest
from unittest.mock import call

from docker_cleanup import dates, docker, error
import test_dates

def test_AttrDict():
    json = [{'dct': dict(b=7),
             'lst': [dict()],
            }
           ]

    json_ad = docker.AttrDict.from_json(json)

    assert json == json_ad

    assert isinstance(json_ad[0], docker.AttrDict)
    assert isinstance(json_ad[0].dct, docker.AttrDict)
    assert isinstance(json_ad[0].lst[0], docker.AttrDict)

    assert 'AttrDict' in repr(json_ad)

@pytest.mark.parametrize("cls", [docker.DockerObj,
                                 docker.Container,
                                 docker.Image])
@pytest.mark.parametrize("input,expected", test_dates.date_time_pairs)
def test_DockerObj(input, expected, cls):
    obj = cls({'Id': '2468',
               'Name': 'roger',
               'Repository': 'jack',
               'Tag': 'jill',
               'Unrelated': '\o/',
               'Created': input,
               'State': {'Unrelated': '...',
                         'StartedAt': input,
                         'FinishedAt': input,
                         },
               })

    assert obj.Id == '2468'
    assert obj.Name == 'roger' or obj.Name == 'jack:jill'
    assert obj.Unrelated == '\o/'
    assert obj.State.Unrelated == '...'
    assert obj.Created == expected
    assert obj.State.StartedAt == expected
    assert obj.State.FinishedAt == expected

    if obj.Created is not None:
        assert isinstance(obj.Created, dates.DateTime)
    if obj.State.StartedAt is not None:
        assert isinstance(obj.State.StartedAt, dates.DateTime)
    if obj.State.FinishedAt is not None:
        assert isinstance(obj.State.FinishedAt, dates.DateTime)

    assert '2468' in str(obj)
    assert 'roger' in str(obj) or 'jack:jill' in str(obj)

dockerobj_equals = [
    (docker.DockerObj({'Id': '123'}), docker.DockerObj({'Id': '123'}), True),
    (docker.DockerObj({'Id': '123'}), docker.DockerObj({'Id': '000'}), False),
    (docker.DockerObj({'Id': '123'}), docker.Container({'Id': '123'}), False),
    (docker.DockerObj({'Id': '123'}), docker.Image({'Id': '123'}),     False),
    (docker.Container({'Id': '123'}), docker.Image({'Id': '123'}),     False),
    (docker.Container({'Id': '123'}), docker.Image({'Id': '123'}),     False),

    (docker.DockerObj({'Id': '123'}), '123',                           True),
    (docker.Container({'Id': '123'}), '123',                           True),
    (docker.Image({'Id': '123'}),     '123',                           True),

    (docker.DockerObj({'Id': '123'}), '000',                           False),
    (docker.Container({'Id': '123'}), '000',                           False),
    (docker.Image({'Id': '123'}),     '000',                           False),
]

@pytest.mark.parametrize("input1,input2,expected", dockerobj_equals)
def test_DockerObj_eq(input1, input2, expected):
    assert (input1 == input2) == expected

@pytest.mark.parametrize("input,expected", test_dates.date_time_pairs)
def test_DockerObj_fixup_date(input, expected):
    d_input = {'value1': 'abc',
               'value2': '18',
               'value3': '2001-01-31T13:05:20.123456Z',
               'value4': input,
               }
    d_expected = dict(d_input)
    d_expected['value4'] = expected

    docker.DockerObj._fixup_date(d_input, 'value4')
    assert d_input == d_expected

def test_DockerObj_fixup_date_cornercases():
    d_input = {'an-int': 18,
               'none': None,
               }
    d_expected = dict(d_input)

    # Should not raise any exceptions
    docker.DockerObj._fixup_date(d_input, 'not-present')
    docker.DockerObj._fixup_date(d_input, 'an-int')
    docker.DockerObj._fixup_date(d_input, 'none')

    assert d_input == d_expected

def test_Container():
    c = docker.Container(
            {'Id': 'deadbeef',
             'Name': '/the_slash',
             })

    # Names coming out from `docker inspect` start with a '/'.
    # Test successful slash removal.
    assert c.Name == 'the_slash'

def test_Image():
    dangling_img = docker.Image(
            {'Id': 'deadbeef',
             'Repository': None,
             'Tag': None,
             })
    normal_img = docker.Image(
            {'Repository': 'some/thing',
             'Tag': 'latest',
             })

    assert dangling_img.Id == 'deadbeef'
    assert dangling_img.Repository is None
    assert dangling_img.Tag is None
    assert dangling_img.Dangling
    assert dangling_img.Name == '<none>:<none>'

    assert normal_img.Repository == 'some/thing'
    assert normal_img.Tag == 'latest'
    assert normal_img.Name == 'some/thing:latest'

def test_crossreference(containers, images):
    docker.cross_reference(containers, images)

    c1, c2, c22 = containers
    i1, i2, i3 = images

    assert c1.Image == i1
    assert c2.Image == i2
    assert c22.Image == i2

    assert i1.ContainerObjects == {c1}
    assert i2.ContainerObjects == {c2, c22}
    assert i3.ContainerObjects == set()

    assert not i1.Dangling
    assert not i2.Dangling
    assert i3.Dangling

def test_call_docker_errors(mocker):
    err = subprocess.CalledProcessError(1, ['cmdline', 'args'])
    mocker.patch('subprocess.check_output', side_effect=err)

    with pytest.raises(error.DockerError):
        docker.call_docker('images')

images_output_test_pairs = [
    ('REPOSITORY   TAG      IMAGE ID       CREATED       VIRTUAL SIZE\n'
     'some/th      latest   0123456789AB   2 hours ago   385.8 MB',

     [docker.DockerImagesRepoInfo(
         {'REPOSITORY': 'some/th',
          'TAG': 'latest',
          'IMAGE ID': '0123456789AB',
          })
      ]
    ),
    ('REPOSITORY   TAG      IMAGE ID       CREATED       VIRTUAL SIZE\n'
     '<none>       <none>   0987654321AB   2 hours ago   385.8 MB\n'
     'some/other   lt       0123456789AB   2 hours ago   385.8 MB',

     [docker.DockerImagesRepoInfo(
         {'REPOSITORY': '<none>',
          'TAG': '<none>',
          'IMAGE ID': '0987654321AB',
          }),
      docker.DockerImagesRepoInfo(
          {'REPOSITORY': 'some/other',
           'TAG': 'lt',
           'IMAGE ID': '0123456789AB',
           }),
      ]
    ),
]

@pytest.mark.parametrize("input,expected", images_output_test_pairs)
def test_parse_docker_images_output(input, expected):
    imagesdata = list(docker._parse_docker_images_output(input))

    assert len(imagesdata) == len(expected)
    for entry, entry_expected in zip(imagesdata, expected):
        assert entry.id == entry_expected.id
        assert entry.repo == entry_expected.repo
        assert entry.tag == entry_expected.tag

def test_load_inspect_json(mock_call_docker):
    id = '81834'
    mock_call_docker.return_value = '{"Id": "%s", "Name": "bingo"}' % id

    json = docker._load_docker_inspect_json([id])

    assert json['Id'] == id
    assert json['Name'] == 'bingo'

def test_load_containers(mock_call_docker):
    id = '81835'
    mock_call_docker.side_effect = [
        id,
        '[{ "Id": "%s",  "Name": "bingo" }]' % id
    ]

    containers = docker.load_containers()

    assert len(containers) == 1

    container = containers[0]
    assert container.Id == id
    assert container.Name == 'bingo'

    mock_call_docker.assert_has_calls([
        call('ps', '-aq'),
        call('inspect', id),
    ])

def test_load_images(mock_call_docker):
    mock_call_docker.side_effect = [
        images_output_test_pairs[0][0],
        '[{ "Id": "0123456789AB",  "Comment": "testcomment" }]'
    ]

    images = docker.load_images()

    assert len(images) == 1

    image = images[0]
    assert image.Repository == 'some/th'
    assert image.Tag == 'latest'
    assert image.Name == 'some/th:latest'
    assert image.Id == '0123456789AB'
    assert image.Comment == 'testcomment'

    mock_call_docker.assert_has_calls([
        call('images', '--no-trunc'),
        call('inspect', '0123456789AB'),
    ])

def test_delete_container(mock_call_docker):
    container = docker.Container(dict(Id='c0'))

    docker.delete_container(container)
    mock_call_docker.assert_called_once_with('rm', 'c0')

    mock_call_docker.reset_mock()
    docker.delete_container(container, force=True)
    mock_call_docker.assert_called_once_with('rm', '-f', 'c0')

def test_delete_container_del_ImageRef(mock_call_docker, images, containers):
    docker.cross_reference(containers, images)

    container = containers[0]
    assert container in container.Image.ContainerObjects

    docker.delete_container(container)

    assert container not in container.Image.ContainerObjects

def test_delete_image(mock_call_docker):
    image = docker.Image(dict(Id='i0'))

    docker.delete_image(image)
    mock_call_docker.assert_called_once_with('rmi', 'i0')

    mock_call_docker.reset_mock()
    docker.delete_image(image, force=True)
    mock_call_docker.assert_called_once_with('rmi', '-f', 'i0')


# -*- coding: utf-8 -*-
"""
Created on Fri Jul  7 10:28:45 2017

@author: ChingWei
"""
import turtle_wei as te
def draw(x,y):
    te.penup()
    te.goto(x,y)
    te.pendown()
    te.forward(200)
    direct(100)
    direct(200)
    direct(100)
def direct(x):
    te.left(90)
    te.forward(x)
def line(x1,y1,x2,y2):
    te.penup()
    te.goto(x1,y1)
    te.pendown()
    te.goto(x2,y2)

draw(0,0)
te.left(90)
draw(-50,-60)
line(200,100,150,40)
line(200,0,150,-60)
line(0,0,-50,-60)
line(0,100,-50,40)
te.done()


from Holopy.Engine import *

def get_holo(path, new_path,new2_path, zz, res, wave, sph,z0):
    _object = image_converter.convert_image(path,'L', (500,500))
    z = propagator.z_const(_object, zz)
    res2 = res
    if sph=='Spherical waves':
        res2 = zz*res/(z0) + res
    hologram = propagator.holo_arr(_object, z, res, res, wave)
    rehologram = propagator.reholo_arr(hologram, z, res, res, wave)
    propagator.save_holo(hologram, new_path, res2)
    propagator.save_holo(rehologram, new2_path, res, 'Reconstruct')
    return None


import datetime
import re

from ... import processors
from ... import sql, exc
from ... import types as sqltypes, schema as sa_schema
from ... import util
from ...engine import default, reflection
from ...sql import compiler

from ...types import (BLOB, BOOLEAN, CHAR, DATE, DECIMAL, FLOAT,
                      INTEGER, REAL, NUMERIC, SMALLINT, TEXT,
                      TIMESTAMP, VARCHAR)

class _DateTimeMixin(object):
    _reg = None
    _storage_format = None

    def __init__(self, storage_format=None, regexp=None, **kw):
        super(_DateTimeMixin, self).__init__(**kw)
        if regexp is not None:
            self._reg = re.compile(regexp)
        if storage_format is not None:
            self._storage_format = storage_format

    def adapt(self, cls, **kw):
        if issubclass(cls, _DateTimeMixin):
            if self._storage_format:
                kw["storage_format"] = self._storage_format
            if self._reg:
                kw["regexp"] = self._reg
        return super(_DateTimeMixin, self).adapt(cls, **kw)

    def literal_processor(self, dialect):
        bp = self.bind_processor(dialect)

        def process(value):
            return "'%s'" % bp(value)
        return process

class DATETIME(_DateTimeMixin, sqltypes.DateTime):
    """Represent a Python datetime object in SQLite using a string.

    The default string storage format is::

        "%(year)04d-%(month)02d-%(day)02d %(hour)02d:%(min)02d:\
%(second)02d.%(microsecond)06d"

    e.g.::

        2011-03-15 12:05:57.10558

    The storage format can be customized to some degree using the
    ``storage_format`` and ``regexp`` parameters, such as::

        import re
        from sqlalchemy.dialects.sqlite import DATETIME

        dt = DATETIME(
            storage_format="%(year)04d/%(month)02d/%(day)02d %(hour)02d:\
%(min)02d:%(second)02d",
            regexp=r"(\d+)/(\d+)/(\d+) (\d+)-(\d+)-(\d+)"
        )

    :param storage_format: format string which will be applied to the dict
     with keys year, month, day, hour, minute, second, and microsecond.

    :param regexp: regular expression which will be applied to incoming result
     rows. If the regexp contains named groups, the resulting match dict is
     applied to the Python datetime() constructor as keyword arguments.
     Otherwise, if positional groups are used, the datetime() constructor
     is called with positional arguments via
     ``*map(int, match_obj.groups(0))``.
    """

    _storage_format = (
        "%(year)04d-%(month)02d-%(day)02d "
        "%(hour)02d:%(minute)02d:%(second)02d.%(microsecond)06d"
    )

    def __init__(self, *args, **kwargs):
        truncate_microseconds = kwargs.pop('truncate_microseconds', False)
        super(DATETIME, self).__init__(*args, **kwargs)
        if truncate_microseconds:
            assert 'storage_format' not in kwargs, "You can specify only "\
                "one of truncate_microseconds or storage_format."
            assert 'regexp' not in kwargs, "You can specify only one of "\
                "truncate_microseconds or regexp."
            self._storage_format = (
                "%(year)04d-%(month)02d-%(day)02d "
                "%(hour)02d:%(minute)02d:%(second)02d"
            )

    def bind_processor(self, dialect):
        datetime_datetime = datetime.datetime
        datetime_date = datetime.date
        format = self._storage_format

        def process(value):
            if value is None:
                return None
            elif isinstance(value, datetime_datetime):
                return format % {
                    'year': value.year,
                    'month': value.month,
                    'day': value.day,
                    'hour': value.hour,
                    'minute': value.minute,
                    'second': value.second,
                    'microsecond': value.microsecond,
                }
            elif isinstance(value, datetime_date):
                return format % {
                    'year': value.year,
                    'month': value.month,
                    'day': value.day,
                    'hour': 0,
                    'minute': 0,
                    'second': 0,
                    'microsecond': 0,
                }
            else:
                raise TypeError("SQLite DateTime type only accepts Python "
                                "datetime and date objects as input.")
        return process

    def result_processor(self, dialect, coltype):
        if self._reg:
            return processors.str_to_datetime_processor_factory(
                self._reg, datetime.datetime)
        else:
            return processors.str_to_datetime

class DATE(_DateTimeMixin, sqltypes.Date):
    """Represent a Python date object in SQLite using a string.

    The default string storage format is::

        "%(year)04d-%(month)02d-%(day)02d"

    e.g.::

        2011-03-15

    The storage format can be customized to some degree using the
    ``storage_format`` and ``regexp`` parameters, such as::

        import re
        from sqlalchemy.dialects.sqlite import DATE

        d = DATE(
                storage_format="%(month)02d/%(day)02d/%(year)04d",
                regexp=re.compile("(?P<month>\d+)/(?P<day>\d+)/(?P<year>\d+)")
            )

    :param storage_format: format string which will be applied to the
     dict with keys year, month, and day.

    :param regexp: regular expression which will be applied to
     incoming result rows. If the regexp contains named groups, the
     resulting match dict is applied to the Python date() constructor
     as keyword arguments. Otherwise, if positional groups are used, the
     date() constructor is called with positional arguments via
     ``*map(int, match_obj.groups(0))``.
    """

    _storage_format = "%(year)04d-%(month)02d-%(day)02d"

    def bind_processor(self, dialect):
        datetime_date = datetime.date
        format = self._storage_format

        def process(value):
            if value is None:
                return None
            elif isinstance(value, datetime_date):
                return format % {
                    'year': value.year,
                    'month': value.month,
                    'day': value.day,
                }
            else:
                raise TypeError("SQLite Date type only accepts Python "
                                "date objects as input.")
        return process

    def result_processor(self, dialect, coltype):
        if self._reg:
            return processors.str_to_datetime_processor_factory(
                self._reg, datetime.date)
        else:
            return processors.str_to_date

class TIME(_DateTimeMixin, sqltypes.Time):
    """Represent a Python time object in SQLite using a string.

    The default string storage format is::

        "%(hour)02d:%(minute)02d:%(second)02d.%(microsecond)06d"

    e.g.::

        12:05:57.10558

    The storage format can be customized to some degree using the
    ``storage_format`` and ``regexp`` parameters, such as::

        import re
        from sqlalchemy.dialects.sqlite import TIME

        t = TIME(
            storage_format="%(hour)02d-%(minute)02d-%(second)02d-\
%(microsecond)06d",
            regexp=re.compile("(\d+)-(\d+)-(\d+)-(?:-(\d+))?")
        )

    :param storage_format: format string which will be applied to the dict
     with keys hour, minute, second, and microsecond.

    :param regexp: regular expression which will be applied to incoming result
     rows. If the regexp contains named groups, the resulting match dict is
     applied to the Python time() constructor as keyword arguments. Otherwise,
     if positional groups are used, the time() constructor is called with
     positional arguments via ``*map(int, match_obj.groups(0))``.
    """

    _storage_format = "%(hour)02d:%(minute)02d:%(second)02d.%(microsecond)06d"

    def __init__(self, *args, **kwargs):
        truncate_microseconds = kwargs.pop('truncate_microseconds', False)
        super(TIME, self).__init__(*args, **kwargs)
        if truncate_microseconds:
            assert 'storage_format' not in kwargs, "You can specify only "\
                "one of truncate_microseconds or storage_format."
            assert 'regexp' not in kwargs, "You can specify only one of "\
                "truncate_microseconds or regexp."
            self._storage_format = "%(hour)02d:%(minute)02d:%(second)02d"

    def bind_processor(self, dialect):
        datetime_time = datetime.time
        format = self._storage_format

        def process(value):
            if value is None:
                return None
            elif isinstance(value, datetime_time):
                return format % {
                    'hour': value.hour,
                    'minute': value.minute,
                    'second': value.second,
                    'microsecond': value.microsecond,
                }
            else:
                raise TypeError("SQLite Time type only accepts Python "
                                "time objects as input.")
        return process

    def result_processor(self, dialect, coltype):
        if self._reg:
            return processors.str_to_datetime_processor_factory(
                self._reg, datetime.time)
        else:
            return processors.str_to_time

colspecs = {
    sqltypes.Date: DATE,
    sqltypes.DateTime: DATETIME,
    sqltypes.Time: TIME,
}

ischema_names = {
    'BIGINT': sqltypes.BIGINT,
    'BLOB': sqltypes.BLOB,
    'BOOL': sqltypes.BOOLEAN,
    'BOOLEAN': sqltypes.BOOLEAN,
    'CHAR': sqltypes.CHAR,
    'DATE': sqltypes.DATE,
    'DATETIME': sqltypes.DATETIME,
    'DOUBLE': sqltypes.FLOAT,
    'DECIMAL': sqltypes.DECIMAL,
    'FLOAT': sqltypes.FLOAT,
    'INT': sqltypes.INTEGER,
    'INTEGER': sqltypes.INTEGER,
    'NUMERIC': sqltypes.NUMERIC,
    'REAL': sqltypes.REAL,
    'SMALLINT': sqltypes.SMALLINT,
    'TEXT': sqltypes.TEXT,
    'TIME': sqltypes.TIME,
    'TIMESTAMP': sqltypes.TIMESTAMP,
    'VARCHAR': sqltypes.VARCHAR,
    'NVARCHAR': sqltypes.NVARCHAR,
    'NCHAR': sqltypes.NCHAR,
}

class SQLiteCompiler(compiler.SQLCompiler):
    extract_map = util.update_copy(
        compiler.SQLCompiler.extract_map,
        {
            'month': '%m',
            'day': '%d',
            'year': '%Y',
            'second': '%S',
            'hour': '%H',
            'doy': '%j',
            'minute': '%M',
            'epoch': '%s',
            'dow': '%w',
            'week': '%W',
        })

    def visit_now_func(self, fn, **kw):
        return "CURRENT_TIMESTAMP"

    def visit_localtimestamp_func(self, func, **kw):
        return 'DATETIME(CURRENT_TIMESTAMP, "localtime")'

    def visit_true(self, expr, **kw):
        return '1'

    def visit_false(self, expr, **kw):
        return '0'

    def visit_char_length_func(self, fn, **kw):
        return "length%s" % self.function_argspec(fn)

    def visit_cast(self, cast, **kwargs):
        if self.dialect.supports_cast:
            return super(SQLiteCompiler, self).visit_cast(cast, **kwargs)
        else:
            return self.process(cast.clause, **kwargs)

    def visit_extract(self, extract, **kw):
        try:
            return "CAST(STRFTIME('%s', %s) AS INTEGER)" % (
                self.extract_map[extract.field],
                self.process(extract.expr, **kw)
            )
        except KeyError:
            raise exc.CompileError(
                "%s is not a valid extract argument." % extract.field)

    def limit_clause(self, select):
        text = ""
        if select._limit is not None:
            text += "\n LIMIT " + self.process(sql.literal(select._limit))
        if select._offset is not None:
            if select._limit is None:
                text += "\n LIMIT " + self.process(sql.literal(-1))
            text += " OFFSET " + self.process(sql.literal(select._offset))
        else:
            text += " OFFSET " + self.process(sql.literal(0))
        return text

    def for_update_clause(self, select):
        # sqlite has no "FOR UPDATE" AFAICT
        return ''

class SQLiteDDLCompiler(compiler.DDLCompiler):

    def get_column_specification(self, column, **kwargs):
        coltype = self.dialect.type_compiler.process(column.type)
        colspec = self.preparer.format_column(column) + " " + coltype
        default = self.get_column_default_string(column)
        if default is not None:
            colspec += " DEFAULT " + default

        if not column.nullable:
            colspec += " NOT NULL"

        if (column.primary_key and
                column.table.dialect_options['sqlite']['autoincrement'] and
                len(column.table.primary_key.columns) == 1 and
                issubclass(column.type._type_affinity, sqltypes.Integer) and
                not column.foreign_keys):
            colspec += " PRIMARY KEY AUTOINCREMENT"

        return colspec

    def visit_primary_key_constraint(self, constraint):
        # for columns with sqlite_autoincrement=True,
        # the PRIMARY KEY constraint can only be inline
        # with the column itself.
        if len(constraint.columns) == 1:
            c = list(constraint)[0]
            if (c.primary_key and
                    c.table.dialect_options['sqlite']['autoincrement'] and
                    issubclass(c.type._type_affinity, sqltypes.Integer) and
                    not c.foreign_keys):
                return None

        return super(SQLiteDDLCompiler, self).visit_primary_key_constraint(
            constraint)

    def visit_foreign_key_constraint(self, constraint):

        local_table = list(constraint._elements.values())[0].parent.table
        remote_table = list(constraint._elements.values())[0].column.table

        if local_table.schema != remote_table.schema:
            return None
        else:
            return super(
                SQLiteDDLCompiler,
                self).visit_foreign_key_constraint(constraint)

    def define_constraint_remote_table(self, constraint, table, preparer):
        """Format the remote table clause of a CREATE CONSTRAINT clause."""

        return preparer.format_table(table, use_schema=False)

    def visit_create_index(self, create):
        return super(SQLiteDDLCompiler, self).visit_create_index(
            create, include_table_schema=False)

class SQLiteTypeCompiler(compiler.GenericTypeCompiler):
    def visit_large_binary(self, type_):
        return self.visit_BLOB(type_)

class SQLiteIdentifierPreparer(compiler.IdentifierPreparer):
    reserved_words = set([
        'add', 'after', 'all', 'alter', 'analyze', 'and', 'as', 'asc',
        'attach', 'autoincrement', 'before', 'begin', 'between', 'by',
        'cascade', 'case', 'cast', 'check', 'collate', 'column', 'commit',
        'conflict', 'constraint', 'create', 'cross', 'current_date',
        'current_time', 'current_timestamp', 'database', 'default',
        'deferrable', 'deferred', 'delete', 'desc', 'detach', 'distinct',
        'drop', 'each', 'else', 'end', 'escape', 'except', 'exclusive',
        'explain', 'false', 'fail', 'for', 'foreign', 'from', 'full', 'glob',
        'group', 'having', 'if', 'ignore', 'immediate', 'in', 'index',
        'indexed', 'initially', 'inner', 'insert', 'instead', 'intersect',
        'into', 'is', 'isnull', 'join', 'key', 'left', 'like', 'limit',
        'match', 'natural', 'not', 'notnull', 'null', 'of', 'offset', 'on',
        'or', 'order', 'outer', 'plan', 'pragma', 'primary', 'query',
        'raise', 'references', 'reindex', 'rename', 'replace', 'restrict',
        'right', 'rollback', 'row', 'select', 'set', 'table', 'temp',
        'temporary', 'then', 'to', 'transaction', 'trigger', 'true', 'union',
        'unique', 'update', 'using', 'vacuum', 'values', 'view', 'virtual',
        'when', 'where',
    ])

    def format_index(self, index, use_schema=True, name=None):
        """Prepare a quoted index and schema name."""

        if name is None:
            name = index.name
        result = self.quote(name, index.quote)
        if (not self.omit_schema and
                use_schema and
                getattr(index.table, "schema", None)):
            result = self.quote_schema(
                index.table.schema, index.table.quote_schema) + "." + result
        return result

class SQLiteExecutionContext(default.DefaultExecutionContext):
    @util.memoized_property
    def _preserve_raw_colnames(self):
        return self.execution_options.get("sqlite_raw_colnames", False)

    def _translate_colname(self, colname):
        # adjust for dotted column names.  SQLite
        # in the case of UNION may store col names as
        # "tablename.colname", or if using an attached database,
        # "database.tablename.colname", in cursor.description
        if not self._preserve_raw_colnames and "." in colname:
            return colname.split(".")[-1], colname
        else:
            return colname, None

class SQLiteDialect(default.DefaultDialect):
    name = 'sqlite'
    supports_alter = False
    supports_unicode_statements = True
    supports_unicode_binds = True
    supports_default_values = True
    supports_empty_insert = False
    supports_cast = True
    supports_multivalues_insert = True
    supports_right_nested_joins = False

    default_paramstyle = 'qmark'
    execution_ctx_cls = SQLiteExecutionContext
    statement_compiler = SQLiteCompiler
    ddl_compiler = SQLiteDDLCompiler
    type_compiler = SQLiteTypeCompiler
    preparer = SQLiteIdentifierPreparer
    ischema_names = ischema_names
    colspecs = colspecs
    isolation_level = None

    supports_cast = True
    supports_default_values = True

    construct_arguments = [
        (sa_schema.Table, {
            "autoincrement": False
        })
    ]

    _broken_fk_pragma_quotes = False

    def __init__(self, isolation_level=None, native_datetime=False, **kwargs):
        default.DefaultDialect.__init__(self, **kwargs)
        self.isolation_level = isolation_level

        # this flag used by pysqlite dialect, and perhaps others in the
        # future, to indicate the driver is handling date/timestamp
        # conversions (and perhaps datetime/time as well on some hypothetical
        # driver ?)
        self.native_datetime = native_datetime

        if self.dbapi is not None:
            self.supports_default_values = (
                self.dbapi.sqlite_version_info >= (3, 3, 8))
            self.supports_cast = (
                self.dbapi.sqlite_version_info >= (3, 2, 3))
            self.supports_multivalues_insert = (
                # http://www.sqlite.org/releaselog/3_7_11.html
                self.dbapi.sqlite_version_info >= (3, 7, 11))
            # see http://www.sqlalchemy.org/trac/ticket/2568
            # as well as http://www.sqlite.org/src/info/600482d161
            self._broken_fk_pragma_quotes = (
                self.dbapi.sqlite_version_info < (3, 6, 14))

    _isolation_lookup = {
        'READ UNCOMMITTED': 1,
        'SERIALIZABLE': 0,
    }

    def set_isolation_level(self, connection, level):
        try:
            isolation_level = self._isolation_lookup[level.replace('_', ' ')]
        except KeyError:
            raise exc.ArgumentError(
                "Invalid value '%s' for isolation_level. "
                "Valid isolation levels for %s are %s" %
                (level, self.name, ", ".join(self._isolation_lookup))
            )
        cursor = connection.cursor()
        cursor.execute("PRAGMA read_uncommitted = %d" % isolation_level)
        cursor.close()

    def get_isolation_level(self, connection):
        cursor = connection.cursor()
        cursor.execute('PRAGMA read_uncommitted')
        res = cursor.fetchone()
        if res:
            value = res[0]
        else:
            # http://www.sqlite.org/changes.html#version_3_3_3
            # "Optional READ UNCOMMITTED isolation (instead of the
            # default isolation level of SERIALIZABLE) and
            # table level locking when database connections
            # share a common cache.""
            # pre-SQLite 3.3.0 default to 0
            value = 0
        cursor.close()
        if value == 0:
            return "SERIALIZABLE"
        elif value == 1:
            return "READ UNCOMMITTED"
        else:
            assert False, "Unknown isolation level %s" % value

    def on_connect(self):
        if self.isolation_level is not None:
            def connect(conn):
                self.set_isolation_level(conn, self.isolation_level)
            return connect
        else:
            return None

    @reflection.cache
    def get_table_names(self, connection, schema=None, **kw):
        if schema is not None:
            qschema = self.identifier_preparer.quote_identifier(schema)
            master = '%s.sqlite_master' % qschema
            s = ("SELECT name FROM %s "
                 "WHERE type='table' ORDER BY name") % (master,)
            rs = connection.execute(s)
        else:
            try:
                s = ("SELECT name FROM "
                     " (SELECT * FROM sqlite_master UNION ALL "
                     "  SELECT * FROM sqlite_temp_master) "
                     "WHERE type='table' ORDER BY name")
                rs = connection.execute(s)
            except exc.DBAPIError:
                s = ("SELECT name FROM sqlite_master "
                     "WHERE type='table' ORDER BY name")
                rs = connection.execute(s)

        return [row[0] for row in rs]

    def has_table(self, connection, table_name, schema=None):
        quote = self.identifier_preparer.quote_identifier
        if schema is not None:
            pragma = "PRAGMA %s." % quote(schema)
        else:
            pragma = "PRAGMA "
        qtable = quote(table_name)
        statement = "%stable_info(%s)" % (pragma, qtable)
        cursor = _pragma_cursor(connection.execute(statement))
        row = cursor.fetchone()

        # consume remaining rows, to work around
        # http://www.sqlite.org/cvstrac/tktview?tn=1884
        while not cursor.closed and cursor.fetchone() is not None:
            pass

        return row is not None

    @reflection.cache
    def get_view_names(self, connection, schema=None, **kw):
        if schema is not None:
            qschema = self.identifier_preparer.quote_identifier(schema)
            master = '%s.sqlite_master' % qschema
            s = ("SELECT name FROM %s "
                 "WHERE type='view' ORDER BY name") % (master,)
            rs = connection.execute(s)
        else:
            try:
                s = ("SELECT name FROM "
                     " (SELECT * FROM sqlite_master UNION ALL "
                     "  SELECT * FROM sqlite_temp_master) "
                     "WHERE type='view' ORDER BY name")
                rs = connection.execute(s)
            except exc.DBAPIError:
                s = ("SELECT name FROM sqlite_master "
                     "WHERE type='view' ORDER BY name")
                rs = connection.execute(s)

        return [row[0] for row in rs]

    @reflection.cache
    def get_view_definition(self, connection, view_name, schema=None, **kw):
        if schema is not None:
            qschema = self.identifier_preparer.quote_identifier(schema)
            master = '%s.sqlite_master' % qschema
            s = ("SELECT sql FROM %s WHERE name = '%s'"
                 "AND type='view'") % (master, view_name)
            rs = connection.execute(s)
        else:
            try:
                s = ("SELECT sql FROM "
                     " (SELECT * FROM sqlite_master UNION ALL "
                     "  SELECT * FROM sqlite_temp_master) "
                     "WHERE name = '%s' "
                     "AND type='view'") % view_name
                rs = connection.execute(s)
            except exc.DBAPIError:
                s = ("SELECT sql FROM sqlite_master WHERE name = '%s' "
                     "AND type='view'") % view_name
                rs = connection.execute(s)

        result = rs.fetchall()
        if result:
            return result[0].sql

    @reflection.cache
    def get_columns(self, connection, table_name, schema=None, **kw):
        quote = self.identifier_preparer.quote_identifier
        if schema is not None:
            pragma = "PRAGMA %s." % quote(schema)
        else:
            pragma = "PRAGMA "
        qtable = quote(table_name)
        statement = "%stable_info(%s)" % (pragma, qtable)
        c = _pragma_cursor(connection.execute(statement))

        rows = c.fetchall()
        columns = []
        for row in rows:
            (name, type_, nullable, default, primary_key) = (
                row[1], row[2].upper(), not row[3], row[4], row[5])

            columns.append(self._get_column_info(name, type_, nullable,
                                                 default, primary_key))
        return columns

    def _get_column_info(self, name, type_, nullable, default, primary_key):
        coltype = self._resolve_type_affinity(type_)

        if default is not None:
            default = util.text_type(default)

        return {
            'name': name,
            'type': coltype,
            'nullable': nullable,
            'default': default,
            'autoincrement': default is None,
            'primary_key': primary_key,
        }

    def _resolve_type_affinity(self, type_):
        """Return a data type from a reflected column, using affinity tules.

        SQLite's goal for universal compatibility introduces some complexity
        during reflection, as a column's defined type might not actually be a
        type that SQLite understands - or indeed, my not be defined *at all*.
        Internally, SQLite handles this with a 'data type affinity' for each
        column definition, mapping to one of 'TEXT', 'NUMERIC', 'INTEGER',
        'REAL', or 'NONE' (raw bits). The algorithm that determines this is
        listed in http://www.sqlite.org/datatype3.html section 2.1.

        This method allows SQLAlchemy to support that algorithm, while still
        providing access to smarter reflection utilities by regcognizing
        column definitions that SQLite only supports through affinity (like
        DATE and DOUBLE).

        """
        match = re.match(r'([\w ]+)(\(.*?\))?', type_)
        if match:
            coltype = match.group(1)
            args = match.group(2)
        else:
            coltype = ''
            args = ''

        if coltype in self.ischema_names:
            coltype = self.ischema_names[coltype]
        elif 'INT' in coltype:
            coltype = sqltypes.INTEGER
        elif 'CHAR' in coltype or 'CLOB' in coltype or 'TEXT' in coltype:
            coltype = sqltypes.TEXT
        elif 'BLOB' in coltype or not coltype:
            coltype = sqltypes.NullType
        elif 'REAL' in coltype or 'FLOA' in coltype or 'DOUB' in coltype:
            coltype = sqltypes.REAL
        else:
            coltype = sqltypes.NUMERIC

        if args is not None:
            args = re.findall(r'(\d+)', args)
            try:
                coltype = coltype(*[int(a) for a in args])
            except TypeError:
                util.warn(
                    "Could not instantiate type %s with "
                    "reflected arguments %s; using no arguments." %
                    (coltype, args))
                coltype = coltype()
        else:
            coltype = coltype()

        return coltype

    @reflection.cache
    def get_pk_constraint(self, connection, table_name, schema=None, **kw):
        cols = self.get_columns(connection, table_name, schema, **kw)
        pkeys = []
        for col in cols:
            if col['primary_key']:
                pkeys.append(col['name'])
        return {'constrained_columns': pkeys, 'name': None}

    @reflection.cache
    def get_foreign_keys(self, connection, table_name, schema=None, **kw):
        quote = self.identifier_preparer.quote_identifier
        if schema is not None:
            pragma = "PRAGMA %s." % quote(schema)
        else:
            pragma = "PRAGMA "
        qtable = quote(table_name)
        statement = "%sforeign_key_list(%s)" % (pragma, qtable)
        c = _pragma_cursor(connection.execute(statement))
        fkeys = []
        fks = {}
        while True:
            row = c.fetchone()
            if row is None:
                break
            (numerical_id, rtbl, lcol, rcol) = (
                row[0], row[2], row[3], row[4])

            self._parse_fk(fks, fkeys, numerical_id, rtbl, lcol, rcol)
        return fkeys

    def _parse_fk(self, fks, fkeys, numerical_id, rtbl, lcol, rcol):
        # sqlite won't return rcol if the table was created with REFERENCES
        # <tablename>, no col
        if rcol is None:
            rcol = lcol

        if self._broken_fk_pragma_quotes:
            rtbl = re.sub(r'^[\"\[`\']|[\"\]`\']$', '', rtbl)

        try:
            fk = fks[numerical_id]
        except KeyError:
            fk = {
                'name': None,
                'constrained_columns': [],
                'referred_schema': None,
                'referred_table': rtbl,
                'referred_columns': [],
            }
            fkeys.append(fk)
            fks[numerical_id] = fk

        if lcol not in fk['constrained_columns']:
            fk['constrained_columns'].append(lcol)
        if rcol not in fk['referred_columns']:
            fk['referred_columns'].append(rcol)
        return fk

    @reflection.cache
    def get_indexes(self, connection, table_name, schema=None, **kw):
        quote = self.identifier_preparer.quote_identifier
        if schema is not None:
            pragma = "PRAGMA %s." % quote(schema)
        else:
            pragma = "PRAGMA "
        include_auto_indexes = kw.pop('include_auto_indexes', False)
        qtable = quote(table_name)
        statement = "%sindex_list(%s)" % (pragma, qtable)
        c = _pragma_cursor(connection.execute(statement))
        indexes = []
        while True:
            row = c.fetchone()
            if row is None:
                break
            # ignore implicit primary key index.
            # http://www.mail-archive.com/sqlite-users@sqlite.org/msg30517.html
            elif (not include_auto_indexes and
                  row[1].startswith('sqlite_autoindex')):
                continue

            indexes.append(dict(name=row[1], column_names=[], unique=row[2]))
        # loop thru unique indexes to get the column names.
        for idx in indexes:
            statement = "%sindex_info(%s)" % (pragma, quote(idx['name']))
            c = connection.execute(statement)
            cols = idx['column_names']
            while True:
                row = c.fetchone()
                if row is None:
                    break
                cols.append(row[2])
        return indexes

    @reflection.cache
    def get_unique_constraints(self, connection, table_name,
                               schema=None, **kw):
        UNIQUE_SQL = """
            SELECT sql
            FROM
                sqlite_master
            WHERE
                type='table' AND
                name=:table_name
        """
        c = connection.execute(UNIQUE_SQL, table_name=table_name)
        table_data = c.fetchone()[0]

        UNIQUE_PATTERN = 'CONSTRAINT (\w+) UNIQUE \(([^\)]+)\)'
        return [
            {'name': name,
             'column_names': [col.strip(' "') for col in cols.split(',')]}
            for name, cols in re.findall(UNIQUE_PATTERN, table_data)
        ]

def _pragma_cursor(cursor):
    """work around SQLite issue whereby cursor.description
    is blank when PRAGMA returns no rows."""

    if cursor.closed:
        cursor.fetchone = lambda: None
        cursor.fetchall = lambda: []
    return cursor


import os

# Local import
from morphman.automated_landmarking.automated_landmarking_tools import *

def landmarking_bogunovic(centerline, base_path, approximation_method, algorithm, resampling_step, smooth_line, nknots,
                          smoothing_factor, iterations, coronal_axis):
    """
    Perform landmarking of an input centerline to
    identify different segments along the vessel.
    Landmarking algorithm based on Bogunovic (2012).
    Bends are identified where the angle in the k1-k2 basis
    exceeds a certain limit.

    Args:
        centerline (vtkPolyData): Centerline data points.
        base_path (str): Location of case to landmark.
        approximation_method (str): Method used for computing curvature.
        algorithm (str): Name of landmarking algorithm.
        resampling_step (float): Resampling step. Is None if no resampling.
        smooth_line (bool): Smooths centerline with VMTK if True.
        nknots (int): Number of knots for B-splines.
        smoothing_factor (float): Smoothing factor used in VMTK
        iterations (int): Number of smoothing iterations.
        coronal_axis (str) : Axis determining coronal coordinate

    Returns:
        landmarks (dict): Landmarking interfaces as points.
    """

    if resampling_step is not None:
        centerline = vmtk_resample_centerline(centerline, length=resampling_step)

    if approximation_method == "vmtk":
        line = vmtk_compute_centerline_attributes(centerline)
        line = vmtk_compute_geometric_features(line, smooth_line, factor=smoothing_factor, iterations=iterations)
        curvature = get_point_data_array("Curvature", line)
        curvature = gaussian_filter(curvature, 2)

    elif approximation_method == "disc":
        neigh = 20
        line = vmtk_compute_centerline_attributes(centerline)
        line = vmtk_compute_geometric_features(line, smooth_line, factor=smoothing_factor, iterations=iterations)
        line, curvature__ = compute_discrete_derivatives(line, neigh=neigh)
        curvature = []
        for c in curvature__:
            curvature.append([c])
        curvature = np.array(curvature)

    elif approximation_method == "spline":
        line, max_point_ids, min_point_ids = spline_centerline_and_compute_geometric_features(centerline, smooth_line,
                                                                                nknots)
        curvature = get_point_data_array("Curvature", line)

    if approximation_method != "spline":
        max_point_ids = list(argrelextrema(curvature, np.greater)[0])
        min_point_ids = list(argrelextrema(curvature, np.less)[0])
        get_k1k2_basis(curvature, line)

    curvilinear_coordinates = get_curvilinear_coordinate(line)
    k1 = get_point_data_array("k1", line)
    k2 = get_point_data_array("k2", line)

    # Remove a min / max point that is in reality a saddle point
    for i in min_point_ids:
        for j in max_point_ids:
            if abs(i - j) < 5 and abs(curvature[i] - curvature[j]) < 0.01:
                if i in min_point_ids:
                    min_point_ids.remove(i)
                if j in max_point_ids:
                    max_point_ids.remove(j)

    # Find local curvature max in the k1-k2 space, and compute angle between the points
    k1_points = k1[max_point_ids]
    k2_points = k2[max_point_ids]
    k_points = np.zeros((k1_points.shape[0], 2))
    k_points[:, 0] = k1_points[:, 0]
    k_points[:, 1] = k2_points[:, 0]
    theta = np.zeros(k1_points.shape[0] - 1)
    for i in range(theta.shape[0]):
        a = k_points[i, :] / np.sqrt(np.sum(k_points[i, :] ** 2))
        b = k_points[i + 1, :] / np.sqrt(np.sum(k_points[i + 1, :] ** 2))
        theta[i] = math.acos(np.dot(a, b))
        theta[i] = theta[i] * 180 / math.pi

    # Tolerance parameters from Bogunovic et al. (2012)
    tol_anterior_posterior = 60
    tol_superior_anterior = 45
    tol_posterior_inferior = 45
    tol_inferior_end = 110

    # Find coronal coordinate and maximum (within anterior bend)
    coordinates = get_centerline_coordinates(line, curvilinear_coordinates)
    coronal_coordinate = coordinates[coronal_axis]
    max_coronal_coordinate_id = get_maximum_coronal_coordinate(coronal_coordinate, curvilinear_coordinates)

    interfaces = {}
    min_point_ids = np.array(min_point_ids)

    # Find interfaces between bends based on angles between curvature vectors and tolerance parameters
    index = np.array((max_coronal_coordinate_id > max_point_ids).nonzero()[0]).max()
    start = find_interface(index, -1, tol_anterior_posterior, "anterior_posterior", theta, max_point_ids, min_point_ids,
                           interfaces)
    if start is None:
        return None
    start = find_interface(start, -1, tol_posterior_inferior, "posterior_inferior", theta, max_point_ids, min_point_ids,
                           interfaces)
    if start is None:
        return None
    find_interface(start, -1, tol_inferior_end, "inferior_end", theta, max_point_ids, min_point_ids, interfaces)
    start = find_interface(index + 1, 1, tol_superior_anterior, "superior_anterior", theta, max_point_ids,
                           min_point_ids, interfaces)
    if start is None:
        return None

    # Set landmarks following Bogunovic
    landmarks = {}
    for k, v in interfaces.items():
        landmarks[k] = line.GetPoint(int(v))

    # Map landmarks to initial centerline
    landmarks = map_landmarks(landmarks, centerline, algorithm)

    # Save landmarks
    print("-- Case was successfully landmarked.")
    print("-- Number of landmarks (Segments): %s" % len(landmarks))
    try:
        os.remove(base_path + "_landmark_bogunovic_%s.particles" % approximation_method)
    except FileNotFoundError:
        pass

    if landmarks is not None:
        write_parameters(landmarks, base_path)
        create_particles(base_path, algorithm, approximation_method)

    return landmarks

def find_interface(start, direction, tol, part, theta, max_point_ids, min_point_ids, interfaces):
    """
    Find landmark interfaces according to Bogunovic.
    Based on local curvature extrema computed in the k1-k2 space.
    Angles between curvature vectors determine interfaces based on a pre-defined tolerance.

    Args:
        start (int): Index where search for curvature max starts
        direction (int): Direction to search (1 or -1)
        tol (double): Tolerance on angle between curvature vectors
        part (str): Name of interface
        theta (ndarray): Array of angles between curvature vectors
        max_point_ids (ndarray): Local curvature maximum
        min_point_ids (ndarray): Local curvature minimum
        interfaces (dict): Dictionary of landmarks/interfaces and coresponding points

    Returns:
        i (int): Index of curvature maximum in bend of interest
    """
    stop = direction if direction == -1 else theta.shape[0]
    success = False
    for i in range(start - 1, stop, direction):
        if theta[i] > tol:
            success = True
            break

    if success:
        start = max_point_ids[i]
        stop = max_point_ids[i + 1]
        index = ((min_point_ids > start) * (min_point_ids < stop)).nonzero()[0].max()
        min_point = (min_point_ids[index])
        interfaces[part] = min_point

    elif not success and part == "superior_anterior":
        print("-- Where not able to identify the interface between the " +
              "anterior and superior bend. Check the coronal coordinates")
        return None

    elif not success and part != "inferior_end":
        print("-- The geometry is to short to be classified with superior" +
              ", anterior, posterior and inferior.")
        return None

    elif not success and part == "inferior_end":
        interfaces["inf_end"] = np.array([0])
        i = 0
        print("-- End of inferior is at the end of the geometry, this might" +
              "affect the geometry stats")
    else:
        print("-- Something happened, idea: some bend ended at the last point")
        return None

    return i


from typing import List

class Solution:
    def search(self, nums: List[int], target: int) -> int:
        # check whether to start from left or right
        l = 0
        r = len(nums) - 1
        m = l if nums[l] <= target else r

        start = m

        # search towards the direction you started if you are past the pivot
        while l <= r:
            # print(f"nums[{m}] = {nums[m]}", (l, r))

            if nums[m] == target:
                return m

            elif start == len(nums) - 1 and nums[m] > nums[start]:
                l = m+1
            elif start == 0 and nums[start] > nums[m]:
                r = m-1

            elif nums[m] < target:
                l = m+1
            elif nums[m] > target:
                r = m-1

            m = (l + r) // 2

        return -1

print('\033c')
# print(Solution().search(nums = [4,5,6,7,8,9,1,2,3], target = 9))

nums = [4,5,6,7,8,9,1,2,3]
# """
for i in nums:
    print(Solution().search(nums, i))
# """


from valsys.modeling.utils import check_success, module_from_resp
from valsys.modeling.vars import Resp, Vars
import pytest
from unittest import mock
from valsys.modeling.model.module import Module

MODULE_PREFIX = "valsys.modeling.utils"

class FakeException(Exception):
    pass

class TestCheckSuccess:

    def test_works_ok(self):
        resp = {Resp.STATUS: Vars.SUCCESS}
        assert check_success(resp, None)

    def test_not_success(self):
        resp = {Resp.STATUS: 'garbage', Resp.ERROR: 'error'}
        desc = 'info'
        with pytest.raises(Exception) as err:
            check_success(resp, desc)
        assert desc in str(err)
        assert resp[Resp.ERROR] in str(err)

    def test_not_success_custom_exception(self):
        resp = {Resp.STATUS: 'garbage', Resp.ERROR: 'error'}
        custom_exception = FakeException
        desc = 'info'
        with pytest.raises(custom_exception) as err:
            check_success(resp, desc, exception=custom_exception)
        assert desc in str(err)
        assert resp[Resp.ERROR] in str(err)

class TestModuleFromResp:

    @mock.patch(f"{MODULE_PREFIX}.Module.from_json")
    def test_works_ok(self, mock_from_json):
        resp = {Resp.DATA: {Resp.MODULE: {Module.fields.NAME: 'Name'}}}
        m = module_from_resp(resp)
        assert mock_from_json.called_once_with(
            resp.get(Resp.DATA).get(Resp.MODULE))
        assert m == mock_from_json.return_value


#ler 5 valores de uma lista, mostrar o maior o menor e a localização deles

valores = []

for n in range(0,5):
    valores.append(int(input('Digite um número: ')))

for n in range(0,len(valores)):
    if n ==0:
        maior = valores[n]
        menor = valores[n]
        posmaior = n
        posmenor = n
    if valores[n] > maior:
        maior = valores[n]
        posmaior = n
    elif valores[n] < menor:
        menor = valores[n]
        posmenor = n

print(f'Maior valor {maior}')
print(f'Menor valor {menor}')
print(f'Posição Maior {posmaior}')
print(f'Posição Menor {posmenor}')


import sys
import argparse
from web3 import Web3

def main(argv=sys.argv[1:]):
    """ Make a simple payment to be run on the test node using an
    already-unlocked account
    """

    parser = argparse.ArgumentParser(description='Test payment script')
    parser.add_argument(
        'destination_account',
        metavar='ADDRESS',
        type=str,
        nargs=1,
        help='Destination Ethereum account address'
    )
    parser.add_argument(
        'amount_in_wei',
        metavar='WEI',
        type=int,
        nargs=1,
        help='The amount to send in wei'
    )
    args = parser.parse_args(argv)

    web3 = Web3(Web3.HTTPProvider('http://localhost:8545'))

    assert int(web3.version.network) > 100, 'This is a test script.'

    tx = {
        'from': web3.eth.accounts[0],
        'to': args.destination_account[0],
        'gas': 21000,
        'gasPrice': int(1e9),
        'value': args.amount_in_wei[0]
    }
    txhash = web3.eth.sendTransaction(tx)
    print('Sending transaction {}'.format(txhash))
    receipt = web3.eth.waitForTransactionReceipt(txhash)
    assert receipt.status == 1, 'Transaction failed!'
    print(receipt)

if __name__ == '__main__':
    main()


from itertools import permutations

class Permutation:
    def __init__(self, d, size):
        self.size = size
        self.d = d

    def __eq__(self, other):
        if type(other) != Permutation: raise Exception('Type error')
        return self.size == other.size and self.d == other.d

    def __repr__(self):
        return str(self)

    def __str__(self):
        if self == get_identity(self.size): return 'e'
        cycles = []
        d = {key: value for key, value in self.d.items() if key != value}
        digits = list(sorted(d.keys()))
        while len(digits) > 0:
            cycles.append([])
            digit = digits.pop(0)
            cycles[-1].append(digit)
            while d[digit] not in cycles[-1]:
                cycles[-1].append(d[digit])
                digit = d[digit]
                digits.remove(digit)
        string = ''
        for cycle in cycles:
            string += '(' + ''.join([str(digit) for digit in cycle]) + ')'
        return string

    def composite(self, other):
        """ Note: self.composite(other) <==> self o other
        """
        d = {}
        for key in self.d:
            d[key] = self.d[other.d[key]]
        return Permutation(d, self.size)

def get_identity(size):
    return Permutation({i: i for i in range(1, size + 1)}, size)

def get_all_permutations(size):
    all_permutations = []
    for t in permutations('123456789'[:size], size):
        p = Permutation({i + 1: int(t[i]) for i in range(size)}, size)
        all_permutations.append(p)
    return all_permutations

def validate(permutation):
    expect_digit = False
    exp = None
    p = ''
    cycles = [[]]
    for char in permutation:
        if expect_digit:
            if char.isdigit():
                exp = 0 if exp is None else exp
                time = 9 * exp + int(char)
                exp = 10 * exp + int(char)
                for i in range(exp - 1):
                    cycles.append(cycles[-1][:])
            else:
                if exp is None or char != '*':
                    return False, 'Exponent error'
                expect_digit = False
        if not expect_digit:
            if char == '(':
                if len(p) == 0 or p[-1] == ')':
                    p += char
                    cycles[-1].append([])
                else:
                    return False, 'Invalid left parenthesis position'
            elif char == ')':
                if len(p) > 0 and p[-1] == '(':
                    p += char
                else:
                    return False, 'Invalid right parenthesis position'
            elif char == '*':
                if len(p) > 0 and p[-1] == ')':
                    cycles.append([])
                else:
                    return False, 'Invalid binary operator position'
            elif char == '^':
                if len(p) > 0 and p[-1] == ')':
                    expect_digit = True
                else:
                    return False, 'Invalid exponent operator position'
            elif '1' <= char <= str(size):
                if len(p) > 0 and p[-1] == '(':
                    cycles[-1][-1].append(int(char))
                else:
                    return False, 'Invalid digit position'
            else:
                return False, 'Invalid input character'
    return True, cycles

def form_permutations(cycles, size):
    for i in range(len(cycles)):
        d = {}
        for j in range(len(cycles[i])):
            for k in range(len(cycles[i][j])):
                if cycles[i][j][k] not in d:
                    d[cycles[i][j][k]] = cycles[i][j][(k+1)%len(cycles[i][j])]
                else:
                    return False, str(cycles[i][j][k]) + ' appears more than once'

        for j in range(1, size + 1):
            if j not in d: d[j] = j
        cycles[i] = Permutation(d, size)
    return True, cycles

def validate_and_form_permutations(permutation, size):
    valid, cycles = validate(permutation)
    if not valid:
        return False, cycles
    return form_permutations(cycles, size)

def calculate(permutation):
    while len(permutation) > 1:
        p1 = permutation.pop()
        p2 = permutation.pop()
        p3 = p2.composite(p1)
        permutation.append(p3)
    return permutation[0]

def get_permutation(hint="calculation"):
    permutation = None
    while permutation is None:
        permutation = input('Input your expression for ' + hint + ': ')
        valid, result = validate_and_form_permutations(permutation, size)
        if not valid:
            print(result + '. Please try again.')
            permutation = None
        else:
            permutation = calculate(result)
    return permutation

def generate(generator):
    subgroup = [generator]
    cur = generator
    while cur != get_identity(generator.size):
        cur = generator.composite(cur)
        subgroup.append(cur)
    return subgroup

if __name__ == '__main__':
    size = None
    print('Permutation (Group Theorem) Calculator')
    while size is None:
        size = input('Input size (1-9): ')
        if size.isdigit() and 1 <= int(size) <= 9: size = int(size)
        else:
            print('Invalid input. Please try again.')
            size = None
    print('1. Given expression, calculate expression')
    print('2. Given expression of generator, generate subgroup.')
    print('3. Given g and generator of subgroup H, calculate gH.')
    print('4. Given generator of subgroup H, calculate all gH for g in Sn')
    print('5. Given generator of subgroup H, calculate all Hg for g in Sn')
    while True:
        selection = None
        while selection is None:
            selection = input('Input your selection: ')
            if selection.isdigit() and 1 <= int(selection) <= 5:
                selection = int(selection)
            else:
                print('Invalid input. Please try again.')
                selection = None
        if selection == 1:
            print('Result is:', get_permutation())
        elif selection == 2:
            generator = get_permutation('generator')
            print('Generator is:', generator)
            subgroup = generate(generator)
            print('Subgroup is: ', subgroup)
        elif selection == 3:
            g = get_permutation('g')
            generator = get_permutation('generator of H')
            print('g =', g)
            H = generate(generator)
            print('H =', H)
            gH = [g.composite(h) for h in H]
            print('gH =', gH)
        elif selection == 4 or selection == 5:
            H = generate(get_permutation('generator of H'))
            print('H =', H)
            Sn = get_all_permutations(size)
            gH_all = []
            print('All gH:')
            while len(Sn) != 0:
                gH = [Sn[0].composite(h) for h in H] if selection == 4 else \
                     [h.composite(Sn[0]) for h in H]
                for p in gH: Sn.remove(p)
                if selection == 4:
                    print(''.join([str(gh) + 'H = ' for gh in gH]), end='')
                else:
                    print(''.join(['H' + str(gh) + ' = ' for gh in gH]), end='')
                gH_all.append(gH)
                print(gH)


# written by https://github.com/mikefrostov
#
# Aim: show the implementation of the signly linked list
#
# Linked list is a data structure that has a number of nodes that are
# linked to each other only once like this:
#
# {NODE1[payload][pointer_to_next_node]} -> {NODE2[payload][pointer_to_next_node]}
#
# pre-pend operation takes O(1)
#
# append takes O(n) since we have to traverse the list in order to append new node
#
# NODE object consists of a "payload" and a "pointer to next node"
#
# Linked List consists of NODE objects, head, a counter, print method, append method, prepend method, init method
#
#

class MyList:

    def __init__(self, *values):
        self.head = None
        self.cursor = self.head
        for value in values:
            node = Node(value)
            if self.head is None:
                self.head = node
            else:
                self.append_node(node)
        self.cursor = self.head    # cursor needs to always start from the head

    @property
    def _value(self):
        return self.head._value

    @_value.setter
    def _value(self, val):
        self.head._value = val

    def __iter__(self):
        return self

    def __next__(self):
        if self.cursor is None:
            self.cursor = self.head
            raise StopIteration
        value = self.cursor._value
        self.cursor = self.cursor._pointer
        return value

    def __add__(self, operand):
        if isinstance(operand, Node):
            self.append_node(operand)
        if isinstance(operand, int):
            self.append(operand)
        if isinstance(operand, MyList):
            for value in operand:
                self.append(value)
            return self
        if isinstance(operand, list):
            for value in operand:
                self.append(int(value))
        if isinstance(operand, tuple):
            for value in operand:
                self.append(int(value))
        return self

    def prepend_node(self, node):
        node._pointer = self.head
        self.head = node

    def append_node(self, new_node):
        if self.head is None:
            self.head = new_node
            return self
        self.cursor = self.head
        while self.cursor._pointer is not None:
            self.cursor = self.cursor._pointer
        self.cursor._pointer = new_node
        self.cursor = self.head
        return self

    def append(self, value):
        node = Node(value)
        self.append_node(node)
        return self

    def find(self, value):
        pass

    def delete(self, value):
        pass

    def reverse(self):
        pass

    def print(self):
        self.cursor = self.head
        temp = ''
        while self.cursor is not None:
            temp = temp + ' ' + str(self.cursor._value)
            self.cursor = self.cursor._pointer
        print(temp)
        self.cursor = self.head

    def print_reversed(self):  # using reversed string
        self.cursor = self.head
        temp = ''
        while self.cursor is not None:
            temp = temp + " " + str(self.cursor._value)
            self.cursor = self.cursor._pointer
        temp1 = ''
        for c in temp:
            temp1 = c + temp1  # appending chars in reverse order
        print(temp1)
        self.cursor = self.head

class Node:

    def __init__(self, _value, _pointer=None):
        self._value = _value
        self._pointer = _pointer


'''
Takes a positional data set (time, x, y, z) and applies the Savintzky Golay filter on it based on the
polynomial and window parameters we input
'''

from math import *
import numpy as np
import sys
import os
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), os.path.pardir)))
from scipy.signal import savgol_filter
from util import read_data

def golay(data, window, degree):
    '''
    Apply the Savintzky-Golay filter to a positional data set.

    Args:
        data (numpy array): containing all of the positional data in the format of (time, x, y, z)
        window (int): window size of the Savintzky-Golay filter
        degree (int): degree of the polynomial in Savintzky-Golay filter

    Returns:
        numpy array: filtered data in the same format
    '''

    x = data[:, 1]
    y = data[:, 2]
    z = data[:, 3]

    x_new = savgol_filter(x, window, degree)
    y_new = savgol_filter(y, window, degree)
    z_new = savgol_filter(z, window, degree)

    new_positions = np.zeros((len(data), 4))
    new_positions[:, 1] = x_new
    new_positions[:, 2] = y_new
    new_positions[:, 3] = z_new
    new_positions[:, 0] = data[:, 0]

    return new_positions

#
# if __name__ == "__main__":
#
#     pd.set_option('display.width', 1000)
#     my_data = read_data.load_data('../example_data/orbit.csv')
#     window = 21 # its better to select it as the len(data)/3 and it needs to be an odd number
#     degree = 6
#     positions_filtered = golay(my_data, window, degree)
#     print(positions_filtered - my_data)
#


import requests
from app import routers
from app.firebase import Firebase
import pytest
import os

from fastapi import status
from fastapi.testclient import TestClient
from firebase_admin import auth, initialize_app, credentials
from app.main import app

@pytest.fixture(scope="session")
def firebase_app():
    os.environ["FIRESTORE_EMULATOR_HOST"] = "localhost:8080"
    os.environ["FIREBASE_AUTH_EMULATOR_HOST"] = "localhost:9099"
    os.environ["FIREBASE_DATABASE_EMULATOR_HOST"] = "localhost:9000"
    os.environ["FIREBASE_FUNCTIONS_EMULATOR_HOST"] = "localhost:5001"
    os.environ["FIREBASE_STORAGE_EMULATOR_HOST"] = "localhost:9199"

    return Firebase.get_firebase_app()

@pytest.fixture
def client():
    return TestClient(app)

@pytest.fixture
def firebase_auth(firebase_app):
    return auth

@pytest.fixture
def firebase_user(firebase_auth):
    try:
        user = firebase_auth.get_user("test_user")
    except auth.UserNotFoundError:
        user = firebase_auth.create_user(uid="test_user")
    return user

@pytest.fixture
def firebase_test_token(firebase_user):
    custom_token = auth.create_custom_token(firebase_user.uid).decode("utf-8")

    url = "http://localhost:9099/identitytoolkit.googleapis.com/v1/accounts:signInWithCustomToken?key=hello"

    payload = {"token": custom_token, "returnSecureToken": True}

    response = requests.post(url, json=payload)

    if response.ok:
        id_token = response.json()["idToken"]
    else:
        error_message = response.json()["error"]["message"]
        # show in test
        assert False, error_message

    return id_token

def test_hello_user(client, firebase_user, firebase_test_token):
    response = client.get(
        "/api/user_token", headers={"Authorization": f"Bearer {firebase_test_token}"}
    )

    # response = client.get('/api/user_token', headers={'Authorization': f'Bearer {custom_token}'})
    assert response.status_code == status.HTTP_200_OK
    assert response.json() == {"msg": "Hello, user", "uid": f"{firebase_user.uid}"}


# Placeholder unit test

import os
import sys
import unittest

from CommonEnvironment.CallOnExit import CallOnExit

# ---------------------------------------------------------------------------
_script_fullpath = os.path.abspath(__file__) if "python" in sys.executable.lower() else sys.executable
_script_dir, _script_name = os.path.split(_script_fullpath)
# ---------------------------------------------------------------------------

sys.path.insert(0, os.path.join(_script_dir, ".."))
with CallOnExit(lambda: sys.path.pop(0)):
    from RegularExpression import *

# ----------------------------------------------------------------------
class GenerateTest(unittest.TestCase):

    # ----------------------------------------------------------------------
    def test_NoMatches(self):
        results = list(Generate(r"\s", "OneTwoThree"))
        self.assertEqual(len(results), 0)

    # ----------------------------------------------------------------------
    def test_Matches(self):
        results = list(Generate(re.compile(r"[A-Z]"), "One Two Three"))
        self.assertEqual(len(results), 3)

        self.assertEqual(results[0], { "_data_" : "ne ", })
        self.assertEqual(results[1], { "_data_" : "wo ", })
        self.assertEqual(results[2], { "_data_" : "hree", })

    # ----------------------------------------------------------------------
    def test_MatchesWithPrefix(self):
        results = list(Generate(r"\s", "One Two Three", yield_prefix=True))
        self.assertEqual(len(results), 3)

        self.assertEqual(results[0], { "_data_" : "One", })
        self.assertEqual(results[1], { "_data_" : "Two", })
        self.assertEqual(results[2], { "_data_" : "Three", })

    # ----------------------------------------------------------------------
    def test_NoMatchesWithCapture(self):
        results = list(Generate(r"\s(?P<c>\S)", "OneTwoThree"))
        self.assertEqual(len(results), 0)

    # ----------------------------------------------------------------------
    def test_MatchesWithCapture(self):
        results = list(Generate(r"(?P<c>[A-Z][a-z])", "One Two Three"))
        self.assertEqual(len(results), 3)

        self.assertEqual(results[0], { "_data_" : "e ", "c" : "On", })
        self.assertEqual(results[1], { "_data_" : "o ", "c" : "Tw", })
        self.assertEqual(results[2], { "_data_" : "ree", "c" : "Th", })

# ---------------------------------------------------------------------------
if __name__ == "__main__":
    try: sys.exit(unittest.main(verbosity=2))
    except KeyboardInterrupt: pass


"""
This is the main file for the code.
1. This file uses code from other .py files to fit and forecast data.
3. A documentation pdf along with readme.txt file is submitted for reference.
"""

#Importing necessary Libraries
import scipy.signal as signal
import time
import math
import numpy as np
import pandas as pd
from scipy.optimize import fmin_tnc
from scipy import stats
from pylab import *
from scipy.optimize import curve_fit
from multiprocessing import Pool, cpu_count
from contextlib import closing
import pickle

#Importing other .py files
import prepare_data
import initial_estimate_of_time_to_peak as init_peak
import outlier_analysis
import identify_number_and_volume_of_peaks as find_all_peaks
import decline_functions as dec_func
import signal_features

def fit_and_forecast(well_data):
	"""
	Description: This function takes in well_data.
	Input: df
	Output: Preprocessed data for oil and gas for all wells.
	"""

	#Saving the well_name of our well_data into a variable.
	well_name = "Well_170245_gas"
	print("Processing",well_name)

	#Converting pandas series to a numpy array for much faster processing without overhead.
	well_data = np.array(well_data)

	#Creating a time array for our well_data where t1 and y1 are time and welldata respectively.
	t1 = np.array(list(range(len(well_data)))) + 1
	y1 = well_data

	#Remove downtime outliers.
	y2 = y1[np.nonzero(y1)]
	t2 = np.array(list(range(len(y2)))) + 1

	#features = signal_features.reduce_signal_to_basic_features(y2)

	#Outlier analysis using data distribution --> Removes both global and local outliers.
	y2,outliers = np.array(outlier_analysis.remove_outliers(y2))

	#Identify initial time to peak
	max_peak = init_peak.indentify_initial_peak(y2)

	if math.isnan(max_peak):
		index_max_peak = 0
	else:
		index_max_peak = list(y2).index(max_peak)

	#Seperate decline curves and remove operational outlier peaks.
	y3 = y2[index_max_peak:]
	peaks = find_all_peaks.find_all_peaks(y3,max_peak,index_max_peak)
	list_of_subdeclines,all_peaks = find_all_peaks.get_seperate_declines(y2,peaks,index_max_peak)
	find_indexes_for_these_values = y2[all_peaks]
	indexes_for_prediction = [list(y1).index(each_value) for each_value in find_indexes_for_these_values]

	#Initialize lists to store models.
	list_of_all_fits_exponential = []
	list_of_all_fits_harmonic = []
	list_of_all_fits_hyperbolic = []
	list_of_all_fits_hyp2exp = []

	#Check if subdeclines are less than length 7 as per R code.
	length_of_first_sub_decline = len(list_of_subdeclines[0])
	length_of_last_sub_decline = len(list_of_subdeclines[-1])

	if length_of_last_sub_decline <= 7:
		list_of_subdeclines[-2] = np.concatenate((list_of_subdeclines[-2],list_of_subdeclines[-1]))
		list_of_subdeclines = list_of_subdeclines[:-1]
		indexes_for_prediction = indexes_for_prediction[:-1]

	if length_of_first_sub_decline <= 7:
		list_of_subdeclines[1] = np.concatenate((list_of_subdeclines[0],list_of_subdeclines[1]))
		list_of_subdeclines = list_of_subdeclines[1:]
		indexes_for_prediction = indexes_for_prediction[1:]

	#Model traininig to fit the data for several decline curves.
	for index,each_decline in enumerate(list_of_subdeclines):
		if index == 0:
			initial_guess_for_q_i = 200
		elif index == 0 and len(list_of_subdeclines)==1:
			initial_guess_for_q_i = np.mean(each_decline[:3])
		else:
			initial_guess_for_q_i = np.mean(each_decline[:3])
		t = np.array(list(range(len(each_decline)))) + 1
		try:
			popt_1, pcov_1 = curve_fit(dec_func.exponential_decline, t,each_decline,p0=(initial_guess_for_q_i,0.01), bounds = ([0,0.0002738226],[initial_guess_for_q_i*2, 1]),method = "trf")
			list_of_all_fits_exponential.append(popt_1)
		except Exception as e:
			list_of_all_fits_exponential.append(["No_Model"])
			print("Error: "+str(e))
		try:
			popt_2, pcov_2 = curve_fit(dec_func.harmonic_decline, t,each_decline,p0=(initial_guess_for_q_i,0.01), bounds = ([0,0.0002738226],[initial_guess_for_q_i*2, 1]),method = "trf")
			list_of_all_fits_harmonic.append(popt_2)
		except Exception as e:
			list_of_all_fits_harmonic.append(["No_Model"])
			print("Error: "+str(e))
		try:
			popt_3, pcov_3 = curve_fit(dec_func.hyperbolic_decline, t,each_decline,p0=(initial_guess_for_q_i,0.01,0.7), bounds = ([0,0.0002738226,0.6],[initial_guess_for_q_i*2, 1, 4]),method = "trf" )
			list_of_all_fits_hyperbolic.append(popt_3)
		except Exception as e:
			list_of_all_fits_hyperbolic.append(["No_Model"])
			print("Error: "+str(e))
		try:
			popt_4, pcov_4 = curve_fit(dec_func.hyp2exp, t,each_decline,p0=(initial_guess_for_q_i,0.01,0.7,0.1), bounds = ([0,0.0002738226,0.6,0],[initial_guess_for_q_i*2, 1, 4,0.5]),method = "trf")
			list_of_all_fits_hyp2exp.append(popt_4)
		except Exception as e:
			list_of_all_fits_hyp2exp.append(["No_Model"])
			print("Error: "+str(e))

	list_of_prediction_declines = np.split(y1,indexes_for_prediction)
	forecast_from = len(list_of_prediction_declines[-1])+ 1
	forecast_until = forecast_from + 1100
	t_forecast = np.array(list(range(forecast_from,forecast_until+1)))

	#Check how the trained model fits the training data
	y_pred_exponential = []
	for index,each_model in enumerate(list_of_all_fits_exponential):
		current_length = len(list_of_prediction_declines[index])
		t = np.array(list(range(current_length))) + 1
		if index != 0 and "No_Model" not in list(each_model):
			y_pred_exponential = y_pred_exponential + list(dec_func.exponential_decline(t,each_model[0],each_model[1]))
		elif index == 0 and len(list_of_subdeclines)==1:
			y_pred_exponential = y_pred_exponential + list(dec_func.exponential_decline(t,each_model[0],each_model[1]))
		else:
			y_pred_exponential = y_pred_exponential + [float('nan')]*current_length

	y_pred_harmonic = []
	for index,each_model in enumerate(list_of_all_fits_harmonic):
		current_length = len(list_of_prediction_declines[index])
		t = np.array(list(range(current_length))) + 1
		if index!=0 and "No_Model" not in list(each_model):
			y_pred_harmonic = y_pred_harmonic + list(dec_func.harmonic_decline(t,each_model[0],each_model[1]))
		elif index == 0 and len(list_of_subdeclines)==1:
			y_pred_harmonic = y_pred_harmonic + list(dec_func.harmonic_decline(t,each_model[0],each_model[1]))
		else:
			y_pred_harmonic = y_pred_harmonic + [float('nan')]*current_length

	y_pred_hyperbolic = []
	for index,each_model in enumerate(list_of_all_fits_hyperbolic):
		current_length = len(list_of_prediction_declines[index])
		t = np.array(list(range(current_length))) + 1
		if index!=0 and "No_Model" not in list(each_model):
			y_pred_hyperbolic = y_pred_hyperbolic + list(dec_func.hyperbolic_decline(t,each_model[0],each_model[1],each_model[2]))
		elif index == 0 and len(list_of_subdeclines)==1:
			y_pred_hyperbolic = y_pred_hyperbolic + list(dec_func.hyperbolic_decline(t,each_model[0],each_model[1],each_model[2]))
		else:
			y_pred_hyperbolic = y_pred_hyperbolic + [float('nan')]*current_length

	y_pred_hyp2exp = []
	for index,each_model in enumerate(list_of_all_fits_hyp2exp):
		current_length = len(list_of_prediction_declines[index])
		t = np.array(list(range(current_length))) + 1
		if index!=0 and "No_Model" not in list(each_model):
			y_pred_hyp2exp = y_pred_hyp2exp + list(dec_func.hyp2exp(t,each_model[0],each_model[1],each_model[2],each_model[3]))
		elif index == 0 and len(list_of_subdeclines)==1:
			y_pred_hyp2exp = y_pred_hyp2exp + list(dec_func.hyp2exp(t,each_model[0],each_model[1],each_model[2],each_model[3]))
		else:
			y_pred_hyp2exp = y_pred_hyp2exp + [float('nan')]*current_length

	#Forecast for three years in the future based on recent decline.
	if "No_Model" not in list(list_of_all_fits_exponential[-1]):
		exponential_forecast = dec_func.exponential_decline(t_forecast,list_of_all_fits_exponential[-1][0],list_of_all_fits_exponential[-1][1])
	else:
		exponential_forecast = "No_Forecast"

	if "No_Model" not in list(list_of_all_fits_harmonic[-1]):
		harmonic_forecast = dec_func.harmonic_decline(t_forecast,list_of_all_fits_harmonic[-1][0],list_of_all_fits_harmonic[-1][1])
	else:
		harmonic_forecast = "No_Forecast"

	if "No_Model" not in list(list_of_all_fits_hyperbolic[-1]):
		hyperbolic_forecast = dec_func.hyperbolic_decline(t_forecast,list_of_all_fits_hyperbolic[-1][0],list_of_all_fits_hyperbolic[-1][1],list_of_all_fits_hyperbolic[-1][2])
	else:
		hyperbolic_forecast = "No_Forecast"

	if "No_Model" not in list(list_of_all_fits_hyp2exp[-1]):
		hyp2exp_forecast = dec_func.hyp2exp(t_forecast,list_of_all_fits_hyp2exp[-1][0],list_of_all_fits_hyp2exp[-1][1],list_of_all_fits_hyp2exp[-1][2],list_of_all_fits_hyp2exp[-1][3])
	else:
		hyp2exp_forecast = "No_Forecast"

	list_save = []
	list_save.append(y1)
	list_save.append(y_pred_exponential)
	list_save.append(y_pred_harmonic)
	list_save.append(y_pred_hyperbolic)
	list_save.append(y_pred_hyp2exp)
	list_save.append(exponential_forecast)
	list_save.append(harmonic_forecast)
	list_save.append(hyperbolic_forecast)
	list_save.append(hyp2exp_forecast)
	list_save.append(len(list_of_subdeclines[-1]))
	list_save.append(outliers)

	return list_save


# -----------
# User Instructions:
#
# Modify the function search so that it returns
# a table of values called expand. This table
# will keep track of which step each node was
# expanded.
#
# Make sure that the initial cell in the grid
# you return has the value 0.
# ----------
from utils import Queue

grid = [[0, 0, 1, 0, 0, 0],
        [0, 0, 0, 0, 0, 0],
        [0, 0, 1, 0, 1, 0],
        [0, 0, 1, 0, 1, 0],
        [0, 0, 1, 0, 1, 0]]
init = [0, 0]
goal = [len(grid)-1, len(grid[0])-1]
cost = 1

delta = [[-1, 0], # go up
         [ 0,-1], # go left
         [ 1, 0], # go down
         [ 0, 1]] # go right

delta_name = ['^', '<', 'v', '>']

def search(grid,init,goal,cost):
    # ----------------------------------------
    # modify code below
    # ----------------------------------------
    Nr=len(grid)
    Nc=len(grid[0])
    expand=[[-1 for j in range(Nc)] for i in range(Nr)]
    count=0

    def childNode(grid, loc, delta, delta_name):
        child=[]
        for i in range(len(delta)):
            move=delta[i]
            newloc=[loc[0]+move[0], loc[1]+move[1]]
            if loc[0]+move[0]>=0 and loc[0]+move[0]<Nr \
            and loc[1]+move[1]>=0 and loc[1]+move[1]<Nc \
            and grid[newloc[0]][newloc[1]] ==0:
                child.append([newloc,delta_name[i]])
        return child

    visited=[]
    frontier=Queue()
    frontier.push([init,0])

    while not frontier.isEmpty():
        loc, rlen=frontier.pop()
        if not loc in visited:
            visited.append(loc)
            expand[loc[0]][loc[1]]=count
            count += 1

            if loc==goal:
                return expand

            for nextloc, move_name in childNode(grid, loc, delta, delta_name):
                if not nextloc in visited:
                    frontier.push([nextloc, rlen+cost])
    return 'fail'

exp_maze=search(grid,init,goal,cost)
if exp_maze=='fail':
    print(exp_maze)
else:
    print('Expanded sequence:')
    for row in exp_maze:
        print(row)
print('Grid:')
for row in grid:
    print(row)


from datetime import timedelta
from decimal import Decimal

import pytest
from django.core.exceptions import ValidationError
from django.utils import timezone
from graphql.error import GraphQLError

from ..validators import (
    validate_end_is_after_start,
    validate_one_of_args_is_in_query,
    validate_price_precision,
)

@pytest.mark.parametrize(
    "value, currency",
    [
        (Decimal("1.1200"), "USD"),
        (Decimal("1.12"), "USD"),
        (Decimal("1"), "USD"),
        (Decimal("1"), "ISK"),
        (Decimal("1.00"), "ISK"),
        (Decimal("5.12"), None),
        (Decimal("1000"), "USD"),
    ],
)
def test_validate_price_precision(value, currency):
    # when
    result = validate_price_precision(value, currency)

    # then
    assert result is None

@pytest.mark.parametrize(
    "value, currency",
    [
        (Decimal("1.1212"), "USD"),
        (Decimal("1.128"), "USD"),
        (Decimal("1.1"), "ISK"),
        (Decimal("1.11"), "ISK"),
        (Decimal("5.123"), None),
    ],
)
def test_validate_price_precision_raise_error(value, currency):
    with pytest.raises(ValidationError):
        validate_price_precision(value, currency)

def test_validate_end_is_after_start_raise_error():
    start_date = timezone.now() + timedelta(days=365)
    end_date = timezone.now() - timedelta(days=365)

    with pytest.raises(ValidationError) as error:
        validate_end_is_after_start(start_date, end_date)
    assert error.value.message == "End date cannot be before the start date."

def test_validate_one_of_args_is_in_query():
    assert validate_one_of_args_is_in_query("arg1", "present", "arg2", None) is None

def test_validate_one_of_args_is_in_query_false_args():
    with pytest.raises(GraphQLError) as error:
        validate_one_of_args_is_in_query("arg1", None, "arg2", "")
    assert (
        error.value.message == "At least one of arguments is required: 'arg1', 'arg2'."
    )

def test_validate_one_of_args_is_in_query_more_than_one_true():
    with pytest.raises(GraphQLError) as error:
        validate_one_of_args_is_in_query(
            "arg1", "present", "arg2", "present", "arg3", "present"
        )
    assert (
        error.value.message == "Argument 'arg1' cannot be combined with 'arg2', 'arg3'"
    )

def test_validate_one_of_args_is_in_query_single_arg():
    assert validate_one_of_args_is_in_query("arg1", "present") is None

def test_validate_one_of_args_is_in_query_single_arg_absent():
    with pytest.raises(GraphQLError) as error:
        validate_one_of_args_is_in_query("arg1", None) is None
    assert error.value.message == "At least one of arguments is required: 'arg1'."