import torch
import torch.optim as optim
from torchvision import datasets, transforms
from KD_Lib.KD import VanillaKD
from networks.resnet_big import SupConResNet, LinearClassifier
import torch.backends.cudnn as cudnn
from losses import SupConLoss

try:
    import apex
    from apex import amp, optimizers
except ImportError:
    pass

import sys
import argparse
import time
import math

def parse_option():
    parser = argparse.ArgumentParser('argument for training')

    # parser.add_argument('--print_freq', type=int, default=10,
    #                     help='print frequency')
    # parser.add_argument('--save_freq', type=int, default=50,
    #                     help='save frequency')
    parser.add_argument('--batch_size', type=int, default=256,
                        help='batch_size')
    parser.add_argument('--num_workers', type=int, default=8,
                        help='num of workers to use')
    parser.add_argument('--epochs', type=int, default=100,
                        help='number of training epochs')

    # optimization
    parser.add_argument('--learning_rate', type=float, default=0.1,
                        help='learning rate')
    # parser.add_argument('--lr_decay_epochs', type=str, default='60,75,90',
    #                     help='where to decay lr, can be a list')
    # parser.add_argument('--lr_decay_rate', type=float, default=0.2,
    #                     help='decay rate for learning rate')
    parser.add_argument('--weight_decay', type=float, default=0,
                        help='weight decay')
    # parser.add_argument('--momentum', type=float, default=0.9,
    #                     help='momentum')

    # model dataset
    parser.add_argument('--teacher_model', type=str, default='resnet50')
    parser.add_argument('--student_model', type=str, default='resnet50')
    parser.add_argument('--dataset', type=str, default='cifar10',
                        choices=['cifar10', 'cifar100', 'path'], help='dataset')
    parser.add_argument('--data_folder', type=str, default=None, help='path to custom dataset')

    # other setting
    # parser.add_argument('--cosine', action='store_true',
    #                     help='using cosine annealing')
    # parser.add_argument('--warm', action='store_true',
    #                     help='warm-up for large batch training')

    parser.add_argument('--ckpt', type=str, default='',
                        help='path to pre-trained model')

    opt = parser.parse_args()

    # set the path according to the environment
    if opt.dataset != 'path':
        opt.data_folder = './datasets/'

    # iterations = opt.lr_decay_epochs.split(',')
    # opt.lr_decay_epochs = list([])
    # for it in iterations:
    #     opt.lr_decay_epochs.append(int(it))

    opt.model_name = '{}_{}_lr_{}_decay_{}_bsz_{}'.\
        format(opt.dataset, opt.student_model, opt.learning_rate, opt.weight_decay,
               opt.batch_size)

    # if opt.cosine:
    #     opt.model_name = '{}_cosine'.format(opt.model_name)

    # warm-up for large-batch training,
    # if opt.warm:
    #     opt.model_name = '{}_warm'.format(opt.model_name)
    #     opt.warmup_from = 0.01
    #     opt.warm_epochs = 10
    #     if opt.cosine:
    #         eta_min = opt.learning_rate * (opt.lr_decay_rate ** 3)
    #         opt.warmup_to = eta_min + (opt.learning_rate - eta_min) * (
    #                 1 + math.cos(math.pi * opt.warm_epochs / opt.epochs)) / 2
    #     else:
    #         opt.warmup_to = opt.learning_rate

    if opt.dataset in ('cifar10', 'path'):
        opt.n_cls = 10
    elif opt.dataset == 'cifar100':
        opt.n_cls = 100
    else:
        raise ValueError('dataset not supported: {}'.format(opt.dataset))

    return opt

def set_loader(opt):
    # construct data loader
    if opt.dataset == 'cifar10':
        mean = (0.4914, 0.4822, 0.4465)
        std = (0.2023, 0.1994, 0.2010)
    elif opt.dataset == 'cifar100':
        mean = (0.5071, 0.4867, 0.4408)
        std = (0.2675, 0.2565, 0.2761)
    elif opt.dataset == 'path':
        mean = (0.41044191,0.45704237,0.46365224)
        std = std = (4.37454361,4.06389989,4.11659655)
    else:
        raise ValueError('dataset not supported: {}'.format(opt.dataset))
    normalize = transforms.Normalize(mean=mean, std=std)

    train_transform = transforms.Compose([
        #transforms.RandomResizedCrop(size=32, scale=(0.2, 1.)),
        #transforms.RandomHorizontalFlip(),
        transforms.ToTensor(),
        normalize,
    ])

    val_transform = transforms.Compose([
        transforms.ToTensor(),
        normalize,
    ])

    if opt.dataset == 'cifar10':
        train_dataset = datasets.CIFAR10(root=opt.data_folder,
                                         transform=train_transform,
                                         download=True)
        val_dataset = datasets.CIFAR10(root=opt.data_folder,
                                       train=False,
                                       transform=val_transform)
    elif opt.dataset == 'cifar100':
        train_dataset = datasets.CIFAR100(root=opt.data_folder,
                                          transform=train_transform,
                                          download=True)
        val_dataset = datasets.CIFAR100(root=opt.data_folder,
                                        train=False,
                                        transform=val_transform)
    elif opt.dataset == 'path':
        train_dataset = datasets.ImageFolder(root=opt.data_folder+'train/',
                                            transform=train_transform)
        val_dataset = datasets.ImageFolder(root=opt.data_folder+'test/',
                                            transform=val_transform)
    else:
        raise ValueError(opt.dataset)

    train_sampler = None
    train_loader = torch.utils.data.DataLoader(
        train_dataset, batch_size=opt.batch_size, shuffle=True, #(train_sampler is None),
        num_workers=opt.num_workers, #pin_memory=True
        )
    val_loader = torch.utils.data.DataLoader(
        val_dataset, batch_size=opt.batch_size, shuffle=True,
        num_workers=1, pin_memory=True)

    return train_loader, val_loader

def set_teacher_model(opt):
    model = SupConResNet(name=opt.teacher_model)
    criterion = torch.nn.CrossEntropyLoss()

    classifier = LinearClassifier(name=opt.teacher_model, num_classes=opt.n_cls)

    ckpt = torch.load(opt.ckpt, map_location='cpu')
    state_dict = ckpt['model']

    if torch.cuda.is_available():
        if torch.cuda.device_count() > 1:
            model.encoder = torch.nn.DataParallel(model.encoder)
        else:
            new_state_dict = {}
            for k, v in state_dict.items():
                k = k.replace("module.", "")
                new_state_dict[k] = v
            state_dict = new_state_dict
        model = model.cuda()
        classifier = classifier.cuda()
        criterion = criterion.cuda()
        cudnn.benchmark = True

        model.load_state_dict(state_dict)

    return model, classifier, criterion

def set_student_model(opt):
    model = SupConResNet(name=opt.student_model)
    criterion = SupConLoss(temperature=opt.temp)

    # enable synchronized Batch Normalization
    if opt.syncBN:
        model = apex.parallel.convert_syncbn_model(model)

    if torch.cuda.is_available():
        if torch.cuda.device_count() > 1:
            model.encoder = torch.nn.DataParallel(model.encoder)
        model = model.cuda()
        criterion = criterion.cuda()
        cudnn.benchmark = True

    return model, criterion

opt = parse_option()

train_loader, test_loader = set_loader(opt)

teacher_model, classifier, te_criterion = set_teacher_model(opt)
student_model, st_criterion = set_student_model(opt)

teacher_optimizer = optim.SGD(teacher_model.parameters(), 0.01)
student_optimizer = optim.SGD(student_model.parameters(), 0.01)

distiller = VanillaKD(teacher_model, student_model, train_loader, test_loader,
                      teacher_optimizer, student_optimizer)
# # distiller.train_teacher(epochs=5, plot_losses=True, save_model=True)    # Train the teacher network
# distiller.train_student(epochs=5, plot_losses=True, save_model=True)    # Train the student network
# distiller.evaluate(teacher=False)                                       # Evaluate the student network
# distiller.get_parameters()                                              # A utility function to get the number of
                                                                        # parameters in the  teacher and the student network


from __future__ import division
import os
import cartopy.crs as ccrs
import cartopy.io.shapereader as shpreader
import matplotlib.pyplot as plt

#Load country codes for map plotting
def readCodeDic(codeFile):
    codeDic = {}
    for line in open(codeFile):
        line2 = line.replace("\r","").rstrip("\n").split("\t")
        if len(line2) == 2:
            codeDic[line2[0]] = line2[1]
    return(codeDic)

#Load country based data
def loadCountryInfo(file1,codeDic):
    countryData = {}
    l = 0
    maxSpecs = 0
    for line in open(file1):
        l += 1
        line2 = line.replace("\r","").replace("?","").rstrip("\n").split("\t")
        if len(line2) > 2 and l > 1:
            count = codeDic.get(line2[0],"no data yet")
            countryData[count] = [int(line2[1]),float(line2[2]),float(line2[3]),float(line2[4])]
            if count == "no data yet":
                print(line2[0] + " no country code yet")
            if int(line2[1]) > maxSpecs:
                maxSpecs = int(line2[1])
    return(countryData,maxSpecs)

#Make maps for taxonomic groups
def makeMap(countryData,output,maxSpecs):
    #Define panel names
    levels = ["Number of species","BOLD public", "BOLD total", "Total"]

    #Load details of map
    shapename = 'admin_0_countries'
    countries_shp = shpreader.natural_earth(resolution='10m',category='cultural', name=shapename)

    #Load colourmap
    cmap = plt.get_cmap("plasma_r")

    #Make figure
    plt.figure(figsize=(20,14))
    for r in range(0,4):
        ax = plt.subplot(2,2,r+1,projection=ccrs.PlateCarree())
        for country in shpreader.Reader(countries_shp).records():
            code = country.attributes["ADM0_A3_US"]
            value = countryData.get(code,["NA","NA","NA","NA"])
            if value[1] == "NA":
                ax.add_geometries(country.geometry, ccrs.PlateCarree(),
                            lw=1,facecolor=(0.9,0.9,0.9),edgecolor=(0,0,0,1),alpha=1)
            else:
                if r == 0:
                    col = list(cmap(value[r]/maxSpecs))
                else:
                    col = list(cmap(value[r]))
                ax.add_geometries(country.geometry, ccrs.PlateCarree(),
                    lw=1,facecolor=col,edgecolor=(0,0,0,1),alpha=1)

        #Make lables
        if r == 0:
            sm = plt.cm.ScalarMappable(cmap=cmap,norm=plt.Normalize(0,maxSpecs))
        else:
            sm = plt.cm.ScalarMappable(cmap=cmap,norm=plt.Normalize(0,1))
        sm._A = []
        cb = plt.colorbar(sm)
        cb.ax.set_yticklabels(cb.ax.get_yticklabels(), fontsize=8)

        #Map size
        ax.set_extent([-25,52,30,70])
        ax.set_aspect('auto', adjustable="box")
        ax.set_title(levels[r],fontsize=10)

    #Save
    plt.savefig(output)
    plt.savefig(output[:-3] + "pdf")
    plt.close()

#User defined variables
#Folder including country summary files generated by FM_make_result_statistics.py
inputFolder = "output"

#Name of output folder
outputFolder = "maps"

#Name of country code file
codeDicFile = "country_codes.txt"

#Prefix output
outputPrefix = "GapAnalysis"

#Do Analysis

#Test if output folder exists, otherwise create it
if not os.path.exists(outputFolder):
    os.makedirs(outputFolder)

#Load input files for different taxonomic groups
all_files = os.listdir(inputFolder)
all_files = [f for f in all_files if f.endswith("country.tsv")]

#Load country codes for map plotting
codeDic = readCodeDic(codeDicFile)

#For each taxonomic group, generate files
for file1 in all_files:
    #get basic information of the file
    name = file1.split("_")[1]
    version = file1.split("_")[2][1:]
    lim = file1.split("_")[3][3:]
    #make output name
    out = outputFolder + "/" + outputPrefix + "_" + name + "_v" + str(version) + "_lim" + str(lim) + ".svg"
    #load country-based information
    countryData,maxSpecs = loadCountryInfo(inputFolder + "/" + file1,codeDic)
    #generate map file
    makeMap(countryData,out,maxSpecs)
    print("map " + name + " for lim " + str(lim) + " finished")


# for sibling imports
import numpy as np

import os
import sys
sys.path.insert(1, os.path.join(sys.path[0], '..'))

from config.params import KLINES_BEFORE, KLINES_AFTER, PERCENT_MOVEMENT_THRESHOLD
from utils.base_path import get_file_path
from utils.data_mutations import sets_to_grouped_sets
from pprintpp import pprint

raw_data = open(get_file_path("../data/raw_klines_data.m"), "r").read().split('\n')
raw_data_without_timestamps = list(map(lambda x: ' '.join(x.split(' ')[1:]), raw_data))
grouped_sets = sets_to_grouped_sets(raw_data_without_timestamps)

# print(grouped_sets[0])
# print(len(grouped_sets[0]))

def get_aggregations(set):
  # we only want to create aggregates from KLINES_BEFORE
  # lets create an array of all opens from all KLINES_BEFORE

  # first we need to create an array so we can index into each position
  set_array = set.split(" ")
  opens = []
  for i in range(KLINES_BEFORE):
    opens.append(float(set_array[i * 6]))
  np_opens = np.array(opens)

  # print(f"{np_opens.sum()=}")
  # print(f"{np_opens.mean()=}")
  # print(f"{np_opens.std()=}")
  # print(f"{np_opens.var()=}")
  # print(f"{np_opens.min()=}")
  # print(f"{np_opens.max()=}")
  # print(f"{np.median(np_opens)=}")
  # print(f"{np.percentile(np_opens, 25)=}")

  return [np_opens.sum(), np_opens.mean(), np_opens.std(), np_opens.var(), np_opens.min(), np_opens.max(), np.median(np_opens), np.percentile(np_opens, 25)]

# pocs = open(get_file_path("../data/pocs.m"), "r").read().split('\n')
# def get_poc(index):
#   return pocs[index]

def get_label(set):
  # this is getting the y value of the set.
  last_length = KLINES_AFTER * 6
  last_klines = set.split(" ")[-last_length:]

  # get open from first and close from last
  # get total price movement
  # and it should be > 1%
  first_open = float(last_klines[0])
  last_close = float(last_klines[-3])
  price_movement = (last_close - first_open) / first_open

  buy_sell_or_hold = None
  if price_movement > PERCENT_MOVEMENT_THRESHOLD:
    buy_sell_or_hold = "1" # buy
  elif price_movement < -PERCENT_MOVEMENT_THRESHOLD:
    buy_sell_or_hold = "0" # sell
  else:
    buy_sell_or_hold = "2" # hold

  # all_but_last_klines = set.split(" ")[0:-last_length]
  # all_but_last_klines.extend([str(first_open), buy_sell_or_hold])

  # return all_but_last_klines

  return buy_sell_or_hold;

def remove_klines_after(set):
  last_length = KLINES_AFTER * 6
  last_klines = set.split(" ")[-last_length:]
  first_open = float(last_klines[0])
  all_except_last_klines = set.split(" ")[0:-last_length]
  # remove klines_after but keep the next open price
  all_except_last_klines.extend([str(first_open)])
  return all_except_last_klines

first_set = grouped_sets[0]
# print(get_aggregations(grouped_sets[0]))
# print(get_poc(0))
# this should have a length of KLINES_BEFORE * 6 + 1
# print(KLINES_BEFORE * 6 + 1 == len(remove_klines_after(first_set)))
# print(remove_klines_after(first_set))
# print(len(remove_klines_after(first_set)))
# print(get_label(first_set))
print(len(first_set.split(" ")))
input()

first_labeled_set = f"{' '.join(remove_klines_after(first_set))} {get_poc(0)} {' '.join(list(map(lambda x: str(x), get_aggregations(first_set))))} {get_label(first_set)}"
# print(len(first_labeled_set.split(' ')) == KLINES_BEFORE * 6 + 1 + 8 + 1 + 1)

print(len(first_labeled_set.split(' ')))
input()
# print(first_labeled_set)

batch = grouped_sets[:10000]

def get_nn_data(set, index):
  return f"{' '.join(remove_klines_after(set))} {get_poc(index)} {' '.join(list(map(lambda x: str(x), get_aggregations(set))))} {get_label(set)}"

# "\n".join(list(map(get_nn_data)))
nn_data = []

for i, set in enumerate(batch):
  nn_data.append(get_nn_data(set, i))

# pprint(nn_data);
print(len(nn_data))
print(len(pocs))
# "\n".join(nn_data)

nn_file = open(get_file_path("../data/nn_data.m"), "w")
nn_file.write("\n".join(nn_data))


#!@PYTHON@
####!/usr/bin/env python

""":py:class:`Graphics` wrapping methods for matplotlib
=======================================================

Usage::

    import pyimgalgos.Graphics as gr

    # Methods

    fig = gr.figure(figsize=(13,12), title='Image', dpi=80, facecolor='w', edgecolor='w', frameon=True, move=None)
    gr.move_fig(fig, x0=200, y0=100)
    gr.move(x0=200, y0=100)
    gr.add_axes(fig, axwin=(0.05, 0.03, 0.87, 0.93))
    gr.fig_img_cbar_axes(fig=None, win_axim=(0.05,  0.03, 0.87, 0.93), win_axcb=(0.923, 0.03, 0.02, 0.93))
    gr.set_win_title(fig, titwin='Image')
    gr.add_title_labels_to_axes(axes, title=None, xlabel=None, ylabel=None, fslab=14, fstit=20, color='k')
    gr.show(mode=None)
    gr.draw()
    gr.draw_fig(fig)
    gr.save_plt(fname='img.png', verb=True)
    gr.save_fig(fig, fname='img.png', verb=True)
    hi = gr.hist(axhi, arr, bins=None, amp_range=None, weights=None, color=None, log=False)
    imsh = gr.imshow(axim, img, amp_range=None, extent=None, interpolation='nearest', aspect='auto', origin='upper', orientation='horizontal', cmap='inferno')
    cbar = gr.colorbar(fig, imsh, axcb, orientation='vertical', amp_range=None)
    imsh, cbar = gr.imshow_cbar(fig, axim, axcb, img, amin=None, amax=None, extent=None, interpolation='nearest', aspect='auto', origin='upper', orientation='vertical', cmap='inferno')

See:
  - :py:class:`Graphics`
  - :py:class:`GlobalGraphics`
  - :py:class:`NDArrGenerators`
  - :py:class:`HBins`
  - :py:class:`HPolar`
  - :py:class:`HSpectrum`
  - :py:class:`NDArrSpectrum`
  - :py:class:`RadialBkgd`
  - `Radial background <https://confluence.slac.stanford.edu/display/PSDMInternal/Radial+background+subtraction+algorithm>`_.
  - `matplotlib <https://matplotlib.org/contents.html>`_.

This software was developed for the SIT project.
If you use all or part of it, please give an appropriate acknowledgment.

Created in 2015 by Mikhail Dubrovin
"""
from __future__ import print_function

import numpy as np

import matplotlib
#if matplotlib.get_backend() != 'Qt4Agg': matplotlib.use('Qt4Agg')

import matplotlib.pyplot  as plt
#import matplotlib.lines   as lines
#import matplotlib.patches as patches

from CalibManager.PlotImgSpeWidget import add_stat_text

def dict_subset(d, keys):
    return {k:v for k,v in d.items() if k in keys}

def figure(**kwa):
    """ Creates and returns figure.
        figsize=(13,12), title='Image', dpi=80, facecolor='w', edgecolor='w', frameon=True
    """
    fig = plt.figure(**dict_subset(kwa, ('num', 'figsize', 'dpi', 'facecolor', 'edgecolor', 'frameon', 'FigureClass', 'clear',\
                                         'linewidth', 'subplotpars', 'tight_layout', 'constrained_layout')))
    move = kwa.get('move', None)
    title = kwa.get('title', '')
    if title: fig.canvas.set_window_title(title)
    if move: move_fig(fig, x0=move[0], y0=move[1])
    return fig

def pp_hist(axis, x, **kwa):
    """ matplotlib.pyplot.hist(x,
                       bins=10,
                       range=None,
                       normed=False,
                       weights=None,
                       cumulative=False,
                       bottom=None,
                       histtype=u'bar',
                       align=u'mid',
                       orientation=u'vertical',
                       rwidth=None,
                       log=False,
                       color=None,
                       label=None,
                       stacked=False,
                       hold=None,
                       **kwargs)
    """
    return axis.hist(x, **dict_subset(kwa,\
           ('bins', 'range', 'normed', 'weights', 'cumulative', 'bottom', 'histtype', 'align',\
            'orientation', 'rwidth', 'log', 'color', 'label', 'stacked', 'hold')))

def move_fig(fig, x0=200, y0=100):
    #fig.canvas.manager.window.geometry('+%d+%d' % (x0, y0)) # in previous version of matplotlib
    backend = matplotlib.get_backend()
    #logger.debug('matplotlib.get_backend(): %s' % backend)
    if backend == 'TkAgg': # this is our case
        fig.canvas.manager.window.wm_geometry("+%d+%d" % (x0, y0))
    elif backend == 'WXAgg':
        fig.canvas.manager.window.SetPosition((x0, y0))
    else:
        # This works for QT and GTK
        # You can also use window.setGeometry
        fig.canvas.manager.window.move(x0, y0)

def move(x0=200,y0=100):
    move_fig(plt.gcf(), x0, y0)
    #plt.get_current_fig_manager().window.move(x0, y0)
    #plt.get_current_fig_manager().window.geometry('+%d+%d' % (x0, y0))

def add_axes(fig, axwin=(0.05, 0.03, 0.87, 0.93)):
    """Add axes to figure from input list of windows.
    """
    return fig.add_axes(axwin)

def fig_img_axes(fig=None, win_axim=(0.08,  0.05, 0.89, 0.93)):
    """ Returns figure and image axes
    """
    _fig = figure(figsize=(6,5)) if fig is None else fig
    axim = _fig.add_axes(win_axim)
    return _fig, axim

def fig_axes(fig, windows=((0.05,  0.03, 0.87, 0.93), (0.923, 0.03, 0.02, 0.93))):
    """ Returns list of figure axes for input list of windows
    """
    return [fig.add_axes(w) for w in windows]

def fig_img_cbar_axes(fig=None,\
             win_axim=(0.05,  0.03, 0.87, 0.93),\
             win_axcb=(0.923, 0.03, 0.02, 0.93)):
    """ Returns figure and axes for image and color bar
    """
    _fig = figure() if fig is None else fig
    axim = _fig.add_axes(win_axim)
    axcb = _fig.add_axes(win_axcb)
    return _fig, axim, axcb

def fig_axim_axcb_imsh(figsize=(13,12), title='Image', dpi=80,\
                       win_axim=(0.05,  0.03, 0.87, 0.93),\
                       win_axcb=(0.923, 0.03, 0.02, 0.93),\
                       arr2d=np.zeros((10,10)), origin='upper'):
    """ Creates and returns figure, axes for image and color bar, imshow object
    """
    fig  = plt.figure(figsize=figsize, dpi=dpi, facecolor='w', edgecolor='w', frameon=True)
    axim = fig.add_axes(win_axim)
    axcb = fig.add_axes(win_axcb)
    fig.canvas.set_window_title(title)
    imsh = axim.imshow(arr2d, interpolation='nearest', aspect='auto', origin=origin)
    return fig, axim, axcb, imsh

FYMIN, FYMAX = 0.050, 0.90
def fig_img_cbar_hist_axes(fig=None,\
                      win_axim=(0.02,  FYMIN, 0.8,  FYMAX),\
                      win_axcb=(0.915, FYMIN, 0.01, FYMAX),\
                      win_axhi=(0.76,  FYMIN, 0.15, FYMAX),\
                      **kwa):
    """ Returns figure and axes for image, color bar, and spectral histogram
    """
    _fig = figure() if fig is None else fig
    return _fig,\
           _fig.add_axes(win_axim, **kwa),\
           _fig.add_axes(win_axcb, **kwa),\
           _fig.add_axes(win_axhi, **kwa)

def set_win_title(fig, titwin='Image'):
    fig.canvas.set_window_title(titwin)

def add_title_labels_to_axes(axes, title=None, xlabel=None, ylabel=None, fslab=14, fstit=20, color='k'):
    if title  is not None: axes.set_title(title, color=color, fontsize=fstit)
    if xlabel is not None: axes.set_xlabel(xlabel, fontsize=fslab)
    if ylabel is not None: axes.set_ylabel(ylabel, fontsize=fslab)

def show(mode=None):
    #plt.hold(True)
    if mode is None: plt.ioff() # hold contraol at show() (connect to keyboard for controllable re-drawing)
    else           : plt.ion()  # do not hold control
    plt.pause(0.001) # hack to make it work... othervise show() does not work...
    plt.show()

def draw():
    plt.draw()

def draw_fig(fig):
    fig.canvas.draw()

def save_plt(fname='img.png', verb=True):
    if verb: print('Save plot in file: %s' % fname)
    plt.savefig(fname)

def save_fig(fig, fname='img.png', verb=True):
    if verb: print('Save figure in file: %s' % fname)
    fig.savefig(fname)

def hist(axhi, arr, bins=None, amp_range=None, weights=None, color=None, log=False):
    """Makes historgam from input array of values (arr), which are sorted in number of bins (bins) in the range (amp_range=(amin,amax))
    """
    #axhi.cla()
    hi = axhi.hist(arr.flatten(), bins=bins, range=amp_range, weights=weights, color=color, log=log) #, log=logYIsOn)
    if amp_range is not None: axhi.set_xlim(amp_range) # axhi.set_autoscale_on(False) # suppress autoscailing
    wei, bins, patches = hi
    add_stat_text(axhi, wei, bins)
    return hi

def imshow(axim, img, amp_range=None, extent=None,\
           interpolation='nearest', aspect='auto', origin='upper',\
           orientation='horizontal', cmap='inferno'):
    """
    extent - list of four image physical limits for labeling,
    cmap: 'jet', 'gray_r', 'inferno'
    #axim.cla()
    """
    imsh = axim.imshow(img, interpolation=interpolation, aspect=aspect, origin=origin, extent=extent, cmap=cmap)
    if amp_range is not None: imsh.set_clim(amp_range[0],amp_range[1])
    return imsh

def colorbar(fig, imsh, axcb, orientation='vertical', amp_range=None):
    """
    orientation = 'horizontal'
    amp_range = (-10,50)
    """
    if amp_range is not None: imsh.set_clim(amp_range[0],amp_range[1])
    cbar = fig.colorbar(imsh, cax=axcb, orientation=orientation)
    return cbar

def imshow_cbar(fig, axim, axcb, img, amin=None, amax=None, extent=None,\
                interpolation='nearest', aspect='auto', origin='upper',\
                orientation='vertical', cmap='inferno'):
    """
    extent - list of four image physical limits for labeling,
    cmap: 'gray_r'
    #axim.cla()
    """
    axim.cla()
    if img is None: return
    ave = np.mean(img) if amin is None and amax is None else None
    rms = np.std(img)  if amin is None and amax is None else None
    cmin = amin if amin is not None else ave-1*rms if ave is not None else None
    cmax = amax if amax is not None else ave+3*rms if ave is not None else None

    imsh = axim.imshow(img, interpolation=interpolation, aspect=aspect, origin=origin, extent=extent, cmap=cmap, vmin=cmin, vmax=cmax)
    cbar = fig.colorbar(imsh, cax=axcb, orientation=orientation)
    if cmin is not None:
      imsh.set_clim(cmin, cmax)
      #cbar.set_clim(cmin, cmax)
    return imsh, cbar

def test01():
    """ imshow
    """
    img = random_standard(shape=(40,60), mu=200, sigma=25)
    #fig = figure(figsize=(6,5), title='Test imshow', dpi=80, facecolor='w', edgecolor='w', frameon=True, move=(100,10))
    #axim = add_axes(fig, axwin=(0.10, 0.08, 0.85, 0.88))
    fig, axim = fig_img_axes()
    move_fig(fig, x0=200, y0=100)
    imsh = imshow(axim, img, amp_range=None, extent=None,\
           interpolation='nearest', aspect='auto', origin='upper',\
           orientation='horizontal', cmap='jet')

def test02():
    """ hist
    """
    mu, sigma = 200, 25
    arr = random_standard((500,), mu, sigma)
    #fig = figure(figsize=(6,5), title='Test hist', dpi=80, facecolor='w', edgecolor='w', frameon=True, move=(100,10))
    #axhi = add_axes(fig, axwin=(0.10, 0.08, 0.85, 0.88))
    fig, axhi = fig_img_axes()
    his = hist(axhi, arr, bins=100, amp_range=(mu-6*sigma,mu+6*sigma), weights=None, color=None, log=False)

def test03():
    """ Update image in the event loop
    """
    #fig = figure(figsize=(6,5), title='Test hist', dpi=80, facecolor='w', edgecolor='w', frameon=True, move=(100,10))
    #axim = add_axes(fig, axwin=(0.10, 0.08, 0.85, 0.88))
    fig, axim = fig_img_axes()
    imsh = None
    for i in range(10):
       print('Event %3d' % i)
       img = random_standard((1000,1000), mu=200, sigma=25)
       #axim.cla()
       set_win_title(fig, 'Event %d' % i)

       if imsh is None:
           imsh = imshow(axim, img, amp_range=None, extent=None,\
                  interpolation='nearest', aspect='auto', origin='upper',\
                  orientation='horizontal', cmap='jet')
       else:
           imsh.set_data(img)
       show(mode=1)
       #draw_fig(fig)

def test04():
    """ Update histogram in the event loop
    """
    mu, sigma = 200, 25
    #fig = figure(figsize=(6,5), title='Test hist', dpi=80, facecolor='w', edgecolor='w', frameon=True, move=(100,10))
    #axhi = add_axes(fig, axwin=(0.10, 0.08, 0.85, 0.88))
    fig, axhi = fig_img_axes()

    for i in range(10):
       print('Event %3d' % i)
       arr = random_standard((500,), mu, sigma, dtype=np.float)
       axhi.cla()
       set_win_title(fig, 'Event %d' % i)
       his = hist(axhi, arr, bins=100, amp_range=(mu-6*sigma,mu+6*sigma), weights=None, color=None, log=False)

       show(mode=1)
       #draw(fig)

def test05():
    """ Update image with color bar in the event loop
    """
    fig, axim, axcb = fig_img_cbar_axes()
    move_fig(fig, x0=200, y0=0)
    imsh = None
    for i in range(20):
       print('Event %3d' % i)
       img = random_standard((1000,1000), mu=i, sigma=10)
       #axim.cla()
       set_win_title(fig, 'Event %d' % i)
       if imsh is None:
           imsh, cbar = imshow_cbar(fig, axim, axcb, img, amin=None, amax=None, extent=None,\
                                    interpolation='nearest', aspect='auto', origin='upper',\
                                    orientation='vertical', cmap='inferno')
       else:
           imsh.set_data(img)
           ave, rms = img.mean(), img.std()
           imsh.set_clim(ave-1*rms, ave+3*rms)
       show(mode=1)
       #draw_fig(fig)

def test_selected():

    from time import time
    import sys; global sys
    from pyimgalgos.NDArrGenerators import random_standard; global random_standard

    if len(sys.argv)==1:
        print('Use command > python %s <test-number [1-5]>' % sys.argv[0])
        sys.exit ('Add <test-number> in command line...')

    tname = sys.argv[1] if len(sys.argv) > 1 else '1'
    print(50*'_', '\nTest %s' % tname)

    t0_sec=time()
    if   tname == '1': test01()
    elif tname == '2': test02()
    elif tname == '3': test03()
    elif tname == '4': test04()
    elif tname == '5': test05()
    else: sys.exit('Test %s is not implemented' % tname)
    msg = 'Test %s consumed time %.3f' % (tname, time()-t0_sec)
    show()
    sys.exit(msg)

def test_all():
    test01()
    test02()
    show()

if __name__ == "__main__":
    test_selected()
    #test_all()
    print('End of test')

# EOF


import numpy as np
import pandas as pd
import plotly.graph_objects as go

def check(y_test, y_pred):
    if isinstance(y_test, pd.DataFrame):
        y_test = y_test.to_numpy().ravel()
    if isinstance(y_pred, pd.DataFrame):
        y_pred = y_pred.to_numpy()

    # try:
    #     if y_proba.shape[1] == 2:
    #         y_proba = y_proba[:, 1]
    # except IndexError:
    #     pass

    return y_test, y_pred

def compute_confusion_matrix(y_test, y_proba, threshold=0.5, positive_label=1):
    tp = fp = tn = fn = 0
    bool_actuals = [act == positive_label for act in y_test]
    for truth, score in zip(bool_actuals, y_proba):
        if float(score) > float(threshold):
            if truth:
                tp += 1
            else:
                fp += 1
        else:
            if not truth:
                tn += 1
            else:
                fn += 1

    return {"TP": tp, "FP": fp, "TN": tn, "FN": fn}

def aggregate_confusion_matrices(confusion_matrices):
    tp = fp = tn = fn = 0
    for m in confusion_matrices:
        tp += m["TP"]
        fp += m["FP"]
        tn += m["TN"]
        fn += m["FN"]
    agg = {"TP": tp, "FP": fp, "TN": tn, "FN": fn}

    return agg

# def compute_min_max_score(scores):
#     return min(scores), max(scores)

# def agg_compute_thresholds(local_min_max_scores):
#     min_scores = [score[0] for score in local_min_max_scores]
#     max_scores = [score[1] for score in local_min_max_scores]
#     low = min(min_scores)
#     high = max(max_scores)
#     step = (abs(low) + abs(high)) / 1000
#     thresholds = np.arange(low - step, high + step, step)
#
#     return thresholds

# def find_nearest(array, value):
#     array = np.asarray(array)
#     idx = (np.abs(array - value)).argmin()
#     return idx

# def compute_threshold_conf_matrices(actuals, scores, thresholds):
#     confusion_matrices = []
#     for threshold in thresholds:
#         confusion_matrices.append(confusion_matrix(actuals, scores, threshold))
#     return confusion_matrices

# def compute_roc_parameters(confusion_matrices, thresholds):
#     results = {"FPR": list(map(false_positive_rate, confusion_matrices)),
#                "TPR": list(map(true_positive_rate, confusion_matrices)),
#                "THR": thresholds}
#
#     return results

# def roc_plot(fpr, tpr, thresholds):
#     auc = compute_roc_auc(fpr, tpr)
#
#     df = pd.DataFrame(data=[fpr, tpr, thresholds]).transpose()
#     df.columns = ["fpr", "tpr", "thresholds"]
#     plt.title("Receiver operating characteristic")
#     plt.plot(fpr, tpr, color='darkorange', label='AUC: %.3f' % auc)
#     plt.plot([0, 1], [0, 1], color='navy', linestyle='--')
#
#     plt.xlabel('False Positive Rate')
#     plt.ylabel('True Positive Rate')
#     plt.legend()
#
#     return plt, df

# def compute_roc_auc(fpr, tpr):
#     auc = -1 * np.trapz(tpr, fpr)
#     return auc

def false_positive_rate(conf_mtrx):
    fp = conf_mtrx["FP"]
    tn = conf_mtrx["TN"]
    fpr = fp / (fp + tn) if (fp + tn) != 0 else 0
    return fpr

def true_positive_rate(conf_mtrx):
    tp = conf_mtrx["TP"]
    fn = conf_mtrx["FN"]
    tpr = tp / (tp + fn) if (tp + fn) != 0 else 0
    return tpr

def sensitivity(tp, fn):
    sens = tp / (tp + fn) if (tp + fn) != 0 else 0
    return sens

def specificity(tn, fp):
    spec = tn / (tn + fp) if (tn + fp) != 0 else 0
    return spec

def accuracy(tn, tp, fn, fp):
    acc = (tn + tp) / (tn + tp + fn + fp) if (tn + tp + fn + fp) != 0 else 0
    return acc

def precision(tp, fp):
    prec = tp / (tp + fp)
    return prec

def recall(tp, fn):
    rec = tp / (tp + fn)
    return rec

def matthews_corrcoef(tp, tn, fp, fn):
    try:
        mcc = (tp * tn - fp * fn) / (np.sqrt((tp + fp) * (tp + fn) * (tn + fp) * (tn + fn)))
    except:
        mcc = np.nan
    return mcc

def f1(prec, rec):
    f1 = 2 * (prec * rec) / (prec + rec)
    return f1

def create_score_df(conf_mtrx):
    tp = conf_mtrx["TP"]
    tn = conf_mtrx["TN"]
    fp = conf_mtrx["FP"]
    fn = conf_mtrx["FN"]

    sens = sensitivity(tp, fn)
    spec = specificity(tn, fp)
    acc = accuracy(tn, tp, fn, fp)
    prec = precision(tp, fp)
    rec = recall(tp, fn)
    f = f1(prec, rec)
    mcc = matthews_corrcoef(tp, tn, fp, fn)

    scores = ["sensitivity", "specificity", "accuracy", "precision", "recall", "f1_score", "mcc"]
    data = [sens, spec, acc, prec, rec, f, mcc]

    df = pd.DataFrame(list(zip(scores, data)), columns=["metric", "score"])

    return df, data

def create_cv_accumulation(accs, f1s, mccs, precs, recs):
    scores = [accs, f1s, mccs, precs, recs]
    cols = ["accuracy", "f1-score", "mcc", "precision", "recall"]

    df = pd.DataFrame(data=scores).transpose()
    df.columns = cols

    return df

def plot_boxplots(df, title):
    fig = go.Figure()
    fig.add_trace(go.Box(y=df["accuracy"], quartilemethod="linear", name="Accuracy"))
    fig.add_trace(go.Box(y=df["precision"], quartilemethod="linear", name="Precision"))
    fig.add_trace(go.Box(y=df["recall"], quartilemethod="linear", name="Recall"))
    fig.add_trace(go.Box(y=df["f1-score"], quartilemethod="linear", name="f1-score"))
    fig.add_trace(go.Box(y=df["mcc"], quartilemethod="linear", name="MCC"))
    fig.update_layout(title=title)
    fig.update_yaxes(range=[0, 1])

    return fig


import streamlit as st
import pandas as pd
import plotly.express as px

# Set page configuration
st.set_page_config(page_title="Customer Reviews")

with open("style.css") as f:
    st.markdown("<style>{}</style>".format(f.read()), unsafe_allow_html=True)

st.header("Analyzed Customer Reviews")
st.subheader("Ratings from the customer")

excel_file = 'Review_Ans.xlsx'
excel_file2 = 'opinion.xlsx'
sheet = 'Sheet1'

# Takes the following total columns and presents them
st.header("Customer Information")
df = pd.read_excel(excel_file,
                   sheet_name=sheet,
                   usecols='A:C',
                   header=0,)

# Take the opinion excel file and generates a pie chart
st.subheader("Information on the reviews informations")
opinion = pd.read_excel(excel_file2,
                        sheet_name=sheet,
                        usecols='A:C',
                        header=0,)
pie = px.pie(opinion, title="Reviews", values="ProfileName", names="Opinion")

st.button("Send a message")
st.image("whatsapp.png", "Send a message to users", 100)

st.dataframe(df)
st.plotly_chart(pie)


from account.models import User
from rest_framework import authentication
from rest_framework import exceptions
from firebase_admin import auth
from rest_framework.response import Response
from rest_framework import status
from rest_framework.exceptions import AuthenticationFailed

class FirebaseAuthentication(authentication.BaseAuthentication):
    def authenticate(self, request):

        token = request.headers.get('Authorization')
        if not token:
            message = {
                "message": "You don't have enough permission please provide a token",
                "status": status.HTTP_403_FORBIDDEN
                }
            raise AuthenticationFailed(message)

        try:
            decoded_token = auth.verify_id_token(token)
            uid = decoded_token["uid"]
        except:
            message = {
                "message": "You don't have enough permission please provide a valid tocken",
                "status": status.HTTP_403_FORBIDDEN
                }
            raise AuthenticationFailed(message)

        try:
            user = User.objects.get(username=uid)
        except User.DoesNotExist:
            message = {
                "message": "Coudn't find a valid user in our database",
                "status": status.HTTP_403_FORBIDDEN
                }
            raise AuthenticationFailed(message)

        return (user, None)

        # # # Test Only ##
        # user = User.objects.get(username='BkVTy9o8O3Te8CVCkHNvVHXprDn2')
        # return (user, None)


import UCIQE
import UIQM
import cv2
import numpy as np
import os
import glob
import openpyxl
import shutil
import haze
import resize

def fetchimages(path ) :
    return[os.path.join(path,f)for f in os.listdir(path) if (f.endswith('.png') or f.endswith('.jpg') or f.endswith('.jpeg') or f.endswith('.webp')  or f.endswith('.jpeg') or f.endswith('.jfif') )]

def return_resized_images(file):
    image = cv2.imread(file)
    return(resize.resize(image))

def name_of_Image(source , a):

    d =source+ "\\"
    a = a.replace(d, '')
    return a

def paste_resized_images(image , c , nam):
    if(c == 1):
        cv2.imwrite("C:\\Users\\hp\\Desktop\\clear\\d_"+nam,image)
    elif(c == 0):
        cv2.imwrite("C:\\Users\\hp\\Desktop\\degraded\\d_"+nam,image)

def sep(source,degraded,clear,exel, row, m_uism, m_uicm, m_uiqm):

 #Insert the path of the exel sheet in which the values is to be pasted
 re=openpyxl.load_workbook(exel)
 sheet=re['Sheet1']

 filename = fetchimages(source)
 num=0
 i=len(filename)

 k=sheet.cell(row=1,column=1)
 k.value="NAME"
 k=sheet.cell(row=1,column=2)
 k.value="ucique"
 k=sheet.cell(row=1,column=3)
 k.value="uiqm"
 k=sheet.cell(row=1,column=4)
 k.value="uicm"
 k=sheet.cell(row=1,column=5)
 k.value="uism"
 k=sheet.cell(row=1,column=6)
 k.value="uiconm"
 k=sheet.cell(row=1,column=7)
 k.value="Haze"
 k=sheet.cell(row=1,column=8)
 k.value="chroma"
 k=sheet.cell(row=1,column=9)
 k.value="luminance"
 k=sheet.cell(row=1,column=10)
 k.value="saturation"
 k=sheet.cell(row=1,column=11)
 k.value="class"
 ro=row
 co=1

 while (num<i):
     co=1
     image = return_resized_images(filename[num])
     sharpness= UIQM.uism(image)
     colourfullness = UIQM.uicm(image)
     contrast = UIQM.uiconm(image)

     chroma = UCIQE . chroma(image)
     luminance = UCIQE . luminance(image)
     saturation = UCIQE . saturation (image)

     k=sheet.cell(row=ro,column=co)
     nam=name_of_Image(source, filename[num])
     if(row == 2):
         k.value="d_"+nam
     else :
         k.value = nam

     #paste UCIQE value in the excel sheet
     co+=1
     k=sheet.cell(row=ro,column=co)
     k.value=UCIQE.ucique(image)

     co+=1
     k=sheet.cell(row=ro,column=co)
     k.value=(sharpness + colourfullness + contrast)
     m_uiqm = m_uiqm + (sharpness + colourfullness + contrast)

     co+=1
     k=sheet.cell(row=ro,column=co)
     k.value=colourfullness
     m_uicm = m_uicm + colourfullness

     co+=1
     k=sheet.cell(row=ro,column=co)
     k.value=sharpness
     m_uism = m_uism + sharpness

     co+=1
     k=sheet.cell(row=ro,column=co)
     k.value=contrast

     co+=1
     k=sheet.cell(row=ro,column=co)
     k.value= haze.haze(filename[num])

     co+=1
     k=sheet.cell(row=ro,column=co)
     k.value= chroma

     co+=1
     k=sheet.cell(row=ro,column=co)
     k.value= luminance

     co+=1
     k=sheet.cell(row=ro,column=co)
     k.value= saturation

     if(sharpness > 5.00 and colourfullness>4.20  and ((sharpness + colourfullness + contrast)>9.5) and (haze.haze(filename[num]) > 950)):
         #shutil.copy(filename[num], clear)
         #paste_resized_images(image , 1 , nam[last:])
         k=sheet.cell(row=ro,column=11)
         k.value=1
     else:
       #  shutil.copy(filename[num], degraded)
         #paste_resized_images(image , 0 , nam[last:])
         k=sheet.cell(row=ro,column=11)
         k.value=0

     num+=1
     ro+=1
     print(num)
     re.save(exel)

 re.save(exel)

 return ro ,m_uism, m_uicm, m_uiqm


'''
    作者：J.
    日期：2019.4.14
    功能：计算砂地比
    版本：2.0
    2.0 新增功能：分层序计算砂地比，模块化计算程序
'''
import xlrd

def list_section(col_top_depth, top, bottom):
    list_sec = []
    for i, element in enumerate(col_top_depth):
        if element != '顶深' and element >= top and element <= bottom:
            list_sec.append(i)
    return list_sec

def sand_to_strata(col_petrology, top, bottom, col_top_depth, col_bottom_depth):

    list_sand = []

    for i, element in enumerate(col_petrology):
        if '砂岩' in element or '砾岩' in element and '泥质粉砂岩' not in element:
            list_sand.append(i)

    list_sec = list_section(col_top_depth, top, bottom)

    list_sand_in_sec = list(set(list_sand).intersection(list_sec))
    # print(list_sand_in_sec)

    list_sand_to_strata = []
    for i in list_sand_in_sec:
        thickness = col_bottom_depth[i] - col_top_depth[i]
        list_sand_to_strata.append(round(thickness, 2))

    strata_thickness = bottom - top
    sand_to_strata_value = round(sum(list_sand_to_strata) / strata_thickness, 4)
    # print(sum(list_sand_to_strata), strata_thickness)
    return sand_to_strata_value

def main():

    data = xlrd.open_workbook('高11.xlsx')
    table = data.sheets()[0]

    col_top_depth = table.col_values(0)
    col_bottom_depth = table.col_values(1)
    col_petrology = table.col_values(2)

    bottom = col_bottom_depth[len(col_bottom_depth) -1]

    # print(top, bottom)
    #
    # print(sand_to_strata(col_petrology, top, bottom, col_top_depth, col_bottom_depth))

    # 读取层序划分列
    col_strata = table.col_values(6)
    while '' in col_strata:
        col_strata.remove('')

    # print(col_strata)
    Es1s_1 = sand_to_strata(col_petrology, col_strata[1], col_strata[2], col_top_depth, col_bottom_depth)
    Es1s_2 = sand_to_strata(col_petrology, col_strata[2], col_strata[3], col_top_depth, col_bottom_depth)
    Es1s_3 = sand_to_strata(col_petrology, col_strata[3], col_strata[4], col_top_depth, col_bottom_depth)
    Es1xt = sand_to_strata(col_petrology, col_strata[4], col_strata[5], col_top_depth, col_bottom_depth)
    Es1xw = sand_to_strata(col_petrology, col_strata[5], col_strata[6], col_top_depth, col_bottom_depth)
    Es2s = sand_to_strata(col_petrology, col_strata[6], col_strata[7], col_top_depth, col_bottom_depth)
    Es2x = sand_to_strata(col_petrology, col_strata[7], col_strata[8], col_top_depth, col_bottom_depth)
    Es3s = sand_to_strata(col_petrology, col_strata[8], bottom, col_top_depth, col_bottom_depth)
    well_name = table.cell(0, 6).value
    list_final = [well_name, Es1s_1, Es1s_2, Es1s_3, Es1xt, Es1xw, Es2s, Es2x, Es3s]
    print(list_final)

if __name__ == '__main__':
    main()


import requests
import re
import csv

url="https://m.dytt8.net/index2.htm"
domain="https://m.dytt8.net"
resp=requests.get(url)
resp.encoding='gb2312'

obj1=re.compile(r'2022新片精品.*?
(?P
.*?)
',re.S)
obj2=re.compile(r"<a href='(?P<href>.*?)'>",re.S)
obj3=re.compile(r'
(?P<name>.*?)
.*?'
                r'<a target="_blank" href="(?P<link>.*?)">',re.S)
result=obj1.finditer(resp.text)
for it in result:
    ul=it.group('ul')
    result2=obj2.finditer(ul)
    for itt in result2:
        if re.search(r'app',itt.group("href")):
            pass
        else:
            print(itt.group("href"))
            sub_url=domain+itt.group("href")
            sub_resp = requests.get(sub_url)
            sub_resp.encoding="gb2312"
            # print(sub_resp.text)
            result3=obj3.finditer(sub_resp.text)
            f = open("data.csv", mode="+a",encoding="utf-8")
            csvwriter = csv.writer(f)
            for ittt in result3:
                dic=ittt.groupdict()
                csvwriter.writerow(dic.values())
resp.close()
sub_resp.close()


import re, math
import matplotlib.pyplot as plt

infile = 'mypath-1Feb2018.out-2D-GCM'

myfile = open(infile,'r')
mydata = myfile.readlines()

x_out, y_out = [], []
x_exit, y_exit = [], []
x_path, y_path = [], []
actn = []

for line in mydata:
    if re.match('.*Exit point.*',line):   # Actually-attained outer turning points
        mycols = line.split(' ')
        mycols = filter(None,mycols)
        x_exit.append(float(mycols[3]))
        y_exit.append(float(mycols[4]))
        actn.append(float(mycols[5]))
    if re.match('.*path:.*',line):        # Minimum action path
        mycols = line.split(' ')
        mycols = filter(None,mycols)
        x_path.append(float(mycols[1]))
        y_path.append(float(mycols[2]))

plt.plot(x_out, y_out, 'k+')
plt.plot(x_exit, y_exit, 'r^')
plt.plot(x_path, y_path, 'b')
plt.xlim(0,400)
plt.ylim(0,50)
plt.xlabel('q20')
plt.ylabel('q30')

plt.show()

smin = min(actn)
exit_probs = open('exit_probs.out','w')
for x,y,s in zip(x_exit,y_exit,actn):
#    try:
#        prob = 1.0/(1+math.exp(2*s))
#    except:
#        prob = float('inf')
    prob = math.exp(2*(smin-s)) # approximate ratio of tunneling prob compared to max tunneling prob/min action path
    exit_probs.write('{:>5}  {:>5}  {:>12.5}\n'.format(x,y,prob))
exit_probs.close()


import os
import zipfile
import numpy as np
import argparse
import downloader as dld
import zip_extractor as zip
import NMF_experiment as nmf
import unetpipeline as un

def main():

	# reading the command line arguments
	parser = argparse.ArgumentParser(description='Read in file paths and other parameters.')
	parser.add_argument('--technique', choices=['nmf','unet'], help='technique to use to segment neurons', default='nmf', type=str)
	parser.add_argument('--k', help='number of blocks to estimate per block', default="full", type=str)
	parser.add_argument('--max_size', help='max_size maximum size of each region', default="full", type=str)
	parser.add_argument('--min_size', help='min_size minimum size for each region', default=20, type=int)
	parser.add_argument('--max_iter', help='max_iter maximum number of algorithm iterations', default=20, type=int)
	parser.add_argument('--percentile', help='percentile value for thresholding (higher means more thresholding)',  default=95, type=int)
	parser.add_argument('--overlap', help='overlap value for determining whether to merge (higher means fewer merges)', default=0.1, type=float)

	args = parser.parse_args()

    #downloading the data as zip files
	dld.download_data()

    #calling extractor to extract the downloaded files
	zip.extract_zips()

	technique=args.technique
	k_value=args.k
	max_size_value=args.max_size
	min_size_value=args.min_size
	max_iter_value=args.max_iter
	percentile_value=args.percentile
	overlap_value=args.overlap

	if technique =='nmf':
		nmf.NMF_experiments(k=k_value,max_size=max_size_value, min_size=min_size_value,percentile=percentile_value, max_iter=max_iter_value, overlap=overlap_value)
	elif technique=="unet":
		print('Warning: This code is under progress')
		train_image_path,test_image_path,train_region_path=un.get_train_test_region_paths()
		train_images_list=un.get_image_list(train_image_path)
		un.create_nparray(train_images,"train.npy")
		test_images_list=un.get_image_list(test_image_path)
		un.create_nparray(test_images_list,"test.npy")
		mask_list=un.region_to_mask(train_region_path)
		un.train_model()
		result=un.predict()
		masks=un.prepare_masks(result)
		un.masks_to_json(masks)
		un.remove_npy()
if __name__ == '__main__':
	sys.exit(main())


# coding: utf-8
"""
RESTful API for SampleDB
"""
import json
import typing

import flask

from .authentication import multi_auth
from ..utils import Resource, ResponseData
from ...logic.actions import get_action, update_action
from ...logic.action_translations import set_action_translation
from ...logic.languages import Language
from ...logic.action_permissions import get_user_action_permissions, get_actions_with_permissions
from ...logic import errors, utils, actions, action_types
from ...logic.schemas.templates import find_invalid_template_paths
from ...logic.schemas.validate_schema import validate_schema
from ...models import Permissions

__author__ = 'Florian Rhiem <f.rhiem@fz-juelich.de>'

def action_to_json(action: actions.Action) -> typing.Dict[str, typing.Any]:
    return {
        'action_id': action.id,
        'instrument_id': action.instrument_id if not flask.current_app.config['DISABLE_INSTRUMENTS'] else None,
        'user_id': action.user_id,
        'type': {
            action_types.ActionType.SAMPLE_CREATION: 'sample',
            action_types.ActionType.MEASUREMENT: 'measurement',
            action_types.ActionType.SIMULATION: 'simulation'
        }.get(action.type_id, 'custom') if action.type_id is not None else 'custom',
        'type_id': action.type_id,
        'name': utils.get_translated_text(
            action.name,
            language_code='en'
        ) or None,
        'description': utils.get_translated_text(
            action.description,
            language_code='en'
        ) or None,
        'is_hidden': action.is_hidden,
        'schema': action.schema
    }

class Action(Resource):
    @multi_auth.login_required
    def get(self, action_id: int) -> ResponseData:
        try:
            action = get_action(
                action_id=action_id
            )
        except errors.ActionDoesNotExistError:
            return {
                "message": f"action {action_id} does not exist"
            }, 404
        if Permissions.READ not in get_user_action_permissions(action_id=action_id, user_id=flask.g.user.id):
            return flask.abort(403)
        return action_to_json(action)

    @multi_auth.login_required
    def post(self, action_id: int) -> ResponseData:
        try:
            action = get_action(
                action_id=action_id
            )
        except errors.ActionDoesNotExistError:
            return {
                "message": f"action {action_id} does not exist"
            }, 404
        if Permissions.WRITE not in get_user_action_permissions(action_id=action_id, user_id=flask.g.user.id):
            return flask.abort(403)
        if action.fed_id is not None:
            return flask.abort(403)
        action_json = action_to_json(action)
        request_json = flask.request.get_json(force=True)
        if not isinstance(request_json, dict):
            return {
                "message": "JSON object body required"
            }, 400
        name = action.name.get('en')
        description = action.description.get('en')
        short_description = action.short_description.get('en')
        schema = action.schema
        is_hidden = action.is_hidden
        for key in request_json:
            if key not in action_json:
                return {
                    "message": f"invalid key '{key}'"
                }, 400
            if isinstance(request_json[key], str) and '\0' in request_json[key]:
                return {
                    "message": f"{key} must not contain NULL"
                }, 400
            if key == 'name':
                if not isinstance(request_json['name'], str):
                    return {
                        "message": "name must be string"
                    }, 400
                if len(request_json['name']) < 1 or len(request_json['name']) > 100:
                    return {
                        "message": "name must be between 1 and 100 characters long"
                    }, 400
                name = request_json['name']
            elif key == 'description':
                if not isinstance(request_json['description'], str):
                    return {
                        "message": "description must be string"
                    }, 400
                description = request_json['description']
            elif key == 'is_hidden':
                if not isinstance(request_json['is_hidden'], bool):
                    return {
                        "message": "is_hidden must be boolean"
                    }, 400
                is_hidden = request_json['is_hidden']
            elif key == 'schema':
                if not isinstance(request_json['schema'], dict):
                    return {
                        "message": "schema must be dict"
                    }, 400
                schema = request_json['schema']
                error_message = None
                try:
                    invalid_template_paths = find_invalid_template_paths(schema, flask.g.user.id)
                    if invalid_template_paths:
                        raise errors.ValidationError('insufficient permissions for template action', invalid_template_paths[0])
                    validate_schema(schema, invalid_template_action_ids=[] if action is None else [action.id], strict=True)
                except errors.ValidationError as e:
                    error_message = e.message
                except Exception as e:
                    error_message = str(e)
                if error_message is not None:
                    return {
                        "message": error_message
                    }, 400
            else:
                if action_json[key] != request_json[key]:
                    return {
                        "message": f"{key} must be {json.dumps(action_json[key])}"
                    }, 400
        update_action(
            action_id=action_id,
            schema=schema,
            description_is_markdown=action.description_is_markdown,
            is_hidden=is_hidden,
            short_description_is_markdown=action.short_description_is_markdown,
        )
        set_action_translation(
            language_id=Language.ENGLISH,
            action_id=action_id,
            name=name or '',
            description=description or '',
            short_description=short_description or ''
        )
        action = get_action(action_id=action_id)
        return action_to_json(action)

class Actions(Resource):
    @multi_auth.login_required
    def get(self) -> ResponseData:
        actions = get_actions_with_permissions(user_id=flask.g.user.id, permissions=Permissions.READ)
        return [
            action_to_json(action)
            for action in actions
        ]


"""
This module contains these classes: `Layer` and `Layers`.

This module provides all layer stackup functionalities for the Circuit and HFSS 3D Layout tools.
"""
from __future__ import absolute_import  # noreorder

from collections import OrderedDict

from pyaedt.application.Variables import decompose_variable_value
from pyaedt.generic.constants import unit_converter
from pyaedt.generic.general_methods import pyaedt_function_handler

@pyaedt_function_handler()
def _str2bool(str0):
    """Convert a string to a Boolean value.

    Parameters
    ----------
    str0 : str
       String to convert.

    Returns
    -------
    bool
        ``True`` when successful, ``False`` when failed.
    """
    if str0.lower() == "false":
        return False
    elif str0 == "true":
        return True
    else:
        return ""

def _conv_number(number, typen=float):
    """Convert a number.

    Parameters
    ----------
    number : int, float
       Number represented a float.
    typen : type
         The default is ``float``.

    Returns
    -------
    int or float
        Number converted either to ``int`` or ``float``.

    """
    if typen is float:
        try:
            return float(number)
        except:
            return number
    elif typen is int:
        try:
            return int(number)
        except:
            return number

@pyaedt_function_handler()
def _getIfromRGB(rgb):
    """Retrieve if from a specific layer color.

    Parameters
    ----------
    rgb : list
        List representing the color. IT is made of 3 values: blue, green, and red.

    Returns
    -------
    int

    """
    red = rgb[2]
    green = rgb[1]
    blue = rgb[0]
    rgb_int = (red << 16) + (green << 8) + blue
    return rgb_int

@pyaedt_function_handler()
def _getRGBfromI(value):
    """Retrieve the Integer from a specific layer color.

    Parameters
    ----------
    value : int
        Integer value representing the layer color.

    Returns
    -------
    list

    """
    r = (value >> 16) & 0xFF
    g = (value >> 8) & 0xFF
    b = (value >> 0) & 0xFF
    return [r, g, b]

class Layer(object):
    """Manages the stackup layer for the Circuit and HFSS 3D Layout tools.

    Parameters
    ----------
    app : :class:`pyaedt.modules.LayerStackup.Layers`
    layertype : string, optional
        The default is ``"signal"``.
    negative : bool, optional
        Whether the geometry on the layer is cut away
        from the layer. The default is ``False``.

    Examples
    --------
    >>> from pyaedt import Hfss3dLayout
    >>> app = Hfss3dLayout()
    >>> layers = app.modeler.layers["Top"]
    """

    def __init__(self, app, layertype="signal", negative=False):
        self.LengthUnit = app.LengthUnit
        self.LengthUnitRough = app.LengthUnit
        self._layers = app
        self.name = None
        self.type = layertype
        self.id = 0
        self._color = [255, 0, 0]
        self._transparency = 60
        self._is_visible = True
        self._is_visible_shape = True
        self._is_visible_path = True
        self._is_visible_pad = True
        self._is_visible_hole = True
        self._is_visible_component = True
        self._is_mesh_background = True
        self._is_mesh_overlay = True
        self._locked = False
        self._topbottom = "neither"
        self._pattern = 1
        self._drawoverride = 0
        self._thickness = 0
        self._lower_elevation = 0
        self._roughness = 0
        self._botroughness = 0
        self._toprounghenss = 0
        self._sideroughness = 0
        self._material = "copper"
        self._fillmaterial = "FR4_epoxy"
        self._index = 1
        self._is_negative = negative
        self._thickness_units = ""
        # Etch option
        self._useetch = False
        self._etch = 0
        # Rough option
        self._user = False
        self._RMdl = "Huray"
        self._NR = 0.0005
        self._HRatio = 2.9
        self._BRMdl = "Huray"
        self._BNR = 0.0005
        self._BHRatio = 2.9
        self._SRMdl = "Huray"
        self._SNR = 0.0005
        self._SHRatio = 2.9
        # Solver option
        self._usp = False
        self.hfssSp = {"si": True, "dt": 0, "dtv": 0.1}
        self.planaremSp = {"ifg": False, "vly": False}
        self._zones = None

    @property
    def color(self):
        """Return or set the property of the active layer. Color it is list of rgb values (0,255).

        Returns
        -------
        list

        """
        if isinstance(self._color, list):
            return self._color
        else:
            self._color = _getRGBfromI(self._color)
            return self._color

    @color.setter
    def color(self, val):
        if isinstance(val, list):
            self._color = val
        else:
            self._color = _getRGBfromI(val)
        self.update_stackup_layer()

    @property
    def transparency(self):
        """Get/Set the property to the active layer.

        Returns
        -------
        int
        """
        return self._transparency

    @transparency.setter
    def transparency(self, val):
        self._transparency = val
        self.update_stackup_layer()

    @property
    def is_visible(self):
        """Get/Set the active layer visibility.

        Returns
        -------
        bool
        """
        return self._is_visible

    @is_visible.setter
    def is_visible(self, val):
        self._is_visible = val
        self.update_stackup_layer()

    @property
    def is_visible_shape(self):
        """Get/Set the active layer shape visibility.

        Returns
        -------
        bool
        """
        return self._is_visible_shape

    @is_visible_shape.setter
    def is_visible_shape(self, val):
        self._is_visible_shape = val
        self.update_stackup_layer()

    @property
    def is_visible_path(self):
        """Get/Set the active layer paths visibility.

        Returns
        -------
        bool
        """
        return self._is_visible_path

    @is_visible_path.setter
    def is_visible_path(self, val):
        self._is_visible_path = val
        self.update_stackup_layer()

    @property
    def is_visible_pad(self):
        """Get/Set the active layer pad visibility.

        Returns
        -------
        bool
        """
        return self._is_visible_pad

    @is_visible_pad.setter
    def is_visible_pad(self, val):
        self._is_visible_pad = val
        self.update_stackup_layer()

    @property
    def is_visible_hole(self):
        """Get/Set the active layer hole visibility.

        Returns
        -------
        bool
        """
        return self._is_visible_hole

    @is_visible_hole.setter
    def is_visible_hole(self, val):
        self._is_visible_hole = val
        self.update_stackup_layer()

    @property
    def is_visible_component(self):
        """Get/Set the active layer component visibility.

        Returns
        -------
        bool
        """
        return self._is_visible_component

    @is_visible_component.setter
    def is_visible_component(self, val):
        self._is_visible_component = val
        self.update_stackup_layer()

    @property
    def is_mesh_background(self):
        """Get/Set the active layer mesh backgraound.

        Returns
        -------
        bool
        """
        return self._is_mesh_background

    @is_mesh_background.setter
    def is_mesh_background(self, val):
        self._is_mesh_background = val
        self.update_stackup_layer()

    @property
    def is_mesh_overlay(self):
        """Get/Set the active layer mesh overlay.

        Returns
        -------
        bool
        """
        return self._is_mesh_overlay

    @is_mesh_overlay.setter
    def is_mesh_overlay(self, val):
        self._is_mesh_overlay = val
        self.update_stackup_layer()

    @property
    def locked(self):
        """Get/Set the active layer lock flag.

        Returns
        -------
        bool
        """
        return self._locked

    @locked.setter
    def locked(self, val):
        self._locked = val
        self.update_stackup_layer()

    @property
    def top_bottom(self):
        """Get/Set the active layer top bottom alignment.

        Returns
        -------
        str
        """
        return self._topbottom

    @top_bottom.setter
    def top_bottom(self, val):
        self._topbottom = val
        self.update_stackup_layer()

    @property
    def pattern(self):
        """Get/Set the active layer pattern.

        Returns
        -------
        float
        """
        return self._pattern

    @pattern.setter
    def pattern(self, val):
        self._pattern = val
        self.update_stackup_layer()

    @property
    def draw_override(self):
        """Get/Set the active layer draw override value.

        Returns
        -------
        float
        """
        return self._drawoverride

    @draw_override.setter
    def draw_override(self, val):
        self._drawoverride = val
        self.update_stackup_layer()

    @property
    def thickness(self):
        """Get/Set the active layer thickness value.

        Returns
        -------
        float
        """
        return self._thickness

    @thickness.setter
    def thickness(self, val):
        self._thickness = self._arg_with_dim(val, self.thickness_units)
        self.update_stackup_layer()
        tck = decompose_variable_value(self._thickness)
        self._thickness = tck[0]
        self._thickness_units = tck[1]

    @property
    def upper_elevation(self):
        """Get the active layer upper elevation value with units.

        Returns
        -------
        float
        """
        return (
            unit_converter(self.thickness, input_units=self.thickness_units, output_units=self.LengthUnit)
            + self.lower_elevation
        )

    @property
    def thickness_units(self):
        """Get the active layer thickness units value.

        Returns
        -------
        str
        """
        return self._thickness_units

    @property
    def lower_elevation(self):
        """Get/Set the active layer lower elevation.

        Returns
        -------
        float
        """
        return self._lower_elevation

    @lower_elevation.setter
    def lower_elevation(self, val):
        self._lower_elevation = val
        self.update_stackup_layer()

    @property
    def roughness(self):
        """Return or set the active layer roughness (with units).

        Returns
        -------
        str
        """
        return self._roughness

    @roughness.setter
    def roughness(self, value):
        self._roughness = value
        self.update_stackup_layer()

    @property
    def bottom_roughness(self):
        """Return or set the active layer bottom roughness (with units).

        Returns
        -------
        str
        """
        return self._botroughness

    @bottom_roughness.setter
    def bottom_roughness(self, value):
        self._botroughness = value
        self.update_stackup_layer()

    @property
    def top_roughness(self):
        """Get/Set the active layer top roughness (with units).

        Returns
        -------
        str
        """
        return self._toprounghenss

    @top_roughness.setter
    def top_roughness(self, val):
        self._toprounghenss = val
        self.update_stackup_layer()

    @property
    def side_roughness(self):
        """Get/Set the active layer side roughness (with units).

        Returns
        -------
        str
        """
        return self._sideroughness

    @side_roughness.setter
    def side_roughness(self, val):
        self._sideroughness = val
        self.update_stackup_layer()

    @property
    def material(self):
        """Get/Set the active layer material name.

        Returns
        -------
        str
        """
        return self._material

    @material.setter
    def material(self, val):
        self._material = val
        self.update_stackup_layer()

    @property
    def fill_material(self):
        """Get/Set the active layer filling material.

        Returns
        -------
        str
        """
        return self._fillmaterial

    @fill_material.setter
    def fill_material(self, val):
        self._fillmaterial = val
        self.update_stackup_layer()

    @property
    def index(self):
        """Get/Set the active layer index.

        Returns
        -------
        int
        """
        return self._index

    @index.setter
    def index(self, val):
        self._index = val
        self.update_stackup_layer()

    @property
    def is_negative(self):
        """Get/Set the active layer negative flag. When `True` the layer will be negative.

        Returns
        -------
        bool
        """
        return self._is_negative

    @is_negative.setter
    def is_negative(self, val):
        self._is_negative = val
        self.update_stackup_layer()

    @property
    def use_etch(self):
        """Get/Set the active layer etiching flag. When `True` the layer will use etch.

        Returns
        -------
        bool
        """
        return self._useetch

    @use_etch.setter
    def use_etch(self, val):
        self._useetch = val
        self.update_stackup_layer()

    @property
    def etch(self):
        """Get/Set the active layer etch value.

        Returns
        -------
        float
        """
        return self._etch

    @etch.setter
    def etch(self, val):
        self._etch = val
        self.update_stackup_layer()

    @property
    def user(self):
        """Get/Set the active layer user flag.

        Returns
        -------
        bool
        """
        return self._user

    @user.setter
    def user(self, val):
        self._user = val
        self.update_stackup_layer()

    @property
    def top_roughness_model(self):
        """Get/Set the active layer top roughness model.

        Returns
        -------
        str
        """
        return self._RMdl

    @top_roughness_model.setter
    def top_roughness_model(self, val):
        self._RMdl = val
        self.update_stackup_layer()

    @property
    def top_nodule_radius(self):
        """Get/Set the active layer top roughness radius.

        Returns
        -------
        float
        """
        return self._NR

    @top_nodule_radius.setter
    def top_nodule_radius(self, val):
        self._NR = val
        self.update_stackup_layer()

    @property
    def top_huray_ratio(self):
        """Get/Set the active layer top roughness ratio.

        Returns
        -------
        float
        """
        return self._HRatio

    @top_huray_ratio.setter
    def top_huray_ratio(self, val):
        self._HRatio = val
        self.update_stackup_layer()

    @property
    def bottom_roughness_model(self):
        """Get/Set the active layer bottom roughness model.

        Returns
        -------
        str
        """
        return self._BRMdl

    @bottom_roughness_model.setter
    def bottom_roughness_model(self, val):
        self._BRMdl = val
        self.update_stackup_layer()

    @property
    def bottom_nodule_radius(self):
        """Get/Set the active layer bottom roughness radius.

        Returns
        -------
        float
        """
        return self._BNR

    @bottom_nodule_radius.setter
    def bottom_nodule_radius(self, val):
        self._BNR = val
        self.update_stackup_layer()

    @property
    def bottom_huray_ratio(self):
        """Get/Set the active layer bottom roughness ratio.

        Returns
        -------
        float
        """
        return self._BHRatio

    @bottom_huray_ratio.setter
    def bottom_huray_ratio(self, val):
        self._BHRatio = val
        self.update_stackup_layer()

    @property
    def side_model(self):
        """Get/Set the active layer side roughness model.

        Returns
        -------
        str
        """
        return self._SRMdl

    @side_model.setter
    def side_model(self, val):
        self._SRMdl = val
        self.update_stackup_layer()

    @property
    def side_nodule_radius(self):
        """Get/Set the active layer side roughness radius.

        Returns
        -------
        float
        """
        return self._SNR

    @side_nodule_radius.setter
    def side_nodule_radius(self, val):
        self._SNR = val
        self.update_stackup_layer()

    @property
    def side_huray_ratio(self):
        """Get/Set the active layer bottom roughness ratio.

        Returns
        -------
        float
        """
        return self._SHRatio

    @side_huray_ratio.setter
    def side_huray_ratio(self, val):
        self._SHRatio = val
        self.update_stackup_layer()

    @property
    def usp(self):
        """Get/Set the active layer usp flag.

        Returns
        -------
        bool
        """
        return self._usp

    @usp.setter
    def usp(self, val):
        self._usp = val
        self.update_stackup_layer()

    @property
    def hfss_solver_settings(self):
        """Get/Set the active layer hfss solver settings.

        Returns
        -------
        dict
        """
        return self.hfssSp

    @hfss_solver_settings.setter
    def hfss_solver_settings(self, val):
        self.hfssSp = val
        self.update_stackup_layer()

    @property
    def planar_em_solver_settings(self):
        """Get/Set the active layer PlanarEm solver settings.

        Returns
        -------
        dict
        """
        return self.planaremSp

    @planar_em_solver_settings.setter
    def planar_em_solver_settings(self, val):
        self.planaremSp = val
        self.update_stackup_layer()

    @property
    def zones(self):
        """Get/Set the active layer zoness.

        Returns
        -------
        list
        """
        if self._zones is None:
            self._zones = [i for i in self._layers.all_layers if self.name in i and ";" in i]
        return self._zones

    @zones.setter
    def zones(self, val):
        self._zones = val
        self.update_stackup_layer()

    @property
    def oeditor(self):
        """Oeditor Module."""
        return self._layers.oeditor

    @property
    def visflag(self):
        """Visibility flag for objects on the layer."""
        visflag = 0
        if not self._is_visible:
            visflag = 0
        else:
            if self._is_mesh_background:
                visflag += 64
            if self._is_mesh_overlay:
                visflag += 32
            if self._is_visible_shape:
                visflag += 1
            if self._is_visible_path:
                visflag += 2
            if self.is_visible_pad:
                visflag += 4
            if self._is_visible_hole:
                visflag += 8
            if self._is_visible_component:
                visflag += 16
        return visflag

    @pyaedt_function_handler()
    def set_layer_color(self, r, g, b):
        """Update the color of the layer.

        Parameters
        ----------
        r : int
            Red color value.
        g : int
            Green color value.
        b :  int
            Blue color value.

        Returns
        -------
        bool
            ``True`` when successful, ``False`` when failed.

        References
        ----------

        >>> oEditor.ChangeLayer
        """
        rgb = [r, g, b]
        self.color = _getIfromRGB(rgb)
        return True

    @pyaedt_function_handler()
    def create_stackup_layer(self):
        """Create a stackup layer.

        Returns
        -------
        bool
            ``True`` when successful, ``False`` when failed.

        References
        ----------

        >>> oEditor.AddStackupLayer
        """
        self.remove_stackup_layer()
        self.oeditor.AddStackupLayer(self._get_layer_arg)
        infos = self.oeditor.GetLayerInfo(self.name)
        infos = [i.split(": ") for i in infos]
        infosdict = {i[0]: i[1] for i in infos}
        self.id = int(infosdict["LayerId"])

        return True

    @pyaedt_function_handler()
    def _arg_with_dim(self, value, units=None):
        """Argument with dimensions.

        Parameters
        ----------
        value : str, float
            Value of the quantity.
        units :
            Unit of the quantity. The default is ``None``.

        Returns
        -------
        str
            String containing both the value and the unit properly formatted.

        """
        if units is None:
            units = self.LengthUnit
        if type(value) is str:
            try:
                float(value)
                val = "{0}{1}".format(value, units)
            except:
                val = value
        else:
            val = "{0}{1}".format(value, units)
        return val

    @property
    def _get_layer_arg(self):
        if self.type in ["signal", "via", "dielectric"]:
            args = [
                "NAME:stackup layer",
                "Name:=",
                self.name,
            ]
        else:
            args = [
                "NAME:layer",
                "Name:=",
                self.name,
            ]
        if self.id > 0:
            args.extend(
                ["ID:=", self.id],
            )
        if self.type == "signal":
            args.extend(
                [
                    "Type:=",
                    self.type,
                    "Top Bottom:=",
                    self.top_bottom,
                    "Color:=",
                    _getIfromRGB(self.color),
                    "Transparency:=",
                    self.transparency,
                    "Pattern:=",
                    self.pattern,
                    "VisFlag:=",
                    self.visflag,
                    "Locked:=",
                    self.locked,
                    "DrawOverride:=",
                    self.draw_override,
                    "Zones:=",
                    self.zones,
                    [
                        "NAME:Sublayer",
                        "Thickness:=",
                        self._arg_with_dim(self.thickness, self.thickness_units),
                        "LowerElevation:=",
                        self._arg_with_dim(self.lower_elevation, self.LengthUnit),
                        "Roughness:=",
                        self._arg_with_dim(self.roughness, self.LengthUnitRough),
                        "BotRoughness:=",
                        self._arg_with_dim(self.bottom_roughness, self.LengthUnitRough),
                        "SideRoughness:=",
                        self._arg_with_dim(self.top_roughness, self.LengthUnitRough),
                        "Material:=",
                        self._layers._app.materials[self.material].name if self.material != "" else "",
                        "FillMaterial:=",
                        self._layers._app.materials[self.fill_material].name if self.fill_material != "" else "",
                    ],
                    "Neg:=",
                    self._is_negative,
                    "Usp:=",
                    self.usp,
                    [
                        "NAME:Sp",
                        "Sn:=",
                        "HFSS",
                        "Sv:=",
                        "so(si="
                        + str(self.hfssSp["si"]).lower()
                        + " , dt="
                        + str(self.hfssSp["dt"])
                        + ", dtv='"
                        + self._arg_with_dim(self.hfssSp["dtv"])
                        + "')",
                    ],
                    [
                        "NAME:Sp",
                        "Sn:=",
                        "PlanarEM",
                        "Sv:=",
                        "so(ifg="
                        + str(self.planaremSp["ifg"]).lower()
                        + ", vly="
                        + str(self.planaremSp["vly"]).lower()
                        + ")",
                    ],
                    "Etch:=",
                    str(self.etch),
                    "UseEtch:=",
                    self.use_etch,
                    "UseR:=",
                    self.user,
                    "RMdl:=",
                    self._RMdl,
                    "NR:=",
                    self._arg_with_dim(self._NR, self.LengthUnitRough),
                    "HRatio:=",
                    str(self._HRatio),
                    "BRMdl:=",
                    self._BRMdl,
                    "BNR:=",
                    self._arg_with_dim(self._BNR, self.LengthUnitRough),
                    "BHRatio:=",
                    str(self._BHRatio),
                    "SRMdl:=",
                    self._SRMdl,
                    "SNR:=",
                    self._arg_with_dim(self._SNR, self.LengthUnitRough),
                    "SHRatio:=",
                    str(self._SHRatio),
                ]
            )
        elif self.type == "dielectric":
            args.extend(
                [
                    "Type:=",
                    self.type,
                    "Top Bottom:=",
                    self.top_bottom,
                    "Color:=",
                    self.color,
                    "Transparency:=",
                    self.transparency,
                    "Pattern:=",
                    self.pattern,
                    "VisFlag:=",
                    self.visflag,
                    "Locked:=",
                    self.locked,
                    "DrawOverride:=",
                    self.draw_override,
                    "Zones:=",
                    self.zones,
                    [
                        "NAME:Sublayer",
                        "Thickness:=",
                        self._arg_with_dim(self.thickness, self.thickness_units),
                        "LowerElevation:=",
                        self._arg_with_dim(self.lower_elevation, self.LengthUnit),
                        "Roughness:=",
                        0,
                        "BotRoughness:=",
                        0,
                        "SideRoughness:=",
                        0,
                        "Material:=",
                        self.material,
                    ],
                ]
            )
        else:
            args.extend(
                [
                    "Type:=",
                    self.type,
                    "Top Bottom:=",
                    self.top_bottom,
                    "Color:=",
                    self.color,
                    "Transparency:=",
                    self.transparency,
                    "Pattern:=",
                    self.pattern,
                    "VisFlag:=",
                    self.visflag,
                    "Locked:=",
                    self.locked,
                ]
            )
        return args

    @pyaedt_function_handler()
    def update_stackup_layer(self):
        """Update the stackup layer.

        .. note::
           This method is valid for release 2021 R1 and later.
           This method works only for signal and dielectric layers.

        Returns
        -------
        bool
            ``True`` when successful, ``False`` when failed.

        References
        ----------

        >>> oEditor.ChangeLayer
        """
        self.oeditor.ChangeLayer(self._get_layer_arg)
        return True

    @pyaedt_function_handler()
    def remove_stackup_layer(self):
        """Remove the stackup layer.

        Returns
        -------
        bool
            ``True`` when successful, ``False`` when failed.

        References
        ----------

        >>> oEditor.RemoveLayer
        """
        if self.name in self.oeditor.GetStackupLayerNames():
            self.oeditor.RemoveLayer(self.name)
            return True
        return False

class Layers(object):
    """Manages stackup for the Circuit and HFSS 3D Layout tools.

    Parameters
    ----------
    modeler : :class:`pyaedt.modeler.modelerpcb.Modeler3DLayout`

    roughnessunits : str, optional
       Units for the roughness of layers. The default is ``"um"``.

    Examples
    --------
    >>> from pyaedt import Hfss3dLayout
    >>> app = Hfss3dLayout()
    >>> layers = app.modeler.layers
    """

    def __init__(self, modeler, roughnessunits="um"):
        self._modeler = modeler
        self._app = self._modeler._app
        self._currentId = 0
        self.lengthUnitRough = roughnessunits
        self.logger = self._app.logger

    @property
    def oeditor(self):
        """Editor.

        References
        ----------

        >>> oEditor = oDesign.SetActiveEditor("Layout")
        """
        return self._modeler.oeditor

    @property
    def zones(self):
        """List of all available zones.

        Returns
        -------
        list
        """
        all_layers = list(self._modeler.oeditor.GetStackupLayerNames())
        zones = []
        for lay in all_layers:
            if ";" in lay:
                zones.append(lay.split(";")[0])
        return list(set(zones))

    @property
    def LengthUnit(self):
        """Length units."""
        return self._modeler.model_units

    @property
    def all_layers(self):
        """All stackup layers.

        Returns
        -------
        list
           List of stackup layers.

        References
        ----------

        >>> oEditor.GetStackupLayerNames()
        """
        return [i for i in self.oeditor.GetAllLayerNames() if ";" not in i]

    @property
    def drawing_layers(self):
        """All drawing layers.

        Returns
        -------
        list
           List of drawing layers.

        References
        ----------

        >>> oEditor.GetAllLayerNames()
        """
        return [v for k, v in self.layers.items() if v.type not in ["signal", "via", "dielectric"]]

    @property
    def stackup_layers(self):
        """All stackup layers.

        Returns
        -------
        List of :class:`pyaedt.modules.LayerStackup.Layer`
           List of stackup layers.

        References
        ----------

        >>> oEditor.GetAllLayerNames()
        """
        return [v for k, v in self.layers.items() if v.type in ["signal", "via", "dielectric"]]

    @property
    def all_signal_layers(self):
        """All signal layers.

        Returns
        -------
        List of :class:`pyaedt.modules.LayerStackup.Layer`
            List of signal layers.
        """
        return [v for k, v in self.layers.items() if v.type == "signal"]

    @property
    def signals(self):
        """All signal layers.

        Returns
        -------
        Dict[str, :class:`pyaedt.modules.LayerStackup.Layer`]
           Conductor layers.

        References
        ----------

        >>> oEditor.GetAllLayerNames()
        """
        return {k: v for k, v in self.layers.items() if v.type == "signal"}

    @property
    def dielectrics(self):
        """All dielectric layers.

        Returns
        -------
        Dict[str, :class:`pyaedt.modules.LayerStackup.Layer`]
           Dielectric layers.

        References
        ----------

        >>> oEditor.GetAllLayerNames()
        """
        return {k: v for k, v in self.layers.items() if v.type == "dielectric"}

    @property
    def drawings(self):
        """All stackup layers.

        Returns
        -------
        Dict[str, :class:`pyaedt.modules.LayerStackup.Layer`]
           Drawing layers.

        References
        ----------

        >>> oEditor.GetAllLayerNames()
        """
        return {k: v for k, v in self.layers.items() if v.type in ["signal", "via", "dielectric"]}

    @property
    def all_diel_layers(self):
        """All dielectric layers.

        Returns
        -------
        List of :class:`pyaedt.modules.LayerStackup.Layer`
            List of dielectric layers.
        """
        return [v for k, v in self.layers.items() if v.type == "dielectric"]

    @pyaedt_function_handler()
    def layer_id(self, name):
        """Retrieve a layer ID.

        Parameters
        ----------
        name : str
            Name of the layer.

        Returns
        -------
        :class:`pyaedt.modules.LayerStackup.Layer`
            Layer objecy if the layer name exists.
        """
        for el in self.layers:
            if self.layers[el].name == name:
                return el
        return None

    @property
    def layers(self):
        """Refresh all layers in the current stackup.

        Returns
        -------
         Dict[int, :class:`pyaedt.modules.LayerStackup.Layer`]
            Number of layers in the current stackup.
        """
        layers = OrderedDict({})
        for el in self.all_layers:
            o = Layer(self, "signal")
            o.name = el
            infos = self.oeditor.GetLayerInfo(el)
            infos = [i.split(": ") for i in infos]
            infosdict = {i[0].strip(): i[1].strip() for i in infos}
            o.id = int(infosdict["LayerId"])
            if infosdict["Type"] == "metalizedsignal":
                o.type = "signal"
                o._is_negative = True
            else:
                o.type = infosdict["Type"]
                o._is_negative = False
            o._locked = _str2bool(infosdict["IsLocked"])
            o._top_bottom = infosdict["TopBottomAssociation"].lower()
            o._is_visible = _str2bool(infosdict["IsVisible"])
            if "IsVisiblePath" in infosdict:
                o._is_visible_path = _str2bool(infosdict["IsVisiblePath"])
                o._is_visible_pad = _str2bool(infosdict["IsVisiblePad"])
                o._is_visible_component = _str2bool(infosdict["IsVisibleComponent"])
                o._is_visible_shape = _str2bool(infosdict["IsVisibleShape"])
                o._is_visible_hole = _str2bool(infosdict["IsVisibleHole"])
            o._color = _getRGBfromI(int(infosdict["Color"][:-1]))
            if o.type in ["signal", "dielectric", "via"]:
                o._index = int(infosdict["Index"])
                tck = decompose_variable_value(infosdict["LayerThickness"])
                o._thickness = tck[0]
                o._thickness_units = tck[1] if tck[1] else "meter"
                tck = decompose_variable_value(infosdict["LowerElevation0"])

                o._lower_elevation = tck[0]
                o.LengthUnit = tck[1] if tck[1] else "meter"
                o._fillmaterial = infosdict["FillMaterial0"]
                o._material = infosdict["Material0"]
                if "EtchFactor" in infosdict:
                    o._useetch = True
                    o._etch = decompose_variable_value(infosdict["EtchFactor"])[0]
                if "Roughness0 Type" in infosdict:
                    o._user = True
                    o._RMdl = infosdict["Roughness0 Type"]
                    o._NR = infosdict["Roughness0"].split(", ")[0]
                    o._HRatio = decompose_variable_value(infosdict["Roughness0"].split(", ")[1])[0]
                if "BottomRoughness0 Type" in infosdict:
                    o._user = True
                    o._BRMdl = infosdict["BottomRoughness0 Type"]
                    o._BNR = infosdict["BottomRoughness0"].split(", ")[0]
                    o._BHRatio = decompose_variable_value(infosdict["BottomRoughness0"].split(", ")[1])[0]
                if "SideRoughness0 Type" in infosdict:
                    o._user = True
                    o._SRMdl = infosdict["SideRoughness0 Type"]
                    o._SNR = infosdict["SideRoughness0"].split(", ")[0]
                    o._SHRatio = decompose_variable_value(infosdict["SideRoughness0"].split(", ")[1])[0]
            layers[o.id] = o
        return layers

    @pyaedt_function_handler()
    def add_layer(
        self, layername, layertype="signal", thickness="0mm", elevation="0mm", material="copper", isnegative=False
    ):
        """Add a layer.

        Parameters
        ----------
        layername : str
            Name of the layer.
        layertype : str, optional
            Type of the layer. The default is ``"signal"``.
        thickness : str, optional
            Thickness with units. The default is ``"0mm"``.
        elevation : str, optional
            Elevation with units. The default is ``"0mm"``.
        material : str, optional
            Name of the material. The default is ``"copper"``.
        isnegative : bool, optional
            If ``True``, the geometry on the layer is cut away from the layer. The default is ``False``.

        Returns
        -------
        :class:`pyaedt.modules.LayerStackup.Layer`
            Layer object.
        """
        newlayer = Layer(self, layertype, isnegative)
        newlayer.name = layername
        newlayer._thickness = thickness

        if elevation == "0mm":
            el = (
                0
                if list(self.layers.values())[0].type not in ["dielectric", "signal", "via"]
                else "{}{}".format(
                    list(self.layers.values())[0].upper_elevation, list(self.layers.values())[0].LengthUnit
                )
            )
            if el:
                newlayer._lower_elevation = el
            else:
                newlayer._lower_elevation = "0mm"
        else:
            newlayer._lower_elevation = elevation
        newlayer._material = material
        newlayer.create_stackup_layer()

        return self.layers[newlayer.id]

    @pyaedt_function_handler()
    def change_stackup_type(self, mode="MultiZone", number_zones=3):
        """Change the stackup type between Multizone, Overlap and Laminate.

        Parameters
        ----------
        mode : str, optional
            Stackup type. Default is `"Multizone"`. Options are `"Overlap"` and `"Laminate"`.
        number_zones : int, optional
            Number of zones of multizone. By default all layers will be enabled in all zones.

        Returns
        -------
        bool
            `True` if successful.
        """
        if mode.lower() == "multizone":
            zones = ["NAME:Zones", "Primary"]
            for i in range(number_zones):
                zones.append("Zone{}".format(i + 1))
            args = ["NAME:layers", "Mode:=", "Multizone", zones, ["NAME:pps"]]
        elif mode.lower() == "overlap":
            args = args = ["NAME:layers", "Mode:=", "Overlap", ["NAME:pps"]]
        elif mode.lower() == "laminate":
            args = args = ["NAME:layers", "Mode:=", "Laminate", ["NAME:pps"]]
        else:
            self.logger.error("Stackup mode has to be Multizone, Overlap or Laminate.")
            return False
        for v in list(self.layers.values()):
            if v.type in ["signal", "dielectric"]:
                if mode.lower() == "multizone":
                    v._zones = [i for i in range(number_zones)]
                else:
                    v._zones = []
            args.append(v._get_layer_arg)
        self.oeditor.ChangeLayers(args)
        return True


from plyer import notification
import time

notification_title="TAKE CARE OF YOURSELF"
notification_message="Please Drink water in every two hours"
while(True):

    notification.notify(
        title = notification_title,
        message = notification_message,
        app_icon = "D:/CODING/PYTHON/DAY_94/1.ico",
        timeout = 8,
        toast = False
    )
    time.sleep(60*60*2)