from tkinter import *
from tkinter import ttk
from src.utilities.productsTable import TablaProductos

class nuevoPedidos:
    def __init__(self,window):
        self.win=window
        #Creacion de un frame container
        self.container=Frame(self.win)
        frame = LabelFrame(self.container,text='Registrar Nuevo Pedido')
        frame.pack(side="top",padx=15,pady=15,ipadx=8)

        Label(frame,text='Fecha de pedido').grid(row=1,column=0,pady=15,padx=8)
        self.orderDate = Entry(frame)
        self.orderDate.grid(row=1,column=1)

        Label(frame,text="Estado").grid(row=1,column=2,padx=8)
        self.state=ttk.Combobox(frame,
            state='readonly',
            values=['Transito','Entregado'],
            width=10

        ).grid(row=1,column=3)

        Label(frame,text='Costo de inversion').grid(row=3,column=0,pady=15,padx=8)
        self.investment = Entry(frame)
        self.investment.grid(row=3,column=1)

        Label(frame,text='Envio Aprox').grid(row=4,column=0,padx=8,pady=15)
        self.delivery = Entry(frame)
        self.delivery.grid(row=4,column=1)
        #Tabla para mostrar los pedidos agregados
        self.tablaPedidos=TablaProductos(self.container)

    def cerrarPedidos(self):
        self.container.destroy
        print('ventana pedidos destruida')


"""
Gourav Verma
DSC550 - Data Mining
Summer-2020
Week-4 : Assignment- 7.3.4 : BFR Algorithm
Book-Mining of Massive Datasets
"""

# Import important libraries
import numpy as np
import math

# Given 3 clusters
c1 = np.array([[4, 8], [4, 10], [6, 8], [7, 10]])
c2 = np.array([[9, 3], [10, 5], [11, 4], [12, 3], [12, 6]])
c3 = np.array([[2, 2], [3, 4], [5, 2]])

def cal_BFR(c):
    """
    Function to calculate BRF representations
    """
    # Initialize the variables
    n = len(c)
    sumc = [0, 0]
    sumsqc = [0, 0]
    varc = [0, 0]
    sdc = [0, 0]

    for i in range(n):                     # Loop for number of elements in cluster
        sumc[0] += c[i][0]                 # Calculate SUM
        sumc[1] += c[i][1]
        sumsqc[0] += pow(c[i][0], 2)       # Calculate SUM SQUARE
        sumsqc[1] += pow(c[i][1], 2)

    print('==> Cluster - ', c)
    print('N for cluster is     : ', n)
    print('SUM for cluster is   : ', sumc)
    print('SUMSQ for cluster is : ', sumsqc, '\n')

    varc[0] = round(sumsqc[0]/n - pow(sumc[0]/n, 2), 2)    # Calculate Variance for 1st dimension
    varc[1] = round(sumsqc[1]/n - pow(sumc[1]/n, 2), 2)    # Calculate Variance for 2nd dimension

    sdc[0] = round(math.sqrt(varc[0]), 2)                  # Calculate Standard Deviation for 1st dimension
    sdc[1] = round(math.sqrt(varc[1]), 2)                  # Calculate Standard Deviation for 2nd dimension

    print('Variance for cluster is : ', varc)
    print('Standard Deviation for cluster is : ', sdc, '\n')

    return

if __name__ == '__main__':
    print('\n(a) Compute the representation of the cluster as in the BFR Algorithm. Compute N, SUM, and SUMSQ.')
    print('(b) Compute the variance and standard deviation of each cluster in each of the two dimensions.\n')
    cal_BFR(c1)
    cal_BFR(c2)
    cal_BFR(c3)


"""Tests for the VSG instrument class"""

from pyarbtools.instruments import VSG
from pyarbtools.vsaControl import VSA
from pyarbtools import wfmBuilder
import socketscpi
import unittest

class VSGTests(unittest.TestCase):
    @classmethod
    def setUpClass(cls) -> None:
        ipAddress = '192.168.50.124'
        cls.vsg = VSG(ipAddress, reset=True)
        cls.num = 400
        cls.neg = -400
        cls.string = 'bad'
        cls.numList = [0, 1, 2]
        cls.stringList = ['zero', 'one', 'two']
        cls.mixList = [0, 'one', 2e2]
        cls.vsg.err_check()

    # @unittest.skip('Saving time testing the tests.')
    def test_constructor(self):
        self.assertRaises(ValueError, VSG, 'not a valid IP address')
        self.assertRaises(TypeError, VSG, self.num)
        # It's odd that a negative number results in a ValueError rather than a TypeError
        self.assertRaises(ValueError, VSG, self.neg)
        self.assertEqual(type(self.vsg), VSG)

    # @unittest.skip('Saving time testing the tests.')
    def test_configure(self):

        # general
        self.assertRaises(KeyError, self.vsg.configure, badkey=0)
        self.assertRaises(TypeError, self.vsg.configure, 5)
        self.assertRaises(TypeError, self.vsg.configure, self.string)

    # @unittest.skip('Saving time testing the tests.')
    def test_rfState(self):
        # rfState
        self.assertRaises(ValueError, self.vsg.configure, rfState=self.string)
        self.assertRaises(ValueError, self.vsg.configure, rfState=self.num)
        self.assertRaises(ValueError, self.vsg.configure, rfState=self.neg)

        self.vsg.configure(rfState='on')
        self.assertEqual(self.vsg.rfState, 1)
        self.vsg.configure(rfState='off')
        self.assertEqual(self.vsg.rfState, 0)

    # @unittest.skip('Saving time testing the tests.')
    def test_modState(self):
        # modState
        self.assertRaises(ValueError, self.vsg.configure, modState=self.string)
        self.assertRaises(ValueError, self.vsg.configure, modState=self.num)
        self.assertRaises(ValueError, self.vsg.configure, modState=self.neg)

        self.vsg.configure(modState='on')
        self.assertEqual(self.vsg.modState, 1)
        self.vsg.configure(modState='off')
        self.assertEqual(self.vsg.modState, 0)

    # @unittest.skip('Saving time testing the tests.')
    def test_cf(self):
        # cf
        self.assertRaises(ValueError, self.vsg.configure, cf=self.string)
        self.assertRaises(ValueError, self.vsg.configure, cf=self.neg)

        cf = 1e9
        self.vsg.configure(cf=cf)
        self.assertEqual(self.vsg.cf, cf)

    # @unittest.skip('Saving time testing the tests.')
    def test_amp(self):
        # amp
        self.assertRaises(ValueError, self.vsg.configure, amp=self.string)

        amp = -20
        self.vsg.configure(amp=amp)
        self.assertEqual(self.vsg.amp, amp)

    # @unittest.skip('Saving time testing the tests.')
    def test_alcState(self):
        # alcState
        self.assertRaises(ValueError, self.vsg.configure, alcState=self.string)
        self.assertRaises(ValueError, self.vsg.configure, alcState=self.num)
        self.assertRaises(ValueError, self.vsg.configure, alcState=self.neg)

        self.vsg.configure(alcState='on')
        self.assertEqual(self.vsg.alcState, 1)
        self.vsg.configure(alcState='off')
        self.assertEqual(self.vsg.alcState, 0)

    # @unittest.skip('Saving time testing the tests.')
    def test_iqScale(self):
        # iqScale
        self.assertRaises(ValueError, self.vsg.configure, iqScale=self.string)
        self.assertRaises(ValueError, self.vsg.configure, iqScale=self.num)
        self.assertRaises(ValueError, self.vsg.configure, iqScale=self.neg)

        iqScale = 65
        self.vsg.configure(iqScale=iqScale)
        self.assertEqual(self.vsg.iqScale, iqScale)

    # @unittest.skip('Saving time testing the tests.')
    def test_refSrc(self):
        # refSrc
        self.assertRaises(ValueError, self.vsg.configure, refSrc=self.string)
        self.assertRaises(ValueError, self.vsg.configure, refSrc=self.num)
        self.assertRaises(ValueError, self.vsg.configure, refSrc=self.neg)

        refSrc = 'int'
        self.vsg.configure(refSrc=refSrc)
        self.assertEqual(self.vsg.refSrc.lower(), refSrc)

    # @unittest.skip('Saving time testing the tests.')
    def test_fs(self):
        # fs
        self.assertRaises(ValueError, self.vsg.configure, fs=self.string)
        self.assertRaises(ValueError, self.vsg.configure, fs=self.neg)

        fs = 10e6
        self.vsg.configure(fs=fs)
        self.assertEqual(self.vsg.fs, fs)

        # self.vsg.configure(rfState=1)
        # print(self.vsg.rfState)

    # @unittest.skip('Saving time testing the tests.')
    def test_download_play_stop(self):
        fs = 40e6
        self.vsg.configure(cf=1e9, amp=-20, fs=fs)
        wfmData = wfmBuilder.digmod_generator(fs=fs, symRate=10e6, modType='qpsk')
        badData = wfmBuilder.sine_generator(fs=fs, wfmFormat='real')

        self.assertRaises(TypeError, self.vsg.download_wfm, self.string)
        self.assertRaises(TypeError, self.vsg.download_wfm, self.num)
        self.assertRaises(TypeError, self.vsg.download_wfm, self.neg)
        self.assertRaises(TypeError, self.vsg.download_wfm, badData)

        id = self.vsg.download_wfm(wfmData)
        self.vsg.err_check()

        self.vsg.play(id)
        self.assertEqual(self.vsg.rfState, 1)
        self.assertEqual(self.vsg.modState, 1)
        self.assertEqual(self.vsg.arbState, 1)

        self.vsg.stop()
        self.assertEqual(self.vsg.rfState, 0)
        self.assertEqual(self.vsg.modState, 0)
        self.assertEqual(self.vsg.arbState, 0)

    def test_wfm_fidelity(self):

        amplitude = -10
        fs = 40e6
        freq = 1e9
        self.vsg.configure(amp=amplitude, fs=fs, cf=freq)

        # Waveform creation variables
        symRate = 10e6
        modType = 'qpsk'
        psFilter = 'rootraisedcosine'
        alpha = 0.35
        name = 'digmod'
        mFilter = 'rootraisedcosine'
        rFilter = 'raisedcosine'

        print('Creating waveform.')
        # This is the new digital modulation waveform creation function
        data = wfmBuilder.digmod_generator(fs=fs, symRate=symRate, modType=modType, filt=psFilter, numSymbols=1000,
                                                      alpha=alpha)

        # Download and play waveform
        self.vsg.download_wfm(data, wfmID=name)
        self.vsg.play(name)

        # Create VSA object
        vsa = VSA('127.0.0.1', vsaHardware='Morgan Office MXA', timeout=30, reset=False)

        # Select a digital demod measurement and configure it to measure the saved waveform
        vsa.set_measurement('ddemod')

        # Configure digital demodulation in VSA
        vsa.configure_ddemod(cf=freq, amp=0, span=symRate * 2, modType=modType, symRate=symRate, measFilter=mFilter,
                             refFilter=rFilter, filterAlpha=alpha, measLength=4096, eqState=False)

        # Perform a single-shot replay in VSA
        vsa.acquire_single()

        meas = float(vsa.query(f'trace4:data:table? "EvmRms"').strip())
        self.assertLess(meas, 2)

        # Check for errors and gracefully disconnect
        vsa.err_check()
        vsa.disconnect()

    @classmethod
    def tearDownClass(cls) -> None:
        cls.vsg.write('*rst')
        cls.vsg.query('*opc?')
        cls.vsg.disconnect()

if __name__ == 'main':

    unittest.main()


# -*- coding: utf-8 -*-
# Required to import the rest of the oscar models unfortunately
import stripe

from django.conf import settings
from django.db import models
from django.db.models.deletion import SET_NULL
from django.utils.translation import ugettext_lazy as _
from oscar.apps.customer.models import *  # noqa

from djstripe.stripe_objects import StripeCustomer
from djstripe.models import Charge

class GuestStripeCustomer(StripeCustomer):
    """ Anonymous User (Guest) used for creating charges during checkout """
    email = models.EmailField(_('email address'))
    default_source = models.ForeignKey(
        Charge,
        null=True,
        related_name="guest_customers",
        on_delete=SET_NULL
    )

    def can_charge(self):
        return self.has_valid_card()

    @classmethod
    def _api(cls):
        """
        Get the api object for this type of stripe object (requires
        stripe_api_name attribute to be set on model).
        """
        if cls.stripe_api_name is None:
            raise NotImplementedError("StripeObject descendants are required to define "
                                      "the stripe_api_name attribute")
        # e.g. stripe.Event, stripe.Charge, etc
        return getattr(stripe, cls.stripe_api_name)

    @classmethod
    def _api_create(cls, api_key=settings.STRIPE_SECRET_KEY, **kwargs):
        """
        Call the stripe API's create operation for this model.
        :param api_key: The api key to use for this request. Defualts to settings.STRIPE_SECRET_KEY.
        :type api_key: string
        """

        return cls._api().create(api_key=api_key, **kwargs)

    @classmethod
    def create(cls, email):
        stripe_customer = cls._api_create(email=email)
        customer, created = cls.objects.get_or_create(
            email=email,
            stripe_id=stripe_customer.id,
        )
        return customer

    def add_card(self, source, set_default=True):
        """
        Adds a card to this customer's account.
        :param source: Either a token, like the ones returned by our Stripe.js, or a dictionary containing a
                       user's credit card details. Stripe will automatically validate the card.
        :type source: string, dict
        :param set_default: Whether or not to set the source as the customer's default source
        :type set_default: boolean
        """

        stripe_customer = self.api_retrieve()
        stripe_card = stripe_customer.sources.create(source=source)

        if set_default:
            stripe_customer.default_source = stripe_card["id"]
            stripe_customer.save()

        return stripe_card


import scipy.signal as signal
from scipy.io.wavfile import write, read
import numpy as np
import xlrd
from xlutils.copy import copy
import scipy.signal as signal
import copy
import math

def invoke(sig, mov, sen, vel):
	"""
	Importa archivos .wav de prueba de acuerdo a sus caracteristicas
	"""

	fs, x = read('../Sonidos/viet/'+sig+mov+vel+sen+'m.wav')
	fs, y = read('../Sonidos/viet/'+sig+mov+vel+sen+'f.wav')
	fs = float(fs)
	return fs, x, y

def trim(X1, X2, fs, t):

	if len(X1)>t*fs and len(X2)>t*fs:
		X1 = X1[:int(t*fs)]
		X2 = X2[:int(t*fs)]

	elif len(X1)>len(X2):
		X1 = X1[:len(X2)]

	else:
		X2 = X2[:len(X1)]

	return X1, X2

def norm(x):
	"""
	Normaliza los archivos de audio poniendo el pico en el valor 1
	"""
	m = float(max(abs(x)))
	X = x/m
	return X

def filtroPB(n,f1,f2,fs,x,lv):
	"""
	Filtro pasa banda para archivos .wav mono.
	Input:
		n: Numero de muestras de la respuesta al impulso
		f1: Frecuencia de corte inferior
		f2: Frecuencia de corte superior
		fs: Frecuencia de muestreo
		x: Archivo .wav a filrar
	Output:
		array del archivo filtrado
	"""
	fs = float(fs)
	# f1 = fs/float((lv/2.0))  # Define la frecuencia de corte inferior de forma que entren al menos 2 ciclos por ventana
	# if f1 < 100:
	# 	f1 = 100
	a = signal.firwin(n, cutoff = f1/(fs/2.0), window = 'blackman')
	b = - signal.firwin(n, cutoff = f2/(fs/2.0), window = 'blackman')
	b[n/2] = b[n/2] + 1
	d = - (a+b)
	d[n/2] = d[n/2] + 1

	X = signal.fftconvolve(x, d, 'same')
	return X

def vinicial(X1, X2, lv, y1, y2):

	X11 = copy.deepcopy(X1)
	X22 = copy.deepcopy(X2)
	X11 = np.append(X11, np.zeros(lv-len(X11)%lv))
	X22 = np.append(X22, np.zeros(lv-len(X22)%lv))
	l   = len(X11)/lv

	rms1 = float(np.sqrt(np.mean(X11**2)))
	rms2 = float(np.sqrt(np.mean(X22**2)))
	X11  = X11/rms1
	X22  = X22/rms2

	X11  = X11[:l*lv]
	X111 = copy.deepcopy(X11)
	X22  = X22[:l*lv]
	nl   = np.floor(np.log2(len(X11)/lv)) #Numero de loops

	cmax  = np.zeros(2)
	cpos  = np.zeros(2)
	Cposa = 0
	X2pos = 0 # Posicion inicial del segmento final de X2
	j     = 0

	while j<nl:
		l2 = np.round(len(X111)/2)

		for i in range(2):
			u1      = l2*i
			u2      = u1 + l2
			X2C     = X22[u1:u2] # Corta la senal modificada en partes igualles
			Y       = signal.correlate(X111,X2C,'full','fft') # Correlacion entre senal modificada cortada y de referencia
			cmax[i] = float(max(Y)/float(len(Y))) # Vector de valores maximos de correlacion
			s       = len(Y)/2
			cpos[i] = np.argmax(Y) - s # Vector de posicion de valores maximos de correlacion

		Cposr = np.argmax(cmax) # Maxima posicion relativa
		X2pos = Cposr*l2 + X2pos
		Cposa = int(cpos[Cposr]) + Cposa   # Maxima posicion absoluta
		X22   = X22[l2*Cposr:l2*(Cposr+1)]
		# print Cposa

		mp = len(X11)/2+Cposa-l2/2  # Posicion inicial del vector X111 con respecto a X11

		if mp>=0:
			X111 = X11[mp:mp+l2]
		else:
			X111 = np.append(np.zeros(abs(mp)),X11[:l2+mp])

		# c = signal.correlate(X111,X22,'full','fft')
		# print(np.argmax(c)-len(c)/2)

		j+=1

	n = mp-X2pos

	if n<0:
		z = np.zeros(abs(n))
		X1 = np.append(z,X1)
		y1 = np.append(z,y1)
		X2 = np.append(X2,z)
		y2 = np.append(y2,z)
		r = X2pos
	elif n>0:
		z = np.zeros(abs(n))
		X2 = np.append(z,X2)
		y2 = np.append(z,y2)
		X1 = np.append(X1,z)
		y1 = np.append(y1,z)
		r = mp

	return X1, X2, r, y1, y2

def cor2(X1, X2, lv, p, g, mv, fs, CCM, u):
	"""
	Correlacion cruzada de audios.
	lv es la longitud de la ventana temporal a utilizar.
	p es el porcentaje de lv donde transiciona entre 0 y 1.
	g es el umbral del gate
	mv es la maxima velocidad de desplazamiento entre microfonos
	fs es la frecuencia de muestreo
	CCM es el coeficiente de correlacion minima
	"""

	X11 = copy.deepcopy(X1)
	X12 = copy.deepcopy(X2)
	X11 = np.append(X11,np.zeros(lv-len(X11)%lv))
	X12 = np.append(X12,np.zeros(lv-len(X12)%lv))

	################## Ventana temporal #########################
	w  = np.blackman(round(lv*p)) 	 # Genera la ventana blackman
	w1 = np.append(w[:len(w)/2],np.ones(int(round(lv*(1-p)))))
	w1 = np.append(w1, w[len(w)/2:]) # Crea la ventana temporal de longitud lv

	################## Generacion de arrays del bucle for #######
	l  = int(len(X11)/float(lv))  # Cantidad de ventanas temporales/ cilos for
	ta = np.zeros(l) 			  # Vector de corrimentos absolutos
	CC = np.zeros(l) 			  # Vector de maximas correlaciones por ventana
	M  = np.ones(l)   			  # Vector de coeficientes de correccion por umbral de amplitud
	N  = np.ones(l)   			  # Vector de coeficientes de correccion por umbral de correlacion

	################## Maximo Corrimiento Posible ###############
	h    = 2.0 							# Multiplicador del maximo corrimiento
	mcs  = math.ceil(fs*mv/343.0) 		# Maximo corrimiento en muestras por segundo
	mcv  = int(math.ceil(lv*mcs/fs)*h)  # Maximo corrimiento en muestras por ventana
	mcvl = int(math.ceil(mcv/2.0)) 		# Maximo corrimiento lateral

	################## Parametros del bucle #####################
	m    = 3									# Coeficiente de correccion por umbral de amplitud
	mm   = 5									# Maximo valor de m
	n    = 10 									# Coeficiente de correccion por umbral de correlacion
	nm   = 5									# Maximo valor de n
	tt   = 0 							    	# Parametro de ajuste para la correlacion
	rms1 = float(np.sqrt(np.mean(X11**2))) 	# Valor rms de la senal X11
	rms2 = float(np.sqrt(np.mean(X12**2))) 	# Valor rms de la senal X12

	################## Bucle de correlacion #####################

	z  = np.arange(u/lv-1,-1,-1)
	t0 = np.zeros(len(z)) 			            # Vector de corrimientos relativos a i-1
	for i in z:									# Calculo de corrimientos a la izquierda de la ventana inicial
		lv1  = int(lv*i) 						# Limite inferior
		lv2  = int(lv*(i+1))					# Limite superior
		Y1   = X11[lv1:lv2]*w1 					# Senal de referencia ventaneada en tiempo
		RMS1 = float(np.sqrt(np.mean(Y1**2))) 	# Valor RMS de la ventana de referencia
		Y1   = Y1/RMS1 							# Senal de referencia normalizada a su valor RMS

		if RMS1/rms1>g:							# Gate de la senal de referencia
			r = int(np.ceil(mcvl*m*n)) 			# Cantidad de muestras del corrimiento lateral por ventana
			c = np.zeros(int(np.ceil(mcv*m*n)+1))	# Vector de correlaciones por ciclo del bucle

			for j in range(-r, r+1): # Ventaneo de la senal desplazada

				if i == 0 and j < 0: 		# Condicion inicial de corrimiento hacia la izquierda
					Y2   = np.append(np.zeros(abs(j)),X12[:int(lv2+j)])*w1 # Ventana Y2
					RMS2 = float(np.sqrt(np.mean(Y2**2)))				   # Valor RMS de Y2
					Y2   = Y2/RMS2 										   # Y2 Normalizada a su valor RMS

				elif i == 0 and j >= 0:		# Condicion inicial de corrimiento hacia la derecha
					Y2   = X12[j:int(lv2+j)]*w1  						   # Ventana Y2
					RMS2 = float(np.sqrt(np.mean(Y2**2)))				   # Valor RMS de Y2
					Y2   = Y2/RMS2										   # Y2 Normalizada a su valor RMS

				elif len(X12[int(lv1-tt-j):int(lv2-tt-j)]) == lv: # Condicion normal
					Y2   = X12[int(lv1-tt-j):int(lv2-tt-j)]*w1 	# Ventana Y2
					RMS2 = float(np.sqrt(np.mean(Y2**2))) 		# Valor cuadratico medio de Y2
					Y2   = Y2/RMS2								# Y2 Normalizada a su valor RMS

				else:
					T    = len(X12[int(lv1-tt-j):int(lv2-tt-j)])	 	                # Ultima ventana
					TT   = np.append(X12[int(lv1-tt-j):int(lv2-tt-j)],np.zeros(lv-T))	# Ventana Y2
					Y2   = TT*w1
					RMS2 = float(np.sqrt(np.mean(Y2**2)))   					    	# Valor cuadratico medio de Y2
					Y2   = Y2/float(RMS2)						 					    # Y2 Normalizada a su valor RMS

				if RMS2/rms2>g: 								    	# Gate de la senal desplazada
					m      = 1 											# Reset del coeficiente de corrimiento maximo por amplitud
					c[j+r] = signal.correlate(Y1, Y2,'valid','fft')     # Correlacion de senales
					C      = max(c)/float(lv) 							# Valor de correlacion maxima

					if C >= CCM: 			# Condicion para valores de correlacion por debajo del umbral CCM
						cm    = np.argmax(c)-r 	# Posicion del valor de maxima correlacion
						t0[i] = cm
						n     = 1				# Reset del coeficiente de corrimiento maximo por correlacion
						CC[i] = C				# Vector de valores maximos de correlacion

					else:
						cm     = 0
						CC [i] = CCM

						if n<nm:
							n += 1

					N[i] = n # Vector de coeficientes de correccion por umbral de correlacion

				else:
					t0[i] = 0

					if m<mm:
						m += 1
		else:
			t0[i] = 0

			if m<mm:
				m += 1

		M[i] = m # Vector de coeficientes de correccion por umbral de amplitud

		####### Vectores de corrimientos tt y ta ########
		tt = sum(t0)
		ta[i] = tt

	t1 = np.zeros(2+l-u/lv) 			    # Vector de corrimientos relativos a i-1
	m  = 1									# Coeficiente de correccion por umbral de amplitud
	n  = 10 									# Coeficiente de correccion por umbral de correlacion
	tt = 0 									# Parametro de ajuste para la correlacion
	z  = np.arange(u/lv,l)

	for i in z:
		lv1  = int(lv*i) 						# Limite inferior
		lv2  = int(lv*(i+1))						# Limite superior
		Y1   = X11[lv1:lv2]*w1 					# Senal de referencia ventaneada en tiempo
		RMS1 = float(np.sqrt(np.mean(Y1**2))) 	# Valor RMS de la ventana de referencia
		Y1   = Y1/RMS1 							# Senal de referencia normalizada a su valor RMS

		if RMS1/rms1>g:							# Gate de la senal de referencia
			r = int(np.ceil(mcvl*m*n)) 			# Cantidad de muestras del corrimiento lateral por ventana
			c = np.zeros(int(np.ceil(mcv*m*n)+1))	# Vector de correlaciones por ciclo del bucle

			for j in range(-r, r+1): 			# Ventaneo de la senal desplazada
				if i == 0 and j < 0: 		# Condicion inicial de corrimiento hacia la izquierda
					Y2   = np.append(np.zeros(abs(j)),X12[:int(lv2+j)])*w1 # Ventana Y2
					RMS2 = float(np.sqrt(np.mean(Y2**2)))				 # Valor RMS de Y2
					Y2   = Y2/RMS2 										 # Y2 Normalizada a su valor RMS

				elif i == 0 and j >= 0:		# Condicion inicial de corrimiento hacia la derecha
					Y2   = X12[j:int(lv2+j)]*w1  							 # Ventana Y2
					RMS2 = float(np.sqrt(np.mean(Y2**2)))				 # Valor RMS de Y2
					Y2   = Y2/RMS2										 # Y2 Normalizada a su valor RMS

				elif len(X12[int(lv1-tt-j):int(lv2-tt-j)]) == lv: # Condicion normal
					Y2   = X12[int(lv1-tt-j):int(lv2-tt-j)]*w1 	  # Ventana Y2
					RMS2 = float(np.sqrt(np.mean(Y2**2))) 		  # Valor cuadratico medio de Y2
					Y2   = Y2/RMS2								  # Y2 Normalizada a su valor RMS

				else:
					T    = len(X12[int(lv1-tt-j):int(lv2-tt-j)])	  					# Ultima ventana
					TT   = np.append(X12[int(lv1-tt-j):int(lv2-tt-j)],np.zeros(lv-T))	# Ventana Y2
					Y2   = TT*w1
					RMS2 = float(np.sqrt(np.mean(Y2**2)))   						# Valor cuadratico medio de Y2
					Y2   = Y2/float(RMS2)						 						# Y2 Normalizada a su valor RMS

				if RMS2/rms2>g: 									# Gate de la senal desplazada
					m      = 1 											# Reset del coeficiente de corrimiento maximo por amplitud
					c[j+r] = signal.correlate(Y1, Y2,'valid','fft') # Correlacion de senales
					C      = max(c)/float(lv) 							# Valor de correlacion maxima

					if C >= CCM: 				# Condicion para valores de correlacion por debajo del umbral CCM
						cm         = np.argmax(c)-r 	# Posicion del valor de maxima correlacion
						t1[i-u/lv] = cm
						n          = 1					# Reset del coeficiente de corrimiento maximo por correlacion
						CC[i]      = C				# Vector de valores maximos de correlacion

					else:
						cm     = 0
						CC [i] = CCM

						if n<nm:
							n += 1

					N[i] = n # Vector de coeficientes de correccion por umbral de correlacion

				else:
					t1[i-u/lv] = 0

					if m<mm:
						m += 1

		else:
			t1[i-u/lv] = 0

			if m<mm:
				m += 1

		M[i] = m # Vector de coeficientes de correccion por umbral de amplitud

		####### Vectores de corrimientos tt y ta ########
		tt    = sum(t1)
		ta[i] = tt

	return t0, t1, ta, l, CC, N, M

def aligne(ta, X2, lv, pcf):
	"""
	Alinea temporalmente X2 de acuerdo a los coeficientes ta de a lv muestras
	"""

	############ Crossover ###############
	lon = lv*pcf                        # Longitud del CO
	t = np.arange(0, np.pi, np.pi/lon)  # Variable independiente del CO
	fad = 0.5 + 0.5*np.sin(t+np.pi/2.0) # Funcion del CO

	############ Generacion de arrays para el ciclo #################
	X2 = np.append(X2, np.zeros(abs(int(ta[-1]))))  # Extiende X2 en caso que el resultado final sea mas largo que el original
	X2 = np.append(X2, np.zeros(lv-len(X2)%lv)) 	# Extiende X2 para ser multiplo de lv
	Xf = np.zeros(len(X2)) 							# Genera el array Xf donde se guardan las muestras del archivo final

	############# Alineacion de la ultima ventana ##################
	if ta[-1]>0:
		Xf[len(Xf)-lv:len(Xf)-lv+len(X2[int((len(ta)-1)*lv):int((len(ta)-1)*lv)+lv])] = X2[int((len(ta)-1)*lv):int((len(ta)-1)*lv)+lv]

	else:
		Xf[int((len(ta)-1)*lv+ta[-1]):int((len(ta)-1)*lv+ta[-1])+len(X2[int((len(ta)-1)*lv):])] = X2[int((len(ta)-1)*lv):]

	############# Alineacion de las ventanas centrales #############
	for i in range(1,len(ta)-2):
		# print(ta[i])
		# Evaluar caso donde ta[1]>lv
		if ta[i]>=0:
			Xf[int(i*lv-lon/2.0):int(i*lv+lon/2.0)] = X2[int(i*lv-ta[i-1]-lon/2.0):int(i*lv-ta[i-1]+lon/2.0)]*fad+X2[int(i*lv-ta[i]-lon/2.0):int(i*lv-ta[i]+lon/2.0)]*(1-fad) #Banda de transicion
			Xf[int(i*lv+lon/2.0):int(i*lv+lv+ta[i]-lon/2.0)] = X2[int(i*lv-ta[i]+lon/2.0):int(i*lv+lv-lon/2.0)]

		elif all([ta[i]<0,i*lv+ta[i]+lon/2.0>0]):
			Xf[int(i*lv-lon/2.0):int(i*lv+lon/2.0)] = X2[int(i*lv-ta[i-1]-lon/2.0):int(i*lv-ta[i-1]+lon/2.0)]*fad+X2[int(i*lv-ta[i]-lon/2.0):int(i*lv-ta[i]+lon/2.0)]*(1-fad) # Banda de transicion
			Xf[int(i*lv+ta[i]+lon/2.0):int(i*lv+lv-lon/2.0)] = X2[int(i*lv+lon/2.0):int(i*lv+lv-ta[i]-lon/2.0)]

	############# Alineacion de la primer ventana ##################
	if ta[0]>0: # mover senal desplazada hacia la derecha
		Xf[:int(ta[0]+lv)] = np.append(np.zeros(int(abs(ta[0]))), X2[:lv])

	elif all([ta[0]<0,abs(ta[0])<lv]): 		# mover senal desplazada hacia la izquierda
		Xf[:int(lv+ta[0])] = X2[int(abs(ta[0])):lv]

	elif all([ta[0]<0,abs(ta[0])>lv]):
		Xf = np.append(X2[:int(abs(t[0]))],Xf)

	return Xf

def expExcel(fileName, sheetNum, row0, col0, x):
	"""
	Exporta un array a un archivo .xls existente.
	Input:
		fileName: ubicacion del archivo
		sheetNum: numero de la hoja a modificar
		row0: fila inicial
		col0: columna inicial
		x: array
	"""
	rb = xlrd.open_workbook(fileName)
	wb = copy(rb)
	w_sheet = wb.get_sheet(sheetNum)

	r, c = np.shape(x)

	for i in np.arange(r):
		for j in np.arange(c):
			w_sheet.write(i + row0, j + col0, x[i][j])

	wb.save(fileName)


class CPU:
    def __init__(self, name, fr):
        self.name = name
        self.fr = fr

class Memory:
    def __init__(self, name, volume):
        self.name = name
        self.volume = volume

class MotherBoard:
    def __init__(self, name, cpu, *args):
        self.name = name
        self.cpu = cpu
        self.total_mem_slots = 4
        self.mem_slots = args

    def get_config(self):
        print(f'Материнская плата: {self.name}'
              f'Центральный процессор: {self.cpu.name}, <тактовая частота>'
              f'Слотов памяти: {self.total_mem_slots}'
              f'Память: <наименование_1> - <объем_1>; <наименование_2> - <объем_2>; ...; <наименование_N> - <объем_N>')

cpu = CPU('intel', 2800)
mem = Memory('pioneer', 8)
mb = MotherBoard('asus', cpu, mem)

mb.get_config()


import pprint as pretty
from pymongo import MongoClient
# Assumes state and airport are already a db collection

# create mongo connection
client = MongoClient() # default port
db = client.geo # db connection
states = db.states # collection in db
airports = db.airports

state = states.find_one()['loc']
# pretty.pprint(state)

query = airports.find({ "loc": {"$geoWithin": {"$geometry": state}}})

for result in query:
    pretty.pprint(result)


from getInput import *

def playMadlibs():

    #I If you aren't using these; you can just delete them.

    # friend1 = getWord("Enter a Name: ")
    # numAnimals = getNumber("Enter a number: ", 2, 10)
    # animals1 = getWord("Enter a pluaral animal name: ")
    # color1 = getColor("Enter a color: ")
    # friend2 = getWord("Enter a Name: ")
    country1 = getCountry("Enter a Middle Eastern Country: ")
    animal1 = getWord( "Enter an animal: ")
    bodypart1 = getWord( "Enter an appropriate body part: ")
    object1 = getWord( "Enter a household object: ")
    noise1 = getWord( "Enter a common sound heard in New York City: ")
    object2 = getWord( "Enter a musical instrament: " )
    bodypart2 = getWord("Enter an appropriate body part: ")
    cry1 = getWord("Enter a victory noise: ")

    output = ""
    output += "One day, I stumbled into " + country1 + ","
    output += " Where I suddenly came face-to-face with a wild " + animal1 + "."
    output += " I stood frozen there, my eyes glued to the animals massive " + bodypart1 + "."
    output += "Thinking fast, I grabbed the nearest weapon, a " + object1 + "."
    output += "The " + animal1 + " charged, releasing a war cry that sounded like a " + noise1 +"."
    output += " I perried the first blow with my trusty " + object2
    output += " and stabbeded the monster with its own " + bodypart2
    output += " The moster vanished and I stood triumphantly, waving my shiny " + object1 + " high in the air and letting loose my signature victory cry, " + cry1 + "."
    output += " THE END"

    return output


from galaxy_analysis.plot.plot_styles import *
rc('font', size=22)#, ftype=42)

import yt
import numpy as np
from copy import copy
import sys
import deepdish as dd
from scipy.optimize import brentq
from galaxy_analysis.utilities import utilities
import h5py
from galaxy_analysis.utilities import functions

import matplotlib.pyplot as plt

from scipy import integrate
from scipy.stats import distributions  # may not need
from scipy import stats

def gather_time_series(datafile, dsarray, phase, field, centers = None):

    if 'over' in field:
        cname = 'abins'
    else:
        cname = 'bins'

    i = 0
#    ldata = {dsarray[0]: dd.io.load(datafile, "/" + dsarray[0])}
    data  = load_distribution_data(datafile, dsarray[0], phase, field, centers = cname)
    time_series = {}
    for k in data.keys():
        if k == 'hist':
            continue
        time_series[k] = np.zeros(np.size(dsarray))

    for dsname in dsarray:
#        ldata = {dsname : dd.io.load(gas_file, "/" + dsname)}

        data  = load_distribution_data(datafile, dsname, phase, field, centers = cname)

        for k in data.keys():

            if np.size(data[k]) > 1: # cannot handle > 1D data for now
                continue

            time_series[k][i] = data[k]

        i = i + 1

    return time_series

def plot_normalized(ax, masses, field, xnorm = 'median'):
    return

def resolution_study(abundance_filename,
                     work_dir = './', output_dir = None,
                     comparison = None):

    phases = ['CNM','WNM','WIM','HIM']

    if output_dir is None:
        output_dir = work_dir

    if comparison is None:
        labels = {'3pcH2' : '3.6 pc', '6pcH2' : '7.2 pc' , 'Fiducial' : 'Fiducial'}
        lstyle = {'3pcH2' : '--', '6pcH2' : '-.' , 'Fiducial' : '-'}
        dirs   = {'3pcH2' : '../3pc_H2/abundances/', '6pcH2' : '../6pc_H2/abundances/', 'Fiducial' : ''}
        for k in dirs.keys():
            dirs[k] = work_dir + dirs[k]
    else:
        dirs = {}
        labels = {}
        lstyle = {}
        for k in comparison.keys():
            dirs[k] = work_dir + comparison[0]
            labels[k] = comparison[1]
            lstyle[k] = comparison[2]

    fig, ax = plt.subplots(2,2,sharex=True,sharey=True)
    fig.set_size_inches(12,12)
    fig.subplots_adjust(hspace=0.0,wspace=0.0)
    #
    # Plot individual panels showing:
    #   a time evolution of
    #
    time_data = {}
    for k in labels.keys():
        f = h5py.File(dirs[k] + abundance_filename,'r')
        dsarray = np.sort([str(x) for x in f.keys() if 'DD' in x])
        f.close()
        time_data[k] = {}
        time_data[k]['times'] = np.array([float(x.strip('DD')) for x in dsarray])
        time_data[k]['times'] = time_data[k]['times'] - time_data[k]['times'][0]
        for field in ['O_Fraction','Ba_Fraction']:
            time_data[k][field] = {}
            for phase in phases:
                time_data[k][field][phase] = gather_time_series(dirs[k] + abundance_filename,
                                                                dsarray, phase, field)

    for phase in phases:
        ls = '-'
        if phase == 'HIM':
            ls = ':'
        ax[(0,0)].plot(time_data['3pcH2']['times'],
                       time_data['3pcH2']['O_Fraction'][phase]['q90_q10_range'],
                        lw = 3, color = color_dict[phase], ls = ls)
        ax[(1,0)].plot(time_data['3pcH2']['times'],
                       time_data['3pcH2']['Ba_Fraction'][phase]['q90_q10_range'],
                       lw = 3, color = color_dict[phase], ls = ls)
        ax[(0,1)].plot(time_data['6pcH2']['times'],
                       time_data['6pcH2']['O_Fraction'][phase]['q90_q10_range'],
                         lw = 3, color = color_dict[phase], ls = ls)
        ax[(1,1)].plot(time_data['6pcH2']['times'],
                       time_data['6pcH2']['Ba_Fraction'][phase]['q90_q10_range'],
                         lw = 3, color = color_dict[phase], ls = ls)

    for a1 in ax:
        for a2 in a1:
            a2.set_xlim(0, 600)
            a2.set_ylim(0, 3)
            a2.minorticks_on()

    for i in [0,1]:
        ax[(i,0)].set_ylabel(r'log(90%) - log(10%) [dex]')
        ax[(1,i)].set_xlabel(r'Time (Myr)')

    x = 400
    y = 2.7
    size = 20
    ax[(0,0)].text(x, y, r'O  - 3.6 pc', color = 'black', size = size)
    ax[(1,0)].text(x, y, r'Ba - 3.6 pc', color = 'black', size = size)
    ax[(0,1)].text(x, y, r'O  - 7.2 pc', color = 'black', size = size)
    ax[(1,1)].text(x, y, r'Ba - 7.2 pc', color = 'black', size = size)

    #plt.tight_layout()
    fig.savefig('O_Ba_spread_resolution-comparison.png')
    plt.close()

    return

def single_element(datafile, galaxy_file, dsname, show_fit = True,
                   element = 'O', phases = ['Disk','CNM','WNM','WIM','HIM'], outname = None,
                   xlabel = None, ylabel = None, label = None, xnorm = None):

    if outname is None:
        outname = galaxy_file.split('_galaxy')[0] + '_' + element + '_' +  '_'.join(phases)
        if show_fit:
            outname = outname + '_fit'
        outname = outname + '.png'

    print(outname)
    fig, ax = plt.subplots(1)
    fig.set_size_inches(8,8)

    gasdata = dd.io.load(galaxy_file, '/gas_meta_data/masses')
    masses = {}
    for k in gasdata.keys():
        try:
            masses[k] = gasdata[k]['Total']
        except:
            print(k)

    if not 'over' in element:
        centers = 'bins'
        field = element + '_Fraction'
    else:
        centers = 'abins'
        field = element
    disk_data = load_distribution_data(datafile, dsname, 'Disk', field, centers = centers)
    print(list(disk_data.keys()))
    disk_data['norm_y'] = disk_data['hist'] / disk_data['binsize']
    xbins = disk_data['bins']
    xcent = disk_data['centers']

    if not ((xnorm is None) or (xnorm == 'None')):
        ax.set_xlim(-3,3)
    else:
        ax.set_xlim(disk_data['median']-3.0, disk_data['median']+3.0)

    if xnorm is None  or  xnorm == "None":
        xplotnorm = 0.0
    elif xnorm == 'median':
        xplotnorm = disk_data['median']
    xnorm = disk_data['median']

    if not 'over' in field:
        xplot  = np.log10(xbins) - xplotnorm
        xplotc = np.log10(xcent) - xplotnorm
    else:
        xplot = xbins - xplotnorm
        xplotc = xcent - xplotnorm

    mass_norm = masses['Disk'] #- masses['Molecular']
    yplot     = disk_data['norm_y'] * masses['Disk'] / mass_norm
    ynorm     = np.max(yplot)
    yplot     = yplot / ynorm

    if 'Disk' in phases:
        # plot disk here
        plot_histogram(ax, xplot, yplot, lw = line_width, color = 'black', label = 'Disk')
        if show_fit:
            fit = fit_multifunction_PDF(xbins, disk_data['hist'], disk_data)
            ax.plot(xplotc, fit['fit_result'](xcent)/ynorm*masses['Disk']/mass_norm,
                               lw = line_width, color = 'black', ls = '--')

    for phase in phases:
        if phase == 'Disk':
            continue
        data  = load_distribution_data(datafile, dsname, phase, field, centers = centers)
        data['norm_y'] = data['hist'] / disk_data['binsize']
        yplot = data['norm_y'] / ynorm * masses[phase] / mass_norm
        plot_histogram(ax, xplot, yplot, lw = line_width, color = color_dict[phase],
                           label=phase)

        if show_fit:
            fit = fit_multifunction_PDF(xbins, data['hist'], data)
            ax.plot( xplotc, fit['fit_result'](xcent) / ynorm * masses[phase]/mass_norm,
                            lw = line_width, color = color_dict[phase], ls = '--')

    ax.set_ylim(5.0E-7, 1.0)
    ax.semilogy()
    if len(phases) >= 1:
        xlim = ax.get_xlim()
        x1 = (xlim[1] + xlim[0])*0.5
        ax.plot([x1,x1],[1.0E-7,2.0], lw = 0.75 * line_width, ls = '-.', color = 'black')
        ax.plot([x1-1,x1-1],[1.0E-7,2.0], lw = 0.5 * line_width, ls = ':', color = 'black')
        ax.plot([x1+1,x1+1],[1.0E-7,2.0], lw = 0.5 * line_width, ls = ':', color = 'black')

    # ax[index].annotate()
    ax.minorticks_on()
    xytext = (-2.98,0.2)
#    if len(phases) >=1:
#        annotate_text = element
#        if element == 'O':
#            annotate_text = 'Oxygen'
#        if element == 'Ba':
#            annotate_text = 'Barium'

    if not (label is None):
        ax.text(xytext[0], xytext[1], label,  color = 'black', size = 40)

    if xlabel is None:
        xlabel = 'Median Normalized Mass Fraction'

    ax.set_xlabel(xlabel)

    if ylabel is None:
        ylabel = r'Mass-Weighted PDF'

    ax.set_ylabel(ylabel)

    ax.legend(loc = 'upper right', ncol = 1, fancybox=True, framealpha = 0.4)
    plt.tight_layout()
    fig.savefig(outname)
    plt.close()

    return

def element_by_element_panel(datafile, galaxy_file, dsname, show_fit = True,
                             elements = '3x3', outname = None):
    """
    Constructs a panel plot showing all phases for a single element
    on a single panel (so 4x4 plot: 15 elements + total metallicity field).
    Each plot is normalized to the median mass fraction (i.e. log(median) = 0)
    and centered on this value (so shareaxis is on). Each plot is normalized
    such that the integral over the disk PDF / max(disk PDF) = 1, and so that
    integral(phase)/integral(disk) gives mass fraction of that phase.

    Requires galaxy analysis output file (For mass fractions)
    """

    if outname is None:
        outname = galaxy_file.split('_galaxy')[0] + '_element_by_element.png'

    all_phases = ['CNM', 'WNM', 'WIM', 'HIM']

    if elements is None:
        elements   = get_element_list(datafile, dsname)
        xp,yp = 4,4
    elif elements == '3x3':
#        elements   = ['O','C','Fe','Mg','N','Mn','Y','Sr','Ba']
        elements   = ['C','N','O','Mg','Mn','Fe','Sr','Y','Ba']
        xp,yp = 3,3

    xsize, ysize = xp*6, yp*6

    fig, ax = plt.subplots(xp,yp, sharex=True, sharey=True)
    fig.set_size_inches(xsize,ysize)
    fig.subplots_adjust(hspace = 0.0, wspace = 0.0)

    gasdata = dd.io.load(galaxy_file, '/gas_meta_data/masses')
    masses = {}
    for k in gasdata.keys():
        try:
            masses[k] = gasdata[k]['Total']
        except:
          print(k)

#    disk_mass = masses['Disk']
#    for k in masses.keys():
#        masses[k] = masses[k] / disk_mass
# ----
    axi = 0
    axj = 0

    for element in elements:
        centers = 'bins'
        index = (axi,axj)

        field = element + '_Fraction'
        print(element, axi, axj)
        disk_data = load_distribution_data(datafile, dsname, 'Disk', field, centers = centers)
        disk_data['norm_y'] = disk_data['hist'] / disk_data['binsize']
        xbins = disk_data['bins']
        xcent = disk_data['centers']
        xnorm = disk_data['median']
        xplot  = np.log10(xbins) - xnorm
        xplotc = np.log10(xcent) - xnorm

        mass_norm = masses['Disk'] #- masses['Molecular']
        yplot     = disk_data['norm_y'] * masses['Disk'] / mass_norm
        ynorm     = np.max(yplot)
        yplot     = yplot / ynorm

        # plot disk here
        plot_histogram(ax[index], xplot, yplot, lw = line_width, color = 'black', label = 'Disk')
        if show_fit:
            fit = fit_multifunction_PDF(xbins, disk_data['hist'], disk_data)
            ax[index].plot(xplotc, fit['fit_result'](xcent)/ynorm*masses['Disk']/mass_norm,
                           lw = line_width, color = 'black', ls = '--')

        for phase in all_phases:
            data  = load_distribution_data(datafile, dsname, phase, field, centers = 'bins')
            data['norm_y'] = data['hist'] / disk_data['binsize']
            yplot = data['norm_y'] / ynorm * masses[phase] / mass_norm
            plot_histogram(ax[index], xplot, yplot, lw = line_width, color = color_dict[phase],
                           label=phase)

            if show_fit:
                fit = fit_multifunction_PDF(xbins, data['hist'], data)
                ax[index].plot( xplotc, fit['fit_result'](xcent) / ynorm * masses[phase]/mass_norm,
                                lw = line_width, color = color_dict[phase], ls = '--')

        ax[index].set_xlim(-3.8,3.3)
        ax[index].set_ylim(5.0E-7, 1.0)
        ax[index].semilogy()
        ax[index].plot([0,0],[1.0E-7,2.0], lw = 0.75 * line_width, ls = '-.', color = 'black')
        ax[index].plot([-1,-1],[1.0E-7,2.0], lw = 0.5 * line_width, ls = ':', color = 'black')
        ax[index].plot([1,1],[1.0E-7,2.0], lw = 0.5 * line_width, ls = ':', color = 'black')

        # ax[index].annotate()
        ax[index].minorticks_on()
        xytext = (-3.4,0.2)
        ax[index].text(xytext[0], xytext[1], element,  color = 'black', size = 40)
        axj = axj + 1
        if axj >= yp:
            axj = 0
            axi = axi + 1

    if (xp,yp) == (3,3):
        ax[(2,1)].set_xlabel(r'log(Z) - log(Z$_{\rm median}$)')
#r'Median Normalized Mass Fraction')
        ax[(1,0)].set_ylabel(r'Peak-Normalized PDF')

#    for i in [0,1,2]:
#        ax[(2,i)].set_xticks([-3,-2,-1,0,1,2,3], [-3,-2,-1,0,1,2,3])

    ax[(1,0)].legend(loc = 'lower left', ncol = 1, fancybox=True, framealpha = 0.4)
    fig.savefig(outname)
    plt.close()

    return

def plot_time_evolution(datafile, dsarray, denominator = None):
    """
    Make a panel plot showing the evolution of:
        Median abundance           : top row
        log(median) - log(average) : middle row
        q90 - q10                  : bottom row
    For the following elements as columns (7):
        Ba, Sr, Fe, Mn, Mg, O, N

    Either as mass fractions (denominator = None) or as abundance
    ratios (e.g. denominator = "Fe")
    """

    all_phases = ['CNM','WNM','WIM']
    elements   = ['Ba','Sr','Fe','Mn','Ni','Mg','N','O']

    all_time_data = {}
    for e in elements:
        all_time_data[e] = {}

        if denominator is None:
            field = e + '_Fraction'
        elif e == denominator:
            continue # skip
        else:
            field = e + '_over_' + denominator

        for phase in all_phases:
            all_time_data[e][phase] =\
              gather_time_series(datafile, dsarray, phase, field)

    nrow = 3
    ncol = 8

    fig, ax = plt.subplots(nrow,ncol)
    fig.set_size_inches(ncol*6,nrow*6)

    axi = 0
    axj = 0

    times = np.arange(0, np.size(dsarray), 1) * 5

    color = {'Molecular' : 'C1', 'CNM' : 'C0', 'WNM' : 'C2', 'WIM':'C4','HIM' : 'C3'}

    for e in elements:

        if not (e == denominator):
            for phase in all_phases:

                median = all_time_data[e][phase]['median']
                mean   = all_time_data[e][phase]['mean']
                d9d1   = all_time_data[e][phase]['q90_q10_range']

                ax[(0,axj)].plot(times, median, lw = 3, color = color[phase], ls = '-')
                ax[(1,axj)].plot(times, median - mean, lw = 3, color = color[phase], ls = '-')
                ax[(2,axj)].plot(times, d9d1, lw = 3, color = color[phase], ls = '-')

        if not (denominator is None):
            if denominator == 'H':
                ax[(0,axj)].set_ylim(-8, 0)
                ax[(1,axj)].set_ylim(0, 1)
                ax[(2,axj)].set_ylim(0, 3)
            else:
                ax[(0,axj)].set_ylim(-4, 2)
                ax[(1,axj)].set_ylim(-0.2, 0.2)
                ax[(2,axj)].set_ylim(0, 2)

        for i in [0,1,2]:
            ax[(i,axj)].set_xlim(0, 500.0)
            xy = (0.9,0.1)
            ax[(i,axj)].annotate(e, xy,xy, textcoords='axes fraction')

        axj = axj + 1

    ax[(0,0)].set_ylabel('Median (dex)')
    ax[(1,0)].set_ylabel('Med - Mean (dex)')
    ax[(2,0)].set_ylabel('d9 - d1 (dex)')

    fig.subplots_adjust(hspace = 0)
    outname = 'time_evolution_'
    if denominator is None:
        outname += 'fraction'
    else:
        outname += denominator

    fig.savefig(outname + '.png')

    plt.close()

    return

def get_element_list(file_name, dsname):
    keys = list(dd.io.load(file_name, '/' + '/'.join([dsname,'CNM','mass_fraction'])).keys())

    x = [y.split('_over_')[0] for y in keys if '_over_Fe' in y]
    x = x + ['Fe']

    return utilities.sort_by_anum(x)

def load_distribution_data(file_name, dsname, phase, field, centers = None):
    """
    Extracts some information from the dataset
    """

    # load the data from file
    ldata = dd.io.load(file_name, '/' + '/'.join([dsname,phase,'mass_fraction',field]))

    rdata  = ldata
    y      = ldata['hist']
    mean   = ldata['mean']
    std    = ldata['std']
    q1     = ldata['Q1']
    q3     = ldata['Q3']
    q10    = ldata['decile_1']
    q90    = ldata['decile_9']

    if not (centers is None):

        if not (np.size(centers) == np.size(y)):
            if centers == 'bins' or centers == 'abins':
                bins = dd.io.load(file_name, '/' + '/'.join([dsname,phase,'mass_fraction',centers]))
                rdata['binsize'] = bins[1:] - bins[:-1]
                rdata['bins'] = bins

            centers = 0.5 * (bins[1:] + bins[:-1])

    if rdata['Q3'] is None or rdata['Q1'] is None:
        rdata['iqr']           = None
        rdata['q90_q10_range'] = None
    else:

        if (q1 > 0 and q3 > 0 and q10 > 0 and q90 > 0) and (not 'over' in field):
            # safe to assume these are not logged data if all positive
            rdata['iqr']    = np.log10(q3) - np.log10(q1) # ldata['inner_quartile_range']
            rdata['q90_q10_range'] = np.log10(q90) - np.log10(q10)
        else:
            rdata['iqr'] = q3 - q1
            rdata['q90_q10_range'] = q90 - q10

    rdata['label']  = dd.io.load(file_name, '/' + '/'.join([dsname,'general','Time']))
    rdata['median'] = np.interp(0.5, np.cumsum(y)/(1.0*np.sum(y)), centers)
    if not 'over' in field:
        rdata['median'] = np.log10(rdata['median'])

    rdata['centers'] = centers
#    rdata['bins'] = bins
    rdata['q90'] = q90
    rdata['q10'] = q10
    return rdata

def fit_multifunction_PDF(bins, y, data):
    """
    Fit lognormal + power law
    """

    success = {}
    rdict   = {}

    centers = 0.5 * (bins[1:] + bins[:-1])

    def _error(yfitvals, yvals):
        return np.sum( np.abs(yvals[yvals>0] - yfitvals[yvals>0])**2/yvals[yvals>0] )

    # lognormal
    try:
        lognormal_alone = fit_PDF(bins*1.0, y*1.0, data = data, function_to_fit = 'log-normal')
        success['lognormal'] = True
        lognormal_alone['error'] = _error( lognormal_alone['fit_function']._f(centers, *lognormal_alone['popt']) , lognormal_alone['norm_y'])
        rdict['lognormal']   = lognormal_alone
    except RuntimeError:
        success['lognormal'] = False

    # lognormal powerlaw
    ln_pl = fit_PDF(bins*1.0, y*1.0, data=data, function_to_fit = 'lognormal_powerlaw')
    success['lognormal_powerlaw'] = True
    ln_pl['error'] = _error(ln_pl['fit_function']._f(centers, *ln_pl['popt']) , ln_pl['norm_y'])
    rdict['lognormal_powerlaw'] = ln_pl

    try:
        gau_pl = fit_PDF(bins*1.0, y*1.0, data=data, function_to_fit = 'gaussian_powerlaw')
        success['gaussian_powerlaw'] = True
        gau_pl['error'] = _error(gau_pl['fit_function']._f(centers, *gau_pl['popt']), gau_pl['norm_y'])
        rdict['gaussian_powerlaw'] = gau_pl
    except RuntimeError:
        success['gaussian_powerlaw'] = False

    # powerlaw
    try:
        powerlaw_alone  = fit_PDF(bins, y, data = data, function_to_fit = 'powerlaw')
        success['powerlaw'] = True
#    powerlaw_alone['error'] = _error(powerlaw_alone['fit_function']._f( centers[centers>centers[np.argmax(powerlaw_alone['norm_y'])]] , *powerlaw_alone['popt']) ,
#                                         powerlaw_alone['norm_y'][ centers > centers[np.argmax(powerlaw_alone['norm_y'])]]  )
        powerlaw_alone['error'] = _error(powerlaw_alone['fit_function']._f( centers, *powerlaw_alone['popt']), powerlaw_alone['norm_y'])
        rdict['powerlaw'] = powerlaw_alone
    except RuntimeError:
        success['powerlaw'] = False

    # truncated powerlaw
    #truncated_powerlaw  = fit_PDF(bins, y, data = data, function_to_fit = 'truncated_powerlaw')
    #success['truncated_powerlaw'] = True
    #truncated_powerlaw['error'] = _error(truncated_powerlaw['fit_function']._f( centers , *truncated_powerlaw['popt']) ,
    #                                     truncated_powerlaw['norm_y'])
    #rdict['truncated_powerlaw'] = truncated_powerlaw

#    if all([not success[k] for k in success.keys()]):
#        print "Cannot find a fit"
#        raise ValueError

    min_error = np.inf
    for k in success.keys():

        if success[k]:
            print(k, success[k])
            rdict[k]['name'] = k
            if rdict[k]['error'] < min_error:
                min_error = rdict[k]['error']
                min_key   = k

    return rdict[min_key]

def fit_PDF(bins, y, data = None, function_to_fit = None, p0 = None, bounds = None,
                     fit_method = 'curve_fit', remove_residual = None):
    """
    fit_function is either a function object from utilities.functions OR
    the name of one of these functions
    """

    centers = 0.5 * (bins[1:] + bins[:-1])
    binsize = (bins[1:] - bins[:-1])

    norm_y = y / binsize
    if not (remove_residual is None):
        norm_y = norm_y - remove_residual

    # if data is provided we can do some cool things
    if p0 is None:
        if not (data is None):
            if function_to_fit == 'log-normal' or function_to_fit == 'lognormal_powerlaw':
                u_guess   = np.log( data['mean'] / (np.sqrt(1.0 + data['std']**2 / (data['mean']**2))))
                std_guess = np.sqrt( np.log(1.0 + data['std']**2 / data['mean']**2))

                p0 = [u_guess, std_guess]
                bounds = ( [p0[0]*1.0 - 10, 0.0], [p0[0]*1.0+10, 30.0])

            if function_to_fit == 'lognormal_powerlaw':
                 p0 = [u_guess - 3, 2.0, np.sqrt(-0.5 * (u_guess - 3 - np.log(data['mean'])))  ]
                 bounds = ( [p0[0] - 5, 1.0, 0.01], [u_guess+3, 20.0, 10.0])

        if function_to_fit == 'powerlaw' or function_to_fit == 'truncated_powerlaw':
            p0     = [2, 1.0E-5]
            bounds = ( [1.0,0], [np.inf,1.0])

        if function_to_fit == 'truncated_powerlaw':
            p0      = [p0[0]*1,p0[1]*1, centers[np.max([np.argmax(norm_y)-1,0])] ]
            bounds  = ([bounds[0][0]*1, 1*bounds[0][1], centers[np.max([np.argmax(norm_y)-10,0])]],
                                                        [1*bounds[1][0],1*bounds[1][1],centers[np.min([np.argmax(norm_y)+20,np.size(centers)-1])]])
        if function_to_fit == 'gaussian_powerlaw':
            p0     = [data['mean'], 2.0, data['std']]
            bounds = [ (p0[0]/100.0, 0.01, p0[2] / 1000.0), (p0[0]*100.0, 10.0, p0[2]*100.0)]

    # choose the region to fit over
    #   for all, this will be where there is data

    selection = (norm_y > 0)
#    if function_to_fit == 'log-normal':
#        selection = selection * (centers > 10.0**(np.log10(centers[np.argmax(norm_y)]) - 1.0)  )*\
#                                (centers < 10.0**(np.log10(centers[np.argmax(norm_y)]) + 1.0)  )
#    elif function_to_fit == 'powerlaw':
#        selection = selection * ( centers > centers[np.argmax(norm_y)] )  # Fit everything to the right of the peak

    x_to_fit = centers[selection]
    y_to_fit = norm_y[selection]

    # set fitting function
    if isinstance(function_to_fit, str):
        function_to_fit= functions.by_name[function_to_fit]()

    if function_to_fit.name == 'lognormal_powerlaw' or function_to_fit.name == 'gaussian_powerlaw':
        function_to_fit.full_mean = data['mean']

    # If we are using KS test to fit, then need to compute the CDF from the data
    if fit_method == 'KS':
        data_cdf  = np.cumsum(y[selection])
    else:
        data_cdf  = None

    # Fit -
    popt, pcov = function_to_fit.fit_function(x_to_fit, y_to_fit, p0 = p0,
                                              bounds = bounds, method = fit_method,
                                              data_cdf = data_cdf)

    fit_dictionary = {'popt' : copy(popt), 'pcov': copy(pcov),
                      'fit_function' : function_to_fit, 'norm_y' : norm_y*1.0,
                      'fit_x' : x_to_fit*1.0, 'fit_y' : y_to_fit*1.0,
                      'fit_result' : lambda xx : function_to_fit._f(xx, *popt) }

    return fit_dictionary

colors = ['C' + str(i) for i in [0,1,2,4,5,6,7,8,9]]
lss     = ['-','--']

def plot_all_elements(file_name, dsname, phase, elements = None, **kwargs):

    if elements is None:
        elements = ['Ba','Y','As','Sr','Mn','Na','Ca','N','Ni','Mg','S','Si','Fe','C','O']

    elements = ['Ba', 'Sr', 'Fe', 'Mn', 'Mg', 'O', 'N']

    fig, ax = plt.subplots(2)
    fig.set_size_inches(24,16)

    bins    = dd.io.load(file_name, '/' + '/'.join([dsname,phase,'mass_fraction','bins']))
    centers = 0.5 * (bins[1:]+ bins[:-1])

#    sort   = np.argsort(ymax_order)
#    sort_e = np.array(elements)[sort]

    label_pos = np.empty((np.size(elements),))
    label_pos[::2] = 1
    label_pos[1::2] = -1

#    label_pos = label_pos[sort]

    ci = li = 0
    for i, e in enumerate(elements):
        field = e + '_Fraction'

        ds_data = load_distribution_data(file_name, dsname, phase, field, centers = centers) # subselect

        fit_dict = fit_multifunction_PDF(1.0*bins, 1.0*ds_data['hist'], ds_data)
                   #fit_PDF(bins, ds_data['hist'], data = ds_data, **kwargs)

        plot_histogram(ax[0], np.log10(bins), fit_dict['norm_y']/np.max(fit_dict['norm_y']),
                                    color = colors[ci], ls = lss[li], lw = line_width)

        ax[0].plot(np.log10(centers),
                   #np.log10(fit_dict['fit_x']),
                   fit_dict['fit_result'](centers) / np.max(fit_dict['norm_y']),
                                      lw = line_width, ls = lss[li], color = colors[ci])

        select = fit_dict['norm_y'] > 0
        chisqr = (fit_dict['fit_result'](centers[select]) - fit_dict['norm_y'][select])**2 / fit_dict['norm_y'][select]
        error  = np.abs(fit_dict['fit_result'](centers[select]) - fit_dict['norm_y'][select]) / fit_dict['norm_y'][select]

        ax[1].plot(np.log10(centers[select]), error, lw = line_width, ls = lss[li], color = colors[ci])

####
        xtext = np.log10(centers[np.argmax(fit_dict['norm_y'])]) - 0.1 - 0.05
        xa    = np.log10(centers[np.argmax(fit_dict['norm_y'])])
        ya    = 1.0
        pos = label_pos[i]
        if pos > 0:
            xtext = xtext + 0.05
            ytext = 2.0
        xy = (xtext, ytext)
        xya = (xa,ya)
        ax[0].annotate(e, xy = xya, xytext=xy, color = colors[ci],
                       arrowprops=dict(arrowstyle="-", connectionstyle="arc3"))
####

        print(e, fit_dict['name'], fit_dict['popt'], np.sqrt(-0.5 * fit_dict['popt'][0]), np.sum(chisqr) / (1.0*np.size(fit_dict['norm_y'][select])))
        ci = ci + 1
        if ci >= np.size(colors):
            ci = 0
            li = li + 1

    for i in [0,1]:
        ax[i].set_xlim(-14, -1.5)
        ax[i].set_ylim(1.0E-5, 9.0)
        ax[i].semilogy()
    ax[1].set_ylim(0.01, 10.0)

    ax[0].set_ylabel('Peak Normalized PDF from Data')
    ax[1].set_ylabel('Peak Normalized PDF from Fit')

    fig.subplots_adjust(hspace = 0)
    plt.setp([a.get_xticklabels() for a in fig.axes[:-1]], visible = False)
    plt.minorticks_on()

    fig.savefig(dsname + '_' + phase + '_all_elements_fit.png')
    plt.close()

    return

def plot_phase_panel(file_name, dsname, elements = None, plot_fit = True, **kwargs):

    phases = ['CNM','WNM','WIM','HIM','Disk']

    if elements is None:
        elements = ['Ba','Y','As','Sr','Mn','Na','Ca','N','Ni','Mg','S','Si','Fe','C','O']

    elements = ['Ba', 'Sr', 'Fe', 'Mn', 'Mg', 'O', 'N']
    #elements = ['Mg','O']
    fig, ax = plt.subplots(3,2)
    fig.set_size_inches(36,6*3)

    bins    = dd.io.load(file_name,'/'+'/'.join([dsname,phases[0],'mass_fraction','bins']))
    centers = 0.5 * (bins[1:]+ bins[:-1])

#    sort   = np.argsort(ymax_order)
#    sort_e = np.array(elements)[sort]

    label_pos = np.empty((np.size(elements),))
    label_pos[::2] = 1
    label_pos[1::2] = -1

#    label_pos = label_pos[sort]

    ax_indexes = [(0,0),(0,1), (1,0), (1,1), (2,0), (2,1)]
    for axi, phase in enumerate(phases):
        ci = li = 0

        axi = ax_indexes[axi]
        for i, e in enumerate(elements):
            field = e + '_Fraction'

            ds_data = load_distribution_data(file_name, dsname, phase, field, centers = centers) # subselect

            if plot_fit:
                fit_dict = fit_multifunction_PDF(1.0*bins, 1.0*ds_data['hist'], ds_data)
                   #fit_PDF(bins, ds_data['hist'], data = ds_data, **kwargs)

                y = fit_dict['norm_y'] / np.max(fit_dict['norm_y'])
                plot_histogram(ax[axi], np.log10(bins), y,
                                            color = colors[ci], ls = lss[li], lw = line_width)

                ax[axi].plot(np.log10(centers),
                           #np.log10(fit_dict['fit_x']),
                           fit_dict['fit_result'](centers) / np.max(fit_dict['norm_y']),
                                              lw = line_width, ls = '--', color = colors[ci])
            else:
                y = ds_data['hist'] / (bins[1:] - bins[:-1])
                plot_histogram(ax[axi], np.log10(bins), y / np.max(y), color = colors[ci],
                                       lw = line_width, ls = '--')
####
            xtext = np.log10(centers[np.argmax(y) ]) - 0.1 - 0.05
            xa    = np.log10(centers[np.argmax(y)])
            ya    = 1.0
            pos = label_pos[i]
            if pos > 0:
                xtext = xtext + 0.05
                ytext = 2.0
            xy = (xtext, ytext)
            xya = (xa,ya)
            ax[axi].annotate(e, xy = xya, xytext=xy, color = colors[ci],
                           arrowprops=dict(arrowstyle="-", connectionstyle="arc3"))
####

            if plot_fit:
                if fit_dict['name'] == 'lognormal_powerlaw':
                    N = fit_dict['fit_function'].N
                else:
                    N = 0
                print(phase, e, fit_dict['name'], fit_dict['popt'], "%5.5E"%(N))

            ci = ci + 1
            if ci >= np.size(colors):
                ci = 0
                li = li + 1

    for i, axi in enumerate(ax_indexes):
        ax[axi].set_xlim(-25, -1.5)
        ax[axi].set_ylim(1.0E-5, 9.0)
        ax[axi].semilogy()
        xy = (-3.0,1.0)
        ax[axi].annotate(phases[i], xy = xy, xytext=xy)

    for i in [0,1,2]:
        ax[(i,0)].set_ylabel('Peak Normalized PDF')
        plt.setp( ax[(i,1)].get_yticklabels(), visible = False)
    #ax[1].set_ylim(0.01, 10.0)
    for i in [0,1]:
        ax[(2,i)].set_xlabel('log(Z)')

    #ax[1].set_ylabel('Peak Normalized PDF')

    fig.subplots_adjust(hspace = 0, wspace = 0)
   # plt.setp([a.get_yticklabels() for a in fig.axes[1:]], visible = False)
    plt.minorticks_on()

    fig.savefig(dsname + '_multiphase_all_elements_fit.png')
    plt.close()

    return

def plot_phase_abundance_panel(file_name, dsname, elements = None, denominator = 'H', **kwargs):

    phases = ['CNM','WNM','WIM','HIM','Disk']

    if elements is None:
        elements = ['Ba','Y','As','Sr','Mn','Na','Ca','N','Ni','Mg','S','Si','Fe','C','O']

    elements = ['Ba', 'Sr', 'Fe', 'Mn', 'Mg', 'O', 'N']
    #elements = ['Mg','O']
    fig, ax = plt.subplots(3,2)
    fig.set_size_inches(36,6*3)

    bins    = dd.io.load(file_name,'/'+'/'.join([dsname,phases[0],'mass_fraction','abins']))
    centers = 0.5 * (bins[1:]+ bins[:-1])

#    sort   = np.argsort(ymax_order)
#    sort_e = np.array(elements)[sort]

    label_pos = np.empty((np.size(elements),))
    label_pos[::2] = 1
    label_pos[1::2] = -1

#    label_pos = label_pos[sort]

    ax_indexes = [(0,0),(0,1), (1,0), (1,1), (2,0), (2,1)]
    for axi, phase in enumerate(phases):
        ci = li = 0

        axi = ax_indexes[axi]
        for i, e in enumerate(elements):
            if e == denominator:
                continue
            field = e + '_over_' + denominator

            ds_data = load_distribution_data(file_name, dsname, phase, field, centers = centers) # subselect

            #fit_dict = fit_multifunction_PDF(1.0*bins, 1.0*ds_data['hist'], ds_data)
                   #fit_PDF(bins, ds_data['hist'], data = ds_data, **kwargs)

            yplot = np.cumsum(ds_data['hist'])  / (1.0*np.sum(ds_data['hist']))
            binsize = (10**(bins[1:]) - 10**(bins[:-1]))
            yplot = ds_data['hist'] / binsize

#            select = yplot > 0
#            xplot = bins[select]
#            yplot = yplot[select]

            plot_histogram(ax[axi], bins, yplot / np.max(yplot), #fit_dict['norm_y']/np.max(fit_dict['norm_y']),
                                        color = colors[ci], ls = lss[li], lw = line_width, label = e)

            #ax[axi].plot(np.log10(centers),
                       #np.log10(fit_dict['fit_x']),
            #           fit_dict['fit_result'](centers) / np.max(fit_dict['norm_y']),
            #                              lw = line_width, ls = lss[li], color = colors[ci])

####
            xtext = np.log10(centers[np.argmax(ds_data['hist'])]) - 0.1 - 0.05
            xa    = np.log10(centers[np.argmax(ds_data['hist'])])
            ya    = 1.0
            pos = label_pos[i]
            if pos > 0:
                xtext = xtext + 0.05
                ytext = 2.0
            xy = (xtext, ytext)
            xya = (xa,ya)
#            ax[axi].annotate(e, xy = xya, xytext=xy, color = colors[ci],
#                           arrowprops=dict(arrowstyle="-", connectionstyle="arc3"))
####

            print(phase, e, end=' ')
# fit_dict['name'], fit_dict['popt']
            ci = ci + 1
            if ci >= np.size(colors):
                ci = 0
                li = li + 1

    for i, axi in enumerate(ax_indexes):

        if denominator == 'H':
            ax[axi].set_xlim(-8,0)
        else:
            ax[axi].set_xlim(-3,3)
        ax[axi].set_ylim(1.0E-5, 5.0)
        ax[axi].semilogy()
        xy = (-3.0,1.0)
        ax[axi].annotate(phases[i], xy = xy, xytext=xy)

    ax[(0,0)].legend(loc = 'upper right')
    for i in [0,1,2]:
        ax[(i,0)].set_ylabel('Peak Normalized PDF')
        plt.setp( ax[(i,1)].get_yticklabels(), visible = False)
    #ax[1].set_ylim(0.01, 10.0)
    for i in [0,1]:
        ax[(2,i)].set_xlabel('[X/' + denominator + ']')

    #ax[1].set_ylabel('Peak Normalized PDF')

    fig.subplots_adjust(hspace = 0, wspace = 0)
   # plt.setp([a.get_yticklabels() for a in fig.axes[1:]], visible = False)
    plt.minorticks_on()

    fig.savefig(dsname + '_multiphase_elements_over_' + denominator + '.png')
    plt.close()

    return

if __name__ == '__main__':
    """
    Runs the analysis and plots a full panel of all phases and
    the full disk for selected elements. Additional arguments
    to run are:
       1) ds_number
       2) ds_number_start ds_number_end  (assume go up by 1)
       3) ds_number_start ds_number_end di

    e.x. To run starting with DD0400 to DD0500 going up by 5:
        $python ./PDF.py 400 500 5
    """

    if len(sys.argv) == 1:
        all_ds = ["DD0400"]
    elif len(sys.argv) == 2:
        all_ds = ["DD%0004i"%(int(sys.argv[1]))]
    elif len(sys.argv) == 3 or len(sys.argv) == 4:

        if len(sys.argv) == 4:
            di = int(sys.argv[3])
        else:
            di = 1

        all_ds = ["DD%0004i"%(x) for x in np.arange( int(sys.argv[1]),
                                                     int(sys.argv[2])+di/2.0, di)]

    individual_fail = False
    gas_file = 'gas_abundances.h5'
#    try:
#        data = {all_ds[0] : dd.io.load(gas_file, "/" + all_ds[0]) }
#    except:
#        individual_fail = True
#        all_data = dd.io.load(gas_file)

#    dsarray = ["DD%0004i"%(x) for x in np.arange(119, 202, 1)] #np.arange(50, 555, 250)]
#    plot_time_evolution(gas_file, dsarray, denominator = None)
#    plot_time_evolution(gas_file, dsarray, denominator = 'O')
#    plot_time_evolution(gas_file, dsarray, denominator = 'Fe')
#    plot_time_evolution(gas_file, dsarray, denominator = 'N')

    for dsname in all_ds:
        print("Beginning on " + dsname)

#        if individual_fail:
#            data = {dsname : all_data[dsname]}
#        else:
#            data = {dsname : dd.io.load(gas_file, "/" + dsname) }

        plot_phase_panel(gas_file, dsname, plot_fit = False)

#        if True:
#             plot_phase_abundance_panel(data, dsname, denominator = 'Fe')
#            plot_phase_abundance_panel(data, dsname, denominator = 'Mg')
#            plot_phase_abundance_panel(data, dsname, denominator = 'O')
#
#
        if False:
            plot_all_elements(data, dsname, 'Molecular', function_to_fit = 'lognormal_powerlaw') #'lognormal_powerlaw')
            plot_all_elements(data, dsname, 'CNM', function_to_fit = 'lognormal_powerlaw') #'lognormal_powerlaw')
            plot_all_elements(data, dsname, 'WNM', function_to_fit = 'lognormal_powerlaw') #'lognormal_powerlaw')
            plot_all_elements(data, dsname, 'WIM', function_to_fit = 'lognormal_powerlaw') #'lognormal_powerlaw')
            plot_all_elements(data, dsname, 'HIM', function_to_fit = 'lognormal_powerlaw') #'lognormal_powerlaw')
            plot_all_elements(data, dsname, 'Disk', function_to_fit = 'lognormal_powerlaw') #'lognormal_powerlaw')


""" Provides list of functions to create a St. Patrick's Day Card
"""

__author__ = "Roger Terrill, Abby Packham, Carlos Orduna"
__copyright__ = "Copyright 2019, CST205"
__license__ = "GPL"
__version__ = "1.0.1"
__email__ = "rchicasterrill@csumb.edu, apackham@csumb.edu, cordunacorrales@csumb.edu  "
__status__ = "Production"

def get_pic():
  return makePicture(pickAFile())

# Warmup
def draw():
  pic = get_pic()
  addOvalFilled(pic, 500, 500, 100, 100, white)
  addOvalFilled(pic, 512, 425, 75, 75, white)
  addOvalFilled(pic, 525, 375, 50, 50, white)
  show(pic)

# Problem 1
def mirror(pic):
  width = getWidth(pic)
  height = getHeight(pic)
  mirror = makeEmptyPicture(width, height)
  for x in range(0, width):
    for y in range(0, height):
      p = getPixel(pic, x, y)
      red = getRed(p)
      green = getGreen(p)
      blue = getBlue(p)
      mp = getPixel(mirror, width-x-1, y)
      setRed(mp, red)
      setGreen(mp, green)
      setBlue(mp, blue)
  return mirror

def chromakey(green_pic, background_pic):
  background_green = makeColor(61,255,15)
  width = getWidth(green_pic)
  height = getHeight(green_pic)
  for x in range(0, width):
    for y in range(0, height):
      px = getPixel(green_pic, x, y)
      color = getColor(px)
      background_px = getPixel(background_pic, x, y)
      background_color = getColor(background_px)
      if distance(color, background_green) < 80.0:
        setColor(px, background_color)
  return green_pic

def card():
  green_screen = get_pic()
  background = get_pic()
  logo = get_pic()
  header1 = "Happy St."
  header2 = "Patrick's Day..."
  footer = "...From Space"
  paddy_green = makeColor(0, 102, 0)
  chromakey(green_screen, background)
  import java.awt.Font as Font
  myFont = makeStyle("Comic Sans", Font.BOLD, 80)
  addTextWithStyle(green_screen, 229, 104, header1, myFont, black)
  addTextWithStyle(green_screen, 225, 100, header1, myFont, white)
  addTextWithStyle(green_screen, 140, 200, header2, myFont, white)
  addTextWithStyle(green_screen, 136, 196, header2, myFont, paddy_green)
  addTextWithStyle(green_screen, 140, 900, footer, myFont, black)
  addTextWithStyle(green_screen, 144, 904, footer, myFont, white)
  pyCopy(logo, green_screen, 50, 240)
  mirror_logo = mirror(logo)
  pyCopy(mirror_logo, green_screen, 470, 240)
  show(green_screen)
  writePictureTo(green_screen, "C://Developing//School//CST205//card.jpeg")


# -*- coding: utf-8 -*-
'''
Some helper functions
author: zhang guanghua
date: 2018-0814
'''
import numpy as np
import glob
import os
import sys
import gzip
import struct
import cv2
import matplotlib.pyplot as plt
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
sys.path.append(BASE_DIR)
from six.moves import urllib

LOG_DIR = os.path.join(BASE_DIR, 'log')
if not os.path.exists(LOG_DIR):
    os.makedirs(LOG_DIR)

MNIST_DATA_PATH = r'F:\my_learning\DL\tensorflow\mnist\mnist_data'

def maybe_download(filename, data_dir, SOURCE_URL):
    """Download the data from Yann's website, unless it's already here."""
    filepath = os.path.join(data_dir, filename)
    if not os.path.exists(filepath):
        filepath, _ = urllib.request.urlretrieve(SOURCE_URL + filename, filepath)
        statinfo = os.stat(filepath)
        print('Successfully downloaded', filename, statinfo.st_size, 'bytes.')

def check_file(data_dir):
    if os.path.exists(data_dir):
        return True
    else:
        os.mkdir(data_dir)
        return False

def _read_data(gzfname):
    with gzip.open(gzfname) as gz:
        n = struct.unpack('I', gz.read(4))
        # 读取magic number
        if n[0] != 0x3080000:
            raise Exception('文件无效: 未预期的magic number.')
        # 将数据整体读入
        n = struct.unpack('>I', gz.read(4))[0]
        crow = struct.unpack('>I', gz.read(4))[0]
        ccol = struct.unpack('>I', gz.read(4))[0]
        if crow != 28 or ccol != 28:
            raise Exception('文件无效: 每张图像应该有 28 行/列.')
        # 读取数据
        res = np.fromstring(gz.read(n * crow * ccol), dtype = np.uint8)

    return res.reshape((n, crow, ccol, 1))

def _read_label(gzfname):
    with gzip.open(gzfname) as gz:
        n = struct.unpack('I', gz.read(4))
        # 读取magic number
        if n[0] != 0x1080000:
            raise Exception('文件无效: 未预期的 magic number.')
        # 将数据整体读入
        n = struct.unpack('>I', gz.read(4))[0]

        # 读取标签
        res = np.fromstring(gz.read(n), dtype = np.uint8)
        #n_class = res.max() + 1
        #res_one_hot = np.eye(n_class)[res]
    return res.reshape((n,1))

def load_data(data_dir, isTraing=True):
    if check_file(data_dir):
        print(data_dir)
        print('dir mnist already exist.')

    SOURCE_URL = 'http://yann.lecun.com/exdb/mnist/'
    data_keys = ['train-images-idx3-ubyte.gz', 'train-labels-idx1-ubyte.gz', 't10k-images-idx3-ubyte.gz', 't10k-labels-idx1-ubyte.gz']

    train_imgs = []
    val_imgs = []
    test_imgs = []
    train_label = []
    val_label = []
    test_label = []

    if isTraing:
        # image_data
        if os.path.isfile(os.path.join(data_dir, data_keys[0])):
             print("[warning...]", data_keys[0], "already exist.")
        else:
            maybe_download(data_keys[0], data_dir, SOURCE_URL)
        image_data = _read_data(os.path.join(data_dir, data_keys[0]))
        #print(image_data.shape)
        train_imgs = image_data[0:55000,:]
        val_imgs = image_data[55000:,:]

        # label_data
        if os.path.isfile(os.path.join(data_dir, data_keys[1])):
             print("[warning...]", data_keys[1], "already exist.")
        else:
            maybe_download(data_keys[1], data_dir, SOURCE_URL)
        label_data = _read_label(os.path.join(data_dir, data_keys[1]))
        #print(label_data)
        train_label = label_data[0:55000,:]
        val_label = label_data[55000:,:]

    else:
        # image_data
        if os.path.isfile(os.path.join(data_dir, data_keys[2])):
             print("[warning...]", data_keys[2], "already exist.")
        else:
            maybe_download(data_keys[2], data_dir, SOURCE_URL)
        test_imgs = _read_data(os.path.join(data_dir, data_keys[2]))
        #print(test_imgs.shape)
        # label_data
        if os.path.isfile(os.path.join(data_dir, data_keys[3])):
             print("[warning...]", data_keys[3], "already exist.")
        else:
            maybe_download(data_keys[3], data_dir, SOURCE_URL)
        test_label = _read_label(os.path.join(data_dir, data_keys[3]))
        #print(test_label.shape)

    return train_imgs, val_imgs, test_imgs, train_label, val_label, test_label

def mnist2img():
    image_path = os.path.join(BASE_DIR,'image_path')
    if not os.path.exists(image_path):
        os.makedirs(image_path)

    train_imgs,_,_,_,_,_ = load_data(MNIST_DATA_PATH)
    for i in range(1000):
        print(i)
        img_name = os.path.join(image_path, 'mnist_image{}.png'.format(i))
        cv2.imwrite(img_name, train_imgs[i])

def draw_loss_curve():
    with open(os.path.join('log', 'log_train.txt')) as file:
        train_loss = []
        train_acc = []
        logs = file.readlines()
        for log in logs[6::4]:
            key = log.split(':')[0]
            if 'train mean loss' == key:
                value = log.split(':')[1]
                train_loss.append(float(value))
        for log in logs[7::4]:
            key = log.split(':')[0]
            if 'train accuracy' == key:
                value = log.split(':')[1]
                train_acc.append(float(value))

    x = range(len(train_loss))
    plt.plot(x,train_loss,color='blue',label='train loss')
    plt.plot(x,train_acc,color='orange',label='train accuracy')
    plt.title('Mnist detect train loss & accuracy')
    plt.legend()
    plt.show()

if __name__ == '__main__':
    #load_data(MNIST_DATA_PATH)
    #load_data()
    #mnist2img()
    draw_loss_curve()


from Scrapy_CQC_NYDL_FNCY_tianjinbm import upload_replace as ur
from Scrapy_CQC_NYDL_FNCY_tianjinbm.pipelines import MongoDBPipeline
from Scrapy_CQC_NYDL_FNCY_tianjinbm.items import InfoItem  # 需要修改下爬虫项目名！！！

from scrapy_splash import SplashRequest  # 处理经过渲染的页面！！！

import scrapy
from scrapy.utils import request  # 处理哈希值id（news_id）
import logging
import time
logger = logging.getLogger(__name__)

import json

class TianjinbmZcSpider(scrapy.Spider):
    name = 'tianjinbm_zc'
    # allowed_domains = ['www']
    start_urls = ['http://sthj.tj.gov.cn/ZWGK4828/ZCWJ6738/']
    web_name = '天津市生态环境局'  # 网站名称
    category = '能源电力'  # 模块
    sub_category = '风能产业'  # 产业
    address = '天津'  # 地址

    mongo = MongoDBPipeline()
    db = mongo.db
    collection = mongo.mongo_collection

    def start_requests(self):
        for url in self.start_urls:
            yield scrapy.Request(url, callback=self.parse,
                                 dont_filter=True)

    def parse(self, response):
        li_list = response.xpath('//div[@class="commonList-body"]/ul/li')

        for li in li_list:
            content_url = li.xpath("./a/@href").extract_first()
            content_url = response.urljoin(content_url)
            title = li.xpath('./a/@title').extract_first()
            issue_time = li.xpath('./p[@class="fr"]/text()').extract_first()
            import re
            issue_time = re.findall(r'\d+-\d+-\d+',issue_time)[0]

            item = InfoItem()
            item["information_source"] = self.web_name
            item["category"] = self.category
            item["sub_category"] = self.sub_category
            item["content_url"] = content_url
            item["title"] = title
            item["issue_time"] = issue_time
            req = scrapy.Request(url=content_url, callback=self.detail_parse, meta={"item": item},
                                 dont_filter=True)
            news_id = request.request_fingerprint(req)  # 必须要求每一个url都有一个唯一的id，所以需要在此处设置
            req.meta['news_id'] = news_id

            if self.db[self.collection].count({'news_id': news_id}):
                continue
            yield req

        # # 翻页操作
        # for num in range(1,56):
        #     next_page = "http://sthj.tj.gov.cn/ZWGK4828/ZCWJ6738/index_{0}.html".format(num)
        #     yield scrapy.Request(url=next_page, callback=self.parse)

    def detail_parse(self, response):

        source = self.web_name
        author = None

        # 固定模式，改下xpath即可
        content = response.xpath('//div[@class="xxgk-main2-bg xxgk_xqCenter"] | //div[@class="xl-zw-main"] | //div[@class="ty-content"]').extract()
        content = ''.join(content)  # 转化成字符串，并且去掉空格

        # 处理图片的通用格式:
        _xpath1 = '//div[@class="TRS_PreAppend"]//img/@src'  # 改下xpath即可
        images = response.xpath(_xpath1).extract()
        # 处理附件的通用格式
        _xpath2 = '//div[@class="qt-attachments qt-has"]//a/@href'  # 改下xpath即可
        attachments = response.xpath(_xpath2).extract()
        # attachments = None

        # 使用自定义的函数upload_and_replace来处理图片和附件和内容
        content, images = ur.upload_and_replace(content, images, response)
        content, attachments = ur.upload_and_replace(content, attachments, response)

        # 以下除了item["information_categories"]不固定，其余的全部固定！！！
        item = response.meta["item"]
        item["information_categories"] = "政策法规"
        item["news_id"] = response.meta["news_id"]  # id
        item['area'] = None
        item["tags"] = None
        item["title_image"] = None
        item['attachments'] = attachments
        item['address'] = self.address
        item['sign'] = '37'
        item['update_time'] = str(int(time.time() * 1000))
        item['cleaning_status'] = 0
        item["source"] = source
        item["author"] = author
        item["content"] = content
        item["images"] = images
        yield item

import os

if __name__ == '__main__':
    os.system('scrapy crawl tianjinbm_zc')  ##改下爬虫名


# see http://jsfiddle.net/dFrHS/1/
# http://math.stackexchange.com/questions/296794/finding-the-transform-matrix-from-4-projected-points-with-javascript

# create a 4x4 transformation matrix based on the movement of 4 points (corner pin)
# s-variables are the 4 points before the transform and d variables after
def computeProjectionMatrix4FromCornerPin(x1s, y1s, x1d, y1d,
                                          x2s, y2s, x2d, y2d,
                                          x3s, y3s, x3d, y3d,
                                          x4s, y4s, x4d, y4d):
    x1s = float(x1s)
    x2s = float(x2s)
    x3s = float(x3s)
    x4s = float(x4s)
    x1d = float(x1d)
    x2d = float(x2d)
    x3d = float(x3d)
    x4d = float(x4d)
    y1s = float(y1s)
    y2s = float(y2s)
    y3s = float(y3s)
    y4s = float(y4s)
    y1d = float(y1d)
    y2d = float(y2d)
    y3d = float(y3d)
    y4d = float(y4d)

    t3 = computeProjectionMatrix3FromCornerPin(x1s, y1s, x1d, y1d,
                                               x2s, y2s, x2d, y2d,
                                               x3s, y3s, x3d, y3d,
                                               x4s, y4s, x4d, y4d)
    for i in range(0, 9):
        t3[i] = t3[i] / t3[8]

    t4 = [t3[0], t3[1], 0, t3[2],
          t3[3], t3[4], 0, t3[5],
          0, 0, 1, 0,
          t3[6], t3[7], 0, t3[8]]
    return t4

def matrix4ToString(tm):
    result = str(tm[0]) + " " + str(tm[1]) + " " + str(tm[2]) + " " + str(tm[3]) + "\n" + str(tm[4]) + " " + str(
        tm[5]) + " " + str(tm[6]) + " " + str(tm[7]) + "\n" + str(tm[8]) + " " + str(tm[9]) + " " + str(
        tm[10]) + " " + str(tm[11]) + "\n" + str(tm[12]) + " " + str(tm[13]) + " " + str(tm[14]) + " " + str(tm[15])
    return result

def multiply3MatrixAnd3Matrix(a, b):  # multiply two matrices
    c = [0] * 9  # list of length 9
    for i in range(0, 3):
        for j in range(0, 3):
            cij = 0
            for k in range(0, 3):
                cij += a[3 * i + k] * b[3 * k + j]
            c[3 * i + j] = cij
    return c

def multiply3MatrixAnd3Vector(m, v):  # multiply matrix and vector
    result = [
        m[0] * v[0] + m[1] * v[1] + m[2] * v[2],
        m[3] * v[0] + m[4] * v[1] + m[5] * v[2],
        m[6] * v[0] + m[7] * v[1] + m[8] * v[2]
    ]
    return result

def computeAdjugateMatrix(m):  # Compute the adjugate of m
    result = [m[4] * m[8] - m[5] * m[7], m[2] * m[7] - m[1] * m[8], m[1] * m[5] - m[2] * m[4],
              m[5] * m[6] - m[3] * m[8], m[0] * m[8] - m[2] * m[6], m[2] * m[3] - m[0] * m[5],
              m[3] * m[7] - m[4] * m[6], m[1] * m[6] - m[0] * m[7], m[0] * m[4] - m[1] * m[3]
              ]
    return result

def basisToMatrix3(x1, y1, x2, y2, x3, y3, x4, y4):
    m = [
        x1, x2, x3,
        y1, y2, y3,
        1, 1, 1
    ]
    v = multiply3MatrixAnd3Vector(computeAdjugateMatrix(m), [x4, y4, 1])
    result = multiply3MatrixAnd3Matrix(m, [
        v[0], 0, 0,
        0, v[1], 0,
        0, 0, v[2]
    ])
    return result

def computeProjectionMatrix3FromCornerPin(
        x1s, y1s, x1d, y1d,
        x2s, y2s, x2d, y2d,
        x3s, y3s, x3d, y3d,
        x4s, y4s, x4d, y4d
):
    s = basisToMatrix3(x1s, y1s, x2s, y2s, x3s, y3s, x4s, y4s)
    d = basisToMatrix3(x1d, y1d, x2d, y2d, x3d, y3d, x4d, y4d)
    return multiply3MatrixAnd3Matrix(d, computeAdjugateMatrix(s))


import sys
A = [64, 25, 12, 22, 11]

# Traverse through all array elements
for i in range(len(A)):
    index = i
    for j in range(i+1, len(A)):
        if A[index] > A[j]:
            index = j

    # Swap the found minimum element with
    # the first element
    A[i], A[index] = A[index], A[i]

# Driver code to test above
print ("Sorted array")
for i in range(len(A)):
    print("%d" %A[i])


import numpy as np
from metrics.metrics import distance

class KMeans:
    """The k-means clustering algorithm.

    Parameters
    ----------
    k : int, default = 3
        The number of clusters
    warm_start : bool, default = False
        Whether to reuse the previous result as the initialization or erase it on fit_predict() call.
    """
    def __init__(self, k=3, warm_start=False):
        self.k = k
        self.warm_start = warm_start
        self.trained = False
        self.centroids = None
        self.labels = None

    def fit_predict(self, x, n_iter=300):
        """Assign the inputs to clusters.

        Parameters
        ----------
        x : array-like
            Input array.
        n_iter : int, default = 300
            Number of iterations (finishes earlier if convergence is reached)
        """

        if not (self.warm_start and self.trained):
            index = np.random.permutation(x.shape[0])[:self.k]
            self.centroids = x[index]
            self.trained = True
        for i in range(n_iter):
            self.labels = np.array([distance(x, c) for c in self.centroids]).argmin(axis=0)
            new_centroids = np.array([x[self.labels == i].mean(axis=0) for i in range(self.k)])
            if np.all(new_centroids == self.centroids):
                break
            self.centroids = new_centroids
        return self.labels