# coding: utf-8
import functools
import itertools
import operator
from openerp import models, fields, api, _, SUPERUSER_ID
from openerp.exceptions import UserError
from openerp.osv.orm import browse_record

def is_integer_list(ids):
    return all(isinstance(i, (int, long)) for i in ids)

class WizardDistrictMergeAutomatic(models.TransientModel):
    _name = 'wizard.district.merge.automatic'

    state = fields.Selection([('option', 'Option'),
                               ('selection', 'Selection'),
                               ('finished', 'Finished')],
                              'State', readonly=True, required=True, default='option')
    district_from = fields.Many2one('res.district', string='Account from')
    district_to = fields.Many2one('res.district', string='Account to')
    maximum_group = fields.Integer("Maximum of Group of Contacts")

    def get_fk_on(self, cr, table, tables=None):
        tables = tables and tuple(tables) or []
        where = tables and 'AND cli.relname in %s' % (str(tables))
        q = """  SELECT cl1.relname as table,
                        att1.attname as column
                   FROM pg_constraint as con, pg_class as cl1, pg_class as cl2,
                        pg_attribute as att1, pg_attribute as att2
                  WHERE con.conrelid = cl1.oid
                    AND con.confrelid = cl2.oid
                    AND array_lower(con.conkey, 1) = 1
                    AND con.conkey[1] = att1.attnum
                    AND att1.attrelid = cl1.oid
                    AND cl2.relname = %s
                    AND att2.attname = 'id'
                    AND array_lower(con.confkey, 1) = 1
                    AND con.confkey[1] = att2.attnum
                    AND att2.attrelid = cl2.oid
                    AND con.contype = 'f'
                    %s
        """
        return cr.execute(q, (table, tables and where or '',))

    def _update_foreign_keys(self, cr, uid, src_accounts, dst_account,
                             model=None, context=None):
        # find the many2one relation to a account
        account_bad = []

        self.get_fk_on(cr, 'res_district')
        for table, column in cr.fetchall():
            if 'wizard_account_merge_automatic' in table:
                continue

            account_ids = tuple(map(int, src_accounts))

            query = """SELECT column_name FROM information_schema.columns
                       WHERE table_name LIKE '%s'""" % (
                table)
            cr.execute(query, ())
            columns = []
            for data in cr.fetchall():
                if data[0] != column:
                    columns.append(data[0])

            query_dic = {
                'table': table,
                'column': column,
                'value': columns[0],
            }

            #THANH: Value can be id or a field in many2many relation table
            query = """
                UPDATE "%(table)s" as ___tu
                SET %(column)s = %%s
                WHERE
                    %(column)s = %%s AND
                    NOT EXISTS (
                        SELECT 1
                        FROM "%(table)s" as ___tw
                        WHERE
                            %(column)s = %%s AND
                            ___tu.%(value)s = ___tw.%(value)s
                    )""" % query_dic
            for account_id in account_ids:
                cr.execute(query, (
                    dst_account.id, account_id, dst_account.id))
        return account_bad

    def _update_reference_fields(self, cr, uid, src_district, dst_district, context=None):
        account_bad = []

        def update_records(model, src, field_model='model',
                           field_id='res_id', context=None):
            proxy = self.pool.get(model)
            if proxy is None:
                return
            domain = [(field_model, '=', 'res.district'), (
                field_id, '=', src.id)]
            ids = proxy.search(
                cr, SUPERUSER_ID, domain, context=context)
            return proxy.write(cr, SUPERUSER_ID, ids,
                               {field_id: dst_district.id},
                               context=context)

        update_records = functools.partial(update_records,
                                           context=context)

        proxy = self.pool['ir.model.fields']
        domain = [('ttype', '=', 'reference')]
        record_ids = proxy.search(
            cr, SUPERUSER_ID, domain, context=context)

        for record in proxy.browse(cr, SUPERUSER_ID, record_ids,
                                   context=context):
            proxy_model = self.pool[record.model]

            field_type = proxy_model._columns.get(record.name).__class__._type

            if field_type == 'function':
                continue

            for district in src_district:
                domain = [
                    (record.name, '=', 'res.district,%d' % district.id)
                ]
                model_ids = proxy_model.search(
                    cr, SUPERUSER_ID, domain, context=context)
                values = {
                    record.name: 'res.district,%d' % dst_district.id,
                }
                proxy_model.write(
                    cr, SUPERUSER_ID, model_ids, values,
                    context=context)
        return account_bad

    def _update_values(self, cr, uid, src_district, dst_district, context=None):
        account_bad = []
        columns = dst_district._columns

        def write_serializer(column, item):
            if isinstance(item, browse_record):
                return item.id
            else:
                return item

        values = dict()
        for column, field in columns.iteritems():
            if field._type not in ('many2many', 'one2many'):
                for item in itertools.chain(src_district, [dst_district]):
                    if item[column]:
                        values[column] = write_serializer(column, item[column])
        return account_bad

    def close_cb(self, cr, uid, ids, context=None):
        return {'type': 'ir.actions.act_window_close'}

    def _merge(self, cr, uid, district_ids, dst_district=None, context=None):
        proxy = self.pool.get('res.district')
        district_ids = proxy.exists(
            cr, uid, list(district_ids), context=context)
        if len(district_ids) < 2:
            return True

        if len(district_ids) > 10:
            raise UserError(_('Error!'), _(
                """
                For safety reasons, you cannot merge more than 10 accounts
                together. You can re-open the wizard several
                times if needed.
                """))
        if dst_district and dst_district.id in district_ids:
            src_district = proxy.browse(cr, uid, [
                                        id for id in district_ids
                                        if id != dst_district.id],
                                        context=context)
        else:
            ordered_accounts = self._get_ordered_district(
                cr, uid, district_ids, context)
            dst_district = ordered_accounts[-1]
            dst_district = ordered_accounts[:-1]

        if SUPERUSER_ID != uid and \
                self._model_is_installed(cr, uid, 'account.move.line',
                                         context=context) and \
                self.pool.get('account.move.line').\
        search(cr, SUPERUSER_ID,
                    [('account_id', 'in', [district.id for district in dst_district])],
                    context=context):
            raise UserError(_('Error!'), _(
                """Only the destination account may be linked to existing
                   Journal Items. Please ask the Administrator if you need
                   to merge several accounts linked to existing Journal
                   Items."""))
        call_it = lambda function: function(
            cr, uid, src_district, dst_district, context=context)
        district_bad = []

        district_bad += call_it(self._update_foreign_keys)
        district_bad += call_it(self._update_reference_fields)
        district_bad += call_it(self._update_values)
        district_bad = set(district_bad)
        for district in src_district:
            if district.id not in district_bad:
                #Kiet: DELETE it to inactive
                sql = '''
                    DELETE FROM res_district where id = %s
                '''%(district.id)
                cr.execute(sql)
                proxy.exists(cr, uid, district.id, context=context)
        return True

    def _get_ordered_district(self, cr, uid, account_ids, context=None):
        districts = self.pool.get('res.district').browse(
            cr, uid, list(account_ids), context=context)
        ordered_districts = sorted(
            sorted(districts, key=operator.attrgetter('create_date'),
                   reverse=True),
            key=operator.attrgetter('active'), reverse=True)
        return ordered_districts

    def _model_is_installed(self, cr, uid, model, context=None):
        proxy = self.pool.get('ir.model')
        domain = [('model', '=', model)]
        return proxy.search_count(cr, uid, domain, context=context) > 0

    def merge_cb(self, cr, uid, ids, context=None):
        assert is_integer_list(ids)

#         context = dict(context or {}, active_test=False)
#         this = self.browse(cr, uid, ids[0], context=context)
#         sql ='''
#             SELECT count(id), name
#             FROM res_district
#             group by name
#             having count(id)>1
#         '''
#         cr.execute(sql)
#         for i in cr.dictfetchall():
#             sql ='''
#                 SELECT id from res_district where name = '%s'
#                 order by id
#             '''%(i['name'])
#             cr.execute(sql)
#             i = 1
#             district_to = district_from = False
#             for j in cr.dictfetchall():
#                 if i == 1:
#                     district_from = j['id']
#                     i +=1
#                     continue
#                 if i == 2:
#                     district_to = self.pool.get('res.district').browse(cr,uid,j['id'])
#                     i +=1
#                     continue
#
#             p_ids = [district_to]
#             district_ids = set(map(int, district_from and
#                                   [district_to, district_from] or
#                                   p_ids))
#
#             self._merge(cr, uid, district_ids, district_to,
#                     context=context)
        context = dict(context or {}, active_test=False)
        this = self.browse(cr, uid, ids[0], context=context)
        p_ids = [this.district_to]
        district_ids = set(map(int, this.district_from and
                              [this.district_to, this.district_from] or
                              p_ids))
        if not list(district_ids):
            raise UserError(_('Error!'), _(
                """The account from must be selected for
                    this option."""))
        else:
            self._merge(cr, uid, district_ids, this.district_to,
                        context=context)
        return True


from os import path
from . import views
from . import views
from django.urls import path
from django.conf import settings
from django.conf.urls.static import static
from django.urls import path
from .views import creer_groupe, autocomplete_etudiants
urlpatterns = [
    path('', views.login, name='login'),
    path('index', views.index, name='index'),
    path('logout/', views.logout, name='logout'),
    path('register/', views.register, name='register'),

   # dep
    path('dep/<int:pk>/update/', views.depUpdateView.as_view(), name='dep_update'),
    path('dep/<int:pk>/delete/', views.depDeleteView.as_view(), name='delete_dep'),
    path('dep/', views.dep, name='dep'),
    path('create_dep/', views.depCreateView.as_view(), name='create_dep'),

    # entre
    path('entre/<int:pk>/update/', views.entreUpdateView.as_view(), name='entre_update'),
    path('entre/<int:pk>/delete/', views.entreDeleteView.as_view(), name='delete_entre'),
    path('entre/', views.entre, name='entre'),
    path('create_entre/', views.entreCreateView.as_view(), name='create_entre'),

    path('et/', views.et, name='et'),
    path('add_etudiant/', views.add_etudiant, name='add_etudiant'),
    # etud
    path('etud/<int:pk>/update/', views.etudUpdateView.as_view(), name='etud_update'),
    path('etud/<int:pk>/delete/', views.etudDeleteView.as_view(), name='delete_etud'),
    path('etud/', views.etud, name='etud'),
    path('createetud/', views.etudCreateView.as_view(), name='create_etud'),

     path('encours/', views.encours, name='encours'),

   # Type_Encadrant
    path('Type_Encadrant/<int:pk>/update/', views.Type_EncadrantUpdateView.as_view(), name='Type_Encadrant_update'),
    path('Type_Encadrant/<int:pk>/delete/', views.Type_EncadrantDeleteView.as_view(), name='delete_Type_Encadrant'),
    path('type_Encadrant/', views.type_Encadrant, name='type_Encadrant'),
    path('create_Type_Encadrant/', views.Type_EncadrantCreateView.as_view(), name='create_Type_Encadrant'),

   # Type_stage
    path('type_stage/<int:pk>/update/', views.type_stageUpdateView.as_view(), name='type_stage_update'),
    path('type_stage/<int:pk>/delete/', views.type_stageDeleteView.as_view(), name='delete_type_stage'),
    path('type_stage/', views.type_stage, name='type_stage'),
    path('create_type_stage/', views.type_stageCreateView.as_view(), name='create_type_stage'),

     #Simester
    path('simester/<int:pk>/update/', views.simesterUpdateView.as_view(), name='simester_update'),
    path('simester/<int:pk>/delete/', views.simesterDeleteView.as_view(), name='delete_simester'),
    path('simester/', views.simester, name='simester'),
    path('create_simester/', views.simesterCreateView.as_view(), name='create_simester'),

    # encadrant
    path('encadrant/<int:pk>/update/', views.encadrantUpdateView.as_view(), name='encadrant_update'),
    path('encadrant/<int:pk>/delete/', views.encadrantDeleteView.as_view(), name='delete_encadrant'),
    path('encadrant/', views.encadrant, name='encadrant'),
    path('createencadrant/', views.encadrantCreateView.as_view(), name='create_encadrant'),

    #etd
    path('etd/', views.etd, name='etd'),
    path('addetd/', views.addetd, name='addetd'),
    #encad
    path('encad/', views.encad, name='encad'),
     #stg
    path('stg/', views.stg, name='stg'),
     #stg
    path('stage/', views.stage, name='stage'),
    path('ajouter_groupe/',views.ajouter_groupe, name='ajouter_groupe'),
    path('ajouter_stage/',views.ajouter_stage, name='ajouter_stage'),
    path('ajouter_encd/',views.ajouter_encd, name='ajouter_encd'),

    path('import/', views.import_excel, name='import_excel'),

    path('creer-groupe/', creer_groupe, name='creer_groupe'),
    path('autocomplete-etudiants/', autocomplete_etudiants, name='autocomplete_etudiants'),

    path('export_excel/', views.export_excel, name='export_excel'),

    path('export_excel/', views.export_excel, name='export_excel'),

    path('compte/', views.compte, name='compte'),

]


from django.http import HttpResponse
from django.shortcuts import render
from .models import Producto, Categoria, Proveedor
def inicio(request):
    return render(request, 'home.html')

def productos(request):
    productos = Producto.objects.all()
    proovedor = Proveedor.objects.all()
    categorias = Categoria.objects.all()
    return render(request, 'productos.html', {'productos':productos, 'proveedor':proovedor, 'categorias':categorias})

def productoFormulario(request):
    if request.method == 'POST':
        categoria_id = request.POST.get('categoria')
        proveedor_id = request.POST.get('proveedor')
        if categoria_id == 'nueva':
            # Seleccionó una nueva categoría, con lo cual primero lo guardo.
            nueva_categoria = Categoria(nombre=request.POST['nueva_categoria'])
            nueva_categoria.save()
            categoria_id = nueva_categoria.id #Guardo el id de la categoria generada, para poder referenciarla posteriormente.
        if proveedor_id == 'nueva':
            nuevo_proveedor = Proveedor(nombre=request.POST['nuevo_proveedor'])
            nuevo_proveedor.save()
            proveedor_id = nuevo_proveedor.id
        producto = Producto.objects.create(nombre=request.POST['nombre'],precio=request.POST['precio'],stock=request.POST['stock'],categoria_id=categoria_id, proveedor_id=proveedor_id)
        producto.save()
        return render(request, 'home.html')
    proveedores = Proveedor.objects.all()
    categorias = Categoria.objects.all()
    return render(request, 'productoFormulario.html', {'categorias':categorias})


#!/usr/bin/env python2

import numpy as np
from numpy import cos,sin
import matplotlib.pyplot as plt
from mpl_toolkits import mplot3d
from scipy import optimize

import rospy
from geometry_msgs.msg import Vector3
from sensor_msgs.msg import Imu
from sensor_msgs.msg import MagneticField
import time
import os

from filter_lib import *

def rotation_matrix(pitch, roll):

	R_pitch  = np.array([[cos(pitch),0,-sin(pitch)],[0,1,0],[sin(pitch),0,cos(pitch)]])
	R_roll   = np.array([[1,0,0],[0,cos(roll),sin(roll)],[0,-sin(roll),cos(roll)]])
	R_repere = np.array([[0,-1,0],[-1,0,0],[0,0,1]])

	return np.dot(R_repere,np.dot(R_pitch,R_roll))

##############################################################################################
#      ROS
##############################################################################################

# http://docs.ros.org/melodic/api/sensor_msgs/html/msg/Imu.html
def sub_imu_nf(data):
	global vect_imu, vect_temps, get
	#rospy.loginfo("Pos x : %s, Pos y : %s",data.x, data.y)
	vect_imu[0,0] = data.linear_acceleration.x # ax
	vect_imu[1,0] = data.linear_acceleration.y # ay
	vect_imu[2,0] = data.linear_acceleration.z # az
	vect_imu[3,0] = data.angular_velocity.x    # gx
	vect_imu[4,0] = data.angular_velocity.y    # gy
	vect_imu[5,0] = data.angular_velocity.z    # gz
	t = data.header.stamp.nsecs
	vect_temps = np.array([vect_temps[1],t,(t-vect_temps[1])/1000.])
	get = 1

def sub_mag_nf(data):
	global vect_imu
	#rospy.loginfo("Pos x : %s, Pos y : %s",data.x, data.y)
	vect_imu[6,0] = data.magnetic_field.x         # mx
	vect_imu[7,0] = data.magnetic_field.y         # my
	vect_imu[8,0] = data.magnetic_field.z         # mz

##############################################################################################
#      Calibration
##############################################################################################

def resSphere(p,x,y,z):
	""" residuals from sphere fit """

	a,b,c,r = p                             # a,b,c are center x,y,c coords to be fit, r is the radius to be fit
	distance = np.sqrt( (x-a)**2 + (y-b)**2 + (z-c)**2 )
	err = distance - r                 # err is distance from input point to current fitted surface

	return err

def calibrate_imu(n = 200):# number of points to calibrate

	# --- Get data ---------------------------------------------------------- #
	mx,my,mz = np.zeros(n), np.zeros(n), np.zeros(n)
	counter = 0
	while counter < n: # while there is not enough values
		a = vect_imu.copy()
		rospy.sleep(0.01)
		if not(np.all(a==vect_imu)): #each time we have a new value
			mx[counter],my[counter],mz[counter] = a[6,0],a[7,0],a[8,0] # the value is added
			counter += 1
			rospy.loginfo(counter)

	params = [0.,0.,0.,0.]
	myResult = optimize.leastsq(resSphere, params, args=(mx,my,mz) )
	ox, oy, oz, r = myResult[0]
	rospy.loginfo(myResult[0])

	# ---- Save in text file ------------------------------------------------- #
	THIS_FOLDER = os.path.dirname(os.path.abspath(__file__))
	my_file = os.path.join(THIS_FOLDER, 'imu_previous_calibration.txt')
	f = open(my_file,'w')
	#f.write('offset_x:{}\noffset_y:{}\noffset_z:{}'.format(np.mean(mx), np.mean(my), np.mean(mz)))
	f.write('offset_x:{}\noffset_y:{}\noffset_z:{}'.format(-ox,-oy,-oz))
	f.close()
	offset = np.zeros((9,1))
	offset[6,0],offset[7,0],offset[8,0] = -ox,-oy,-oz
	return offset

def get_previous_imu():
	THIS_FOLDER = os.path.dirname(os.path.abspath(__file__))
	my_file = os.path.join(THIS_FOLDER, 'imu_previous_calibration.txt')
	f = open(my_file,'r')
	doc = f.readlines()
	f.close()
	offset = np.zeros((9,1))
	for i in range(len(doc)):
		offset[i+6] = float(doc[i].split(':')[1])
	rospy.loginfo(offset)
	return offset

##############################################################################################
#      Filtre
##############################################################################################

# ----  EKF plus dur --------------------------------------------------------- #

def f(x,u):
	dt = vect_temps[2]
	mat = np.array([[1,-dt*u,0],[dt*u,1,0],[0,0,1]])
	mat = np.matmul(mat,x)
	return mat

def F(x,u):
	dt = vect_temps[2]
	mat = np.array([[1,-dt*u,0],[dt*u,1,0],[0,0,1]])
	return mat

def h(x):
	x1,x2 = x[0,0],x[1,0]
	mat = np.array([[x1],[x2],[x1**2+x2**2]])
	return mat

def H(x):
	x1,x2 = x[0,0],x[1,0]
	mat = np.array([[1,0,0],[0,1,0],[2*x1,2*x2,0]])
	return mat

def EKF_predict(x_prec,P_prec,u,f,F):
	Fx = F(x_prec,u)
	x_pred = f(x_prec,u)
	P_pred = np.matmul(np.matmul(Fx,P_prec),np.transpose(Fx))+Q
	return(x_pred,P_pred)

def EKF_update(z,x_pred,P_pred,h,H):
	Hk = H(x_pred)
	#innovation
	y = z - h(x_pred)
	S = np.matmul(np.matmul(Hk,P_pred),np.transpose(Hk))+R
	# Kalman gain
	K = np.matmul(np.matmul(P_pred,np.transpose(Hk)),np.linalg.inv(S))
	# Update
	x = x_pred + np.matmul(K,y)
	I = np.eye(P_pred.shape[0])
	P = np.matmul((I-np.matmul(K,Hk)), P_pred)

	return [x,P]

##############################################################################################
#      Display
##############################################################################################

def clear(ax):
    plt.pause(0.001)
    plt.cla()
    a = 15
    ax.set_xlim(-a,a)
    ax.set_ylim(-a,a)
    ax.set_zlim(-a,a)

def display_mag(offset, scale=1):

	fig = plt.figure()
	ax = plt.axes(projection='3d')
	l = []

	t0 = time.time()
	while not rospy.is_shutdown():
		m = (vect_imu + offset)*scale
		mx,my,mz = m[6,0],m[7,0],m[8,0]
		l.append([mx,my,mz])
		clear(ax)
		ax.plot([0,mx],[0,my],[0,mz],'r')
		ax.plot([0,mx],[0,0],[0,0],'b')
		ax.plot([mx,mx],[0,my],[0,0],'b')
		ax.plot([mx,mx],[my,my],[0,mz],'b')
		ax.plot([0,10],[0,0],[0,0],'g')
		ax.plot([0,0],[0,5],[0,0],'g')
		ax.plot([0,0],[0,0],[0,5],'g')
		for i in l:
			ax.scatter(i[0],i[1],i[2])
		#rospy.loginfo(np.arctan2(my,mx)*180/np.pi)
		rospy.loginfo(np.sqrt(mx**2+my**2+mz**2))

##############################################################################################
#      Main
##############################################################################################

vect_imu = np.zeros((9,1)) # ax;ay;az;gx;gy;gz;mx;my;mz
vect_temps = np.array([0,0,0]) # t_prec, t_curr, dt
get = 0

if __name__ == '__main__':
	# kalman : https://pdfs.semanticscholar.org/7274/0405dcf42373fd4ed6fbd0a6f2d8d2208590.pdf

	try:
		# Three calibration modes :
		# 'None' for no calibration, 'New' for new calibration, 'Previous' to take the previous one
		calibration = 'Previous'
		rospy.init_node('filtre_imu')
		rospy.Subscriber("ardu_send_imu", Imu, sub_imu_nf)
		rospy.Subscriber("ardu_send_mag", MagneticField, sub_mag_nf)
		if calibration == 'Previous':
			offset = get_previous_imu()
		elif calibration == 'New':
			offset = calibrate_imu()
		else:

			offset = np.zeros((9,1))

		raw_imu = vect_imu + offset
		low_pass_imu = raw_imu.copy()

		#display_mag(offset, scale)
		alpha = 0.3

		pub_send_euler_angles = rospy.Publisher('imu_send_euler_angles', Vector3, queue_size=10)
		euler_angles_msg = Vector3()

		Gx_yaw = np.array([[2,0],[0,1]])
		Gx_pitch = np.array([[2,0],[0,1]])
		Gx_roll = np.array([[2,0],[0,1]])
		xhat_yaw = np.array([[0],[0]])
		xhat_pitch = np.array([[0],[0]])
		xhat_roll = np.array([[0],[0]])
		Galpha = 0.028**2*np.eye(2,2)#0.028**2
		Gbeta = 0.095*np.eye(2)# 0.095**2

		dt = vect_temps[2]
		A = np.array([[1,-dt*raw_imu[5,0]],[dt*raw_imu[5,0],1]])
		C = np.array([[1,0],[0,1]])
		kf_yaw = Kalman_filter(xhat_yaw,Gx_yaw,A,0,C,Galpha,Gbeta)

		x_EKF_yaw = np.array([[0],[0],[0]])
		P_EKF_yaw = 10*np.eye(3)
		x_EKF_pitch = np.array([[0],[0],[0]])
		P_EKF_pitch = 10*np.eye(3)
		x_EKF_roll = np.array([[0],[0],[0]])
		P_EKF_roll = 10*np.eye(3)

		n = 5
		lx,ly = np.zeros(n),np.zeros(n)

		l_temps = []
		l_yaw_EKF = []
		l_yaw_kalman = []
		l_yaw_raw = []
		#l_pitch_EKF = []
		#l_pitch_kalman = []
		#l_pitch_raw = []
		#l_roll_EKF = []
		#l_roll_kalman = []
		#l_roll_raw = []

		C_pitch = np.arctan2(raw_imu[1,0],raw_imu[0,0])
		while not rospy.is_shutdown():
			raw_imu = (vect_imu + offset) * 1
			#display_mag(offset)
			#prev_yaw = raw_roll_pitch_yaw(new_imu, prev_yaw)
			rospy.sleep(0.01)
			a = raw_imu.copy()

			if get == 1:#not(np.all(a==vect_imu)): #each time we have a new value
				get = 0
				low_pass_imu = a#alpha*a +(1-alpha)*low_pass_imu
				ax,ay,az = low_pass_imu[0,0],low_pass_imu[1,0],low_pass_imu[2,0]
				gx,gy,gz = low_pass_imu[3,0],low_pass_imu[4,0],low_pass_imu[5,0]
				mx,my,mz = low_pass_imu[6,0],low_pass_imu[7,0],low_pass_imu[8,0]
				dt = vect_temps[2]
				#lx[:n-1],ly[:n-1] = lx[1:], ly[1:]
				#lx[n-1],ly[n-1] = mx,my
				#rospy.loginfo([np.median(l),a[7,0]])
				#rospy.loginfo([np.arctan2(np.median(ly),np.median(lx))*180/np.pi,np.arctan2(my,mx)*180/np.pi,np.arctan2(a[7,0],a[6,0])*180/np.pi])

				# ----  Calcul des angles ------------------------------------------------------ #

				A_pitch = np.arctan2(ay,az)
				A_roll = np.arctan2(-ax,np.sqrt(ay**2+az**2))
				Mx = mx*cos(A_pitch)+mz*sin(A_pitch) #tilt compensation
				My = mx*sin(A_roll)*sin(A_pitch)+my*cos(A_roll)-mz*sin(A_roll)*cos(A_pitch)
				G_yaw = np.arctan2(-My,Mx)

				# ----  Kalman Filter ---------------------------------------------------------- #

				#[xhat_yaw,Gx_yaw]     = use_kalman(xhat_yaw  ,Gx_yaw  ,G_yaw  ,-gz)
				A = np.array([[1,-dt*gz],[dt*gz,1]])
				y = np.array([[np.cos(G_yaw)],[np.sin(G_yaw)]])
				[xhat_yaw,Gx_yaw] = kf_yaw.kalman_step(0,y,A)
				#[xhat_pitch,Gx_pitch] = use_kalman(xhat_pitch,Gx_pitch,A_pitch,gx)
				#[xhat_roll,Gx_roll]   = use_kalman(xhat_roll ,Gx_roll ,A_roll ,gy)

				#rospy.loginfo([kalman_to_deg(xhat_yaw),kalman_to_deg(xhat_pitch),kalman_to_deg(xhat_roll)])

				#R_mat = rotation_matrix(kalman_to_rad(xhat_pitch),kalman_to_rad(xhat_roll))
				#acc_NED = np.dot(np.linalg.inv(R_mat),np.array([[ax],[ay],[az]]))

				Q = 0.028**2*np.eye(3)#0.028
				R = 0.1*np.eye(3)

				# ----  Extended Kalman Filter ------------------------------------------------- #

				[x_p_yaw,P_p_yaw] = EKF_predict(x_EKF_yaw,P_EKF_yaw,-gz,f,F)
				z = np.array([[np.cos(G_yaw)],[np.sin(G_yaw)],[1]])
				[x_EKF_yaw,P_EKF_yaw] = EKF_update(z,x_p_yaw,P_p_yaw,h,H)
				yaw_EKF = np.arctan2(x_EKF_yaw[1,0],x_EKF_yaw[0,0])-0.035
				#rospy.loginfo([np.arctan2(x_EKF[1,0],x_EKF[0,0])*180/np.pi,kalman_to_deg(xhat_yaw),G_yaw*180/np.pi])

				[x_p_pitch,P_p_pitch] = EKF_predict(x_EKF_pitch,P_EKF_pitch,gx,f,F)
				z = np.array([[np.cos(A_pitch)],[np.sin(A_pitch)],[1]])
				[x_EKF_pitch,P_EKF_pitch] = EKF_update(z,x_p_pitch,P_p_pitch,h,H)
				pitch_EKF = np.arctan2(x_EKF_pitch[1,0],x_EKF_pitch[0,0])-0.018

				[x_p_roll,P_p_roll] = EKF_predict(x_EKF_roll,P_EKF_roll,gy,f,F)
				z = np.array([[np.cos(A_roll)],[np.sin(A_roll)],[1]])
				[x_EKF_roll,P_EKF_roll] = EKF_update(z,x_p_roll,P_p_roll,h,H)
				roll_EKF = np.arctan2(x_EKF_roll[1,0],x_EKF_roll[0,0])+0.008

				v = ax**2+ay**2+az**2
				coeff = min(abs(v-1.05),0.15)/0.15
				C_pitch = (C_pitch + dt*gx)#*coeff + A_pitch*(1-coeff)
				rospy.loginfo([C_pitch,v,coeff])

				euler_angles_msg.x = yaw_EKF
				euler_angles_msg.y = pitch_EKF
				euler_angles_msg.z = roll_EKF
				pub_send_euler_angles.publish(euler_angles_msg)

				l_temps.append(vect_temps[1])
				l_yaw_raw.append(A_pitch*180/np.pi)
				l_yaw_kalman.append(C_pitch*180/np.pi)
				l_yaw_EKF.append(pitch_EKF*180/np.pi)
				#l_pitch_raw.append(A_pitch*180/np.pi)
				#l_pitch_kalman.append(kalman_to_deg(xhat_pitch))
				#l_pitch_EKF.append(pitch_EKF*180/np.pi)
				#l_roll_raw.append(A_roll*180/np.pi)
				#l_roll_kalman.append(kalman_to_deg(xhat_roll))
				#l_roll_EKF.append(roll_EKF*180/np.pi)

				#plt.subplot('131')
				plt.plot(l_temps,l_yaw_raw,'b')
				plt.plot(l_temps,l_yaw_kalman,'r')
				plt.plot(l_temps,l_yaw_EKF,'g')
				plt.xlim((vect_temps[1]-5000,vect_temps[1]))
				plt.ylim((-50,50))
				#plt.subplot('132')
				#plt.plot(l_temps,l_pitch_raw,'b')
				#plt.plot(l_temps,l_pitch_kalman,'r')
				#plt.plot(l_temps,l_pitch_EKF,'g')
				#plt.xlim((vect_temps[1]-5000,vect_temps[1]))
				#plt.ylim((-50,50))
				#plt.subplot('133')
				#plt.plot(l_temps,l_roll_raw,'b')
				#plt.plot(l_temps,l_roll_kalman,'r')
				#plt.plot(l_temps,l_roll_EKF,'g')
				#plt.xlim((vect_temps[1]-5000,vect_temps[1]))
				#plt.ylim((-10,10))
				plt.pause(0.01)
				plt.cla()

	except rospy.ROSInterruptException:
		pass


from .module_types import (
    single,
    integer,
    idx,
    dword,
    word,
    byte,
    sized_ascii_z,
    float,
    qword,
    Computed,
)
from construct import Struct, this, Probe, Int16sl

color = Struct("R" / byte, "G" / byte, "B" / byte, "A" / byte)

vector = Struct("x" / single, "y" / single, "z" / single)

pointregion = Struct("zone" / idx, "ileaf" / integer, "zonenumber" / byte)

rotator = Struct("yaw" / integer, "roll" / integer, "pitch" / integer)

scale = Struct(
    "x" / single, "y" / single, "z" / single, "sheerrate" / single, "sheeraxis" / byte
)

plane = Struct(*vector.subcons, "w" / single)

sphere = Struct(*plane.subcons)

quat = Struct("x" / single, "y" / single, "z" / single, "w" / single)

polygon = Struct(
    "vertex_array_size" / idx,
    "base" / vector,
    "normal" / vector,
    "texture_u" / vector,
    "texture_v" / vector,
    "vertex" / vector[this.vertex_array_size],
    "poly_flags" / dword,
    "actor" / idx,
    "texture" / idx,
    "item_name" / idx,
    "i_link" / idx,
    "i_brush_poly" / idx,
    "pan_u" / Int16sl,
    "pan_v" / Int16sl,
)

url = Struct(
    "protocol" / sized_ascii_z,
    "host" / sized_ascii_z,
    "map" / sized_ascii_z,
    "size" / idx,
    "options" / sized_ascii_z[this.size],
    "portal" / sized_ascii_z,
    "port" / dword,
    "valid" / dword,
)

named_bone = Struct("name_idx" / idx, "flags" / dword, "parent_index" / dword,)

analog_track = Struct(
    "flags" / dword,
    "num_key_quats" / idx,
    "key_quats" / quat[this.num_key_quats],
    "num_key_pos" / idx,
    "key_pos" / vector,
    "num_key_times" / idx,
    "key_times" / single[this.num_key_times],
)

motion_chunk = Struct(
    "root_speed_vector" / vector,
    "track_time" / single,
    "start_bone" / dword,
    "flags" / dword,
    "num_indeces" / idx,
    "bone_indeces" / dword[this.num_indeces],
    "num_anims" / idx,
    "anim_tracks" / analog_track[this.num_anims],
    "root_track" / analog_track,
)

bounding_box = Struct("min" / vector, "max" / vector, "valid" / byte)

bounding_sphere = Struct(
    "center" / vector, "radius" / float  # only valid if version > 61
)

bsp_node = Struct(
    "plane" / plane,
    "zone_mask" / qword,
    "node_flags" / byte,
    "vert_pool_index" / idx,
    "suface_index" / idx,
    "front_index" / idx,
    "back_index" / idx,
    "plane_index" / idx,
    "collision_bound_index" / idx,
    "render_bound_index" / idx,
    "zone_index" / byte[2],
    "num_vertices" / byte,
    "leaf_index" / dword[2],
)

bsp_surface = Struct(
    "texture_index" / idx,
    "poly_flags" / dword,
    "p_base" / idx,
    "v_normal" / idx,
    "v_texture_u" / idx,
    "v_texture_v" / idx,
    "lightmap_index" / idx,
    "brush_poly_index" / idx,
    "pan_u" / word,
    "pan_v" / word,
    "actor" / idx,
)

f_vertex = Struct("p_vertex" / idx, "side_index" / idx)

mesh_vertex = Struct(
    # if game is not Deus Ex, these will be sized differently
    "x" / Int16sl,
    "y" / Int16sl,
    "z" / Int16sl,
    "trash" / Int16sl,
)

triangle = Struct(
    "vertex1" / word,
    "vertex2" / word,
    "vertex3" / word,
    "u1" / byte,
    "v1" / byte,
    "u2" / byte,
    "v2" / byte,
    "u3" / byte,
    "v3" / byte,
    "flags" / dword,
    "texture_index" / dword,
)

anim_seq_notify = Struct("time" / float, "function_index" / idx)

anim_seq = Struct(
    "name_index" / idx,
    "group_index" / idx,
    "startframe" / dword,
    "numframes" / dword,
    "num_notifys" / idx,
    "notifys" / anim_seq_notify[this.num_notifys],
    "rate" / float,
)

connect = Struct("num_vert_tiangles" / dword, "triangle_list_offset" / dword)

struct_texture = Struct("index" / idx)

face = Struct(
    "wedge_index_1" / word,
    "wedge_index_2" / word,
    "wedge_index_3" / word,
    "material_index" / word,
)

material = Struct("flags" / dword, "texture_index" / dword,)

wedge = Struct("vertex_index" / word, "u" / byte, "v" / byte,)

zone = Struct("actor" / idx, "connectivity" / qword, "visibility" / qword,)

lightmap = Struct(
    "data_offset" / dword,
    "pan" / vector,
    "u_clamp" / idx,
    "v_clamp" / idx,
    "u_scale" / float,
    "v_scale" / float,
    "light_actors_index" / dword,
)

leaf = Struct(
    "zone_index" / idx,
    "permeating_index" / idx,
    "volumetric_index" / idx,
    "visible_zones" / qword,
)

struct_map = {
    "color": color,
    "vector": vector,
    "pointregion": pointregion,
    "rotator": rotator,
    "scale": scale,
    "plane": plane,
    "sphere": sphere,
}


import cv2
import matplotlib
import matplotlib.pyplot as plt

#reading image
img1 = cv2.imread('broken1.png')
gray1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)

#keypoints
sift = cv2.SIFT_create()
kp = sift.detect(gray1,None)
img1 = cv2.drawKeypoints(gray1, kp, img1)
plt.imshow(img1)
plt.show()


import os
import pandas as pd
import sys
import matplotlib.pyplot as plt
import lib.math as lib

def draw():
	ax = plt.subplot2grid(shape=(nb[0], nb[1]), loc=(y, i - y * size))
	ax.set_title(title[i], color='#2497C0')
	ax.set_ylabel('Frequency', color='#A9ADAF')
	ax.set_xlabel('Score', color='#DCD0A1')
	ax.hist(g[title[i]], bins='auto', density=True, alpha=0.75, histtype='stepfilled', color='#EC493C', label="Gryffindor")
	ax.hist(r[title[i]], bins='auto', density=True, alpha=0.75, histtype='stepfilled', color='#125E9F', label="Ravenclaw")
	ax.hist(s[title[i]], bins='auto', density=True, alpha=0.75, histtype='stepfilled', color='#24C070', label="Slytherin")
	ax.hist(h[title[i]], bins='auto', density=True, alpha=0.75, histtype='stepfilled', color='#F8FC05', label="Hufflepuff")
	ax.legend()

def get_size_to_draw():
	ncol = size
	if len(title) < size:
		ncol = len(title)
	nrow = int((len(title)) / size) + 1
	if ((len(title)) % size == 0):
		nrow -= 1
	if (ncol == 0 or nrow == 0):
		print("Error: no line data")
		exit(-1)
	return ([nrow, ncol])

if __name__ == "__main__":
	if (len(sys.argv) < 2):
		print("Error: no file data included")
		exit(-1)
	FILENAME = str(sys.argv[1])
	# read the data
	if not os.path.exists(FILENAME):
		print("Error: file not found")
		exit(-1)
	data = pd.read_csv(FILENAME, index_col=False)
	if (lib.describe_count(data['Hogwarts House'].dropna()) == 0):
		print("Error: empty value")
		exit(-1)
	# drop the data
	data.drop(['Index', 'First Name', 'Last Name', 'Birthday', 'Best Hand'], axis='columns', inplace=True)
	g = data.loc[data['Hogwarts House'] == "Gryffindor"]
	r = data.loc[data['Hogwarts House'] == "Ravenclaw"]
	s = data.loc[data['Hogwarts House'] == "Slytherin"]
	h = data.loc[data['Hogwarts House'] == "Hufflepuff"]
	data.drop(['Hogwarts House'], axis='columns', inplace=True)
	title = list(data.columns)
	size = 4
	nb = get_size_to_draw()
	fig = plt.figure(figsize=(nb[0] * 2, nb[1] * 2))
	plt.style.use('seaborn')
	fig.set_size_inches(18.5, 10.5)

	y = -1
	for i in range(len(title)):
		if (i % size == 0):
			y += 1
		draw()
	colors = ['red', 'tan', 'lime']
	fig.tight_layout()
	fig.savefig('img/histogram.png', dpi=100)
	plt.show()


from training_loop import teaching_training

import utils
import numpy as np
def run_train_loop(args):
    save_single_run = True
    if save_single_run:
        end = args.num_runs_start+1
    else:
        end = args.num_runs_end

    dir = f'{args.rootdir}/teacher-data'

    for seed in range(args.num_runs_start, end):

        print(f'\n\n\n\nrun {seed} with teacher SR = {args.SR} and batch size = {args.teacher_batchsize} and learning rate = {args.teacher_lr} buffer = {args.teacher_buffersize}, reward {args.reward_function}\n\n\n\n')
        print(f'start seed = {args.num_runs_start}, ending seed = {end}')
        if args.trained_teacher:
            file = utils.get_file_name(args, dir, seed)
            return_file = utils.get_return_file_name(args, dir, seed)
            return_list = utils.get_data(return_file)
            print(f'file being used = {file}, return_file = {return_file}')
        else:
            file = None
            return_list = None
        teacher_return_list, teacher_scores, teacher_actions, eval_student_score  = teaching_training(seed, args, file, return_list)
        print(f'Teacher returns on run {seed}, {teacher_return_list}')

        collected_data = [teacher_return_list, teacher_scores, teacher_actions, eval_student_score]
        data_names = ['teacher_return_list', 'teacher_scores', 'teacher_actions', 'eval_student_score']

        for idx, data in enumerate(collected_data):
            dir = f'{args.rootdir}/teacher-data'
            utils.make_dir(args, dir)
            file_details = [data_names[idx], seed]
            model_name = utils.get_model_name(args, dir, file_details)
            utils.save_data(model_name,data)

    print(f'run {seed} complete')


import torch
import torch.nn as nn
from torch.nn import init
import functools
from torch.autograd import Variable
from torch.optim import lr_scheduler
import numpy as np
import torch.nn.functional as F
###############################################################################
# Functions
###############################################################################

def weights_init_zero(m):
    classname = m.__class__.__name__
    modulename = m.__name__
    #print(classname)
    if classname.find('Deformable') != -1:
        pass
    elif classname.find('Conv') != -1:
        init.normal(m.weight.data, 0.0, 0.02)
    elif classname.find('Linear') != -1:
        init.normal(m.weight.data, 0.0, 0.02)
    elif classname.find('BatchNorm2d') != -1:
        init.normal(m.weight.data, 1.0, 0.02)
        init.constant(m.bias.data, 0.0)

def weights_init_normal(m):
    classname = m.__class__.__name__
    #print(classname)
    if classname.find('Deformable') != -1:
        pass
    elif hasattr(m, 'weight') and classname.find('Conv') != -1:
        init.normal(m.weight.data, 0.0, 0.02)
    elif classname.find('Linear') != -1:
        init.normal(m.weight.data, 0.0, 0.02)
    elif classname.find('BatchNorm2d') != -1:
        init.normal(m.weight.data, 1.0, 0.02)
        init.constant(m.bias.data, 0.0)

def weights_init_xavier(m):
    classname = m.__class__.__name__
    if classname.find('Deformable') != -1:
        pass
    elif classname.find('HetConv') != -1:
        init.xavier_normal(m.conv3x3.weight.data, gain=0.02)
        # init.xavier_normal(m.conv3x3.weight.data, gain=0.02)
        init.xavier_normal(m.conv1x1_.weight.data, gain=0.02)
        # init.xavier_normal(m.conv1x1_.weight.data, gain=0.02)
        init.xavier_normal(m.conv1x1.weight.data, gain=0.02)
        # init.xavier_normal(m.conv1x1.weight.data, gain=0.02)
    elif hasattr(m, 'weight') and classname.find('Conv') != -1:
        init.xavier_normal(m.weight.data, gain=0.02)
    elif classname.find('Linear') != -1:
        init.xavier_normal(m.weight.data, gain=0.02)
    elif classname.find('BatchNorm2d') != -1:
        init.normal(m.weight.data, 1.0, 0.02)
        init.constant(m.bias.data, 0.0)

def weights_init_kaiming(m):
    classname = m.__class__.__name__
    # print(classname)
    if classname.find('Conv') != -1:
        init.kaiming_normal(m.weight.data, a=0, mode='fan_in')
    elif classname.find('Linear') != -1:
        init.kaiming_normal(m.weight.data, a=0, mode='fan_in')
    elif classname.find('BatchNorm2d') != -1:
        init.normal(m.weight.data, 1.0, 0.02)
        init.constant(m.bias.data, 0.0)

def weights_init_orthogonal(m):
    classname = m.__class__.__name__
    print(classname)
    if classname.find('Conv') != -1:
        init.orthogonal(m.weight.data, gain=1)
    elif classname.find('Linear') != -1:
        init.orthogonal(m.weight.data, gain=1)
    elif classname.find('BatchNorm2d') != -1:
        init.normal(m.weight.data, 1.0, 0.02)
        init.constant(m.bias.data, 0.0)

def init_weights(net, init_type='normal'):
    print('initialization method [%s]' % init_type)
    if init_type == 'normal':
        net.apply(weights_init_normal)
    elif init_type == 'xavier':
        net.apply(weights_init_xavier)
    elif init_type == 'kaiming':
        net.apply(weights_init_kaiming)
    elif init_type == 'orthogonal':
        net.apply(weights_init_orthogonal)
    else:
        raise NotImplementedError('initialization method [%s] is not implemented' % init_type)

def get_norm_layer(norm_type='instance'):
    if norm_type == 'batch':
        norm_layer = functools.partial(nn.BatchNorm2d, affine=True)
    elif norm_type == 'instance':
        norm_layer = functools.partial(nn.InstanceNorm2d, affine=False)
    elif norm_type == 'none':
        norm_layer = None
    else:
        raise NotImplementedError('normalization layer [%s] is not found' % norm_type)
    return norm_layer

def get_scheduler(optimizer, opt):
    if opt.lr_policy == 'lambda':
        def lambda_rule(epoch):
            lr_l = 1.0 - max(0, epoch + 1 + opt.epoch_count - opt.niter) / float(opt.niter_decay + 1)
            return lr_l
        scheduler = lr_scheduler.LambdaLR(optimizer, lr_lambda=lambda_rule)
    elif opt.lr_policy == 'step':
        scheduler = lr_scheduler.StepLR(optimizer, step_size=opt.lr_decay_iters, gamma=0.1)
    elif opt.lr_policy == 'plateau':
        scheduler = lr_scheduler.ReduceLROnPlateau(optimizer, mode='min', factor=0.2, threshold=0.01, patience=5)
    else:
        return NotImplementedError('learning rate policy [%s] is not implemented', opt.lr_policy)
    return scheduler

def get_grid(batchsize, size, minval=-1.0, maxval=1.0):
    r"""Get a grid ranging [-1, 1] of 2D/3D coordinates.

    Args:
        batchsize (int) : Batch size.
        size (tuple) : (height, width) or (depth, height, width).
        minval (float) : minimum value in returned grid.
        maxval (float) : maximum value in returned grid.
    Returns:
        t_grid (4D tensor) : Grid of coordinates.
    """
    if len(size) == 2:
        rows, cols = size
    elif len(size) == 3:
        deps, rows, cols = size
    else:
        raise ValueError('Dimension can only be 2 or 3.')
    x = torch.linspace(minval, maxval, cols)
    x = x.view(1, 1, 1, cols)
    x = x.expand(batchsize, 1, rows, cols)

    y = torch.linspace(minval, maxval, rows)
    y = y.view(1, 1, rows, 1)
    y = y.expand(batchsize, 1, rows, cols)

    t_grid = torch.cat([x, y], dim=1)

    if len(size) == 3:
        z = torch.linspace(minval, maxval, deps)
        z = z.view(1, 1, deps, 1, 1)
        z = z.expand(batchsize, 1, deps, rows, cols)

        t_grid = t_grid.unsqueeze(2).expand(batchsize, 2, deps, rows, cols)
        t_grid = torch.cat([t_grid, z], dim=1)

    t_grid.requires_grad = False
    return t_grid.to('cuda')

def resample(image, flow):
    r"""Resamples an image using the provided flow.

    Args:
        image (NxCxHxW tensor) : Image to resample.
        flow (Nx2xHxW tensor) : Optical flow to resample the image.
    Returns:
        output (NxCxHxW tensor) : Resampled image.
    """
    assert flow.shape[1] == 2
    b, c, h, w = image.size()
    grid = get_grid(b, (h, w))
    flow = torch.cat([flow[:, 0:1, :, :] / ((w - 1.0) / 2.0),
                      flow[:, 1:2, :, :] / ((h - 1.0) / 2.0)], dim=1)
    final_grid = (grid + flow).permute(0, 2, 3, 1)
    try:
        output = F.grid_sample(image, final_grid, mode='bilinear',
                               padding_mode='border', align_corners=True)
    except Exception:
        output = F.grid_sample(image, final_grid, mode='bilinear',
                               padding_mode='border')
    return output

def define_G(input_nc, output_nc, ngf, which_model_netG, norm='batch', use_dropout=False, init_type='normal', gpu_ids=[]):
    netG = None
    use_gpu = len(gpu_ids) > 0
    norm_layer = get_norm_layer(norm_type=norm)

    if use_gpu:
        assert(torch.cuda.is_available())

    if which_model_netG == 'resnet_9blocks':
        netG = ResnetGenerator(input_nc, output_nc, ngf, norm_layer=norm_layer, use_dropout=use_dropout, n_blocks=9, gpu_ids=gpu_ids)
    elif which_model_netG == 'resnet_6blocks':
        netG = ResnetGenerator(input_nc, output_nc, ngf, norm_layer=norm_layer, use_dropout=use_dropout, n_blocks=6, gpu_ids=gpu_ids)
    elif which_model_netG == 'mobile_resnet_9blocks':
        netG = MobileResnetGenerator(input_nc, output_nc, ngf, norm_layer=norm_layer, use_dropout=use_dropout, n_blocks=9, gpu_ids=gpu_ids)
    elif which_model_netG == 'mobile_resnet_6blocks':
        netG = MobileResnetGenerator(input_nc, output_nc, ngf, norm_layer=norm_layer, use_dropout=use_dropout, n_blocks=6, gpu_ids=gpu_ids)
    elif which_model_netG == 'unet_128':
        netG = UnetGenerator(input_nc, output_nc, 7, ngf, norm_layer=norm_layer, use_dropout=use_dropout, gpu_ids=gpu_ids)
    elif which_model_netG == 'unet_256':
        netG = UnetGenerator(input_nc, output_nc, 8, ngf, norm_layer=norm_layer, use_dropout=use_dropout, gpu_ids=gpu_ids)
    elif which_model_netG == 'prediction':
        netG = PredictionNViews(input_nc, output_nc, 6, ngf, norm_layer=norm_layer, use_dropout=use_dropout)
    else:
        raise NotImplementedError('Generator model name [%s] is not recognized' % which_model_netG)
    if len(gpu_ids) > 0:
        assert (torch.cuda.is_available())
        netG.to(gpu_ids[0])
        if len(gpu_ids) > 1:
            netG = torch.nn.DataParallel(netG, gpu_ids)
    init_weights(netG, init_type=init_type)
    return netG

def define_D(input_nc, ndf, which_model_netD,
             n_layers_D=3, norm='batch', use_sigmoid=False, init_type='normal', gpu_ids=[]):
    netD = None
    use_gpu = len(gpu_ids) > 0
    norm_layer = get_norm_layer(norm_type=norm)

    if use_gpu:
        assert(torch.cuda.is_available())
    if which_model_netD == 'basic':
        netD = NLayerDiscriminator(input_nc, ndf, n_layers=3, norm_layer=norm_layer, use_sigmoid=use_sigmoid, gpu_ids=gpu_ids)
    elif which_model_netD == 'sn_basic': # default n_layers_D = 1
        netD = SN_NLayerDiscriminator(input_nc, ndf, n_layers=n_layers_D, norm_layer=None, use_sigmoid=use_sigmoid, gpu_ids=gpu_ids)
    elif which_model_netD == 'n_layers':
        netD = NLayerDiscriminator(input_nc, ndf, n_layers_D, norm_layer=norm_layer, use_sigmoid=use_sigmoid, gpu_ids=gpu_ids)
    elif which_model_netD == 'pixel':
        netD = PixelDiscriminator(input_nc, ndf, norm_layer=norm_layer, use_sigmoid=use_sigmoid, gpu_ids=gpu_ids)
    elif which_model_netD == 'activation': # default n_layers_D = 1
        netD = NLayerDiscriminator(input_nc, ndf, n_layers=n_layers_D, norm_layer=norm_layer, use_sigmoid=use_sigmoid, gpu_ids=gpu_ids)
    elif which_model_netD == 'temporal_patchGAN':
        netD = TemporalPatchGANDiscriminator(input_nc, ndf, n_layers=n_layers_D, use_sigmoid=use_sigmoid, gpu_ids=gpu_ids)
    else:
        raise NotImplementedError('Discriminator model name [%s] is not recognized' %
                                  which_model_netD)
    if use_gpu:
        assert (torch.cuda.is_available())
        netD.to(gpu_ids[0])
        if len(gpu_ids) > 1:
            netD = torch.nn.DataParallel(netD, gpu_ids)
    init_weights(netD, init_type=init_type)
    return netD

def define_FusionNet(input_nc, output_nc, ngf, which_model_FusionNet, norm='instance', use_dropout=False, init_type='normal', gpu_ids=[]):
    FusionNet = None
    use_gpu = len(gpu_ids) > 0
    norm_layer = get_norm_layer(norm_type=norm)

    if use_gpu:
        assert(torch.cuda.is_available())

    if which_model_FusionNet == 'default':
        FusionNet = FusionNetGenerator(input_nc, output_nc, ngf, norm_layer=norm_layer, use_dropout=use_dropout, n_blocks=9, gpu_ids=gpu_ids)
    else:
        raise NotImplementedError('Generator model name [%s] is not recognized' % which_model_FusionNet)
    if len(gpu_ids) > 0:
        FusionNet.cuda(gpu_ids[0])
    init_weights(FusionNet, init_type=init_type)
    return FusionNet

def init_net(net, init_type='normal', gpu_ids=[]):
    if len(gpu_ids) > 0:
        assert(torch.cuda.is_available())
        net.to(gpu_ids[0])
        net = torch.nn.DataParallel(net, gpu_ids)
    init_weights(net, init_type)
    return net

def print_network(net):
    num_params = 0
    for param in net.parameters():
        num_params += param.numel()
    print(net)
    print('Total number of parameters: %d' % num_params)

def define_C(output_nc, ndf, init_type='normal', gpu_ids=[]):
    #if output_nc == 3:
    #    netC = get_model('DTN', num_cls=10)
    #else:
    #    Exception('classifier only implemented for 32x32x3 images')
    netC = Classifier(output_nc, ndf)
    return init_net(netC, init_type, gpu_ids)

##############################################################################
# Classes
##############################################################################

# Defines the GAN loss which uses either LSGAN or the regular GAN.
# When LSGAN is used, it is basically same as MSELoss,
# but it abstracts away the need to create the target label tensor
# that has the same size as the input
class GANLoss(nn.Module): # not used here
    def __init__(self, use_lsgan=True, target_real_label=1.0, target_fake_label=0.0,
                 tensor=torch.FloatTensor):
        super(GANLoss, self).__init__()
        self.real_label = target_real_label
        self.fake_label = target_fake_label
        self.real_label_var = None
        self.fake_label_var = None
        self.Tensor = tensor
        if use_lsgan:
            self.loss = nn.MSELoss()
        else:
            self.loss = nn.BCELoss()

    def get_target_tensor(self, input, target_is_real):
        target_tensor = None
        if target_is_real:
            create_label = ((self.real_label_var is None) or
                            (self.real_label_var.numel() != input.numel()))
            if create_label:
                real_tensor = self.Tensor(input.size()).fill_(self.real_label)
                self.real_label_var = Variable(real_tensor, requires_grad=False)
            target_tensor = self.real_label_var
        else:
            create_label = ((self.fake_label_var is None) or
                            (self.fake_label_var.numel() != input.numel()))
            if create_label:
                fake_tensor = self.Tensor(input.size()).fill_(self.fake_label)
                self.fake_label_var = Variable(fake_tensor, requires_grad=False)
            target_tensor = self.fake_label_var
        return target_tensor

    def __call__(self, input, target_is_real):
        if isinstance(input, list):
            losses = []
            for p in input:
                target_tensor = self.get_target_tensor(p, target_is_real)
                losses.append(self.loss(p, target_tensor))
            return sum(losses)
        else:
            target_tensor = self.get_target_tensor(input, target_is_real)
            loss = self.loss(input, target_tensor)
        # original code:
        # target_tensor = self.get_target_tensor(input, target_is_real)
        # loss = self.loss(input, target_tensor)
        return loss

class GANLoss_custom(nn.Module):
    """Define different GAN objectives.

    The GANLoss class abstracts away the need to create the target label tensor
    that has the same size as the input.
    """

    def __init__(self, gan_mode, target_real_label=1.0, target_fake_label=0.0):
        """ Initialize the GANLoss class.

        Parameters:
            gan_mode (str) - - the type of GAN objective. It currently supports vanilla, lsgan, and wgangp.
            target_real_label (bool) - - label for a real image
            target_fake_label (bool) - - label of a fake image

        Note: Do not use sigmoid as the last layer of Discriminator.
        LSGAN needs no sigmoid. vanilla GANs will handle it with BCEWithLogitsLoss.
        """
        super(GANLoss_custom, self).__init__()
        self.register_buffer('real_label', torch.tensor(target_real_label))
        self.register_buffer('fake_label', torch.tensor(target_fake_label))
        self.register_buffer('zero_tensor', torch.tensor(0.))
        self.zero_tensor.requires_grad_(False)
        self.gan_mode = gan_mode
        if gan_mode == 'lsgan':
            self.loss = nn.MSELoss()
        elif gan_mode == 'vanilla':
            self.loss = nn.BCEWithLogitsLoss()
        elif gan_mode == 'wgangp':
            self.loss = None
        elif gan_mode == 'hinge':
            self.loss = None
        else:
            raise NotImplementedError('gan mode %s not implemented' % gan_mode)

    def get_target_tensor(self, prediction, target_is_real):
        if target_is_real:
            target_tensor = self.real_label
        else:
            target_tensor = self.fake_label
        return target_tensor.expand_as(prediction)

    def get_zero_tensor(self, prediction):
        return self.zero_tensor.expand_as(prediction)

    def __call__(self, prediction, target_is_real, for_discriminator=True):
        """Calculate loss given Discriminator's output and grount truth labels.

        Parameters:
            prediction (tensor) - - tpyically the prediction output from a discriminator
            target_is_real (bool) - - if the ground truth label is for real images or fake images

        Returns:
            the calculated loss.
        """
        if self.gan_mode in ['lsgan', 'vanilla']:
            if isinstance(prediction, list):
                losses = []
                for p in prediction:
                    target_tensor = self.get_target_tensor(p, target_is_real)
                    losses.append(self.loss(p, target_tensor))
                return sum(losses)
            else:
                target_tensor = self.get_target_tensor(prediction, target_is_real)
                loss = self.loss(prediction, target_tensor)
        elif self.gan_mode == 'wgangp':
            if target_is_real:
                loss = -prediction.mean()
            else:
                loss = prediction.mean()
        elif self.gan_mode == 'hinge':
            if isinstance(prediction, list):
                loss = 0
                for pred_i in prediction:
                    if isinstance(pred_i, list):
                        pred_i = pred_i[-1]
                    loss_tensor = self(pred_i, target_is_real, for_discriminator)
                    bs = 1 if len(loss_tensor.size()) == 0 else loss_tensor.size(0)
                    new_loss = torch.mean(loss_tensor.view(bs, -1), dim=1)
                    loss += new_loss
                return loss / len(prediction)
            else:
                if for_discriminator:
                    if target_is_real:
                        minval = torch.min(prediction - 1, self.get_zero_tensor(prediction))
                        loss = -torch.mean(minval)
                    else:
                        minval = torch.min(-prediction - 1, self.get_zero_tensor(prediction))
                        loss = -torch.mean(minval)
                else:
                    assert target_is_real
                    loss = -torch.mean(prediction)
        else:
            raise NotImplementedError('gan mode %s not implemented' % self.gan_mode)
        return loss

class FusionNetGenerator(nn.Module):
    def __init__(self, input_nc, output_nc, nff=64, norm_layer=nn.BatchNorm2d, use_dropout=False, n_blocks=6, gpu_ids=[], padding_type='reflect'):
        assert(n_blocks >= 0)
        super(FusionNetGenerator, self).__init__()
        self.input_nc = input_nc
        self.output_nc = output_nc
        self.nff = nff
        self.gpu_ids = gpu_ids
        if type(norm_layer) == functools.partial:
            use_bias = norm_layer.func == nn.InstanceNorm2d
        else:
            use_bias = norm_layer == nn.InstanceNorm2d

        model = [nn.ReflectionPad2d(3),
                 nn.Conv2d(input_nc, nff, kernel_size=7, padding=0, bias=use_bias),
                 norm_layer(nff),
                 nn.ReLU(True)]

        model += [nn.ReflectionPad2d(3),
                  nn.Conv2d(nff, nff, kernel_size=7, padding=0, bias=use_bias),
                  norm_layer(nff),
                  nn.ReLU(True)]

        model += [nn.ReflectionPad2d(3),
                 nn.Conv2d(nff, output_nc, kernel_size=7, padding=0, bias=use_bias),
                 norm_layer(nff),
                 nn.Sigmoid()]

        self.model = nn.Sequential(*model)

    def forward(self, input):
        return self.model(input)

# Defines the generator that consists of Resnet blocks between a few
# downsampling/upsampling operations.
# Code and idea originally from Justin Johnson's architecture.
# https://github.com/jcjohnson/fast-neural-style/
class ResnetGenerator(nn.Module):
    def __init__(self, input_nc, output_nc, ngf=64, norm_layer=nn.BatchNorm2d, use_dropout=False, n_blocks=6, gpu_ids=[], padding_type='reflect'):
        assert(n_blocks >= 0)
        super(ResnetGenerator, self).__init__()
        self.input_nc = input_nc
        self.output_nc = output_nc
        self.ngf = ngf
        self.gpu_ids = gpu_ids
        self.inplace=False # True
        if type(norm_layer) == functools.partial:
            use_bias = norm_layer.func == nn.InstanceNorm2d
        else:
            use_bias = norm_layer == nn.InstanceNorm2d

        model = [nn.ReflectionPad2d(3),
                 nn.Conv2d(input_nc, ngf, kernel_size=7, padding=0,
                           bias=use_bias),
                 norm_layer(ngf),
                 nn.ReLU(self.inplace)]

        n_downsampling = 2
        for i in range(n_downsampling):
            mult = 2**i
            model += [nn.Conv2d(ngf * mult, ngf * mult * 2, kernel_size=3,
                                stride=2, padding=1, bias=use_bias),
                      norm_layer(ngf * mult * 2),
                      nn.ReLU(self.inplace)]

        mult = 2**n_downsampling
        for i in range(n_blocks):
            model += [ResnetBlock(ngf * mult, padding_type=padding_type, norm_layer=norm_layer, use_dropout=use_dropout, use_bias=use_bias)]

        for i in range(n_downsampling):
            mult = 2**(n_downsampling - i)
            model += [nn.ConvTranspose2d(ngf * mult, int(ngf * mult / 2),
                                         kernel_size=3, stride=2,
                                         padding=1, output_padding=1,
                                         bias=use_bias),
                      norm_layer(int(ngf * mult / 2)),
                      nn.ReLU(self.inplace)]
        #decoder = model
        model += [nn.ReflectionPad2d(3)]
        model += [nn.Conv2d(ngf, output_nc, kernel_size=7, padding=0)]
        model += [nn.Tanh()]
        #self.decoder = nn.Sequential(*decoder)
        self.model = nn.Sequential(*model)

    def forward(self, input):
        # if self.gpu_ids and isinstance(input.data, torch.cuda.FloatTensor):
        #     return nn.parallel.data_parallel(self.model, input, self.gpu_ids)
        # else:
        #     return self.model(input)
        return self.model(input)

class MobileResnetGenerator(nn.Module):
    def __init__(self, input_nc, output_nc, ngf=64, norm_layer=nn.BatchNorm2d, use_dropout=False, n_blocks=9, gpu_ids=[], padding_type='reflect'):
        assert(n_blocks >= 0)
        super(MobileResnetGenerator, self).__init__()
        self.input_nc = input_nc
        self.output_nc = output_nc
        self.ngf = ngf
        self.gpu_ids = gpu_ids
        if type(norm_layer) == functools.partial:
            use_bias = norm_layer.func == nn.InstanceNorm2d
        else:
            use_bias = norm_layer == nn.InstanceNorm2d

        model = [nn.ReflectionPad2d(3),
                 nn.Conv2d(input_nc, ngf, kernel_size=7, padding=0,
                           bias=use_bias),
                 norm_layer(ngf),
                 nn.ReLU(True)]

        n_downsampling = 2
        for i in range(n_downsampling):
            mult = 2**i
            model += [nn.Conv2d(ngf * mult, ngf * mult * 2, kernel_size=3,
                                stride=2, padding=1, bias=use_bias),
                      norm_layer(ngf * mult * 2),
                      nn.ReLU(True)]

        mult = 2**n_downsampling
        for i in range(n_blocks):# Define a resnet block
            model += [MobileResnetBlock(ngf * mult, padding_type=padding_type, norm_layer=norm_layer, use_dropout=use_dropout, use_bias=use_bias)]

        for i in range(n_downsampling):
            mult = 2**(n_downsampling - i)
            model += [nn.ConvTranspose2d(ngf * mult, int(ngf * mult / 2),
                                         kernel_size=3, stride=2,
                                         padding=1, output_padding=1,
                                         bias=use_bias),
                      norm_layer(int(ngf * mult / 2)),
                      nn.ReLU(True)]
        model += [nn.ReflectionPad2d(3)]
        model += [nn.Conv2d(ngf, output_nc, kernel_size=7, padding=0)]
        model += [nn.Tanh()]

        self.model = nn.Sequential(*model)

    def forward(self, input):
        # if self.gpu_ids and isinstance(input.data, torch.cuda.FloatTensor):
        #     return nn.parallel.data_parallel(self.model, input, self.gpu_ids)
        # else:
        #     return self.model(input)
        return self.model(input)

class ResnetBlock(nn.Module):
    def __init__(self, dim, padding_type, norm_layer, use_dropout, use_bias):
        super(ResnetBlock, self).__init__()
        self.conv_block = self.build_conv_block(dim, padding_type, norm_layer, use_dropout, use_bias)

    def build_conv_block(self, dim, padding_type, norm_layer, use_dropout, use_bias):
        conv_block = []
        p = 0
        if padding_type == 'reflect':
            conv_block += [nn.ReflectionPad2d(1)]
        elif padding_type == 'replicate':
            conv_block += [nn.ReplicationPad2d(1)]
        elif padding_type == 'zero':
            p = 1
        else:
            raise NotImplementedError('padding [%s] is not implemented' % padding_type)

        conv_block += [nn.Conv2d(dim, dim, kernel_size=3, padding=p, bias=use_bias),
                       norm_layer(dim),
                       nn.ReLU(True)]
        if use_dropout:
            conv_block += [nn.Dropout(0.5)]

        p = 0
        if padding_type == 'reflect':
            conv_block += [nn.ReflectionPad2d(1)]
        elif padding_type == 'replicate':
            conv_block += [nn.ReplicationPad2d(1)]
        elif padding_type == 'zero':
            p = 1
        else:
            raise NotImplementedError('padding [%s] is not implemented' % padding_type)
        conv_block += [nn.Conv2d(dim, dim, kernel_size=3, padding=p, bias=use_bias),
                       norm_layer(dim)]

        return nn.Sequential(*conv_block)

    def forward(self, x):
        out = x + self.conv_block(x)
        return out

class MobileResnetBlock(nn.Module):
    def __init__(self, dim, padding_type, norm_layer, use_dropout, use_bias):
        super(MobileResnetBlock, self).__init__()
        self.conv_block = self.build_conv_block(dim, padding_type, norm_layer, use_dropout, use_bias)

    def build_conv_block(self, dim, padding_type, norm_layer, use_dropout, use_bias):
        conv_block = []
        p = 0
        if padding_type == 'reflect':
            conv_block += [nn.ReflectionPad2d(1)]
        elif padding_type == 'replicate':
            conv_block += [nn.ReplicationPad2d(1)]
        elif padding_type == 'zero':
            p = 1
        else:
            raise NotImplementedError('padding [%s] is not implemented' % padding_type)

        conv_block += [
            SeparableConv2d(in_channels=dim, out_channels=dim,
                            kernel_size=3, padding=p, stride=1),
            norm_layer(dim), nn.ReLU(True)
        ]
        if use_dropout:
            conv_block += [nn.Dropout(0.5)]

        p = 0
        if padding_type == 'reflect':
            conv_block += [nn.ReflectionPad2d(1)]
        elif padding_type == 'replicate':
            conv_block += [nn.ReplicationPad2d(1)]
        elif padding_type == 'zero':
            p = 1
        else:
            raise NotImplementedError('padding [%s] is not implemented' % padding_type)

        conv_block += [
            SeparableConv2d(in_channels=dim, out_channels=dim,
                            kernel_size=3, padding=p, stride=1),
            norm_layer(dim)
        ]

        return nn.Sequential(*conv_block)

    def forward(self, x):
        out = x + self.conv_block(x)
        return out

class SeparableConv2d(nn.Module):
    def __init__(self, in_channels, out_channels, kernel_size, stride=1, padding=0, norm_layer=nn.InstanceNorm2d,
                 use_bias=True, scale_factor=1):
        super(SeparableConv2d, self).__init__()
        self.conv = nn.Sequential(
            nn.Conv2d(in_channels=in_channels, out_channels=in_channels * scale_factor, kernel_size=kernel_size,
                      stride=stride, padding=padding, groups=in_channels, bias=use_bias),
            norm_layer(in_channels * scale_factor),
            nn.Conv2d(in_channels=in_channels * scale_factor, out_channels=out_channels,
                      kernel_size=1, stride=1, bias=use_bias),
        )

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

# ----------------------------------------------------------------------------------------------------
# Prediction Model (2Views) --
# PredictionNViews(input_nc, output_nc, 6, ngf, norm_layer=norm_layer, use_dropout=use_dropout)
# ---------------------------------------------------------------------------------------------------

class PredictionNViews(nn.Module):
    def __init__(self, input_nc, output_nc,num_downs,  ngf=32,  norm_layer=nn.BatchNorm2d, use_dropout=False, n_blocks=6):
        assert(n_blocks >= 0)
        super(PredictionNViews, self).__init__()
        self.input_nc = input_nc
        self.output_nc = output_nc
        self.ngf = ngf
        #self.gpu_ids = gpu_ids

        if type(norm_layer) == functools.partial:
            use_bias = norm_layer.func == nn.InstanceNorm2d
        else:
            use_bias = norm_layer == nn.InstanceNorm2d

        model1 = [nn.ReflectionPad2d(3),
                 nn.Conv2d(input_nc, ngf, kernel_size=7, padding=0,
                           bias=use_bias),
                 norm_layer(ngf),
                 nn.ReLU(True)]

        model1 += [nn.Conv2d(ngf, ngf*2, kernel_size=3,
                              stride=1, padding=1, bias=use_bias),
                      norm_layer(ngf*2),
                      nn.ReLU(True)]
        model1 += [nn.Conv2d(ngf*2, ngf*4, kernel_size=3,
                              stride=1, padding=1, bias=use_bias),
                      norm_layer(ngf*4),
                      nn.ReLU(True)]

        # feed this data to a U-Net generator
        model = UnetGenerator(ngf*4*2, ngf*4, num_downs, ngf*4*4, norm_layer=norm_layer, use_dropout=use_dropout)
        #unet_block = UnetSkipConnectionBlock(ngf*mult*4, , input_nc=None, submodule=None, norm_layer=norm_layer, innermost=True)

        model3 = [nn.Conv2d(ngf * 4, ngf * 2, kernel_size=3,
                               stride=1, padding=1, bias=use_bias),
                      norm_layer(ngf * 2),
                      nn.ReLU(True)]
        model3 += [nn.Conv2d(ngf * 2, ngf, kernel_size=3,
                               stride=1, padding=1, bias=use_bias),
                      norm_layer(ngf),
                      nn.ReLU(True)]
        model3 += [nn.ReflectionPad2d(3)]
        model3 += [nn.Conv2d(ngf, output_nc, kernel_size=7, padding=0)]
        model3 += [nn.Tanh()]

        self.model = model
        self.model1 = nn.Sequential(*model1)
        self.model3 = nn.Sequential(*model3)

    def forward(self, input0, input1):
        f0 = self.model1(input0)
        f1 = self.model1(input1)

        g =  self.model(torch.cat((f0,f1),1))
        return self.model3(g)

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

# Defines the Unet generator.
# |num_downs|: number of downsamplings in UNet. For example,
# if |num_downs| == 7, image of size 128x128 will become of size 1x1
# at the bottleneck
class UnetGenerator(nn.Module):
    def __init__(self, input_nc, output_nc, num_downs, ngf=64,
                 norm_layer=nn.BatchNorm2d, use_dropout=False, gpu_ids=[]):
        super(UnetGenerator, self).__init__()
        self.gpu_ids = gpu_ids

        # construct unet structure
        unet_block = UnetSkipConnectionBlock(ngf * 8, ngf * 8, input_nc=None, submodule=None, norm_layer=norm_layer, innermost=True)
        for i in range(num_downs - 5):
            unet_block = UnetSkipConnectionBlock(ngf * 8, ngf * 8, input_nc=None, submodule=unet_block, norm_layer=norm_layer, use_dropout=use_dropout)
        unet_block = UnetSkipConnectionBlock(ngf * 4, ngf * 8, input_nc=None, submodule=unet_block, norm_layer=norm_layer)
        unet_block = UnetSkipConnectionBlock(ngf * 2, ngf * 4, input_nc=None, submodule=unet_block, norm_layer=norm_layer)
        unet_block = UnetSkipConnectionBlock(ngf, ngf * 2, input_nc=None, submodule=unet_block, norm_layer=norm_layer)
        unet_block = UnetSkipConnectionBlock(output_nc, ngf, input_nc=input_nc, submodule=unet_block, outermost=True, norm_layer=norm_layer)

        self.model = unet_block

    def forward(self, input):
        if self.gpu_ids and isinstance(input.data, torch.cuda.FloatTensor):
            return nn.parallel.data_parallel(self.model, input, self.gpu_ids)
        else:
            return self.model(input)

# Defines the submodule with skip connection.
# X -------------------identity---------------------- X
#   |-- downsampling -- |submodule| -- upsampling --|
class UnetSkipConnectionBlock(nn.Module):
    def __init__(self, outer_nc, inner_nc, input_nc=None,
                 submodule=None, outermost=False, innermost=False, norm_layer=nn.BatchNorm2d, use_dropout=False):
        super(UnetSkipConnectionBlock, self).__init__()
        self.outermost = outermost
        if type(norm_layer) == functools.partial:
            use_bias = norm_layer.func == nn.InstanceNorm2d
        else:
            use_bias = norm_layer == nn.InstanceNorm2d
        if input_nc is None:
            input_nc = outer_nc
        downconv = nn.Conv2d(input_nc, inner_nc, kernel_size=4,
                             stride=2, padding=1, bias=use_bias)
        downrelu = nn.LeakyReLU(0.2, True)
        downnorm = norm_layer(inner_nc)
        uprelu = nn.ReLU(True)
        upnorm = norm_layer(outer_nc)

        if outermost:
            upconv = nn.ConvTranspose2d(inner_nc * 2, outer_nc,
                                        kernel_size=4, stride=2,
                                        padding=1)
            down = [downconv]
            up = [uprelu, upconv, nn.Tanh()]
            model = down + [submodule] + up
        elif innermost:
            upconv = nn.ConvTranspose2d(inner_nc, outer_nc,
                                        kernel_size=4, stride=2,
                                        padding=1, bias=use_bias)
            down = [downrelu, downconv]
            up = [uprelu, upconv, upnorm]
            model = down + up
        else:
            upconv = nn.ConvTranspose2d(inner_nc * 2, outer_nc,
                                        kernel_size=4, stride=2,
                                        padding=1, bias=use_bias)
            down = [downrelu, downconv, downnorm]
            up = [uprelu, upconv, upnorm]

            if use_dropout:
                model = down + [submodule] + up + [nn.Dropout(0.5)]
            else:
                model = down + [submodule] + up

        self.model = nn.Sequential(*model)

    def forward(self, x):
        if self.outermost:
            return self.model(x)
        else:
            return torch.cat([x, self.model(x)], 1)

# Defines the PatchGAN discriminator with the specified arguments.
class NLayerDiscriminator(nn.Module):
    def __init__(self, input_nc, ndf=64, n_layers=3, norm_layer=nn.BatchNorm2d, use_sigmoid=False, gpu_ids=[]):
        super(NLayerDiscriminator, self).__init__()
        self.gpu_ids = gpu_ids
        if type(norm_layer) == functools.partial:
            use_bias = norm_layer.func == nn.InstanceNorm2d
        else:
            use_bias = norm_layer == nn.InstanceNorm2d

        kw = 4
        padw = 1
        sequence = [
            nn.Conv2d(input_nc, ndf, kernel_size=kw, stride=2, padding=padw),
            nn.LeakyReLU(0.2, True)
        ]

        nf_mult = 1
        nf_mult_prev = 1
        for n in range(1, n_layers):
            nf_mult_prev = nf_mult
            nf_mult = min(2**n, 8)
            sequence += [
                nn.Conv2d(ndf * nf_mult_prev, ndf * nf_mult,
                          kernel_size=kw, stride=2, padding=padw, bias=use_bias),
                norm_layer(ndf * nf_mult),
                nn.LeakyReLU(0.2, True)
            ]

        nf_mult_prev = nf_mult
        nf_mult = min(2**n_layers, 8)
        sequence += [
            nn.Conv2d(ndf * nf_mult_prev, ndf * nf_mult,
                      kernel_size=kw, stride=1, padding=padw, bias=use_bias),
            norm_layer(ndf * nf_mult),
            nn.LeakyReLU(0.2, True)
        ]

        sequence += [nn.Conv2d(ndf * nf_mult, 1, kernel_size=kw, stride=1, padding=padw)]

        if use_sigmoid:
            sequence += [nn.Sigmoid()]

        self.model = nn.Sequential(*sequence)

    def forward(self, input):
            # if len(self.gpu_ids) and isinstance(input.data, torch.cuda.FloatTensor):
            #     return nn.parallel.data_parallel(self.model, input, self.gpu_ids)
            # else:
        return self.model(input)

class SN_NLayerDiscriminator(nn.Module):
    def __init__(self, input_nc, ndf=64, n_layers=3, norm_layer=None, use_sigmoid=False, gpu_ids=[]):
        super(SN_NLayerDiscriminator, self).__init__()
        self.gpu_ids = gpu_ids
        if type(norm_layer) == functools.partial:
            use_bias = norm_layer.func == nn.InstanceNorm2d
        else:
            use_bias = norm_layer == nn.InstanceNorm2d

        kw = 4
        padw = 1
        sequence = [
            nn.utils.spectral_norm(nn.Conv2d(input_nc, ndf, kernel_size=kw, stride=2, padding=padw)),
            nn.LeakyReLU(0.2, True)
        ]

        nf_mult = 1
        nf_mult_prev = 1
        for n in range(1, n_layers):
            nf_mult_prev = nf_mult
            nf_mult = min(2**n, 8)
            sequence += [
                nn.utils.spectral_norm(nn.Conv2d(ndf * nf_mult_prev, ndf * nf_mult,
                          kernel_size=kw, stride=2, padding=padw, bias=use_bias)),
                nn.LeakyReLU(0.2, True)
            ]

        nf_mult_prev = nf_mult
        nf_mult = min(2**n_layers, 8)
        sequence += [
            nn.utils.spectral_norm(nn.Conv2d(ndf * nf_mult_prev, ndf * nf_mult,
                      kernel_size=kw, stride=1, padding=padw, bias=use_bias)),
            nn.LeakyReLU(0.2, True)
        ]
        sequence += [nn.Conv2d(ndf * nf_mult, ndf * nf_mult, kernel_size=kw, stride=1, padding=padw)]
        #sequence += [nn.utils.spectral_norm(nn.Conv2d(ndf * nf_mult, 1, kernel_size=kw, stride=1, padding=padw))]

        if use_sigmoid:
            sequence += [nn.Sigmoid()]

        self.model = nn.Sequential(*sequence)

    def forward(self, input):
        # if len(self.gpu_ids) and isinstance(input.data, torch.cuda.FloatTensor):
        #     return nn.parallel.data_parallel(self.model, input, self.gpu_ids)
        # else:
        #     return self.model(input)
        return self.model(input)

class PixelDiscriminator(nn.Module):
    def __init__(self, input_nc, ndf=64, norm_layer=nn.BatchNorm2d, use_sigmoid=False, gpu_ids=[]):
        super(PixelDiscriminator, self).__init__()
        self.gpu_ids = gpu_ids
        if type(norm_layer) == functools.partial:
            use_bias = norm_layer.func == nn.InstanceNorm2d
        else:
            use_bias = norm_layer == nn.InstanceNorm2d

        self.net = [
            nn.Conv2d(input_nc, ndf, kernel_size=1, stride=1, padding=0),
            nn.LeakyReLU(0.2, True),
            nn.Conv2d(ndf, ndf * 2, kernel_size=1, stride=1, padding=0, bias=use_bias),
            norm_layer(ndf * 2),
            nn.LeakyReLU(0.2, True),
            nn.Conv2d(ndf * 2, 1, kernel_size=1, stride=1, padding=0, bias=use_bias)]

        if use_sigmoid:
            self.net.append(nn.Sigmoid())

        self.net = nn.Sequential(*self.net)

    def forward(self, input):
        if len(self.gpu_ids) and isinstance(input.data, torch.cuda.FloatTensor):
            return nn.parallel.data_parallel(self.net, input, self.gpu_ids)
        else:
            return self.net(input)

class Classifier(nn.Module):
    def __init__(self, input_nc, ndf, norm_layer=nn.BatchNorm2d):
        super(Classifier, self).__init__()

        kw = 3
        sequence = [
            nn.Conv2d(input_nc, ndf, kernel_size=kw, stride=2),
            nn.LeakyReLU(0.2, True)
        ]

        nf_mult = 1
        nf_mult_prev = 1
        for n in range(3):
            nf_mult_prev = nf_mult
            nf_mult = min(2**n, 8)
            sequence += [
                nn.Conv2d(ndf * nf_mult_prev, ndf * nf_mult,
                          kernel_size=kw, stride=2),
                norm_layer(ndf * nf_mult, affine=True),
                nn.LeakyReLU(0.2, True)
            ]
        self.before_linear = nn.Sequential(*sequence)

        sequence = [
            nn.Linear(ndf * nf_mult, 1024),
            nn.Linear(1024, 10)
        ]

        self.after_linear = nn.Sequential(*sequence)

    def forward(self, x):
        bs = x.size(0)
        out = self.after_linear(self.before_linear(x).view(bs, -1))
        return out
 #       return nn.functional.log_softmax(out, dim=1)

class TemporalPatchGANDiscriminator(nn.Module):
    def __init__(self, input_nc, ndf=64, n_layers=3, norm_layer=None, use_sigmoid=False, gpu_ids=[]):
        super().__init__()
        if type(norm_layer) == functools.partial:
            use_bias = norm_layer.func == nn.InstanceNorm3d
        else:
            use_bias = norm_layer == nn.InstanceNorm3d

        # default norm : Spectral normalization
        self.gpu_ids = gpu_ids

        kw = (3, 4, 4)
        padw = (1, 1, 1)
        sequence = [
            nn.utils.spectral_norm(nn.Conv3d(input_nc, ndf, kernel_size=kw, stride=(1, 2, 2), padding=padw)),
            nn.LeakyReLU(0.2, True)
        ]

        nf_mult = 1
        nf_mult_prev = 1
        for n in range(1, n_layers):
            nf_mult_prev = nf_mult
            nf_mult = min(2**n, 8)
            sequence += [
                nn.utils.spectral_norm(nn.Conv3d(ndf * nf_mult_prev, ndf * nf_mult,
                          kernel_size=kw, stride=(1, 2, 2), padding=padw, bias=use_bias)),
                # norm_layer(ndf * nf_mult),
                nn.LeakyReLU(0.2, True)
            ]

        nf_mult_prev = nf_mult
        nf_mult = min(2**n_layers, 8)
        sequence += [
            nn.utils.spectral_norm(nn.Conv3d(ndf * nf_mult_prev, ndf * nf_mult,
                      kernel_size=kw, stride=1, padding=padw, bias=use_bias)),
            #norm_layer(ndf * nf_mult),
            nn.LeakyReLU(0.2, True)
        ]

        sequence += [nn.Conv3d(ndf * nf_mult, ndf * nf_mult, kernel_size=kw, stride=1, padding=padw)]

        if use_sigmoid:
            sequence += [nn.Sigmoid()]

        self.model = nn.Sequential(*sequence)

    def forward(self, input):
        # if len(self.gpu_ids) and isinstance(input.data, torch.cuda.FloatTensor):
        #     return nn.parallel.data_parallel(self.model, input, self.gpu_ids)
        # else:
        #     return self.model(input)
        return self.model(input)


import requests
from PIL import Image
from io import BytesIO
import os
import threading
import time

class EenaduEpaper:
	def __init__(self,no,filename,quality):
		self.id=no
		self.data=self.allPageDetails()
		self.name=filename
		self.quality=quality
		self.emptyImage=[]
		for i in self.data:
			self.emptyImage.append(None)

	def allPageDetails(self):
		print(time.strftime("%T"))
		res=requests.get("https://epaper.eenadu.net/Home/GetAllpages?editionid="+str(self.id)+"&editiondate="+time.strftime("%d")+"%2F"+time.strftime("%m")+"%2F"+time.strftime("%Y"),timeout=8000).json()
		data=[]
		for i in res:
			data.append(i["XHighResolution"])
		return data

	def formCompleteImg(self,url,no):
		headers={'Referer': 'https://epaper.eenadu.net/Home/Index', 'Sec-Fetch-Mode': 'no-cors', 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36'}
		url1=url
		url2=url[:-3]+'png'
		img = Image.open(BytesIO(requests.get(url2,headers=headers,timeout=8000).content)).convert("RGBA")
		background = Image.open(BytesIO(requests.get(url1,headers=headers,timeout=8000).content))
		background.paste(img, (0, 0), img)
		self.emptyImage[no]=background

	def DownloadPaper(self):
		arr=[]
		for no,i in enumerate(self.data):
			t=threading.Thread(target=self.formCompleteImg,args=(i,no))
			arr.append(t)
			t.start()
		no=1
		for i in arr:
			print(no)
			no+=1
			i.join()
		img=self.emptyImage[0]
		self.emptyImage.pop(0)
		img.save(self.name+'.pdf',save_all=True,optimize=True,quality=int(self.quality),append_images=self.emptyImage)
		#optimize=True,quality=quality

def downloadPaper(no,name,quality):
	pap=EenaduEpaper(no,name,quality)
	pap.DownloadPaper()


from __future__ import annotations
import ezdxf
from ezdxf.math import Vec2
from ezdxf.enums import MTextEntityAlignment
from ezdxf.layouts import Modelspace

SIZE_X = 20
SIZE_Y = 20
GAP_X = 5
GAP_Y = 5
CHAR_HEIGHT = 3
TEXT_OFFSET = Vec2(3, 3)
TEXT_COLOR = 255
TEXT_BG_COLOR = (10, 10, 10)
GRADIENT = [9, 7, 5, 3, 1, 0, 2, 4, 6, 8]
ORDERED = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

def add_index(msp: Modelspace, location: Vec2, aci: int):
    mtext = msp.add_mtext(
        str(aci),
        dxfattribs={
            "style": "OpenSans",
            "char_height": CHAR_HEIGHT,
            "layer": "TEXT",
        },
    )
    mtext.set_location(
        location + TEXT_OFFSET,
        attachment_point=MTextEntityAlignment.BOTTOM_LEFT,
    )
    mtext.set_bg_color(TEXT_BG_COLOR)

def add_color(msp: Modelspace, location: Vec2, aci: int):
    points = [
        location,
        location + Vec2(SIZE_X, 0),
        location + Vec2(0, SIZE_Y),
        location + Vec2(SIZE_X, SIZE_X),
    ]
    msp.add_solid(points, dxfattribs={"color": aci, "layer": "ACI"})

def add_row(msp: Modelspace, x: int, y: int, colors: list[int]):
    for color in colors:
        location = Vec2(x, y)
        add_color(msp, location, color)
        add_index(msp, location, color)
        x += SIZE_X + GAP_X

def draw_aci_color_table(msp: Modelspace, order: list[int], x: int, y: int):
    add_row(msp, x, y, [1, 2, 3, 4, 5, 6, 7, 8, 9])
    y -= SIZE_Y + GAP_Y
    for start_index in range(10, 250, 10):
        colors = [start_index + offset for offset in order]
        add_row(msp, x, y, colors)
        y -= SIZE_Y + GAP_Y
    add_row(msp, x, y, [250, 251, 252, 253, 254, 255])

def main():
    doc = ezdxf.new()
    doc.styles.add("OpenSans", font="OpenSans-Regular.ttf")
    doc.layers.add("SOLID")
    doc.layers.add("TEXT", color=TEXT_COLOR)
    msp = doc.modelspace()
    draw_aci_color_table(msp, order=ORDERED, x=0, y=700)
    draw_aci_color_table(msp, order=GRADIENT, x=300, y=700)
    doc.set_modelspace_vport(800, center=(300, 400))
    doc.saveas("aci_color_table.dxf")

if __name__ == "__main__":
    main()


# -*- coding: utf-8 -*-
"""
Created on Sat May 18 14:26:37 2019

@author: ritap
"""
#import the packages
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns

#import the data
data = pd.read_csv('heart.csv')

#analize The age data
age_data = data['age']
print("Total Age Data| Count:"+str(len(age_data)))
print("Minimum age:"+str(min(age_data)))
print("Maximum age:"+str(max(age_data)))
print("Average age:"+str(np.mean(age_data)))
print("Median age:"+str(np.median(age_data)))

sorted_age = np.sort(age_data)
plt.figure(0)
plt.hist(age_data, bins = 8)
plt.title('Total Age Data')
plt.xlabel('Age')
plt.ylabel('No. of Person')
plt.show()

true_age_data = data[data.target==1]['age']
print("Diseased Age Data| Count:"+str(len(true_age_data)))
print("Minimum age:"+str(min(true_age_data)))
print("Maximum age:"+str(max(true_age_data)))
print("Average age:"+str(np.mean(true_age_data)))
print("Median age:"+str(np.median(true_age_data)))

sorted_age = np.sort(true_age_data)
plt.figure(1)
plt.hist(true_age_data, bins = 8)
plt.title('Diseased Age Data')
plt.xlabel('Age')
plt.ylabel('No. of Person')
plt.show()

#Analyze sex data
sex_data = data['sex']
print("Total Sex Data and Diseased Sex Data")
plt.figure(2)
plt.subplot(2,1,1)
plt.hist(sex_data)
plt.title('Total Sex Data')
plt.ylabel('No. of Person')
plt.xticks([0,1],['', ''])

true_sex_data = data[data.target==1]['sex']
plt.subplot(2,1,2)
plt.hist(true_sex_data)
plt.title('Diseased Sex Data')
plt.xlabel('Sex')
plt.ylabel('No. of Person')
plt.xticks([0,1],['Female', 'Male'])
plt.show()

#Analyze cp data
cp_data = data['cp']
print("Total Chest Pain Data and Diseased Chest Pain Data")
plt.figure(3)
plt.subplot(2,1,1)
plt.hist(cp_data)
plt.title('Total Chest Pain Data')
plt.ylabel('No. of Person')
plt.xticks([0,1, 2, 3],['', '', '', ''])

true_cp_data = data[data.target==1]['cp']
plt.subplot(2,1,2)
plt.hist(true_cp_data)
plt.title('Diseased Chest Pain Data')
plt.xlabel('Chest Pain')
plt.ylabel('No. of Person')
plt.xticks([0, 1, 2, 3])
plt.show()

def ecdf(data):
    """Compute ECDF for a one-dimensional array of measurements."""
    # Number of data points: n
    n = len(data)

    # x-data for the ECDF: x
    x = np.sort(data)

    # y-data for the ECDF: y
    y = np.arange(1, n+1) / n

    return x, y

#Analyze cp data
#Plotting a histogram
rbp_data = data['trestbps']
print("Total Blood Pressure Data")
print("Minimum BP:"+str(min(rbp_data)))
print("Maximum BP:"+str(max(rbp_data)))
print("Average BP:"+str(np.mean(rbp_data)))
print("Median BP:"+str(np.median(rbp_data)))
plt.figure(4)
plt.hist(rbp_data, bins=8)
plt.title('Total Resting Blood Pressure Data')
plt.ylabel('No. of Person')
plt.xlabel('Resting Blood Pressure')
plt.show()

true_rbp_data = data[data.target==1]['trestbps']
print("Diseased Resting Blood Pressure Data")
print("Minimum BP:"+str(min(true_rbp_data)))
print("Maximum BP:"+str(max(true_rbp_data)))
print("Average BP:"+str(np.mean(true_rbp_data)))
print("Median BP:"+str(np.median(true_rbp_data)))
plt.figure(5)
plt.hist(true_rbp_data, bins=8)
plt.title('Diseased Resting Blood Pressure Data')
plt.xlabel('Resting Blood Pressure')
plt.ylabel('No. of Person')
plt.show()

#Making a comparison between diseased and non-diseased people's RBP using ECDF
x1, y1 = ecdf(true_rbp_data)
false_rbp_data = data[data.target==0]['trestbps']
x2, y2 = ecdf(false_rbp_data)
plt.figure(6, figsize=(10,7))
plt.scatter(x1, y1, marker='.')
plt.scatter(x2, y2, marker='.')
plt.legend(['Diseased', 'Non-diseased'])
plt.title("Comparison between diseased and non-diseased people's RBP")
plt.xlabel('Resting Blood Pressure')
plt.ylabel('ECDF')
plt.show()

#Cholesterol analysis
chol_data = data['chol']
print("Total Cholesterol Data")
print("Minimum Cholesterol:"+str(min(chol_data)))
print("Maximum Cholesterol:"+str(max(chol_data)))
print("Average Cholesterol:"+str(np.mean(chol_data)))
print("Median Cholesterol:"+str(np.median(chol_data)))
plt.figure(7)
plt.hist(rbp_data, bins=8)
plt.title('Total Cholesterol Data')
plt.ylabel('No. of Person')
plt.xlabel('Cholesterol')
plt.show()

true_chol_data = data[data.target==1]['chol']
print("Diseased Cholesterol Data")
print("Minimum Cholesterol:"+str(min(true_chol_data)))
print("Maximum Cholesterol:"+str(max(true_chol_data)))
print("Average Cholesterol:"+str(np.mean(true_chol_data)))
print("Median Cholesterol:"+str(np.median(true_chol_data)))
plt.figure(8)
plt.hist(true_rbp_data, bins=8)
plt.title('Diseased Cholesterol Data')
plt.xlabel('Cholesterol')
plt.ylabel('No. of Person')
plt.show()

false_chol_data = data[data.target==0]['chol']
chol_com_data = [true_chol_data, false_chol_data]
plt.figure(8)
plt.boxplot(chol_com_data)
plt.title("Comaring cholesterol for people with heart disease and healthy people")
plt.xticks([1,2], [True, False])
plt.ylabel("Cholesterol")
plt.show()


"""
Get the best ROI for a given currency based on current market board
prices for Exodus.
"""

import numpy as np
import os
import pandas as pd
import streamlit as st

from ffxiv_shugo.constants import DATA_DIR
from ffxiv_shugo.utilities import lookup_prices

# TODO: clean this code up

COLS_TO_NORMALIZE = [
    "current_average_price",
    # "min_price",
    "average_recent_price",
]
NORMALIZED_COLS = [f"normalized_{col}" for col in COLS_TO_NORMALIZE]
ALL_KEYS = [
    # from items_by_currency
    "id",
    "item_name",
    "currency_cost",
    # from lookup_prices
    *COLS_TO_NORMALIZE,
    "sale_velocity",
    "average_recent_stack_size",
    # from computation here
    *NORMALIZED_COLS,
]

def load_data() -> pd.DataFrame:
    data_path = os.path.join(DATA_DIR, "items_by_currency.csv")
    data = pd.read_csv(data_path)
    data = data.loc[data["is_untradable"] == 0].drop("is_untradable", axis=1)
    return data

def main():
    data = load_data()
    available_currencies = data["currency_type"].unique().tolist()

    st.title("FFXIV: Fetch Prices")
    st.info(
        "This app looks up current market prices so you can spend your currencies "
        "on the best ROI."
    )
    with st.form("Options", clear_on_submit=False):
        currency = st.selectbox(
            label="Currency",
            options=available_currencies,
        )
        keys_to_show = st.multiselect(
            label="Final columns to show in output",
            options=ALL_KEYS,
            default=ALL_KEYS,
        )
        sort_by_column = st.selectbox(
            label="Column to sort the output by",
            options=ALL_KEYS, # narrow this down
        )
        sort_ascending = st.selectbox(
            label="Sort output by column ascending?",
            options=["False", "True"],
        )
        submit = st.form_submit_button(label="Submit")
        display = st.empty()
        if submit:
            fetch_prices(
                data.loc[data["currency_type"] == currency],
                display,
                keys_to_show,
                sort_by_column,
                sort_ascending,
            )

def fetch_prices(
    data: pd.DataFrame,
    display: st.empty,
    keys_to_show: st.multiselect,
    sort_by_column: st.selectbox,
    sort_ascending: st.selectbox,
) -> None:
    ids = data["id"].values.tolist()
    col_map = {
        "currentAveragePriceNQ": "current_average_price",
        "nqSaleVelocity": "sale_velocity",
        # "minPriceNQ": "min_price",
        "averageRecentHistoryStackSize": "average_recent_stack_size",
        "averageRecentPrice": "average_recent_price",
    }
    # data[col_map.values()] = np.nan
    for new_col in col_map.values():
        data[new_col] = np.nan

    price_results = lookup_prices(ids)
    for price_data in price_results:
        item_id = price_data["item_id"]
        idx = data.loc[data["id"] == item_id].index[0]
        for price_col, data_col in col_map.items():
            data[data_col][idx] = price_data[price_col]

    for col, normalized_col in zip(COLS_TO_NORMALIZE, NORMALIZED_COLS):
        data[normalized_col] = data[col] / data["currency_cost"]

    display.write(
        data.sort_values(
            by=[sort_by_column],
            ascending=str(sort_ascending).lower() == "true",
        )[keys_to_show]
    )

if __name__ == "__main__":
    main()


from django.shortcuts import render, redirect, get_object_or_404
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from .forms import AddGameForm
from library.views import library
from library.models import Post

@login_required
def add_game(request):
    if request.method == 'POST':
        form = AddGameForm(request.POST, request.FILES)
        if form.is_valid():
            form.instance.user = request.user
            form.save()
            messages.success(request, "Game successfully added")
            return redirect(library)
        else:
            messages.error(
                request,
                "There was a problem adding this game. Please try again")
    form = AddGameForm()
    template = 'add_game/add_game.html'
    context = {
        'form': form
    }
    return render(request, template, context)

@login_required
def update_game(request, id):
    game = get_object_or_404(Post, id=id)
    if not game.user == request.user:
        messages.error(request, "You are not authorised")
        return redirect(library)

    if request.method == 'POST':
        form = AddGameForm(request.POST, request.FILES, instance=game)
        if form.is_valid():
            form.instance.user = request.user
            form.save()
            messages.success(request, "Game successfully updated")
            return redirect(library)
        else:
            messages.error(
                request,
                "There was a problem updated this game. Please try again")
    form = AddGameForm(instance=game)
    template = 'add_game/update_game.html'
    context = {
        'form': form,
        'game': game,
    }
    return render(request, template, context)

@login_required
def delete_game(request, id):
    game = get_object_or_404(Post, id=id)
    if not game.user == request.user:
        messages.error(request, "You are not authorised")
        return redirect(library)

    messages.success(request, "Game successfully deleted")
    game.delete()
    return redirect(library)


import os
import h5py
import pandas as pd
from PIL import Image
import numpy as np
import matplotlib.pyplot as plt
from collections import Counter

GRANULARITY = 0.025
SIZE_FINAL_MATRIX = 256

calocell_file = "data/calocell/user.cantel.33075755._000001.calocellD3PD_mc16_JZW4.r14423.h5"

def normalization_method(val, method, min=0, max=0, mean=0, std=0):
    if method == 0:
        return val
    elif method == 1:
        return np.log(val)
    elif method == 2:
        return 2*((val-min)/(max-min))-1
    elif method == 3:
        return ((val-min)/(max-min))
    elif method == 4:
        if val > max:
            val = max
        return ((val-min)/(max-min))
    elif method == 5:
        return (val-mean)/std
    elif method == 6:
        return val/max
    elif method == 7:
        return 1-(mean+std)/((mean+std)+val)
    elif method == 8:
        return (np.power(2, val)-1)/(2-1)

    return 0

########################################################################
# Deal generated matrices
########################################################################

matrices_training = []
matrices_validation = []
matrices_test = []

########################################################################
# Transform data
########################################################################

# Compute the len of phi and eta based on a given granularity
len_phi = len(np.arange(start=-3.15, stop=3.15+GRANULARITY, step=GRANULARITY))
len_eta = len(np.arange(start=-2.4, stop=2.4+GRANULARITY, step=GRANULARITY))

print("Size eta : " + str(len_eta))
print("Size phi : " + str(len_phi))

f = h5py.File(calocell_file, "r")

data_calo = f["caloCells"]["2d"][('cell_E', 'cell_Sigma', 'cell_eta', 'cell_phi', 'cell_pt')][0]

f.close()

df_calo = pd.DataFrame(data_calo,  columns=['cell_E', 'cell_Sigma', 'cell_eta', 'cell_phi', 'cell_pt'])

# Check if the cell_E is above 2 sigma (that defined that the energy is interesting)
# We keep the negative values
df_calo['cell_EoverSigma'] = (df_calo["cell_E"]/df_calo['cell_Sigma'])
df_calo = df_calo[df_calo['cell_EoverSigma'] > 2]
# df_calo[df_calo['cell_EoverSigma'] > 6] = 6

# df_calo['cell_eta_rounded'] = df_calo['cell_eta'].apply(lambda x : round(x*40)/40)

# df_calo['cell_phi_rounded'] = df_calo['cell_phi'].apply(lambda x : round(x*40)/40)

# matrix = np.zeros((3, len_phi, len_eta))

# for j in range(len(df_calo['cell_eta'])):
#     if np.absolute(df_calo['cell_eta'].iloc[j]) <= 2.4:
#         matrix[0][round((df_calo['cell_phi_rounded'].iloc[j] + 3.15) / (3.15*2) * (len_phi-1))][round((df_calo['cell_eta_rounded'].iloc[j] + 2.4) / (2.4*2) * (len_eta-1))] += df_calo["cell_EoverSigma"].iloc[j]
#         matrix[1][round((df_calo['cell_phi_rounded'].iloc[j] + 3.15) / (3.15*2) * (len_phi-1))][round((df_calo['cell_eta_rounded'].iloc[j] + 2.4) / (2.4*2) * (len_eta-1))] += df_calo["cell_pt"].iloc[j]

# val_min = matrix[0].min()
# val_max = matrix[0].max()
# val_mean = matrix[0].mean()
# val_std = matrix[0].std()

# val_min1 = matrix[1].min()
# val_max1 = matrix[1].max()
# val_mean1 = matrix[1].mean()
# val_std1 = matrix[1].std()

# for k in range(len(matrix[0])):
#     for j in range(len(matrix[0][k])):
#         matrix[0][k][j] = normalization_method(matrix[0][k][j], 7, val_min, val_max, val_mean, val_std)
#         matrix[1][k][j] = normalization_method(matrix[1][k][j], 7, val_min1, val_max1, val_mean1, val_std1)

# matrix = np.ascontiguousarray(matrix.transpose(1,2,0))

# matrix *= 255
# matrix = matrix.astype(np.uint8)

# im = Image.fromarray(matrix, 'RGB')

hist,bins = np.histogram(df_calo["cell_EoverSigma"])

print(len(hist))
print(len(bins))

print((df_calo['cell_EoverSigma'].lt(5)).sum())
print((df_calo['cell_EoverSigma'].ge(5)).sum())

print(df_calo["cell_EoverSigma"].mean())
print(df_calo["cell_EoverSigma"].median())
print(df_calo["cell_EoverSigma"].std())

plt.hist(df_calo["cell_EoverSigma"], 600)
plt.yscale('log')
plt.xscale('log')
plt.xlabel("Energie sur bruit")
plt.ylabel("Occurences")
plt.grid(axis='both', linestyle='--')
plt.show()

# plt.imshow(im)
# plt.show()