Tips and tricks for Julia practitioners — Julia Eindhoven
As a Julia practitioner you may want to publish your work in various forms: notebooks, Markdown, HTML, PDF and more. What if you could produce all these different outputs from the same input? I will share how I’ve been using Quarto with Julia, for package documentation, blogging and JuliaCon proceedings.
DISCLAIMER: Views presented in this presentation are my own. I am not affiliated with either Quarto or Posit (RStudio).
R
whenever possible (see here).We have some wonderful news: RStudio is now Posit! 🎉
— Posit PBC (@posit_pbc) November 2, 2022
While many things will stay the same, our rebrand will result in changes beyond a new name. To start, our new website https://t.co/vI56Gz7Yqf is now live. Please check out our new home and let us know what you think! pic.twitter.com/hzJGXsX0tj
A plain Markdown document blended with your favorite programming language and a YAML header defining your output.
Quarto enables effective communication and reproducibility without compromises.
Most science today involves code.
using Markdown
Markdown.parse("""
Often code forms such an integral part of the science, that it deserves its place in the final publication.
""")
Often code forms such an integral part of the science, that it deserves its place in the final publication.
Using simple YAML options, we can specify how code is displayed. For example, we may want to use code folding to avoid unnecessary interruptions or hide large code chunks like this one that builds Figure 1.
using Javis, Animations, Colors
www_path = "www/images"
_size = 600
radius_factor = 0.33
function ground(args...)
background("transparent")
sethue("white")
end
function rotate_anim(idx::Number, total::Number)
distance_circle = 0.875
steps = collect(range(distance_circle,1-distance_circle,length=total))
Animation(
[0, 1], # must go from 0 to 1
[0, steps[idx]*2π],
[sineio()],
)
end
translate_anim = Animation(
[0, 1], # must go from 0 to 1
[O, Point(_size*radius_factor, 0)],
[sineio()],
)
translate_back_anim = Animation(
[0, 1], # must go from 0 to 1
[O, Point(-(_size*radius_factor), 0)],
[sineio()],
)
julia_colours = Dict(
:blue => "#4063D8",
:green => "#389826",
:purple => "#9558b2",
:red => "#CB3C33"
)
colour_order = [:red, :purple, :green, :blue]
n_colours = length(julia_colours)
function color_anim(start_colour::String, quarto_col::String="#4b95d0")
Animation(
[0, 1], # must go from 0 to 1
[Lab(color(start_colour)), Lab(color(quarto_col))],
[sineio()],
)
end
video = Video(_size, _size)
frame_starts = 1:10:40
n_total = 250
n_frames = 150
Background(1:n_total, ground)
# Blob:
function element(; radius = 1)
circle(O, radius, :fill) # The 4 is to make the circle not so small
end
# Cross:
function cross(color="black";orientation=:horizontal)
sethue(color)
setline(10)
if orientation==:horizontal
out = line(Point(-_size,0),Point(_size,0), :stroke)
else
out = line(Point(0,-_size),Point(0,_size), :stroke)
end
return out
end
for (i, frame_start) in enumerate(1:10:40)
# Julia circles:
blob = Object(frame_start:n_total, (args...;radius=1) -> element(;radius=radius))
act!(blob, Action(1:Int(round(n_frames*0.25)), change(:radius, 1 => 75))) # scale up
act!(blob, Action(n_frames:(n_frames+50), change(:radius, 75 => 250))) # scale up further
act!(blob, Action(1:30, translate_anim, translate()))
act!(blob, Action(31:120, rotate_anim(i, n_colours), rotate_around(Point(-(_size*radius_factor), 0))))
act!(blob, Action(121:150, translate_back_anim, translate()))
act!(blob, Action(1:150, color_anim(julia_colours[colour_order[i]]), sethue()))
# Quarto cross:
cross_h = Object((n_frames+50):n_total, (args...) -> cross(;orientation=:horizontal))
cross_v = Object((n_frames+50):n_total, (args...) -> cross(;orientation=:vertical))
end
render(
video;
pathname = joinpath(www_path, "julia_quarto.gif"),
)
Javis.jl
.
Scientific Ideas can often be most effectively communicated through dynamic visualizations.
using Plots
using StatsBase
steps = randn(1)
T = 100
anim = @animate for t in 2:T
append!(steps, randn(1))
random_walk = cumsum(steps)
p1 = plot(random_walk, color=1, label="", title="A Gaussian random walk ...", xlims=(0,T))
acf = autocor(random_walk)
p2 = bar(acf, color=1, label="", title="... is non-stationary", xlims=(0,10), ylims=(0,1))
plot(p1, p2, size=(800,300))
end
gif(anim, fps=5)
Quarto has fantastic support for traditional and modern scholarly writing.
. . .
Some people still prefer to read paper or work with MS Office. Most scientific journals, for example, still work with PDF and \(\LaTeX\).
. . .
Equations like Equation 1 (as well as Sections, Figures, Theorems, …) can be cross-referenced in a standardized way.
\[ \begin{aligned} Z &= \sum_{t=0}^T X_t, && X_t \sim N(\mu, \sigma) \end{aligned} \qquad(1)\]
Quarto allows us to cater to different requirements, while at the same time facilitating reproducibility by bridging the gap between computations and writing.
The world and the data that describes it is not static 📈. Why should scientific outputs be?
. . .
The code below depends on remote data that is continuously updated:
We’d like any updates to the inputs to automatically affect our output (ideally, all the way through to the finished report or paper).
Documenter.jl
and Quarto play nicely with each other (both Markdown based)..tex
file.To get started, see here.
startup.jl
If you install a new Julia binary […], you must update the IJulia installation […] by running
Pkg.build("IJulia")
— Source: IJulia docs
. . .
.ipynb
vs .qmd
.qmd
with ease..qmd
, code chunks connect to REPL.keep-ipynb: true
to have interactive notebooks in repo.These very slides are not only built using Quarto, but also hosted on a website that is also run on Quarto.
Organization — Quarto uses something call document listings: an easy way to collect, arrange and navigate content like this one.
Code Execution — You can specify YAML options such that changes to your underlying Julia code will trigger your blog post to be rerendered. This essentially allows you to easily test that the code you publish actually runs:
Reproducibility — The Julia version and environment can be managed globally or locally for individual blog posts:
Documenter.jl
and Quarto generally play nicely with each other (both Markdown based).jldoctest
is not always straight-forward (see here). Letting docs run through the Quarto engine provides an additional layer of quality assurance.| !!! note \"An optional title\"
| Here is something that you should pay attention to.
As an example, we will look at … 🥁
LaplaceRedux.jl
LaplaceRedux.jl
is a library written in pure Julia that can be used for effortless Bayesian Deep Learning trough Laplace Approximation (LA).
rticles
still has an edge here.As an example we will look at … 🥁
… my pending JuliaCon Proceedings submission for my 2022 talk: Explaining Black-Box Models through Counterfactuals
CounterfactualExplanations.jl
CounterfactualExplanations.jl
is a package for generating Counterfactual Explanations (CE) and Algorithmic Recourse (AR) for black-box algorithms. Both CE and AR are related tools for explainable artificial intelligence (XAI). While the package is written purely in Julia, it can be used to explain machine learning algorithms developed and trained in other popular programming languages like Python and R. See below for short introduction and other resources or dive straight into the docs.
LaplaceRedux.jl
JuliaCon 22: Effortless Bayesian Deep Learning through Laplace Redux
LaplaceRedux.jl
is a small package that can be used for effortless Bayesian Deep Learning and Logistic Regression trough Laplace Approximation. It is inspired by this Python library and its companion paper.
ConformalPrediction.jl
ConformalPrediction.jl
is a package for Uncertainty Quantification (UQ) through Conformal Prediction (CP) in Julia. It is designed to work with supervised models trained in MLJ (Blaom et al. 2020). Conformal Prediction is distribution-free, easy-to-understand, easy-to-use and model-agnostic.
Read on …
… or get involved! 🤗
CounterfactualExplanations.jl
ConformalPrediction.jl
A year of using Quarto with Julia — Patrick Altmeyer — CC BY-NC