# \[ANN\] MakieExtra.jl – more recipes and tools for Makie plots

**URL:** <https://discourse.julialang.org/t/ann-makieextra-jl-more-recipes-and-tools-for-makie-plots/118618>\
**Category:** Package Announcements\
**Tags:** makie\
**Created:** [August 26, 2024, 10:48am UTC](https://discourse.julialang.org/t/ann-makieextra-jl-more-recipes-and-tools-for-makie-plots/118618 "2024-08-26T10:48:53Z")\
**Posts on this page:** 6\
**Page:** 2

<div class="post-metadata">

**Author:** ![aplavin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/aplavin/32/222056_2.png) [@aplavin](https://discourse.julialang.org/u/aplavin)\
**Post date:** [October 27, 2024, 3:54pm UTC](https://discourse.julialang.org/t/ann-makieextra-jl-more-recipes-and-tools-for-makie-plots/118618/21 "2024-10-27T15:54:04Z")

</div>

> [@aplavin](#):
>
> - and one more, major and relatively self-contained feature – will post separately soon 🙂

The promised new feature is:

# `FPlot`: composable plotting specification

What started as a simple proof of concept in the `#makie` channel several months ago – now became the primary way I do plotting.  
I believe it is generally a nice way to do basically all kinds of plots, aside from images/volumes/similar stuff.

The design of most plotting libraries, including Makie, tends to take different properties of the plot (xy coordinates, color, size, …) as separate arrays. This is convenient for tiny self-contained snippets, hard to argue with the simplicity of `scatter(rand(100), rand(100))`. However, this approach feels suboptimal for anything even slightly more complicated.

It’s very common that one has a dataset – a collection of elements – and thinks of plotting in terms of these elements. Like, "for `r ∈ data`, plot `abs(r.value)` along the x axis, `angle(r.value)` along the y axis, and color them by `r.age`.  
`FPlot` is an object that encapsulates the whole plot definition – the dataset, xy mapping, and mappings for other attributes like color.

```julia-auto
FPlot(
	dataset,
	r->abs(r.value), r->angle(r.value); # what to plot on x and y axes 
	color=r->r.age, # mappings for any keyword arguments
)

```

As `FPlot` “knows” what is shown along axes, it can automatically set axis labels – `lines(FPlot(data, (@o _.a), (@o _.b)))` results in this:

 ![image](https://global.discourse-cdn.com/julialang/original/3X/b/f/bf08057b5f6dd8b9d6be5086010a5bff4ed051d9.png)  
It also naturally leads to reusing/modifying the same `FPlot` for multiple views into a dataset, and makes basic composable interactivity possible with a few lines of code:  

See a more detailed [overview and more examples](https://juliaaplavin.github.io/MakieExtraDocs.jl/notebooks/fplot.html) in the docs.

Try playing with `FPlot` to get a feeling how it works, I should say it becomes very natural quickly 🙂  
Suggestions for a better name are welcome!

---

<div class="post-metadata">

**Author:** ![tecosaur](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tecosaur/32/23206_2.png) [@tecosaur](https://discourse.julialang.org/u/tecosaur)\
**Post date:** [October 28, 2024, 6:45am UTC](https://discourse.julialang.org/t/ann-makieextra-jl-more-recipes-and-tools-for-makie-plots/118618/22 "2024-10-28T06:45:46Z")

</div>

> [@aplavin](#):
>
> more convenient rich text manipulation:

Just on this, I’ve been campaigning for use of `StyledStrings` for this, and I think I’ll continue to do so 😁.

Here’s an API I’d put to you all:

```julia-auto
# Current Makie
rich("a", subscript("x"), ": ", rich(a, font=:bold), ", b: ", rich(b, font=:italic))
# MakieExtra
"a" * subscript("x") * ": " * rich(a, font=:bold) * ", b: " * rich(b, font=:italic)
@rich "a$(subscript("x")): $(rich(a, font=:bold)), b: $(rich(b, font=:italic))"
# Proposed
styled"a{_:x}: {bold:$a}, b: {italic:$b}"

```

---

<div class="post-metadata">

**Author:** ![aplavin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/aplavin/32/222056_2.png) [@aplavin](https://discourse.julialang.org/u/aplavin)\
**Post date:** [October 28, 2024, 11:16am UTC](https://discourse.julialang.org/t/ann-makieextra-jl-more-recipes-and-tools-for-makie-plots/118618/23 "2024-10-28T11:16:43Z")

</div>

In general yes, would be nice to have a consistent interface for rich text to be used across different Julia packages.  
It’s just that in this thread, I only highlight already existing features, something that one could use right now. The implementation in MakieExtra is extremely simple, [just a few lines](https://github.com/JuliaAPlavin/MakieExtra.jl/blob/000000007dac9715520764e334380ae8ab26d598/src/MakieExtra.jl#L88-L96).  
AFAIK, StyledStrings cannot be currently used in Makie. Also, all those annotated strings are an experimental API that has a different behavior between Julia versions. That’s another difference from Makie rich text, something one should also be careful about…

---

<div class="post-metadata">

**Author:** ![tecosaur](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tecosaur/32/23206_2.png) [@tecosaur](https://discourse.julialang.org/u/tecosaur)\
**Post date:** [October 28, 2024, 1:11pm UTC](https://discourse.julialang.org/t/ann-makieextra-jl-more-recipes-and-tools-for-makie-plots/118618/24 "2024-10-28T13:11:24Z")

</div>

> [@aplavin](#):
>
> AFAIK, StyledStrings cannot be currently used in Makie

I think it would be worth waiting till I can put together another compat release to reflect a few of the changes that slipped into 1.11 last-minute, but I don’t see any hard reason why not: the compat/1.11 differences don’t affect what I think Makie would need to use

Anyway, as you say — not something you can do anything about, but I’m excited about where this can lead and I like to take opportunities to share that with other people 🙂

---

<div class="post-metadata">

**Author:** ![aplavin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/aplavin/32/222056_2.png) [@aplavin](https://discourse.julialang.org/u/aplavin)\
**Post date:** [December 9, 2025, 4:41am UTC](https://discourse.julialang.org/t/ann-makieextra-jl-more-recipes-and-tools-for-makie-plots/118618/25 "2025-12-09T04:41:30Z")

</div>

More than a year has passed since my last post here – and MakieExtra.jl got quite a bit of updates over that time 🙂  
Most are quite self-contained – some examples (not a complete list):

- `zoomlines` is more flexible and take arbitrary attributes to pass to lines and rects it draws;
- `mouse_position_obs()` gets the mouse position as observable
- `@lift ...::T` to manually specify the type of the resulting Observable (useful if the value type changes)
- `rel2data()` / `data2rel()` to plot at “x=5, y=bottom of axis” or “x = 5 + 1/10 of the axis width”
- automatic split of lines/polygons for `GeoAxis` – to avoid artifacts when crossing the map seam

Some MakieExtra features have even been upstreamed to Makie proper: stuff like `textwithbox` (Makie got `textlabel`) or rich strings concatenation.

But I would also like to highlight more major features here once in a while \<see the next post…\>

---

<div class="post-metadata">

**Author:** ![aplavin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/aplavin/32/222056_2.png) [@aplavin](https://discourse.julialang.org/u/aplavin)\
**Post date:** [December 9, 2025, 4:41am UTC](https://discourse.julialang.org/t/ann-makieextra-jl-more-recipes-and-tools-for-makie-plots/118618/26 "2025-12-09T04:41:53Z")

</div>

Today, it’s time to highlight…

# `InteractivePoints()`: the easiest way to make your plot data directly editable!

Very few changes needed to turn a static plot into an interactive one – this is the full diff:

 ![image](https://global.discourse-cdn.com/julialang/original/3X/f/e/fe826bcac9bf41f35be82aa01d267020e6e92d09.jpeg)

With that, you can move each point with your mouse, add/remove points to the plot. All interactions are built on `Observable`s, and arbitrary calculations can run on update of `data`.  
For example, here we use Interpolations.jl to create a continuous functions from user-drawn points, which can be used in downstream computations:

> **Full code**
>
> ```julia-auto
> # set up calculations first – nothing specific to InteractivePoints here:
> data = Observable([(0.2, 1.), (0.5, 0.5)])
> func = @lift @p let
> $data
> sort(by=first)
> linear_interpolation(first.(__), last.(__), extrapolation_bc=Linear())
> end
> 
> # now create and fill the figure:
> fig = Figure()
> 
> axplot(scatter; widgets=[InteractivePoints(data)])(
> fig[1,1], (@lift FPlot($data, first, last)), label="Points")
> lines!((@lift x->$func(x)); label="Linear", yautolimits=false)
> axislegend()
> 
> ```

A neat demo with `Complex` math, showcasing two interactive `Axes` connected to the same dataset with different functions assigned to their x/y axes:

> **Full code**
>
> ```julia-auto
> # definitions and calculations - generic, not specific to InteractivePoints
> # - define data:
> data = Observable([
> (z=0. +0im, pow=1.),
> (z=1. -3im, pow=2.),
> (z=-2. -3im, pow=1.5),
> ])
> # - define function: sum of 1/(z - r.z)^r.pow over data
> f = @lift z -> sum(r -> 1 / (z - r.z)^r.pow, $data)
> # - compute the function on a grid for plotting
> reimvals = range(0±5, length=500)
> f_plane = @lift map($f, grid(Complex, reimvals, reimvals))
> 
> # now create and fill the figure
> fig = Figure()
> 
> # first axis: show real(z) and imag(z) with interactivity
> axplot(scatter; widgets=[InteractivePoints(data)])(fig[1,1],
> (@lift FPlot($data,
> AxFunc(limit=0±5, @o real(_.z)),
> AxFunc(limit=0±5, @o imag(_.z)))),
> axis=(;height=200))
> 
> # second axis: show abs(z) and pow with interactivity
> axplot(scatter; widgets=[InteractivePoints(data)])(fig[1,2],
> (@lift FPlot($data,
> AxFunc(limit=0..5, @o abs(_.z)),
> AxFunc(limit=-1..3, @o _.pow))),
> axis=(;height=200))
> 
> # final axis: display the surface-plot of the function
> surface(fig[2,:],
> (@lift abs.($f_plane)),
> color=(@lift angle.($f_plane)),
> colormap=:cyclic_mrybm_35_75_c68_n256, interpolate=false,
> axis=(;zlabel="|f(z)|", type=Axis3, viewmode=:free, height=500, limits=(nothing, nothing, 0..20)))
> 
> resize_to_layout!()
> 
> ```

* * *

Check out the code for these examples – it’s really just a few lines of code to get interactivity, no boilerplate!  
More details are available in [the docs](https://juliaaplavin.github.io/MakieExtraDocs.jl/notebooks/interactivepoints.html).

Also, please let me know if you’ve seen even more straightforward interactive plots in other ecosystems – happy to draw inspiration for the best interface from elsewhere 🙂

[Previous page](https://discourse.julialang.org/t/ann-makieextra-jl-more-recipes-and-tools-for-makie-plots/118618.md?page=1)
