import warnings

from flask import request, json, jsonify, Response
from flask.views import MethodView
from sqlalchemy.orm import load_only
from sqlalchemy.orm.collections import InstrumentedList

from flask_restalchemy.serialization import ModelSerializer
from .querybuilder import create_collection_query

class BaseResource(MethodView):
    """The Base class for resources

    :param dict|list request_decorators: a list of decorators
    """

    def __init__(self, request_decorators=None):
        if not request_decorators:
            return
        for verb, decorator_list in request_decorators.items():
            for decorator in decorator_list:
                if verb == "ALL":
                    self.dispatch_request = decorator(self.dispatch_request)
                else:
                    verb_method_name = verb.lower()
                    decorated_method = decorator(getattr(self, verb_method_name))
                    setattr(self, verb_method_name, decorated_method)

    def dispatch_request(self, *args, **kwargs):
        view_response = super().dispatch_request(*args, **kwargs)
        data, code, header = unpack(view_response)
        if isinstance(data, Response):
            return data
        elif isinstance(data, str):
            return data, code, header
        else:
            return jsonify(data), code, header

class ViewFunctionResource(BaseResource):

    """
    Class created to provide url rules for free functions.

    :param callable func: function to be called

    :param dict request_decorators: dictionary of decorators for the function
    """

    def __init__(self, func, request_decorators=None):
        super().__init__(request_decorators)
        self.func = func

    def get(self, *args, **kwargs):
        return self.func(*args, **kwargs)

    def post(self, *args, **kwargs):
        return self.func(*args, **kwargs)

    def put(self, *args, **kwargs):
        return self.func(*args, **kwargs)

    def delete(self, *args, **kwargs):
        return self.func(*args, **kwargs)

class BaseModelResource(BaseResource):
    """The Base class for ORM resources

    :param class declarative_model: the SQLAlchemy declarative class.

    :param ModelSerializer serializer: schema for serialization. If `None`, a default serializer will be created.

    :param callable session_getter: a callable that returns the DB session. A callable is used since a reference to
        DB session may not be available on the resource initialization.

    :param callable query_modifier: function that returns a query and expects a `model` as parameter that
        should be used to create the query and expects a `parent_query` to be incremented with the callback query
        function. The method signature should look like this: query_callback(parent_query, resource_model)

    :param dict|list request_decorators: a list of decorators
    """

    def __init__(
        self,
        declarative_model,
        serializer,
        session_getter,
        query_modifier=None,
        request_decorators=None,
    ):
        """Constructor
        """

        super().__init__(request_decorators)
        self._resource_model = declarative_model
        self._serializer = serializer
        self._serializer.strict = True
        assert isinstance(
            self._serializer, ModelSerializer
        ), f"Invalid serializer instance: {serializer}"
        self._session_getter = session_getter
        self._query_modifier = query_modifier

    def _save_model(self, model):
        session = self._session_getter()
        session.add(model)
        session.commit()

    def _save_serialized(self, serialized_data, existing_model=None):
        model = self._serializer.load(
            serialized_data, existing_model, self._session_getter()
        )
        self._save_model(model)
        return self._serializer.dump(model)

    @property
    def _db_session(self):
        return self._session_getter()

class ModelResource(BaseModelResource):
    def get(self, id=None):
        if id is not None:
            model = self._resource_model.query.get(id)
            if model is None:
                return NOT_FOUND_ERROR, 404
            return self._serializer.dump(model)
        else:
            query = self._resource_model.query
            if self._query_modifier:
                query = self._query_modifier(query, self._resource_model)
            query = create_collection_query(
                query, self._resource_model, self._serializer, request.args
            )

            return create_response_from_query(query, self._serializer)

    def post(self):
        serialized = load_request_json()
        saved = self._save_serialized(serialized)
        return saved, 201

    def put(self, id):
        model = self._resource_model.query.get(id)
        if model is None:
            return NOT_FOUND_ERROR, 404

        serialized = self._serializer.dump(model)
        request_data = load_request_json()
        serialized.update(request_data)
        result = self._save_serialized(serialized, existing_model=model)
        return result

    def delete(self, id):
        model = self._resource_model.query.get(id)
        if model is None:
            return NOT_FOUND_ERROR, 404
        session = self._db_session
        session.delete(model)
        session.flush()
        session.commit()
        return "", 204

class ToManyRelationResource(BaseModelResource):
    """Resource class that receives an SQLAlchemy relationship define the API to provide
    LIST and CREATE over data of the child model associated with a specific
    element of the parent model.

    :param relationship relation_property: the SQLAlchemy relationship.

    :param ModelSerializer serializer: schema for serialization. If `None`, a default serializer will be created.

    :param callable session_getter: a callable that returns the DB session. A callable is used since a reference to
        DB session may not be available on the resource initialization.

    :param callable query_modifier: function that returns a query and expects a `model` as parameter that
        should be used to create the query and expects a `parent_query` to be incremented with the callback query
        function. The method signature should look like this: query_callback(parent_query, resource_model)

    :param dict|list request_decorators: a list of decorators
    """

    def __init__(
        self,
        relation_property,
        serializer,
        session_getter,
        query_modifier=None,
        request_decorators=None,
    ):
        """Constructor
        """
        resource_model = relation_property.prop.mapper.class_
        super().__init__(
            resource_model,
            serializer,
            session_getter,
            query_modifier=query_modifier,
            request_decorators=request_decorators,
        )
        self._relation_property = relation_property
        self._related_model = relation_property.class_

    def get(self, relation_id, id=None):
        if id:
            requested_obj = self._query_related_obj(relation_id, id)
            if not requested_obj:
                return NOT_FOUND_ERROR, 404
            return self._serializer.dump(requested_obj), 200
        else:
            session = self._db_session
            # using options(load_only('id')) avoid unintended subquerying, as all we want is
            # check if the element exists
            related_obj = (
                session.query(self._related_model)
                .options(load_only("id"))
                .get(relation_id)
            )
            if related_obj is None:
                return NOT_FOUND_ERROR, 404

            # TODO: Is there a more efficient way than using getattr?
            relation_list_or_query = getattr(related_obj, self._relation_property.key)
            if isinstance(relation_list_or_query, InstrumentedList) or not hasattr(
                relation_list_or_query, "paginate"
            ):
                warnings.warn(
                    "Warnning: relationship does not support pagination nor filter."
                    'Use flask-sqlalchemy relationship with lazy="dynamic".'
                )
                collection = [
                    self._serializer.dump(item) for item in relation_list_or_query
                ]
            else:
                query = relation_list_or_query
                if self._query_modifier:
                    query = self._query_modifier(query, self._resource_model)
                query = create_collection_query(
                    query, self._resource_model, self._serializer, request.args
                )
                collection = create_response_from_query(query, self._serializer)
            return collection

    def post(self, relation_id):
        session = self._db_session
        related_obj = session.query(self._related_model).get(relation_id)
        if not related_obj:
            return NOT_FOUND_ERROR, 404
        collection = getattr(related_obj, self._relation_property.key)
        data_dict = load_request_json()
        resource_id = data_dict.get("id", None)

        if resource_id is not None:
            model = session.query(self._resource_model).get(resource_id)
            if model is None:
                return NOT_FOUND_ERROR, 404
            status_code = 200
        else:
            model = self._serializer.load(data_dict, session=session)
            status_code = 201
            session.add(model)
        collection.append(model)
        self._save_model(model)
        saved = self._serializer.dump(model)
        return saved, status_code

    def put(self, relation_id, id):
        request_data = load_request_json()
        requested_obj = self._query_related_obj(relation_id, id)
        if not requested_obj:
            return NOT_FOUND_ERROR, 404
        serialized = self._serializer.dump(requested_obj)
        serialized.update(request_data)
        saved = self._save_serialized(serialized, requested_obj)
        return saved

    def delete(self, relation_id, id):
        session = self._db_session
        requested_obj = self._query_related_obj(relation_id, id)
        if not requested_obj:
            return NOT_FOUND_ERROR, 404
        related_obj = session.query(self._related_model).get(relation_id)
        collection = getattr(related_obj, self._relation_property.key)
        collection.remove(requested_obj)
        session.delete(requested_obj)
        session.commit()
        return "", 204

    def _query_related_obj(self, relation_id, id):
        """
        Query resource model by ID but also add the relationship as a query constrain.

        :param relation_id: id of the related model
        :param id: id of the model being required
        :return: model with 'id' that has a related model with 'related_id'
        """

        # This checks if there is a parent with the related child on its relation property
        related = (
            self._db_session.query(self._related_model)
            .options(load_only("id"))
            .filter(
                self._related_model.id == relation_id,
                self._relation_property.any(id=id),
            )
            .one_or_none()
        )

        if related is None:
            return None

        return self._db_session.query(self._resource_model).get(id)

class CollectionPropertyResource(ToManyRelationResource):
    def __init__(
        self,
        declarative_model,
        related_model,
        property_name,
        serializer,
        session_getter,
        query_modifier=None,
        request_decorators=None,
    ):
        super(ToManyRelationResource, self).__init__(
            declarative_model,
            serializer,
            session_getter,
            query_modifier=query_modifier,
            request_decorators=request_decorators,
        )
        self._related_model = related_model
        self._property_name = property_name

    def get(self, relation_id, id=None):
        session = self._db_session
        related_obj = session.query(self._related_model).get(relation_id)
        if related_obj is None:
            return NOT_FOUND_ERROR, 404
        relation_list_or_query = getattr(related_obj, self._property_name)
        if isinstance(relation_list_or_query, InstrumentedList) or not hasattr(
            relation_list_or_query, "paginate"
        ):
            warnings.warn(
                "Warnning: property "
                + self._property_name
                + " does not support pagination nor filter."
                " Use flask-sqlalchemy and make your property return a query object"
            )
            collection = [
                self._serializer.dump(item) for item in relation_list_or_query
            ]
        else:
            query = relation_list_or_query
            if self._query_modifier:
                query = self._query_modifier(query, self._related_model)
            query = create_collection_query(
                query, self._resource_model, self._serializer, request.args
            )
            collection = create_response_from_query(query, self._serializer)
        return collection

    def post(self, relation_id):
        return "POST not allowed for property resources", 405

def load_request_json():
    """
    Returns request data as dict.

    :rtype: dict
    """
    if request.data:
        return json.loads(request.data.decode("utf-8"))
    else:
        return request.form.to_dict()

def unpack(value):
    """
    Return a three tuple of data, code, and headers

    :param value:
    :return:
    """
    if not isinstance(value, tuple):
        return value, 200, {}

    try:
        data, code, headers = value
        return data, code, headers
    except ValueError:
        pass

    try:
        data, code = value
        return data, code, {}
    except ValueError:
        pass

    return value, 200, {}

def create_response_from_query(query, serializer):
    if "page" in request.args:
        data = query.paginate()
        return {
            "page": data.page,
            "per_page": data.per_page,
            "count": data.total,
            "results": [serializer.dump(item) for item in data.items],
        }
    else:
        data = query.all()
        return [serializer.dump(item) for item in data]

NOT_FOUND_ERROR = "Resource not found in the database!"


from flask import Flask, render_template, request
from recommend import recommend

app = Flask(__name__)

@app.route('/')
def index():
    return render_template('login.html')

@app.route('/search/')
def search():
    query = request.args.get('query')
    dic = recommend(query)

    return render_template('search.html', DATA=dic)

if __name__ == "__main__":
    app.run(debug=True)


"""
Flux calibration
"""
import numpy as np
import matplotlib.pyplot as plt

def check_GD153():
    import mywfc3.flux

    os.chdir('/Users/brammer/WFC3/Calibration/Cycle20/13092_Flux/Reduce')

    asn = threedhst.utils.ASNFile('Vy22-blue-F098M_asn.fits')

    root=''
    images = {'F098M':'ic461aghq_flt.fits.gz', 'F105W':'ic461agiq_flt.fits.gz', 'G102':'ic461agjq_flt.fits.gz', 'F140W':'ic461ah4q_flt.fits.gz', 'F160W':'ic461ah5q_flt.fits.gz', 'G141':'ic461ah6q_flt.fits.gz'}

    root='-off+x'
    images = {'F098M':'ic461agpq_flt.fits.gz', 'F105W':'ic461agqq_flt.fits.gz', 'G102':'ic461agrq_flt.fits.gz', 'F140W':'ic461ahbq_flt.fits.gz', 'F160W':'ic461ahcq_flt.fits.gz', 'G141':'ic461ahdq_flt.fits.gz'}
    #
    # root='-off-x'
    # images = {'F098M':'ic5v02aiq_flt.fits.gz', 'F105W':'ic5v02ajq_flt.fits.gz', 'G102':'ic5v02akq_flt.fits.gz', 'F140W':'ic5v41b6q_flt.fits.gz', 'F160W':'ic5v41b7q_flt.fits.gz', 'G141':'ic5v41b8q_flt.fits.gz'}

    blue = ['F098M', 'F105W', 'G102']

    flat_file = {'G102':os.getenv('iref')+'/uc72113oi_pfl.fits', #F105W
                 'G141':os.getenv('iref')+'/uc721143i_pfl.fits'} #F140W

    flat = {}
    for key in flat_file.keys():
        im = pyfits.open(flat_file[key])
        flat[key] = im[1].data[5:-5, 5:-5]

    for filter in images.keys():
        test = filter in blue
        band = 'blue'*test + 'red'*(not test)
        asn.product = 'GD153%s-%s-%s' %(root, band, filter)
        asn.exposures = [images[filter].split('_flt')[0]]
        asn.write(asn.product+'_asn.fits')
        im = pyfits.open('../RAW/'+images[filter])
        if filter in flat.keys():
            im[1].data /= flat[key]
            sky = pyfits.open('/Users/brammer/3DHST/Spectra/Work/CONF/sky.G141.set002.fits ')[0].data
            #sky /= flat[key]
            a = np.median(im[1].data/sky)
            im[1].data -= a*sky
        else:
            im[1].data -= np.median(im[1].data)
        #
        #if not os.path.exists(images[filter][:-3]):
        im.writeto(images[filter].split('.gz')[0], clobber=True)

    files=glob.glob('GD*%s*asn.fits' %(root))
    for file in files:
        unicorn.reduce.interlace_combine(file.split('_asn')[0], growx=1, growy=1, pad=60, NGROW=0, view=False)

    model = unicorn.reduce.GrismModel('GD153-blue', direct='F105W', grism='G102', growx=1, growy=1, grow_factor=1)
    model.twod_spectrum(20, miny=-50)
    model.show_2d(savePNG=True)

    model = unicorn.reduce.GrismModel('GD153-red', growx=1, growy=1, grow_factor=1)
    model.twod_spectrum(12, miny=-50)
    model.show_2d(savePNG=True)

    import scipy.ndimage as nd

    twod = unicorn.reduce.Interlace2D('GD153-red_00012.2D.fits')
    wave, flux = twod.optimal_extract(twod.im['SCI'].data-twod.im['CONTAM'].data)
    sens = twod.im['SENS'].data
    plt.plot(wave, flux/sens, color='black', alpha=0.5, linewidth=3)

    plt.plot(wave, flux/nd.shift(sens, -0.5), color='purple', alpha=0.5)
    #plt.plot(wave, flux/nd.shift(sens, -1), color='green', alpha=0.5)
    # plt.plot(wave, flux/nd.shift(sens, -1.), color='red', alpha=0.5)

    sp = pyfits.open('/grp/hst/cdbs/calspec/gd153_mod_008.fits')[1].data
    plt.plot(sp['WAVELENGTH'], sp['FLUX']/1.e-17*0.92)

    twod.compute_model(lam_spec=np.cast[float](sp['WAVELENGTH']), flux_spec=np.cast[float](sp['FLUX'])/1.e-17*0.92/twod.total_flux)
    twod.model[twod.im['SCI'].data == 0] = 0
    w2, f2 = twod.optimal_extract(twod.model)
    plt.plot(w2, f2/sens, color='green')

    bl = unicorn.reduce.Interlace2D('GD153-blue_00020.2D.fits')
    blwave, blflux = bl.optimal_extract(bl.im['SCI'].data-bl.im['CONTAM'].data)
    blsens = bl.im['SENS'].data
    plt.plot(blwave, blflux/blsens, color='black', alpha=0.5, linewidth=3)
    plt.plot(blwave, blflux/nd.shift(blsens, -0.5), color='purple', alpha=0.5)

    bl.compute_model(lam_spec=np.cast[float](sp['WAVELENGTH']), flux_spec=np.cast[float](sp['FLUX'])/1.e-17*0.92/bl.total_flux)
    bl.model[bl.im['SCI'].data == 0] = 0
    w2, f2 = bl.optimal_extract(bl.model)
    plt.plot(w2, f2/blsens, color='green')

    plt.xlim(0.7e4,1.7e4)
    plt.ylim(10,500)
    plt.semilogy()

    model = unicorn.reduce.GrismModel('GD153-off+x-blue', direct='F105W', grism='G102', growx=1, growy=1, grow_factor=1)
    model.twod_spectrum(17, miny=-50)
    model.show_2d(savePNG=True)

    twod = unicorn.reduce.Interlace2D('GD153-off+x-blue_00017.2D.fits')
    w, f = twod.optimal_extract(twod.im['SCI'].data-twod.im['CONTAM'].data)
    s = twod.im['SENS'].data
    plt.plot(w, f/s, color='red', alpha=0.5, linewidth=3)

    model = unicorn.reduce.GrismModel('GD153-off+x-red', direct='F140W', grism='G141', growx=1, growy=1, grow_factor=1)
    model.twod_spectrum(18, miny=-50)
    model.show_2d(savePNG=True)

    twod = unicorn.reduce.Interlace2D('GD153-off+x-red_00018.2D.fits')
    w, f = twod.optimal_extract(twod.im['SCI'].data-twod.im['CONTAM'].data)
    s = twod.im['SENS'].data
    plt.plot(w, f/s, color='red', alpha=0.5, linewidth=3)


# -*- coding: utf-8 -*-
"""
Created on Sat Apr 16 14:40:09 2016

@author: Johnny
"""
import tools
import datastructures as ds
import matplotlib.pyplot as plt

class SimulationPi:
    def __init__(self, nanoWeb):
        if not isinstance(nanoWeb, ds.SimpleWeb):
            raise tools.InvalideParamException("invalide parametre")
        self.nanoWeb = nanoWeb
        self.epsilonHisto = list()
        self.pi = None

        self.ergodique = None

    def walk(self, step, pi, epsilon):
        """se deplacer dans le web au max nbStep pas et s arreter si se seuil est < epsilon"""
        self.epsilonHisto.clear()
        i = 0
        pi1 = None
        pi2 = pi
        limite = self.nanoWeb.nbNode*10
        count = 0
        max = 1
        self.ergodique = True
        while i < step:
            i += 1
            pi1 = pi2
            pi2 = self.nanoWeb.nextStep(pi2)
            tabEpsilon = self.nanoWeb.getTabEpsilon(pi1, pi2)
            ep = self.nanoWeb.maxEpsilon(tabEpsilon)
            if max <= ep:
                count += 1
                if count == limite:
                    self.ergodique = False
                    break
            max = ep
            self.epsilonHisto.append(max)
            if max < epsilon:
                break
        self.pi = pi2

    def drawEpsilon(self):
        """dessiner l historique de epsilon"""
        plt.plot(self.epsilonHisto)
        plt.title(self.nanoWeb.name+" methode pi*P\nevolotion de la convergence en fonction de nombre de pas")
        plt.xlabel("nombre de pas")
        plt.ylabel("valeur d epsilon")
        plt.show()


from django.conf.urls import url, include
from django.urls import path
from rest_framework.urlpatterns import format_suffix_patterns
from music import views

urlpatterns = [
    # songs urls
    path('songs', views.SongList.as_view(), name='song-list'),
    path('song/<int:pk>', views.SongDetail.as_view(), name='song-detail'),
    path('song/<int:pk>/album', views.SongAlbum.as_view(), name='song-album'),
    path('song/<int:pk>/artist', views.SongArtist.as_view(), name='song-artist'),

    # albums urls
    path('albums', views.AlbumList.as_view(), name='album-list'),
    path('album/<int:pk>', views.AlbumDetail.as_view(), name='album-detail'),
    path('album/<int:pk>/songs', views.AlbumSongs.as_view(), name='album-songs'),
    path('album/<int:pk>/artist', views.AlbumArtist.as_view(), name='album-artist'),

    # artists urls
    path('artists', views.ArtistList.as_view(), name='artist-list'),
    path('artist/<int:pk>', views.ArtistDetail.as_view(), name='artist-detail'),
    path('artist/<int:pk>/albums', views.ArtistAlbums.as_view(), name='artist-albums'),

    # users urls
    path('users', views.UserList.as_view(), name='user-list'),
    path('user/<int:pk>', views.UserDetail.as_view(), name='user-detail'),
    path('user/<int:pk>/songs', views.UserSongs.as_view(), name='user-songs'),

    # genre urls
    path('genre/<int:gid>/songs', views.GenreSongs.as_view(), name='genre=songs'),

    # stream urls
    path('stream/<int:pk>', views.Stream.as_view(), name='song-stream'),

    # recommend urls
    path('recommend', views.Recommend.as_view(), name='recommend'),

    #Sign UP Url
    path('signup', views.SignUp.as_view(), name='sign-up'),
]

urlpatterns = format_suffix_patterns(urlpatterns)


# game.py
# 游戏流程控制

import sys
from pygame.locals import *

from render import background, animation
from object import bullet, tama, enemy, item, player
from process.stage import level1
from utility import dialogue

from render.hud import *

from process.scene import menu

class Scene_Game(object):

    def __init__(self):
        # 各种元素初始化
        globe.scgame = self
        self.rs = globe.destiny.rsManager

        globe.playrc = Rect(32, 16, 384, 448)

        self.hud = Hud()
        self.time = -60

        self.player = player.Player()
        self.player.power = 200
        self.bgManager = background.BackgroundManager()
        self.itManager = item.ItemManager()
        self.tmManager = tama.TamaManager()
        self.blManager = bullet.BulletManager()
        self.anManager = animation.AnimeManager()
        self.enManager = enemy.EnemyManager()

        self.txplayer = dialogue.TextPlayer()

        level1.init()

        globe.destiny.msManager.stop()
        globe.destiny.msManager.play_BGM("lv1")

        self.score = 0
        self.graze = 0
        self.hiscore = globe.hiscore
        print(globe.hiscore)

        self.pause = False
        self.timestop = False
        globe.BOSSING = False

    def stop(self):
        self.pause = True

    def start(self):
        self.pause = False

    def tstop(self):
        self.timestop = True

    def tstart(self):
        self.timestop = False

    def update(self):
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()

            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_F4 and event.mod == pygame.KMOD_LALT:
                    pygame.quit()
                    sys.exit()
                elif event.key == pygame.K_ESCAPE:
                    # 处理ESC暂停
                    globe.destiny.msManager.play_SE("pause")
                    globe.destiny.msManager.pause()
                    globe.destiny.call(menu.Scene_Menu)

                elif event.key == K_z and self.timestop:
                    # 对于dialogue: 下一个对话
                    self.txplayer.command("next")

        if not self.pause:
            # 流程更新
            self.bgManager.update()
            self.player.update()
            self.itManager.update()
            self.tmManager.update()
            self.blManager.update()
            self.anManager.update()
            self.enManager.update()
            level1.update(self.time)
            if not self.timestop:
                self.time += 1
            else:
                self.txplayer.update()

    def draw(self, screen):
        screen.fill((255, 255, 255))
        self.bgManager.draw(screen)
        self.itManager.draw(screen)
        self.enManager.draw(screen)
        self.player.draw(screen)
        self.tmManager.draw(screen)
        self.anManager.draw(screen)
        self.blManager.draw(screen)
        self.hud.draw(screen)

        if self.timestop:
            self.txplayer.draw(screen)


"""
    Universidad del Valle de Guatemala
    Gustavo Mendez - 18500

    gl.py - all logic to create a bmp file
"""

from utils.color import *
from utils.encoder import *
from obj import Obj
import random

from collections import namedtuple

V2 = namedtuple('Vertex2', ['x', 'y'])
V3 = namedtuple('Vertex3', ['x', 'y', 'z'])

# ===============================================================
# Math - Code given in class from @denn1s
# ===============================================================

def sum(v0, v1):
    """
        Input: 2 size 3 vectors
        Output: Size 3 vector with the per element sum
    """
    return V3(v0.x + v1.x, v0.y + v1.y, v0.z + v1.z)

def sub(v0, v1):
    """
        Input: 2 size 3 vectors
        Output: Size 3 vector with the per element substraction
    """
    return V3(v0.x - v1.x, v0.y - v1.y, v0.z - v1.z)

def mul(v0, k):
    """
        Input: 2 size 3 vectors
        Output: Size 3 vector with the per element multiplication
    """
    return V3(v0.x * k, v0.y * k, v0.z *k)

def dot(v0, v1):
    """
        Input: 2 size 3 vectors
        Output: Scalar with the dot product
    """
    return v0.x * v1.x + v0.y * v1.y + v0.z * v1.z

def length(v0):
    """
        Input: 1 size 3 vector
        Output: Scalar with the length of the vector
    """
    return (v0.x**2 + v0.y**2 + v0.z**2)**0.5

def norm(v0):
    """
        Input: 1 size 3 vector
        Output: Size 3 vector with the normal of the vector
    """
    v0length = length(v0)

    if not v0length:
        return V3(0, 0, 0)

    return V3(v0.x/v0length, v0.y/v0length, v0.z/v0length)

def bbox(*vertices):
    xs = [ vertex.x for vertex in vertices ]
    ys = [ vertex.y for vertex in vertices ]

    xs.sort()
    ys.sort()

    xmin = xs[0]
    xmax = xs[-1]
    ymin = ys[0]
    ymax = ys[-1]

    return xmin, xmax, ymin, ymax

def cross(v1, v2):
    return V3(
        v1.y * v2.z - v1.z * v2.y,
        v1.z * v2.x - v1.x * v2.z,
        v1.x * v2.y - v1.y * v2.x,
    )

def barycentric(A, B, C, P):
    cx, cy, cz = cross(
        V3(B.x - A.x, C.x - A.x, A.x - P.x),
        V3(B.y - A.y, C.y - A.y, A.y - P.y),
    )

    if abs(cz) < 1:
        return -1, -1, -1

    u = cx/cz
    v = cy/cz
    w = 1 - (cx + cy) / cz

    return w, v, u

class Render(object):
    # glInit dont needed, 'cause we have an __init__ func
    def __init__(self):
        self.framebuffer = []
        self.width = 800
        self.height = 800
        self.viewport_x = 0
        self.viewport_y = 0
        self.viewport_width = 800
        self.viewport_height = 800
        self.clear()

    def point(self, x, y, color):
        self.framebuffer[y][x] = color

    def create_window(self, width, height):
        self.height = height
        self.width = width

    def viewport(self, x, y, width, height):
        # Setting viewport initial values
        self.viewport_x = x
        self.viewport_y = y
        self.viewport_height = height
        self.viewport_width = width

    def clear(self):
        BLACK = color(0,0,0)
        self.framebuffer = [
            [BLACK for x in range(self.width)] for y in range(self.height)
        ]

        self.zbuffer = [
            [-float('inf') for x in range(self.width)]
            for y in range(self.height)
        ]

    def load(self, filename='default.obj', translate=[0,0], scale=[1,1]):
        model = Obj(filename)

        light = V3(0, 0, 1)

        for face in model.faces:
            vcount = len(face)

            if vcount == 3:
                face1 = face[0][0] - 1
                face2 = face[1][0] - 1
                face3 = face[2][0] - 1

                v1 = model.vertices[face1]
                v2 = model.vertices[face2]
                v3 = model.vertices[face3]

                x1 = round((v1[0] * scale[0]) + translate[0])
                y1 = round((v1[1] * scale[1]) + translate[1])
                z1 = round((v1[2] * scale[2]) + translate[2])

                x2 = round((v2[0] * scale[0]) + translate[0])
                y2 = round((v2[1] * scale[1]) + translate[1])
                z2 = round((v2[2] * scale[2]) + translate[2])

                x3 = round((v3[0] * scale[0]) + translate[0])
                y3 = round((v3[1] * scale[1]) + translate[1])
                z3 = round((v3[2] * scale[2]) + translate[2])

                a = V3(x1, y1, z1)
                b = V3(x2, y2, z2)
                c = V3(x3, y3, z3)

                normal = cross(sub(b, a), sub(c, a))
                intensity = dot(norm(normal), norm(light))
                grey = round(255 * intensity)
                if grey < 0:
                    continue

                intensity_color = color(grey, grey, grey)
                self.triangle(a, b, c, intensity_color)

            else:
                face1 = face[0][0] - 1
                face2 = face[1][0] - 1
                face3 = face[2][0] - 1
                face4 = face[3][0] - 1

                v1 = model.vertices[face1]
                v2 = model.vertices[face2]
                v3 = model.vertices[face3]
                v4 = model.vertices[face4]

                x1 = round((v1[0] * scale[0]) + translate[0])
                y1 = round((v1[1] * scale[1]) + translate[1])
                z1 = round((v1[2] * scale[2]) + translate[2])

                x2 = round((v2[0] * scale[0]) + translate[0])
                y2 = round((v2[1] * scale[1]) + translate[1])
                z2 = round((v2[2] * scale[2]) + translate[2])

                x3 = round((v3[0] * scale[0]) + translate[0])
                y3 = round((v3[1] * scale[1]) + translate[1])
                z3 = round((v3[2] * scale[2]) + translate[2])

                x4 = round((v4[0] * scale[0]) + translate[0])
                y4 = round((v4[1] * scale[1]) + translate[1])
                z4 = round((v4[2] * scale[2]) + translate[2])

                a = V3(x1, y1, z1)
                b = V3(x2, y2, z2)
                c = V3(x3, y3, z3)
                d = V3(x4, y4, z4)

                intensity = dot(norm(normal), norm(light))
                grey = round(255 * intensity)
                if grey < 0:
                    continue

                intensity_color = color(grey, grey, grey)

                self.triangle(a, b, c, intensity_color)
                self.triangle(a, c, d, intensity_color)

    def triangle(self, A, B, C, color):
        xmin, xmax, ymin, ymax = bbox(A, B, C)

        for x in range(xmin, xmax + 1):
            for y in range(ymin, ymax + 1):
                P = V2(x, y)
                w, v, u = barycentric(A, B, C, P)
                if w < 0 or v < 0 or u < 0:
                    # point is outside
                    continue

                z = A.z * u + B.z * v + C.z * w
                if z > self.zbuffer[y][x]:
                    self.point(x, y, color)
                    self.zbuffer[y][x] = z

    def finish(self, filename='out.bmp'):
        # starts creating a new bmp file
        f = open(filename, 'bw')

        f.write(char('B'))
        f.write(char('M'))
        f.write(dword(14 + 40 + self.width * self.height * 3))
        f.write(dword(0))
        f.write(dword(14 + 40))

        # image header
        f.write(dword(40))
        f.write(dword(self.width))
        f.write(dword(self.height))
        f.write(word(1))
        f.write(word(24))
        f.write(dword(0))
        f.write(dword(self.width * self.height * 3))
        f.write(dword(0))
        f.write(dword(0))
        f.write(dword(0))
        f.write(dword(0))

        # Finishing placing points
        try:
            for x in range(self.height):
                for y in range(self.width):
                    f.write(self.framebuffer[x][y])
        except:
            print('Your obj file is too big. Try another scale/translate values')

        f.close()
        self.finish_zbuffer(filename='z_buffer.bmp')

    def finish_zbuffer(self, filename):
        # starts creating a new bmp file
        f = open(filename, 'wb')

        f.write(char('B'))
        f.write(char('M'))
        f.write(dword(14 + 40 + self.width * self.height * 3))
        f.write(dword(0))
        f.write(dword(14 + 40))

        # image header
        f.write(dword(40))
        f.write(dword(self.width))
        f.write(dword(self.height))
        f.write(word(1))
        f.write(word(24))
        f.write(dword(0))
        f.write(dword(self.width * self.height * 3))
        f.write(dword(0))
        f.write(dword(0))
        f.write(dword(0))
        f.write(dword(0))

        z_min = float('inf')
        z_max = -float('inf')

        for x in range(self.height):
            for y in range(self.width):
                if self.zbuffer[x][y] != -float('inf'):
                    if self.zbuffer[x][y] > z_max:
                        z_max = self.zbuffer[x][y]

                    if self.zbuffer[x][y] < z_min:
                        z_min = self.zbuffer[x][y]

        for x in range(self.height):
            for y in range(self.width):
                z_value = self.zbuffer[x][y]

                if z_value == -float('inf'):
                    z_value = z_min

                z_value = round(((z_value - z_min) / (z_max - z_min)) * 255)
                z_color = color(z_value, z_value, z_value)
                f.write(z_color)

        f.close()


import numpy as np
import matplotlib.pyplot as plt
import sys
from argparse import ArgumentParser

def scale(a):
    return a/1000000.0

parser = ArgumentParser(description="plot")

parser.add_argument('--dir', '-d',
                    help="Directory to store outputs",
                    required=True)

parser.add_argument('--name', '-n',
                    help="name of the experiment",
                    required=True)

parser.add_argument('--trace', '-tr',
                    help="name of the trace",
                    required=True)

args = parser.parse_args()

fig = plt.figure(figsize=(21,3), facecolor='w')
ax = plt.gca()

# plotting the trace file
f1 = open (args.trace,"r")
BW = []
nextTime = 1000
cnt = 1
lastTime = 0
firstTime = f1.readline().strip()
if not firstTime:
    firstTime = 0
firstTime = float(firstTime)
lastTime = float(lastTime)
for line in f1:
    lastTime = float(line.strip())
    if int(lastTime) > nextTime:
        BW.append(cnt*1492*8)
        cnt = 0
        nextTime+=1000

    else:
        cnt+=1
f1.close()

ax.fill_between(range(len(BW)), 0, list(map(scale,BW)),color='#D3D3D3')

# plotting throughput
throughputDL = []
timeDL = []

traceDL = open (args.dir+"/"+str(args.name), 'r')
traceDL.readline()

tmp = traceDL.readline().strip().split(",")
bytes = int(tmp[1])
startTime = float(tmp[0])
stime=float(startTime)

firstTime /= 1000
lastTime /= 1000
tLoop = (lastTime-firstTime)
if tLoop:
    utime = (stime-firstTime)
    utime += 165.0 # this constant might need adjustment, it is the number that synced the graphs for me
    utime = utime%tLoop
else:
    tLoop = 1000000
    utime = 0
looper = 0
for i in range(0,int(utime)):
    timeDL.append(float(i))
    throughputDL.append(0)
for time in traceDL:
    if (float(time.strip().split(",")[0]) - float(startTime)) <= 1.0:
        bytes += int(time.strip().split(",")[1])
    else:
        timeP = (float(startTime)-stime+utime)
        if timeP < tLoop:
            timeDL.append(timeP)
            throughputDL.append(bytes*8/1000000.0)
        else:
            timeDL[looper] = int(timeP%tLoop)
            throughputDL[looper] = bytes*8/1000000.0
            looper = int(looper+1%tLoop)

        bytes = int(time.strip().split(",")[1])
        startTime += 1.0

print (timeDL)
print (throughputDL)

plt.plot(timeDL, throughputDL, lw=2, color='r')

plt.ylabel("Throughput (Mbps)")
plt.xlabel("Time (s)")
# plt.xlim([0,300])
plt.grid(True, which="both")
plt.savefig(args.dir+'/throughput.pdf',dpi=1000,bbox_inches='tight')


# Learned the os.walk() method from https://www.tutorialspoint.com/python/os_walk.htm
# Learned the os.listdir() method from https://www.tutorialspoint.com/python/os_listdir.htm#:~:text=Python%20os.listdir%20%28%29%20Method%201%20Description.%20Python%20method,example%20shows%20the%20usage%20of%20listdir%20%28%29%20method.
# Learned the os.path.exists() method from https://pythontect.com/python-os-path-exists-method-tutorial/
# Learned the os.path.splitext() method from https://docs.python.org/3/library/os.path.html
# Learned the detect method of chardet from https://chardet.readthedocs.io/en/latest/usage.html#example-using-the-detect-function

from logging import log
import logging
import os
import chardet
from openapi_server.scorer.src.file_parser import file_parser

def ramp_up_time(dir_check):
    if os.path.exists(dir_check) == False:
        return -1

    logging.info('The current module directory is not None, continue to evaluate the ramp-up time score of the current module.')

    #  Evaluate the ramp up time score of moddule based on three dimensions: number_lines,Documentation, and inclusion of use case example, also set up the counters.

    num_codes = 0
    num_doc = 0
    num_case = 0
    num_https = 0
    usage_time = 0
    paths = os.listdir(dir_check)
    if len(paths) == 0:
        logging.info('There is no any file in current module path, returning value of -1')
        return -1
    input_dir = ''
    logging.info('Now finding the readme file directory and read the file to get info for the scoring, i.e. line_in_readme, num_https, num_case.')

    for curr_path in paths:
        if 'README' in curr_path or 'readme' in curr_path or 'ReadMe' in curr_path or "Readme" in curr_path:
            input_dir = dir_check + '/' + curr_path
    line_in_readme = 0

    if os.path.exists(input_dir):
        try:
            temp2= open(input_dir,'rb')
            temp_data2 = temp2.read()
            temp_check2 = chardet.detect(temp_data2)
            #read_data = temp_data2.decode(temp_check2['encoding'],'ignore').encode('utf-8')
            #read_readme = open(input_dir,encoding = 'utf-8')
            read_data = open(input_dir,encoding = temp_check2['encoding'])
            # read_readme = open(input_dir,encoding = 'utf-8')
            for curr_line in read_data:
                    line_in_readme += 1
                    if '```bash' in curr_line:
                        num_case += 1
                    if '```' in curr_line:
                        num_case += 1
                        usage_time += 1
                    if 'https' in curr_line:
                        num_https += 1
        except:
            logging.info('Reading error of the current readme file occurs.')
            if line_in_readme == 0:
                line_in_readme = 1
            handle_error = 1
    else:
        num_case = 0
        line_in_readme = 0

    num_case = num_case - usage_time // 2
    num_doc = line_in_readme
    logging.info('Read info of readme file done.')

   # Check how many total lines of js code in this module

    logging.info('Now getting all js files in the module and use file parser to get all info of the all files.')
    js_files_container = []

    for curr_folder, sub_folders, curr_files in os.walk(dir_check):
        for curr_file in curr_files:
            if'.js' in os.path.splitext(curr_file):
                js_files_container.append((str(curr_folder)) + '/' + curr_file)

    total_statistics = {'num_lines':0,'num_comments':0,'num_functions':0,'num_class':0,'num_bytes':0}

    for curr_js_file in js_files_container:
        curr_file_data = file_parser(curr_js_file)
        for per_data_pos in curr_file_data:
            total_statistics[per_data_pos] = curr_file_data[per_data_pos] + total_statistics[per_data_pos]

    num_codes = total_statistics['num_lines']
    num_comments = total_statistics['num_comments']

    logging.info('Getting info from all js files done')

    # Score for the documentation

    logging.info('Now calculating the score for readability of the module')
    readabilitiy_score = ((0.1)*(num_doc >= 25) +(0.1)*(num_doc>=40) + (0.2)*(num_doc>=80) + (0.1)*(num_doc>120) + 0.1 * (num_doc > 140) + 0.2 *(num_doc>180) + 0.2 *(num_doc > 220)) * 100

    # Score for comments line

    logging.info('Now calculating the score for comments lines')
    score_comments = 0.15 * (num_comments>= 0 and num_comments <200) * 100 +  (num_comments / 1000 * 100) * (num_comments >= 200 and num_comments < 500) \
    + (num_comments >= 500 and num_comments < 1500) * (num_comments / 2500 * 100) + (num_comments >= 1500 and num_comments < 5000) * 0.625 * 100 \
    + (num_comments >= 5000 and num_comments < 8000) * 0.65 * 100 + (num_comments >= 8000 and num_comments < 11000) * 0.7 * 100 \
    + (num_comments >= 11000 and num_comments) * 0.75 * 100 + (num_comments >= 19000 and num_comments < 22000) *0.78 * 100 \
    + (num_comments >= 22000 and num_comments < 25000) * 0.85 * 100 + (num_comments >= 25000 and num_comments < 29000) *0.88 * 100 \
    + (num_comments >= 29000 and num_comments < 31000) * 0.92 * 100 + (num_comments > 31000) * 100

    # Score for usage cases

    logging.info('Now calculating the usage cases score')
    case_score = 0.1 * 100 * (num_case == 0) + 0.15 * 100 * (num_case == 1) + 0.3 * 100 * (num_case == 2) + 0.4 * 100 * (num_case == 3) \
    + (num_case == 4) * 0.5 * 100 + ( num_case >= 10 and num_case < 20) * 0.75 * 100  \
    + (num_case >= 20 and num_case < 30) *0.8 * 100 + (num_case >= 30 and num_case < 70) * 0.9 * 100 + (num_case >= 70) * 100 \
    + (num_case > 4 and num_case < 10) * 0.65*100

    logging.info('Now calculating the bonus score')
    bonus_score = num_https * 0.75

    logging.info('Now calculating the total ramp-up time score')
    ramp_up_time_score = (readabilitiy_score + score_comments + case_score + bonus_score) / 3

    if ramp_up_time_score > 100:
       logging.info('The total ramp-up time score of the current module is greater than 100, it will be set to at most 100')
       ramp_up_time_score = 100

    return ramp_up_time_score /100

if __name__ == "__main__":
    print('test')
    # # print(ramp_up_time(the module dir))
    # # Below are modules samples given on the Brightspace
    # print('-----------------------------------------')
    # print(ramp_up_time('cloudinary_npm-master'))
    # print('-----------------------------------------')
    # print(ramp_up_time('express-master'))
    # print('-----------------------------------------')
    # print(ramp_up_time('nodist-master'))
    # print('-----------------------------------------')
    # print(ramp_up_time('lodash-master'))
    # print('-----------------------------------------')
    # print(ramp_up_time('browserify-master'))
    # print('-----------------------------------------')


from pathlib import Path, PurePath
from openbabel import pybel
from vinautil.vinaconfig import xyz_point

from vinautil.utils.typecheck import typeassert

class center(xyz_point):
    def __init__(self, x, y, z):
        super().__init__(x, y, z)

    def __repr__(self):
        return 'center: {},{},{}'.format(self.x, self.y, self.z)

class box_size(xyz_point):
    def __init__(self, x, y, z):
        super().__init__(x, y, z)

    def __repr__(self):
        return 'box_size: {},{},{}'.format(self.x, self.y, self.z)

@typeassert(file=Path, fmt=str)
class molecule:

    def __init__(self, file: Path, fmt:str=None):
        self.file = file
        self.fmt = fmt if bool(fmt) else file.suffix.replace('.','')
        # self.center, self.box_size = self.compute_box().values()

    def compute_box(self, extending = 10):
        coords_lst = self.get_coord_lst()
        xlst, ylst, zlst = [i[0] for i in coords_lst], [i[1] for i in coords_lst], [i[2] for i in coords_lst]
        ([minX, minY, minZ], [maxX, maxY, maxZ]) = ([min(xlst), min(ylst), min(zlst)], [max(xlst), max(ylst), max(zlst)])
        minX = minX - float(extending)
        minY = minY - float(extending)
        minZ = minZ - float(extending)
        maxX = maxX + float(extending)
        maxY = maxY + float(extending)
        maxZ = maxZ + float(extending)
        SizeX = maxX - minX
        SizeY = maxY - minY
        SizeZ = maxZ - minZ
        CenterX = (maxX + minX) / 2
        CenterY = (maxY + minY) / 2
        CenterZ = (maxZ + minZ) / 2
        c = {
                'x': float("{:.2f}".format(CenterX)),
                'y': float("{:.2f}".format(CenterY)),
                'z': float("{:.2f}".format(CenterZ)),
        }
        s = {
                'x': float("{:.2f}".format(SizeX)),
                'y': float("{:.2f}".format(SizeY)),
                'z': float("{:.2f}".format(SizeZ))
        }
        rd = {
            'center': center(**c),
            'box_size': box_size(**s)
        }
        return rd

    @property
    def center(self):
        return self.center

    @property
    def box_size(self):
        return self.box_size

    def get_coord_lst(self, addHs:bool = True):
        molH = pybel.readfile(format = self.fmt, filename=self.file.__str__())
        molH = next(molH)
        # molH.OBMol.DeleteHydrogens()
        if addHs: molH.OBMol.AddPolarHydrogens()
        return [list(atom.coords) for atom in molH]

    def get_coord_dict(self, addHs:bool = True):
        molH = pybel.readfile(format = self.fmt, filename=self.file.__str__())
        molH = next(molH)
        if addHs: molH.OBMol.AddPolarHydrogens()
        return {atom.idx: atom.coords for atom in molH}

if __name__ == '__main__':
    file = Path('./test_file/2xd1_C_CEF.mol2')
    mol = molecule(file)


""" get_rhythm_features

Extract Rhythm features for segments and statistics over segments in (day or call)

Required Library:
https://pypi.org/project/EMD-signal/

"""

import os
import sys
import argparse
import pandas as pd
from IPython import embed
import math
import numpy as np
from rhythm_extract import extractRhythmMap

def chunks(l, n_chunks):
	n_in_chunk = math.ceil(float(len(l))/float(n_chunks))
	for i in range(0,len(l),n_in_chunk):
		yield l[i:i+n_in_chunk]

def extract_rhythm_features(args):
    """
    Extract Rhythm features for segments and statistics over segments in (day or call)

    :param args: input arguments from argparse
    :return: none
    """

    #set up
    level = args.level
    temp_dir = os.path.join(args.output_dir, 'segments')
    output_dir = os.path.join(args.output_dir, level, args.call_type)

    #get segment metadata
    metadata_df = pd.read_csv(args.metadata_path)
    metadata_df['call_datetime'] = pd.to_datetime(metadata_df['call_datetime'])
    metadata_df['call_date'] = metadata_df['call_datetime'].dt.date
    metadata_df['day_id'] = metadata_df['subject_id'].apply(str) + '_' + metadata_df['call_date'].apply(str)

    #filter call type (personal, assessment, all)
    if metadata_df['is_assessment'].dtypes == 'bool':
        metadata_df.loc[metadata_df['is_assessment'] == True, 'is_assessment'] = 't'
        metadata_df.loc[metadata_df['is_assessment'] == False, 'is_assessment'] = 'f'
    if args.call_type == 'personal':
        metadata_df = metadata_df.loc[metadata_df['is_assessment'] == 'f', :]
    elif args.call_type == 'assessment':
        metadata_df = metadata_df.loc[metadata_df['is_assessment'] == 't', :]
    elif args.call_type != 'all':
        print('Invalid call_type: ' + str(args.call_type))
        return

    #get call_ids in chunk
    chunk = int(args.job_num)
    call_ids = sorted(metadata_df['call_id'].unique())
    call_ids = list(chunks(call_ids,100))[chunk-1]

    #aggregation level
    if level == 'call':
        idx_vals = metadata_df['call_id'].sort_values().unique().tolist()
        idx_col = 'call_id'
    elif level == 'day':
        idx_vals = metadata_df['day_id'].drop_duplicates().values.tolist()
        idx_col = 'day_id'
    idx_vals = list(chunks(idx_vals,100))[chunk-1]

    #make output directories
    if not os.path.exists(temp_dir):
        os.makedirs(temp_dir)
    if not os.path.exists(output_dir):
        os.makedirs(output_dir)

    #COMPUTE RHYTHM FEATURES
    #***********************************************************
    #***********************************************************
    for idx in idx_vals: #iterate over calls or days
        seg_ids = metadata_df.loc[metadata_df[idx_col] == idx, 'segment_id'].unique()

        #Compute features for all segment in idx
        feats_df = pd.DataFrame()
        for seg_id in seg_ids: #iterate over segments
            seg_input_path = os.path.join(args.segments_dir, str(seg_id) + '.wav')
            seg_output_path = os.path.join(temp_dir, str(seg_id) + '.csv')

            #compute rhythm features for segment
            if not os.path.exists(seg_output_path):
                extractRhythmMap(str(seg_id)+'.wav', args.segments_dir, temp_dir)

            #add segment features to feature dataframe
            seg_feats_df = pd.read_csv(seg_output_path)
            seg_feats_df['segment_id'] = seg_id
            feats_df = feats_df.append(seg_feats_df)

        #compute mean and std over segment features
        s = pd.Series()
        for col in feats_df.columns:
            if col in ['segment_id']:
                continue
            s[col+'_mean'] = feats_df[col].mean()
            s[col+'_median'] = feats_df[col].median()
            s[col+'_p01'] = feats_df[col].quantile(0.01)
            s[col+'_p99'] = feats_df[col].quantile(0.99)
            s[col+'_range'] = feats_df[col].max() - feats_df[col].min()
            s[col+'_std'] = feats_df[col].std()

        #save feature stats for index to file
        output_path = os.path.join(output_dir, str(idx) + '.csv')
        s.to_csv(output_path)

def _parse_args():
    parser = argparse.ArgumentParser()
    parser.add_argument('--level', type=str, default='call')
    parser.add_argument('--job_num', type=int, default=1)
    parser.add_argument('--call_type', type=str, default='all', help='specifies type of call (assessment, personal, or all)')
    parser.add_argument('--segments_dir', type=str, help='Path to directory with segment wave files')
    parser.add_argument('--output_dir', type=str, help="Path to directory to output feature files to.")
    parser.add_argument('--metadata_path', type=str, help="Path to segment metadata file (subject, call, etc.).")
    return parser.parse_args()

def main():
    args = _parse_args()
    extract_rhythm_features(args)

if __name__ == '__main__':
    main()


import torch
import torch.nn as nn
from math import sqrt
import torch.nn.functional as F

class dense(nn.Module):
    def __init__(self):
        super(dense, self).__init__()

        self.res1 = Conv_Res_Block()
        self.res2 = Conv_Res_Block()
        self.res3 = Conv_Res_Block()
        self.res4 = Conv_Res_Block()

    def forward(self, x):
        x1 = x
        x2 = self.res1(x1)# + x1
        x3 = self.res2(x2)# + x2 + x1
        x4 = self.res3(x3)# + x3 + x2 + x1
        x5 = self.res4(x4)#
        return x5

class Conv_ReLU_Block(nn.Module):
    def __init__(self):
        super(Conv_ReLU_Block, self).__init__()
        self.conv = nn.Conv2d(in_channels=64, out_channels=64, kernel_size=3, stride=1, padding=1, bias=False)
        self.bn = nn.BatchNorm2d(64)
        self.relu = nn.ReLU()

    def forward(self, x):
        return self.relu(self.bn(self.conv(x)))

class Conv_Res_Block(nn.Module):
    def __init__(self):
        super(Conv_Res_Block, self).__init__()
        self.convs = nn.Sequential(
                Conv_ReLU_Block(),
                Conv_ReLU_Block(),

                )
    def forward(self, x):
        return self.convs(x) + x

class MASK(nn.Module):
    def __init__(self, scale = 2):
        super(MASK, self).__init__()
        self.residual_layer = self.make_layer(Conv_ReLU_Block, 10)
        self.input = nn.Sequential(
                nn.Conv2d(in_channels=3, out_channels=64, kernel_size=3, stride=1, padding=1),
                nn.ReLU(),
                nn.Conv2d(in_channels=64, out_channels=64, kernel_size=3, stride=1, padding=1),
                nn.ReLU(),
                )
        self.output = nn.Sequential(
                nn.Conv2d(64,64,3,1,1),
                nn.ReLU(),
                nn.Conv2d(in_channels=64, out_channels=3, kernel_size=3, stride=1, padding=1, bias=False)
                )
        self.dense_down_1 = dense()
        self.dense_down_2 = dense()
        self.dense_up_1 = dense()
        self.dense_up_2 = dense()
        self.dense_bottom = dense()

        for m in self.modules():
            if isinstance(m, nn.Conv2d):
                n = m.kernel_size[0] * m.kernel_size[1] * m.out_channels
                m.weight.data.normal_(0, sqrt(2. / n))
        # self.sigmoid = nn.Sigmoid()
    def make_layer(self, block, num_of_layer):
        layers = []
        for _ in range(num_of_layer):
            layers.append(block())
        return (nn.Sequential(*layers))

    def forward(self, x):
        residual = x
        out1 = self.input(x)
        out2 = self.dense_down_1(F.max_pool2d(out1,2))
        out3 = self.dense_down_2(F.avg_pool2d(out2,2))
        out3_ = out3 + self.dense_bottom(out3)
        out2_ = out2 + F.upsample(self.dense_up_2(out3_), scale_factor=2)
        out1_ = out1 + F.upsample(self.dense_up_1(out2_), scale_factor=2)
        out = self.output(out1_)
        # out = torch.add(out,residual)
        return F.sigmoid(out)


# -*- coding: UTF-8 -*-
from pymongo import MongoClient
import logging
import contextlib
import redis
from configs.read_parser import ParserReader
from configs.const import getConfigType,get_db

class RedisDB(object):
    def __init__(self, *args, **kwargs):
       pass

    pool = {}
    @staticmethod
    def getRedisConn(**kwargs):
        conf_name = kwargs.get("conf_name")
        server = RedisDB.pool.get(conf_name, None)
        if not server:
            conf = ParserReader(conf_name=conf_name).get_db_config()
            db_url = conf.get("db_url", "")
            host = conf.get("host", "127.0.0.1")
            port = conf.get("port", 6379)
            db = conf.get("db", 0)
            max_connections = conf.get("max_connections", 2)
            if db_url:
                pool = redis.ConnectionPool.from_url(url=db_url)
            else:
                pool = redis.ConnectionPool(host=host, port=port, db=db, max_connections=max_connections)
            server = redis.StrictRedis(connection_pool=pool)
            RedisDB.pool.setdefault(conf_name, server)
        return server

if __name__ == '__main__':
    rd=RedisDB()
    conn=rd.get_redis_conn(conf_name="redis_local")
    print(conn)


from typing import List

from items import Item

class ItemDB(object):
    """A DB for global Item state."""
    items: dict = None

    def __init__(self, items: dict = None):
        if items is None:
            self.items = {}
        else:
            self.items = items

    def __str__(self):
        s = ''
        if self.items is not None:
            for item in self.items.values():
                s += '{} ({})\n'.format(item.get_title(), item.get_id())
        return s

    def get_item(self, item_id: int):
        return self.items.get(item_id, None)

    def delete_item(self, item_id: int):
        """Delete an Item by ID, returning True if successful and False if not."""
        try:
            del self.items[item_id]
            return True
        except KeyError:
            return False

    def add_all_items(self, items: List[Item]):
        for item in items:
            self.add_item(item)

    def add_item(self, i: Item):
        if self.items.get(i.get_id(), None) is not None:
            self.update_item(i)
        else:
            self.items[i.get_id()] = i

    def update_item(self, i: Item):
        # Use the ID of the passed in Item to locate the desired Item
        # in the items dictionary
        db_item: Item = self.items[i.get_id()]

        # Loop over the content dictionary of the passed-in Item, and
        # for each key-value pair, update the existing Item's content
        # dictionary with that data. For dictionary members of content
        # like 'kids', make sure you don't overwrite the dictionary, but
        # instead update it with the items in that dictionary. A lot of
        # the other, non-dictionary fields in content should be overwritten
        # since they might correspond to quantitative things -- like number of
        # comments or number of points -- which need to be frequently updated.
        for key, value in i.get_content().items():
            if value is not None:
                if key == 'kids':
                    db_item.content.update(value)
                else:
                    db_item.content[key] = value


import argparse
import platform
import shutil
import subprocess

import matplotlib.pyplot as plt
import numpy as np

parser = argparse.ArgumentParser()
parser.add_argument("pages", type=int, help="number of pages.")
parser.add_argument("epochs", type=int, help="number of epochs to run the experiment.")
args = parser.parse_args()

data = []
x = np.arange(args.pages)
pages = 2 ** x
for i in pages:
    r = subprocess.run(
        ["./tlb", str(i), str(args.epochs)], capture_output=True, check=True, text=True,
    )
    # print(r.stdout)
    process = r.stdout.split("elapsed = ")[1].split(" ")[0]
    data.append(float(process))

plt.plot(x, data, marker="x", color="green")
plt.margins(0.2)
# plt.xticks(x, pages, fontsize="x-small")
plt.xlabel("Numer of pages")
plt.ylabel("Time per access (ns)")
plt.show()


import numpy as np
from sklearn.externals import joblib
from sklearn.model_selection import KFold
from sklearn.svm import SVC, LinearSVC
from utils.constants import Constants
from utils.utils import from_csv_with_filenames
import os
import logging

OUTPUT_ERRORS = True

def fix_seq_length(xs, length=50):
    truncated = 0
    padded = 0
    print('xs[0]: {}'.format(str(xs[0].shape)))
    for i, x in enumerate(xs):
        if length < x.shape[0]:
            x = x[0:length][:]
            truncated += 1
        elif length > x.shape[0]:
            x = np.pad(x, ((0, length - x.shape[0]), (0, 0)), mode='constant', constant_values=(0))
            padded += 1
        xs[i] = x
    print('xs[0]: {}'.format(str(xs[0].shape)))
    print('Truncated {}; Padded {}'.format(truncated/len(xs), padded/len(xs)))
    return xs

def apply_loaded_pca(xs, path):
    pca = joblib.load(path)
    print('xs[0]: {}'.format(str(xs[0].shape)))
    xs = np.array([pca.transform(x) for x in xs])
    print('xs[0]: {}'.format(str(xs[0].shape)))
    return xs

def train_svc(xs, ys, k = 5):
    kf = KFold(n_splits=5)
    results_rbf = []
    results_linear = []
    flat_xs = np.array([x.ravel() for x in xs])
    ys = np.array(ys)
    for train_i, test_i in kf.split(flat_xs):
        rbf = SVC()
        linear = LinearSVC()
        print('Fitting RBF...')
        rbf.fit(flat_xs[train_i], ys[train_i])
        print('Fitting linear...')
        linear.fit(flat_xs[train_i], ys[train_i])
        pred = rbf.predict(flat_xs[test_i])
        results_rbf.append(np.average(pred == ys[test_i]))
        pred = linear.predict(flat_xs[test_i])
        results_linear.append(np.average(pred == ys[test_i]))
    print('SVC RBF: {}; SVC Linear: {}'.format(np.average(results_rbf), np.average(results_linear)))

def train_svc_report_errors(xs, ys, filenames, k=5):
    kf = KFold(n_splits=5)
    results_rbf = []
    results_linear = []
    flat_xs = np.array([x.ravel() for x in xs])
    ys = np.array(ys)
    j = 0
    for train_i, test_i in kf.split(flat_xs):
        rbf = SVC()
        linear = LinearSVC()
        print('Fitting RBF...')
        rbf.fit(flat_xs[train_i], ys[train_i])
        print('Fitting linear...')
        linear.fit(flat_xs[train_i], ys[train_i])
        pred = rbf.predict(flat_xs[test_i])
        results_rbf.append(np.average(pred == ys[test_i]))
        pred = linear.predict(flat_xs[test_i])
        results_linear.append(np.average(pred == ys[test_i]))
        print('Fold {}, wrong ones: '.format(j))
        for i, is_correct in enumerate(pred == ys[test_i]):
            if not is_correct:
                print('{}: was predicted {}'
                      .format(filenames[test_i[i]], pred[i]))
        j += 1
    print('SVC RBF: {}; SVC Linear: {}'.format(np.average(results_rbf), np.average(results_linear)))

if __name__ == '__main__':
    logging.info('Loading pickle')
    #xs, ys = load_data(os.path.join(Constants.DATA_FOLDER, 'activations.pkl'))
    xs, ys, filenames = from_csv_with_filenames(
                        os.path.join(Constants.DATA_FOLDER, '10classes', 'audio_data.csv')
                        )
    train_svc_report_errors(xs, ys, filenames)


#!/usr/bin/env python3
"""
This module provides classes representing the accounting double entry system.
"""

from datetime import datetime

from enum import Enum

from auxi.core.objects import NamedObject
from auxi.core.reporting import ReportFormat

__version__ = '0.3.6'
__license__ = 'LGPL v3'
__copyright__ = 'Copyright 2016, Ex Mente Technologies (Pty) Ltd'
__author__ = 'Johan Zietsman'
__credits__ = ['Johan Zietsman']
__maintainer__ = 'Johan Zietsman'
__email__ = 'johan.zietsman@ex-mente.co.za'
__status__ = 'Planning'

class AccountType(Enum):
    """
    Represents the type of general ledger account.
    """

    asset = 1
    equity = 2
    expense = 3
    liability = 4
    revenue = 5

AT = AccountType

class GeneralLedgerAccount(NamedObject):
    """
    Represents an account of a general ledger.

    :param name: The name.
    :param description: The description.
    :param number: The number.
    :param account_type: The type of account.
    """

    def __init__(self, name, description=None,
                 number=None,
                 account_type=AccountType.revenue):
        self._parent_path = ""
        self.path = name
        self.number = number
        self.account_type = account_type
        self.accounts = []
        super(GeneralLedgerAccount, self).__init__(name, description)

    def __getitem__(self, key):
        return [a for a in self.accounts if a.name == key][0]

    def __missing__(self, key):
        return None

    def set_parent_path(self, value):
        """
        Set the parent path and the path from the new parent path.

        :param value: The path to the object's parent
        """

        self._parent_path = value
        self.path = value + r'/' + self.name
        self._update_childrens_parent_path()

    def _update_childrens_parent_path(self):
        for a in self.accounts:
            a.set_parent_path(self.path)

    @property
    def name(self):
        return self._name

    @name.setter
    def name(self, value):
        self._name = value
        if self._parent_path != "":
            self.path = self._parent_path + r'/' + self.name
        else:
            self.path = self.name
        self._update_childrens_parent_path()

    def create_account(self, name, number=None, description=None):
        """
        Create a sub account in the account.

        :param name: The account name.
        :param description: The account description.
        :param number: The account number.

        :returns: The created account.
        """

        new_account = GeneralLedgerAccount(name, description, number,
                                           self.account_type)
        new_account.set_parent_path(self.path)
        self.accounts.append(new_account)
        return new_account

    def remove_account(self, name):
        """
        Remove an account from the account's sub accounts.

        :param name: The name of the account to remove.
        """

        acc_to_remove = None
        for a in self.accounts:
            if a.name == name:
                acc_to_remove = a
        if acc_to_remove is not None:
            self.accounts.remove(acc_to_remove)

    def get_child_account(self, account_name):
        """
        Retrieves a child account.
        This could be a descendant nested at any level.

        :param account_name: The name of the account to retrieve.

        :returns: The child account, if found, else None.
        """

        if r'/' in account_name:
            accs_in_path = account_name.split(r'/', 1)

            curr_acc = self[accs_in_path[0]]
            if curr_acc is None:
                return None
            return curr_acc.get_child_account(accs_in_path[1])
            pass
        else:
            return self[account_name]

class Transaction(NamedObject):
    """
    Represents a financial transaction between two general ledger accounts.

    :param name: The name.
    :param description: The description.
    :param tx_date: The transaction's date.
    :param dt_account: The account to debit.
    :param cr_account: The account to credit.
    :param source: The source that created the transaction.
    :param amount: The transaction's amount.
    :param is_closing_dt_account: Specifies whether this is a closing debit
      account.
    :param is_closing_cr_account: Specifies whether this is a closing credit
      account.
    """

    def __init__(self, name, description=None,
                 tx_date=datetime.min.date(),
                 dt_account=None, cr_account=None,
                 source=None, amount=0.00,
                 is_closing_dt_account=False,
                 is_closing_cr_account=False):
        super(Transaction, self).__init__(name, description)
        self.tx_date = tx_date
        self.dt_account = dt_account
        self.cr_account = cr_account
        self.source = source
        self.amount = amount
        self.is_closing_dt_account = is_closing_dt_account
        self.is_closing_cr_account = is_closing_cr_account

class TransactionTemplate(NamedObject):
    """
    Represents a template for how a transaction is to be created.

    :param name: The name of the transaction.
    :param description: The description of the transaction.
    :param dt_account: The account to debit.
    :param cr_account: The account to credit.
    """

    def __init__(self, name, dt_account, cr_account, description=None):
        """
        """
        super(TransactionTemplate, self).__init__(name, description)
        self.dt_account = dt_account
        self.cr_account = cr_account

class GeneralLedgerStructure(NamedObject):
    """
    The account structure of a general ledger.

    :param name: The name.
    :param description: The description.
    """

    # TODO: add _acc_ name abbr. descriptions

    def __init__(self, name, description=None):
        super(GeneralLedgerStructure, self).__init__(name, description)
        self.accounts = []

        ca = self._create_account_

        # create income statement account categories
        self._acci_unalloc_inc_ = ca("Unallocated Income Statement", "I05",
                                     AT.revenue)
        self._acci_sales_ = ca("Sales", "I10", AT.revenue)
        self._acci_cos_ = ca("Cost of Sales", "I15", AT.expense)
        self._acci_oth_inc_ = ca("Other Income", "I20", AT.revenue)
        self._acci_exp_ = ca("Expense", "I25", AT.expense)
        self._acci_tax_ = ca("Tax", "I30", AT.expense)
        self._acci_divs_ = ca("Dividends", "I35", AT.expense)

        # create balance sheet account categories
        self._accb_sh_cap_ = ca("Share Capital", "B10", AT.asset)
        self._accb_ret_inc_ = ca("Retained Income", "B15", AT.equity)
        self._accb_shh_loan_ = ca("Shareholders Loan", "B20", AT.liability)
        self._accb_lt_borrow_ = ca("Long Term Borrowing", "B25", AT.liability)
        self._accb_oth_lt_lia_ = ca("Other Long Term Liabilities", "B30",
                                    AT.liability)
        self._accb_fixed_ass_ = ca("Fixed Assets", "B35", AT.asset)
        self._accb_investments_ = ca("Investments", "B40", AT.asset)
        self._accb_oth_fixed_ass_ = ca("Other Fixed Assets", "B45", AT.asset)
        self._accb_inventory_ = ca("Inventory", "B50", AT.asset)
        self._accb_acc_receivable_ = ca("Accounts Receivable", "B55", AT.asset)
        self._accb_bank_ = ca("Bank", "B60", AT.asset)
        self._accb_bank_.create_account("Default", "0000")
        self._accb_oth_curr_ass_ = ca("Other Current Assets", "B65", AT.asset)
        self._accb_acc_payable_ = ca("Account Payable", "B70", AT.liability)
        self._accb_taxation_ = ca("Taxation", "B75", AT.liability)
        self._accb_oth_curr_lia_ = ca("Other Current Liabilities", "B80",
                                      AT.liability)

        # create the year end sub accounts
        self._acci_gross_prof_ = self._acci_unalloc_inc_.create_account(
            "Gross Profit", "0000")
        self._acci_inc_sum_ = self._acci_unalloc_inc_.create_account(
            "Income Summary", "0010")
        self._accb_ret_earnings_acc_ = self._accb_ret_inc_.create_account(
            "Retained Earnings", "0000")
        self._acci_inc_tax_exp_acc_ = self._acci_tax_.create_account(
            "Income Tax Expense", "0000")

        self.tax_payment_account = "Bank/Default"

    def __getitem__(self, key):
        items = [a for a in self.accounts if a.name == key]
        if len(items) == 0:
            return None
        else:
            return items[0]

    def __missing__(self, key):
        return None

    def _create_account_(self, name, number, account_type):
        """
        Create an account in the general ledger structure.

        :param name: The account name.
        :param number: The account number.
        :param account_type: The account type.

        :returns: The created account.
        """

        new_acc = GeneralLedgerAccount(name, None, number, account_type)
        self.accounts.append(new_acc)
        return new_acc

    def get_account(self, account_name):
        """
        Retrieves an account from the general ledger structure
        given the account name.

        :param account_name: The account name.

        :returns: The requested account, if found, else None.
        """

        if r'/' in account_name:
            accs_in_path = account_name.split(r'/', 1)

            curr_acc = self[accs_in_path[0]]
            if curr_acc is None:
                return None
            return curr_acc.get_child_account(accs_in_path[1])
            pass
        else:
            return self[account_name]

    def get_account_descendants(self, account):
        """
        Retrieves an account's descendants from the general ledger structure
        given the account name.

        :param account_name: The account name.

        :returns: The decendants of the account.
        """

        result = []
        for child in account.accounts:
            self._get_account_and_descendants_(child, result)
        return result

    def _get_account_and_descendants_(self, account, result):
        """
        Returns the account and all of it's sub accounts.

        :param account: The account.
        :param result: The list to add all the accounts to.
        """

        result.append(account)
        for child in account.accounts:
            self._get_account_and_descendants_(child, result)

    def validate_account_names(self, names):
        """
        Validates whether the accounts in a list of account names exists.

        :param names: The names of the accounts.

        :returns: The descendants of the account.
        """

        for name in names:
            if self.get_account(name) is None:
                raise ValueError("The account '{}' does not exist in the"
                                 "  general ledger structure.".format(name))

    def report(self, format=ReportFormat.printout, output_path=None):
        """
        Returns a report of this class.

        :param format: The format of the report.
        :param output_path: The path to the file the report is written to.
          If None, then the report is not written to a file.

        :returns: The descendants of the account.
        """

        rpt = GlsRpt(self, output_path)
        return rpt.render(format)

class GeneralLedger(NamedObject):
    """
    Represents the account structure of a general ledger.

    :param name: The name.
    :param structure: The general ledger structure.
    :param description: The description.
    """

    def __init__(self, name, structure, description=None):
        super(GeneralLedger, self).__init__(name, description)
        self.structure = structure
        self.transactions = []

    def create_transaction(self, name, description=None,
                           tx_date=datetime.min.date(),
                           dt_account=None, cr_account=None,
                           source=None, amount=0.00):
        """
        Create a transaction in the general ledger.

        :param name: The transaction's name.
        :param description: The transaction's description.
        :param tx_date: The date of the transaction.
        :param cr_account: The transaction's credit account's name.
        :param dt_account: The transaction's debit account's name.
        :param source: The name of source the transaction originated from.
        :param amount: The transaction amount.

        :returns: The created transaction.
        """

        new_tx = Transaction(name, description, tx_date,
                             dt_account, cr_account, source, amount)
        self.transactions.append(new_tx)
        return new_tx

    def transaction_list(self, start=datetime.min,
                         end=datetime.max,
                         format=ReportFormat.printout,
                         component_path="",
                         output_path=None):
        """
        Generate a transaction list report.

        :param start: The start date to generate the report for.
        :param end: The end date to generate the report for.
        :param format: The format of the report.
        :param component_path: The path of the component to filter the report's
          transactions by.
        :param output_path: The path to the file the report is written to.
          If None, then the report is not written to a file.

        :returns: The generated report.
        """

        rpt = TransactionList(self, start, end, component_path, output_path)
        return rpt.render(format)

    def balance_sheet(self, end=datetime.max,
                      format=ReportFormat.printout, output_path=None):
        """
        Generate a transaction list report.

        :param end: The end date to generate the report for.
        :param format: The format of the report.
        :param output_path: The path to the file the report is written to.
          If None, then the report is not written to a file.

        :returns: The generated report.
        """

        rpt = BalanceSheet(self, end, output_path)
        return rpt.render(format)

    def income_statement(self, start=datetime.min,
                         end=datetime.max,
                         format=ReportFormat.printout,
                         component_path="",
                         output_path=None):
        """
        Generate a transaction list report.

        :param start: The start date to generate the report for.
        :param end: The end date to generate the report for.
        :param format: The format of the report.
        :param component_path: The path of the component to filter the report's
          transactions by.
        :param output_path: The path to the file the report is written to.
          If None, then the report is not written to a file.

        :returns: The generated report.
        """

        rpt = IncomeStatement(self, start, end, component_path, output_path)
        return rpt.render(format)

from auxi.modelling.financial.reporting import GeneralLedgerStructure as GlsRpt
from auxi.modelling.financial.reporting import TransactionList
from auxi.modelling.financial.reporting import BalanceSheet
from auxi.modelling.financial.reporting import IncomeStatement

from auxi.modelling.financial.reporting import GeneralLedgerStructure as GlsRpt
from auxi.modelling.financial.reporting import TransactionList as TxList

if __name__ == "__main__":
    import unittest
    from auxi.modelling.financial.des_test import GeneralLedgerAccountUnitTester
    from auxi.modelling.financial.des_test import TransactionUnitTester
    from auxi.modelling.financial.des_test import TransactionTemplateUnitTester
    from auxi.modelling.financial.des_test import GeneralLedgerStructureUnitTester
    from auxi.modelling.financial.des_test import GeneralLedgerUnitTester
    unittest.main()


from setuptools import setup

with open("README.md", "r") as readme:
    long_description = readme.read()

setup(
    name="joshuaavalon-favicon",
    version="1.0.0",
    author="Joshua Avalon",
    url="https://github.com/joshuaavalon/favicon",
    description="Download favicon from urls",
    long_description=long_description,
    long_description_content_type="text/markdown",
    python_requires=">=3.7",
    packages=["joshuaavalon.favicon"],
    install_requires=[
        "Pillow>=5.3.0",
        "beautifulsoup4>=4.6.3",
        "requests>=2.21.0"
    ],
    classifiers=[
        "Programming Language :: Python :: 3",
        "Programming Language :: Python :: 3 :: Only",
        "Programming Language :: Python :: 3.7",
        "License :: OSI Approved :: Apache Software License",
        "Operating System :: OS Independent"
    ]
)


import sqlite3

import psycopg2
from psycopg2.extensions import connection as _connection

TABLES = ('film_work', 'genre', 'person', 'genre_film_work', 'person_film_work')

class DBExtractor:

    def __init__(self, connection: sqlite3.Connection | _connection):
        self.conn = connection
        self.cursor = connection.cursor()

    def data_generator(self):
        for row in self.cursor:
            yield dict(row)

    def extract_movies(self):
        for table in TABLES:
            if isinstance(self.conn, sqlite3.Connection):
                query = '''
                        SELECT *, (SELECT COUNT(*) FROM {}) as count FROM {} ORDER BY id;
                        '''.format(table, table)
            elif isinstance(self.conn, psycopg2.extensions.connection):
                query = '''
                        SELECT * FROM {} ORDER BY id;
                        '''.format(table)
            self.cursor.execute(query)
            yield self.data_generator()

        self.cursor.close()


# -*- utf-8 -*-
from django.urls import path, re_path
from . import views

app_name='blog'
urlpatterns = [
    re_path(r'^$', views.blog_title, name='blog_title'),
    re_path(r'(?P<article_id>\d)/$', views.blog_articles, name='blog_detail')
]


# NOTE :

# 1. This Project is for only webcam face detection
# 2. We can see in further projects , which is the extension of this where we can see to detect multiple faces in a clip.
# 3. Also we will see how  to detect faces in an image and  clip.

# STEP 1 : Install OpenCV
# Steps to Install : File > Setting > Project > Python Interpreter > "+" sign > Search  "opencv python" > click Install
# *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-

# STEP 2 : Import libraries

import cv2
from random import randrange as r

# *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-

# STEP 3 : Import HARR Cascade which contains tons of trained data which stored in a variable for further use

trained_data = cv2.CascadeClassifier("file.xml")

# *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-

# I use third party app for webcam purpose , you can inserty 1 or 0 instead video_path
# # STEP 4 : Open video camera

video_path = "https://192.168.1.201:8080/video"
capture = cv2.VideoCapture(video_path,cv2.CAP_DSHOW)
capture.open(video_path)
print("Your Webcam is :\nTrue : Open \nFalse:Close\n",capture.isOpened())

while (capture.isOpened()):

    ret,frame = capture.read()
    frame = cv2.resize(frame,(800,600))

# *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-

# STEP 5 : Grayscale Image

    grayscale = cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)

# *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-

# STEP 6 : Find out the Coordinates of the Gray scale image to recognise the Face
#          and then store in to a variable for further use.

    find_coordinates = trained_data.detectMultiScale(grayscale)

# *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-

# STEP 7 : Draw A rectangle around face to show the detected area .

    for x,y,w,h in find_coordinates:
        cv2.rectangle(frame, (x, y), ((x + w), (y + h)), (r(0, 255), r(0, 255), r(0, 255)), 8)
        cv2.imshow("final output",frame)

    key = cv2.waitKey(1) & 0xFF
    if key ==27:
        print("Congratulation ....\nYou have Successfully Detecting the Face")
        break

capture.release()
cv2.destroyAllWindows()

Image Face Recognition/Main File/03Webcam_face_detection.py


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

import os
import glob

import numpy as np
import seaborn as sns
import matplotlib.pylab as plt

import pickle
import pdb

# 1 data scatter ----
def Scatter(exact, predict, savepath='test'):

    #pdb.set_trace()
    sns.set_style('dark')

    # 45 linear
    line = np.arange(0.0,0.38,0.1)
    plt.plot(line, line, color='coral', linewidth=2)

    #pdb.set_trace()

    # scatter
    plt.scatter(exact, predict, c='dimgrey', linewidth=0.1)

    plt.savefig(os.path.join('figure', 'result', f'scatter_{savepath}.png'))
    plt.close()
# ----

# 2 data linear ----
def Linear(data1, data2, savepath='test'):

    #pdb.set_trace()

    sns.set_style('dark')

    # num of data
    y = [30, 60, 120, 240]

    fig = plt.figure()
    ax = fig.add_subplot(111)

    ax.plot(data1, y, color='skyblue', linewidth=5)
    ax.plot(data2, y, color='coral', linewidth=5)

    plt.savefig(os.path.join('figure', 'result', f'linear_{savepath}.png'))
    plt.close()
# ----

# ----

with open(os.path.join('model', 'burgers', f'IMGtestXTUNU2_large_noise100.pkl'), 'rb') as fp:
    _ = pickle.load(fp)
    _ = pickle.load(fp)
    _ = pickle.load(fp)
    exactnu = pickle.load(fp)
    _ = pickle.load(fp)
    #_ = pickle.load(fp)
    idx = pickle.load(fp)
#pdb.set_trace()
csvpath_k = glob.glob(os.path.join('savetxt','burgers_PINN','*csv'))
csvpath_p = glob.glob(os.path.join('savetxt','burgers_poNN','*csv'))

for kpath, ppath in zip(csvpath_k, csvpath_p):

    kpred = np.loadtxt(kpath, delimiter=',')
    ppred = np.loadtxt(ppath, delimiter=',')

    # mse
    mse_k = np.square(exactnu - kpred)
    mse_p = np.square(exactnu - ppred)

    # psnr
    psnr_k = 10 * np.log10(0.305**2/(mse_k+0.00000000000001))
    psnr_p = 10 * np.log10(0.305**2/(mse_p+0.00000000000001))

    # mean psnr
    mean_psnr_k = np.mean(psnr_k)
    mean_psnr_p = np.mean(psnr_p)

    # mean std
    mean_std_k = np.std(mse_k)
    mean_std_p = np.std(mse_p)

    kf = kpath.split('\\')[-1].split('.')[0]
    pf = ppath.split('\\')[-1].split('.')[0]

    print('----')
    print(kf)
    print(pf)
    print('PINN mean psnr: %.3f' % (mean_psnr_k))
    print('proposed mean psnr: %.3f' % (mean_psnr_p))
    print('PINN std std: %.10f' % (mean_std_k))
    print('proposed std psnr: %.10f' % (mean_std_p))

    Scatter(exactnu, kpred, savepath=f'{kf}')
    Scatter(exactnu, ppred, savepath=f'{pf}')
# ----
'''
# ----
# results of kNN
# lambda=0.01
l001_k = [14.0,20.1,27.6,43.7]
l01_k = [31.8,35.3,42.5,55.7]
l02_k = [21.6,28.2,44.6,51.6]
# lambda=0.1
m001_k = [14.8,20.1,27.6,43.7]
m01_k = [31.8,35.4,42.5,55.7]
m02_k = [21.6,28.2,44.6,57.6]
# lambda=0.2
s001_k = [14.8,20.1,27.6,43.7]
s01_k = [31.8,35.4,42.5,55.7]
s02_k = [21.6,28.2,44.6,51.6]

# results of our
l001_p = [83.7,83.7,83.7,83.7]
l01_p = [67.4,89.7,129.7,71.6]
l02_p = [44.2,48.0,51.6,48.4]

m001_p = [77.6,77.6,77.6,77.6]
m01_p = [68.9,70.6,77.6,83.7]
m02_p = [39.4,38.5,47.7,45.9]

s001_p = [72.8,72.8,72.8,72.8]
s01_p = [61.7,64.1,74.1,67.4]
s02_p = [47.8,36.0,46.4,54.6]

data = [[l001_k,l001_p],[l01_k,l01_p],[l02_k,l02_p],[m001_k,m001_p],[m01_k,m01_p],[m02_k,m02_p],[s001_k,s001_p],[s01_k,s01_p],[s02_k,s02_p]]
path = ['l001','l01','l02','m001','m01','m02','s001','s01','s02']

for d,p in zip(data, path):
    d1 = d[0]
    d2 = d[1]
    Linear(d1,d2,savepath=p)
# ----
'''


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Fri Oct 11 10:50:17 2019

@author: armandnasserischool
"""

import numpy as np
import pandas as pd
from numpy.linalg import inv
from sklearn.utils import shuffle

# Import the dataset and add labels
dataset = pd.read_csv('auto-mpg.data', delim_whitespace=True,
                       names=["mpg","Cylinder","Displacement","Horsepower","Weight","Acceleration",
                              "Year","Origin","Model"])
# Remove all ?'s
dataset = dataset.drop(dataset[dataset['Horsepower'] == '?'].index)
# Resest indexes
dataset = dataset.reset_index(drop=True)
# Typecast Horsepower column back to float
dataset['Horsepower'] = dataset['Horsepower'].apply(pd.to_numeric, errors='coerce')

# Assign each column a set of features and shuffling the dataset
mpg = shuffle(dataset.iloc[:,0].values, random_state = 0)
cyl = shuffle(dataset.iloc[:,1].values, random_state = 0)
disp = shuffle(dataset.iloc[:,2].values, random_state = 0)
hp = shuffle(dataset.iloc[:,3].values, random_state = 0)
wt = shuffle(dataset.iloc[:,4].values,random_state = 0)
acc = shuffle(dataset.iloc[:,5].values, random_state = 0)
yr = shuffle(dataset.iloc[:,6].values, random_state = 0)
org= shuffle(dataset.iloc[:,7].values, random_state = 0)

# Sort and find the cutoff threshold for each category
sortedMPG = np.sort(mpg)
low = sortedMPG[97]
med = sortedMPG[194]
high = sortedMPG[291]
vhigh = sortedMPG[391]

# Assigning each category to mpg values
# low
dataset.loc[mpg <= low, 'threshold'] = "low"
# med
dataset.loc[np.logical_and(mpg > low, mpg <= med), 'threshold']= "med"
# high
dataset.loc[np.logical_and(mpg > med, mpg < high), 'threshold']= "high"
# very high
dataset.loc[mpg >= high, 'threshold'] = "very high"

# Create a column of ones for bias
dataset.insert(10, 'bias', 1)
bias = dataset.iloc[:,10].values

# Splitting up train and test data
biasTrain = bias[0:292]
biasTest = bias[292:392]

mpg_train = mpg[0:292]
mpg_test = mpg[292:392]

# mpg vs. cyl
cyl_train = cyl[0:292]
cyl_test = cyl[292:392]

# mpg vs. disp
disp_train = disp[0:292]
disp_test = disp[292:392]

# mpg vs. hp
hp_train = hp[0:292]
hp_test = hp[292:392]

# mpg vs. wt
wt_train = wt[0:292]
wt_test = wt[292:392]

# mpg vs. acc
acc_train = acc[0:292]
acc_test = acc[292:392]

# mpg vs. yr
yr_train = yr[0:292]
yr_test = yr[292:392]

# mpr vs. org
org_train = org[0:292]
org_test = org[292:392]

def linReg(x,y):

    # degree 0 weights are simply the mean
    degreeZero = mpg.mean()

    # degree 1
    # Checking sizes for bias for train or test for to resolve dimension issues with train/test data
    if (x.size < 101 and y.size < 101):
        n1 = np.column_stack((biasTest, x))
        n11 = np.column_stack((biasTest, x))
        n111 = np.column_stack((biasTest, x))
    else:
        n1 = np.column_stack((biasTrain, x))
        n11 = np.column_stack((biasTrain, x))
        n111 = np.column_stack((biasTrain, x))

    # Applying the OLS Formula to acquire 1st degree weights
    n1Transposed = np.transpose(n1)
    n1Term1 = np.dot(n1Transposed,n1)
    invertedn1 = inv(n1Term1)
    n2Term2 = np.dot(n1Transposed,y)
    degreeOne = np.dot(invertedn1,n2Term2)
    w0 = degreeOne[0]
    w1 = degreeOne[1]

    # degree 2
    # Applying the OLS Formula to acquire 2nd degree weights
    n22 =np.column_stack((n11, x**2))
    n2Transposed = np.transpose(n22)
    n22Term1 = np.dot(n2Transposed,n22)
    invertedn2 = inv(n22Term1)
    n22Term2 = np.dot(n2Transposed,y)
    degreeTwo = np.dot(invertedn2,n22Term2)
    w00 = degreeTwo[0]
    w11 = degreeTwo[1]
    w22 = degreeTwo[2]

    # degree 3
    # Applying the OLS Formula to acquire 3rd degree weights
    n222 = np.column_stack((n111, x**2))
    n333 = np.column_stack((n222, x**3))
    n3Transposed = np.transpose(n333)
    n33Term1 = np.dot(n3Transposed,n333)
    invertedn3 = inv(n33Term1)
    n33Term2 = np.dot(n3Transposed,y)
    degreeThree = np.dot(invertedn3,n33Term2)
    w000 = degreeThree[0]
    w111 = degreeThree[1]
    w222 = degreeThree[2]
    w333 = degreeThree[3]

    # Printing and returning weights
    print("Oth Order Weights:",degreeZero)
    print("1st Order Weights:",w0,w1)
    print("2nd Order Weights:",w00,w11,w22)
    print("3rd Order Weights:",w000,w111,w222,w333)

    return degreeZero, degreeOne, degreeTwo, degreeThree

# Testing the linear regression function with sample data
testRegression = linReg(wt_train,mpg_train)