| Title: | Read and Plot 'Rhylthyme' Schedules with 'ggplot2' |
|---|---|
| Description: | Reads 'Rhylthyme' programs (JSON descriptions of parallel tracks of timed steps: recipes, lab protocols, run-of-shows) and plots them as Gantt charts with 'ggplot2'. Step times come from the same timing engine that <https://www.rhylthyme.com> uses, embedded through 'V8', so a plot agrees with the website to the second. |
| Authors: | Jeremy Leipzig [aut, cre] |
| Maintainer: | Jeremy Leipzig <[email protected]> |
| License: | Apache License (>= 2) |
| Version: | 0.0.0.9000 |
| Built: | 2026-10-12 06:16:36 UTC |
| Source: | https://github.com/rhylthyme/rhylthyme-r |
The parsed program JSON, unchanged. jsonlite::toJSON(as.list(p), auto_unbox = TRUE, null = "null", digits = NA) turns it back into the
program's JSON, and p$json holds the text exactly as it was read.
## S3 method for class 'rhylthyme_program' as.list(x, ...)## S3 method for class 'rhylthyme_program' as.list(x, ...)
x |
A |
... |
Unused. |
A list.
ggplot(program) + geom_rhylthyme() with theme_rhylthyme() and the
program's name as the title. With one lane per track the fill legend only
repeats the lane names, so it is left out. Add to it like any ggplot.
## S3 method for class 'rhylthyme_programs' autoplot(object, ...) ## S3 method for class 'rhylthyme_run' autoplot(object, ...) ## S3 method for class 'rhylthyme_program' autoplot(object, ...)## S3 method for class 'rhylthyme_programs' autoplot(object, ...) ## S3 method for class 'rhylthyme_run' autoplot(object, ...) ## S3 method for class 'rhylthyme_program' autoplot(object, ...)
object |
A |
... |
Passed on to |
A ggplot.
library(ggplot2) p <- read_rhylthyme(system.file("extdata", "breakfast_schedule.json", package = "rhylthyme")) autoplot(p) autoplot(p, lanes = "task")library(ggplot2) p <- read_rhylthyme(system.file("extdata", "breakfast_schedule.json", package = "rhylthyme")) autoplot(p) autoplot(p, lanes = "task")
One row per step: the columns of steps(), plus program (a factor, for
faceting), step_key (the step id, prefixed by the program within a set
of programs, so it is unique), track (a factor in authored order; tracks
with the same name share a level, and a colour), the lane factors lane
(by track), step_lane and task_lane (see lanes in
geom_rhylthyme(); levels run bottom to top so the first track or step
is drawn at the top, and within a set each program's lanes are its own),
and range_min / range_max (a variable step's shortest and longest
end; NA otherwise). start, end and the ranges are seconds from
program start, or clock times for programs read with start_at /
finish_at; they carry a class that makes ggplot2 use
scale_x_rhylthyme() (or scale_x_rhylthyme_clock()) by default, as
track does for scale_fill_rhylthyme() and the lanes for
scale_y_rhylthyme(). The program rides along as the
"rhylthyme_program" attribute, for geom_rhylthyme()'s arrows and
replicate collapsing.
## S3 method for class 'rhylthyme_program' fortify(model, data, ...) ## S3 method for class 'rhylthyme_programs' fortify(model, data, ...) ## S3 method for class 'rhylthyme_run' fortify(model, data, ...)## S3 method for class 'rhylthyme_program' fortify(model, data, ...) ## S3 method for class 'rhylthyme_programs' fortify(model, data, ...) ## S3 method for class 'rhylthyme_run' fortify(model, data, ...)
model |
A |
data |
Ignored. |
... |
Ignored. |
A data frame.
geom_rhylthyme() draws one bar per step, from its start to its end, in
one lane per track, with arrows for dependencies between lanes and step
names on (or beside) the bars. With a program as the plot's data
(ggplot(program) + geom_rhylthyme()), the aesthetics default to
xmin = start, xmax = end, y = lane, fill = track, step = step_id
and label = name, and the arrows come from the program's
dependencies(); anything you map or pass yourself wins. The geom also
works by name: geom = "rhylthyme".
geom_rhylthyme( mapping = NULL, data = NULL, stat = "rhylthyme", position = "identity", ..., arrows = TRUE, labels = TRUE, ranges = TRUE, estimates = TRUE, lanes = c("track", "step", "task"), collapse_replicates = FALSE, dependencies = NULL, label_size = 3, na.rm = FALSE, show.legend = NA, inherit.aes = TRUE ) stat_rhylthyme( mapping = NULL, data = NULL, geom = "rhylthyme", position = "identity", ..., na.rm = FALSE, show.legend = NA, inherit.aes = TRUE )geom_rhylthyme( mapping = NULL, data = NULL, stat = "rhylthyme", position = "identity", ..., arrows = TRUE, labels = TRUE, ranges = TRUE, estimates = TRUE, lanes = c("track", "step", "task"), collapse_replicates = FALSE, dependencies = NULL, label_size = 3, na.rm = FALSE, show.legend = NA, inherit.aes = TRUE ) stat_rhylthyme( mapping = NULL, data = NULL, geom = "rhylthyme", position = "identity", ..., na.rm = FALSE, show.legend = NA, inherit.aes = TRUE )
mapping |
Set of aesthetic mappings created by |
data |
The data to be displayed in this layer. There are three options: If A A |
stat |
The statistical transformation to use on the data for this layer.
When using a
|
position |
A position adjustment to use on the data for this layer. This
can be used in various ways, including to prevent overplotting and
improving the display. The
|
... |
Other arguments passed on to |
arrows |
Draw dependency arrows between lanes, as curves the way rhylthyme.com draws them: a sweep into the waiting step's start, or an S-curve between the two bars when they are close. Solid for a step that waits for another; dashed when it starts before the other ends (a negative offset); dotted for a step that runs only if the other aborts. |
labels |
Draw each bar's |
ranges |
Show each variable step's range: a faded extension from its planned end to its longest, and a thin line under the bar from its shortest to its longest. |
estimates |
Outline, dotted, the bars whose length is an estimate
(instrument steps with no duration, indefinite steps, and durations
|
lanes |
What each lane is, for a program as the data: |
collapse_replicates |
Draw one bar per authored step instead of one
per replicate instance, spanning all its instances and labelled with
the count (only for a program as the data; |
dependencies |
A data frame with |
label_size |
Label text size, in mm (as |
na.rm |
If |
show.legend |
logical. Should this layer be included in the legends?
|
inherit.aes |
If |
geom |
The geometric object to use to display the data for this layer.
When using a
|
Aesthetics: xmin, xmax and y (required); fill, colour, alpha,
linewidth, linetype; label (the text for each bar), step (the id
the dependencies table refers to), xlower and xupper (a variable
step's shortest and longest end) and estimate (TRUE for an estimated
length). For a program these default to range_min, range_max and
estimate.
A layer to add to a plot.
library(ggplot2) p <- read_rhylthyme(system.file("extdata", "breakfast_schedule.json", package = "rhylthyme")) ggplot(p) + geom_rhylthyme() ggplot(p) + geom_rhylthyme(labels = FALSE)library(ggplot2) p <- read_rhylthyme(system.file("extdata", "breakfast_schedule.json", package = "rhylthyme")) ggplot(p) + geom_rhylthyme() ggplot(p) + geom_rhylthyme(labels = FALSE)
Reads a Rhylthyme program (JSON), checks it against the program schema and times every step with the same engine rhylthyme.com uses.
read_rhylthyme(x, validate = TRUE, start_at = NULL, finish_at = NULL)read_rhylthyme(x, validate = TRUE, start_at = NULL, finish_at = NULL)
x |
The program: a path to a JSON file, an |
validate |
If |
start_at, finish_at
|
Anchor the program to the clock: when it starts,
or when its last step should end ("everything ready at 6 pm"). A
|
A rhylthyme_program: a list with the program's name,
description, schema_version and source, the steps, tracks and
dependencies tables (see steps()), the parsed program and its
json text, and start_at when anchored. Times are seconds from
program start.
p <- read_rhylthyme(system.file("extdata", "breakfast_schedule.json", package = "rhylthyme")) p read_rhylthyme('{"programId": "tea", "name": "Tea", "resourceConstraints": [], "tracks": [{"trackId": "kettle", "name": "Kettle", "steps": [{"stepId": "boil", "name": "Boil", "duration": {"type": "fixed", "seconds": 180}, "startTrigger": {"type": "programStart"}}]}]}') # Everything ready at 6 pm p <- read_rhylthyme(system.file("extdata", "breakfast_schedule.json", package = "rhylthyme"), finish_at = "2026-11-26 18:00") steps(p)[c("name", "start_time", "end_time")]p <- read_rhylthyme(system.file("extdata", "breakfast_schedule.json", package = "rhylthyme")) p read_rhylthyme('{"programId": "tea", "name": "Tea", "resourceConstraints": [], "tracks": [{"trackId": "kettle", "name": "Kettle", "steps": [{"stepId": "boil", "name": "Boil", "duration": {"type": "fixed", "seconds": 180}, "startTrigger": {"type": "programStart"}}]}]}') # Everything ready at 6 pm p <- read_rhylthyme(system.file("extdata", "breakfast_schedule.json", package = "rhylthyme"), finish_at = "2026-11-26 18:00") steps(p)[c("name", "start_time", "end_time")]
A run record (the runs schema) is what actually happened when a program
was run: when each step really started and ended, and what ended it. It
is written by the rhylthyme runner and by rhylthyme.com.
read_rhylthyme_run(x, program = NULL, validate = TRUE, clock = TRUE)read_rhylthyme_run(x, program = NULL, validate = TRUE, clock = TRUE)
x |
The run record: a path, an |
program |
The program that was run (a |
validate |
Check the record against the runs schema (see
|
clock |
If |
A rhylthyme_run: a list with name, run_id, program_id,
program_version, started_at, ended_at, outcome (completed,
aborted or abandoned), context, the steps table and the parsed
record. The steps table has one row per step in the record: the
program's step_id and track columns, the actual start, end and
duration (seconds from startedAt; NA for a step that never
started), status (completed, aborted, skipped, unfinished or
not_started), ended_by, failed (an instrument command failed at
least once) and last_code (its last reply), and the plan the runner
had (planned_start, planned_end).
extdata <- function(f) system.file("extdata", f, package = "rhylthyme") dinner <- read_rhylthyme(extdata("thanksgiving_one_oven.json")) run <- read_rhylthyme_run(extdata("thanksgiving_one_oven.run.json"), program = dinner) run steps(run)[c("name", "start", "end", "status")] autoplot(run)extdata <- function(f) system.file("extdata", f, package = "rhylthyme") dinner <- read_rhylthyme(extdata("thanksgiving_one_oven.json")) run <- read_rhylthyme_run(extdata("thanksgiving_one_oven.run.json"), program = dinner) run steps(run)[c("name", "start", "end", "status")] autoplot(run)
rhylthyme_engine_version() is the version of the
@rhylthyme/timeline
timing engine this package carries: step times match rhylthyme.com's for
that engine version. rhylthyme_schema_versions() lists the program
schemaVersions read_rhylthyme() accepts.
rhylthyme_engine_version() rhylthyme_schema_versions()rhylthyme_engine_version() rhylthyme_schema_versions()
A character vector.
rhylthyme_engine_version() rhylthyme_schema_versions()rhylthyme_engine_version() rhylthyme_schema_versions()
Read from the embedded engine, so they are exactly rhylthyme.com's.
rhylthyme_palettes()rhylthyme_palettes()
A named list of character vectors of hex colours.
names(rhylthyme_palettes()) rhylthyme_palettes()$classicnames(rhylthyme_palettes()) rhylthyme_palettes()$classic
Combines programs so they can be tabulated and plotted together:
steps(), tracks(), dependencies() and resources() stack each
program's table with a program column, and a plot keeps each program's
lanes separate (facet with facet_wrap(~ program, scales = "free_y"), or
use autoplot()). Step ids may repeat between programs: plots match
dependencies within a program only. c(p1, p2) does the same.
rhylthyme_programs(...)rhylthyme_programs(...)
... |
|
A rhylthyme_programs.
library(ggplot2) breakfast <- read_rhylthyme(system.file("extdata", "breakfast_schedule.json", package = "rhylthyme")) both <- rhylthyme_programs(Saturday = breakfast, Sunday = breakfast) both autoplot(both)library(ggplot2) breakfast <- read_rhylthyme(system.file("extdata", "breakfast_schedule.json", package = "rhylthyme")) both <- rhylthyme_programs(Saturday = breakfast, Sunday = breakfast) both autoplot(both)
A program plotted with geom_rhylthyme() picks these by default: its
bars are filled by track from rhylthyme.com's palette, and its time axis
reads as elapsed time (or clock time, when the program was read with
start_at or finish_at). Add one yourself to change its options; any
other ggplot2 scale replaces them as usual.
scale_fill_rhylthyme(palette = "classic", ..., aesthetics = "fill") scale_colour_rhylthyme(palette = "classic", ..., aesthetics = "colour") scale_color_rhylthyme(palette = "classic", ..., aesthetics = "colour") scale_x_rhylthyme( name = ggplot2::waiver(), breaks = elapsed_breaks, labels = ggplot2::waiver(), ... ) scale_y_rhylthyme(...) scale_x_rhylthyme_clock(name = ggplot2::waiver(), ...)scale_fill_rhylthyme(palette = "classic", ..., aesthetics = "fill") scale_colour_rhylthyme(palette = "classic", ..., aesthetics = "colour") scale_color_rhylthyme(palette = "classic", ..., aesthetics = "colour") scale_x_rhylthyme( name = ggplot2::waiver(), breaks = elapsed_breaks, labels = ggplot2::waiver(), ... ) scale_y_rhylthyme(...) scale_x_rhylthyme_clock(name = ggplot2::waiver(), ...)
palette |
A palette name: one of |
aesthetics |
The aesthetics the scale applies to. |
name, breaks, labels, ...
|
Passed on to the underlying ggplot2 scale. |
scale_fill_rhylthyme() / scale_colour_rhylthyme(): the web
timeline's palettes, in the same order (colours repeat, as on the web,
when there are more tracks than colours). See rhylthyme_palettes().
scale_x_rhylthyme(): seconds from program start, labelled m:ss, or
h:mm once the axis reaches an hour, at round breaks (1, 5, 15 or 30
minutes, 1 or 2 hours, ...). Titled "Elapsed (m:ss)" or "Elapsed
(h:mm)" unless you give a title.
scale_x_rhylthyme_clock(): clock times, for an anchored program; a
ggplot2::scale_x_datetime() titled "Clock time".
scale_y_rhylthyme(): the lanes, labelled by track, step or task name
(within a set of rhylthyme_programs() each program's lanes are its
own even when names repeat).
A ggplot2 scale.
library(ggplot2) p <- read_rhylthyme(system.file("extdata", "breakfast_schedule.json", package = "rhylthyme")) ggplot(p) + geom_rhylthyme() + scale_fill_rhylthyme("cookbook") ggplot(p) + geom_rhylthyme() + scale_x_rhylthyme(name = "Time since start")library(ggplot2) p <- read_rhylthyme(system.file("extdata", "breakfast_schedule.json", package = "rhylthyme")) ggplot(p) + geom_rhylthyme() + scale_fill_rhylthyme("cookbook") ggplot(p) + geom_rhylthyme() + scale_x_rhylthyme(name = "Time since start")
Each returns a plain data frame, ready for dplyr and ggplot2.
steps(x, ...) tracks(x, ...) dependencies(x, ...) resources(x, ...) ## S3 method for class 'rhylthyme_program' as.data.frame(x, row.names = NULL, optional = FALSE, ...) ## S3 method for class 'rhylthyme_program' tidy(x, ...)steps(x, ...) tracks(x, ...) dependencies(x, ...) resources(x, ...) ## S3 method for class 'rhylthyme_program' as.data.frame(x, row.names = NULL, optional = FALSE, ...) ## S3 method for class 'rhylthyme_program' tidy(x, ...)
x |
A |
... |
Unused. |
row.names, optional
|
Unused; for compatibility with |
steps(): one row per step, replicate instances included, in authored
order: track_id, track_name, track_index, step_id, name,
task, start and end (seconds from program start, as the engine
times them), duration, resolved (FALSE when the engine could not
place the step), duration_type (fixed, variable, indefinite or
instrument), min_seconds and max_seconds (the authored range),
estimate (the planned length is a guess: instrument steps with no
duration, indefinite steps, and durations rhylthyme plan filled in),
trigger_type, and for a replicate instance instance_of (the
authored step) and instance_index. For a program read with
start_at or finish_at, also start_time and end_time (POSIXct).
as.data.frame() and tidy() give the same table.
tracks(): one row per track as the engine lays them out (replicate and
template tracks included): track_id, name, track_index,
parent_track_id, template_id, n_steps, start, end.
dependencies(): one row per trigger that refers to another step:
from_step, to_step, relation (end_to_start, start_to_start or
on_abort), offset in seconds (buffers included; negative for a
hand-off before the other step ends), trigger_type, and logic (all
or any) for a trigger inside a compound one.
resources(): one row per task: task, max_concurrent (NA for a
task steps use that has no constraint), description, n_steps.
A data frame.
p <- read_rhylthyme(system.file("extdata", "breakfast_schedule.json", package = "rhylthyme")) steps(p) tracks(p) dependencies(p) resources(p)p <- read_rhylthyme(system.file("extdata", "breakfast_schedule.json", package = "rhylthyme")) steps(p) tracks(p) dependencies(p) resources(p)
Summarise a Rhylthyme program
## S3 method for class 'rhylthyme_program' summary(object, ...)## S3 method for class 'rhylthyme_program' summary(object, ...)
object |
A |
... |
Unused. |
A summary.rhylthyme_program: a list with name,
schema_version, makespan (seconds), n_steps, n_estimated,
n_unresolved, and the tracks() and resources() tables. Printing it
shows each track's steps and time span, and each resource's limit.
summary(read_rhylthyme(system.file("extdata", "breakfast_schedule.json", package = "rhylthyme")))summary(read_rhylthyme(system.file("extdata", "breakfast_schedule.json", package = "rhylthyme")))
A minimal theme for Gantt charts: light vertical grid lines on the time axis, none between lanes, no y-axis title (the lanes name themselves) and the legend underneath.
theme_rhylthyme(base_size = 11, base_family = "")theme_rhylthyme(base_size = 11, base_family = "")
base_size, base_family
|
Base font size (pt) and family. |
A ggplot2 theme.
library(ggplot2) p <- read_rhylthyme(system.file("extdata", "breakfast_schedule.json", package = "rhylthyme")) ggplot(p) + geom_rhylthyme() + theme_rhylthyme()library(ggplot2) p <- read_rhylthyme(system.file("extdata", "breakfast_schedule.json", package = "rhylthyme")) ggplot(p) + geom_rhylthyme() + theme_rhylthyme()
Lists every problem the program schema finds, each tied to the step (or
track) it is in. read_rhylthyme() runs the same check and stops on the
first invalid program; use this to see all the problems as a table.
validate_rhylthyme(x)validate_rhylthyme(x)
x |
A program: anything |
A data frame with one row per problem (none when the program is
valid): track_id, step_id (NA where the problem is not inside a
track or step, or the step has no id), where (the field, relative to
the step or track), message and path (a JSON pointer into the
program).
validate_rhylthyme('{"name": "Draft", "tracks": [{"trackId": "a", "steps": [{"name": "x"}]}]}')validate_rhylthyme('{"name": "Draft", "tracks": [{"trackId": "a", "steps": [{"name": "x"}]}]}')