# Using @lift with @sprintf for animation in Makie.jl

I want to display a text box which acts as a counter in an animation. I followed the tutorial here, but the text I want to display consists of an integer and a really small number (which is visually better displayed using scientific notation with fixed decimal places with `@sprintf`).

The following works:

``````iter_idx = Observable(1)
text_str = @lift("iteration : \$(\$iter_idx-1)\ncost function : \$(trace_J[\$iter_idx])")
text!(ax1, Point2f(0, 0), text=text_str, align=(:left, :top))
``````

but then the value of cost function displayed will have fluctuating number of digits and switch between floating point numbers and scientific notation for display.

I tried the following

``````text_str = @lift(@sprintf("iteration : %.0f\ncost function : %.3e",\$iter_idx, \$(trace_J[\$iter_idx])))
``````

but I get the error

``````ERROR: syntax: "\$" expression outside quote around ...
``````

I also tried

``````current_iter = @lift(\$iter_idx-1)
current_J = @lift(trace_J[\$iter_idx])
text_str = @sprintf("iteration : %.0f\ncost function : %.3e", current_iter, current_J)
``````

which gives the error

``````ERROR: MethodError: no method matching Float64(::Observable{Int64})
Closest candidates are:
(::Type{T})(::AbstractChar) where T<:Union{AbstractChar, Number} at char.jl:50
(::Type{T})(::Base.TwicePrecision) where T<:Number at twiceprecision.jl:266
(::Type{T})(::Complex) where T<:Real at complex.jl:44
``````

So what’s the proper way to handle this where I want string formatting for a text which is being updated at each frame of the animation?

More than one macro confuses Julia. What I have ended up doing is getting rid of one macro call and burying the other one.

Something like

``````function title_string(current_iter, current_J)
@sprintf "iteration : %.0f\ncost function : %.3e" current_iter current_J
end

iter_idx = Observable(1)

text_itr = lift(t -> title_string(trace_J[t], t - 1), iter_idx) #Avoid the macro call here

text!(ax1, Point2f(0, 0), text=text_str, align=(:left, :top))
``````

(You may need to adjust to make it run but that is the idea)