def __init__(self):
		super(GaussianPlot, self).__init__(None,None)
		self.poly = [[],[],[]];
		self.oldGauss = None
		self.oldLine = [None,None,None]
		self.line = None
		self.sedimentLenght = 0.1
		self.r = 0.3
		self.polyMarshal = PolinomialMarshal()
 def __init__(self):
     super(MeloshPlot, self).__init__(None, None)
     self.polyMarshal = PolinomialMarshal()
     self.x, self.y = 491, 953
class MeloshPlot(movablePoints.HandleMovablePoints):
    def __init__(self):
        super(MeloshPlot, self).__init__(None, None)
        self.polyMarshal = PolinomialMarshal()
        self.x, self.y = 491, 953

    def addControlPoint(self, x, y, i):
        pt = super(MeloshPlot, self).addControlPoint(x, y)
        self.poly[i].append(pt)
        return pt

    def addPoint(self, pt, i):
        self.poly[i].append(pt)

    def getProfile(self, elipse_transform_radious):
        x1, y1 = self.plotSediment()
        x2, y2 = self.plotInterior()
        xp, yp = self.plotPeak()
        x3, y3 = self.plotEjecta()
        # x = np.array([x1,x2]).flatten()
        # y = np.array([y1,y2]).flatten() - self.yTrans
        x = elipse_transform_radious * np.array([x1, x2, xp, x3]).flatten()
        y = np.array([y1, y2, yp, y3]).flatten()  # - self.yTrans
        return x, y

    def paintLeyend(self):
        print "leyenda"

    def paint(self, line, elipse_transform_radious=1.0):
        # print "paint"
        self.CADConstraints()
        # D2 = self.D2
        # xs = self.xs
        # self.xs = self.xs*elipse_transform_radious
        # self.D2 = self.D2*elipse_transform_radious
        x, y = self.getProfile(elipse_transform_radious)
        # self.D2 = D2
        # self.xs = xs
        # if(self.line == None):
        # 	self.line, =  plt.plot(x,y,lw=2,color='blue')
        # else:
        line.set_xdata(x)
        line.set_ydata(y)
        return x, y

    def marshalPolynomialCrater(self):
        return self.polyMarshal.marshalPolynomialCrater()

    def marshalPolynomialCraterMock(self):
        return self.polyMarshal.marshalPolynomialCraterMock()

    def repaint(self):
        self.paint(self.line)

    def plotSediment(self):
        # syms hs xs ys yp_s a b c d f
        # e1 = hs + (xs^4)*c + (xs^3)*d == ys;
        # e2 = 4*c*xs^3 + 3*d*xs^2 == yp_s;
        # sol = solve([e1,e2],[c,d]);
        minX = 0
        maxX = self.xs
        xs = self.xs
        ys = self.ys
        hs = self.hs
        D = 2 * self.D2
        h = self.h
        hr = self.hr
        # coef = [(ys-hs)/(xs**2),0, hs]
        # p = np.poly1d(coef)
        xp = np.linspace(minX, maxX, 200)
        # if(hs>ys):
        # return xp,hs*np.ones(len(xp))
        yp_s = (h + hs + hr) * (8 * xs / (D * D))
        c = -(3 * hs - 3 * ys + xs * yp_s) / (xs ** 2)
        d = (2 * hs - 2 * ys + xs * yp_s) / (xs ** 3)
        if c < 0:
            xFlat = -2 * c / (3 * d)
            yFlat = hs + (c * xFlat) * xFlat + (d * xFlat) * xFlat * xFlat
            # xp = np.linspace(xFlat,maxX, 200)

            return xp, (xp <= xFlat) * yFlat + (xp > xFlat) * (hs + (c * xp) * xp + (d * xp) * xp * xp)
            # (2*c*xp) + (d*xp)*3*xp = 0
            # c = (3*hs - 3*ys + xs*yp_s)/xs**4
            # d = -(4*hs - 4*ys + xs*yp_s)/xs**3
            # print "c: %f\td: %f\n"%(c,d)
            # print c
            # if(c<0):
            # 	return xp,hs*np.ones(len(xp))
            # return xp, hs + (c*xp)*xp*xp*xp + (d*xp)*xp*xp
        return xp, hs + (c * xp) * xp + (d * xp) * xp * xp
        # return xp,hs + (xp*xp)*(ys-hs)/(xs**2) # p(xp)

    def plotInterior(self):
        minX = self.xs
        maxX = self.getPeakXMinLimit()  # self.D2-self.D2/12
        xs = self.xs
        ys = self.ys
        hr = self.hr
        hs = self.hs
        h = self.h
        D = 2 * self.D2
        xp = np.linspace(minX, maxX, 200)
        return xp, (h + hs + hr) * ((2 * xp / D) ** 2)  # (xp**2)*(ys/(xs**2))# (h+hr)*( (2*xp/D)**2)

    def getPeakXMinLimit(self):
        m = np.amax([self.xs, self.D2 - self.D2 / 12])
        return m

    def plotPeak(self):

        # x_1 = self.getPeakXMinLimit() +0.0001# self.D2-self.D2/12+0.0001
        # x_2 = self.D2+self.D2/12-0.0001

        # a = -(2*x_1**5*y_1 + x_2**5*y_2 - x_1**6*yp_1 - x_2**6*yp_2 - 4*x_1*x_2**4*y_1 - 6*x_1**4*x_2*y_2 + 3*x_1**2*x_2**3*y_1 + 4*x_1**3*x_2**2*y_2 - 2*x_1**2*x_2**4*yp_1 + 3*x_1**3*x_2**3*yp_1 + 4*x_1**3*x_2**3*yp_2 - 3*x_1**4*x_2**2*yp_2)/((x_1 - x_2)**2*(- 2*x_1**3 + 2*x_1**2*x_2 + 2*x_1*x_2**2 - x_2**3))
        # b = -(x_1*(2*x_2**5*y_1 - 2*x_2**5*y_2 + 2*x_2**6*yp_2 - 4*x_1**4*x_2*y_1 + 4*x_1**4*x_2*y_2 + x_1*x_2**5*yp_1 + 2*x_1**5*x_2*yp_1 - 3*x_1**3*x_2**3*yp_1 - 4*x_1**2*x_2**4*yp_2 + 2*x_1**4*x_2**2*yp_2))/((x_1 - x_2)**2*(- 2*x_1**3 + 2*x_1**2*x_2 + 2*x_1*x_2**2 - x_2**3))
        # c = (x_1**2*x_2**2*(2*x_1**3*y_2 - 2*x_1**3*y_1 + x_2**3*y_1 - x_2**3*y_2 + x_1**4*yp_1 + x_2**4*yp_2 + x_1*x_2**3*yp_1 + 2*x_1**3*x_2*yp_2 - 2*x_1**2*x_2**2*yp_1 - 3*x_1**2*x_2**2*yp_2))/((x_1**2 - 2*x_1*x_2 + x_2**2)*(- 2*x_1**3 + 2*x_1**2*x_2 + 2*x_1*x_2**2 - x_2**3))
        # d = -(x_1**3*yp_1 - x_2**3*yp_2 - x_1**2*x_2*yp_1 + x_1*x_2**2*yp_2 - 2*x_1*x_2*y_1 + 2*x_1*x_2*y_2)/((x_1 - x_2)*(- 2*x_1**3 + 2*x_1**2*x_2 + 2*x_1*x_2**2 - x_2**3))

        D = self.D2 * 2
        h = self.h
        hs = self.hs
        hr = self.hr
        x_1 = self.x_1
        x_2 = self.x_2

        xp2 = np.linspace(x_1, x_2, 200)
        # y_1 = (h+hr+hs)* ( (2*x_1/D)**2)
        # yp_1 = (8/(D*D))*(h+hr+hs)*x_1
        # y_2 = ((hr)* (D**3) * (x_2**(-3))  )/8 +h + hs #((hr)* ((D/x_2)**3  ))/8 +h + hs
        # yp_2 = ((hr)* (D**3) *(-3) * (x_2**(-4))  )/8

        # a = (x_1**3*y_2 - x_2**3*y_1 + 3*x_1*x_2**2*y_1 - 3*x_1**2*x_2*y_2 + x_1*x_2**3*yp_1 - x_1**3*x_2*yp_2 - x_1**2*x_2**2*yp_1 + x_1**2*x_2**2*yp_2)/((x_1 - x_2)*(x_1**2 - 2*x_1*x_2 + x_2**2))
        # b = (x_1**3*yp_2 - x_2**3*yp_1 - x_1*x_2**2*yp_1 + 2*x_1**2*x_2*yp_1 - 2*x_1*x_2**2*yp_2 + x_1**2*x_2*yp_2 - 6*x_1*x_2*y_1 + 6*x_1*x_2*y_2)/((x_1 - x_2)*(x_1**2 - 2*x_1*x_2 + x_2**2))
        # c = (3*x_1*y_1 - 3*x_1*y_2 + 3*x_2*y_1 - 3*x_2*y_2 - x_1**2*yp_1 - 2*x_1**2*yp_2 + 2*x_2**2*yp_1 + x_2**2*yp_2 - x_1*x_2*yp_1 + x_1*x_2*yp_2)/((x_1 - x_2)*(x_1**2 - 2*x_1*x_2 + x_2**2))
        # d = -(2*y_1 - 2*y_2 - x_1*yp_1 - x_1*yp_2 + x_2*yp_1 + x_2*yp_2)/((x_1 - x_2)*(x_1**2 - 2*x_1*x_2 + x_2**2))

        # coef = [(ys-hs)/(xs**2),0, hs]
        # p = np.poly1d(coef)
        # xp = np.linspace(x_1,x_2, 200)

        y_1 = (h + hr + hs) * ((2 * x_1 / D) ** 2)
        yp_1 = (8 / (D * D)) * (h + hr + hs) * x_1
        yp_2 = ((hr) * (D ** 3) * (-3) * (x_2 ** (-4))) / 8
        y_2 = ((hr) * (D ** 3) * (x_2 ** (-3))) / 8 + h + hs
        # transform to local space
        y_2 = y_2 - y_1
        x_2 = x_2 - x_1

        a = 0
        b = yp_1
        c = -(2 * x_2 * yp_1 - 3 * y_2 + x_2 * yp_2) / (x_2 * x_2)
        d = (x_2 * yp_1 - 2 * y_2 + x_2 * yp_2) / (x_2 ** 3)

        # print "y_1,yp_1,yp_2,y_2",y_1,yp_1,yp_2,y_2
        # print "a,b,c,d : ",a,b,c,d

        xp_t = xp2 - x_1
        yp_t = a + b * xp_t + c * (xp_t ** 2) + d * (xp_t ** 3) + y_1
        # xp_t = xp_t + x_1
        # yp = a + b*xp + c * (xp**2) +d * (xp ** 3)
        # plt.figure(2)
        # plt.clf()
        # plt.plot(xp_t,yp_t,'g^')
        # plt.plot(xp,yp,'r^')
        # plt.show()
        # return np.array([0]),np.array([0])
        return xp2, yp_t
        # return xp-xp[0],yp-yp[0]
        # return np.concatenate((xp,xp_t)), np.concatenate( (yp,yp_t))  #a + b/(xp) + c/(xp*xp) + d*xp*xp # p(xp)
        # return xp,  self.a + self.b*xp_t + self.c * (xp_t**2) +self.d * (xp_t ** 3) #a + b/(xp) + c/(xp*xp) + d*xp*xp # p(xp)

    def plotEjecta(self):
        minX = self.D2 + self.D2 / 12
        maxX = self.D2 + 200 + 300
        D = self.D2 * 2
        h = self.h
        hr = self.hr
        hs = self.hs
        xp = np.linspace(minX, maxX, 200)
        return xp, ((hr) * ((D / xp) ** 3)) / 8 + h + hs  # hr*( (2*xp/D)**(-3)) + h

    def setParameters(self, hs, D2, hr, aRepose, lemp, lema):
        self.hs = hs
        self.D2 = D2
        self.hr = hr
        self.aRepose = aRepose
        self.lema = lema
        self.lemp = lemp
        # self.x,self.y = 491,953

    def setLocation(self, crater):
        self.x, self.y = crater.x, crater.y
        print "new loc ", self.x, self.y

    def setParametersCrater(self, c):
        self.polyMarshal.popFloatStack()
        self.hs = c.hs
        self.D2 = c.D2
        self.hr = c.hr
        self.aRepose = c.aRepose
        self.x = c.x
        self.y = c.y
        self.lema = c.lema
        self.lemp = c.lemp

        # 	self.curvature = curvature
        # def setParametersCrater(self,crater):
        # 	self.sedimentLenght = crater.sediment
        # 	self.r = crater.w
        # 	self.hs = crater.h
        # 	self.sigma = crater.sigma
        # 	self.curvature = crater.curvature

    def CADConstraints(self):
        D = self.D2 * 2
        hr = self.hr
        hs = self.hs
        if D < 0.00001:
            return
            # from http://www.lpi.usra.edu/meetings/lpsc2013/pdf/1304.pdf
            #    Smp (N = 3693)	d = 0.165D1.094	d = 0.073D1.311	d = 0.011D1.992
            # 0.073D1.311
            # ha = 0.073*(D**1.311)
            # H.-J. Hsu1 and N. G. Barlow1, INVESTIGATION OF THE RELATIONSHIP OF CRATER DEPTHS AND DIAMETERS IN SELECTED REGIONS OF MARS, Department of Physics and Astronomy, Northern Arizona University, NAU Box 6010, Flagstaff, Arizona 2013
            # RV to calculate true ht and Dt
        ht = 0.1624 * D + 0.0065  # *1000
        ht = ht / 0.8
        Dt = D
        ha = ht - hs
        self.yTrans = 0  # hs+ha
        # print "hs "+str(hs)
        # print "ht+hr "+str(ht+hr)
        err = ht + hr - hs
        # print "err "+str( (1.30/err)**2  )
        # print ht*0.8
        # print ha,D
        # print hs,ha,hr,ht

        # # *0.8 # true depth calcuate aparent h, based on apparent D
        self.h = ha  # - self.hr + self.hs
        self.ha = ha
        self.xs = np.tan((np.pi / 180) * self.aRepose) * (D ** 2) / (8 * (ha + hr + hs))
        self.ys = (ha + hr + hs) * ((2 * self.xs / D) ** 2)

        # aRepose = np.atan(  xs * (8  * (ha+hr+hs) )/ (D**2) )*(180.0/np.pi)
        if hs > self.ys:
            self.ys = hs
            self.xs = np.sqrt(self.ys / (hs + hr + ha)) * D / 2.0
            # self.ys = hs+self.aRepose
            # self.xs = np.sqrt(self.ys/(hs+hr+ha) )*D/2.0 # np.tan(self.aRepose)*(D**2) / (8  * (ha+hr) )
            # self.ys = (ha+self.hr) *  ((2*self.xs/D)**2) # (ha+self.hr) *  ((2*self.xs/D)**2) # self.aRepose+hs # self.aRepose # (ha+self.hr) *  ((2*self.xs/D)**2)
            # np.sqrt(self.ys/(ha+hr+ha) )*D/2.0 # np.sqrt(self.ys/(ha+hr) )*D/2.0   # np.tan(self.aRepose)*(D**2) / (8  * (h+hr) )
            # print self.xs,self.ys
        h = self.h

        x_1 = self.getPeakXMinLimit() + 0.0001  # self.D2-self.D2/12+0.0001
        x_2 = self.D2 + self.D2 / 12 - 0.0001

        # y_1 = (h+hr+hs)* ( (2*x_1/D)**2)
        # yp_1 = (8/(D*D))*(h+hr+hs)*x_1

        #  #((hr)* ((D/x_2)**3  ))/8 +h + hs
        # yp_2 = ((hr)* (D**3) *(-3) * (x_2**(-4))  )/8

        # y_2 = ((hr)* (D**3) * (x_2**(-3))  )/8 +h + hs
        # y_2 =  (y_2 - y_1)
        # x_2 =  (x_2 - x_1)

        # self.a = (x_1**3*y_2 - x_2**3*y_1 + 3*x_1*x_2**2*y_1 - 3*x_1**2*x_2*y_2 + x_1*x_2**3*yp_1 - x_1**3*x_2*yp_2 - x_1**2*x_2**2*yp_1 + x_1**2*x_2**2*yp_2)/((x_1 - x_2)*(x_1**2 - 2*x_1*x_2 + x_2**2))
        # self.b = (x_1**3*yp_2 - x_2**3*yp_1 - x_1*x_2**2*yp_1 + 2*x_1**2*x_2*yp_1 - 2*x_1*x_2**2*yp_2 + x_1**2*x_2*yp_2 - 6*x_1*x_2*y_1 + 6*x_1*x_2*y_2)/((x_1 - x_2)*(x_1**2 - 2*x_1*x_2 + x_2**2))
        # self.c = (3*x_1*y_1 - 3*x_1*y_2 + 3*x_2*y_1 - 3*x_2*y_2 - x_1**2*yp_1 - 2*x_1**2*yp_2 + 2*x_2**2*yp_1 + x_2**2*yp_2 - x_1*x_2*yp_1 + x_1*x_2*yp_2)/((x_1 - x_2)*(x_1**2 - 2*x_1*x_2 + x_2**2))
        # self.d = -(2*y_1 - 2*y_2 - x_1*yp_1 - x_1*yp_2 + x_2*yp_1 + x_2*yp_2)/((x_1 - x_2)*(x_1**2 - 2*x_1*x_2 + x_2**2))
        # x_2 = x_2 + x_1

        # self.a = 0
        # self.b = yp_1
        # self.c = -(2*x_2*yp_1 - 3*y_2 + x_2*yp_2)/(x_2*x_2)
        # self.d = (x_2*yp_1 - 2*y_2 + x_2*yp_2)/(x_2**3)
        self.x_1 = x_1
        self.x_2 = x_2
        # self.y_1 = y_1
        # e1 = (x_2)*yp_1 + (x_2^2)*c + (x_2^3)*d == y_2;
        # e2 = yp_1 + 2*x_2*c + 3*d*x_2^2 == yp_2;

        # self.peakXMin = x_1
        # print "xs,ys : "+str(self.xs)+", "+str(self.ys)
        # push parameters
        # print "\tX --> "+str(self.x)+" size "+str(len(self.polyMarshal.floatStack))
        self.polyMarshal.pushFloat(self.x)
        self.polyMarshal.pushFloat(self.y)
        self.polyMarshal.pushFloat(D)
        self.polyMarshal.pushFloat(self.hs)
        self.polyMarshal.pushFloat(self.h)
        # ha
        self.polyMarshal.pushFloat(self.hr)
        self.polyMarshal.pushFloat(self.xs)
        self.polyMarshal.pushFloat(self.ys)

        self.polyMarshal.pushFloat(err)
        self.polyMarshal.pushFloat(self.lemp)
        self.polyMarshal.pushFloat(self.lema)

        self.polyMarshal.pushFloat(self.x_1)
        self.polyMarshal.pushFloat(self.x_2)
        self.polyMarshal.pushFloat(self.aRepose)
        self.polyMarshal.pushFloat(self.ha)
        self.polyMarshal.pushFloat(self.x_1)
class GaussianPlot(movablePoints.HandleMovablePoints):
	def __init__(self):
		super(GaussianPlot, self).__init__(None,None)
		self.poly = [[],[],[]];
		self.oldGauss = None
		self.oldLine = [None,None,None]
		self.line = None
		self.sedimentLenght = 0.1
		self.r = 0.3
		self.polyMarshal = PolinomialMarshal()
	def addControlPoint(self,x,y,i):
		pt = super(GaussianPlot, self).addControlPoint(x,y)
		self.poly[i].append(pt)
		return pt
	def addPoint(self,pt,i):
		self.poly[i].append(pt)

	def paint(self,line):
		self.CADConstraints()
		# t = np.arange(0,1.699, 0.1)
		x1,y1 = self.plotPolynomial(0)
		x2,y2 = self.plotPolynomial(1)
		x3,y3 = self.plotGaussian()
		x = np.array([x1,x2,x3]).flatten()
		y = np.array([y1,y2,y3]).flatten()
		if(self.line == None):
			self.line, =  plt.plot(x,y,lw=2,color='blue')
		else:
			line.set_xdata(x)
			line.set_ydata(y)
	def marshalPolynomialCrater(self):
		return self.polyMarshal.marshalPolynomialCrater()

	def repaint(self):
		self.paint(self.line)

		# self.plotPolynomial(2)

	def plotPolynomial(self,iPoly):
		p = self.poly[iPoly] 
		ptX = []
		ptY = []
		n = len(p)
		c0 = p[0]
		c1 = p[n-1]
		# add dinamyc points
		for i in range(0,n):
			c = p[i]
			ptX.append(c.x)
			ptY.append(c.y)
			# add point reflexion with c0 axis
			# print "c.x "+str(c.x) + str(c0.x)
			if(-c.x+c0.x != 0):
				ptX.append(-c.x+2*c0.x)
				ptY.append(c.y)
		coef = np.polyfit(np.array(ptX),np.array(ptY),3)
		p = np.poly1d(coef)
		xp = np.linspace(c0.x, c1.x, 100)
		self.polyMarshal.pushPolynomial(c0.x, c1.x,coef)

		return xp,p(xp)
		# self.oldLine[iPoly].set_ydata(p(xp))
	#	movablePoints.removeLine(self.oldLine[iPoly])
	#	self.oldLine[iPoly] = plt.plot( xp,p(xp),'r')
	
	def plotGaussian(self):
		mean = self.mean
		sigma = self.sigma
		hs =  self.hs #0.025
		xp = np.linspace(mean, 2, 100)
		a = 1/(sigma*np.sqrt(2*np.pi))
		# Calculate the max y value of the gaussian
		# My = a
		# print a
		# print np.exp(   -(0.0)**2/(2.0*sigma**2)  ) 
		yp = hs*np.exp(-(xp-mean)**2/(2.0*sigma**2)  ) + self.h - hs
		# yp = 1/ (1+np.exp(-( -xp*10+10) ) )
		# print yp
		self.polyMarshal.pushGaussian(mean, 2.0,mean,sigma,self.h,hs)
		
		#movablePoints.removeLine(self.oldGauss)
		#self.oldGauss = plt.plot( xp,yp,'r')
		# print "gauss Down"
		return xp,yp
	def addGaussian(self,h,sigma):
		self.h = h
		self.sigma = sigma
	# def addEvents(self):
	# 	fig.canvas.mpl_connect('key_press_event', press)
	def keyPressEvents(self,e):
		print "KeySon: "+e.key
		if(e.key == 'x'):
			self.sigma +=0.01
		elif(e.key=='z'):
			self.sigma -=0.01
		elif(e.key == 'q'):
			self.r +=0.01
		elif(e.key=='w'):
			self.r -=0.01		
		elif(e.key == 'e'):
			self.sedimentLenght +=0.01
		elif(e.key=='r'):
			self.sedimentLenght -=0.01

		print self.sigma
		print self.r
		# repaint
		self.repaint()
	def setParameters(self,sediment,w,h,sigma):
		self.sedimentLenght = sediment
		self.r = w
		self.hs = h
		self.sigma = sigma
	def CADConstraints(self):
		k = 0.047
		j = 1.284
		sediment = self.poly[0]
		sedimentLenght = self.sedimentLenght
		interiorCurve = self.poly[1]
		lowerPt = sediment[0]
		sedimentEnd = sediment[1]
		sedimentEnd.setCenter(sedimentLenght,sedimentEnd.y)
		n = len(interiorCurve)
		topPt = interiorCurve[n-1]
		# r = topPt.x
		r = self.r
		h = 2*k*r**j +lowerPt.y
		# set parameters for gaussian
		self.h = h
		self.mean = r
		self.base = lowerPt.y
		topPt.setCenter(r,h)