#!/usr/bin/python
# -*- coding: utf-8 -*-

#-----------------------------------------------------------------------
# PROGRAM: app_static.py
#-----------------------------------------------------------------------
# Version 0.8
# 7 June, 2020
# Dr Michael Taylor
# https://patternizer.github.io
# patternizer AT gmail DOT com
#-----------------------------------------------------------------------

# ========================================================================
# SETTINGS
# ========================================================================
run_smoother = True
run_forecast = True
run_plots = True
plot_intervention = True
plot_total_error = True
plot_raw_obs = True
plot_mcmc = True

#value = 'Bangladesh'
#value = 'Brazil'
#value = 'Greece'
#value = 'India'
#value = 'Iran'
#value = 'Italy'
#value = 'Mexico'
#value = 'Morocco'
#value = 'Peru'
#value = 'Russia'
#value = 'Spain'
#value = 'Saudi Arabia'
value = 'United Kingdom'
#value = 'US'

# FAILING:
#value = 'China'
#value = 'South Korea'
#value = 'North Korea'
# ========================================================================

import numpy as np
import scipy.stats as st
from scipy.stats.kde import gaussian_kde
import pandas as pd
import matplotlib.pyplot as plt
import subprocess
from pandas.plotting import register_matplotlib_converters
register_matplotlib_converters()
import seaborn as sns; sns.set()

import dash
import dash_core_components as dcc
import dash_html_components as html
import dash_bootstrap_components as dbc
from dash.dependencies import Input, Output, State
import plotly.graph_objects as go
import plotly.figure_factory as ff
import plotly.express as px
from plotly.subplots import make_subplots
from flask import Flask
import os
from random import randint

# -----------------------------------------------------------------------------
def quantile(x,q):
    n = len(x)
    y = np.sort(x)
    return(np.interp(q, np.linspace(1/(2*n), (2*n-1)/(2*n), n), y))

def smoother(vec):
    newvec = np.ones(len(vec))
    weekly = np.zeros(7)
    for i in np.arange(0,7):
        dy = np.arange(0,int(np.ceil((len(vec)-i)/7)))
        weekly[i] = np.mean(vec[dy*7+i])
    weeklymean = np.mean(weekly)
    for i in np.arange(0,7):
        dy = np.arange(0,int(np.ceil((len(vec)-i)/7)))
        newvec[dy*7+i] = vec[dy*7+i]*np.mean(weekly)/weekly[i]
    return newvec

def nearest_power_of_10(n):
    x = int(10**np.ceil(np.log10(n)))
    return x

def update_status(dp,dl,df,value):
    # Handle inconsistencies in population, intervention and daily loss data sets
    if value == 'US':
        population = dp[dp['Country Name']=='United States']['Value'].values[0]
    elif value == 'China':
        population = dp[dp['Country Code']=='CHN']['Value'].values[0]
    elif value == 'Russia':
        population = dp[dp['Country Code']=='RUS']['Value'].values[0]
    elif value == 'Iran':
        population = dp[dp['Country Code']=='IRN']['Value'].values[0]
    elif value == 'North Korea':
        population = dp[dp['Country Code']=='PRK']['Value'].values[0]
    elif value == 'South Korea':
        population = dp[dp['Country Code']=='KOR']['Value'].values[0]
    else:
        population = dp[dp['Country Name']==value]['Value'].values[0]

    if value == 'US':
        interventiondate = dl[dl['country_name']=='United States']['date'].values[0]
        interventionlevel = dl[dl['country_name']=='United States']['intervention'].values[0]
    elif value == 'United Kingdom':
        interventiondate = dl[dl['country_name']=='UK']['date'].values[0]
        interventionlevel = dl[dl['country_name']=='UK']['intervention'].values[0]
    else:
        interventiondate = dl[dl['country_name']==value]['date'].values[0]
        interventionlevel = dl[dl['country_name']==value]['intervention'].values[0]

    if value == 'Australia':
        country = df[df['Country/Region'] == value].T[4:]
    elif value == 'Canada':
        country = df[df['Country/Region'] == value].T[4:]
    elif value == 'China':
        country = df[df['Country/Region'] == value].T[4:]
    else:
        country = df[(df['Country/Region'] == value) & (pd.isnull(df['Province/State']))].T[4:]

    if value == 'United Kingdom':
        backshift = pd.to_datetime(interventiondate) - pd.to_timedelta(pd.np.ceil(4), unit="D") # 2020-03-21
        interventiondate = str(int(backshift.year)) + "-" + str(int(backshift.month)) + "-" + str(int(backshift.day))
    if value == 'US':
        backshift = pd.to_datetime(interventiondate) - pd.to_timedelta(pd.np.ceil(12), unit="D") # 2020-03-22
        interventiondate = str(int(backshift.year)) + "-" + str(int(backshift.month)) + "-" + str(int(backshift.day))

    total = country.sum(axis=1).astype('int') # full record cumulative total
    deaths = total[total>0]                   # 1st case onwards cumulative total
    daily = total[total>0].diff()             # 1st case onwards counts
    daily[pd.isnull(daily)] = 1               # 1st case onwards counts - fix 1st NaN
    daily = daily.astype('int')               # 1st case onwards counts - integers
    dates = daily.index                       # 1st case onwards dates

    npre = 28                                 # Hindcast spin-up window
    npad = 14                                 # Pad with 2 weeks of zeros
    nforecast = 28                            # Forecast window

    startdatestamp = pd.to_datetime(dates[0]) - pd.to_timedelta(npre, unit="D")
    initdatestamp = pd.to_datetime(dates[0]) - pd.to_timedelta(npad, unit="D")
    casedatestamp = pd.to_datetime(dates[0])
    stopdatestamp = pd.to_datetime(dates[-1])
    enddatestamp = pd.to_datetime(dates[-1]) + pd.to_timedelta(nforecast, unit="D")
    startdate = str(int(startdatestamp.year)) + "-" + str(int(startdatestamp.month)) + "-" + str(int(startdatestamp.day))
    initdate = str(int(initdatestamp.year)) + "-" + str(int(initdatestamp.month)) + "-" + str(int(initdatestamp.day))
    casedate = str(int(casedatestamp.year)) + "-" + str(int(casedatestamp.month)) + "-" + str(int(casedatestamp.day))
    stopdate = str(int(stopdatestamp.year)) + "-" + str(int(stopdatestamp.month)) + "-" + str(int(stopdatestamp.day))
    enddate = str(int(enddatestamp.year)) + "-" + str(int(enddatestamp.month)) + "-" + str(int(enddatestamp.day))
    dates_pad = pd.date_range(initdatestamp, dates[-1])
    raw_pad = np.concatenate([np.zeros(npad).astype('int'), daily.values])

    dt = pd.DataFrame({'case': value,
                       'N': population,
                       'startdate': startdate,
                       'initdate': initdate,
                       'casedate': casedate,
                       'interventiondate': interventiondate,
                       'interventionlevel': interventionlevel,
                       'stopdate': stopdate,
                       'enddate': enddate,
                       'dates': dates_pad,
                       'raw': raw_pad})

    if run_smoother:
#        for i in range(0,dt.shape[0]-6):
#            dt.loc[dt.index[i+2],'ma'] = np.round(((dt.raw.iloc[i] + dt.raw.iloc[i+1] + dt.raw.iloc[i+2] + dt.raw.iloc[i+3] + dt.raw.iloc[i+4] + dt.raw.iloc[i+5] + dt.raw.iloc[i+6])/7),1)
#        dt['daily'] = dt.raw.rolling(7).mean().fillna(0).astype('int') # Pandas rolling mean
        dt['daily'] = dt.raw.iloc[:].ewm(span=3,adjust=False).mean()    # Exponential weighted mean (3)
#        dt['daily'] = smoother(dt.raw).astype('int')                   # Regularisation (James Annan)
    else:
        dt['daily'] = daily_pad
    dt['cumulative'] = dt['daily'].cumsum()
    dt['raw_cumulative'] = dt['raw'].cumsum()
    ma = dt[dt.daily == max(dt.daily)]['dates']
    peakidx = ma[ma == max(ma)].index
    peakdatestamp = ma[ma.index.values[0]]
    peakdate = str(int(peakdatestamp.year)) + "-" + str(int(peakdatestamp.month)) + "-" + str(int(peakdatestamp.day))
    dt['peakdate'] = peakdate

#    fig,ax = plt.subplots(figsize=[15,10])
#    plt.plot(dt.dates, dt.daily, label='smoothed')
#    plt.plot(dt.dates, dt.raw, label='raw')
#    plt.legend()
#    plt.savefig('smoothing.png')

    return dt
# -----------------------------------------------------------------------------

#----------------------------
# LOAD GLOBAL POPULATION DATA
#----------------------------
"""
Country level data from the World Bank:
https://data.worldbank.org/indicator/SP.POP.TOTL

Extract latest population census value per Country Code
"""

url = r'https://raw.githubusercontent.com/datasets/population/master/data/population.csv'
#Index(['Country Name', 'Country Code', 'Year', 'Value'], dtype='object')
df = pd.read_csv(url)
df.to_csv('dataset_population.csv', sep=',', index=False, header=False, encoding='utf-8')
countries = df['Country Code'].unique()
dp = pd.DataFrame(columns = df.columns)
dp['Country Name'] = [ df[df['Country Code']==countries[i]]['Country Name'].tail(1).values[0] for i in range(len(countries)) ]
dp['Country Code'] = [ df[df['Country Code']==countries[i]]['Country Code'].tail(1).values[0] for i in range(len(countries)) ]
dp['Year'] = [ df[df['Country Code']==countries[i]]['Year'].tail(1).values[0] for i in range(len(countries)) ]
dp['Value'] = [ df[df['Country Code']==countries[i]]['Value'].tail(1).values[0] for i in range(len(countries)) ]

#----------------------------
# LOAD GLOBAL LOCKDOWN STATUS
#----------------------------
"""
Daily updated Coronavirus containment measures taken by governments from 2020-01-23 to date
Provided by Olivier Lejeune: http://www.olejeune.com/ at:
https://github.com/OlivierLej/Coronavirus_CounterMeasures
dataset.csv has structure: country_id, country_name, 20200123_date, ...
"""

url = r'https://raw.githubusercontent.com/OlivierLej/Coronavirus_CounterMeasures/master/dataset.csv'
#Index(['country_id', 'country_name', '20200123_date',
df = pd.read_csv(url)
df.to_csv('dataset_lockdown.csv', sep=',', index=False, header=False, encoding='utf-8')
countries = df['country_name'].unique()
dl = pd.DataFrame(columns = ['country_id', 'country_name', 'intervention', 'date'])
dl['country_id'] = [ df[df['country_name']==countries[i]]['country_id'].tail(1).values[0] for i in range(len(countries)) ]
dl['country_name'] = [ df[df['country_name']==countries[i]]['country_name'].tail(1).values[0] for i in range(len(countries)) ]
for i in range(len(countries)-1):
    if i  == 182:
        m = df[df['country_id']=='TX'].T[2:]
    else:
        m = df[df['country_name']==countries[i]].T[2:]
    datestr = []
    try:
        datestr = m[m.values>3].index[0]
        level = m[m.values>3].values[0][0]
    except:
        try:
            datestr = m[m.values>2].index[0]
            level = m[m.values>2].values[0][0]
        except:
            continue
    dl['intervention'][i] = level
    dl['date'][i] = datestr[0:4] + '-' + str(int(datestr[4:6])) + '-' + str(int(datestr[6:8]))

#----------------------------
# LOAD GLOBAL DAILY DEATHS
#----------------------------
"""
Daily updated Coronavirus daily death total per country
https://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/csse_covid_19_time_series/time_series_covid19_deaths_global.csv
"""

url = r'https://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/csse_covid_19_time_series/time_series_covid19_deaths_global.csv'
#Index(['Province/State', 'Country/Region', 'Lat', 'Long', '1/22/20',
df = pd.read_csv(url)
df.to_csv('dataset_dailydeaths.csv', sep=',', index=False, header=False, encoding='utf-8')

dt = update_status(dp,dl,df,value)

N = dt.N[0]
startdate = dt.startdate[0]
initdate = dt.initdate[0]
casedate = dt.casedate[0]
interventiondate = dt.interventiondate[0]
peakdate = dt.peakdate[0]
stopdate = dt.stopdate[0]
enddate = dt.enddate[0]

nforecast = (pd.to_datetime(enddate)-pd.to_datetime(stopdate)).days

#-----------------------------------------
# I/O Python <--> R (NB filename mathcing)
#-----------------------------------------

countrystr = value.replace(" ", "_").lower() + '_'
fileout = 'out.csv'
fileout_post_samp = countrystr + 'post_samp.csv'
fileout_obs = countrystr + 'obs.csv'
fileout_allouts = countrystr + 'allouts.csv'
fileout_alldeadout = countrystr + 'alldeadout.csv'
fileout_allcumdeadout = countrystr + 'allcumdeadout.csv'

# Write Python output for loading by R executable
dt.to_csv(fileout, index=False)

# Call R forecast executable

if run_forecast:
#    subprocess.call ("C:\\Program Files\\R\\R-3.6.3\\bin\\Rscript --vanilla C:\\Users\\User\\Desktop\\REPOS\\COVID-19-operational-forecast\\GITHUB\\covid-19_mcmc_prediction_public_executable.R")
    subprocess.call ("Rscript --vanilla covid-19_mcmc_prediction_public_executable.R")

# Read R output back into Python

post_samp = pd.read_csv(fileout_post_samp)
obs = pd.read_csv(fileout_obs)
allouts = pd.read_csv(fileout_allouts)
alldeadout = pd.read_csv(fileout_alldeadout)
allcumdeadout = pd.read_csv(fileout_allcumdeadout)

n_ens = len(allouts)
data_pts = len(obs.columns)
r0_mean = np.mean(post_samp['V5'])
r0_sd = np.std(post_samp['V5'])
rt_mean = np.mean(post_samp['V6'])
rt_sd = np.std(post_samp['V6'])
corr = post_samp.corr()

interval_start = int(obs.values[:,0][0])
interval_end = int(obs.values[:,0][-1]) + nforecast
interval = np.arange(interval_start, interval_end+1)
dates_all = pd.to_datetime(startdate) + pd.to_timedelta(interval, unit='D')

mcmc_daily = alldeadout.values[:,interval]
lowcent_daily = N*np.array([quantile(mcmc_daily[:,i],0.05) for i in range(len(interval))])
midcent_daily = N*np.array([quantile(mcmc_daily[:,i],0.5) for i in range(len(interval))])
upcent_daily = N*np.array([quantile(mcmc_daily[:,i],0.95) for i in range(len(interval))])
# V2---
report_err = 0.05
model_err = 0.05
#total_error = np.sqrt(.2**2 + (0.03*abs(interval_end - nforecast - interval))**2) # V1
#total_error <- sqrt((log((midcent+sqrt(midcent))/midcent))^2+(report_err)^2 + (model_err*pmax(interval-nowdate,0))^2) # V2
total_error = np.sqrt((np.log((midcent_daily + np.sqrt(midcent_daily))/midcent_daily))**2 + (report_err)**2 + (model_err*abs(interval_end - nforecast - interval))**2) # V2
# V2---
up_log_daily = np.sqrt((total_error*1.64)**2 + (np.log(upcent_daily/midcent_daily))**2) #1.64 for 5-95% range
low_log_daily = np.sqrt((total_error*1.64)**2 + (np.log(midcent_daily/lowcent_daily))**2)
upper_daily = midcent_daily*np.exp(up_log_daily)
lower_daily = midcent_daily*np.exp(-low_log_daily)

mcmc_total = allcumdeadout.values[:,interval]
lowcent_total = N*np.array([quantile(mcmc_total[:,i],0.05) for i in range(len(interval))])
midcent_total = N*np.array([quantile(mcmc_total[:,i],0.5) for i in range(len(interval))])
upcent_total = N*np.array([quantile(mcmc_total[:,i],0.95) for i in range(len(interval))])
up_log_total = np.sqrt((total_error*1.64)**2 + (np.log(upcent_total/midcent_total))**2) #1.64 for 5-95% range
low_log_total = np.sqrt((total_error*1.64)**2 + (np.log(midcent_total/lowcent_total))**2)
upper_total = midcent_total*np.exp(up_log_total)
lower_total = midcent_total*np.exp(-low_log_total)

# JDAnnan:
# note as a matter of preference we include the model error term only for the future in the graphics,
# and the hindcast spread shows only ensemble spread and sampling/obs error. A debateable
# decision but including model error here makes it look like we have a massive spread in the past,
# which is not the case. It could be the case that our model error term is a little large?

upcent_daily[dates_all>stopdate] = upper_daily[dates_all>stopdate]
lowcent_daily[dates_all>stopdate] = lower_daily[dates_all>stopdate]
upcent_total[dates_all>stopdate] = upper_total[dates_all>stopdate]
lowcent_total[dates_all>stopdate] = lower_total[dates_all>stopdate]

upper_daily[dates_all<=stopdate] = upcent_daily[dates_all<=stopdate]
lower_daily[dates_all<=stopdate] = lowcent_daily[dates_all<=stopdate]
upper_total[dates_all<=stopdate] = upcent_total[dates_all<=stopdate]
lower_total[dates_all<=stopdate] = lowcent_total[dates_all<=stopdate]

# -----------------------------------------------------------------------------
# PLOTS
# -----------------------------------------------------------------------------

if not run_plots:
    print('Python code end')
    import sys
    sys.exit()

# Plot observations

ymin = min(dt[dt.cumulative>0]['daily'])
ymax = max(dt[dt.cumulative>0]['daily'])
yintervention = dt[dt.dates==interventiondate]['daily'].values[0]
ypeak = dt[dt.dates==peakdate]['daily'].values[0]

data = [
            go.Bar(y=dt[dt.cumulative>0]['raw'], x=dt[dt.cumulative>0]['dates'],
                   marker_color='lightgrey',
                   name='Daily deaths',
                   yaxis='y1'),
            go.Scatter(x=dt[dt.cumulative>0]['dates'], y=dt[dt.cumulative>0]['daily'],
                       mode='lines+markers',
                       line=dict(width=1.0,color='red'),
                       marker=dict(size=5, opacity=0.5),
                       name='3-day EWA',
                       yaxis='y1'),
]

if plot_intervention:
    data_intervention = [
            go.Scatter(x=[interventiondate, interventiondate],
                       y=[ymin, ymax],
                       mode="lines",
                       legendgroup="a",
                       showlegend=False,
                       marker=dict(size=12, line=dict(width=0.5), color="grey"),
                       name="Intervention",
                       yaxis='y1'),
            go.Scatter(x=[peakdate, peakdate],
                       y=[ymin, ymax],
                       mode="lines",
                       legendgroup="a",
                       showlegend=False,
                       marker=dict(size=12, line=dict(width=0.5), color="grey"),
                       name="Peak",
                       yaxis='y1'),
    ]
    data = data + data_intervention

if plot_intervention:
    layout = go.Layout(
        yaxis=dict(title='Daily', range=[ymin, ymax]),
        annotations = [
                dict(
                    text = 'Lockdown
' + interventiondate,
                    x = pd.to_datetime(interventiondate) - pd.to_timedelta(1, unit='D'),
                    y = ymax,
                    xanchor = 'right',
                    yanchor = 'top',
                    showarrow = False,
                    ),
                dict(
                    text = 'Peak
' + peakdate,
                    x = pd.to_datetime(peakdate) + pd.to_timedelta(1, unit='D'),
                    y = ymax,
                    xanchor = 'left',
                    yanchor = 'top',
                    showarrow = False,
                ),
                dict(
                    text = "{0:.0f}".format((pd.to_datetime(peakdate)-pd.to_datetime(interventiondate)).days) + ' days',
                    x = pd.to_datetime(peakdate) + pd.to_timedelta(1, unit='D'),
                    y = (ymax-ymin)/4,
                    xanchor = 'left',
                    yanchor = 'middle',
                    showarrow = False,
                ),
                dict(
                    x = peakdate,
                    y = (ymax-ymin)/4,
                    xref = "x", yref = "y1",
                    axref = "x", ayref = "y1",
                    text = "",
                    showarrow = True,
                    arrowhead = 4,
                    arrowwidth = 2,
                    arrowcolor = 'purple',
                    ax = interventiondate,
                    ay = (ymax-ymin)/4,
                    ),
        ],
        legend_orientation="v", legend=dict(x=0.72, y=0.95, bgcolor='rgba(205, 223, 212, .4)', bordercolor="Black"),
        margin=dict(r=60, l=60, b=60, t=20),
    )
else:
    layout = go.Layout(
        yaxis=dict(title='Daily', range=[ymin, ymax]),
        legend_orientation="v", legend=dict(x=0.72, y=0.95, bgcolor='rgba(205, 223, 212, .4)', bordercolor="Black"),
        margin=dict(r=60, l=60, b=60, t=20),
    )

fig = go.Figure(data, layout)
fig.write_image(countrystr + 'static-input.png')

# Plot observations (cumulative)

ymin = min(dt[dt.cumulative>0]['cumulative'])
ymax = max(dt[dt.cumulative>0]['cumulative'])
yintervention = dt[dt.dates==interventiondate]['cumulative'].values[0]
ypeak = dt[dt.dates==peakdate]['cumulative'].values[0]

data = [
            go.Bar(y=dt[dt.cumulative>0]['raw_cumulative'], x=dt[dt.cumulative>0]['dates'],
                   marker_color='lightgrey',
                   name='Total deaths',
                   yaxis='y1'),
            go.Scatter(x=dt[dt.cumulative>0]['dates'], y=dt[dt.cumulative>0]['cumulative'],
                       mode='lines+markers',
                       line=dict(width=1.0,color='red'),
                       marker=dict(size=5, opacity=0.8),
                       name='3-day EWA',
                       yaxis='y1'),
]

if plot_intervention:
    data_intervention = [
            go.Scatter(x=[interventiondate, interventiondate],
                       y=[ymin, ymax],
                       mode="lines",
                       legendgroup="a",
                       showlegend=False,
                       marker=dict(size=12, line=dict(width=0.5), color="grey"),
                       name="Intervention",
                       yaxis='y1'),
            go.Scatter(x=[peakdate, peakdate],
                       y=[ymin, ymax],
                       mode="lines",
                       legendgroup="a",
                       showlegend=False,
                       marker=dict(size=12, line=dict(width=0.5), color="grey"),
                       name="Peak",
                       yaxis='y1'),
    ]
    data = data + data_intervention

if plot_intervention:
    layout = go.Layout(
        yaxis=dict(title='Cumulative', range=[ymin, ymax]),
        annotations = [
                dict(
                    text = 'Lockdown
' + interventiondate,
                    x = pd.to_datetime(interventiondate) - pd.to_timedelta(1, unit='D'),
                    y = ymax,
                    xanchor = 'right',
                    yanchor = 'top',
                    showarrow = False,
                    ),
                dict(
                    text = 'Peak
' + peakdate,
                    x = pd.to_datetime(peakdate) + pd.to_timedelta(1, unit='D'),
                    y = ymax,
                    xanchor = 'left',
                    yanchor = 'top',
                    showarrow = False,
                ),
                dict(
                    text = "{0:.0f}".format((pd.to_datetime(peakdate) - pd.to_datetime(interventiondate)).days) + ' days',
                    x = pd.to_datetime(peakdate) + pd.to_timedelta(1, unit='D'),
                    y = ypeak,
                    xanchor = 'left',
                    yanchor = 'middle',
                    showarrow = False,
                ),
                dict(
                    x = peakdate,
                    y = ypeak,
                    xref = "x", yref = "y1",
                    axref = "x", ayref = "y1",
                    text = "",
                    showarrow = True,
                    arrowhead = 4,
                    arrowwidth = 2,
                    arrowcolor = 'purple',
                    ax = interventiondate,
                    ay = ypeak,
                    ),
        ],
        legend_orientation="v", legend=dict(x=0.72, y=0.05, bgcolor='rgba(205, 223, 212, .4)', bordercolor="Black"),
        margin=dict(r=60, l=60, b=60, t=20),
    )
else:
    layout = go.Layout(
        yaxis=dict(title='Cumulative', range=[ymin, ymax]),
        legend_orientation="v", legend=dict(x=0.72, y=0.05, bgcolor='rgba(205, 223, 212, .4)', bordercolor="Black"),
        margin=dict(r=60, l=60, b=60, t=20),
    )

fig = go.Figure(data, layout)
fig.write_image(countrystr + 'static-input-cumulative.png')

# Plot forecast

ymin = np.log10(0.2)
if plot_total_error:
    ymax = nearest_power_of_10(np.max(upper_daily))
else:
    ymax = nearest_power_of_10(np.max(upcent_daily))
yintervention = midcent_daily[dates_all==interventiondate][0]
ypeak = midcent_daily[dates_all==peakdate][0]

data = [
            go.Scatter(x=dates_all, y=upcent_daily,
                       mode='lines',
                       fill=None,
                       line=dict(width=1.0, color='navajowhite'),
                       name='95% centile',
                       showlegend=False,
                       yaxis='y1'),
            go.Scatter(x=dates_all, y=lowcent_daily,
                       mode='lines',
                       fill='tonexty',
                       line=dict(width=1.0, color='navajowhite'),
                       name='5-95% range',
                       showlegend=True,
                       yaxis='y1'),
            go.Scatter(x=dates_all, y=lowcent_daily,
                       mode='lines',
                       fill=None,
                       line=dict(width=1.0, color='navajowhite'),
                       name='5% centile',
                       showlegend=False,
                       yaxis='y1'),
            go.Scatter(x=dates_all, y=midcent_daily,
                       mode='lines',
                       line=dict(width=3.0, color='red'),
                       name='Hindcast/forecast',
                       showlegend=True,
                       yaxis='y1'),
            go.Scatter(x=dt[dt.dates>=casedate]['dates'], y=dt[dt.dates>=casedate]['daily'],
                       mode='markers',
                       marker=dict(size=5, symbol='circle-open', color='red'),
                       name='3-day EWA',
                       showlegend=True,
                       yaxis='y1'),
]

if plot_raw_obs:
    data_raw_obs = [
            go.Scatter(x=dt[dt.dates>=casedate]['dates'], y=dt[dt.dates>=casedate]['raw'].astype('int'),
                       mode='markers',
                       marker=dict(size=5, symbol='cross-thin-open', color='darkslategrey'),
                       name='Daily deaths',
                       showlegend=True,
                       yaxis='y1'),
    ]
else:
    data_raw_obs = []

if plot_total_error:
    data_total_error = [
             go.Scatter(x=dates_all, y=upper_daily,
                       mode='lines',
                       fill=None,
                       line=dict(width=1.0, color='navajowhite'),
                       name='forecast uncertainty (upper limit)',
                       showlegend=False,
                       yaxis='y1'),
             go.Scatter(x=dates_all, y=lower_daily,
                       mode='lines',
                       fill='tonexty',
                       line=dict(width=1.0, color='navajowhite'),
                       name='forecast uncertainty',
                       showlegend=False,
                       yaxis='y1'),
             go.Scatter(x=dates_all, y=lower_daily,
                       mode='lines',
                       fill=None,
                       line=dict(width=1.0, color='navajowhite'),
                       name='forecast uncertainty (lower limit)',
                       showlegend=False,
                       yaxis='y1'),
    ]
else:
    data_total_error = []

if plot_intervention:
    data_intervention = [
            go.Scatter(x=[interventiondate, interventiondate],
                       y=[ymin, ymax],
                       mode="lines",
                       legendgroup="a",
                       showlegend=False,
                       marker=dict(size=12, line=dict(width=0.5), color="grey"),
                       name="Intervention",
                       yaxis='y1'),
            go.Scatter(x=[peakdate, peakdate],
                       y=[ymin, ymax],
                       mode="lines",
                       legendgroup="a",
                       showlegend=False,
                       marker=dict(size=12, line=dict(width=0.5), color="grey"),
                       name="Peak",
                       yaxis='y1'),
            go.Scatter(x=[stopdate, stopdate],
                       y=[ymin, ymax],
                       mode="lines",
                       legendgroup="a",
                       showlegend=False,
                       marker=dict(size=12, line=dict(width=0.5), color="grey"),
                       name="",
                       yaxis='y1'),
    ]
else:
    data_intervention = []

data = data_total_error + data + data_raw_obs + data_intervention

if plot_intervention:
    layout = go.Layout(
            title = {'text' : 'Initialised on ' + stopdate + ' (' + str(pd.to_timedelta(pd.to_datetime(stopdate) - pd.to_datetime(interventiondate), unit='D').days) + ' days after intervention)', 'x': 0.5, 'y': 1.0},
            yaxis=dict(title='Daily', range=[ymin, np.log10( ymax ) ]),
            yaxis_type="log",
            legend_orientation="v", legend=dict(x=.72, y=0.05, bgcolor='rgba(205, 223, 212, .4)', bordercolor="Black"),
            annotations = [
                dict(
                    text = 'R0
' + "{0:.2f}".format(r0_mean) + '±' + "{0:.2f}".format(r0_sd),
                    x = pd.to_datetime(interventiondate) - pd.to_timedelta(1, unit='D'),
                    y = np.log10( ymax ),
                    xanchor = 'right',
                    yanchor = 'top',
                    showarrow = False,
                    ),
                dict(
                    text = 'Rt
' + "{0:.2f}".format(rt_mean) + '±' + "{0:.2f}".format(rt_sd),
                    x = pd.to_datetime(interventiondate) + pd.to_timedelta(1, unit='D'),
                    y = np.log10( ymax ),
                    xanchor = 'left',
                    yanchor = 'top',
                    showarrow = False,
                ),
                dict(
                    text = 'Tomorrow
' + "{0:.0f}".format(midcent_daily[dates_all>stopdate][0])
                        + ' ('
                        + "{0:.0f}".format(lowcent_daily[dates_all>stopdate][0])
                        + '-'
                        + "{0:.0f}".format(upcent_daily[dates_all>stopdate][0])
                        +')',
                    x = pd.to_datetime(stopdate) - pd.to_timedelta(1, unit='D'),
                    y = np.log10( ymax ),
                    xanchor = 'right',
                    yanchor = 'top',
                    showarrow = False,
                ),
            ],
            margin=dict(r=60, l=60, b=60, t=20),
    )
else:
    layout = go.Layout(
            title = {'text' : 'Initialised on ' + stopdate + ' (' + str(pd.to_timedelta(pd.to_datetime(stopdate) - pd.to_datetime(interventiondate), unit='D').days) + ' days after intervention)', 'x': 0.5, 'y': 1.0},
            yaxis=dict(title='Daily', range=[ymin, np.log10( ymax ) ], which="major"),
            yaxis_type="log",
            legend_orientation="v", legend=dict(x=.72, y=0.05, bgcolor='rgba(205, 223, 212, .4)', bordercolor="Black"),
            annotations = [
                dict(
                    text = 'Tomorrow
' + "{0:.0f}".format(midcent_daily[dates_all>dates[-1]][0])
                        + ' ('
                        + "{0:.0f}".format(lowcent_daily[dates_all>stopdate][0])
                        + '-'
                        + "{0:.0f}".format(upcent_daily[dates_all>stopdate][0])
                        +')',
                    x = pd.to_datetime(stopdate) - pd.to_timedelta(1, unit='D'),
                    y = np.log10( ymax ),
                    xanchor = 'right',
                    yanchor = 'top',
                    showarrow = False,
                ),
            ],
            margin=dict(r=60, l=60, b=60, t=20),
    )

fig = go.Figure(data, layout)
fig.write_image(countrystr + 'static-forecast.png')

# Plot forecast (cumulative)

ymin = np.log10(0.2)
if plot_total_error:
    ymax = nearest_power_of_10(np.max(upper_total))
else:
    ymax = nearest_power_of_10(np.max(upcent_total))
yintervention = midcent_total[dates_all==interventiondate][0]
ypeak = midcent_total[dates_all==peakdate][0]

data = [
            go.Scatter(x=dates_all, y=upcent_total,
                       mode='lines',
                       fill=None,
                       line=dict(width=1.0, color='navajowhite'),
                       name='95% centile',
                       showlegend=False,
                       yaxis='y1'),
            go.Scatter(x=dates_all, y=lowcent_total,
                       mode='lines',
                       fill='tonexty',
                       line=dict(width=1.0, color='navajowhite'),
                       name='5-95% range',
                       showlegend=True,
                       yaxis='y1'),
            go.Scatter(x=dates_all, y=lowcent_total,
                       mode='lines',
                       fill=None,
                       line=dict(width=1.0, color='navajowhite'),
                       name='5% centile',
                       showlegend=False,
                       yaxis='y1'),
            go.Scatter(x=dates_all, y=midcent_total,
                       mode='lines',
                       line=dict(width=3.0, color='red'),
                       name='Hindcast/forecast',
                       showlegend=True,
                       yaxis='y1'),
            go.Scatter(x=dt[dt.dates>=casedate]['dates'], y=dt[dt.dates>=casedate]['cumulative'],
                       mode='markers',
                       marker=dict(size=5, symbol='circle-open', color='red'),
                       name='3-day EWA',
                       showlegend=True,
                       yaxis='y1'),
]

if plot_raw_obs:
    data_raw_obs = [
            go.Scatter(x=dt[dt.dates>=casedate]['dates'], y=dt[dt.dates>=casedate]['raw_cumulative'].astype('int'),
                       mode='markers',
                       marker=dict(size=5, symbol='cross-thin-open', color='darkslategrey'),
                       name='Cumulative deaths',
                       showlegend=True,
                       yaxis='y1'),
    ]
else:
    data_raw_obs = []

if plot_total_error:
    data_total_error = [
             go.Scatter(x=dates_all, y=upper_total, mode='lines',
                       fill=None,
                       line=dict(width=1.0, color='navajowhite'),
                       showlegend=False,
                       yaxis='y1'),
             go.Scatter(x=dates_all, y=lower_total, mode='lines',
                       fill='tonexty',
                       line=dict(width=1.0, color='navajowhite'),
                       name='forecast uncertainty',
                       showlegend=False,
                       yaxis='y1'),
             go.Scatter(x=dates_all, y=upper_total, mode='lines',
                       fill=None,
                       line=dict(width=1.0, color='navajowhite'),
                       showlegend=False,
                       yaxis='y1'),
    ]
else:
    data_total_error = []

if plot_intervention:
    data_intervention = [
            go.Scatter(x=[interventiondate, interventiondate],
                       y=[ymin, ymax],
                       mode="lines",
                       legendgroup="a",
                       showlegend=False,
                       marker=dict(size=12, line=dict(width=0.5), color="grey"),
                       name="Intervention",
                       yaxis='y1'),
            go.Scatter(x=[peakdate, peakdate],
                       y=[ymin, ymax],
                       mode="lines",
                       legendgroup="a",
                       showlegend=False,
                       marker=dict(size=12, line=dict(width=0.5), color="grey"),
                       name="Peak",
                       yaxis='y1'),
            go.Scatter(x=[stopdate, stopdate],
                       y=[ymin, ymax],
                       mode="lines",
                       legendgroup="a",
                       showlegend=False,
                       marker=dict(size=12, line=dict(width=0.5), color="grey"),
                       name="",
                       yaxis='y1'),
    ]
else:
    data_intervention = []

data = data_total_error + data + data_raw_obs + data_intervention

if plot_intervention:
    layout = go.Layout(
            title = {'text' : 'Initialised on ' + stopdate + ' (' + str(pd.to_timedelta(pd.to_datetime(stopdate) - pd.to_datetime(interventiondate), unit='D').days) + ' days after intervention)', 'x': 0.5, 'y': 1.0},
            yaxis=dict(title='Cumulative', range=[ymin, np.log10( ymax )]),
            yaxis_type="log",
            legend_orientation="v", legend=dict(x=.72, y=0.05, bgcolor='rgba(205, 223, 212, .4)', bordercolor="Black"),
            annotations = [
                dict(
                    text = 'R0
' + "{0:.2f}".format(r0_mean) + '±' + "{0:.2f}".format(r0_sd),
                    x = pd.to_datetime(interventiondate) - pd.to_timedelta(1, unit='D'),
                    y = np.log10( ymax ),
                    xanchor = 'right',
                    yanchor = 'top',
                    showarrow = False,
                    ),
                dict(
                    text = 'Rt
' + "{0:.2f}".format(rt_mean) + '±' + "{0:.2f}".format(rt_sd),
                    x = pd.to_datetime(interventiondate) + pd.to_timedelta(1, unit='D'),
                    y = np.log10( ymax ),
                    xanchor = 'left',
                    yanchor = 'top',
                    showarrow = False,
                ),
                dict(
                    text = 'Tomorrow
' + "{0:.0f}".format(midcent_total[dates_all>stopdate][0])
                        + ' ('
                        + "{0:.0f}".format(midcent_total[dates_all>stopdate][0] - lowcent_daily[dates_all>stopdate][0])
                        + '-'
                        + "{0:.0f}".format(midcent_total[dates_all>stopdate][0] + upcent_daily[dates_all>stopdate][0])
                        +')',
                    x = pd.to_datetime(stopdate) - pd.to_timedelta(1, unit='D'),
                    y = np.log10( ymax ),
                    xanchor = 'right',
                    yanchor = 'top',
                    showarrow = False,
                ),
            ],
            margin=dict(r=60, l=60, b=60, t=20),
    )
else:
    layout = go.Layout(
            title = {'text' : 'Initialised on ' + stopdate + ' (' + str(pd.to_timedelta(pd.to_datetime(stopdate) - pd.to_datetime(interventiondate), unit='D').days) + ' days after intervention)', 'x': 0.5, 'y': 1.0},
            yaxis=dict(title='Cumulative', range=[ymin, np.log10( ymax )]),
            yaxis_type="log",
            legend_orientation="v", legend=dict(x=.72, y=0.05, bgcolor='rgba(205, 223, 212, .4)', bordercolor="Black"),
            annotations = [
                dict(
                    text = 'Tomorrow
' + "{0:.0f}".format(midcent_total[dates_all>stopdate][0])
                        + ' ('
                        + "{0:.0f}".format(midcent_total[dates_all>stopdate][0] - lowcent_daily[dates_all>stopdate][0])
                        + '-'
                        + "{0:.0f}".format(midcent_total[dates_all>stopdate][0] + upcent_daily[dates_all>stopdate][0])
                        +')',
                    x = pd.to_datetime(stopdate) + pd.to_timedelta(1, unit='D'),
                    y = np.log10(1),
                    xanchor = 'left',
                    yanchor = 'bottom',
                    showarrow = False,
                ),
            ],
            margin=dict(r=60, l=60, b=60, t=20),
    )

fig = go.Figure(data, layout)
fig.write_image(countrystr + 'static-forecast_total.png')

if not plot_mcmc:
    print('Python code end')
    import sys
    sys.exit()

# Plot MCMC tunable parameter traces

fig = make_subplots(rows=2, cols=3, start_cell='top-left')
fig.add_trace(go.Scatter(x=post_samp.index, y=post_samp['V1'], line=dict(width=1.0, color='black'), name=post_samp.columns[0]), row=1, col=1)
fig.add_trace(go.Scatter(x=post_samp.index, y=post_samp['V2'], line=dict(width=1.0, color='red'), name=post_samp.columns[1]), row=1, col=2)
fig.add_trace(go.Scatter(x=post_samp.index, y=post_samp['V3'], line=dict(width=1.0, color='blue'), name=post_samp.columns[2]), row=1, col=3)
fig.add_trace(go.Scatter(x=post_samp.index, y=post_samp['V4'], line=dict(width=1.0, color='grey'), name=post_samp.columns[3]), row=2, col=1)
fig.add_trace(go.Scatter(x=post_samp.index, y=post_samp['V5'], line=dict(width=1.0, color='pink'), name=post_samp.columns[4]), row=2, col=2)
fig.add_trace(go.Scatter(x=post_samp.index, y=post_samp['V6'], line=dict(width=1.0, color='cyan'), name=post_samp.columns[5]), row=2, col=3)
fig.update_xaxes(row=2, col=1, title="Iterations")
fig.update_xaxes(row=2, col=2, title="Iterations")
fig.update_xaxes(row=2, col=3, title="Iterations")
fig.update_layout(showlegend = True)
fig.write_image(countrystr + 'static-mcmc-traces.png')

# Plot MCMC tunable parameter kernel densities

hist_data = [post_samp['V1'].values, post_samp['V2'].values, post_samp['V3'].values,
                 post_samp['V4'].values, post_samp['V5'].values, post_samp['V6'].values]
rug_values = np.mean(post_samp)
group_labels = list(post_samp)
colors = ['black', 'red', 'blue', 'grey', 'pink', 'cyan']

fig = make_subplots(rows=2, cols=3, start_cell='top-left')
fig2 = ff.create_distplot(hist_data, group_labels)
fig.add_trace(go.Scatter(fig2['data'][6], line=dict(color='black', width=2.0), name=post_samp.columns[0]), row=1, col=1)
fig.add_trace(go.Scatter(fig2['data'][7], line=dict(color='red', width=2.0), name=post_samp.columns[1]), row=1, col=2)
fig.add_trace(go.Scatter(fig2['data'][8], line=dict(color='blue', width=2.0), name=post_samp.columns[2]), row=1, col=3)
fig.add_trace(go.Scatter(fig2['data'][9], line=dict(color='grey', width=2.0), name=post_samp.columns[3]), row=2, col=1)
fig.add_trace(go.Scatter(fig2['data'][10], line=dict(color='pink', width=2.0), name=post_samp.columns[4]), row=2, col=2)
fig.add_trace(go.Scatter(fig2['data'][11], line=dict(color='cyan', width=2.0), name=post_samp.columns[5]), row=2, col=3)

fig.add_trace(go.Scatter(x=post_samp['V1'], y = post_samp['V1']*0., mode = 'markers',
                             marker=dict(color = 'black', symbol='line-ns-open'), name=post_samp.columns[0]), row=1, col=1)
fig.add_trace(go.Scatter(x=post_samp['V2'], y = post_samp['V2']*0., mode = 'markers',
                             marker=dict(color = 'red', symbol='line-ns-open'), name=post_samp.columns[1]), row=1, col=2)
fig.add_trace(go.Scatter(x=post_samp['V3'], y = post_samp['V3']*0., mode = 'markers',
                             marker=dict(color = 'blue', symbol='line-ns-open'), name=post_samp.columns[2]), row=1, col=3)
fig.add_trace(go.Scatter(x=post_samp['V4'], y = post_samp['V4']*0., mode = 'markers',
                             marker=dict(color = 'grey', symbol='line-ns-open'), name=post_samp.columns[3]), row=2, col=1)
fig.add_trace(go.Scatter(x=post_samp['V5'], y = post_samp['V5']*0., mode = 'markers',
                             marker=dict(color = 'pink', symbol='line-ns-open'), name=post_samp.columns[4]), row=2, col=2)
fig.add_trace(go.Scatter(x=post_samp['V6'], y = post_samp['V6']*0., mode = 'markers',
                             marker=dict(color = 'cyan', symbol='line-ns-open'), name=post_samp.columns[5]), row=2, col=3)
fig.update_layout(showlegend=True)
fig.write_image(countrystr + 'static-mcmc-histograms.png')

# Plot tunable parameter correlation matrix

f = plt.figure()
f.set_size_inches(11,8)
mask = np.triu(np.ones_like(corr, dtype=np.bool))
sns.heatmap(corr, mask=mask, cmap='coolwarm', vmax=1.0, center=0, square=False, linewidths=.5, cbar_kws={"shrink": .5}, label='Correlation Coefficient')
plt.xlabel('Parameter')
plt.ylabel('Parameter')
title_str = 'Correlation matrix of MCMC parameter ensemble'
plt.title(title_str)
plt.savefig(countrystr + 'static-mcmc-corr.png')

# -----------------------------------------------------------------------------
print('Python code end')


from __future__ import annotations

from pygame.sprite import Sprite
from pygame.transform import scale
from IO_XmlHandler import IO_XmlHandler
from IO_Texture import IO_Texture, IO_TextureManager
from IO_Object import IO_Entity, IO_Object
import pygame

class IO_Animation(IO_Object):
    def __init__(self,
                id : str,
                frameCount : int,
                repeat : bool = True,
                isEnded : bool = False,
                pause : bool = False,
                speed=100,
                scale = None,
                roatation = None,
                flip = None):
        """
        @member repeat conttollers wheter animation repeats after cycle\n
        @member isEnded checks if animation is ended\n
        @member pause pauses animation\n
        @member frame current frame\n
        """
        super().__init__()
        self.id = id
        self.repeat = repeat
        self.isEnded = isEnded
        self.pause = pause
        self.currentFrame = 0
        self.speed = speed
        self.frameCount = frameCount
        self.scale = scale
        self.roatation = roatation
        self.flip = flip

    def update(self,dt : float =0,scrollRatio : float = 0):
        raise NotImplementedError()

    def render(self,x,y):
        raise NotImplementedError()

    def setAttrib(self,
                frameCount : int = None,
                repeat : bool = None,
                isEnded : bool  = None,
                pause : bool = None,
                currentFrame : int  = None,
                speed= None,
                scale = None,
                rotation = None,
                flip = None):

        if (repeat != None): self.repeat = repeat
        if (isEnded != None): self.isEnded = isEnded
        if (pause != None): self.pause = pause
        if (currentFrame != None): self.currentFrame = currentFrame
        if (speed != None): self.speed = speed
        if (frameCount != None): self.frameCount = frameCount
        if (scale != None): self.scale = scale
        if (rotation != None): self.roatation = rotation
        if (flip != None): self.flip = flip

    def __iter__(self):
        yield 'class', self.__class__
        yield 'repeat', self.repeat
        yield 'pause', self.pause
        yield 'isEnded', self.isEnded
        yield 'currentFrame', self.currentFrame
        yield 'speed',self.speed
        yield 'frameCount' , self.frameCount

class IO_SpriteAnimation(IO_Animation):
    def __init__(self,
                texture :IO_Texture,
                id : str,
                frameArea : tuple[int,int],
                row : int,
                frameCount : int,
                repeat : bool = True,
                isEnded : bool = False,
                pause : bool = False,
                speed=100,
                scale = None,
                rotation = None,
                flip = None):
        """

        """
        super().__init__(id,frameCount,repeat,isEnded,pause,speed,scale,rotation,flip)

        self.row = row
        self.frameArea = frameArea
        self.texture : IO_Texture = texture
        self.texture.transform(scale,rotation,flip)

    def update(self, dt : float = 0):
        """
        update current frame
        """
        #ondDlength = self.frameCount * self.rowCount
        ondDlength = self.frameCount

        if (self.repeat or self.isEnded == False) and self.pause == False:
            self.isEnded = False
            self.currentFrame = int((pygame.time.get_ticks()/self.speed)% ondDlength)

        if self.repeat == False and self.currentFrame == ondDlength -1:
            self.isEnded = True
            self.currentFrame = ondDlength -1

    def setAttrib(self,
                frameCount : int = None,
                repeat : bool = None,
                isEnded : bool  = None,
                pause : bool = None,
                currentFrame : int  = None,
                speed= 100,
                scale = None,
                rotation = None,
                flip = None):

        super().setAttrib(frameCount=frameCount,repeat=repeat,isEnded=isEnded,pause=pause,currentFrame=currentFrame,speed=speed,scale =scale,rotation=rotation,flip=flip)
        self.texture.transform(scale,rotation,flip)

    def render(self,x,y,scrollRatio =1):

        destination=(x,y)
        frame = int(self.currentFrame % self.frameCount)
        frameArea = (self.frameArea[0] * self.scale[0],self.frameArea[1] * self.scale[1])
        self.texture.drawFrame(source=frameArea,destination=destination,frame=frame,row=self.row,scrollRatio=scrollRatio)

class IO_SequenceAnimation(IO_Animation):
    def __init__(self,
                textures :list[IO_Texture] | list[None],
                id : str,
                frameCount : int,
                repeat : bool = True,
                isEnded : bool = False,
                pause : bool = False,
                speed=100,
                scale = None,
                rotation = None,
                flip = None):
        """

        """
        super().__init__(id,frameCount,repeat,isEnded,pause,speed,scale,rotation,flip)
        self.textures : list[IO_Texture] | list[None] = textures
        for texture in self.textures:
            texture.transform(scale,rotation,flip)

    def setAttrib(self,
                frameCount : int = None,
                repeat : bool = None,
                isEnded : bool  = None,
                pause : bool = None,
                currentFrame : int  = None,
                speed= 100,
                scale = None,
                rotation = None,
                flip = None):

        super().setAttrib(frameCount=frameCount,repeat=repeat,isEnded=isEnded,pause=pause,currentFrame=currentFrame,speed=speed,scaleX=scaleX,scaleY=scaleY)
        for texture in self.textures:
            texture.transform(scale,rotation,flip)

    def update(self,dt=0):
        if (self.repeat or self.isEnded == False) and self.pause == False:
            self.isEnded = False
            self.currentFrame = int((pygame.time.get_ticks() /self.speed) % self.frameCount)

        if self.repeat == False and self.currentFrame == (self.frameCount-1):
            self.isEnded = True
            self.currentFrame = (self.frameCount-1)

    def render(self,x,y,scrollRatio =1):
        destination = (x,y)
        self.textures[self.currentFrame].draw(destination=destination,scrollRatio=scrollRatio)

class IO_AnimationHandler(IO_Object):

    __instance = None
    def __init__(self):
        if IO_AnimationHandler.__instance != None:
            raise Exception("This class is a singleton!")
        else:
            IO_AnimationHandler.__instance = self

        self.animationMap = {}

    def parse(self,source):
        xmlRoot = IO_XmlHandler.getRoot(source)
        xmlspriteanimations = IO_XmlHandler.getChild(xmlRoot,"spriteanimations")
        xmlspriteanimation = xmlspriteanimations[0]
        xmlspriteanimations = IO_XmlHandler.getChild(xmlspriteanimation,"spriteanimation")

        for xmlspriteanimation in xmlspriteanimations:
            id = IO_XmlHandler.getAttribute(xmlspriteanimation,"id")
            texture = IO_XmlHandler.getAttribute(xmlspriteanimation,"texture")
            frameW = float(IO_XmlHandler.getAttribute(xmlspriteanimation,"frameW"))
            frameH = float(IO_XmlHandler.getAttribute(xmlspriteanimation,"frameH"))
            row = int(IO_XmlHandler.getAttribute(xmlspriteanimation,"row"))
            frameCount = int(IO_XmlHandler.getAttribute(xmlspriteanimation,"frameCount"))
            repeat = IO_XmlHandler.getAttribute(xmlspriteanimation,"repeat") == "True"
            speed = float(IO_XmlHandler.getAttribute(xmlspriteanimation,"speed"))
            scaleX = float(IO_XmlHandler.getAttribute(xmlspriteanimation,"scaleX"))
            scaleY = float(IO_XmlHandler.getAttribute(xmlspriteanimation,"scaleY"))
            angle = float(IO_XmlHandler.getAttribute(xmlspriteanimation,"angle"))
            flipX = IO_XmlHandler.getAttribute(xmlspriteanimation,"flipX") == "True"
            flipY = IO_XmlHandler.getAttribute(xmlspriteanimation,"flipY") == "True"

            texture =IO_TextureManager.getInstance().textureMap[texture]
            self.animationMap[id] = IO_SpriteAnimation(texture,id,(frameW,frameH),row,frameCount,repeat,speed=speed,scale= (scaleX,scaleY),rotation=angle,flip=(flipX,flipY))

        xmlsequenceanimations = IO_XmlHandler.getChild(xmlRoot,"sequenceanimations")
        xmlsequenceanimation = xmlsequenceanimations[0]
        xmlsequenceanimations = IO_XmlHandler.getChild(xmlsequenceanimation,"sequenceanimation")

        for xmlsequenceanimation in xmlsequenceanimations:
            id = IO_XmlHandler.getAttribute(xmlsequenceanimation,"id")
            repeat = IO_XmlHandler.getAttribute(xmlsequenceanimation,"repeat") == "True"
            speed = float(IO_XmlHandler.getAttribute(xmlsequenceanimation,"speed"))
            scaleX = float(IO_XmlHandler.getAttribute(xmlsequenceanimation,"scaleX"))
            scaleY = float(IO_XmlHandler.getAttribute(xmlsequenceanimation,"scaleY"))
            angle = float(IO_XmlHandler.getAttribute(xmlsequenceanimation,"angle"))
            flipX = IO_XmlHandler.getAttribute(xmlsequenceanimation,"flipX") == True
            flipY = IO_XmlHandler.getAttribute(xmlsequenceanimation,"flipY") == True

            xmltextures =IO_XmlHandler.getChild(xmlsequenceanimation,"texture")
            frameCount = len(xmltextures)
            textures = []
            for xmltexture in xmltextures:
                textureid = IO_XmlHandler.getAttribute(xmltexture,"id")

    @staticmethod
    def getInstance():
        if IO_AnimationHandler.__instance == None:
            IO_AnimationHandler()
        return IO_AnimationHandler.__instance


import sys
from collections import deque

M, N = map(int, sys.stdin.readline().split())

#print(M, N)

box = []

for _ in range(N):
    tomatoes = list(map(int, sys.stdin.readline().split()))
    box.append(tomatoes)
#print(box)

visit = [[0 for _ in range(M)] for _ in range(N)]

dx, dy = [-1, 1, 0, 0], [0, 0, 1, -1] #위 아래 오른쪽 왼쪽

def bfs():
    while queue:
        node = queue.popleft()
        for i in range(4):
            x2 = node[0] + dx[i]
            y2 = node[1] + dy[i]
            if (0<=x2<N and 0<=y2<M) and visit[x2][y2]==0:
                if box[x2][y2] == 0:
                    visit[x2][y2] = visit[node[0]][node[1]] + 1
                    queue.append([x2, y2])
    return visit

queue = deque() # 핵심. queue를 바깥으로 빼면서, 토마토가 익은거 동시에 큐에 넣어줌으로써, 동시에 카운트 가능!
for i in range(N):
    for j in range(M):
        if box[i][j] == 1:
            queue.append([i, j])
            visit[i][j] = 1
        elif box[i][j] == -1:
            visit[i][j] = -1

visit = bfs()

max1 = -5

'''
for v in visit:
    print(v)
'''

answer = True
for line in visit:
    if 0 in line:
        answer = False
    elif max(line) >= max1:
        max1 = max(line)

if answer:
    print(max1-1)
else:
    print(-1)


#!/usr/bin/env python3
"""
File: messagesWindow.py
Messages list window handling.
"""
from typing import Optional
import curses

import common
from SignalCliApi import SignalReceivedMessage, SignalSentMessage
from SignalCliApi.signalMessage import SignalMessage
from SignalCliApi.signalMessages import SignalMessages
from common import ROW, COL, TOP, LEFT, BOTTOM, RIGHT, STRINGS, Focus
from cursesFunctions import calc_attributes, add_title_to_win, add_ch
from messageItem import MessageItem
from themes import ThemeColours
from typeError import __type_error__
from verticalScrollBar import VerticalScrollBar
from window import Window

class MessagesWindow(Window):
    """
    Class to store the messages' window.
    """
    def __init__(self,
                 std_screen: curses.window,
                 size: tuple[int, int],
                 top_left: tuple[int, int],
                 theme: dict[str, dict[str, int | bool | str]]
                 ) -> None:
        """
        Initialize the messages window.
        :param size: tuple[int, int]: The size of the window: (ROWS, COLS).
        :param top_left: tuple[int, int]: The top left corner of the window: (ROW, COL).
        :param theme: dict[str, dict[str, int | bool | str]]: The current theme.
        """
        # Set title theme, and background character:
        title: str = STRINGS['titles']['messages']
        self._theme: dict[str, dict[str, int | bool | str]] = theme
        """Store the theme for future use."""
        self._bg_char: str = theme['backgroundChars']['messagesWin']
        """Store the background character."""

        # Set theme attrs and strings:
        window_attrs: int = calc_attributes(ThemeColours.MESSAGES_WIN, theme['msgsWin'])
        border_attrs: int = calc_attributes(ThemeColours.MESSAGES_WIN_BORDER, theme['msgsWinBorder'])
        border_focus_attrs: int = calc_attributes(ThemeColours.MESSAGES_WIN_FOCUS_BORDER, theme['msgsWinFBorder'])
        border_chars: dict[str, str] = theme['msgsWinBorderChars']
        border_focus_chars: dict[str, str] = theme['msgsWinFBorderChars']
        title_attrs: int = calc_attributes(ThemeColours.MESSAGES_WIN_TITLE, theme['msgsWinTitle'])
        title_focus_attrs: int = calc_attributes(ThemeColours.MESSAGES_WIN_FOCUS_TITLE, theme['msgsWinFTitle'])
        title_chars: dict[str, str] = theme['msgsWinTitleChars']
        title_focus_chars: dict[str, str] = theme['msgsWinFTitleChars']

        # Create the curses window:
        window = curses.newwin(size[ROW], size[COL], top_left[ROW], top_left[COL])

        # Run Super:
        Window.__init__(self, std_screen, window, title, top_left, window_attrs, border_attrs, border_focus_attrs,
                        border_chars, border_focus_chars, title_attrs, title_focus_attrs, title_chars,
                        title_focus_chars, self._bg_char, Focus.MESSAGES, 'left')

        # Set this window as always visible:
        self.always_visible = True
        self.is_static_size = False

        # Create the vertical scroll bar:
        self._v_scrollbar: VerticalScrollBar = VerticalScrollBar(
            height=self.height,
            top_left=(self.real_top_left[common.TOP] + 1, self.real_bottom_right[common.RIGHT] - 1),
            theme=theme
        )
        """The vertical scroll bar object."""
        self._v_scrollbar.is_visible = True

        # Create the conversation var:
        self._conversation: list[SignalSentMessage | SignalReceivedMessage] = []
        """The conversation we build the pad from."""
        self.__update_conversation__()

        # Create the message items for the messages in the conversation:
        self._message_item_list: list[MessageItem] = []
        """The message item list for the conversation."""
        self.__update_message_items__()

        # Create the pad:
        self._pad: Optional[curses.window] = None
        """The pad we draw on."""
        self._pad_out_top_left: tuple[int, int] = (0, 0)
        """The top left of the pad to start the output from."""
        self.__create_pad__()

        return

    def __update_conversation__(self) -> None:
        if common.CURRENT_RECIPIENT is None:
            self._conversation = []
            return

        def _sort_(item: SignalMessage) -> int:
            return item.timestamp.timestamp

        messages: SignalMessages = common.CURRENT_ACCOUNT.messages
        self._conversation = messages.get_conversation(common.CURRENT_RECIPIENT)
        self._conversation.sort(key=_sort_, reverse=False)
        return

    def __update_message_items__(self) -> None:
        self._message_item_list = []
        for message in self._conversation:
            message_item = MessageItem(message=message,
                                       pad_width=self.pad_width,
                                       theme=self._theme
                                       )
            self._message_item_list.append(message_item)

    def __clear_pad__(self) -> None:
        for row in range(0, self.pad_height):
            for col in range(0, self.pad_width):
                add_ch(self._pad, self._bg_char, self._bg_attrs, row, col)
        return

    def __create_pad__(self):
        self._pad = curses.newpad(self.pad_height, self.pad_width)
        self.__clear_pad__()
        item_top = 0
        for message_item in self._message_item_list:
            message_item.pad = self._pad
            message_item.top = item_top
            message_item.redraw()
            item_top += message_item.height
        self.pad_out_bottom = self.pad_bottom
        return

    #############################################
    # External methods:
    #############################################
    def recipient_changed(self) -> None:
        self.__update_conversation__()
        self.__update_message_items__()
        self.__create_pad__()
        return

    def message_received(self) -> None:
        self.__update_conversation__()
        self.__update_message_items__()
        self.__create_pad__()
        return

    #############################################
    # External overrides:
    #############################################
    def resize(self,
               size: Optional[tuple[int, int]],
               real_top_left: Optional[tuple[int, int]],
               do_resize: bool = True,
               do_move: bool = True,
               ) -> None:
        super().resize(size, real_top_left, do_resize, do_move)
        self._v_scrollbar.resize(self.height, (self.real_top_left[TOP] + 1, self.real_bottom_right[RIGHT] - 1))
        self.__update_message_items__()
        self.__create_pad__()
        return

    def redraw(self) -> None:
        super().redraw()
        if common.CURRENT_RECIPIENT is None:
            recipient_text = 'None'
        else:
            recipient_text = common.CURRENT_RECIPIENT.get_display_name()
        recipient_text = "Thread: " + recipient_text
        add_title_to_win(self._window, recipient_text, self.border_attrs, self.title_attrs, self.title_chars['lead'],
                         self.title_chars['tail'], 'right')
        if self.pad_height > self.display_height:
            self._v_scrollbar.is_enabled = True
        else:
            self._v_scrollbar.is_enabled = False
        self._v_scrollbar.redraw()

        # Redraw the pad:
        self.__clear_pad__()
        for message_item in self._message_item_list:
            message_item.redraw()

        self._window.noutrefresh()
        self._pad.noutrefresh(self.pad_out_top, self.pad_out_left,
                              self.display_top, self.display_left,
                              self.display_bottom, self.display_right)
        return

##################################
# Properties:
##################################

    #############
    # Display output:
    @property
    def display_top_left(self):
        return self.real_top + 1, self.real_left + 1

    @property
    def display_top(self):
        return self.real_top + 1

    @property
    def display_left(self):
        return self.real_left + 1

    @property
    def display_width(self):
        return self.width - 1

    @property
    def display_height(self):
        return self.height

    @property
    def display_bottom_right(self):
        return self.display_top + self.display_height - 1, self.display_left + self.display_width - 1

    @property
    def display_bottom(self):
        return self.display_top + self.display_height - 1

    @property
    def display_right(self):
        return self.display_left + self.display_width - 1

    ##############
    # Pad properties:
    @property
    def pad_top_left(self):
        return 0, 0

    @property
    def pad_top(self):
        return 0

    @property
    def pad_left(self):
        return 0

    @property
    def pad_width(self):
        return self.display_width

    @property
    def pad_height(self):
        pad_height = 0
        for message_item in self._message_item_list:
            pad_height += message_item.height
        if pad_height < self.display_height:
            pad_height = self.display_height
        return pad_height

    @property
    def pad_bottom_right(self):
        return self.pad_top + self.pad_height - 1, self.pad_left + self.pad_width - 1

    @property
    def pad_bottom(self):
        return self.pad_top + self.pad_height - 1

    @property
    def pad_right(self):
        return self.pad_left + self.pad_width - 1

    ##############
    # pad output size, top_left, etc:
    @property
    def pad_out_size(self):
        return self.display_height, self.display_width

    @property
    def pad_out_height(self):
        return self.display_height

    @property
    def pad_out_width(self):
        return self.display_width

    @property
    def pad_out_top_left(self):
        return self._pad_out_top_left

    @pad_out_top_left.setter
    def pad_out_top_left(self, value):
        if not common.__type_check_position_or_size__(value):
            __type_error__("value", 'tuple[int, int]', value)
        self._pad_out_top_left = value

    @property
    def pad_out_top(self):
        return self._pad_out_top_left[TOP]

    @pad_out_top.setter
    def pad_out_top(self, value):
        if not isinstance(value, int):
            __type_error__('value', 'int', value)
        self._pad_out_top_left = (value, self._pad_out_top_left[LEFT])
        return

    @property
    def pad_out_left(self):
        return self._pad_out_top_left[LEFT]

    @pad_out_left.setter
    def pad_out_left(self, value: int):
        if not isinstance(value, int):
            __type_error__('value', 'int', value)
        self._pad_out_top_left = (self.pad_out_top_left[TOP], value)
        return

    @property
    def pad_out_bottom_right(self) -> tuple[int, int]:
        return self.pad_out_top + self.pad_out_height - 1, self.pad_out_left + self.pad_out_width - 1

    @pad_out_bottom_right.setter
    def pad_out_bottom_right(self, value: tuple[int, int]) -> None:
        if not common.__type_check_position_or_size__(value):
            __type_error__('value', 'tuple[int, int]', value)
        top = value[BOTTOM] - self.pad_out_height + 1
        if top < 0:
            top = 0
        left = value[RIGHT] - self.pad_out_width + 1
        if left < 0:
            left = 0
        self._pad_out_top_left = (top, left)

    @property
    def pad_out_bottom(self):
        return self.pad_out_top + self.pad_out_height - 1

    @pad_out_bottom.setter
    def pad_out_bottom(self, value):
        if not isinstance(value, int):
            __type_error__('value', 'int', value)
        top = value - self.pad_out_height + 1
        if top < 0:
            top = 0
        self._pad_out_top_left = (top, self._pad_out_top_left[LEFT])
        return

    @property
    def pad_out_right(self):
        return self.pad_out_left + self.pad_out_width - 1

    @pad_out_right.setter
    def pad_out_right(self, value):
        if not isinstance(value, int):
            __type_error__('value', 'int', value)
        left = value - self.pad_out_width + 1
        if left < 0:
            left = 0
        self._pad_out_top_left = (self._pad_out_top_left[TOP], left)
        return

#############################################
# Property hooks:
#############################################
    def __is_focused_hook__(self, is_get: bool, value: bool) -> Optional[bool]:
        if not is_get and value:
            for message in self._conversation:
                if not message.is_read:
                    try:
                        message.mark_read()
                    except TypeError as e:
                        common.out_error("mark read failed for message type:")
                        common.out_debug(str(type(message)))
                        raise TypeError(str(type(message)))
        return None


import streamlit as st
import pandas_datareader as datas
# Machine learning
from sklearn.svm import SVC
from sklearn.metrics import accuracy_score

# For data manipulation
import pandas as pd
import numpy as np

# To plot
import matplotlib.pyplot as plt
plt.style.use('seaborn-darkgrid')

# To ignore warnings
import warnings
warnings.filterwarnings("ignore")

# Libreria de yahoo financie
import yfinance as yf

def app():

    st.title("Modelo SVM")
    st.title("Predicción de tendencia de acciones del Mes usando SVM")
    start = st.date_input(
        "Inicio (Start)", value=pd.to_datetime("2022-12-01")
    )  # 2021-01-01
    end = st.date_input("Fin (End)", value=pd.to_datetime("today"))
    user_input = st.text_input("Introducir cotización bursátil", "NFLX")
    # df = datas.DataReader(user_input, "yahoo", start, end)
    df = yf.download(user_input, start, end)
    df.index=df.index.strftime('%Y-%m-%d')
    df.reset_index(inplace=True)

    # Describiendo los datos
    st.subheader("Datos del Diciembre - 2022")
    st.write(df)
    st.subheader("Descripción de la dataset")
    st.write(df.describe())

    # Visualizaciones
    st.subheader("Closing Price vs Time")
    fig = plt.figure(figsize=(12, 6))
    plt.plot(df.Close)
    st.pyplot(fig)
    # se obtiene el numero de filas y columnas
    df.shape
    st.subheader("filas y columnas")
    st.subheader(df.shape)

    actual_prices = df.tail(1)
    actual_prices
    st.subheader(actual_prices)

    # Crear variables predictoras
    df['Open-Close'] = df.Open - df.Close
    df['High-Low'] = df.High - df.Low

    # Almacenar todas las variables predictoras en una variable X
    X = df[['Open-Close', 'High-Low']]

    # Variables objetivo
    y = np.where(df['Close'].shift(-1) > df['Close'], 1, 0)

    #Dividiendo los datos para entrenamiento y prueba
    split_percentage = 0.8
    split = int(split_percentage*len(df))

    # Train data set
    X_train = X[:split]
    y_train = y[:split]

    # Test data set
    X_test = X[split:]
    y_test = y[split:]

    # Support vector classifier
    cls = SVC().fit(X_train, y_train)

    # Vamos a predecir la señal (compra o venta) utilizando la función cls.predict().
    df['Predicted_Signal'] = cls.predict(X)

    # Calcular daily Return
    df['Return'] = df.Close.pct_change()

    # Calcular Strategy Return
    df['Strategy_Return'] = df.Return *df.Predicted_Signal.shift(1)

    # Calculate Cumulutive returns
    df['Cum_Ret'] = df['Return'].cumsum()

    # Plot Strategy Cumulative returns
    df['Cum_Strategy'] = df['Strategy_Return'].cumsum()

    # Graficamos Plot Strategy vs Original Returns
    st.subheader("Plot Strategy vs Original Retuns")
    fig1 = plt.figure(figsize=(16, 8))
    plt.plot(df['Cum_Ret'],color='red')
    plt.plot(df['Cum_Strategy'],color='blue')
    st.pyplot(fig1)


import json
import os
import os.path
import shutil

from PIL import Image

import generators

class _Profile(object):
    def __init__(self, out_path_mod, rescale_factor):
        self.out_path_mod = out_path_mod
        self.rescale_factor = rescale_factor

    def modify_path(self, path):
        if self.out_path_mod == '1x':
            (root_path, ext_path) = os.path.splitext(path)
            return '%s%s' % (root_path, '.png')
        else:
            (root_path, ext_path) = os.path.splitext(path)
            return '%s@%s%s' % (root_path, self.out_path_mod, '.png')

_PROFILES = {
    '1x': _Profile('1x', 29.0 / 60.0),
    '2x': _Profile('2x', 40.0 / 60.0),
    '3x': _Profile('3x', 60.0 / 60.0)
    }

_MODIFIER_FOR_USAGE = {
    'appicon': 'appiconset',
    'launcher': 'launchimage',
    'asset': 'imageset'
    }

class _PngHandler(generators._Handler):
    def __init__(self):
        super(_PngHandler, self).__init__('.png')

    def __call__(self, output_dir_path, g_name, g_config, path):
        (g_name_base, g_name_ext) = os.path.splitext(g_name)
        dir_path = os.path.join(output_dir_path,
            '%s.%s' % (g_name_base, _MODIFIER_FOR_USAGE[g_config['usage']]))
        base_out_path = os.path.join(dir_path, g_name)
        os.mkdir(dir_path)

        metadata = {
            'images': [],
            'info': {
                'version': 1,
                'author': 'xcode' # Should be the assets pipeline.
                }
            }

        for p_name, profile in _PROFILES.iteritems():
            out_path = profile.modify_path(base_out_path)
            image = Image.open(path)
            desired_width = int(image.size[0] * profile.rescale_factor)
            image_resized = generators._resize_to_width(image, desired_width)
            image_resized[0].save(out_path)
            metadata['images'].append({
                    'idiom': 'universal',
                    'scale': profile.out_path_mod,
                    'filename': os.path.basename(out_path)
                    })

        with open(os.path.join(dir_path, 'Contents.json'), 'w') as contents_file:
            contents_file.write(json.dumps(metadata))

class _GifHandler(generators._Handler):
    def __init__(self):
        super(_GifHandler, self).__init__('.gif')

    def __call__(self, output_dir_path, g_name, g_config, path):
        (g_name_base, g_name_ext) = os.path.splitext(g_name)
        dir_path_pattern = os.path.join(output_dir_path,
            '%s%%02d.imageset' % g_name_base)
        g_name_pattern = '%s%%02d%s' % (g_name_base, g_name_ext)
        base_out_path_pattern = os.path.join(dir_path_pattern, g_name_pattern)

        fr = 0
        image = Image.open(path)
        while True:
            try:
                image.seek(fr)
            except EOFError:
                break

            dir_path = dir_path_pattern % fr
            os.mkdir(dir_path)
            metadata = {
                'images': [],
                'info': {
                    'version': 1,
                    'author': 'xcode' # Should be the assets pipeline.
                    }
                }

            for g_name, profile in _PROFILES.iteritems():
                out_path = profile.modify_path(base_out_path_pattern % (fr, fr))
                frame = image.copy()
                desired_width = int(frame.size[0] * profile.rescale_factor)
                frame_resized = generators._resize_to_width(image, desired_width)
                frame_resized[0].save(out_path)
                metadata['images'].append({
                        'idiom': 'universal',
                        'scale': profile.out_path_mod,
                        'filename': os.path.basename(out_path)
                        })

                with open(os.path.join(dir_path, 'Contents.json'), 'w') as contents_file:
                    contents_file.write(json.dumps(metadata))

            fr = fr + 1

_HANDLERS = {
    '.png': _PngHandler(),
    '.gif': _GifHandler()
}

class Generator(generators.BaseGenerator):
    def __init__(self, output_dir_path):
        super(Generator, self).__init__(output_dir_path)

    def __enter__(self):
        # Recreate the directory for graphics assets. In iOS, this directory is completely under
        # the application's control, so we can just recreate it without issues at this point.
        generators._recreate_directory(self.output_dir_path)

        return self

    def generate(self, g_name, g_config):
        path = g_config['path']
        path_type = os.path.splitext(path)[1]
        _HANDLERS[path_type](self.output_dir_path, g_name, g_config, path)


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

import os
from setuptools import setup, find_packages

version = '3.0.2.dev0'

tests_require = ['zope.testing', 'Products.PloneTestCase']

setup(name='cciaa.modulistica',
      version=version,
      description="An additional view for Plone folders, to improve"
                  " management of repositories of files",
      long_description=open("README.rst").read() + "\n" + open(
          os.path.join("docs", "HISTORY.txt")).read(),
      classifiers=[
        'Framework :: Plone',
        'Framework :: Plone :: 4.0',
        'Framework :: Plone :: 4.1',
        'Framework :: Plone :: 4.2',
        'Framework :: Plone :: 4.3',
        'Framework :: Plone :: 5.0',
        'Framework :: Plone :: 5.1',
        'Topic :: Software Development :: Libraries :: Python Modules',
        'License :: OSI Approved :: GNU General Public License (GPL)',
        ],
      keywords='plone plonegov form file',
      author='RedTurtle Technology',
      author_email='sviluppoplone@redturtle.it',
      url='http://plone.org/products/cciaa.modulistica',
      license='GPL',
      packages=find_packages(exclude=['ez_setup']),
      namespace_packages=['cciaa', ],
      include_package_data=True,
      zip_safe=False,
      install_requires=[
          'setuptools',
          'Products.CMFPlone',
      ],
      tests_require=tests_require,
      extras_require=dict(test=tests_require),
      entry_points="""
      [z3c.autoinclude.plugin]
      target = plone
      """,
      )


import numpy as np
import os
import cv2

filename = 'video.avi'
frames_per_second = 24.0
my_res = '700p'

# Set resolution for the video capture
# Function adapted from https://kirr.co/0l6qmh
def change_res(cap, width, height):
    cap.set(3, width)
    cap.set(4, height)

# Standard Video Dimensions Sizes
STD_DIMENSIONS =  {
    "480p": (640, 480),
    "720p": (1280, 720),
    "1080p": (1920, 1080),
    "4k": (3840, 2160),
}

# grab resolution dimensions and set video capture to it.
def get_dims(cap, res='1080p'):
    width, height = STD_DIMENSIONS["480p"]#if params of resolution is error then it default set 480p res

    if res in STD_DIMENSIONS:
        width,height = STD_DIMENSIONS[res]
    ## change the current caputre device
    ## to the resulting resolution
    change_res(cap, width, height)
    return width, height

# Video Encoding, might require additional installs
# Type of Codes: http://www.fourcc.org/codecs.php
VIDEO_TYPE = {
    'avi': cv2.VideoWriter_fourcc(*'XVID'),
    #'mp4': cv2.VideoWriter_fourcc(*'H264'),
    'mp4': cv2.VideoWriter_fourcc(*'XVID'),
}

def get_video_type(filename):
    filename, ext = os.path.splitext(filename)#it splits video.avi to video and avi and assign to var
    print(filename)

    if ext in VIDEO_TYPE:
      return  VIDEO_TYPE[ext]

    return VIDEO_TYPE['avi']

cap = cv2.VideoCapture(0)
dims = get_dims(cap, res=my_res)
video_type_cv2 = get_video_type(filename)

out = cv2.VideoWriter(filename,video_type_cv2,frames_per_second,dims)#instead of dims i can also write width height
# dims = get_dims(cap,res=my_res)

while True:
    ret, frame = cap.read()
    out.write(frame)#save video to video.avi file in project folder
    cv2.imshow('frame',frame)

    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

cap.release()
out.release()
cv2.destroyAllWindows()


import tensorflow as tf
import json
import os
import custom_function as cf
import wav
import numpy as np
import denoise_wavenet_condition_test as DWC
import time
import datetime
import math
import make_dataset_test as md

# tf version check
tf_version = cf.get_tf_version()

# prevent GPU overflow
cf.tf_gpu_active_alloc()

# read config file
with open("config.json", "r") as f_json:
    config = json.load(f_json)

previous_size = config['previous_size']
frame_size = config["frame_size"]
future_size = config["future_size"]
shift_size = config["shift_size"]
window_type = config["window_type"]
dilation = config["dilation"]
num_of_speaker = config["num_of_speaker"]
num_of_noise = config["num_of_noise"]
if num_of_speaker < 2:
    num_of_speaker = 0
if num_of_noise < 2:
    num_of_noise = 0
max_condition = num_of_speaker + num_of_noise
if max_condition == 0:
    raise Exception("E: num_of_speaker and num_of_noise can't 0 same time in train_cond.py")

batch_size = 1
epochs = 1
learning_rate = config["learning_rate"]
default_float = config["default_float"]

train_source_path = config["train_source_path"]
train_target_path = config["train_target_path"]

load_check_point_name = config["load_check_point_name"]
save_check_point_name = config["save_check_point_name"]
save_check_point_period = config["save_check_point_period"]

# multi gpu init
# strategy = tf.distribute.experimental.CentralStorageStrategy()
strategy = tf.distribute.MirroredStrategy()

with strategy.scope():
    # make dataset
    train_source_cut_list, train_source_condition_list, train_target_cut_list, number_of_total_frame = md.make_dataset(train_source_path, train_target_path, batch_size,
                                                                 previous_size, frame_size, future_size, num_of_speaker,
                                                                 num_of_noise, shift_size, window_type, shuffle=True)
    train_dataset = tf.data.Dataset.from_tensor_slices(
        (train_source_cut_list, train_source_condition_list, train_target_cut_list)).shuffle(number_of_total_frame).batch(batch_size)
    dist_dataset_train = strategy.experimental_distribute_dataset(dataset=train_dataset)

    # make model
    model = DWC.DenoiseWavenetCondition(dilation, previous_size+frame_size+future_size, max_condition)
    loss_object = tf.keras.losses.MeanAbsoluteError(reduction=tf.keras.losses.Reduction.NONE)
    optimizer = tf.keras.optimizers.Adam(learning_rate=config['learning_rate'])
    train_loss = tf.keras.metrics.Mean(name='train_loss')

# train function
@tf.function
def train_step(dist_inputs):
    def step_fn(inputs):
        x, cond, y = inputs
        cond = tf.reshape(cond, [-1, max_condition, 1])

        with tf.GradientTape() as tape:
            condition_list = model(cond)
        cond = tf.squeeze(cond)
        return cond, condition_list

    if tf_version[1] > 2:
        cond, condition_list = strategy.run(step_fn, args=(dist_inputs,))
    else:
        cond, condition_list = strategy.experimental_run_v2(step_fn, args=(dist_inputs,))
    return cond, condition_list
# train run
with strategy.scope():
    # load model
    if load_check_point_name != "":
        saved_epoch = int(load_check_point_name.split('_')[-1])
        model.load_weights('{}/checkpoint/{}/data.ckpt'.format(cf.load_directory(), load_check_point_name))

    for epoch in range(saved_epoch, saved_epoch+epochs):
        i = 0
        for inputs in dist_dataset_train:
            cond, condition_list = train_step(inputs)
            print(cond.numpy(), np.array(condition_list))
            i += 1


import pygame

class Button:
    def __init__(self, image, center, button_press_command, screen_size, scale_factor, call, scene=None, list_to_append=None):
        self.screen_size = screen_size
        self.image = pygame.image.load(image)
        self.image = pygame.transform.scale(self.image, (round(screen_size[0] / scale_factor[0]), round(screen_size[1] / scale_factor[1])))
        self.center = center
        if scene is not None:
            self.scene = scene
            scene.append(self)
        self.rect = self.image.get_rect()
        self.rect = pygame.Rect(self.center[0] - (self.rect[2] // 2), self.center[1] - (self.rect[3] // 2), self.rect[2], self.rect[3])

        # Making a hover over version of itself (lighter and slightly bigger)
        self.image_lighter = self.image.copy()
        self.image_lighter = brighten_image(self.image_lighter, 20)
        self.image_lighter = pygame.transform.scale(self.image_lighter, (int(self.rect[2] * 1.2), int(self.rect[3] * 1.2)))

        # Making a press down version of itself (darker)
        self.image_darker = self.image.copy()
        self.image_darker = darken_image(self.image_darker, 50)

        # Start by displaying default version of itself
        self.image_to_display = self.image
        self.is_hovering = False
        self.is_pressed_down = False
        self.is_pressed_up = False
        self.button_press_command = button_press_command
        self.call_events = call
        self.is_active = False
        if list_to_append is not None:
            list_to_append.append(self)

    def __repr__(self):
        return "Button: " + str(self.button_press_command)

    def state_check(self):
        mouse_pos = pygame.mouse.get_pos()
        if self.is_hovering:
            self.is_hovering = False

        if self.rect[0] + self.rect[2] > mouse_pos[0] > self.rect[0] and self.rect[1] + self.rect[3] > mouse_pos[
            1] > self.rect[1] and not self.is_hovering and self.is_active:
            self.is_hovering = True

        if self.is_pressed_up:
            self.button_press_command()
            self.is_pressed_up = False

        if self.is_hovering and not self.is_pressed_down:
            self.image_to_display = self.image_lighter
        elif self.is_pressed_down and self.is_hovering:
            self.image_to_display = self.image_darker
        else:
            self.image_to_display = self.image

        for event in self.call_events:
            if not event:
                self.is_active = False
        for event in self.call_events:
            if event:
                self.is_active = True

    def get_center_cor(self):
        if self.is_hovering and not self.is_pressed_down:
            return self.center[0] - ((self.rect[2] * 1.2) // 2), self.center[1] - ((self.rect[3] * 1.2) // 2)
        elif not self.is_hovering or self.is_pressed_down:
            return self.center[0] - (self.rect[2] // 2), self.center[1] - (self.rect[3] // 2)

# Function that brightens image by certain amount
def brighten_image(image, brighten):
    image.fill((brighten, brighten, brighten), special_flags=pygame.BLEND_RGB_ADD)
    return image

# Function that darkens image by certain amount
def darken_image(image, darken):
    image.fill((darken, darken, darken), special_flags=pygame.BLEND_RGB_SUB)
    return image


import subprocess
import time
from typing import Dict

from django.utils import timezone

import pandas as pd

from data_refinery_common.enums import PipelineEnum
from data_refinery_common.logging import get_and_configure_logger
from data_refinery_common.models import (
    ComputationalResult,
    ComputationalResultAnnotation,
    ComputedFile,
    Experiment,
    Pipeline,
)
from data_refinery_common.utils import queryset_iterator
from data_refinery_workers.processors import smashing_utils, utils

logger = get_and_configure_logger(__name__)

def _prepare_input(job_context: Dict) -> Dict:

    # We're going to use the smasher outside of the smasher.
    # I'm not crazy about this yet. Maybe refactor later,
    # but I need the data now.
    job_context = smashing_utils.prepare_files(job_context)

    # work_dir is already created by smasher._prepare_files
    outfile_base = job_context["work_dir"] + str(time.time()).split(".")[0]
    job_context["target_file"] = outfile_base + "_target.tsv"

    return job_context

def _build_qn_target(job_context: Dict) -> Dict:
    """Iteratively creates a QN target file, method described here:
    https://github.com/AlexsLemonade/refinebio/pull/1013
    """
    job_context["time_start"] = timezone.now()

    # Get the gene list from the first input
    (computed_file, _) = job_context["input_files"]["ALL"][0]
    computed_file_path = computed_file.get_synced_file_path()
    geneset_target_frame = smashing_utils._load_and_sanitize_file(computed_file_path)

    # Get the geneset
    geneset = set(geneset_target_frame.index.values)

    # Sequentially build the target
    sum_frame_input = {"index": list(geneset), "sum": [0 for value in geneset]}
    sum_frame = pd.DataFrame(data=sum_frame_input)
    sum_frame = sum_frame.set_index("index")

    # Read and sum all of the inputs
    num_valid_inputs = 0
    for file, sample in job_context["input_files"]["ALL"]:
        try:
            input_filepath = file.get_synced_file_path()
            input_frame = smashing_utils._load_and_sanitize_file(input_filepath)
        except Exception:
            logger.warn(
                "No file loaded for input file",
                exc_info=1,
                bad_file=file,
                num_valid_inputs_so_far=num_valid_inputs,
            )
            continue

        # If this input doesn't have the same geneset, we don't want it!
        if set(input_frame.index.values) != geneset:
            logger.warn(
                "Input frame doesn't match target geneset, skipping!",
                bad_file=file,
                target_geneset_len=len(geneset),
                bad_geneset_len=len(input_frame.index.values),
                geneset_difference=list(geneset ^ set(input_frame.index.values))[:3],
                num_valid_inputs_so_far=num_valid_inputs,
            )
            continue

        # We don't want to build QNs that have Nulls in them, so
        # filter out any samples that still have null genes at this
        # point.
        num_nulls = input_frame.isnull().sum(axis=0)[0]
        if num_nulls != 0:
            logger.warn(
                "Input frame contains NA values, skipping!",
                bad_file=file,
                number_of_NAs=num_nulls,
                num_valid_inputs_so_far=num_valid_inputs,
            )
            continue

        # Sort the input
        sample_name = list(input_frame.columns.values)[0]
        expressions = input_frame.sort_values(sample_name)

        # Add the sorted input to the sum frame
        sum_frame["sum"] = sum_frame["sum"] + expressions[sample_name].values

        # We'll divide by this later
        num_valid_inputs = num_valid_inputs + 1

    # Divide our summation by the number of inputs and save the resulting object and metadata
    sum_frame["sum"] = sum_frame["sum"] / num_valid_inputs
    job_context["time_end"] = timezone.now()
    job_context["sum_frame"] = sum_frame
    job_context["num_valid_inputs"] = num_valid_inputs
    job_context["geneset"] = list(geneset)

    sum_frame.to_csv(
        job_context["target_file"], index=False, header=False, sep="\t", encoding="utf-8"
    )
    job_context["formatted_command"] = "qn_reference.py"

    return job_context

def _create_result_objects(job_context: Dict) -> Dict:
    if not job_context["create_results"]:
        return job_context

    result = ComputationalResult()
    result.commands.append(" ".join(job_context["formatted_command"]))
    result.is_ccdl = True
    result.is_public = True
    result.time_start = job_context["time_start"]
    result.time_end = job_context["time_end"]
    try:
        processor_key = "QN_REFERENCE"
        result.processor = utils.find_processor(processor_key)
    except Exception as e:
        return utils.handle_processor_exception(job_context, processor_key, e)
    result.save()

    computed_file = ComputedFile()
    computed_file.absolute_file_path = job_context["target_file"]
    computed_file.filename = job_context["target_file"].split("/")[-1]
    computed_file.calculate_sha1()
    computed_file.calculate_size()
    computed_file.is_smashable = False
    computed_file.is_qn_target = True
    computed_file.result = result
    computed_file.save()

    annotation = ComputationalResultAnnotation()
    annotation.result = result
    annotation.data = {
        "organism_id": job_context["samples"]["ALL"][0].organism_id,
        "is_qn": True,
        "platform_accession_code": job_context["samples"]["ALL"][0].platform_accession_code,
        "samples": [sample.accession_code for sample in job_context["samples"]["ALL"]],
        "geneset": str(job_context["geneset"]),
        "num_valid_inputs": job_context["num_valid_inputs"],
    }
    annotation.save()

    job_context["result"] = result
    job_context["computed_files"] = [computed_file]
    job_context["annotation"] = annotation
    job_context["success"] = True
    return job_context

def _update_caches(job_context: Dict) -> Dict:
    """Experiments have a cached value with the number of samples that have QN targets
    generated, this value should be updated after generating new QN targets."""
    if not job_context["create_results"]:
        # No new results were created, so there's no point in updating the cache
        return job_context

    organism = job_context["samples"]["ALL"][0].organism

    if job_context["result"]:
        # Associate the organism with the latest qn target that was generated for it
        organism.qn_target = job_context["result"]
        organism.save()

    unique_experiments = Experiment.objects.all().filter(organism=organism).distinct()

    for experiment in queryset_iterator(unique_experiments):
        experiment.update_num_samples()

    return job_context

def create_qn_reference(job_id: int, create_results=True) -> None:
    pipeline = Pipeline(name=PipelineEnum.QN_REFERENCE.value)
    job_context = utils.run_pipeline(
        {"job_id": job_id, "pipeline": pipeline, "create_results": create_results},
        [
            utils.start_job,
            _prepare_input,
            _build_qn_target,
            _create_result_objects,
            _update_caches,
            utils.end_job,
        ],
    )
    return job_context


from genmesh import genmesh
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

# msh_file = 'mesh/3d_sphere_unit.msh'
msh_file = 'mesh/3d_sphere_forloop_big.msh'
mesh = genmesh(P_bdry=None, meshsize=None, msh_file =msh_file, dimension=3, mesh_optimize=True)

# mesh.plot(plot_node_text=False, highlight_bdry_nodes=False, dotsize=20)

fig = plt.figure()
# ax = fig.add_subplot(111, projection='3d')
ax = Axes3D(fig)
Pos = mesh.pos
plt.scatter(Pos[:,0], Pos[:,1], Pos[:,2])
plt.show()


# -*- coding: utf-8 -*-
"""
Created on Thu Mar 12 09:50:59 2020
@author: EmrahSariboz

"""

from sklearn import datasets
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
import argparse
import pandas as pd
import AdaBoostC
import os
import sys
import timeit
import RandomFC
import BaggingC
from sklearn.svm import SVC

if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument("classifier", help = "Name of the Classifier")
    parser.add_argument("datasetPassed", help = "Dataset Location")
    args = parser.parse_args()

    classifierName = str(args.classifier)
    dataset = str(args.datasetPassed)

    #pass the dataset varible to if statement
    #example: if (dataset == dataset)
    isfile = os.path.isfile(dataset)

    #Check the existence of dataset and split it
    if isfile:
        df = pd.read_csv(dataset)
        X = df.iloc[:, 0:(df.shape[1]-1)]
        y = df.iloc[:, -1]
        X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=1)
    else:
        if dataset == "digit":
            #Loading the digits dataset
            digist_dataset = datasets.load_digits()
            X = digist_dataset.data
            y = digist_dataset.target
            X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.2, random_state = 0)
        else:
            print("\nThe provided dataset does not exist!")
            sys.exit()

    #Comparison
    #comparison = SVC(kernel = 'rbf')
    #comparison.fit(X_train, y_train)
    #print(accuracy_score(y_test, comparison.predict(X_test)))

    #If else statemets for each model
    if classifierName == "randomForest":
        start = timeit.default_timer()
        classifier =  RandomFC.RandomForest(X_train, y_train)
        classifier.fit(X_train, y_train)
        prediction = classifier.predict(X_test)
        prediction_training = classifier.predict(X_train);
        stop = timeit.default_timer()
        print('The total runtime of this classifier on ', dataset, ' dataset is: ', stop-start , ' seconds')
        print('\nThe accuracy of random forest classifier on test dataset is: ', accuracy_score(y_test, prediction))
        print('\nThe accuracy of random forest classifier on training dataset is: ', accuracy_score(y_train, prediction_training))
    elif classifierName == "bagging":
        start = timeit.default_timer()
        classifier =  BaggingC.BaggingEns(X_train, y_train)
        classifier.fit(X_train, y_train)
        prediction = classifier.predict(X_test)
        prediction_training = classifier.predict(X_train);
        stop = timeit.default_timer()
        print('The total runtime of this classifier is: ', stop-start , ' seconds')
        print('\nThe accuracy of bagging classifier on test dataset is: ', accuracy_score(y_test, prediction))
        print('\nThe accuracy of bagging classifier on training dataset is: ', accuracy_score(y_train, prediction_training))
    elif classifierName == "adaboost":
        start = timeit.default_timer()
        classifier =  AdaBoostC.AdaBoostEns(X_train, y_train)
        classifier.fit(X_train, y_train)
        prediction = classifier.predict(X_test)
        prediction_training = classifier.predict(X_train);
        stop = timeit.default_timer()
        print('The total runtime of this classifier is: ', stop-start , ' seconds')
        print('\nThe accuracy of adaboost classifier on test dataset is: ', accuracy_score(y_test, prediction))
        print('\nThe accuracy of adaboost classifier on training dataset is: ', accuracy_score(y_train, prediction_training))
    else:
        print('Wrong parameter(s)')

Selected Homework/Ensemble Method Analysis/main.py