# Training Decission Tree for Classification
import streamlit as st
from sklearn.tree import DecisionTreeClassifier
from sklearn import metrics
from sklearn.metrics import classification_report
from sklearn.neural_network import MLPClassifier
from sklearn.preprocessing import StandardScaler
# from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import LabelEncoder

# Basic preprocessing required for all the models.
def preprocessing(df):
	# Assign X and y
	X = df.iloc[:, [0, 3, 5]].values
	y = df.iloc[:, -1].values

	# X and y has Categorical data hence needs Encoding
	le = LabelEncoder()
	y = le.fit_transform(y.flatten())

	# 1. Splitting X,y into Train & Test
	X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.20, random_state=0)
	return X_train, X_test, y_train, y_test, le

@st.cache_resource(experimental_allow_widgets=True)
def decisionTree(X_train, X_test, y_train, y_test):
	# Train the model
	tree = DecisionTreeClassifier(max_leaf_nodes=3, random_state=0)
	tree.fit(X_train, y_train)
	y_pred = tree.predict(X_test)
	score = metrics.accuracy_score(y_test, y_pred) * 100
	report = classification_report(y_test, y_pred)

	return score, report, tree

# Training Neural Network for Classification.
@st.cache_resource(experimental_allow_widgets=True)
def neuralNet(X_train, X_test, y_train, y_test):
	# Scalling the data before feeding it to the Neural Network.
	scaler = StandardScaler()
	scaler.fit(X_train)
	X_train = scaler.transform(X_train)
	X_test = scaler.transform(X_test)
	# Instantiate the Classifier and fit the model.
	clf = MLPClassifier(solver='lbfgs', alpha=1e-5, hidden_layer_sizes=(5, 2), random_state=1)
	clf.fit(X_train, y_train)
	y_pred = clf.predict(X_test)
	score1 = metrics.accuracy_score(y_test, y_pred) * 100
	report = classification_report(y_test, y_pred)

	return score1, report, clf

# # Training KNN Classifier
# @st.cache_resource(experimental_allow_widgets=True)
# def Knn_Classifier(X_train, X_test, y_train, y_test):
# 	clf = KNeighborsClassifier(n_neighbors=5)
# 	clf.fit(X_train, y_train)
# 	y_pred = clf.predict(X_test)
# 	score = metrics.accuracy_score(y_test, y_pred) * 100
# 	report = classification_report(y_test, y_pred)

# 	return score, report, clf


#!/usr/bin/python
# -*- coding: utf-8 -*-

"""
ZetCode PyQt4 tutorial

This program shows a confirmation
message box when we click on the close
button of the application window.

author: Jan Bodnar
website: zetcode.com
last edited: October 2011
"""

import sys
from PyQt4 import QtGui

class Example(QtGui.QWidget):

    def __init__(self):
        super(Example, self).__init__()

        self.initUI()

    def initUI(self):

        self.setGeometry(300, 300, 250, 150)
        self.setWindowTitle('Message box')
        self.show()

    def closeEvent(self, event):

        reply = QtGui.QMessageBox.question(self, 'Message',
            "Are you sure to quit?", QtGui.QMessageBox.Yes |
            QtGui.QMessageBox.No, QtGui.QMessageBox.No)

        if reply == QtGui.QMessageBox.Yes:
            event.accept()
        else:
            event.ignore()

def main():

    app = QtGui.QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())

if __name__ == '__main__':
    main()


# Create your views here.
from django.contrib.auth.decorators import login_required
from django.contrib.auth.models import User
from django.core.urlresolvers import reverse
from django.db.models import Q
from django.http import HttpResponse, HttpResponseForbidden, HttpResponseRedirect, Http404
from django.shortcuts import get_object_or_404, render_to_response
from django.template import RequestContext
from django.utils.encoding import smart_str
from genenews_main.models import Article, Gene, Sequence, Vote, LeaderboardCache, get_user_score, type_to_date
from genenews_main.forms import SubmissionForm

def index(request):
    articles = Article.objects.all().order_by('-pk')[:25]
    entries = add_votes(request, articles)
    return render_to_response('index.html',{'entries': entries}, context_instance=RequestContext(request))

def leaderboard(request):
    entries = []
    type = request.GET.get('type', 'all')

    if type not in ['all', 'year', 'month', 'day']:
        type = 'all'

    LeaderboardCache.objects.update(type=type) # only temporarily until a cron job can be set up
    for entry in LeaderboardCache.objects.filter(type=type):
        entries.append((entry.score, entry.user, entry.user.article_set.filter(date__gte=type_to_date(type)).count()))
    entries.sort()
    entries.reverse()
    return render_to_response('leaderboard.html', {'entries': entries, 'type': type}, context_instance=RequestContext(request))

@login_required
def submit(request):
    genes = []
    if request.method=="POST":
        form = SubmissionForm(request.POST)
        try:
            genes = [Gene.objects.get(pk=long(gene_id)) for gene_id in request.POST.getlist('gene')]
        except Gene.DoesNotExist:
            return HttpResponseForbidden()
        if form.is_valid():
            article = form.save(commit=False)
            article.user = request.user
            article.save()
            map(lambda g: article.genes.add(g), genes)
            article.save()
            v = Vote(article=article, user=request.user, vote=1)
            v.save()
            return HttpResponseRedirect(reverse('article', args=[article.id]))
    else:
        form = SubmissionForm()
    return render_to_response('submit.html', {'form': form, 'genes': genes}, context_instance=RequestContext(request))

@login_required
def gene_autocomplete(request):
    if request.method == "GET":
        if not request.GET.has_key('q') or not request.GET.has_key('limit'):
            return HttpResponseForbidden()
        try:
            int(request.GET.get('limit'))
        except ValueError:
            return HttpResponseForbidden()
        qtemp = Q(name__icontains=request.GET.get('q'))
        genes = Gene.objects.filter(qtemp)[:request.GET.get('limit', 10)]
        tempstr = '['
        for index, m in enumerate(genes):
            temp = {}
            temp['id'] = smart_str(m.id)
            temp['name'] = smart_str(m.medname())
            if index > 0:
                tempstr += ','
            tempstr += str(temp)
        tempstr += ']'
        return HttpResponse(tempstr, mimetype="application/json")
    resp = HttpResponse()
    resp.status_code = 405
    return resp

def gene_page(request, gene_name):
    genes = Gene.objects.filter(name=gene_name)
    if not genes.exists():
        raise Http404
    gene = genes[0] # just get the first gene that comes up

    articles = gene.article_set.all()
    entries = add_votes(request, articles)
    seq = gene.sequence
    return render_to_response('gene_page.html', {'gene': gene, 'entries': entries, 'seq':seq}, context_instance=RequestContext(request))

def add_votes(request, articles):
    if request.user.is_anonymous():
        return [(article, None) for article in articles]

    else:
        out = []
        for article in articles:
            if article.vote_set.filter(user=request.user).exists():
                out.append((article, article.vote_set.get(user=request.user)))
            else:
                out.append((article, None))

        return out


import pandas as pd
from NaiveBayesQuestionClassifier import NBFunctions
from sklearn.feature_extraction.text import CountVectorizer
from nltk.tokenize import word_tokenize

print("Reading Training data ... ")
questionFile = pd.read_csv("data/filtratedTrainingQuestions.csv")

# --> Helpers
# print(questionFile.iloc[0])
# print(questionFile.loc[:,'Category'])
# print(questionFile.loc[questionFile.Category == "Logic"])
# questionFile['test']='success' # assigning to the table
# <-- End.

def wordProbability(wordList, countList):
    probWords = []
    for eachWord, count in zip(wordList, countList):
        probWords.append(count/len(wordList))
    return(dict(zip(wordList, probWords)))

print("Training NB algo")
questionDocs = questionFile.loc[:,'Question']
vectorizer = CountVectorizer()
X = vectorizer.fit_transform(questionDocs)
totalFeatures = len(vectorizer.get_feature_names())

# # --> CountVectorizer for logic questions
logicDocs = questionFile.loc[questionFile.Category == "Logic",'Question']
logicVectorizer = CountVectorizer()
X_logic = logicVectorizer.fit_transform(logicDocs)
word_list_logic = logicVectorizer.get_feature_names();
count_list_logic = X_logic.toarray().sum(axis=0)
freqLogic = dict(zip(word_list_logic,count_list_logic))
logicWordsProb = wordProbability(word_list_logic, count_list_logic)
totalCntLogic = count_list_logic.sum(axis=0)
# print(logicWordsProb)
# # --> End.

# # --> CountVectorizer for fraction questions
fractionDocs = questionFile.loc[questionFile.Category == "Fractions",'Question']
fractionVectorizer = CountVectorizer()
X_fraction = fractionVectorizer.fit_transform(fractionDocs)
word_list_fraction = fractionVectorizer.get_feature_names();
count_list_fraction = X_fraction.toarray().sum(axis=0)
freqFraction = dict(zip(word_list_fraction,count_list_fraction))
fractionWordsProb = wordProbability(word_list_fraction, count_list_fraction)
totalCntFraction = count_list_fraction.sum(axis=0)
# print(fractionWordsProb)
# # --> End.

# # --> CountVectorizer for algebra questions
algebraDocs = questionFile.loc[questionFile.Category == "Algebra",'Question']
algebraVectorizer = CountVectorizer()
X_algebra = algebraVectorizer.fit_transform(algebraDocs)
wordListAlgebra = algebraVectorizer.get_feature_names();
countListAlgebra = X_algebra.toarray().sum(axis=0)
freqAlgebra = dict(zip(wordListAlgebra,countListAlgebra))
algebraWordsProb = wordProbability(wordListAlgebra, countListAlgebra)
totalCntAlgebra = countListAlgebra.sum(axis=0)
# # --> End.

# # --> CountVectorizer for comparison questions
comparisonDocs = questionFile.loc[questionFile.Category == "Comparisons",'Question']
comparisonVectorizer = CountVectorizer()
X_comparison = comparisonVectorizer.fit_transform(comparisonDocs)
wordListComparison = comparisonVectorizer.get_feature_names();
countListComparison = X_comparison.toarray().sum(axis=0)
freqComparison = dict(zip(wordListComparison,countListComparison))
comparisonWordsProb = wordProbability(wordListComparison, countListComparison)
totalCntComparison = countListComparison.sum(axis=0)
# # --> End.

# --> CountVectorizer for percentage questions
percentageDocs = questionFile.loc[questionFile.Category == "Percentages",'Question']
# print(percentageDocs)
percentageVectorizer = CountVectorizer()
X_percentage = percentageVectorizer.fit_transform(percentageDocs)
wordListPercentage = percentageVectorizer.get_feature_names();
countListPercentage = X_percentage.toarray().sum(axis=0)
freqPercentage = dict(zip(wordListPercentage,countListPercentage))
percentageWordsProb = wordProbability(wordListPercentage, countListPercentage)
totalCntPercentage = countListPercentage.sum(axis=0)
# --> End.

# # --> CountVectorizer for probability questions
probabilityDocs = questionFile.loc[questionFile.Category == "Probability",'Question']
probabilityVectorizer = CountVectorizer()
X_probability = probabilityVectorizer.fit_transform(probabilityDocs)
wordListProbability = probabilityVectorizer.get_feature_names();
countListProbability = X_probability.toarray().sum(axis=0)
freqProbability = dict(zip(wordListProbability,countListProbability))
probabilityWordsProb = wordProbability(wordListProbability, countListProbability)
totalCntProbability = countListProbability.sum(axis=0)
# # --> End.

# --> CountVectorizer for general knowledge questions
gkDocs = questionFile.loc[questionFile.Category == "General Knowledge",'Question']
gkVectorizer = CountVectorizer()
X_gk = gkVectorizer.fit_transform(gkDocs)
wordListGk = gkVectorizer.get_feature_names()
countListGk = X_gk.toarray().sum(axis=0)
freqGk = dict(zip(wordListGk,countListGk))
gkWordsProb = wordProbability(wordListGk, countListGk)
totalCntGk = countListGk.sum(axis=0)
# --> End.

# <-- Naive Bayes Function
categoryList = ['Logic','Fraction','Algebra','Comparison','Percentage','Probability','Gk']

def calcProbability(question):
    """
    Function to calcuate probability of question being in a certain category
    :param question: question to calculate probability of
    :return: maxProbCategory category with the highest probability.
    """
    # print("Classifying Question:",question)
    question = NBFunctions.stopWordRemoval(question)
    wordList = word_tokenize(question)
    wordProbabilities = []
    for eachCategory in categoryList:
        if eachCategory == "Logic":
            probWordInCategory = NBFunctions.bayesWordProb(wordList, freqLogic, totalCntLogic, totalFeatures)
        elif eachCategory == "Fraction":
            probWordInCategory = NBFunctions.bayesWordProb(wordList, freqFraction, totalCntFraction, totalFeatures)
        elif eachCategory == "Algebra":
            probWordInCategory = NBFunctions.bayesWordProb(wordList, freqAlgebra, totalCntAlgebra, totalFeatures)
        elif eachCategory == "Comparison":
            probWordInCategory = NBFunctions.bayesWordProb(wordList, freqComparison, totalCntComparison, totalFeatures)
        elif eachCategory == "Percentage":
            probWordInCategory = NBFunctions.bayesWordProb(wordList, freqPercentage, totalCntPercentage, totalFeatures)
        elif eachCategory == "Probability":
            probWordInCategory = NBFunctions.bayesWordProb(wordList, freqProbability, totalCntProbability, totalFeatures)
        elif eachCategory=="Gk":
            probWordInCategory = NBFunctions.bayesWordProb(wordList, freqGk, totalCntGk, totalFeatures)
        wordProbabilities.append(probWordInCategory)

    probabilityMap = {}
    probabilityMap = NBFunctions.probProduct(categoryList, wordProbabilities, probabilityMap)
    maxProbCategory = max(probabilityMap, key=probabilityMap.get)
    return (maxProbCategory)
# --> End.
trialQuestion = "Write the next term of the series below: 1, 1, 2, 4, 3, 9, 4 _ _ _"
print(calcProbability(trialQuestion))
# wordList = word_tokenize(question)R
# NBFunctions.bayesWordProb(wordList,freqGk, totalCntGk,totalFeatures)
# NBFunctions.bayesWordProb(wordList,freqLogic, totalCntGk,totalFeatures)


import datetime
import random
import string
import itertools
import os
import requests
import time
import json
from .managerapi import ManagerApi
from .blobserverapi import BlobServerApi
from .url import join_url, parse_url
from .errors import BIMcloudBlobServerError, BIMcloudManagerError
import uuid

CHARS = list(itertools.chain(string.ascii_lowercase, string.digits))
PROJECT_ROOT = 'Project Root'
PROJECT_ROOT_ID = 'projectRoot'

class Workflow:
	def __init__(self, manager_url, client_id):
		self._manager_api = ManagerApi(manager_url)

		self.client_id = client_id
		self.username= None

		self._auth_context = None

		self._root_dir_name = Workflow.to_unique('DEMO_RootDir')
		self._sub_dir_name = Workflow.to_unique('DEMO_SubDir')
		self._root_dir_data = None
		self._sub_dir_data = None
		self._inner_dir_path = None
		self._model_server_urls = {}
		self._blob_server_sessions = {}

		# Changeset polling starts on revision 0
		self._next_revision_for_sync = 0

	def run(self):
		# WORKFLOW BEGIN
		self.login_sso()
		try:
			self.create_dirs()
			self.upload_files()
			self.rename_file()
			self.move_file()
			self.locate_download_and_delete_files()
			self.create_directory_tree_and_delete_recursively()
		finally:
			self.logout()
		# WORKFLOW END

	def login_sso(self):
		print('Logging in ...')
		state = uuid.uuid4()
		self._manager_api.open_authorization_page(self.client_id, state)
		time.sleep(0.2)

		authorization_code = None
		for i in range(300):
			result = self._manager_api.get_authorization_code_by_state(state)
			print (result)
			if result[0] == 'succeeded':
				authorization_code = result[1]
				break
			elif result[0] == 'pending':
				print('Waiting for login ...')
				time.sleep(1)

		if authorization_code is None:
			print('Login failed')
			quit(1)

		print('Exchanging authorization code for access & refresh token')
		self._auth_context = self._manager_api.get_token_by_authorization_code_grant(authorization_code, self.client_id)
		print(f'Received token type is "{self._auth_context.token_type}"')
		print(f'Access token is going to expire at {Workflow.convert_timestamp(self._auth_context.access_token_exp)}')
		print('Logged in.')

		self.username = self._manager_api.get_user(self._auth_context, self._auth_context.user_id)['username']

	def create_dirs(self):
		print('Creating directories ...')
		self._root_dir_data = self.get_or_create_dir(self._root_dir_name)
		self._sub_dir_data = self.get_or_create_dir(self._sub_dir_name, self._root_dir_data)
		print('Directories created.')

	def upload_files(self):
		print('Uploading files ...')

		self.upload_file(self._root_dir_data['$path'], 'pic1.jpg')
		self.upload_file(self._sub_dir_data['$path'], 'text1.txt')
		self.upload_file(self._sub_dir_data['$path'], 'text2.txt')

		# Addign a new version of an already existsing file.
		# You can find file versions on Manager's UI.
		self.upload_file(self._sub_dir_data['$path'], 'text2.1.txt', 'text2.txt')

		# We can even upload files to non-existsing paths,
		# required directories will get createad.
		self._inner_dir_path = join_url(self._sub_dir_data['$path'], self.to_unique('foo'), self.to_unique('bar'))
		self.upload_file(self._inner_dir_path, 'pic2.jpg')

		self.wait_for_blob_changes()

		print('\nFiles uploaded.')

	def upload_file(self, path, name, alias=None):
		if not alias:
			alias = name
		file_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', 'blobs', name))
		description = f'\nUploading file "{file_path}" to "{path}/{alias}" ...'
		print(description)

		data = None
		with open(file_path, 'rb') as f: data = f.read()

		# To know to which File Server we should upload the file,
		# we should get the setting.
		immediate_parent_dir = self.find_immediate_parent_dir(path)
		immediate_parent_path = immediate_parent_dir['$path']
		print(f'Immediate existing parent directory: "{immediate_parent_path}".')

		configured_blob_server_id = \
			self._manager_api.get_inherited_default_blob_server_id(
				self._auth_context,
				immediate_parent_dir['id'])

		# Blob Server is a role of a Model Server, basically they are the same thing:
		model_server = self._manager_api.get_resource_by_id(self._auth_context, configured_blob_server_id)
		model_server_name = model_server['name']
		print(f'Configured host Blob Server: "{ model_server_name }".')

		def do_upload(blob_server_session_id: str, blob_server_api: BlobServerApi):
			print('Uploading data ...')

			# For more efficient uploads, we could use one batch for many upload operations,
			# and commit them together.
			# But for the sake of simplicity, we open a batch for every upload for now.
			batch = blob_server_api.begin_batch_upload(blob_server_session_id, description)

			# We should extract the manager side mandatory "Project Root" prefix:
			blob_server_file_path = self.create_blob_server_path(path, alias)

			upload = blob_server_api.begin_upload(blob_server_session_id, blob_server_file_path, batch['namespace-name'])

			# It is advised to upload large content in chunks.
			CHUNK_SIZE = 1024 * 40 # NOTE: We use 40Kb for the DEMO but in real life it should be around several megabytes!
			offset = 0
			while offset < len(data):
				chunk = data[offset:offset + CHUNK_SIZE]
				blob_server_api.put_blob_content_part(blob_server_session_id, upload['id'], chunk, offset=offset)
				offset += CHUNK_SIZE

			blob_server_api.commit_upload(blob_server_session_id, upload['id'])
			blob_server_api.commit_batch_upload(blob_server_session_id, batch['id'])

			print(f'File uploaded as "{blob_server_file_path}".')

		self.run_with_blob_server_session(model_server, do_upload)

	def rename_file(self):
		print('\nRenaming a file ...')

		text1_blob_path = join_url(self._sub_dir_data['$path'], 'text1.txt')
		text1_blob = self._manager_api.get_resource(self._auth_context, text1_blob_path)

		update_body = {
			# Update body should contains the identifier.
			'id': text1_blob['id'],
			# And to-be-updated properties with their new values.
			# Please note properties with names starting with '$' cannot get updated from client side, they are read only. (Like $parentId, $path, etc.)
			'name': 'text1_rename.txt'
		}

		self._manager_api.update_blob(self._auth_context, update_body)

		self.wait_for_blob_changes()

	def move_file(self):
		print('\nMoving a file (updating parent path) ...')

		text2_blob_path = join_url(self._sub_dir_data['$path'], 'text2.txt')
		text2_blob = self._manager_api.get_resource(self._auth_context, text2_blob_path)

		body = {
			# aka.: move file to its parent's parent directory.
			'parentPath': self._root_dir_data['$path']
		}

		self._manager_api.update_blob_parent(self._auth_context, text2_blob['id'], body)

		self.wait_for_blob_changes()

	def locate_download_and_delete_files(self):
		self.locate_download_and_delete_files_in(self._root_dir_data, True)

	def locate_download_and_delete_files_in(self, directory, get_changes=False):
		directory_id = directory['id']
		directory_path = directory['$path']

		print(f'\nGetting content of directory "{directory_path}".')

		# To look up content of a directory, we get all resources
		# which have parents set as the directory.

		criterion = { '$eq': { '$parentId': directory_id } }

		# All query APIs have default result limit of 1000 items,
		# so you should get contents of directories by using pagination.
		limit = 100 # Keep it reasonably small.
		options = {
			'sort-by': 'name',
			'skip': 0,
			'limit': limit
		}
		all_content = []
		while True:
			content = self._manager_api.get_resources_by_criterion(self._auth_context, criterion, options)
			all_content.extend(content)
			if len(content) < limit:
				break
			options['skip'] += limit

		if not all_content:
			print('Directory has no content.')
			return

		print(f'Directory has {len(all_content)} resources.')

		# Type of directory is 'resourceGroup' in BIMcloud.
		for subdir in filter(lambda i: i['type'] == 'resourceGroup', all_content):
			self.locate_download_and_delete_files_in(subdir)

		# Type of file is 'blob' in BIMcloud.
		for blob in filter(lambda i: i['type'] == 'blob', all_content):
			self.download_and_delete_file(blob)

		if get_changes:
			self.wait_for_blob_changes()

		# We do this at last, because non-empty directories cannot get deleted (easily).
		self._manager_api.delete_resource_group(self._auth_context, directory_id)
		print(f'\nDirectory "{directory_path}" deleted.')

	def create_directory_tree_and_delete_recursively(self):
		print('Creating and deleting a directory subtree.')

		# Creating example directory tree structure:
		# example_root
		# L example_sub1
		#  L example_sub1_sub1
		#  L example_sub1_sub2
		# L example_sub2
		#  L example_sub2_sub1
		#  L example_sub2_sub2
		example_root_dir = self.get_or_create_dir(Workflow.to_unique('example_root'))
		example_sub1_dir = self.get_or_create_dir(Workflow.to_unique('example_sub1'), example_root_dir)
		example_sub2_dir = self.get_or_create_dir(Workflow.to_unique('example_sub2'), example_root_dir)
		self.get_or_create_dir(Workflow.to_unique('example_sub1_sub1'), example_sub1_dir)
		self.get_or_create_dir(Workflow.to_unique('example_sub1_sub2'), example_sub1_dir)
		self.get_or_create_dir(Workflow.to_unique('example_sub2_sub1'), example_sub2_dir)
		self.get_or_create_dir(Workflow.to_unique('example_sub2_sub2'), example_sub2_dir)

		print(f'Example directory subtree created in {example_root_dir["name"]}.')

		# We can delete directorys with their entire content recursively by using delete-resources-by-id-list API.
		# The API is asynchronous which means the directory won't get deleted as soon as the API call get finished.
		# The result of the API is a job that we can poll to get result of the ongoing delete operation.

		print(f'\nStartig job to delete {example_root_dir["name"]} recusively.')

		job = self._manager_api.delete_resources_by_id_list(self._auth_context, [example_root_dir['id']])

		print(f'Job has been started. Id: {job["id"]}, type: {job["jobType"]}.')
		print('\nWaiting to job get completed.')
		while job['status'] != 'completed' and job['status'] != 'failed':
			print(f'Job stauts is {job["status"]}, polling ...')
			time.sleep(0.1)
			job = self._manager_api.get_job(self._auth_context, job['id'])

		if job['status'] == 'completed':
			print('Job has been completed successfully.')
			print(f'Result code: {job["resultCode"]}')
			print('Progress:')
			print(json.dumps(job['progress'], sort_keys=False, indent=4))
		else:
			assert job['status'] == 'failed'
			print(f'Job has been falied. Erro code: {job["resultCode"]}, error message: {job["result"]}.')

	def download_and_delete_file(self, blob):
		blob_id = blob['id']
		blob_path = blob['$path']

		blob_model_server_id = blob['modelServerId']
		blob_model_server = self._manager_api.get_resource_by_id(self._auth_context, blob_model_server_id)

		def download(blob_server_session_id, blob_server_api):
			print(f'\nDownloading "{blob_path}".')
			stream = blob_server_api.get_blob_content(blob_server_session_id, blob_id)
			first_byte = None
			last_byte = None
			size = 0
			for chunk in stream.iter_content(chunk_size=8192):
				if chunk:
					size += len(chunk)
					if not first_byte:
						first_byte = chunk[0]
					last_byte = chunk[-1]
			print(f'Downloaded {size} bytes. First byte: {first_byte}, last byte: {last_byte}.')

		self.run_with_blob_server_session(blob_model_server, download)

		self._manager_api.delete_blob(self._auth_context, blob_id)
		print(f'\nBlob "{blob_path}" deleted.')

	def run_with_blob_server_session(self, model_server, fn):
		blob_server_session_id, blob_server_api = self._blob_server_sessions.get(model_server['id'], (None, None))
		if blob_server_session_id is None:
			# There could be Many Model Server urls configured,
			# to be able to accessed from different network locations.
			# We should pick that one that we can access.
			model_server_url = self.find_working_model_server_url(model_server)
			blob_server_api = BlobServerApi(model_server_url)

			# Ticket is an authentication token for Model (Blob) Server.
			ticket = self._manager_api.get_ticket(self._auth_context, model_server['id'])

			blob_server_session_id = blob_server_api.create_session(self.username, ticket)

			self._blob_server_sessions[model_server['id']] = (blob_server_session_id, blob_server_api)

		try:
			return fn(blob_server_session_id, blob_server_api)
		except BIMcloudBlobServerError as err:
			if err.code == 4 or err.code == 11:
				# Session or ticket expired, drop:
				del self._blob_server_sessions[model_server['id']]
				# Retry:
				return self.run_with_blob_server_session(model_server, fn)
			raise err

	def find_working_model_server_url(self, model_server):
		# We should cache this, because it's static and takes too long to determine:
		result_url = self._model_server_urls.get(model_server['id'])
		if result_url is not None:
			return result_url

		possible_urls = model_server['connectionUrls']
		assert isinstance(possible_urls, list), '"possible_urls" is not a list.'
		parsed_manager_url = parse_url(self._manager_api.manager_url)
		manager_hostname = parsed_manager_url.hostname
		manager_protocol = parsed_manager_url.scheme + ':'

		# Order is important here, urls on top are most likely accessible.
		for url in possible_urls:
			url = url.replace('$protocol', manager_protocol)
			url = url.replace('$hostname', manager_hostname)
			try:
				response = requests.get(join_url(url, 'application-server-service/get-runtime-id'))
				if response.ok:
					self._model_server_urls[model_server['id']] = url
					return url
			except:
				pass
		model_server_name = model_server['name']
		raise RuntimeError(f'Model Server "{model_server_name}" is unreachable.')

	def find_immediate_parent_dir(self, path):
		# We should find the immediate existing (parent) directory of an arbitrary path.
		dir_data = self._manager_api.get_resource(self._auth_context, by_path=path, try_get=True)
		if dir_data is None or dir_data['type'] != 'resourceGroup':
			idx = path.rindex('/')
			return self.find_immediate_parent_dir(path[0:idx])
		return dir_data

	def get_or_create_dir(self, name, parent=None):
		path_of_dir = name if parent is None else join_url(parent['$path'], name)
		path_of_dir = self.ensure_root(path_of_dir)

		print(f'Getting directory "{path_of_dir}" ...')
		dir_data = self._manager_api.get_resource(self._auth_context, by_path=path_of_dir)

		if dir_data is not None:
			print('Directory exists.')
			return dir_data

		print('Directory doesn\'t exist, creating ...')

		dir_id = self._manager_api.create_resource_group(
			self._auth_context,
			name,
			parent['id'] if parent is not None else PROJECT_ROOT_ID)

		dir_data = self._manager_api.get_resource(self._auth_context, by_id=dir_id)

		dir_path = dir_data['$path']
		assert dir_path == path_of_dir, 'Resource created on a wrong path.'

		print('Directory created.')

		return dir_data

	def logout(self):
		# Since access tokens are decentralized, manager API is lack of logout methods
		for server_id in self._blob_server_sessions:
			session_id, api = self._blob_server_sessions[server_id]
			api.close_session(session_id)
		self._blob_server_sessions = {}
		self._auth_context = None
		self._model_server_urls = {}

	def wait_for_blob_changes(self):
		# It migth take a couple of seconds until the next changeset appears.
		for i in range(10):
			if self.get_blob_changes(str(i + 1)):
				break
			time.sleep(3)

	def get_blob_changes(self, attempt):
		# Blob Server side changes are accessible for helping synchronization scenarios.
		# We support a simple polling mechanism for that, by utilizing the get-blob-changes-for-sync API.
		# Changesets are separated by revisions, and synchronization always start at revision 0.
		# Revision 0 is a special case, it gives all content in the given directory in its result's "created" array field.
		# After revision 0 the next set of changes are are accessible by using the last knonw changeset's "endRevision" value in the request's "fromRevison" parameter.
		curr_revision = self._next_revision_for_sync
		try:
			path = self._root_dir_data['$path']
			print(f'\nAttempt #{attempt}: Getting changes after revision {curr_revision} from: "{path}".\n')

			blob_changes = self._manager_api.get_blob_changes_for_sync(self._auth_context, path, None, curr_revision)

			print(json.dumps(blob_changes, sort_keys=False, indent=4))

			self._next_revision_for_sync = blob_changes['endRevision']
		except BIMcloudManagerError as err:
			if err.code == 9:
				# Error code 9 means Revision Obsoleted Error.
				# This happen when the underlying content database has been replaced to another one under the hood,
				# for example after restoring backups.
				# When this happens, synchronization flow should reset, and should get started from revision 0.
				# The first response from revision zero will contain the whole content of the of the directory in the new database in the "created" array field of the API result.
				# The client should use this as a basis of a new synchronization cycle, and should reinitialize its content according the content of the "created" array.
				self._next_revision_for_sync = 0
				return self.get_blob_changes(attempt + ':RESET')
			else:
				raise
		return self._next_revision_for_sync != curr_revision

	@staticmethod
	def create_blob_server_path(manager_dir_path, file_name):
		return join_url(manager_dir_path[len(PROJECT_ROOT):], file_name)

	@staticmethod
	def ensure_root(path):
		# resource paths under Project Root starts with "Project Root".
		return path if path.startswith(PROJECT_ROOT) else join_url(PROJECT_ROOT, path)

	@staticmethod
	def to_unique(name):
		return f'{name}_{random.choice(CHARS)}{random.choice(CHARS)}{random.choice(CHARS)}{random.choice(CHARS)}'

	@staticmethod
	def convert_timestamp(timestamp):
		return datetime.datetime.fromtimestamp(timestamp).strftime("%B %d, %Y %I:%M:%S")


__all__ = ("SkyMapDataIdPacker",)

from lsst.daf.butler import DataIdPacker, DataId

class SkyMapDataIdPacker(DataIdPacker):
    """A `DataIdPacker` for Tract, Patch and optionally AbstractFilter, given
    a SkyMap.

    Parameters
    ----------
    dimensions : `DataIdPackerDimensions`
        Struct containing dimensions related to this `DataIdPacker`.  Must
        have SkyMap as the only given dimension, Tract, Patch, and possibly
        AbstractFilter as the covered dimensions, and all of these as required
        dimensions.
    skymap : `str`
        SkyMap name from `Registry`.
    tractMax : `int`
        Maximum (exclusive) tract index for this skymap.
    patchNxMax : `int`
        Maximum (exclusive) patch index in the x direction.
    patchNyMax : `int`
        Maximum (exclusive) patch index in the y direction.
    """

    SUPPORTED_FILTERS = [None] + list("ugrizyUBGVRIZYJHK")  # split string into single chars
    """AbstractFilter names supported by this packer.

    New filters should be added to the end of the list to maximize
    compatibility with existing IDs.
    """

    @classmethod
    def getIntFromFilter(cls, name):
        """Return an integer that represents the AbstractFilter with the given
        name.
        """
        try:
            return cls.SUPPORTED_FILTERS.index(name)
        except ValueError:
            raise NotImplementedError(f"AbstractFilter '{name}'' not supported by this ID packer.")

    @classmethod
    def getFilterNameFromInt(cls, num):
        """Return an AbstractFilter name from its integer representation.
        """
        return cls.SUPPORTED_FILTERS[num]

    @classmethod
    def getMaxIntForFilters(cls):
        return len(cls.SUPPORTED_FILTERS)

    @classmethod
    def configure(cls, dimensions):
        # Docstring inherited from DataIdPacker.configure
        assert dimensions.given == ["SkyMap"]
        assert dimensions.required.issuperset(["Tract", "Patch"])
        metadata = {"SkyMap": ["tract_max", "patch_nx_max", "patch_ny_max"]}
        kwds = {}
        return metadata, kwds

    def __init__(self, dimensions, skymap, tractMax, patchNxMax, patchNyMax):
        self._skyMapName = skymap
        self._patchMax = patchNxMax*patchNyMax
        self._tractPatchMax = self._patchMax*tractMax
        if "AbstractFilter" in dimensions.required:
            self._filterMax = self.getMaxIntForFilters()
        else:
            self._filterMax = None

    @property
    def maxBits(self):
        # Docstring inherited from DataIdPacker.maxBits
        packedMax = self._tractPatchMax
        if self._filterMax is not None:
            packedMax *= self._filterMax
        return packedMax.bit_length()

    def _pack(self, dataId):
        # Docstring inherited from DataIdPacker.pack
        packed = dataId["patch"] + self._patchMax*dataId["tract"]
        if self._filterMax is not None:
            packed += self.getIntFromFilter(dataId["abstract_filter"])*self._tractPatchMax
        return packed

    def unpack(self, packedId):
        # Docstring inherited from DataIdPacker.unpack
        d = {"skymap": self._skyMapName}
        if self._filterMax is not None:
            d["abstract_filter"] = self.getFilterNameFromInt(packedId // self._tractPatchMax)
            packedId %= self._tractPatchMax
        d["tract"] = packedId // self._patchMax
        d["patch"] = packedId % self._patchMax
        return DataId(d, dimensions=self.dimensions.required)


#!/usr/bin/python3
"""function that queries the Reddit API and
    returns the number of subscribers"""

import requests

def number_of_subscribers(subreddit):
    """ Reddit API"""
    respons = requests.get("https://www.reddit.com/r/{}/about.json"
                           .format(subreddit), headers={'User-agent': 'hello'})

    if not respons:
        return 0
    return(respons.json().get('data').get('subscribers'))


import os
from django.utils.timezone import now
from datetime import datetime

from django.db import models
from django.contrib.auth.models import User
from phone_field import PhoneField

# Create your models here.

class Tags(models.Model):
    tg_name = models.CharField('тэг', max_length=200, null=True, unique=True)

    def __str__(self):
        return self.tg_name

    class Meta:
        verbose_name = 'Тег'
        verbose_name_plural = 'Теги'

class Calendar(models.Model):
    cal_date = models.DateField('Дата')
    cal_text = models.TextField('Текст')
    cal_tag = models.ManyToManyField(Tags, blank=True, verbose_name='Тэг')

    def __str__(self):
        return self.cal_text

    class Meta:
        verbose_name = 'Календарь'
        verbose_name_plural = 'Календарь'

class Problems(models.Model):
    STAT_dif = (('1', 'простая'), ('2', 'обычная'), ('3', 'сложная'), ('4', 'ОЧЕНЬ СЛОЖНАЯ'))
    STAT = (('актуально', 'актуально'), ('решено', 'решено'))
    pr_name = models.CharField('Наименование проблемы', max_length=100)
    pr_status = models.CharField('Статус', choices=STAT, max_length=50)
    pr_dif = models.CharField('Сложность', choices=STAT_dif, max_length=50)
    pr_solution = models.TextField('Решение')
    pr_document = models.FileField('Файл', blank=True)
    pr_calendar = models.ManyToManyField(Calendar, blank=True, verbose_name='События')

    def __str__(self):
        return self.pr_name

    class Meta:
        verbose_name = 'Проблема'
        verbose_name_plural = 'Проблемы'

class Tasks(models.Model):
    STAT_dif = (('1', 'простая'), ('2', 'обычная'), ('3', 'сложная'), ('4', 'ОЧЕНЬ СЛОЖНАЯ'))
    STAT = (('актуально', 'актуально'), ('выполнено', 'выполнено'))
    tk_name = models.CharField('Наименование задачи', max_length=50)
    tk_status = models.CharField('Статус', choices=STAT, max_length=50)
    tk_dif = models.CharField('Сложность', choices=STAT_dif, max_length=50)
    tk_type = models.ManyToManyField(Tags, blank=True, verbose_name='Тэг')
    tk_problem = models.ManyToManyField(Problems, blank=True, verbose_name='Проблемы')
    tk_calendar = models.ManyToManyField(Calendar,  blank=True, verbose_name='События')

    def __str__(self):
        return self.tk_name

    class Meta:
        verbose_name = 'Задача'
        verbose_name_plural = 'Задачи'

class Projects(models.Model):
    STAT = (('открыт', 'открыт'), ('завершен', 'завершен'))
    pr_name = models.CharField('Название проекта', max_length=50)
    pr_team = models.ManyToManyField(User)
    pr_start = models.DateField('Начало работ')
    pr_deadline = models.DateField('Завершение работ')
    pr_status = models.CharField('Статус', choices=STAT, max_length=50)
    pr_calendar = models.ManyToManyField(Calendar, blank=True, verbose_name='События')
    pr_task = models.ManyToManyField(Tasks, blank=True, verbose_name='Задачи')

    def __str__(self):
        return self.pr_name

    class Meta:
        verbose_name = 'Проект'
        verbose_name_plural = 'Проекты'

class Messages(models.Model):
    mes_from = models.ForeignKey(User, related_name='author', on_delete=models.SET_NULL, null=True, verbose_name='От')
    mes_to = models.ManyToManyField(User, related_name='to',  verbose_name='Кому')
    mes_text = models.TextField('Текст сообщения')
    mes_tag = models.ManyToManyField(Tags)

    class Meta:
        verbose_name = 'Сообщение'
        verbose_name_plural = 'Сообщения'

class Jobs(models.Model):
    job_name = models.CharField('должность', max_length=200, null=True, unique=True)

    def __str__(self):
        return self.job_name

    class Meta:
        verbose_name = 'Должность'
        verbose_name_plural = 'Должности'

class Information(models.Model):
    info_employee = models.OneToOneField(User, on_delete=models.CASCADE, verbose_name='Сотрудник')
    info_job = models.ManyToManyField(Jobs, blank=True, verbose_name='Должность')
    info_tel = PhoneField('Номер телефона', blank=True, help_text='Телефон | ext. ')
    info_image = models.ImageField('Фото', default="unnamed.png", null=True, blank=True)

    def __str__(self):
        return self.info_employee.get_username()

    def filename(self):
        return os.path.basename(self.info_image.name)

    class Meta:
        verbose_name = 'Информация о работнике'
        verbose_name_plural = 'Информация о работниках'

class Documents(models.Model):
    STAT = (('принят', 'принят'), ('на рассмотрении', 'на рассмотрении'), ('отклонен', 'отклонен'))
    doc_name = models.CharField('Название', max_length=50)
    doc_owner = models.ManyToManyField(User, 'Владельцы')
    doc_date = models.DateField('Последние изменения', default=datetime.now)
    doc_tag = models.ManyToManyField(Tags, 'Тэг')
    doc_doc = models.FileField('Файл', blank=True)
    doc_link = models.URLField('Ссылка на документ', blank=True, max_length=100)
    doc_calendar = models.ManyToManyField(Calendar, blank=True, verbose_name='События')
    doc_task = models.ForeignKey(Tasks, verbose_name='Задача', blank=True, null=True, on_delete=models.SET_NULL)
    doc_project = models.ManyToManyField(Projects, verbose_name='Для проекта')
    doc_acc = models.CharField('Статус', choices=STAT, null=True, max_length=50, default='на рассмотрении')

    def __str__(self):
        return self.doc_name

    def filename(self):
        return os.path.basename(self.doc_doc.name)

    class Meta:
        verbose_name = 'Документы'
        verbose_name_plural = 'Документы'

class Comments(models.Model):
    com_title = models.CharField('Заголовок комментария', max_length=50)
    com_user = models.ForeignKey(User, verbose_name='Пользователь', on_delete=models.SET_NULL, null=True)
    com_text = models.TextField('Текст комментария')
    com_date = models.DateTimeField(default=now, editable=False)
    com_teg = models.ManyToManyField(Tags, blank=True, verbose_name='Тэг')
    com_doc = models.ManyToManyField(Documents, blank=True, verbose_name='Документы')
    com_proj = models.ForeignKey(Projects, blank=True, null=True, on_delete=models.CASCADE, verbose_name='Проекты')
    com_tasks = models.ManyToManyField(Tasks, blank=True, verbose_name='Задачи')
    com_prob = models.ManyToManyField(Problems, blank=True, verbose_name='Проблемы')

    def __str__(self):
        return self.com_title

    class Meta:
        verbose_name = 'Комментарий'
        verbose_name_plural = 'Комментарии'


import cv2
from utils import constants as cs
from utils import utility, os_utils

if __name__ == '__main__':
    fg_bg = cv2.createBackgroundSubtractorMOG2()
    IMAGE_SIZE = (12, 8)

    path_gen = os_utils.iterate_data(cs.BASE_DATA_PATH + cs.DATA_TRAIN_VIDEOS, ".mp4")

    for path in path_gen:
        utility.write_videos(path, cs.DATA_TRAIN_VIDEOS, cs.DATA_BG_TRAIN_VIDEO)

    path_gen = os_utils.iterate_test_data(cs.BASE_DATA_PATH + cs.DATA_TEST_VIDEOS, ".mp4")
    for path in path_gen:
        utility.write_videos(path, cs.DATA_TEST_VIDEOS, cs.DATA_BG_TEST_VIDEO)


"""
    基于 selenium.webdriver 操控Chrome浏览器搜索信息，并提取第一个标题信息
    注1：需要安装 selenium: pip install selenium
    注2：需要下载 chromedriver.exe（版本要与实际浏览器一致），放置到 python3安装根目录下
    注3：selenium的性质是一个web测试工具，用于模拟人操作浏览器用的
"""
import time
from selenium import webdriver

keys = "lifeeeee"
# 创建Chrome驱动器
driver = webdriver.Chrome()
# 打开网页
driver.get("https://www.baidu.com/")
time.sleep(1)
# 定位到搜索栏，并在搜索栏输入关键字
inputElement = driver.find_element_by_name("wd")
inputElement.send_keys(keys)
# 定位到提交按钮，点击提交
su_find = driver.find_element_by_id('su')
su_find.click()
time.sleep(3)
# 搜索name为 description的标签
re_title = driver.find_element_by_name('')
print(re_title.get_attribute("content"))
# 退出
time.sleep(3)
driver.quit()


from trac.core import *
from trac.web.api import IRequestFilter
from trac.ticket.report import ReportModule

from api import PrivateTicketsSystem

__all__ = ['PrivateTicketsReportFilter']

class PrivateTicketsReportFilter(Component):
    """Show only ticket the user is involved in in the reports."""

    implements(IRequestFilter)

    # IRequestFilter methods
    def pre_process_request(self, req, handler):
        if isinstance(handler, ReportModule) and \
           not req.perm.has_permission('TICKET_VIEW') and \
           req.args.get('format') in ('tab', 'csv'):
            raise TracError('Access denied')
        return handler

    def post_process_request(self, req, template, content_type):
        if req.args.get('DO_PRIVATETICKETS_FILTER') == 'report':
            # Walk the HDF
            fn = PrivateTicketsSystem(self.env).check_ticket_access
            deleted = []
            left = []
            node = req.hdf.getObj('report.items')
            if node is None:
                return template, content_type
            node = node.child()

            while node:
                i = node.name()
                id = req.hdf['report.items.%s.ticket'%i]
                if not fn(req, id):
                    deleted.append(i)
                else:
                    left.append(i)
                node = node.next()

            # Delete the needed subtrees
            for n in deleted:
                req.hdf.removeTree('report.items.%s'%n)

            # Recalculate this
            req.hdf['report.numrows'] = len(left)

            # Move the remaining items into their normal places
            for src, dest in zip(left, xrange(len(left)+len(deleted))):
                if src == dest: continue
                req.hdf.getObj('report.items').copy(str(dest), req.hdf.getObj('report.items.%s'%src))
            for n in xrange(len(left), len(left)+len(deleted)):
                req.hdf.removeTree('report.items.%s'%n)

        return template, content_type


# Create two lists, one containing arithmetic expressions as strings, and the other containing their corresponding results
expr_list = ["1 + 5", "5 + 8", "12 + 5"]
result_list = ["6", "13", "17"]

# Use the `zip()` function to combine the two lists into a list of tuples, with each tuple containing an expression and its result
# Then, use the `dict()` function to convert the list of tuples into a dictionary, with each expression as the key and its result as the value
result_dict = dict(zip(expr_list, result_list))

# Print the resulting dictionary
print(result_dict)


def solution(numbers, target):
    answer = 0
    total_num = len(numbers)
    def dfs(idx, result):
        if(idx == total_num):
            if(result == target):
                nonlocal answer
                answer += 1
            return
        else :
            dfs(idx + 1, result + numbers[idx])
            dfs(idx + 1, result - numbers[idx])

    dfs(0, 0)
    return answer


"""
"""
import os
import GalaxyTestBase
import test_util
from bioblend.galaxy.tools.inputs import (
    inputs,
    dataset,
    repeat,
    conditional,
)

def get_abspath(path):
    return os.path.join(os.path.dirname(__file__), path)

@test_util.skip_unless_galaxy()
class TestGalaxyTools(GalaxyTestBase.GalaxyTestBase):

    def setUp(self):
        super(TestGalaxyTools, self).setUp()

    def test_get_tools(self):
        # Test requires target Galaxy is configured with at least one tool.
        tools = self.gi.tools.get_tools()
        assert len(tools) > 0
        assert all(map(self._assert_is_tool_rep, tools))

    def test_get_tool_panel(self):
        # Test requires target Galaxy is configured with at least one tool
        # section.
        tool_panel = self.gi.tools.get_tool_panel()
        sections = [s for s in tool_panel if "elems" in s]
        assert len(sections) > 0
        assert all(map(self._assert_is_tool_rep, sections[0]["elems"]))

    def _assert_is_tool_rep(self, data):
        assert data["model_class"].endswith("Tool")
        # Special tools like SetMetadataTool may have different model_class
        # than Tool - but they all seem to end in tool.

        for key in ["name", "id", "version"]:
            assert key in data, "key %s not in %s" % (key, data)
        return True

    def test_paste_data(self):
        history = self.gi.histories.create_history(name="test_paste_data history")

        tool_output = self.gi.tools.paste_content("test contents", history["id"])
        assert len(tool_output["outputs"]) == 1

    def test_upload_file(self):
        history = self.gi.histories.create_history(name="test_upload_file history")

        fn = get_abspath(os.path.join(os.pardir, "setup.py"))
        file_name = "test1"
        tool_output = self.gi.tools.upload_file(
            fn,
            # First param could be a regular path also of course...
            history_id=history["id"],
            file_name=file_name,
            dbkey="?",
            file_type="txt",
        )
        assert len(tool_output["outputs"]) == 1
        assert tool_output['outputs'][0]['name'] == file_name

    @test_util.skip_unless_tool("random_lines1")
    def test_run_random_lines(self):
        # Run second test case from randomlines.xml
        history_id = self.gi.histories.create_history(name="test_run_random_lines history")["id"]
        with open(get_abspath(os.path.join("data", "1.bed"))) as f:
            contents = f.read()
        dataset_id = self._test_dataset(history_id, contents=contents)
        tool_inputs = inputs().set(
            "num_lines", "1"
        ).set(
            "input", dataset(dataset_id)
        ).set(
            "seed_source", conditional().set(
                "seed_source_selector", "set_seed"
            ).set(
                "seed", "asdf"
            )
        )
        tool_output = self.gi.tools.run_tool(
            history_id=history_id,
            tool_id="random_lines1",
            tool_inputs=tool_inputs
        )
        assert len(tool_output["outputs"]) == 1
        # TODO: Wait for results and verify has 1 line and is
        # chr5  131424298   131424460   CCDS4149.1_cds_0_0_chr5_131424299_f 0   +

    @test_util.skip_unless_tool("cat1")
    def test_run_cat1(self):
        history_id = self.gi.histories.create_history(name="test_run_cat1 history")["id"]
        dataset1_id = self._test_dataset(history_id, contents="1 2 3")
        dataset2_id = self._test_dataset(history_id, contents="4 5 6")
        dataset3_id = self._test_dataset(history_id, contents="7 8 9")
        tool_inputs = inputs().set(
            "input1", dataset(dataset1_id)
        ).set(
            "queries", repeat().instance(
                inputs().set("input2", dataset(dataset2_id))
            ).instance(
                inputs().set("input2", dataset(dataset3_id))
            )
        )
        tool_output = self.gi.tools.run_tool(
            history_id=history_id,
            tool_id="cat1",
            tool_inputs=tool_inputs
        )
        assert len(tool_output["outputs"]) == 1
        # TODO: Wait for results and verify it has 3 lines - 1 2 3, 4 5 6,
        # and 7 8 9.


from mlflow import end_run, start_run

from blob_operations import Blob_Operation
from mlflow_operations import MLFlow_Operation
from tuner import Model_Finder
from utils.logger import App_Logger
from utils.main_utils import Main_Utils
from utils.read_params import read_params

class Run:
    """
    Description :   This class is used for running the model training service

    Version     :   1.2
    Revisions   :   Moved to setup to cloud
    """

    def __init__(self):
        self.class_name = self.__class__.__name__

        self.config = read_params()

        self.mlflow_config = self.config["mlflow_config"]

        self.model = Model_Finder("model_train")

        self.utils = Main_Utils()

        self.blob = Blob_Operation()

        self.log_writer = App_Logger()

        self.mlflow_op = MLFlow_Operation("model_train")

    def training_model(self):
        """
        Method Name :   training_model
        Description :   This method performs the trains the models based on the training data

        Output      :   Model training is done, along with logging of models, metrics and parameters to mlflow and artifacts are stored
                        blob container
        On Failure  :   Write an exception log and then raise an exception

        Version     :   1.2
        Revisions   :   Moved to setup to cloud
        """
        method_name = self.training_model.__name__

        self.log_writer.start_log("start", self.class_name, method_name, "model_train")

        try:
            lst_clusters = self.utils.get_number_of_clusters("model_train")

            self.log_writer.log(
                f"Found the number of cluster to be {lst_clusters}", "model_train",
            )

            kmeans_model = self.blob.load_model(
                "KMeans", "model", "model_train", model_dir="train"
            )

            kmeans_model_name = kmeans_model.__class__.__name__

            self.mlflow_op.set_mlflow_tracking_uri()

            self.mlflow_op.set_mlflow_experiment("exp_name")

            with start_run(run_name=self.mlflow_config["run_name"]):
                self.mlflow_op.log_sklearn_model(kmeans_model, kmeans_model_name)

                end_run()

            for i in range(lst_clusters):
                cluster_feat = self.utils.get_cluster_features(i, "model_train")

                cluster_label = self.utils.get_cluster_targets(i, "model_train")

                self.log_writer.log(
                    "Got cluster features and cluster labels dataframe from feature store container",
                    "model_train",
                )

                with start_run(run_name=self.mlflow_config["run_name"] + str(i)):
                    self.model.train_and_log_models(
                        cluster_feat, cluster_label, "model_train", idx=i,
                    )

            self.log_writer.log(
                "Completed model and training and logging of the models to mlflow",
                "model_train",
            )

            self.log_writer.start_log(
                "exit", self.class_name, method_name, "model_train"
            )

        except Exception as e:
            self.log_writer.exception_log(
                e, self.class_name, method_name, "model_train"
            )

if __name__ == "__main__":
    try:
        run = Run()

        run.training_model()

    except Exception as e:
        raise e

    finally:
        utils = Main_Utils()

        utils.upload_logs()


# results.py
from collections.abc import (
    MutableMapping,
    Mapping,
    MutableSequence,
    Iterator,
    Sequence,
    Container,
)
import pprint
from typing import Tuple, Any, Dict, Set, List

str_type: Tuple[type, ...] = (str, bytes)
_generator_type = type((_ for _ in ()))

class _ParseResultsWithOffset:
    tup: Tuple["ParseResults", int]
    __slots__ = ["tup"]

    def __init__(self, p1: "ParseResults", p2: int):
        self.tup: Tuple[ParseResults, int] = (p1, p2)

    def __getitem__(self, i):
        return self.tup[i]

    def __getstate__(self):
        return self.tup

    def __setstate__(self, *args):
        self.tup = args[0]

class ParseResults:
    """Structured parse results, to provide multiple means of access to
    the parsed data:

    - as a list (``len(results)``)
    - by list index (``results[0], results[1]``, etc.)
    - by attribute (``results.<results_name>`` - see :class:`ParserElement.set_results_name`)

    Example::

        integer = Word(nums)
        date_str = (integer.set_results_name("year") + '/'
                    + integer.set_results_name("month") + '/'
                    + integer.set_results_name("day"))
        # equivalent form:
        # date_str = (integer("year") + '/'
        #             + integer("month") + '/'
        #             + integer("day"))

        # parse_string returns a ParseResults object
        result = date_str.parse_string("1999/12/31")

        def test(s, fn=repr):
            print(f"{s} -> {fn(eval(s))}")
        test("list(result)")
        test("result[0]")
        test("result['month']")
        test("result.day")
        test("'month' in result")
        test("'minutes' in result")
        test("result.dump()", str)

    prints::

        list(result) -> ['1999', '/', '12', '/', '31']
        result[0] -> '1999'
        result['month'] -> '12'
        result.day -> '31'
        'month' in result -> True
        'minutes' in result -> False
        result.dump() -> ['1999', '/', '12', '/', '31']
        - day: '31'
        - month: '12'
        - year: '1999'
    """

    _null_values: Tuple[Any, ...] = (None, [], ())

    _name: str
    _parent: "ParseResults"
    _all_names: Set[str]
    _modal: bool
    _toklist: List[Any]
    _tokdict: Dict[str, Any]

    __slots__ = (
        "_name",
        "_parent",
        "_all_names",
        "_modal",
        "_toklist",
        "_tokdict",
    )

    class List(list):
        """
        Simple wrapper class to distinguish parsed list results that should be preserved
        as actual Python lists, instead of being converted to :class:`ParseResults`::

            LBRACK, RBRACK = map(pp.Suppress, "[]")
            element = pp.Forward()
            item = ppc.integer
            element_list = LBRACK + pp.DelimitedList(element) + RBRACK

            # add parse actions to convert from ParseResults to actual Python collection types
            def as_python_list(t):
                return pp.ParseResults.List(t.as_list())
            element_list.add_parse_action(as_python_list)

            element <<= item | element_list

            element.run_tests('''
                100
                [2,3,4]
                [[2, 1],3,4]
                [(2, 1),3,4]
                (2,3,4)
                ''', post_parse=lambda s, r: (r[0], type(r[0])))

        prints::

            100
            (100, <class 'int'>)

            [2,3,4]
            ([2, 3, 4], <class 'list'>)

            [[2, 1],3,4]
            ([[2, 1], 3, 4], <class 'list'>)

        (Used internally by :class:`Group` when `aslist=True`.)
        """

        def __new__(cls, contained=None):
            if contained is None:
                contained = []

            if not isinstance(contained, list):
                raise TypeError(
                    f"{cls.__name__} may only be constructed with a list, not {type(contained).__name__}"
                )

            return list.__new__(cls)

    def __new__(cls, toklist=None, name=None, **kwargs):
        if isinstance(toklist, ParseResults):
            return toklist
        self = object.__new__(cls)
        self._name = None
        self._parent = None
        self._all_names = set()

        if toklist is None:
            self._toklist = []
        elif isinstance(toklist, (list, _generator_type)):
            self._toklist = (
                [toklist[:]]
                if isinstance(toklist, ParseResults.List)
                else list(toklist)
            )
        else:
            self._toklist = [toklist]
        self._tokdict = dict()
        return self

    # Performance tuning: we construct a *lot* of these, so keep this
    # constructor as small and fast as possible
    def __init__(
        self, toklist=None, name=None, asList=True, modal=True, isinstance=isinstance
    ):
        self._tokdict: Dict[str, _ParseResultsWithOffset]
        self._modal = modal
        if name is not None and name != "":
            if isinstance(name, int):
                name = str(name)
            if not modal:
                self._all_names = {name}
            self._name = name
            if toklist not in self._null_values:
                if isinstance(toklist, (str_type, type)):
                    toklist = [toklist]
                if asList:
                    if isinstance(toklist, ParseResults):
                        self[name] = _ParseResultsWithOffset(
                            ParseResults(toklist._toklist), 0
                        )
                    else:
                        self[name] = _ParseResultsWithOffset(
                            ParseResults(toklist[0]), 0
                        )
                    self[name]._name = name
                else:
                    try:
                        self[name] = toklist[0]
                    except (KeyError, TypeError, IndexError):
                        if toklist is not self:
                            self[name] = toklist
                        else:
                            self._name = name

    def __getitem__(self, i):
        if isinstance(i, (int, slice)):
            return self._toklist[i]
        else:
            if i not in self._all_names:
                return self._tokdict[i][-1][0]
            else:
                return ParseResults([v[0] for v in self._tokdict[i]])

    def __setitem__(self, k, v, isinstance=isinstance):
        if isinstance(v, _ParseResultsWithOffset):
            self._tokdict[k] = self._tokdict.get(k, list()) + [v]
            sub = v[0]
        elif isinstance(k, (int, slice)):
            self._toklist[k] = v
            sub = v
        else:
            self._tokdict[k] = self._tokdict.get(k, list()) + [
                _ParseResultsWithOffset(v, 0)
            ]
            sub = v
        if isinstance(sub, ParseResults):
            sub._parent = self

    def __delitem__(self, i):
        if isinstance(i, (int, slice)):
            mylen = len(self._toklist)
            del self._toklist[i]

            # convert int to slice
            if isinstance(i, int):
                if i < 0:
                    i += mylen
                i = slice(i, i + 1)
            # get removed indices
            removed = list(range(*i.indices(mylen)))
            removed.reverse()
            # fixup indices in token dictionary
            for name, occurrences in self._tokdict.items():
                for j in removed:
                    for k, (value, position) in enumerate(occurrences):
                        occurrences[k] = _ParseResultsWithOffset(
                            value, position - (position > j)
                        )
        else:
            del self._tokdict[i]

    def __contains__(self, k) -> bool:
        return k in self._tokdict

    def __len__(self) -> int:
        return len(self._toklist)

    def __bool__(self) -> bool:
        return not not (self._toklist or self._tokdict)

    def __iter__(self) -> Iterator:
        return iter(self._toklist)

    def __reversed__(self) -> Iterator:
        return iter(self._toklist[::-1])

    def keys(self):
        return iter(self._tokdict)

    def values(self):
        return (self[k] for k in self.keys())

    def items(self):
        return ((k, self[k]) for k in self.keys())

    def haskeys(self) -> bool:
        """
        Since ``keys()`` returns an iterator, this method is helpful in bypassing
        code that looks for the existence of any defined results names."""
        return not not self._tokdict

    def pop(self, *args, **kwargs):
        """
        Removes and returns item at specified index (default= ``last``).
        Supports both ``list`` and ``dict`` semantics for ``pop()``. If
        passed no argument or an integer argument, it will use ``list``
        semantics and pop tokens from the list of parsed tokens. If passed
        a non-integer argument (most likely a string), it will use ``dict``
        semantics and pop the corresponding value from any defined results
        names. A second default return value argument is supported, just as in
        ``dict.pop()``.

        Example::

            numlist = Word(nums)[...]
            print(numlist.parse_string("0 123 321")) # -> ['0', '123', '321']

            def remove_first(tokens):
                tokens.pop(0)
            numlist.add_parse_action(remove_first)
            print(numlist.parse_string("0 123 321")) # -> ['123', '321']

            label = Word(alphas)
            patt = label("LABEL") + Word(nums)[1, ...]
            print(patt.parse_string("AAB 123 321").dump())

            # Use pop() in a parse action to remove named result (note that corresponding value is not
            # removed from list form of results)
            def remove_LABEL(tokens):
                tokens.pop("LABEL")
                return tokens
            patt.add_parse_action(remove_LABEL)
            print(patt.parse_string("AAB 123 321").dump())

        prints::

            ['AAB', '123', '321']
            - LABEL: 'AAB'

            ['AAB', '123', '321']
        """
        if not args:
            args = [-1]
        for k, v in kwargs.items():
            if k == "default":
                args = (args[0], v)
            else:
                raise TypeError(f"pop() got an unexpected keyword argument {k!r}")
        if isinstance(args[0], int) or len(args) == 1 or args[0] in self:
            index = args[0]
            ret = self[index]
            del self[index]
            return ret
        else:
            defaultvalue = args[1]
            return defaultvalue

    def get(self, key, default_value=None):
        """
        Returns named result matching the given key, or if there is no
        such name, then returns the given ``default_value`` or ``None`` if no
        ``default_value`` is specified.

        Similar to ``dict.get()``.

        Example::

            integer = Word(nums)
            date_str = integer("year") + '/' + integer("month") + '/' + integer("day")

            result = date_str.parse_string("1999/12/31")
            print(result.get("year")) # -> '1999'
            print(result.get("hour", "not specified")) # -> 'not specified'
            print(result.get("hour")) # -> None
        """
        if key in self:
            return self[key]
        else:
            return default_value

    def insert(self, index, ins_string):
        """
        Inserts new element at location index in the list of parsed tokens.

        Similar to ``list.insert()``.

        Example::

            numlist = Word(nums)[...]
            print(numlist.parse_string("0 123 321")) # -> ['0', '123', '321']

            # use a parse action to insert the parse location in the front of the parsed results
            def insert_locn(locn, tokens):
                tokens.insert(0, locn)
            numlist.add_parse_action(insert_locn)
            print(numlist.parse_string("0 123 321")) # -> [0, '0', '123', '321']
        """
        self._toklist.insert(index, ins_string)
        # fixup indices in token dictionary
        for name, occurrences in self._tokdict.items():
            for k, (value, position) in enumerate(occurrences):
                occurrences[k] = _ParseResultsWithOffset(
                    value, position + (position > index)
                )

    def append(self, item):
        """
        Add single element to end of ``ParseResults`` list of elements.

        Example::

            numlist = Word(nums)[...]
            print(numlist.parse_string("0 123 321")) # -> ['0', '123', '321']

            # use a parse action to compute the sum of the parsed integers, and add it to the end
            def append_sum(tokens):
                tokens.append(sum(map(int, tokens)))
            numlist.add_parse_action(append_sum)
            print(numlist.parse_string("0 123 321")) # -> ['0', '123', '321', 444]
        """
        self._toklist.append(item)

    def extend(self, itemseq):
        """
        Add sequence of elements to end of ``ParseResults`` list of elements.

        Example::

            patt = Word(alphas)[1, ...]

            # use a parse action to append the reverse of the matched strings, to make a palindrome
            def make_palindrome(tokens):
                tokens.extend(reversed([t[::-1] for t in tokens]))
                return ''.join(tokens)
            patt.add_parse_action(make_palindrome)
            print(patt.parse_string("lskdj sdlkjf lksd")) # -> 'lskdjsdlkjflksddsklfjkldsjdksl'
        """
        if isinstance(itemseq, ParseResults):
            self.__iadd__(itemseq)
        else:
            self._toklist.extend(itemseq)

    def clear(self):
        """
        Clear all elements and results names.
        """
        del self._toklist[:]
        self._tokdict.clear()

    def __getattr__(self, name):
        try:
            return self[name]
        except KeyError:
            if name.startswith("__"):
                raise AttributeError(name)
            return ""

    def __add__(self, other: "ParseResults") -> "ParseResults":
        ret = self.copy()
        ret += other
        return ret

    def __iadd__(self, other: "ParseResults") -> "ParseResults":
        if not other:
            return self

        if other._tokdict:
            offset = len(self._toklist)
            addoffset = lambda a: offset if a < 0 else a + offset
            otheritems = other._tokdict.items()
            otherdictitems = [
                (k, _ParseResultsWithOffset(v[0], addoffset(v[1])))
                for k, vlist in otheritems
                for v in vlist
            ]
            for k, v in otherdictitems:
                self[k] = v
                if isinstance(v[0], ParseResults):
                    v[0]._parent = self

        self._toklist += other._toklist
        self._all_names |= other._all_names
        return self

    def __radd__(self, other) -> "ParseResults":
        if isinstance(other, int) and other == 0:
            # useful for merging many ParseResults using sum() builtin
            return self.copy()
        else:
            # this may raise a TypeError - so be it
            return other + self

    def __repr__(self) -> str:
        return f"{type(self).__name__}({self._toklist!r}, {self.as_dict()})"

    def __str__(self) -> str:
        return (
            "["
            + ", ".join(
                [
                    str(i) if isinstance(i, ParseResults) else repr(i)
                    for i in self._toklist
                ]
            )
            + "]"
        )

    def _asStringList(self, sep=""):
        out = []
        for item in self._toklist:
            if out and sep:
                out.append(sep)
            if isinstance(item, ParseResults):
                out += item._asStringList()
            else:
                out.append(str(item))
        return out

    def as_list(self) -> list:
        """
        Returns the parse results as a nested list of matching tokens, all converted to strings.

        Example::

            patt = Word(alphas)[1, ...]
            result = patt.parse_string("sldkj lsdkj sldkj")
            # even though the result prints in string-like form, it is actually a pyparsing ParseResults
            print(type(result), result) # -> <class 'pyparsing.ParseResults'> ['sldkj', 'lsdkj', 'sldkj']

            # Use as_list() to create an actual list
            result_list = result.as_list()
            print(type(result_list), result_list) # -> <class 'list'> ['sldkj', 'lsdkj', 'sldkj']
        """
        return [
            res.as_list() if isinstance(res, ParseResults) else res
            for res in self._toklist
        ]

    def as_dict(self) -> dict:
        """
        Returns the named parse results as a nested dictionary.

        Example::

            integer = Word(nums)
            date_str = integer("year") + '/' + integer("month") + '/' + integer("day")

            result = date_str.parse_string('12/31/1999')
            print(type(result), repr(result)) # -> <class 'pyparsing.ParseResults'> (['12', '/', '31', '/', '1999'], {'day': [('1999', 4)], 'year': [('12', 0)], 'month': [('31', 2)]})

            result_dict = result.as_dict()
            print(type(result_dict), repr(result_dict)) # -> <class 'dict'> {'day': '1999', 'year': '12', 'month': '31'}

            # even though a ParseResults supports dict-like access, sometime you just need to have a dict
            import json
            print(json.dumps(result)) # -> Exception: TypeError: ... is not JSON serializable
            print(json.dumps(result.as_dict())) # -> {"month": "31", "day": "1999", "year": "12"}
        """

        def to_item(obj):
            if isinstance(obj, ParseResults):
                return obj.as_dict() if obj.haskeys() else [to_item(v) for v in obj]
            else:
                return obj

        return dict((k, to_item(v)) for k, v in self.items())

    def copy(self) -> "ParseResults":
        """
        Returns a new shallow copy of a :class:`ParseResults` object. `ParseResults`
        items contained within the source are shared with the copy. Use
        :class:`ParseResults.deepcopy()` to create a copy with its own separate
        content values.
        """
        ret = ParseResults(self._toklist)
        ret._tokdict = self._tokdict.copy()
        ret._parent = self._parent
        ret._all_names |= self._all_names
        ret._name = self._name
        return ret

    def deepcopy(self) -> "ParseResults":
        """
        Returns a new deep copy of a :class:`ParseResults` object.
        """
        ret = self.copy()
        # replace values with copies if they are of known mutable types
        for i, obj in enumerate(self._toklist):
            if isinstance(obj, ParseResults):
                self._toklist[i] = obj.deepcopy()
            elif isinstance(obj, (str, bytes)):
                pass
            elif isinstance(obj, MutableMapping):
                self._toklist[i] = dest = type(obj)()
                for k, v in obj.items():
                    dest[k] = v.deepcopy() if isinstance(v, ParseResults) else v
            elif isinstance(obj, Container):
                self._toklist[i] = type(obj)(
                    v.deepcopy() if isinstance(v, ParseResults) else v for v in obj
                )
        return ret

    def get_name(self):
        r"""
        Returns the results name for this token expression. Useful when several
        different expressions might match at a particular location.

        Example::

            integer = Word(nums)
            ssn_expr = Regex(r"\d\d\d-\d\d-\d\d\d\d")
            house_number_expr = Suppress('#') + Word(nums, alphanums)
            user_data = (Group(house_number_expr)("house_number")
                        | Group(ssn_expr)("ssn")
                        | Group(integer)("age"))
            user_info = user_data[1, ...]

            result = user_info.parse_string("22 111-22-3333 #221B")
            for item in result:
                print(item.get_name(), ':', item[0])

        prints::

            age : 22
            ssn : 111-22-3333
            house_number : 221B
        """
        if self._name:
            return self._name
        elif self._parent:
            par: "ParseResults" = self._parent
            parent_tokdict_items = par._tokdict.items()
            return next(
                (
                    k
                    for k, vlist in parent_tokdict_items
                    for v, loc in vlist
                    if v is self
                ),
                None,
            )
        elif (
            len(self) == 1
            and len(self._tokdict) == 1
            and next(iter(self._tokdict.values()))[0][1] in (0, -1)
        ):
            return next(iter(self._tokdict.keys()))
        else:
            return None

    def dump(self, indent="", full=True, include_list=True, _depth=0) -> str:
        """
        Diagnostic method for listing out the contents of
        a :class:`ParseResults`. Accepts an optional ``indent`` argument so
        that this string can be embedded in a nested display of other data.

        Example::

            integer = Word(nums)
            date_str = integer("year") + '/' + integer("month") + '/' + integer("day")

            result = date_str.parse_string('1999/12/31')
            print(result.dump())

        prints::

            ['1999', '/', '12', '/', '31']
            - day: '31'
            - month: '12'
            - year: '1999'
        """
        out = []
        NL = "\n"
        out.append(indent + str(self.as_list()) if include_list else "")

        if full:
            if self.haskeys():
                items = sorted((str(k), v) for k, v in self.items())
                for k, v in items:
                    if out:
                        out.append(NL)
                    out.append(f"{indent}{('  ' * _depth)}- {k}: ")
                    if isinstance(v, ParseResults):
                        if v:
                            out.append(
                                v.dump(
                                    indent=indent,
                                    full=full,
                                    include_list=include_list,
                                    _depth=_depth + 1,
                                )
                            )
                        else:
                            out.append(str(v))
                    else:
                        out.append(repr(v))
            if any(isinstance(vv, ParseResults) for vv in self):
                v = self
                for i, vv in enumerate(v):
                    if isinstance(vv, ParseResults):
                        out.append(
                            "\n{}{}[{}]:\n{}{}{}".format(
                                indent,
                                ("  " * (_depth)),
                                i,
                                indent,
                                ("  " * (_depth + 1)),
                                vv.dump(
                                    indent=indent,
                                    full=full,
                                    include_list=include_list,
                                    _depth=_depth + 1,
                                ),
                            )
                        )
                    else:
                        out.append(
                            "\n%s%s[%d]:\n%s%s%s"
                            % (
                                indent,
                                ("  " * (_depth)),
                                i,
                                indent,
                                ("  " * (_depth + 1)),
                                str(vv),
                            )
                        )

        return "".join(out)

    def pprint(self, *args, **kwargs):
        """
        Pretty-printer for parsed results as a list, using the
        `pprint <https://docs.python.org/3/library/pprint.html>`_ module.
        Accepts additional positional or keyword args as defined for
        `pprint.pprint <https://docs.python.org/3/library/pprint.html#pprint.pprint>`_ .

        Example::

            ident = Word(alphas, alphanums)
            num = Word(nums)
            func = Forward()
            term = ident | num | Group('(' + func + ')')
            func <<= ident + Group(Optional(DelimitedList(term)))
            result = func.parse_string("fna a,b,(fnb c,d,200),100")
            result.pprint(width=40)

        prints::

            ['fna',
             ['a',
              'b',
              ['(', 'fnb', ['c', 'd', '200'], ')'],
              '100']]
        """
        pprint.pprint(self.as_list(), *args, **kwargs)

    # add support for pickle protocol
    def __getstate__(self):
        return (
            self._toklist,
            (
                self._tokdict.copy(),
                None,
                self._all_names,
                self._name,
            ),
        )

    def __setstate__(self, state):
        self._toklist, (self._tokdict, par, inAccumNames, self._name) = state
        self._all_names = set(inAccumNames)
        self._parent = None

    def __getnewargs__(self):
        return self._toklist, self._name

    def __dir__(self):
        return dir(type(self)) + list(self.keys())

    @classmethod
    def from_dict(cls, other, name=None) -> "ParseResults":
        """
        Helper classmethod to construct a ``ParseResults`` from a ``dict``, preserving the
        name-value relations as results names. If an optional ``name`` argument is
        given, a nested ``ParseResults`` will be returned.
        """

        def is_iterable(obj):
            try:
                iter(obj)
            except Exception:
                return False
            # str's are iterable, but in pyparsing, we don't want to iterate over them
            else:
                return not isinstance(obj, str_type)

        ret = cls([])
        for k, v in other.items():
            if isinstance(v, Mapping):
                ret += cls.from_dict(v, name=k)
            else:
                ret += cls([v], name=k, asList=is_iterable(v))
        if name is not None:
            ret = cls([ret], name=name)
        return ret

    asList = as_list
    """Deprecated - use :class:`as_list`"""
    asDict = as_dict
    """Deprecated - use :class:`as_dict`"""
    getName = get_name
    """Deprecated - use :class:`get_name`"""

MutableMapping.register(ParseResults)
MutableSequence.register(ParseResults)


from Models.clustering import KMeans
from datasets import get_dataset
from Pipelines.clustering_pipeline import get_clustering_res
from Metrics.metrics import accuracy
import matplotlib.pyplot as plt

def get_color(l):

    if l == 0:
        return "red"
    elif l == 1:
        return "blue"
    elif l == 2:
        return "yellow"

def plot_clustering(x, y, title):

    fig = plt.figure(figsize=(x.shape[1] * 5, x.shape[1] * 5))

    plt.title(title)
    for i in range(x.shape[1]):
        for j in range(x.shape[1]):

            plt.subplot(x.shape[1], x.shape[1], 1 + i * x.shape[1] + j)
            plt.scatter(x[:, i], x[:, j], c = [get_color(lab) for lab in y])
    plt.show()

def clustering_test():

    cluster = KMeans(k=3)

    x, y = get_dataset("iris")

    outp = get_clustering_res({"kmeans": cluster}, x)

    plot_clustering(x, y, "original")
    plot_clustering(x, outp[0], "clustering")

if __name__ == "__main__":

    clustering_test()


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

def main(a, b):
    hit = 0
    blow = 0

    for a_e, b_e in zip(a, b):
        if a_e == b_e:
            hit += 1
        elif a_e in b:
            blow += 1

    print(hit, blow, sep=' ')

while True:
    try:
        a = [int(e) for e in input().split()]
        b = [int(e) for e in input().split()]
    except:
        break

    main(a, b)


import hngd.run
import hngd.default
import experimental_data
import numpy as np
import matplotlib.pyplot as plt

# TODO > En la tesis de Florian Passelaigue (2020 - Hydride
# nucleation-growth-dissolution model: Implementation in BISON) muestra
# barras de error para estos experimentos (no encontre de donde salen?).

"""
Generate plots for the experiments made by Kammenzind, published in Merlino
J. T., 'Experiments in hydrogen distribution in thermal gradients calculated
using BISON', M. Eng. Thesis, The Pennsylvania State University (2019).

This script runs experiments from the Experiment 1 Data Set. Experimental data
can be found in Appendix A, Tables A1-A14. In these experiments, specimens
containing various amounts of hydrogen were annealed while subjected to various
temperature gradients. The anneals were conducted for periods of time ranging
from weeks to months in order to approach equilibrium. The specimens were then
removed from heat, sectioned, and analyzed for total hydrogen content.

Zirconium alloys used include alpha-annealed Zircaloy-4, Zircaloy-1%Niobium and
Zircaloy-2.5%Niobium.

This script takes ~ 35 minutes to run all 28 experiments.

"""

slab_length = 2.54*1e-2
experiment_data = (slab_length, 0, 0, 1, 0)

model_parameters = hngd.default.model_parameters

# TSSp and TSSd of Zry-4 by Zanellato et al. (most experiments are with Zry-4).

model_parameters['TSSd0'] = 510800
model_parameters['Q_TSSd'] = 45610
model_parameters['TSSp0'] = 66440
model_parameters['Q_TSSp'] = 29630

# Diffusion coefficient for Zry-4 by Kammenzind et al.

#model_parameters['D0'] = 0.8e-7
#model_parameters['Ed'] = 0.34

# Diffusion coefficient for Zry-4 by Kearns.

model_parameters['D0'] = 7.73e-7
model_parameters['Ed'] = 0.47

#%% Simulate

for i, (experiment, data) in enumerate(experimental_data.linear_cases.items()):

    print(f'\n- Running experiment {experiment}. Simulation {i+1} out of {len(experimental_data.linear_cases)}.')

    simulation_data = (experiment, 70, 2, 500, 0.05, 'mHNGD')

    temperature_data = np.array([[                np.nan,                       0,              slab_length],
                                 [                     0, data['low_temperature'], data['high_temperature']],
                                 [data['annealing_time'], data['low_temperature'], data['high_temperature']]])

    initial_hydrogen_data = np.array([[                       0,             slab_length],
                                      [data['initial_hydrogen'], data['initial_hydrogen']]])

    model_parameters['Q_star'] = data['heat_of_transport']

    hngd.run.simulation(temperature_data, initial_hydrogen_data, experiment_data, simulation_data, model_parameters,
                        save_results=False, save_last_concentration_profile=True)

#%% Plot

for experiment, data in experimental_data.linear_cases.items():

    # Load experimental and simulated data.

    pos_exp = data['midpoint_location']
    hyd_exp = data['hydrogen_concentration']

    pos_sim, temp_sim, Css_sim, Cp_sim = np.loadtxt(f'Outputs/{experiment}_last_concentration_profile.txt',
                                                    skiprows=1, unpack=True)
    hyd_sim = Css_sim + Cp_sim

    # Plot.

    fig, ax1 = plt.subplots(figsize=(7,4))

    fig.canvas.manager.set_window_title(f'Simulation of the Kammenzind linear case {experiment}')

    ax1.scatter(pos_exp*1e2, hyd_exp, label='Experimental')
    ax1.plot(pos_sim*1e2, hyd_sim, label='Simulated')

    ax1.axhline(y=data['initial_hydrogen'], linestyle='dotted', color='k')

    ax1.annotate(f'$C_0$ = {np.round(data["initial_hydrogen"], 1)} wt.ppm',
                xy=(1.3,data["initial_hydrogen"]), xytext=(0,3), textcoords='offset points', va='bottom')

    ax1.set_xlabel('Distance [cm]')
    ax1.set_ylabel('Hydrogen content [wt.ppm]', color='#1f77b4')

    ax1.set_xlim([0, slab_length*1e2])
    ax1.set_ylim(bottom=0)

    ax1.tick_params(axis='y', labelcolor='#1f77b4')

    ax1.legend(loc='upper center')

    ax2 = ax1.twinx()

    ax2.plot(pos_sim*1e2, temp_sim, color='#ff7f0e', linestyle='dashed')

    ax2.set_ylabel('Temperature [K]', color='#ff7f0e')

    ax2.tick_params(axis='y', labelcolor='#ff7f0e')

    fig.tight_layout()

    fig.savefig(f'Outputs/linear_{experiment}.png', bbox_inches='tight')

plt.show()


#! /usr/bin/python

"""
Цикл лекций некоего Абглазова. Хорошо излагает
https://www.youtube.com/watch?v=9-6NkEK72pM
Попалось на глаза 15 марта 2021
"""

import threading
import time
import serial
import tkinter as tk

#-- глобальные переменные
in_list = []
out_flag = 0

#-- access to port: sudo chmod a+rw /dev/ttyUSB0
ser = serial.Serial("/dev/ttyUSB0", 9600, timeout=1)

#-- функция приема строки
def fn_in():
    global in_list
    while 1:
        in_len = 0
        while in_len < 1:
            in_st = ser.readline()
            in_len = len(in_st)
        in_list.append(in_st)
        time.sleep(1)

#-- запуск потока приема
tr_in = threading.Thread(target=fn_in)
tr_in.daemon = True
tr_in.start()

#-- функция
def fn_out():
    global out_flag
    out_flag = 1

#-- функция
def fn_send():
    out_st = ed.get()
    if len(out_st) > 0:
        ser.write(str.encode(out_st))
        lb.insert(tk.END, ">>> "+out_st)
    ed.delete(0, tk.END)

#-- функция вывода строк текста в листбокс
def fn_disp():
    global out_flag
    while len(in_list) > 0:
        st = in_list.pop(0)
        lb.insert(tk.END, st)
    if out_flag:
        fn_send()
        out_flag = 0
    root.after(100, fn_disp)

root = tk.Tk()
lb = tk.Listbox(root, width=20, height=5, font=('Calibri', 50))
lb.pack()
ed = tk.Entry(root, width=20, font=('Calibri', 50))
ed.pack()
bt = tk.Button(root, text="SEND", width=20, command=fn_out, font=('Calibri', 50))
bt.pack()
root.after(10,fn_disp)
root.mainloop()


import matplotlib.gridspec as gridspec
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

def plot_means(sim) :

    areas = sim.SELECTED_META_AREAS
    meansdf = sim.meandf
    des_means = sim.targets.iloc[:,2:]
    des_means = des_means.as_matrix()

    fig = plt.figure(figsize=(16, 10))

    if np.any(meansdf.TIC=='NOTIC') :
        for i,area in zip(xrange(len(areas)), areas):

            select = (meansdf.META_AREA==area) & (meansdf.TIC=='NOTIC')
            ax = fig.add_subplot(5,2,(i*2 +1))
            y = meansdf[select].iloc[:,5:-1].as_matrix().T
            ax.plot(y, lw=2)
            x = np.linspace(0,sim.INNER_WINDOW-1, sim.MEASURE_INTERVALS )
            ax.plot(x, des_means[i*2,:], c="red")

    if np.any(meansdf.TIC=='TIC') :
        for i,area in zip(xrange(len(areas)), areas):

            select = (meansdf.META_AREA==area) & (meansdf.TIC=='TIC')
            ax = fig.add_subplot(5,2,(i*2+2))
            y = meansdf[select].iloc[:,5:-1].as_matrix().T
            ax.plot(y, lw=2)
            x = np.linspace(0,sim.INNER_WINDOW-1, sim.MEASURE_INTERVALS )
            ax.plot(x, des_means[((i*2)+1),:], c="red")

# we define a general plot function for a layer
def plot_layer_gs(data,row,xaxis=True, label="layer",N=3) :

    gs = gridspec.GridSpec(rows, 20 )

    # paramenters
    colors = ['r','g','b']    # color types
    xlims =[250,stime+50]    # limits on the x axis
    ylims = [-0.1,4.1]    # limits on the y axis
    linewidth = 2    # width of the plot line
    plotalpha = 0.5    # alpha color of the line
    fillalpha = 0.01    # alpha color of the filled area

    plt.subplot(gs[row,:2])    # plot within the subplot window
    plt.axis("off")
    plt.text(.1,.2,label,fontsize=11)

    plt.subplot(gs[row,2:])    # plot within the subplot window

    # for each channel
    x = arange(stime)
    cols=iter(cm.rainbow(np.linspace(0,1,N)))
    for i in xrange(N) :
        color = next(cols)
        y = data[i,:]
        # plot the line
        plt.plot(y, color=color, linewidth=linewidth, alpha=plotalpha)
        # fill the area below the line
        plt.fill_between(x, y, 0, facecolor=color, alpha=fillalpha)

    plt.xlim(xlims)
    plt.ylabel(label)
    plt.yticks([0,1])
    if not xaxis :
        plt.xticks([])

def plot_raw_layers(sim) :

    # open the plot window (sizes in figsize are in inches)
    f = plt.figure("BASAL GANGLIA-CORTEX SIMULATION EFP",figsize=([10,6]),facecolor='white')

    rows = 6    # we have 6 rows in our figure
    row = 0    # start the row counter
    for area in np.hstack(("DA", sim.SELECTED_META_AREAS )) :

        data = sim.raw_df[sim.raw_df.AREA==area].iloc[:,1:].as_matrix().ravel()
        plot_row_gs(data, row, xaxis=False, label=area)
        row +=1

def plot_ctx_channels(sim) :

    # open the plot window (sizes in figsize are in inches)
    f = plt.figure("CHANNELS",figsize=([10,6]),facecolor='white')

    rows = 10
    cols = (sim.TRIALS-1)/10 +1
    stime = sim.INNER_WINDOW
    gs = gridspec.GridSpec(rows, cols)

    xlims =[-50,stime+50]
    ylims = [-0.5,4.5]
    linewidth = 2.0    # width of the plot line
    plotalpha = 0.8    # alpha color of the line
    fillalpha = 0.1    # alpha color of the filled area

    for win in range(sim.TRIALS-1) :
        win_data = sim.df[(sim.df.AREA=="CTX") & (sim.df.WIN==win) ].iloc[:,5:-1].as_matrix()

        ax = f.add_subplot(gs[int(win%10),int(win/10)])
        ax.plot(win_data.T, linewidth=linewidth, alpha=plotalpha)
        ax.set_xlim(xlims)
        ax.set_ylim(ylims)
        ax.set_axis_off()

# we define a general plot function for a single row
def plot_row_gs(data, row, xaxis=True, label="layer", color="black") :

    stime = data.shape[0]

    gs = gridspec.GridSpec(6, 20 )

    xlims =[250,stime+50] # limits on the x axis

    mmax = 1
    mmin =  .5
    ylims = [-0.5,4.5] # limits on the y axis

    linewidth = 2.0    # width of the plot line
    plotalpha = 0.8    # alpha color of the line
    fillalpha = 0.1    # alpha color of the filled area

    plt.subplot(gs[row,:2])    # plot within the subplot window
    plt.axis("off")
    plt.text(.1,.2,label,fontsize=11)

    plt.subplot(gs[row,2:])    # plot within the subplot window

    y = data
    x = np.arange(stime)

    # plot the line
    plt.plot(y, color=color, linewidth=linewidth, alpha=plotalpha)

    plt.axis("off")
    plt.xlim(xlims)
    plt.ylim(ylims)
    plt.ylabel(label)
    plt.yticks([])
    plt.xticks([])