from sklearn.model_selection import train_test_split
from tensorflow.keras.layers import Dense
from keras.utils import np_utils
from tensorflow.keras.models import Sequential
import matplotlib.pyplot as plt
from scipy.io import loadmat
import numpy as np

def display(i):
    img = X[i]
    plt.title('Example'+ str(i)+ 'Label:'+str(Y[i])+ 'Predicted:'+str(ypred[i]))
    plt.imshow(img.reshape((28,28)),cmap=plt.cm.gray_r)
    plt.show()

def plot_accuracy(history):
    plt.plot(history.history['accuracy'])
    plt.plot(history.history['val_accuracy'])
    plt.title('Model accuracy')
    plt.ylabel('Accuracy')
    plt.xlabel('Epoch')
    plt.legend(['Train', 'Test'], loc='upper left')
    plt.show()

def plot_loss(history):
    plt.plot(history.history['loss'])
    plt.plot(history.history['val_loss'])
    plt.title('Model loss')
    plt.ylabel('Loss')
    plt.xlabel('Epoch')
    plt.legend(['Train', 'Test'], loc='upper left')
    plt.show()

mnist = loadmat('mnist-original')
X , Y = mnist['data'] , mnist['label']
X= X.T
Y = Y.T
X_train , X_test , Y_train , Y_test = train_test_split(X,Y,test_size=0.1,shuffle = True)
X_train , X_val , Y_train , Y_val = train_test_split(X_train,Y_train,test_size=0.2,shuffle = True)

X_train = X_train/255
X_test = X_test/255
X_val = X_val/255
Ytrain = np_utils.to_categorical(Y_train)
Ytest = np_utils.to_categorical(Y_test)
Yval = np_utils.to_categorical(Y_val)

model = Sequential()
model.add(Dense(784,input_shape=(784,),activation='relu',kernel_initializer='normal'))
model.add(Dense(10, activation = 'softmax',kernel_initializer='normal'))
model.compile(loss='categorical_crossentropy' , optimizer = 'adam' , metrics = ['accuracy'])

history = model.fit(X_train ,Ytrain,batch_size = 512 ,epochs=30,verbose=2, validation_data=(X_val,Yval))

test_accuracy = model.evaluate(x=X_test,y=Ytest,batch_size=200,verbose=2)
print("Test results : ", test_accuracy)

Ypred = model.predict(X)
ypred = []
for i in Ypred:
    ypred.append(np.argmax(i))

plot_accuracy(history)
plot_loss(history)


from PyQt5 import QtCore, QtGui, QtWidgets, uic
import sys
from AssignmentCategoryDict import AssignmentCategoryDict
from Assignment import Assignment
import uuid

class EditCategories(object):

    def __init__(self, course, reload_gradesheet):

        col_headers = ['Category Name', 'Drop Count']

        self.ECategories = QtWidgets.QDialog()
        self.ui = uic.loadUi('../assets/ui/EditCategories.ui', self.ECategories)
        self.ECategories.categoryTable.setHorizontalHeaderLabels(col_headers)

        self.course = course
        self.ECategories.show()
        self.category_uuids = []
        self.setup_display()
        self.reload_gradesheet = reload_gradesheet

        self.original_row_count = self.ECategories.categoryTable.rowCount()

        self.ECategories.removeSelectedCategoryButton.clicked.connect(self.remove_category)
        self.ECategories.addCategoryButton.clicked.connect(self.add_category)
        self.ECategories.saveCategoriesButton.clicked.connect(self.save_table_data)

    def setup_display(self):
        for category in self.course.assignment_category_dict.assignment_categories.values():
            row_insert = self.ECategories.categoryTable.rowCount()
            self.add_category()
            self.ECategories.categoryTable.setItem(row_insert, 0, QtWidgets.QTableWidgetItem(category.categoryName))
            self.ECategories.categoryTable.setItem(row_insert, 1, QtWidgets.QTableWidgetItem(category.drop_count))
            self.category_uuids.append(category.category_uuid)

    def add_category(self):
        row_insert = self.ECategories.categoryTable.rowCount()
        self.ECategories.categoryTable.insertRow(self.ECategories.categoryTable.rowCount())
        self.ECategories.categoryTable.setItem(row_insert, 0, QtWidgets.QTableWidgetItem(""))
        self.ECategories.categoryTable.setItem(row_insert, 1, QtWidgets.QTableWidgetItem(""))

    def remove_category(self):
        if self.ECategories.categoryTable.rowCount() <= 0:
            return
        row = self.ECategories.categoryTable.currentRow()
        if row > self.original_row_count:
            self.ECategories.categoryTable.removeRow(row)
        else:
            choice = QtWidgets.QMessageBox.question(self.ECategories, "Warning",
                                                    "You are about to delete one of your original categories.  Continue?",
                                                    QtWidgets.QMessageBox.Yes, QtWidgets.QMessageBox.No)
            if choice == QtWidgets.QMessageBox.Yes:
                cat_to_delete_uuid = self.category_uuids[row]
                self.course.assignment_category_dict.delete_category(self.course, cat_to_delete_uuid)
                self.original_row_count = self.original_row_count - 1
                del self.category_uuids[row]
                self.ECategories.categoryTable.removeRow(row)
                self.reload_gradesheet()

    def save_table_data(self):
        row_count = self.ECategories.categoryTable.rowCount()
        output = []
        for row in range(0, row_count):
            cat_name = self.ECategories.categoryTable.item(row, 0).text()
            cat_drop_count = self.ECategories.categoryTable.item(row, 1).text()
            output.append([cat_name, cat_drop_count])

        valid = self.error_checking(output)

        if valid:
            self.course.assignment_category_dict.reload_categories()
            for i in range(len(output)):
                if i < self.original_row_count:
                    self.course.assignment_category_dict.save_category_info(output[i][0], output[i][1], self.category_uuids[i])
                    # Add the database update function
                else:
                    self.course.assignment_category_dict.add_category(str(uuid.uuid4()), output[i][0], output[i][1], self.course.student_list)
                    # Add the database create function
            self.reload_gradesheet()

    def error_checking(self, user_input):

        category_names = [user_input[i][0] for i in range(len(user_input))]
        category_drop_counts = [user_input[i][1] for i in range(len(user_input))]

        for i in category_names:
            if i == "":
                self.bad_input('Error', 'Please enter a category name for all categories')
                return False

        for i in category_drop_counts:

            if "." in i:
                return False

            try:
                x = int(i.strip())
                if x < 0:
                    return False
            except ValueError:
                self.bad_input('Error', 'You have a drop count that is a nonnegative integer.  Please try again.')
                return False

        return True
    """
        Function for telling the user they entered bad input
        Parameters:
            window_text: (string) the name of the window
            error_message: (string) the error message that is displayed to the user
    """

    def bad_input(self, window_text, error_message):
        choice = QtWidgets.QMessageBox.question(self.ECategories, window_text, error_message,
                                                QtWidgets.QMessageBox.Cancel)
        if choice:
            pass


from django.shortcuts import render
from .models    import *
import cv2
import numpy as np
from pytesseract import *

pytesseract.tesseract_cmd="C:/Program Files/Tesseract-OCR/tesseract.exe"

def main(request):

    return render(request,'main.html')

def maintest(request):

    return render(request,'maintest.html')

def kakaomap(request):
    hospital = Hospital.objects.all()

    return render(request,'kakaomap.html',{'hospital':hospital })

def camera(request):

    return render(request,'camera.html')

def history(request):

    img = image.objects.all()

    return render(request,'history.html',{'img':img})

def result(request):

    prescription = image.objects.create(
       sample=request.FILES.get('camera'),
   )

    pic = prescription.sample

    pic = "./media/"+ str(pic)

    img = cv2.imread("test4.jpg")
    orig = img.copy() #원본 이미지 복사

    rect_img = img[355:660, 60:317]

    #r = 800.0 / img.shape[0]
    #dim = (int(img.shape[1] * r), 800)
    #img = cv2.resize(img, dim, interpolation=cv2.INTER_AREA)

    #print("STEP 1: Edge Detection")

    #cv2.namedWindow('img', cv2.WINDOW_NORMAL)
    #cv2.namedWindow('edged', cv2.WINDOW_NORMAL)

    #print(str(pytesseract.image_to_string(img)))
    custom_config = 'outputbase nobatch digits'

    number = pytesseract.image_to_string(rect_img,config=custom_config)

    dist = ""
    db = []

    for num in number:
        dist += num
        if(num == "\n"):
            try:
                db.append(Medicine.objects.get(m_Code=int(dist)))
            except:
                continue

    count = len(db)

    return render(request,'result.html',{'db':db, 'count':count})


########################################################
###   Programmers:    Steffan Davies                 ###
###   Contact:        steffanclentdavies@gmail.com   ###
###   Date:           27/12/2022                     ###
########################################################

# This script will demonstrate dictionaries

favorite_numbers = {
    "john": [3, 5, 4],
    "sarah": [5],
    "michael": [1, 6],
    "doug": [13, 7],
    "sam": [7],
}

for person, numbers in favorite_numbers.items():
    if len(numbers) > 1:
        print(f"{person.title()}'s favorite numbers are:")
    elif len(numbers) == 1:
        print(f"{person.title()}'s favorite number is:")
    for number in numbers:
        print(f"\t{number}")


# from __future__ import absolute_import
import torch
import torch.nn as nn
import onnx
from typing import List, Dict, Union, Optional, Tuple, Sequence
import copy
from .util import*
from torch.autograd import Variable

class onnxTorchModel(nn.Module):
    def __init__(self,onnx_model: onnx.ModelProto,cfg:dict):
        super(onnxTorchModel,self).__init__()
        self.onnx_model=onnx_model
        self.nodes=self.onnx_model.graph.node
        self.pad_split=cfg["pad_split"]

        self.weights_in_constant_flg=False
        if len(onnx_model.graph.initializer)==0:
            self.weights_in_constant_flg=True

        self.op_type_list=[]
        self.current_id=0
        self.forwardExcList=[]
        self.onnxBlobNameTable={}

        self.generateOnnxBlobNameTable()
        self.parseOnnx()

    def getOnnxNameFromTable(self,name):
        for n in self.onnxBlobNameTable.keys():
            if self.onnxBlobNameTable[n]==name:
                return n

    def forward(self, input):
        net_input=self.onnx_model.graph.input
        net_output=self.onnx_model.graph.output
        if len(net_input)==1:
            exc_str="{node_input}=input".format(node_input=self.onnxBlobNameTable[net_input[0].name])
            exec(exc_str)

        for exc_info in self.forwardExcList:
            if "exec_pad" in exc_info.keys():
                exec(exc_info["exec_pad"])
            exc_str=exc_info["exec"]
            exec(exc_str)

        if len(net_output)==1:
            exc_str="self.net_output={node_output}".format(node_output=self.onnxBlobNameTable[net_output[0].name])
            exec(exc_str)
        return self.net_output

    def parseOnnx(self):
        nodes = self.onnx_model.graph.node
        for nid,node in enumerate(nodes):
            self.current_id=nid
            op_type=node.op_type
            if op_type not in self.op_type_list:
                self.op_type_list.append(op_type)
            print("Parsing onnx:",op_type)

            if op_type=="Conv":
                self.parseConv(node)
            elif op_type=="BatchNormalization":
                self.parseBN(node)
            elif op_type=="Flatten":
                self.parseFlatten(node)
            elif op_type=="Relu":
                self.parseRelu(node)
            elif op_type=="MaxPool":
                self.parseMaxPool(node)
            elif op_type=="Add":
                self.parseAdd(node)
            elif op_type=="GlobalAveragePool":
                self.parseGlobalAveragePool(node)
            elif op_type=="MatMul":
                self.parseMatMul(node)
            elif op_type=="Softmax":
                self.parseSoftmax(node)
            elif op_type=="Identity":
                self.parseIdentity(node)
            elif op_type=="Constant":
                self.parseNonWeightsConstant(node)

    # torch.nn.Conv2d(in_channels: int, out_channels: int,
    # kernel_size: Union[T, Tuple[T, T]], stride: Union[T, Tuple[T, T]] = 1,
    # padding: Union[T, Tuple[T, T]] = 0, dilation: Union[T, Tuple[T, T]] = 1,
    # groups: int = 1, bias: bool = True, padding_mode: str = 'zeros')
    def parseConv(self,node):
        attr=attribute_to_dict(node.attribute)
        if(self.weights_in_constant_flg):
            wt,bt=get_conv_params_in_constant(node,self.onnx_model.graph.node)
        has_bias=True
        if len(node.input)==2:
            has_bias=False
        c,n,k_w,k_h=wt.shape
        c=c*int(attr["group"])
        n=n*int(attr["group"])
        var_name="self.{type}_{id}".format(type=node.op_type,id=self.current_id)
        pad_t=attr["pads"][0]
        pad_b=attr["pads"][2]
        pad_l=attr["pads"][1]
        pad_r=attr["pads"][3]

        if(pad_t!=pad_b or pad_l!=pad_r or self.pad_split):
            exc_str_pad="{var_name}_pad=nn.ConstantPad2d(padding={padding},value={value})".format(var_name=var_name,padding=(pad_l,pad_r,pad_t,pad_b),value=0)
            exc_str_conv="{var_name}=nn.Conv2d(in_channels={in_channels},out_channels={out_channels},kernel_size={kernel_size},stride={stride},padding={padding},dilation={dilation},groups={groups},bias={bias})".format(var_name=var_name,\
                in_channels=c,\
                out_channels=n,\
                kernel_size=tuple(attr["kernel_shape"]),\
                stride=tuple(attr["strides"]),\
                padding=(0,0),\
                dilation=tuple(attr["dilations"]),\
                groups=attr["group"],\
                bias=True)

            self.generateForwardExec(node,var_name,op_pad_split=True)
            exec(exc_str_pad)
            exec(exc_str_conv)
            exc_init_weights_str="{var_name}.weight=torch.nn.Parameter(torch.Tensor(wt))".format(var_name=var_name)
            exec(exc_init_weights_str)
        else:
            exc_str="{var_name}=nn.Conv2d(in_channels={in_channels},out_channels={out_channels},kernel_size={kernel_size},stride={stride},padding={padding},dilation={dilation},groups={groups},bias={bias})".format(var_name=var_name,\
                            in_channels=c,\
                            out_channels=n,\
                            kernel_size=tuple(attr["kernel_shape"]),\
                            stride=tuple(attr["strides"]),\
                            padding=tuple(attr["pads"][:2]),\
                            dilation=tuple(attr["dilations"]),\
                            groups=attr["group"],\
                            bias=True)

            self.generateForwardExec(node,var_name)
            exec(exc_str)
            exc_init_weights_str="{var_name}.weight=torch.nn.Parameter(torch.Tensor(wt))".format(var_name=var_name)
            exec(exc_init_weights_str)

        if has_bias:
            self.forwardExcList[len(self.forwardExcList)-1]["has_bias"]=True
            exc_init_bias_str="{var_name}.bias=torch.nn.Parameter(torch.Tensor(bt))".format(var_name=var_name)
            exec(exc_init_bias_str)
        else:
            self.forwardExcList[len(self.forwardExcList)-1]["has_bias"]=False
            exc_init_bias_str="nn.init.constant_({var_name}.bias, 0)".format(var_name=var_name)
            exec(exc_init_bias_str)

    # torch.nn.BatchNorm2d(num_features, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    def parseBN(self,node):
        attr=attribute_to_dict(node.attribute)
        if(self.weights_in_constant_flg):
            bn_scale,bn_B,bn_mean,bn_var=get_bn_params_in_constant(node,self.onnx_model.graph.node)
        n=bn_scale.shape[0]
        var_name="self.{type}_{id}".format(type=node.op_type,id=self.current_id)
        exc_str="{var_name}=nn.BatchNorm2d(num_features={num_features},eps={eps},momentum={momentum})".format(var_name=var_name,\
            num_features=n,eps=attr["epsilon"],momentum=attr["momentum"])
        exec(exc_str)
        bn_scale,bn_B,bn_mean,bn_var=get_bn_params_in_constant(node, self.nodes)
        exc_init_scale_str="{var_name}.weight=torch.nn.Parameter(torch.Tensor(bn_scale))".format(var_name=var_name)
        exc_init_bias_str="{var_name}.bias=torch.nn.Parameter(torch.Tensor(bn_B))".format(var_name=var_name)
        exc_init_mean_str="{var_name}.running_mean=torch.Tensor(bn_mean)".format(var_name=var_name)
        exc_init_var_str="{var_name}.running_var=torch.Tensor(bn_var)".format(var_name=var_name)
        exec(exc_init_scale_str)
        exec(exc_init_bias_str)
        exec(exc_init_mean_str)
        exec(exc_init_var_str)
        self.generateForwardExec(node,var_name)

    def parseFlatten(self,node):
        attr=attribute_to_dict(node.attribute)
        var_name="self.{type}_{id}".format(type=node.op_type,id=self.current_id)
        exc_str="{var_name}=nn.Flatten(start_dim={start_dim})".format(var_name=var_name,start_dim=attr["axis"])
        self.generateForwardExec(node,var_name)
        exec(exc_str)

    def parseRelu(self,node):
        attr=attribute_to_dict(node.attribute)
        var_name="self.{type}_{id}".format(type=node.op_type,id=self.current_id)
        exc_str="{var_name}=nn.ReLU()".format(var_name=var_name)
        self.generateForwardExec(node,var_name)
        exec(exc_str)

    # torch.nn.MaxPool2d(kernel_size: Union[T, Tuple[T, ...]],
    # stride: Optional[Union[T, Tuple[T, ...]]] = None,
    # padding: Union[T, Tuple[T, ...]] = 0, dilation: Union[T, Tuple[T, ...]] = 1,
    # return_indices: bool = False, ceil_mode: bool = False)
    def parseMaxPool(self,node):
        attr=attribute_to_dict(node.attribute)
        var_name="self.{type}_{id}".format(type=node.op_type,id=self.current_id)
        pad_t=attr["pads"][0]
        pad_b=attr["pads"][2]
        pad_l=attr["pads"][1]
        pad_r=attr["pads"][3]

        if(pad_t!=pad_b or pad_l!=pad_r or pad_r!=pad_t or self.pad_split):
            exc_str_pad="{var_name}_pad=nn.ConstantPad2d(padding={padding},value={value})".format(var_name=var_name,padding=(pad_l,pad_r,pad_t,pad_b),value=0)
            exc_str="{var_name}=nn.MaxPool2d(kernel_size={kernel_shape},padding={pads},stride={strides})".format(var_name=var_name,\
                kernel_shape=tuple(attr["kernel_shape"]),\
                pads=0,\
                strides=tuple(attr["strides"]))
            exec(exc_str_pad)
            exec(exc_str)
            self.generateForwardExec(node,var_name,op_pad_split=True)
        else:
            exc_str="{var_name}=nn.MaxPool2d(kernel_size={kernel_shape},padding={pads},stride={strides})".format(var_name=var_name,\
                kernel_shape=tuple(attr["kernel_shape"]),\
                pads=attr["pads"][0],\
                strides=tuple(attr["strides"]))
            exec(exc_str)
            self.generateForwardExec(node,var_name)

    def parseAdd(self,node):
        attr=attribute_to_dict(node.attribute)
        var_name="torch.add"
        self.generateForwardExecMultiInput(node,var_name,filter_const=False,is_instance=False)

    def parseGlobalAveragePool(self,node):
        attr=attribute_to_dict(node.attribute)
        var_name="self.{type}_{id}".format(type=node.op_type,id=self.current_id)
        exc_str="{var_name}=nn.AdaptiveAvgPool2d((1, 1))".format(var_name=var_name)
        self.generateForwardExec(node,var_name)
        exec(exc_str)

    def parseMatMul(self,node):
        attr=attribute_to_dict(node.attribute)
        var_name="torch.matmul"
        self.generateForwardExecMultiInput(node,var_name,filter_const=False,is_instance=False)

    def parseSoftmax(self,node):
        attr=attribute_to_dict(node.attribute)
        var_name="self.{type}_{id}".format(type=node.op_type,id=self.current_id)
        if attr["axis"]==-1:
            exc_str="{var_name}=nn.Softmax(dim=1)".format(var_name=var_name)
            exec(exc_str)
        else:
            exc_str="{var_name}=nn.Softmax(dim={dim})".format(var_name=var_name,dim= attr["axis"])
            exec(exc_str)
        self.generateForwardExec(node,var_name)

    def parseIdentity(self,node):
        inputs=node.input
        outputs=node.output
        var_name="self.{type}_{id}".format(type=node.op_type,id=self.current_id)
        input_blob=self.onnxBlobNameTable[inputs[0]]
        output_blob=self.onnxBlobNameTable[outputs[0]]
        forwardExcStr="{output_name}={input_name}".format(output_name=output_blob,input_name=input_blob)
        nodeInfoDict={"exec":forwardExcStr,"var_name":var_name,"type":"Identity","input":[input_blob],"output":[output_blob],"is_instance":False,"id":self.current_id}
        self.forwardExcList.append(nodeInfoDict)

    def parseNonWeightsConstant(self,node):
        output_name=node.output[0]
        next_type=get_node_type_by_input(output_name,self.nodes)
        weight_node_list=["Conv","BatchNormalization"]
        if next_type not in weight_node_list:
            constant_tonser=get_tensor_in_constant(output_name,self.nodes)
            var_name="self.{type}_{id}".format(type=node.op_type,id=self.current_id)
            output_blob=self.onnxBlobNameTable[output_name]
            exc_str="{var_name}=torch.nn.Parameter(torch.tensor(constant_tonser))".format(var_name=var_name)
            exec(exc_str)
            forwardExcStr="{output}={var_name}".format(output=output_blob,var_name=var_name)
            nodeInfoDict={"exec":forwardExcStr,"var_name":var_name,"type":node.op_type,"input":[],"output":[output_blob],"is_instance":True}
            self.forwardExcList.append(nodeInfoDict)

    ###################################### support func area
    def generateForwardExec(self,node,var_name,filter_const=True,is_instance=True,op_pad_split=False):
        inputs=node.input
        outputs=node.output
        # node_type=node.op_type
        # next_type=
        dynamic_input=[]
        dynamic_output=[]

        for inputname in inputs:
            if filter_const and get_node_type_by_output(inputname,self.nodes)=="Constant":
                continue
            dynamic_input.append(self.onnxBlobNameTable[inputname])

        for outputname in outputs:
            dynamic_output.append(self.onnxBlobNameTable[outputname])

        if len(dynamic_input)>1:
            assert(0)

        if len(dynamic_input)==0:
            dynamic_input.append(self.onnxBlobNameTable[inputs[0]])

        input_blob=dynamic_input[0]
        output_blob=dynamic_output[0]

        if op_pad_split:
            forwardExcStrPad="{output_name}_pad={var_name}_pad({input_name})".format(output_name=input_blob,var_name=var_name,input_name=input_blob)
            forwardExcStr="{output_name}={var_name}({input_name}_pad)".format(output_name=output_blob,var_name=var_name,input_name=input_blob)
            nodeInfoDict={"exec":forwardExcStr,"exec_pad":forwardExcStrPad,"var_name":var_name,"type":node.op_type,"input":dynamic_input,"output":[output_blob],"is_instance":is_instance,"id":self.current_id}
        else:
            forwardExcStr="{output_name}={var_name}({input_name})".format(output_name=output_blob,var_name=var_name,input_name=input_blob)
            nodeInfoDict={"exec":forwardExcStr,"var_name":var_name,"type":node.op_type,"input":dynamic_input,"output":[output_blob],"is_instance":is_instance,"id":self.current_id}

        self.forwardExcList.append(nodeInfoDict)

        for i in range(1,len(dynamic_output)):
            forwardExcStr="{output_name}={input_name}".format(output_name=dynamic_output[i],input_name=dynamic_output[0])
            nodeInfoDict={"exec":forwardExcStr,"var_name":"Copy","type":"Copy","input":[dynamic_output[0]],"output":[output_blob],"is_instance":False,"id":self.current_id}
            self.forwardExcList.append(nodeInfoDict)

    def generateForwardExecMultiInput(self,node,var_name,filter_const=True,is_instance=True):
        inputs=node.input
        outputs=node.output
        dynamic_input=[]
        dynamic_output=[]

        for inputname in inputs:
            if filter_const and get_node_type_by_output(inputname,self.nodes)=="Constant":
                continue
            dynamic_input.append(self.onnxBlobNameTable[inputname])

        for outputname in outputs:
            dynamic_output.append(self.onnxBlobNameTable[outputname])

        input_blob=dynamic_input[0]
        output_blob=dynamic_output[0]

        input_blob_str=""
        for input_blob in dynamic_input:
            input_blob_str+=","+input_blob

        input_blob_str=input_blob_str[1:]
        forwardExcStr="{output_name}={var_name}({input_name})".format(output_name=output_blob,var_name=var_name,input_name=input_blob_str)
        nodeInfoDict={"exec":forwardExcStr,"var_name":var_name,"type":node.op_type,"input":dynamic_input,"output":[output_blob],"is_instance":is_instance,"id":self.current_id}
        self.forwardExcList.append(nodeInfoDict)

        for i in range(1,len(dynamic_output)):
            forwardExcStr="{output_name}={input_name}".format(output_name=dynamic_output[i],input_name=dynamic_output[0])
            nodeInfoDict={"exec":forwardExcStr,"var_name":"Copy","type":"Copy","input":[dynamic_output[0]],"output":[output_blob],"is_instance":False,"id":self.current_id}
            self.forwardExcList.append(nodeInfoDict)

    def generateOnnxBlobNameTable(self):
        nodes = self.onnx_model.graph.node
        id_count=0
        for nid,node in enumerate(nodes):
            inputs=node.input
            outputs=node.output
            for name in inputs:
                if name not in self.onnxBlobNameTable.keys():
                    self.onnxBlobNameTable[name]="self.blob_"+str(id_count)
                    id_count+=1
            for name in outputs:
                if name not in self.onnxBlobNameTable.keys():
                    self.onnxBlobNameTable[name]="self.blob_"+str(id_count)
                    id_count+=1

    def getFeatureTensor(self,name):
        exec("self.outTensor= {name}".format(name=name))
        return self.outTensor


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

""" #+begin_org
* *[Summary]* :: A =CmndLib= for providing currents configuration to CS-s.
#+end_org """

####+BEGIN: b:py3:cs:file/dblockControls :classification "cs-u"
""" #+begin_org
* [[elisp:(org-cycle)][| /Control Parameters Of This File/ |]] :: dblk ctrls classifications=cs-u
#+BEGIN_SRC emacs-lisp
(setq-local b:dblockControls t) ; (setq-local b:dblockControls nil)
(put 'b:dblockControls 'py3:cs:Classification "cs-u") ; one of cs-mu, cs-u, cs-lib, bpf-lib, pyLibPure
#+END_SRC
#+RESULTS:
: cs-u
#+end_org """
####+END:

####+BEGIN: b:prog:file/proclamations :outLevel 1
""" #+begin_org
* *[[elisp:(org-cycle)][| Proclamations |]]* :: Libre-Halaal Software --- Part Of BISOS ---  Poly-COMEEGA Format.
** This is Libre-Halaal Software. © Neda Communications, Inc. Subject to AGPL.
** It is part of BISOS (ByStar Internet Services OS)
** Best read and edited  with Blee in Poly-COMEEGA (Polymode Colaborative Org-Mode Enhance Emacs Generalized Authorship)
#+end_org """
####+END:

####+BEGIN: b:prog:file/particulars :authors ("./inserts/authors-mb.org")
""" #+begin_org
* *[[elisp:(org-cycle)][| Particulars |]]* :: Authors, version
** This File: /bisos/git/auth/bxRepos/bisos-pip/currents/py3/bisos/currents/currentsConfig.py
** Authors: Mohsen BANAN, http://mohsen.banan.1.byname.net/contact
#+end_org """
####+END:

####+BEGIN: b:python:file/particulars-csInfo :status "inUse"
""" #+begin_org
* *[[elisp:(org-cycle)][| Particulars-csInfo |]]*
#+end_org """
import typing
csInfo: typing.Dict[str, typing.Any] = { 'moduleName': ['currentsConfig'], }
csInfo['version'] = '202209290819'
csInfo['status']  = 'inUse'
csInfo['panel'] = 'currentsConfig-Panel.org'
csInfo['groupingType'] = 'IcmGroupingType-pkged'
csInfo['cmndParts'] = 'IcmCmndParts[common] IcmCmndParts[param]'
####+END:

""" #+begin_org
* /[[elisp:(org-cycle)][| Description |]]/ :: [[file:/bisos/git/auth/bxRepos/blee-binders/bisos-core/COMEEGA/_nodeBase_/fullUsagePanel-en.org][BISOS COMEEGA Panel]]
Module description comes here.
** Relevant Panels:
** Status: In use with blee3
** /[[elisp:(org-cycle)][| Planned Improvements |]]/ :
*** TODO complete fileName in particulars.
#+end_org """

####+BEGIN: b:prog:file/orgTopControls :outLevel 1
""" #+begin_org
* [[elisp:(org-cycle)][| Controls |]] :: [[elisp:(delete-other-windows)][(1)]] | [[elisp:(show-all)][Show-All]]  [[elisp:(org-shifttab)][Overview]]  [[elisp:(progn (org-shifttab) (org-content))][Content]] | [[elisp:(blee:ppmm:org-mode-toggle)][Nat]] | [[elisp:(bx:org:run-me)][Run]] | [[elisp:(bx:org:run-me-eml)][RunEml]] | [[elisp:(progn (save-buffer) (kill-buffer))][S&Q]]  [[elisp:(save-buffer)][Save]]  [[elisp:(kill-buffer)][Quit]] [[elisp:(org-cycle)][| ]]
** /Version Control/ ::  [[elisp:(call-interactively (quote cvs-update))][cvs-update]]  [[elisp:(vc-update)][vc-update]] | [[elisp:(bx:org:agenda:this-file-otherWin)][Agenda-List]]  [[elisp:(bx:org:todo:this-file-otherWin)][ToDo-List]]
#+end_org """
####+END:

####+BEGIN: b:python:file/workbench :outLevel 1
""" #+begin_org
* [[elisp:(org-cycle)][| Workbench |]] :: [[elisp:(python-check (format "/bisos/venv/py3/bisos3/bin/python -m pyclbr %s" (bx:buf-fname))))][pyclbr]] || [[elisp:(python-check (format "/bisos/venv/py3/bisos3/bin/python -m pydoc ./%s" (bx:buf-fname))))][pydoc]] || [[elisp:(python-check (format "/bisos/pipx/bin/pyflakes %s" (bx:buf-fname)))][pyflakes]] | [[elisp:(python-check (format "/bisos/pipx/bin/pychecker %s" (bx:buf-fname))))][pychecker (executes)]] | [[elisp:(python-check (format "/bisos/pipx/bin/pycodestyle %s" (bx:buf-fname))))][pycodestyle]] | [[elisp:(python-check (format "/bisos/pipx/bin/flake8 %s" (bx:buf-fname))))][flake8]] | [[elisp:(python-check (format "/bisos/pipx/bin/pylint %s" (bx:buf-fname))))][pylint]]  [[elisp:(org-cycle)][| ]]
#+end_org """
####+END:

####+BEGIN: b:py3:cs:orgItem/basic :type "=PyImports= " :title "*Py Library IMPORTS*" :comment "-- with classification based framework/imports"
""" #+begin_org
*  _[[elisp:(blee:menu-sel:outline:popupMenu)][±]]_ _[[elisp:(blee:menu-sel:navigation:popupMenu)][Ξ]]_ [[elisp:(outline-show-branches+toggle)][|=]] [[elisp:(bx:orgm:indirectBufOther)][|>]] *[[elisp:(blee:ppmm:org-mode-toggle)][|N]]*  =PyImports=  [[elisp:(outline-show-subtree+toggle)][||]] *Py Library IMPORTS* -- with classification based framework/imports  [[elisp:(org-cycle)][| ]]
#+end_org """
####+END:

####+BEGIN: b:py3:cs:framework/imports :basedOn "classification"
""" #+begin_org
** Imports Based On Classification=cs-u
#+end_org """
from bisos import b
from bisos.b import cs
from bisos.b import b_io

import collections
####+END:

import os
import collections
#import enum

import shutil

import sys

####+BEGIN: blee:bxPanel:foldingSection :outLevel 1 :title "Obtain Package Bases"  :extraInfo ""
""" #+begin_org
*  _[[elisp:(blee:menu-sel:outline:popupMenu)][±]]_ _[[elisp:(blee:menu-sel:navigation:popupMenu)][Ξ]]_ [[elisp:(outline-show-branches+toggle)][|=]] [[elisp:(bx:orgm:indirectBufOther)][|>]] *[[elisp:(blee:ppmm:org-mode-toggle)][|N]]*       [[elisp:(outline-show-subtree+toggle)][| *Obtain Package Bases:* |]]    [[elisp:(org-shifttab)][<)]] E|
#+end_org """
####+END:

####+BEGIN: b:py3:cs:func/typing :funcName "configBaseDir_obtain" :deco "track"
""" #+begin_org
*  _[[elisp:(blee:menu-sel:outline:popupMenu)][±]]_ _[[elisp:(blee:menu-sel:navigation:popupMenu)][Ξ]]_ [[elisp:(outline-show-branches+toggle)][|=]] [[elisp:(bx:orgm:indirectBufOther)][|>]] *[[elisp:(blee:ppmm:org-mode-toggle)][|N]]*  F-T-       [[elisp:(outline-show-subtree+toggle)][||]] /configBaseDir_obtain/  deco=track  [[elisp:(org-cycle)][| ]]
#+end_org """
@cs.track(fnLoc=True, fnEntry=True, fnExit=True)
def configBaseDir_obtain(
####+END:

) -> str:
    """ #+begin_org
** [[elisp:(org-cycle)][| *DocStr | ]
    #+end_org """

    outcome =  b.subProc.WOpW(invedBy=None, log=0).bash(
        f"""usgBpos.sh -i usgBpos_usageEnvs_fullUse_bxoPath""")

    if outcome.isProblematic():
        b_io.eh.badOutcome(outcome)
        return ""

    retVal = outcome.stdout.rstrip('\n')

    return retVal

####+BEGIN: bx:cs:python:func :funcName "configUsgCursBaseDir_obtain" :funcType "anyOrNone" :retType "bool" :deco "" :argsList "configBaseDir"
""" #+begin_org
*  _[[elisp:(blee:menu-sel:outline:popupMenu)][±]]_ _[[elisp:(blee:menu-sel:navigation:popupMenu)][Ξ]]_ [[elisp:(outline-show-branches+toggle)][|=]] [[elisp:(bx:orgm:indirectBufOther)][|>]] *[[elisp:(blee:ppmm:org-mode-toggle)][|N]]*  F-anyOrNone [[elisp:(outline-show-subtree+toggle)][||]] /configUsgCursBaseDir_obtain/ retType=bool argsList=(configBaseDir)  [[elisp:(org-cycle)][| ]]
#+end_org """
def configUsgCursBaseDir_obtain(
    configBaseDir,
):
####+END:
    if not configBaseDir:
        configBaseDir = configBaseDir_obtain()

    return os.path.abspath(os.path.join(configBaseDir, "control/currents"))

####+BEGIN: bx:cs:python:func :funcName "configUsgCursFpBaseDir_obtain" :funcType "anyOrNone" :retType "bool" :deco "" :argsList "configBaseDir"
""" #+begin_org
*  _[[elisp:(blee:menu-sel:outline:popupMenu)][±]]_ _[[elisp:(blee:menu-sel:navigation:popupMenu)][Ξ]]_ [[elisp:(outline-show-branches+toggle)][|=]] [[elisp:(bx:orgm:indirectBufOther)][|>]] *[[elisp:(blee:ppmm:org-mode-toggle)][|N]]*  F-anyOrNone [[elisp:(outline-show-subtree+toggle)][||]] /configUsgCursFpBaseDir_obtain/ retType=bool argsList=(configBaseDir)  [[elisp:(org-cycle)][| ]]
#+end_org """
def configUsgCursFpBaseDir_obtain(
    configBaseDir,
):
####+END:
    if not configBaseDir:
        configBaseDir = configBaseDir_obtain()

    return os.path.abspath(os.path.join(configBaseDir,"control/currents/fp"))

####+BEGIN: blee:bxPanel:foldingSection :outLevel 1 :title "File Parameters Obtain"
""" #+begin_org
*  _[[elisp:(blee:menu-sel:outline:popupMenu)][±]]_ _[[elisp:(blee:menu-sel:navigation:popupMenu)][Ξ]]_ [[elisp:(outline-show-branches+toggle)][|=]] [[elisp:(bx:orgm:indirectBufOther)][|>]] *[[elisp:(blee:ppmm:org-mode-toggle)][|N]]*       [[elisp:(outline-show-subtree+toggle)][| *File Parameters Obtain:* |]]    [[elisp:(org-shifttab)][<)]] E|
#+end_org """
####+END:

####+BEGIN: bx:cs:python:func :funcName "bxoId_fpObtain" :comment "Configuration Parameter" :funcType "anyOrNone" :retType "bool" :deco "" :argsList "configBaseDir"
""" #+begin_org
*  _[[elisp:(blee:menu-sel:outline:popupMenu)][±]]_ _[[elisp:(blee:menu-sel:navigation:popupMenu)][Ξ]]_ [[elisp:(outline-show-branches+toggle)][|=]] [[elisp:(bx:orgm:indirectBufOther)][|>]] *[[elisp:(blee:ppmm:org-mode-toggle)][|N]]*  F-anyOrNone [[elisp:(outline-show-subtree+toggle)][||]] /bxoId_fpObtain/ =Configuration Parameter= retType=bool argsList=(configBaseDir)  [[elisp:(org-cycle)][| ]]
#+end_org """
def bxoId_fpObtain(
    configBaseDir,
):
####+END:
    if not configBaseDir:
        configBaseDir = configBaseDir_obtain()

    return(
        b.fp.FileParamValueReadFrom(
            parRoot= os.path.abspath("{}/usgCurs/fp".format(configBaseDir)),
            parName="bxoId")
    )

####+BEGIN: bx:cs:python:func :funcName "sr_fpObtain" :comment "Configuration Parameter" :funcType "anyOrNone" :retType "bool" :deco "" :argsList "configBaseDir"
""" #+begin_org
*  _[[elisp:(blee:menu-sel:outline:popupMenu)][±]]_ _[[elisp:(blee:menu-sel:navigation:popupMenu)][Ξ]]_ [[elisp:(outline-show-branches+toggle)][|=]] [[elisp:(bx:orgm:indirectBufOther)][|>]] *[[elisp:(blee:ppmm:org-mode-toggle)][|N]]*  F-anyOrNone [[elisp:(outline-show-subtree+toggle)][||]] /sr_fpObtain/ =Configuration Parameter= retType=bool argsList=(configBaseDir)  [[elisp:(org-cycle)][| ]]
#+end_org """
def sr_fpObtain(
    configBaseDir,
):
####+END:
    if not configBaseDir:
        configBaseDir = configBaseDir_obtain()

    return(
        b.fp.FileParamValueReadFrom(
            parRoot= os.path.abspath("{}/usgCurs/fp".format(configBaseDir)),
            parName="sr")
    )

####+BEGIN: blee:bxPanel:foldingSection :outLevel 1 :title "Common Command Parameter Specification"
""" #+begin_org
*  _[[elisp:(blee:menu-sel:outline:popupMenu)][±]]_ _[[elisp:(blee:menu-sel:navigation:popupMenu)][Ξ]]_ [[elisp:(outline-show-branches+toggle)][|=]] [[elisp:(bx:orgm:indirectBufOther)][|>]] *[[elisp:(blee:ppmm:org-mode-toggle)][|N]]*       [[elisp:(outline-show-subtree+toggle)][| *Common Command Parameter Specification:* |]]    [[elisp:(org-shifttab)][<)]] E|
#+end_org """
####+END:

####+BEGIN: bx:cs:python:func :funcName "commonParamsSpecify" :funcType "void" :retType "bool" :deco "" :argsList "csParams"
""" #+begin_org
*  _[[elisp:(blee:menu-sel:outline:popupMenu)][±]]_ _[[elisp:(blee:menu-sel:navigation:popupMenu)][Ξ]]_ [[elisp:(outline-show-branches+toggle)][|=]] [[elisp:(bx:orgm:indirectBufOther)][|>]] *[[elisp:(blee:ppmm:org-mode-toggle)][|N]]*  F-void     [[elisp:(outline-show-subtree+toggle)][||]] /commonParamsSpecify/ retType=bool argsList=(csParams)  [[elisp:(org-cycle)][| ]]
#+end_org """
def commonParamsSpecify(
    csParams,
):
####+END:

    csParams.parDictAdd(
        parName='configBaseDir',
        parDescription="Root Of usgCurs/fp from which file parameters will be read",
        parDataType=None,
        parDefault=None,
        parChoices=["any"],
        # parScope=cs.CmndParamScope.TargetParam,
        argparseShortOpt=None,
        argparseLongOpt='--configBaseDir',
    )

    csParams.parDictAdd(
        parName='bxoId',
        parDescription="BISOS Default UserName",
        parDataType=None,
        parDefault=None,
        parChoices=["any"],
        # parScope=cs.CmndParamScope.TargetParam,
        argparseShortOpt=None,
        argparseLongOpt='--bxoId',
    )

    csParams.parDictAdd(
        parName='sr',
        parDescription="BISOS Default GroupName",
        parDataType=None,
        parDefault=None,
        parChoices=["any"],
        # parScope=cs.CmndParamScope.TargetParam,
        argparseShortOpt=None,
        argparseLongOpt='--sr',
    )

####+BEGIN: blee:bxPanel:foldingSection :outLevel 1 :title "Common Command Examples Sections"
""" #+begin_org
*  _[[elisp:(blee:menu-sel:outline:popupMenu)][±]]_ _[[elisp:(blee:menu-sel:navigation:popupMenu)][Ξ]]_ [[elisp:(outline-show-branches+toggle)][|=]] [[elisp:(bx:orgm:indirectBufOther)][|>]] *[[elisp:(blee:ppmm:org-mode-toggle)][|N]]*       [[elisp:(outline-show-subtree+toggle)][| *Common Command Examples Sections:* |]]    [[elisp:(org-shifttab)][<)]] E|
#+end_org """
####+END:

####+BEGIN: bx:cs:python:func :funcName "examples_usgCursParsFull" :funcType "anyOrNone" :retType "bool" :deco "" :argsList "configBaseDir"
""" #+begin_org
*  _[[elisp:(blee:menu-sel:outline:popupMenu)][±]]_ _[[elisp:(blee:menu-sel:navigation:popupMenu)][Ξ]]_ [[elisp:(outline-show-branches+toggle)][|=]] [[elisp:(bx:orgm:indirectBufOther)][|>]] *[[elisp:(blee:ppmm:org-mode-toggle)][|N]]*  F-anyOrNone [[elisp:(outline-show-subtree+toggle)][||]] /examples_usgCursParsFull/ retType=bool argsList=(configBaseDir)  [[elisp:(org-cycle)][| ]]
#+end_org """
def examples_usgCursParsFull(
    configBaseDir,
):
####+END:
    """
** Auxiliary examples to be commonly used.
"""

    def cpsInit(): return collections.OrderedDict()
    def menuItem(verbosity): cs.examples.cmndInsert(cmndName, cps, cmndArgs, verbosity=verbosity,
                             comment='none', icmWrapper=None, icmName=None) # verbosity: 'little' 'basic' 'none'
    def execLineEx(cmndStr): cs.examples.execInsert(execLine=cmndStr)

    cs.examples.menuChapter(' =FP Values=  *usgCurs Clear InfoBase --- Deletes All FPs*')

    cmndName = "usgCursParsDelete" ; cmndArgs = "" ;
    cps = collections.OrderedDict() ;  cps['configBaseDir'] = configBaseDir
    cs.examples.cmndInsert(cmndName, cps, cmndArgs, verbosity='little')

    cmndName = "usgCursParsDelete" ; cmndArgs = "" ; cps=cpsInit(); menuItem(verbosity='none')

    cmndName = "usgCursParsDelete" ; cmndArgs = "anyName" ;
    cps = collections.OrderedDict() ;
    cs.examples.cmndInsert(cmndName, cps, cmndArgs, icmWrapper="echo", verbosity='little')

    cs.examples.menuChapter(' =FP Values=  *usgCurs Get Parameters*')

    cmndName = "usgCursParsGet" ; cmndArgs = "" ;
    cps = collections.OrderedDict() ;  cps['configBaseDir'] = configBaseDir
    cs.examples.cmndInsert(cmndName, cps, cmndArgs, verbosity='little')

    cmndName = "usgCursParsGet" ; cmndArgs = "" ; cps=cpsInit(); menuItem(verbosity='none')

    cs.examples.menuChapter(' =FP Values=  *UsgCurs Defaults ParsSet  --*')

    cmndName = "usgCursParsDefaultsSet" ; cmndArgs = "bxoPolicy /" ;
    cpsInit(); menuItem('none')

    cmndName = "usgCursParsDefaultsSet" ; cmndArgs = "bxoPolicy /tmp" ;
    cpsInit(); menuItem('none')

    cs.examples.menuChapter(' =FP Values=  *UsgCurs ParsSet -- Set Parameters Explicitly*')

    cmndName = "usgCursParsSet" ; cmndArgs = "" ;
    cps = collections.OrderedDict() ;  cps['bxoId'] = "mcm"
    cs.examples.cmndInsert(cmndName, cps, cmndArgs, verbosity='little')

    cmndName = "usgCursParsSet" ; cmndArgs = "" ;
    cps = collections.OrderedDict() ;  cps['bxoId'] = "ea-59043"
    cs.examples.cmndInsert(cmndName, cps, cmndArgs, verbosity='little')

    cmndName = "usgCursParsSet" ; cmndArgs = "" ;
    cps = collections.OrderedDict() ;  cps['sr'] = "marme/dsnProc"
    cs.examples.cmndInsert(cmndName, cps, cmndArgs, verbosity='little')

    cmndName = "usgCursParsSet" ; cmndArgs = "" ;
    cps = collections.OrderedDict() ;  cps['sr'] = "apache2/plone3"
    cs.examples.cmndInsert(cmndName, cps, cmndArgs, verbosity='little')

    # cmndName = "usgCursParsSet" ; cmndArgs = "" ;
    # cps = collections.OrderedDict() ;  cps['configBaseDir'] = configBaseDir ; cps['platformControlBaseDir'] = "${HOME}/bisosControl"
    # cs.examples.cmndInsert(cmndName, cps, cmndArgs, verbosity='little')

    cmndName = "usgCursParsSet" ; cmndArgs = "anyName=anyValue" ;
    cps = collections.OrderedDict() ;
    cs.examples.cmndInsert(cmndName, cps, cmndArgs, verbosity='little')

    cmndName = "usgCursParsSet" ; cmndArgs = "anyName=anyValue" ;
    cps = collections.OrderedDict() ;
    cs.examples.cmndInsert(cmndName, cps, cmndArgs, icmWrapper="echo", verbosity='little')

####+BEGIN: blee:bxPanel:foldingSection :outLevel 1 :title "File Parameters Get/Set -- Commands"
""" #+begin_org
*  _[[elisp:(blee:menu-sel:outline:popupMenu)][±]]_ _[[elisp:(blee:menu-sel:navigation:popupMenu)][Ξ]]_ [[elisp:(outline-show-branches+toggle)][|=]] [[elisp:(bx:orgm:indirectBufOther)][|>]] *[[elisp:(blee:ppmm:org-mode-toggle)][|N]]*       [[elisp:(outline-show-subtree+toggle)][| *File Parameters Get/Set -- Commands:* |]]    [[elisp:(org-shifttab)][<)]] E|
#+end_org """
####+END:

####+BEGIN: bx:cs:python:func :funcName "FP_readTreeAtBaseDir_CmndOutput" :funcType "anyOrNone" :retType "bool" :deco "" :argsList "interactive fpBaseDir cmndOutcome"
""" #+begin_org
*  _[[elisp:(blee:menu-sel:outline:popupMenu)][±]]_ _[[elisp:(blee:menu-sel:navigation:popupMenu)][Ξ]]_ [[elisp:(outline-show-branches+toggle)][|=]] [[elisp:(bx:orgm:indirectBufOther)][|>]] *[[elisp:(blee:ppmm:org-mode-toggle)][|N]]*  F-anyOrNone [[elisp:(outline-show-subtree+toggle)][||]] /FP_readTreeAtBaseDir_CmndOutput/ retType=bool argsList=(interactive fpBaseDir cmndOutcome)  [[elisp:(org-cycle)][| ]]
#+end_org """
def FP_readTreeAtBaseDir_CmndOutput(
    interactive,
    fpBaseDir,
    cmndOutcome,
):
####+END:
    """Invokes FP_readTreeAtBaseDir.cmnd as interactive-output only."""
    #
    # Interactive-Output + Chained-Outcome Command Invokation
    #
    FP_readTreeAtBaseDir = icm.FP_readTreeAtBaseDir()
    FP_readTreeAtBaseDir.cmndLineInputOverRide = True
    FP_readTreeAtBaseDir.cmndOutcome = cmndOutcome

    return FP_readTreeAtBaseDir.cmnd(
        interactive=interactive,
        FPsDir=fpBaseDir,
    )

####+BEGIN: b:py3:cs:cmnd/classHead :cmndName "usgCursParsDelete" :comment "" :parsMand "" :parsOpt "configBaseDir" :argsMin 0 :argsMax 9999 :pyInv ""
""" #+begin_org
*  _[[elisp:(blee:menu-sel:outline:popupMenu)][±]]_ _[[elisp:(blee:menu-sel:navigation:popupMenu)][Ξ]]_ [[elisp:(outline-show-branches+toggle)][|=]] [[elisp:(bx:orgm:indirectBufOther)][|>]] *[[elisp:(blee:ppmm:org-mode-toggle)][|N]]*  CmndSvc-   [[elisp:(outline-show-subtree+toggle)][||]] <<usgCursParsDelete>>  =verify= parsOpt=configBaseDir argsMax=9999 ro=cli   [[elisp:(org-cycle)][| ]]
#+end_org """
class usgCursParsDelete(cs.Cmnd):
    cmndParamsMandatory = [ ]
    cmndParamsOptional = [ 'configBaseDir', ]
    cmndArgsLen = {'Min': 0, 'Max': 9999,}

    @cs.track(fnLoc=True, fnEntry=True, fnExit=True)
    def cmnd(self,
             rtInv: cs.RtInvoker,
             cmndOutcome: b.op.Outcome,
             configBaseDir: typing.Optional[str]=None,  # Cs Optional Param
             argsList: typing.Optional[list[str]]=None,  # CsArgs
    ) -> b.op.Outcome:

        callParamsDict = {'configBaseDir': configBaseDir, }
        if self.invocationValidate(rtInv, cmndOutcome, callParamsDict, argsList).isProblematic():
            return b_io.eh.badOutcome(cmndOutcome)
        cmndArgsSpecDict = self.cmndArgsSpec()
####+END:
        self.cmndDocStr(f""" #+begin_org
** [[elisp:(org-cycle)][| *CmndDesc:* | ]]  Remove The entire infoBaseDir
        #+end_org """)

        if not configBaseDir:
            configBaseDir = configUsgCursFpBaseDir_obtain(None)

        cmndArgs = self.cmndArgsGet("0&-1", cmndArgsSpecDict, argsList)

        if len(cmndArgs) == 0:
            try:
                shutil.rmtree(configBaseDir)
            except OSError as e:
                print(f"Error: {configBaseDir} : {e.strerror}")
            b.dir.createIfNotThere(configBaseDir)

        else:
            for each in cmndArgs:
                parNameFullPath = os.path.join(
                        configBaseDir,
                        each
                )
                try:
                    shutil.rmtree(parNameFullPath)
                except OSError as e:
                    print(f"Error: {parNameFullPath} : {e.strerror}")

        return cmndOutcome

####+BEGIN: b:py3:cs:method/args :methodName "cmndArgsSpec" :methodType "anyOrNone" :retType "bool" :deco "default" :argsList "self"
    """ #+begin_org
**  _[[elisp:(blee:menu-sel:outline:popupMenu)][±]]_ _[[elisp:(blee:menu-sel:navigation:popupMenu)][Ξ]]_ [[elisp:(outline-show-branches+toggle)][|=]] [[elisp:(bx:orgm:indirectBufOther)][|>]] *[[elisp:(blee:ppmm:org-mode-toggle)][|N]]*  Mtd-T-anyOrNone [[elisp:(outline-show-subtree+toggle)][||]] /cmndArgsSpec/ deco=default  deco=default  [[elisp:(org-cycle)][| ]]
    #+end_org """
    @cs.track(fnLoc=True, fnEntry=True, fnExit=True)
    def cmndArgsSpec(self, ):
####+END:
        """
***** Cmnd Args Specification
"""
        cmndArgsSpecDict = cs.CmndArgsSpecDict()
        cmndArgsSpecDict.argsDictAdd(
            argPosition="0&-1",
            argName="cmndArgs",
            argDefault=None,
            argChoices='any',
            argDescription="A sequence of parNames"
        )

        return cmndArgsSpecDict

####+BEGIN: b:py3:cs:func/typing :funcName "curParsGetAsDictValue_wOp" :funcType "WOp" :retType "extTyped" :deco "" :argsList ""
""" #+begin_org
*  _[[elisp:(blee:menu-sel:outline:popupMenu)][±]]_ _[[elisp:(blee:menu-sel:navigation:popupMenu)][Ξ]]_ [[elisp:(outline-show-branches+toggle)][|=]] [[elisp:(bx:orgm:indirectBufOther)][|>]] *[[elisp:(blee:ppmm:org-mode-toggle)][|N]]*  F-T-WOp    [[elisp:(outline-show-subtree+toggle)][||]] /curParsGetAsDictValue_wOp/   [[elisp:(org-cycle)][| ]]
#+end_org """
def curParsGetAsDictValue_wOp(
####+END:
        parNamesList: list,
        outcome: b.op.Outcome = None,
) -> b.op.Outcome:
    """ #+begin_org
** [[elisp:(org-cycle)][| *DocStr | ] A Wrapped Operation with results being a dictionary of values.
    if not ~parNamesList~, get all the values.
*** TODO --- NOTYET This needs to be moved to
    #+end_org """

    configBaseDir = configUsgCursFpBaseDir_obtain(None)

    return (
        FP_parsGetAsDictValue_wOp(parNamesList, configBaseDir, outcome)
    )

####+BEGIN: b:py3:cs:func/typing :funcName "FP_parsGetAsDictValue_wOp" :funcType "wOp" :retType "OpOutcome" :deco "" :argsList ""
""" #+begin_org
*  _[[elisp:(blee:menu-sel:outline:popupMenu)][±]]_ _[[elisp:(blee:menu-sel:navigation:popupMenu)][Ξ]]_ [[elisp:(outline-show-branches+toggle)][|=]] [[elisp:(bx:orgm:indirectBufOther)][|>]] *[[elisp:(blee:ppmm:org-mode-toggle)][|N]]*  F-T-wOp    [[elisp:(outline-show-subtree+toggle)][||]] /FP_parsGetAsDictValue_wOp/   [[elisp:(org-cycle)][| ]]
#+end_org """
def FP_parsGetAsDictValue_wOp(
####+END:
        parNamesList: list,
        configBaseDir,
        outcome: b.op.Outcome = None,
) -> b.op.Outcome:
    """ #+begin_org
** [[elisp:(org-cycle)][| *DocStr | ] A Wrapped Operation with results being a dictionary of values.
    if not ~parNamesList~, get all the values.
*** TODO --- NOTYET This needs to be moved to
    #+end_org """

    return b.fp.parsGetAsDictValue_wOp(parNamesList, configBaseDir, outcome=outcome)

    if not outcome:
        outcome = b.op.Outcome()

    FP_readTreeAtBaseDir_CmndOutput(
        interactive=False,
        fpBaseDir=configBaseDir,
        cmndOutcome=outcome,
    )

    results = outcome.results

    opResults = dict()
    opErrors = ""

    if parNamesList:
        for each in parNamesList:
            # NOTYET, If no results[each], we need to record it in opErrors
            opResults[each] = results[each].parValueGet()
            #print(f"{each} {eachFpValue}")

    else:
        for eachFpName in results:
            opResults[eachFpName] = results[eachFpName].parValueGet()
            #print(f"{eachFpName} {eachFpValue}")

    return outcome.set(
        opError=b.OpError.Success,
        opResults=opResults,
    )

####+BEGIN: b:py3:cs:cmnd/classHead :cmndName "usgCursParsGetK2" :comment "" :parsMand "" :parsOpt "configBaseDir" :argsMin 0 :argsMax 9999 :pyInv ""
""" #+begin_org
*  _[[elisp:(blee:menu-sel:outline:popupMenu)][±]]_ _[[elisp:(blee:menu-sel:navigation:popupMenu)][Ξ]]_ [[elisp:(outline-show-branches+toggle)][|=]] [[elisp:(bx:orgm:indirectBufOther)][|>]] *[[elisp:(blee:ppmm:org-mode-toggle)][|N]]*  CmndSvc-   [[elisp:(outline-show-subtree+toggle)][||]] <<usgCursParsGetK2>>  =verify= parsOpt=configBaseDir argsMax=9999 ro=cli   [[elisp:(org-cycle)][| ]]
#+end_org """
class usgCursParsGetK2(cs.Cmnd):
    cmndParamsMandatory = [ ]
    cmndParamsOptional = [ 'configBaseDir', ]
    cmndArgsLen = {'Min': 0, 'Max': 9999,}

    @cs.track(fnLoc=True, fnEntry=True, fnExit=True)
    def cmnd(self,
             rtInv: cs.RtInvoker,
             cmndOutcome: b.op.Outcome,
             configBaseDir: typing.Optional[str]=None,  # Cs Optional Param
             argsList: typing.Optional[list[str]]=None,  # CsArgs
    ) -> b.op.Outcome:

        callParamsDict = {'configBaseDir': configBaseDir, }
        if self.invocationValidate(rtInv, cmndOutcome, callParamsDict, argsList).isProblematic():
            return b_io.eh.badOutcome(cmndOutcome)
        cmndArgsSpecDict = self.cmndArgsSpec()
####+END:
        self.cmndDocStr(f""" #+begin_org
** [[elisp:(org-cycle)][| *CmndDesc:* | ]]  it reads from ../usgCurs/fp.
        #+end_org """)

        if not configBaseDir:
            configBaseDir = configUsgCursFpBaseDir_obtain(None)

        cmndArgs = self.cmndArgsGet("0&-1", cmndArgsSpecDict, argsList)

        # FP_readTreeAtBaseDir_CmndOutput(
        #     interactive=False,
        #     fpBaseDir=configBaseDir,
        #     cmndOutcome=cmndOutcome,
        # )

        b.fp.readTreeAtBaseDir_wOp(configBaseDir, cmndOutcome=cmndOutcome)

        results = cmndOutcome.results

        if len(cmndArgs) == 0:
            for eachFpName in results:
                eachFpValue = results[eachFpName].parValueGet()
                print(f"{eachFpName} {eachFpValue}")
        else:
            for each in cmndArgs:
                eachFpValue = results[each].parValueGet()
                print(f"{each} {eachFpValue}")

        return cmndOutcome

####+BEGIN: b:py3:cs:cmnd/classHead :cmndName "usgCursParsGet" :comment "" :parsMand "" :parsOpt "configBaseDir" :argsMin 0 :argsMax 9999 :pyInv ""
""" #+begin_org
*  _[[elisp:(blee:menu-sel:outline:popupMenu)][±]]_ _[[elisp:(blee:menu-sel:navigation:popupMenu)][Ξ]]_ [[elisp:(outline-show-branches+toggle)][|=]] [[elisp:(bx:orgm:indirectBufOther)][|>]] *[[elisp:(blee:ppmm:org-mode-toggle)][|N]]*  CmndSvc-   [[elisp:(outline-show-subtree+toggle)][||]] <<usgCursParsGet>>  =verify= parsOpt=configBaseDir argsMax=9999 ro=cli   [[elisp:(org-cycle)][| ]]
#+end_org """
class usgCursParsGet(cs.Cmnd):
    cmndParamsMandatory = [ ]
    cmndParamsOptional = [ 'configBaseDir', ]
    cmndArgsLen = {'Min': 0, 'Max': 9999,}

    @cs.track(fnLoc=True, fnEntry=True, fnExit=True)
    def cmnd(self,
             rtInv: cs.RtInvoker,
             cmndOutcome: b.op.Outcome,
             configBaseDir: typing.Optional[str]=None,  # Cs Optional Param
             argsList: typing.Optional[list[str]]=None,  # CsArgs
    ) -> b.op.Outcome:

        callParamsDict = {'configBaseDir': configBaseDir, }
        if self.invocationValidate(rtInv, cmndOutcome, callParamsDict, argsList).isProblematic():
            return b_io.eh.badOutcome(cmndOutcome)
        cmndArgsSpecDict = self.cmndArgsSpec()
####+END:
        self.cmndDocStr(f""" #+begin_org
** [[elisp:(org-cycle)][| *CmndDesc:* | ]]  it reads from ../usgCurs/fp.
        #+end_org """)

        if not configBaseDir:
            configBaseDir = configUsgCursFpBaseDir_obtain(None)

        cmndArgs = self.cmndArgsGet("0&-1", cmndArgsSpecDict, argsList)

        curParsGetAsDictValue_wOp(cmndArgs, cmndOutcome)
        results = cmndOutcome.results

        if rtInv.outs:
            for eachKey in results:
                print(f"{eachKey}: {results[eachKey]}")

        return cmndOutcome

####+BEGIN: b:py3:cs:method/args :methodName "cmndArgsSpec" :methodType "anyOrNone" :retType "bool" :deco "default" :argsList "self"
    """ #+begin_org
**  _[[elisp:(blee:menu-sel:outline:popupMenu)][±]]_ _[[elisp:(blee:menu-sel:navigation:popupMenu)][Ξ]]_ [[elisp:(outline-show-branches+toggle)][|=]] [[elisp:(bx:orgm:indirectBufOther)][|>]] *[[elisp:(blee:ppmm:org-mode-toggle)][|N]]*  Mtd-T-anyOrNone [[elisp:(outline-show-subtree+toggle)][||]] /cmndArgsSpec/ deco=default  deco=default  [[elisp:(org-cycle)][| ]]
    #+end_org """
    @cs.track(fnLoc=True, fnEntry=True, fnExit=True)
    def cmndArgsSpec(self, ):
####+END:
        """
***** Cmnd Args Specification
"""
        cmndArgsSpecDict = cs.CmndArgsSpecDict()
        cmndArgsSpecDict.argsDictAdd(
            argPosition="0&-1",
            argName="cmndArgs",
            argDefault=None,
            argChoices='any',
            argDescription="A sequence of parNames"
        )

        return cmndArgsSpecDict

####+BEGIN: b:py3:cs:cmnd/classHead :cmndName "usgCursParsSet" :comment "" :parsMand "" :parsOpt "configBaseDir bxoId sr" :argsMin 0 :argsMax 1000 :pyInv ""
""" #+begin_org
*  _[[elisp:(blee:menu-sel:outline:popupMenu)][±]]_ _[[elisp:(blee:menu-sel:navigation:popupMenu)][Ξ]]_ [[elisp:(outline-show-branches+toggle)][|=]] [[elisp:(bx:orgm:indirectBufOther)][|>]] *[[elisp:(blee:ppmm:org-mode-toggle)][|N]]*  CmndSvc-   [[elisp:(outline-show-subtree+toggle)][||]] <<usgCursParsSet>>  =verify= parsOpt=configBaseDir bxoId sr argsMax=1000 ro=cli   [[elisp:(org-cycle)][| ]]
#+end_org """
class usgCursParsSet(cs.Cmnd):
    cmndParamsMandatory = [ ]
    cmndParamsOptional = [ 'configBaseDir', 'bxoId', 'sr', ]
    cmndArgsLen = {'Min': 0, 'Max': 1000,}

    @cs.track(fnLoc=True, fnEntry=True, fnExit=True)
    def cmnd(self,
             rtInv: cs.RtInvoker,
             cmndOutcome: b.op.Outcome,
             configBaseDir: typing.Optional[str]=None,  # Cs Optional Param
             bxoId: typing.Optional[str]=None,  # Cs Optional Param
             sr: typing.Optional[str]=None,  # Cs Optional Param
             argsList: typing.Optional[list[str]]=None,  # CsArgs
    ) -> b.op.Outcome:

        callParamsDict = {'configBaseDir': configBaseDir, 'bxoId': bxoId, 'sr': sr, }
        if self.invocationValidate(rtInv, cmndOutcome, callParamsDict, argsList).isProblematic():
            return b_io.eh.badOutcome(cmndOutcome)
        cmndArgsSpecDict = self.cmndArgsSpec()
####+END:
        self.cmndDocStr(f""" #+begin_org
** [[elisp:(org-cycle)][| *CmndDesc:* | ]] Args are in the form of a list of varName=varValue. Well known pars can also be set.
=configBaseDir= defaults to ~configBaseDir_obtain()~
        #+end_org """)

        if not configBaseDir:
            configBaseDir = configBaseDir_obtain()

        cmndArgs = self.cmndArgsGet("0&-1", cmndArgsSpecDict, argsList)

        parNameFullPath = ""

        def createPathAndFpWrite(
                fpPath,
                valuePath,
        ):
            valuePath = os.path.abspath(valuePath)
            try:
                os.makedirs(valuePath)
            except OSError:
                if not os.path.isdir(valuePath):
                    raise

            b.fp.b.fp.FileParamWriteToPath(
                parNameFullPath=fpPath,
                parValue=valuePath,
            )
            parNameFullPath = fpPath

        # Any number of Name=Value can be passed as args
        for each in cmndArgs:
            varNameValue = each.split('=')
            parNameFullPath = os.path.join(
                    configUsgCursFpBaseDir_obtain(configBaseDir=configBaseDir),
                    varNameValue[0],
            )
            b.fp.b.fp.FileParamWriteToPath(
                parNameFullPath=parNameFullPath,

                parValue=varNameValue[1],
            )

        if bxoId:
             parNameFullPath = b.fp.b.fp.FileParamWriteToPath(
                parNameFullPath=os.path.join(
                    configUsgCursFpBaseDir_obtain(configBaseDir=configBaseDir),
                    "bxoId",
                ),
                parValue=bxoId,
            )

        if sr:
             parNameFullPath = b.fp.b.fp.FileParamWriteToPath(
                parNameFullPath=os.path.join(configUsgCursFpBaseDir_obtain(configBaseDir=configBaseDir),
                             "sr",
                ),
                parValue=sr,
            )

        if rtInv.outs:
            parValue = b.fp.FileParamValueReadFromPath(parNameFullPath)
            b_io.ann.here("usgCursParsSet: {parValue} at {parNameFullPath}".
                         format(parValue=parValue, parNameFullPath=parNameFullPath))

        return cmndOutcome.set(
            opError=b.OpError.Success,
            opResults=True,
        )

####+BEGIN: b:py3:cs:method/args :methodName "cmndArgsSpec" :methodType "anyOrNone" :retType "bool" :deco "default" :argsList "self"
    """ #+begin_org
**  _[[elisp:(blee:menu-sel:outline:popupMenu)][±]]_ _[[elisp:(blee:menu-sel:navigation:popupMenu)][Ξ]]_ [[elisp:(outline-show-branches+toggle)][|=]] [[elisp:(bx:orgm:indirectBufOther)][|>]] *[[elisp:(blee:ppmm:org-mode-toggle)][|N]]*  Mtd-T-anyOrNone [[elisp:(outline-show-subtree+toggle)][||]] /cmndArgsSpec/ deco=default  deco=default  [[elisp:(org-cycle)][| ]]
    #+end_org """
    @cs.track(fnLoc=True, fnEntry=True, fnExit=True)
    def cmndArgsSpec(self, ):
####+END:
        """
***** Cmnd Args Specification
"""
        cmndArgsSpecDict = cs.CmndArgsSpecDict()
        cmndArgsSpecDict.argsDictAdd(
            argPosition="0&-1",
            argName="cmndArgs",
            argDefault=None,
            argChoices='any',
            argDescription="A sequence of varName=varValue"
        )

        return cmndArgsSpecDict

####+BEGIN: b:prog:file/endOfFile :extraParams nil
""" #+begin_org
* *[[elisp:(org-cycle)][| END-OF-FILE |]]* :: emacs and org variables and control parameters
#+end_org """
### local variables:
### no-byte-compile: t
### end:
####+END:


import re
import requests
from bs4 import BeautifulSoup

URL = "https://sourcesup.renater.fr/scm/viewvc.php/rec/2019-CONVECS/REC/"
page = requests.get(URL)

soup = BeautifulSoup(page.content, "html.parser")
for link in soup.find_all('a', href=True):
    print(link['href'])
    if 'name' in link:
        print(link['name'])
    m = re.search(r"/(\w+)\.rec", link["href"])
    if m is not None:
        print(m.group(1))
        name = m.group(1)
        URL = f"https://sourcesup.renater.fr/scm/viewvc.php/rec/2019-CONVECS/REC/{name}.rec?revision=3&view=co"

        page = requests.get(URL)
        print(page.content)
        f = open(f"rec/{name}.rec", "wb")
        f.write(page.content)
        f.close()


from pyecharts import options as opts
from typing import Any,Optional
from pyecharts.charts import Radar
import os
import sys
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
from easy_pyechart import constants,baseParams,radar_base_config,round_radar_base_config

class eRadar():
    def __init__(
        self,
        lableList:Optional[list] = [],
        valueList:Optional[list] = [],
    ):
        self.opts: dict = {
                           "lengend":Radar,
                           "lableList":lableList,
                           "valueList":valueList,
                           }

    #基本雷达图
    def basic_radar_chart(self,baseParams):
        self.opts.update(baseParams.opts)
        return radar_base_config(self)

    #单选模式
    def radar_selected_mode(self,baseParams):
        self.opts.update(baseParams.opts)
        c=radar_base_config(self)
        c.set_global_opts(
                legend_opts=opts.LegendOpts(selected_mode="single"),
                title_opts=opts.TitleOpts(title=self.opts['title'],subtitle=self.opts['subTitle'],))
        return c

    #
    def radar_air_quality(self,baseParams):
        self.opts.update(baseParams.opts)
        return radar_base_config(self)

    #设置带有阴影区域的雷达图
    def radar_angle_radius_axis(self,baseParams):
        self.opts.update(baseParams.opts)
        return     round_radar_base_config(self)


'''
Created on 16/ago/2011

@author: Marco
'''
from reportlab.pdfgen import canvas
from reportlab.lib.units import cm
from math import sqrt
import ModelsCache
import Configuration

class PdfStructure(object):
    '''
    classdocs
    '''

    __markerList = []
    __modelsCache = ModelsCache.ModelsCache()

    @staticmethod
    def AddMarker(digitalMarker):
        PdfStructure.__markerList.append(digitalMarker)

    @staticmethod
    def RemoveMarker(tagName):
        for tag in PdfStructure.__markerList:
            if tag.name == tagName:
                PdfStructure.__markerList.remove(tag)

    @staticmethod
    def GeneratePDF(fileName):
        c = canvas.Canvas(fileName);
        for digitalMarker in PdfStructure.__markerList:
            inputFile = open(Configuration.TAG_DIR()+digitalMarker.name+".txt","r")
            tagDefinition = inputFile.read()

            lines = tagDefinition.split("\n")

            (x,y) = digitalMarker.GetCenter();
            tX = (float(x)/424)*21
            tY = (float(y)/600)*29.7

            for line in lines:
                ellipse = line.split(" ")
                if len(ellipse) == 10:
                    xCenter = -1*float(ellipse[3])
                    xCenter = (float(xCenter)/digitalMarker.defaultSize)*digitalMarker.size

                    yCenter = -1*float(ellipse[6])
                    yCenter = (float(yCenter)/digitalMarker.defaultSize)*digitalMarker.size

                    radius = ((0.5*sqrt((float(ellipse[3])*2)*(float(ellipse[3])*2)+(float(ellipse[6])*2)*(float(ellipse[6])*2)-4*float(ellipse[9])))/224)*digitalMarker.size
                    c.circle(xCenter/10*cm+tX*cm, yCenter/10*cm+tY*cm, radius/10*cm, fill=True)

        c.save()

    @staticmethod
    def SaveModel(modelName):
        out_file = open(Configuration.MODEL_DIR()+modelName+".model","a")
        if not modelName:
            raise Exception("ERROR: name is empty")
        if not PdfStructure.__markerList:
            raise Exception("ERROR: nothing to save as model")
        for model in PdfStructure.__modelsCache.models:
            if modelName == model.name:
                raise Exception("ERROR: duplicated name")

        model_names_file = open("ModelNames","a")
        model_names_file.write(modelName+"\n")
        model_names_file.close()

        runeNames = []
        runePositions = []
        runeSizes = []
        runeDefaultSizes = []

        for rune in PdfStructure.__markerList:
            runeNames.append(rune.name)
            runePositions.append((rune.x, rune.y))
            runeSizes.append(rune.size)
            runeDefaultSizes.append(rune.defaultSize)
            out_file.write(rune.name+" "+str(rune.x)+" "+str(rune.y)+" "+str(rune.size)+" "+str(rune.defaultSize)+"\n")
        out_file.close()

        PdfStructure.__modelsCache.AddModel(modelName, runeNames, runePositions, runeSizes, runeDefaultSizes)

    @staticmethod
    def GetModelNames():
        modelNames = []
        for model in PdfStructure.__modelsCache.models:
            modelNames.append(model.name)
        return modelNames

    @staticmethod
    def GetModel(modelName):
        return PdfStructure.__modelsCache.GetModel(modelName)

    @staticmethod
    def DeleteModel(name):
        model_names_file = open("ModelNames","r")
        modelNames = model_names_file.read()
        model_names_file.close()
        model_names_file = open("ModelNames","w")
        modelNames = modelNames.replace(name, "")
        model_names_file.write(modelNames)
        model_names_file.close()

        for model in PdfStructure.__modelsCache.models:
            if model.name == name:
                PdfStructure.__modelsCache.models.remove(model)


import flask
import grpc
import search_pb2_grpc as pb2_grpc
import search_pb2 as pb2
import redis
import json
from google.protobuf.json_format import MessageToJson
from flask import request, jsonify

app = flask.Flask(__name__)
app.config["DEBUG"] = True

class SearchClient(object):
    """
    Client for gRPC functionality
    """

    def __init__(self):
        self.host = 'localhost'
        self.server_port = 50051

        self.channel = grpc.insecure_channel(
            '{}:{}'.format(self.host, self.server_port))

        self.stub = pb2_grpc.SearchStub(self.channel)

    def get_results(self, message):
        """
        Client function to call the rpc for GetServerResponse
        """
        message = pb2.Message(message=message)
        print(f'{message}')
        return self.stub.GetServerResponse(message)

@app.route('/inventory/search', methods=['GET'])
def busqueda():
    if 'q' in request.args:
        busqueda= request.args['q']

        r= redis.Redis(host='localhost', port=6379, db=0)
        resultado = (r.get(busqueda))

        if(resultado!=None):
            products= json.loads(resultado)
            return jsonify(products)

        else:
            client = SearchClient()
            result = client.get_results(busqueda)
            print(result.product[0].name + "*******")
            serialized = MessageToJson(result)
            r.set(busqueda, serialized)
            return serialized
    else:
        return "Error, porfavor especifique la busqueda a realizar"

app.run()


import torch
import torch.nn as nn
from torch.utils.data   import Dataset, DataLoader
from djtransgan.dataset import batchlize

class DataLoaderSampler():
    def __init__(self, dataset, batch_size, drop_last=True, shuffle=True):
        self.count      = 0
        self.dataset    = dataset
        self.batch_size = batch_size
        self.drop_last  = drop_last
        self.shuffle    = shuffle

        self.current    = self.get_new_dataloader()
        self.length     = len(self.current)

    def get_new_dataloader(self):
        return iter(batchlize(self.dataset, self.batch_size, shuffle=self.shuffle))

    def __call__(self):
        self.count      += 1
        if self.count > self.length:
            self.current = self.get_new_dataloader()
            self.length  = len(self.current)
            self.count  += 1

        return next(self.current)


from .player import Player1
from .enemy import (
Enemy1, Enemy2, Boss1, Boss2
)
from .asteroids import Asteroid1
from .background import (
Backgr_lev1, Backgr_lev1a, Backgr_lev2, Backgr_lev2a, Backgr_lev3, Backgr_lev3a,
Backgr_lev4, Backgr_lev4a, Backgr_lev5,
Backgr_lev5a
)
from .startboard import StartBoard
from .explosion import (
ExplBig, ExplSmall)
from .shootall import (
ShootPlayer, ShootEnemy)
from .staticobjects import (
Arrow_left, Arrow_right, Shoot_label)
from .labels import  (
    Label1, Label2, Label3, Label4, Label5)

class UnitFactory():

    units_dict = {
        'startboard': StartBoard,
        'player1':Player1,
        'asteroid1':Asteroid1,
        'enemy1':Enemy1,
        'enemy2':Enemy2,
        'boss1':Boss1,
        'boss2':Boss2,
        'asteroids':Asteroid1,
        'explbig':ExplBig,
        'explsmall':ExplSmall,
        'shootplayer':ShootPlayer,
        'shootenemy':ShootEnemy,
        'backgrlev1':Backgr_lev1,
        'backgrlev1a':Backgr_lev1a,
        'backgrlev2':Backgr_lev2,
        'backgrlev2a':Backgr_lev2a,
        'backgrlev3':Backgr_lev3,
        'backgrlev3a':Backgr_lev3a,
        'backgrlev4':Backgr_lev4,
        'backgrlev4a':Backgr_lev4a,
        'backgrlev5':Backgr_lev5,
        'backgrlev5a':Backgr_lev5a,
        'arrowleft':Arrow_left,
        'arrowright':Arrow_right,
        'shootlabel':Shoot_label,
        'label1':Label1,
        'label2':Label2,
        'label3':Label3,
        'label4':Label4,
        'label5':Label5
        }

    @classmethod
    def create_unit(cls, unit_type, *a, **kwa):
        return cls.units_dict.get(unit_type)(*a, **kwa)

class Units():

    factory = UnitFactory

    def build_unit(self, unit_type, *a, **kwa):

        unit = self.__class__.factory.create_unit(unit_type, *a, **kwa)
        #self.update_records(unit_type)
        return unit

    #def update_records(self,unit_type):
       #pass

    def cr_sources(self):
        sources = [
        'startboard',
        'player1',
        'asteroid1',
        'enemy1',
        'enemy2',
        'boss1',
        'boss2',
        'asteroids',
        'explbig',
        'explsmall',
        'shootplayer',
        'shootenemy',
        'backgrlev1',
        'backgrlev1a',
        'backgrlev2',
        'backgrlev2a',
        'backgrlev3',
        'backgrlev3a',
        'backgrlev4',
        'backgrlev4a',
        'backgrlev5',
        'backgrlev5a',
        'arrowleft',
        'arrowright',
        'shootlabel',
        'label1',
        'label2',
        'label3',
        'label4',
        'label5'
        ]

        for n in sources:
            self.build_unit(n)


import re
from collections import Counter, defaultdict
from itertools import combinations
from typing import Dict, List, Tuple, Set

import numpy as np
from helper import load_input

def create_input():
    '''Extract puzzle input and transform'''

    # creates pattern for extracting replcements
    pattern = r"(\w+) => (\w+)"

    # splits puzzle input into replacements and molecule
    replacements, molecule = load_input(day=19).read().strip("\n").split("\n\n")

    # regex and init empty dict of lists
    matches = re.findall(pattern, replacements)
    replacements_dict = defaultdict(list)

    # converts the replacements into dictionary of lists
    for match in matches:
        replacements_dict[match[0]].append(match[1])

    return replacements_dict, molecule

def insert_replacements(start: str, end: str, replacements: List[str]) -> List[str]:
    '''
    Given start & end of molecule and a list of replacements,
    incrementally inserts replacements between start and end to create new molecules.
    Returns this as a list.
    '''
    return [
        start + replacement + end
        for replacement in replacements
    ]

def generate_molecules(replacements_dict: Dict[str, List[str]], molecule: str) -> Set[str]:
    '''
    Given the replacements and starting molecule,
    generates all the possible molecules after replacement,
    and returns as a set.
    '''

    # Prep storage for generated molecules
    generated_molecules = set()

    # loop through each element in starting molecule
    for i, element in enumerate(molecule):

        # extract replacements if a match
        replacement1 = replacements_dict.get(element, None)
        replacement2 = replacements_dict.get(molecule[i:i+2], None)

        # slice the correct end of molecule, dependent on length
        if replacement1:
            end = molecule[i+1:]
        elif replacement2:
            end = molecule[i+2:]
        else:
            continue

        # Updates the generated molecules set with new molecules after replacement
        generated_molecules.update(insert_replacements(
                start = molecule[:i],
                end = end,
                replacements = replacement1 or replacement2)
        )

    return generated_molecules

def part1():
    '''
    How many distinct molecules can be created
    after all the different ways you can do one replacement on the medicine molecule
    '''
    replacements_dict, molecule = create_input()
    return len(generate_molecules(replacements_dict, molecule))

def part2():
    ...

if __name__ == '__main__':
    print(part1())
    print(part2())


from elasticsearch import Elasticsearch, helpers
import csv
import json
import time

mvar = "clara"

matching_query = { "query_string": {
                    "query": mvar
                    }
                 }

def main():
    #sundesh
    es = Elasticsearch(host = "localhost", port = 9200)
    #anagnwsh arxeiou
    f = open('BX-Books.csv',"r",encoding="utf8")
    reader = csv.DictReader(f)
    #pairnw ws list o,ti paizei mesa se reader
    #lst = list(reader)
    #dhmiourgeia arxeiou ann auto den yparxei
    helpers.bulk(es, reader, index="bx_books_2")

if __name__ == "__main__":
    main()


import http

import requests
import telegram
from flask import Blueprint, Response, request
from sqlalchemy_utils import create_database, database_exists

from config import BUILD_NUMBER, DATABASE_URL, REBASE_URL, VERSION

from .bot import dispatcher
from .db import db, test_db
from .utils import log

routes = Blueprint('routes', __name__, url_prefix='/')

@routes.get('/health')
def health_check() -> Response:
  try:
    if not database_exists(DATABASE_URL):
      create_database(DATABASE_URL)
    db.create_all()
  except Exception as exc:
    log.exception('Health checking database... %s: %s', 'ERR', exc)

  return {
    'bot': 'up' if dispatcher is not None else 'down',
    'version': f'{VERSION}-{BUILD_NUMBER}',
    'db': 'up' if test_db() else 'down',
  }, http.HTTPStatus.OK

@routes.get('/rebase')
def reset() -> Response:
  if REBASE_URL is None:
    return { 'error': 'No rebase URL provided' }, http.HTTPStatus.INTERNAL_SERVER_ERROR

  return requests.get(
    f'https://api.telegram.org/bot{dispatcher.bot.token}/setWebhook?url={REBASE_URL}'
  ).content

@routes.post('/')
def index() -> Response:
  if dispatcher is None:
    return 'Bot is inactive', http.HTTPStatus.INTERNAL_SERVER_ERROR

  update = telegram.Update.de_json(request.get_json(force=True), dispatcher.bot)
  dispatcher.process_update(update)

  return '', http.HTTPStatus.NO_CONTENT


import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits import mplot3d

# plots intensity time series for MDRE model
def plotIntensity ():

	# index boundaries for time 3D plot
	nStart = 0
	nEnd   = 10000

	with open("time_series.txt", "r") as file:
		lines = file.readlines()

	time           = []
	intensity      = []
	rho_GS_e_act   = []
	rho_GS_h_act   = []
	rho_GS_e_inact = []
	rho_GS_h_inact = []
	rho_ES_e       = []
	rho_ES_h       = []
	E_real         = []
	E_imag         = []

	for line in lines:
		time.append(float((line.split('	')[0])))
		intensity.append(float((line.split('	')[1])))
		E_real.append(float((line.split('	')[2])))
		E_imag.append(float((line.split('	')[3])))
		rho_GS_e_act.append(float((line.split('	')[6])))
		rho_GS_h_act.append(float((line.split('	')[7])))
		rho_GS_e_inact.append(float((line.split('	')[8])))
		rho_GS_h_inact.append(float((line.split('	')[9])))
		rho_ES_e.append(float((line.split('	')[10])))
		rho_ES_h.append(float((line.split('	')[11])))

	time           = np.array(time)
	intensity      = np.array(intensity)
	E_real         = np.array(E_real)
	E_imag         = np.array(E_imag)
	rho_GS_e_act   = np.array(rho_GS_e_act)
	rho_GS_h_act   = np.array(rho_GS_h_act)
	rho_GS_e_inact = np.array(rho_GS_e_inact)
	rho_GS_h_inact = np.array(rho_GS_h_inact)
	rho_ES_e       = np.array(rho_ES_e)
	rho_ES_h       = np.array(rho_ES_h)

	# calculation of inversion
	inversion_GS_act   = rho_GS_e_act   + rho_GS_h_act   - 1.0
	inversion_GS_inact = rho_GS_e_inact + rho_GS_h_inact - 1.0
	inversion_ES       = rho_ES_e       + rho_ES_h       - 1.0

	fig, (ax1, ax2) = plt.subplots(1, 2) #sharey=True
	ax12 = ax1.twinx()
	fig.set_size_inches(5.9, 3.2)
	plt.rcParams.update({"font.size": 9})
	fig.subplots_adjust(wspace=0.7, top=0.99, bottom=0.22, left=0.08, right=0.99)

	fig.text(0.005, 0.93, "a)")
	ax1.plot(time[nStart:nEnd], intensity[nStart:nEnd], color="crimson")
	ax1.set_xlabel(r"time $t$ / ns", size=9.0)
	ax1.set_ylabel(r"intensity $|E|^2$", color="crimson", size=9.0)
	ax1.set_ylim(np.min(intensity) - 0.1, np.max(intensity) + 0.3)
	ax1.set_xticks([0.0, 5.0, 10.0])
	ax1.set_yticks([0.0, 1.0, 2.0, 3.0])
	ax1.tick_params(axis="x", labelsize=9.0)
	ax1.tick_params(axis="y", colors="crimson", labelsize=9.0)
	ax1.set_zorder(1)
	ax1.set_facecolor("none")

	ax12.plot(time[nStart:nEnd], inversion_GS_act[nStart:nEnd], color="orange", label="GS act")
	ax12.plot(time[nStart:nEnd], inversion_GS_inact[nStart:nEnd], color="gray", linestyle="--", label="GS inact")
	ax12.plot(time[nStart:nEnd], inversion_ES[nStart:nEnd], color="cornflowerblue", label="ES")
	ax12.set_ylabel(r"population inversion" + "\n" + r"$\rho_{m,e}^{(in)act} + \rho_{m,h}^{(in)act} - 1$", size=9.0)
	ax12.set_ylim(-1.075, 1.075)
	ax12.set_yticks([-1.0, 0.0, 1.0])
	ax12.tick_params(axis="y", labelsize=9.0)
	ax12.set_zorder(2)

	ax12.legend(bbox_to_anchor=(0.44, 0.33))

	# ~ fig, ax = plt.subplots()
	# ~ fig.set_size_inches(5.9, 4.8)
	# ~ fig.subplots_adjust(top=0.99, bottom=0.15, left=0.10, right=0.99)

	fig.text(0.575, 0.93, "b)")
	ax2.plot(inversion_GS_act, intensity, color="orange", label="GS act")
	ax2.plot(inversion_GS_inact, intensity, color="gray", linestyle="--", label="GS inact")
	ax2.plot(inversion_ES, intensity, color="cornflowerblue", label="ES")
	ax2.set_xlabel(r"population inversion" + "\n" + r"$\rho_{m,e}^{(in)act} + \rho_{m,h}^{(in)act} - 1$", size=9.0)
	ax2.set_ylabel(r"intensity $|E|^2$", color="crimson", size=9.0)
	ax2.set_xlim(-1.075, 1.075)
	ax2.set_ylim(-0.15, 3.15)
	ax2.set_xticks([-1.0, 0.0, 1.0])
	ax2.set_yticks([0.0, 1.0, 2.0, 3.0])
	ax2.tick_params(axis="x", labelsize=9.0)
	ax2.tick_params(axis="y", colors="crimson", labelsize=9.0)
	ax2.grid(color="lightgray")

	ax2.legend(loc="upper left")

	plt.show()

plotIntensity()


# Subgroup enumeration for cyclic, dicyclic, and tricyclic integer groups.
# PM Larsen, 2019
#
# The theory implemented here is described for two-dimensional groups in:
#     Representing and counting the subgroups of the group Z_m x Z_n
#     Mario Hampejs, Nicki Holighaus, László Tóth, and Christoph Wiesmeyr
#     Journal of Numbers, vol. 2014, Article ID 491428
#     http://dx.doi.org./10.1155/2014/491428
#     https://arxiv.org/abs/1211.1797
#
# and for three-dimensional groups in:
#     On the subgroups of finite Abelian groups of rank three
#     Mario Hampejs and László Tóth
#     Annales Univ. Sci. Budapest., Sect. Comp. 39 (2013), 111–124
#     https://arxiv.org/abs/1304.2961

import itertools
import numpy as np
from math import gcd

def get_divisors(n):
    return [i for i in range(1, n + 1) if n % i == 0]

def get_subgroup_elements(orders, H):

    size = 1
    for e, x in zip(np.diag(H), orders):
        if e != 0:
            size *= x // e

    dimension = len(orders)
    indices = np.zeros((size, dimension), dtype=int)
    indices[:, 0] = H[0, 0] * np.arange(size)

    for i, order in enumerate(orders):
        if i > 0 and H[i, i] != 0:
            k = np.prod(orders[:i]) // np.prod(np.diag(H)[:i])
            p = np.arange(size) // k
            for j in range(i + 1):
                indices[:, j] += H[i, j] * p

    return indices % orders

def consistent_first_rows(dimension, dm, ffilter):
    for a in dm:
        H = np.zeros((dimension, dimension), dtype=int)
        H[0, 0] = a
        if ffilter is None or ffilter(H):
            yield a

def solve_linear_congruence(r, a, b, c, s, v):
    for u in range(a + 1):
        if (r // c * u) % a == (r * v * s // (b * c)) % a:
            return u
    raise Exception("u not found")

def enumerate_subgroup_bases(orders, ffilter=None,
                             min_index=1, max_index=float("inf")):
    """Get the subgroup bases of a cyclic/dicyclic/tricyclic integer group.

    Parameters:

    orders: list-like integer object
        Orders of the constituent groups.
        [m] if the group is a cyclic group Zm
        [m, n] if the group is a dicyclic group Zm x Zn
        [m, n, r] if the group is a tricyclic group Zm x Zn x Zr

    ffilter: function, optional
        A boolean filter function. Avoids generation of unwanted subgroups by
        rejecting partial bases.

    Returns iterator object yielding:

    H: integer ndarray
        Subgroup basis.
    """
    dimension = len(orders)
    assert dimension in [1, 2, 3]
    if dimension == 1:
        m = orders[0]
    elif dimension == 2:
        m, n = orders
    else:
        m, n, r = orders
    dm = get_divisors(m)

    if dimension == 1:
        for d in consistent_first_rows(dimension, dm, ffilter):
            group_index = m // d
            if group_index >= min_index and group_index <= max_index:
                yield np.array([[d]])

    elif dimension == 2:
        dn = get_divisors(n)

        for a in consistent_first_rows(dimension, dm, ffilter):
            for b in dn:
                group_index = m * n // (a * b)
                if group_index < min_index or group_index > max_index:
                    continue

                for t in range(gcd(a, n // b)):
                    s = t * a // gcd(a, n // b)

                    H = np.array([[a, 0], [s, b]])
                    if ffilter is None or ffilter(H):
                        yield H

    elif dimension == 3:
        dn = get_divisors(n)
        dr = get_divisors(r)

        for a in consistent_first_rows(dimension, dm, ffilter):
            for b, c in itertools.product(dn, dr):
                group_index = m * n * r // (a * b * c)
                if group_index < min_index or group_index > max_index:
                    continue

                A = gcd(a, n // b)
                B = gcd(b, r // c)
                C = gcd(a, r // c)
                ABC = A * B * C
                X = ABC // gcd(a * r // c, ABC)

                for t in range(A):
                    s = a * t // A

                    H = np.zeros((dimension, dimension), dtype=int)
                    H[0] = [a, 0, 0]
                    H[1] = [s, b, 0]
                    H[2, 2] = r
                    if ffilter is not None and not ffilter(H):
                        continue

                    for w in range(B * gcd(t, X) // X):
                        v = b * X * w // (B * gcd(t, X))
                        u0 = solve_linear_congruence(r, a, b, c, s, v)

                        for z in range(C):
                            u = u0 + a * z // C
                            H = np.array([[a, 0, 0], [s, b, 0], [u, v, c]])
                            if ffilter is None or ffilter(H):
                                yield H

def count_subgroups(orders):
    """Count the number of subgroups of a cyclic/dicyclic/tricyclic integer
    group.

    Parameters:

    orders: list-like integer object
        Orders of the constituent groups.
        [m] if the group is a cyclic group Zm
        [m, n] if the group is a dicyclic group Zm x Zn
        [m, n, r] if the group is a tricyclic group Zm x Zn x Zr

    Returns:

    n: integer
        Subgroup basis.
    """
    def P(n):
        return sum([gcd(k, n) for k in range(1, n + 1)])

    dimension = len(orders)
    assert dimension in [1, 2, 3]
    if dimension == 1:
        m = orders[0]
    elif dimension == 2:
        m, n = orders
    else:
        m, n, r = orders
    dm = get_divisors(m)

    if dimension == 1:
        return len(dm)
    elif dimension == 2:
        dn = get_divisors(n)
        return sum([gcd(a, b) for a in dm for b in dn])
    else:
        dn = get_divisors(n)
        dr = get_divisors(r)

        total = 0
        for a, b, c in itertools.product(dm, dn, dr):
            A = gcd(a, n // b)
            B = gcd(b, r // c)
            C = gcd(a, r // c)
            ABC = A * B * C
            X = ABC // gcd(a * r // c, ABC)
            total += ABC // X**2 * P(X)
        return total


#!/usr/bin/python3
import sys, getopt, os
import pandas as pd
import numpy as np

from analytical_settings import HAP1_control_1, HAP1_control_2, HAP1_control_3, HAP1_control_4
from analytical_settings import grouping
from analytical_settings import cauchy_compatibility

from global_functions import read_csv, write_csv
from create_phenosaurus_reference import build_phenosaurus_reference

##################################
# Function 'normalize_to_median'
##################################
# Arguments: reference <pandas DataFrame with accumulated counts sense and antisense>
#            sample    <pandas DataFrame with sense and antisense counts for
#                       sample that requires normalization>
# Returns:   ns        <pandas DataFrame with identical structure to sample but with normalized counts>
##################################
def normalize_to_median(raw, reference):
    # Calculate sense/total ratio for reference dataset and store in 'ref_ratio' column in DataFrame
    reference = reference.assign(ref_ratio=(reference['sense_reference'] + 1)
                                           / (reference['sense_reference'] + reference['antisense_reference'] + 2))
    normalized_data = pd.DataFrame(columns=['gene'])
    if cauchy_compatibility:
        print("original Cauchy.R algorithm...", end='')
    else:
        print("latest algorithm...", end='')
    subset = ['gene', 'sense', 'antisense']
    s = pd.merge(reference, raw, on='gene', how='outer')

    # Split sample(s) into part of sample that can be normalized (sn) and the part the cannot be normalized (scn)
    sn = s[((s['sense'] + s['antisense']) > 0) & (
    (s.sense_reference + s.antisense_reference) > 0)]  # meaning counts in reference and sample
    scn = s[((s['sense'] + s['antisense']) > 0) & (
    (s.sense_reference + s.antisense_reference) == 0)]  # meaning counts in sample but not in reference

    # Calculate sense-ratio for current sample and sort DataFrame based on sense-ratio of reference set
    sn = sn.assign(ratio=(s[subset[1]] + 1) / (s[subset[1]] + s[subset[2]] + 2))
    sn = sn.sort_values(by='ref_ratio')

    # Create empty dataframe for the normalized sample (ns)
    ns = pd.DataFrame(columns=subset)

    if not cauchy_compatibility:

        # Calculate optimal grouping value based on requested grouping (to create equal groups and hence identical normalization for every gene)
        divider = np.round(sn.shape[0] / grouping)
        groupsize = (sn.shape[0] / divider)

        # Group sorted DataFrame in equally sized groups and loop over these groups
        for g, df in sn.groupby(np.arange(len(sn)) // groupsize):
            ref_median = df['ref_ratio'].median()
            sample_median = df['ratio'].median()
            df = df.assign(norm_sense=np.where(df['ratio'] <= sample_median
                                               , np.where(
                    np.round((df['ratio'] / (sample_median) * ref_median * (df[subset[1]] + df[subset[2]]))) > (
                    df[subset[1]] + df[subset[2]])  # ie. the normalized sense count is higer than the total counts
                    , (df[subset[1]] + df[subset[2]])
                    , np.round((df['ratio'] / (sample_median) * ref_median * (df[subset[1]] + df[subset[2]]))))
                                               , np.where(np.round(((1 - (1 - df['ratio']) / (1 - sample_median) * (
                1 - ref_median)) * (df[subset[1]] + df[subset[2]]))) > (df[subset[1]] + df[subset[2]])
                                                          , (df[subset[1]] + df[subset[2]])
                                                          , np.round(((1 - (1 - df['ratio']) / (1 - sample_median) * (
                    1 - ref_median)) * (df[subset[1]] + df[subset[2]]))))))

            df = df.assign(norm_antisense=(df[subset[1]] + df[subset[2]] - df['norm_sense']))
            df[['norm_sense', 'norm_antisense']] = df[['norm_sense', 'norm_antisense']].astype(np.int32)
            df = df[['gene', 'norm_sense', 'norm_antisense']]
            df.columns = subset
            ns = ns.append(df)  # Append to DataFrame with normalized counts of previous group

    else:
        # If cauchy_compatibility==True, grouping of genes will be performed according to the previous version of
        # the pipeline as in 'cauchy.R'

        # Calculate the number of groups
        divider = int(np.ceil(sn.shape[0] / grouping))  # The total number of groups
        genes = sn.shape[0]

        i = 1  # Current index of input dataframe
        for g in range(0, divider):  # Loop over the groups of genes
            df = pd.DataFrame()  # Create temporary dataframe for current group
            for gi in range(0, grouping):  # Append the genes to the current group
                i = gi + g * grouping  # DataFrame Index
                if i <= genes:  # For the last group
                    df = df.append(sn[i:i + 1])
            ref_median = df['ref_ratio'].median()
            sample_median = df['ratio'].median()
            df = df.assign(norm_sense=np.where(df['ratio'] <= sample_median
                                               , np.where(
                    np.round((df['ratio'] / (sample_median) * ref_median * (df[subset[1]] + df[subset[2]]))) > (
                    df[subset[1]] + df[subset[2]])  # ie. the normalized sense count is higer than the total counts
                    , (df[subset[1]] + df[subset[2]])
                    , np.round((df['ratio'] / (sample_median) * ref_median * (df[subset[1]] + df[subset[2]]))))
                                               , np.where(np.round(((1 - (1 - df['ratio']) / (1 - sample_median) * (
                1 - ref_median)) * (df[subset[1]] + df[subset[2]]))) > (df[subset[1]] + df[subset[2]])
                                                          , (df[subset[1]] + df[subset[2]])
                                                          , np.round(((1 - (1 - df['ratio']) / (1 - sample_median) * (
                    1 - ref_median)) * (df[subset[1]] + df[subset[2]]))))))

            df = df.assign(norm_antisense=(df[subset[1]] + df[subset[2]] - df['norm_sense']))
            df = df[['gene', 'norm_sense', 'norm_antisense']]
            df.columns = subset
            ns = ns.append(df)  # Append to DataFrame with normalized counts of previous group

    # Merge the normalized sample with the datapoint of the sample that could not be normalized because of absense
    # of these genes in the reference
    ns = ns.append(scn[subset])
    normalized_data = pd.merge(ns, normalized_data, on='gene', how='outer')
    normalized_data[['sense', 'antisense']] = normalized_data[['sense', 'antisense']].astype(np.int32)

    return normalized_data

def process_controls(controls):
    controls = controls.copy()
    reference_cols = ['gene', 'sense_reference', 'antisense_reference']
    reference = pd.DataFrame(columns=reference_cols)
    for c, f in controls.items():  # c is control, f = file
        controls[c] = pd.read_csv(f, sep='\t')[['gene', 'sense',
                                                'antisense']]  # Read the file and overwrite the value of the name of the with the actual data
        reference = pd.merge(controls[c], reference, on='gene', how='outer').fillna(0)
        reference = reference.assign(
            sense_reference=(reference[['sense', 'sense_reference']].sum(axis=1)).astype(np.int32))
        reference = reference.assign(
            antisense_reference=(reference[['antisense', 'antisense_reference']].sum(axis=1)).astype(np.int32))
        reference.drop(['sense', 'antisense'], axis=1, inplace=True)
    return controls, reference

def main(argv):
    syntax = 'normalize.py -n <controls or directory of replicate> -o <directory where normalized control will be saved>'
    try:
        opts, args = getopt.getopt(argv, "hnosr:", ["normalize=", "outdir=", "screenname=", "refname="])
    except getopt.GetoptError:
        print(syntax)
        sys.exit(2)
    for opt, arg in opts:
        if opt == '-h':
            print(syntax)
            sys.exit()
        elif opt in ("-n", "--normalize"):
            data = arg
        elif opt in ("-o", "--outdir"):
            outdir = arg
        elif opt in ("-s", "--screenname"):
            screenname = arg
        elif opt in ("-r", "--refname"):
            refname = arg
        else:
            assert False, "unhandled option"

    # Create dictionary to store the names of the controls (keys) and their associated records (values)
    control_files = {'HAP1_control_1': HAP1_control_1, 'HAP1_control_2': HAP1_control_2, 'HAP1_control_3': HAP1_control_3,
                'HAP1_control_4': HAP1_control_4}
    # Read in controls and calculate aggregate reference counts
    controls, reference = process_controls(control_files)

    if data == 'controls':
        for c, d in controls.items():  # c = control, d = data
            print("Normalizing control using ", end='')
            norm = normalize_to_median(d, reference).sort_values(by='gene')
            write_csv(''.join([screenname, "_replicate_", str(int(c[-1:])), "_sense_vs_antisense_counts_normalized.csv"]), os.path.join(outdir, ''), norm) # Create file for normalization of samples
            print(control_files[c])
            build_phenosaurus_reference(norm, read_csv(control_files[c]), screenname, refname, outdir, int(c[-1:]))
            print("done")
    else:
        data = os.path.join(data, '')
        raw = read_csv(''.join([data, 'sense_vs_antisense_counts.csv']))[['gene', 'sense', 'antisense']]
        print("Normalizing sample using ", end='')
        norm = normalize_to_median(raw, reference).sort_values(by='gene')
        write_csv('sense_vs_antisense_counts_normalized.csv', data, norm)
        print("done")

if __name__ == "__main__":
    main(sys.argv[1:])


import shutil
import tempfile

from django.conf import settings
from django.contrib.auth import get_user_model
from django.core.files.uploadedfile import SimpleUploadedFile
from django.test import Client, TestCase, override_settings
from django.urls import reverse

from ..forms import PostForm
from ..models import Post

User = get_user_model()
TEMP_MEDIA_ROOT = tempfile.mkdtemp(dir=settings.BASE_DIR)
small_gif = (
    b'\x47\x49\x46\x38\x39\x61\x02\x00'
    b'\x01\x00\x80\x00\x00\x00\x00\x00'
    b'\xFF\xFF\xFF\x21\xF9\x04\x00\x00'
    b'\x00\x00\x00\x2C\x00\x00\x00\x00'
    b'\x02\x00\x01\x00\x00\x02\x02\x0C'
    b'\x0A\x00\x3B'
)

@override_settings(MEDIA_ROOT=TEMP_MEDIA_ROOT)
class PostFormTests(TestCase):
    @classmethod
    def setUpTestData(cls):
        cls.user = User.objects.create_user(username='username')
        cls.uploaded = SimpleUploadedFile(
            name='small.gif',
            content=small_gif,
            content_type='image/gif'
        )
        cls.form = PostForm()

    @classmethod
    def tearDownClass(cls):
        super().tearDownClass()
        shutil.rmtree(TEMP_MEDIA_ROOT, ignore_errors=True)

    def setUp(self):
        self.authorized_client = Client()
        self.authorized_client.force_login(self.user)

    def test_create_post(self):
        """Валидная форма создает запись в Post."""
        # Подсчитаем количество записей в Post
        posts_count = Post.objects.count()
        form_data = {
            'text': 'Тестовый пост',
            'image': PostFormTests.uploaded,
        }
        self.uploaded.seek(0)
        # Отправляем POST-запрос
        response = self.authorized_client.post(
            reverse('posts:post_create'),
            data=form_data,
            follow=True
        )
        # Проверяем, сработал ли редирект
        self.assertRedirects(response, reverse(
            'posts:profile',
            kwargs={'username': 'username'})
        )
        # Проверяем, увеличилось ли число постов
        self.assertEqual(Post.objects.count(), posts_count + 1)
        # Проверяем, что создалась запись с заданным id
        self.assertTrue(
            Post.objects.filter(
                text='Тестовый пост',
                pk=1,
                image='posts/small.gif',
            ).exists()
        )

    def test_edit_post(self):
        Post.objects.create(
            text='Тестовый пост',
            author=self.user,
            pk=1,
            image=self.uploaded,
        )
        form_data = {
            'text': 'Тестовый пост изменился',
        }
        # Отправляем POST-запрос
        response = self.authorized_client.post(
            reverse('posts:post_edit', kwargs={'post_id': 1}),
            data=form_data,
            follow=True
        )
        post_changed = Post.objects.get(pk=1)
        # Проверяем, сработал ли редирект c тем же id
        self.assertRedirects(response, reverse(
            'posts:post_detail',
            kwargs={'post_id': 1})
        )
        self.assertEqual(post_changed.text, 'Тестовый пост изменился')

class CommentFormTests(TestCase):
    @classmethod
    def setUpTestData(cls):
        cls.user = User.objects.create_user(username='username')
        cls.guest_client = Client()
        cls.authorized_client = Client()
        cls.authorized_client.force_login(cls.user)

        Post.objects.create(
            text='Тестовый пост',
            author=cls.user,
            pk=1,
        )

    def test_add_comment(self):
        """Комментировать посты может только авторизованный пользователь."""
        form_data = {
            'text': 'Тестовый комментарий',
        }
        response1 = self.authorized_client.post(
            reverse('posts:add_comment', kwargs={'post_id': 1}),
            data=form_data,
            follow=True
        )
        response2 = self.guest_client.post(
            reverse('posts:add_comment', kwargs={'post_id': 1}),
            data=form_data,
            follow=True
        )
        # Проверяем, сработал ли редирект
        self.assertRedirects(response1, reverse(
            'posts:post_detail',
            kwargs={'post_id': 1})
        )
        self.assertRedirects(response2,
                             '/auth/login/?next=/posts/1/comment/'
                             )