from django import forms
from django.contrib.auth import get_user_model
from django.contrib.auth.forms import UserCreationForm
from django.core.exceptions import ValidationError

from newspaper.models import Newspaper, Redactor

class NewspaperForm(forms.ModelForm):
    publishers = forms.ModelMultipleChoiceField(
        queryset=get_user_model().objects.all(),
        widget=forms.CheckboxSelectMultiple,
    )

    class Meta:
        model = Newspaper
        fields = "__all__"

class RedactorCreationForm(UserCreationForm):
    class Meta(UserCreationForm.Meta):
        model = Redactor
        fields = UserCreationForm.Meta.fields + (
            "years_of_experience",
            "first_name",
            "last_name",
        )

    def clean_experience(self):
        return validate_experience(self.cleaned_data["years_of_experience"])

class RedactorExperienceUpdateForm(forms.ModelForm):
    class Meta:
        model = Redactor
        fields = ["years_of_experience"]

    def clean_experience(self):
        return validate_experience(self.cleaned_data["years_of_experience"])

def validate_experience(
    years_of_experience,
):
    if years_of_experience > 80:
        raise ValidationError("Years of experience should be less than 80")

    return years_of_experience

class RedactorSearchForm(forms.Form):
    username = forms.CharField(
        max_length=100,
        required=False,
        label="",
        widget=forms.TextInput(attrs={"placeholder": "Search by username"})
    )

class NewspaperSearchForm(forms.Form):
    title = forms.CharField(
        max_length=100,
        required=False,
        label="",
        widget=forms.TextInput(attrs={"placeholder": "Search by title"})
    )

class TopicSearchForm(forms.Form):
    name = forms.CharField(
        max_length=100,
        required=False,
        label="",
        widget=forms.TextInput(
            attrs={"placeholder": "Search by topic name"}
        )
    )


from django.http import HttpResponse

from fb_post.exceptions.custom_exceptions import InvalidPostException
from fb_post.interactors.presenter_interfaces.dtos import GetPostResponseDto
from fb_post.interactors.presenter_interfaces.presenter_interface_get_post import \
    PresenterInterfaceGetPost
from fb_post.interactors.storage_interfaces.comment_storage_interface import \
    CommentStorageInterface
from fb_post.interactors.storage_interfaces.dtos import GetPostParametersDto
from fb_post.interactors.storage_interfaces.post_storage_interface import \
    PostStorageInterface
from fb_post.interactors.storage_interfaces.reaction_storage_interface import \
    ReactionStorageInterface
from fb_post.adapters.service_adapter import get_service_adapter

class GetPostInteractor:
    def __init__(self, post_storage: PostStorageInterface,
                 comment_storage: CommentStorageInterface,
                 reaction_storage: ReactionStorageInterface,
                 presenter: PresenterInterfaceGetPost):
        self.post_storage = post_storage
        self.comment_storage = comment_storage
        self.reaction_storage = reaction_storage
        self.presenter = presenter

    def get_post_wrapper(self, post_id: int) -> HttpResponse:
        try:
            response_dto = self.get_post(post_id)
            return self.presenter.get_success_get_post_response(response_dto)
        except InvalidPostException:
            return self.presenter.get_invalid_get_post_response()

    def get_post(self, post_id: int) -> GetPostResponseDto:
        self._validate_post_id(post_id)

        post_dto = self.post_storage.get_post_details(post_id=post_id)

        comments_on_post_dtos = self.comment_storage.get_comments_on_post(
            post_dto.post_id)

        comment_ids = []
        commenter_ids_list = []
        for comments_on_post_dto in comments_on_post_dtos:
            comment_ids.append(comments_on_post_dto.comment_id)
            commenter_ids_list.append(comments_on_post_dto.commented_by_id)

        user_ids = commenter_ids_list
        user_ids.append(post_dto.posted_by_id)

        replies_dtos = self.comment_storage.get_replies_dtos(comment_ids)

        for replies_dto in replies_dtos:
            comment_ids.append(replies_dto.comment_id)
            user_ids.append(
                replies_dto.commented_by_id)
        adapter = get_service_adapter()
        user_dtos = adapter.fb_post_auth.get_user_dtos(user_ids=user_ids)
        reactions_on_post_dtos = self.reaction_storage.get_reactions_on_post(
            post_id=post_id)
        reactions_on_comments_dtos = self.reaction_storage.get_reactions_on_comments(
            comment_ids=comment_ids)

        response_dto = GetPostResponseDto(
            post_dto=post_dto,
            user_dtos=user_dtos,
            comment_dtos=comments_on_post_dtos,
            reply_dtos=replies_dtos,
            reactions_on_post_dtos=reactions_on_post_dtos,
            reactions_on_comments_dtos=reactions_on_comments_dtos
        )

        return response_dto

    def _validate_post_id(self, post_id: int) -> None:
        is_post_not_exists = not self.post_storage.is_post_exists(post_id)
        if is_post_not_exists:
            raise InvalidPostException


import logging
import pytest

from mos_tests.functions.common import wait

logger = logging.getLogger(__name__)

def run_and_check_job(sahara, template_id, cluster_id, input_id, output_id):
    def is_job_succeeded(job_id):
        job = sahara.job_executions.get(job_id)
        assert job.info['status'] not in ['KILLED', 'FAILED'], (
            "job is {0}".format(job.info['status']))
        return job.info['status'] == 'SUCCEEDED'

    logger.info('Execute job on existing cluster')
    job = sahara.job_executions.create(job_id=template_id,
                                       cluster_id=cluster_id,
                                       input_id=input_id,
                                       output_id=output_id)
    wait(lambda: is_job_succeeded(job.id), timeout_seconds=10 * 60,
         sleep_seconds=10, waiting_for='job success')

@pytest.mark.check_env_('is_sahara_enabled')
@pytest.mark.testrail_id('1295481')
def test_restart_all_sahara_services(env, data_sources, cluster, job_template,
                                     sahara):
    """Restart all Sahara services

    Scenario:
        1. Register vanilla 2.7.1 image for sahara
        2. Create vanilla cluster based on default template for vanilla
        3. Create job template and run job on cluster
        4. Check that job is finished successfully
        5. Restart sahara services on controllers
        6. Re-run job and check that it's finished successfully again
    """

    input_id, output_id1, output_id2 = data_sources
    run_and_check_job(sahara, job_template, cluster, input_id, output_id1)

    for node in env.get_nodes_by_role('controller'):
        with node.ssh() as remote:
            remote.check_call("service sahara-api restart && "
                              "service sahara-engine restart")

    run_and_check_job(sahara, job_template, cluster, input_id, output_id2)


import datetime
import uuid
import logging

logging.basicConfig(level=logging.DEBUG)

LOCATION_QUERY_TEMPLATE_MINIMAL = """
            DECLARE @Id UNIQUEIDENTIFIER;
            EXEC [OpticomManagement].[dbo].[LocationInsert] @RegionId=?,
                                                            @LocationName=?,
                                                            @LocationDescription=?,
                                                            @Address=?,
                                                            @City=?,
                                                            @StateProvince=?,
                                                            @PostalCode=?,
                                                            @CreatedDateTime=?,
                                                            @ModifiedDateTime=?,
                                                            @CreatedUserId=?,
                                                            @ModifiedUserId=?,
                                                            @IsDeleted=?,
                                                            @IsActive=?,
                                                            @Latitude=?,
                                                            @Longitude=?,
                                                            @Elevation=?,
                                                            @LocationNumber=?,
                                                            @LocationType=?,
                                                            @LocationConfigXml=?,
                                                            @IsShared=?,
                                                            @AllianceId=?,
                                                            @ForeignId=?,
                                                            @ForeignRegionId=?,
"""
CMS_VERSION_6_8_0 = (
    "6.8.0",
    """                                                            @LocationId=@Id OUTPUT;
            SELECT @Id as id;""",
)
CMS_VERSION_6_10_0 = (
    "6.10.0",
    """                                                            @ControllerId=?,
                                                            @LocationId=@Id OUTPUT;
            SELECT @Id as id;""",
)
CMS_VERSIONS = [CMS_VERSION_6_10_0, CMS_VERSION_6_8_0]

def read_locationtable(cursor):
    cursor.execute("select LocationName, LocationId, RegionId from dbo.Location")
    result = cursor.fetchall()
    return {
        "LocationName": [i.LocationName for i in result],
        "LocationId": [i.LocationId for i in result],
        "RegionId": [i.RegionId for i in result],
    }

def does_location_exist(LocationTable, locationname, jurisdictionid):
    for i in range(len(LocationTable["LocationName"])):
        if (
            locationname == LocationTable["LocationName"][i]
            and jurisdictionid == LocationTable["RegionId"][i]
        ):
            return True
    return False

def get_location(LocationTable, locationname, jurisdictionid):
    for i in range(len(LocationTable["LocationName"])):
        if (
            locationname == LocationTable["LocationName"][i]
            and jurisdictionid == LocationTable["RegionId"][i]
        ):
            return LocationTable["LocationId"][i]
    return None

def validate_location(LocationTable, data, jurisdictionid):
    locationguid = uuid.uuid4()
    locationname = data["location name"]
    locationid = data["location id"] if "location id" in data else ""
    locationdesc = (
        data["location description"] if "location description" in data else ""
    )
    locationconfigxml = (
        '<?xml version="1.0"?>\n'
        '    <LocationConfig xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" '
        'xmlns:xsd="http://www.w3.org/2001/XMLSchema">\n'
        "        <Approaches />\n"
        "        <MQTTCommEnabled>true</MQTTCommEnabled>\n"
        "    </LocationConfig>"
    )
    latitude = (
        float(data["latitude"])
        if "latitude" in data and data["latitude"] != ""
        else -360
    )
    longitude = (
        float(data["longitude"])
        if "longitude" in data and data["longitude"] != ""
        else -360
    )
    now = datetime.datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S.%f")[:-3]

    parameters = {
        "RegionId": str(jurisdictionid),
        "LocationName": locationname,
        "LocationDescription": locationdesc,
        "Address": "",
        "City": "",
        "StateProvince": "",
        "PostalCode": "",
        "CreatedDateTime": now,
        "ModifiedDateTime": now,
        "CreatedUserId": 0,
        "ModifiedUserId": 0,
        "IsDeleted": 0,
        "IsActive": 1,
        "Latitude": latitude,
        "Longitude": longitude,
        "Elevation": 0,
        "LocationNumber": locationid,
        "LocationType": 1,
        "LocationConfigXml": locationconfigxml,
        "IsShared": 1,
        "AllianceId": str(uuid.UUID(int=0)),
        "ForeignId": str(uuid.UUID(int=0)),
        "ForeignRegionId": str(uuid.UUID(int=0)),
        "ControllerId": "",
    }

    LocationTable["LocationName"].append(locationname)
    LocationTable["LocationId"].append(locationguid)
    LocationTable["RegionId"].append(jurisdictionid)

    return parameters, locationguid

def commit_location_query(cursor, LocationTable, parameters, id):
    working_query_parameters = [
        id,
        parameters["LocationName"],
        parameters["LocationDescription"],
        parameters["Address"],
        parameters["City"],
        parameters["StateProvince"],
        parameters["PostalCode"],
        parameters["CreatedDateTime"],
        parameters["ModifiedDateTime"],
        parameters["CreatedUserId"],
        parameters["ModifiedUserId"],
        parameters["IsDeleted"],
        parameters["IsActive"],
        parameters["Latitude"],
        parameters["Longitude"],
        parameters["Elevation"],
        parameters["LocationNumber"],
        parameters["LocationType"],
        parameters["LocationConfigXml"],
        parameters["IsShared"],
        parameters["AllianceId"],
        parameters["ForeignId"],
        parameters["ForeignRegionId"],
    ]
    for version in CMS_VERSIONS:
        try:
            if version[0] == "6.10.0":
                query_parameters = working_query_parameters.copy()
                query_parameters.append(parameters["ControllerId"])
                query_parameters = tuple(query_parameters)
            elif version[0] == "6.8.0":
                query_parameters = working_query_parameters.copy()
                query_parameters = tuple(query_parameters)

            cursor.execute(
                f"{LOCATION_QUERY_TEMPLATE_MINIMAL}{version[1]}",
                query_parameters,
            )

            locationid = uuid.UUID(cursor.fetchval())

            logging.debug(
                f"Successfully commited Location to CMS Database version {version[0]}"
            )

            break
        except Exception:
            logging.warning(
                f"Failed to commit Location to CMS Database version {version[0]}"
            )

    LocationTable["LocationName"].append(parameters["LocationName"])
    LocationTable["LocationId"].append(locationid)
    LocationTable["RegionId"].append(id)

    return locationid


import numpy as np
from scipy import linalg

# Not working...
def rsvdpi(a, k, p, s):
    n, m = np.shape(a)
    O = np.random.randn(m, k + s)
    Q = np.dot(a, O)
    for i in range(p+1):
        if i < p:
            P, L, U = linalg.lu(Q)
            Q = np.dot(P.T, L)
        else:
            Q = eigsvd(Q)[0]
        Q = np.dot(a, np.dot(a.T, Q))
    b = np.dot(Q.T, a)
    V, S, U = eigsvd(b.T)
    ind = np.arange(s, k+s)
    return np.dot(Q, U[:, ind]), np.diag(S)[ind, ind], V[:, ind]

def rsvd(a, k, p, s):
    n, m = np.shape(a)
    O = np.random.randn(m, k + s)
    Q = linalg.orth(np.dot(a, O))
    for i in range(p):
        G = linalg.orth(np.dot(a.T, Q))
        Q = linalg.orth(np.dot(a, G))
    b = np.dot(Q.T, a)
    u, s, v = eigsvd(b)
    u = np.dot(Q, u)
    return u[:, :k], s[:k], v[:, :k]

def eigsvd(a):
    transposeflag = None
    if np.size(a, axis=0) < np.size(a, axis=1):
        transposeflag = True
        a = a.T
    b = np.dot(a.T, a)
    eval, v = np.linalg.eig(b)
    v = v[:, np.argsort(-eval)]
    eval = eval[np.argsort(-eval)]
    s = np.sqrt(eval)
    u = np.dot(np.dot(a, v), np.diag(1/s))
    if transposeflag:
        u = v.T
        v = u.T
    return u, s, v


import tensorflow as tf
import numpy as np
import argparse
import os
import yaml
"""
Save normalization statistics as binaries for use with unity
"""

with open('LPN_100Style25B_BLL.yml') as f:
    config = yaml.load(f, Loader=yaml.FullLoader)

stats_path = config["stats_path"]
save_path = config["save_path"] + "Weights/"

with open(stats_path + "InputNorm.txt", 'r') as f:
    lines = f.readlines()
    X_mean = np.fromstring(lines[0], dtype=np.float32, sep=' ')[0:config["Xdim"]]  # dtype float32 is vital here - without it, doesn't work at all!
    X_std = np.fromstring(lines[1], dtype=np.float32, sep=' ')[0:config["Xdim"]]

    X_mean = np.concatenate([X_mean, np.zeros(config["one_hot_dim"], dtype=np.float32)])
    X_std = np.concatenate([X_std, np.ones(config["one_hot_dim"], dtype=np.float32)])

    assert config["Pdim"] == 8

    X_mean_gt = np.fromstring(lines[0], dtype=np.float32, sep=' ')[config["Xdim"]:config["Xdim"] + 8]
    X_std_gt = np.fromstring(lines[1], dtype=np.float32, sep=' ')[config["Xdim"]:config["Xdim"] + 8]

    for i in range(len(X_std)):
        if (X_std[i]==0):
            X_std[i]=1

    for i in range(len(X_std_gt)):
        if (X_std_gt[i]==0):
            X_std_gt[i]=1

with open(stats_path + "OutputNorm.txt", 'r') as f:
    lines = f.readlines()
    Y_mean = np.concatenate((np.fromstring(lines[0], dtype=np.float32, sep=' ')[0:config["Ydim"] - 2],
                             np.fromstring(lines[0], dtype=np.float32, sep=' ')[-2:]))
    Y_std = np.concatenate((np.fromstring(lines[1], dtype=np.float32, sep=' ')[0:config["Ydim"] - 2],
                            np.fromstring(lines[1], dtype=np.float32, sep=' ')[-2:]))

    for i in range(config["Ydim"]):
        if (Y_std[i]==0):
            Y_std[i]=1

X_mean.tofile(save_path + "Xmean.bin")
X_std.tofile(save_path + "Xstd.bin")
Y_mean.tofile(save_path + "Ymean.bin")
Y_std.tofile(save_path + "Ystd.bin")

X_mean_gt.tofile(save_path + "GT_Xmean.bin")
X_std_gt.tofile(save_path + "GT_Xstd.bin")

with open(save_path + "Xmean.bin") as f:
	in_arr = np.fromfile(f, dtype=np.float32)
	print(in_arr.shape)

with open(save_path + "GT_Xmean.bin") as f:
    in_arr = np.fromfile(f, dtype=np.float32)
    print(in_arr.shape)


'''
DESCRIPTION
----------

Plotting script to make the skymap figure of the proposal. (Where are the
clusters on the sky?)

'''

import matplotlib.pyplot as plt, seaborn as sns
import pandas as pd, numpy as np

from astropy.table import Table
from astropy.io import ascii
from astropy.coordinates import SkyCoord
import astropy.units as u

from math import pi
import pickle, os

from scipy.interpolate import interp1d

global COLORS
COLORS = ['#1f77b4', '#ff7f0e', '#2ca02c', '#d62728', '#9467bd', '#8c564b',
          '#e377c2', '#7f7f7f', '#bcbd22', '#17becf']

# cite:
#
# Jaffe, T. J. & Barclay, T. 2017, ticgen: A tool for calculating a TESS
# magnitude, and an expected noise level for stars to be observed by TESS.,
# v1.0.0, Zenodo, doi:10.5281/zenodo.888217
#
# and Stassun & friends (2017).
#import ticgen as ticgen

# # These two, from the website
# # http://dc.zah.uni-heidelberg.de/mwsc/q/clu/form
# # are actually outdated or something. They provided too few resuls..
# close_certain = pd.read_csv('../data/MWSC_search_lt_2000_pc_type_certain.csv')
# close_junk = pd.read_csv('../data/MWSC_search_lt_2000_pc_type_certain.csv')

def get_cluster_data():

    # Downloaded the MWSC from
    # http://cdsarc.u-strasbg.fr/viz-bin/Cat?cat=J%2FA%2BA%2F558%2FA53&target=http&
    tab = Table.read('../data/Kharchenko_2013_MWSC.vot', format='votable')

    df = tab.to_pandas()

    for colname in ['Type', 'Name', 'n_Type', 'SType']:
        df[colname] = [e.decode('utf-8') for e in list(df[colname])]

    # From erratum:
    # For the Sun-like star, a 4 Re planet produces a transit depth of 0.13%. The
    # limiting magnitude for transits to be detectable is about I_C = 11.4 . This
    # also corresponds to K_s ~= 10.6 and a maximum distance of 290 pc, assuming no
    # extinction.

    cinds = np.array(df['d']<500)
    close = df[cinds]
    finds = np.array(df['d']<1000)
    far = df[finds]

    N_c_r0 = int(np.sum(close['N1sr0']))
    N_c_r1 = int(np.sum(close['N1sr1']))
    N_c_r2 = int(np.sum(close['N1sr2']))
    N_f_r0 = int(np.sum(far['N1sr0']))
    N_f_r1 = int(np.sum(far['N1sr1']))
    N_f_r2 = int(np.sum(far['N1sr2']))

    type_d = {'a':'association', 'g':'globular cluster', 'm':'moving group',
              'n':'nebulosity/presence of nebulosity', 'r':'remnant cluster',
              's':'asterism', '': 'no label'}

    ntype_d = {'o':'object','c':'candidate','':'no label'}

    print('*'*50)
    print('\nMilky Way Star Clusters (close := <500pc)'
          '\nN_clusters: {:d}'.format(len(close))+\
          '\nN_stars (in core): {:d}'.format(N_c_r0)+\
          '\nN_stars (in central part): {:d}'.format(N_c_r1)+\
          '\nN_stars (in cluster): {:d}'.format(N_c_r2))

    print('\n'+'*'*50)
    print('\nMilky Way Star Clusters (far := <1000pc)'
          '\nN_clusters: {:d}'.format(len(far))+\
          '\nN_stars (in core): {:d}'.format(N_f_r0)+\
          '\nN_stars (in central part): {:d}'.format(N_f_r1)+\
          '\nN_stars (in cluster): {:d}'.format(N_f_r2))

    print('\n'+'*'*50)

    ####################
    # Post-processing. #
    ####################
    # Compute mean density
    mean_N_star_per_sqdeg = df['N1sr2'] / (pi * df['r2']**2)
    df['mean_N_star_per_sqdeg'] = mean_N_star_per_sqdeg

    # # Compute King profiles
    # king_profiles, theta_profiles = [], []
    # for rt, rc, k, d in zip(np.array(df['rt']),
    #                         np.array(df['rc']),
    #                         np.array(df['k']),
    #                         np.array(df['d'])):

    #     sigma, theta = get_king_proj_density_profile(rt, rc, k, d)
    #     king_profiles.append(sigma)
    #     theta_profiles.append(theta)

    # df['king_profile'] = king_profiles
    # df['theta'] = theta_profiles

    ra = np.array(df['RAJ2000'])
    dec = np.array(df['DEJ2000'])

    c = SkyCoord(ra=ra*u.degree, dec=dec*u.degree, frame='icrs')

    galactic_long = np.array(c.galactic.l)
    galactic_lat = np.array(c.galactic.b)
    ecliptic_long = np.array(c.barycentrictrueecliptic.lon)
    ecliptic_lat = np.array(c.barycentrictrueecliptic.lat)

    df['galactic_long'] = galactic_long
    df['galactic_lat'] = galactic_lat
    df['ecliptic_long'] = ecliptic_long
    df['ecliptic_lat'] = ecliptic_lat

    cinds = np.array(df['d']<500)
    close = df[cinds]
    finds = np.array(df['d']<1000)
    far = df[finds]

    return close, far, df

def make_wget_script(df):
    '''
    to download stellar data for each cluster, need to run a script of wgets.
    this function makes the script.
    '''

    # get MWSC ids in "0012", "0007" format
    mwsc = np.array(df['MWSC'])
    mwsc_ids = np.array([str(int(f)).zfill(4) for f in mwsc])

    names = np.array(df['Name'])

    f = open('../data/MWSC_stellar_data/get_stellar_data.sh', 'w')

    outstrs = []
    for mwsc_id, name in zip(mwsc_ids, names):
        startstr = 'wget '+\
                 'ftp://cdsarc.u-strasbg.fr/pub/cats/J/A%2BA/558/A53/stars/2m_'
        middlestr = str(mwsc_id) + '_' + str(name)
        endstr = '.dat.bz2 ;\n'
        outstr = startstr + middlestr + endstr
        outstrs.append(outstr)

    f.writelines(outstrs)
    f.close()

    print('made wget script!')

def plot_cluster_positions_scicase(df):
    '''
    Show the positions of d<2kpc clusters, and highlight those with rotation
    period measurements & transiting planets.
    '''

    rotn_clusters = ['NGC_1976', # AKA the orion nebula cluster
                     'NGC_6530',
                     'NGC_2264',
                     'Cep_OB3',
                     'NGC_2362',
                     'NGC_869', # h Per, one of the double cluster
                     'NGC_2547',
                     'IC_2391',
                     'Melotte_20', # alpha Persei cluster, alpha Per
                     'Melotte_22', # AKA Pleiades
                     'NGC_2323', # M 50
                     'NGC_2168', #M 35
                     'NGC_2516',
                     'NGC_1039', #M 34
                     'NGC_2099', # M 37
                     #'NGC_2632', #Praesepe, comment out to avoid overlap
                     #'NGC_6811', #comment out to avoid overlap
                     'NGC_2682' ] #M 67

    transiting_planet_clusters = [
                     'NGC_6811',
                     'NGC_2632' #Praesepe
                    ]

    df = df[df['d'] < 2000]

    df_rotn = df.loc[df['Name'].isin(rotn_clusters)]
    df_rotn = df_rotn[
            ['ecliptic_lat','ecliptic_long','galactic_lat','galactic_long',
            'Name']
            ]

    df_tra = df.loc[df['Name'].isin(transiting_planet_clusters)]

    # Above rotation lists were from Table 1 of Gallet & Bouvier 2015,
    # including M67 which was observed by K2.  Transiting planets from the few
    # papers that have them.  They are cross-matching MWSC's naming scheme. I
    # could not find the Hyades or ScoCen OB.  They both have transiting
    # planets, and the former has rotation studies done.

    c_Hyades = SkyCoord(ra='4h27m', dec=15*u.degree + 52*u.arcminute)
    df_hyades = pd.DataFrame({
            'Name':'Hyades',
            'ecliptic_long':float(c_Hyades.barycentrictrueecliptic.lon.value),
            'ecliptic_lat':float(c_Hyades.barycentrictrueecliptic.lat.value),
            'galactic_long':float(c_Hyades.galactic.l.value),
            'galactic_lat':float(c_Hyades.galactic.b.value)}, index=[0])

    c_ScoOB2 = SkyCoord(ra='16h10m14.73s', dec='-19d19m09.38s') # Mann+2016's position
    df_ScoOB2 = pd.DataFrame({
            'Name':'Sco_OB2',
            'ecliptic_long':float(c_ScoOB2.barycentrictrueecliptic.lon.value),
            'ecliptic_lat':float(c_ScoOB2.barycentrictrueecliptic.lat.value),
            'galactic_long':float(c_ScoOB2.galactic.l.value),
            'galactic_lat':float(c_ScoOB2.galactic.b.value)}, index=[0])

    df_tra = df_tra.append(df_hyades, ignore_index=True)
    df_tra = df_tra.append(df_ScoOB2, ignore_index=True)
    #df_rotn = df_rotn.append(df_hyades, ignore_index=True) #avoid overlap

    # End of data wrangling.

    import matplotlib as mpl
    from mpl_toolkits.basemap import Basemap

    for coord in ['galactic','ecliptic']:

        plt.close('all')
        #f, ax = plt.subplots(figsize=(4,4))
        f = plt.figure(figsize=(0.7*5,0.7*4))
        ax = plt.gca()
        m = Basemap(projection='kav7',lon_0=0, resolution='c', ax=ax)

        lats = np.array(df[coord+'_lat'])
        lons = np.array(df[coord+'_long'])
        x, y = m(lons, lats)
        m.scatter(x,y,2,marker='o',facecolor=COLORS[0], zorder=4,
                alpha=0.9,edgecolors=COLORS[0], lw=0)

        lats = np.array(df_rotn[coord+'_lat'])
        lons = np.array(df_rotn[coord+'_long'])
        x, y = m(lons, lats)
        m.scatter(x,y,42,marker='*',color=COLORS[1],edgecolors='k',
                label='have rotation studies', zorder=5,lw=0.4)

        lats = np.array(df_tra[coord+'_lat'])
        lons = np.array(df_tra[coord+'_long'])
        x, y = m(lons, lats)
        m.scatter(x,y,13,marker='s',color=COLORS[1],edgecolors='k',
                label='also have transiting planets', zorder=6, lw=0.45)

        parallels = np.arange(-90.,120.,30.)
        meridians = np.arange(0.,420.,60.)
	# labels = [left,right,top,bottom]
        ps = m.drawparallels(parallels, labels=[1,0,0,0], zorder=2,
                fontsize='x-small')
        ms = m.drawmeridians(meridians, labels=[0,0,0,1], zorder=2,
                fontsize='x-small')

        # Shrink current axis's height by 10% on the bottom
        box = ax.get_position()
        ax.set_position([box.x0, box.y0 + box.height * 0.1,
            box.width, box.height * 0.9])

	# Put a legend below current axis
        #ax.legend(loc='upper center', bbox_to_anchor=(0.01, 0.02),
        #        fancybox=True, ncol=1, fontsize='x-small')

        for _m in ms:
            try:
                #ms[_m][1][0].set_rotation(45)
                if '60' in ms[_m][1][0].get_text():
                    ms[_m][1][0].set_text('')
            except:
                pass
        for _p in ps:
            try:
                if '30' in ps[_p][1][0].get_text():
                    ps[_p][1][0].set_text('')
            except:
                pass

        ax.set_xlabel(coord+' long', labelpad=13, fontsize='x-small')
        ax.set_ylabel(coord+' lat', labelpad=13, fontsize='x-small')

        ######################
	# add TESS footprint #
        ######################
        dat = np.genfromtxt('../data/shemi_nhemi.csv', delimiter=',')
        dat = pd.DataFrame(np.transpose(dat), columns=['icSys', 'tSys', 'teff',
            'logg', 'r', 'm', 'eLat', 'eLon', 'micSys', 'mvSys', 'mic', 'mv',
            'stat', 'nPntg'])
        eLon, eLat = np.array(dat.eLon), np.array(dat.eLat)
        nPntg = np.array(dat.nPntg)
        if coord=='galactic':
            c = SkyCoord(lat=eLat*u.degree, lon=eLon*u.degree,
                    frame='barycentrictrueecliptic')
            lon = np.array(c.galactic.l)
            lat = np.array(c.galactic.b)

        elif coord=='ecliptic':
            lon, lat = eLon, eLat

        nPntg[nPntg >= 4] = 4

        ncolor = 4
        cmap1 = mpl.colors.ListedColormap(
                sns.color_palette("Greys", n_colors=ncolor, desat=1))
        bounds= list(np.arange(0.5,ncolor+1,1))
        norm1 = mpl.colors.BoundaryNorm(bounds, cmap1.N)

        x, y = m(lon, lat)
        out = m.scatter(x,y,s=0.2,marker='s',c=nPntg, zorder=1, cmap=cmap1,
                norm=norm1, rasterized=True, alpha=0.5)
        out = m.scatter(x,y,s=0, marker='s',c=nPntg, zorder=-1, cmap=cmap1,
                norm=norm1, rasterized=True, alpha=1)
        m.drawmapboundary()
        #cbar = f.colorbar(out, cmap=cmap1, norm=norm1, boundaries=bounds,
        #    fraction=0.025, pad=0.05, ticks=np.arange(ncolor)+1,
        #    orientation='vertical')

        #ylabels = np.arange(1,ncolor+1,1)
        #cbarlabels = list(map(str, ylabels))[:-1]
        #cbarlabels.append('$\geq\! 4$')
        #cbar.ax.set_yticklabels(cbarlabels, fontsize='x-small')
        #cbar.set_label('N pointings', rotation=270, labelpad=5, fontsize='x-small')
        ####################
        f.tight_layout()

        f.savefig('cluster_positions_'+coord+'_scicase.pdf', bbox_inches='tight')

if __name__ == '__main__':

    #make_wget_script(df)

    close, far, df = get_cluster_data()

    plot_cluster_positions_scicase(df)


# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at https://mozilla.org/MPL/2.0/.

# Generated by Django 2.1.7 on 2019-03-26 15:43

from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
import django.utils.timezone

class Migration(migrations.Migration):
    initial = True

    dependencies = [migrations.swappable_dependency(settings.AUTH_USER_MODEL)]

    operations = [
        migrations.CreateModel(
            name="PolicyException",
            fields=[
                (
                    "id",
                    models.AutoField(
                        auto_created=True,
                        primary_key=True,
                        serialize=False,
                        verbose_name="ID",
                    ),
                ),
                (
                    "comment",
                    models.TextField(help_text="Explanation for this exception."),
                ),
                ("created", models.DateTimeField(default=django.utils.timezone.now)),
                (
                    "user",
                    models.OneToOneField(
                        help_text="This user is excepted from the Mozilla-employees-only policy.",
                        on_delete=django.db.models.deletion.CASCADE,
                        to=settings.AUTH_USER_MODEL,
                    ),
                ),
            ],
        )
    ]


# -*- coding: utf-8 -*-
import torch
from tqdm import tqdm

from .base import SolverBase

class RK4(SolverBase):

    def __init__(self, func, t0, t1, dt, y0, *args, **kwargs):
        super(RK4, self).__init__(func, t0, t1, dt, y0, *args, **kwargs)

    def step(self, func, t0, y0, dt, *args, **kwargs):
        k1 = dt * func(t0, y0)
        k2 = dt * func(t0 + 0.5 * dt, y0 + 0.5 * k1)
        k3 = dt * func(t0 + 0.5 * dt, y0 + 0.5 * k2)
        k4 = dt * func(t0 + dt, y0 + k3)
        y1 = y0 + (k1 + k2 * 2 + k3 * 2 + k4) / 6
        return y1

class RK4_high_order(SolverBase):
    """
    仅限于输出为q_ori, dq_ori, lam的情况
    """

    def __init__(self,  *args, **kwargs):
        super(RK4_high_order, self)

    def step_with_lam(self, func, t0, y0, dt, dof, *args, **kwargs):
        q_ori, dq_ori, lam = torch.tensor_split(y0, (dof, dof * 2), dim=-1)

        k1 = q_ori
        dk1 = dq_ori
        dqddqlam = func(t0, torch.cat([k1, dk1, lam], dim=-1))
        dq, ddk1, lam = torch.tensor_split(dqddqlam, (dof, dof * 2), dim=-1)

        k2 = k1 + 0.5 * dt * dk1
        dk2 = dk1 + 0.5 * dt * ddk1
        dqddqlam = func(t0, torch.cat([k2, dk2, lam], dim=-1))
        dq, ddk2, lam = torch.tensor_split(dqddqlam, (dof, dof * 2), dim=-1)

        k3 = k1 + 0.5 * dt * dk2
        dk3 = dk1 + 0.5 * dt * ddk2
        dqddqlam = func(t0, torch.cat([k3, dk3, lam], dim=-1))
        dq, ddk3, lam = torch.tensor_split(dqddqlam, (dof, dof * 2), dim=-1)

        k4 = k1 + dt * dk3
        dk4 = dk1 + dt * ddk3
        dqddqlam = func(t0, torch.cat([k4, dk4, lam], dim=-1))
        dq, ddk4, lam = torch.tensor_split(dqddqlam, (dof, dof * 2), dim=-1)

        q_next = k1 + dt * dk1 + (dt ** 2) / 6 * (ddk1 + ddk2 + ddk3)
        dq_next = dk1 + dt / 6 * (ddk1 + 2 * ddk2 + 2 * ddk3 + ddk4)

        return torch.cat([q_next, dq_next, lam], dim=-1)

    def step(self, func, t0, y0, dt, *args, **kwargs):
        q_ori, dq_ori = torch.chunk(y0, 2, dim=-1)

        k1 = q_ori
        dk1 = dq_ori
        dqddq = func(t0, torch.cat([k1, dk1], dim=-1))
        dq, ddk1 = torch.chunk(y0, 2, dim=-1)

        k2 = k1 + 0.5 * dt * dk1
        dk2 = dk1 + 0.5 * dt * ddk1
        dqddq = func(t0, torch.cat([k2, dk2], dim=-1))
        dq, ddk2 = torch.chunk(dqddq, 2, dim=-1)

        k3 = k1 + 0.5 * dt * dk2
        dk3 = dk1 + 0.5 * dt * ddk2
        dqddq = func(t0, torch.cat([k3, dk3], dim=-1))
        dq, ddk3 = torch.chunk(dqddq, 2, dim=-1)

        k4 = k1 + dt * dk3
        dk4 = dk1 + dt * ddk3
        dqddq = func(t0, torch.cat([k4, dk4], dim=-1))
        dq, ddk4 = torch.chunk(dqddq, 2, dim=-1)

        q_next = k1 + dt * dk1 + (dt ** 2) / 6 * (ddk1 + ddk2 + ddk3)
        dq_next = dk1 + dt / 6 * (ddk1 + 2 * ddk2 + 2 * ddk3 + ddk4)

        return torch.cat([q_next, dq_next], dim=-1)

    def solve(self, func, t, y0, dt, *args, **kwargs):
        sol = torch.empty(len(t), *y0.shape, device=self.device, dtype=self.dtype)
        sol[0] = y0

        pbar = tqdm(range(len(self.t) - 1), desc='solving ODE...')
        for idx in pbar:
            temp = self.step_with_lam(self.func, self.t[idx], sol[idx], self.dt, *args, **kwargs)
            if sum((temp[0, 0:3] - temp[0, 15:18]) * (temp[0, 12:15] - temp[0, 3:6])) < 0:  # 16与52的夹角
                print('stop time is ', self.t[idx].cpu().detach().numpy())
                sol = sol[:idx + 1]
                t = t[:idx + 1]
                break
            else:
                sol[idx + 1] = temp
        sol = sol.permute(1, 0, 2)
        return t, sol


from flask import Flask, url_for, render_template, request
import json
from markupsafe import Markup, escape

app = Flask(__name__)

@app.route("/")
def render_home():
    return render_template('home.html')

@app.route("/page1")
def render_page1():
    if "playercount" in request.args:
        with open ('video_games.json') as ratings_data:
            data = json.load(ratings_data)
        playercount = int(request.args['playercount'])
        year = request.args['year']
        rating = 0
        output = ""
        for x in data:
            if x['Features']['Max Players'] == playercount and str(x['Release']['Year']) == year and x['Metrics']['Review Score'] > rating:
                rating = x['Metrics']['Review Score']
                year = x['Release']['Year']
                playercount = x['Features']['Max Players']
                output = Markup("
Your perfect game would be " + x['Title'] + "! It has a review score of " + str(x['Metrics']['Review Score']) + " out of 100. It was released by " + x['Metadata']['Publishers'] + " in " + str(x['Release']['Year']) + ". Have fun playing!
")
        return render_template('page1.html', output = output)
    else:
        return render_template('page1.html')

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


from flask import Flask, render_template, request
# import webapp2
# import jinja2
# import os
# from google.appengine.api import urlfetch
# import json
# import random
# import urlparse
# from webapp2_extras import sessions
#
# class BaseHandler(webapp2.RequestHandler):
#     def dispatch(self):
#         # Get a session store for this request.
#         self.session_store = sessions.get_store(request=self.request)
#
#         try:
#             # Dispatch the request.
#             webapp2.RequestHandler.dispatch(self)
#         finally:
#             # Save all sessions.
#             self.session_store.save_sessions(self.response)
#
#     @webapp2.cached_property
#     def session(self):
#         # Returns a session using the default cookie key.
#         return self.session_store.get_session()
#
# jinja_env = jinja2.Environment(
#     loader=jinja2.FileSystemLoader(os.path.dirname(__file__)),
#     extensions=['jinja2.ext.autoescape'],
#     autoescape=True)
#
# class SeedPage(BaseHandler):
#     def get(self):
#          animalsEasyEndPoint = "https://opentdb.com/api.php?amount=30&category=17&difficulty=easy&encode=url3986"
#          # exerciseCategory =
#          # exerciseLength =
#
#          a_e_response = urlfetch.fetch(animalsEasyEndPoint).content
#          print a_e_response
#          json_a_e_response = json.loads(a_e_response)
#          a_e_results = json_a_e_response["results"]
#          for a in a_e_results:
#             aeqp = urlparse.unquote(a["question"])
#             aecp = urlparse.unquote(a["correct_answer"])
#             aewplist = []
#             # for x in a["incorrect_answers"]:
#             #    aewp = urlparse.unquote(x)
#             #    aewplist.append(aewp)
#             a_e_question = easyAnimals(
#                animal_e_question = aeqp,
#                animal_e_correct = aecp,
#                animal_e_wrong = aewplist)
#             a_e_question.put()
#
#
# class Cover(BaseHandler):
#     def get(self):
#         start_template = jinja_env.get_template('templates/index.html')
#
#         category = self.request.get("category")    # Category
#         self.session['category'] = category
#
#         difficulty = self.request.get("difficulty")     # Difficulty
#         self.session['difficulty'] = difficulty
#
#         self.response.write(start_template.render(difficulty=difficulty,category=category))
#
#     def post(self):
#         start_template = jinja_env.get_template('templates/index.html')
#
#         category = self.request.get("category")    # Category
#         self.session['category'] = category
#
#         difficulty = self.request.get("difficulty")     # Difficulty
#         self.session['difficulty'] = difficulty
#
#         self.response.write(start_template.render(difficulty=difficulty,category=category))
#
# config = {}
# config['webapp2_extras.sessions'] = {
#     'secret_key': 'my-super-secret-key',
# }
#
# app = webapp2.WSGIApplication([
#     ('/', Cover),
#     ('/seed-page', SeedPage),
# ], config=config,
#    debug=True)

app = Flask(__name__)
@app.route('/form')
def form():
    return render_template('index.html')

@app.route('/submitted', methods=['POST'])
def submitted_form():
    name = request.form['name']
    category = request.form['category']

    return render_template(
        'index.html',
        name=name,
        category=category)

@app.route('/submitted', methods=['GET'])
def submitted_form():
    name = request.form['name']
    category = request.form['category']

    return render_template(
        'exercise_results.html',
        name=name,
        category=category)

# Entity employee = new Entity("Employee", "asalieri");
# employee.setProperty("firstName", "Antonio");
# employee.setProperty("lastName", "Salieri");
# employee.setProperty("hireDate", new Date());
# employee.setProperty("attendedHrTraining", true);
#
# DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
# datastore.put(employee);


# coding:utf-8
import unittest2
from peatio_client import StreamingClient, ClientError

class StreamingClientTestCase(unittest2.TestCase):
    def test_init(self):
        sc = StreamingClient(
            access_key= "access",
            secret_key = "secret"
        )

        self.assertEqual("access", sc.access_key)
        self.assertEqual("secret", sc.secret_key)


import asyncio
import json
import logging
import traceback
from typing import Generator

from eth_utils import to_checksum_address
from web3 import HTTPProvider, Web3
from web3.contract import Contract
from web3.types import HexBytes, LogReceipt

from backend.admin import send_admin_message
from backend.database import Database
from backend.notifier import Notifier
from backend.types import Chain, ChainAccount, ChainAccountWithAllData

HEALTH_FACTOR_CHECK_PERIOD = 60 * 15  # every 15 minutes
LIQUIDATIONS_CHECK_PERIOD = 60 * 15  # every 15 minutes
HEALTH_FACTOR_BATCH_SIZE = 100  # How many accounts to check at once. Limited by max gas per call.
MAX_UINT256 = 2 ** 256 - 1
MAX_BLOCK_RANGE = 100

LIQUIDATION_TOPIC = '0xe413a321e8681d831f4dbccbca790d2952b56f977908e45be37335533e005286'
MULTICALL_ADDRESS = '0xcA11bde05977b3631167028862bE2a173976CA11'

def topic_to_address(topic: HexBytes) -> str:
    return to_checksum_address('0x' + topic.hex()[-40:])

def build_subscription_message(pool_address: str, liquidation_topic: str) -> dict:
    return {'id': 2, 'method': 'eth_subscribe', 'params': ['logs', {
        'address': pool_address,
        'topics': [liquidation_topic],
    }]}

def make_batches(lst: list, batch_size: int) -> Generator[list, None, None]:
    """Yield successive n-sized batches from lst."""
    for i in range(0, len(lst), batch_size):
        yield lst[i:i + batch_size]

class ChainConnector():
    def __init__(
            self,
            chain: Chain,
            http_rpc_url: str,
            notifier: Notifier,
            database: Database,
            pool_address: str,
            aave_version: int,
    ) -> None:
        self.http_rpc_url = http_rpc_url
        self.web3 = Web3(HTTPProvider(http_rpc_url))
        self.chain = chain
        self.notifier = notifier
        self.database = database
        self.pool_address = pool_address
        self.aave_version = aave_version

        with open(f'./backend/abi/v{aave_version}_pool.json') as f:
            pool_abi = json.loads(f.read())

        with open('./backend/abi/erc20.json') as f:
            erc20_abi = json.loads(f.read())

        with open('./backend/abi/multicall.json') as f:
            multicall_abi = json.loads(f.read())

        self.erc20_abi = erc20_abi
        self.pool_contract: Contract = self.web3.eth.contract(
            address=pool_address,
            abi=pool_abi,
        )
        self.multical_contract: Contract = self.web3.eth.contract(
            address=MULTICALL_ADDRESS,
            abi=multicall_abi,
        )

    def get_health_factors(
            self,
            accounts_batch: list[ChainAccountWithAllData],
    ) -> list[float]:
        """Get aave health factors of all accounts in the batch"""
        encoded_calls = []
        for account in accounts_batch:
            encoded = self.pool_contract.encodeABI(
                fn_name='getUserAccountData',
                args=[account.account.address],
            )
            encoded_calls.append((self.pool_contract.address, encoded))

        accounts_data = self.multical_contract.functions.aggregate(encoded_calls).call()[1]

        health_factors = []
        for account_data in accounts_data:
            raw_health_factor = int.from_bytes(account_data[-32:], "big")
            if raw_health_factor == MAX_UINT256:
                health_factors.append(-1)
            else:
                health_factors.append(raw_health_factor / 1e18)

        return health_factors

    def check_health_factors(self) -> None:
        """
        1. Get all accounts from the DB that belong to this chain and their threshold health factors.
        2. Check health factor of all these accounts.
        3. Check the health factors against the thresholds and send notifications if needed.
        """
        logging.info(f'Checking health factors on {self.chain.name} x Aave V{self.aave_version}')
        all_accounts = self.database.get_accounts_for_hf_check(self.chain, self.aave_version)
        health_factors: list[float] = []
        for batch in make_batches(all_accounts, HEALTH_FACTOR_BATCH_SIZE):
            health_factors += self.get_health_factors(batch)

        logging.info(f'Got {len(health_factors)} health factors on {self.chain.name} x Aave V{self.aave_version}')
        for account, health_factor in zip(all_accounts, health_factors):
            if health_factor < account.health_factor_threshold and health_factor != -1:
                message = f'Health factor on your account {str(self.chain)} {account.account.address} is {health_factor:.2f} which is below the threshold of {account.health_factor_threshold}.'
                self.notifier.notify_about_health_factor(account=account, message=message)

    async def monitor_health_factor(self) -> None:
        """Periodically check health factor of all accounts on this chain"""
        while True:
            try:
                self.check_health_factors()
            except Exception:
                await send_admin_message('Critical error!')
                logging.error(f'Error while checking health factors on {self.chain.name} x Aave V{self.aave_version}: {traceback.format_exc()}')

            await asyncio.sleep(HEALTH_FACTOR_CHECK_PERIOD)

    def catchup_on_liquidations(self) -> None:
        """Catchup on liquidations that occured while the program was not running"""
        logging.info(f'Checking for liquidations on {self.chain.name} x Aave V{self.aave_version}')
        setting_key = f'LAST_{self.chain.name}_V{self.aave_version}_CHECKED_BLOCK'
        last_checked_block_raw = self.database.get_setting(setting_key)
        current_block = self.web3.eth.block_number - 1  # Doing -1 because it may be that the current block is not confirmed yet on Avalanche.
        if last_checked_block_raw is None:
            logging.info(f'No last checked block found. But we set {setting_key} to {current_block}')
            return  # Cant do anything. No state saved.

        logging.info(f'Checking liquidations from block {last_checked_block_raw} to {current_block} on {self.chain.name} x Aave V{self.aave_version}')
        last_checked_block = int(last_checked_block_raw)
        logs = []
        for from_block in range(last_checked_block, current_block, MAX_BLOCK_RANGE):
            logs += self.web3.eth.get_logs({
                'address': self.pool_address,
                'topics': [LIQUIDATION_TOPIC],
                'fromBlock': from_block,
                'toBlock': min(current_block, from_block + MAX_BLOCK_RANGE),
            })
        logging.info(f'Found {len(logs)} liquidations on {self.chain.name} x Aave V{self.aave_version}')
        for log in logs:
            self.process_liquidation_log(log)

        self.database.set_setting(setting_key, str(current_block))

    def process_liquidation_log(self, log: LogReceipt) -> None:
        """Process a single aave liquidation log and send a notification if the liquidated account is tracked."""
        collateral_token_address = topic_to_address(log['topics'][1])
        debt_token_address = topic_to_address(log['topics'][2])
        user = topic_to_address(log['topics'][3])

        account = ChainAccount(
            address=user,
            chain=self.chain,
            aave_version=self.aave_version,
        )
        if not self.database.is_tracked(account):
            logging.info(f'The liquidated address {user} is not being tracked on {self.chain.name} x Aave V{self.aave_version}. Skipping.')
            return

        logging.info(f'The liquidated address {user} is being tracked on {self.chain.name} x Aave V{self.aave_version}! Querying data for the notification.')
        covered_debt_amount_raw = int(log['data'][:32].hex(), 16)
        liquidated_collateral_amount_raw = int(log['data'][32:64].hex(), 16)

        collateral_token_symbol = self.web3.eth.contract(address=collateral_token_address, abi=self.erc20_abi).functions.symbol().call()  # type: ignore[call-overload]
        collateral_token_decimals = self.web3.eth.contract(address=collateral_token_address, abi=self.erc20_abi).functions.decimals().call()  # type: ignore[call-overload]
        liquidated_collateral_amount = liquidated_collateral_amount_raw / 10 ** collateral_token_decimals

        debt_token_symbol = self.web3.eth.contract(address=debt_token_address, abi=self.erc20_abi).functions.symbol().call()  # type: ignore[call-overload]
        debt_token_decimals = self.web3.eth.contract(address=debt_token_address, abi=self.erc20_abi).functions.decimals().call()  # type: ignore[call-overload]
        covered_debt_amount = covered_debt_amount_raw / 10 ** debt_token_decimals

        logging.info(f'Queried data for the liquidation of {user} on {self.chain.name} x Aave V{self.aave_version}. Sending the notification!')
        message = f'Your account {user} on chain {self.chain.name} was liquidated. {collateral_token_symbol} {liquidated_collateral_amount} was liquidated to cover {debt_token_symbol} {covered_debt_amount} debt.'
        self.notifier.notify_about_liquidation(chain_account=account, title='Liquidation occured!', message=message)

    async def monitor_liquidations(self):
        """Periodically check liquidations on this chain"""
        while True:
            try:
                self.catchup_on_liquidations()
            except Exception:
                await send_admin_message('Critical error!')
                logging.error(f'Error while catching up on liquidations on {self.chain.name} x Aave V{self.aave_version}: {traceback.format_exc()}')
            await asyncio.sleep(LIQUIDATIONS_CHECK_PERIOD)


import os
import platform
import shutil
from pathlib import Path
from typing import List
import docker
from docker.types import Mount
from datetime import datetime
import hashlib

from aws_cdk import aws_lambda
from aws_cdk.core import BundlingOptions, DockerVolume, DockerVolumeConsistency

# pylint: disable=print-used
def timeit(method):

    def timed(*args, **kw):
        t_start = datetime.now()
        result = method(*args, **kw)
        t_end = datetime.now()
        print(f'{method.__name__} - Total time = {(t_end - t_start).total_seconds()} seconds')
        return result

    return timed

class BuildLambdaAsset:

    def __init__(self, include_paths: List[str], build_dir: Path, cache_dir: Path = None, requirements_txt: Path = Path('requirements.txt'),
                 consume_dependencies: bool = None, verbose: bool = False) -> None:
        self._include_paths = include_paths
        self._build_dir: Path = build_dir
        self._cache_dir: Path = cache_dir if cache_dir is not None else Path.home() / ".everest-pip-cache"
        self._requirements_txt: Path = requirements_txt
        self._req_md5_file: Path = Path(str(requirements_txt) + '.md5')
        self._consume_dependencies = consume_dependencies
        self._verbose = verbose

    @timeit
    def build(self):
        md5_sum: str = None
        if self._consume_dependencies is None:
            prev_md5_sum: str = self._req_md5_file.read_text() if self._req_md5_file.is_file() else ''
            md5_sum = hashlib.md5(self._requirements_txt.read_bytes()).hexdigest()
            self._consume_dependencies = prev_md5_sum != md5_sum
        self._clean_build_target()
        self._copy_resources()
        if self._consume_dependencies:
            self._consume()
        if md5_sum is not None:
            self._req_md5_file.write_text(md5_sum)

    def _clean_build_target(self):
        if self._consume_dependencies:
            if self._req_md5_file.is_file():
                self._req_md5_file.unlink()
            shutil.rmtree(self._build_dir, ignore_errors=True)
            self._build_dir.mkdir(parents=True, exist_ok=True)
            self._cache_dir.mkdir(parents=True, exist_ok=True)
        else:
            for include_path in self._include_paths:
                shutil.rmtree(self._build_dir / os.path.basename(os.path.normpath(include_path)), ignore_errors=True)

    def _copy_resources(self):
        print('Copying \'include\' resources:')
        for include_path in self._include_paths:
            print(f'    -  {(Path.cwd() / include_path).resolve()}')
            shutil.copytree(include_path, (self._build_dir / os.path.basename(os.path.normpath(include_path))).as_posix())
        shutil.copy(self._requirements_txt.as_posix(), (self._build_dir / 'requirements.txt').as_posix())

    def _consume(self) -> None:
        if platform.system().lower() == 'linux':
            self._consume_natively()
        else:
            self._consume_using_docker()

    @timeit
    def _consume_natively(self) -> None:
        """
        Build lambda dependencies natively on linux. Should be the same architecture though.
        """
        print('Installing lambda runtime dependencies on Linux')
        if os.system(f"python -m pip install --target {self._build_dir} --requirement {self._requirements_txt}") != 0:
            raise Exception('Cloud not resolve lambda runtime dependencies')
        print('Finish to install lambda runtime dependencies')

    @timeit
    def _consume_using_docker(self) -> None:
        """
        Build lambda dependencies in a container as-close-as-possible to the actual runtime environment.
        """
        print('Installing dependencies [running in Docker]...')
        client = docker.from_env()
        client.images.pull(repository='amazon/aws-sam-cli-build-image-python3.8', tag='latest')
        # pylint: disable=bad-option-value
        container = client.containers.run(
            image='amazon/aws-sam-cli-build-image-python3.8:latest',
            command="/bin/sh -c 'python3.8 -m pip install --target /var/task/ --requirement /var/task/requirements.txt && "
            "find /var/task -name \\*.so -exec strip \\{\\} \\;'",
            auto_remove=True,
            mounts=[
                Mount(target="/var/task", source=self._build_dir.as_posix(), type="bind", consistency="delegated"),
                Mount(target="/root/.cache", source=self._cache_dir.as_posix(), type="bind", consistency="delegated"),
                #Mount(target="/root/.netrc", source=f"{str(Path.home())}/.netrc", type="bind", consistency="delegated", read_only=True)
            ],
            user=0,
            detach=True,
        )
        try:
            if self._verbose:
                for log in container.logs(stream=True, follow=True):
                    print(log.decode('utf-8'), end='')
            else:
                container.wait()
        finally:  # handle Ctrl-C or other interruptions: kill the container
            try:
                container.kill()
            except (docker.errors.NotFound, docker.errors.APIError):
                pass  # container has already exited, was already deleted, etc.


import argparse
import sys

if sys.version_info >= (3, 9):
  List = list
else:
  from typing import List

from pathlib import Path
from typing import Optional

from .command_base import BaseCommand
from .command_base import BaseCommandExecutor

from .encoding import has_bom

from .gettext_tools import compile_translations
from .gettext_tools import validate_gettext_tools_exist

from .paths import get_names_of_immediate_subdirectories
from .paths import make_messages_dir_path
from .paths import make_mo_file_path

from .text import flatten_comma_separated_values
from .text import stringify_path

from .utils import halt
from .utils import print_err
from .utils import print_out
from .utils import show_usage_error_and_halt

from . import defaults

class CompileCommandExecutor(BaseCommandExecutor):

  def __init__(self, args=argparse.Namespace) -> None:
    self._locales_dir_path = self._handle_locales_dir_path(args.locales_dir)
    self._validate_locales_dir_path(self._locales_dir_path)

    self._locales = self._handle_locales(
      locales=args.locale,
      locales_dir_path=self._locales_dir_path,
    )
    self._validate_locales(
      locales=self._locales,
      locales_dir_path=self._locales_dir_path,
    )

    self._exclude = set(flatten_comma_separated_values(args.exclude))

    self._fuzzy = args.fuzzy

    self._msgfmt_extra_args = flatten_comma_separated_values(args.msgfmt_extra_args)
    self._verbose = args.verbose

  @staticmethod
  def _handle_locales_dir_path(path: str) -> Path:
    return Path(path).absolute()

  @staticmethod
  def _validate_locales_dir_path(path: Path) -> None:
    if not path.exists():
      print_err(f"locales dir does not exist (path={stringify_path(path)}")
      show_usage_error_and_halt()

    if not path.is_dir():
      print_err(f"locales dir is not a directory (path={stringify_path(path)})")
      show_usage_error_and_halt()

  @staticmethod
  def _handle_locales(
    locales: Optional[List[str]],
    locales_dir_path: Path,
  ) -> List[str]:

    if locales:
      return flatten_comma_separated_values(locales)

    return get_names_of_immediate_subdirectories(locales_dir_path)

  @staticmethod
  def _validate_locales(
    locales: List[str],
    locales_dir_path: Path,
  ) -> None:
    if not locales:
      print_err(
        "specify at least 1 locale or specify processing of all existing locales"
      )
      show_usage_error_and_halt()

    for locale in locales:
      path = make_messages_dir_path(locales_dir_path, locale)
      if not (path.exists() and path.is_dir()):
        print_err(
          f"invalid locale '{locale}': "
          f"directory '{stringify_path(path)}' expected to exist"
        )
        show_usage_error_and_halt()

  def __call__(self) -> None:
    validate_gettext_tools_exist()

    if self._verbose:
      self._print_input_args(
        locales_dir_path=stringify_path(self._locales_dir_path),
        locales=self._locales,
        fuzzy=self._fuzzy,
        msgfmt_extra_args=self._msgfmt_extra_args,
        verbose=self._verbose,
      )

    final_locales = sorted(set(self._locales) - self._exclude)

    for locale in final_locales:
      self._process_locale(locale=locale)

  def _process_locale(self, locale: str) -> None:
    if self._verbose:
      print_out(f"processing locale '{locale}'")

    messages_dir_path = make_messages_dir_path(self._locales_dir_path, locale)

    for path in messages_dir_path.iterdir():
      if path.is_file() and path.suffix == ".po":
        self._process_translations_file(file_path=path)

  def _process_translations_file(self, file_path: Path) -> None:
    if self._verbose:
      print_out(f"processing file '{stringify_path(file_path)}'")

    if has_bom(file_path):
      print_err(
        f"the file '{stringify_path(file_path)}' file has a BOM (Byte Order Mark). "
        f"Verboselib supports only '.po' files encoded in UTF-8 and without any BOM."
      )
      halt()

    mo_file_path = make_mo_file_path(file_path)

    compile_translations(
      mo_file_path=mo_file_path,
      po_file_path=file_path,
      fuzzy=self._fuzzy,
      msgfmt_extra_args=self._msgfmt_extra_args,
    )

class CompileCommand(BaseCommand):
  name = "compile"
  aliases = ["c", ]
  executor_class = CompileCommandExecutor

  @classmethod
  def make_parser(cls, factory=argparse.ArgumentParser) -> argparse.ArgumentParser:
    description = "compile '.po' text files into '.mo' binaries"
    parser = factory(
      prog=cls.name,
      description=description,
      add_help=True,
      help=description,
      formatter_class=argparse.ArgumentDefaultsHelpFormatter,
    )
    parser.add_argument(
      "-d", "--locale-dir",
      dest="locales_dir",
      default=defaults.DEFAULT_LOCALE_DIR_NAME,
      help="path to the directory where locales are stored",
    )
    parser.add_argument(
      "-l", "--locale",
      dest="locale",
      action="append",
      help=(
        "locale(s) to process, ex: 'en_US'; "
        "can be specified multiple times; "
        "all locales are processed if not specified"
      ),
    )
    parser.add_argument(
      "-e", "--exclude",
      dest="exclude",
      action="append",
      help="locale(s) to exclude, ex: 'en_US'; can be specified multiple times",
    )
    parser.add_argument(
      "-f", "--use-fuzzy",
      action="store_true",
      dest="fuzzy",
      default=False,
      help="use fuzzy translations",
    )
    parser.add_argument(
      "--msgfmt-extra-args",
      action="append",
      dest="msgfmt_extra_args",
      help=(
        "extra arguments for 'msgfmt' utility; "
        "can be comma-separated or specified multiple times"
      ),
    )
    parser.add_argument(
      "-v", "--verbose",
      action="store_true",
      dest="verbose",
      default=False,
      help="use verbose output",
    )
    return parser


from app.models import db, March_Madness_Team, League, League_User, Draft, Drafted_Team, User, Tournament
import json
from datetime import datetime
import random
from app.api.draft_routes import generate_draft_order

def seed_draft_2019():
    # This is for the Demo Draft functionality
    league = League.query.filter(
        League.name == 'The League of Extraordinary Gentlemen').one()

    tournament = Tournament.query.filter(Tournament.year==2019).one()

    draft_order = generate_draft_order(league.id)
    draft = Draft(league_id=league.id, tournament_id=tournament.id,
                  draft_order=json.dumps(draft_order), draft_index=0,
                  draft_time=datetime.now(),
                  drafting=True, current_drafter_id=draft_order[0])
    db.session.add(draft)
    db.session.commit()

    # This is for a second year of the Demo data
    league = League.query.filter(
        League.name == 'The Dumb Friends League').one()

    draft_order = generate_draft_order(league.id)
    draft = Draft(league_id=league.id, tournament_id=tournament.id,
                  draft_order=json.dumps(draft_order), draft_index=64,
                  draft_time=datetime.now(),
                  drafting=False, current_drafter_id=None)
    db.session.add(draft)
    db.session.commit()

    march_madness_team_ids = {
        march_madness_team.id for march_madness_team in tournament.march_madness_teams
    }
    for i in range(0, 64):
        pick = random.choice(tuple(march_madness_team_ids))
        march_madness_team_ids.remove(pick)
        drafted_team = Drafted_Team(
            march_madness_team_id=pick,
            league_user_id=draft_order[i],
            draft_id=draft.id,
            selection_num=i+1)
        db.session.add(drafted_team)

    db.session.commit()

def undo_draft_2019():
    db.session.execute(
        'DELETE FROM drafts USING tournaments WHERE drafts.tournament_id = tournaments.id AND tournaments.year = 2019;')
    db.session.commit()


from tkinter import *
from tkinter import ttk
from matplotlib.figure import Figure
from matplotlib.backends.backend_tkagg import (FigureCanvasTkAgg, NavigationToolbar2Tk)
import numpy as np
import warnings
warnings.filterwarnings("ignore", category=np.VisibleDeprecationWarning)
import sys
import math
import time
import os
import numpy as np
import matplotlib.pyplot as plt
from functions_v6 import calculate_optimized_alphas, get_stress_points_in_Yieldlocus, get_R_vs_Theta_Rb_values

class widgets(Frame):

    def __init__(self, window, picks=[]):

      Frame.__init__(self, window)

      self.inputs = []
      self.stress_and_R = ['S45','S90','Sbiax','R00','R45','R90','Rbiax', 'e']
      lf = LabelFrame(window, text='Inputs')
      lf.grid(column=0, row=0)
      value_picks = [[0.85, 1.15, 2], [6,8,2]]

      label = Label(lf, text='S00', width=6)
      label.grid(row=0, column=0)
      var = IntVar()
      var.set(1)
      self.S00 = Entry(lf, textvariable=var, width=6)
      self.S00.grid(row=0, column=1)

      for j, para in enumerate(self.stress_and_R):
          label = Label(lf, text=self.stress_and_R[j], width=8)
          label.grid(row=0, column=j+3)

          stress_and_R_range  = []
          for i in range(len(picks)):

              label = Label(lf, text=picks[i], width=6)
              label.grid(row=i+1, column=2)

              var = IntVar()
              if para== 'e':
                  var.set(value_picks[1][i])
              else:
                  var.set(value_picks[0][i])

              ent = Entry(lf, textvariable=var, width=8)
              ent.grid(row=i+1, column=j+3)

              stress_and_R_range.append(ent)

          self.inputs.append(stress_and_R_range)

          Button(lf, text='Get the plot!', command=allstates).grid(row=12,column=1)

    def state(self):

      S00 = float(self.S00.get())
      #e_min = float(self.e_min.get())
      #e_max = float(self.e_max.get())
      #exponent_values = [float(self.e_min.get()), float(self.e_max.get())]

      input_data = []
      for i, stress_and_R_input in enumerate(self.inputs):
          #alpha_values_list = []
          stress_and_R_input = list(map((lambda ent: float(ent.get())), stress_and_R_input))
          #print(alpha_input)
          n_step = stress_and_R_input[-1]
          stress_and_R_values = stress_and_R_input[:-1]

          step = (stress_and_R_values[1]-stress_and_R_values[0]) / (n_step - 1)
          #print(step_alpha)
          if n_step > 2:
              for j in range(int(n_step-2)): # 2 accounting for the first and the last points
                stress_and_R_values = np.insert(stress_and_R_values, j+1, stress_and_R_values[j]+step, axis=0)

          input_data.append(stress_and_R_values)

      return input_data, S00, n_step

def allstates():

    global count, canvas, fig, ax1, ax2, ax3, toolbar

    count +=1

    if count != 1:
        ax1.cla()
        ax2.cla()
        ax3.cla()
        ax4.cla()
        ax5.cla()
        ax6.cla()
        ax7.cla()
        ax8.cla()

    input_data, S00, n_step = lng.state()

    print(np.shape(input_data))
    print(input_data)

    no_of_calcns = int(n_step)**8
    alpha1_values = np.zeros(no_of_calcns).tolist()  # or use [0] * inputs[4]**8   OR use numpy arrays (faster and smaller in size)
    alpha2_values = np.zeros(no_of_calcns).tolist()
    alpha3_values = np.zeros(no_of_calcns).tolist()
    alpha4_values = np.zeros(no_of_calcns).tolist()
    alpha5_values = np.zeros(no_of_calcns).tolist()
    alpha6_values = np.zeros(no_of_calcns).tolist()
    alpha7_values = np.zeros(no_of_calcns).tolist()
    alpha8_values = np.zeros(no_of_calcns).tolist()

    no_of_calcns = 0
    track_calcn_no = []
    for a in input_data[7]: # this is the exponent of the yield locus
        for S45 in input_data[0]:
            for S90 in input_data[1]:
                for Sbiax in input_data[2]:
                    for R00 in input_data[3]:
                        for R45 in input_data[4]:
                            for R90 in input_data[5]:
                                for Rbiax in input_data[6]:

                                    alpha = calculate_optimized_alphas(a,S00,S45,S90,Sbiax,R00,R45,R90,Rbiax)

                                    S = get_stress_points_in_Yieldlocus(alpha,a,shear=0)
                                    R,Rb = get_R_vs_Theta_Rb_values(alpha,a)

                                    given_stress = np.array([[S00, S45, S90, Sbiax]])
                                    given_R = np.array([[R00, R45, R90, Rbiax]])

                                    calculated_stress = np.array([[S[0][2], S[0][4], S[0][3], S[0][5]]])
                                    calculated_R = np.array([[R[0][0], R[0][45], R[0][90], Rb[0]]])

                                    Absolute_Error_for_stress = (abs(given_stress - calculated_stress))
                                    Absolute_Error_for_R_value = (abs(given_R - calculated_R))
                                    # the lines below perform element by element division, / is a shorthand for numpy.divide
                                    Percentage_Error_for_stress = (abs(given_stress - calculated_stress) / given_stress)*100.0
                                    Percentage_Error_for_R_value = (abs(given_R - calculated_R) / given_R)*100.0

                                    alpha1_values[no_of_calcns] = alpha[0]
                                    alpha2_values[no_of_calcns] = alpha[1]
                                    alpha3_values[no_of_calcns] = alpha[2]
                                    alpha4_values[no_of_calcns] = alpha[3]
                                    alpha5_values[no_of_calcns] = alpha[4]
                                    alpha6_values[no_of_calcns] = alpha[5]
                                    alpha7_values[no_of_calcns] = alpha[6]
                                    alpha8_values[no_of_calcns] = alpha[7]

                                    for (pe_stress, pe_R) in zip(Percentage_Error_for_stress[0], Percentage_Error_for_R_value[0]):
                                        if (pe_stress > 1) or (pe_R > 1):
                                            track_calcn_no.append(no_of_calcns)
                                            break
                                            # if no_of_calcns not in track_calcn_no:
                                            #     track_calcn_no.append(no_of_calcns)

                                    no_of_calcns += 1

                                    #break

    x = list(range(no_of_calcns))
    print("total number of simulations:", no_of_calcns)

    min_alpha1, max_alpha1 = min(alpha1_values), max(alpha1_values)
    min_alpha2, max_alpha2 = min(alpha2_values), max(alpha2_values)
    min_alpha3, max_alpha3 = min(alpha3_values), max(alpha3_values)
    min_alpha4, max_alpha4 = min(alpha4_values), max(alpha4_values)
    min_alpha5, max_alpha5 = min(alpha5_values), max(alpha5_values)
    min_alpha6, max_alpha6 = min(alpha6_values), max(alpha6_values)
    min_alpha7, max_alpha7 = min(alpha7_values), max(alpha7_values)
    min_alpha8, max_alpha8 = min(alpha8_values), max(alpha8_values)

    print("red points:", track_calcn_no)

    for idx in x:
        if idx in track_calcn_no:
            ax1.scatter(idx, alpha1_values[idx], color='red', s=10)
            ax2.scatter(idx, alpha2_values[idx], color='red', s=10)
            ax3.scatter(idx, alpha3_values[idx], color='red', s=10)
            ax4.scatter(idx, alpha4_values[idx], color='red', s=10)
            ax5.scatter(idx, alpha5_values[idx], color='red', s=10)
            ax6.scatter(idx, alpha6_values[idx], color='red', s=10)
            ax7.scatter(idx, alpha7_values[idx], color='red', s=10)
            ax8.scatter(idx, alpha8_values[idx], color='red', s=10)

        else:
            ax1.scatter(idx, alpha1_values[idx], color='green', s=10)
            ax2.scatter(idx, alpha2_values[idx], color='green', s=10)
            ax3.scatter(idx, alpha3_values[idx], color='green', s=10)
            ax4.scatter(idx, alpha4_values[idx], color='green', s=10)
            ax5.scatter(idx, alpha5_values[idx], color='green', s=10)
            ax6.scatter(idx, alpha6_values[idx], color='green', s=10)
            ax7.scatter(idx, alpha7_values[idx], color='green', s=10)
            ax8.scatter(idx, alpha8_values[idx], color='green', s=10)

    ax1.set_ylabel('alpha1', fontweight='bold')
    ax1.set_xlabel('no. of calculations', fontweight='bold')
    ax2.set_ylabel('alpha2', fontweight='bold')
    ax2.set_xlabel('no. of calculations', fontweight='bold')
    ax3.set_ylabel('alpha3', fontweight='bold')
    ax3.set_xlabel('no. of calculations', fontweight='bold')
    ax4.set_ylabel('alpha4', fontweight='bold')
    ax4.set_xlabel('no. of calculations', fontweight='bold')
    ax5.set_ylabel('alpha5', fontweight='bold')
    ax5.set_xlabel('no. of calculations', fontweight='bold')
    ax6.set_ylabel('alpha6', fontweight='bold')
    ax6.set_xlabel('no. of calculations', fontweight='bold')
    ax7.set_ylabel('alpha7', fontweight='bold')
    ax7.set_xlabel('no. of calculations', fontweight='bold')
    ax8.set_ylabel('alpha8', fontweight='bold')
    ax8.set_xlabel('no. of calculations', fontweight='bold')

    ax1.axhline(y=max_alpha1, color='red', label=f'max={max_alpha1}')
    ax1.axhline(y=min_alpha1, color='green', label=f'min={min_alpha1}')
    ax1.legend(loc='upper right')
    ax2.axhline(y=max_alpha2, color='red', label=f'max={max_alpha2}')
    ax2.axhline(y=min_alpha2, color='green', label=f'min={min_alpha2}')
    ax2.legend(loc='upper right')
    ax3.axhline(y=max_alpha3, color='red', label=f'max={max_alpha3}')
    ax3.axhline(y=min_alpha3, color='green', label=f'min={min_alpha3}')
    ax3.legend(loc='upper right')
    ax4.axhline(y=max_alpha4, color='red', label=f'max={max_alpha4}')
    ax4.axhline(y=min_alpha4, color='green', label=f'min={min_alpha4}')
    ax4.legend(loc='upper right')
    ax5.axhline(y=max_alpha5, color='red', label=f'max={max_alpha5}')
    ax5.axhline(y=min_alpha5, color='green', label=f'min={min_alpha5}')
    ax5.legend(loc='upper right')
    ax6.axhline(y=max_alpha6, color='red', label=f'max={max_alpha6}')
    ax6.axhline(y=min_alpha6, color='green', label=f'min={min_alpha6}')
    ax6.legend(loc='upper right')
    ax7.axhline(y=max_alpha7, color='red', label=f'max={max_alpha7}')
    ax7.axhline(y=min_alpha7, color='green', label=f'min={min_alpha7}')
    ax7.legend(loc='upper right')
    ax8.axhline(y=max_alpha8, color='red', label=f'max={max_alpha8}')
    ax8.axhline(y=min_alpha8, color='green', label=f'min={min_alpha8}')
    ax8.legend(loc='upper right')

    #ax1.tick_params(axis='both')
    #ax2.tick_params(axis='both')
    #ax3.tick_params(axis='both')

    canvas.draw()
    canvas.get_tk_widget().grid(row = 10, column=0)

    ###########################################################################

    alpha1_values.clear()
    alpha2_values.clear()
    alpha3_values.clear()
    alpha4_values.clear()
    alpha5_values.clear()
    alpha6_values.clear()
    alpha7_values.clear()
    alpha8_values.clear()

    print('plotted!')

    end_time = time.time()
    total_time = (end_time - start_time)/60
    print(f'Total Time: {(total_time):.4f} mins')

if __name__ == '__main__':

    root = Tk()
    root.title('Reverse  Computation')
    root.geometry("1280x800")

    start_time = time.time()

    count = 0

    content = ttk.Frame(root)
    frame1 = ttk.Frame(content, borderwidth=5, relief="ridge")
    frame3 = ttk.Frame(content, borderwidth=5, relief="ridge")
    #width and height here sets the dimension of the frame , width=1250, height=550
    content.grid(column=0, row=0)

    frame1.grid(column=0, row=0)
    frame3.grid(column=0, row=10, columnspan=70, rowspan=70)

    fig = plt.figure()
    fig.set_figheight(8) #sets the height and width of the white space inside frame3
    fig.set_figwidth(18)

    ax1 = plt.subplot2grid(shape=(2,4), loc=(0, 0), rowspan = 1, colspan = 1) #shape=Shape of grid in which to place axis
    ax2 = plt.subplot2grid(shape=(2,4), loc=(0, 1), rowspan = 1, colspan = 1)
    ax3 = plt.subplot2grid(shape=(2,4), loc=(0, 2), rowspan = 1, colspan = 1)
    ax4 = plt.subplot2grid(shape=(2,4), loc=(0, 3), rowspan = 1, colspan = 1)
    ax5 = plt.subplot2grid(shape=(2,4), loc=(1, 0), rowspan = 1, colspan = 1)
    ax6 = plt.subplot2grid(shape=(2,4), loc=(1, 1), rowspan = 1, colspan = 1)
    ax7 = plt.subplot2grid(shape=(2,4), loc=(1, 2), rowspan = 1, colspan = 1)
    ax8 = plt.subplot2grid(shape=(2,4), loc=(1, 3), rowspan = 1, colspan = 1)

    #fig.tight_layout()

    canvas = FigureCanvasTkAgg(fig, master = frame3)

    toolbarFrame = Frame(master=frame1)
    toolbarFrame.grid(row=25,column=0)
    toolbar = NavigationToolbar2Tk(canvas, toolbarFrame)

    lng = widgets(frame1, ['min', 'max', 'NPoints'])

    root.mainloop()