import json
import os
import argparse
import itertools

def argument_parser():

    parser = argparse.ArgumentParser(description='Process arguments')
    parser.add_argument('-j', '--json_file', type=str, default="./", help="path to json")
    parser.add_argument('-i', '--image_folder', type=str, default="./", help="path to imgs")
    parser.add_argument('-o', '--output_folder', type=str, default=None, help="path to output folder")

    return parser.parse_args()

# ===========================
# Main
# ===========================
Type = ['dial','meter']
if __name__ == '__main__':

    # ===============
    # INTRO
    # ===============

    opt = argument_parser()

    if opt.output_folder is None:
        output_folder = os.path.join(opt.image_folder,'annotations')
        if not os.path.exists(output_folder):
            os.makedirs(output_folder)
    else:
        output_folder = opt.output_folder

    js = open(opt.json_file) #os.path.join(opt.image_folder,'annot.json')

    data = json.load(js)

    print("Creating json files for %d images" % len(data.items()))

    for _ , value in data.items():
        filename = value['filename']

        basename = os.path.basename(filename)
        basename = os.path.splitext(basename)[0]
        output_filename = os.path.join(output_folder, basename + '.json')

        data = {}

        regions = value['regions']

        for attr in regions:
            # shape = regions[attr]['shape_attributes']
            # region = regions[attr]['region_attributes']
            shape = attr['shape_attributes']
            region = attr['region_attributes']

            if(region['type'] in Type):
                dd = dict(itertools.islice(region.items(), 3))
                shape.update(dd)
                idx = 'object' + region['identifier']
                data[idx] = []
                data[idx].append(shape)
            else:
                idx = 'object' + region['belongs to']
                shape['type'] = region['type']
                if len(region)==3:
                    shape['value'] = region['value']
                try:
                    data[idx].append(shape)
                except:
                    data[idx] = []
                    data[idx].append(shape)

        with open(output_filename, 'w') as outfile:
            print("Writing %s .." % output_filename)
            json.dump(data, outfile)


def Tandem_filter(fasta_file,k = 6,k_max = 3):

    # Import libs
    import itertools
    from Bio import SeqIO
    import matplotlib.pyplot as plt

    # k-mer based tandem filter
    list_k_mer = [''.join(c) for c in itertools.product(['A','C','G','T'], repeat=k)]

    with open(fasta_file,'r') as handle:
        dict_fasta = SeqIO.to_dict(rec.upper() for rec in SeqIO.parse(handle,'fasta'))

    # Remove sequences that have tandem repeats
    Output_Seq = [] # Sequence that will be used for peak calling
    Clear_Seq = [] # Sequence that will be removed
    peak_loc = []
    kmer_list = []
    N_loc = []
    for seq in dict_fasta:
        kmer_count = [dict_fasta[seq].seq.count(kmer) for kmer in list_k_mer]
        top_kmer = list_k_mer[kmer_count.index(max(kmer_count))]
        peaks = [kmer.start() for kmer in re.finditer(top_kmer, str(dict_fasta[seq].seq))]
        Ns = [kmer.start() for kmer in re.finditer(str('N'), str(dict_fasta[seq].seq))]
        if len(peaks)>=k_max or len(Ns)>1:
            peak_loc.append(peaks)
            Clear_Seq.append(dict_fasta[seq])
            kmer_list.append(top_kmer)
            N_loc.append(Ns)
        else:
            Output_Seq.append(dict_fasta[seq])

    # Plot all removed sequences for quality control
    f,ax = plt.subplots(int(len(Clear_Seq)/3)+1,3,figsize = (12,max(3,int(len(Clear_Seq)/10))))
    [axi.set_axis_off() for axi in ax.ravel()]
    ax = ax.ravel()
    plt.suptitle(fasta_file.split('/')[-1].split('.')[0])
    for ix,seq in enumerate(Clear_Seq):
        ax[ix].plot([0,len(seq)],[0,0],'lightblue')
        if len(N_loc[ix])>1:
            ax[ix].plot([N_loc[ix][0],N_loc[ix][-1]],[0,0],'grey')
        for x in peak_loc[ix]:
            ax[ix].plot([x,x+k],[0,0],'r')
            if k_max > 2:
                ax[ix].set_title(kmer_list[ix]+'='+str(len(peak_loc[ix])),fontsize = 10)
    with open(fasta_file[:-5]+'filtered.fasta','w') as output_handle:
        SeqIO.write(Output_Seq, output_handle, "fasta")


# -*- coding: utf-8 -*-
# Royal HaskoningDHV

from radar_calibrate.tests import testconfig
from radar_calibrate import files
from radar_calibrate import plot

import numpy as np

import argparse
import logging
import os

def get_parser():
    '''get argumentparser and add arguments'''
    parser = argparse.ArgumentParser(
        'plot difference of two radar images',
        )

    # Command line arguments
    parser.add_argument('firstfile', type=str,
        help=('input path to first HDF5 file (first - second)'))
    parser.add_argument('secondfile', type=str,
            help=('input path to second HDF5 file (first - second)'))
    parser.add_argument('-f', '--imagefile', type=str,
        help=('output calibrate path to HDF5 file'))
    parser.add_argument('--figsize', type=float, nargs=2,
        default=[10., 10.],
        help=('figure size (width, height) [inch]'))
    parser.add_argument('--shapefile', type=str,
        help=('path to background shapefile'))
    parser.add_argument('--vrange', type=float, nargs=2,
        default=[-10., 10.],
        help=('value range for image colormap'))
    parser.add_argument('--mask_range', type=float, nargs=2,
            default=[-1., 1.],
            help=('value range for image colormap'))
    return parser

def plot_image(**kwargs):
    # read first HDF5 file
    firstfile = kwargs['firstfile']
    first, basegrid, timestamp = files.read_file(firstfile)

    # read second HDF5 file
    secondfile = kwargs['secondfile']
    second, basegrid, timestamp = files.read_file(secondfile)

    # difference
    difference = first - second
    if kwargs.get('mask_range'):
        mask_lower, mask_upper = kwargs['mask_range']
        mask = (difference > mask_lower) & (difference < mask_upper)
        difference = np.ma.masked_array(difference, mask=mask)

    # plot to image file
    imagefile = kwargs.get('imagefile')
    if imagefile is None:
        filedir, filename = os.path.split(firstfile)
        name, ext = os.path.splitext(filename)
        imagefile = os.path.join(filedir, 'difference_{}.png'.format(name))

    # get figure size [inch]
    figsize = kwargs.get('figsize')

    # get shapefile from config if not given
    shapefile = kwargs.get('shapefile')
    if shapefile is None:
        shapefile = testconfig.BACKGROUND_SHAPEFILE

    # read features from shapefile
    features = files.read_shape(shapefile, basegrid.get_geotransform())

    # unpack value range
    vrange = kwargs['vrange']
    vmin, vmax = vrange

    plot.image(difference,
        imagefile=imagefile,
        figsize=figsize,
        features=features,
        vmin=vmin,
        vmax=vmax,
        cmap_under=None,
        cmap='coolwarm_r',
        )

def main():
    # parse command line arguments
    arguments = get_parser().parse_args()

    # run
    plot_image(**vars(arguments))

if __name__ == '__main__':
    logging.basicConfig(level=logging.DEBUG)
    main()


#!/usr/bin/python

import numpy as np
#import matplotlib.pyplot as plt
#import netCDF4
#import sys
#import time
#from datetime import datetime

#opening file
iyear='2014'
mypath='./out/'
from os import listdir
from os.path import isfile, join
onlyfiles = [ f for f in listdir(mypath) if isfile(join(mypath,f)) ]

#select only files for the year
yonlyfiles=[]
for f in onlyfiles:
    yf = f[-8:-4]
    if yf==iyear:
        yonlyfiles.append(f)

#initialization of array events for each season to zeros
lats=[]
lons=[]
e_spring=[]
e_summer=[]
e_autumn=[]
e_winter=[]
e1_spring, e2_spring, e3_spring = [], [], []
e1_summer, e2_summer, e3_summer = [], [], []
e1_autumn, e2_autumn, e3_autumn = [], [], []
e1_winter, e2_winter, e3_winter = [], [], []

#read file
import csv
#if in region, append
nsites=0
n=0
for fil in yonlyfiles:
		#print fil
		#observation reading
		readCSV = csv.reader(open(mypath+fil), delimiter='\t')
		i,j = 0, 0
		for row in readCSV:
			if i==0:
				site=row[1]
			if i==1:
				lat=float(row[1])
				lats.append(lat)
			if i==2:
				lon=float(row[1])
				lons.append(lon)
			if i>=4 and i<=7:
				seas=row[0]
				tot=int(row[1])
				s00=row[2]
				s01=row[3]
				s02=row[4]
				s03=row[5]
				s10=row[6]
				s11=row[7]
				s12=row[8]
				s13=row[9]
				s20=row[10]
				s21=row[11]
				s22=row[12]
				s23=row[13]
				s30=row[14]
				s31=row[15]
				s32=row[16]
				s33=row[17]
				if s10=='nan':
					s10=0
				if s11=='nan':
					s11=0
				if s12=='nan':
					s12=0
				if s13=='nan':
					s13=0
				if s20=='nan':
					s20=0
				if s21=='nan':
					s21=0
				if s22=='nan':
					s22=0
				if s23=='nan':
					s23=0
				if s30=='nan':
					s30=0
				if s31=='nan':
					s31=0
				if s32=='nan':
					s32=0
				if s33=='nan':
					s33=0

				if i==4:#spring
					e1_spring.append(0+int(s10)+int(s11)+int(s12)+int(s13))
					e2_spring.append(0+int(s20)+int(s21)+int(s22)+int(s23))
					e3_spring.append(0+int(s30)+int(s31)+int(s32)+int(s33))
					e_spring.append(e1_spring[n]+e2_spring[n]+e3_spring[n])

				if i==5:#summer
					e1_summer.append(0+int(s10)+int(s11)+int(s12)+int(s13))
					e2_summer.append(0+int(s20)+int(s21)+int(s22)+int(s23))
					e3_summer.append(0+int(s30)+int(s31)+int(s32)+int(s33))
					e_summer.append(e1_summer[n]+e2_summer[n]+e3_summer[n])
				if i==6:#autumn
					e1_autumn.append(0+int(s10)+int(s11)+int(s12)+int(s13))
					e2_autumn.append(0+int(s20)+int(s21)+int(s22)+int(s23))
					e3_autumn.append(0+int(s30)+int(s31)+int(s32)+int(s33))
					e_autumn.append(e1_autumn[n]+e2_autumn[n]+e3_autumn[n])
				if i==7:#winter
					e1_winter.append(0+int(s10)+int(s11)+int(s12)+int(s13))
					e2_winter.append(0+int(s20)+int(s21)+int(s22)+int(s23))
					e3_winter.append(0+int(s30)+int(s31)+int(s32)+int(s33))
					e_winter.append(e1_winter[n]+e2_winter[n]+e3_winter[n])

			i=i+1

		n=n+1

# plot
from mpl_toolkits.basemap import Basemap
import matplotlib.pyplot as plt

#fig=plt.figure(i+j*10,figsize=(8, 4), dpi=240)
#fig=plt.figure(1,figsize=(8, 4), dpi=240)
#ax=plt.gca()
fig,ax=plt.subplots(2,2,figsize=(12,6))

# setup Lambert Conformal basemap.
# set resolution=None to skip processing of boundary datasets.
#m = Basemap(width=12000000,height=9000000,projection='lcc',
#            resolution=None,lat_1=i-90.,lat_2=0,lat_0=-90,lon_0=180.)

seasons=['Spring','Summer','Autumn','Winter']
j=0
for s in seasons:
		if s=='Spring':
			cols=[e1_spring,e2_spring,e3_spring,e_spring]
			axx=ax[0,0]
		if s=='Summer':
			cols=[e1_summer,e2_summer,e3_summer,e_summer]
			axx=ax[0,1]
		if s=='Autumn':
			cols=[e1_autumn,e2_autumn,e3_autumn,e_autumn]
			axx=ax[1,0]
		if s=='Winter':
			cols=[e1_winter,e2_winter,e3_winter,e_winter]
			axx=ax[1,1]
		for i in range(3,4):
				col=cols[j]
				if i==0:
					title='High alerts'+' - '+s+' '+iyear
				if i==1:
					#col=e2_spring
					title='Very high alerts'+' - '+s+' '+iyear
				if i==2:
					#col=e3_spring
					title='Extreme alerts'+' - '+s+' '+iyear
				if i==3:
					#col=e_spring
					title=s+' '+iyear

				map = Basemap(width=12000000,height=9000000,projection='cyl',
					resolution=None,llcrnrlat=-90,urcrnrlat=90, llcrnrlon=-180,urcrnrlon=180,ax=axx)
				#map.bluemarble()
				map.shadedrelief()
				#map.etopo()

				#for i in range(0,n-1)
				cm = plt.cm.get_cmap('Reds',10)
				sc = map.scatter(lons,lats,c=col,s=20,vmin=0,vmax=10,cmap=cm,linewidth='0.25',edgecolor='#848484')

				#title
				axx.set_title(title)

				# of ax and the padding between cax and ax will be fixed at 0.05 inch.
				from mpl_toolkits.axes_grid1 import make_axes_locatable
				divider = make_axes_locatable(axx)
				cax = divider.append_axes("right", size="5%", pad=0.25)
				cbar=plt.colorbar(sc,cax=cax,extend='max')
				cbar.set_label('Number of alerts', rotation=270)

		j=j+1

fig.tight_layout()
fig.show()
fig.savefig('./maps/Map-'+iyear+'.png', dpi=300)

#analysis per region
regions=['World','Africa','Europe','Asia']

# - - - - - - - - - - - - - - - - - - - -
from matplotlib.patches import Polygon
#plot different regions
fig = plt.figure(2,figsize=(12,6))
axx=plt.gca()
map = Basemap(width=12000000,height=9000000,projection='cyl',
resolution=None,llcrnrlat=-90,urcrnrlat=90, llcrnrlon=-180,urcrnrlon=180,ax=axx)
map.shadedrelief()

#add rectangle defined by coordinates
def draw_screen_poly(lats, lons):
	x, y = lons, lats
	xy = zip(x,y)
	poly = Polygon( xy, facecolor='red', alpha=0.3, linewidth=0.5, color='black' )
	axx.add_patch(poly)

#analysis per region
regions=['World','Africa','Europe','Asia']

for region in regions[1:len(regions)]:
	n=0
	idx=[]

	if region=='Europe':
		lat_min, lat_max = 38.27, 69.16
		lon_min, lon_max = -25.13, 52.91
	elif region=='Africa':
		lat_min, lat_max = -40.31, 36.80
		lon_min, lon_max = -23.9, 57.77
	elif region=='Asia':
		lat_min, lat_max = 5.26, 55.38
		lon_min, lon_max = 58.54, 147.13

	rlats = [ lat_min, lat_min, lat_max, lat_max ]
	rlons = [ lon_min, lon_max, lon_max, lon_min ]
	draw_screen_poly(rlats, rlons)

fig.tight_layout()
fig.show()
fig.savefig('./maps/Map-Areas.png', dpi=300)
# - - - - - - - - - - - - - - - - - - - -

# - - - - - - - - - - - - - - - - - - - -
# histograms per regions
fig,ax=plt.subplots(2,2,figsize=(12,6))

for region in regions:
	n=0
	idx=[]

	if region=='World':
		lat_min, lat_max = -90, 90
		lon_min, lon_max = -180, 180
		axx=ax[0,0]
	elif region=='Europe':
		lat_min, lat_max = 38.27, 69.16
		lon_min, lon_max = -25.13, 52.91
		axx=ax[0,1]
	elif region=='Africa':
		lat_min, lat_max = -40.31, 36.80
		lon_min, lon_max = -23.9, 57.77
		axx=ax[1,0]
	elif region=='Asia':
		lat_min, lat_max = 5.26, 55.38
		lon_min, lon_max = 58.54, 147.13
		axx=ax[1,1]

	#loop on all measurments and filter by lat/lon
	for lat in lats:
		if lat>lat_min and lat<lat_max and lons[n]>lon_min and lons[n]<lon_max:
			idx.append(n)
		n=n+1
	#idx = np.array(idx)
	e1_spring=np.array(e1_spring)
	e1_summer=np.array(e1_summer)
	e1_autumn=np.array(e1_autumn)
	e1_winter=np.array(e1_winter)
	e2_spring=np.array(e2_spring)
	e2_summer=np.array(e2_summer)
	e2_autumn=np.array(e2_autumn)
	e2_winter=np.array(e2_winter)
	e3_spring=np.array(e3_spring)
	e3_summer=np.array(e3_summer)
	e3_autumn=np.array(e3_autumn)
	e3_winter=np.array(e3_winter)

	h1plot=[sum(e1_spring[idx]),sum(e1_summer[idx]),sum(e1_autumn[idx]),sum(e1_winter[idx])]
	h2plot=[sum(e2_spring[idx]),sum(e2_summer[idx]),sum(e2_autumn[idx]),sum(e2_winter[idx])]
	h3plot=[sum(e3_spring[idx]),sum(e3_summer[idx]),sum(e3_autumn[idx]),sum(e3_winter[idx])]
	ind=np.arange(4)
	width=0.1
	gap=0.03
	axx.bar(ind,h1plot,width,color='peachpuff',label='High')
	axx.bar(ind+(width+gap),h2plot,width,color='coral',label='Very High')
	axx.bar(ind+2*(width+gap),h3plot,width,color='red',label='Extreme')

	#title
	axx.set_title(region)
	#xlabel
	axx.set_xticks([0.25,1.25,2.25,3.25])
	axx.set_xticklabels(['Spring','Summer','Autumn','Winter'])

	axx.set_ylim([0,250])
	xs=axx.get_xlim()
	axx.set_xlim([xs[0]-width,xs[1]])
	axx.tick_params(axis='x',which='both',bottom='off',top='off')

	#add number of events per season
	from pylab import text
	htplot=[x+y+z for x,y,z in zip(h1plot,h2plot,h3plot)]
	axx.text(ind[0]+(width+gap)-0.05,max(h1plot[0],h2plot[0],h2plot[0])+10, str(htplot[0]),size=12,color='black',bbox=dict(facecolor='white', alpha=0.0, linewidth=0))
	axx.text(ind[1]+(width+gap)-0.05,max(h1plot[1],h2plot[1],h2plot[1])+10, str(htplot[1]),size=12,color='black',bbox=dict(facecolor='white', alpha=0.0, linewidth=0))
	axx.text(ind[2]+(width+gap)-0.05,max(h1plot[2],h2plot[2],h2plot[2])+10, str(htplot[2]),size=12,color='black',bbox=dict(facecolor='white', alpha=0.0, linewidth=0))
	axx.text(ind[3]+(width+gap)-0.05,max(h1plot[3],h2plot[3],h2plot[3])+10, str(htplot[3]),size=12,color='black',bbox=dict(facecolor='white', alpha=0.0, linewidth=0))

	#legend in Europe fig
	if region=='Europe':
		axx.legend(loc='upper right', ncol=1, fancybox=True, shadow=True, prop={'size':12})

#fig.savefig('./maps/Histo-'+iyear+'.png', dpi=300)
fig.show()
# - - - - - - - - - - - - - - - - - - - -

print("something")
wait = input("PRESS ENTER TO CONTINUE.")


"""mlm URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/1.11/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  url(r'^$', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  url(r'^$', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.conf.urls import url, include
    2. Add a URL to urlpatterns:  url(r'^blog/', include('blog.urls'))
"""
from django.conf.urls import url, include
from django.contrib import admin
from django.conf.urls.static import static
from mlm import settings
from shop_mlm.urls import cabinet_urlpatterns
from user_accounts.views import referral, AdminLoginRedirect
from django.contrib.sitemaps.views import sitemap
from django.contrib import sitemaps
from blog.sitemaps import BlogPostSitemap, BlogCategorySitemap, BlogTagSitemap
from django.urls import reverse

class StaticViewSitemap(sitemaps.Sitemap):
    priority = 0.5
    changefreq = 'daily'

    def items(self):
        return ['landing', 'upravlenie', 'about-us', 'active']

    def location(self, item):
        return reverse(item)

sitemaps = {
    'blog_categories': BlogCategorySitemap,
    'blog_posts': BlogPostSitemap,
    'blog_tags': BlogTagSitemap,
    'static': StaticViewSitemap,
}

urlpatterns = [
    url(r'^jet/', include('jet.urls', 'jet')),
    url(r'^admin/login/$', AdminLoginRedirect.as_view()),
    url(r'^admin/', admin.site.urls),
    url(r'^ckeditor/', include('ckeditor_uploader.urls')),
    url(r'^r/(?P<referral>[0-9A-Za-z]+)$', referral, name='referral-register'),
    url(r'^dashboard/', include([
        url(r'^', include('dashboard.urls')),
        url(r'^binary/', include('binary_tree.urls')),
        url(r'^account/', include('user_accounts.urls')),
        url(r'^payment/', include('payment.urls')),
        url(r'^linear-tree/', include('linear_tree.urls')),
        url(r'^finance/', include('finance.urls')),
        url(r'^investing/', include('investing.urls')),
        url(r'^calendar/', include('calendar_mlm.urls')),
        url(r'^legal/', include('legal_agreements.urls')),
        url(r'^faq/', include('faq.urls')),
        url(r'^lessons/', include('lessons.urls')),
        url(r'^packages/', include('partner_packages.urls')),
        url(r'^questions/', include('faq_new.urls')),
        url(r'^monastic-world/', include('monastic_world.urls')),
        url(r'^shop/', include(cabinet_urlpatterns)),
        url(r'^verification/', include('verification.urls')),
        url(r'^reports/', include('reports.urls')),
    ])),
    url(r'^', include('publick.urls')),
    url(r'^i18n/', include('django.conf.urls.i18n')),
    url(r'^blog/', include('blog.urls')),
    url(r'^telegram/', include('telegram_bot.urls')),
    url(r'^sitemap\.xml$', sitemap, {'sitemaps': sitemaps}, name='django.contrib.sitemaps.views.sitemap')
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

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


from flask import Flask, url_for, render_template, Response, request, redirect, g, session
from keras.preprocessing.image import load_img, img_to_array
from keras.models import load_model
import numpy as np
import cv2
import json
import random
from flask_babel import Babel, gettext
from datetime import datetime
import os
import tensorflow as tf
from tensorflow.python.keras.backend import set_session
app = Flask(__name__)
babel = Babel(app)

app.config['lang_code'] = ['en', 'ko']

sess = tf.Session()
graph = tf.get_default_graph()

set_session(sess)
alphamodel = load_model('model/handlang_model_4.h5')
numbmodel = load_model('model/su_adamax.h5')

print("Loaded model from disk")

# crop_img 엉키지 않게
class Microsecond(object):
    def __init__(self):
        dt = datetime.now()
        self.microsecond = dt.microsecond

    def get_path_name(self):
        return 'model/' + str(self.microsecond)

crop_img_origin_path = Microsecond()
default_img = cv2.imread('model/crop_img.jpg')

# 새로운 폴더 만들기!
try:
    if not(os.path.isdir(crop_img_origin_path.get_path_name())):
        os.makedirs(os.path.join(crop_img_origin_path.get_path_name()))
except OSError as e:
    if e.errno != errno.EEXIST:
        print("Failed to create directory!!!!!")
        raise

# make directory
origin_path = crop_img_origin_path.get_path_name() + '/crop_img.jpg'
cv2.imwrite(origin_path, default_img)

class Models:
    def __init__(self,label,letter_list):
        self.__label=label
        self.__letter_list=letter_list

    def get_label(self,idx):
        # label = ["A", "B", "C", "D", "E", "F", "G",
        #     "H", "I", "K", "L", "M", "N", "O", "P", "Q",
        #     "R", "S", "T", "U", "V", "W", "X", "Y",
        #     "del", "nothing", "space"]
        return self.__label[idx]
    def get_letter_list(self):
        # alphabet_list = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'k', 'l', 'm', 'n', 'o',
        #              'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y']
        return self.__letter_list
    def letter_list_idx(self,element):
        next_topic = ""
        previous_topic = ""
        letter_list=self.__letter_list
        list_idx_end = len(letter_list) - 1  # 마지막 인덱스
        idx_now = letter_list.index(element)
        if idx_now == list_idx_end:
            next_topic = letter_list[0]
        else:
            next_topic = letter_list[idx_now + 1]
        if idx_now != 0:
            previous_topic = letter_list[idx_now - 1]
        return next_topic, previous_topic
alphabet_label=["A", "B", "C", "D", "E", "F", "G",
             "H", "I", "K", "L", "M", "N", "O", "P", "Q",
            "R", "S", "T", "U", "V", "W", "X", "Y",
            "del", "nothing", "space"]
alphabet_list=['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'k', 'l', 'm', 'n', 'o',
                      'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y']

number_label = ["0","1","2","3","4","5","6","7","8","9","del", "nothing", "space"]
number_list = ['0','1','2','3','4','5','6','7','8','9']
alphabet_model=Models(alphabet_label,alphabet_list)
number_model= Models(number_label, number_list)

def get_model(group):
    if group=="alphabet":
        return alphabet_model
    if group=="number":
        return number_model

# ** 전역변수 대신 클래스 객체 사용
class PredictLabel(object):
    def __init__(self, label):
        self.label = label

    def set_label(self, label):
        self.label = label

    def get_label(self):
        return self.label

class Target_idx(object):
    def __init__(self, idx):
        self.idx = idx

    def set_idx(self, idx):
        self.idx = idx

    def get_idx(self):
        return self.idx

target_idx = Target_idx(0)
predict_label = PredictLabel('')

#
total_q = 5

@babel.localeselector
def get_locale():
    try:
        language = session['language']
    except KeyError:
        language = "ko"
    if language is not None:
        return language
    return request.accept_languages.best_match(['en', 'ko'])

def get_alphabet_list():
    alphabet_list = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'k', 'l', 'm', 'n', 'o',
                     'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y']

    return alphabet_list

def gen(camera,group):
    global alphamodel
    global numbmodel
    if not camera.isOpened():
        raise RuntimeError("Could not start camera")
    if(group=='alphabet'):
        model=alphamodel
    else:
        model = numbmodel

    while True:
        success, img = camera.read()
        if success:
            try:

                cv2.rectangle(img, (250,250), (600,600), (000,51,51), 2)

                crop_img = img[250:600, 250:600]
                crop_img_path = crop_img_origin_path.get_path_name() + '/crop_img.jpg'
                cv2.imwrite(crop_img_path, crop_img)
                # # print(crop_img)
                # result = model_predict()
                image = load_img(crop_img_path, target_size=(64,64))
                image = img_to_array(image)
                image = image.reshape((1, image.shape[0], image.shape[1], image.shape[2]))
                global sess
                global graph
                with graph.as_default():
                    set_session(sess)
                    prediction = model.predict(image)

                target_idx_for_predict = target_idx.get_idx()
                print("타겟예측: ", prediction[0][target_idx_for_predict])

                if np.argmax(prediction[0]) == 1:
                    result = get_model(group).get_label(np.argmax(prediction[0]))

                elif prediction[0][target_idx_for_predict] > 0:
                    result = get_model(group).get_label(target_idx_for_predict)
                else:
                    result = ''

                predict_label.set_label(result)

                ret, jpeg = cv2.imencode('.jpg', crop_img)
                frame = jpeg.tobytes()

                yield (b'--frame\r\n'
                       b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n\r\n')
            except:
                print("An exception occurred")

        else:
            print("Status of camera.read()\n", success, "\n=======================")

def make_quiz(language_model):
    question_list = {}
    img_list = []
    for i in range(total_q):
        question, examples, img = make_random_quiz(question_list,language_model)
        question_list[question] = examples
        img_list.append(img)
    return question_list, img_list

def make_random_quiz(question_list,language_model):
    alphabet_list = language_model.get_letter_list()
    examples = []  # 보기
    while True:
        answer = alphabet_list[random.randint(0, len(alphabet_list) - 1)]
        if is_valid_quiz(answer, question_list):
            break
    examples.append(answer)
    while len(examples) != 4:
        randomIndex = random.randint(0, len(alphabet_list) - 1)
        if alphabet_list[randomIndex] not in examples:
            examples.append(alphabet_list[randomIndex])
    random.shuffle(examples)
    img = []
    for i in examples:
        img.append('../static/img/asl_' + i + ".png")

    return answer, examples, img

# 이전에 낸 문제인지 확인
def is_valid_quiz(answer, question_list):
    if answer in question_list:
        return False
    else:
        return True

@app.route('/return_label', methods=['POST', 'GET'])
def return_label():
    value = request.form.get("target", False)
    # 띄어쓰기 조심!@!

    label_list = [" A ", " B ", " C ", " D ", " E ", " F ", " G ",
            " H ", " I ", " J ", " K ", " L ", " M ", " N ", " O ", " P ", " Q ",
            " R ", " S ", " T ", " U ", " V ", " W ", " X ", " Y ", " Z ",
            " del ", " nothing ", " space "]

    tem = label_list.index(value)
    print(tem)
    idx = target_idx.set_idx(tem)
    print(idx)
    label = " " + predict_label.get_label() + " "

    # ajax 에서 값 받아올때 공백이 앞뒤로 붙는데 python strip() 함수가 안먹어서...

    if label == '':
        predict_result = {
            'status': 0,
            'info': 'not detected',
            'label': '',
            'lang_code': session['language']

        }
    elif label != value:
        predict_result = {
            'status': 0,
            'info': gettext('predict_incorrect'),
            'label': label,
            'lang_code': session['language']

        }
        print("틀림!")
    else:
        predict_result = {
            'status': 1,
            'info': gettext('predict_correct'),
            'label': label,
            'lang_code': session['language']
        }

    # result 의 status 값이 1이면 참 -> main.js 에서 correct 값 증가

    json_data = json.dumps(predict_result)  # json 형태로 바꿔줘야 에러 안남
    return json_data

@app.route('/return_label2', methods=['POST', 'GET'])
def return_label2():
    value = request.form.get("target", False)
    # 띄어쓰기 조심!@!

    label_list = [" 0 ", " 1 "," 2 ", " 3 ", " 4 ", " 5 ", " 6 ", " 7 ", " 8 ", " 9 ", " del ", " nothing ", " space "]

    tem = label_list.index(value)
    print(tem)
    idx = target_idx.set_idx(tem)
    print(idx)
    label = " " + predict_label.get_label() + " "

    # ajax 에서 값 받아올때 공백이 앞뒤로 붙는데 python strip() 함수가 안먹어서...

    if label == '':
        predict_result = {
            'status': 0,
            'info': 'not detected',
            'label': '',
            'lang_code': session['language']

        }
    elif label != value:
        predict_result = {
            'status': 0,
            'info': gettext('predict_incorrect'),
            'label': label,
            'lang_code': session['language']

        }
        print("틀림!")
    else:
        predict_result = {
            'status': 1,
            'info': gettext('predict_correct'),
            'label': label,
            'lang_code': session['language']
        }

    # result 의 status 값이 1이면 참 -> main.js 에서 correct 값 증가

    json_data = json.dumps(predict_result)  # json 형태로 바꿔줘야 에러 안남
    return json_data

# for ajax
@app.route('/english')
def english():
    session['language'] = 'en'
    link = request.args.get('link')
    if link:
        return redirect(link)
    else:
        return redirect('/')

# for ajax
@app.route('/korean')
def korean():
    session['language'] = 'ko'
    link = request.args.get('link')
    if link:
        return redirect(link)
    else:
        return redirect('/')

@app.route('/quiz/<group>', methods=['GET', 'POST'])
def quiz(group):
    if request.method == 'GET':
        language_model=get_model(group)
        question_list, img_list = make_quiz(language_model)
        print(question_list)
        return render_template('quiz.html',group=group, str=str, enumerate=enumerate, question_list=question_list,
                               img_list=img_list, total_q=total_q, link=request.full_path)

    if request.method == 'POST':
        user_answers = {}
        for i in range(total_q):
            question = "question" + str(i)
            answer = "answer" + str(i)
            q = request.form[question]
            a = request.form[answer]
            user_answers[q] = a
            print(user_answers)
        user_answers = json.dumps(user_answers)

        return redirect(url_for('quiz_result',group=group, user_answers=user_answers))

@app.route('/quiz/<group>/result')
def quiz_result(group):
    try:
        user_answers = json.loads(request.args['user_answers'])
        items = user_answers.items()
    except:
        user_answers = {}
    items = user_answers.items()
    correct_num = 0
    incorrect_questions = []
    for q, a in items:
        if (q == a):
            correct_num += 1
        else:
            incorrect_questions.append(q.upper())

    if correct_num == total_q:
        img_path = "score_100.png"
    elif correct_num >= (total_q // 2):
        img_path = "score_50.png"
    else:
        img_path = "score_0.png"
    print(img_path)
    return render_template('result.html', group=group,correct_num=correct_num, incorrect_questions=incorrect_questions,
                           total_q=total_q, img_path=img_path, link=request.full_path)

@app.route('/<group>')
def practice_list(group):
    alphabet_list = get_model(group).get_letter_list()
    return render_template('practice_list.html',group=group , alphabet_list=alphabet_list, link=request.full_path)

# video streaming
@app.route('/<group>/video_feed')
def video_feed(group):
    camera = cv2.VideoCapture(0)
    return Response(gen(camera,group), mimetype='multipart/x-mixed-replace; boundary=frame')

@app.route('/<group>/practice', methods=['GET', 'POST'])
def practice(group):
    element = request.args.get('element')
    if(group=='alphabet'):
        alphabet=element.upper()
    else:
        alphabet=element

    img = "../static/img/asl_" + element + ".png"

    next_topic, previous_topic = get_model(group).letter_list_idx(element)

    return render_template('practice.html',group=group,alphabet=alphabet, img=img, previous_topic=previous_topic,
                           next_topic=next_topic, link=request.full_path)

@app.route('/')
def index():
    if session.get('language') is None:
        session['language'] = 'ko'
    return render_template('index.html', link=request.full_path)

if __name__ == "__main__":
    app.secret_key = 'super secret key'
    app.config['SESSION_TYPE'] = 'filesystem'

    app.run(host='0.0.0.0', port=5000, debug=True)


import tensorflow as tf
import tflearn
from tflearn.layers.conv import conv_2d, max_pool_2d
from tflearn.layers.core import input_data, dropout, fully_connected
from tflearn.layers.estimator import regression
import numpy as np
from PIL import Image
import cv2
import imutils

class HGR:

    bg = None
    clone = None
    thresholded = None
    predicted_class = None
    confidence = None

    def __init__(self, video_source=0, model_location="TrainedModel/GestureRecogModel.tfl"):
        tf.reset_default_graph()
        convnet = input_data(shape=[None, 89, 100, 1], name='input')
        convnet = conv_2d(convnet, 32, 2, activation='relu')
        convnet = max_pool_2d(convnet, 2)
        convnet = conv_2d(convnet, 64, 2, activation='relu')
        convnet = max_pool_2d(convnet, 2)

        convnet = conv_2d(convnet, 128, 2, activation='relu')
        convnet = max_pool_2d(convnet, 2)

        convnet = conv_2d(convnet, 256, 2, activation='relu')
        convnet = max_pool_2d(convnet, 2)

        convnet = conv_2d(convnet, 256, 2, activation='relu')
        convnet = max_pool_2d(convnet, 2)

        convnet = conv_2d(convnet, 128, 2, activation='relu')
        convnet = max_pool_2d(convnet, 2)

        convnet = conv_2d(convnet, 64, 2, activation='relu')
        convnet = max_pool_2d(convnet, 2)

        convnet = fully_connected(convnet, 1000, activation='relu')
        convnet = dropout(convnet, 0.75)

        convnet = fully_connected(convnet, 7, activation='softmax')

        convnet = regression(convnet, optimizer='adam', learning_rate=0.001, loss='categorical_crossentropy',
                             name='regression')

        self.model = tflearn.DNN(convnet, tensorboard_verbose=0)

        # Load Saved Model
        self.model.load(model_location)

        # initialize weight for running average
        self.a_weight = 0.5

        # get the reference to the webcam
        self.camera = cv2.VideoCapture(video_source)

        # region of interest (ROI) coordinates
        self.top, self.right, self.bottom, self.left = 10, 350, 225, 590

        # initialize num of frames
        self.num_frames = 0

    def predict(self):
        predicted_class = None
        confidence = None
        # get the current frame
        (grabbed, frame) = self.camera.read()

        # resize the frame
        frame = imutils.resize(frame, width=700)

        # flip the frame so that it is not the mirror view
        frame = cv2.flip(frame, 1)

        # clone the frame
        self.clone = frame.copy()

        # get the height and width of the frame
        (height, width) = frame.shape[:2]

        # get the ROI
        roi = frame[self.top:self.bottom, self.right:self.left]

        # convert the roi to grayscale and blur it
        gray = cv2.cvtColor(roi, cv2.COLOR_BGR2GRAY)
        gray = cv2.GaussianBlur(gray, (7, 7), 0)

        # to get the background, keep looking till a threshold is reached
        # so that our running average model gets calibrated
        if self.num_frames < 30:
            self.run_avg(gray, self.a_weight)
        else:
            # segment the hand region
            hand = self.segment(gray)

            # check whether hand region is segmented
            if hand is not None:
                # if yes, unpack the thresholded image and
                # segmented region
                (self.thresholded, segmented) = hand

                # draw the segmented region and display the frame
                cv2.drawContours(self.clone, [segmented + (self.right, self.top)], -1, (0, 0, 255))
                cv2.imwrite('Temp.png', self.thresholded)
                self.resize_image('Temp.png')
                self.predicted_class, self.confidence = self.get_predicted_class()

        # draw the segmented hand
        cv2.rectangle(self.clone, (self.left, self.top), (self.right, self.bottom), (0, 255, 0), 2)

        # increment the number of frames
        self.num_frames += 1

    def get_frame(self):
        return self.clone

    def get_thresholded_hand(self):
        return self.thresholded

    def run_avg(self, image, a_weight):
        # initialize the background
        if self.bg is None:
            self.bg = image.copy().astype("float")
            return

        # compute weighted average, accumulate it and update the background
        cv2.accumulateWeighted(image, self.bg, a_weight)

    def segment(self, image, threshold=25):
        # find the absolute difference between background and current frame
        diff = cv2.absdiff(self.bg.astype("uint8"), image)

        # threshold the diff image so that we get the foreground
        thresholded = cv2.threshold(diff,
                                    threshold,
                                    255,
                                    cv2.THRESH_BINARY)[1]

        # get the contours in the thresholded image
        (cnts, _) = cv2.findContours(thresholded.copy(),
                                     cv2.RETR_EXTERNAL,
                                     cv2.CHAIN_APPROX_SIMPLE)

        # return None, if no contours detected
        if len(cnts) == 0:
            return
        else:
            # based on contour area, get the maximum contour which is the hand
            segmented = max(cnts, key=cv2.contourArea)
            return thresholded, segmented

    def get_predicted_class(self):
        # Predict
        image = cv2.imread('Temp.png')
        gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
        prediction = self.model.predict([gray_image.reshape(89, 100, 1)])
        predicted_class = np.argmax(prediction)
        if predicted_class == 0:
            class_name = "Palm"
        elif predicted_class == 1:
            class_name = "Fist"
        elif predicted_class == 2:
            class_name = "OK"
        elif predicted_class == 3:
            class_name = "Thumb"
        elif predicted_class == 4:
            class_name = "V"
        elif predicted_class == 5:
            class_name = "L"
        elif predicted_class == 6:
            class_name = "Swing"
        return class_name, (np.amax(prediction) / (
                    prediction[0][0] + prediction[0][1] + prediction[0][2] + prediction[0][3] + prediction[0][4] +
                    prediction[0][5] + prediction[0][6]))

    def resize_image(self, image_name):
        basewidth = 100
        img = Image.open(image_name)
        wpercent = (basewidth / float(img.size[0]))
        hsize = int((float(img.size[1]) * float(wpercent)))
        img = img.resize((basewidth, hsize), Image.ANTIALIAS)
        img.save(image_name)


from panda3d.core import PStatClient, Thread
from direct.directnotify import DirectNotifyGlobal
from otp.settings.Settings import Settings
from direct.stdpy import threading
import OTPLocalizer
import atexit, subprocess, psutil, sys, os, wx

DEFAULT_TEXT = ''
DEFAULT_IMPORTS = '''from panda3d.core import *
from direct.actor.Actor import Actor
from direct.interval.IntervalGlobal import *
from direct.gui.DirectGui import *
from otp.otpbase import OTPGlobals, OTPLocalizer
from pirates.piratesbase import PiratesGlobals, PLocalizer
'''

class CustomDialog(wx.Dialog):

    def __init__(self, parent, caption, title, inputMethod):
        wx.Dialog.__init__(self, parent, -1, title)

        self.text = wx.StaticText(self, -1, caption)
        self.input = inputMethod(self)
        self.buttons = self.CreateButtonSizer(wx.OK | wx.CANCEL)
        self.sizer = wx.BoxSizer(wx.VERTICAL)

        self.sizer.Add(self.text, 0, wx.ALL, 5)
        self.sizer.Add(self.input, 1, wx.EXPAND | wx.ALL, 5)
        self.sizer.Add(self.buttons, 0, wx.EXPAND | wx.ALL, 5)
        self.SetSizerAndFit(self.sizer)
        self.input.SetFocus()
        self.Centre()

class ListDialog(CustomDialog):

    def __init__(self, parent, caption, title, choices):
        CustomDialog.__init__(self, parent, caption, title, lambda self: wx.ListBox(self, choices=sorted(choices)))

class InputDialog(CustomDialog):

    def __init__(self, parent, caption, title):
        CustomDialog.__init__(self, parent, caption, title, lambda self: wx.TextCtrl(self))

    def getInput(self):
        return self.input.GetValue()

class Injector:
    notify = DirectNotifyGlobal.directNotify.newCategory('Injector')

    def __init__(self):
        self.snippets = Settings('snippets.json')
        self.app = wx.App(redirect=False)
        self.frame = wx.Frame(None, title=OTPLocalizer.InjectorTitle, size=(635, 325), style=wx.SYSTEM_MENU | wx.CAPTION | wx.MINIMIZE_BOX | wx.CLOSE_BOX | wx.RESIZE_BORDER)
        self.panel = wx.Panel(self.frame)

        self.buttonPanel = wx.Panel(self.panel)
        self.checkboxPanel = wx.Panel(self.panel)
        self.sizer = wx.BoxSizer(wx.VERTICAL)
        self.buttonSizer = wx.BoxSizer(wx.HORIZONTAL)
        self.checkboxSizer = wx.BoxSizer(wx.HORIZONTAL)

        self.injectBox = wx.TextCtrl(parent=self.panel, style=wx.TE_MULTILINE | wx.TE_RICH2)
        self.injectButton = wx.Button(parent=self.buttonPanel, size=(100, 50), label=OTPLocalizer.InjectorInject)
        self.injectAiButton = wx.Button(parent=self.buttonPanel, size=(100, 50), label=OTPLocalizer.InjectorInjectAI)
        self.saveButton = wx.Button(parent=self.buttonPanel, size=(100, 50), label=OTPLocalizer.InjectorSave)
        self.loadButton = wx.Button(parent=self.buttonPanel, size=(100, 50), label=OTPLocalizer.InjectorLoad)
        self.removeButton = wx.Button(parent=self.buttonPanel, size=(100, 50), label=OTPLocalizer.InjectorRemove)
        self.pstatsBox = wx.CheckBox(parent=self.checkboxPanel, label=OTPLocalizer.InjectorPStats)

        self.injectBox.SetLabel(DEFAULT_TEXT)
        self.injectBox.Bind(wx.EVT_KEY_DOWN, self.__keyDown)
        self.injectButton.Bind(wx.EVT_BUTTON, self.__inject)
        self.injectAiButton.Bind(wx.EVT_BUTTON, lambda event: self.__inject(event, True))
        self.saveButton.Bind(wx.EVT_BUTTON, self.__save)
        self.loadButton.Bind(wx.EVT_BUTTON, self.__load)
        self.removeButton.Bind(wx.EVT_BUTTON, self.__remove)
        self.pstatsBox.Bind(wx.EVT_CHECKBOX, self.__pstats)

        self.addToSizer(self.buttonSizer, self.injectButton, self.injectAiButton, self.saveButton, self.loadButton, self.removeButton)
        self.addToSizer(self.checkboxSizer, self.pstatsBox)

        self.sizer.Add(self.checkboxPanel, 0, wx.ALIGN_CENTER)
        self.sizer.Add(self.injectBox, 1, wx.EXPAND)
        self.sizer.Add(self.buttonPanel, 0, wx.ALIGN_CENTER)

        self.buttonPanel.SetSizer(self.buttonSizer)
        self.panel.SetSizer(self.sizer)
        self.frame.SetMinSize((635, 325))
        self.frame.Show()

        atexit.register(self.__pstatCleanup)
        threading.Thread(target=self.app.MainLoop).start()

    def addToSizer(self, sizer, *args):
        for i, arg in enumerate(args):
            if i:
                sizer.AddSpacer(30)

            sizer.Add(arg)

    def info(self, parent, message, caption, icon=wx.ICON_INFORMATION, buttons=wx.OK):
        return wx.MessageDialog(parent, message, caption, buttons | icon).ShowModal() == wx.ID_YES

    def chooseSnippet(self, caption):
        dialog = ListDialog(self.frame, caption, OTPLocalizer.InjectorTitle, self.snippets.keys())

        if dialog.ShowModal() == wx.ID_OK:
            return dialog.input.GetStringSelection()

    def reloadSnippets(self):
        self.snippets.read()

    def saveSnippet(self, name, content):
        self.snippets[name] = content

    def getPandaDirectory(self):
        return os.sep.join(sys.path[1].split(os.sep)[:-2])

    def getPStatsPath(self):
        return os.path.join(self.getPandaDirectory(), 'bin', 'pstats')

    def getProcesses(self, name):
        return [process for process in psutil.process_iter() if process.name().startswith(name)]

    def __keyDown(self, event):
        if event.GetKeyCode() == wx.WXK_TAB:
            self.injectBox.WriteText(' ' * 4)
        else:
            event.Skip()

    def __inject(self, event, ai=False):
        injection = DEFAULT_IMPORTS + self.injectBox.GetValue()

        if ai:
            if hasattr(base, 'cr') and base.cr.timeManager:
                base.cr.timeManager.inject(injection)
            else:
                self.notify.warning(OTPLocalizer.InjectorAIUnavailable)
        else:
            exec(injection, globals())

    def __save(self, event):
        dialog = InputDialog(self.frame, OTPLocalizer.InjectorSaveQuestion, OTPLocalizer.InjectorTitle)

        if dialog.ShowModal() != wx.ID_OK:
            return

        input = dialog.getInput()
        snippet = self.injectBox.GetValue()

        if not input or not snippet:
            self.info(dialog, OTPLocalizer.InjectorNotSaved, OTPLocalizer.InjectorOops, wx.ICON_WARNING)
            return
        elif input in self.snippets and not self.info(dialog, OTPLocalizer.InjectorSnippetExists, OTPLocalizer.InjectorOops, wx.ICON_WARNING, wx.YES_NO):
            return

        self.snippets[input] = snippet
        self.info(dialog, OTPLocalizer.InjectorSaved % input, OTPLocalizer.InjectorOhYea)

    def __load(self, event):
        input = self.chooseSnippet(OTPLocalizer.InjectorLoadQuestion)

        if not input or (self.injectBox.GetValue() and not self.info(self.frame, OTPLocalizer.InjectorOverwriteWarning, OTPLocalizer.InjectorOops, wx.ICON_WARNING, wx.YES_NO)):
            return

        self.injectBox.SetValue(self.snippets[input])
        self.info(self.frame, OTPLocalizer.InjectorLoaded % input, OTPLocalizer.InjectorOhYea)

    def __remove(self, event):
        input = self.chooseSnippet(OTPLocalizer.InjectorRemoveQuestion)

        if not input or not self.info(self.frame, OTPLocalizer.InjectorRemoveWarning % input, OTPLocalizer.InjectorOops, wx.ICON_WARNING, wx.YES_NO):
            return

        del self.snippets[input]
        self.info(self.frame, OTPLocalizer.InjectorRemoved % input, OTPLocalizer.InjectorOhYea)

    def __pstats(self, event):
        box = event.GetEventObject()
        box.Disable()

        if box.GetValue():
            if not self.getProcesses('pstats'):
                subprocess.Popen([self.getPStatsPath()])

            PStatClient.connect()
        else:
            PStatClient.disconnect()

            for process in self.getProcesses('pstats'):
                process.kill()

        taskMgr.doMethodLater(1, lambda task: box.Enable(), 'enableElement-%d' % id(box))

    def __pstatCleanup(self):
        if self.pstatsBox.GetValue():
            for process in self.getProcesses('pstats'):
                process.kill()


#modification requirements:focal loss modulation, medical normalization.

import tensorflow as tf
import numpy as np
import functools as ft
import os
import shutil
import glob
import math
import random
import time
#from tensorflow.python import debug as tf_debug
from toolbox.config import config
from toolbox import BasicTools as bt
from toolbox import MITools as mt
from toolbox import TensorflowTools as tft

try:
	from tqdm import tqdm  # long waits are not fun
except:
	print('tqdm not installed')
	tqdm = lambda x: x

MAX_BOUND = float(config["MAX_BOUND"])
MIN_BOUND = float(config["MIN_BOUND"])
PIXEL_MEAN = float(config["PIXEL_MEAN"])
NORM_CROP = config["NORM_CROP"]

#NUM_EPOCH = 200
SNAPSHOT_EPOCH = 1
#DECAY_EPOCH = 0
#INITIAL_LEARNING_RATE = 0.001
#DECAY_LEARNING_RATE = 1.0

ALL_NEGATIVE = False
REGION_SIZES = [20, 30, 40]
BATCH_SIZE = 15
VALIDATION_RATE = 0.2

SCALE_AUGMENTATION = False
TRANSLATION_AUGMENTATION = False
ROTATION_AUGMENTATION = True
FLIP_AUGMENTATION = True
CENTERING = True
AUGMENTATION = SCALE_AUGMENTATION or TRANSLATION_AUGMENTATION or ROTATION_AUGMENTATION or FLIP_AUGMENTATION

print("batch size:{}" .format(BATCH_SIZE))
print("region sizes:{}" .format(REGION_SIZES))
print("max bound:{}" .format(MAX_BOUND))
print("min bound:{}" .format(MIN_BOUND))
print("pixel mean:{}" .format(PIXEL_MEAN))
region_halfs = [int(REGION_SIZES[0]/2), int(REGION_SIZES[1]/2), int(REGION_SIZES[2]/2)]

store_path = "models_tensorflow"
load_path = "models_tensorflow"
net_store_name = "luna_slh_3D_fusion_test"
net_store_path = store_path + "/" + net_store_name
tensorboard_path = net_store_path + "/tensorboard/"
net_init_names = ["luna_slh_3D_bndo_flbias_l5_20_aug_stage3", "luna_slh_3D_bndo_flbias_l5_30_aug2_stage2", "luna_slh_3D_bndo_flbias_l6_40_aug_stage2"]
if 'net_init_names' in dir():
	net_init_paths = [load_path + "/" + net_init_names[0], load_path + "/" + net_init_names[1], load_path + "/" + net_init_names[2]]
	net_init_files = [net_init_paths[0]+"/epoch20/epoch20", net_init_paths[1]+"/epoch10/epoch10", net_init_paths[2]+"/epoch28/epoch28", "models_tensorflow/luna_slh_3D_fusion/epoch6/epoch6"]
	#pfilelist_path = net_init_path + "/pfilelist.log"
	#nfilelist_path = net_init_path + "/nfilelist.log"

if os.access(net_store_path, os.F_OK):
	shutil.rmtree(net_store_path)
os.makedirs(net_store_path)
if os.access(tensorboard_path, os.F_OK):
	shutil.rmtree(tensorboard_path)

#data arrangement
data_dir1 = "luna_cubes_56_overbound"
#data_dir2 = "tianchi_cubes_56_overbound"
data_dir3 = "slh_cubes_56_overbound"
train_sets = ["subset0", "subset1", "subset2", "subset3", "subset4", "subset5", "subset6", "subset7", "subset8"]
train_sets2 = ["train", "val"]
#train_sets = ["subset9"]

if "pfilelist_path" in dir() and os.path.exists(pfilelist_path):
	print("read pfilelist from: %s" %(pfilelist_path))
	pfiles = bt.filelist_load(pfilelist_path)
	#pfilelist_file = open(pfilelist_path, "r")
	#pfiles = pfilelist_file.readlines()
	#for pfi in range(len(pfiles)):
	#	pfiles[pfi] = pfiles[pfi][:-1]
	#pfilelist_file.close()
else:
	pfiles = []
	for set in train_sets:
		train_dir = os.path.join(data_dir1, set)
		pdir = os.path.join(train_dir,"npy","*.npy")
		pfiles.extend(glob.glob(pdir))
		#ndir = os.path.join(train_dir,"npy_non","*.npy")
		#nfiles.extend(glob.glob(ndir))
	if "data_dir2" in dir():
		for set in train_sets2:
			train_dir2 = os.path.join(data_dir2, set)
			pdir = os.path.join(train_dir2,"npy","*.npy")
			pfiles.extend(glob.glob(pdir))
	if "data_dir3" in dir():
		pfiles.extend(glob.glob(os.path.join(data_dir3,"npy","*.npy")))
	random.shuffle(pfiles)
bt.filelist_store(pfiles, net_store_path + "/pfilelist.log")
#pfile_storage = open(net_store_path + "/pfilelist.log", "w")
#for pfile in pfiles:
#	pfile_storage.write("%s\n" %(pfile))
#pfile_storage.close()
if "nfilelist_path" in dir() and os.path.exists(nfilelist_path):
	print("read nfilelist from: %s" % (nfilelist_path))
	nfiles = bt.filelist_load(nfilelist_path)
	#nfilelist_file = open(nfilelist_path, "r")
	#nfiles = nfilelist_file.readlines()
	#for nfi in range(len(nfiles)):
	#	nfiles[nfi] = nfiles[nfi][:-1]
	#nfilelist_file.close()
else:
	nfiles = []
	for set in train_sets:
		train_dir = os.path.join(data_dir1, set)
		ndir = os.path.join(train_dir, "npy_non", "*.npy")
		nfiles.extend(glob.glob(ndir))
	random.shuffle(nfiles)
bt.filelist_store(nfiles, net_store_path + "/nfilelist.log")
#nfile_storage = open(net_store_path + "/nfilelist.log", "w")
#for nfile in nfiles:
#	nfile_storage.write("%s\n" %(nfile))
#nfile_storage.close()

num_positive = len(pfiles)
num_negative = len(nfiles)
#num_positive = 10
#num_negative = 200
aug_proportion = (1+2*int(SCALE_AUGMENTATION)) * (1+26*int(TRANSLATION_AUGMENTATION)*(1+2*int(CENTERING))) * (1+9*int(ROTATION_AUGMENTATION)+3*int(FLIP_AUGMENTATION))
if ALL_NEGATIVE:
	np_proportion = num_negative / float(num_positive)
else:
	np_proportion = aug_proportion

#num_negative = 1000 * num_positive
if num_positive==0:
	print("no positive training file found")
	exit()

positive_val_num = int(num_positive * VALIDATION_RATE)
#positive_val_num = 1
positive_train_num = num_positive - positive_val_num
negative_val_num = int(num_negative * VALIDATION_RATE)
negative_train_num = num_negative - negative_val_num
tpfiles = pfiles[:positive_train_num]
vpfiles = pfiles[positive_train_num:num_positive]
positive_train_indices = [i for i in range(positive_train_num)]
positive_val_indices = [i for i in range(positive_val_num)]
tnfiles = nfiles[:negative_train_num]
vnfiles = nfiles[negative_train_num:num_negative]
negative_train_indices = [i for i in range(negative_train_num)]
negative_val_indices = [i for i in range(negative_val_num)]
#negative_importances = 1000*np.ones(shape=[num_negative], dtype=float)

#net construct
volume_inputs = [tf.placeholder(tf.float32, [None, REGION_SIZES[0], REGION_SIZES[0], REGION_SIZES[0]]),
		 tf.placeholder(tf.float32, [None, REGION_SIZES[1], REGION_SIZES[1], REGION_SIZES[1]]),
		 tf.placeholder(tf.float32, [None, REGION_SIZES[2], REGION_SIZES[2], REGION_SIZES[2]])]
volumes_reshape = [tf.reshape(volume_inputs[0], [-1, REGION_SIZES[0], REGION_SIZES[0], REGION_SIZES[0], 1]),
		   tf.reshape(volume_inputs[1], [-1, REGION_SIZES[1], REGION_SIZES[1], REGION_SIZES[1], 1]),
		   tf.reshape(volume_inputs[2], [-1, REGION_SIZES[2], REGION_SIZES[2], REGION_SIZES[2], 1])]
real_label = tf.placeholder(tf.float32, [None, 2])
#r_bn1, b_bn1, w_conv1, w_conv2, out_conv1, out_bn1, hidden_conv1, hidden_conv2, hidden_conv3, out_fc1, out_fc2, softmax_out = tft.volume_bnnet2_l6_56(volume_reshape)
#bn_params = np.load(net_init_path + "/batch_normalization_statistic.npy")
positive_confidence = num_positive_aug / float(num_positive_aug + num_positive * np_proportion)
net_outs0, variables0, _ = tft.volume_bndo_flbias_l5_20(volumes_reshape[0], False, positive_confidence, dropout_rate=0.0, batch_normalization_statistic=False, bn_params=None)
net_outs1, variables1, _ = tft.volume_bndo_flbias_l5_30(volumes_reshape[1], False, positive_confidence, dropout_rate=0.0, batch_normalization_statistic=False, bn_params=None)
net_outs2, variables2, _ = tft.volume_bndo_flbias_l6_40(volumes_reshape[2], False, positive_confidence, dropout_rate=0.0, batch_normalization_statistic=False, bn_params=None)
features = [net_outs0['flattened_out'], net_outs1['flattened_out'], net_outs2['flattened_out']]
net_out, sm_out, fusion_variables = tft.late_fusion(features, True, positive_confidence)
cross_entropy = tf.nn.softmax_cross_entropy_with_logits(logits = net_out, labels = real_label)
modulation = tf.pow(real_label[:,0]+tf.pow(tf.constant(-1, dtype=tf.float32), real_label[:,0])*sm_out[:,0], tf.constant(2, dtype=tf.float32)) * (real_label[:,0]+tf.pow(tf.constant(-1, dtype=tf.float32), real_label[:,0])*tf.constant(positive_confidence, tf.float32))
focal_loss = tf.multiply(modulation, cross_entropy)
batch_loss = tf.reduce_mean(focal_loss)
correct_prediction = tf.equal(tf.argmax(sm_out, 1), tf.argmax(real_label, 1))
batch_accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
train_loss_summary = tf.summary.scalar('train loss', batch_loss)
val_loss_summary = tf.summary.scalar('val loss', batch_loss)
train_acc_summary = tf.summary.scalar('train acc', batch_accuracy)
val_acc_summary = tf.summary.scalar('val acc', batch_accuracy)
train_merge = tf.summary.merge([train_loss_summary, train_acc_summary])
val_merge = tf.summary.merge([val_loss_summary, val_acc_summary])
'''
trains = []
epochs = []
learning_rate = INITIAL_LEARNING_RATE
for ti in range(0, NUM_EPOCH, DECAY_EPOCH):
	optimizer = tf.train.GradientDescentOptimizer(learning_rate)
	trains.append(optimizer.minimize(batch_loss))
	epochs.append(min(NUM_EPOCH-ti, DECAY_EPOCH))
	learning_rate *= DECAY_LEARNING_RATE
'''
epochs = [10, 0, 0]
learning_rates = [0.01, 0.001, 0.0001]
trains = []
for stage in range(len(learning_rates)):
	optimizer = tf.train.GradientDescentOptimizer(learning_rates[stage])
	train = optimizer.minimize(batch_loss)
	trains.append(train)
'''
optimizer1 = tf.train.GradientDescentOptimizer(0.01)
train1 = optimizer1.minimize(batch_loss)
optimizer2 = tf.train.GradientDescentOptimizer(0.001)
train2 = optimizer2.minimize(batch_loss)
optimizer3 = tf.train.GradientDescentOptimizer(0.0001)
train3 = optimizer3.minimize(batch_loss)
trains = [train1, train2, train3]	#training stages of different learning rates
'''

extract_volumes = [ft.partial(mt.extract_volumes, volume_shape=np.int_([REGION_SIZES[0], REGION_SIZES[0], REGION_SIZES[0]]), centering=CENTERING, scale_augment=SCALE_AUGMENTATION, translation_augment=TRANSLATION_AUGMENTATION, rotation_augment=ROTATION_AUGMENTATION, flip_augment=FLIP_AUGMENTATION),
		   ft.partial(mt.extract_volumes, volume_shape=np.int_([REGION_SIZES[1], REGION_SIZES[1], REGION_SIZES[1]]), centering=CENTERING, scale_augment=SCALE_AUGMENTATION, translation_augment=TRANSLATION_AUGMENTATION, rotation_augment=ROTATION_AUGMENTATION, flip_augment=FLIP_AUGMENTATION),
		   ft.partial(mt.extract_volumes, volume_shape=np.int_([REGION_SIZES[2], REGION_SIZES[2], REGION_SIZES[2]]), centering=CENTERING, scale_augment=SCALE_AUGMENTATION, translation_augment=TRANSLATION_AUGMENTATION, rotation_augment=ROTATION_AUGMENTATION, flip_augment=FLIP_AUGMENTATION)]

saver0 = tf.train.Saver(variables0)
saver1 = tf.train.Saver(variables1)
saver2 = tf.train.Saver(variables2)
fusion_saver = tf.train.Saver(fusion_variables, max_to_keep=None)
config = tf.ConfigProto()
config.gpu_options.allow_growth = True
with tf.Session(config=config) as sess:
	#sess = tf_debug.LocalCLIDebugWrapperSession(sess)
	if 'net_init_files' not in dir() or net_init_files is None:
		print("net randomly initialized")
		sess.run(tf.global_variables_initializer())
	else:
		print("loading net from files:{}" .format(net_init_files))
		saver0.restore(sess, net_init_files[0])
		saver1.restore(sess, net_init_files[1])
		saver2.restore(sess, net_init_files[2])
		if len(net_init_files)>3:
			fusion_saver.restore(sess, net_init_files[3])
		else:
			sess.run(tf.variables_initializer(bt.dict2list(fusion_variables)))
	tensorboard_writer = tf.summary.FileWriter(tensorboard_path, sess.graph)
	best_accuracy = 0.0
	best_epoch = 0
	overall_epoch = 0
	training_messages = []
	for train_stage in range(len(trains)):
		train = trains[train_stage]
		for epoch in range(epochs[train_stage]):
			print('epoch:%d/%d' %(overall_epoch+1, epochs[train_stage]))
			#batch_num = 0
			#bn_stats = np.zeros(shape=np.array(bn_params).shape, dtype=float)

			# the number of negative samples is in default larger than the number of positive samples
			ptd_num = 0
			ptd_loss = 0.0
			ptd_accuracy = 0.0
			ntd_num = 0
			ntd_loss = 0.0
			ntd_accuracy = 0.0
			random.shuffle(positive_train_indices)
			random.shuffle(negative_train_indices)
			#positive_batch_size = 1
			positive_batch_size = (1-int(ALL_NEGATIVE))*(int(BATCH_SIZE/2/aug_proportion)-1) + 1	#if augmentatiion implemented then set batch size to 1 or half of BATCH_SIZE
			#negative_batch_size = int(positive_batch_size * np_proportion)
			for pbi in tqdm(range(0, positive_train_num, positive_batch_size)):
				#if AUGMENTATION:
				#	print("training process:%d/%d" %(pbi, positive_train_num))
				posbatchend = min(pbi+positive_batch_size, positive_train_num)
				for pti in range(pbi, posbatchend):
					data_index = positive_train_indices[pti]
					pfile = tpfiles[data_index]
					#pfile = 'luna_cubes_56_overbound/subset5/npy/1.3.6.1.4.1.14519.5.2.1.6279.6001.112740418331256326754121315800_34_ob_annotations.npy'
					if pfile.split('/')[0].find("luna")>=0:
						patient_uid, nodule_diameter = mt.get_annotation_informations(pfile, "luna_cubes_56_overbound/luna_annotations.csv")
					elif pfile.split('/')[0].find("tianchi")>=0:
						patient_uid, nodule_diameter = mt.get_annotation_informations(pfile, "tianchi_cubes_56_overbound/tianchi_annotations.csv")
					else:
						patient_uid = mt.get_volume_informations(pfile)[0]
						nodule_diameter = 0
					positive_data = np.load(pfile)
					if "positive_batches" not in dir():
						#positive_batch = mt.extract_volumes(positive_data, centering=CENTERING, nodule_diameter=nodule_diameter, scale_augment=SCALE_AUGMENTATION, translation_augment=TRANSLATION_AUGMENTATION, rotation_augment=ROTATION_AUGMENTATION, flip_augment=FLIP_AUGMENTATION)
						positive_batches = [extract_volumes[0](positive_data, nodule_diameter=nodule_diameter), extract_volumes[1](positive_data, nodule_diameter=nodule_diameter), extract_volumes[2](positive_data, nodule_diameter=nodule_diameter)]
					else:
						#positive_batch = np.concatenate((positive_batch, mt.extract_volumes(positive_data, centering=CENTERING, nodule_diameter=nodule_diameter, scale_augment=SCALE_AUGMENTATION, translation_augment=TRANSLATION_AUGMENTATION, rotation_augment=ROTATION_AUGMENTATION, flip_augment=FLIP_AUGMENTATION)), axis=0)
						positive_batches = [np.concatenate((positive_batches[0], extract_volumes[0](positive_data, nodule_diameter=nodule_diameter)), axis=0),
								    np.concatenate((positive_batches[1], extract_volumes[1](positive_data, nodule_diameter=nodule_diameter)), axis=0),
								    np.concatenate((positive_batches[2], extract_volumes[2](positive_data, nodule_diameter=nodule_diameter)), axis=0)]
					del positive_data
				negative_batches = [[], [], []]
				if posbatchend==positive_train_num and ALL_NEGATIVE:
					negbatchend = negative_train_num
				else:
					negbatchend = min(int((pbi+positive_batch_size)*np_proportion), negative_train_num)
				for nti in range(int(pbi*np_proportion), negbatchend):
					data_index = negative_train_indices[nti]
					nfile = tnfiles[data_index]
					negative_data = np.load(nfile)
					ndcenter = np.int_([negative_data.shape[0]/2, negative_data.shape[1]/2, negative_data.shape[2]/2])
					#negative_datas = [negative_data[ndcenter[0]-region_halfs[0]:ndcenter[0]+REGION_SIZES[0]-region_halfs[0], ndcenter[1]-region_halfs[0]:ndcenter[1]+REGION_SIZES[0]-region_halfs[0], ndcenter[2]-region_halfs[0]:ndcenter[2]+REGION_SIZES[0]-region_halfs[0]],
					#		  negative_data[ndcenter[0]-region_halfs[1]:ndcenter[0]+REGION_SIZES[1]-region_halfs[1], ndcenter[1]-region_halfs[1]:ndcenter[1]+REGION_SIZES[1]-region_halfs[1], ndcenter[2]-region_halfs[1]:ndcenter[2]+REGION_SIZES[1]-region_halfs[1]],
					#		  negative_data[ndcenter[0]-region_halfs[2]:ndcenter[0]+REGION_SIZES[2]-region_halfs[2], ndcenter[1]-region_halfs[2]:ndcenter[1]+REGION_SIZES[2]-region_halfs[2], ndcenter[2]-region_halfs[2]:ndcenter[2]+REGION_SIZES[2]-region_halfs[2]]]
					#negative_datas_reshape = [np.reshape(negative_datas[0], (1, negative_datas[0].shape[0], negative_datas[0].shape[1], negative_datas[0].shape[2])),
					#			  np.reshape(negative_datas[1], (1, negative_datas[1].shape[0], negative_datas[1].shape[1], negative_datas[1].shape[2])),
					#			  np.reshape(negative_datas[2], (1, negative_datas[2].shape[0], negative_datas[2].shape[1], negative_datas[2].shape[2]))]

					negative_batches[0].append(negative_data[ndcenter[0]-region_halfs[0]:ndcenter[0]+REGION_SIZES[0]-region_halfs[0], ndcenter[1]-region_halfs[0]:ndcenter[1]+REGION_SIZES[0]-region_halfs[0], ndcenter[2]-region_halfs[0]:ndcenter[2]+REGION_SIZES[0]-region_halfs[0]])
					negative_batches[1].append(negative_data[ndcenter[0]-region_halfs[1]:ndcenter[0]+REGION_SIZES[1]-region_halfs[1], ndcenter[1]-region_halfs[1]:ndcenter[1]+REGION_SIZES[1]-region_halfs[1], ndcenter[2]-region_halfs[1]:ndcenter[2]+REGION_SIZES[1]-region_halfs[1]])
					negative_batches[2].append(negative_data[ndcenter[0]-region_halfs[2]:ndcenter[0]+REGION_SIZES[2]-region_halfs[2], ndcenter[1]-region_halfs[2]:ndcenter[1]+REGION_SIZES[2]-region_halfs[2], ndcenter[2]-region_halfs[2]:ndcenter[2]+REGION_SIZES[2]-region_halfs[2]])
					#if "negative_batches" not in dir():
					#	negative_batches = negative_datas_reshape
					#else:
					#	negative_batches = [np.concatenate((negative_batches[0], negative_datas_reshape[0]), axis=0),
					#			    np.concatenate((negative_batches[1], negative_datas_reshape[1]), axis=0),
					#			    np.concatenate((negative_batches[2], negative_datas_reshape[2]), axis=0)]
					del negative_data

				if positive_batches[0].shape[0]!=positive_batches[1].shape[0] or positive_batches[1].shape[0]!=positive_batches[2].shape[0]:
					print('batches inconsistency')
					continue
				posbatch_size = positive_batches[0].shape[0]
				allbatch_size = positive_batches[0].shape[0] + len(negative_batches[0])
				train_datas = [np.zeros(shape=(allbatch_size, positive_batches[0].shape[1], positive_batches[0].shape[2], positive_batches[0].shape[3]), dtype=float),
					       np.zeros(shape=(allbatch_size, positive_batches[1].shape[1], positive_batches[1].shape[2], positive_batches[1].shape[3]), dtype=float),
					       np.zeros(shape=(allbatch_size, positive_batches[2].shape[1], positive_batches[2].shape[2], positive_batches[2].shape[3]), dtype=float)]
				train_label = np.zeros(shape=(allbatch_size, 2), dtype=float)
				batch_random = np.random.permutation(allbatch_size)
				#batch_random = np.arange(positive_batch.shape[0]+negative_batch.shape[0])
				for bi in range(batch_random.size):
					batch_index = batch_random[bi]
					if batch_index<posbatch_size:
						train_datas[0][bi] = (positive_batches[0][batch_index] - MIN_BOUND) / (MAX_BOUND - MIN_BOUND) - PIXEL_MEAN
						train_datas[1][bi] = (positive_batches[1][batch_index] - MIN_BOUND) / (MAX_BOUND - MIN_BOUND) - PIXEL_MEAN
						train_datas[2][bi] = (positive_batches[2][batch_index] - MIN_BOUND) / (MAX_BOUND - MIN_BOUND) - PIXEL_MEAN
						train_label[bi][0] = 1
					else:
						train_datas[0][bi] = (negative_batches[0][batch_index-posbatch_size] - MIN_BOUND) / (MAX_BOUND - MIN_BOUND) - PIXEL_MEAN
						train_datas[1][bi] = (negative_batches[1][batch_index-posbatch_size] - MIN_BOUND) / (MAX_BOUND - MIN_BOUND) - PIXEL_MEAN
						train_datas[2][bi] = (negative_batches[2][batch_index-posbatch_size] - MIN_BOUND) / (MAX_BOUND - MIN_BOUND) - PIXEL_MEAN
						train_label[bi][1] = 1
				for bi in range(0, allbatch_size, BATCH_SIZE):
					batch_size = min(BATCH_SIZE, allbatch_size-bi)
					data_batches = [train_datas[0][bi:bi+batch_size], train_datas[1][bi:bi+batch_size], train_datas[2][bi:bi+batch_size]]
					label_batch = train_label[bi:bi+batch_size]
					_, losses, accuracies, train_summary = sess.run([train, focal_loss, correct_prediction, train_merge], {volume_inputs[0]: data_batches[0], volume_inputs[1]: data_batches[1], volume_inputs[2]: data_batches[2], real_label: label_batch})
					#parameters2 = sess.run(variables, {volume_input: data_batch, real_label: label_batch})
					tensorboard_writer.add_summary(train_summary, epoch)
					for di in range(batch_size):
						if label_batch[di][0]>label_batch[di][1]:
							ptd_num += 1
							ptd_loss += losses[di]
							ptd_accuracy += accuracies[di]
						else:
							ntd_num += 1
							ntd_loss += losses[di]
							ntd_accuracy += accuracies[di]
					#if batch_size > 1:
					#	batch_num += 1
					#	bn_stat = np.array(bn_stat)
					#	bn_stat[:,1] = bn_stat[:,1] * batch_size / (batch_size-1)	#unbiased variance estimate
					#	bn_stats += bn_stat

				if 'negative_batches' in dir():
					del negative_batches
				del positive_batches
				del train_datas

			if ptd_num > 0:
				ptd_loss /= ptd_num
				ptd_accuracy /= ptd_num
			if ntd_num > 0:
				ntd_loss /= ntd_num
				ntd_accuracy /= ntd_num

			pvd_num = 0
			pvd_loss = 0.0
			pvd_accuracy = 0.0
			nvd_num = 0
			nvd_loss = 0.0
			nvd_accuracy = 0.0
			random.shuffle(positive_val_indices)
			random.shuffle(negative_val_indices)
			#positive_batch_size = 1
			positive_batch_size = (1-int(AUGMENTATION or ALL_NEGATIVE))*(int(BATCH_SIZE/2)-1) + 1	#if augmentatiion implemented then set batch size to 1 or half of BATCH_SIZE
			#negative_batch_size = int(positive_batch_size * np_proportion)
			for pbi in tqdm(range(0, positive_val_num, positive_batch_size)):
				posbatchend = min(pbi+positive_batch_size, positive_val_num)
				for pvi in range(pbi, posbatchend):
					data_index = positive_val_indices[pvi]
					pfile = vpfiles[data_index]
					#pfile = 'luna_cubes_56_overbound/subset5/npy/1.3.6.1.4.1.14519.5.2.1.6279.6001.112740418331256326754121315800_34_ob_annotations.npy'
					if pfile.split('/')[0].find("luna")>=0:
						patient_uid, nodule_diameter = mt.get_annotation_informations(pfile, "luna_cubes_56_overbound/luna_annotations.csv")
					elif pfile.split('/')[0].find("tianchi")>=0:
						patient_uid, nodule_diameter = mt.get_annotation_informations(pfile, "tianchi_cubes_56_overbound/tianchi_annotations.csv")
					else:
						patient_uid = mt.get_volume_informations(pfile)[0]
						nodule_diameter = 0
					positive_data = np.load(pfile)
					if "positive_batches" not in dir():
						#positive_batch = mt.extract_volumes(positive_data, centering=CENTERING, nodule_diameter=nodule_diameter, scale_augment=SCALE_AUGMENTATION, translation_augment=TRANSLATION_AUGMENTATION, rotation_augment=ROTATION_AUGMENTATION, flip_augment=FLIP_AUGMENTATION)
						positive_batches = [extract_volumes[0](positive_data, nodule_diameter=nodule_diameter), extract_volumes[1](positive_data, nodule_diameter=nodule_diameter), extract_volumes[2](positive_data, nodule_diameter=nodule_diameter)]
					else:
						#positive_batch = np.concatenate((positive_batch, mt.extract_volumes(positive_data, centering=CENTERING, nodule_diameter=nodule_diameter, scale_augment=SCALE_AUGMENTATION, translation_augment=TRANSLATION_AUGMENTATION, rotation_augment=ROTATION_AUGMENTATION, flip_augment=FLIP_AUGMENTATION)), axis=0)
						positive_batches = [np.concatenate((positive_batches[0], extract_volumes[0](positive_data, nodule_diameter=nodule_diameter)), axis=0),
								    np.concatenate((positive_batches[1], extract_volumes[1](positive_data, nodule_diameter=nodule_diameter)), axis=0),
								    np.concatenate((positive_batches[2], extract_volumes[2](positive_data, nodule_diameter=nodule_diameter)), axis=0)]
					del positive_data
				negative_batches = [[], [], []]
				if posbatchend==positive_val_num and ALL_NEGATIVE:
					negbatchend = negative_val_num
				else:
					negbatchend = min(int((pbi+positive_batch_size)*np_proportion), negative_val_num)
				for nvi in range(int(pbi*np_proportion), negbatchend):
					data_index = negative_val_indices[nvi]
					nfile = vnfiles[data_index]
					negative_data = np.load(nfile)
					ndcenter = np.int_([negative_data.shape[0]/2, negative_data.shape[1]/2, negative_data.shape[2]/2])
					#negative_datas = [negative_data[ndcenter[0]-region_halfs[0]:ndcenter[0]+REGION_SIZES[0]-region_halfs[0], ndcenter[1]-region_halfs[0]:ndcenter[1]+REGION_SIZES[0]-region_halfs[0], ndcenter[2]-region_halfs[0]:ndcenter[2]+REGION_SIZES[0]-region_halfs[0]],
					#		  negative_data[ndcenter[0]-region_halfs[1]:ndcenter[0]+REGION_SIZES[1]-region_halfs[1], ndcenter[1]-region_halfs[1]:ndcenter[1]+REGION_SIZES[1]-region_halfs[1], ndcenter[2]-region_halfs[1]:ndcenter[2]+REGION_SIZES[1]-region_halfs[1]],
					#		  negative_data[ndcenter[0]-region_halfs[2]:ndcenter[0]+REGION_SIZES[2]-region_halfs[2], ndcenter[1]-region_halfs[2]:ndcenter[1]+REGION_SIZES[2]-region_halfs[2], ndcenter[2]-region_halfs[2]:ndcenter[2]+REGION_SIZES[2]-region_halfs[2]]]
					#negative_datas_reshape = [np.reshape(negative_datas[0], (1, negative_datas[0].shape[0], negative_datas[0].shape[1], negative_datas[0].shape[2])),
					#			  np.reshape(negative_datas[1], (1, negative_datas[1].shape[0], negative_datas[1].shape[1], negative_datas[1].shape[2])),
					#			  np.reshape(negative_datas[2], (1, negative_datas[2].shape[0], negative_datas[2].shape[1], negative_datas[2].shape[2]))]

					negative_batches[0].append(negative_data[ndcenter[0]-region_halfs[0]:ndcenter[0]+REGION_SIZES[0]-region_halfs[0], ndcenter[1]-region_halfs[0]:ndcenter[1]+REGION_SIZES[0]-region_halfs[0], ndcenter[2]-region_halfs[0]:ndcenter[2]+REGION_SIZES[0]-region_halfs[0]])
					negative_batches[1].append(negative_data[ndcenter[0]-region_halfs[1]:ndcenter[0]+REGION_SIZES[1]-region_halfs[1], ndcenter[1]-region_halfs[1]:ndcenter[1]+REGION_SIZES[1]-region_halfs[1], ndcenter[2]-region_halfs[1]:ndcenter[2]+REGION_SIZES[1]-region_halfs[1]])
					negative_batches[2].append(negative_data[ndcenter[0]-region_halfs[2]:ndcenter[0]+REGION_SIZES[2]-region_halfs[2], ndcenter[1]-region_halfs[2]:ndcenter[1]+REGION_SIZES[2]-region_halfs[2], ndcenter[2]-region_halfs[2]:ndcenter[2]+REGION_SIZES[2]-region_halfs[2]])
					#if "negative_batches" not in dir():
					#	negative_batches = negative_datas_reshape
					#else:
					#	negative_batches = [np.concatenate((negative_batches[0], negative_datas_reshape[0]), axis=0),
					#			    np.concatenate((negative_batches[1], negative_datas_reshape[1]), axis=0),
					#			    np.concatenate((negative_batches[2], negative_datas_reshape[2]), axis=0)]
					del negative_data

				if positive_batches[0].shape[0]!=positive_batches[1].shape[0] or positive_batches[1].shape[0]!=positive_batches[2].shape[0]:
					print('batches inconsistency')
					continue
				posbatch_size = positive_batches[0].shape[0]
				allbatch_size = positive_batches[0].shape[0] + len(negative_batches[0])
				val_datas = [np.zeros(shape=(allbatch_size, positive_batches[0].shape[1], positive_batches[0].shape[2], positive_batches[0].shape[3]), dtype=float),
					       np.zeros(shape=(allbatch_size, positive_batches[1].shape[1], positive_batches[1].shape[2], positive_batches[1].shape[3]), dtype=float),
					       np.zeros(shape=(allbatch_size, positive_batches[2].shape[1], positive_batches[2].shape[2], positive_batches[2].shape[3]), dtype=float)]
				val_label = np.zeros(shape=(allbatch_size, 2), dtype=float)
				batch_random = np.random.permutation(allbatch_size)
				#batch_random = np.arange(positive_batch.shape[0]+negative_batch.shape[0])
				for bi in range(batch_random.size):
					batch_index = batch_random[bi]
					if batch_index<posbatch_size:
						val_datas[0][bi] = (positive_batches[0][batch_index] - MIN_BOUND) / (MAX_BOUND - MIN_BOUND) - PIXEL_MEAN
						val_datas[1][bi] = (positive_batches[1][batch_index] - MIN_BOUND) / (MAX_BOUND - MIN_BOUND) - PIXEL_MEAN
						val_datas[2][bi] = (positive_batches[2][batch_index] - MIN_BOUND) / (MAX_BOUND - MIN_BOUND) - PIXEL_MEAN
						val_label[bi][0] = 1
					else:
						val_datas[0][bi] = (negative_batches[0][batch_index-posbatch_size] - MIN_BOUND) / (MAX_BOUND - MIN_BOUND) - PIXEL_MEAN
						val_datas[1][bi] = (negative_batches[1][batch_index-posbatch_size] - MIN_BOUND) / (MAX_BOUND - MIN_BOUND) - PIXEL_MEAN
						val_datas[2][bi] = (negative_batches[2][batch_index-posbatch_size] - MIN_BOUND) / (MAX_BOUND - MIN_BOUND) - PIXEL_MEAN
						val_label[bi][1] = 1
				for bi in range(0, allbatch_size, BATCH_SIZE):
					batch_size = min(BATCH_SIZE, allbatch_size-bi)
					data_batches = [val_datas[0][bi:bi+batch_size], val_datas[1][bi:bi+batch_size], val_datas[2][bi:bi+batch_size]]
					label_batch = val_label[bi:bi+batch_size]
					losses, accuracies, val_summary = sess.run([focal_loss, correct_prediction, val_merge], {volume_inputs[0]: data_batches[0], volume_inputs[1]: data_batches[1], volume_inputs[2]: data_batches[2], real_label: label_batch})
					#parameters2 = sess.run(variables, {volume_input: data_batch, real_label: label_batch})
					tensorboard_writer.add_summary(val_summary, epoch)
					for di in range(batch_size):
						if label_batch[di][0]>label_batch[di][1]:
							pvd_num += 1
							pvd_loss += losses[di]
							pvd_accuracy += accuracies[di]
						else:
							nvd_num += 1
							nvd_loss += losses[di]
							nvd_accuracy += accuracies[di]
					#if batch_size > 1:
					#	batch_num += 1
					#	bn_stat = np.array(bn_stat)
					#	bn_stat[:,1] = bn_stat[:,1] * batch_size / (batch_size-1)	#unbiased variance estimate
					#	bn_stats += bn_stat

				if 'negative_batches' in dir():
					del negative_batches
				del positive_batches
				del val_datas

			if pvd_num > 0:
				pvd_loss /= pvd_num
				pvd_accuracy /= pvd_num
			if nvd_num > 0:
				nvd_loss /= nvd_num
				nvd_accuracy /= nvd_num

			#tensorboard_writer.add_summary(summary, epoch)
			print("positive_train_loss:%f positive_train_acc:%f negative_train_loss:%f negative_train_acc:%f\npositive_val_loss:%f positive_val_acc:%f negative_val_loss:%f negative_val_acc:%f" % (
				ptd_loss, ptd_accuracy, ntd_loss,
				ntd_accuracy, pvd_loss, pvd_accuracy, nvd_loss,
				nvd_accuracy))
			if (pvd_accuracy+nvd_accuracy)/2>=best_accuracy:
				best_accuracy = (pvd_accuracy+nvd_accuracy)/2
				best_epoch = overall_epoch
				#best_dir = net_store_path+"/"+net_store_name+"_best"
				best_dir = net_store_path+"/"+"best"
				if os.access(best_dir, os.F_OK):
					shutil.rmtree(best_dir)
				os.mkdir(best_dir)
				#saver.save(sess, best_dir+"/"+net_store_name+"_best")
				fusion_saver.save(sess, best_dir+"/"+"best")
			training_messages.append(
				[overall_epoch + 1, ptd_loss, ptd_accuracy, ntd_loss,
				 ntd_accuracy, pvd_loss, pvd_accuracy, nvd_loss,
				 nvd_accuracy])
			# write training process to a logger file
			logger = open(net_store_path + "/" + net_store_name + ".log", 'w')
			logger.write("random validation with overall negative samples\n")
			logger.write("validation rate:{}\n" .format(VALIDATION_RATE))
			logger.write("batch size:{}\n" .format(BATCH_SIZE))
			logger.write("region sizes:{}\n" .format(REGION_SIZES))
			logger.write("max bound:{}\n" .format(MAX_BOUND))
			logger.write("min bound:{}\n" .format(MIN_BOUND))
			logger.write("pixel mean:{}\n" .format(PIXEL_MEAN))
			logger.write("scale augmentation:{}\n" .format(SCALE_AUGMENTATION))
			logger.write("translation augmentation:{}\n" .format(TRANSLATION_AUGMENTATION))
			logger.write("rotation augmentation:{}\n" .format(ROTATION_AUGMENTATION))
			logger.write("flip augmentation:{}\n" .format(FLIP_AUGMENTATION))
			logger.write("centering augmentation:{}\n" .format(CENTERING))
			# logger.write("initial_learning_rate:%f decay_rate:%f decay_epoch:%d\n" %(INITIAL_LEARNING_RATE, DECAY_LEARNING_RATE, DECAY_EPOCH))
			logger.write(
				"learning_rates:%f %f %f\n" % (learning_rates[0], learning_rates[1], learning_rates[2]))
			logger.write("epochs:%d %d %d\n" % (epochs[0], epochs[1], epochs[2]))
			logger.write(
				"epoch pos_train_loss pos_train_acc neg_train_loss neg_train_acc pos_val_loss pos_val_acc neg_val_loss neg_val_acc\n")
			for tm in range(len(training_messages)):
				logger.write("%d %f %f %f %f %f %f %f %f\n" % (
				training_messages[tm][0], training_messages[tm][1], training_messages[tm][2],
				training_messages[tm][3], training_messages[tm][4], training_messages[tm][5],
				training_messages[tm][6], training_messages[tm][7], training_messages[tm][8]))
			logger.write("best epoch:%d" %(best_epoch+1))
			logger.close()
			if SNAPSHOT_EPOCH>0 and (overall_epoch+1)%SNAPSHOT_EPOCH==0:
				#snapshot_dir = net_store_path+"/"+net_store_name+"_epoch"+str(overall_epoch+1)
				snapshot_dir = net_store_path+"/"+"epoch"+str(overall_epoch+1)
				if os.access(snapshot_dir, os.F_OK):
					shutil.rmtree(snapshot_dir)
				os.mkdir(snapshot_dir)
				fusion_saver.save(sess, snapshot_dir+"/"+"epoch"+str(overall_epoch+1))
				#np.save(snapshot_dir+"/batch_normalization_statistic.npy", bn_stats)
			overall_epoch += 1
	fusion_saver.save(sess, net_store_path + "/" + net_store_name)
	#np.save(net_store_path + "/batch_normalization_statistic.npy", bn_stats)
sess.close()
print("Overall training done!")
print("The network is saved as:%s" %(net_store_name))


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

urlpatterns = patterns('',
	url(r'^genre/(?P<genre_name>[a-zA-Z\-]+)$', views.genre, name='genres'),
	url(r'^movies', views.movies, name='movies'),
	url(r'^movie/(?P<movie_id>\d+)/$', views.detail, name='detail'),
	url(r'^$', views.index, name='index'),
	url(r'^register/$', views.register, name='register'),
    url(r'^login/$', views.user_login, name='login'),
    url(r'^logout/$', views.user_logout, name='logout'),
)


from matplotlib import pyplot as plt
from PEPS import cft_entanglement_entropy as cft
from PEPS import IO_helper as IO
import sfig

i=10
stri = str(i)
IO.go_to_data_parent('interpolatedboson/a'+stri)
IO.add_to_path()
state = IO.get_state()

params = IO.Params.kw('LKN', L=[10], K=[0], N=[0])

for p in params:
    cft.compare_edge_gs_ee_to_cft(state, p)
    plt.xlabel('Number of sites in cut')
    plt.ylabel('Entanglement entropy of cut')
    plt.tight_layout()
    plt.show()


"""
    输入一个矩阵，按照从外向里以顺时针的顺序依次打印出每一个数字。
    示例 1：
        输入：matrix = [[1,2,3],[4,5,6],[7,8,9]]
        输出：[1,2,3,6,9,8,7,4,5]

    示例 2：
        输入：matrix = [[1,2,3,4],[5,6,7,8],[9,10,11,12]]
        输出：[1,2,3,4,8,12,11,10,9,5,6,7]
    限制：
        0 <= matrix.length <= 100
        0 <= matrix[i].length <= 100
"""
from typing import List

class Solution:
    def spiralOrder(self, matrix: List[List[int]]) -> List[int]:
        """
            思路：
                1、定义上先左右四个边界  上 t  下b  左l 右r
                2、按照顺时针打印
        """
        row_size = len(matrix)
        col_size = row_size and len(matrix[0])
        res = []

        l = 0
        r = col_size - 1
        t = 0
        b = row_size - 1
        while True:
            for i in range(l, r + 1):
                res.append(matrix[t][i])
            t += 1
            if t > b:
                break

            for j in range(t, b + 1):
                res.append(matrix[j][r])
            r -= 1
            if l > r:
                break

            for x in range(r, l - 1, -1):
                res.append(matrix[b][x])
            b -= 1
            if t > b:
                break

            for z in range(b, t - 1, -1):
                res.append(matrix[z][l])
            l += 1
            if l > r:
                break
        return res

if __name__ == '__main__':
    print(Solution().spiralOrder([[1, 2, 3], [4, 5, 6], [7, 8, 9]]))

剑指offer/面试题29.顺时针打印矩阵.py

面试题29.顺时针打印矩阵.py


import requests
class blog():
    def __init__(self,s):
        self.s=s
    def login(self):
        url = 'https://passport.cnblogs.com/user/signin'
        headers={
        'Cookie': '__utma=226521935.941366269.1508751496.1508751496.1508751496.1; __utmz=226521935.1508751496.1.1.utmccn=(organic)|utmcsr=baidu|utmctr=|utmcmd=organic; __gads=ID=8019f9e6f4ec84a4:T=1509541344:S=ALNI_MaHsxheE6Nqp15k7DfgUGc45I0SMQ; UM_distinctid=15f80eaa2b73fe-03faa50a5ce9df-193e6d56-fa000-15f80eaa2b83d6; CNZZDATA1258637387=1850015044-1509693391-null%7C1509693391; CNZZDATA3347352=cnzz_eid%3D1352186815-1509957096-null%26ntime%3D1510903373; _ga=GA1.2.479464532.1501746521; _gid=GA1.2.1459045168.1515377290'
      ,
        'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.108 Safari/537.36'
        ,"Accept-Encoding": "gzip, deflate, br",
        "Content-Type": "application/json; charset=utf-8",
        "X-Requested-With": "XMLHttpRequest",
        "Content-Length": "557",

        "Connection": "keep-alive",
        'Accept':'application / json, text / javascript, * / *; q = 0.01'

    }
        payload = {
            'input1': 'gbNFGhVhXxIH5+JMoeKPBusQiFmS2fTt5qm2Y+VTMkHUNtHkS9eKbZUwiR3J3zEBDADBvzCRuIXxnuhVkz97Gd92cec5jZYUNedYiVdYMPK4ULB3WhCxtHmtkKLDfg3xP2LcjrsK8u2vIZ3kETjVES3EwaxviNn+qWTAwRLJ5zQ='
            ,
            'input2': 'VDNPL53eINNwunQHa13D0lNmVYEzyZ8o/RmyuHG5lhPG/QMVaRMFNvX/mxbt27b1Fygi73NyNZZYIrL8+vp0+X3dsZro/0kXSkAfOUiwVRUv5y6WVAC3SmbLk/WqpJbR+WyV7GZWCCERSgnoDlUSaCK7brhcE7gV5OMVCufrZ+Y='
            , 'remember': 'false',
            'geetest_challenge':'647143d6449c1a0adf457bf8830e33e0ki',
            'geetest_validate':'5c90b3889408e90f28828c2f78f5778c',
            'geetest_seccode':'5c90b3889408e90f28828c2f78f5778c | jordan',
        }
        r=self.s.post(url,json=payload,headers=headers)
        result=r.content
        print(result)
        print(r.json())
    def save_box(self, title, body_data):
        url2 = 'https://i.cnblogs.com/EditPosts.aspx?opt=1'
        '''# 获取报存之后url地址'''
        body = {"__VIEWSTATE": "",
        "__VIEWSTATEGENERATOR": "FE27D343",
        "Editor$Edit$txbTitle": title,
        "Editor$Edit$EditorBody": "<p>%s</p>"%body_data,
        "Editor$Edit$Advanced$ckbPublished": "on",
        "Editor$Edit$Advanced$chkDisplayHomePage": "on",
        "Editor$Edit$Advanced$chkComments": "on",
        "Editor$Edit$Advanced$chkMainSyndication": "on",
        "Editor$Edit$lkbDraft": "存为草稿",
            }
        r2=self.s.post(url2,data=body)
        return r2.url

    def get_postid(self,url):
        '''正则提取postid'''
        import re
        postid = re.findall(r"postid=(.+?)&", url)
        print(postid)# 这里是list
        if len(postid) < 1:
            return ''
        else:
            return postid[0]
if __name__ == '__main__':

        s=requests.session()
        blog(s).login()#验证码缓存已失效


from django.shortcuts import render
from rest_framework import response
from . import models as api_models, serializers as api_serializers
from rest_framework import viewsets, status
from rest_framework.response import Response
from rest_framework.decorators import action
from rest_framework.authentication import TokenAuthentication
from rest_framework.permissions import IsAuthenticated, AllowAny

class UserViewSets(viewsets.ModelViewSet):
    queryset = api_models.User.objects.all()
    serializer_class = api_serializers.UserSerializer

class MovieViewSets(viewsets.ModelViewSet):
    authentication_classes = (TokenAuthentication, )
    permission_classes = (IsAuthenticated, )
    queryset = api_models.Movie.objects.all()
    serializer_class = api_serializers.MovieSerializer

    @action(detail=True, methods=['POST'])
    def rate_movie(self,request, pk):
        result = {}
        message = ''
        error_message = ''
        _status = ''
        if not request.data.get('stars'):
            error_message = 'you need to provide stars'
            _status = status.HTTP_400_BAD_REQUEST

        stars = request.data['stars']

        try:
            stars = int(stars)
        except:
            error_message = 'stars must be integer'
            _status = status.HTTP_400_BAD_REQUEST

        if not error_message:

            # user = api_models.User.objects.get(id=2)
            user = request.user
            movie = api_models.Movie.objects.get(id=pk)

            try:
                rating = api_models.Raiting.objects.get(
                    user=user.id,
                    movie=movie.id
                )
                rating.stars = stars
                rating.save()
                message = 'Rating updated'
            except api_models.Raiting.DoesNotExist:
                rating = api_models.Raiting.objects.create(
                    user=user,
                    movie=movie,
                    stars = stars
                )
                message = 'Rating created'

            _status = status.HTTP_200_OK
            result = api_serializers.RaitingSerializer(rating,many=False).data

        response = {
            'error_message': error_message,
            'message': message,
            'result': result
        }

        return Response(response, status=_status)

class RaitingViewSets(viewsets.ModelViewSet):
    authentication_classes = (TokenAuthentication, )
    permission_classes = (IsAuthenticated, )
    queryset = api_models.Raiting.objects.all()
    serializer_class = api_serializers.RaitingSerializer

    def create(self, request, *args, **kwargs):
        response = {'message': "You can't update this"}
        return Response(response, status=status.HTTP_400_BAD_REQUEST)

    def update(self, request, *args, **kwargs):
        response = {'message': "You can't update this"}
        return Response(response, status=status.HTTP_400_BAD_REQUEST)


from flask import Flask, request, render_template, abort, jsonify
import pickle
import numpy as np
import os

app = Flask('__name__')

pipeline = pickle.load(open('./model.pkl', 'rb'))

def make_prediction(features):
    X = np.array([features['Age'], features['Days in Shelter'],int(features['Good Health'] == True)]).reshape(1,-1)
    prob_euth = pipeline.predict_proba(X)[0, 1]

    result = {
        'prediction': int(prob_euth > 0.5),
        'prob_euthanization': prob_euth
    }
    return result

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

@app.route('/predict', methods=['POST'])
def score_api():
    if not request.json:
        abort(400)
    response = make_prediction(request.json['data'])
    return jsonify(response), 201

if __name__ == '__main__':
  port = int(os.environ.get('PORT', 5000))
  app.run(host='0.0.0.0', port=port, debug=True)


# The game
#
WHITE = 'w'
BLACK = 'b'
EMPTY = '_'

WHITE_X = 'X'
BLACK_X = 'O'
EMPTY_X = ' ' # '·'
VALID_X = '?'

WIDTH  = 8
HEIGHT = 8

BLANK_BOARD = [EMPTY for x in range(WIDTH * HEIGHT)]

import json

class Reversi:
    def __init__(self):
        self._turn = WHITE
        self._board = BLANK_BOARD[:]
        self._complete = False
        self._moves = []

        # Starting configuration
        #
        self.place(3, 3, checked = False)
        self.place(3, 4, checked = False)
        self.place(4, 4, checked = False)
        self.place(4, 3, checked = False)

    def invert(self):
        state = self.state_to_string()
        TEMP = "_X_"
        state = state.replace('"%s"'%WHITE, '"%s"'%TEMP).replace('"%s"'%BLACK, '"%s"'%WHITE).replace('"%s"'%TEMP, '"%s"'%BLACK)
        self.state_from_string(state)

    def state_to_string(self):
        return json.dumps({
            "turn": self._turn,
            "board": self._board,
            "complete": self._complete,
            "moves": self._moves,
        })

    def state_from_string(self, jsonstring):
        state = json.loads(jsonstring)
        self._turn = state["turn"]
        self._board = state["board"]
        self._complete = state["complete"]
        self._moves = state["moves"]

    def stats(self):
        whitepoints = 0
        blackpoints = 0
        empty = 0
        for x in range(WIDTH):
            for y in range(HEIGHT):
                if self._board[(x * WIDTH) + y] == WHITE:
                    whitepoints += 1
                elif self._board[(x * WIDTH) + y] == BLACK:
                    blackpoints += 1
                elif self._board[(x * WIDTH) + y] == EMPTY:
                    empty += 1
        return (self._complete or empty == 0, whitepoints, blackpoints, empty)

    def place(self, x, y, checked = True):
        if checked and (x, y) not in self.all_valid_placements():
            raise Exception("Invalid move!")

        if checked:
            self._moves.append((self._turn, (x, y), self._board[:]))

            opponent_colour = self.opposite_color(self._turn)
            opponent_offsets = self.adjacent_offsets_matching(x, y, opponent_colour)
            for (ox, oy) in opponent_offsets:
                #print ("X = %d, Y = %d -> OX = %d, OY = %d"%(x, y, ox, oy))
                paths = self.find_path_to(x, y, ox, oy, self._turn)
                if paths:
                    for (px, py) in paths:
                        # Set all pathways to our colour
                        #
                        self._board[(px * WIDTH) + py] = self._turn

        self._board[(x * WIDTH) + y] = self._turn
        self._turn = BLACK if self._turn == WHITE else WHITE

    def skip(self):
        if len(self.all_valid_placements()) > 0:
            raise Exception("Invalid attempt to skip (valid moves found)!")
        self._turn = BLACK if self._turn == WHITE else WHITE

        # Check we not in deadlock (ie next move is also going to want to skip)
        if len(self.all_valid_placements()) == 0:
            #print("Game deadlocked, finishing")
            #print(self.draw())
            self._complete = True

    def get_at(self, x, y):
        return self._board[(x * WIDTH) + y]

    def on_board(self, x, y):
        return x < WIDTH and x >= 0 and y < HEIGHT and y >= 0

    def opposite_color(self, colour):
        return WHITE if colour == BLACK else BLACK

    def adjacent_offsets_matching(self, x, y, colour):
        tests = [
            (-1, -1), (0, -1), (+1, -1),
            (-1,  0),          (+1,  0),
            (-1, +1), (0, +1), (+1, +1)
        ]
        offsets = [(tx, ty) for (tx, ty) in tests
                   if self.on_board((tx + x), (ty + y)) and self.get_at(tx + x, ty + y) == colour]
        return offsets

    def all_valid_placements(self):
        opponent_colour = self.opposite_color(self._turn)
        result = []
        for x in range(WIDTH):
            for y in range(HEIGHT):
                if self._board[(x * WIDTH) + y] == EMPTY:
                    opponent_offsets = self.adjacent_offsets_matching(x, y, opponent_colour)
                    for (ox, oy) in opponent_offsets:
                        #print ("X = %d, Y = %d -> OX = %d, OY = %d"%(x, y, ox, oy))
                        paths = self.find_path_to(x, y, ox, oy, self._turn)
                        if paths:
                            #print ("X = %d, Y = %d -> OX = %d, OY = %d"%(x, y, ox, oy))
                            result.append((x, y))
        return result

    def find_path_to(self, x, y, offset_x, offset_y, colour):
        path = []
        while self.on_board((x + offset_x), (y + offset_y)):
            x = x + offset_x
            y = y + offset_y
            path.append((x, y))
            if self.get_at(x, y) == EMPTY:
                return None
            if self.get_at(x, y) == colour:
                return path
        return None

    def draw(self):
        valid_placements = self.all_valid_placements()
        (complete, whitepoints, blackpoints, empty) = self.stats()
        display = '  01234567 -> %ss turn (complete: %d, white: %d, black: %d, empty: %d)\n'%(self._turn, complete, whitepoints, blackpoints, empty)
        for y in range(HEIGHT):
            display += '%d|'%(y)
            for x in range(WIDTH):
                if self._board[(x * WIDTH) + y] == WHITE:
                    display += WHITE_X
                elif self._board[(x * WIDTH) + y] == BLACK:
                    display += BLACK_X
                elif (x, y) in valid_placements:
                    display += VALID_X
                else:
                    display += EMPTY_X
            display += '\n'
        return display