"""
Plots Figure 5B.
"""

from __future__ import absolute_import, division, print_function

import os

import numpy as np
import matplotlib.pyplot as plt
from six.moves import cPickle, range

from wholecell.io.tablereader import TableReader
from wholecell.utils.sparkline import whitePadSparklineAxis
from wholecell.analysis.analysis_tools import exportFigure
from models.ecoli.analysis import multigenAnalysisPlot
import six

PLOT_GENES_OF_INTEREST = False
PLOT_DENOMINATOR_N_EACH_FREQ_GROUP = False
FIRST_N_GENS = 5

COLOR_F1 = "r"
COLOR_F0 = "y"
COLOR_FSUB = "b"

def remove_xaxis(axis):
	axis.spines["bottom"].set_visible(False)
	axis.tick_params(bottom=False, axis="x", labelbottom=False)
	axis.set_xlabel("")

class Plot(multigenAnalysisPlot.MultigenAnalysisPlot):
	def do_plot(self, seedOutDir, plotOutDir, plotOutFileName, simDataFile, validationDataFile, metadata):
		# Get all cells
		if 0 not in self.ap._path_data["seed"]:
			print("Skipping -- figure5B only runs for seed 0")
			return
		allDir = self.ap.get_cells(seed = [0])

		if len(allDir) <= 1:
			print("Skipping -- figure5B only runs for multigen")
			return

		sim_data = cPickle.load(open(simDataFile, "rb"))
		validation_data = cPickle.load(open(validationDataFile, "rb"))

		# Get mRNA cistrons data
		cistron_ids = sim_data.process.transcription.cistron_data["id"]
		is_mRNA = sim_data.process.transcription.cistron_data['is_mRNA']
		mRNA_cistron_indexes = np.where(is_mRNA)[0]
		mRNA_cistron_ids = np.array([cistron_ids[x] for x in mRNA_cistron_indexes])

		time = []
		time_eachGen = []
		transcribedBool = []
		simulatedSynthProbs = []
		transcriptionEvents = []

		for gen, simDir in enumerate(allDir):
			simOutDir = os.path.join(simDir, "simOut")

			if gen < FIRST_N_GENS:
				main_reader = TableReader(os.path.join(simOutDir, "Main"))
				time += main_reader.readColumn("time").tolist()
				time_eachGen.append(main_reader.readColumn("time").tolist()[0])

			rnaSynthProb = TableReader(os.path.join(simOutDir, "RnaSynthProb"))
			simulatedSynthProb = np.mean(rnaSynthProb.readColumn("rna_synth_prob_per_cistron")[:, mRNA_cistron_indexes], axis = 0)
			simulatedSynthProbs.append(simulatedSynthProb)

			mRNA_counts_reader = TableReader(
				os.path.join(simOutDir, 'mRNACounts'))
			moleculeCounts = mRNA_counts_reader.readColumn("mRNA_cistron_counts")
			moleculeCountsSumOverTime = moleculeCounts.sum(axis = 0)
			mRnasTranscribed = np.array([x != 0 for x in moleculeCountsSumOverTime])
			transcribedBool.append(mRnasTranscribed)

			rnapDataReader = TableReader(os.path.join(simOutDir, "RnapData"))
			rnaInitEvent = rnapDataReader.readColumn("rna_init_event_per_cistron")[:, mRNA_cistron_indexes]

			if gen == 0:
				transcriptionEvents = (rnaInitEvent != 0)
			elif gen < FIRST_N_GENS:
				transcriptionEvents = np.vstack((transcriptionEvents, (rnaInitEvent != 0)))
			else:
				pass

		time = np.array(time)
		time_eachGen.append(time[-1])
		time_eachGen = np.array(time_eachGen)
		transcribedBool = np.array(transcribedBool)
		simulatedSynthProbs = np.array(simulatedSynthProbs)

		indexingOrder = np.argsort(np.mean(simulatedSynthProbs, axis = 0))
		transcribedBoolOrdered = np.mean(transcribedBool, axis = 0)[indexingOrder]
		transcriptionEventsOrdered = transcriptionEvents[:, indexingOrder]
		mRNA_cistron_ids_ordered = mRNA_cistron_ids[indexingOrder]

		## Commented code is used when PLOT_GENES_OF_INTEREST is True
		# raw_data = cPickle.load(open("out/SET_A_000000/rawData.cPickle", "rb"))
		# geneIdToGeneSymbol = {x["id"]: x["symbol"] for x in raw_data.genes}
		# geneSymbolsOrdered = [geneIdToGeneSymbol[x] for x in geneIdsOrdered]
		# cPickle.dump({"geneId": geneIdsOrdered, "geneSymbol": geneSymbolsOrdered}, open(os.path.join(plotOutDir, "figure5B_genes.pickle"), "wb"))

		alwaysPresentIndexes = np.where(transcribedBoolOrdered == 1.)[0]
		neverPresentIndexes = np.where(transcribedBoolOrdered == 0.)[0]
		sometimesPresentIndexes = np.array([x for x in np.arange(len(transcribedBoolOrdered)) if x not in alwaysPresentIndexes and x not in neverPresentIndexes])
		colors = np.repeat(COLOR_FSUB, len(transcribedBoolOrdered))
		colors[alwaysPresentIndexes] = COLOR_F1
		colors[neverPresentIndexes] = COLOR_F0
		always = transcribedBoolOrdered[alwaysPresentIndexes]
		never = transcribedBoolOrdered[neverPresentIndexes]
		sometimes = transcribedBoolOrdered[sometimesPresentIndexes]

		alwaysTranscriptionEvents = []
		for i in alwaysPresentIndexes:
			v = (time[transcriptionEventsOrdered[:, i]] / 3600.).tolist()
			if transcriptionEventsOrdered[:, i].sum() == 0:
				v = [-1]
			alwaysTranscriptionEvents.append(v)

		neverTranscriptionEvents = []
		for i in neverPresentIndexes:
			v = (time[transcriptionEventsOrdered[:, i]] / 3600.).tolist()
			if transcriptionEventsOrdered[:, i].sum() == 0:
				v = [-1]
			neverTranscriptionEvents.append(v)

		sometimesTranscriptionEvents = []
		for i in sometimesPresentIndexes:
			v = (time[transcriptionEventsOrdered[:, i]] / 3600.).tolist()
			if transcriptionEventsOrdered[:, i].sum() == 0:
				v = [-1]
			sometimesTranscriptionEvents.append(v)

		# Plot
		fig = plt.figure(figsize = (16, 8))
		scatterAxis = plt.subplot2grid((2, 4), (0, 0), colspan = 3, rowspan = 2)
		histAxis = plt.subplot2grid((2, 4), (0, 3), colspan = 1, rowspan = 2, sharey = scatterAxis)

		scatterAxis.scatter(np.arange(len(transcribedBoolOrdered)), transcribedBoolOrdered, marker = 'o', facecolors = colors, edgecolors = "none", s = 20)
		scatterAxis.set_xlim([0, len(transcribedBoolOrdered)])
		scatterAxis.set_ylim([0, 1])
		whitePadSparklineAxis(scatterAxis)

		N, bins, patches = histAxis.hist(transcribedBoolOrdered, bins = len(allDir) + 1, orientation = 'horizontal')
		for i in range(1, len(patches) - 1):
			plt.setp(patches[i], facecolor = "none", edgecolor = COLOR_FSUB)
		plt.setp(patches[0], facecolor = "none", edgecolor = COLOR_F0)
		plt.setp(patches[-1], facecolor = "none", edgecolor = COLOR_F1)
		histAxis.set_xscale("log")
		whitePadSparklineAxis(histAxis)
		histAxis.xaxis.tick_bottom()
		histXmin, histXmax = histAxis.get_xlim()

		scatterAxis.set_ylim([-.01, 1.01])
		scatterAxis.set_yticklabels([])
		scatterAxis.set_xticklabels([])
		histAxis.set_yticklabels([])
		histAxis.set_xticklabels([])

		plt.subplots_adjust(wspace = 0.6, hspace = 0.4, right = 0.9, bottom = 0.1, left = 0.1, top = 0.9)
		exportFigure(plt, plotOutDir, "figure5B__top__clean", "")

		if PLOT_GENES_OF_INTEREST:
			## Identifying particular genes
			dcurId = "G7826_RNA"
			clppId = "EG10158_RNA"
			dcucId = "G6347_RNA"
			dcurIndex = np.where(mRNA_cistron_ids_ordered == dcurId)[0]
			clppIndex = np.where(mRNA_cistron_ids_ordered == clppId)[0]
			dcucIndex = np.where(mRNA_cistron_ids_ordered == dcucId)[0]

			scatterAxis.scatter(dcurIndex, transcribedBoolOrdered[dcurIndex], facecolor = "orange", edgecolors = "none")
			scatterAxis.scatter(clppIndex, transcribedBoolOrdered[clppIndex], facecolor = "orange", edgecolors = "none")
			scatterAxis.scatter(dcucIndex, transcribedBoolOrdered[dcucIndex], facecolor = "orange", edgecolors = "none")
			scatterAxis.text(dcurIndex + 500, transcribedBoolOrdered[dcurIndex], "dcuR", fontsize = 18)
			scatterAxis.text(clppIndex + 500, transcribedBoolOrdered[clppIndex], "clpP", fontsize = 18)
			scatterAxis.text(dcucIndex + 500, transcribedBoolOrdered[dcucIndex], "dcuC", fontsize = 18)
			exportFigure(plt, plotOutDir, "figure5B__top__clean__genes", "")

		plt.suptitle("Frequency of observing at least 1 transcript per generation", fontsize = 14)
		scatterAxis.set_xlabel("Genes ordered by simulated synthesis probability", fontsize = 12)
		histAxis.text(histAxis.get_xlim()[1] * 1.6, 0, "%s genes\n(%0.1f%%)" % (len(never), 100. * (len(never) / float(len(transcribedBoolOrdered)))), fontsize = 14, verticalalignment = "center", color = COLOR_F0)
		histAxis.text(histAxis.get_xlim()[1] * 1.6, 1, "%s genes\n(%0.1f%%)" % (len(always), 100. * (len(always) / float(len(transcribedBoolOrdered)))), fontsize = 14, verticalalignment = "center", color = COLOR_F1)
		histAxis.text(histAxis.get_xlim()[1] * 1.6, 0.5, "%s genes\n(%0.1f%%)" % (len(sometimes), 100. * (len(sometimes) / float(len(transcribedBoolOrdered)))), fontsize = 14, verticalalignment = "center", color = COLOR_FSUB)
		scatterAxis.set_yticklabels([0, 1])
		scatterAxis.set_xticklabels([0, len(transcribedBoolOrdered)])
		histAxis.set_yticklabels([0, 1])
		histAxis.set_xticklabels([histXmin, histXmax])
		exportFigure(plt, plotOutDir, "figure5B__top", metadata)
		plt.close("all")

		fig = plt.figure(figsize = (16, 8))
		alwaysAxis = plt.subplot(2, 1, 1)
		sometimesAxis = plt.subplot(2, 1, 2, sharex = alwaysAxis)

		alwaysAxis.eventplot(alwaysTranscriptionEvents, orientation = "horizontal", linewidths = 2., linelengths = 4., color = COLOR_F1)
		alwaysAxis.set_xlim([0, time[-1] / 3600.])
		alwaysAxis.set_ylim([-1, len(always)])
		alwaysAxis.set_xticks([])
		alwaysAxis.set_yticks([])
		alwaysAxis.tick_params(top=False, bottom=False)
		alwaysAxis.tick_params(axis="x", labelbottom=False)

		sometimesAxis.eventplot(sometimesTranscriptionEvents, orientation = "horizontal", linewidths = 2., linelengths = 4., color = COLOR_FSUB)
		sometimesAxis.set_xlim([0, time[-1] / 3600.])
		sometimesAxis.set_ylim([-1, len(sometimes)])
		sometimesAxis.set_xticks([0, time[-1] / 3600.])
		sometimesAxis.set_yticks([])
		sometimesAxis.tick_params(top=False)
		sometimesAxis.tick_params(which = 'both', direction = 'out', labelsize = 12)
		sometimesXmin, sometimesXmax = sometimesAxis.get_xlim()
		time_eachGen = np.array(time_eachGen)
		sometimesAxis.set_xticks(time_eachGen / 3600.)
		sometimesAxis.set_xticklabels([])

		plt.subplots_adjust(wspace = 0, hspace = 0, right = 0.9, bottom = 0.1, left = 0.1, top = 0.9)
		exportFigure(plt, plotOutDir, "figure5B__bottom__clean")

		plt.suptitle("Transcription initiation events", fontsize = 14)
		alwaysAxis.set_ylabel("Freq. = 1", fontsize = 14)
		sometimesAxis.set_ylabel("0 < Freq. < 1", fontsize = 14)
		sometimesAxis.set_xlabel("Time (gens)", fontsize = 14)
		sometimesAxis.set_xticklabels(np.arange(FIRST_N_GENS + 1))
		exportFigure(plt, plotOutDir, "figure5B__bottom", metadata)
		plt.close("all")

		# Figure 5E
		nRed = len(never)
		nGreen = len(sometimes)
		nBlue = len(always)

		plotRed = 0
		plotGreen = 0
		plotBlue = 0

		mRNA_id_set = set(mRNA_cistron_ids_ordered)

		essential_genes_cistrons = validation_data.essential_genes.essential_cistrons
		for g in essential_genes_cistrons:
			if g not in mRNA_id_set:
				continue
			i = np.where(mRNA_cistron_ids_ordered == str(g))[0][0]
			f = transcribedBoolOrdered[i]

			if f == 0.0:
				plotRed += 1
			elif f == 1.0:
				plotBlue += 1
			else:
				plotGreen += 1
		xloc = np.arange(3)
		width = 0.8

		fig = plt.figure()
		ax = plt.subplot(1, 1, 1)
		ax.bar(xloc + width, [plotRed / float(len(essential_genes_cistrons)), plotGreen / float(len(essential_genes_cistrons)), plotBlue / float(len(essential_genes_cistrons))], width, color = [COLOR_F0, COLOR_FSUB, COLOR_F1], edgecolor = "none")
		whitePadSparklineAxis(ax)
		ax.spines["left"].set_position(("outward", 0))
		ax.set_yticks([0.0, 0.2, 0.4, 0.6, 0.8])
		ax.set_yticklabels(["0%", "20%", "40%", "60%", "80%"])
		ax.set_ylabel("Percentage of essential genes")
		ax.set_xticks(xloc + 1.5 * width)
		ax.set_xticklabels(["%s / %s" % (plotRed, len(essential_genes_cistrons)), "%s / %s" % (plotGreen, len(essential_genes_cistrons)), "%s / %s" % (plotBlue, len(essential_genes_cistrons))])
		ax.set_xlabel("Total number of essential genes: %s" % len(essential_genes_cistrons))
		plt.subplots_adjust(right = 0.9, bottom = 0.15, left = 0.2, top = 0.9)
		exportFigure(plt, plotOutDir, "figure5E", metadata)

		ax.set_yticklabels([])
		ax.set_ylabel("")
		remove_xaxis(ax)
		plt.savefig(os.path.join(plotOutDir, "figure5E__clean.pdf"))

		if PLOT_DENOMINATOR_N_EACH_FREQ_GROUP:
			fig = plt.figure()
			ax = plt.subplot(1, 1, 1)
			ax.bar(xloc + width, [plotRed / float(nRed), plotGreen / float(nGreen), plotBlue / float(nBlue)], width, color = [COLOR_F0, COLOR_FSUB, COLOR_F1], edgecolor = "none")
			whitePadSparklineAxis(ax)
			ax.spines["left"].set_position(("outward", 0))
			ax.set_yticks([0.0, 0.1, 0.2])
			ax.set_yticklabels(["0%", "10%", "20%"])
			ax.set_ylabel("Percentage of genes that are essential genes")
			ax.set_xticks(xloc + 1.5 * width)
			ax.set_xticklabels(["%s / %s" % (plotRed, nRed), "%s / %s" % (plotGreen, nGreen), "%s / %s" % (plotBlue, nBlue)])
			plt.subplots_adjust(right = 0.9, bottom = 0.1, left = 0.2, top = 0.9)
			exportFigure(plt, plotOutDir, "figure5E_v2", metadata)
		plt.close()

		# Figure 5F and 5G
		geneFunctions = validation_data.geneFunctions.geneFunctions
		unknown = {"r": 0, "g": 0, "b": 0}
		resistance = {"r": 0, "g": 0, "b": 0}
		for frameID, function_ in six.viewitems(geneFunctions):
			try:
				i = np.where([frameID in x for x in mRNA_cistron_ids_ordered])[0][0]
			# Skip over genes that aren't used in the simulation
			except IndexError:
				continue
			if function_ in ["Unknown function", "Unclear/under-characterized"]:
				f = transcribedBoolOrdered[i]
				if f == 0.0:
					unknown["r"] += 1
				elif f == 1.0:
					unknown["b"] += 1
				else:
					unknown["g"] += 1

			elif function_ in ["Antibiotic resistance", "Toxin/antitoxin"]:
				f = transcribedBoolOrdered[i]
				if f == 0.0:
					resistance["r"] += 1
				elif f == 1.0:
					resistance["b"] += 1
				else:
					resistance["g"] += 1

		nUnknown = np.sum([unknown[x] for x in ["r", "g", "b"]])
		fig = plt.figure()
		ax = plt.subplot(1, 1, 1)
		ax.bar(xloc + width, [unknown["r"] / float(nUnknown), unknown["g"] / float(nUnknown), unknown["b"] / float(nUnknown)], width, color = [COLOR_F0, COLOR_FSUB, COLOR_F1], edgecolor = "none")
		whitePadSparklineAxis(ax)
		ax.spines["left"].set_position(("outward", 0))
		ax.set_yticks([0.0, 0.2, 0.4, 0.6, 0.8])
		ax.set_yticklabels(["0%", "20%", "40%", "60%", "80%"])
		ax.set_ylabel("Percentage of poorly understood / annotated genes")
		ax.set_xticks(xloc + 1.5 * width)
		ax.set_xticklabels(["%s / %s" % (unknown["r"], nUnknown), "%s / %s" % (unknown["g"], nUnknown), "%s / %s" % (unknown["b"], nUnknown)])
		ax.set_xlabel("Total number of poorly understood / annotated genes: %s" % nUnknown)
		plt.subplots_adjust(right = 0.9, bottom = 0.15, left = 0.2, top = 0.9)
		exportFigure(plt, plotOutDir, "figure5F", metadata)

		ax.set_yticklabels([])
		ax.set_ylabel("")
		remove_xaxis(ax)
		plt.savefig(os.path.join(plotOutDir, "figure5F__clean.pdf"))

		if PLOT_DENOMINATOR_N_EACH_FREQ_GROUP:
			fig = plt.figure()
			ax = plt.subplot(1, 1, 1)
			ax.bar(xloc + width, [unknown["r"] / float(nRed), unknown["g"] / float(nGreen), unknown["b"] / float(nBlue)], width, color = [COLOR_F0, COLOR_FSUB, COLOR_F1], edgecolor = "none")
			whitePadSparklineAxis(ax)
			ax.spines["left"].set_position(("outward", 0))
			ax.set_yticks([0.0, 0.2, 0.4, 0.6])
			ax.set_yticklabels(["0%", "20%", "40%", "60%"])
			ax.set_ylabel("Percentage of genes that are poorly understood / annotated")
			ax.set_xticks(xloc + 1.5 * width)
			ax.set_xticklabels(["%s / %s" % (unknown["r"], nRed), "%s / %s" % (unknown["g"], nGreen), "%s / %s" % (unknown["b"], nBlue)])
			plt.subplots_adjust(right = 0.9, bottom = 0.1, left = 0.2, top = 0.9)
			exportFigure(plt, plotOutDir, "figure5F_v2", metadata)
		plt.close()

		nResistance = float(np.sum([resistance[x] for x in ["r", "g", "b"]]))
		fig = plt.figure()
		ax = plt.subplot(1, 1, 1)
		ax.bar(xloc + width, [resistance["r"] / nResistance, resistance["g"] / nResistance, resistance["b"] / nResistance], width, color = [COLOR_F0, COLOR_FSUB, COLOR_F1], edgecolor = "none")
		whitePadSparklineAxis(ax)
		ax.spines["left"].set_position(("outward", 0))
		ax.set_yticks([0.0, 0.2, 0.4, 0.6, 0.8])
		ax.set_yticklabels(["0%", "20%", "40%", "60%", "80%"])
		ax.set_ylabel("Percentage of antibiotic related genes")
		ax.set_xticks(xloc + 1.5 * width)
		ax.set_xticklabels(["%s / %s" % (resistance["r"], int(nResistance)), "%s / %s" % (resistance["g"], int(nResistance)), "%s / %s" % (resistance["b"], int(nResistance))])
		ax.set_xlabel("Total number of antibiotic related genes: %s" % int(nResistance))
		plt.subplots_adjust(right = 0.9, bottom = 0.15, left = 0.2, top = 0.9)
		exportFigure(plt, plotOutDir, "figure5G", metadata)

		ax.set_yticklabels([])
		ax.set_ylabel("")
		remove_xaxis(ax)
		exportFigure(plt, plotOutDir, "figure5G__clean", "")

		if PLOT_DENOMINATOR_N_EACH_FREQ_GROUP:
			fig = plt.figure()
			ax = plt.subplot(1, 1, 1)
			ax.bar(xloc + width, [resistance["r"] / float(nRed), resistance["g"] / float(nGreen), resistance["b"] / float(nBlue)], width, color = [COLOR_F0, COLOR_FSUB, COLOR_F1], edgecolor = "none")
			whitePadSparklineAxis(ax)
			ax.spines["left"].set_position(("outward", 0))
			ax.set_yticks([0.0, 0.025])
			ax.set_yticklabels(["0%", "2.5%"])
			ax.set_ylabel("Percentage of genes that are antibiotic related")
			ax.set_xticks(xloc + 1.5 * width)
			ax.set_xticklabels(["%s / %s" % (resistance["r"], nRed), "%s / %s" % (resistance["g"], nGreen), "%s / %s" % (resistance["b"], nBlue)])
			plt.subplots_adjust(right = 0.9, bottom = 0.1, left = 0.2, top = 0.9)
			exportFigure(plt, plotOutDir, "figure5G", metadata)
		plt.close()

if __name__ == "__main__":
	Plot().cli()


def eh_identidade(matriz):
    if (len(matriz) != len(matriz[0])): return False
    i = 0
    j = 0

    while(i < len(matriz)):
        while(j < len(matriz[i])):
            if(i != j and matriz[i][j] != 0): return False
            elif(i == j and matriz[i][j] != 1): return False
            j += 1
        j = 0

        i += 1

    return True

#print(eh_identidade([[1, 0, 0], [0, 0, 0], [0, 0, 1]]))


from .prints import prints
import requests
import time
import urllib3

OK = ()
ERROR = ()

STATUS_CODE_LIST = "other/http_status_codes.csv"

class Requests:
    """Just a wrapper for sending requests with the correct user runtime options"""
    def __init__(self, cmd_args):
        self.agent = cmd_args.agent
        self.cookies = self.validate_cookies(cmd_args.cookies)
        self.http_header = cmd_args.header
        self.proxy = cmd_args.proxy

        self.code_dict = self.populate_code_dict()

        self.last_request = None
        self.last_response = None
        self.time_taken = None

    def validate_agent(self):
        # TODO
        pass

    def random_agent(self):
        # TODO
        pass

    def validate_cookies(self, cookies):
        """Validates the cmdline cookies passed to crabsticks"""
        validated_cookies = dict()
        if cookies is None:
            return validated_cookies
        try:
            pairs = cookies.split(";")
            for pair in pairs:
                validated_cookies[pair.split("=")[0]] = pair.split("=")[1]
            return validated_cookies
        except IndexError:
            prints(f"Could not validate cookies {cookies}", "error")
            prints(f'Example:\t cookies="security=low; PHPSESSID=ac342fa8793966be6d0732dc872ca0c9"', "info")
        exit()

    def validate_header(self):
        # TODO
        pass

    def validate_proxy(self):
        # TODO
        pass

    @staticmethod
    def populate_code_dict():
        """Creates a dictionary containing information about status codes"""
        list_of_dicts = []
        with open(STATUS_CODE_LIST, "r") as f:
            for line in f.readlines():
                clean = line.strip("\n")
                data = clean.split(",")
                if "Code" in data[0]:
                    continue
                list_of_dicts.append({"Code": data[0].strip(" "),
                                      "Name": data[1].strip(" "),
                                      "Type": data[2].strip(" "),
                                      "Info": data[3]
                                      })
        return list_of_dicts

    def send_get(self, url):
        """
        Sends a HTTP request
        :param url: URL to send it too
        :return: Returns the request
        """
        start = time.time()
        try:
            urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
            r = requests.get(url, headers={'User-Agent': "tettra_"}, cookies=self.cookies, proxies=self.proxy, verify=False)
            self.time_taken = time.time() - start
            self.last_request = r
            return self.get_data()
        except requests.exceptions.ConnectionError as e:
            print()
            prints(str(e), "error")
            print()
            return False
        except requests.exceptions.MissingSchema:
            prints("")

    def get_data(self):
        return self.Status(self.last_request, self.code_dict, self.time_taken)

    class Status:
        """Quick way of getting all the information about a request, if it failed etc"""
        def __init__(self, last_request, code_dict, time_taken):
            self.code_dict = code_dict
            self.last_request = last_request
            self.results = self.parse_status()

            self.response_time = time_taken
            self.status_code = self.results["Code"]
            self.status_name = self.results["Name"]
            self.status_type = self.results["Type"]
            self.status_info = self.results["Info"]
            self.text = last_request.text

        def parse_status(self):
            """
            Calculates the type of status code the last request responded with then uses this to search through the CSV
            dict to grab all the info about that type of request
            :return:
            """
            last_status = self.last_request.status_code
            for dicts in self.code_dict:
                if int(dicts["Code"]) == last_status:
                    return dicts
            prints(f"Status Code not found {self.last_request.status_code}", "error")
            return False

class Request_interface:
    """Dependency injection to allow calling the Requeset class,
    whithout having to have an object with attributes"""
    def __init__(self, agent, cookie, header, proxy):
        self.agent = agent
        self.cookie = cookie
        self.header = header
        self.proxy = proxy

    def get_interface(self):
        return self


'''
@author: Irfan Nur Afif
'''

def buildIndex(diction):
	dictionary=diction
	file_out = open('tweetindex.csv', 'w')
	all_df = []
	for term in sorted(dictionary):
		tweetIDs=dictionary[term]
		file_out.write(term+"; ")
		frequency_map={}
		for idtweet in tweetIDs:
			#file_out.write(str(idtweet)+",")
			tweetID=frequency_map.get(idtweet,None)
			if(tweetID==None):
				frequency_map[idtweet]=1
			else:
				frequency_map[idtweet]=frequency_map[idtweet]+1
		leng=len(frequency_map)
		all_df.append(leng)
		iterator=0
		for idtweet in sorted(frequency_map):
			file_out.write(str(idtweet)+","+str(frequency_map[idtweet]))
			if iterator==leng-1:
				file_out.write("\n")
			else:
				file_out.write(";")
			iterator=iterator+1
	file_out.close()
	return all_df


"""Description of changes

Revision ID: 1699a92bae3d
Revises: f5e6b5a61337
Create Date: 2023-07-31 13:08:59.203041

"""
from alembic import op
import sqlalchemy as sa

# revision identifiers, used by Alembic.
revision = '1699a92bae3d'
down_revision = 'f5e6b5a61337'
branch_labels = None
depends_on = None

def upgrade() -> None:
    # ### commands auto generated by Alembic - please adjust! ###
    op.drop_index('ix_user_email', table_name='user')
    op.create_index(op.f('ix_user_email'), 'user', ['email'], unique=False)
    # ### end Alembic commands ###

def downgrade() -> None:
    # ### commands auto generated by Alembic - please adjust! ###
    op.drop_index(op.f('ix_user_email'), table_name='user')
    op.create_index('ix_user_email', 'user', ['email'], unique=False)
    # ### end Alembic commands ###


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

"""This module implements a data structure and associated methods for modelling Chicken - and - Foxes problems.
"""
__author__ = "Amittai"
__copyright__ = "Copyright 2021"
__credits__ = ["Amittai", "Alberto Quattrini Li"]
__email__ = "Amittai.J.Wekesa.24@dartmouth.edu"
__github__ = "@siavava"

class FoxProblem:
    def __init__(self, start_state=(3, 3, 1)):
        self.start_state = start_state
        self.goal_state = (0, 0, 0)
        self.state = start_state
        self.total_chickens = start_state[0]
        self.total_foxes = start_state[1]
        self.boat_ashore = bool(start_state[2])

        # you might want to add other things to the problem,
        #  like the total number of chickens (which you can figure out
        #  based on start_state

    # get successor states for the given state
    def get_successors(self, state):
        # you write this part. I also had a helper function
        #  that tested if states were safe before adding to successor list
        next_states = set()
        for num_chickens in range(0, 3):
            for num_foxes in range(0, 3):
                total = num_chickens + num_foxes
                # print("total = ", total)
                if 1 <= total <= 2:  # ignore states the empty transition

                    if state[2] == 1:
                        # BOAT LEAVING SHORE
                        new_chickens = state[0] - num_chickens  # find new number of chicken ashore
                        new_foxes = state[1] - num_foxes  # find new number of foxes ashore
                        next_state = (new_chickens, new_foxes, 0)

                        # check the state for validity, append to valid states
                        if self.is_valid(next_state):
                            # print("2", next_state)
                            next_states.add(next_state)

                    elif state[2] == 0:
                        # BOAT RETURNING TO SHORE
                        new_chickens = state[0] + num_chickens  # find new number of chicken ashore
                        new_foxes = state[1] + num_foxes  # find new number of foxes ashore
                        next_state = (new_chickens, new_foxes, 1)

                        # check the state for validity, append to valid states
                        if self.is_valid(next_state):
                            next_states.add(next_state)
        # return set of states
        return next_states

    # I also had a goal test method. You should write one.
    def is_goal(self, state):
        return self.goal_state == state

    def is_valid(self, state):

        # A valid state cannot have negative chickens / foxes
        if state[0] < 0 or state[1] < 0:
            return False

        new_chicken_count = state[0]
        chickens_side_B = self.total_chickens - new_chicken_count

        new_fox_count = state[1]
        foxes_side_B = self.total_foxes - new_fox_count

        # 1, make sure proposed move is within bounds of how many chickens and foxes are available.
        if new_chicken_count <= self.total_chickens and new_fox_count <= self.total_foxes:

            # 2, if chickens >= foxes on both sides of the bank, move is valid.
            if new_chicken_count >= new_fox_count and chickens_side_B >= foxes_side_B:
                return True

            # 3, otherwise, if there are more foxes on a bank that has 0 chickens, move is valid.
            elif new_chicken_count < new_fox_count and new_chicken_count == 0:
                return True
            elif chickens_side_B < foxes_side_B and chickens_side_B == 0:
                return True

        # 4 move is invalid
        return False

    def __str__(self):
        string = "Chickens and foxes problem: " + str(self.start_state)
        return string

# A bit of test code

def check_states(state, goal_state):
    if state == goal_state:
        print("Found!")
        return

    print(test_cp.get_successors(state))
    for n_state in test_cp.get_successors(state):
        check_states(n_state, goal_state)

if __name__ == "__main__":
    test_cp = FoxProblem((5, 5, 1))
    print(test_cp.get_successors((5, 5, 1)))
    start_state = (5, 5, 1)
    goal_state = (0, 0, 0)
    check_states(start_state, goal_state)
    # while True:

    print(test_cp)

# Note: I used these loops to hunt for a path to the solution for the (3, 3, 1) search problem using brute force.

    # To test next states
    # start_state = (3, 3, 1)
    # test2 = FoxProblem(start_state)
    # print(test2.get_successors((0, 3, 1)))
    # for n_state in test2.get_successors(start_state):
    #     for next_state_2 in test2.get_successors(n_state):
    #         for next_state_3 in test2.get_successors(next_state_2):
    #             for next_state_4 in test2.get_successors(next_state_3):
    #                 print(f"{start_state} "
    #                       f"-> {n_state} "
    #                       f"-> {next_state_2} "
    #                       f"-> {next_state_3} "
    #                       f"-> {next_state_4} "
    #                       f"-> {test2.get_successors(next_state_4)}")
    # print(test2.get_successors((3, 3, 1)))


'''Spencer Schill, SDEV300
This project uses pandas to read a set of data from an excel sheet
and uses matplotlib to graph the data from the excel sheets and print a graph of the data'''

import pandas as pd
import matplotlib.pyplot as plt

def popChange(sub_option):                          #PopChange method
    df = pd.read_csv('PopChange.csv')               #reads PopChange.csv in project folder

    if sub_option == 'a':                           #menu options for PopChange
        print("You selected Pop Apr 1")
        column = df['Pop Apr 1']
    elif sub_option == 'b':
        print("You selected Pop Jul 1")
        column = df['Pop Jul 1']
    else:
        print("You selected Change pop")
        column = df['Change Pop']

    #prints the statistics for PopChange

    print(f'''Count = {column.count():.1f} \nMean = {column.mean():.1f} \nStandard Deviation = {column.std():.1f}
    \nMin = {column.min():.1f}\nMax = {column.max():.1f}''')
    print('The Histogram of this column is now displayed.')

                        #make histogram
    n, bins, patches = plt.hist(column, 40, density=True, facecolor='b',alpha=0.75)

    plt.grid(True)
                    #Assign to a grid
    fig=plt
                    #Save figure in folder where program is
    fig.savefig(f'popchange-{sub_option}.png')

def Housing(sub_option):                    #Housing method
    df = pd.read_csv('Housing.csv')         #read Housing.csv in project folder

    if sub_option == 'a':                   #menu options for Housing
        print('You selected Age')
        column = df['AGE']
    elif sub_option == 'b':
        print('You selected BEDRMS')
        column = df['BEDRMS']
    elif sub_option == 'c':
        print('You selected BUILT')
        column = df['BUILT']
    elif sub_option == 'd':
        print('You selected ROOMS')
        column = df['ROOMS']
    else:
        print('You selected UTILITY')
        column = df['UTILITY']

        #Print the statistics for Housing

    print(
        f'''Count = {column.count():.1f} \nMean = {column.mean():.1f} \nStandard Deviation = {column.std():.1f}
        \nMin = {column.min():.1f}\nMax = {column.max():.1f}''')
    print('The Histogram of this column is now displayed.')

                    #make histogram
    n, bins, patches = plt.hist(column, 10, density=True, facecolor='b', alpha=0.75)
    plt.grid(True)
                    #assign hist to grid
    fig = plt
                    #save figure in folder where program is
    fig.savefig(f'housing-{sub_option}.png')

#Main program
if __name__ == "__main__":
    print("------- Welcome to the Python Data Analysis App --------")
    while (True):                                               #while loop menu
        print("1. Population data")
        print("2. Housing Data")
        print("3. Exit the program")
        main_option = int(input("Select the file you want to analyze: "))            #user input option
        if main_option == 3:
            print("Thank you for using the python analysis program")                    #break if user wants to exit
            break
        if main_option == 1:                            #PopChange menu
            while (True):
                print("a. Pop Apr 1")
                print("b. Pop Jul 1")
                print("c. Change Pop")
                print("d. Exit Column")
                sub_option = input("Select the column you want to analyze: ")
                if sub_option.lower() == 'd':
                    print('You selected to exit the column menu')
                    break
                if sub_option.lower() in ['a', 'b', 'c']:
                    popChange(sub_option)
                else:
                    print('Please select from one of the menu items')
        if main_option == 2:                                            #Housing menu
            while (True):
                print("a. AGE")
                print("b. BEDRMS")
                print("c. BUILT")
                print("d. ROOMS")
                print("e. UTILITY")
                print("f. Exit Column")
                sub_option = input("Select the Column you want to analyze: ")
                if sub_option.lower() == 'f':
                    print('You selected to exit the column menu')
                    break
                if sub_option.lower() in ['a', 'b', 'c', 'd', 'e']:
                    Housing(sub_option)
                else:                                                       #if user inputs option not on menu
                    print('Please select from one of the menu items')

        else:                                                               #if user inputs option not on menu
            print('Please select from one of the menu items ')


import argparse
import os
import csv
from elasticsearch import Elasticsearch, helpers, exceptions

try:
    es = Elasticsearch(['192.168.0.26:9200'])
except exceptions.ConnectionError:
    raise Exception('Could not connect to 192.168.0.26:9200')

def main(args):
    for i in os.listdir(args.input):
        with open(os.path.join(args.input, i)) as f:
            it = csv.DictReader(f)
            helpers.bulk(
                client=es,
                actions=it,
                index='dummy_index',
                doc_type='person'
            )

def parse_args():
    parser = argparse.ArgumentParser()
    parser.add_argument('--input', required=True)
    return parser.parse_args()

if __name__ == '__main__':
    main(parse_args())


import argparse
import numpy as np
import time
import os
import torch

from dataset.transforms import ValTransforms
from dataset.coco import COCODataset, coco_class_index, coco_class_labels
from utils.com_flops_params import FLOPs_and_Params
from utils import fuse_conv_bn
from utils.misc import load_weight

from config import build_config
from models import build_model

def parse_args():
    parser = argparse.ArgumentParser(description='FreeYOLO')
    # Model
    parser.add_argument('-v', '--version', default='yolo_free_large', type=str,
                        help='build yolo')
    parser.add_argument('--fuse_conv_bn', action='store_true', default=False,
                        help='fuse conv and bn')
    parser.add_argument('--conf_thresh', default=0.1, type=float,
                        help='confidence threshold')
    parser.add_argument('--nms_thresh', default=0.45, type=float,
                        help='NMS threshold')
    parser.add_argument('--topk', default=100, type=int,
                        help='NMS threshold')
    parser.add_argument("--no_decode", action="store_true", default=False,
                        help="not decode in inference or yes")

    # data root
    parser.add_argument('--root', default='/mnt/share/ssd2/dataset',
                        help='data root')
    # basic
    parser.add_argument('-size', '--img_size', default=608, type=int,
                        help='the min size of input image')
    parser.add_argument('--weight', default=None,
                        type=str, help='Trained state_dict file path to open')
    # cuda
    parser.add_argument('--cuda', action='store_true', default=False,
                        help='use cuda.')

    return parser.parse_args()

def test(net, device, img_size, testset, transform):
    # Step-1: Compute FLOPs and Params
    FLOPs_and_Params(model=net,
                     img_size=img_size,
                     device=device)

    # Step-2: Compute FPS
    num_images = 2002
    total_time = 0
    count = 0
    with torch.no_grad():
        for index in range(num_images):
            if index % 500 == 0:
                print('Testing image {:d}/{:d}....'.format(index+1, num_images))
            image, _ = testset.pull_image(index)

            orig_h, orig_w, _ = image.shape

            # prepare
            x = transform(image)[0]
            x = x.unsqueeze(0).to(device)

            # star time
            torch.cuda.synchronize()
            start_time = time.perf_counter()

            # inference
            bboxes, scores, cls_inds = net(x)

            # rescale
            bboxes *= max(orig_h, orig_w)

            # end time
            torch.cuda.synchronize()
            elapsed = time.perf_counter() - start_time

            # print("detection time used ", elapsed, "s")
            if index > 1:
                total_time += elapsed
                count += 1

        print('- FPS :', 1.0 / (total_time / count))

if __name__ == '__main__':
    args = parse_args()
    # cuda
    if args.cuda:
        print('use cuda')
        device = torch.device("cuda")
    else:
        device = torch.device("cpu")

    # dataset
    print('test on coco-val ...')
    data_dir = os.path.join(args.root, 'COCO')
    class_names = coco_class_labels
    class_indexs = coco_class_index
    num_classes = 80
    dataset = COCODataset(
                data_dir=data_dir,
                image_set='val2017',
                img_size=args.img_size)

    # config
    cfg = build_config(args)

    # build model
    model = build_model(args=args,
                        cfg=cfg,
                        device=device,
                        num_classes=num_classes,
                        trainable=False)

    # load trained weight
    model = load_weight(device=device,
                        model=model,
                        path_to_ckpt=args.weight)

    # fuse conv bn
    if args.fuse_conv_bn:
        print('fuse conv and bn ...')
        model = fuse_conv_bn.fuse_conv_bn(model)

    # transform
    transform = ValTransforms(img_size=args.img_size)

    # run
    test(net=model,
        img_size=args.img_size,
        device=device,
        testset=dataset,
        transform=transform
        )


from django.urls import path
from . import views

app_name = "discussions"

urlpatterns = [
    path(
        "v1/discussions-list/",
        views.DiscussionListCreateView.as_view(),
        name="discussions-list",
    ),
    path(
        "v1/discussion/<int:pk>/",
        views.DiscussionRetrieveUpdateView.as_view(),
        name="discussion-retrieve-update-view",
    ),
    path(
        "v1/<int:discussion_id>/messages/",
        views.MessageListCreateView.as_view(),
        name="create-discussion-messages",
    ),
    path(
        "v1/<int:discussion_id>/messages/<int:pk>/",
        views.MessageUpdateView.as_view(),
        name="update-discussion-messages",
    ),
    # Scheme Discussions
    path(
        "v1/scheme-discussions-list/",
        views.SchemeDiscussionListCreateView.as_view(),
        name="scheme-discussions-list",
    ),
    path(
        "v1/scheme-discussion/<int:pk>/",
        views.SchemeDiscussionRetrieveUpdateView.as_view(),
        name="scheme-discussion-retrieve-update-view",
    ),
    path(
        "v1/scheme-discussion/<int:discussion_id>/messages/",
        views.SchemeMessageListCreateView.as_view(),
        name="create-scheme-discussion-messages",
    ),
    path(
        "v1/scheme-discussion/<int:discussion_id>/messages/<int:pk>/",
        views.SchemeMessageUpdateView.as_view(),
        name="update-scheme-discussion-messages",
    ),
    # filtered discussion according to scheme
    path(
        "v1/discussion-per-scheme/<int:scheme_id>/",
        views.DiscussionPerSchemeListView.as_view(),
        name="list-discussion-per-scheme",
    ),
]


from tkinter import *
from table import * # 프롬 모듈 임폴트 * 는 모듈명을 안적어줘도됨
from ball import *
from bat import *
# import table,ball,bat는 모듈명을 일일히 적어줘야함

####전역변수초기화
x_speed=10 #공의 x속도
y_speed=0#공의 y속도

first_serve = True

#메인부
window=Tk()
window.title("MyPingPong")
window.resizable(width=FALSE, height=FALSE)

###game_flow()함수부
def game_flow():

    global score_left, score_right, first_serve

    # 첫번째 서브를 기다립니다:
    if(first_serve == True):
        my_ball.stop_ball()
        first_serve = False

    #공을 일정 시간마다 움직이게함
    my_ball.move_next()
    window.after(30, game_flow) #30밀리초마다 함 실행

    #공이 배트에 닿았는지 충돌확인
    bat_L.detect_collision(my_ball)
    bat_R.detect_collision(my_ball)

    ##공이 좌우 벽에 충돌 했을 때 처리
      #공이 x좌표값이 0보다 작으면 왼쪽벽에 충돌
    if(my_ball.x_posn<=0):
        my_ball.stop_ball()  # 공이 멈춤
        my_ball.start_position() # 공 위치 초기화
        bat_L.start_position() #배트위치 초기화
        bat_R.start_position()
        my_table.move_item2(bat_L.rectangle, (20+35)/2, (150+250)/2)
        my_table.move_item2(bat_R.rectangle, (565+580)/2, (150+250)/2)
    #득점판 득점 표시
        score_right += 1
        if(score_right>=3):
            score_right="W"
            score_left="L"
        my_table.draw_score(score_left, score_right)

    # 이건 오른쪽 벽
    if(my_ball.x_posn+my_ball.width>=my_table.width):
        my_ball.stop_ball()
        my_ball.start_position()
        bat_L.start_position()
        bat_R.start_position()
        my_table.move_item2(bat_L.rectangle, (20+35)/2, (150+250)/2)
        my_table.move_item2(bat_R.rectangle, (565+580)/2, (150+250)/2)
    #이것도 득점
        score_left += 1
        if(score_left>=3):
            score_left="W"
            score_right="L"
        my_table.draw_score(score_left, score_right)

def restart_game(master):
    global score_left, score_right

    my_ball.start_ball(x_speed=x_speed, y_speed=y_speed)

    if(score_left=="W" or score_right=="W"):
        score_left=0
        score_right=0
        my_table.draw_score(score_left, score_right)

    bat_L.start_position()
    bat_R.start_position()
    my_table.move_item2(bat_L.rectangle, (20+35)/2, (150+250)/2)
    my_table.move_item2(bat_R.rectangle, (565+580)/2, (150+250)/2)

### Table 클래스를 사용해서 테이블 생성
my_table=Table(window, 600, 400, PhotoImage(file="../PPbg.png"))

### 공생성
#Ball(self, table, width, height, color, x_speed, y_speed, x_posn, y_posn)
my_ball=Ball(table=my_table, x_speed=5, y_speed=5, width=24, height=24, color="orange", x_posn=288, y_posn=188)
my_ball.move_next()

###배트생성
#Bat(self, table, width, height, color, x_speed=25, y_speed=25, x_posn, y_posn)
bat_L=Bat(table=my_table, width=15, height=100, batImage=PhotoImage(file="../bat1.png"), x_posn=20, y_posn=150)
bat_R=Bat(table=my_table, width=15, height=100, batImage=PhotoImage(file="../bat2.png"), x_posn=565, y_posn=150)

####함수의 실행부
game_flow()

#스페이스바를 눌러 게임시작또는 재시
window.bind("<space>", restart_game)

###배트를 제어하기 위한 키 이벤트 및 연결될 함수 지정
#window.bind("<키명>", 함수명)
window.bind("<Up>", bat_R.move_up)
window.bind("<Down>", bat_R.move_down)
window.bind("<w>", bat_L.move_up)
window.bind("<s>", bat_L.move_down)

window.mainloop()


from oslo.config import cfg

from manila.common import constants
from manila.db import base as db_base
from manila import exception
from manila import network as manila_network
from manila.network.neutron import api as neutron_api
from manila.network.neutron import constants as neutron_constants
from manila.openstack.common import log as logging

CONF = cfg.CONF
LOG = logging.getLogger(__name__)

class NeutronNetworkPlugin(manila_network.NetworkBaseAPI, db_base.Base):

    def __init__(self):
        super(NeutronNetworkPlugin, self).__init__()
        self.neutron_api = neutron_api.API()

    def allocate_network(self, context, share_server, share_network, **kwargs):
        """Allocate network resources using given network information.

        Create neutron ports for a given neutron network and subnet,
        create manila db records for allocated neutron ports.

        :param context: RequestContext object
        :param share_network: share network data
        :param kwargs: allocations parameters given by the back-end
                       driver. Supported params:
                       'count' - how many allocations should be created
                       'device_owner' - set owner for network allocations
        :rtype: list of :class: 'dict'
        """
        if not self._has_provider_network_extension():
            msg = "%s extension required" % neutron_constants.PROVIDER_NW_EXT
            raise exception.NetworkBadConfigurationException(reason=msg)

        self._save_neutron_network_data(context, share_network)
        self._save_neutron_subnet_data(context, share_network)

        allocation_count = kwargs.get('count', 1)
        device_owner = kwargs.get('device_owner', 'share')

        ports = []
        for __ in range(0, allocation_count):
            ports.append(self._create_port(context, share_server,
                                           share_network, device_owner))

        return ports

    def deallocate_network(self, context, share_server):
        """Deallocate neutron network resources for the given network info.

        Delete previously allocated neutron ports, delete manila db
        records for deleted ports.

        :param context: RequestContext object
        :param share_network: share network data
        :rtype: None
        """
        ports = self.db.network_allocations_get_for_share_server(
            context, share_server['id'])

        for port in ports:
            self._delete_port(context, port)

    def _create_port(self, context, share_server, share_network, device_owner):
        port = self.neutron_api.create_port(
            share_network['project_id'],
            network_id=share_network['neutron_net_id'],
            subnet_id=share_network['neutron_subnet_id'],
            device_owner='manila:' + device_owner)
        port_dict = {
            'id': port['id'],
            'share_server_id': share_server['id'],
            'ip_address': port['fixed_ips'][0]['ip_address'],
            'mac_address': port['mac_address'],
            'status': constants.STATUS_ACTIVE,
        }
        return self.db.network_allocation_create(context, port_dict)

    def _delete_port(self, context, port):
        try:
            self.neutron_api.delete_port(port['id'])
        except exception.NetworkException:
            self.db.network_allocation_update(
                context, port['id'], {'status': constants.STATUS_ERROR})
            raise
        else:
            self.db.network_allocation_delete(context, port['id'])

    def _has_provider_network_extension(self):
        extentions = self.neutron_api.list_extensions()
        return neutron_constants.PROVIDER_NW_EXT in extentions

    def _save_neutron_network_data(self, context, share_network):
        net_info = self.neutron_api.get_network(
            share_network['neutron_net_id'])

        provider_nw_dict = {
            'network_type': net_info['provider:network_type'],
            'segmentation_id': net_info['provider:segmentation_id']
        }

        self.db.share_network_update(context,
                                     share_network['id'],
                                     provider_nw_dict)

    def _save_neutron_subnet_data(self, context, share_network):
        subnet_info = self.neutron_api.get_subnet(
            share_network['neutron_subnet_id'])

        subnet_values = {
            'cidr': subnet_info['cidr'],
            'ip_version': subnet_info['ip_version']
        }

        self.db.share_network_update(context,
                                     share_network['id'],
                                     subnet_values)


#Caitlin Pinkard
#Snag Assessment
#Program Description: This program takes a file on command line, parses it manually, and outputs
#rows that correspond to optional query parameters also given on command line. There is functionality for
#outputting either the union or intersection of the given queries.
#USAGE: [Snag.py] [file name] [optional filters with form like "location=richmond"]

import sys
print("\n\n","-"*70,"\n",sep="")

numFilters = len(sys.argv) - 2
#if the user input more than 1 query filter, it will ask them if they want the union or intersection of
#those filters - if they input an invalid character, it will continue to prompt them with this question
orAnd = "NULL"
if numFilters > 1:
      while orAnd != "u" and orAnd != "i":
            orAnd = input("Would you like a union or an intersection of these queries (u/i)?  ")
      print("\n","-"*70,"\n",sep="")

rows = []
numFail = 0
failRowNum  = []
fileName = sys.argv[1]
rowNum = 0
sepCar = ","
#use with so that the file will be closed when read completely
#break the column up into lines and split lines on commas
#if a line fails, print the error and save the row number to output to the user
with open(fileName, 'r', encoding = 'utf-8-sig') as file:
      for line in file:
            try:
                  if(rowNum == 0):
                        if(line.find("\t") != -1):
                              sepCar = "\t"
                  line = line.strip()
                  rows.append(line.split(sep = sepCar))
            except Exception as e:
                  print(e)
                  numFail+=1
                  failRowNum.append(rowNum)
            rowNum += 1

print("Number of successful rows read in:",len(rows),"\n")
if numFail > 0:
      print("Row Numbers of failures: ",failRowNum,"\n")
print("Number of failures encountered: ", numFail, "\n")
print("-"*70,"\n")

#queryDict will store filters
queryDict = {}
#this while loop will handle multiple filters input by the user
while numFilters > 0:
      strFilter = sys.argv[len(sys.argv)-numFilters]

      #parse each optional command line argument by splitting up it on an equal sign
      #store both the column name and the desired value in a dictionary
      #if the argument is invalid, inform the user of the correct form
      try:
            strip = [x.strip() for x in strFilter.split('=')]
            colName = strip[0]
            value = strip[1]
            queryDict[colName] = value
      except:
            print("\nIllegal Query - Please input a query of the form: ColumnName=DesiredValue\n")
            sys.exit()
      numFilters = numFilters - 1

retVal = []
GoodRowNums = []
#print(queryDict)
try:
      #if the user wants the union of their filters or only input one filter, we just accumulate
      #all of the columns that fit that criteria into retVal
      if orAnd == "u" or len(sys.argv) - 2 == 1:
            #iterate over the filters
            for key, value in queryDict.items():
                  colNum = rows[0].index(key)
                  #look through rows of data for those that match the filter criteria
                  for i in range(1,len(rows)):
                        if rows[i][colNum] == value and i not in GoodRowNums:
                              retVal.append(rows[i])
                              GoodRowNums.append(i)
      #if the user wants the intersection of their filters, we search each row and if it satisfies all
      #the filters, add it to the rows to be returned
      elif orAnd == "i":
            GoodRows = []
            for i in range(1,len(rows)):
                  flag = 0
                  for key, value in queryDict.items():
                        if rows[i][rows[0].index(key)] != value:
                              flag = 1
                  if flag == 0:
                        GoodRows.append(rows[i])
                        GoodRowNums.append(i)
                  retVal = GoodRows

 #alert the user if the column they input isn't in the data
except Exception as e:
      print(e)
      print("\nInvalid column ("+colName+") specified. Nothing returned for this query.\n")
      sys.exit()

#if retVal is empty, alert the user that there are no rows matching their query
if not retVal:
      print("No rows matching that query.")
#otherwise print out their filters again, and any rows that fit their criteria
else:
      print("Rows with ",end = "")
      for key,val in queryDict.items():
            if  key == list(queryDict.keys())[-1]:
                  print(key,"=",val, end = ":")
            else:
                  if orAnd == "u":
                        print(key,"=",val, end = "  OR  ")
                  elif orAnd == "i":
                        print(key,"=",val, end = "  AND  ")

      print("\n\n", retVal)
      print("\nRow numbers: ",GoodRowNums,"\n")

print("\n","-"*70,"\n\n",sep="")


from gj_solution import gj_Solve

def calculateMSE(X,Y,m,b):
    ind = len(X)
    if ind == 0:
        return "point sets error"
    mse = [(y-m*x -b)**2 for x,y in zip(X,Y)]
    calmse = sum(mse)/ind
    return calmse

#3.4 XtXh = XtY

def linearRegression(X, Y):
    leng = len(X)
    XtX = [[0,0],[0,0]]
    XtY = [[0],[0]]
    XtX[0][0] = sum([x**2 for x in X])
    XtX[0][1] = XtX[1][0] = sum([x for x in X])
    XtX[1][1] = leng
    XtY = [[sum([x*y for x,y in zip(X,Y)])],
           [sum([y for y in Y])]]
    m,b = gj_Solve(XtX, XtY)
    return m,b

m2,b2 = linearRegression(X,Y)
assert isinstance(m2,float),"m is not a float"
assert isinstance(b2,float),"b is not a float"
print(m2,b2)


def main():
    with open('01.input') as file:
        data = file.readlines()[0].strip()
        # print(first_task(data))
        print(second_part(data));

def first_task(inputData):
    data = list(inputData)
    data += str(data[0])
    val = 0
    prev = None
    for d in data:
        if d == prev:
            val += int(d)
        prev=d
    return val

def second_part(inputData):
    data = list(inputData)
    length = len(data)
    offset = int(length/2)
    val = 0
    for i, d in enumerate(data):
        index = i+offset
        if index >= length:
            index -= length
        match = data[index]
        if d == match:
            val += int(d)
    return val

if __name__ == '__main__':
    main()


import numpy as np
import scipy.stats as stat
import h5py
import corner
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
import utilities
import os
from multiprocessing import Pool
import emcee
import seaborn as sns
import warnings
import time
import pandas as pd
import datetime

warnings.filterwarnings("ignore")
os.environ["OMP_NUM_THREADS"] = "1"

sns.set_style("whitegrid")
sns.set_context("paper", rc={"font.size": 12, "axes.titlesize": 12, "axes.labelsize": 12})

class cultivarModel:

    def __init__(self, cultivar, region_tol=0.25, weather=("temperature", "rainfall"), metric="yield",
                 metric_units="t/Ha", extract_flag=False, initial_guess=(10, 3375, 380, 705, 220, 0),
                 initial_spread=(15, 500, 300, 400, 300, 1)):

        start = time.time()

        # Get the inputs
        data = utilities.extract_data("../example_data/" + cultivar + "_Data.csv")
        region_lats, region_longs, years, ripe_days, yields, sow_day, sow_month = data

        self.reg_lats = region_lats
        self.reg_longs = region_longs
        self.reg_yrs = years
        self.sow_days = sow_day
        self.sow_months = sow_month
        self.sow_year = years - 1
        self.ripe_days = ripe_days
        self.reg_keys = self.get_day_keys()
        self.yield_data = yields
        self.cult = cultivar
        self.tol = region_tol
        self.wthr_dict = {}
        self.wthr_anom_dict = {}
        self.mean_params = {}
        self.fit = None
        self.extract_flag = extract_flag

        self.initial_guess = initial_guess
        self.initial_spread = initial_spread
        self.samples = {}
        self.reg_pred = np.zeros_like(self.yield_data)
        self.resi = None
        self.weather = weather
        self.metric = metric
        self.metric_units = metric_units

        # Open file
        try:

            hdf = h5py.File("../Climate_Data/Region_Climate_" + self.cult + "_daily.hdf5", "r")

            self.temp_anom, self.temp = hdf["Temperature_Anomaly"][...], hdf["Temperature"][...]
            self.temp[self.temp <= 0] = np.nan
            print("Temperature Extracted")
            self.precip_anom, self.precip = hdf["Rainfall_Anomaly"][...], hdf["Rainfall"][...]
            print("Rainfall Extracted")

            hdf.close()

        except KeyError:
            self.extract_flag = True
        except OSError:
            self.extract_flag = True

        if self.extract_flag:

            self.temp_anom, self.temp = self.get_weather_anomaly(weather[0])
            self.temp[self.temp <= 0] = np.nan
            print("Temperature Extracted")
            self.precip_anom, self.precip = self.get_weather_anomaly(weather[1])
            print("Rainfall Extracted")

            hdf = h5py.File("../Climate_Data/Region_Climate_" + self.cult + "_daily.hdf5", "w")

            hdf.create_dataset("Temperature", shape=self.temp.shape, dtype=self.temp.dtype,
                               data=self.temp, compression="gzip")
            hdf.create_dataset("Temperature_Anomaly", shape=self.temp_anom.shape, dtype=self.temp_anom.dtype,
                               data=self.temp_anom, compression="gzip")
            hdf.create_dataset("Rainfall", shape=self.precip.shape, dtype=self.precip.dtype,
                               data=self.precip, compression="gzip")
            hdf.create_dataset("Rainfall_Anomaly", shape=self.precip_anom.shape, dtype=self.precip_anom.dtype,
                               data=self.precip_anom, compression="gzip")

            hdf.close()

        # Compute thermal days and total rainfall
        self.therm_days = np.nansum(self.temp, axis=1)
        self.tot_precip = np.nansum(self.precip, axis=1)

        print("Input extracted:", time.time() - start)

    @staticmethod
    def extract_region(lat, long, region_lat, region_long, weather, tol):

        # Get the boolean array for points within tolerence
        bool_cond = np.logical_and(np.abs(lat - region_lat) < tol, np.abs(long - region_long) < tol)

        # Get the extracted region
        ex_reg = weather[bool_cond]

        # Remove any nan and set them to 0 these correspond to ocean
        ex_reg = ex_reg[ex_reg < 1e8]

        if ex_reg.size == 0:
            print("Region not in coords:", region_lat, region_long)
            return np.nan
        else:
            return np.mean(ex_reg)

    @staticmethod
    def gauss3d(norm, t, mu_t, sig_t, p, mu_p, sig_p, s, mu_s, sig_s, rho_tp, rho_ts, rho_ps):

        dy = 0
        for mon in range(0, 12):
            dy += norm * np.exp(-(0.5 * 1 / (1 - np.square(rho_tp) - np.square(rho_ts) - np.square(rho_ps)
                                             + 2 * rho_tp * rho_ts * rho_ps))
                                * (np.square((t[mon] - mu_t) / sig_t)
                                   + np.square((p[mon] - mu_p) / sig_p) + np.square((s[mon] - mu_s) / sig_s)
                                   + 2 * ((t[mon] - mu_t) * (p[mon] - mu_p) * (rho_ts * rho_ps - rho_tp) / (
                                sig_t * sig_p)
                                          + (t[mon] - mu_t) * (s[mon] - mu_s) * (rho_tp * rho_ts - rho_ps)
                                          / (sig_t * sig_s) + (p[mon] - mu_p) * (s[mon] - mu_s)
                                          * (rho_tp * rho_ts - rho_ps) / (sig_s * sig_p))))

        return dy

    @staticmethod
    def gauss2d_country(norm, t, mu_t, sig_t, p, mu_p, sig_p, rho, dy=0):

        for mon in range(0, 12):
            dy += norm * np.exp(-(1 / (2 - 2 * np.square(rho))) * (np.square((t[:, :, mon] - mu_t) / sig_t) +
                                                                   np.square((p[:, :, mon] - mu_p) / sig_p)
                                                                   - 2 * rho * (t[:, :, mon] - mu_t) * (
                                                                               p[:, :, mon] - mu_p)
                                                                   / (sig_t * sig_p)))
        return dy

    @staticmethod
    def gauss2d_resp(t, norm, mu_t, sig_t, p, mu_p, sig_p, rho):

        t_term = ((t - mu_t) / sig_t) ** 2
        p_term = ((p - mu_p) / sig_p) ** 2
        tp_term = 2 * rho * (t - mu_t) * (p - mu_p) / (sig_t * sig_p)

        dy = norm * np.exp(-(1 / (2 - 2 * rho * rho)) * (t_term + p_term - tp_term))

        return dy

    def get_day_keys(self):

        # Initialise the dictionary to hold keys
        sow_dict = {}

        # Loop over regions
        for regind, (lat, long, sow_yr) in enumerate(zip(self.reg_lats, self.reg_longs, self.sow_year)):

            # Initialise this regions entry
            sow_dict.setdefault(str(lat) + "." + str(long), {})

            # Extract this years sowing date and ripening time in days
            sow_day = self.sow_days[regind]
            sow_month = self.sow_months[regind]
            ripe_time = self.ripe_days[regind]
            sow_date = datetime.date(year=sow_yr, month=int(sow_month), day=int(sow_day))

            # Initialise this region"s dictionary entry
            hdf_keys = np.empty(ripe_time + 1, dtype=object)

            # Loop over months between sowing and ripening
            for nday in range(ripe_time + 1):

                # Compute the correct month number for this month
                key_date = sow_date + datetime.timedelta(days=nday)

                # Append this key to the dictionary under this region in chronological order
                hdf_keys[nday] = str(key_date.year) + "_%03d" % key_date.month + "_%04d" % key_date.day

            # Assign keys to dictionary
            sow_dict[str(lat) + "." + str(long)][str(sow_yr)] = hdf_keys

        return sow_dict

    def get_weather_anomaly(self, weather):

        hdf = h5py.File("../SimFarm2030_" + weather + ".hdf5", "r")

        # Get the mean weather data for each month of the year
        uk_monthly_mean = hdf["all_years_mean"][...]

        lats = hdf["Latitude_grid"][...]
        longs = hdf["Longitude_grid"][...]

        # Loop over regions
        anom = np.full((len(self.reg_lats), 400), np.nan)
        wthr = np.full((len(self.reg_lats), 400), np.nan)
        for llind, (lat, long, year) in enumerate(zip(self.reg_lats, self.reg_longs, self.sow_year)):

            hdf_keys = self.reg_keys[str(lat) + "." + str(long)][str(year)]

            # Initialise arrays to hold results
            key_ind = 0
            for key in hdf_keys:

                year, month, day = key.split("_")

                wthr_grid = hdf[key]["daily_grid"][...]

                ex_reg = self.extract_region(lats, longs, lat, long, wthr_grid, self.tol)

                # If year is within list of years extract the relevant data
                wthr[llind, key_ind] = ex_reg
                anom[llind, key_ind] = ex_reg - uk_monthly_mean[int(month) - 1]
                key_ind += 1

        # Assign weather data to variable
        self.wthr_anom_dict[weather] = anom

        hdf.close()

        return anom, wthr

    @staticmethod
    def gauss2d(t, norm, mu_t, sig_t, p, mu_p, sig_p, rho):

        t_term = ((t - mu_t) / sig_t) ** 2
        p_term = ((p - mu_p) / sig_p) ** 2
        tp_term = 2 * rho * (t - mu_t) * (p - mu_p) / (sig_t * sig_p)

        dy = norm * np.exp(-0.5 / (1 - rho * rho) * (t_term + p_term - tp_term))

        return dy

    # @staticmethod
    # def gauss1d(x, norm, mu, sig):
    #
    #     exp_term = ((x - mu) / sig) ** 2
    #
    #     dy = norm * np.nansum(np.exp(-0.5 * exp_term), axis=1)
    #
    #     return dy

    def log_likelihood_2d(self, theta, t, p, y, yerr):

        # Extract initial guesses
        norm, mu_t, sig_t, mu_p, sig_p, rho = theta

        # Define model
        model = self.gauss2d(t, norm, mu_t, sig_t, p, mu_p, sig_p, rho)

        sigma2 = yerr ** 2

        return -0.5 * np.sum((y - model) ** 2 / sigma2)

    # def log_likelihood_1d(self, theta, t, y, yerr):
    #
    #     # Extract initial guesses
    #     norm, mu, sig = theta
    #
    #     # Define model
    #     model = self.gauss1d(t, norm, mu, sig)
    #
    #     sigma2 = yerr ** 2
    #
    #     return -0.5 * np.sum((y - model) ** 2 / sigma2)

    def log_prior_2d(self, theta):

        # Extract parameters from vector
        norm, mu_t, sig_t, mu_p, sig_p, rho = theta

        # The only parameters with a lower bound are norm and the sigmas
        cond = (0 < norm < 20
                and 2000 < mu_t < 4050 and 0 < sig_t < 10000
                and 350 < mu_p < 1700 and 0 < sig_p < 10000
                and -1 <= rho <= 1)
        if cond:

            # # Define ln(prior) for each prior
            norm_lnprob = np.log(stat.norm.pdf(norm, loc=self.initial_guess[0], scale=self.initial_spread[0]))
            mut_lnprob = np.log(stat.norm.pdf(mu_t, loc=self.initial_guess[1], scale=self.initial_spread[1]))
            sigt_lnprob = np.log(stat.norm.pdf(sig_t, loc=self.initial_guess[2], scale=self.initial_spread[2]))
            mup_lnprob = np.log(stat.norm.pdf(mu_p, loc=self.initial_guess[3], scale=self.initial_spread[3]))
            sigp_lnprob = np.log(stat.norm.pdf(sig_p, loc=self.initial_guess[4], scale=self.initial_spread[4]))
            rho_lnprob = np.log(stat.norm.pdf(rho, loc=self.initial_guess[5], scale=self.initial_spread[5]))

            return norm_lnprob + mut_lnprob + sigt_lnprob + mup_lnprob + sigp_lnprob + rho_lnprob
            # return 0
        else:
            return -np.inf

    # def log_prior_1d(self, theta, inds):
    #
    #     # Extract parameters from vector
    #     norm, mu, sig = theta
    #
    #     # The only parameters with a lower bound are norm and the sigmas
    #     cond = (0 < norm < 20 and 0 < mu < 50000 and 0 < sig < 10000)
    #     if cond:
    #
    #         # # Define ln(prior) for each prior
    #         norm_lnprob = np.log(
    #             stat.norm.pdf(norm, loc=self.initial_guess[inds[0]], scale=self.initial_spread[inds[0]]))
    #         mu_lnprob = np.log(stat.norm.pdf(mu, loc=self.initial_guess[inds[1]], scale=self.initial_spread[inds[1]]))
    #         sig_lnprob = np.log(stat.norm.pdf(sig, loc=self.initial_guess[inds[2]], scale=self.initial_spread[inds[2]]))
    #
    #         return norm_lnprob + mu_lnprob + sig_lnprob
    #         # return 0
    #     else:
    #         return -np.inf

    def log_probability_2d(self, theta, t, p, y, yerr):
        lp = self.log_prior_2d(theta)
        if not np.isfinite(lp):
            return -np.inf
        return lp + self.log_likelihood_2d(theta, t, p, y, yerr)

    # def log_probability_1d(self, theta, x, y, yerr, inds):
    #     lp = self.log_prior_1d(theta, inds)
    #     if not np.isfinite(lp):
    #         return -np.inf
    #     return lp + self.log_likelihood_1d(theta, x, y, yerr)

    def train_model(self, nsample=5000, nwalkers=500):

        temp = self.therm_days
        rain = self.tot_precip

        yields = self.yield_data
        yerr = np.std(self.yield_data)

        ndim = len(self.initial_guess)

        p0 = np.random.randn(nwalkers, ndim) * 0.0001 + self.initial_guess

        with Pool() as pool:
            sampler = emcee.EnsembleSampler(nwalkers, ndim, self.log_probability_2d,
                                            args=(temp, rain, yields, yerr), pool=pool, threads=8)

            # Run 200 steps as a burn-in.
            print("Burning in ...")
            pos, prob, state = sampler.run_mcmc(p0, 200)

            # Reset the chain to remove the burn-in samples.
            sampler.reset()

            print("Running MCMC ...")
            pos, prob, state = sampler.run_mcmc(p0, nsample, progress=True, rstate0=state)

        self.model = sampler

        # Print out the mean acceptance fraction. In general, acceptance_fraction
        # has an entry for each walker so, in this case, it is a 250-dimensional
        # vector.
        af = sampler.acceptance_fraction
        print("Mean acceptance fraction:", np.mean(af))
        af_msg = '''As a rule of thumb, the acceptance fraction (af) should be
                                    between 0.2 and 0.5
                    If af < 0.2 decrease the a parameter
                    If af > 0.5 increase the a parameter
                    '''

        print(af_msg)

        flat_samples = sampler.get_chain(discard=500, thin=100, flat=True)
        self.flat_samples = flat_samples

        # Extract fitted parameters
        d = self.mean_params
        maxprob_indice = np.argmax(prob)
        self.maxprob_params = pos[maxprob_indice]
        self.fitted_params = np.median(flat_samples, axis=0)
        d["norm"], d['mu_t'], d["sig_t"], d['mu_p'], d["sig_p"], d["rho"] = self.fitted_params

        # Extract the samples
        d = self.samples
        d["norm"], d['mu_t'], d["sig_t"], d['mu_p'], d["sig_p"], d["rho"] = [flat_samples[:, i] for i in range(ndim)]

        # Extract the errors on the fitted parameters
        self.param_errors = np.std(flat_samples, axis=0)
        norm_err, mu_t_err, sig_t_err, mu_p_err, sig_p_err, rho_err = self.param_errors

        print("================ Model Parameters ================")
        print("norm = %.3f +/- %.3f" % (self.mean_params['norm'], norm_err))
        print("mu_t = %.3f +/- %.3f" % (self.mean_params['mu_t'], mu_t_err))
        print("sig_t = %.3f +/- %.3f" % (self.mean_params["sig_t"], sig_t_err))
        print("mu_p = %.3f +/- %.3f" % (self.mean_params['mu_p'], mu_p_err))
        print("sig_p = %.3f +/- %.3f" % (self.mean_params["sig_p"], sig_p_err))
        print("rho = %.3f +/- %.3f" % (self.mean_params["rho"], rho_err))

    def train_and_validate_model(self, split=0.7, nsample=5000, nwalkers=500):

        # Compute the ratio to split by
        size = self.therm_days.shape[0]
        predict_size = int(size * (1 - split))

        rand_inds = np.random.choice(np.arange(size), predict_size)
        okinds = np.zeros(size, dtype=bool)
        okinds[rand_inds] = True

        train_temp = self.therm_days[~okinds]
        train_rain = self.tot_precip[~okinds]
        train_yields = self.yield_data[~okinds]
        predict_temp = self.therm_days[okinds]
        predict_rain = self.tot_precip[okinds]
        predict_yields = self.yield_data[okinds]
        yerr = np.std(self.yield_data)

        ndim = len(self.initial_guess)

        p0 = np.random.randn(nwalkers, ndim) * 0.001 + self.initial_guess

        sampler = emcee.EnsembleSampler(nwalkers, ndim, self.log_probability_2d,
                                        args=(train_temp, train_rain, train_yields, yerr))

        # Run 200 steps as a burn-in.
        print("Burning in ...")
        pos, prob, state = sampler.run_mcmc(p0, 200)

        # Reset the chain to remove the burn-in samples.
        sampler.reset()

        print("Running MCMC ...")
        pos, prob, state = sampler.run_mcmc(p0, nsample, progress=True, rstate0=state)

        self.model = sampler

        # Print out the mean acceptance fraction. In general, acceptance_fraction
        # has an entry for each walker so, in this case, it is a 250-dimensional
        # vector.
        af = sampler.acceptance_fraction
        print("Mean acceptance fraction:", np.mean(af))
        af_msg = '''As a rule of thumb, the acceptance fraction (af) should be
                                    between 0.2 and 0.5
                    If af < 0.2 decrease the a parameter
                    If af > 0.5 increase the a parameter
                    '''

        print(af_msg)

        flat_samples = sampler.get_chain(discard=1000, thin=100, flat=True)
        self.flat_samples = flat_samples

        # Extract fitted parameters
        d = self.mean_params
        maxprob_indice = np.argmax(prob)
        self.maxprob_params = pos[maxprob_indice]
        self.fitted_params = np.median(flat_samples, axis=0)
        d["norm"], d['mu_t'], d["sig_t"], d['mu_p'], d["sig_p"], d["rho"] = self.fitted_params

        # Extract the samples
        d = self.samples
        d["norm"], d['mu_t'], d["sig_t"], d['mu_p'], d["sig_p"], d["rho"] = [flat_samples[:, i] for i in range(ndim)]

        # Extract the errors on the fitted parameters
        self.param_errors = np.std(flat_samples, axis=0)
        norm_err, mu_t_err, sig_t_err, mu_p_err, sig_p_err, rho_err = self.param_errors

        print("================ Model Parameters ================")
        print("norm = %.3f +/- %.3f" % (self.mean_params['norm'], norm_err))
        print("mu_t = %.3f +/- %.3f" % (self.mean_params['mu_t'], mu_t_err))
        print("sig_t = %.3f +/- %.3f" % (self.mean_params["sig_t"], sig_t_err))
        print("mu_p = %.3f +/- %.3f" % (self.mean_params['mu_p'], mu_p_err))
        print("sig_p = %.3f +/- %.3f" % (self.mean_params["sig_p"], sig_p_err))
        print("rho = %.3f +/- %.3f" % (self.mean_params["rho"], rho_err))

        # Calculate the predicted results
        preds = self.gauss2d(predict_temp, self.mean_params['norm'], self.mean_params['mu_t'],
                             self.mean_params['sig_t'], predict_rain, self.mean_params['mu_p'],
                             self.mean_params['sig_p'], self.mean_params["rho"])
        print(preds)

        # Calculate the percentage residual
        resi = (1 - preds / predict_yields) * 100
        print(resi)
        print(np.mean(resi))
        print(np.median(resi))
        # Plot results
        fig = plt.figure()
        ax = fig.add_subplot(111)

        ax.scatter(np.arange(preds.size), resi, marker="+", label="Regions")
        ax.axhline(np.mean(resi), linestyle="-", color="k", label="Mean")
        ax.axhline(np.median(resi), linestyle="--", color="k", label="Median")

        ax.set_xlabel("Region")
        ax.set_ylabel("$1 - Y_{\mathrm{Pred}} / Y_{\mathrm{True}}$ (%)")

        handles, labels = ax.get_legend_handles_labels()
        ax.legend(handles, labels)

        fig.savefig("../model_performance/Validation/" + self.cult + ".png", bbox_inches="tight")

    def plot_walkers(self):

        ndim = len(self.initial_guess)

        for i in range(ndim):
            fig = plt.figure()
            ax = fig.add_subplot(111)
            res = ax.plot(self.model.chain[:, :, i].T, "-", color="k", alpha=0.3)
            fig.savefig(f"../model_performance/Chains/samplerchain_{i}_" + self.cult + "_daily.png", bbox_inches="tight")
            plt.close(fig)

    def plot_response(self):

        # Create arrays to evaluate response function at
        eval_t = np.linspace(0, 6000, 1000)
        eval_p = np.linspace(0, 3500, 1000)

        # Get grid of values
        tt, pp = np.meshgrid(eval_t, eval_p)

        # Compute temperature response
        t_resp = self.gauss2d_resp(eval_t, self.mean_params["norm"], self.mean_params["mu_t"],
                                   self.mean_params["sig_t"], 0, self.mean_params["mu_p"],
                                   self.mean_params["sig_p"], self.mean_params["rho"])

        # Compute precipitation response
        p_resp = self.gauss2d_resp(0, self.mean_params["norm"], self.mean_params["mu_t"],
                                   self.mean_params["sig_t"], eval_p, self.mean_params["mu_p"],
                                   self.mean_params["sig_p"], self.mean_params["rho"])

        # Compute the response grid
        resp_grid = self.gauss2d_resp(tt, self.mean_params["norm"], self.mean_params["mu_t"],
                                      self.mean_params["sig_t"], pp, self.mean_params["mu_p"],
                                      self.mean_params["sig_p"], self.mean_params["rho"])

        # Set up figure
        fig = plt.figure(figsize=(9, 9.6))
        gs = gridspec.GridSpec(3, 2)
        gs.update(wspace=0.3, hspace=0.3)
        ax1 = fig.add_subplot(gs[:2, :])
        ax2 = fig.add_subplot(gs[2, 0])
        ax3 = fig.add_subplot(gs[2, 1])

        # Plot the response functions
        cba = ax1.pcolormesh(eval_t, eval_p, resp_grid)

        cbar = fig.colorbar(cba, ax=ax1)
        cbar.ax.set_ylabel(self.metric + " (" + self.metric_units + "month$^{-1}$)")

        ax2.plot(eval_t, t_resp)
        ax3.plot(eval_p, p_resp)

        # Label axes
        ax1.set_xlabel(r"Thermal days ($^\circ$C days)")
        ax1.set_ylabel(r"$\sum P$ (mm)")
        ax2.set_xlabel(r"Thermal days ($^\circ$C days)")
        ax2.set_ylabel(self.metric + " (" + self.metric_units + "month$^{-1}$)")
        ax3.set_xlabel(r"$\sum P$ (mm)")
        ax3.set_ylabel(self.metric + " (" + self.metric_units + "month$^{-1}$)")

        # Save the figure
        fig.savefig("../Response_functions/response_" + self.cult + "_daily.png", dpi=300, bbox_inches="tight")

        return eval_t, eval_p, t_resp, p_resp, resp_grid

    def post_prior_comp(self):

        labels = [r"norm", r"$\mu_t$", r"$\sigma_t$", r"$\mu_p$", r"$\sigma_p$", r"$\rho$", "lagt", "lagp"]
        fig = corner.corner(self.flat_samples, show_titles=True, labels=labels, plot_datapoints=True,
                            quantiles=[0.16, 0.5, 0.84])

        fig.savefig("../model_performance/Corners/corner_" + self.cult + "_daily.png", bbox_inches="tight")

        plt.close(fig)


# Function with 2 arguments
# Join strings together
# Reverse newString
# string1 = "hello";
# string2 = "you";

# def addAndReverse(string1, string2):
#     return string2[::-1], string1[::-1];

# print(addAndReverse(string1, string2));

# Function that takes string and returns 4th char
# If string too short, print "too short of a string"

def find4thChar(string):
    if len(string) < 4:
        print("too short of a string");
    else:
        print(string[3])
    return

find4thChar("hello");
find4thChar("hey");
find4thChar("hi");


from user_agents import parse
import pandas as pd
from dateutil import parser
from polyglot.text import Text
from multiprocessing import Pool
import numpy as np
from polyglot.detect import Detector

csv_train = '../data/train.csv'
csv_test = '../data/test.csv'

def apply(func, list_):
    with Pool(8) as pool:
        res = pool.map(func, list_)
    return pd.Series(res)

def foo(x):
    try:
        lang = Detector(x).language.name
        if lang not in ['Russian', 'Ukrainian']:
            lang = 'unk'

    except:
        lang = 'unk'
    return lang

class DataProvider:

    def __init__(self, csv_path):
        self.df = pd.read_csv(csv_path)
        s = self.df.shape[0]
        print('Found {} samples'.format(s))
        self.df.product_id.fillna(1005004242, inplace=True)
        self.df = self.df.dropna()
        print('Delete {} samples with NAN'.format(s - self.df.shape[0]))
        self.unk_code_int = 100500
        self.fit()

    def one_hot(self, uniq, series, unk_code):
        ser = series.apply(lambda x: x if x in uniq else unk_code)
        return pd.get_dummies(ser)

    def fit(self):
        # self.company_id_uniq = self.df[self.df.is_fake==True]['company_id'].unique()
        # self.user_id_uniq = self.df[self.df.is_fake == True]['user_id'].unique()
        # self.product_id_uniq = self.df[self.df.is_fake == True]['product_id'].unique()
        self.df['date_created_unix'] = apply(str2unix, self.df.date_created.tolist())
        self.df['user_date_created_unix'] = apply(str2unix, self.df.user_date_created.tolist())
        self.maxdatetime_diff = (self.df.date_created_unix - self.df.user_date_created_unix).max()
        self.date_created_unix_max = self.df['date_created_unix'].max()
        self.user_date_created_unix_max = self.df['user_date_created_unix'].max()

        self.company_id_mean = self.df.groupby(['company_id']).is_fake.mean()
        self.company_id_mean = {id: self.company_id_mean[id] for id in self.company_id_mean.index}

        self.company_id_sum = self.df.groupby(['company_id']).is_fake.sum()
        self.company_id_sum = {id: self.company_id_sum[id] for id in self.company_id_sum.index}
        self.company_id_sum_max = max([i for i in list(self.company_id_sum.values())])

        self.user_id_mean = self.df.groupby(['user_id']).is_fake.mean()
        self.user_id_mean = {id: self.user_id_mean[id] for id in self.user_id_mean.index}

        self.user_id_sum = self.df.groupby(['user_id']).is_fake.sum()
        self.user_id_sum = {id: self.user_id_sum[id] for id in self.user_id_sum.index}
        self.user_id_sum_max = max([i for i in list(self.user_id_sum.values())])

        self.product_id_mean = self.df.groupby(['product_id']).is_fake.mean()
        self.product_id_mean = {id: self.product_id_mean[id] for id in self.product_id_mean.index}

        self.product_id_sum = self.df.groupby(['product_id']).is_fake.sum()
        self.product_id_sum = {id: self.product_id_sum[id] for id in self.product_id_sum.index}
        self.product_id_sum_max = max([i for i in list(self.product_id_sum.values())])

        print('fit finished')

    def transform(self, csv_path=None):
        df = self.df if csv_path == None else pd.read_csv(csv_path)
        if csv_path is not None:
            df.user_agent.fillna('', inplace=True)
        parsed_user_agent = apply(parse, df.user_agent.tolist())

        # company_id_onehot = self.one_hot(self.company_id_uniq, df.company_id, unk_code=self.unk_code_int)
        # print('company_id_onehot')
        # user_id_onehot = self.one_hot(self.user_id_uniq, df.user_id, unk_code=self.unk_code_int)
        # print('user_id_onehot')
        # product_id_onehot = self.one_hot(self.product_id_uniq, df.product_id, unk_code=self.unk_code_int)
        # print('product_id_onehot')
        rating_onehot = pd.get_dummies(df.rating)
        print('rating_onehot')
        if csv_path is not None:
            df['date_created_unix'] = apply(str2unix, df.date_created.tolist())
            df['user_date_created_unix'] = apply(str2unix, df.user_date_created.tolist())
        datetime_diff = (df.date_created_unix - df.user_date_created_unix)/self.maxdatetime_diff
        date_created_unix = df['date_created_unix']/self.date_created_unix_max
        user_date_created_unix = df['user_date_created_unix'] / self.user_date_created_unix_max

        is_mobile = parsed_user_agent.apply(lambda x: x.is_mobile)
        is_touch_capable = parsed_user_agent.apply(lambda x: x.is_touch_capable)
        is_pc = parsed_user_agent.apply(lambda x: x.is_pc)
        is_bot = parsed_user_agent.apply(lambda x: x.is_bot)

        company_id_mean = df.company_id.apply(lambda x: self.company_id_mean.get(x, 0))
        company_id_sum = df.company_id.apply(lambda x: self.company_id_sum.get(x, 0))
        company_id_sum /= self.company_id_sum_max
        user_id_mean = df.user_id.apply(lambda x: self.user_id_mean.get(x, 0))
        user_id_sum = df.user_id.apply(lambda x: self.user_id_sum.get(x, 0))
        user_id_sum /= self.user_id_sum_max
        product_id_mean = df.product_id.apply(lambda x: self.product_id_mean.get(x, 0))
        product_id_sum = df.product_id.apply(lambda x: self.product_id_sum.get(x, 0))
        product_id_sum /= self.product_id_sum_max
        languages = pd.get_dummies(apply(foo, df.comment.tolist()))

        to_concat = [
            # company_id_onehot,
            # user_id_onehot,
            # product_id_onehot,
            rating_onehot,
            datetime_diff,
            date_created_unix,
            user_date_created_unix,
            is_mobile,
            is_touch_capable,
            is_pc,
            is_bot,
            company_id_mean,
            company_id_sum,
            user_id_mean,
            user_id_sum,
            product_id_mean,
            product_id_sum,
            languages
        ]

        print('shapes')
        for d in to_concat:
            print(d.shape)

        X = pd.concat(to_concat, axis=1, ignore_index=True)
        print(X.shape)
        X.fillna(0, inplace=True)
        print('transform finished')
        return X

def str2unix(text):
    return parser.parse(text).timestamp()

if __name__ == '__main__':
    data_provider = DataProvider(csv_train)
    Y = data_provider.df.is_fake
    Y.to_pickle('../Y.pkl')
    X_train = data_provider.transform()
    X_train.to_pickle('../X_train.pkl')
    X_test = data_provider.transform(csv_test)
    X_test.to_pickle('../X_test.pkl')


from PyQt5.QtWidgets import QApplication, QMainWindow, QAction, QMessageBox, QFileDialog, QTextEdit, QFontDialog, QColorDialog
import sys
from PyQt5.Qt import QIcon
from PyQt5.QtPrintSupport import QPrinter, QPrintDialog, QPrintPreviewDialog
from PyQt5.QtCore import QFileInfo

class Window(QMainWindow):
    def __init__(self):
        super().__init__()

        self.title = "PyQt5 ColorDialog"
        self.left = 500
        self.top = 200
        self.width = 500
        self.height = 400

        self.setWindowTitle(self.title)
        self.setGeometry(self.left, self.top, self.width, self.height)

        self.create_editor()
        self.create_menu()

        self.show()

    def create_menu(self):
        mainMenu = self.menuBar()
        fileMenu = mainMenu.addMenu("File")
        editMenu = mainMenu.addMenu("Edit")
        viewMenu = mainMenu.addMenu("View")
        helpMenu = mainMenu.addMenu("Help")

        printAction = QAction(QIcon("print.png"), "Print", self)
        printAction.triggered.connect(self.print_dialog)
        fileMenu.addAction(printAction)

        printpreviewAction = QAction(QIcon("printprev.png"), "Print Preview", self)
        printpreviewAction.triggered.connect(self.print_preview_dialog)
        fileMenu.addAction(printpreviewAction)

        pdfAction = QAction(QIcon("pdf.png"), "Export PDF", self)
        pdfAction.triggered.connect(self.pdfExport)
        fileMenu.addAction(pdfAction)

        copyAction = QAction(QIcon("copy.png"), "Copy", self)
        copyAction.setShortcut("Ctrl+C")
        editMenu.addAction(copyAction)

        cutAction = QAction(QIcon("cut.png"), "Cut", self)
        cutAction.setShortcut("Ctrl+X")
        editMenu.addAction(cutAction)

        saveAction = QAction(QIcon("save.png"), "Save", self)
        saveAction.setShortcut("Ctrl+S")
        fileMenu.addAction(saveAction)

        exitAction = QAction(QIcon("exit.png"), "Exit", self)
        exitAction.setShortcut("Alt+F4")
        exitAction.triggered.connect(self.exit_window)
        fileMenu.addAction(exitAction)

        pasteAction = QAction(QIcon("paste.png"), "Paste", self)
        pasteAction.setShortcut("Ctrl+V")
        editMenu.addAction(pasteAction)

        fontAction = QAction(QIcon("font.svg"), "Font", self)
        fontAction.setShortcut("Ctrl+F")
        fontAction.triggered.connect(self.font_dialog)
        viewMenu.addAction(fontAction)

        colorAction = QAction(QIcon("color.png"), "Color", self)
        viewMenu.addAction(colorAction)
        colorAction.triggered.connect(self.color_dialog)

        helpAction = QAction(QIcon("help.png"), "Help", self)
        helpAction.triggered.connect(self.AboutMessageBox)
        helpMenu.addAction(helpAction)

        choiceAction = QAction(QIcon("choice.png"), "Choice Message", self)
        choiceAction.triggered.connect(self.choice_message_box)
        helpMenu.addAction(choiceAction)

        toolbar = self.addToolBar("Toolbar")
        toolbar.addAction(copyAction)
        toolbar.addAction(cutAction)
        toolbar.addAction(pasteAction)
        toolbar.addAction(saveAction)
        toolbar.addAction(exitAction)
        toolbar.addAction(fontAction)
        toolbar.addAction(colorAction)
        toolbar.addAction(printAction)
        toolbar.addAction(printpreviewAction)
        toolbar.addAction(pdfAction)
        toolbar.addAction(helpAction)

    def exit_window(self):
        self.close()

    def create_editor(self):
        self.textEdit = QTextEdit(self)
        self.setCentralWidget(self.textEdit)

    def font_dialog(self):
        font, ok = QFontDialog.getFont()

        if ok:
            self.textEdit.setFont(font)

    def color_dialog(self):
        color = QColorDialog.getColor()
        self.textEdit.setTextColor(color)

    def print_dialog(self):
        printer = QPrinter(QPrinter.HighResolution)
        dialog = QPrintDialog(printer, self)

        if dialog.exec_() == QPrintDialog.Accepted:
            self.textEdit.print_(printer)

    def print_preview_dialog(self):
        printer = QPrinter(QPrinter.HighResolution)
        previewDialog = QPrintPreviewDialog(printer, self)
        previewDialog.paintRequested.connect(self.print_preview)
        previewDialog.exec_()

    def print_preview(self, printer):
        self.textEdit.print_(printer)

    def pdfExport(self):
        fn, _= QFileDialog.getSaveFileName(self, "Export PDF", None, "PDF Files (.pdf);;All Files()")

        if fn != '':
            if QFileInfo(fn).suffix() == "home/ttn/Desktop/" :fn += '.pdf'

            printer = QPrinter(QPrinter.HighResolution)
            printer.setOutputFormat(QPrinter.PdfFormat)
            printer.setOutputFileName(fn)
            self.textEdit.document().print_(printer)

    def AboutMessageBox(self):
        message = QMessageBox.about(self, "About Application", "This is a simple text editor application")

    def choice_message_box(self):
        message = QMessageBox.question(self, "Choice Message", "Do you like PyQt5?",
                                       QMessageBox.Yes | QMessageBox.No)
        if message == QMessageBox.Yes:
            self.textEdit.setText("Yes, I Like PyQt5")

        else:
            self.textEdit.setText("No, I don't!")

App = QApplication(sys.argv)
window = Window()
sys.exit(App.exec())


import pandas as pd
import numpy as np

"""
Vis fordelingen af private parkeringspladser og parkeringsmuligheder for el-biler
ift hver bydels gennemsnitlige bruttoindkomst.
 """

def privat_parking_electric_cars(data, data_income):
    # pivot table is a table of statistics that summarize the data of a more extensive table.
    # They enable a person to arrange and rearrange (or "pivot") statistics in order to draw attention to useful information.
    # We choose with columns we will use as our index and it the pivot table will arrange our data based on the indexs.
    # We the columns "antal_pladser" as our value. and sum it.
    # aggfunc can take a list of functions.
    sort_data = pd.pivot_table(data, index=["bydel", "vejstatus", "p_ordning"], aggfunc=np.sum) # Muligt at tilføje values=["antal_pladser"],
    # print(sort_data)

    privat_parking_el_cars = sort_data.query(
        'vejstatus == ["Privat fællesvej"] & p_ordning ==["El-Bil plads"]') #  & p_ordning ==["El-Bil plads"]

    print('Because of the small amount of private parkingspots for electric cars. We decided not to make a map. This is the private parkingspots.')
    print(privat_parking_el_cars)

    # print(data_income.columns)

    # sort_income_data = pd.pivot_table(data_income, index=["BYDEL", "INDKOMSTKATEGORI"]) # , values=["HUSTANDE"]

    # print(sort_income_data)