Closed tabitaCatalan closed 3 years ago
Mi idea para "latexificar" las variables simbólicas tiene un problema al tratar la variable α
. Mi idea era usar split_var_and_real_index
que permite obtener, por ejemplo, la tupla ("R", "2")
a partir de la variable simbólica R[2]
creada con MTK (@variables t R[1,2](t)
). Para hacer esto estaba buscando los índices de los caracteres [
y ]
, lo que funciona sin problema con las variables S
, E
, I
, etc., pero que ya no funciona con la variable α
. Esto es debido a que la indexación de los string en Julia es rara (por motivos de eficiencia, ver documentación). Esa indexación provoca cosas como esta:
julia> length("α[1](t)")
7
julia> lastindex("α[1](t)")
8
julia> "α[1](t)"[1]
'α': Unicode U+03B1 (category Ll: Letter, lowercase)
julia> "α[1](t)"[2]
ERROR: StringIndexError: invalid index [2], valid nearby indices [1]=>'α', [3]=>'['
Stacktrace:
[1] string_index_err(s::String, i::Int64)
@ Base .\strings\string.jl:12
[2] getindex_continued(s::String, i::Int64, u::UInt32)
@ Base .\strings\string.jl:233
[3] getindex(s::String, i::Int64)
@ Base .\strings\string.jl:226
[4] top-level scope
@ REPL[219]:1
julia> "α[1](t)"[3]
'[': ASCII/Unicode U+005B (category Ps: Punctuation, open)
Siguiendo esta sugerencia decidí aplicar un collect
al string "α[1](t)"
, lo que lo transforma en un arreglo de caracteres. Hay que reemplazar también el caracter α
por la variable en LaTeX \alpha
.
Tenía un código parecido en plotting.jl
, la función plot_scnotation!
. Para que funcione se necesita:
scaling_factor
a plot_smoothed!
x10^{exponente}
a los subplots donde se necesiteEsto está casi listo, aunque tengo un problema: el grupo destacado debería ser el último en graficarse porque queda tapado por los grupos siguientes.
En Matplotlib existe el argumento zorder
para hacer esto, pero según el issue JuliaPlots/Plots.jl/issues/3834 eso no está implementado en Plots.jl.
Decidí reemplazar el ciclo for
en las clases, reordenando las clases con la función put_at_the_end
, de manera que la destacada quedara al final. class_to_highlight
toma el valor de n
(total de clases) por defecto, así que si hightlight
es false
debería verse normal.
# antes
for class = 1:n
...
end
# ahora
for class = put_at_the_end(1:n, class_to_highlight)
...
end
Date
sDecidí usar multiple dispatch para definir una función to_latex_string
para distintos tipos, que se encargue de "latexificar" correctamente las distintas cosas. En primera instancia estaba utilizado la 1ra componente de las xticks
, y mientras solo usaba números no había problema, pero al tratar de usar fechas me topé con un problema con la lógica interna de Plots.jl al usar Date
s. Me aparecía esto
julia> Plots.xticks(b_plot[5])
([737516.0, 737638.0, 737760.0, 737881.0], ["2020-04-01", "2020-08-01", "2020-12-01", "2021-04-01"])
Mirando el código de Plots.jl se ve que transforman las fechas a enteros/floats (no entiendo cómo ni para qué sentido). Eso funciona bien para posicionar los xtixcs
, pero tiene como consecuencia que las xtixcs
que efectivamente se muestran no tengan nada que ver.
Esto me obliga a usar los strings de 2da componente de los xticks
, que para el caso en que uso fechas tiene la forma "yyyy-mm-dd"
, y cuando uso números es algo como "123.456"
. El motivo por el que no quería usar los strings es que cada caso debe ser tratado de forma independiente, y no tengo forma de diferenciarlos. Finalmente me incliné por una solución con dispatch.
Definí una función transform
que recibe el string y algún dato de ejemplo que diga el tipo al que corresponde ese string.
transform(strdate, example_data::Date) = Date(strdate, "y-m-d") # retorna un Date
transform(strfloat, example_data::Float64) = parse(Float64, strfloat) # retorna un Float64
La idea es que si uso transform
en un string de la forma "2020-03-05"
y tomando t
como un Date
cualquiera, podré parsear la fecha correctamente (y lo mismo para un Float).
Esto obliga, desde luego, a cambiar la interfaz de latexify_ticks!
, puesto que ahora debe recibir el argumento example_data
para transferirlo a transform
.
latexify_ticks!(a_plot::Plots.Subplot, axis::Symbol, example_data)
A la hora de "latexificar" ambos ejes, necesitamos un tipo de dato de ejemplo para cada uno.
latexify_ticks!(a_plot::Plots.Plot, t0, y0)
La función transform
se encarga de entregar el tipo correcto a to_latex_string
, que deberá estar definida para los distintos tipos (Num
, Float64
, Date
).
1. Este comportamiento era inesperado (pensé que sería un Num
), y no me permitía diferenciar adecuadamente a las variables simbólicas del modelo de los otros tipos de datos:
julia> eltype(states(simple_episys_uknown))
Any
Afortunadamente, esto se resolvió de manera sencilla transformando a Num
las variables simbólicas dentro de plot_all_states_grid
(Num(symstates[index])
).
2. to_latex_string
para Date
s dio algunos problemas porque no lograba encontrar la sintaxis para mezclar texto y matemáticas dentro de una latex string. La forma que me dio resultado fue esta:
function to_latex_string(t::Date)
(y, m, d) = Dates.yearmonthday(t)
strm = Dates.monthabbr(m; locale = "spanish")
L"%$d \textrm{/%$(strm)/} %$y" # esta parte fue la difícil
end
Llegué a ella por medio del issue JuliaPlots/Plots.jl/issues/3203.
Para formatear correctamente los Floats me fue muy útil la macro @printf
y su variante que devuelve un string @sprintf
. Ver documentación para más detalles.
Los meses puede aparecer en español (enero
en lugar de january
). Para eso revisé la documentación de Dates, en particular el atributo locale
.
El gráfico estándar ahora se ve así, y puede obtenerse con el código:
plot_all_states_grid(tsdate, xs, Ps, states(simple_episys_uknown))
(tsdate
es un rango de Date
s)
Ahora además existe la posibilidad de destacar una clase:
plot_all_states_grid(tsdate, xs, Ps, states(simple_episys_uknown), highlight = true, class_to_highlight = 4)
Problema
Los gráficos no son satisfactorios, los
labels
se podrían mejorar, la notación científica no se ve bien, etc.Cosas que mejorar