CANU (CANvas UNIfier) is a lightweight C++17 header-only library utility for the ROOT framework that helps produce publicationโready, consistently formatted plots. It solves common issues in ROOT graphics related to canvas sizes, font scaling, axis formatting, margins, and legend placement.
Designed for highโenergy physics analysis and journal publication workflows (e.g. EPJC, PRC, NIM, etc.).
It will transform your paper into a polished, consistently professional piece of writing.:
| None-formatted output | CANU-formatted plots |
|---|---|
![]() |
![]() |
-
๐ Canvas sizing tools
Resize canvases to true physical sizes with consistent aspect ratio. -
๐ Font & axis formatting
Uniform font sizes in points, axis division/offset control. -
๐ Legend utilities
Automatic placement and sizing ofTLegendboxes. -
๐ Margins & layout helpers
Normalization of margins with reference to page width. -
๐งฐ Journal presets
Readyโtoโuse formatting for EPJC, NIM, PRC.
- ROOT (โฅ 6.x)
- C++17 compiler
CANU is headerโonly โ just include the header in your project:
#include "canu/canu.hpp"And compile with:
g++ my_analysis.cpp $(root-config --cflags --libs)or add to your cmake
find_package(canu REQUIRED)
target_link_libraries(project_exe PRIVATE canu::canu)There are builtโin presets for common publication formats:
auto canu = cu::make_epjc_paper();Resize a ROOT canvas
TCanvas c("c", "Plot", 800, 600);
hist->Draw();
canu.make_page_wide(&c);
c.SaveAs("figure.pdf");This resizes the canvas to page width, applies fonts and margins.
| Method | Description |
|---|---|
resize_canvas(can, w, h) |
Resize to arbitrary width/height |
make_page_wide(can) |
Resize to page width |
make_column_wide(can) |
Resize to standard column width |
| Method | Description |
|---|---|
set_max_digits(n) |
Maximum number of digits on axis |
set_ndivisions(n) |
Number of axis divisions |
set_title_offset(f) |
Title offset |
set_label_offset(f) |
Label offset |
| Method | Description |
|---|---|
place_legend(x, y, rows, cols, width) |
Creates a TLegend |
format_legend(can) |
Formats all legends in canvas |
Prepare macros to make page (_canu_2d_page.C):
#include "canu.hpp"
void _canu_2d_page(const char * macro_name)
{
gStyle->SetPalette(kBird);
auto canu = cu::make_nim_paper();
canu.set_details_scale(2);
gROOT->ProcessLine(Form(".x %s", macro_name));
canu.make_page_wide(gPad->GetCanvas());
canu.format_legend(gPad->GetCanvas());
TString fname = macro_name;
fname.ReplaceAll(".C", "");
gPad->SaveAs(Form("out/%s.pdf", basename(fname.Data())));
gPad->SaveAs(Form("out/%s.png", basename(fname.Data())));
gPad->SaveAs(Form("out/%s.C", basename(fname.Data())));
}and column-wide formatter (_canu_2d_column.C):
#include "canu.hpp"
void _canu_2d_column(const char * macro_name)
{
gStyle->SetPalette(kBird);
auto canu = cu::make_nim_paper();
canu.set_details_scale(2);
gROOT->ProcessLine(Form(".x %s", macro_name));
canu.make_column_wide(gPad->GetCanvas());
canu.format_legend(gPad->GetCanvas());
TString fname = macro_name;
fname.ReplaceAll(".C", "");
gPad->SaveAs(Form("out/%s.pdf", basename(fname.Data())));
gPad->SaveAs(Form("out/%s.png", basename(fname.Data())));
gPad->SaveAs(Form("out/%s.C", basename(fname.Data())));
}(these two differ by make_page_wide and make_column_wide only).
Prepare wrapper scripts: wrapper_canu_page.sh
#!/bin/bash
mkdir -p out
for f in $@; do
root -l _canu_2d_page.C\(\"$f\"\) -q -b
doneand wrapper_canu_column.sh
#!/bin/bash
mkdir -p out
for f in $@; do
root -l _canu_2d_column.C\(\"$f\"\) -q -b
doneNow, all your plots supposed for page-wide display format with:
./wrapper_canu_page.sh plot1.C plot2.Cand for column-wide plots:
./wrapper_canu_column.sh plot3.C plot4.CSee example/ directory for working examples. Use make or build_examples.sh. Example can be used as a base for your paper workflow.
void plot1() {
TH1F h("h","Example",100,-3,3);
h.FillRandom("gaus",10000);
TCanvas c("c","c",800,600);
h.Draw();
auto canu = cu::make_epjc_paper();
canu.make_column_wide(&c);
c.SaveAs("hist_column.pdf");
}void plot_overlay() {
TH1F h1("h1","Data",100,-5,5);
TH1F h2("h2","Model",100,-5,5);
h1.SetLineColor(kBlue);
h2.SetLineColor(kRed);
TCanvas c("c","Overlay",800,600);
h1.Draw();
h2.Draw("same");
auto canu = cu::make_prc_paper();
canu.x_prop().set_ndivisions(510);
canu.y_prop().set_ndivisions(505);
canu.make_page_wide(&c);
c.SaveAs("overlay_prc.pdf");
}- Batch mode window/canvas size inconsistencies
- Incorrect font scaling in points
- Inconsistent margins across different canvases
- Axis label offsets and legend sizing issues
auto epjc = cu::make_epjc_paper();
auto nim = cu::make_nim_paper();
auto prc = cu::make_prc_paper();To request other journals, create new issue or submit new Pull request. See example how to prepare new journal definition.
See the BUILDING document.
See the CONTRIBUTING document. Pull requests are welcome.
GPL-3.0 โ see LICENSE.

