import pandas as pd
import os
import sys
import warnings
import clang.cindex
import copy
import random #debug
import pickle #debug
import chardet
warnings.filterwarnings('ignore')

#clang.cindex.Config.set_library_file("/usr/lib/llvm-6.0/lib/libclang.so")
clang.cindex.Config.set_library_file("/home/k1462425/llvm/llvm-project/build/lib/libclang.so")
transIndex = 0
globalNodes = []
missingTokens = []
indexO = 0
corpus = 0

class Pipeline:

    def __init__(self,  ratio, root, language):
        self.ratio = ratio
        self.root = root
        self.language = language
        self.sources = None
        self.blocks = None
        self.pairs = None
        self.train_file_path = None
        self.dev_file_path = None
        self.test_file_path = None
        self.size = None

    # parse source code
    def parse_source(self, output_file, option):

        # Function to convert a char list to a string
        def listToString(s):
            str1 = ""
            for ele in s:
                str1 += ele
            return str1

        def findChildren(node,entry):
            nodeSplit = node.split(",")
            children = []
            node_identifier = nodeSplit[0]
            entry_split = entry.split("¬")
            for entry_x in entry_split:
                node_split = entry_x.split(",")
                if node_split[-1] == node_identifier:
                    children.append(entry_x)
            return children

        def find_parent(node, all_nodes_string):
            all_nodes_split = all_nodes_string.split('¬')
            node_split = node.split(',')
            parent_identifier = node_split[-1]
            parent = ""
            for nod in all_nodes_split:
                nod_split = nod.split(',')
                if nod_split[0] == parent_identifier:
                    parent = nod
            return parent

        def engineer_var_decls(all_nodes_string):
            all_nodes_split = all_nodes_string.split('¬')
            ALPHABET = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
            for node in all_nodes_split:
                node_split = node.split(',')
                if len(node_split) > 1:
                    if node_split[2] == 'VAR_DECL':
                        parent = find_parent(node,all_nodes_string)
                        parent_split = parent.split(',')
                        depth = int(parent_split[1]) + 1
                        child_chars = []
                        for i in range(16):
                            child_chars.append(random.choice(ALPHABET))
                        all_nodes_string = all_nodes_string + listToString(child_chars) + "," + str(depth) + "," + "VAR_TYPE" + "," + str(parent_split[3]) + "," + str(node_split[0]) + "¬"
            for node in all_nodes_split:
                node_split = node.split(',')
                if len(node_split) > 1:
                    if node_split[2] == 'VAR_DECL':
                        parent = find_parent(node,all_nodes_string)
                        parent_split = parent.split(',')
                        if parent_split[2] == 'DECL_STMT':
                            var_decl_children = find_var_decl_children(parent,all_nodes_string)
                            for var_decl_child in var_decl_children:
                                all_nodes_string = create_decl_stmt_parent(var_decl_child,all_nodes_string)
            for node in all_nodes_split:
                nodesplit = node.split(',')
                children = findChildren(node,all_nodes_string)
                if len(children) == 0 and nodesplit[2] == 'DECL_STMT':
                    all_nodes_string = all_nodes_string.replace(node,'')
            return all_nodes_string

        def find_var_decl_children(node, all_nodes_string):
            var_decl_children = []
            children = findChildren(node,all_nodes_string)
            for child in children:
                childsplit = child.split(',')
                if childsplit[2] == 'VAR_DECL':
                    var_decl_children.append(child)

            return var_decl_children

        def create_decl_stmt_parent(node,all_nodes_string):
            parent_of_obsolete_parent = find_parent(find_parent(node,all_nodes_string),all_nodes_string)
            identifier_of_parent_of_obsolete_parent = parent_of_obsolete_parent.split(',')[0]
            ALPHABET = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
            child_chars = []
            for i in range(16):
                child_chars.append(random.choice(ALPHABET))
            depth = 1
            new_decl_statement = listToString(child_chars)+","+str(depth)+","+"DECL_STMT"+","+","+identifier_of_parent_of_obsolete_parent+"¬"
            all_nodes_string = all_nodes_string+new_decl_statement
            nodesplit = node.split(',')
            nodesplit[-1] = listToString(child_chars)

            y = 0
            while y < len(nodesplit):
                if y != len(nodesplit) - 1:
                    nodesplit[y] = nodesplit[y] + ","
                y = y + 1
            this_node_with_updated_parent = listToString(nodesplit)

            all_nodes_string = all_nodes_string.replace(node,this_node_with_updated_parent)
            return all_nodes_string

        def engineer_unary_operators(all_nodes_string):
            all_nodes_split = all_nodes_string.split('¬')
            unary_operators = ['+','-','&','!','~','*','++','--']
            for node in all_nodes_split:
                node_split = node.split(',')
                old_node = node
                if len(node_split) > 1:
                    #print("Length bigger than 1")
                    if node_split[2] == 'UNARY_OPERATOR':
                        print("Unary operator found")
                        print(node_split[3])
                        print(node_split[4])
                        if node_split[4] in unary_operators:

                            node_split[3] = node_split[4]
                            y = 0
                            while y < len(node_split):
                                if y != len(node_split) - 1:
                                    node_split[y] = node_split[y] + ","
                                y = y + 1
                            subs_node = listToString(node_split)
                            print("Replacing " +old_node)
                            print("With "+subs_node)
                            all_nodes_string = all_nodes_string.replace(old_node,subs_node)

            return all_nodes_string

        def engineer_expr_list(all_nodes_string):
            all_nodes_split = all_nodes_string.split('¬')
            parents_done = []
            callexprs_exprlist_dict = {}
            ALPHABET = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
            for node in all_nodes_split:
                node_split = node.split(',')
                if len(node_split) > 1:
                    if node_split[2] == 'UNEXPOSED_EXPR' or node_split[2] == 'UNARY_OPERATOR':
                        parent = find_parent(node, all_nodes_string)
                        if len(parent) > 1:
                            parent_split = parent.split(',')
                            depth = int(parent_split[1]) + 1
                            if parent_split[2] == 'CALL_EXPR':
                                #print("Node: "+node)
                                #print("Parent: "+parent)
                                child_chars = []
                                if parent not in parents_done:
                                    for i in range(16):
                                        child_chars.append(random.choice(ALPHABET))
                                    new_node = listToString(child_chars) + "," + str(depth) + "," + "EXPR_LIST" + ",," + str(parent_split[0]) + "¬"
                                    old_node = node
                                    subs_node = node_split
                                    subs_node[-1] = listToString(child_chars)
                                    y = 0
                                    while y < len(subs_node):
                                        if y != len(subs_node) - 1:
                                            subs_node[y] = subs_node[y] + ","
                                        y = y + 1
                                    subs_node = listToString(subs_node)
                                    all_nodes_string = all_nodes_string.replace(old_node,subs_node)

                                    all_nodes_string = all_nodes_string + new_node
                                    parents_done.append(parent)
                                    callexprs_exprlist_dict[parent] = new_node
                                else:
                                    old_node = node
                                    new_node = callexprs_exprlist_dict.get(parent)
                                    new_node_split = new_node.split(',')
                                    subs_node = node_split
                                    subs_node[-1] = new_node_split[0]
                                    y = 0
                                    while y < len(subs_node):
                                        if y != len(subs_node) - 1:
                                            subs_node[y] = subs_node[y] + ","
                                        y = y + 1
                                    subs_node = listToString(subs_node)

                                    all_nodes_string = all_nodes_string.replace(old_node,subs_node)
            return all_nodes_string

        def remove_useless_unexposed(all_nodes_string):
            all_nodes_split = all_nodes_string.split('¬')
            for node in all_nodes_split:
                if 'UNEXPOSED_EXPR'  in node:
                    parent = find_parent(node, all_nodes_string)
                    if 'UNEXPOSED_EXPR' in parent:
                        all_nodes_string = all_nodes_string.replace(node, '')

                if 'DECL_REF_EXPR'  in node:
                    parent = find_parent(node, all_nodes_string)
                    if 'UNEXPOSED_EXPR' in parent:
                        nodesplit = node.split(',')
                        parentsplit = parent.split(',')
                        if nodesplit[3] == parentsplit[3]:
                            all_nodes_string = all_nodes_string.replace(node, '')
            return all_nodes_string

        def remove_top_level_compound(all_nodes_string):
            all_nodes_split = all_nodes_string.split('¬')
            for node in all_nodes_split:
                nodesplit = node.split(',')
                if len(nodesplit) > 1:
                    if nodesplit[2] == 'COMPOUND_STMT':
                        parent = find_parent(node,all_nodes_string)
                        parentsplit = parent.split(',')
                        if len(parentsplit) > 1:
                            if parentsplit[2] == 'FUNCTION_DECL':
                                children = findChildren(node,all_nodes_string)
                                for child in children:
                                    oldchild = child
                                    childsplit = child.split(',')
                                    childsplit[-1] = parentsplit[0]
                                    y = 0
                                    while y < len(childsplit):
                                        if y != len(childsplit) - 1:
                                            childsplit[y] = childsplit[y] + ","
                                        y = y + 1
                                    all_nodes_string = all_nodes_string.replace(oldchild,listToString(childsplit))
                                all_nodes_string = all_nodes_string.replace(node,'')
            return all_nodes_string

        def engineer_field_decls(all_nodes_string):
            all_nodes_split = all_nodes_string.split('¬')
            ALPHABET = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
            for node in all_nodes_split:
                nodesplit = node.split(',')
                if len(nodesplit) > 1:
                    if nodesplit[2] == 'FIELD_DECL':
                        new_child = ""
                        child_chars = []
                        for i in range(16):
                            child_chars.append(random.choice(ALPHABET))
                        node_name = 'VAR_TYPE'
                        token = nodesplit[3]
                        parent_identifier = nodesplit[0]
                        depth = int(nodesplit[1]) + 1
                        all_nodes_string = all_nodes_string + listToString(child_chars) + "," + str(depth) + "," + node_name + "," + token + "," + parent_identifier + "¬"

            return all_nodes_string

        def recursive_produce_nodes_string(cursor,nodes_string,depth,parent_identifier):
            if cursor.spelling != '':
                addition_string = str(depth)+","+cursor.kind.name+","+cursor.spelling+","
            else:
                addition_string = str(depth)+","+cursor.kind.name+","
            tokens = []
            for token in cursor.get_tokens():
                tokens.append(token)

            if cursor.kind.name == 'BINARY_OPERATOR':
                if len(tokens) > 1:
                    addition_string = addition_string + tokens[1].spelling + ","

            elif cursor.kind.name == 'UNARY_OPERATOR':
                unary_operators = ['+','-','&','!','~','*','++','--']
                if len(tokens) > 1:
                    if tokens[0].spelling in unary_operators:
                        #print(tokens[0].spelling)
                        addition_string = addition_string + tokens[0].spelling + ","
                    elif tokens[1].spelling in unary_operators:
                        #print(tokens[1].spelling)
                        addition_string = addition_string + tokens[1].spelling + ","

            elif len(tokens) > 0:
                addition_string = addition_string + tokens[0].spelling + ","

            ALPHABET = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
            chars=[]
            for i in range(16):
                chars.append(random.choice(ALPHABET))

            salt = "".join(chars)

            addition_string = salt+","+addition_string+","+parent_identifier+"¬"
            child_string = ""

            addition_split = addition_string.split(',')

            if cursor.kind.name == 'CALL_EXPR':
                child_chars=[]
                for i in range(16):
                    child_chars.append(random.choice(ALPHABET))
                child_string = listToString(child_chars) + "," + str(depth+1) + "," + "CALL_NAME" + "," + addition_split[3] + "," + addition_split[0] + "¬"

            child_string2 = ""
            if cursor.kind.name == 'INTEGER_LITERAL':
                child_chars = []
                for i in range(16):
                    child_chars.append(random.choice(ALPHABET))

                child_string2 = listToString(child_chars) + "," + str(depth+1) + "," + "INTEGER_VALUE" + "," + addition_split[3] + "," + addition_split[0] + "¬"

            child_string3 = ""
            child_string4 = ""
            if cursor.kind.name == 'FUNCTION_DECL':
                child_chars = []
                for i in range(16):
                    child_chars.append(random.choice(ALPHABET))
                child_string3 = listToString(child_chars) + "," + str(depth+1) + "," + "FUNCTION_NAME" + "," + addition_split[3] + "," + addition_split[0] + "¬"
                parent_chars = child_chars
                child_chars = []
                for i in range(16):
                    child_chars.append(random.choice(ALPHABET))
                child_string4 = listToString(child_chars) + "," + str(depth+2) + "," + "FUNCTION_TYPE" + "," + addition_split[4] + "," + str(parent_chars) + "¬"

            nodes_string = nodes_string + addition_string + child_string + child_string2 + child_string3
            children = cursor.get_children()
            for child in children:
                nodes_string = recursive_produce_nodes_string(child,nodes_string,depth+1,salt)
            return nodes_string

        path = self.root+self.language+'/'+output_file
        if os.path.exists(path) and option == 'existing':
            source = pd.read_pickle(path)
        else:
            if self.language is 'c':
                source = pd.read_pickle(self.root+self.language+'/programs.pkl')
                source.columns = ['id', 'code', 'label']

                x = 0
                while x < len(source['code']):
                    #if x == 8200:
                    filename = "program.c"
                    with open(filename,'w+') as fp:
                        fp.write(source['code'][x])
                        fp.close()

                    index = clang.cindex.Index.create()
                    tu = index.parse(filename)
                    all_nodes_string = recursive_produce_nodes_string(tu.cursor,"",0,"NONE")
                    all_nodes_string = engineer_var_decls(all_nodes_string)
                    all_nodes_string = remove_useless_unexposed(all_nodes_string)
                    all_nodes_string = engineer_expr_list(all_nodes_string)
                    #all_nodes_string = engineer_unary_operators(all_nodes_string)
                    all_nodes_string = remove_top_level_compound(all_nodes_string)
                    all_nodes_string = engineer_field_decls(all_nodes_string)
                    source['code'][x] = all_nodes_string
                    if(x % 100 == 0):
                        print(x)
                    x = x + 1
                #sys.exit(0)

                #       x = x + 1

                source.to_pickle(path)
        self.sources = source

        return source

    # create clone pairs
    def read_pairs(self, filename):
        pairs = pd.read_pickle(self.root+self.language+'/'+filename)
        self.pairs = pairs

    # split data for training, developing and testing
    def split_data(self):
        data_path = self.root+self.language+'/'
        data = self.pairs
        data_num = len(data)
        ratios = [int(r) for r in self.ratio.split(':')]
        train_split = int(ratios[0]/sum(ratios)*data_num)
        val_split = train_split + int(ratios[1]/sum(ratios)*data_num)

        data = data.sample(frac=1, random_state=666)
        train = data.iloc[:train_split]
        dev = data.iloc[train_split:val_split]
        test = data.iloc[val_split:]

        def check_or_create(path):
            if not os.path.exists(path):
                os.mkdir(path)
        train_path = data_path+'train/'
        check_or_create(train_path)
        self.train_file_path = train_path+'train_.pkl'
        train.to_pickle(self.train_file_path)

        dev_path = data_path+'dev/'
        check_or_create(dev_path)
        self.dev_file_path = dev_path+'dev_.pkl'
        dev.to_pickle(self.dev_file_path)

        test_path = data_path+'test/'
        check_or_create(test_path)
        self.test_file_path = test_path+'test_.pkl'
        test.to_pickle(self.test_file_path)

    # construct dictionary and train word embedding
    def dictionary_and_embedding(self, input_file, size):
        global corpus
        self.size = size
        data_path = self.root+self.language+'/'
        if not input_file:
            input_file = self.train_file_path
        pairs = pd.read_pickle(input_file)
        train_ids = pairs['id1'].append(pairs['id2']).unique()

        trees = self.sources.set_index('id',drop=False).loc[train_ids]
        if not os.path.exists(data_path+'train/embedding'):
            os.mkdir(data_path+'train/embedding')
        if self.language is 'c':
            sys.path.append('../')
            from prepare_data_clang_rewritten import get_sequences as func
        else:
            from utils import get_sequence as func

        def preprocess_trees(code):
            trees1 = []

            code_split = code.split('¬')
            code = []
            for elem in code_split:
                node_split = elem.split(',')
                new_node = node_split[2:-1] #gets rid of node identifier and node depth and parent identifier
                new_node_string = ''
                for info in new_node:
                    if info != '' and '.' not in info:
                        code.append(info)

            return code

        def trans_to_sequences(ast):
            sequence = []
            func(ast, sequence, ast)
            return sequence

        #trees = trees[:1000]

        trees['code'] = trees['code'].apply(preprocess_trees)

        corpus = trees['code']

        from gensim.models.word2vec import Word2Vec
        print("Corpus:")
        print(corpus)
        w2v = Word2Vec(corpus, size=size, workers=16, sg=1, max_final_vocab=3000)
        w2v.save(data_path+'train/embedding/node_w2v_' + str(size))

    # generate block sequences with index representations
    def generate_block_seqs(self):
        if self.language is 'c':
            from prepare_data_clang_rewritten import get_blocks as func
        else:
            from utils import get_blocks_v1 as func
        from gensim.models.word2vec import Word2Vec

        def save_obj(obj, name ):
            with open('obj/'+ name + '.pkl', 'wb') as f:
                pickle.dump(obj, f, pickle.HIGHEST_PROTOCOL)

        def load_obj(name ):
            with open('obj/' + name + '.pkl', 'rb') as f:
                return pickle.load(f)

        word2vec = Word2Vec.load(self.root+self.language+'/train/embedding/node_w2v_' + str(self.size)).wv
        vocab = word2vec.vocab
        max_token = word2vec.syn0.shape[0]
        print("Original vocab length: "+str(max_token))

        data_path = self.root+self.language+'/'
        debugfile = data_path+"vocabDict"

        dict = {}
        for elem in vocab:
            dict[vocab[elem].index] = elem

        save_obj(dict,"tokenDict")

        with open(debugfile,'a+') as fp:
            for elem in vocab:
                fp.write(str(vocab[elem].index)+","+elem+"\n")
        fp.close()

        def tree_to_index(node):
            token = node.token
            result = [vocab[token].index if token in vocab else max_token]
            children = node.children
            for child in children:
                result.append(tree_to_index(child))
            return result

        def trans2seq(r):
            global transIndex

            blocks = []
            func(r, blocks, r)
            tree = []

            btree = tree_to_index(blocks[0])
            tree.append(btree)

            transIndex = transIndex + 1
            if transIndex % 1000 == 0:
                print("Generated " +str(transIndex) +" sequences.")
            return tree

        def tree_to_index_debug(node):
            global globalNodes
            token = node.token

            if not token in globalNodes:
                globalNodes.append(token)
            #result = [vocab[token].index if token in vocab else max_token]
            children = node.children
            for child in children:
                tree_to_index_debug(child)

        def listToString(s):
            str1 = ""
            for ele in s:
                str1 += ele
            return str1

        def correctTrees(code):
            #print(code)
            #codesplit = code.split(',')
            new_entry_list = []
            for elem in code:
                if elem in globalNodes:
                    new_entry_list.append(elem)

            return new_entry_list

        def cleanVocab(code):
            global globalNodes, missingTokens, indexO
            vocabUsed = []
            #missingTokens = []
            for elem in code:
                blocks = []
                func(elem, blocks, elem)
                tree_to_index_debug(blocks[0])
                indexO = indexO + 1
                if indexO % 100 == 0:
                    print(indexO)
            #tree.append(btree)
            #for token in vocab:
            #    if not token in globalNodes:
            #        missingTokens.append(token)
            #        vocab.pop(token)

            print("Tokens found: -----------------------------------")
            tokensFound = []
            for i in list(vocab):
                if not i in globalNodes:
                    missingTokens.append(i)
                    vocab.pop(i)
                else:
                    #print(i)
                    tokensFound.append(i)
            #print("Number: "+str(len(tokensFound)))

        print("Old vocab length: ")
        print(len(vocab))
        global indexO,globalNodes, corpus
        trees = pd.DataFrame(self.sources, copy=True)
        #trees = trees[:1000]
        #copy_of_trees = copy.deepcopy(trees)
        #print("Vocab:")
        #print(vocab)

        print("Cleaning vocab...")
        print(trees['code'])
        #print(trees['code'])
        cleanVocab(trees['code'])

        corpus = corpus.apply(correctTrees)
        print(corpus)

        os.remove(data_path+'train/embedding/node_w2v_' + str(self.size))
        w2v = Word2Vec(corpus, size=self.size, workers=16, sg=1, max_final_vocab=3000)
        w2v.save(data_path+'train/embedding/node_w2v_' + str(self.size))
        word2vec = Word2Vec.load(self.root+self.language+'/train/embedding/node_w2v_' + str(self.size)).wv
        vocab = word2vec.vocab

        print("New vocab length: ")
        print(len(vocab))

        #word2vec = Word2Vec.load(self.root+self.language+'/train/embedding/node_w2v_' + str(self.size)).wv
        #vocab2 = word2vec.vocab
        #print("Elements of vocab2:")
        #for i in list(vocab2):
        #    print(vocab2.get(i))
        max_token = word2vec.syn0.shape[0]
        #print("Vocab2: ")
        #print(vocab2)
        #print("New vocab length: "+str(word2vec.syn0.shape[0]))
        #trees['code'].apply(cleanVocab)
        #print("Missing tokens: "+str(len(missingTokens)))
        #print(missingTokens)
        #print("Global nodes: ")
        #print(globalNodes)
        #print("Length of global nodes: "+str(len(globalNodes)))
        #max_token = word2vec.syn0.shape[0]
        print("Vocab cleaned.")
        print("generate_block_seqs() before applying anything: --------------------------")
        print(trees)
        trees['code'] = trees['code'].apply(trans2seq)
        #trees['code'][8200] = trans2seq(trees['code'][8200])

        #print(trees['code'][8200])

        #sys.exit(0)

        print("after applying transformation: ------------------------------------")
        print(trees['code'])

        if 'label' in trees.columns:
            trees.drop('label', axis=1, inplace=True)
        self.blocks = trees

    # merge pairs
    def merge(self,data_path,part):
        pairs = pd.read_pickle(data_path)
        pairs['id1'] = pairs['id1'].astype(int)
        pairs['id2'] = pairs['id2'].astype(int)
        df = pd.merge(pairs, self.blocks, how='left', left_on='id1', right_on='id')
        df = pd.merge(df, self.blocks, how='left', left_on='id2', right_on='id')
        df.drop(['id_x', 'id_y'], axis=1,inplace=True)
        df.dropna(inplace=True)

        df.to_pickle(self.root+self.language+'/'+part+'/blocks.pkl')

    # run for processing data to train
    def run(self):
        print('parse source code...')
        self.parse_source(output_file='ast_clang.pkl',option='existing')
        print('read id pairs...')
        if self.language is 'c':
            self.read_pairs('oj_clone_ids.pkl')
        else:
            self.read_pairs('bcb_pair_ids.pkl')
        print('split data...')
        self.split_data()
        print('train word embedding...')
        self.dictionary_and_embedding(None,128)
        print('generate block sequences...')
        self.generate_block_seqs()
        print('merge pairs and blocks...')
        self.merge(self.train_file_path, 'train')
        self.merge(self.dev_file_path, 'dev')
        self.merge(self.test_file_path, 'test')

import argparse
parser = argparse.ArgumentParser(description="Choose a dataset:[c|java]")
parser.add_argument('--lang')
args = parser.parse_args()
if not args.lang:
    print("No specified dataset")
    exit(1)
ppl = Pipeline('3:1:1', 'data/', str(args.lang))
ppl.run()


# %%
import numpy as np
import matplotlib.pyplot as plt
from pylab import figure

def MS2_extractor(
        Df_MS2RawData,
        Df_FindPFAS,
        prec_mz,
        ):

    if np.sum(np.abs(Df_MS2RawData['m/z'] - prec_mz) < 0.005) == 0: # NOTE: Make mass tol as user input
        print('No MS2 available')
    else:
        idx = np.abs(Df_MS2RawData['m/z'] - prec_mz) < 0.005

        prec_mz_true = Df_MS2RawData['m/z'][idx].values[0]
        mz_array = Df_MS2RawData['MS2SpecMZ'][idx].values[0]
        intens_array = Df_MS2RawData['MS2SpecIntens'][idx].values[0]

        intens_array_normalized = intens_array/np.max(intens_array)
        idx_label = intens_array_normalized > 0.05
        mz_array_label = mz_array[idx_label]
        intens_array_label = intens_array[idx_label]

        figure()
        _, sl1, _ = plt.stem(mz_array, intens_array, 'Black', markerfmt=" ", basefmt=" ")
        plt.setp(sl1, color = 'Black', linewidth = 1)
        for i, txt in enumerate(np.round(mz_array_label, 4)):
            plt.annotate(txt, (mz_array_label[i],intens_array_label[i]), color = 'Black', rotation = 0, fontsize = 9)

        # Find MS/MS spectrum in Df_FindPFAS
        if type(Df_FindPFAS) != str:
            idx_FindPFAS = Df_FindPFAS['m/z_MSMS'] == prec_mz_true
            if np.sum(idx_FindPFAS) > 0: # CHANGED FROM == 1! NEED TO BE VALIDATED!
                start_idx = Df_FindPFAS.columns.get_loc('formula_diagnostic') + 1 # find first index with diff (e.g. CF2)
                end_idx = Df_FindPFAS.columns.get_loc(f'mz_{Df_FindPFAS.columns[start_idx]}')

                diffs = list(Df_FindPFAS.columns[start_idx:end_idx].values) # get diffs
                for diff in diffs:
                    if len(Df_FindPFAS[idx_FindPFAS][f'mz_{diff}'].values[0]) > 0:
                        _, sl2, _ = plt.stem(Df_FindPFAS[idx_FindPFAS][f'mz_{diff}'].values[0],
                                             Df_FindPFAS[idx_FindPFAS][f'intens_{diff}'].values[0], markerfmt=" ", basefmt=" ")
                        plt.setp(sl2, linewidth = 1.5)

                if len(Df_FindPFAS[idx_FindPFAS]['mz_peaks_diagnostic'].values[0]) > 0:
                    _, sl3, _ = plt.stem(Df_FindPFAS[idx_FindPFAS]['mz_peaks_diagnostic'].values[0],
                                         Df_FindPFAS[idx_FindPFAS]['intens_peaks_diagnostic'].values[0], 'Red', markerfmt=" ", basefmt=" ")
                    plt.setp(sl3, color = 'Red', linewidth = 1.5)

                    label = [n +'\n' for n in Df_FindPFAS[idx_FindPFAS]['formula_diagnostic'].values[0].to_list()]
                    for i, txt in enumerate(label):
                        plt.annotate(txt, (Df_FindPFAS[idx_FindPFAS]['mz_peaks_diagnostic'].values[0][i],
                                           Df_FindPFAS[idx_FindPFAS]['intens_peaks_diagnostic'].values[0][i]),
                                           color = 'Red', rotation = 0, fontsize = 9)

                if isinstance(Df_FindPFAS['new_formulas'][idx_FindPFAS].values[0], list): # NOTE: There could be a bug here, check again
                    #label2 = [n +'\n\n' for n in Df_FindPFAS['new_formulas'][idx_FindPFAS].values[0]] # NOTE: include two linebreaks
                    u, c = np.unique(Df_FindPFAS['frag_idx'][idx_FindPFAS].values[0], return_counts = True)
                    prefix_c = np.zeros(len(Df_FindPFAS['frag_idx'][idx_FindPFAS].values[0]))
                    for x in range(len(u)):
                        prefix_c[np.where(u[x] == Df_FindPFAS['frag_idx'][idx_FindPFAS].values[0])[0]] = np.arange(0, c[x])
                    prefix_c = prefix_c + 2
                    prefix_c = prefix_c.astype('int')
                    label2 = []
                    for n, formula in enumerate(Df_FindPFAS['new_formulas'][idx_FindPFAS].values[0]):
                        label2.append(formula + prefix_c[n]*'\n')

                    for i, txt in enumerate(label2):
                        plt.annotate(txt, (Df_FindPFAS['mz_peaks'][idx_FindPFAS].values[0][Df_FindPFAS['frag_idx'][idx_FindPFAS].values[0]][i],
                                           Df_FindPFAS['intens_peaks'][idx_FindPFAS].values[0][Df_FindPFAS['frag_idx'][idx_FindPFAS].values[0]][i]),
                                           color = 'Blue', rotation = 0, fontsize = 9)

                    #str_formulas = ' '.join(Df_FindPFAS['new_formulas'][idx_FindPFAS].values[0])
                    #plt.title(f'MS2 spectrum (m/z = {np.round(prec_mz_true, 4)}) \n {str_formulas}')
                    plt.title(f'MS2 spectrum (m/z = {np.round(prec_mz_true, 4)})')

        else:
            plt.title(f'MS2 spectrum (m/z = {np.round(prec_mz_true, 4)})')

        plt.ticklabel_format(axis = 'y', style = 'sci', scilimits=(0,0), useMathText=True)
        plt.xlabel('m/z')
        plt.ylabel('Counts (-)')
        plt.ylim(ymin = 0)
        plt.show()

        mz = mz_array[mz_array < prec_mz_true + 5]
        intens = intens_array[mz_array < prec_mz_true + 5]
        MD = mz - np.round_(mz, decimals = 0)  # NOTE: Change rounding!!
        MD_prec = prec_mz_true - np.round_(prec_mz_true, decimals = 0)
        idx = intens > 100

        figure()
        cmap = 'Reds'
        plt.scatter(mz[idx], MD[idx], 80, c = np.log10(intens[idx]), cmap = cmap, alpha = 0.8, edgecolors='lightgrey')
        plt.axhline(y = MD_prec, color = 'grey', linestyle = ':', alpha = 0.5)
        cbar = plt.colorbar()
        cbar.set_label('log(Intensity)')
        plt.xlabel('m/z')
        plt.ylabel('MD')
        plt.title(np.round(prec_mz_true, 4))
        plt.show()


# Multiples of 3 and 5
# Problem 1
# If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3, 5, 6 and 9. The sum of these
# multiples is 23.

# Find the sum of all the multiples of 3 or 5 below 1000.

import math
import itertools

def is_divisible_by_one(x, factors):
    for factor in factors:
        if x % factor == 0:
            return True
    return False

def is_divisible_by_all(x, factors):
    for factor in factors:
        if x % factor != 0:
            return False
    return True

def lcm(factors, return_generator=False):
    max_factor = max(factors)
    generator = (f
                 for f in itertools.count(max_factor, max_factor)
                 if is_divisible_by_all(f, factors))
    if return_generator:
        return generator
    else:
        return next(generator)

FACTORS = [3, 5]
N = 1000

lcm = lcm(FACTORS)
mod_lcm = [i for i in range(0, lcm) if is_divisible_by_one(i, FACTORS)]
print("modulo lcm numbers\t", mod_lcm)

N_lcm = math.ceil(N / lcm)
print("number of modulos\t", N_lcm)

num_below_1000 = [i
                  for m in range(0, N_lcm)
                  for i in map(lambda j: j + (m * lcm), mod_lcm)
                  if i < N]
print("numbers below N\t\t", num_below_1000)

result = sum(num_below_1000)
print("final result\t\t", result)


# Licensed under a 3-clause BSD style license - see LICENSE.rst

import numpy as np
from sofia_redux.toolkit.utilities.fits import gethdul
from sofia_redux.toolkit.image.adjust import rotate90 as idlrot

__all__ = ['readwavecal']

def readwavecal(filename, rotate=None, info=None):
    """
    Read a Spextool wavecal file

    Parameters
    ----------
    filename : str
        The path to a 2-d Spextool wavecal file.
    rotate : int, optional
        Rotation direction (not angle) to pass to rotate wavecal
        and spatcal images when passed to
        `sofia_redux.toolkit.image.adjust.rotate90`.
    info : dict, optional
        If supplied will be updated with wctype, wavefmt, spatfmt,
        wdisp, flatname, orders, and norders.

    Returns
    -------
    wavecal, spatcal : numpy.ndarray, numpy.ndarray
        - wavecal (nrow, ncol) array where each pixel is set to its
          wavelength (column in this case).
        - spatcal (nrow, ncol) array where each pixel is set to its
          angular position on the sky.
    """
    hdul = gethdul(filename, verbose=True)
    if hdul is None:
        return

    header = hdul[0].header

    wavecal, spatcal = hdul[0].data[:2].copy()
    if rotate is not None:
        wavecal = idlrot(wavecal, rotate)
        spatcal = idlrot(spatcal, rotate)

    if isinstance(info, dict):
        orders = np.array(header.get('ORDERS', '0').split(',')).astype(int)
        norders = int(header.get('NORDERS', 0))
        info['wctype'] = str(header.get('WCTYPE')).strip()
        info['orders'] = orders
        info['norders'] = norders
        keys = ['wdeg', 'odeg', 'homeordr', 'wxdeg',
                'wydeg', 'sxdeg', 'sydeg']
        for key in keys:
            info[key] = header.get(key.upper(), 0)
        if (info['wdeg'] + info['odeg']) > 0:
            info['xo2w'] = np.array(list(header['1DWC*'].values()))
        else:
            info['xo2w'] = np.zeros(0)

        if np.sum([info[x] for x in
                   ['wxdeg', 'wydeg', 'sxdeg', 'sydeg']]) > 0:
            nwxy = (info['wxdeg'] + 1) * (info['wydeg'] + 1)
            nsxy = (info['sxdeg'] + 1) * (info['sydeg'] + 1)
            info['xy2w'] = np.zeros((norders, nwxy))
            info['xy2s'] = np.zeros((norders, nsxy))
            for i in range(norders):
                ordi = str(orders[i]).zfill(2)
                info['xy2w'][i] = np.array(
                    list(header['OR%sWC*' % ordi].values()))
                info['xy2s'][i] = np.array(
                    list(header['OR%sSC*' % ordi].values()))
        else:
            info['xy2w'] = np.zeros((norders, 0))
            info['xy2s'] = np.zeros((norders, 0))

    return wavecal, spatcal


from compound.i.iOx import iOx_oxs
from compound.i.iBa import iBa_oxs
from database.compounds.iOx import *
from database.compounds.iBa import *
from element import Element
from formula import *
from tools.comps import index, simple
from tools.container import key_in_dict

def id_inorganic_type(comp):
    formula = comp.formula

    isAlkMe = lambda el: el.elem_sub_type == "AlkMe" \
      or el.elem_sub_type == "AlkEMe"
    isMe = lambda el: el.elem_type == "Me"
    isNonMe = lambda el: el.elem_type == "NonMe"

    if Element("Bz") in formula.consist:
        return "nil"

    def id_iWa(): # water
        if formula.value == "H2O":
            return "iWa"

    def id_iSi(): # simple compound
        if len(formula.consist) != 1:
            return ""

        elem = list(formula.consist.keys())[0]
        if elem.name == "O":
            if formula.value not in ["[O]", "O2", "O3"]:
                return "nil"
        elif formula.value != simple(elem.name):
            return "nil"

        if elem.elem_type == "Me": # metal
            return "iSiMe"
        elif elem.elem_type == "NonMe": # non-metal
            return "iSiNme"
        else:
            return "nil"

    def id_iOx(): # oxide
        if len(formula.consist) != 2:
            return ""
        if Element("O") not in formula.consist:
            return ""
        if Element("F") in formula.consist: # OF2 is not oxide
            return ""
        if formula.value == "H2O2":
            return "nil"
        if formula.value in db_peroxides:
            return "iSaPer"

        def id_iOxAlk(): # alkaline oxide
            if key_in_dict(formula.consist, isAlkMe):
                return "iOxAlk"

        def id_iOxBa(): # basic oxide
            if not key_in_dict(formula.consist, isMe):
                return ""
            _, oxs = iOx_oxs(formula)
            if (oxs <= 2 and formula.value not in db_iOxAm) \
              or formula.value in db_iOxBa:
                return "iOxBa"

        def id_iOxAc(): # acidic oxide
            if not (key_in_dict(formula.consist, isNonMe)-1):
                _, oxs = iOx_oxs(formula)
                if oxs < 5:
                    return ""
            return "iOxAc"

        def id_iOxAm(): # amphoteric oxide
            return "iOxAm"

        def id_iOxNs(): # non salt formating oxide
            if formula.value in db_iOxNs:
                return "iOxNs"

        sub_fns = [id_iOxNs, id_iOxAlk, id_iOxBa, id_iOxAc, id_iOxAm]
        for fn in sub_fns:
            comp_type = fn()
            if comp_type:
                return comp_type
        return ""

    def id_iBa(): # base
        if "OH" not in formula.value:
            return ""
        if key_in_dict(formula.consist, isNonMe) > 2 and \
           '[' not in formula.value:
            return ""
        if formula.value.find("OH") < formula.value.find("]"):
            return ""
        if formula.value == "AmmOH":
            return "nil"

        def id_iBaCo(): # complex base
            if "]OH" in formula.value:
                return "iBaCo"
            elif "](OH)" in formula.value:
                return "iBaCo"

        def id_iBaAlk(): # alkaline
            if key_in_dict(formula.consist, isAlkMe):
                return "iBaAlk"

        def id_iBaBa(): # base
            _, oxs = iBa_oxs(formula)
            if (oxs <= 2 and formula.value not in db_iBaAm) \
              or formula.value in db_iBaBa:
                return "iBaBa"

        def id_iBaAm(): # amphoteric base
            return "iBaAm"

        sub_fns = [id_iBaCo, id_iBaAlk, id_iBaBa, id_iBaAm]
        for fn in sub_fns:
            comp_type = fn()
            if comp_type:
                return comp_type
        return ""

    def id_iAc(): # acid
        if formula.value[0] != "H":
            return ""
        if formula.value == "H2O2":
            return ""
        if Element("H") not in formula.consist:
            return ""
        if Element("C") in formula.consist:
            if formula.value not in ["H2CO3", "HCN", "HCNO"]:
                return "nil"
        if key_in_dict(formula.consist, isMe) \
          and len(formula.consist) < 3:
            return ""

        def id_iAcOx(): # acid with oxygen
            if Element("O") in formula.consist:
                return "iAcOx"

        def id_iAcNox(): # acid without oxygen
            return "iAcNox"

        def id_iAcCo(): # complex base
            if '[' in formula.value:
                return "iAcCo"

        sub_fns = [id_iAcCo, id_iAcOx, id_iAcNox]
        for fn in sub_fns:
            comp_type = fn()
            if comp_type:
                val = formula.value
                pos = 0
                while val[pos] == 'H':
                    pos += 1
                val = "H" + index(pos) + val[pos : ]
                comp.formula = Formula(val)
                return comp_type
        return ""

    def id_iSa(): # salt
        if not key_in_dict(formula.consist, isNonMe):
            return ""
        if not key_in_dict(formula.consist, isMe):
            return ""
        if Element("H") in formula.consist and len(formula.consist) < 3:
            return ""
        if len(formula.consist) == 2:
            if Element("C") in formula.consist or \
               Element("N") in formula.consist or \
               Element("Si") in formula.consist:
               return ""
        if Element("C") in formula.consist:
            if "CO3" not in formula.value and \
               "CN" not in formula.value and "CNO" not in formula.value:
                return ""

        def id_iSaCo(): # complex salt
            if '[' in formula.value:
                return "iSaCo"

        def id_iSaNo(): # normal salt
            return "iSaNo"

        def id_iSaBa(): # basic salt
            if "OH" in formula.value:
                return "iSaBa"

        def id_iSaAc(): # acidic salt
            if Element("H") in formula.consist:
                return "iSaAc"

        def id_iSaAmm():
            if Element("Amm") in formula.consist:
                return "iSaAmm"

        def id_iSaAmmAc():
            if Element("Amm") in formula.consist \
              and Element("H") in formula.consist:
                return "iSaAac"

        sub_fns = [id_iSaCo, id_iSaAmmAc, id_iSaAmm, id_iSaBa, id_iSaAc, id_iSaNo]
        for fn in sub_fns:
            comp_type = fn()
            if comp_type:
                return comp_type
        return ""

    def id_iBi():
        if len(formula.consist) != 2:
            return ""
        if Element("C") in formula.consist:
            if list(formula.consist.keys())[0].elem_type != "Me" and \
               list(formula.consist.keys())[1].elem_type != "Me":
               return ""
        if list(formula.consist.keys())[0].elem_type == "In" or \
           list(formula.consist.keys())[1].elem_type == "In":
           return ""
        return "iBi"

    fns = [id_iWa, id_iSi, id_iOx, id_iBa, id_iAc, id_iSa, id_iBi]
    for fn in fns:
        comp_type = fn()
        if comp_type:
            return comp_type
    return "nil"


#!/usr/bin/env python3

from argparse import ArgumentParser
from pathlib import Path
import colorama
import datetime as dt
import os.path

TASKS_PATH = str(Path.home()) + "/" + ".tasker_tasks.txt"

PRIORITY = {'1': colorama.Fore.RESET,
			'2': colorama.Fore.LIGHTYELLOW_EX,
			'3': colorama.Fore.LIGHTRED_EX}

def die(error):
	print()
	print("tasker.py: error: " + error)
	exit(1)

def add_arguments(parser):
	parser.add_argument("-a", "--add", action="store_true",
						dest="add", default=False,
						help="add new task to list")
	parser.add_argument("-d", nargs="+", dest="delete",
						help="delete tasks from list")
	parser.add_argument("-l", "--list", action="store_true",
						dest="print", default=False,
						help="print tasks list")
	parser.add_argument("-t", "--time", action="store_true",
						dest="time", default=False,
						help="add deadline for task")
	parser.add_argument("-q", "--quiet",
	                    action="store_false", dest="verbose", default=True,
	                    help="don't print messages to stdout")
	# TODO: edit task option

def check_file_exist():
	# create file if not found
	if not os.path.isfile(TASKS_PATH):
		file = open(TASKS_PATH, 'w+')
		file.close()

def read_tasks():
	check_file_exist()

	with open(TASKS_PATH, 'r') as handler:
		tasks = handler.read().strip().split('\n')

	if len(tasks) == 1 and tasks[0] == '':
		print("Your tasks list is empty")
		exit(0)
	return tasks

def print_tasks():
	tasks = read_tasks()
	colorama.init()
	for i, task in enumerate(tasks):
		prior, date, task, deadline = task.split('|')

		if deadline and deadline != " ":
			deadline = colorama.Fore.MAGENTA + " (due: " + deadline + ")"

		print(PRIORITY['1'] + str(i+1) + "."
			+ colorama.Fore.LIGHTMAGENTA_EX
			+ " (" + date + ") "
			+ PRIORITY[prior] + task
			+ deadline)

def add_new_task(verbose, time):
	if verbose:
		print("Write your task:")
	task = input()

	if task == '':
		die("empty task")
	if '|' in task:
		die("char '|' restricted")

	if verbose:
		print("Set your priority:")
	priority = input()

	if priority.strip() not in ['1', '2', '3']:
		priority = '1'

	date = dt.datetime.now()

	if time:
		if verbose:
			print("Write days to deadline")
		try:
			days = abs(int(input()))
		except ValueError:
			die("invalid integer input")

		days = (date + dt.timedelta(days=days)).strftime("%d.%m.%y")
	else:
		days = ' '

	date = date.strftime("%d.%m.%y")

	with open(TASKS_PATH, 'a') as handler:
		handler.write(priority + '|'
						+ date + '|'
						+ task + '|'
						+ days + '\n')

	if verbose:
		print("Task added successfully")

def delete_task(args):
	tasks = read_tasks()
	tasks_to_delete = sorted(list(map(int, set(args.delete))))[::-1]

	for index in tasks_to_delete:
		index = int(index) - 1
		if index < 0:
			die("index can't be negative number")
		try:
			tasks.pop(index)
		except ValueError:
			die("invalid task index")
		except IndexError:
			die("index is out of range")

	with open(TASKS_PATH, 'w') as handler:
		for task in tasks:
			if task:
				handler.write(task + '\n')

	if args.verbose:
		print("Tasks " + str(tasks_to_delete[::-1]) + " deleted")

def main():
	parser = ArgumentParser(description='Simple task manager')
	add_arguments(parser)
	args = parser.parse_args()

	if args.delete and args.add:
		parser.print_usage()
		die("only one option required")

	if not args.delete and not args.add:
		print_tasks()
		exit(0)
	elif args.add:
		add_new_task(args.verbose, args.time)
	elif args.delete:
		delete_task(args)

	if args.print:
		print_tasks()

if __name__ == "__main__":
	main()


from abc import ABC, abstractmethod
import numpy as np
import tensorflow as tf
import edward as ed
import tqdm
import uuid
from edward.models import Normal, Categorical, Multinomial
from keras.models import Sequential
from keras import optimizers
from keras.layers import Dense
from keras.layers import Activation
from keras.layers import Dropout
from keras.layers import Lambda
from keras.layers import Conv2D
from keras.layers import MaxPooling2D
from keras.layers import Flatten
from keras.callbacks import EarlyStopping
from keras.callbacks import ModelCheckpoint
from layers import BayesianDropout
from keras import backend as K
from sklearn.preprocessing import LabelEncoder
from sklearn.preprocessing import OneHotEncoder

class Model(ABC):

    @abstractmethod
    def fit(X, y):
        pass

    @abstractmethod
    def predict_proba(X):
        pass

    @abstractmethod
    def predict(X):
        pass

class LogisticRegression(Model):

    def __init__(self, n_samples=5, n_iter=100, inference='variational'):
        self.inference = inference
        self.n_samples = n_samples
        self.n_iter = n_iter
        self.model = None

    def fit(self, X, y):
        self.label_encoder = LabelEncoder().fit(y)
        y = self.oh_encoder.transform(y)

        DIN = X.shape[1]
        DOUT = len(set(y))

        X_data = tf.placeholder(tf.float32, [None, DIN])
        W = Normal(loc=tf.zeros([DIN, DOUT]), scale=tf.ones([DIN, DOUT]))
        b = Normal(loc=tf.zeros([DOUT]), scale=tf.ones([DOUT]))
        y_data = Categorical(logits=tf.matmul(X_data, W) + b)

        qW = Normal(loc=tf.Variable(tf.random_normal([DIN, DOUT])),
                    scale=tf.nn.softplus(tf.Variable(tf.random_normal([DIN, DOUT]))))
        qb = Normal(loc=tf.Variable(tf.random_normal([DOUT])),
                    scale=tf.nn.softplus(tf.Variable(tf.random_normal([DOUT]))))

        self.model = ed.KLqp({W: qW, b: qb}, data={X_data: X, y_data: y})
        self.model.run(n_samples=self.n_samples, n_iter=self.n_iter)

        self.W = qW
        self.b = qb

    def predict_proba(self, X):
        W = self.W.eval()
        b = self.b.eval()
        return np.matmul(X, W) + b

    def predict(self, X):
        return self.predict_proba(X).argmax(axis=1)

class MLP(Model):

    def __init__(self, epochs=10, batch_size=32, inference='dropout'):
        self.epochs = epochs
        self.batch_size = batch_size
        self.inference = inference
        self.model = None

    def fit(self, X, y):
        self.label_encoder = LabelEncoder().fit(y)
        n_labels = len(self.label_encoder.classes_)
        y = np.eye(n_labels)[y]

        model = Sequential()

        model.add(Dense(1024, activation='relu', input_shape=(X.shape[1],)))

        if self.inference == 'dropout':
            model.add(Lambda(lambda x: K.dropout(x, level=0.5)))
        else:
            model.add(Dropout(0.5))
        model.add(Dense(1024, activation='relu'))

        if self.inference == 'dropout':
            model.add(Lambda(lambda x: K.dropout(x, level=0.5)))
        else:
            model.add(Dropout(0.5))
        model.add(Dense(n_labels, activation='softmax'))

        model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
        model.fit(X, y, epochs=self.epochs, batch_size=self.batch_size)
        self.model = model
        return self

    def predict_proba(self, X):
        return self.model.predict_proba(X, verbose=0)

    def predict(self, X):
        return self.predict_proba(X).argmax(axis=1)

class CNN(Model):

    def __init__(self, input_shape, num_classes, epochs=10, batch_size=32):
        self.input_shape = input_shape
        self.num_classes = num_classes
        self.epochs = epochs
        self.batch_size = batch_size

        model = Sequential()
        model.add(Conv2D(32, (3, 3), padding='same', input_shape=input_shape))
        model.add(Activation('relu'))
        model.add(Conv2D(32, (3, 3)))
        model.add(Activation('relu'))
        model.add(MaxPooling2D(pool_size=(2, 2)))
        model.add(Dropout(0.25))
        model.add(Conv2D(64, (3, 3), padding='same'))
        model.add(Activation('relu'))
        model.add(Conv2D(64, (3, 3)))
        model.add(Activation('relu'))
        model.add(MaxPooling2D(pool_size=(2, 2)))
        model.add(Dropout(0.25))
        model.add(Flatten())
        model.add(Dense(512))
        model.add(Activation('relu'))
        model.add(Dropout(0.5))
        model.add(Dense(num_classes))
        model.add(Activation('softmax'))
        opt = optimizers.rmsprop(lr=0.0001, decay=1e-6)
        model.compile(loss='categorical_crossentropy', optimizer=opt, metrics=['accuracy'])
        self.model = model

        probabilistic_model = Sequential()
        probabilistic_model.add(Conv2D(32, (3, 3), padding='same', input_shape=input_shape))
        probabilistic_model.add(Activation('relu'))
        probabilistic_model.add(Conv2D(32, (3, 3)))
        probabilistic_model.add(Activation('relu'))
        probabilistic_model.add(MaxPooling2D(pool_size=(2, 2)))
        probabilistic_model.add(BayesianDropout(0.25))
        probabilistic_model.add(Conv2D(64, (3, 3), padding='same'))
        probabilistic_model.add(Activation('relu'))
        probabilistic_model.add(Conv2D(64, (3, 3)))
        probabilistic_model.add(Activation('relu'))
        probabilistic_model.add(MaxPooling2D(pool_size=(2, 2)))
        probabilistic_model.add(BayesianDropout(0.25))
        probabilistic_model.add(Flatten())
        probabilistic_model.add(Dense(512))
        probabilistic_model.add(Activation('relu'))
        probabilistic_model.add(BayesianDropout(0.5))
        probabilistic_model.add(Dense(num_classes))
        probabilistic_model.add(Activation('softmax'))
        opt = optimizers.rmsprop(lr=0.0001, decay=1e-6)
        probabilistic_model.compile(loss='categorical_crossentropy', optimizer=opt, metrics=['accuracy'])
        self.probabilistic_model = probabilistic_model

    def fit(self, X_train, y_train, X_val, y_val):
        es = EarlyStopping(monitor='val_loss', patience=10)
        weights_filename = 'runs/' + uuid.uuid4().hex + '.hdf5'
        cp = ModelCheckpoint(weights_filename, save_best_only=True)

        self.model.fit(X_train, y_train,
                       epochs=self.epochs,
                       batch_size=self.batch_size,
                       validation_data=(X_val, y_val),
                       callbacks=[cp, es])
        self.model.load_weights(weights_filename)
        self.probabilistic_model.set_weights(self.model.get_weights())

        return self

    def predict_proba(self, X, probabilistic=False):
        model = self.model
        if probabilistic:
            model = self.probabilistic_model

        return model.predict(X, batch_size=self.batch_size, verbose=0)

    def predict(self, X, probabilistic=False):
        y = self.predict_proba(X, probabilistic)
        return y.argmax(axis=1)

def load(model):
    name = model.pop('name')

    if name == 'logistic_regression':
        model = LogisticRegression(**model)
    elif name == 'mlp':
        model = MLP(**model)
    elif name == 'cnn':
        model = CNN(**model)
    else:
        raise Exception('Unknown model {0}'.format(model))

    return model


#-*- coding: utf-8 -*-
import argparse
import datetime
import imutils
import time
import cv2
import threading
import os
from timer import TimeRecord
from push import push
from example_utf8_sendsms  import sendsms

class VideoCamera(object):
	def __init__(self):
		self.ap = argparse.ArgumentParser()
		self.ap.add_argument("-v", "--video", help="path to the video file")
		self.ap.add_argument("-a", "--min-area", type=int, default=1500, help="minimum area size")
		self.args = vars(self.ap.parse_args())
		os.system("sudo modprobe bcm2835-v4l2")
		self.frame = None
		self.grebbed = None
		self.gray = None
		self.text = None
		self.autotext = None
		self.frameDelta = None
		self.thresh = None
		self.timer = TimeRecord()
		self.pushAL = push()

		self.x = None
		self.y = None
		self.ii = 1

		if self.args.get("video", None) is None:
			self.camera = cv2.VideoCapture(0)
			time.sleep(0.25)

		else:
			self.camera = cv2.VideoCapture(self.args["video"])

		self.firstFrame = None

		if os.path.exists("auto.txt")==False:
			os.system("touch auto.txt")

	def __del__(self):
		self.cemera.release()
		cv2.destroyAllWindows()

	def getFrame(self):
		(self.grabbed, self.frame) = self.camera.read()
		self.frame = cv2.flip(self.frame,0)
		self.frame = cv2.flip(self.frame,1)
		self.text = ""

	def resizeFrame(self):
		self.frame = imutils.resize(self.frame, width=350)
		self.gray = cv2.cvtColor(self.frame, cv2.COLOR_BGR2GRAY)
		self.gray = cv2.GaussianBlur(self.gray, (21, 21), 0)

	def showFrame(self,frame,thresh,frameDelta):
		cv2.imshow("Security Feed", frame)
		cv2.imshow("Thresh", thresh)
		cv2.imshow("Frame Delta", frameDelta)

	def di(self):
		if self.ii == 1:
			time.sleep(5)
			self.ii = 0

		if self.x >= 0 and self.x <= 146 and self.y >=0 and self.y <= 111:
			self.x = None
			self.y = None
			os.system("touch leftup.txt")

		elif self.x >= 0 and self.x <= 146 and self.y >111 and self.y <= 148:
			self.x = None
			self.y = None
			os.system("touch left.txt")

		elif self.x >= 0 and self.x <= 146 and self.y >148:
			self.x = None
			self.y = None
			os.system("touch leftdown.txt")

		elif self.x > 146 and self.x <=195 and self.y >=0 and self.y <=111:
			self.x = None
			self.y = None
			os.system("touch up.txt")

		elif self.x >146 and self.x <= 195 and self.y >148:
			self.x = None
			self.y = None
			os.system("touch down.txt")

		elif self.x > 195 and self.y >=0 and self.y <=111:
			self.x = None
			self.y = None
			os.system("touch rightup.txt")

		elif self.x > 195 and self.y > 111 and self.y <= 148:
			self.x = None
			self.y = None
			os.system("touch right.txt")

		elif self.x > 195 and self.y >148:
			self.x = None
			self.y = None
			os.system("touch rightdown.txt")

	def motion(self):
		self.frameDelta = cv2.absdiff(self.firstFrame, self.gray)
		self.thresh = cv2.threshold(self.frameDelta ,67 , 255, cv2.THRESH_BINARY)[1]

		self.thresh = cv2.dilate(self.thresh, None, iterations=2)
		(_, cnts, _) = cv2.findContours(self.thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

		sense = None

		for c in cnts:
			if cv2.contourArea(c) < self.args["min_area"]:
				continue

			(x, y, w, h) = cv2.boundingRect(c)
			cv2.rectangle(self.frame, (x, y), (x + w, y + h), (0, 255, 0), 2)
			self.text = "Something sensering now"

			sense = True

			self.x = x + w / 2
			self.y = y + h / 2

			break

		if self.timer.Record(sense) == True:
			print("이미지를 캡처합니다.")
			cv2.imwrite("capture.jpg", self.frame)
			self.pushAL.alarm()
			sendsms()

	def putText(self):
		cv2.putText(self.frame, "{}".format(self.text), (10, 20), cv2.FONT_HERSHEY_SIMPLEX, 0.45, (0, 0, 255), 2)
		cv2.putText(self.frame, datetime.datetime.now().strftime("%A %d %B %Y %I:%M:%S%p"), (10, self.frame.shape[0] - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.35, (0, 0, 255), 1)
		cv2.putText(self.frame, "{}".format(self.autotext), (self.frame.shape[1]-35, 20), cv2.FONT_HERSHEY_SIMPLEX, 0.4, (0, 0, 255), 2)

	def Camera(self):
		while True:
			self.autotext = ""
			if os.path.exists("auto.txt"):
				self.autotext = "Auto"
				self.di()

			if os.path.exists("move2.txt"):
				self.firstFrame = None
				os.system("rm move.txt")
				os.system("rm move2.txt")
				continue

			self.getFrame()

			if not self.grabbed:
				break

			self.resizeFrame()

			if self.firstFrame is None:
				self.firstFrame = self.gray
				continue

			if os.path.exists("move.txt")==False:
				self.motion()

			cv2.imwrite("output.jpg",self.frame)

			self.putText()

			self.showFrame(self.frame,self.thresh,self.frameDelta)

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


# -*- coding: utf-8 -*-
"""Tests that all of often used portlets are patched."""

from Products.CMFCore.utils import getToolByName
from hexagonit.portletstyle.tests.base import IntegrationTestCase
from plone.app.portlets import portlets
from plone.portlet.collection import collection
from plone.portlet.static import static
from plone.portlets.interfaces import IPortletManager
from plone.portlets.interfaces import IPortletRenderer
from plone.portlets.interfaces import IPortletType
from zope.component import getUtility
from zope.component import queryMultiAdapter
from zope.interface import alsoProvides

import mock

class TestPorltets(IntegrationTestCase):
    """Tests patching of often used portlets."""

    def setUp(self):
        """Custom shared utility setup for tests."""
        # apply IPortletStyleLayer browser layer so that z3c.jbot overrides take
        # effect
        from hexagonit.portletstyle.interfaces import IPortletStyleLayer
        alsoProvides(self.layer['app'].REQUEST, IPortletStyleLayer)

        # shortcuts
        self.portal = self.layer['portal']
        self.request = self.portal.REQUEST
        self.view = self.portal.restrictedTraverse('@@plone')
        self.installer = getToolByName(self.portal, 'portal_quickinstaller')
        self.mapping = self.portal.restrictedTraverse('++contextportlets++plone.leftcolumn')
        self.manager = getUtility(IPortletManager, name='plone.leftcolumn', context=self.portal)

    def tearDown(self):
        """Cleanup after running tests."""
        # remove all portlets assigned to left column
        for m in self.mapping.keys():
            del self.mapping[m]

    def _add_portlet(self, name=None, assignment_class=None, data=None):
        """A helper method for quickly adding a portlet."""
        portlet = getUtility(IPortletType, name=name)

        data = data or {'portlet_style': 'noheader'}

        addview = self.mapping.restrictedTraverse('+/' + portlet.addview)
        addview.createAndAdd(data=data)

        # is portlet really there?
        assignment = self.mapping.values()[-1]  # portlet is the last in mapping
        # self.assertEquals(len(self.mapping), 1)
        self.assertIsInstance(assignment, assignment_class)
        return assignment

    def test_portlet_events(self):
        """Test that events portlet is patched."""
        # add portlet
        portlet = self._add_portlet(
            name='portlets.Events',
            assignment_class=portlets.events.Assignment
        )

        # what does Renderer.portlet_style give us?
        renderer = queryMultiAdapter((self.portal, self.request, self.view, self.manager, portlet), IPortletRenderer)
        self.assertEquals(renderer.portlet_style(), 'noheader')

        # test HTML
        renderer.update()
        self.assertIn('<dl class="portlet portletEvents noheader">', renderer.render())

    def test_portlet_navigation(self):
        """Test that navigation portlet is patched."""
        # add portlet
        portlet = self._add_portlet(
            name='portlets.Navigation',
            assignment_class=portlets.navigation.Assignment,
            data={
                'portlet_style': 'noheader',
                'topLevel': 0,  # so the portlet is displayed on root
            }
        )

        # what does Renderer.portlet_style give us?
        renderer = queryMultiAdapter((self.portal, self.request, self.view, self.manager, portlet), IPortletRenderer)
        self.assertEquals(renderer.portlet_style(), 'noheader')

        # test HTML
        renderer.update()
        self.assertIn('<dl class="portlet portletNavigationTree noheader">', renderer.render())

    def test_portlet_news(self):
        """Test that news portlet is patched."""
        # add portlet
        portlet = self._add_portlet(
            name='portlets.News',
            assignment_class=portlets.news.Assignment
        )

        # what does Renderer.portlet_style give us?
        renderer = queryMultiAdapter((self.portal, self.request, self.view, self.manager, portlet), IPortletRenderer)
        self.assertEquals(renderer.portlet_style(), 'noheader')

        # test HTML
        renderer.update()
        self.assertIn('<dl class="portlet portletNews noheader">', renderer.render())

    def test_portlet_login(self):
        """Test that login portlet is patched."""
        # XXX
        pass

    def test_portlet_recent(self):
        """Test that recent portlet is patched."""
        # add portlet
        portlet = self._add_portlet(
            name='portlets.Recent',
            assignment_class=portlets.recent.Assignment
        )

        # what does Renderer.portlet_style give us?
        renderer = queryMultiAdapter((self.portal, self.request, self.view, self.manager, portlet), IPortletRenderer)
        self.assertEquals(renderer.portlet_style(), 'noheader')

        # test HTML
        renderer.update()
        self.assertIn('<dl class="portlet portletRecent noheader">', renderer.render())

    @mock.patch('plone.app.portlets.portlets.rss.Renderer.initializing', new=False)
    @mock.patch('plone.app.portlets.portlets.rss.Renderer.enabled', new=True)
    def test_portlet_rss(self):
        """Test that rss portlet is patched."""
        # add portlet
        portlet = self._add_portlet(
            name='portlets.rss',
            assignment_class=portlets.rss.Assignment
        )

        # what does Renderer.portlet_style give us?
        renderer = queryMultiAdapter((self.portal, self.request, self.view, self.manager, portlet), IPortletRenderer)
        self.assertEquals(renderer.portlet_style(), 'noheader')

        # test HTML
        renderer.update()
        self.assertIn('<dl class="portlet portletRss noheader">', renderer.render())

    def test_portlet_search(self):
        """Test that Search portlet is patched."""
        # add portlet
        portlet = self._add_portlet(
            name='portlets.Search',
            assignment_class=portlets.search.Assignment
        )

        # what does Renderer.portlet_style give us?
        renderer = queryMultiAdapter((self.portal, self.request, self.view, self.manager, portlet), IPortletRenderer)
        self.assertEquals(renderer.portlet_style(), 'noheader')

        # test HTML
        renderer.update()
        self.assertIn('<dl class="portlet portletSearch noheader">', renderer.render())

    def test_portlet_static(self):
        """Test that static-text portlet is patched."""
        # add portlet
        portlet = self._add_portlet(
            name='plone.portlet.static.Static',
            assignment_class=static.Assignment
        )

        # what does Renderer.portlet_style give us?
        renderer = queryMultiAdapter((self.portal, self.request, self.view, self.manager, portlet), IPortletRenderer)
        self.assertEquals(renderer.portlet_style(), 'noheader')

        # test HTML
        renderer.update()
        self.assertIn('<dl class="portlet portletStaticText noheader portlet-static">', renderer.render())

    def test_portlet_collection(self):
        """Test that collection portlet is patched."""
        # add portlet
        portlet = self._add_portlet(
            name='plone.portlet.collection.Collection',
            assignment_class=collection.Assignment
        )

        # what does Renderer.portlet_style give us?
        renderer = queryMultiAdapter((self.portal, self.request, self.view, self.manager, portlet), IPortletRenderer)
        self.assertEquals(renderer.portlet_style(), 'noheader')

        # test HTML
        renderer.update()
        self.assertIn('<dl class="portlet portletCollection noheader portlet-collection-">', renderer.render())

    def test_portlet_quickupload(self):
        """Test that quickupload portlet is patched."""
        from collective.quickupload.portlet.quickuploadportlet import Assignment
        # add portlet
        portlet = self._add_portlet(
            name='collective.quickupload.QuickUploadPortlet',
            assignment_class=Assignment
        )

        # what does Renderer.portlet_style give us?
        renderer = queryMultiAdapter((self.portal, self.request, self.view, self.manager, portlet), IPortletRenderer)
        self.assertEquals(renderer.portlet_style(), 'noheader')

        # test HTML
        renderer.update()
        self.assertIn('<dl class="portlet QuickUploadPortlet noheader">', renderer.render())

    def test_portlet_TagClouds(self):
        """Test that TagClouds portlet is patched."""
        from qi.portlet.TagClouds.tagcloudportlet import Assignment
        # add portlet
        portlet = self._add_portlet(
            name='qi.portlet.TagClouds.TagCloudPortlet',
            assignment_class=Assignment
        )

        # what does Renderer.portlet_style give us?
        renderer = queryMultiAdapter((self.portal, self.request, self.view, self.manager, portlet), IPortletRenderer)
        self.assertEquals(renderer.portlet_style(), 'noheader')

        # test HTML
        renderer.update()
        self.assertIn('<dl class="portlet portletTagCloudPortlet noheader">', renderer.render())


import numpy as np
from scipy.io import loadmat

class Factor():
    def __init__(self, table, condVars, inputVars, givenVars, givenVals, symptomsInit = False, diseasesInit = False, summerInit = False):
        self.table = table
        self.condVars = condVars
        self.inputVars = inputVars
        self.allVars = self.condVars + self.inputVars

        diseaseIndices = [1, 2, 3, 4]
        self.diseasesLeft = [index for index in diseaseIndices if not index in givenVars]

        self.convert_matlab_table()

        if symptomsInit:
            # only keep the dimensions that are not given
            if diseaseIndices[0] in givenVars:
                givenVarIndex = givenVars.index(diseaseIndices[0])
                self.table = self.table[givenVals[givenVarIndex]]
                self.condVars.remove(diseaseIndices[0])
            if diseaseIndices[1] in givenVars:
                givenVarIndex = givenVars.index(diseaseIndices[1])
                self.table = self.table[:, givenVals[givenVarIndex]]
                self.condVars.remove(diseaseIndices[1])
            if diseaseIndices[2] in givenVars:
                givenVarIndex = givenVars.index(diseaseIndices[2])
                self.table = self.table[:, :, givenVals[givenVarIndex]]
                self.condVars.remove(diseaseIndices[2])
            if diseaseIndices[3] in givenVars:
                givenVarIndex = givenVars.index(diseaseIndices[3])
                self.table = self.table[:, :, :, givenVals[givenVarIndex]]
                self.condVars.remove(diseaseIndices[3])
            if inputVars[0] in givenVars:
                givenVarIndex = givenVars.index(inputVars[0])
                self.table = self.table[:, :, :, :, givenVals[givenVarIndex]]
                self.inputVars.remove(inputVars[0])
        elif diseasesInit:
            # only keep the dimensions that are not given
            if 0 in givenVars:
                givenVarIndex = givenVars.index(0)
                self.table = self.table[givenVals[givenVarIndex]]
                self.condVars.remove(0)
            if inputVars[0] in givenVars:
                givenVarIndex = givenVars.index(inputVars[0])
                self.table = self.table[:, givenVals[givenVarIndex]]
                self.inputVars.remove(inputVars[0])
        elif summerInit:
            if 0 in givenVars:
                self.table = np.array([self.table[givenVals[0]]])
                self.condVars.remove(0)

        self.allVars = self.condVars + self.inputVars
        self.table = self.table.squeeze()

    def mult_factor_symptom(self, newFactor):
        messageTable = self.table
        newTable = newFactor.get_table()

        if len(self.table.shape) == len(self.diseasesLeft) and len(newTable.shape) == len(self.diseasesLeft):
            newMessageTable = messageTable
            newVars = self.diseasesLeft
        else:
            newMessageTable = np.stack((messageTable, messageTable), axis = -1) # converts from 2x2x2x2x2 to 2x2x2x2x2x2 (1 more dimension)
            newVars = list(self.diseasesLeft)
            newVars += self.allVars if not len(self.table.shape) == len(self.diseasesLeft) else []
            newVars += newFactor.allVars if not len(newTable.shape) == len(self.diseasesLeft) else []
        newVars = list(set(newVars))

        for i in range(0, int(2**len(newVars))):
            assignments = toBinaryArray(i, len(newVars)) #len(self.diseasesLeft)) # currently storing assignments for x1, x2, x3, x4, and x10
            diseaseAssignments = assignments[0:len(self.diseasesLeft)] # currently storing assignments for x1, x2, x3, x4

            currTable = newTable
            for assignment in diseaseAssignments: # traverse the table to get this combination's assignment
                currTable = currTable[assignment] # newTable[x1][x2][x3][x4]
            newFalseTrueVars = []
            if len(newTable.shape) == len(self.diseasesLeft): # this table is a table with a given variable (e.g. x8), so it doesn't have a true and false column, just a true column (its shape is 2x2x2x2, not 2x2x2x2x2)
                newFalseTrueVars.append(currTable)
                newFalseTrueVars.append(currTable)
            else:
                newFalseTrueVars.append(currTable[0]) # x10 = false
                newFalseTrueVars.append(currTable[1]) # x10 = true

            currNewMessageTable = newMessageTable
            for assignment in assignments[:-2]:
                currNewMessageTable = currNewMessageTable[assignment]
            if len(self.table.shape) == len(self.diseasesLeft):
                currNewMessageTable = currNewMessageTable[assignments[-2]]
                currNewMessageTable[assignments[-1]] *= newFalseTrueVars[0]
            else:
                # TODO: control for the case when we have a 2x2x2x2x1 and a 2x2x2x2x2 table
                # multiplying a 2x2x2x2x2 table by a 2x2x2x2x2 table
                #currNewMessageTable = currNewMessageTable[assignments[-1]]
                #print(i, currNewMessageTable.shape)
                for val in range(0, len(currNewMessageTable)): # is it 1 or 2?
                    currNewMessageTable[val][0] *= newFalseTrueVars[0]
                    currNewMessageTable[val][1] *= newFalseTrueVars[1]

        # handle some logistics
        self.condVars = newVars
        self.inputVars = []
        self.allVars = newVars
        self.table = newMessageTable.squeeze()
        assert(len(self.allVars) == len(self.table.shape))

    def mult_factor_disease(self, newFactor, marginalizedVar):
        newVars = set(self.get_vars()).union(set(newFactor.get_vars())) # combine [0, 4] and [1, 2, 3, 4] into set(0, 1, 2, 3)
        newVars.remove(marginalizedVar)
        newVars = sorted(list(newVars)) # convert from set(0, 1, 2, 3) to [0, 1, 2, 3]

        newFactorTable = np.zeros((2, ) * len(newVars))
        for i in range(0, 2**(len(newVars))): # from 0 to 7 inclusive
            assignments = toBinaryArray(i, len(newVars)) # each variable in this assignment corresponds to the respective variable in newVars
            varAssignments = {}
            for index, assignment in enumerate(assignments):
                varAssignments[newVars[index]] = assignment # place all variable assignments into a collective dict

            marginalizedVarFalseAssignment = dict(varAssignments) # create variable assignment for when the marginalized variable is false
            marginalizedVarTrueAssignment = dict(varAssignments) # create variable assignment for when the marginalized variable is true
            marginalizedVarFalseAssignment[marginalizedVar] = 0
            marginalizedVarTrueAssignment[marginalizedVar] = 1

            newFactorFalse = newFactor.getProb(marginalizedVarFalseAssignment) # disease table probability when marginalized variable is false
            newFactorTrue = newFactor.getProb(marginalizedVarTrueAssignment) # disease table prob when marginalized variable is true
            thisFalse = self.getProb(marginalizedVarFalseAssignment) # messageTable probability when marginalized variable is false
            thisTrue = self.getProb(marginalizedVarTrueAssignment) # messageTable probability when marginalized variable is true

            newProb = newFactorFalse * thisFalse + newFactorTrue * thisTrue # sum over the marginalized variable, and for each summation, there is one multiplication

            # traverse the new factor table and insert this newly calculated probability
            currTable = newFactorTable
            for assignment in assignments[:-1]:
                currTable = currTable[assignment]
            currTable[assignments[-1]] = newProb

        # handle some higher-level logistics
        self.condVars = newVars
        self.inputVars = []
        self.allVars = newVars
        self.table = newFactorTable.squeeze()
        assert(len(self.allVars) == len(self.table.shape))

    def mult_factor_multiple(self, newFactors, marginalizedVar):
        if len(newFactors) == 1: # special case, only happens when the query is P(x0)
            self.condVars = newFactors[0].get_vars()
            self.inputVars = []
            self.allVars = self.condVars
            self.table = newFactors[0].get_table()

        newVars = set(newFactors[0].get_vars())
        for factor in newFactors:
            newVars = newVars.union(factor.get_vars())
        if marginalizedVar in newVars:
            newVars.remove(marginalizedVar)
        newVars = sorted(list(newVars))

        newFactorTable = np.zeros((2, ) * len(newVars))
        for i in range(2**len(newVars)):
            assignments = toBinaryArray(i, len(newVars))
            varAssignments = {}
            for index, assignment in enumerate(assignments):
                varAssignments[newVars[index]] = assignment # place all variable assignments into a collective dict

            marginalizedVarFalseAssignment = dict(varAssignments) # create variable assignment for when the marginalized variable is false
            marginalizedVarTrueAssignment = dict(varAssignments) # create variable assignment for when the marginalized variable is true
            marginalizedVarFalseAssignment[marginalizedVar] = 0
            marginalizedVarTrueAssignment[marginalizedVar] = 1

            newProbFalse = 1.0
            newProbTrue = 1.0
            for factor in newFactors:
                factorFalse = factor.getProb(marginalizedVarFalseAssignment) # disease table probability when marginalized variable is false
                factorTrue = factor.getProb(marginalizedVarTrueAssignment) # disease table prob when marginalized variable is true

                newProbFalse *= factorFalse
                newProbTrue *= factorTrue

            newProb = newProbFalse + newProbTrue # sum over the marginalized variable, and for each summation, there is one multiplication

            # traverse the new factor table and insert this newly calculated probability
            currTable = newFactorTable
            for assignment in assignments[:-1]:
                currTable = currTable[assignment]
            currTable[assignments[-1]] = newProb

        # handle some higher-level logistics
        self.condVars = newVars
        self.inputVars = []
        self.allVars = newVars
        self.table = newFactorTable.squeeze()
        assert(len(self.allVars) == len(self.table.shape))

    def getProb(self, varAssignments):
        if self.table.size == 1:
            return self.table

        assignments = []
        for var in self.allVars: # if vars = [1, 2, 3, 4], then map varAssignments {4: 1, 0: 1, 2: 0, 3: 1, 1: 0} to [0, 0, 1, 1]
            assignments.append(varAssignments[var])

        # iterate over the table and find the probability that matches the corresponding variable assignments
        currTable = self.table
        for assignment in assignments:
            currTable = currTable[assignment]

        return currTable

    def convert_matlab_table(self):
        newTable = np.zeros((2, ) * (len(self.allVars))) # convert the table from 16x2 to 2x2x2x2x2

        if len(self.allVars) == 1: # special case: isSummer table
            newTable[0] = self.table[0]
            newTable[1] = self.table[1]
            self.table = newTable
            return

        for i in range(0, newTable.size): # loop through all the possible 16 states
            assignments = toBinaryArray(i, len(newTable.shape)) # convert from i = 5 to [0, 1, 1]

            currTable = newTable
            for assignment in assignments[:-1]: # traverse to currTable[0][1]
                currTable = currTable[assignment]
            condAssignmentToDecimal = toDecimal(assignments[:-1]) # convert [x1, x2, x3, x4] to the appropriate decimal value
            currTable[assignments[-1]] = self.table[condAssignmentToDecimal][assignments[-1]] # assign currTable[0][1][1] = self.table[5]
        self.table = newTable

    def get_table(self):
        return self.table

    def get_vars(self):
        return self.allVars

    def print_table(self):
        for i in range(0, self.table.size):
            binary = toBinaryArray(i, len(self.table.shape))
            currTable = self.table
            for assignment in binary:
                currTable = currTable[assignment]
            print(binary, currTable)

    def normalize_table(self):
        sum_probs = np.sum(self.table)
        self.table /= sum_probs

def toBinaryArray(number, length = None):
    if length is not None:
        return [int(ch) for ch in list(format(number, 'b').zfill(length)[::-1])] # all elements are ints e.g. [1, 0, 1, 0, 0, 0, 0, 0] for int(5) -- LSB is at index 0
    else:
        return [int(ch) for ch in list(format(number, 'b')[::-1])]

def toDecimal(bitArray):
    val = 0
    for index, bit in enumerate(bitArray):
        val += bit * (2**index)
    return int(val)

assignments = np.zeros((12, 1))
givens = [] # user input -- the nodes that are given
givenVals = [] # user input -- binary values, the assignments of the nodes in the givens list
queries = [] # user input -- the nodes we are querying
which_query = 1
if which_query == 1:
    givens = [8, 11]
    givenVals = [1, 1]
    queries = [1]
elif which_query == 2:
    givens = [4]
    givenVals = [1]
    queries = [7, 8, 9, 10, 11]
elif which_query == 3:
    givens = [0]
    givenVals = [1]
    queries = [10]
diseasesIndices = [1, 2, 3, 4]
for g in givens:
    assignments[g] = 1
data = loadmat("q8_vars.mat")
symptoms = data["symptoms"]
diseases = data["diseases"]
summerTable = data["summer_probs"]

variablesLeft = [1, 2, 3, 4]
messageTable = None

remainingFactors = []

# combine the symptoms tables
for i in range(5, 12): # 5 to 11 inclusive
    if not i in givens + queries: # this symptom will be marginalized out, so skip this step
        continue

    newFactor = Factor(symptoms[i-5], condVars = list(diseasesIndices), inputVars = [i], givenVars = givens, givenVals = givenVals, symptomsInit = True)

    if messageTable is None: # initialize messageTable
        messageTable = newFactor
        continue # go to next iteration/factor

    messageTable.mult_factor_symptom(newFactor)

# combine the diseases tables
for i in range(4, 0, -1):
    newFactor = Factor(diseases[i-1], condVars = [0], inputVars = [i], givenVars = givens, givenVals = givenVals, diseasesInit = True)

    if i in queries + givens:
        remainingFactors.append(newFactor)
        continue

    if messageTable is None: # in the off chance we marginalized away all the symptoms, then the message table will begin as a disease table
        messageTable = newFactor
        continue

    messageTable.mult_factor_disease(newFactor, i)

# combine the isSummer node
for i in [0]:
    newFactor = Factor(summerTable, condVars = [0], inputVars = [], givenVars = givens, givenVals = givenVals, summerInit = True)
    remainingFactors.append(newFactor)

    if messageTable is None:
        messageTable = newFactor # really weird scenario where no variables are given, so they're all marginalized out and all we get is P(x0)
        continue

remainingFactors.append(messageTable)
messageTable.mult_factor_multiple(remainingFactors, 0) # marginalize over 0

messageTable.normalize_table()
print("{} <-- variables in order".format(messageTable.get_vars()))
messageTable.print_table()
print("Sum:", np.sum(messageTable.table))


import requests
from bs4 import BeautifulSoup

def scrape_weather():
    print("[오늘의 날씨]")
    url="https://www.weather.go.kr/w/index.do#"
    res = requests.get(url)
    #res.raise_for_status()
    soup=BeautifulSoup(res.text,"lxml")
    rain_rate = soup.find("span",attrs={"class":"val"})

    print(rain_rate)

scrape_weather() #오늘의 날씨 정보 가져오기


# -*- coding: utf-8 -*-
# Created on Mon Jul  4 09:27:32 2022
# @author: Ajit Johnson Nirmal
# Drop provided markers or cells from anndata object including the raw matrix

"""
!!! abstract "Short Description"
    `sm.hl.dropFeatures`:  A handy function that allows users to susbet the anndata object.

    The function can be used to drop markers, cells, columns in metadata, groups of cells
    belonging to a certain category.

## Function
"""

import numpy as np
import anndata as ad

def dropFeatures (adata, drop_markers=None, drop_cells=None,
                  drop_meta_columns=None,
                  drop_groups=None, groups_column=None,
                  subset_raw=True):
    """
Parameters

    adata : AnnData Object

    drop_markers (list):
        Provide a list of markers to drop. The default is None.

    drop_cells (list):
        Provide a list of cells (index name) to drop. The default is None.

    drop_meta_columns (list):
        Provide a list of column names in `adata.obs` to drop. The default is None.

    drop_groups (list):
        Provide a list of categorical names to drop.
        Works in conjunction with `groups_column`. The default is None.

    groups_column (str):
        Pass the column name of the column that contains the categories passed to
        `drop_groups`. The default is None.

    subset_raw (bool):
        Generally any subsetting of `AnnData` object does not affect the raw data
        stored in `adata.raw`. Pass `True` to apply the same transformations to
        `adata.raw` as well. The default is True.

Returns

    adata : Modified `adata` object

Example

```python

# Drop certain genes
drop_markers = ['ELANE', 'CD57']
adata = sm.hl.dropFeatures (adata, drop_markers=drop_markers)

# Drop a few cells
drop_cells = ['unmicst-exemplar-001_cell_1', 'unmicst-exemplar-001_cell_2','unmicst-exemplar-001_cell_3']
adata = sm.hl.dropFeatures (adata, drop_cells=drop_cells)

# Drop a few columns from `adata.obs`
drop_meta_columns = ['ROI', 'shapes']
adata = sm.hl.dropFeatures (adata, drop_meta_columns=drop_meta_columns)

# Drop two cell-types from the 'phenotype' column
drop_groups = ['Unknown', 'Treg']
adata = sm.hl.dropFeatures (adata, drop_groups=drop_groups, groups_column = 'phenotype')

```
    """

    # Drop Markers
    if drop_markers is not None:
        if isinstance(drop_markers, str):
            drop_markers = [drop_markers]
        # find the index of the given markers
        idx_markers = [adata.var.index.get_loc(x) for x in drop_markers]
        # remove from adata
        keep_markes = list(set(adata.var.index).difference(drop_markers))
        adata = adata[:, keep_markes]
        # remove from raw
        if subset_raw is True:
            raw = np.delete(adata.raw.X, idx_markers, axis=1)
            del adata.raw
            adata.raw = ad.AnnData (raw)

    # Drop cells
    if drop_cells is not None:
        if isinstance(drop_cells, str):
            drop_cells = [drop_cells]
        # find the index of the given markers
        idx_markers = [adata.obs.index.get_loc(x) for x in drop_cells]
        # remove from adata
        keep_markes = list(set(adata.obs.index).difference(drop_cells))
        adata = adata[keep_markes, :]
        # remove from raw
        if subset_raw is True:
            raw = np.delete(adata.raw.X, idx_markers, axis=1)
            del adata.raw
            adata.raw = ad.AnnData (raw)

    # Drop meta columns
    if drop_meta_columns is not None:
        if isinstance(drop_meta_columns, str):
            drop_meta_columns = [drop_meta_columns]
        # remove from adata
        adata.obs = adata.obs.drop(drop_meta_columns, axis=1)

    # Drop specific categories of cells
    if drop_groups is not None:
        if isinstance(drop_groups, str):
            drop_groups = [drop_groups]
        if isinstance(groups_column, list):
            groups_column = groups_column[0]
        # find the index of the given markers
        idx = adata[adata.obs[groups_column].isin(drop_groups)].obs.index
        idx_markers = [adata.obs.index.get_loc(x) for x in idx]
        # remove from raw
        if subset_raw is True:
            raw = np.delete(adata.raw.X, idx_markers, axis=0)
        # remove from adata
        adata = adata[~adata.obs[groups_column].isin(drop_groups)]
        # return adata raw
        if subset_raw is True:
            del adata.raw
            adata.raw = ad.AnnData (raw)

    # return
    return adata


import cv2
import numpy as np

cap = cv2.VideoCapture(0)

while(True):

    #Read frames from the camera
    _,frame = cap.read()

    #Split the color channels
    b,g,r = cv2.split(frame)

    #Equalise each color channel
    b_equ = cv2.equalizeHist(b)
    g_equ = cv2.equalizeHist(g)
    r_equ = cv2.equalizeHist(r)

    #Merge the color channels
    equ = cv2.merge((b_equ,g_equ,r_equ))

    #Stack the images side-by-side
    res = np.hstack((frame,equ))

    #Display the image
    cv2.imshow('Result',res)

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

cap.release()
cv2.destroyAllWindows()