library(designit)
library(ggplot2)
library(dplyr)
library(tidyr)

Example 3: 3 plates with different dimension and different sample group sizes

We simulate one ordinary 96 well plate and two smaller ones with sizes 6x8 and 4x6, respectively. There are 3 experimental groups as well with sample sizes of 69, 30 and 69, respectively. This example should demonstrate that an empirically determined normalization of the scores yield 3 comparable numerical values, independent of the different plate and group sizes.

Again, a first optimization aims to achieve same group allocation on each plate, while the second run takes care of the sample distribution on each plate.

We use assign_random in this example to start from a more balanced initial position as compared to example 2.

Aggregation of scores is done by the L2s method (square of L2 norm). Because of the comparable numerical range of scores, also the worst_score method could be used for aggregation. However, the L2s method always takes into account all individual scores, providing more stability in case the 3 plate scores are not exactly normalized.

# Setting up the batch container

example3 <- BatchContainer$new(
  dimensions = c(
    plate = 3,
    row = 8, col = 12
  ),
  exclude = dplyr::bind_rows(
    tidyr::crossing(plate = 2, row = 1:8, col = 1:12) |> dplyr::filter(row > 6 | col > 8),
    tidyr::crossing(plate = 3, row = 1:8, col = 1:12) |> dplyr::filter(row > 4 | col > 6)
  )
)


# Assign samples randomly to start from a better initial state
example3 <- assign_random(example3,
  samples = tibble::tibble(
    Group = rep.int(c("Grp 1", "Grp 2", "Grp3"),
      times = c(69, 30, 69)
    ),
    ID = 1:168
  )
)

scoring_f <- osat_score_generator(batch_vars = c("plate"), feature_vars = c("Group"))
set.seed(42)
bc <- optimize_design(
  example3,
  scoring = scoring_f,
  quiet = TRUE,
  max_iter = 150,
  n_shuffle = 2,
  acceptance_func = mk_simanneal_acceptance_func(mk_simanneal_temp_func(T0 = 1000, alpha = 0.5)),
)
bc$trace$elapsed
#> Time difference of 1.534469 secs
plot_plate(bc,
  plate = plate, row = row, column = col, .color = Group,
  title = "Ex3: Dealing with plates of different size\nStep 1: after distributing groups across plates"
)

scoring_f <- mk_plate_scoring_functions(bc,
  plate = "plate", row = "row",
  column = "col", group = "Group"
)

bc$score(scoring_f)
#>   Plate 1   Plate 2   Plate 3 
#>  9.706637  9.585770 10.419567
set.seed(42)
bc <- optimize_design(
  bc,
  scoring = scoring_f,
  max_iter = 300,
  shuffle_proposal_func = mk_subgroup_shuffling_function(
    subgroup_vars = c("plate"),
    n_swaps = c(rep(5, 500), rep(3, 1500), rep(2, 3000), rep(1, 5000))
  ),
  # acceptance_func = mk_simanneal_acceptance_func(mk_simanneal_temp_func(T0 = 10000, alpha = 1)),
  aggregate_scores_func = L2s_norm,
  quiet = TRUE
)
bc$trace$elapsed
#> Time differences in secs
#> [1] 1.534469 3.973510

bc$score(scoring_f)
#>  Plate 1  Plate 2  Plate 3 
#> 8.974408 8.253074 7.980756
plot_plate(bc,
  plate = plate, row = row, column = col, .color = Group,
  title = "Ex3: Dealing with plates of different size\nStep 2: after swapping samples within plates"
)