# Graficar funciones de distribucion discretas con soporte finito
# Funciones definidas: grafica_fdist(p,x) y grafica_dos_fdist(pa,xa,pb,xb)
# Es necesario tener PyPlot (y por tanto una distribucion de python)
# Ricard Torres <rtorres@itam.mx>
module fdistgraficar
export grafica_fdist
export grafica_dos_fdist
using PyPlot  # es complicado usar librerias dentro de una funcion
"""
function grafica_fdist(p, x)\n
Graficar la funcion de distribucion de una distribucion discreta (p, x)\n
p: son las probabilidades de cada valor\n
x: son los valores respectivos (en estricto orden ascendiente)
"""
function grafica_fdist(p, x)
   lx = length(x)
   if lx != length(p)
      error("Valores y probabilidades deben tener la misma longitud")
   end
   tol = 1e-10 # tolerancia para comparar magnitudes
   if abs(sum(p)-1) > tol
      error("Vectores de probabilidad deben sumar 1")
   end
   if x != sort(unique(x))
      error("Vectores de valores deben estar en orden ascendiente estricto")
   end
   F = cumsum(p) # funcion de distribucion (suma cumulativa)
   # Rango de valores que graficaremos
   xavg = (x[end] - x[1]) / lx
   xmin = x[1] - xavg
   xmax = x[end] + xavg
   # generar puntos para graficar funcion tipo escalera
   xs = zeros(2*lx)
   Fs = zeros(2*lx)
   for i = 1 : lx
       xs[2*i-1] = x[i]
       xs[2*i] = x[i]
   end
   for i = 1 : lx - 1
       Fs[2*i] = F[i]
       Fs[2*i+1] = F[i]
   end
   Fs[2*lx] = 1
   figure()
   plot([xmin,x[1]],[0,0],linestyle="-",linewidth=2,color="blue")
   plot([x[end],xmax],[1,1],linestyle="-",linewidth=2,color="blue")
   plot(xs,Fs,linestyle="-",linewidth=2,color="blue")
   plot(x,F,linestyle="None",linewidth=2,marker="o") 
   axis([xmin,xmax,-0.1,1.1])
   xlabel("Valores")
   ylabel("Probabilidad acumulada")
   title("Funcion de distribucion")
end  # function

"""
function grafica_dos_fdist(pa, xa, pb, xb)\n
Graficar las funciones de distribucion de dos distribuciones discretas\n
pi: son las probabilidades de cada valor\n
xi: son los valores respectivos (en estricto orden ascendiente)
"""
function grafica_dos_fdist(pa, xa, pb, xb)
   la = length(xa)
   lb = length(xb)
   if la != length(pa) || lb != length(pb)
      error("Valores y probabilidades deben tener la misma longitud")
   end
   tol = 1e-10 # tolerancia para comparar magnitudes
   if max( abs(sum(pa)-1), abs(sum(pb)-1) ) > tol
      error("Vectores de probabilidad deben sumar 1")
   end
   if xa != sort(unique(xa)) || xb != sort(unique(xb)) 
      error("Vectores de valores deben estar en orden ascendiente estricto")
   end
   Fa = cumsum(pa)
   Fb = cumsum(pb)
   # Rango de valores que graficaremos
   vmax = max(xa[end],xb[end])
   vmin = min(xa[1],xb[1])
   vavg = ( vmax - vmin ) / max(la,lb) # distancia media entre valores
   xmin = vmin - vavg
   xmax = vmax + vavg
   # generar puntos para graficar funcion tipo escalera
   xas = zeros(2*la)
   Fas = zeros(2*la)
   for i = 1 : la
       xas[2*i-1] = xa[i]
       xas[2*i] = xa[i]
   end
   for i = 1 : la - 1
       Fas[2*i] = Fa[i]
       Fas[2*i+1] = Fa[i]
   end
   Fas[2*la] = 1
   xbs = zeros(2*lb)
   Fbs = zeros(2*lb)
   for i = 1 : lb
       xbs[2*i-1] = xb[i]
       xbs[2*i] = xb[i]
   end
   for i = 1 : lb - 1
       Fbs[2*i] = Fb[i]
       Fbs[2*i+1] = Fb[i]
   end
   Fbs[2*lb] = 1
   figure()
   plot([xmin,xa[1]],[0,0],linestyle="-",linewidth=2,color="blue")
   plot([xa[end],xmax],[1,1],linestyle="-",linewidth=2,color="blue")
   h1 = plot(xas,Fas,linestyle="-",linewidth=2,color="blue")
   plot(xa,Fa,linestyle="None",linewidth=2,marker="o",color="blue") 
   plot([xmin,xb[1]],[0,0],linestyle="-",linewidth=2,color="red")
   plot([xb[end],xmax],[1,1],linestyle="-",linewidth=2,color="red")
   h2 = plot(xbs,Fbs,linestyle="-",linewidth=2,color="red")
   plot(xb,Fb,linestyle="None",linewidth=2,marker="o",color="red") 
   axis([xmin,xmax,-0.1,1.1])
   legend([h1;h2],["F distrib A","F distrib B"],loc="upper left")
   xlabel("Valores")
   ylabel("Probabilidad acumulada")
   title("Funciones de distribucion")
end  # function

end  # module

using fdistgraficar
