In the Lab, a FlowScript document is a typed model of your study: its cohorts, arms, estimates, judgements and observations. A view is one way of drawing that model. You declare a view with a single line, such as view survival: km(os), and the Lab draws it with a renderer, a built-in figure type such as a Kaplan–Meier plot, a forest plot or a CONSORT flow. One document can carry many views of the same data, so a forest plot and its funnel plot can never be drawn from two different copies of the numbers. This page explains how views work, how to add and switch between them, how to use the Figures bench (the views gallery), and gives a reference entry for every one of the Lab's 36 renderers: what it is built from, the argument it takes, the options it reads, what it computes for you, what it refuses to draw, and the messages it shows when something is missing.
At a glance
| Topic | What you need to know |
|---|---|
| Declaring a view | view <name>: <renderer> or view <name>: <renderer>(<argument>, …) on a line of its own |
| Renderers available | 36, listed in the renderer reference below. Many also answer to one or more aliases |
| Adding a view without typing | The rail's Insert a block or view flyout (section Add view), or a worked example from the Figures bench |
| Seeing every figure with a working example | Rail: Figures, or ⌘K and type "Figures" |
| Switching views | One view is simply drawn. Two or three views appear as a toggle labelled Views in this document. Four or more appear as View rows in the zoom menu. ⌘K lists every view by name |
| Computed, never typed | The research figures compute their statistics (survival steps, AUC, pooled effects, τ², I², certainty, absolute risks) from your data. A number you type for the same statistic is checked against the computed one, never printed instead of it |
| When a figure cannot be drawn | The renderer draws an explanatory message instead of a figure, naming the block it needs. See Messages you may see |
| Example data | Starters that carry the "EXAMPLE text from a fictional …" notice are stamped Example data — not real on the canvas and on every export until you delete that notice |
| Plans and AI | Views, the gallery and every renderer work without AI and without a network call. Your plan's access to the Lab is described in Lab and Plans and what they include |
On Windows and Linux, read ⌘ as Ctrl and ⇧ as Shift.
How a view works
The declaration
A view is a one-line declaration in your FlowScript source:
view flow: consort(trial)
view survival: km(os)
view timeline: gantt
The parts are:
| Part | Meaning |
|---|---|
view | The keyword |
flow | The view's name. It is what the view toggle, the zoom menu, ⌘K, share links and multi-panel figures use to refer to this view |
consort | The renderer: the figure type to draw. A canonical id or any of its aliases |
(trial) | Optional arguments. Most renderers take one, naming the block to draw (km(os) draws the survival block called os). A few take something else, such as an instrument name for the risk-of-bias figures. Arguments may be identifiers, quoted strings or numbers, separated by commas |
A document can declare as many views as you like. Each one is drawn from the same model, so every view of a document always agrees with every other.
Names, anonymous views and duplicates
- A view without a name, such as
view : consort(trial), still draws, but it is listed asuntitledand nothing can address it. The checker warns: "Thisviewhas no name, so it is listed asuntitledand nothing can address it — not the remembered tab, not a share link, not apanelchild." and suggests an id. Give it a name. - Several unnamed views are listed as
untitled,untitled-2,untitled-3and so on. - A view name is a block id, so two views with the same name are a "Duplicate id" error, exactly like two blocks with the same id. Rename one of them.
- The Lab remembers which view you were looking at, per document, and reopens it there.
Renderer names and aliases
Every renderer has one canonical id and may have aliases. view v: kaplan_meier(os) and view v: km(os) draw the same figure. If two names could collide, the canonical id always wins, so an alias can never silently redirect an existing view.
Two collisions are worth knowing:
funnelis the business conversion funnel. The meta-analysis funnel plot isfunnel_plot(aliasessmall_study,publication_bias).timelineis an alias of the clinical case timeline (clinical_timeline). The project timeline isgantt(aliasroadmap).
What the checker tells you about views
The Lab's FlowScript checker validates view lines as you type:
| Situation | Severity | What you see |
|---|---|---|
| The renderer name is not one the Lab knows | Error | "View v names renderer x, which no renderer answers to — it would render as a placeholder reading "No view renderer named x" rather than fail." followed by "Did you mean …?" when a known name is within two edits, or otherwise by the first ten known renderer names and the total count |
| Two views share a name | Error | "Duplicate id … — every block id must be unique." |
| An argument names no block in the document | Warning | "View v passes arg to renderer, but no block with that id is declared — the view would draw an empty figure rather than say so." with a suggestion when one is close |
| The view has no name | Warning | The untitled message above |
Numeric arguments are never reported, and the risk-of-bias figures (rob_traffic_light, rob_summary_bar and their aliases) are exempt from the argument check because their argument is an instrument name, not a block id.
Illustrative values are drawn on every view
A FlowScript note is normally a private remark that no view draws. There is one exception: a note whose text contains the words "Illustrative values" or "(illustrative)" is drawn in a band below every view of the document. The figure's declared width never changes; the drawing grows downwards to make room. This is how a disclosure that some values were made up stays attached to the figure, whichever view a reader sees.
note disclosure { text: "Illustrative values: the counts below are invented for teaching." }
Example data stamp
The Lab's reporting-standard starters, and the Lab templates built on fictional data, open with a comment such as "Every string below is EXAMPLE text from a fictional trial: replace it." While that notice is in your source:
- the canvas shows an amber note, Example data — not real. "This starter uses values from a fictional study — replace them with yours, then delete its "EXAMPLE text" notice to remove this mark from the figure and its exports." Click Got it to fold it to a small Example data chip; click the chip to open it again;
- every view is drawn with a faint diagonal "EXAMPLE DATA" watermark and an amber Example data — not real label in the bottom-right corner;
- the stamp travels with every export that comes from the canvas: SVG, PNG, print-size PNG, Copy image to clipboard, Export all views (ZIP) and the submission bundle.
To remove it, replace the example values with your own and then delete the notice line. The stamp is triggered by the words "EXAMPLE text from a fictional" (with upper-case EXAMPLE; "from fictional trials" counts too) anywhere in the source, so make sure no other line still contains them. The stamp disappears at the next redraw. The worked examples in the Figures bench do not carry that notice, so they are not stamped: treat every value in them as made up. See Core concepts and glossary for the marker across all studios.
Adding a view
There are four ways to add a view.
1. From the Insert flyout
- Click Insert a block or view on the Lab's tool rail (or run Insert block… from ⌘K).
- Type in the search field to filter, or scroll to the section headed Add view. Each row shows the renderer id and the engine's one-line description. The search matches the id, the renderer's domain and its description.
- Click a renderer. The Lab appends
view <id>: <id>to your document, using the renderer id as the view's name (km, thenkm2,km3if the name is taken), switches the canvas to it, and confirms with a toast such as "Added view 'km'".
A view added this way has no argument. Renderers that take one fall back to the first matching block in the document, which is what you want when there is only one. Add the argument by hand when you have several.
2. From a worked example on the Figures bench
The Figures bench shows every renderer with a complete, minimal document that compiles and draws. Use it when your document does not yet have the blocks a figure is built from. See The Figures bench below.
3. By typing
Open the Source shelf (rail Source, or ⌘\ to toggle the code pane) and type the line. After you type view <name>:, autocomplete suggests renderer names.
4. From the Advisor
The Lab's Advisor pane reads your document and your field of work and may propose a figure. Depending on what your document already has, the proposal either adds the view directly (when every block it needs is present) or opens the Figures bench on that renderer's card, for example "Nothing is drawn yet — add the Kaplan–Meier survival curves" or "Learn the Forest plot". See Lab.
Switching between views
| How many views the document declares | Where they appear |
|---|---|
| None | The canvas shows Add a view to draw it ("A view is how this document becomes a figure."), with Add a view (opens the Insert flyout) and Browse templates |
| One | It is drawn. There is nothing to switch |
| Two or three | A segmented toggle labelled Views in this document on the view island, one segment per view name |
| Four or more | View rows in the zoom menu, each showing the view name and its renderer, with the current one checked |
| Two or more, on a phone | View rows under ⋮ ▸ Zoom |
Every view also appears in ⌘K under Go to, labelled with the view's name, badged with its renderer and described as, for example, "Draw the km view of this document".
The Lab keeps drawing while your document has errors: the blocks that parsed are drawn as a best-effort figure, and the errors are listed in the Validation section of the document status popover (⇧⌘M). Only when the document has errors and there is nothing to draw does the canvas show Fix N errors to render ("The figure draws as soon as the source checks.") with Go to the first error. If a view's renderer fails while drawing, the canvas shows a notice such as "The "survival" view couldn't be drawn", the renderer's message, and: "Your source is fine — it parsed and validated, and only the drawing failed. Switch to another view, or undo the last change to this one; the rest of the studio keeps working."
To export one view or all of them, use the ⋮ menu's Export submenu: Export SVG, Export PNG (2×) (⌘⇧P), Export PNG (4×, print), Export PNG at print size (300 dpi), Export all views (ZIP) and Copy image to clipboard. Journal sizing, preflight and LaTeX are covered in Publishing, provenance and compliance in Lab and Exporting your work.
The Figures bench (views gallery)
The Figures bench is the complete answer to "what can the Lab draw?". It lists every renderer the Lab registers, each as a card with a researcher's description, the blocks it is built from, what a list of blocks cannot say, and a worked example that compiles clean and draws the figure. The worked examples are checked against the real engine renderer by renderer, so pasting one never teaches you a broken shape.
Opening it
- Click Figures on the Lab's tool rail. Click it again to close the workbench sheet.
- Press ⌘K and choose Figures under Go to ("The gallery of view renderers, each with a scaffold you can start from").
- Click an Advisor proposal that offers a figure. The bench opens with that figure's card expanded and scrolled into view, and clears any search or filter that would hide it.
The bench shares the workbench sheet with Source, Data, Statistics and Standards. On a narrow sheet, the shelves you are not using fold to icons.
Controls
| Control | What it does |
|---|---|
| Search field (placeholder "survival, funnel, risk of bias…") | Filters the cards. Every word you type must match (words are combined with AND), each as a case-insensitive substring. It searches the renderer id, every alias, the title, the purpose and the field labels. It does not search the worked examples or the note under Built from, so typing "2019" does not find the forest plot just because one example study is called "Ahmed 2019". An empty search shows every figure |
| Every field chip | Shows all fields. Selected by default |
| One chip per field of work | Shows only figures tagged with that field. Hover a chip to read the field's description; once selected, the description is shown in italics above the list |
| Count line | "N of 36 figures", counting distinct figures on screen (a figure tagged with two fields is counted once), with the note "every card carries a working example" |
Cards are grouped under field headings, in the order of the table below. A figure that serves two fields, such as roc, appears under both. If nothing matches, the bench says: "No figure matches those words in this field. Try one term at a time, or widen the filter to every field."
The fields of work
| Field chip | Description shown | Figures |
|---|---|---|
| Clinical trials | Prospective interventional studies: allocation, follow-up and a pre-specified outcome. | consort, km, table_one, spirit_schedule, intervention_table |
| Epidemiology | Observational cohorts and case-control studies, where the comparison was found rather than made. | km, table_one |
| Clinical case reports | One patient or a small series: what happened, in what order, and what came of it. | clinical_timeline |
| Evidence synthesis | Systematic reviews, meta-analysis, risk of bias and certainty of evidence. | prisma, forest, funnel_plot, rob_traffic_light, rob_summary_bar, grade_sof, appraisal_table |
| Diagnostics and prediction | Does the test discriminate, is the model calibrated, and is acting on it worth it? | roc, calibration, decision_curve |
| Health economics | Costs, effects and the trade-off between them. | ce_plane, decision_curve |
| Statistics | Distributions, estimates and intervals, drawn from the observations rather than from summaries. | forest, raincloud, panel, control_chart |
| Machine-learning evaluation | Benchmarks, ablations and the discrimination and calibration of a learned model. | ablation_table, roc, calibration |
| Laboratory science | Bench experiments: samples, conditions, replicates and readouts. | experiment_flow, raincloud |
| Survey research | Instruments, constructs and the items that are supposed to measure them. | item_map |
| Qualitative research | Interviews and focus groups: the themes found, the quotations that ground them, and whose voices they are. | theme_map |
| Reliability engineering | Failure modes, their consequences, and what detection is worth. | fmea_table |
| Operations and supply | Networks of suppliers, plants and customers, with lead time and cost on the arrows. | supply_map |
| Quality improvement | Iterative change in a service, judged against its own baseline over time rather than by one before-and-after. | control_chart, intervention_table |
| Project delivery | Plans with dates on them, and the dependencies that decide whether the dates hold. | gantt |
| Software architecture | Systems, the containers they are made of, and what talks to what. | c4_container |
| Business strategy | Objectives, the measures behind them, and where a funnel leaks. | funnel, okr_grid |
| Finance | Ownership, dilution and the arithmetic of a round. | captable |
| Security | Threats against assets, and how much of each one a control actually covers. | risk_matrix |
| Education and assessment | Criteria, performance levels and the descriptors that keep marking consistent. | rubric_grid |
| Law and contracts | Who owes what to whom, and by when. | clause_map |
| Scientific illustration | Schematics, scenes and composed multi-panel figures, where the structure is the claim. | figure, scene, panel |
A further field, Not yet filed, exists for any renderer that has no gallery card yet. Every renderer has a card today, so its chip does not appear.
What a card shows
Collapsed, a card shows the figure's title, its renderer id, a one-sentence purpose, and an in this document badge when your open document already declares a view with that renderer (under any alias). Click the card to expand it:
| Part | What it tells you |
|---|---|
| Built from | The block kinds the figure is made of. Write these and you get the figure; write fewer and you get a shell or an explanatory message. This is the combination known to work, not always the only one: several figures accept a substitute, which the note below names |
| Note | What a list of blocks cannot say: how many of a block you need, which values are dropped silently, which values default to a number you did not state, and what the figure refuses |
| The engine calls it: | The renderer's own one-line description, verbatim |
| Also accepted: | Every alias the renderer answers to |
| Worked example | A complete, minimal FlowScript document: the required blocks plus the view line |
| Start a new document from this example | Loads the worked example (see below) |
Starting from a worked example
A worked example is a whole small document: several blocks, the references between them, and a view line. It is never appended to your document, because adding it to a document that already uses the same block names would create duplicate ids and break every from: reference in the example. So:
- Expand the card and read the example.
- Click Start a new document from this example.
- The example replaces the content of the open document straight away. A toast reads "Template loaded —" followed by the renderer id (for example "Template loaded — km"), with an Undo button. There is no separate confirmation dialog (even though the small print under the button says the studio confirms first); the Undo in the toast, or
⌘Z, brings your document back. - If your document had data rows bound from the Data bench, they are released, because they described the study that was there before. The Data bench says: "The rows bound to this document were released when the template replaced it — they described the study that was here before. Load the file again to switch the column checks back on."
If the open document already holds exactly that example, clicking the button does nothing.
Tip: To keep your current work and try an example, create a new document first (⌘K New document, or the document switcher), then start it from the example.
Renderer reference
The table lists all 36 renderers in the order the Lab registers them. The sections that follow describe each one in detail.
| Renderer | Figure | Also accepted | Built from | Argument |
|---|---|---|---|---|
consort | CONSORT participant flow | none | cohort | A study id |
prisma | PRISMA screening flow | none | cohort | None |
gantt | Gantt timeline | roadmap | project, task | None |
c4_container | C4 container diagram | c4, container | system, service | None |
funnel | Conversion funnel | none | funnel_step | The first step's id |
okr_grid | Objectives and KPI grid | okr | kpi | None |
experiment_flow | Experiment design flow | experiment | experiment, condition | None |
ablation_table | Ablation table | ablation | model, dataset, eval, ablation | None |
figure | Free-form schematic | schematic | figure | None |
scene | Isometric 3-D scene | scene3d, isometric | scene, box3d | None |
captable | Capitalisation table | cap_table, captable_waterfall | shareholder | None |
risk_matrix | Risk matrix | stride, threat_matrix | threat | None |
ce_plane | Cost-effectiveness plane | icer, cost_effectiveness | intervention (two or more) | An econ_model id |
item_map | Instrument item map | instrument_map, survey_map | item | None |
fmea_table | FMEA risk-priority table | fmea, rpn_table | failure_mode | None |
supply_map | Supply-chain map | supply_chain, supply_network | sc_node | None |
rubric_grid | Assessment rubric grid | rubric, criteria_grid | criterion | None |
clause_map | Contract clause map | agreement_map, contract_map | clause | None |
km | Kaplan–Meier survival curves | kaplan_meier, survival | survival, group | A survival id |
roc | ROC curve | auc, pr_curve | roc, series | A roc id |
calibration | Calibration plot | calibration_plot, reliability_diagram | calibration, series | A calibration id |
decision_curve | Decision curve (net benefit) | dca, net_benefit | decision_curve, series | A decision_curve id |
forest | Forest plot | forest_plot | meta, estimate | A meta id |
funnel_plot | Funnel plot (small-study effects) | small_study, publication_bias | meta, estimate | A meta id |
rob_traffic_light | Risk-of-bias traffic light | rob, robvis, risk_of_bias | study, bias_domain, bias_assessment | An instrument name |
rob_summary_bar | Risk-of-bias summary bar | rob_summary | study, bias_domain, bias_assessment | An instrument name |
grade_sof | GRADE Summary of Findings | sof, summary_of_findings | outcome, estimate, grade_outcome, sof_row | A sof_row id |
raincloud | Raincloud plot | distribution, violin | distribution, group | A distribution id |
table_one | Table 1 — baseline characteristics | baseline, characteristics | table_one, group, distribution | A table_one id |
panel | Multi-panel figure | multi_panel, figure_panel | view, panel | The container panel id |
clinical_timeline | Clinical case timeline | timeline, case_timeline | timeline, timeline_event | A timeline or case_report id |
theme_map | Thematic map with quotations | themes, qualitative_themes, coreq | theme, quotation | A theme, study or qual_study id |
spirit_schedule | SPIRIT schedule of assessments | spirit, schedule_of_assessments, soa | spirit_schedule, spirit_row | A spirit_schedule id |
control_chart | Run or control chart | spc, run_chart, shewhart | control_chart, series | A control_chart or series id |
intervention_table | TIDieR intervention description | tidier, tidier_table, intervention_description | tidier_intervention | study, tidier_intervention or arm ids |
appraisal_table | Critical-appraisal table (AMSTAR 2) | amstar, appraisal, checklist_table | appraisal, amstar_item | An appraisal or study id, a block kind, or amstar2 |
Where a renderer takes an argument and you leave it out, it draws the first matching block in the document. Where an argument names nothing the renderer can use, the reporting-standard figures (ce_plane, theme_map, spirit_schedule, intervention_table, appraisal_table and similar) say so in a footnote and draw what they can, while the statistical figures (such as km, raincloud, table_one and grade_sof) draw a message naming the block they could not find.
A rule shared by the research figures
The renderers from km onwards, plus ce_plane and the reporting-standard figures, follow one rule: every statistic on the figure is computed from the data in your document. Attributes such as auc:, p_logrank:, median:, i2:, tau2:, egger_p:, slope:, certainty:, risk_difference: or mean: exist so you can transcribe a published result, but they are never printed in place of the computed value. When what you typed disagrees with what your data give, the figure prints the computed value and says so in a footnote. Colour is never the only channel: groups, judgements and phases also carry a symbol, a shape, a dash pattern or a word, so the figures survive greyscale printing and colour-vision deficiency.
Trial and review flow renderers
consort — CONSORT participant flow
Shows where every screened participant went (excluded, randomised, allocated, analysed) so a reader can check the trial's arithmetic before reading its result.
- Built from: a chain of
cohortblocks linked byfrom:. The root is the cohort with nofrom:. Each drop is accounted for inexcluded: { reason: count, … }.study,armandoutcomeare optional. - Argument: the
studyid, as inconsort(trial). - How it draws: a vertical spine of cohort boxes with exclusion call-outs on the right (each reason with its count), and a row of
armboxes branching off the cohort each arm names infrom:(an arm with nofrom:hangs off the last cohort). Each arm box shows itsintervention:text beside its name. Anyoutcomeblocks are summarised in a small results table underneath (events and n percontrolandtreatment, the test and p). The validator checks the arithmetic, so a box whose numbers do not add up is flagged in your source. A cohort with no usablenis drawn as "n = —", never as 0. A number carrying an inline source (n: 420 source "Table 1") gets a small citation marker. An arrow is drawn only where you declaredfrom:; two independent streams are drawn with a visible break rather than an invented arrow. A cohort reached twice, or a cycle offrom:references, is drawn once. - Header: with a
studyblock (the one named in the argument, or the first), the header is the study's id written as words, with itsdesign:in capitals underneath. With nostudyblock, the header is thetitle:of the document's first block with that block's kind underneath, or no header at all if the first block has no title. Nothing in this renderer prints the words CONSORT or PRISMA on its own. - Editing on the canvas:
nvalues, box headings (when the cohort has alabel:) and arm intervention text are click-to-edit; a corrected number is re-checked on the next compile. - Message: "Add a
cohortblock — e.g.cohort screened { n: 1500 }"
study trial {
title: "Early mobilisation after hip fracture"
design: "Randomised parallel-group trial"
}
cohort screened { n: 420 }
cohort randomised {
n: 300
from: screened
excluded: { ineligible: 88, declined: 32 }
}
arm mobilisation { n: 150 from: randomised intervention: "Early mobilisation" }
arm usual_care { n: 150 from: randomised intervention: "Usual care" }
view flow: consort(trial)
prisma — PRISMA screening flow
Shows how a database search became an included set, with a reason and a count for every record dropped.
- Built from: the same
cohortchain asconsort(identified,screened,full_text,included, each withfrom:andexcluded:). - Important:
prismauses exactly the same drawing code asconsort; choosing theprismaid does not change the output. A review normally declares nostudyblock (in a review document astudyis an included study), so the header comes from the title of the document's first block, as described underconsort. The gallery card's note says the header reads PRISMA when there is nostudyblock; the figure no longer prints that word itself, so name the review in the first block'stitle:. - Message: the same as
consort.
Clinical, epidemiology and protocol renderers
km — Kaplan–Meier survival curves
Shows time to event by arm, with censoring marked and the numbers at risk underneath, computed from per-subject follow-up rather than a typed median.
- Built from: a
survivalblock with one nestedgroupper arm. Eachgroupcarriestimes:(one follow-up time per subject) and a matching 0/1events:list, plus an optionallabel:. - Life-table form: to digitise a published figure, add
at_risk:to a group;times:then lists the distinct times andevents:andcensored:are counts. The life table goes through the same estimator, and a table whose at-risk column does not reconcile with its own counts is refused. - Argument: the
survivalid, as inkm(os). Use it when a document has several survival blocks. - Options on the
survivalblock:
| Attribute | Effect |
|---|---|
time_unit: | Label for the time axis, such as "months" |
level: | Confidence level as a fraction, such as 0.95 (the default). Never write 95 |
cumulative: true | Draw cumulative incidence (1 − survival) instead of survival |
risk_table: false | Suppress the numbers-at-risk row. The figure's footnote states that it was suppressed |
censor_marks: false | Suppress the censoring ticks. Also stated in the footnote |
confidence_band: | true or false. By default the band is on for a single curve and off when comparing arms |
- Computes: the product-limit curves, log–log confidence bands, numbers at risk, medians with their intervals, and the log-rank χ² and p. A typed
p_logrank:that disagrees is reported in a footnote. Each arm gets a colour and a dash pattern; colours too pale to read against the background are adjusted, and the footnote says which. - Refuses: a curve with no events (it would assert 100% survival);
competing_risks: true(1 − Kaplan–Meier overstates risk when competing events exist); a log-rank p for a single arm (the annotation explains why); a hazard ratio (put one in anestimateoreffectblock with its model stated); more arms than the palette can tell apart. - Messages: "Add a
survivalblock with onegroupper arm …", "Nosurvivalblock with id "x". …", "ghas no subjects. Remove the group, or give ittimes.", "Zero subjects. …", "No events in N subject(s) — every follow-up ended without the outcome, …", and thecompeting_risksrefusal.
survival os {
title: "Overall survival by arm"
time_unit: "months"
group treated {
label: "Treated"
times: [4, 7, 9, 12, 12, 15, 18, 20, 24, 24]
events: [1, 0, 1, 1, 0, 1, 0, 1, 0, 0]
}
group control {
label: "Usual care"
times: [2, 3, 5, 6, 8, 9, 11, 14, 16, 20]
events: [1, 1, 1, 0, 1, 1, 1, 0, 1, 0]
}
}
view survival: km(os)
table_one — Table 1, baseline characteristics
Describes the groups before anything was done to them, with the summary each variable's shape calls for.
- Built from: a
table_oneblock. Agroupdirectly inside it is a column (label:,n:). Adistributioninside it is a row; agroupinside thatdistributionis the row's cell, names its column withfrom:and carries the rawvalues:. A categorical row usesseriesblocks (withgroup:,labels:and counts invalues:). Nesting decides meaning, so check it carefully. - Argument: the
table_oneid. - Options on the
table_oneblock:
| Attribute | Effect |
|---|---|
digits: | Decimal places, a whole number from 0 to 6 (1 by default). A distribution row can set its own digits: (0 to 6), which overrides the table's for that row; the footnote names each row that does |
p_values: true | Add a p-value column. Honoured for any design. When the document describes a randomised design, the figure also prints an objection above the table and adds the standardised mean difference |
overall: true | Add a Total column |
smd: true | Add the standardised mean difference (two columns only) |
continuous_summary: | Table-wide summary for continuous rows: mean_sd, median_iqr, median_range, mean_ci or geometric_mean |
categorical_summary: | Table-wide summary for categorical rows: n_percent, percent or n |
A row may declare its own summary: with the same words, which pre-specifies both the display and the test.
- Computes: each summary from the observations (mean (SD) for symmetric data, median [IQR] for skewed data, n (%) for categorical), and says which rule chose it; missingness per cell as the column's denominator minus the observations present (never a typed
missing:; when a column declares non, the most complete row is used and a footnote says the denominator was inferred); tests for categorical rows by chi-squared, switching to Fisher's exact test for a 2×2 row with a small expected count; and adjusts the family of p-values for multiple comparisons by Holm's method. A row whose observations are all 0 or 1 is treated as a yes/no characteristic rather than summarised as a mean (SD). - Messages: "Add a
table_oneblock with agroupper arm and adistributionper characteristic …", "Notable_oneblock with id "x". …", "thas no columns. Add agroupper arm … — or list them withgroups: ["Placebo", "Active"].", "thas no characteristics. …", and "No characteristic intcarries data. A row's cells aregroupblocks withfrom:naming a column andvalues:holding that column's observations."
clinical_timeline — Clinical case timeline (CARE item 7)
Lays one patient's episode of care against time, so a reader can see what happened, in what order, and how long each step took.
- Built from: a
timelineblock (title:,origin:such as "Day 0 is the first presentation", optionalorientation:) and onetimeline_eventper event withat:(such as"Day 26","Week 11 after withdrawal"or a date),label:, andphase:. Optional detail goes indetail:(ordetails:,description:,note:,notes:,result:,findings:). An event whose text containsTODOis drawn as a placeholder. - Synonyms accepted: for the time,
at,date,day,time,when,offsetort; for the text,label,title,text,nameorevent; for the phase,phase,category,type,stage,kindorstatus. If there is notimeline_event, aneventblock is read, and failing that amilestone. - Phases: presentation (sky blue, circle), diagnosis (orange, diamond), intervention (blue, square), adverse event (vermillion, inverted triangle) and outcome (bluish green, triangle). The phase is recognised from the word you write, so "adverse drug reaction" is an adverse event and "follow-up assessment" is an outcome. A phase outside these five gets its own open marker and colour. Each card also prints the phase name.
- Header: the kicker reads CASE REPORT · CARE ITEM 7 TIMELINE when the document has a
case_reportblock (or aguidelineblock naming CARE), and CLINICAL TIMELINE otherwise, followed by the number of events, the number of phases and the first and last times. - Time handling: events are spaced evenly in sequence (the footnote says so), and the interval since the previous event is printed on the axis whenever both times can be read in the same frame. A time relative to another event ("Week 11 after withdrawal") is resolved against that event. Intervals converted through months or years are marked ≈. An unreadable time gets no interval, never a guessed one. When every event resolves to one frame, events are drawn in chronological order; otherwise in document order.
- Layout: horizontal while every card can be at least 150 units wide and there are no more than 12 events (at the default width that is up to nine events), vertical beyond that.
orientation: "horizontal"or"vertical"(orlayout:) on thetimelineblock overrides. - Argument: a
timelineid, or acase_reportid whose title heads the figure. With severaltimelineblocks, events attach to their timeline throughtimeline:orof:, or by being nested inside it. - Message: "Add
timeline_eventblocks to draw the case timeline — e.g.timeline_event onset { at: "Day 0", label: "Presenting symptoms", phase: "presentation" }."
spirit_schedule — SPIRIT schedule of enrolment, interventions and assessments
Shows a trial protocol's visit schedule on one page, as SPIRIT 2013 item 13 asks.
- Built from: a
spirit_scheduleblock whoseperiods:list is the columns, each led by its code ("-t1 Screening","0 Allocation","t1 Week 6","Close-out"), and onespirit_rowper procedure withsection:(Enrolment, Interventions or Assessments),label:andat:(the period codes it happens at). - Matching: a row's
at:entries are matched on the period's first word only, soat: ["-t1"]lands in the column"-t1 Screening (week −2)". - Placeholders: a row with
placeholder: true, or whose label starts withTODO, is drawn faint and in italics until you write it, and a footnote counts them. - Missing pieces: with no
spirit_scheduleblock, the columns are taken from the rows'at:lists and a footnote asks you to declare the periods; a row with nosection:is drawn under "Unassigned rows". - Several schedules: a row with
schedule: <id>belongs only to that schedule; a row without one belongs to whichever schedule is drawn. With no argument the first schedule is drawn and a footnote says so; an argument that names nospirit_scheduleis reported in a footnote. - Header: read from
study(title,registry) andprotocol(version,allocation_ratio); summary chips fromarm(n) andoutcome(role). - Argument: the
spirit_scheduleid. - Message: "Declare a
spirit_schedulewith itsperiods, and onespirit_row { section, label, at }per procedure, to draw the SPIRIT schedule of enrolment, interventions and assessments."
Diagnostics and prediction renderers
These three renderers share one set of per-subject data: scores or predicted probabilities, and 0/1 outcomes. A prediction paper that shows discrimination should also show calibration and clinical usefulness, and these are built to sit side by side.
roc — ROC curve
Shows how well a score separates cases from non-cases across every threshold.
- Built from: a
rocblock with a nestedseries. In the series,x:holds one score per subject andy:the matching 0/1 outcome. - Paired curves: a second
seriesmay omity:to inherit the first one's labels. That makes the two curves paired, which is what allows the DeLong comparison between them. - Argument: the
rocid. - Option:
level:on therocblock sets the confidence level. - Computes: the curve, the area under it and its confidence interval, and the Youden-optimal cut-off (marked and labelled with its sensitivity and specificity, as the criterion's choice rather than a result). With two curves on the same subjects it runs DeLong's paired test; if the two series do not share one label vector, a note says the test was not run. A typed
auc:is not what is drawn. The panel is square by construction so the chance diagonal stays a diagonal. - Refuses: a curve from one class (no positives or no negatives); a zero-width interval when the area is exactly 1.
- Limitation: the alias
pr_curvestill draws the ROC curve. There is no precision–recall view today, even though the footnote on an ROC whose prevalence is below about 10% recommends one (and names a renderer that does not exist). - Messages: "Add a
rocblock — e.g.roc model_a { series subjects { x: [0.1, 0.8, …] y: [0, 1, …] } }.", "rocneeds per-subject data — addseries subjects { x: […] y: [0, 1, …] }inside it. …" and "No ROC curve is computable from this block. …" - Labels: the chance diagonal's name, the cut-off label and the statistics block are placed clear of every curve. On a narrow figure the statistics block may move below the x axis.
calibration — Calibration plot
Shows whether predicted risks match observed risks.
- Built from: a
calibrationblock with a nestedseries:x:must be predicted probabilities between 0 and 1 (not raw scores),y:the 0/1 outcome. - Options:
bins:chooses the number of groups (a whole number of 2 or more; 10 by default);level:the confidence level. - Computes: observed versus predicted risk by bin (each dot at the bin's mean predicted risk), the calibration slope and intercept, the Brier score, and the integrated calibration index (ICI) with E90. A typed
slope:is not drawn. The panel is square, with the ideal line drawn corner to corner. Only the firstseriesis analysed. - Messages: "Add a
calibrationblock — e.g. …" and, with no per-subject data, the same "needs per-subject data" message asrocfollowed by "x must be predicted PROBABILITIES in [0, 1], not scores." - Labels: the ideal (diagonal) line is named in the legend, which is placed clear of the points; on a narrow figure it may move below the x axis, and a very long series name may be shortened there (the full name stays in the figure description).
decision_curve — Decision curve (net benefit)
Shows whether acting on a model beats treating everyone or nobody across the threshold probabilities a clinician might use.
- Built from: a
decision_curveblock with a nestedserieswhosex:holds predicted probabilities andy:the 0/1 outcome. - Option:
thresholds:is used only when every entry lies strictly between 0 and 1; otherwise the curve uses 0.01 to 0.50. - Computes: net benefit for the model, treat-all and treat-none, and the range of threshold probabilities over which the model beats both (or says that there is none). Unlike the other two, this panel is not square.
- Messages: "Add a
decision_curveblock — e.g. …", the "needs per-subject data" message, and "A decision curve needs at least two threshold probabilities. Givethresholds: [0.05, 0.1, …], or leave it unset for 0.01 … 0.50." - Labels: the treat-none line is named in the legend, which is placed clear of the curves and may move below the x axis on a narrow figure.
Evidence synthesis renderers
forest — Forest plot
Shows every study's estimate beside the pooled result, with marker area proportional to weight and the prediction interval drawn apart from the confidence interval.
- Built from: a
metablock and its study rows:estimate,effectorcontrastblocks nested inside themeta, or beside it carryingof:. Rows inside asubgroupblock form subgroups (named by itscategory,stratum,labelor id). - On the
metablock:measure:(such asrr),scale: logfor ratio measures (risk, odds, hazard ratios; a recognised ratio measure gets the log scale even if you leavescale:out, andscale: identityforces a linear axis),level:for the confidence level,title:, andmodel:. Aweight_by:other thaninverse_varianceis noted and not honoured. - Where each row's numbers come from, in order of preference: counts on a
contrast(events_a,n_a,events_b,n_b); an estimate with its interval (point,lo,hi); an estimate with a standard error (point,se). A published pooled summary is never used as a row. - Pooling (
model:on themetablock):
| You write | What is drawn |
|---|---|
| nothing | Random effects, DerSimonian–Laird τ² |
fixed, fixed_effect, common_effect or inverse_variance | Fixed effect, inverse variance |
random, random_effects or dersimonian_laird | Random effects, DerSimonian–Laird |
paule_mandel | Random effects, Paule–Mandel τ² |
reml or ml | Random effects, REML τ² (a note says REML is used when you wrote ml) |
hartung_knapp or hksj | Random effects with the Hartung–Knapp interval |
mantel_haenszel | Inverse-variance fixed effect, labelled as such, with a note that Mantel–Haenszel weights are not computed |
peto | Inverse-variance fixed effect, with a note that Peto's one-step odds ratio is not computed |
bayesian | DerSimonian–Laird random effects, with a note that no posterior is computed |
- Computes: each study's weight, the pooled estimate and interval, τ², I², Q and its p, the prediction interval (which needs at least three studies; the row says why when it cannot be computed), and for subgroups their own diamonds and the between-subgroup test. Typed pooled values (
point,i2,tau2,q,p_heterogeneity,prediction_lo,prediction_hion themeta) are never printed; disagreements are footnoted. - Drawing: marker area (not side) is proportional to weight; ratio measures use a log axis with the null at 1; an interval that leaves the axis gets an arrowhead.
- Refuses: a pool of one study; a row with no interval and no standard error (drawn as its own refusal row and left out of the pool, with the count in the footnote); a ratio at or below zero.
- Argument: the
metaid. Any othermodel:word than those in the table is read as DerSimonian–Laird random effects. - Messages: "Add a
metablock with oneestimateper study — e.g. …", "Nometablock with id "x". …" and "pooledhas no study rows. Add oneestimateper study … inside themeta, or beside it withof: pooled."
meta pooled {
title: "Antibiotic prophylaxis and surgical site infection"
measure: rr
scale: log
estimate trial_a { label: "Ahmed 2019" point: 0.68 lo: 0.51 hi: 0.90 n: 412 }
estimate trial_b { label: "Barros 2020" point: 0.81 lo: 0.62 hi: 1.06 n: 528 }
estimate trial_c { label: "Chen 2021" point: 0.59 lo: 0.38 hi: 0.92 n: 244 }
estimate trial_d { label: "Dubois 2022" point: 0.74 lo: 0.55 hi: 0.99 n: 366 }
}
view forest_plot: forest(pooled)
view small_study: funnel_plot(pooled)
funnel_plot — Funnel plot (small-study effects)
Plots effect against precision to look for small-study effects.
- Built from: exactly the same
metaand rows asforest. Onemetaserves both figures, so they can never disagree about which studies are in the review. - Draws: the standard-error axis inverted (0 at the top); shaded pseudo-confidence contours at 90, 95 and 99%; Egger's regression line with its test; trim-and-fill imputed studies as open downward triangles in their own colour and legend entry, with the pool printed before and after; and, below about ten studies, a statement in the panel that the funnel's shape is dominated by chance.
- Refuses: a funnel over one study; Egger's test below three studies or when every study has the same precision; trim-and-fill when every standard error is identical. A typed
egger_p:is never printed. - Reading it: asymmetry is not the same thing as publication bias, and with real heterogeneity studies fall outside the pseudo-limits for other reasons. The figure reprints those caveats.
- Argument: the
metaid.
rob_traffic_light — Risk-of-bias traffic light
Shows every study's risk-of-bias judgement domain by domain as a grid.
- Built from:
studyblocks (the rows),bias_domainblocks (the columns:tool:,name:,label:,order:) and onebias_assessmentper study per domain (study:,domain:,tool:,judgement:, optionalsupport:). Both references must name blocks the document declares, and the domain ids must match the instrument's own domains. RoB 2 wants all five. - Argument: the instrument, not a block id:
rob2,robins_i,robins_e,quadas2orrobis. - Instrument choice: with no
tool:anywhere, the figure assumes RoB 2. If the document names two instruments and the view gives no argument, it refuses and asks you to draw one figure per instrument. AMSTAR 2 is not a grid and is refused here; useappraisal_table. - Judgement symbols:
| Symbol | Judgements |
|---|---|
+ | Low; probably low |
! | Some concerns; moderate |
? | Unclear; no information |
− | Probably high; high; serious |
× | Critical |
· | Not assessed |
Each cell carries the symbol, a silhouette (which only differs where two judgements share a symbol) and a colour-blind-safe fill.
- Row labels: each row is labelled with the study's
label:, else itstitle:, else its id written as words (smith_2019reads "Smith 2019"). A label or title that is still a placeholder (containingTODO) is ignored. - Unrecognised judgements: a missing or misspelt
judgement:is drawn as Not assessed (·), never guessed. - Overall column: an overall you recorded is what the cell shows; if your own domain judgements contradict it, a footnote says so and names the domains. When you recorded no overall, RoB 2 derives one by its own rule, and ROBINS-I and ROBINS-E by ROBINS-I's rule; a derived overall is drawn with a dashed border and a footnote says it is the tool's arithmetic, not the assessor's judgement. QUADAS-2 has no overall column at all (unless your document asserts one) and adds its applicability columns instead; ROBIS's overall is its phase-3 judgement and is never derived.
- Before any judgement is recorded: a document that declares the instrument's
bias_domainblocks and names its studies, but has nobias_assessmentyet, draws the full grid with every cell "not yet judged" rather than a refusal. - Messages: "No risk-of-bias judgements for
toolin this document. Add abias_assessmentper study and domain …", the two-instrument refusal ("This document assesses risk of bias with N different instruments … Draw one figure per instrument …"), and "xis not an instrument this figure can lay out as a studies × domains grid. …"
rob_summary_bar — Risk-of-bias summary bar
Shows the percentage of studies at each judgement, domain by domain, in the instrument's own domain order (never sorted by severity). Within each bar, segments stack by severity. It reads the same blocks and takes the same instrument argument as rob_traffic_light, with the same refusals, so one set of assessments serves both figures. When you recorded no overall judgement, the Overall bar counts the overalls RoB 2 or ROBINS-I derive by their own rules, exactly as the grid's overall column does, and is labelled Overall (derived), or Overall (k of n derived) when only some were derived.
grade_sof — GRADE Summary of Findings
Puts the certainty of the evidence, the relative effect and the absolute risks in one table a guideline panel can act on.
- Built from: for each outcome, an
outcome(metric:,role:,timepoint:), anestimate(the pooled relative effect withmeasure,scale,point,lo,hi), agrade_outcomerating the five downgrading domains (starting_certainty:,risk_of_bias:,inconsistency:,indirectness:,imprecision:,publication_bias:, plusstudies:,participants:,design:) and asof_rowpointing at all three (outcome:,estimate:,grade:,risk_control:,participants:,studies:,importance:). - Write the comparator risk with its denominator:
risk_control: 220 per 1000, or as a percentage (22%), or as a bare fraction between 0 and 1 (0.22). A bare220is refused, because it could be per 1000 or per 100 000, and a unit that is not a proportion is refused too. - Computes: the absolute risks per 1000, as whole people, from the comparator risk and the relative effect, worded "N fewer per 1000 (from A fewer to B more)"; and the certainty by GRADE's stepwise rule from the domain ratings. A typed
certainty:,risk_intervention:orrisk_difference:that disagrees is footnoted, not printed. - Refuses per cell: a row with no
grade_outcome, or one that rates none of the five domains, gets a certainty cell that says so and names the fix. A reference that does not resolve turns that cell into a footnote rather than blanking the table. - Certainty display: the word plus the conventional circle glyphs (for example ⊕⊕⊕⊖ for moderate). No colour is used.
- Argument: a
sof_rowid draws one row; with none, every row is drawn. - Messages: "Add a
sof_rowper outcome — e.g. … — and agrade_outcomerating the five downgrading domains." and "Nosof_rowwith id "x" in this document."
appraisal_table — Critical-appraisal table (AMSTAR 2)
Appraises a systematic review item by item against AMSTAR 2, with the critical domains flagged, so the overall confidence can be traced to the answers.
- Built from: an
appraisalblock (tool: amstar2,version:,review_question:,assessors:,disagreements:, optionalconfidence:), astudyfor the header, and oneamstar_itemper item withnumber:"1" to "16",answer:(yes,partial_yes,noornot_applicable) andnote:. - Critical domains: items 2, 4, 7, 9, 11, 13 and 15 are flagged with a filled number, a CRITICAL DOMAIN chip and a rule down the row.
- Overall confidence: shown only once all sixteen items are answered, computed by AMSTAR 2's critical-domain rule on the High / Moderate / Low / Critically low scale. Until then the panel reads Not yet rated with the number of items left. A
confidence:you wrote on theappraisalis checked against the rule, not trusted. - Answers: an unanswered item, or one whose answer is only a
TODO, is drawn as Not yet judged; an answer the figure cannot place is shown verbatim, labelled Unrecognised and counted as not yet judged. Neither is ever drawn as yes. Five tally tiles (Yes, Partial yes, No, Not applicable, Not yet judged) double as the legend, with Can't tell and Unrecognised tiles added when they occur. - Other checklists: any block carrying
answer:orjudgement:, such ascasp_item q1 { question: "…" answer: cant_tell }, draws as the same table with a wider vocabulary (yes, partial, no, can't tell, not applicable). No published rule turns those into a rating, so the panel shows the overall judgement yourappraisalstates. - Arguments: each may name an
appraisal, astudy, a block kind to treat as the items (appraisal_table(casp_item)) or the toolamstar2. Arguments that name a kind or a tool rather than a block may draw an "argument names no block" warning in the checker; the figure still draws. - Width: below 700 px the support column folds under the question.
- Messages: "Declare an
appraisalblock withtool: amstar2, or one block per appraisal item with anumber, aquestionand ananswer…" and "Noxblock carries an item to draw. Give each one aquestionand ananswer."
intervention_table — TIDieR intervention description
Describes each intervention and its comparator item by item, the twelve TIDieR items down the side, so another team could deliver it again.
- Built from: one
tidier_interventionper column, the comparator included, with the twelve fieldsbrief_name,why,materials,procedures,provider,mode,location,schedule,tailoring,modifications,fidelity_plannedandfidelity_actual. - Pairing with arms: an
armwhoseintervention:text names a description's id pairs with it and lends the column its label and n. - Not reported versus not applicable: an empty field, or one containing only TODO, is marked Not reported. Item 12 is drawn as Not applicable only when item 11 says fidelity was not assessed.
- Header: four tiles count what is reported, not reported and not applicable; each column has a twelve-segment completeness strip and a letter.
- Arguments: each may name a
study(the header), atidier_interventionor anarm(draw only those columns, in that order). - Width: the figure widens rather than squeezing a column below its minimum; a cell may run to 28 lines before it is shortened.
- Message: "Declare a
tidier_interventionblock per intervention — the comparator included — with the twelve TIDieR fields (…)."
Statistics and quality improvement renderers
raincloud — Raincloud plot
Shows the whole distribution (a half violin for its shape, a box for the robust summary and every raw observation as jittered points) instead of a mean and an error bar.
- Built from: a
distributionblock (title:,unit:) with a nestedgroupper condition, each withlabel:and rawvalues:, one entry per observation andnullfor a missing one. - Options on the
distributionblock:bandwidth_rule: silvermanorscottchooses the kernel bandwidth rule;bandwidth:with a number fixes it. The rule and the numeric bandwidth are printed for every group. - Deterministic jitter: point offsets come from the data and the block ids, so the same data redraw identically in every export.
- Computes: density, quartiles, Tukey whiskers, n, missing, mean and SD from the observations. Typed
mean:,sd:ormedian:are footnoted when they disagree. - Refuses: a distribution that gives only summary statistics (
mean:andsd:, or a five-number summary) and no observations. Useforestfor an estimate ortable_onefor a baseline row instead. A group with novalues:is left out of the figure. - Bandwidth notes: if you give both
bandwidth:andbandwidth_rule:, the number wins and a footnote says so; an unknown rule name falls back to Silverman's, with a footnote. For data that are all non-negative, the drawn density is truncated at 0. - Argument: the
distributionid. - Messages: "Add a
distributionblock holding the raw observations — …", "Nodistributionblock with id "x". …", "x.valuesis not a list of numbers. Writevalues: [4, 6, 6, 9]…", "recoverygivesmean,sdbut novalues. A raincloud needs the observations …", "recoveryhas novalues. …", and "Every observation inrecoveryis missing or non-finite, so there is no distribution to draw. Check the column mapping — a text column read as numbers produces exactly this."
control_chart — Run or control chart (SQUIRE 2.0)
Tracks a measure over time against its own baseline, with the changes your team made marked and the special-cause signals computed rather than judged by eye.
- Built from: a
control_chartblock (what counts as a signal) and aseries(the points:values:, monthlabels:such as"2024-01",unit:). Link them withof:on the series when a document holds more than one chart. - On the
control_chartblock:metric:,chart:(free text naming a run chart, an I chart, or a p, u or c chart),baseline_period:,centre_line:,intervention_at:(each change becomes a numbered marker),rules:,limits:(such as "2 sigma") andannotations:(other events, lettered). - Denominators: a p or u chart needs each point's denominator in the series'
n:. - Baseline: found, in order, from a date range in
baseline_periodmatched to the labels; else every point before the first change inintervention_at; else a count inbaseline_period("the first 12 weeks"); else every point. The footnote says which. - Computes: the centre line from the baseline (median for a run chart unless
centre_linesays mean; mean for I; n-weighted mean for p and u; mean count for c), control limits for I, p, u and c charts (sigma multiplier fromlimits, default 3), re-based phases where the chart says it was re-based, and the signals: a shift (default 8 points on one side), a trend (default 6 points rising or falling) and points beyond a limit. Rule lengths are read from yourrulestext. A typed centre line that disagrees is reported. An aim line is drawn from akpiwhose title matches the metric. - Not computed: x̄–S limits (only the centre line is drawn, with a note), Laney p′ or u′ limits, "astronomical point" judgements, and any rule the figure cannot recognise, which is listed as not evaluated.
- Argument: a
control_chartorseriesid. - Message: "Declare a
control_chartblock (metric, chart, baseline_period, centre_line, intervention_at, rules) and aserieswithvaluesandlabelsto draw the run or control chart."
Qualitative and survey renderers
theme_map — Thematic map with quotations
Shows the themes a qualitative analysis found, the sub-themes under each and the attributed quotations that ground them.
- Built from:
themeblocks (label:,description:,major:, andof:naming the parent for a sub-theme) andquotationblocks (text:,participant:,of:naming the theme). - Header and sample: a
studyorqual_studysupplies the header. Thecohortchain is printed as the sample line, and the participant count is thenof the cohort (or cohorts) at the end of the chain; with no cohort the PARTICIPANTS tile reads "—" and "no cohort declared". Aninstrumentwith itsitems is read as the topic guide. - Tiles: PARTICIPANTS (the sample size and the cohort it comes from), THEMES (with the number of major themes and sub-themes), QUOTATIONS (flagging quotations linked to no theme, or themes without one) and VOICES QUOTED (distinct participants quoted, as a share of the sample when the sample is known).
- Counts per theme: quotations (sub-themes included), share of all quotations, and distinct voices. Voices are counted from the
participant:identifiers, so keep them pseudonymised but consistent. A quotation with no participant is shown as "— unattributed". - Argument: a
themeid (draw only that branch) or thestudy/qual_studythe header should describe. - Message: "Declare
themeblocks (sub-themes name their parent withof:) andquotationblocks withparticipantandof:to draw the thematic map."
item_map — Instrument item map
Shows which items measure which construct in a survey instrument, with reverse-coded items marked.
- Built from:
itemblocks (text:,construct:,scale:,reverse: true).instrumentandconstructare optional. An item whoseconstruct:matches no construct collects in an "Unassigned items" group. - Message: "Declare an
instrument, at least oneconstruct, and items."
Health economics renderer
ce_plane — Cost-effectiveness plane
Plots incremental cost against incremental effect for every strategy, with the full incremental analysis drawn on top.
- Built from: at least two
interventionoreconomic_strategyblocks with a numericcost:andqalys:(oreffect:witheffect_unit:). Anecon_model(title,currency,horizon,perspective,discount) is optional. A willingness-to-paythreshold:on anicerorpsablock draws a dashed ray. - Reference: the strategy whose
arm:names standard or usual care sits at the origin; otherwise a comparator or control arm; otherwise the cheapest. - Draws: the frontier as a solid line labelled with sequential ICERs; strongly dominated strategies as ×, extendedly dominated as ◇, the frontier as ●, the reference as ◎; and an incremental-analysis table beside the plane at widths of 760 px and above, underneath it below that.
- Whose verdict: a status you declared (
on_frontier,dominated,extendedly_dominated) is what is drawn; the computed analysis fills in strategies that declare none, and every disagreement is footnoted. - Argument: an
econ_modelid restricts the plane to strategies naming it inof:(plus those naming none). - Message: "Declare at least two
economic_strategy(orintervention) blocks with acost:andqalys:— one of them the comparator,arm: standard_of_care."
Composition and illustration renderers
panel — Multi-panel figure
Composes several views into one journal-ready plate, labelled a, b, c and aligned on their plot rectangles rather than their outer boxes.
- Built from:
panelblocks in two roles. A panel withoutview:is the container (rows:,cols:,width:in millimetres,height:,gutter:,gutter_x:,gutter_y:,share_x:,share_y:,label_style:,label_position:,title:). A panel withview:is a child naming a view your document declares (row:,col:,row_span:,col_span:,caption:,alt:, andlabel:orletter:to override its letter). A panel figure therefore needs everything its children's renderers need. - Argument: the container's id, as in
panel(figure_1). - Width, from the strongest statement available:
width:on the container; else thewidth_mmof apublishblock for this panel; else the named journal's column measure; else a width supplied by the place the figure is drawn (converted at 96 dpi); otherwise an 85 mm single-column fallback. The footnote states which source was used. - Columns when you give none: one panel uses one column; at widths of 150 mm or more, up to three; otherwise up to two. Height is derived from what the panels need (capped at 297 mm unless the destination sets its own limit), unless you declare
height:. - Letters: bold lower case, outside the panel above its top-left corner, assigned in reading order (top row left to right, then down).
label_style:acceptsa,A,(a),(A),a.,A.,1,1.ori.label_position:acceptstop-leftorinside-top-left,top-rightorinside-top-right,top-centerorabove-center(outside, centred), andabove,outsideoroutside-top-left(the convention). An unknown style or position falls back to the convention, with a note. - Shared axes:
share_xandshare_yare verified. Two panels on different scales under one shared axis are reported, never drawn as if they agreed. - Degrades gracefully: a child view that refuses, fails or does not exist becomes a labelled placeholder in its cell; the other panels still render.
- Limitations: it cannot hide a child's duplicate axis, and it cannot restyle a child's type. Each child is drawn at its own cell's width to keep scaling near 1, and an effective point size far from the nominal one is reported.
- Messages: "
panel phas no panels to compose. Addpanel { view: <view id> }blocks — one per panel — naming views this document declares." and "A panel figure is one or morepanel { view: <view id> }blocks, optionally inside apanel { rows: 2 cols: 2 width: 88 mm }container. This document has none."
panel figure_1 { title: "Recovery and pooled effect" rows: 1 cols: 2 width: 180 mm }
panel panel_a { view: spread row: 1 col: 1 }
panel panel_b { view: pooled_effect row: 1 col: 2 }
view composite: panel(figure_1)
Here spread and pooled_effect are two other views the document declares (a raincloud and a forest).
figure — Free-form schematic
Draws a mechanism, apparatus or concept as a labelled schematic.
- Built from: a
figureblock (title:,width:,height:) plusshape(kind:such as"rect"or"circle", position, size,fill:,stroke:,label:),label_2d,arrow_2d(from:,to:,label:),annotationandgroup_2dblocks. - Notes: a
figurewith no children draws an empty canvas at its declared size. Any other block kind inside is ignored without a message, and anarrow_2dwhose endpoints do not resolve draws nothing. - Message: "No
figureblock — tryfigure my_diagram { width: 800, height: 500 … }"
scene — Isometric 3-D scene
Shows a three-dimensional arrangement as an isometric projection placed by coordinates.
- Built from: a
sceneblock (title:,projection:,width:,height:,grid:,axes:) and at least one primitive:box3d,sphere3d,cylinder3d,plane3d,edge3dorlabel3d. - Note: the canvas size comes from the
sceneblock's ownwidthandheight; a width requested by the host is ignored when the block declares one. - Messages: "No
sceneblock — tryscene lattice { projection: isometric … }" and "Add at least one 3D primitive: box3d, sphere3d, cylinder3d, plane3d, or edge3d."
Machine learning and laboratory renderers
ablation_table — Ablation table
Ranks what each component of a system is worth by removing it.
- Built from:
model,dataset, oneeval(the baseline) andablationblocks (base:,change:,delta:).model:anddataset:are required references oneval, so anevalwithout them is a compile error ("evalis missing required attributemodel"). Anablationwith nodelta:is read as zero, which is a claim, so write it. - Messages: "No
evalblock — declare one as the baseline." and "Addablationblocks to compare against the baseline."
experiment_flow — Experiment design flow
Shows a bench experiment's design (samples, conditions, doses and readouts) at the level someone else would need to repeat it.
- Built from: an
experimentblock (title:,model:) plus at least onesample(n:,replicates:) or onecondition(title:,dose:,duration:).assayblocks (kind:,readout:) add the readout panel. Animal-study blocks are also read. - Messages: "No
experimentblock found — tryexperiment my_screen { … }" and "Add at least onesampleand onecondition."
Business, engineering and other renderers
| Renderer | Built from, and what to watch | Message when something is missing |
|---|---|---|
gantt | A project (title, start, end) and task blocks (title, start, end, depends: [...]). A task is dropped silently unless both dates parse as YYYY-MM-DD, and a milestone unless its date: does. Milestones alone draw a plan with "0 tasks" | "No project block found — try project q3_launch { … }" and "Add a task or milestone to populate the timeline." |
c4_container | A system and service, datastore or actor blocks with depends:. tier: decides the row: edge/frontend first, then core/backend, then data/store; anything else sorts last, alphabetically. With no tier:, a datastore goes in the data row and a service in the core row. An actor with depends: [...] gets one arrow to each container it names; an actor that names none gets a single dashed arrow to the first container of the top row, titled as an assumed entry point (declare depends: on the actor to replace it) | "No system block found — try system saas_platform { … }" and "Add a service, datastore, or actor block." |
funnel | funnel_step blocks (title, n) chained by from:, not by document order. The head is the step with no from:; pass its id as the argument, as in funnel(visited) | "Add a chain of funnel_step blocks linked via from:." |
okr_grid | kpi blocks (title, baseline, target, unit). An initiative supplies the banner and segment blocks a customer-segment strip. A KPI missing a baseline or target prints a prompt instead of inventing numbers | "Declare an initiative and at least one kpi." |
captable | shareholder blocks (name, shares, class, role) and optional option_pool (shares, granted; only the ungranted remainder is a bar), cap_table (title, currency, default USD) and round. Percentages are computed from share counts | "Declare a cap_table and at least one shareholder." and "Total shares is 0 — fill shares on each shareholder." |
risk_matrix | threat blocks (title, asset, category, likelihood, impact) on a 5×5 grid. Likelihood and impact default to 3 when absent, so state both. A control reduces the residual likelihood of each threat in its mitigates: list by its coverage: | "Declare a threat_model and at least one threat." |
fmea_table | failure_mode blocks (component, mode, cause, effect, severity, occurrence, detection), ranked by RPN. Each rating defaults to 5, giving an RPN of 125, so state all three. A mitigation (mode, action, target_occurrence, target_detection) shows the residual risk | "Declare an fmea and at least one failure_mode." |
supply_map | sc_node blocks with role: of supplier, factory, warehouse, distributor or customer (anything else falls to the first column), and sc_link blocks (from, to, lead_time_days, cost_per_unit, mode). A link missing from or to is skipped without a message | "Declare a supply_chain and at least two sc_node blocks." |
rubric_grid | criterion blocks (name, weight, description) and level blocks (criterion, label, points, descriptor). Level columns are sorted by points, worst to best | "Declare a rubric and at least one criterion." |
clause_map | clause blocks (title, type, party, summary, section), optional party and agreement, and obligation blocks for the obligations strip. A clause whose party matches no party goes in an "Unassigned" column | "Declare an agreement, parties, and at least one clause." |
Messages you may see
| Message | What it means | What to do |
|---|---|---|
| No view renderer named "x" — available: … | The view names a renderer the Lab does not have. The checker also reports this as an error | Correct the name; the checker's "Did you mean …?" usually has it |
| Add a view to draw it | The document compiles but declares no view | Click Add a view, use the Figures bench, or type a view line |
| Fix N errors to render | The document has errors and nothing could be drawn from it | Click Go to the first error |
| The "name" view couldn't be drawn | The renderer failed while drawing. Your source is fine | Switch to another view, or undo the last change to this one |
A renderer's own explanation, such as "Add a survival block with one group per arm …" | The blocks the figure is built from are missing, or the data cannot support the figure | Follow the sentence; the renderer names the exact block or attribute it needs. The gallery card shows a working shape |
| The X could not be built from this document (…). Check that … | Something in the document made the renderer stop; the message names what to check | Fix the named attribute. The rest of the studio keeps working |
| A footnote saying a typed value disagrees with the computed one | You transcribed a statistic that your own data do not give | Check the transcription, or the data. The figure shows the computed value |
Tips
- Give every view a name and an argument when a document has more than one block of the same kind:
view os_plot: km(os)rather thanview : km. - Draw the forest plot and the funnel plot from one
metablock. Both figures then always describe the same studies. - Use the Figures bench to learn a figure in a fresh document, then copy the blocks you need into your own. Starting from a worked example replaces whatever is open.
- When a research figure footnotes a disagreement, read it before you submit. It is usually a transcription slip.
- State the numbers that would otherwise default (likelihood and impact on threats; severity, occurrence and detection on failure modes;
delta:on ablations). - Put a
notewith "Illustrative values" in its text into any document whose numbers are not real. Every view of it then says so. - To lay several figures out for a journal, compose them with
panelrather than assembling exported images by hand; the letters, widths and alignment then update when your data change.
Limits and known constraints
- There is no precision–recall view;
pr_curveis an alias ofroc. prismaandconsortdraw the same figure; neither prints the name of the reporting standard in its header.calibrationanddecision_curveanalyse only the firstseriesin their block.forestpools by inverse variance only. Mantel–Haenszel, Peto and Bayesian pooling are declarable but not computed; the figure draws the nearest inverse-variance pool and labels it.control_chartcomputes limits for I, p, u and c charts only. An x̄–S chart gets its centre line only.kmdoes not draw cumulative incidence under competing risks, does not print a hazard ratio, and does not print a log-rank p for a single arm.panelcannot remove a child's duplicate axis or restyle a child's type.rob_traffic_lightandrob_summary_bardraw one instrument per figure: RoB 2, ROBINS-I, ROBINS-E, QUADAS-2 or ROBIS. AMSTAR 2 is drawn byappraisal_table.ganttreads dates only inYYYY-MM-DDform.- The Insert flyout adds a view without an argument; add the argument by hand when the document has several candidate blocks.
- Starting from a worked example replaces the open document's content and releases any data rows bound to it.
Troubleshooting
My Gantt chart shows fewer bars than tasks. A task is dropped unless both start: and end: are dates in YYYY-MM-DD form. Check the dates of the missing tasks.
The Kaplan–Meier view says there are no events. Every events: entry is 0, so the curve would claim 100% survival. Check that events are coded 1 and censorings 0, and that events: has one entry per entry in times:.
The raincloud refuses my group. It has mean: and sd: but no values:. A raincloud needs the raw observations. Add them, or draw the estimate with forest.
The risk-of-bias grid asks me to choose an instrument. Your document assesses studies with two tools. Draw one figure per tool, for example view rob_main: rob_traffic_light(rob2) and view rob_obs: rob_traffic_light(robins_i).
My multi-panel figure shows a placeholder in one cell. That child view failed or refuses to draw on its own. Open that view by itself to read its message, fix it, and the plate redraws.
The canvas says Example data — not real, but I replaced every number. The stamp follows the starter's "EXAMPLE text from a fictional …" comment line, not the numbers. Delete that line (and any other line that still contains those words).
I clicked Start a new document from this example and lost my work. Click Undo in the toast, or press ⌘Z. The previous content comes back.
