diff --git a/scripts/run.jl b/scripts/run.jl
index c45cd5c7a721610c2faa5adf7472dbef438233ec..77678897dd0acc5e7830ae49920db9c851cdafe9 100644
--- a/scripts/run.jl
+++ b/scripts/run.jl
@@ -4,16 +4,16 @@ const datapath = joinpath(@__DIR__, "..", "data")
 
 ctx = Util.Context(datapath)
 
-#ctx(experiment_convergence_test, "convergence/test")
-ctx(experiment_convergence_denoising, "convergence/denoising")
-ctx(experiment_convergence_inpainting, "convergence/inpainting")
-ctx(experiment_convergence_opticalflow, "convergence/opticalflow")
+#ctx(experiment_convergence_test, "fd/convergence/test")
+ctx(experiment_convergence_denoising, "fd/convergence/denoising")
+ctx(experiment_convergence_inpainting, "fd/convergence/inpainting")
+ctx(experiment_convergence_opticalflow, "fd/convergence/opticalflow")
 
-ctx(experiment_surrogate_outerinner, "surrogate/outerinner")
-ctx(experiment_surrogate_outerinner_ref, "surrogate/outerinner_ref")
+ctx(experiment_surrogate_outerinner, "fd/surrogate/outerinner")
+ctx(experiment_surrogate_outerinner_ref, "fd/surrogate/outerinner_ref")
 
-ctx(experiment_global_basic, "global/basic")
+ctx(experiment_global_basic, "fd/global/basic")
 
 # note: run these with multiple worker processes
 # don't forget `@everywhere Pkg.activate(".")`
-ctx(experiment_scaling_opticalflow, "scaling/opticalflow")
+ctx(experiment_scaling_opticalflow, "fd/scaling/opticalflow")
diff --git a/scripts/run_experiments.jl b/scripts/run_experiments.jl
index c04231b699806726e3b7fe57d2e43847c344bd40..6a0806e8b06f2e6cfae4670467c4e1b62ee7a913 100644
--- a/scripts/run_experiments.jl
+++ b/scripts/run_experiments.jl
@@ -170,7 +170,7 @@ end
 function compare_algs(prob; τ, M, overlap, maxiters, ninner)
     algs = comparison_algs(prob; τ, M, overlap, ninner)
 
-    df, states = run_algs(algs; maxiters=maxiters ÷ 10) do state
+    df, states = run_algs(algs; maxiters) do state
         return (
             energy = energy(fetch(state), prob),
             residual = residual(fetch(state), prob))
@@ -178,7 +178,8 @@ function compare_algs(prob; τ, M, overlap, maxiters, ninner)
 
     #filter!(:k => k -> k < maxiters / 10, df)
 
-    energymin = calc_energymin(prob, algs.glob; maxiters)
+    # subtract minimal energy for logarithmic plot
+    energymin = calc_energymin(prob, algs.glob; maxiters=maxiters * 10)
     for x in names(df)
         contains(x, r"_energy$") || continue
         df[!,Symbol(x)] .-= energymin
@@ -257,7 +258,8 @@ function experiment_convergence_test(ctx)
 
     CSV.write(joinpath(ctx.outdir, "energies.csv"), df)
     #saveimg(joinpath(ctx.outdir, "output_glob.png"), fetch_u(states.glob))
-    savedata(ctx, "data.tex"; lambda=λ, beta=β, maxiters,
+    savedata(joinpath(ctx.outdir, "data.tex");
+        lambda=λ, beta=β, maxiters,
         width=size(fo, 2), height=size(fo, 1))
 end
 
@@ -316,7 +318,8 @@ function experiment_scaling_opticalflow(ctx)
 
     CSV.write(joinpath(ctx.outdir, "timings.csv"), df)
     #saveimg(joinpath(ctx.outdir, "output_glob.png"), fetch_u(states.glob))
-    savedata(ctx, "data.tex"; lambda=λ, beta=β, Mdir, M=prod(M),
+    savedata(joinpath(ctx.outdir, "data.tex");
+        lambda=λ, beta=β, Mdir, M=prod(M),
         ntimings, stopenergy, ninner,
         width=size(fo, 2), height=size(fo, 1))
 end
@@ -373,7 +376,8 @@ function _experiment_surrogate_outerinner(ctx, ref)
 
     CSV.write(joinpath(ctx.outdir, "energies.csv"), df)
     #saveimg(joinpath(ctx.outdir, "output_glob.png"), fetch_u(states.glob))
-    savedata(ctx, "data.tex"; lambda=λ, beta=β, minenergy_maxiters, maxiters, ninner, M, overlap,
+    savedata(joinpath(ctx.outdir, "data.tex");
+        lambda=λ, beta=β, minenergy_maxiters, maxiters, ninner, M, overlap,
         width=size(fo, 2), height=size(fo, 1))
 end
 
@@ -382,7 +386,7 @@ function experiment_convergence_denoising(ctx)
 
     λ = 0.1
     β = 0.
-    maxiters = 100000
+    maxiters = 10000
     ninner = 100
 
     M = (2,2)
@@ -401,8 +405,11 @@ function experiment_convergence_denoising(ctx)
     df, states, energymin = compare_algs(prob; τ, M, overlap, maxiters, ninner)
 
     CSV.write(joinpath(ctx.outdir, "energies.csv"), df)
-    saveimg(joinpath(ctx.outdir, "output_glob.png"), fetch_u(states.glob))
-    savedata(ctx, "data.tex"; lambda=λ, beta=β, tau=τ, maxiters, noise_sigma=noise_σ, energymin,
+    for alg in keys(states)
+        saveimg(joinpath(ctx.outdir, "output_" * string(alg) * ".png"), fetch_u(states[alg]))
+    end
+    savedata(joinpath(ctx.outdir, "data.tex");
+        lambda=λ, beta=β, tau=τ, maxiters, ninner, noise_sigma=noise_σ, energymin,
         width=size(fo, 2), height=size(fo, 1))
 end
 
@@ -411,7 +418,7 @@ function experiment_convergence_inpainting(ctx)
 
     λ = 0.05
     β = 0.001
-    maxiters = 100000
+    maxiters = 10000
     ninner = 100
 
     M = (2,2)
@@ -430,8 +437,11 @@ function experiment_convergence_inpainting(ctx)
     df, states, energymin = compare_algs(prob; τ, M, overlap, maxiters, ninner)
 
     CSV.write(joinpath(ctx.outdir, "energies.csv"), df)
-    saveimg(joinpath(ctx.outdir, "output_glob.png"), fetch_u(states.glob))
-    savedata(ctx, "data.tex"; lambda=λ, beta=β, tau=τ, maxiters, energymin,
+    for alg in keys(states)
+        saveimg(joinpath(ctx.outdir, "output_" * string(alg) * ".png"), fetch_u(states[alg]))
+    end
+    savedata(joinpath(ctx.outdir, "data.tex");
+        lambda=λ, beta=β, tau=τ, maxiters, ninner, energymin,
         width=size(fo, 2), height=size(fo, 1))
 end
 
@@ -442,7 +452,7 @@ function experiment_convergence_opticalflow(ctx)
     λ = 0.002
     β = 0.001
 
-    maxiters = 100000
+    maxiters = 10000
     ninner = 100
 
     M = (2,2)
@@ -455,11 +465,16 @@ function experiment_convergence_opticalflow(ctx)
 
     CSV.write(joinpath(ctx.outdir, "energies.csv"), df)
 
-    cflow = colorflow(fetch_u(first(states)); maxflow=4.5/(584/48))
-    #p = plot(cflow); display(p)
-    save(joinpath(ctx.outdir, "flow.png"), cflow)
+    for alg in keys(states)
+        u_nested = fetch_u(states[alg])
+        u = reinterpret(reshape, Float64, u_nested)
+        cflow = colorflow(u; maxflow=4.5/(584/48))
+        #p = plot(cflow); display(p)
+        save(joinpath(ctx.outdir, "flow_" * string(alg) * ".png"), cflow)
+    end
 
-    savedata(ctx, "data.tex"; lambda=λ, beta=β, tau=τ, maxiters, energymin,
+    savedata(joinpath(ctx.outdir, "data.tex");
+        lambda=λ, beta=β, tau=τ, maxiters, ninner, energymin,
         width=size(f0, 2), height=size(f0, 1))
 end
 
@@ -475,7 +490,7 @@ function experiment_global_basic(ctx)
     λ = 0.02
     β = 1e-3
 
-    #maxiters = 100000
+    #maxiters = 10000
     maxiters = 100
     ninner = 1000
 
@@ -524,7 +539,7 @@ function experiment_global_basic(ctx)
     #display(fetch_u(st))
     #return
 
-    df, states = run_algs([alg]; maxiters=maxiters) do state
+    df, states = run_algs([alg]; maxiters) do state
         return (
             energy = energy(fetch(state), prob),
             residual = residual(fetch(state), prob))
@@ -550,7 +565,8 @@ function experiment_global_basic(ctx)
     display(p)
 
 
-    savedata(ctx, "data.tex"; lambda=λ, beta=β, tau=τ, maxiters, ninner,
+    savedata(joinpath(ctx.outdir, "data.tex");
+        lambda=λ, beta=β, tau=τ, maxiters, ninner,
         width=size(f, 2), height=size(f, 1))
     return prob
 end
diff --git a/scripts/util.jl b/scripts/util.jl
index 4bcdf1d65cf1a85e4b6f1efc4593c7159a7742d1..790a51cf80fef51919c0b90d28ce2c204872f0ef 100644
--- a/scripts/util.jl
+++ b/scripts/util.jl
@@ -24,6 +24,10 @@ Context(ctx::Context, path::String; params...) =
     Context(joinpath(ctx.indir, path), joinpath(ctx.outdir, path),
         merge(ctx.params, NamedTuple(params)),
         joinpath(ctx.path, path))
+Context(ctx::Context; params...) =
+    Context(ctx.indir, ctx.outdir,
+        merge(ctx.params, NamedTuple(params)),
+        ctx.path)
 
 """
     (ctx::Context)(f, subdir; params...)
@@ -34,19 +38,19 @@ parameters `params`.
 function (ctx::Context)(f::Function, subdir::String; params...)
     # maybe debug output with params?
     subctx = Context(ctx, subdir; params...)
+    mkpath(subctx.outdir)
     println("starting experiment `$(subctx.path)` ...")
     f(subctx)
 end
 
 # LaTeX Data Output
 
-# TODO: don't depend on ctx.path and use filename only
-savedata(ctx::Context, filename; data...) =
-    open(joinpath(ctx.outdir, filename); write=true) do io
-        _savedata(io, ctx.path; data...)
+savedata(filename; data...) =
+    open(filename; write=true) do io
+        _savedata(io; data...)
     end
 
-function _savedata(io, path; data...)
+function _savedata(io; data...)
     isvalidname(x) = contains(string(x), r"^[^/\\]+$")
 
     # define tex command to access data
@@ -63,7 +67,7 @@ function _savedata(io, path; data...)
 
         # actual data encoded as tex-commands
         write(io, "\\expandafter\\def")
-        write(io, "\\csname $(texcmd)/$(path)/$(key)\\endcsname{")
+        write(io, "\\csname $(texcmd)/\\DataPrefix/$(key)\\endcsname{")
         show(io, MIME("text/latex"), value)
         write(io, "}\n")
     end
@@ -73,24 +77,8 @@ end
 
 Base.show(io, ::MIME"text/latex", x) = print(io, x)
 
-function Base.show(io::IO, ::MIME"text/latex", x::AbstractFloat)
-    exponent = x == 0. ? 0 : floor(Int, log10(x))
-    if abs(exponent) <= 3
-        print(io, "\\ensuremath{", x, "}")
-    else
-        base = x / 10. ^ exponent
-        print(io, "\\ensuremath{", base, "\\cdot 10^{", exponent, "}}")
-    end
-end
-
-function Base.show(io::IO, ::MIME"text/latex", x::Integer)
-    p = log10(x)
-    pr = round(Int, p)
-    if x == 10^pr
-        print(io, "\\ensuremath{10^{", pr, "}}")
-    else
-        print(io, "\\ensuremath{", x, "}")
-    end
+function Base.show(io::IO, ::MIME"text/latex", x::Union{Integer,AbstractFloat})
+    print(io, "\\pgfmathprintnumber{", x ,"}")
 end
 
 end
diff --git a/src/chambolle.jl b/src/chambolle.jl
index b220ea4e811310684985611fe2506df2ada76101..65e87639a9e0d72da6e3f00d476ac705a17b140f 100644
--- a/src/chambolle.jl
+++ b/src/chambolle.jl
@@ -114,7 +114,7 @@ function step!(ctx::ChambolleState)
     # p = (p + τ*grad(s)) / (1 + τ/λ|grad(s)|)
 
     sgrad = map(kgrad, ctx.s)
-    f(p, sgrad, λ) = iszero(λ) ? zero(p) :
+    @inline f(p, sgrad, λ) = iszero(λ) ? zero(p) :
         (p + alg.τ * sgrad) ./ (1. .+ projnorm(alg.τ * sgrad, alg.anisotropic) ./ λ)
 
     ctx.p .= f.(ctx.p, sgrad, λ)