CairoMakie Text Box

Hello,

I could use some advice on how to achieve the following.

I am generating a large number of simulation results and I’d like to put somewhere on the plot the parameters for each run. These do not need to be publication ready plots, they are just intended to help me drill down and compare the results of many runs.

For each run I will have some predefined parameters that I can access from the results struct. I’d like to create a textbox somewhere on the plot and include a multiline string that I can pass to Printf for formatting. But I am having two problems. The MWE is below.

The first issue is that this code errors and says ERROR: syntax: invalid assignment location ""Param 1 = %d. I’m open to suggestions for how to achieve a multi-line string with each parameter on a new line and my desired formatting applied.

The second issue is I don’t know how to add a bounding box around the textbox. Ideally I’d like it to be outlined with a black line and then give it a white background color with some opacity (say 0.5).

Does that make sense? Does anyone have any experience with this? Or possibly some advice on how to achieve the desired outcome (perhaps a smarter way to do it?).

using CairoMakie, Printf

begin
    # these will be coming from some results struct like
    # (; param1, param2, param3) = my_run_result
    param1 = 1
    param2 = "param"
    param3 = 0.5

    x = LinRange(-1, 1, 100)
    y = x .^ 3

    fig, ax, ln = lines(x, y, label="Plot 1")
    axislegend(position=:lt)
    fmt = "Param 1 = %d \n Param 2 = %s \n Param 3 = %.2e",
    t = text!(
        -0.5, 0.5;
        text=Printf.format(Printf.Format(fmt), param1, param2, param3),
        align=(:center, :center),
        justification=:center
    )
    fig
end

ERROR: syntax: invalid assignment location ""Param 1 = %d

This is caused by an undesired , at the end of the fmt definition:

fmt = "Param 1 = %d \n Param 2 = %s \n Param 3 = %.2e", # <--- remove comma 

And here is one way (probably not the most optimal one though) to get a box with outline and color into the plot

using CairoMakie, Printf

begin
    # these will be coming from some results struct like
    # (; param1, param2, param3) = my_run_result
    param1 = 1
    param2 = "param"
    param3 = 0.5

    x = LinRange(-1, 1, 100)
    y = x .^ 3

    fig, ax, ln = lines(x, y, label="Plot 1")
    axislegend(position=:lt)
    fmt = "Param 1 = %d \n Param 2 = %s \n Param 3 = %.2e"
    gl = GridLayout(fig[1,1],
                    tellwidth = false, tellheight = false,
                    halign = :center, valign = :top)
    box = Box(gl[1, 1], color = (:orange,0.5), strokecolor = :black)
    lbl = Label(gl[1, 1], Printf.format(Printf.Format(fmt), param1, param2, param3), padding = (10, 10, 20, 20))
    # optionally: bring box and label in front of axis ticks
    # translate!(box.blockscene, (0,0,100))
    # translate!(lbl.blockscene, (0,0,100))

    fig
end

1 Like

Awesome - thank you. Let me make sure I can understand what you did here.

You created a figure. Then you put a 1x1 grid on top of the figure. Then you made an empty box using Box and put that inside the 1x1 gird. Then you put a label in the 1x1 grid.

I guess the 1x1 grid automatically resizes to the size of the label inside? Or is that what the tellwidth and tellheight do?

The inner grid’s size is that of its own columns and rows. Those are determined to be that of the Label. But you don’t want the main grid layout to shrink to that as well, so the inner layout gets tellwidth and tellheight false so the auto-sizing stops there.

This workaround uses the auto-sizing logic that has already been implemented for Label, this way one can kind of “abuse” the layout mechanism to draw the box around it :slight_smile: At some point we should probably add a recipe that does this.

1 Like

I see. Thank you. Is there any way to easily move the box to a different position on the plot. Say centered at (-0.5, 0.5)? I didn’t see a position attribute listed here.

via the halign and valign of the inner grid layout

1 Like

Thank you :slight_smile: