Creates the trial and its plots in a Breedbase database through BrAPI, in
a breeding program and, optionally, a folder of your choice. Works for designs from
augmented_row_column_design(), augmented_prep_design(),
resolvable_row_column_design(), and agricolae designs converted with
as_breedbase_design() or prepared with prepare_breedbase_trial().
Usage
save_breedbase(
design,
con = NULL,
program = NULL,
folder = NULL,
trial_name,
year,
location = NULL,
description,
trial_type = "phenotyping_trial",
design_type = NULL,
plot_names = NULL,
plot_name_pattern = "{trial}_{accession}_{block}_{rep}",
create_folder = FALSE,
dry_run = FALSE,
confirm = interactive()
)Arguments
- design
A design object, including the result of
as_breedbase_design()orprepare_breedbase_trial(). For a prepared trial, recorded trial name, year, location, program, description, folder and trial type are used when their arguments are omitted. Explicit arguments override them.- con
A connection from
breedbase_login().- program
Breeding program name.
- folder
Optional folder inside the program. Without a folder (the default,
NULL) the trial is saved directly in the breeding program. An existing folder is used as it is; a new one is created whencreate_folder = TRUE.- trial_name
Name of the new trial (must not exist yet). In the names saved in Breedbase (trial, plot and new folder names, and the location part of p-rep trial names) spaces and special characters such as
% $ ( ) { } [ ] \\ / < > *are replaced with"_"(only letters, digits,_,-and.are kept), e.g."Alcobaca (BA)"gives"Alcobaca_BA". Accession and location names are kept as they are, to match Breedbase.[ ]: R:%20
- year
Year of the trial.
- location
Breedbase location name. For p-rep designs, a named vector mapping the design's locations to Breedbase locations, e.g.
c(North = "Ibadan", South = "Ubiaja"); by default the design's location names are used.- description
Description of the trial (required), e.g. its purpose, material and season:
"Advanced yield trial of 108 lines and 4 checks, Ibadan 2026". It is shown on the trial page in Breedbase.- trial_type
Breedbase trial type, e.g.
"Preliminary Yield Trial". Types the database does not know are saved as a miscellaneous trial.- design_type
Breedbase design type. Defaults to
"Augmented"for augmented row-column designs,"p-rep"for p-rep designs and"Alpha"(rows as incomplete blocks within replicates) for resolvable row-column designs. Converted agricolae designs use the type selected byas_breedbase_design().- plot_names
Optional plot names given by you: either a character vector with one name per plot, in the row order of
design$design, or the name of a column ofdesign$designthat holds them. Names must be unique.- plot_name_pattern
Pattern for automatic plot names, used when
plot_namesisNULL. The default"{trial}_{accession}_{block}_{rep}"gives names like"AYT_2026_LINE_007_3_1". Available fields:{trial}(the Breedbase trial name),{accession},{block},{rep},{plot}(plot number),{row}and{col}. If a pattern gives the same name to two plots (the same accession twice in one block and rep), the plot number is added to those names.- create_folder
Logical. Create
folderif it does not exist.- dry_run
Logical. Make all checks but write nothing.
- confirm
Logical. Ask before writing (default in interactive sessions).
Value
Invisibly, a tibble with one row per Breedbase trial: location,
trial name, trial id, number of plots sent and found after saving, and
the address of the trial page. With dry_run = TRUE and no connection,
a list with the trial and plot data that would be sent.
Details
Before anything is written, every name is checked: the breeding program,
the folder if given (created when create_folder = TRUE), the location(s), that
every entry and check already exists as an accession, and that the trial
name is free. In an interactive session you are then asked to confirm.
After saving, the plots are read back from Breedbase to verify the upload.
Each plot is saved with its name, plot number, row and column, rep, block
and whether it is a check. Plot names are made automatically from the
trial name, accession, block and rep (see plot_name_pattern), or you can
give your own with plot_names. Plot names must be unique in the whole
database, which is checked before saving. A multi-location p-rep design becomes one Breedbase
trial per location, named "<trial_name>_<location>". Filler plots of
resolvable row-column designs are not saved.
Run first with dry_run = TRUE: all the checks are made, but nothing is
written. Without a connection, dry_run = TRUE returns the data that would
be sent, without contacting any server.
Slow servers
Accessions are searched 25 names at a time, because Breedbase looks up
the pedigree of each one. If the server times out (HTTP 504, 502, 503 or
429), the batch is split in half and tried again, so a busy server is
slower but still works. A line is printed after each batch with the names
done and the time.
Accessions found are remembered until R is restarted, so
save_breedbase() after breedbase_check() does not search them again.
When creating the folder, the trial or its plots times out, the save
does not stop: the server may still finish the job, so it checks for the
result every 20 seconds for 3 minutes, and tries once more if it is not
there (Breedbase refuses names that already exist, so this cannot make
duplicates). If a save is cut off anyway, run save_breedbase() again:
an existing folder is used, and a trial left without plots gets its plots.
Settings: options(breedtools.write_wait = 30, breedtools.write_checks = 10). Settings: options(breedtools.germplasm_batch = 10) for smaller batches, options(breedtools.breedbase_timeout = 600) to
wait longer (seconds) for each answer.
Examples
rc <- augmented_row_column_design(paste0("G", 1:108), paste0("C", 1:4),
12, 12, 4, 4, n_candidates = 5, seed = 1)
# What would be sent (no server needed):
payload <- save_breedbase(rc, trial_name = "AYT_2026_Ithaca", year = 2026,
location = "Ithaca",
description = "Advanced yield trial of 108 lines and 4 checks",
dry_run = TRUE)
#> Dry run without a connection: returning the data that would be sent.
str(payload$studies[[1]], max.level = 1)
#> List of 6
#> $ studyName : chr "AYT_2026_Ithaca"
#> $ studyDescription : chr "Advanced yield trial of 108 lines and 4 checks"
#> $ studyType : chr "phenotyping_trial"
#> $ seasons :List of 1
#> $ experimentalDesign:List of 2
#> $ additionalInfo :List of 1
payload$plots[[1]][[1]]
#> $observationUnitName
#> [1] "AYT_2026_Ithaca_G51_1_1"
#>
#> $germplasmName
#> [1] "G51"
#>
#> $observationUnitPosition
#> $observationUnitPosition$observationLevel
#> $observationUnitPosition$observationLevel$levelName
#> [1] "plot"
#>
#> $observationUnitPosition$observationLevel$levelCode
#> [1] "1"
#>
#>
#> $observationUnitPosition$observationLevelRelationships
#> $observationUnitPosition$observationLevelRelationships[[1]]
#> $observationUnitPosition$observationLevelRelationships[[1]]$levelName
#> [1] "rep"
#>
#> $observationUnitPosition$observationLevelRelationships[[1]]$levelCode
#> [1] "1"
#>
#>
#> $observationUnitPosition$observationLevelRelationships[[2]]
#> $observationUnitPosition$observationLevelRelationships[[2]]$levelName
#> [1] "block"
#>
#> $observationUnitPosition$observationLevelRelationships[[2]]$levelCode
#> [1] "1"
#>
#>
#>
#> $observationUnitPosition$entryType
#> [1] "TEST"
#>
#> $observationUnitPosition$positionCoordinateX
#> [1] "1"
#>
#> $observationUnitPosition$positionCoordinateXType
#> [1] "GRID_COL"
#>
#> $observationUnitPosition$positionCoordinateY
#> [1] "1"
#>
#> $observationUnitPosition$positionCoordinateYType
#> [1] "GRID_ROW"
#>
#>
if (FALSE) { # \dontrun{
con <- breedbase_login("https://cassavabase.org", "jdoe")
save_breedbase(rc, con, program = "IITA", folder = "AYT 2026",
trial_name = "AYT_2026_Ibadan", year = 2026, location = "Ibadan",
description = "Advanced yield trial of 108 lines and 4 checks, Ibadan 2026",
create_folder = TRUE, dry_run = TRUE) # check first
save_breedbase(rc, con, program = "IITA", folder = "AYT 2026",
trial_name = "AYT_2026_Ibadan", year = 2026, location = "Ibadan",
description = "Advanced yield trial of 108 lines and 4 checks, Ibadan 2026")
} # }