import io
import logging
import requests
from pastehunter.common import parse_config
conf = parse_config()

logger = logging.getLogger('pastehunter')

def upload_file(raw_file, paste_object):
    try:
        task_id = send_to_cuckoo(raw_file, paste_object["pasteid"])
        paste_object["Cuckoo Task ID"] = task_id
        logger.info("exe submitted to Cuckoo with task id {0}".format(task_id))
    except Exception as e:
        logger.error("Unabled to submit sample to cuckoo")

    # Send any updated json back
    return paste_object

def send_to_cuckoo(raw_exe, pasteid):
    cuckoo_ip = conf["sandboxes"]["cuckoo"]["api_host"]
    cuckoo_port = conf["sandboxes"]["cuckoo"]["api_port"]
    cuckoo_host = 'http://{0}:{1}'.format(cuckoo_ip, cuckoo_port)
    submit_file_url = '{0}/tasks/create/file'.format(cuckoo_host)
    files = {'file': ('{0}.exe'.format(pasteid), io.BytesIO(raw_exe))}
    submit_file = requests.post(submit_file_url, files=files).json()
    task_id = None
    try:
        task_id = submit_file['task_id']
    except KeyError:
        try:
            task_id = submit_file['task_ids'][0]
        except KeyError:
            logger.error(submit_file)

    return task_id


import urllib.request
import cv2
import numpy as np
import time
import csv
from datetime import datetime

font = cv2.FONT_HERSHEY_SIMPLEX
bottomLeftCornerOfText = (10,600)
fontScale = 1
fontColor = (0,0,0)
thickness = 2
lineType = 2

url = 'http://192.168.4.1/capture'

# Calibration left thermometer
#temperature value 1
t1_F1 = 70
#pixel location of temperature in y axis 1
t1_P1 = 245
#temperature value 2
t1_F2 = 40
#pixel location of temperature in y axis 2
t1_P2 = 552

# Calibration right thermometer (if used)
t2_F1 = 70
t2_P1 = 229
t2_F2 = 40
t2_P2 = 535

# range of blue colors that will be detected based on blue image acquired before
img = cv2.imread("/Users/damianwilliams/Desktop/blue.jpg")
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
mu, sig = cv2.meanStdDev(hsv)

#--------------------------##------------Range of blue_values______________##

a = 15
#--------------------------##----------------------------------------------##

#--------------------------##------------threshold for rectangle size defined as liquid column size (ignores small
# area)______________##

minArea = 2000
#--------------------------##-------------------------------------------------------------------------------------------------------------##

change_resolution= urllib.request.urlopen("http://192.168.4.1/a?ql=6", timeout=5)
time.sleep(2)
change_resolution.close()

def CalculateTemp(temp1, temp2, pixel1, pixel2, yval):
    pix_per_deg = (pixel2 - pixel1) / (temp2 - temp1)
    pixels_diff = yval - pixel2
    delta_fah = pixels_diff / pix_per_deg
    fahrenheit = temp2 + delta_fah
    celcius = ((fahrenheit - 32) * (5 / 9))
    temps = [celcius,fahrenheit]
    return temps

idx = 0

while True:

    with open(url, "a") as f:
        writer = csv.writer(f, delimiter=",")

    try:

        imgResp = urllib.request.urlopen(url, timeout=10)
        print(imgResp)

        imgNp = np.array(bytearray(imgResp.read()), dtype=np.uint8)
        img = cv2.imdecode(imgNp, -1)

        #Crop image
        img = img[400:1000 + 50, 600:1500 + 100]
        #cv2.imshow("orig_thresh", img)

        Image_for_detection = img
        Thermometer_image = img

        height_image, width_image, channels_image = Image_for_detection.shape
        print(f'image dimensions (pixels):, height =  {height_image}, width = {width_image}')

        # Mask for blue color
        therm_hsv = cv2.cvtColor(Image_for_detection, cv2.COLOR_BGR2HSV)
        therm_hsv = cv2.inRange(therm_hsv, mu - a * sig, mu + a * sig)

# --------------------------##------------Parameters that will fill any small gaps in the color mask that
        # encompasses the thermometer-------##

        kernel = np.ones((3, 3), np.uint8)
        dilated_image = cv2.dilate(therm_hsv, kernel, iterations=1)

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

        mask_image = cv2.cvtColor(dilated_image, cv2.COLOR_GRAY2RGB)
        contours, hierarchy = cv2.findContours(image=dilated_image, mode=cv2.RETR_TREE, method=cv2.CHAIN_APPROX_NONE)

        number_regions_found = 0

        for cnt in contours:
            x, y, w, h = cv2.boundingRect(cnt)
            area = cv2.contourArea(cnt)

            if area > minArea:

                #defines area where left thermometer would be found
                if x < 500:

                    ##########################################################################################
                    Thermometer_image = cv2.rectangle(Thermometer_image, (x, y), (x + w, y + h), (0, 255, 0), 1)
                    mask_image = cv2.rectangle(mask_image, (x, y), (x + w, y + h), (0, 255, 0), 1)
                    ##########################################################################################

                    therm_reading_1 = CalculateTemp(t1_F1, t1_F2, t1_P1, t1_P2, y)
                    therm_1_stringC = "%.1f" % round(therm_reading_1[0], 1)
                    print("Therm 1 Calculated_value: " + therm_1_stringC)
                    therm_1_stringF = "%.1f" % round(therm_reading_1[1], 1)
                    print("Therm 1 Calculated_value: " + therm_1_stringF)
                    number_regions_found = 1

                else:
                    #################################################################################################
                    Thermometer_image = cv2.rectangle(Thermometer_image, (x, y), (x + w, y + h), (0, 0, 255), 1)
                    mask_image = cv2.rectangle(mask_image, (x, y), (x + w, y + h), (0, 0, 255), 1)
                    #################################################################################################

                    therm_reading_2 = CalculateTemp(t2_F1, t2_F2, t2_P1, t2_P2, y)
                    therm_2_stringC = "%.1f" % round(therm_reading_2[0], 1)
                    print("Therm 2 Calculated_value C: " + therm_2_stringC)
                    therm_2_stringF = "%.1f" % round(therm_reading_2[1], 1)
                    print("Therm 2 Calculated_value C: " + therm_2_stringF)

                    number_regions_found = number_regions_found + 1

                if (number_regions_found == 2):

                    vis = np.concatenate((mask_image, Thermometer_image), axis=1)

                    #######################################################################
                    cv2.imshow("Image used for detection", vis)
                    #######################################################################

                    # Save data in csv file
                    now = datetime.now()
                    dt_string = now.strftime("%Y-%m-%d %H:%M:%S")
                    current_time = time.time()
                    for_log = [current_time, dt_string, therm_1_stringC, therm_2_stringC, therm_1_stringF,
                    therm_2_stringF]

                    #######################################################################
                    with open("/Users/damianwilliams/Desktop/test_data.csv", "a") as f:
                        writer = csv.writer(f, delimiter=",")
                        writer.writerow(for_log)
                    ######################################################################

                    # Create image with annotation
                    place = (f"{dt_string} \n"
                             f"{therm_1_stringF} F, {therm_1_stringC} C\n"
                             f"{therm_2_stringF} F, {therm_2_stringC} C\n")

                    position = (30, 30)
                    text = place
                    font_scale = 0.75
                    color = (255, 0, 0)
                    thickness = 2
                    font = cv2.FONT_HERSHEY_SIMPLEX
                    line_type = cv2.LINE_AA
                    text_size, _ = cv2.getTextSize(text, font, font_scale, thickness)
                    line_height = text_size[1] + 5
                    x, y0 = position
                    for i, line in enumerate(text.split("\n")):
                        y = y0 + i * line_height
                        img = cv2.putText(img,
                                    line,
                                    (x, y),
                                    font,
                                    font_scale,
                                    color,
                                    thickness,
                                    line_type)

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

                    #Save_name = "/Users/damianwilliams/Desktop/Image_set/thermometer_" + str(idx) + ".jpg"
                    #cv2.imwrite(Save_name, img)
                    #cv2.imshow('Thermometer_images', img)
                    ########################################################################################

                    print(idx)
                    idx = idx + 1

    except Exception as e:
        print(e)
        print("reset")
    pass

    cv2.waitKey(1000)
    cv2.destroyAllWindows()


from sqlalchemy.orm import Session
from fastapi import HTTPException, status, Response, Depends
from ..models import toppings as model
from sqlalchemy.exc import SQLAlchemyError
from sqlalchemy import func
from datetime import datetime
from ..models.toppings import Topping
from ..models.orders import Order
from ..models.pizzas import Pizza, pizza_topping_association

def read_all(db: Session):
    try:
        result = db.query(model.Topping).all()
    except SQLAlchemyError as e:
        error = str(e.__dict__['orig'])
        raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=error)
    return result

def read_one(db: Session, item_id):
    try:
        item = db.query(model.Topping).filter(model.Topping.id == item_id).first()
        if not item:
            raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Id not found!")
    except SQLAlchemyError as e:
        error = str(e.__dict__['orig'])
        raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=error)
    return item

def get_most_popular_topping(db: Session, start_date: datetime, end_date: datetime):
    # Join the necessary tables
    subquery = db.query(Topping.name, func.count(Topping.id).label('topping_count')).join(
        pizza_topping_association).join(Pizza).join(Order).filter(
        Order.order_date >= start_date, Order.order_date <= end_date).group_by(Topping.name).subquery()

    # Get the most popular topping by counting occurrences
    result = db.query(subquery.c.name).order_by(subquery.c.topping_count.desc()).first()
    return result


import random

import numpy as np
from sklearn.metrics import roc_auc_score
from sklearn.model_selection import GridSearchCV

from lasso_ir.features import X, y
from lasso_ir.constants import MULTIPROCESSING
from lasso_ir.models import NLogisticRegression, MarginalRegression
import time

class BaseAlgorithm:
    """
    Base algorithm, defines most of the necessary methods. Implements passive/random search.
    """
    name = "random"

    def __init__(self, seed):
        self.n = len(y)
        self.answers = dict()
        self.answers[seed] = 1
        self.n_positive = 0
        self.unlabeled = list(range(self.n))
        self.unlabeled.pop(seed)

    def get_snapshot(self):
        return {}

    def get_query(self):
        return random.choice(self.unlabeled)

    def process_answer(self, index, label):
        self.answers[index] = label
        self.unlabeled.pop(self.unlabeled.index(index))
        self.n_positive += int(label == 1)

    def select_features(self):
        return X

    def __hash__(self):
        return hash(self.name)

    def __repr__(self):
        return f"'{self.name}'"

class NearestNeighbor(BaseAlgorithm):
    """
    For each query, picks a random positive example seen so far and finds the closest unlabeled example to that.
    The base NN algorithm uses all features, but LassoNN reimplements "select_features"
    """
    name = "nn"

    def get_query(self):
        t = time.time()
        positives = filter(lambda k: self.answers[k] == 1, self.answers.keys())
        target = random.choice(list(positives))
        _X = self.select_features()
        x = _X[target]
        _X = _X[self.unlabeled]
        dists = np.linalg.norm(_X - x, axis=1)
        best = np.argmin(dists)
        self.elapsed = time.time() - t
        return self.unlabeled[best]

class MargionalNN(NearestNeighbor):
    """
    Nearest Neighbor but uses Marginal Regression to select the features.
    Will select n_trained/N features, (N=1 by default)
    """
    def __init__(self, seed, N=1):
        self.N = N
        self.mask = None
        super().__init__(seed)

    def select_features(self):
        labeled = list(self.answers.keys())
        _y = list(self.answers.values())
        if can_fit(_y):
            n_trained = len(_y)
            _X = X[labeled]
            self.mask = MarginalRegression().fit(_X, _y).topfeatures(int(n_trained / self.N))
            return X[:, self.mask]
        else:
            return X

    @property
    def name(self):
        return f"nn-marginal-{self.N}"

    def get_snapshot(self):
        if self.mask is None:
            return {"coefs": None, "n_nonzero": None, "elapsed": self.elapsed}
        else:
            return{"coefs": np.ravel(np.argwhere(self.mask)).tolist(), "n_nonzero": np.count_nonzero(self.mask),  "elapsed": self.elapsed}

class MargionalNNPlus(MargionalNN):
    @property
    def name(self):
        return f"nn-marginalplus-{self.N}"

    def select_features(self):
        labeled = list(self.answers.keys())
        n_trained = len(self.answers)
        n_positive = list(self.answers.values()).count(1)
        n_negative = n_trained - n_positive
        n_sample = n_positive - n_negative
        unlabeled_sample = []
        if 0 < n_sample <= len(self.unlabeled):
            unlabeled_sample = random.sample(self.unlabeled, n_sample)
        sample = labeled + unlabeled_sample
        _y = [self.answers.get(i, 0) for i in sample]  # default to 0
        #_y = [self.answers.get(i, -1) for i in sample]  # default to -1
        if can_fit(_y):
            _X = X[sample]
            self.mask = MarginalRegression().fit(_X, _y).topfeatures(int(n_trained / self.N))
            return X[:, self.mask]
        else:
            return X

class MargionalNNPlusPlus(MargionalNN):
    @property
    def name(self):
        return f"nn-marginalplusplus-{self.N}"

    def select_features(self):
        labeled = list(self.answers.keys())
        n_trained = len(self.answers)
        n_positive = list(self.answers.values()).count(1)
        n_negative = n_trained - n_positive
        n_sample = n_positive - n_negative
        unlabeled_sample = []
        if 0 < n_sample <= len(self.unlabeled):
            unlabeled_sample = random.sample(self.unlabeled, n_sample)
            sample = labeled + unlabeled_sample
        else:
            sample = [i for i in labeled if self.answers[i] == 1]
            neg_sample = [i for i in labeled if self.answers[i] != 1]
            sample = sample + random.sample(neg_sample, n_positive)
        _y = [self.answers.get(i, 0) for i in sample]  # default to 0
        #_y = [self.answers.get(i, -1) for i in sample]  # default to -1
        if can_fit(_y):
            _X = X[sample]
            self.mask = MarginalRegression().fit(_X, _y).topfeatures(int(n_trained / self.N))
            return X[:, self.mask]
        else:
            return X

class LassoNN(NearestNeighbor):
    """
    Nearest Neighbor but uses LASSO to select the features
    """
    name = "nn-lasso"

    def __init__(self, seed, N=1):
        self.coefs = None
        self.C = .1
        self.N = N
        super().__init__(seed)

    def scoring(self):
        return sparsity_score

    def select_features(self):
        labeled = list(self.answers.keys())
        _y = list(self.answers.values())
        if can_fit(_y):
            _X = X[labeled]
            Cs = [self.C*2**n for n in range(-2, 3)] + [.1*2**n for n in range(-2, 3)]
            Cs = list(set(Cs))
            if MULTIPROCESSING:
                n_jobs = 1
            else:
                n_jobs = -1
            search = GridSearchCV(NLogisticRegression(N=self.N, penalty="l1", class_weight="balanced"), param_grid={"C": Cs}, scoring=self.scoring(), n_jobs=n_jobs, refit=True)
            model = search.fit(_X, _y).best_estimator_
            self.coefs = model.coef_
            self.C = model.get_params()["C"]
            mask = np.ravel(model.coef_.astype(bool))
            return X[:, mask]
        else:
            return X

    def get_snapshot(self):
        if self.coefs is None:
            return {"coefs": None, "n_nonzero": None, "C": None, "elapsed": self.elapsed}
        else:
            return{"coefs": self.coefs.tolist(), "n_nonzero": np.count_nonzero(self.coefs), "C": self.C, "elapsed": self.elapsed}

class LassoNNPlus(NearestNeighbor):
    """
        Nearest Neighbor but uses LASSO to select the features plus samples balanced
        """
    name = "nn-lasso-plus"

    def __init__(self, seed, N=1):
        self.coefs = None
        self.C = .1
        self.N = N
        super().__init__(seed)

    def scoring(self):
        return sparsity_score

    def select_features(self):
        labeled = list(self.answers.keys())
        labeled = list(self.answers.keys())
        n_trained = len(self.answers)
        n_positive = sum(self.answers.values())
        n_negative = n_trained - n_positive
        n_sample = n_positive - n_negative
        unlabeled_sample = []
        if 0 < n_sample <= len(self.unlabeled):
            unlabeled_sample = random.sample(self.unlabeled, n_sample)
        sample = labeled + unlabeled_sample
        _y = [self.answers.get(i, 0) for i in sample]  # default to 0
        #_y = [self.answers.get(i, -1) for i in sample]  # default to -1
        if can_fit(_y):
            _X = X[sample]
            Cs = [self.C*2**n for n in range(-2, 3)] + [.1*2**n for n in range(-2, 3)]
            Cs = list(set(Cs))
            if MULTIPROCESSING:
                n_jobs = 1
            else:
                n_jobs = -1
            search = GridSearchCV(NLogisticRegression(N=self.N, penalty="l1", class_weight="balanced"), param_grid={"C": Cs}, scoring=self.scoring(), n_jobs=n_jobs, refit=True)
            model = search.fit(_X, _y).best_estimator_
            self.coefs = model.coef_
            self.C = model.get_params()["C"]
            mask = np.ravel(model.coef_.astype(bool))
            return X[:, mask]
        else:
            return X

def get_snapshot(self):
    if self.coefs is None:
        return {"coefs": None, "n_nonzero": None, "C": None, "elapsed": self.elapsed}
    else:
        return{"coefs": self.coefs.tolist(), "n_nonzero": np.count_nonzero(self.coefs), "C": self.C, "elapsed": self.elapsed}

class NLassoNN(LassoNN):
    """
    LassoNN but requires number of nonzero features to be no larger than (number of training examples / self.N)
    """
    def scoring(self):
        return maximum_sparsity

    @property
    def name(self):
        return f"nn-lasso-{self.N}"

def can_fit(_y):
    return _y.count(1) > 3 and _y.count(0) > 3

def sparsity_score(est, _X: np.ndarray, _y: np.ndarray):
    sparsity = -np.count_nonzero(est.coef_) / est.coef_.shape[1]
    auc = roc_auc_score(_y, est.decision_function(_X))
    return sparsity + auc

def maximum_sparsity(est, _X: np.ndarray, _y: np.ndarray):
    if np.count_nonzero(est.coef_) > (est.n_trained / est.N):
        return -2
    else:
        return roc_auc_score(_y, est.decision_function(_X))


import numpy as np
import matplotlib
import math
matplotlib.use("Agg")
from matplotlib import pyplot as plt
#from scipy.optimize import curve_fit
from lmfit import Model, Parameters
from scipy import special
import os
from os.path import expanduser
import sys
sys.float_info.max

matplotlib.rc('xtick', labelsize=15)
matplotlib.rc('ytick', labelsize=15)

###########################################################################
## Global variables
###########################################################################
Pop = 8
TotalTimePoint = 9
OutputFilePath = "/mnt/c/Users/Ruby/Google Drive/Lab Project/AllPopReadCounts/20190227_NSF_Grant/P"+str(Pop)+"/0307/"
if not os.path.exists(OutputFilePath):
    os.makedirs(OutputFilePath)
BarcodeCountPath = "/mnt/c/Users/Ruby/Google Drive/Lab Project/AllPopReadCounts/SourceFile/"

bluish_green = "#009E73"

def read_MeanFitness(Pop):
    InputFilePath = "/mnt/c/Users/Ruby/Google Drive/Lab Project/AllPopReadCounts/Pop"+str(Pop)+"/"
    FilePathName = InputFilePath+"P"+str(Pop)+"_It5_MeanFitness.txt"
    file = open(FilePathName,"r")
    triplets=file.read().split()
    file.close()
    y=np.array(triplets, dtype=np.float32)
    return y

def read_Fitness(Pop):
    InputFilePath = "/mnt/c/Users/Ruby/Google Drive/Lab Project/AllPopReadCounts/Pop"+str(Pop)+"/"
    FilePathName = InputFilePath+"P"+str(Pop)+"_It5_RelativeFitness.txt"
    file = open(FilePathName,"r")
    triplets=file.read().split()
    file.close()
    y=np.array(triplets, dtype=np.float32)
    #print(y.shape)
    return np.transpose(np.reshape(y,(-1,TotalTimePoint-1)))

def read_Adpative_LNs(Pop):
    InputFilePath = "/mnt/c/Users/Ruby/Google Drive/Lab Project/AllPopReadCounts/Pop"+str(Pop)+"/"
    FilePathName = InputFilePath+"P"+str(Pop)+"_It5_ListAdaptiveBarcodeIndex.txt"
    file = open(FilePathName,"r")
    triplets=file.read().split()
    file.close()
    y=np.array(triplets, dtype=np.int32)
    return y

def readBarcodeCount(Pop):
    global BarcodeCountPath, TotalTimePoint
    FileName = "Pop"+str(Pop)+"BowtieReadCounts"
    FilePathName = BarcodeCountPath +FileName+".txt"
    file = open(FilePathName,"r")
    triplets=file.read().split()
    file.close()
    A=np.array(triplets, dtype=np.int32)
    return  np.transpose(np.reshape(A,(-1,TotalTimePoint)))

def get_Barcode_Freq(BarcodeCountsArray):  # BarcodeCountsArray[t][bc] Add 0.5 to zero count to aviod divergent of log10(freqeuncy)
    AllCountsArray = [sum(BarcodeCountsArray[i]) for i in range(0,len(BarcodeCountsArray))]
    #BarcodeFreqArray =  np.asarray([[(count+ int(count==0)*0.5)/AllCountsArray[t] for count in BarcodeCountsArray[t]] for t in range(0,len(BarcodeCountsArray))])
    BarcodeFreqArray =  np.asarray([[count/AllCountsArray[t]+ int(count==0)*10**-8 for count in BarcodeCountsArray[t]] for t in range(0,len(BarcodeCountsArray))])
    return BarcodeFreqArray, AllCountsArray

def plot_CleanAdaptive_BCFeq(Pop,time_end,ListAdaptive,ListCleanAdaptive):
    global OutputFilePath, TotalTimePoint
    # read barcode count
    BarcodeCountsArray = readBarcodeCount(Pop)
    # get Barcode Freq
    AllCountsArray = np.sum(BarcodeCountsArray,axis=1)
    BarcodeFreqArray =  [[(count/AllCountsArray[t]+ int(count==0)*10**-8) for count in BarcodeCountsArray[t]] for t in range(0,TotalTimePoint)]
    # plot Frequency for Adaptive Lineages
    plt.figure()
    x = np.asarray([2*i for i in range(TotalTimePoint)])
    plt.ylabel("log10 Barcode Freqeuncy")
    plt.xlabel("Time (cycle)")
    plt.title("Adaptive Lineages, Red:" +str(np.size(ListCleanAdaptive))+" Grey:"  +str(np.size(ListAdaptive)-np.size(ListCleanAdaptive)) )
    plt.xlim(0,np.max(x)+1)
    for bc in ListAdaptive:
        y = [np.log10(BarcodeFreqArray[t][bc]) for t in range(0,len(x))]
        if bc in ListCleanAdaptive:
            plt.plot(x,y,color='red',alpha=0.3, linewidth = 0.3)
        else:
            plt.plot(x,y,color='black',alpha=1, linewidth = 0.3)
    plt.savefig(OutputFilePath+"Adaptive_Lineages_Clean_Pop"+str(Pop)+".png")
'''
def plot_DEF_shift(Pop,ListCleanAdaptive,t,t_mid,freq,Med):
    finess = read_Fitness(Pop)
    binwidth = 0.1
    NLs = np.size(ListCleanAdaptive)
    #data = finess[t][ListCleanAdaptive]
    data = finess[t_mid][ListCleanAdaptive]
    data2 = finess[t+1][ListCleanAdaptive]
    #BarcodeCountsArray = readBarcodeCount(Pop)
    #freq = BarcodeFreqArray[t][ListCleanAdaptive]
    ds = data2 - data
    Mean = np.mean(ds)
    Med = np.median(ds)
    Var = np.var(ds)
    # plot without shift
    plt.figure()
    bins = np.arange(min(data), max(data) + binwidth, binwidth)
    #plt.hist(data,bins,label="cycle"+str(2*t+1),color= 'blue', alpha=0.3)
    plt.hist(data,bins,label="cycle"+str(2*t_mid+1),color= 'blue', alpha=0.3)
    bins = np.arange(min(data2), max(data2) + binwidth, binwidth)
    plt.hist(data2,bins,label="cycle"+str(2*t+3),color= 'green', alpha=0.3)
    plt.legend(loc='best')
    plt.xlabel("fitness (1/cycle)")
    plt.title("Adaptive Lineages, NLs="+str(NLs))
    plt.savefig(OutputFilePath+"CleanAdaptive_DFE_Pop"+str(Pop)+"_T"+str(t)+".png")
    # plot scatter
    plt.figure()
    line_max = max(np.max(data),np.max(data2))
    line_min = min(np.min(data),np.min(data2))
    line = np.arange(line_min, line_max, 0.01)
    plt.plot(line,line, 'k--')
    plt.plot(line,line+Med, 'r--')
    colormap = plt.cm.jet(np.linspace(0,1,101))
    colmax = -1
    colmin = -4
    colbin = (colmax-colmin)/100
    for bc in range(np.size(ListCleanAdaptive)):
        s = np.log10(freq[bc])
        if s>=colmax:
            s= colmax
        elif s< colmin:
            s = colmin
        colorIndx = (int)((s-colmin)/colbin)
        plt.scatter(data[bc],data2[bc], s=50, facecolors='none', edgecolors=colormap[colorIndx])
    plt.title("Pop "+str(Pop) + ",  NLs="+str(np.size(ListCleanAdaptive)))
    plt.xlabel("s  cycle " + str(2*t_mid+1))
    plt.ylabel("s  cycle " + str(2*t+3))
    plt.savefig(OutputFilePath+"CleanAdaptive_Pop"+str(Pop)+"_s"+str(t_mid)+"_s"+str(t+1)+".png")
    # plot with shift
    data2 = data2 - Med
    plt.figure()
    bins = np.arange(min(data), max(data) + binwidth, binwidth)
    plt.hist(data,bins,label="cycle"+str(2*t_mid+1),color= 'blue', alpha=0.3)
    bins = np.arange(min(data2), max(data2) + binwidth, binwidth)
    plt.hist(data2,bins,label="cycle"+str(2*t+3),color= 'green', alpha=0.3)
    plt.legend(loc='best')
    plt.xlabel("fitness (1/cycle)")
    plt.title("Adaptive Lineages, NLs="+str(NLs))
    plt.savefig(OutputFilePath+"CleanAdaptive_DFE_Shift_Pop"+str(Pop)+"_T"+str(t)+".png")
    # plot ds
    plt.figure()
    bins = np.arange(min(ds), max(ds) + binwidth, binwidth)
    plt.hist(ds,bins,label="NLs="+str(NLs),color= 'black', alpha=0.4)
    plt.xlabel("s(cycle "+str(2*t+3)+") - s(cycle "+str(2*t_mid+1)+")")
    plt.title("Mean "+str(Mean)+" Median "+str(Med)+" Var "+str(Var))
    plt.legend(loc='best')
    plt.savefig(OutputFilePath+"CleanAdaptive_ds_Dist_Pop"+str(Pop)+"_T"+str(t)+".png")
    plt.close('all')

def DFE_shift(Pop,t_mid):
    global TotalTimePoint
    Adaptive_NLs = read_Adpative_LNs(Pop)
    BarcodeCountsArray = readBarcodeCount(Pop)
    BarcodeFreqArray, AllCountsArray = get_Barcode_Freq(BarcodeCountsArray)
    finess = read_Fitness(Pop)
    mean_fitness = read_MeanFitness(Pop)
    Median_ds = []
    Var_ds = []
    for t in range(t_mid,TotalTimePoint-2):
        #listNonzeros = np.nonzero(BarcodeCountsArray[t]>10)[0]
        listNonzeros = np.nonzero(BarcodeCountsArray[t_mid]>100)[0]
        listNonzeros2 = np.nonzero(BarcodeCountsArray[t+1]>100)[0]
        ListCleanAdaptive = list(set(listNonzeros)&set(listNonzeros2)&set(Adaptive_NLs))
        #ds = finess[t+1][ListCleanAdaptive] - finess[t][ListCleanAdaptive]
        ds = finess[t+1][ListCleanAdaptive] - finess[t_mid][ListCleanAdaptive]
        Median_ds.append(np.median(ds))
        Var_ds.append(np.var(ds))
        freq = BarcodeFreqArray[t_mid][ListCleanAdaptive]
        plot_DEF_shift(Pop,ListCleanAdaptive,t,t_mid,freq,np.median(ds))
    #t0=3
    #sum_Ds = [np.sum(Median_ds[t0:t]) for t in range(t0,np.size(Median_ds)+1)]
    Alignment_mean_fitness = [m for m in mean_fitness[0:t_mid+1]]
    for t in range(t_mid+1,TotalTimePoint-1):
        #Alignment_mean_fitness[t] = Alignment_mean_fitness[t]-sum_Ds[t-t0]
        Alignment_mean_fitness.append(mean_fitness[t]-Median_ds[t-t_mid-1])
    plt.figure()
    x = np.asarray([1+2*i for i in range(np.size(mean_fitness))])
    plt.plot(x,Alignment_mean_fitness,color='blue',marker='o',ls='solid',label='new mean fitness')
    plt.plot(x,mean_fitness,color='black',marker='o',ls='solid',label='old mean fitness')
    plt.legend(loc='best')
    plt.xlabel('Time (cycle)')
    plt.ylabel('Mean Fitness (1/cycle)')
    plt.savefig(OutputFilePath+"AlignmingMeanFitness_Pop"+str(Pop)+".png")

'''

'''
def find_Adaptives(Pop,t_mid,D_fitness,freq):
    CV_CUT = 0.25
    Freq_CUT = -2.5
    S_CUT = 0
    BarcodeFreqArray = freq
    #listlarge = np.nonzero(np.min(BarcodeCountsArray[t_mid-2:t_mid+1],axis=0)>Count_CUT)[0]
    #listlarge = np.nonzero(np.log10(np.min(BarcodeFreqArray[t_mid-2:t_mid+1],axis=0))>Freq_CUT)[0]
    listlarge = np.nonzero(np.log10(BarcodeFreqArray[t_mid+1])>Freq_CUT)[0]
    fitness = [read_Fitness(Pop)[t] - D_fitness[t] for t in range(t_mid-2,t_mid+1)]
    #fitness =
    s_Mean = np.mean(fitness, axis=0)
    s_STD = np.std(fitness, axis=0)
    s_CV= np.abs(np.asarray([std/mean for std,mean in zip(s_STD,s_Mean)]))
    CV_freq = np.asarray([cv/f*10**-3 for cv,f in zip(s_CV,freq[t_mid])])
    #print(CV_freq.shape)
    listCV = np.nonzero(CV_freq < CV_CUT)[0]  #np.nonzero(s_CV < CV_CUT)[0]
    listMean = np.nonzero(s_Mean > S_CUT )[0]
    listADP = list(set(listlarge))#list(set(listCV) & set(listMean) & set(listlarge))
    print(np.size(listADP))

    plt.figure()
    #plt.plot(s_Mean,s_CV,'k.',markersize=2)
    #plt.plot(s_Mean[listlarge],s_CV[listlarge],'b.',markersize=2)
    plt.plot(s_Mean[listlarge],CV_freq[listlarge],'b.',markersize=2)
    #plt.plot(s_Mean[listlarge],np.exp(-1*s_CV[listlarge]),'b.',markersize=2)
    #plt.plot(np.log10(freq[t_mid][listlarge]),s_CV[listlarge],'b.',markersize=2)
    #plt.plot(s_Mean[listADP],s_CV[listADP],'r.',markersize=3)
    plt.plot(s_Mean[listADP],CV_freq[listADP],'r.',markersize=3)
    #plt.plot(np.log10(freq[t_mid][listADP]),s_CV[listADP],'r.',markersize=3)
    #plt.plot(s_Mean[listADP],np.exp(-1*s_CV[listADP]),'r.',markersize=3)
    plt.ylim(0,2)
    plt.xlim(0,1.5)
    plt.xlabel("Mean of fitness")
    #plt.xlabel("log10 Barcode Freq")
    plt.ylabel("abs CV of fitness")
    #plt.ylabel("Exp -| CV of fitness|")
    plt.title("P"+str(Pop)+" Cycle"+str(2*t_mid-3)+"-"+str(2*t_mid+1))
    plt.savefig(OutputFilePath+"P"+str(Pop)+"_s2CV_Cycle"+str(2*t_mid+1)+".png")
    #plt.savefig(OutputFilePath+"P"+str(Pop)+"_s2ExpCV_Cycle"+str(2*t_mid+1)+".png")
    plt.close('all')

    return listADP
'''
def find_largeLNs(Pop,t_mid,freq):
    Freq_CUT = -3.0
    listlarge = np.nonzero(np.log10(freq[t_mid+1])>Freq_CUT)[0]
    listADP = list(set(listlarge))
    return listADP

def plot_S1S2(Pop,list,t1,t2,D_fitness,Freq):
    global OutputFilePath
    s1 = read_Fitness(Pop)[t1][list] - D_fitness[t1]
    s2 = read_Fitness(Pop)[t2][list] - D_fitness[t2]
    freq = Freq[t1][list]
    ds = np.asarray([i-j for i,j in zip(s2,s1)])
    Med = np.median(ds)
    Mean = np.mean(ds)
    WeightMean = np.average(ds,weights=freq)
    line_max = max(np.max(s1),np.max(s2))
    line_min = min(np.min(s1),np.min(s2))
    line = np.arange(line_min, line_max, 0.01)
    plt.figure()
    plt.plot(line,line, 'k--')
    plt.plot(line,line+WeightMean, 'r--')
    #plt.plot(line,line+Med, 'r--')
    colormap = plt.cm.jet(np.linspace(0,1,101))
    colmax = -1
    colmin = -4
    colbin = (colmax-colmin)/100
    for bc in range(np.size(list)):
        s = np.log10(freq[bc])
        if s>=colmax:
            s= colmax
        elif s< colmin:
            s = colmin
        colorIndx = (int)((s-colmin)/colbin)
        plt.scatter(s1[bc],s2[bc],s=20, facecolors='none', edgecolors=colormap[colorIndx])
    plt.xlabel('Fitness cycle '+str(2*t1+1))
    plt.ylabel('Fitness cycle '+str(2*t2+1))
    plt.title('P'+str(Pop)+"  NLs="+str(np.size(list))+" WM "+str(WeightMean))#+ ", weighted mean "+str(WeightMean))
    plt.savefig(OutputFilePath+"P"+str(Pop)+"_Cycle_"+str(2*t1+1)+"-"+str(2*t2+1)+".png")
    return WeightMean
    #return Med
def plot_new_mean_fitness(Pop,D_fitness,t_mid):
    global OutputFilePath
    mean_fitness = read_MeanFitness(Pop)
    x = [2*t+1 for t in range(np.size(mean_fitness))]
    new_mean_fitness = mean_fitness - D_fitness
    print(new_mean_fitness)
    plt.figure()
    plt.plot(x,mean_fitness,color='black',marker='o',ls='solid',label='old mean fitness')
    plt.plot(x[0:t_mid+1],new_mean_fitness[0:t_mid+1],color='red',marker='o',ls='solid',label='new mean fitness')
    plt.xlabel("Time (cycle)")
    plt.title("P"+str(Pop)+"  Mean Fitness (1/cycle)")
    plt.legend(loc='best')
    plt.savefig(OutputFilePath+"P"+str(Pop)+"_MeanFitness_Cycle_"+str(2*t_mid+1)+".png")

##### Plot Mean Fitness

T_ini = 3

D_mean_fitness = [0 for i in range(TotalTimePoint-1)]

BarcodeCountsArray = readBarcodeCount(Pop)

#Adaptive_NLs = read_Adpative_LNs(Pop)
#listsameADP = list(set(listADP)& set(Adaptive_NLs))
#BarcodeCountsArray = readBarcodeCount(Pop)
#AllCountsArray = [sum(BarcodeCountsArray[i]) for i in range(0,len(BarcodeCountsArray))]

BarcodeFreqArray, AllCountsArray = get_Barcode_Freq(BarcodeCountsArray)

#listADP = [0 for i in range(T_ini,TotalTimePoint-1)]
#listADP[0] = find_Adaptives(Pop,T_ini,D_mean_fitness,BarcodeFreqArray)
listlargeLNs = find_largeLNs(Pop,T_ini,BarcodeFreqArray)
#listADP_all = listADP[0]
for t in range(T_ini+1,TotalTimePoint-1):
    #D_mean_fitness[t] = plot_S1S2(Pop,listADP[t-1-T_ini],t-1,t,D_mean_fitness,BarcodeFreqArray)
    D_mean_fitness[t] = plot_S1S2(Pop,listlargeLNs,t-1,t,D_mean_fitness,BarcodeFreqArray)
    plot_new_mean_fitness(Pop,D_mean_fitness,t)
    #print(D_mean_fitness)
    listlargeLNs = find_largeLNs(Pop,t,BarcodeFreqArray)
    #listADP[t-T_ini] = find_Adaptives(Pop,t,D_mean_fitness,BarcodeFreqArray)
    #listADP_all.extend(listADP[t-T_ini])
    #listADP_all = list(set(listADP_all))

#print(np.size(listADP_all))

np.save(OutputFilePath+"P"+str(Pop)+"_Dx.npy", D_mean_fitness)

#BarcodeFreqArray, AllCountsArray = get_Barcode_Freq(BarcodeCountsArray)
'''
D_fitness = np.load(OutputFilePath+"P"+str(Pop)+"_Dx.npy")

old_fitness = read_Fitness(Pop)
new_fitness = [old_fitness[t] - D_fitness[t] for t in range(np.size(D_fitness))]

new_mean_fitness = read_MeanFitness(Pop) - D_fitness
print(new_mean_fitness)
cal_mean_fitness = [sum([(f1+f2)*s/2 for f1,f2,s in zip(BarcodeFreqArray[t],BarcodeFreqArray[t+1],new_fitness[t])]) for t in range(TotalTimePoint-1)]
#cal_mean_fitness = [sum([f1*s for f1,s in zip(BarcodeFreqArray[1+t],new_fitness[t])]) for t in range(TotalTimePoint-1)]
print(cal_mean_fitness)

plt.figure()
x = [2*t+1 for t in range(np.size(new_mean_fitness))]
plt.plot(x,new_mean_fitness,color='red',marker='o',ls='solid',label='new mean fitness')
plt.plot(x,cal_mean_fitness,color='goldenrod',marker='o',ls='solid',label='mean fitness direct calculation')
plt.legend(loc='best')
plt.xlabel("Time (cycle)")
plt.title("P"+str(Pop) + "  Mean Fitness (1/cycle)")
plt.savefig(OutputFilePath+"P"+str(Pop)+"_MeanFitness_check.png")
'''
'''
a = np.load(OutputFilePath+"P"+str(Pop)+"_newADPs_dS_2.npz")

D_fitness = a['Dx']
listADP = a['ADP']

listADP_all = []
for idx in range(listADP.shape[0]):
    listADP_all.extend(listADP[idx])

listADP_all = list(set(listADP_all))

old_fitness = read_Fitness(Pop)
new_fitness = [old_fitness[t] - D_fitness[t] for t in range(np.size(D_fitness))]

ADP_maxS = []
ADP_aveS = []
for bc in listADP_all:
    max_s = 0
    ave_s = 0
    normalized = 0
    for idx in range(listADP.shape[0]):
        if bc in listADP[idx]:
            s = new_fitness[idx+T_ini][bc]
            max_s = max(max_s,s)
            ave_s = ave_s + s
            normalized = normalized +1
    ave_s = ave_s/normalized
    ADP_maxS.append(max_s)
    ADP_aveS.append(ave_s)

plt.figure()
binwidth = 0.05
bins = np.arange(min(ADP_maxS), max(ADP_maxS) + binwidth, binwidth)
plt.hist(ADP_maxS,bins)
plt.title("NLs="+str(np.size(listADP_all)))
plt.savefig(OutputFilePath+"P"+str(Pop)+"DFE_ADP_max.png")

plt.figure()
binwidth = 0.05
bins = np.arange(min(ADP_aveS), max(ADP_aveS) + binwidth, binwidth)
plt.hist(ADP_aveS,bins)
plt.title("NLs="+str(np.size(listADP_all)))
plt.savefig(OutputFilePath+"P"+str(Pop)+"DFE_ADP_ave.png")

plt.figure()
binwidth = 0.05
ADP_T13 = new_fitness[6][listADP[3]]
bins = np.arange(min(ADP_T13), max(ADP_T13) + binwidth, binwidth)
plt.hist(ADP_T13,bins)
plt.title("NLs="+str(np.size(ADP_T13)))
plt.savefig(OutputFilePath+"P"+str(Pop)+"DFE_ADP_Cycle13.png")

plt.figure()
binwidth = 0.05
ADP_T11 = new_fitness[5][listADP[2]]
bins = np.arange(min(ADP_T11), max(ADP_T11) + binwidth, binwidth)
plt.hist(ADP_T11,bins)
plt.title("NLs="+str(np.size(ADP_T11)))
plt.savefig(OutputFilePath+"P"+str(Pop)+"DFE_ADP_Cycle11.png")
'''

'''
t_mid = t_mid + 1
listADP = find_Adaptives(Pop,t_mid,D_mean_fitness,BarcodeFreqArray)
D_mean_fitness[t_mid+1] = plot_S1S2(Pop,listADP,t_mid,t_mid+1,D_mean_fitness,BarcodeFreqArray)
plot_new_mean_fitness(Pop,D_mean_fitness,t_mid)
print(D_mean_fitness)
#print(np.size(listADP),np.size(Adaptive_NLs),np.size(listsameADP))
'''

'''
plt.figure()
plt.xlabel('Time (cycle)')
plt.ylabel('Log10 BC frequency')
plt.title("P"+str(Pop)+"  Grey: old-ADP, Blue: new-ADP, Red: both-ADP ("+str(np.size(listsameADP))+")")
x = [2*t for t in range(t_mid-2,t_mid+2)]
for bc in Adaptive_NLs:
    #count = [BarcodeCountsArray[t][bc] for t in range(t_mid-2,t_mid+2)]
    y = [np.log10(BarcodeCountsArray[t][bc]/AllCountsArray[t]+(10**-8)*(BarcodeCountsArray[t][bc]==0)) for t in range(t_mid-2,t_mid+2)]
    plt.plot(x,y,color='grey',linewidth=0.1,alpha=1)
for bc in listADP:
    #count = [BarcodeCountsArray[t][bc] for t in range(t_mid-2,t_mid+2)]
    y = [np.log10(BarcodeCountsArray[t][bc]/AllCountsArray[t]+(10**-8)*(BarcodeCountsArray[t][bc]==0)) for t in range(t_mid-2,t_mid+2)]
    plt.plot(x,y,color='blue',linewidth=0.2,alpha=1)
for bc in listsameADP:
    #count = [BarcodeCountsArray[t][bc] for t in range(t_mid-2,t_mid+2)]
    y = [np.log10(BarcodeCountsArray[t][bc]/AllCountsArray[t]+(10**-8)*(BarcodeCountsArray[t][bc]==0)) for t in range(t_mid-2,t_mid+2)]
    plt.plot(x,y,color='red',linewidth=0.2,alpha=1)
plt.savefig(OutputFilePath+"P"+str(Pop)+"_ADP_LNs_Cycle"+str(2*t_mid+1)+".png")
'''

#DFE_shift(Pop,t_mid)
#Adaptive_NLs = read_Adpative_LNs(Pop)

#for Pop in range(1,11):
#    DFE_shift(Pop,t_mid)

'''
s1 = read_Fitness(Pop)[0:time_end+1]

s1_mean = np.mean(s1, axis=0)
s1_tend = s1[time_end]
s1_SEM = np.std(s1, axis=0)/(s1.shape[0])**0.5  # standard error of mean
s1_CV = np.abs(np.asarray([sem/mean*(s1.shape[0])**0.5 for sem,mean in zip(s1_SEM, s1_mean)]))
s1_max = np.max(s1[1:], axis=0)
s1_sort = np.sort(s1[1:], axis=0)
s1_sort = s1_sort[::-1] # reverse (decending order)
s1_max2 = np.mean(s1_sort[0:2], axis=0)

listCVsmall = np.nonzero(s1_CV<1)[0]
listPositiveS = np.nonzero(s1_mean>0)[0]

BarcodeCountsArray = readBarcodeCount(Pop)
listNonzeros = np.nonzero(np.min(BarcodeCountsArray,axis=0)>0)[0]
#ListCleanAdaptive = list(set(listCVsmall)&set(listPositiveS)&set(Adaptive_NLs))
ListCleanAdaptive = np.asarray(list(set(Adaptive_NLs)&set(listNonzeros)))#list(set(listNonzeros)&set(Adaptive_NLs))
print(np.size(ListCleanAdaptive),np.size(Adaptive_NLs))
#plot_CleanAdaptive_BCFeq(Pop,time_end,Adaptive_NLs,ListCleanAdaptive)
print(ListCleanAdaptive[0:10])
BarcodeFreqArray, AllCountsArray = get_Barcode_Freq(BarcodeCountsArray)
print(BarcodeFreqArray.shape)
s1 = read_Fitness(Pop)
for t in range(TotalTimePoint-2):
    list1 = np.nonzero(BarcodeCountsArray[t]>10)[0]
    list2 = np.nonzero(BarcodeCountsArray[t+1]>10)[0]
    ListCleanAdaptive = list(set(Adaptive_NLs)&set(listNonzeros))
    x = s1[t][ListCleanAdaptive]
    y = s1[t+1][ListCleanAdaptive]
    freq = BarcodeFreqArray[t][ListCleanAdaptive]
    colormap = plt.cm.jet(np.linspace(0,1,101))
    colmax = -2
    colmin = -6
    colbin = (colmax-colmin)/100
    line_max = max(np.max(x),np.max(y))
    line_min = min(np.min(x),np.min(y))
    line = np.arange(line_min, line_max, 0.01)
    plt.figure()
    plt.plot(line,line, 'k--')
    for bc in range(np.size(ListCleanAdaptive)):
        s = np.log10(freq[bc])
        if s>=colmax:
            s= colmax
        elif s< colmin:
            s = colmin
        colorIndx = (int)((s-colmin)/colbin)
        plt.scatter(x[bc],y[bc], s=50, facecolors='none', edgecolors=colormap[colorIndx])
    plt.title("Pop "+str(Pop) + ",  NLs="+str(np.size(ListCleanAdaptive)))
    plt.xlabel("s  cycle " + str(2*t+1))
    plt.ylabel("s  cycle " + str(2*t+3))
    plt.savefig(OutputFilePath+"CleanAdaptive_Pop"+str(Pop)+"_s"+str(t)+"_s"+str(t+1)+".png")
    plt.close('all')

'''
'''
binwidth = 0.1

finess = read_Fitness(Pop)

for t in range(TotalTimePoint-2):
    plt.figure()
    data = finess[t][ListCleanAdaptive]
    bins = np.arange(min(data), max(data) + binwidth, binwidth)
    plt.hist(data,bins,label="t"+str(t),color= 'blue', alpha=0.3)
    data = finess[t+1][ListCleanAdaptive]
    bins = np.arange(min(data), max(data) + binwidth, binwidth)
    plt.hist(data,bins,label="t"+str(t+1),color= 'green', alpha=0.3)
    plt.legend(loc='best')
    plt.savefig(OutputFilePath+"CleanAdaptive_Dist_Pop"+str(Pop)+"_T"+str(t)+".png")

Ds = []
Var_Ds = []
binwidth = 0.1

for t in range(TotalTimePoint-2):
    data = finess[t][ListCleanAdaptive]
    data2 = finess[t+1][ListCleanAdaptive]
    ds = data2 - data
    plt.figure()
    bins = np.arange(min(ds), max(ds) + binwidth, binwidth)
    plt.hist(ds,bins,label="t"+str(t),color= 'black', alpha=0.3)
    plt.xlabel("ds")
    Ds.append(np.median(ds))
    Var_Ds.append(np.var(ds))
    plt.title("Mean "+str(np.mean(ds))+" Median "+str(np.median(ds))+" Var "+str(np.var(ds)))
    plt.savefig(OutputFilePath+"CleanAdaptive_Dist_ds_Pop"+str(Pop)+"_T"+str(t)+".png")
print("Ds",Ds)
plt.close('all')
#dx=[]
for t in range(TotalTimePoint-2):
    plt.figure()
    data = finess[t][ListCleanAdaptive]
    #mean_s1 = np.mean(data)
    bins = np.arange(min(data), max(data) + binwidth, binwidth)
    plt.hist(data,bins,label="t"+str(t),color= 'blue', alpha=0.3)
    data2 = finess[t+1][ListCleanAdaptive]
    #mean_s2 = np.mean(data2)
    #dx.append(mean_s2 - mean_s1)
    #data = data2 - dx[t]
    data = data2 - Ds[t]
    bins = np.arange(min(data), max(data) + binwidth, binwidth)
    plt.hist(data,bins,label="t"+str(t+1),color= 'green', alpha=0.3)
    plt.legend(loc='best')
    plt.title("median(s(t+1))-median(s(t))="+str(Ds[t]))
    plt.savefig(OutputFilePath+"CleanAdaptive_Dist_Alignment_Pop"+str(Pop)+"_T"+str(t)+".png")
#print("dx ",dx)
plt.close('all')
t0=3
#sum_dx = [np.sum(dx[t0:t]) for t in range(t0,np.size(dx)+1)]
Ds_new = [0,0]
for t in range(0,np.size(Ds)):
    if Var_Ds[t] < 0.5:
        Ds_new.append(Ds[t])
    else:
        Ds_new.append(0)

sum_Ds = [np.sum(Ds[t0:t]) for t in range(t0,np.size(Ds)+1)]
print("sum Ds",sum_Ds)

mean_fitness = read_MeanFitness(Pop)
print("Mean Fitness",mean_fitness)
Alignment_mean_fitness = [m for m in mean_fitness]
for t in range(t0,TotalTimePoint-1):
    #Alignment_mean_fitness[t] = Alignment_mean_fitness[t]+sum_dx[t-t0]
    Alignment_mean_fitness[t] = Alignment_mean_fitness[t]-sum_Ds[t-t0]
print("Align Mean Fitness",Alignment_mean_fitness)
np.save(OutputFilePath+"Pop"+str(Pop)+"_Alignming_MeanFitness.npy",Alignment_mean_fitness)
x = np.asarray([1+2*i for i in range(np.size(mean_fitness))])
print(x)
plt.plot(x,Alignment_mean_fitness,color='blue',marker='o',ls='solid',label='Alignming x')
#mean_fitness = read_MeanFitness(Pop)
plt.plot(x,mean_fitness,color='black',marker='o',ls='solid',label='x')
plt.legend(loc='best')
plt.xlabel('Time (cycle)')
plt.ylabel('Mean Fitness (1/cycle)')
plt.savefig(OutputFilePath+"AlignmingMeanFitness_Pop"+str(Pop)+".png")

'''
'''
plt.figure()
plt.plot(s1_mean,s1_SEM,color = bluish_green, marker='.', ls='None')
plt.xlabel("Mean (fintess) over time")
plt.ylabel("Standard Error of Mean SEM (fitness)")
plt.title("Population "+str(Pop)+", NLs="+str(np.size(Adaptive_NLs)))
plt.savefig(OutputFilePath+"AdaptiveFitness_SEM2Mean_Pop"+str(Pop)+".png")
'''
'''
plt.figure()
plt.plot(s1_mean[Adaptive_NLs],s1_CV[Adaptive_NLs],color = bluish_green, marker='.', ls='None')
dash_x = np.arange(0,2,0.1)
dash_y = np.arange(0,5,0.1)
plt.plot(dash_x,[2 for i in range(np.size(dash_x))],'k--')
plt.plot([0 for i in range(np.size(dash_y))],dash_y,'k--')
plt.xlabel("Mean (fintess) over time")
plt.ylabel("Coefficient of Variation CV (fitness)")
plt.title("Population "+str(Pop)+", NLs="+str(np.size(Adaptive_NLs)))
plt.xlim(-0.5,1.5)
plt.ylim(0,5)
plt.savefig(OutputFilePath+"AdaptiveFitness_CV2Mean_Pop"+str(Pop)+".png")
'''
'''
plt.figure()
binwidth = 0.1
data = s1_mean[ListCleanAdaptive]
bins = np.arange(min(data), max(data) + binwidth, binwidth)
plt.hist(data,bins, label="T_ave S",color='blue', alpha = 0.3)
data = s1_tend[ListCleanAdaptive]
bins = np.arange(min(data), max(data) + binwidth, binwidth)
plt.hist(data,bins,label="cycle7 S",color='red', alpha = 0.3)
data = s1_max2[ListCleanAdaptive]
bins = np.arange(min(data), max(data) + binwidth, binwidth)
plt.hist(data,bins,label="max2 S",color='black', alpha = 0.3)
plt.legend(loc='best')
plt.xlabel("Fitness (1/cycle)")
plt.title("Population "+str(Pop)+" NLs="+str(np.size(ListCleanAdaptive)))
plt.savefig(OutputFilePath+"CleanAdaptive_DFE_Pop"+str(Pop)+"_compare3_max2"+".png")
'''

'''
Pop = 1
y1 = read_MeanFitness(Pop)
Pop = 6
y2 = read_MeanFitness(Pop)

x = np.asarray([1+2*i for i in range(np.size(y1))])
plt.figure()
plt.xlim(0,np.max(x)+1)
plt.ylim(-0.05,0.8)
plt.plot(x,y1,color='black',marker='o',ls='solid',label='Mono-culture')
plt.plot(x,y2,color=bluish_green,marker = 'o',ls= 'solid',label='Co-culture')

for Pop in range(2,6):
    y = read_MeanFitness(Pop)
    plt.plot(x,y,color='black',marker='o',ls='solid')
for Pop in range(7,11):
    y = read_MeanFitness(Pop)
    plt.plot(x,y,color=bluish_green,marker='o',ls='solid')

plt.xlabel('Time (cycle)',size=15)
plt.legend(loc='best',fontsize=15)
plt.title('Mean Fitness (1/cycle)',size=20)
plt.savefig(OutputFilePath+"MeanFitness_1&8.png")
'''
'''
fig, ax = plt.subplots()
width = 0.35       # the width of the bars
barX = [0,1]
barY = [y1[-1], y2[-1]]

ax.bar(barX[0],barY[0],width, color="black")
ax.bar(barX[1],barY[1],width, color=bluish_green)
ax.set_xticks([idx+width/2 for idx in barX])
ax.set_xticklabels(['Mono-culture', 'Co-culture'],fontsize=20)
ax.set_xlim(-0.3,1.7)
ax.set_title("Cycle-9 Mean Fintess (1/cycle)",size=20)
plt.savefig(OutputFilePath+"MeanFitness_Cycle9_1&6.png")
'''


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Fri Jul 10 10:43:17 2020

@author: julescraquelin
"""

from EOMcircuit.functions import Dipole, Node, Hole, Circuit, Representation
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.colors import LogNorm
import matplotlib.gridspec as gridspec
from scipy.optimize import minimize, newton, root

plt.close('all')

import scipy.constants
h = scipy.constants.h
pi=np.pi
hbar = h/2/np.pi
phi0=hbar/(2*scipy.constants.e)
sci = hbar/phi0**2

#connecting and wires
W = Dipole('W')
_ = None
N = Node('') # expect this for dummy nodes
G = Node('G')

if 1 :
    desired_output = np.array([6, 5, 0.2, 0.003, 0.003]) #what do we aim
    #input_param0 = np.array([2*np.pi*6, 2*np.pi*5, 100, 1/(2*np.pi*6)/100/10, 1/(2*np.pi*6)/100/10])
    #input_param0 = np.array([2*np.pi*7, 2*np.pi*6, 200, 1/(2*np.pi*6)/200/10, 1/(2*np.pi*6)/200/10])
    #input_param0 = np.array([2*np.pi*(6.12), 2*np.pi*(5.48), 355, 1/(2*np.pi*(6.27))/465/10, 1/(2*np.pi*(6.27))/541/10])
    #input_param0 = np.array([6.05688463e+00, 5.22853426e+00, 6.09325351e+01, 1.14777012e-06, 7.59989362e-07])*2*pi
    #input_param0 = np.array([6.09837119e+00, 5.22934561e+00, 6.09420074e+01, 1.15169586e-06, 1.91192618e-06])*2*np.pi
    input_param0 = np.array([3.83171962e+01, 3.28569475e+01, 3.82909925e+02, 7.23631853e-06, 1.20129865e-05])

    wa = input_param0[0]
    Za = 50
    wb = input_param0[1]
    Zb = input_param0[2]
    Z0 = 50

    Cb = Dipole('Cb', 1/wb/Zb)
    Jb = Dipole('Jb', Zb/wb)
    Cc = Dipole('Cc', input_param0[3])
    Cg = Dipole('Cg', input_param0[4])
    R0 = Dipole('R0', Z0)
    Ca = Dipole('Ca', 1/wa/Za)
    La = Dipole('La', Za/wa)

if 0 :
    desired_output = np.array([6, 5, 4, 0.2, 0.003, 0.003, 0.0003]) #what do we aim
    input_param0 = np.array([3.83171962e+01, 3.28569475e+01, 2.73569475e+01, 151.09925, 0.000163265306122449, 0.0001142857142857143, 8e-05])

   # input_param0 = np.array([2*np.pi*(6.2), 2*np.pi*(5.2), 2*np.pi*(4.2), 110, 1/(2*np.pi*6)/100/10, 1/(2*np.pi*6)/100/10, 1/(2*np.pi*4)/50/10])
    #[wa, wb, wc, Zb, Cc, Cg, Cc2]

    wa = input_param0[0]
    Za = 50
    wb = input_param0[1]
    Zb = input_param0[3]
    Z0 = 50

    wm = input_param0[2]
    Zm = 50

    Cb = Dipole('Cb', 1/wb/Zb)
    Jb = Dipole('Jb', Zb/wb)
    Cc = Dipole('Cc', input_param0[4])
    Cg = Dipole('Cg', input_param0[5])
    R0 = Dipole('R0', Z0)
    Ca = Dipole('Ca', 1/wa/Za)
    La = Dipole('La', Za/wa)

    Cm = Dipole('Cm', 1/wm/Zm)
    Lm = Dipole('Lm', Zm/wm)
    Cc2 = Dipole('Cc2', input_param0[6])

EJ=phi0**2*wb/Zb/h*2*np.pi #junction's energy in GHz

#Circuit's geometry
#circuit=[[N,W,N,Cg,N],
#         [Jb,_,Cb,_,R0],
 #        [G,W,N,_,G]]
if 1 :
    circuit = [[ N, W, N,Cc, N, W, N,Cg, N],
           [Jb, _,Cb, _,La, _,Ca, _,R0],
           [ G, W, N, _, G, W, N, _, G]]
    dipoles = np.array([Cb, Jb, Ca, La, Cc, Cg, R0])

if 0 :
    circuit = [[ N, W, N, Cc2, N, W, N,Cc, N, W, N,Cg, N],
               [Lm, _, Cm, _, Jb, _,Cb, _,La, _,Ca, _,R0],
               [G, W, N, _, G, W, N, _, G, W, N, _, G]]

    dipoles = np.array([Cb, Jb, Ca, La, Cc, Cg, R0, Cm, Lm, Cc2])

#fig_circuit, ax_circuit = plt.subplots()
c = Circuit(circuit, verbose = False) # parse circuit and much more is done

#c.plot(ax_circuit)
#print('### Circuit plotted ###')

#fig = plt.figure(figsize=(9,6))
#gs = gridspec.GridSpec(ncols=2, nrows = 2)
#gs.update(left=0.10, right=0.95, wspace=0.0, hspace=0.1, top=0.95, bottom =0.05)
#ax_eom = fig.add_subplot(gs[0, :])

#omegas = np.linspace(2*2*np.pi, 8*2*np.pi, 501)
#kappas = np.linspace(1e-6*2*np.pi, 1e-1*2*np.pi, 51)

if 1 :
    guesses = [wa, wb]
    #c.rep_AC.display_eom(ax_eom, omegas, kappas=kappas, guesses=guesses)#, kappas=kappas, guesses=guesses)#kappas=kappas
    eig_omegas, eig_phizpfs = c.rep_AC.solve_EIG(guesses)
if 0 :
    guesses = [wa, wb, wm]
    eig_omegas, eig_phizpfs = c.rep_AC.solve_EIG(guesses)

#ax_eom.vlines(eig_omegas, np.amin(to_plot), np.amax(to_plot), lw=1, color='r')

### plot modes

#ax0 = fig.add_subplot(gs[1, :])
#c.plot(ax0)
#c.rep_AC.plot_phi(ax0, 10*np.real(eig_phizpfs[0]), offset=0.3, color='C0') # 4* -> magnification for plot only
#c.rep_AC.plot_phi(ax0, 10*np.real(eig_phizpfs[1]), offset=0.5, color='C1') # 4* -> magnification for plot only

#Ker, Cross-Ker frequencies and Charging energy
#Ka = EJ/2*np.cos(eig_phizpfs[0][2])*eig_phizpfs[0][2]**4 # ker frequency (mode a) in GHz
#Kb = EJ/2*np.cos(eig_phizpfs[1][2])*eig_phizpfs[1][2]**4 # ker frequency (mode b) in GHz

#Ec=phi0**2/2/Zb*wb*eig_phizpfs[0][1]**2/h # capa energy in GHz

#Ctotb = Cb.val + Cg.val +Cc.val
#Ctota = Ca.val + Cg.val +Cc.val
#ECb = scipy.constants.e**2/Ctotb/2/h # charging energy in mode b
#ECa = scipy.constants.e**2/Ctota/2/h # charging energy in mode a

#Khi=np.sqrt(Ka*Kb*2)

def circuit_outputs (input_param, circuit, dipoles, plot = True) :
    #input_param should be a ndarray like [wa, wb, Zb, Cc, Cg]
    #it returns an array [wcav, wtr, kappacav, kertr, khi
    if 1 :
        if type(input_param) != np.ndarray or len(input_param) != 5:
            print('### circuit_outputs : ERROR ###')
            print('input_param must be a ndarray with 5 elements')
            return

    if 1 :
        wa = input_param[0]
        wb = input_param[1]
        Zb = input_param[2]
        #print ('#### INPUT_PARAM')
        #print (input_param/2/np.pi)
        #print('#### INPUT_PARAM')

        Za = 50
        EJ = phi0**2*wb/Zb/h*2*np.pi #junction's energy in GHz

        dipoles[0].val = 1/wb/Zb
        dipoles[1].val = Zb/wb
        dipoles[2].val = 1/Za/wa
        dipoles[3].val = Za/wa
        dipoles[4].val = input_param[3]
        dipoles[5].val = input_param[4]

        guesses = [wa, wb]
        eig_omegas, eig_phizpfs = c.rep_AC.solve_EIG(guesses, verbose = False)

    if 0 :
        wa = input_param[0]
        wb = input_param[1]
        wm = input_param[2]

        Zb = input_param[3]
        Za = 50
        Zm = 50

        EJ = phi0**2*wb/Zb/h*2*np.pi #junction's energy in GHz

        dipoles[0].val = 1/wb/Zb # Cb
        dipoles[1].val = Zb/wb # Jb
        dipoles[2].val = 1/Za/wa # Ca
        dipoles[3].val = Za/wa # La
        dipoles[4].val = input_param[4] #Cc
        dipoles[5].val = input_param[5]#Cg
        dipoles[7].val = 1/wm/Zm # Cm
        dipoles[8].val = Zm/wm # Lm
        dipoles[9].val = input_param[6]#Cc2

        guesses = [wa, wb, wm]
        eig_omegas, eig_phizpfs = c.rep_AC.solve_EIG(guesses, verbose = False)

    if plot :
        omegas = np.linspace(2*2*np.pi, 8*2*np.pi, 501)
        kappas = np.linspace(1e-6*2*np.pi, 1e-1*2*np.pi, 51)
        fig = plt.figure(figsize=(9,6))
        gs = gridspec.GridSpec(ncols=2, nrows = 2)
        gs.update(left=0.10, right=0.95, wspace=0.0, hspace=0.1, top=0.95, bottom =0.05)
        ax_eom = fig.add_subplot(gs[0, :])

        c.rep_AC.display_eom(ax_eom, omegas, kappas=kappas, guesses=guesses)#, kappas=kappas, guesses=guesses)#kappas=kappas

        ax0 = fig.add_subplot(gs[1, :])
        c.plot(ax0)
        c.rep_AC.plot_phi(ax0, 10*np.real(eig_phizpfs[0]), offset=0.3, color='C0') # 4* -> magnification for plot only
        c.rep_AC.plot_phi(ax0, 10*np.real(eig_phizpfs[1]), offset=0.5, color='C1') # 4* -> magnification for plot only

    #Ker, Cross-Ker frequencies and Charging energy
    if 1 :
        Kcav = EJ/2*np.cos(eig_phizpfs[0][2])*eig_phizpfs[0][2]**4 # ker frequency (mode a) in GHz
        Ktr = EJ/2*np.cos(eig_phizpfs[1][2])*eig_phizpfs[1][2]**4 # ker frequency (mode b) in GHz
        Khi_ab = np.sqrt(2*Ktr*Kcav) # Cross ker frequency in GHz??????? le 2 devrait etre hors de la sqrt

    if 0 :
        Kcav = EJ/2*np.cos(eig_phizpfs[0][2])*eig_phizpfs[0][2]**4 # ker frequency (mode a) in GHz
        Ktr = EJ/2*np.cos(eig_phizpfs[1][2])*eig_phizpfs[1][2]**4 # ker frequency (mode b) in GHz
        Khi_ab = np.sqrt(2*Ktr*Kcav) # Cross ker frequency in GHz??????? le 2 devrait etre hors de la sqrt
        Km = EJ/2*np.cos(eig_phizpfs[2][2])*eig_phizpfs[2][2]**4 # ker frequency (mode c = m) in GHz
        Khi_bc = np.sqrt(2*Ktr*Km)

    if 1 :
        return np.array([np.real(eig_omegas[0]), np.real(eig_omegas[1]), Ktr, Khi_ab, 2*np.imag(eig_omegas[0])])/2/np.pi

    if 0 :
        return np.array([np.real(eig_omegas[0]), np.real(eig_omegas[1]), np.real(eig_omegas[2]), Ktr, Khi_ab, 2*np.imag(eig_omegas[0]), Khi_bc])/2/np.pi

def optimize_components (desired_output, input_param0):
    # If several conditions satisfy the desired outputs, this function may return several lists
    # desired_output should be a list like with 5 elements [wcav, wtr, kappacav, kertr, khi]
    # input_param0 should be like [wa, wb Zb Cc Cg]

    if 1 :
        if type(desired_output) != np.ndarray or len(desired_output) != 5 or type(input_param0) != np.ndarray or len(input_param0) != 5 :
            print('### optimize_components : ERROR ###')
            print('desired_outputs must be a ndarray with 5 elements')
            print('input_param0 must be a ndarray with 5 elements')
            return

    to_minimize = lambda input_param, circuit, dipoles : np.abs(\
        desired_output - circuit_outputs(input_param, circuit, dipoles, plot =False))
    #to_minimize = lambda input_param : np.abs(\
      #   [ a[0] - a[1] for a in zip(desired_output, circuit_outputs(input_param)) ])#if we used lists...
            #to_minimize is a function that take for argument input_param
            #it gives the difference between desired_out and circuit_outputs(input_param)

    return root(to_minimize, input_param0, args=(circuit, dipoles)).x #root finds zeros of a vectorial function

#params = optimize_components(desired_output, input_param0)

result = circuit_outputs(input_param0, circuit, dipoles, plot = False)
print(result)


import z3
import lark
import argparse

GRAMMAR = """
?start: term
  | term "?" term ":" term -> if

?term: item
  | term "*"  item      -> mul
  | item "(" term ")"      -> mul
  | term "/"  item      -> div
  | term ">>" item      -> shr
  | term "<<" item      -> shl
  | term "+" item        -> add
  | term "-" item        -> sub
  | "(" term ")" "^" index -> exp

?item: var
  | const
  | var "[" index "]" -> onebit
  | var "[" index ":" index "]" -> bitsel
  | "(" start ")"
  | var "^" index -> pow
  | const item -> multiple

?var: CNAME -> var

?const: NUMBER           -> num
  | "-" item            -> neg

?index: NUMBER           -> index

%import common.NUMBER
%import common.WS
%import common.CNAME
%ignore WS
""".strip()

rootBitVecSize = 8

def interp(tree, lookup):
    """Evaluate the arithmetic expression.

    Pass a tree as a Lark `Tree` object for the parsed expression. For
    `lookup`, provide a function for mapping variable names to values.
    """

    op = tree.data
    if op in (
        "add",
        "sub",
        "mul",
        "div",
        "shl",
        "shr",
        "multiple",
    ):  # Binary operators.
        lhs = interp(tree.children[0], lookup)
        rhs = interp(tree.children[1], lookup)
        if op == "add":
            return lhs + rhs
        elif op == "sub":
            return lhs - rhs
        elif op == "mul" or op == "multiple":
            return lhs * rhs
        elif op == "div":
            return lhs / rhs
        elif op == "shl":
            return lhs << rhs
        elif op == "shr":
            return lhs >> rhs
    elif op == "neg":  # Negation.
        sub = interp(tree.children[0], lookup)
        return -sub
    elif op == "num":  # Literal number.
        return z3.BitVecVal(int(tree.children[0]), rootBitVecSize)
    elif op == "index":  # Literal number.
        return int(tree.children[0])
    elif op == "var":  # Variable lookup.
        return lookup(tree.children[0])
    elif op == "if":  # Conditional.
        cond = interp(tree.children[0], lookup)
        true = interp(tree.children[1], lookup)
        false = interp(tree.children[2], lookup)
        return (cond != z3.BitVecVal(0, cond.size())) * true + (
            cond == z3.BitVecVal(0, cond.size())
        ) * false
    elif op == "onebit":
        sub = interp(tree.children[0], lookup)
        idx = interp(tree.children[1], lookup)
        if idx >= sub.size() or idx < 0:
            raise ValueError("Index out of bounds")
        return (sub & z3.BitVecVal(pow(2, idx), sub.size())) >> z3.BitVecVal(
            idx, sub.size()
        )
    elif op == "bitsel":
        sub = interp(tree.children[0], lookup)
        hi = interp(tree.children[1], lookup)
        lo = interp(tree.children[2], lookup)
        if hi >= sub.size() or hi < 0:
            raise ValueError("Hi index out of bounds")
        if lo >= sub.size() or lo < 0:
            raise ValueError("Lo index out of bounds")
        if hi < lo:
            raise ValueError("Hi index must be greater than lo index")
        power = hi - lo + 1
        mask = z3.BitVecVal(pow(2, power) - 1, sub.size()) << z3.BitVecVal(
            lo, sub.size()
        )
        return (sub & mask) >> z3.BitVecVal(lo, sub.size())
    elif op == "pow" or op == "exp":
        sub = interp(tree.children[0], lookup)
        exp = interp(tree.children[1], lookup)
        if exp < 1:
            raise ValueError("bad exponent")
        newExpr = sub
        for i in range(exp - 1):
            newExpr = newExpr * sub
        return newExpr

def pretty(tree, subst={}, paren=False):
    """Pretty-print a tree, with optional substitutions applied.

    If `paren` is true, then loose-binding expressions are
    parenthesized. We simplify boolean expressions "on the fly."
    """

    # Add parentheses?
    if paren:

        def par(s):
            return "({})".format(s)

    else:

        def par(s):
            return s

    op = tree.data
    if op in ("add", "sub", "mul", "div", "shl", "shr", "pow", "exp", "multiple"):
        lhs = pretty(tree.children[0], subst, True)
        rhs = pretty(tree.children[1], subst, True)
        c = {
            "add": "+",
            "sub": "-",
            "mul": "*",
            "multiple": " ",
            "div": "/",
            "shl": "<<",
            "shr": ">>",
            "pow": "^",
            "exp": "^",
        }[op]
        if op == "pow" or op == "exp":
            return par("{}{}{}".format(lhs, c, rhs))
        if op == "multiple":
            return par("{}{}".format(lhs, rhs))
        return par("{} {} {}".format(lhs, c, rhs))
    elif op == "neg":
        sub = pretty(tree.children[0], subst)
        return "-{}".format(sub, True)
    elif op == "num" or op == "index":
        return tree.children[0]
    elif op == "var":
        name = tree.children[0]
        return str(subst.get(name, name))
    elif op == "if":
        cond = pretty(tree.children[0], subst)
        true = pretty(tree.children[1], subst)
        false = pretty(tree.children[2], subst)
        return par("{} ? {} : {}".format(cond, true, false))
    elif op == "onebit":
        sub = pretty(tree.children[0], subst)
        idx = pretty(tree.children[1], subst)
        return par("{}[{}]".format(sub, idx))
    elif op == "bitsel":
        sub = pretty(tree.children[0], subst)
        hi = pretty(tree.children[1], subst)
        lo = pretty(tree.children[2], subst)
        return par("{}[{}:{}]".format(sub, hi, lo))

def solve(phi):
    s = z3.Solver()
    s.add(phi)
    s.check()  # The formula can be satisfied
    return s.model()

def vanishes(phi):
    s = z3.Solver()
    s.add(phi)
    try:
        s.check()  # The formula can be satisfied
        # print(s.model())
        return s.model()
    except:
        return None

if __name__ == "__main__":
    parser = argparse.ArgumentParser(
        description="This program uses an SMT solver to determine if a univariate expression is polynomial in 'x' and zero modulo 8"
    )
    parser.add_argument(
        "-v", "--verbose", dest="verbose", default=False, action="store_true"
    )
    parser.add_argument(
        "-N",
        "--bits",
        dest="bits",
        type=int,
        default=16,
        help="The number of bits the input variable 'x' is",
    )
    parser.add_argument(
        "expression", type=str, default="x", help="The expression p(x) to check"
    )
    args = parser.parse_args()
    rootBitVecSize = args.bits
    # Parse a polynomial.
    parser = lark.Lark(GRAMMAR)
    tree1 = parser.parse(args.expression)
    expr = interp(tree1, lambda x: z3.BitVec(x, rootBitVecSize) if x in ["x"] else None)
    if args.verbose:
        print("Expression entered:")
        print(pretty(tree1))

    # Vars needed
    x = z3.BitVec("x", rootBitVecSize)
    # Holes
    A = z3.BitVec("A", rootBitVecSize)
    B = z3.BitVec("B", rootBitVecSize)
    C = z3.BitVec("C", rootBitVecSize)
    D = z3.BitVec("D", rootBitVecSize)
    E = z3.BitVec("E", rootBitVecSize)
    # Ax(x-1)(x-2)(x-3) + 4Bx(x-1)(x-2) + 4Cx(x-1) + 8Dx + 8E
    polynomial = (
        (A * x * (x - 1) * (x - 2) * (x - 3))
        + (4 * B * x * (x - 1) * (x - 2))
        + (4 * C * x * (x - 1))
        + (8 * D * x)
        + (8 * E)
    )

    formula = z3.ForAll([x], expr == polynomial)
    print("Q: Is this expression polynomial in 'x' and zero modulo 8?")
    answer = vanishes(formula)
    if answer is None:
        print("A: No")
    else:
        print("A: Yes it is, with vanishing polynomial")
        VExpr = ""
        if answer[A].as_long() != 0:
            if len(VExpr) > 0:
                VExpr += " + "
            VExpr += f"{answer[A].as_long()}x(x-1)(x-2)(x-3)"
        if answer[B].as_long() != 0:
            if len(VExpr) > 0:
                VExpr += " + "
            VExpr += f"{4 * answer[B].as_long()}x(x-1)(x-2)"
        if answer[C].as_long() != 0:
            if len(VExpr) > 0:
                VExpr += " + "
            VExpr += f"{4 * answer[C].as_long()}x(x-1)"
        if answer[D].as_long() != 0:
            if len(VExpr) > 0:
                VExpr += " + "
            VExpr += f"{8 * answer[D].as_long()}x"
        print(VExpr if len(VExpr) > 0 else "0")


#!/usr/bin/env python3

import argparse, progressbar, json
import logging as log
import numpy as np

from struct import unpack, iter_unpack, calcsize
from collections import namedtuple
from PIL import Image
from itertools import islice

PIX_PER_COLUMN = 64
COLMNS_PER_BUFFER = 16
BYTES_PIXEL = 12
TICK_PER_REVOLUTION = 90112
HEADER_SIZE = 16
FOOTER_SIZE = 4
BYTES_PER_COLUMN = HEADER_SIZE + PIX_PER_COLUMN * BYTES_PIXEL + FOOTER_SIZE
ROWS_PER_FRAME = 1024
BEAM_ANGLE  = 33.468 ## derrived from calibration file

PCAP_HEADER_SIZE = 24
UDP_OVERHEAD = 42

def is_pcap(f):
    f.seek(0)
    magic = unpack("I", f.read(4))[0]
    f.seek(0)
    is_capture    = magic in [0xa1b2c3d4, 0xd4c3b2a1, 0xa1b23c4d, 0x4d3cb2a1]
    is_revsersed  = magic in [0xd4c3b2a1, 0x4d3cb2a1]
    is_nanosecond = magic in [0xa1b23c4d, 0x4d3cb2a1]
    return is_capture

def raw_to_buffers(f):
    while True:
        buf = f.read(BYTES_PER_COLUMN * COLMNS_PER_BUFFER)
        if not buf: break
        yield buf

def pcap_to_buffers(f):
    head = f.read(PCAP_HEADER_SIZE)
    pkt_meta_fmt = "IIII"
    PktMeta = namedtuple("PktMeta", "ts_sec ts_usec incl_len orig_len")
    while True:
        chunk = f.read(calcsize(pkt_meta_fmt))
        if not chunk: break
        pktmeta = PktMeta._make(unpack(pkt_meta_fmt, chunk))
        assert(pktmeta.incl_len == pktmeta.orig_len)
        f.seek(UDP_OVERHEAD, 1)
        pkt = f.read(pktmeta.incl_len - UDP_OVERHEAD)
        yield pkt

def file_to_buffers(f):
    if is_pcap(f):
        return pcap_to_buffers(f)
    else:
        return raw_to_buffers(f)

def buffers_to_frames(buffers):
    struct = "Q H H I 768s I"
    Col = namedtuple("Col", "timestamp column_id frame_id ticks pixeldata valid")
    frame = []
    last_frame_id = -1
    for buffer in buffers:
        for chunck in iter_unpack(struct, buffer):
            column = Col._make(chunck)
            if column.frame_id == last_frame_id:
                frame.append(column)
            else:
                if frame:
                    yield frame
                frame = [column]
                last_frame_id = column.frame_id

def split_pixeldata_to_pixels(pixeldata):
    ## last 2 bytes are unspecified?
    struct = "I H H H xx"
    ## remember to mask range with 0xFFFFF
    Pixel = namedtuple("Pixel", "range reflectivity signal noise")
    for chunck in iter_unpack(struct, pixeldata):
        yield Pixel._make(chunck)

def frames_to_images(frames, start, stop, azimuth_correction):
    def fix_azimuth(x, y):
        return int(y + azimuth_correction[x])

    size = (PIX_PER_COLUMN, ROWS_PER_FRAME)
    if stop: bar = progressbar.ProgressBar(maxval=stop-start).start()
    for i, frame in enumerate(islice(frames, start, stop)):
        data = np.zeros(size, dtype=np.uint8)
        for column in frame:
            y = column.column_id
            pixels = split_pixeldata_to_pixels(column.pixeldata)
            for x, pixel in enumerate(pixels):
                yy = fix_azimuth(x, y)
                data[x, yy%ROWS_PER_FRAME] = 255*(pixel.range & 0xFFFFF)/100000
                #data[x, yy%ROWS_PER_FRAME] = 255*(pixel.reflectivity & 0xFFFFF)/35500
                #data[x, yy%ROWS_PER_FRAME] = 255*(pixel.signal & 0xFFFFF)/1500
                #data[x, yy%ROWS_PER_FRAME] = 255*(pixel.noise & 0xFFFFF)/1500
        img = Image.fromarray(data)
        log.debug(f"writing img {i}")
        yield img
        if stop: bar.update(i)
    if stop: bar.finish()

def parse_arguments():
    parser = argparse.ArgumentParser(description="TODO description",
        epilog="2019 - KapiteinLabs - yuri@kapiteinlabs.com")
    parser.add_argument("-l", "--log-level", help="Set loglevel",
        choices=["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"],
        type=str.upper, action="store", default="INFO")
    parser.add_argument("-c", "--calibration_file", help="JSON file containing calibration info",
        action="store", type=str, default=None)
    parser.add_argument("-r", "--read-file", help="PCAP/RAW file containing OS1 data",
        action="store", type=str, required=True)
    parser.add_argument("-o", "--outfile", help="GIF to write",
        action="store", type=str, required=True)
    parser.add_argument("-n", "--framecount", help="Number of frames",
        action="store", type=int)
    parser.add_argument("-f", "--fps", help="Frame rate of output gif",
        action="store", type=float, default=62.5)
    return parser.parse_args()

def main(args):
    FRAMETIME_MS = 1000//args.fps

    if args.calibration_file:
        with open(args.calibration_file, "r") as f:
            calib = json.load(f)
            azimuths = calib['beam_azimuth_angles']
            altitudes = calib['beam_altitude_angles']
    else:
        log.warning("No calibration file given. Estimating azimuth errors.")
        azimuths = [a*360/1024 for a in [9,3,-3,-9]*16]
        altitudes = np.arange(-BEAM_ANGLE/2,BEAM_ANGLE/2,BEAM_ANGLE/64)
    azimuth_pixel_corrections = [a*1024/360 for a in azimuths]

    with open(args.read_file, "rb") as f:
        buffers = file_to_buffers(f)
        frames = buffers_to_frames(buffers)
        images = frames_to_images(frames, start=1, stop=args.framecount,
            azimuth_correction=azimuth_pixel_corrections)
        first_img = next(images)
        first_img.save(args.outfile, save_all=True, append_images=images,
            duration=FRAMETIME_MS, loop=0)

if __name__ == '__main__':
    args = parse_arguments()
    log.basicConfig(level=args.log_level)
    main(args)


# -*- coding: utf-8 -*-
from Products.CMFCore.utils import getToolByName
from Products.CMFPlone.interfaces import INonInstallable
from zope.interface import implementer

import logging

logger = logging.getLogger("setuphandlers")

class Empty:
    pass

@implementer(INonInstallable)
class HiddenProfiles(object):
    def getNonInstallableProfiles(self):
        """Hide uninstall profile from site-creation and quickinstaller."""
        return [
            "hmn.university:uninstall",
        ]

    def getNonInstallableProducts(self):
        """Hide the upgrades package from site-creation and quickinstaller."""
        return ["hmn.university.upgrades"]

def add_catalog_indexes(context):
    """Add our indexes to the catalog.
    Doing it here instead of in profiles/default/catalog.xml means we
    do not need to reindex those indexes after every reinstall.
    inspiration from https://svn.plone.org/svn/collective/Products.Poi/trunk/Products/Poi/setuphandlers.py
    and
    http://maurits.vanrees.org/weblog/archive/2009/12/catalog
    """

    catalog = getToolByName(context, "portal_catalog")
    indexes = catalog.indexes()

    wanted_dateindex = []
    wanted_fieldindex = ["firstName", "lastName", "age", "gender", "facultyRank"]
    wanted_keywordindex = []
    wanted_zctextindex = ["teacherName"]

    missing_dateindex = [w for w in wanted_dateindex if w not in indexes]
    if missing_dateindex:
        for name in missing_dateindex:
            catalog.addIndex(name, "DateIndex")
            logger.info("Added DateIndex for field %s.", name)
        logger.info("Indexing new date indexes %s.", ", ".join(missing_dateindex))
        catalog.manage_reindexIndex(ids=missing_dateindex)

    missing_fieldindex = [w for w in wanted_fieldindex if w not in indexes]
    if missing_fieldindex:
        for name in missing_fieldindex:
            catalog.addIndex(name, "FieldIndex")
            logger.info("Added FieldIndex for field %s.", name)
        logger.info("Indexing new field indexes %s.", ", ".join(missing_fieldindex))
        catalog.manage_reindexIndex(ids=missing_fieldindex)

    missing_keywordindex = [w for w in wanted_keywordindex if w not in indexes]
    if missing_keywordindex:
        for name in missing_keywordindex:
            catalog.addIndex(name, "KeywordIndex")
            logger.info("Added KeywordIndex for field %s.", name)
        logger.info("Indexing new keyword indexes %s.", ", ".join(missing_keywordindex))
        catalog.manage_reindexIndex(ids=missing_keywordindex)

    missing_zctextindex = [w for w in wanted_zctextindex if w not in indexes]
    if missing_zctextindex:
        for name in missing_zctextindex:
            item_extras = Empty()
            item_extras.doc_attr = name
            item_extras.index_type = "Okapi BM25 Rank"
            item_extras.lexicon_id = "plone_lexicon"
            catalog.addIndex(name, "ZCTextIndex", item_extras)
            logger.info("Added ZCTextIndex for field %s.", name)
        logger.info("Indexing new field indexes %s.", ", ".join(missing_zctextindex))
        catalog.manage_reindexIndex(ids=missing_zctextindex)

def post_install(context):
    """Post install script"""
    # Do something at the end of the installation of this package.
    add_catalog_indexes(context)

def uninstall(context):
    """Uninstall script"""
    # Do something at the end of the uninstallation of this package.


import asyncio
import discord
import os
import utils
from discord.ext import commands

path = os.path.abspath(os.path.join(os.getcwd(), os.pardir))
token = open("token.txt").read()

intents = discord.Intents.all()
intents.members = True
intents.presences = True
intents.messages = True

#bot = commands.Bot(command_prefix=',', intents=intents)

class MyBot(commands.Bot):
    async def setup_hook(self):
        bot.remove_command('help')
        await load_extensions()
        print("extensions loaded")

async def load_extensions():
    for file in os.listdir("cogs"):
        if file.endswith(".py"):
            name = file[:-3]
            await bot.load_extension('cogs.' + name)

bot = MyBot(command_prefix=',', intents=intents)
bot.run(token)

# @bot.event
# async def on_ready():
#     print("bird up")
#     for guild in bot.guilds:
#         for member in guild.members:
#             if utils.check_info(member) == "Error":
#                 utils.add_user_entry(str(member), member.id, member.guild.id)


import argparse
import logging
from core.pipelines.pipelines_controller import (
    get_pipeline_description,
    load_pipeline_dynamically,
)

plid = "bone_segmentation"

def get_description():
    return get_pipeline_description(plid)

def add_parser_arguments(parser):
    parser.add_argument(
        "input",
        metavar="i",
        type=str,
        help="Specify the path to the directory containing the scans in the form of DICOM",
    )
    parser.add_argument(
        "output",
        metavar="o",
        type=str,
        help="Specify the path of a single output file in the form of a glb file",
    )
    parser.add_argument(
        "-q",
        "--quiet",
        action="store_true",
        help="Set the logging level from INFO to ERROR",
    )
    parser.set_defaults(which=plid)

def run(args):
    logging.info("Loading and initializing bone pipeline dynamically")
    input_dir = args.input
    output_path = args.output
    pipeline_module = load_pipeline_dynamically(plid)
    pipeline_module.run(input_dir, output_path, [1])
    logging.info("Done.")

def main():
    parser = argparse.ArgumentParser(description=get_description())
    add_parser_arguments(parser)
    args = parser.parse_args()
    logging.basicConfig(
        level=logging.ERROR if args.quiet else logging.INFO,
        format="%(asctime)s - %(module)s:%(levelname)s - %(message)s",
        datefmt="%d-%b-%y %H:%M:%S",
    )

    run(args)

if __name__ == "__main__":
    main()


import uuid
from pydantic import BaseModel
from typing import List, Optional
from fastapi import Request

class CommodityBase(BaseModel):
    item: str
    itemCategory: str
    quantity: int
    price: int

class CommodityList(BaseModel):
    items: List[CommodityBase]

class ProductCreateForm:
    def __init__(self, request: Request):
        self.request: Request = request
        self.errors: List = []
        self.item: Optional[str] = None
        self.item_category: Optional[str] = None
        self.quantity: Optional[int] = None
        self.price: Optional[int] = None

    async def load_data(self):
        form = await self.request.form()
        self.item_id = str(uuid.uuid4)
        self.item = form.get("item")
        self.item_category = form.get("item_category")
        self.quantity = form.get("quantity")
        self.price = form.get("price")
        self.product = {
            'item': self.item,
            'item_category': self.item_category,
            'quantity': int(self.quantity),
            'price': int(self.price)
        }

    def is_valid(self):
        if not self.item:
            self.errors.append("A valid item is required")
        if not self.item_category:
            self.errors.append("Item Category is required")
        if not self.quantity:
            self.errors.append("Qunatity is required")
        if not self.price:
            self.errors.append("Price si required")
        if not self.errors:
            return True
        return False


import numpy as np
import os.path as path
from scipy import spatial

class Glove:
    """
    Class to handle the glove Embeddings, load the pretrained
    embeddings from the directory and return embedding
    vector for words.
    """
    def __init__(self):
        self.embeddings_dict = {}
        self.n_dimension = 0
        self.average = None

    def load(self):
        """
        Load the embedding vector from directory
        and store the whole embedding as a dictionary
        :return: none
        """
        with open(path.dirname(path.abspath(__file__)) + "pretrained/glove.6B.300d.txt", 'r', encoding="utf-8") as f:
            for line in f:
                values = line.split()
                word = values[0]
                vector = np.asarray(values[1:], "float32")
                self.embeddings_dict[word] = vector

        first_key = next(iter(self.embeddings_dict))
        self.n_dimension = len(self.embeddings_dict[first_key])
        self.calculate_average_vec()

    def calculate_average_vec(self):
        n_vec = len(self.embeddings_dict)
        vecs = np.zeros((n_vec, self.n_dimension), dtype=np.float32)
        for i, key in enumerate(self.embeddings_dict):
            vecs[i] = self.embeddings_dict[key]

        self.average = np.mean(vecs, axis=0)

    def find_closest_words(self, term, limit=5):
        embedding = self.embeddings_dict[term]
        all_words = sorted(self.embeddings_dict.keys(),
                      key=lambda word: spatial.distance.euclidean(self.embeddings_dict[word], embedding))
        return all_words[:limit]

    def get_embedding_val(self, term, average_on_none=False):
        """
        Get the vector of each term
        :param term: a string, for which it will search the dictonary for embedding vector
        :param average_on_none: Boolean, if true will return average vector if not found on Dictionary else
        return None
        :return: Vector or None
        """
        try:
            val = self.embeddings_dict[term.lower()]
        except KeyError:
            if average_on_none:
                val = self.average
            else:
                val = None
        return val


from itertools import combinations
import numpy

class ClusterNode(object):
  def __init__(self, vec, left, right, distance=0.0, count=1):
    self.left = left
    self.right = right
    self.vec = vec
    self.distance = distance
    self.count = count

  def extract_clusters(self, dist):
    '''Extract list of subtree clusters with distance < dist.'''
    if self.distance < dist:
      return [self]
    return self.left.extract_clusters(dist) + self.right.extract_clusters(dist)

  def get_cluster_elements(self):
    '''Return ids for elements in a cluster subtree.'''
    return self.left.get_cluster_elements() + self.right.get_cluster_elements()

  def get_height(self):
    '''Return the height of a node.'''
    return self.left.get_height() + self.right.get_height()

  def get_depth(self):
    '''Return the depth of a node.'''
    return max(self.left.get_depth(), self.right.get_depth()) + self.distance

  def draw(self, draw, x, y, s, imlist, im):
    '''Draw nodes recursively with iages for leaf nodes.'''

    # n^2 :-/
    h1 = int(self.left.get_height() * 20 / 2)
    h2 = int(self.right.get_height() * 20 / 2)
    top = y - (h1 + h2)
    bottom = y + (h1 + h2)

    draw.line((x, top + h1, x, bottom - h2), fill=(0, 0, 0))

    l1 = self.distance * s
    draw.line((x, top + h1, x + l1, top + h1), fill=(0, 0, 0))
    draw.line((x, bottom - h2, x + l1, bottom - h2), fill=(0, 0, 0))

    self.left.draw(draw, x + l1, top + h1, s, imlist, im)
    self.right.draw(draw, x + l1, bottom - h2, s, imlist, im)

class ClusterLeafNode(object):
  def __init__(self, vec, id):
    self.vec = vec
    self.id = id

  def extract_clusters(self, dist):
    return [self]

  def get_cluster_elements(self):
    return [self.id]

  def get_height(self):
    return 1

  def get_depth(self):
    return 0

  def draw(self, draw, x, y, s, imlist, im):
    from PIL import Image
    nodeim = Image.open(imlist[self.id])
    nodeim.thumbnail((20, 20))
    ns = nodeim.size
    im.paste(nodeim, [int(x), int(y - ns[1] // 2),
                      int(x + ns[0]), int(y + ns[1] - ns[1] // 2)])

def l2dist(v1, v2):
  return numpy.sqrt(numpy.sum((v1 - v2) ** 2))

def l1dist(v1, v2):
  return numpy.sum(numpy.abs(v1 - v2))

def hcluster(features, distfn=l2dist):
  '''Cluster the rows of features using hiearchical clustering.'''

  distances = {}

  node = [ClusterLeafNode(numpy.array(f), id=i) for i, f in enumerate(features)]

  # O(n^3)
  while len(node) > 1:
    closest = float('Inf')

    # Find closest pair.
    for ni, nj in combinations(node, 2):
      if (ni, nj) not in distances:
        distances[ni, nj] = distfn(ni.vec, nj.vec)

      d = distances[ni, nj]
      if d < closest:
        closest = d
        lowestpair = ni, nj
    ni, nj = lowestpair

    # Combine closest pair.
    new_vec = (ni.vec + nj.vec) / 2.0

    new_node = ClusterNode(new_vec, left=ni, right=nj, distance=closest)
    node.remove(ni)
    node.remove(nj)
    node.append(new_node)

  return node[0]

def draw_dendrogram(node, imlist, filename='out_clusters.png'):
  '''Draw a clsuter dendrogram and save it.'''
  from PIL import Image, ImageDraw

  rows = node.get_height() * 20
  cols = 1200

  s = float(cols - 150) / node.get_depth()

  im = Image.new('RGB', (cols, rows), (255, 255, 255))
  draw = ImageDraw.Draw(im)

  draw.line((0, rows/2, 20, rows/2), fill=(0, 0, 0))
  node.draw(draw, 20, rows / 2, s, imlist, im)
  im.save(filename)
  im.show()


"""
Routes and views for the flask application.
"""

from datetime import datetime
from flask import render_template, redirect, request, jsonify
import json
import os;

from RasaHost import host
app = host.flask
from RasaHost.services import *

@app.route('/nlu')
def nlu_list():
    return render_template(
        'nlu/index.html',
        title='Nlu',
    )

@app.route('/api/nlu', methods=['GET'])
def api_nlu_list():
    q = request.args.get('q')
    intents = NluService().find_all(q)
    return jsonify(intents)

@app.route('/api/nlu/file', methods=['GET'])
def api_nlu_get():
    path = request.args.get('path')
    intent = NluService().get_by_path(path)
    return jsonify(intent)

@app.route('/api/nlu/file', methods=['POST'])
def api_nlu_post():
    path = request.args.get('path')
    if not request.json["name"]:
        return jsonify({'error': 'Name is required'})

    newPath = os.path.join(os.path.dirname(path), request.json['name']  + ".md")
    if path.lower() != newPath.lower() and os.path.exists(newPath):
        return jsonify({'error': 'File with the name already exists'})

    updated_file = NluService().update(path, request.json)
    return jsonify({'result': updated_file})

@app.route('/api/nlu/file', methods=['PUT'])
def api_nlu_put():
    if not request.json["name"]:
        return jsonify({'error': 'Name is required'})

    if NluService().get_by_name(request.json["name"]):
        return jsonify({'error': 'File with the name already exits.'})

    created_file = NluService().create(request.json)
    return jsonify({'result': created_file})

@app.route('/api/nlu/file', methods=['DELETE'])
def api_nlu_delete():
    path = request.args.get('path')
    NluService().delete(path)
    return jsonify({'result': 'ok'})

@app.route('/api/nlu/analyze', methods=['GET'])
def api_nlu_analyze():
    return jsonify(AnalyzeService().analyze())


from django.shortcuts import render
from ToDoListApp.models import AddTask

# Create your views here.

def homepage(request):
    context = {'success' : False}
    if request.method == 'POST':
        task_title = request.POST['task_title']
        task_desc = request.POST['task_desc']
        task_img = request.POST['task_img']
        # print(task_title, task_desc)

        insert_task = AddTask(taskTitle=task_title, taskDesc=task_desc, taskImg = task_img)
        insert_task.save()
        context = {'success' : True}

    return render(request, 'Homepage.html', context)

def tasks(request):
    allTasks = AddTask.objects.all()
    context = {'tasks' : allTasks}
    return render(request, 'tasks.html', context)


from django.conf import settings
from linebot import LineBotApi
from linebot.models import TextSendMessage
import requests
import twder  #汇率套件

line_bot_api = LineBotApi(settings.LINE_CHANNEL_ACCESS_TOKEN)

currencies = {'美金':'USD','港币':'HKD','英镑':'GBP','澳币':'AUD',\
              '日圆':'JPY','欧元':'EUR','人民币':'CNY' }  #币别字典
keys = currencies.keys()

def sendUse(event):  #使用说明
    try:
        text1 ='''
查询汇率：输入外币名称“XXXX”，例如“美金”,“英镑”,“港币”,“澳币”,“日圆”,“欧元”,“人民币”
               '''
        message = TextSendMessage(
            text = text1
        )
        line_bot_api.reply_message(event.reply_token,message)
    except:
        line_bot_api.reply_message(event.reply_token,TextSendMessage(text='发生错误！'))

#函数 sendLUIS 是课本Ch09 范例 >>> 可以修正为自己的函数 sendTWder
def sendTWder(event, mtext):
    try:
#        money = '美元'
        money = mtext
        if not money == '':  #汇率类币别存在
            if money in keys:
                rate3 = float(twder.now(currencies[money])[3])  #由汇率套件取得汇率
                message = money + '_即期买入汇率 : ' + str(rate3)+ '_(台湾银行端) '
                line_bot_api.reply_message(event.reply_token, TextSendMessage(text=message))
            else:
                line_bot_api.reply_message(event.reply_token, TextSendMessage(text='无此币别汇率资料！'))
        else:  #其他未知输入
            text = '无法了解你的意思，请重新输入！'
            line_bot_api.reply_message(event.reply_token, TextSendMessage(text=text))

    except:
       line_bot_api.reply_message(event.reply_token, TextSendMessage(text='执行时产生错误！'))

def neuWeb(event):  #网页链接
    try:
        text1 ='''
北欧福利网页：https://kknews.cc/zh-tw/world/3q2r8ng.html

铭传网网页：http://172.104.79.148/mcu/?act=shopping&cmd=main&pg_id=2020093000006

               '''
        message = TextSendMessage(
            text = text1
        )
        line_bot_api.reply_message(event.reply_token,message)
    except:
        line_bot_api.reply_message(event.reply_token,TextSendMessage(text='发生错误！'))


from django.core.urlresolvers import reverse
from django.http import Http404
from django.shortcuts import render
from django.shortcuts import redirect
from django.shortcuts import HttpResponseRedirect
from django.conf import settings
from thought.thought import *
from thought.dicontainer import CONTAINER

def index(request):
    tags = CONTAINER.getTagManager().getTags()
    tagMax = tags and max([tag.count for tag in tags]) or 0
    thoughts = CONTAINER.getThoughtManager().latest(settings.THOUGHTS_PER_PAGE)
    showMore = len(thoughts) == settings.THOUGHTS_PER_PAGE
    loadMoreUrl = reverse("latestPage", args=[1])

    return render(request, "thought/index.html",
            {'thoughts': thoughts, 'tags': tags, 'tagMax': tagMax,
             'showMore': showMore, 'loadMoreUrl': loadMoreUrl})

def latestPage(request, page):
    page = int(page)
    thoughts = CONTAINER.getThoughtManager().latest(
        settings.THOUGHTS_PER_PAGE,
        skip=page * settings.THOUGHTS_PER_PAGE)
    showMore = len(thoughts) == settings.THOUGHTS_PER_PAGE
    loadMoreUrl = reverse("latestPage", args=[page + 1])

    return render(request, "thought/thoughts_page.html", {
        'thoughts': thoughts, "showMore": showMore,
        'loadMoreUrl': loadMoreUrl
    })

def post(request):
    error = None
    thought = Thought()

    if request.method == 'POST':
        thought.text = request.POST.get('text')

        if thought.text:
            thought.date = datetime.now()
            thought.tags = getTagsList(request.POST.get('tags'))
            CONTAINER.getThoughtManager().create(thought)

            return redirect('index')
        else:
            error = "Thought shouldn't be empty, otherwise who may need it?"

    return render(request, "thought/post.html", {'thought': thought, 'error': error})

def edit(request, id):
    error = None
    thought = CONTAINER.getThoughtManager().get(id)

    if thought is None:
        raise Http404()

    if request.method == 'POST':
        thought.text = request.POST.get('text')
        if thought.text:
            thought.tags = getTagsList(request.POST.get('tags'))
            CONTAINER.getThoughtManager().save(thought)

            return redirect('index')
        else:
            error = "Thought shouldn't be empty, otherwise who may need it?"

    tags = (thought.get_tags() and ", ".join(thought.get_tags()) or "")
    return render(request, "thought/edit.html", {'thought': thought, 'tags': tags, 'error': error})

def thought(request, id):
    thought = CONTAINER.getThoughtManager().get(id)
    return render(request, "thought/thought.html", {'thought': thought})

def remove(request, id):
    CONTAINER.getThoughtManager().deleteById(id)
    return HttpResponseRedirect(reverse('index'))

def tag(request, tag):
    tags = CONTAINER.getTagManager().getTags()
    tagMax = tags and max([each.count for each in tags]) or 0
    thoughts = CONTAINER.getThoughtManager().searchByTag(tag, settings.THOUGHTS_PER_PAGE)
    showMore = len(thoughts) == settings.THOUGHTS_PER_PAGE
    loadMoreUrl = reverse("tagPage", args=[tag, 1])

    return render(request, "thought/tag.html", {
        "tag": tag, 'thoughts': thoughts, 'tags': tags,
        'tagMax': tagMax, 'showMore': showMore,
        'loadMoreUrl': loadMoreUrl
    })

def tagPage(request, tag, page):
    page = int(page)
    thoughts = CONTAINER.getThoughtManager().searchByTag(
        tag, settings.THOUGHTS_PER_PAGE,
        skip=page * settings.THOUGHTS_PER_PAGE)

    showMore = len(thoughts) == settings.THOUGHTS_PER_PAGE
    loadMoreUrl = reverse("tagPage", args=[tag, page + 1])

    return render(request, "thought/thoughts_page.html", {
        'thoughts': thoughts,
        'showMore': showMore,
        'loadMoreUrl': loadMoreUrl
    })

def appSettings(request):
    return render(request, "thought/settings.html")

def getTagsList(tagsText):
    tags = parseTags(tagsText)
    removeEmptyTag(tags)
    tags.sort()

    return tags

def parseTags(tagsText):
    tags = [tag.strip().lower() for tag in tagsText.split(",")]
    return prepareTags(tags)

def prepareTags(tags):
    return [tag.lower().replace("/", "") for tag in tags]

def removeEmptyTag(tags):
    try:
        tags.remove("")
    except ValueError:
        pass