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

from odoo import models, fields, api, exceptions, _
import logging

def cojo_padding_4_right(number):
    return str(number).rjust(4, '0') if type(number) == str else "0000"

def cojo_padding_3_right(number):
    return str(number).rjust(3, '0') if type(number) == str else "000"

def cojo_padding_2_right(number):
    return str(number).rjust(2, '0') if type(number) == str else "00"

_logger_ = logging.getLogger(__name__)

# We add these fields because we can use odoo's Company, Country and State models
class Company(models.Model):
    _inherit = "res.company"

    analytic_code = fields.Char(string="Analytic Code")

    _sql_constraints = [(
        'analytic_code_unique', 'unique(analytic_code)', 'Analytic Code must be unique!'
    )]

class AnalyticAccounts(models.Model):
    _inherit = "account.analytic.account"

    country_id = fields.Many2one(string="Country", related="company_id.country_id")
    state_id = fields.Many2one(string="State", related="company_id.state_id")

    department = fields.Many2one("analytic_accounts.group.department", string="Department")
    sub_department = fields.Many2one("analytic_accounts.group.sub_department", string="Sub Department")
    type = fields.Many2one("analytic_accounts.group.type", string="Type")
    group = fields.Many2one("analytic_accounts.group", string="Group")
    account = fields.Many2one("analytic_accounts.group.account", string="Account")
    sub_account = fields.Many2one("analytic_accounts.group.sub_account", string="Sub Account")
    item = fields.Many2one("analytic_accounts.group.item", string="Item")

    country_rel_id = fields.Integer(string='Country Id', related='country_id.id', readonly=False)
    state_rel_id = fields.Integer(string='State Id', related='state_id.id', readonly=False)
    company_rel_id = fields.Integer(string='Company Id', related='company_id.id', readonly=False)
    department_rel_id = fields.Integer(string='Department Id', related='department.id', readonly=False)
    sub_department_rel_id = fields.Integer(string='Sub Department Id', related='sub_department.id', readonly=False)
    type_rel_id = fields.Integer(string='Type Id', related='type.id', readonly=False)
    group_rel_id = fields.Integer(string='Group Id', related='group.id', readonly=False)
    account_rel_id = fields.Integer(string='Account Id', related='account.id', readonly=False)
    sub_account_rel_id = fields.Integer(string='Sub Account Id', related='sub_account.id', readonly=False)
    item_rel_id = fields.Integer(string='Item Id', related='item.id', readonly=False)

    country_rel_code = fields.Char(string='Country Code', related='country_id.code', readonly=False)
    state_rel_code = fields.Char(string='State Code', related='state_id.code', readonly=False)
    company_rel_code = fields.Char(string='Company Code', related='company_id.analytic_code', readonly=False)
    department_rel_code = fields.Char(string='Department Code', related='department.code', readonly=False)
    sub_department_rel_code = fields.Char(string='Sub Department Code', related='sub_department.code', readonly=False)
    type_rel_code = fields.Char(string='Type Code', related='type.code', readonly=False)
    group_rel_code = fields.Char(string='Group Code', related='group.code', readonly=False)
    account_rel_code = fields.Char(string='Account Code', related='account.code', readonly=False)
    sub_account_rel_code = fields.Char(string='Sub Account Code', related='sub_account.code', readonly=False)
    item_rel_code = fields.Char(string='Item Code', related='item.code', readonly=False)

    department_rel_name = fields.Char(string='Department Name', related='department.name', readonly=False)
    sub_department_rel_name = fields.Char(string='Sub Department Name', related='sub_department.name', readonly=False)

    def test_foo(self):
        return "test"

    # Domains
    @api.onchange("department")
    def _onchange_department(self):
        if not self.department:
            self.sub_department = False

    @api.onchange("type")
    def _onchange_type(self):
        res = {}
        if self.type:
            res['domain'] = {'group': [('type_id', '=', self.type.id)]}
            self.group = self.type.group_none
        return res

    @api.onchange("group")
    def _onchange_group(self):
        res = {}
        if self.group:
            res['domain'] = {'account': [('group_id', '=', self.group.id)]}
            self.account = self.group.account_none
        return res

    @api.onchange("account")
    def _onchange_account(self):
        res = {}
        if self.account:
            res['domain'] = {'sub_account': [('account_id', '=', self.account.id)]}
            self.sub_account = self.account.sub_account_none
        return res

    @api.onchange("sub_account")
    def _onchange_sub_account(self):
        res = {}
        if self.sub_account:
            res['domain'] = {'item': [('sub_account_id', '=', self.sub_account.id)]}
            self.item = self.sub_account.item_none
        return res

    def make_or_change(self, values):
        company_code = cojo_padding_4_right(self.company_id.analytic_code)
        if "company_id" in values:
            if values["company_id"]:
                company = self.env['res.company'].browse(values["company_id"])
                company_code = cojo_padding_4_right(company.analytic_code)
        if not company_code:
            company_code = "0000"

        country_code = cojo_padding_2_right(self.country_id.code)
        if "country_id" in values:
            if values["country_id"]:
                country = self.env['res.country'].browse(values["country_id"])
                country_code = country.code
        if not country_code:
            country_code = "00"

        state_code = cojo_padding_3_right(self.state_id.code)
        if "state_id" in values:
            if values["state_id"]:
                state = self.env['res.country.state'].browse(values["state_id"])
                state_code = state.code
        if not state_code:
            state_code = "000"

        department_code = cojo_padding_4_right(self.department.code)
        if "department" in values:
            if values["department"]:
                department = self.env['analytic_accounts.group.department'].browse(values["department"])
                department_code = cojo_padding_4_right(department.code)
            else:
                values["sub_department"] = False
        if not department_code:
            department_code = "0000"

        sub_department_code = cojo_padding_4_right(self.sub_department.code)
        if "sub_department" in values:
            if values["sub_department"]:
                sub_department = self.env['analytic_accounts.group.sub_department'].browse(values["sub_department"])
                sub_department_code = cojo_padding_4_right(sub_department.code)
        if not sub_department_code:
            sub_department_code = "0000"

        type_code = cojo_padding_4_right(self.type.code)
        if "type" in values:
            if values["type"]:
                type_record = self.env['analytic_accounts.group.type'].browse(values["type"])
                type_code = cojo_padding_4_right(type_record.code)
        if not type_code:
            type_code = "0000"

        group_code = cojo_padding_4_right(self.group.code)
        if "group" in values:
            if values["group"]:
                group = self.env['analytic_accounts.group'].browse(values["group"])
                group_code = cojo_padding_4_right(group.code)
        if not group_code:
            group_code = "0000"

        account_code = cojo_padding_4_right(self.account.code)
        if "account" in values:
            if values["account"]:
                account = self.env['analytic_accounts.group.account'].browse(values["account"])
                account_code = cojo_padding_4_right(account.code)
        if not account_code:
            account_code = "0000"

        sub_account_code = cojo_padding_4_right(self.sub_account.code)
        if "sub_account" in values:
            if values["sub_account"]:
                sub_account = self.env['analytic_accounts.group.sub_account'].browse(values["sub_account"])
                sub_account_code = cojo_padding_4_right(sub_account.code)
        if not sub_account_code:
            sub_account_code = "0000"

        item_code = cojo_padding_4_right(self.item.code)

        if "item" in values:
            if values["item"]:
                item = self.env['analytic_accounts.group.item'].browse(values["item"])
                item_code = cojo_padding_4_right(item.code)
        if not item_code:
            item_code = "0000"

        code = "{}{}{}{}{}{}{}{}{}{}".format(country_code,
                                             state_code,
                                             company_code,
                                             department_code,
                                             sub_department_code,
                                             type_code,
                                             group_code,
                                             account_code,
                                             sub_account_code,
                                             item_code)

        values["code"] = code

    def _import(self, values):
        code = values["code"]
        _logger_.info("Importing analytic account with reference: {}".format(code))

        if len(code) == 37:
            country_code        = code[0:2]
            region_code         = code[2:5]
            company_code        = code[5:9]

            #===================================================================
            # Verifica si la compañia existen en Odoo
            # Tambien comprueba si el country y el region son
            # igualmente validos
            #===================================================================

            CompanyEnv = self.env["res.company"]
            company_id = CompanyEnv.search([("analytic_code", "=", company_code)])
            if not company_id:
                raise exceptions.ValidationError(_("Invalid company code, must be 1234"))
            company_record = CompanyEnv.browse([company_id])

            if company_record.ids[0].country_id:
                if company_record.ids[0].country_id.code != country_code:
                    raise exceptions.ValidationError(_("Invalid country code, must be 12"))
                if company_record.ids[0].state_id:
                    if company_record.ids[0].state_id.code != region_code:
                        raise exceptions.ValidationError(_("Invalid region/state code, must be 123"))
                else:
                    raise exceptions.ValidationError(_("Country needs state specified"))
            else:
                raise exceptions.ValidationError(_("Company needs country specified"))

            department_code     = code[9:13]
            sub_department_code = code[13:17]

            type_code           = code[17:21]
            group_code          = code[21:25]
            account_code        = code[25:29]
            sub_account_code    = code[29:33]
            item_code           = code[33:37]

            #===================================================================
            # Estos son distinto porque sin independientes y ademas opcionales
            #===================================================================
            DeptEnv = self.env["analytic_accounts.group.department"]
            existing_dept = DeptEnv.search([["code", "=", department_code]])
            if len(existing_dept.ids) > 1:
                _logger_.error("Multiple departments!: {}".format( [r.name for r in existing_dept] ))

            if existing_dept:
                values["department"] = existing_dept.id
            else:
                new_dept= DeptEnv.create({
                        "name": "department-{}".format(department_code),
                        "code": department_code
                    })
                values["department"] = new_dept.id

            #===================================================================
            # Type
            #===================================================================
            SubDeptEnv = self.env["analytic_accounts.group.sub_department"]
            existing_sub_department = SubDeptEnv.search([["code", "=", sub_department_code]])
            if len(existing_sub_department.ids) > 1:
                _logger_.error("Multiple sub departments!: {}".format( [r.name for r in existing_sub_department] ))

            if existing_sub_department:
                values["sub_department"] = existing_sub_department.id
            else:
                new_sub_department = SubDeptEnv.create({
                        "name": "sub_department-{}".format(sub_department_code),
                        "code": sub_department_code
                    })
                values["sub_department"] = new_sub_department.id

            #===================================================================
            # Todo esto se hace para hacer un "merge" a los
            # datos type, group, account, sub account y item
            #===================================================================

            #===================================================================
            # Type
            #===================================================================
            TypeEnv = self.env["analytic_accounts.group.type"]
            existing_type = TypeEnv.search([["code", "=", type_code]])
            if len(existing_type.ids) > 1:
                _logger_.error("Multiple type!: {}".format( [r.name for r in existing_type] ))

            if existing_type:
                values["type"] = existing_type.id
            else:
                new_type = TypeEnv.create({
                        "name": "type-{}".format(type_code),
                        "code": type_code
                    })
                values["type"] = new_type.id

            #===================================================================
            # Group
            #===================================================================
            GroupEnv = self.env["analytic_accounts.group"]
            existing_group= GroupEnv.search(["&", ("code", "=", group_code), ("type_id", "=", values["type"])])
            if len(existing_group.ids) > 1:
                _logger_.error("Multiple groups!: {}".format( [r.name for r in existing_group] ))

            if existing_group:
                values["group"] = existing_group.id
            else:
                new_group = GroupEnv.create({
                        "name": "group-{}".format(group_code),
                        "type_id": values["type"],
                        "code": group_code
                    })
                values["group"] = new_group.id

            #===================================================================
            # Account
            #===================================================================
            AccountEnv = self.env["analytic_accounts.group.account"]
            existing_account= AccountEnv.search(["&", ("code", "=", account_code), ("group_id", "=", values["group"])])
            if len(existing_account.ids) > 1:
                _logger_.error("Multiple account!: {}".format( [r.name for r in existing_account] ))

            if existing_account:
                values["account"] = existing_account.id
            else:
                new_account = AccountEnv.create({
                        "name": "account-{}".format(account_code),
                        "group_id": values["group"],
                        "code": account_code
                    })
                values["account"] = new_account.id

            #===================================================================
            # Sub Account
            #===================================================================
            SubAccountEnv = self.env["analytic_accounts.group.sub_account"]
            existing_sub_account= SubAccountEnv.search(["&", ("code", "=", sub_account_code), ("account_id", "=", values["account"])])
            if len(existing_sub_account.ids) > 1:
                _logger_.error("Multiple sub account!: {} in account: {}".format( [r.name for r in existing_sub_account], values["account"]))

            if existing_sub_account:
                values["sub_account"] = existing_sub_account.id
            else:
                new_sub_account = SubAccountEnv.create({
                        "name": "sub_account-{}".format(sub_account_code),
                        "account_id": values["account"],
                        "code": sub_account_code
                    })
                values["sub_account"] = new_sub_account.id

            #===================================================================
            # Item
            #===================================================================
            ItemEnv = self.env["analytic_accounts.group.item"]
            existing_item = ItemEnv.search(["&", ("code", "=", item_code), ("sub_account_id", "=", values["sub_account"])])
            if len(existing_item.ids) > 1:
                _logger_.error("Multiple items!: {}".format( [r.name for r in existing_item] ))

            if existing_item:
                values["item"] = existing_item.id
            else:
                new_item = ItemEnv.create({
                        "name": "account-{}".format(item_code),
                        "sub_account_id": values["sub_account"],
                        "code": item_code
                    })
                values["item"] = new_item.id
        else:
            raise exceptions.ValidationError(_("Cosas de la vida ¯\_()_/¯"))
        pass

    def change_groups(self, values):

        department = values["department"] if "department" in values else self.department_rel_id
        AnalyticGroupEnv = self.env["account.analytic.group"]

        department_group_id = False
        if department:

            Deparments = self.env["analytic_accounts.group.department"]
            department = Deparments.browse(department)

            ExistingDeptGroup = AnalyticGroupEnv.search(("&", ["parent_id", "=", False],["analytic_code", "=", department.code]))

            if not ExistingDeptGroup:
                print("DeptGroupBefore: {}".format(ExistingDeptGroup))

                print("Departament: {}".format(department.name))

                dept_dict_obj = {
                    "name": department.name,
                    "analytic_code": department.code,
                    "description": "Code: {}".format(department.code)
                }

                department_group_id = AnalyticGroupEnv.create(dept_dict_obj).id
            else:
                ExistingDeptGroup.write({
                    "name": department.name,
                    "analytic_code": department.code
                })
                department_group_id = ExistingDeptGroup.id

        # department_group_id = department_group_id if department_group_id else department.id
        values["group_id"] = department_group_id
        SubDeparments = self.env["analytic_accounts.group.sub_department"]

        sub_department = values["sub_department"] if "sub_department" in values else self.sub_department_rel_id

        if sub_department:
            sub_department = SubDeparments.browse(sub_department)
            ExistingSubDeptGroup = AnalyticGroupEnv.search(("&", ["parent_id.analytic_code", "=", department.code], ["analytic_code", "=", sub_department.code ]))

            if not ExistingSubDeptGroup:

                print("Sub departament: {}".format(sub_department.name))
                sub_dept_dict_obj = {
                    "name": sub_department.name,
                    "parent_id": department_group_id,
                    "analytic_code": sub_department.code,
                    "description": "Code: {}".format(sub_department.code)
                }

                sub_dept = AnalyticGroupEnv.create(sub_dept_dict_obj)
                values["group_id"] = sub_dept.id
            else:
                ExistingSubDeptGroup.write({
                    "name": sub_department.name,
                    "analytic_code": sub_department.code
                })
                values["group_id"] = ExistingSubDeptGroup.id

    def reload_dept_code(self, values):
        if "department_rel_code" in values:
            department = None
            if "department" in values:
                department = self.env["analytic_accounts.group.department"].browse([values["department"]])
            elif self.department:
                department = self.department
            else:
                return
            department.code = values["department_rel_code"]

    def reload_sub_dept_code(self, values):
        if "sub_department_rel_code" in values:
            sub_department = None
            if "sub_department" in values:
                sub_department = self.env["analytic_accounts.group.sub_department"].browse([values["sub_department"]])
            elif self.sub_department:
                sub_department = self.sub_department
            else:
                return
            sub_department.code = values["sub_department_rel_code"]

    def reload_type_code(self, values):
        if "type_rel_code" in values:
            type_record = None
            if "type" in values:
                type_record = self.env["analytic_accounts.group.type"].browse([values["type"]])
            elif self.type:
                type_record = self.type
            else:
                return
            type_record.code = values["type_rel_code"]

    def reload_group_code(self, values):
        if "group_rel_code" in values:
            group_record = None
            if "group" in values:
                group_record = self.env["analytic_accounts.group.group"].browse([values["group"]])
            elif self.group:
                group_record = self.group
            else:
                return
            group_record.code = values["group_rel_code"]

    def reload_account_code(self, values):
        if "account_rel_code" in values:
            account_record = None
            if "account" in values:
                account_record = self.env["analytic_accounts.group.account"].browse([values["account"]])
            elif self.account:
                account_record = self.account
            else:
                return
            account_record.code = values["account_rel_code"]

    def reload_sub_account_code(self, values):
        if "sub_account_rel_code" in values:
            sub_account_record = None
            if "sub_account" in values:
                sub_account_record = self.env["analytic_accounts.group.sub_account"].browse([values["sub_account"]])
            elif self.sub_account:
                sub_account_record = self.sub_account
            else:
                return
            sub_account_record.code = values["sub_account_rel_code"]

    def reload_item_code(self, values):
        if "item_rel_code" in values:
            item_record = None
            if "item" in values:
                item_record = self.env["analytic_accounts.group.item"].browse([values["item"]])
            elif self.item:
                item_record = self.item
            else:
                return
            item_record.code = values["item_rel_code"]

    @api.model
    def create(self, values):
        # self.ensure_one()
        if "group_id" in values:
            self.make_or_change(values)
        else:
            self._import(values)

        # Create a group based on department and sub department

        self.change_groups(values)

        return super(AnalyticAccounts, self).create(values)

    def write(self, values):
        self.ensure_one()

        self.reload_dept_code(values)
        self.reload_sub_dept_code(values)

        self.reload_type_code(values)
        self.reload_type_code(values)
        self.reload_account_code(values)
        self.reload_sub_account_code(values)
        self.reload_item_code(values)

        self.make_or_change(values)
        self.change_groups(values)

        return super().write(values)

# Just simply to make these groups
class GroupBase(models.Model):
    _name = "analytic_accounts.group.base"

    name = fields.Char(string="Name", required=True)
    code = fields.Char(string="Code", required=True, size=4)

    @api.model
    def create(self, values):

        if "code" in values:
            values["code"] = values["code"].rjust(4, "0")[-4:]

        return super(GroupBase, self).create(values)

    def write(self, values):
        # print("Creando un grupo generico")
        if "code" in values:
            values["code"] = cojo_padding_4_right(values["code"])

        return super(GroupBase, self).write(values)

class GroupDepartment(GroupBase):
    _name = "analytic_accounts.group.department"

    # group_id = fields.Many2one("account.analytic.group", string="Group")

    # def write(self, values):
    #     if "name" in values:
    #         group_id.write({
    #             "name": values["name"]
    #         })
    #     return super().write(values)

class GroupSubDepartment(GroupBase):
    _name = "analytic_accounts.group.sub_department"

    #group_id = fields.Many2one("account.analytic.group", string="Group")

    #def write(self, values):
    #    if "name" in values:
    #        group_id.write({
    #            "name": values["name"]
    #        })
    #    return super().write(values)

class GroupType(GroupBase):
    _name = "analytic_accounts.group.type"

    # sub_department.id = fields.Many2one("analytic_accounts.group.sub_department", required=True)
    group_ids = fields.One2many("analytic_accounts.group", "type_id", ondelete="cascade")
    group_none = fields.Many2one("analytic_accounts.group")

    @api.model
    def create(self, values):
        res = super().create(values)

        none_group = self.env["analytic_accounts.group"].create({
            "type_id": res.id,
            "code": "0000",
            "name": "None"
        })

        res.group_none = none_group.id

        return res

class Group(GroupBase):
    _name = "analytic_accounts.group"

    type_id = fields.Many2one("analytic_accounts.group.type", required=True, ondelete="cascade")
    account_ids = fields.One2many("analytic_accounts.group.account", "group_id", ondelete="cascade")
    account_none = fields.Many2one("analytic_accounts.group.account")

    @api.model
    def create(self, values):
        if not "type_id" in values:
            values["type_id"] = self._context.get("type_id")
        res = super().create(values)

        #=======================================================================
        # print(res)
        #=======================================================================

        none_account = self.env["analytic_accounts.group.account"].create({
            "group_id": res.id,
            "code": "0000",
            "name": "None"
        })

        res.account_none = none_account.id

        return res

class GroupAccount(GroupBase):
    _name = "analytic_accounts.group.account"

    group_id = fields.Many2one("analytic_accounts.group", required=True, ondelete="cascade")
    sub_account_ids = fields.One2many("analytic_accounts.group.sub_account", "account_id", ondelete="cascade")
    sub_account_none = fields.Many2one("analytic_accounts.group.sub_account")

    @api.model
    def create(self, values):
        if not "group_id" in values:
            values["group_id"] = self._context.get("group_id")
        res = super().create(values)

        none_sub_account = self.env["analytic_accounts.group.sub_account"].create({
            "account_id": res.id,
            "code": "0000",
            "name": "None"
        })

        res.sub_account_none = none_sub_account.id

        return res

class GroupSubAccount(GroupBase):
    _name = "analytic_accounts.group.sub_account"

    account_id = fields.Many2one("analytic_accounts.group.account", required=True, ondelete="cascade")
    item_ids = fields.One2many("analytic_accounts.group.item", "sub_account_id", ondelete="cascade")
    item_none = fields.Many2one("analytic_accounts.group.item")

    @api.model
    def create(self, values):
        if not "account_id" in values:
            values["account_id"] = self._context.get("account_id")
        res = super().create(values)

        none_item = self.env["analytic_accounts.group.item"].create({
            "sub_account_id": res.id,
            "code": "0000",
            "name": "None"
        })

        res.item_none = none_item.id

        return res

class GroupItem(GroupBase):
    _name = "analytic_accounts.group.item"

    sub_account_id = fields.Many2one("analytic_accounts.group.sub_account", ondelete="cascade")

    @api.model
    def create(self, values):
        if not "sub_account_id" in values:
            values["sub_account_id"] = self._context.get("sub_account_id")
        res = super().create(values)
        return res


from django.conf.urls import patterns, include, url

from django.contrib import admin
admin.autodiscover()

from rollcall.groups.views import (
    GroupListView,
    GroupDetailView,
    GroupStatesView,
    GroupStateListView,
    GroupUpdate,
)
from rollcall.people.views import PersonListView, PersonDetailView

urlpatterns = patterns('',
    # Examples:
    # url(r'^$', 'rollcall.views.home', name='home'),
    # url(r'^blog/', include('blog.urls')),

    url(r'^admin/', include(admin.site.urls)),

    url(
        r'^people/$',
            PersonListView.as_view(),
            name='person-list',
    ),
    url(
        r'^people/(?P<slug>.*)$',
            PersonDetailView.as_view(),
            name='person-detail',
    ),

    url(
        r'^group/$',
            GroupListView.as_view(),
            name='group-list',
    ),
    url(
        r'^group/(?P<slug>.*?)/state$',
        GroupUpdate.as_view(),
        name='group-state',
    ),
    url(
        r'^group/(?P<slug>.*)$',
            GroupDetailView.as_view(),
            name='group-detail',
    ),
    url(
        r'^group-state/$',
            GroupStatesView.as_view(),
            name='group-list-states',
    ),
    url(
        r'^group-state/(?P<state>.*)$',
            GroupStateListView.as_view(),
            name='group-list-by-state',
    ),
)


import requests
import json

def get_practitioner(npi):
    """Returns a Practitioner Resource from Djmongo"""
    url = "https://registry.npi.io/search/fhir/Practitioner.json" \
          "?identifier.value=%s" % (npi)
    response = requests.get(url)
    try:
        jr = json.loads(response.text)

        if 'results' not in jr:
            jr = {'error', 'The lookup failed. Invalid response from server'}

        if not jr['results']:
                jr = {'error', 'Invalid NPI'}
    except ValueError:
        jr = {'error',
              'The lookup failed. JSON was not returned from the server.'}

    return jr['results'][0]

def convert_practitioner_fhir_to_form(pract_res, user):
    """Converts a Practitioner Resource into Values for Form"""
    data = {}
    data['user'] = user
    data['first_name']= pract_res['name'][0]['given'][0]
    data['last_name']= pract_res['name'][0]['family'][0]
    data['npi']= pract_res['identifier'][0]['value']
    data['fhir_id']= pract_res['id']

    return data

def convert_practitioner_fhir_to_meta(pract_res, user):
    """Converts a Practitioner Resource into Values for Meta"""
    data = {}
    data['user'] = user
    data['npi']= pract_res['identifier'][0]['value']
    data['fhir_id']= pract_res['id']

    return data

def get_pecos_individual_affliliation(npi):
    """Returns a Pecos Affiliation Resource from Djmongo"""
    url = "https://registry.npi.io/search/pecos/compiled_individuals." \
          "json?NPI=%s" % (npi)
    response = requests.get(url)
    try:
        jr = json.loads(response.text)

        if 'results' not in jr:
            jr = {'error', 'The lookup failed. Invalid response from server'}

        if not jr['results']:
                jr = {'error', 'Invalid NPI'}
    except ValueError:
        jr = {'error',
              'The lookup failed. JSON was not returned from the server.'}

    return jr['results'][0]['works_for']

def convert_pecos_to_form(pecos_res, user):
    """Converts a Practitioner Resource into Values for Form"""
    data = {}
    data['user'] = user
    data['name']= pecos_res[0]['NAME']
    data['npi']= pecos_res[0]['NPI']
    data['description']= pecos_res[0]['DESCRIPTION']

    return data

def convert_pecos_to_meta(pecos_res, user):
    """Converts a Practitioner Resource into Values for Meta"""
    data = {}
    data['user'] = user
    data['npi']= pecos_res['identifier'][0]['value']
    data['fhir_id']= pecos_res['id']

    return data

# if __name__ == "__main__":
#     print(get_pecos_individual_affliliation(1205824083))


"""Defines the QT powered interface for configuring Stream Decks"""
import os
import shlex
import sys
import time
from functools import partial
from subprocess import Popen  # nosec - Need to allow users to specify arbitrary commands
from typing import Callable, Dict

from pynput.keyboard import Controller, Key
from PySide2 import QtWidgets
from PySide2.QtCore import QMimeData, QSize, Qt, QTimer
from PySide2.QtGui import QDrag, QIcon
from PySide2.QtWidgets import (
    QAction,
    QApplication,
    QDialog,
    QFileDialog,
    QMainWindow,
    QMenu,
    QMessageBox,
    QSizePolicy,
    QSystemTrayIcon,
)

from streamdeck_ui import api
from streamdeck_ui.config import LOGO
from streamdeck_ui.ui_main import Ui_MainWindow
from streamdeck_ui.ui_settings import Ui_SettingsDialog

BUTTON_STYLE = """
    QToolButton{background-color:black; color:white;}
    QToolButton:checked{background-color:darkGray; color:black;}
    QToolButton:focus{border:none; }
"""

BUTTON_DRAG_STYLE = """
    QToolButton{background-color:white; color:black;}
    QToolButton:checked{background-color:darkGray; color:black;}
    QToolButton:focus{border:none; }
"""

selected_button: QtWidgets.QToolButton
text_timer = None
dimmer_options = {
    "Never": 0,
    "10 Seconds": 10,
    "1 Minute": 60,
    "5 Minutes": 300,
    "10 Minutes": 600,
    "15 Minutes": 900,
    "30 Minutes": 1800,
    "1 Hour": 3600,
    "5 Hours": 7200,
    "10 Hours": 36000,
}
last_image_dir = ""

class Dimmer:
    timeout = 0
    brightness = -1
    brightness_dimmed = -1
    __stopped = False
    __dimmer_brightness = -1
    __timer = None
    __change_timer = None

    def __init__(
        self,
        timeout: int,
        brightness: int,
        brightness_dimmed: int,
        brightness_callback: Callable[[int], None],
    ):
        """ Constructs a new Dimmer instance

        :param int timeout: The time in seconds before the dimmer starts.
        :param int brightness: The normal brightness level.
        :param Callable[[int], None] brightness_callback: Callback that receives the current
                                                          brightness level.
         """
        self.timeout = timeout
        self.brightness = brightness
        self.brightness_dimmed = brightness_dimmed
        self.brightness_callback = brightness_callback

    def stop(self) -> None:
        """ Stops the dimmer and sets the brightness back to normal. Call
        reset to start normal dimming operation. """
        if self.__timer:
            self.__timer.stop()

        if self.__change_timer:
            self.__change_timer.stop()

        self.__dimmer_brightness = self.brightness
        self.brightness_callback(self.brightness)
        self.__stopped = True

    def reset(self) -> bool:
        """ Reset the dimmer and start counting down again. If it was busy dimming, it will
        immediately stop dimming. Callback fires to set brightness back to normal."""

        self.__stopped = False
        if self.__timer:
            self.__timer.stop()

        if self.__change_timer:
            self.__change_timer.stop()

        if self.timeout:
            self.__timer = QTimer()
            self.__timer.setSingleShot(True)
            self.__timer.timeout.connect(partial(self.change_brightness))
            self.__timer.start(self.timeout * 1000)

        if self.__dimmer_brightness != self.brightness:
            previous_dimmer_brightness = self.__dimmer_brightness
            self.brightness_callback(self.brightness)
            self.__dimmer_brightness = self.brightness
            if previous_dimmer_brightness < 10:
                return True

        return False

    def dim(self, toggle: bool = False):
        """ Manually initiate a dim event.
            If the dimmer is stopped, this has no effect. """

        if self.__stopped:
            return

        if toggle and self.__dimmer_brightness == 0:
            self.reset()
        elif self.__timer and self.__timer.isActive():
            # No need for the timer anymore, stop it
            self.__timer.stop()

            # Verify that we're not already at the target brightness nor
            # busy with dimming already
            if self.__change_timer is None and self.__dimmer_brightness:
                self.change_brightness()

    def change_brightness(self):
        """ Move the brightness level down by one and schedule another change_brightness event. """
        if self.__dimmer_brightness and self.__dimmer_brightness >= self.brightness_dimmed:
            self.__dimmer_brightness = self.__dimmer_brightness - 1
            self.brightness_callback(self.__dimmer_brightness)
            self.__change_timer = QTimer()
            self.__change_timer.setSingleShot(True)
            self.__change_timer.timeout.connect(partial(self.change_brightness))
            self.__change_timer.start(10)
        else:
            self.__change_timer = None

dimmers: Dict[str, Dimmer] = {}

class DraggableButton(QtWidgets.QToolButton):
    """A QToolButton that supports drag and drop and swaps the button properties on drop """

    def __init__(self, parent, ui):
        super(DraggableButton, self).__init__(parent)

        self.setAcceptDrops(True)
        self.ui = ui

    def mouseMoveEvent(self, e):  # noqa: N802 - Part of QT signature.

        if e.buttons() != Qt.LeftButton:
            return

        dimmers[_deck_id(self.ui)].reset()

        mimedata = QMimeData()
        drag = QDrag(self)
        drag.setMimeData(mimedata)
        drag.exec_(Qt.MoveAction)

    def dropEvent(self, e):  # noqa: N802 - Part of QT signature.
        global selected_button

        self.setStyleSheet(BUTTON_STYLE)

        if e.source():
            # Ignore drag and drop on yourself
            if e.source().index == self.index:
                return

            api.swap_buttons(_deck_id(self.ui), _page(self.ui), e.source().index, self.index)
            # In the case that we've dragged the currently selected button, we have to
            # check the target button instead so it appears that it followed the drag/drop
            if e.source().isChecked():
                e.source().setChecked(False)
                self.setChecked(True)
                selected_button = self
        else:
            # Handle drag and drop from outside the application
            if e.mimeData().hasUrls:
                file_name = e.mimeData().urls()[0].toLocalFile()
                api.set_button_icon(_deck_id(self.ui), _page(self.ui), self.index, file_name)

        redraw_buttons(self.ui)

    def dragEnterEvent(self, e):  # noqa: N802 - Part of QT signature.
        if type(self) is DraggableButton:
            e.setAccepted(True)
            self.setStyleSheet(BUTTON_DRAG_STYLE)
        else:
            e.setAccepted(False)

    def dragLeaveEvent(self, e):  # noqa: N802 - Part of QT signature.
        self.setStyleSheet(BUTTON_STYLE)

def _replace_special_keys(key):
    """Replaces special keywords the user can use with their character equivalent."""
    if key.lower() == "plus":
        return "+"
    if key.lower() == "comma":
        return ","
    if key.lower().startswith("delay"):
        return key.lower()
    return key

def handle_keypress(deck_id: str, key: int, state: bool) -> None:

    if state:

        if dimmers[deck_id].reset():
            return

        keyboard = Controller()
        page = api.get_page(deck_id)

        command = api.get_button_command(deck_id, page, key)
        if command:
            try:
                Popen(shlex.split(command))
            except Exception as error:
                print(f"The command '{command}' failed: {error}")

        keys = api.get_button_keys(deck_id, page, key)
        if keys:
            keys = keys.strip().replace(" ", "")
            for section in keys.split(","):
                # Since + and , are used to delimit our section and keys to press,
                # they need to be substituted with keywords.
                section_keys = [_replace_special_keys(key_name) for key_name in section.split("+")]

                # Translate string to enum, or just the string itself if not found
                section_keys = [
                    getattr(Key, key_name.lower(), key_name) for key_name in section_keys
                ]

                for key_name in section_keys:
                    if isinstance(key_name, str) and key_name.startswith("delay"):
                        sleep_time_arg = key_name.split("delay", 1)[1]
                        if sleep_time_arg:
                            try:
                                sleep_time = float(sleep_time_arg)
                            except Exception:
                                print(f"Could not convert sleep time to float '{sleep_time_arg}'")
                                sleep_time = 0
                        else:
                            # default if not specified
                            sleep_time = 0.5

                        if sleep_time:
                            try:
                                time.sleep(sleep_time)
                            except Exception:
                                print(f"Could not sleep with provided sleep time '{sleep_time}'")
                    else:
                        try:
                            keyboard.press(key_name)
                        except Exception:
                            print(f"Could not press key '{key_name}'")

                for key_name in section_keys:
                    if not (isinstance(key_name, str) and key_name.startswith("delay")):
                        try:
                            keyboard.release(key_name)
                        except Exception:
                            print(f"Could not release key '{key_name}'")

        write = api.get_button_write(deck_id, page, key)
        if write:
            try:
                keyboard.type(write)
            except Exception as error:
                print(f"Could not complete the write command: {error}")

        brightness_change = api.get_button_change_brightness(deck_id, page, key)
        if brightness_change:
            try:
                api.change_brightness(deck_id, brightness_change)
                dimmers[deck_id].brightness = api.get_brightness(deck_id)
                dimmers[deck_id].reset()
            except Exception as error:
                print(f"Could not change brightness: {error}")

        switch_page = api.get_button_switch_page(deck_id, page, key)
        if switch_page:
            api.set_page(deck_id, switch_page - 1)

def _deck_id(ui) -> str:
    return ui.device_list.itemData(ui.device_list.currentIndex())

def _page(ui) -> int:
    return ui.pages.currentIndex()

def update_button_text(ui, text: str) -> None:
    deck_id = _deck_id(ui)
    api.set_button_text(deck_id, _page(ui), selected_button.index, text)
    redraw_buttons(ui)

def update_button_command(ui, command: str) -> None:
    deck_id = _deck_id(ui)
    api.set_button_command(deck_id, _page(ui), selected_button.index, command)

def update_button_keys(ui, keys: str) -> None:
    deck_id = _deck_id(ui)
    api.set_button_keys(deck_id, _page(ui), selected_button.index, keys)

def update_button_write(ui) -> None:
    deck_id = _deck_id(ui)
    api.set_button_write(deck_id, _page(ui), selected_button.index, ui.write.toPlainText())

def update_change_brightness(ui, amount: int) -> None:
    deck_id = _deck_id(ui)
    api.set_button_change_brightness(deck_id, _page(ui), selected_button.index, amount)

def update_switch_page(ui, page: int) -> None:
    deck_id = _deck_id(ui)
    api.set_button_switch_page(deck_id, _page(ui), selected_button.index, page)

def _highlight_first_button(ui) -> None:
    button = ui.pages.currentWidget().findChildren(QtWidgets.QToolButton)[0]
    button.setChecked(False)
    button.click()

def change_page(ui, page: int) -> None:
    deck_id = _deck_id(ui)
    api.set_page(deck_id, page)
    redraw_buttons(ui)
    _highlight_first_button(ui)
    dimmers[deck_id].reset()

def select_image(window) -> None:
    global last_image_dir
    deck_id = _deck_id(window.ui)
    image = api.get_button_icon(deck_id, _page(window.ui), selected_button.index)
    if not image:
        if not last_image_dir:
            image = os.path.expanduser("~")
        else:
            image = last_image_dir
    file_name = QFileDialog.getOpenFileName(
        window, "Open Image", image, "Image Files (*.png *.jpg *.bmp)"
    )[0]
    if file_name:
        last_image_dir = os.path.dirname(file_name)
        deck_id = _deck_id(window.ui)
        api.set_button_icon(deck_id, _page(window.ui), selected_button.index, file_name)
        redraw_buttons(window.ui)

def remove_image(window) -> None:
    deck_id = _deck_id(window.ui)
    image = api.get_button_icon(deck_id, _page(window.ui), selected_button.index)
    if image:
        confirm = QMessageBox(window)
        confirm.setWindowTitle("Remove image")
        confirm.setText("Are you sure you want to remove the image for this button?")
        confirm.setStandardButtons(QMessageBox.Yes | QMessageBox.No)
        confirm.setIcon(QMessageBox.Question)
        button = confirm.exec_()
        if button == QMessageBox.Yes:
            api.set_button_icon(deck_id, _page(window.ui), selected_button.index, "")
            redraw_buttons(window.ui)

def redraw_buttons(ui) -> None:
    deck_id = _deck_id(ui)
    current_tab = ui.pages.currentWidget()
    buttons = current_tab.findChildren(QtWidgets.QToolButton)
    for button in buttons:
        button.setText(api.get_button_text(deck_id, _page(ui), button.index))
        button.setIcon(QIcon(api.get_button_icon(deck_id, _page(ui), button.index)))

def set_brightness(ui, value: int) -> None:
    deck_id = _deck_id(ui)
    api.set_brightness(deck_id, value)
    dimmers[deck_id].brightness = value
    dimmers[deck_id].reset()

def set_brightness_dimmed(ui, value: int, full_brightness: int) -> None:
    deck_id = _deck_id(ui)
    api.set_brightness_dimmed(deck_id, value)
    dimmers[deck_id].brightness_dimmed = int(full_brightness * (value / 100))
    dimmers[deck_id].reset()

def button_clicked(ui, clicked_button, buttons) -> None:
    global selected_button
    selected_button = clicked_button
    for button in buttons:
        if button == clicked_button:
            continue

        button.setChecked(False)

    deck_id = _deck_id(ui)
    button_id = selected_button.index
    ui.text.setText(api.get_button_text(deck_id, _page(ui), button_id))
    ui.command.setText(api.get_button_command(deck_id, _page(ui), button_id))
    ui.keys.setText(api.get_button_keys(deck_id, _page(ui), button_id))
    ui.write.setPlainText(api.get_button_write(deck_id, _page(ui), button_id))
    ui.change_brightness.setValue(api.get_button_change_brightness(deck_id, _page(ui), button_id))
    ui.switch_page.setValue(api.get_button_switch_page(deck_id, _page(ui), button_id))
    dimmers[deck_id].reset()

def build_buttons(ui, tab) -> None:
    deck_id = _deck_id(ui)
    deck = api.get_deck(deck_id)

    if hasattr(tab, "deck_buttons"):
        tab.deck_buttons.hide()
        tab.deck_buttons.deleteLater()

    base_widget = QtWidgets.QWidget(tab)
    tab.children()[0].addWidget(base_widget)
    tab.deck_buttons = base_widget

    row_layout = QtWidgets.QVBoxLayout(base_widget)
    index = 0
    buttons = []
    for _row in range(deck["layout"][0]):  # type: ignore
        column_layout = QtWidgets.QHBoxLayout()
        row_layout.addLayout(column_layout)

        for _column in range(deck["layout"][1]):  # type: ignore
            button = DraggableButton(base_widget, ui)
            button.setCheckable(True)
            button.index = index
            button.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding)
            button.setToolButtonStyle(Qt.ToolButtonTextUnderIcon)
            button.setIconSize(QSize(100, 100))
            button.setStyleSheet(BUTTON_STYLE)
            buttons.append(button)
            column_layout.addWidget(button)
            index += 1

    for button in buttons:
        button.clicked.connect(
            lambda button=button, buttons=buttons: button_clicked(ui, button, buttons)
        )

def export_config(window) -> None:
    file_name = QFileDialog.getSaveFileName(
        window, "Export Config", os.path.expanduser("~/streamdeck_ui_export.json"), "JSON (*.json)"
    )[0]
    if not file_name:
        return

    api.export_config(file_name)

def import_config(window) -> None:
    file_name = QFileDialog.getOpenFileName(
        window, "Import Config", os.path.expanduser("~"), "Config Files (*.json)"
    )[0]
    if not file_name:
        return

    api.import_config(file_name)
    redraw_buttons(window.ui)

def sync(ui) -> None:
    api.ensure_decks_connected()
    ui.pages.setCurrentIndex(api.get_page(_deck_id(ui)))

def build_device(ui, _device_index=None) -> None:
    for page_id in range(ui.pages.count()):
        page = ui.pages.widget(page_id)
        page.setStyleSheet("background-color: black")
        build_buttons(ui, page)

    # Set the active page for this device
    ui.pages.setCurrentIndex(api.get_page(_deck_id(ui)))

    # Draw the buttons for the active page
    redraw_buttons(ui)
    sync(ui)
    _highlight_first_button(ui)

class MainWindow(QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        self.window_shown: bool = True

    def closeEvent(self, event) -> None:  # noqa: N802 - Part of QT signature.
        self.window_shown = False
        self.hide()
        event.ignore()

    def systray_clicked(self, _status=None) -> None:
        if self.window_shown:
            self.hide()
            self.window_shown = False
            return

        self.bring_to_top()

    def bring_to_top(self):
        self.show()
        self.activateWindow()
        self.raise_()
        self.window_shown = True

def queue_text_change(ui, text: str) -> None:
    global text_timer

    if text_timer:
        text_timer.stop()

    text_timer = QTimer()
    text_timer.setSingleShot(True)
    text_timer.timeout.connect(partial(update_button_text, ui, text))
    text_timer.start(500)

def change_brightness(deck_id: str, brightness: int):
    """Changes the brightness of the given streamdeck, but does not save
    the state."""
    api.decks[deck_id].set_brightness(brightness)

class SettingsDialog(QDialog):
    def __init__(self, parent):
        super().__init__(parent)
        self.ui = Ui_SettingsDialog()
        self.ui.setupUi(self)
        self.show()

def show_settings(window) -> None:
    """Shows the settings dialog and allows the user the change deck specific
    settings. Settings are not saved until OK is clicked."""
    ui = window.ui
    deck_id = _deck_id(ui)
    settings = SettingsDialog(window)
    dimmers[deck_id].stop()

    for label, value in dimmer_options.items():
        settings.ui.dim.addItem(f"{label}", userData=value)

    existing_timeout = api.get_display_timeout(deck_id)
    existing_index = next(
        (i for i, (k, v) in enumerate(dimmer_options.items()) if v == existing_timeout), None
    )

    if existing_index is None:
        settings.ui.dim.addItem(f"Custom: {existing_timeout}s", userData=existing_timeout)
        existing_index = settings.ui.dim.count() - 1
        settings.ui.dim.setCurrentIndex(existing_index)
    else:
        settings.ui.dim.setCurrentIndex(existing_index)

    existing_brightness_dimmed = api.get_brightness_dimmed(deck_id)
    settings.ui.brightness_dimmed.setValue(existing_brightness_dimmed)

    settings.ui.label_streamdeck.setText(deck_id)
    settings.ui.brightness.setValue(api.get_brightness(deck_id))
    settings.ui.brightness.valueChanged.connect(partial(change_brightness, deck_id))
    settings.ui.dim.currentIndexChanged.connect(partial(disable_dim_settings, settings))
    if settings.exec_():
        # Commit changes
        if existing_index != settings.ui.dim.currentIndex():
            dimmers[deck_id].timeout = settings.ui.dim.currentData()
            api.set_display_timeout(deck_id, settings.ui.dim.currentData())
        set_brightness(window.ui, settings.ui.brightness.value())
        set_brightness_dimmed(
            window.ui, settings.ui.brightness_dimmed.value(), settings.ui.brightness.value()
        )
    else:
        # User cancelled, reset to original brightness
        change_brightness(deck_id, api.get_brightness(deck_id))

    dimmers[deck_id].reset()

def disable_dim_settings(settings: SettingsDialog, _index: int) -> None:
    disable = dimmer_options.get(settings.ui.dim.currentText()) == 0
    settings.ui.brightness_dimmed.setDisabled(disable)
    settings.ui.label_brightness_dimmed.setDisabled(disable)

def dim_all_displays() -> None:
    for _deck_id, dimmer in dimmers.items():
        dimmer.dim(True)

def start(_exit: bool = False) -> None:
    show_ui = True
    if "-h" in sys.argv or "--help" in sys.argv:
        print(f"Usage: {os.path.basename(sys.argv[0])}")
        print("Flags:")
        print("  -h, --help\tShow this message")
        print("  -n, --no-ui\tRun the program without showing a UI")
        return
    elif "-n" in sys.argv or "--no-ui" in sys.argv:
        show_ui = False

    app = QApplication(sys.argv)

    logo = QIcon(LOGO)
    main_window = MainWindow()
    ui = main_window.ui
    main_window.setWindowIcon(logo)
    tray = QSystemTrayIcon(logo, app)
    tray.activated.connect(main_window.systray_clicked)

    menu = QMenu()
    action_dim = QAction("Dim display (toggle)")
    action_dim.triggered.connect(dim_all_displays)
    action_configure = QAction("Configure...")
    action_configure.triggered.connect(main_window.bring_to_top)
    menu.addAction(action_dim)
    menu.addAction(action_configure)
    menu.addSeparator()
    action_exit = QAction("Exit")
    action_exit.triggered.connect(app.exit)
    menu.addAction(action_exit)

    tray.setContextMenu(menu)

    ui.text.textChanged.connect(partial(queue_text_change, ui))
    ui.command.textChanged.connect(partial(update_button_command, ui))
    ui.keys.textChanged.connect(partial(update_button_keys, ui))
    ui.write.textChanged.connect(partial(update_button_write, ui))
    ui.change_brightness.valueChanged.connect(partial(update_change_brightness, ui))
    ui.switch_page.valueChanged.connect(partial(update_switch_page, ui))
    ui.imageButton.clicked.connect(partial(select_image, main_window))
    ui.removeButton.clicked.connect(partial(remove_image, main_window))
    ui.settingsButton.clicked.connect(partial(show_settings, main_window))

    api.streamdesk_keys.key_pressed.connect(handle_keypress)

    items = api.open_decks().items()
    if len(items) == 0:
        print("Waiting for Stream Deck(s)...")
        while len(items) == 0:
            time.sleep(3)
            items = api.open_decks().items()

    for deck_id, deck in items:
        ui.device_list.addItem(f"{deck['type']} - {deck_id}", userData=deck_id)
        dimmers[deck_id] = Dimmer(
            api.get_display_timeout(deck_id),
            api.get_brightness(deck_id),
            api.get_brightness_dimmed(deck_id),
            partial(change_brightness, deck_id),
        )
        dimmers[deck_id].reset()

    build_device(ui)
    ui.device_list.currentIndexChanged.connect(partial(build_device, ui))

    ui.pages.currentChanged.connect(partial(change_page, ui))

    ui.actionExport.triggered.connect(partial(export_config, main_window))
    ui.actionImport.triggered.connect(partial(import_config, main_window))
    ui.actionExit.triggered.connect(app.exit)

    timer = QTimer()
    timer.timeout.connect(partial(sync, ui))
    timer.start(1000)

    api.render()
    tray.show()

    if show_ui:
        main_window.show()

    if _exit:
        return
    else:
        app.exec_()
        api.close_decks()
        sys.exit()

if __name__ == "__main__":
    start()


#!/usr/bin/env python3

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

def main():

    total_notsee = [10, 20, 30, 40, 50]
    # total_notsee_x = [0, 10, 20, 30, 40, 50]

    plt.rcParams.update({"font.size": 6})

    fig = plt.figure(figsize=(80/25.4, 35/25.4))

    gs = fig.add_gridspec(1, 3, hspace=0.0)
    axs = gs.subplots(sharey="row")

    for d in [0, 1, 2]:
        m = np.load("data/transferlearning_m_mean_dim{}.npy".format(d), allow_pickle=False)
        h = np.load("data/transferlearning_h_std_dim{}.npy".format(d), allow_pickle=False)

        axs[d].set_title("Dimension %d" %(d))
        axs[d].plot(total_notsee, m, c="C%d" %(d))
        axs[d].fill_between(total_notsee, m-h, m+h, alpha=.2, zorder=0, color="C%d" %(d))
        axs[d].set_xlim((10, 50))
        axs[d].set_ylim((55, 95))
        axs[d].set_xticks([10, 20, 30, 40, 50])
        axs[d].set_yticks([60, 70, 80, 90])

    axs[0].set_ylabel("Accuracy")
    axs[1].set_xlabel("% missing")

    fig.tight_layout()
    filename = os.path.splitext(os.path.basename(__file__))[0] + '.pdf'
    fig.savefig(filename)

if __name__ == "__main__":
    main()


'''
Author: Simon Graham
Tissue Image Analytics Lab
Department of Computer Science,
University of Warwick, UK.
'''

import Segmentation_train
import test_classification
import Segmentation_input
import mean_images
import tensorflow as tf
import glob
import os
import sys
import scipy.io as sio
from PIL import Image
import numpy as np
import scipy.misc
import cv2 as cv

FLAGS = tf.app.flags.FLAGS

##############################################################################
def main(argv):
    # Training
  if argv[0] == 'train':

    if not os.path.exists(FLAGS.stats_dir):
      os.mkdir(FLAGS.stats_dir)

    if not os.path.exists(os.path.join(FLAGS.stats_dir,'mean_calc')):
      os.mkdir(os.path.join(FLAGS.stats_dir,'mean_calc'))

    '''
    Below we calculate the mean and variance of all training and validation images. This
    is so that we can use mean subtraction and normalization. If the target size
    is different to the source size, we must first crop the source images so that we can
    subsequently use mean subratction and normalization.

    Images created for the calculation will be written to /stats/mean_calc

    If the images are cropped, the cropped image size is displayed in the folder name
    '''

    if FLAGS.train_image_source_size != FLAGS.train_image_target_size:
      network_stats_file_path = os.path.join(FLAGS.stats_dir,'network_stats.mat')
      if not os.path.isfile(network_stats_file_path):
        if not os.path.exists(os.path.join(FLAGS.stats_dir,'mean_calc','Images_')+str(FLAGS.train_image_target_size)):
          os.mkdir(os.path.join(FLAGS.stats_dir,'mean_calc','Images_')+str(FLAGS.train_image_target_size))
          print('Cropping and writing images for mean and variance calculation...')
          mean_images.crop_and_write()
        list_images = glob.glob(os.path.join(FLAGS.stats_dir,'mean_calc','Images_')+str(FLAGS.train_image_target_size)+'/*'+FLAGS.image_ext)
        print('Calculating mean and variance...')
        mean_image, variance_image = Segmentation_input.calculate_mean_variance_image(list_images)
        sio.savemat(network_stats_file_path,
          {'mean_image': mean_image, 'variance_image': variance_image})

    else:
      network_stats_file_path = os.path.join(FLAGS.stats_dir,'network_stats.mat')
      if not os.path.isfile(network_stats_file_path):
        if not os.path.exists(os.path.join(FLAGS.stats_dir,'mean_calc','Images')):
          os.mkdir(os.path.join(FLAGS.stats_dir,'mean_calc','Images'))
          print('Writing images for mean and variance calculation...')
          mean_images.write()
        list_images = glob.glob(os.path.join(FLAGS.stats_dir,'mean_calc','Images', '*') + FLAGS.image_ext)
        print('Calculating mean and variance...')
        mean_image, variance_image = Segmentation_input.calculate_mean_variance_image(list_images)
        sio.savemat(network_stats_file_path,
          {'mean_image': mean_image, 'variance_image': variance_image})

    if not os.path.exists(FLAGS.checkpoint_dir):
      os.mkdir(FLAGS.checkpoint_dir)

    if not os.path.exists(FLAGS.log_dir):
      os.mkdir(FLAGS.log_dir)

    Segmentation_train.train()

    # Testing
  elif argv[0] == 'test':
    #model_path = Segmentation_train.find_optim_net()
    model_path = FLAGS.checkpoint_dir + '/model.ckpt-172198'
    path_id = os.path.basename(model_path)
    path_id = path_id.split('-')[1]

    print(model_path)

    if not os.path.exists(os.path.join('Results')):
      os.mkdir(os.path.join('Results'))

    result_dir = FLAGS.result_dir
    images_path = FLAGS.test_dir

    images_list = test_classification.get_image_list(images_path)
    filename_list = images_list
    print('Processing test images ...')
    test_classification.testing(model_path, path_id, filename_list)

if __name__ == '__main__':
    main(sys.argv[1:])


from django.conf import settings
from django.conf.urls import include, url
from django.contrib import admin
from django.views.generic import TemplateView

from apps.consumption.views import dcf, complete_dcf
from apps.general import views as general_views
from apps.juliana.views import juliana
from apps.scheduling import views as scheduling_views

urlpatterns = [
    # Root
    url(r'^$', scheduling_views.overview, name='root'),

    # Short urls to 'subsystems'
    url(r'^dcf/(?P<pk>\d+)/$', dcf, name='dcf'),
    url(r'^dcf/(?P<pk>\d+)/check/$', complete_dcf, name='dcf-complete'),
    url(r'^juliana/(?P<pk>\d+)/$', juliana, name='juliana'),

    # Apps
    url(r'^billing/', include('apps.billing.urls')),
    url(r'^consumption/', include('apps.consumption.urls')),
    url(r'^organization/', include('apps.organization.urls')),
    url(r'^profile/', include('apps.profile.urls')),
    url(r'^scheduling/', include('apps.scheduling.urls')),
    url(r'^ical$', scheduling_views.ical),
    url(r'^ical/(?P<ical_id>[^/]+)$', scheduling_views.personal_ical, name='ical'),

    url(r'^api/', include('api.urls')),

    # "Static" general_views
    url(r'^about/$', general_views.about, name='about'),
    url(r'^help/$', general_views.help, name='help'),
    url(r'^login/$', general_views.login, name='login'),
    url(r'^logout/$', general_views.logout, name='logout'),
    url(r'^register/$', general_views.register, name='register'),
    url(r'^change_current_organization/(?P<organization>[-\w]+)/$',
        general_views.change_current_organization, name='change-current-organization'),
    url(r'^change_current_language/$', general_views.change_current_language, name='change-current-language'),

    # Django Admin
    url(r'^admin/doc/', include('django.contrib.admindocs.urls')),
    url(r'^admin/', include(admin.site.urls)),

    # Robots
    url(r'^robots\.txt$', TemplateView.as_view(template_name='robots.txt', content_type='text/plain')),
]

if settings.DEBUG:
    import debug_toolbar
    urlpatterns += [
        url(r'^__debug__/', include(debug_toolbar.urls))
    ]


from pyspark import SparkContext, SparkConf
from pyspark.ml.classification import LogisticRegression
from pyspark.ml.regression import LinearRegression
from pyspark.sql import SQLContext, Row
from pyspark.sql.types import IntegerType
from pyspark.sql.functions import UserDefinedFunction
from pyspark.ml.linalg import Vectors

import os
import pyspark_csv as pycsv

os.environ["SPARK_LOCAL_IP"] = "127.0.0.1" # set local IP

DATADIR = "./Desktop/BDP/predict3/AQI/data"
 # data directory

def mySparkContext():
    """
    Sets the Spark Context
    """
    conf = (SparkConf()
            .setMaster("local")
            .setAppName("predictAQI")
            .set("spark.executor.memory", "4g"))
    sc = SparkContext(conf = conf)
    return sc

sc = mySparkContext()
sqlCtx = SQLContext(sc)
sc.addPyFile("Desktop/BDP/predict3/AQI/pyspark_csv.py")

def loadDF(filename):
    """
    Load and parse filename as pyspark.sql.DataFrame
    using pyspark_csv.py
    """
    path = os.path.join(DATADIR, filename)
    plain = sc.textFile(path)
    df = pycsv.csvToDataFrame(sqlCtx, plain, sep=',')
    return df

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

if __name__ == "__main__":

    train = loadDF("train.csv")
    test = loadDF("test.csv")

    testNumber = test.select('Number').rdd.map(lambda x: x.Number)

    train = train.select('AQI', 'Temp Arithmetic Mean', 'Wind SpeedArithmetic Mean',
    'Wind Direction Arithmetic Mean', 'Barometric pressure Arithmetic Mean', 'CO Arithmetic Mean',
    'SO2 Arithmetic Mean', 'NO2 Arithmetic Mean', 'Ozone Arithmetic Mean', 'PM25 Mean')

    test = test.select('Temp Arithmetic Mean', 'Wind SpeedArithmetic Mean',
    'Wind Direction Arithmetic Mean', 'Barometric pressure Arithmetic Mean', 'CO Arithmetic Mean',
    'SO2 Arithmetic Mean', 'NO2 Arithmetic Mean', 'Ozone Arithmetic Mean', 'PM25 Mean')

    # format train for Linear Regression as (label, features)
    ntrain = train.rdd.map(lambda x: Row(label = float(x[0]) \
         ,features = Vectors.dense(x[1:]))).toDF().cache() # Linear Regression is iterative, need caching
    ntest = test.rdd.map(lambda x: Row(features = Vectors.dense(x[0:]))).toDF()

    lr = LinearRegression(maxIter = 100, regParam = 0.4, elasticNetParam=0.7)
    model = lr.fit(ntrain)

    print("Coefficients: " + str(model.coefficients))
    print("Intercept: " + str(model.intercept))

    pred = model.transform(ntest).select('prediction').rdd.map(lambda x: x.prediction)

    # configure the submission format as follows
    submit = sqlCtx.createDataFrame(testNumber.zip(pred), ["Number", "AQI"])
    """
    NOTE: rdd1.zip(rdd2) works provided that both RDDs have the same partitioner and the same number
    of elements per partition, otherwise should either repartition or can do:

    """
    os.chdir(DATADIR)
    # file is small so can save pandas.DataFrame as csv
    submit.toPandas().to_csv("prediction.csv", index = False)
    # if not, should saveAsTextFile:
    # submit.rdd.saveAsTextFile("/BDP/data/prediction")
    sc.stop()


import cv2 as cv
import numpy as np
import os
# print(os.getcwd())
# Load an image
originalImage = cv.imread(os.getcwd()+'\\images\\10_dr.JPG', 1)
# Resize image
image = cv.resize(originalImage, (701, 468))
# Changing colorspace from BGR to Grayscale
image = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
# Applying median blur
image = cv.medianBlur(image, 3)
# Display the image
cv.namedWindow('image', cv.WINDOW_NORMAL)
cv.imshow('image', image)
cv.waitKey(2000)
cv.destroyAllWindows()

# create a CLAHE object (Arguments are optional).
clahe = cv.createCLAHE(clipLimit=2.0, tileGridSize=(8, 8))
image = clahe.apply(image)
# image = cv.GaussianBlur(image, (11, 11), 0)
# Thresholding to extract bright regions
image = cv.threshold(image, 170, 255, cv.THRESH_BINARY)[1]
# Display the image
cv.namedWindow('image', cv.WINDOW_NORMAL)
cv.imshow('image', image)
cv.waitKey(10000)
cv.destroyAllWindows()


import unittest, json, os, shutil
import pandas as pd
from igf_data.utils.fileutils import get_temp_dir, remove_dir
from igf_data.igfdb.igfTables import Base
from igf_data.igfdb.baseadaptor import BaseAdaptor
from igf_data.igfdb.projectadaptor import ProjectAdaptor
from igf_data.igfdb.sampleadaptor import SampleAdaptor
from igf_data.igfdb.platformadaptor import PlatformAdaptor
from igf_data.igfdb.seqrunadaptor import SeqrunAdaptor
from igf_data.igfdb.experimentadaptor import ExperimentAdaptor
from igf_data.igfdb.runadaptor import RunAdaptor
from igf_portal.metadata_utils import get_db_data_and_create_json_dump
from igf_portal.metadata_utils import _create_json_for_metadata_upload
from igf_portal.metadata_utils import _get_metadata_csv_files_from_metadata_dir

class Metadata_dump_test(unittest.TestCase):
  def setUp(self):
    self.dbconfig = 'data/dbconfig.json'
    dbparam = None
    with open(self.dbconfig, 'r') as json_data:
      dbparam = json.load(json_data)
    base = BaseAdaptor(**dbparam)
    self.engine = base.engine
    self.dbname = dbparam['dbname']
    if os.path.exists(self.dbname):
      os.remove(self.dbname)
    Base.metadata.create_all(self.engine)
    self.session_class = base.session_class
    base.start_session()
    platform_data = [{
      "platform_igf_id" : "M00001" ,
      "model_name" : "MISEQ" ,
      "vendor_name" : "ILLUMINA" ,
      "software_name" : "RTA" ,
      "software_version" : "RTA1.18.54"}]
    flowcell_rule_data = [{
      "platform_igf_id": "M00001",
      "flowcell_type": "MISEQ",
      "index_1": "NO_CHANGE",
      "index_2": "NO_CHANGE"}]
    pl = PlatformAdaptor(**{'session':base.session})
    pl.store_platform_data(data=platform_data)
    pl.store_flowcell_barcode_rule(data=flowcell_rule_data)
    project_data = [{
      'project_igf_id': 'IGFP0001_test_22-8-2017_rna',
      'project_name': 'test_22-8-2017_rna',
      'description': 'Its project 1',
      'project_deadline': 'Before August 2017',
      'comments': 'Some samples are treated with drug X'},{
      'project_igf_id': 'IGFP0001_test_22-8-2017_rna2'}]
    pa = ProjectAdaptor(**{'session':base.session})
    pa.store_project_and_attribute_data(data=project_data)
    sample_data = [{
      'sample_igf_id':'IGF00001',
      'project_igf_id':'IGFP0001_test_22-8-2017_rna',}]
    sa = SampleAdaptor(**{'session':base.session})
    sa.store_sample_and_attribute_data(data=sample_data)
    seqrun_data = [{
      'seqrun_igf_id': '171003_M00001_0089_000000000-TEST',
      'flowcell_id': '000000000-D0YLK',
      'platform_igf_id': 'M00001',
      'flowcell':'MISEQ'}]
    sra = SeqrunAdaptor(**{'session':base.session})
    sra.store_seqrun_and_attribute_data(data=seqrun_data)
    experiment_data = [{
      'experiment_igf_id': 'IGF00001_MISEQ',
      'project_igf_id': 'IGFP0001_test_22-8-2017_rna',
      'library_name': 'IGF00001',
      'sample_igf_id': 'IGF00001'}]
    ea = ExperimentAdaptor(**{'session':base.session})
    ea.store_project_and_attribute_data(data=experiment_data)
    run_data = [{
      'run_igf_id': 'IGF00001_MISEQ_000000000-D0YLK_1',
      'experiment_igf_id': 'IGF00001_MISEQ',
      'seqrun_igf_id': '171003_M00001_0089_000000000-TEST',
      'lane_number': '1',
      'R1_READ_COUNT': 1000}]
    ra = RunAdaptor(**{'session':base.session})
    ra.store_run_and_attribute_data(data=run_data)
    base.close_session()
    self.temp_dir = get_temp_dir()

  def tearDown(self):
    Base.metadata.drop_all(self.engine)
    if os.path.exists(self.dbname):
      os.remove(self.dbname)
    if os.path.exists(self.temp_dir):
      remove_dir(self.temp_dir)

  def test_get_db_data_and_create_json_dump(self):
    temp_dir = get_temp_dir()
    json_path = os.path.join(temp_dir, 'metadata_dump.json')
    get_db_data_and_create_json_dump(
      dbconfig_json=self.dbconfig,
      output_json_path=json_path)
    self.assertTrue(os.path.exists(json_path))
    with open(json_path, 'r') as fp:
      json_data = json.load(fp)
    self.assertTrue(isinstance(json_data, dict))
    self.assertTrue('project' in json_data.keys())
    self.assertTrue('sample' in json_data.keys())
    sample_data = json_data.get('sample')
    self.assertEqual(len(sample_data), 1)
    self.assertTrue('sample_igf_id' in sample_data[0].keys())
    self.assertEqual(sample_data[0].get('sample_igf_id'), 'IGF00001')
    project_data = json_data.get('project')
    self.assertEqual(len(project_data), 2)
    project_record = [
      entry.get('project_igf_id')
        for entry in project_data
          if entry.get('project_id')==sample_data[0].get('project_id')][0]
    self.assertEqual(project_record, 'IGFP0001_test_22-8-2017_rna')

class Metadata_load_test(unittest.TestCase):
  def setUp(self):
    self.temp_dir = get_temp_dir()
    formatted_dir = os.path.join(self.temp_dir, 'metadata', 'formatted_data')
    raw_dir = os.path.join(self.temp_dir, 'metadata', 'raw_data')
    os.makedirs(formatted_dir, exist_ok=True)
    os.makedirs(raw_dir, exist_ok=True)
    self.metadata_list = [
      'formatted_data/project1_reformatted.csv',
      'raw_data/project1.csv',
      'raw_data/project1_SampleSheet.csv',
      'formatted_data/project1_SampleSheet_reformatted.csv',
      'formatted_data/project2_reformatted.csv',
      'raw_data/project2.csv',
      'raw_data/project2_SampleSheet.csv',
      'formatted_data/project2_SampleSheet_reformatted.csv'
      ]
    metadata = pd.DataFrame([{'project_igf_id':'project', 'sample_igf_id':'sample1'}])
    for entry in self.metadata_list:
      path = os.path.join(self.temp_dir, 'metadata', entry)
      metadata.to_csv(path, index=False)

  def tearDown(self):
    remove_dir(self.temp_dir)

  def test_get_metadata_csv_files_from_metadata_dir(self):
    final_metadata_dict = \
      _get_metadata_csv_files_from_metadata_dir(
        metadata_dir=self.temp_dir)
    self.assertEqual(len(final_metadata_dict.keys()), 2)
    self.assertTrue('project1' in final_metadata_dict)
    self.assertTrue(isinstance(final_metadata_dict.get('project1'), dict))
    self.assertTrue('raw_csv' in final_metadata_dict.get('project1'))
    self.assertTrue('formatted_csv' in final_metadata_dict.get('project1'))
    self.assertEqual(
      final_metadata_dict.get('project1').get('raw_csv'),
      os.path.join(self.temp_dir, 'metadata', 'raw_data/project1.csv'))
    self.assertEqual(
      final_metadata_dict.get('project2').get('formatted_csv'),
      os.path.join(self.temp_dir, 'metadata', 'formatted_data/project2_reformatted.csv'))

  def test_create_json_for_metadata_upload(self):
    final_metadata_dict = \
      _get_metadata_csv_files_from_metadata_dir(
        metadata_dir=self.temp_dir)
    project_list = list(final_metadata_dict.keys())
    temp_json = \
      _create_json_for_metadata_upload(
        project_list=project_list,
        metadata_dict=final_metadata_dict)
    self.assertTrue(os.path.exists(temp_json))
    with open(temp_json, 'r') as fp:
      json_data = json.load(fp)
    self.assertEqual(len(json_data), 2)
    self.assertTrue('metadata_tag' in json_data[0])
    self.assertTrue('raw_csv_data' in json_data[0])
    self.assertTrue('formatted_csv_data' in json_data[0])
    self.assertTrue(isinstance(json_data[0].get('formatted_csv_data'), list))
    self.assertEqual(len(json_data[0].get('formatted_csv_data')), 1)
    self.assertTrue('project_igf_id' in json_data[0].get('formatted_csv_data')[0])
    self.assertEqual(json_data[0].get('formatted_csv_data')[0].get('project_igf_id'), 'project')
    self.assertTrue('sample_igf_id' in json_data[0].get('formatted_csv_data')[0])
    self.assertEqual(json_data[0].get('formatted_csv_data')[0].get('sample_igf_id'), 'sample1')

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


from basetypes import *
import os,logging,datetime,json
from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app
from google.appengine.ext.webapp import template

def datefromiso(isodate):
    y=int(isodate[:4])
    m=int(isodate[5:7])
    d=int(isodate[8:10])
    return datetime.date(y,m,d)

class Add(webapp.RequestHandler):
    def get(self):
        template_values = {
            }
        path = os.path.join(os.path.dirname(__file__), './template/upload.html')
        self.response.out.write(template.render(path,template_values))

    def post(self):
        #get all the infomation
        logging.info(self.request.arguments())
        jsondata = self.request.get('jsondata')
        logging.info(jsondata)
        data = json.loads(jsondata)
        #generate and put game object
        record_temp = Record()
        record_temp.Name = data['name'];
        record_temp.Date = datefromiso(data['date'])
        item_list = []
        count = 1
        for item in data['items']:
            item_temp = Item()
            item_temp.Name = item['name']
            item_temp.Number = int(item['num'])
            item_temp.Price = float(item['unitprice'])
            item_temp.Order = count
            count += 1
            key = item_temp.put()
            item_list.append(str(key))
        record_temp.Items = item_list
        record_temp.put()
        self.response.out.write('{"error":"no"}')
        # self.redirect('/main')

def main():
    application = webapp.WSGIApplication([
        (r'.*', Add)
        ],debug=True)
    run_wsgi_app(application)

if __name__ == "__main__":
    main()


from sklearn.cluster import KMeans
from sklearn.ensemble import AdaBoostClassifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import accuracy_score
from sklearn import svm
from sklearn.neighbors import KNeighborsClassifier
from sklearn.metrics import confusion_matrix
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.preprocessing import MinMaxScaler
from sklearn.decomposition import PCA
import matplotlib.pyplot as plt; plt.rcdefaults()
from ttictoc import TicToc
import pre_hot as pre
import numpy as np
t = TicToc()
import  os
from sklearn.externals import joblib
import pandas as pd

TrainTimeList=[]

def fit_model(X,Y,model,filename):
    if (os.path.exists(filename)):
        resmodel=joblib.load(filename)
        #print("ffffffff")
    else:
        t.tic()
        resmodel=model.fit(X,Y)
        t.toc()
        TrainTimeList.append(t.elapsed)
        print("total train =",t.elapsed)
        joblib.dump(resmodel,filename)

    return resmodel

#classsssifier
from sklearn.linear_model import LogisticRegression
def Class_model(X_T ,Y_T,X_Test,Y_test,rootFolder=''):
    TestTimeList=[]
    accracy_bar=[]
    print('-------Logistic Regression-------')
    logistic = LogisticRegression(C=10000,multi_class='auto',solver='liblinear')
    #logistic.fit(X_T,Y_T)
    logistic = fit_model(X_T,Y_T,logistic,rootFolder+'LogisticRegression')
    y = logistic.predict(X_Test)
    acc = accuracy_score(Y_test, y) * 100
    print("Accuracy Logistic Regression : ", acc)
    accracy_bar.append(acc)
    print("Confusion Matrix for Logistic Regression : ")
    print(confusion_matrix(Y_test, y))

    ''''
    print("      ----------- KNN ------------")
    model = KNeighborsClassifier(n_neighbors=20)
    t.tic()
    #model.fit(X_T,Y_T)
    model = fit_model(X_T,Y_T,model,rootFolder+'Knn')
    t.toc()
    TrainTimeList.append(t.elapsed)
    print("total train =", t.elapsed)
    t.tic()
    y=model.predict(X_Test)
    t.toc()

    TestTimeList.append(t.elapsed)
    print("total test =", t.elapsed)

    acc = accuracy_score(Y_test, y) * 100
    print("Accuracy Knn : ", acc)
    accracy_bar.append(acc)
    print("Confusion Matrix for Knn : ")
    print(confusion_matrix(Y_test, y))

    '''
    print("      ------- Tree----------")
    tree = DecisionTreeClassifier(random_state=100, max_depth=15, min_samples_leaf=4)
    R_tree= fit_model(X_T, Y_T, tree, rootFolder+"tree_model_15")
    t.tic()
    y_pred = R_tree.predict(X_Test)
    t.toc()
    TestTimeList.append(t.elapsed)
    print("total test =", t.elapsed )
    acc = accuracy_score(Y_test, y_pred) * 100
    print("Accuracy tree : ", acc)
    accracy_bar.append(acc)
    print("Confusion Matrix for tree : ")
    print(confusion_matrix(Y_test, y_pred))

    print("    ---------- SVM ------------")
    clf = svm.SVC(kernel='linear',gamma='auto')
    R=fit_model(X_T,Y_T,clf,rootFolder+"svm_model_linear ")

    t.tic()
    y_p=R.predict(X_Test)
    t.toc()
    TestTimeList.append(t.elapsed)
    print("total test =", t.elapsed)
    acc=accuracy_score(Y_test, y_p) * 100
    print("Accuracy : ", acc)
    accracy_bar.append(acc)

    print("Confusion Matrix for Svm: ")
    print(confusion_matrix(Y_test, y_p))

    print("      ----- addabos tree ---------")

    bdt = AdaBoostClassifier(DecisionTreeClassifier(max_depth=15),
                             algorithm="SAMME.R",
                             n_estimators=50)
    Res_bdt = fit_model(X_T, Y_T, bdt, rootFolder+"addbos_tree_model_15")

    t.tic()
    y_prediction = Res_bdt.predict(X_Test)
    t.toc()
    TestTimeList.append(t.elapsed)
    print("total test =",t.elapsed)

    acc=accuracy_score(Y_test, y_prediction) * 100
    print("Accuracy addapost tree : ", acc)
    accracy_bar.append(acc)

 #   print("Train=",TrainTimeList)
    #plot_time(TrainTimeList)
#    print("Test=",TestTimeList)

    #plot_time(TestTimeList ,'Test')
    #plot_time(accracy_bar,'Accuracy')

def ModelWithPCA(X_Train ,Y_T,X_Test,Y_test,n_components,rootFolder=''):
    print("    ------------ PCA ----------------")

    train_pca,test_pca=pca(X_Train,X_Test,n_components)

    print('After Applying PCA With n_components = ',n_components)

    print('The data feature was',X_Train.shape,'has reduced to be',train_pca.shape)
    test_Time_List=[]
    accuracy=[]
    print(" ******** SVM _PCA :")
    svm_pca = svm.SVC(decision_function_shape='ovr', gamma='auto')
    print(train_pca.shape)
    svm_result = fit_model(train_pca, Y_T, svm_pca, rootFolder+ "svm_pca_"+str(n_components))
    #clf.fit(train_pca,Y_Train)
    t.tic()
    y_p = svm_result.predict(test_pca)
    t.toc()
    test_Time_List.append(t.elapsed)
    acc=accuracy_score(Y_test, y_p) * 100
    accuracy.append(acc)
    print("PCA--Accuracy svm : ",acc )
    print("confusion_matrix :")
    print(confusion_matrix(Y_test, y_p))

    print(" ******** Tree _PCA :")
    tree_pca=DecisionTreeClassifier()#criterion = "entropy", min_samples_leaf=5)
    tree_result = fit_model(train_pca, Y_T, tree_pca, rootFolder+"tree_pca_"+str(n_components))
    t.tic()
    y_p = tree_result.predict(test_pca)
    t.toc()
    test_Time_List.append(t.elapsed)
    acc=accuracy_score(Y_test, y_p) * 100
    accuracy.append(acc)
    print("PCA--Accuracy tree : ", acc)
    print("confusion_matrix :")
    print(confusion_matrix(Y_test, y_p))

    print(" ******** KNN _PCA :")
    knn_pca= KNeighborsClassifier(n_neighbors=1)
    knn_result = fit_model(train_pca, Y_T, knn_pca,rootFolder+ "knnpca_"+str(n_components))
    t.tic()
    y_p = knn_result.predict(test_pca)
    t.toc()
    test_Time_List.append(t.elapsed)
    acc=accuracy_score(Y_test, y_p) * 100
    accuracy.append(acc)
    print("PCA--Accuracy knn : ", acc)
    print("confusion_matrix :")
    print(confusion_matrix(Y_test, y_p))

    print(" ******** AdaBoost _PCA :")
    bdt_pca= AdaBoostClassifier(DecisionTreeClassifier(max_depth=15),
                             algorithm="SAMME.R",
                             n_estimators=50)
    bdt_result = fit_model(train_pca, Y_T, bdt_pca,rootFolder+ "bdt_pca_"+str(n_components))
    t.tic()
    y_p = bdt_result.predict(test_pca)
    t.toc()
    test_Time_List.append(t.elapsed)
    acc=accuracy_score(Y_test, y_p) * 100
    accuracy.append(acc)
    print("PCA--Accuracy tree-adabost : ", acc)
    print("confusion_matrix :")
    print(confusion_matrix(Y_test, y_p))

    #plot_time(TrainTimeList,"Train")
    plot_time(test_Time_List,"Test")
    plot_time(accuracy,"Accuracy")

def plot_time(draw_list,str):

    objects = ('Svm', 'Tree', 'KNN', 'Adapost_tree')
    y_pos = np.arange(len(objects))
    performance = draw_list
    plt.bar(y_pos, performance, align='center', alpha=0.5)
    plt.xticks(y_pos, objects)
    plt.ylabel(str+'in second')
    plt.title('Models')
    plt.show()

def pca(train,test,n_components):
    scaler = StandardScaler()
    #scaler = MinMaxScaler()
    train = scaler.fit_transform(train)
    test=scaler.transform(test)
    pca = PCA(n_components=n_components)
    principalComponents = pca.fit_transform(train)
    principalComponents_test=pca.transform(test)
    #print("pca",pca.explained_variance_ratio_)
    print("train",principalComponents.shape)
    print("test",principalComponents_test.shape)
    return  principalComponents,principalComponents_test

def Run(rootFolder='',train_val_split=True,pca_n_components=0.98):
    print("--------------------------------------------------")
    print("------------------ Classification Model -------------------")
    datasetpath = 'classification_train_data.csv'
    datasetscaler = 'datasetscaler'
    X_train, y_train = pre.ReadDataset('tmdb_5000_movies_classification.csv', 'tmdb_5000_credits.csv', 'rate')

    if train_val_split:
        X_train, X_test, y_train, y_test = train_test_split(X_train, y_train, test_size=0.20)
    else:
        X_test, y_test = pre.ReadDataset('tmdb_5000_movies_testing_classification.xlsx',
                                         'tmdb_5000_credits_test.csv', 'rate')

    if (os.path.exists(rootFolder+datasetpath)):
        X_train = pd.read_csv(rootFolder+datasetpath)
        X_train = X_train.drop(labels=[X_train.columns[0]],axis=1)
        scaler = joblib.load(rootFolder+datasetscaler)
    else:
        X_train.index = range(len(X_train))
        X_train, scaler = pre.prefull(X_train)
        X_train.to_csv(rootFolder+datasetpath)

        joblib.dump(scaler,rootFolder+datasetscaler)

    #print(scaler)

    y_train = pre.class_label(y_train)

    #X_test, y_test = pre.ReadDataset('samples_tmdb_5000_movies_testing_classification.xlsx','samples_tmdb_5000_credits_test.csv','rate')
    y_test = pre.class_label(y_test)

    X_test.index = range(len(X_test))
    X_test=pre.pre_test(X_test,X_train,scaler)

    #X_train, X_test, y_train, y_test = train_test_split(X, Y, test_size=0.20,shuffle=True)
    print ("train after_pre=",X_train.shape)
    print("test after pre=",X_test.shape)

    Class_model(X_train, y_train,X_test, y_test ,rootFolder)
    ModelWithPCA(X_train, y_train, X_test, y_test,pca_n_components,rootFolder)


import matplotlib.pyplot as plt
import numpy as np
from matplotlib.collections import LineCollection
def plot_one_trajectory(traj):
    """ plots one trajectory which is a dictionary"""
    plt.plot(traj['lon'],traj['lat'])

def plot_one_trajectory_color(traj):
    """ plots one trajectory with colored dots
    SAD it doesn't work :((( """
    cmap = plt.cm.coolwarm(np.linspace(-10.,10.,50))
    fig, ax = plt.subplots()
    grid = np.array([np.array(traj['lon']),np.array(traj['lat'])]).T.reshape(-1,1,2)
    lc = LineCollection(grid, cmap="coolwarm")
    lc.set_array(np.array(traj['temp']))
    ax.add_collection(lc)
    ax.autoscale_view()
    plt.show()

def plot_temp_contour(d):
    """ plot temp contour plot"""
    for j in range(len(d)):
        lats = d[j]['lat']
        lon = np.mean(np.array(d[j]['lon']))
        temp = d[j]['temp']

        plt.plot(lats,temp)

def plot_temp_contour(d):
    """ plot temp contour plot"""
    meanlat = []
    meantemp = []
    meanlon = []
    for j in range(len(d)):
        lats = d[j]['lat']
        lon = np.mean(np.array(d[j]['lon']))
        temp = d[j]['temp']

        meanlat.append(np.mean(np.array(lats)))
        meantemp.append(np.mean(np.array(temp)))
        meanlon.append(lon)
    plt.contourf(np.array(meanlon),np.array(meanlat),np.array(meantemp))