Computing population lags from distribution of single-cell lags

gc_sim_params <- list(lbd_1 = 1/(49*60), # in sec (coarse estimation from pop growth curves)
                     lbd_2 = 1/(58*60),
                     N_max = 1e9,
                     dilution = 1600,
                     F_sw = 1/4, # fraction of final OD at which the switch occurs
                     gr_lags = 0 # no lag (replace with a vector of lags to specify a distribution)
                     )

simul_gc <- function(.pars, .n_quantiles=101, .t_step=60) {
  # browser()
  t_sw <- log(.pars$dilution  * .pars$F_sw) / log(2) / .pars$lbd_1
  t_max <- t_sw + log(.pars$dilution  * (1-.pars$F_sw)) / log(2) / .pars$lbd_2 + 
    max(.pars$gr_lags[is.finite(.pars$gr_lags)])
  .gcs <- tibble(k=seq(0, 1, length.out=.n_quantiles)) %>% mutate(lag=quantile(.pars$gr_lags, k, na.rm=TRUE)) %>% 
    rowwise() %>% mutate(data=map(lag, function(.l) tibble(t=seq(t_sw, t_max, .t_step)) %>% 
                                    mutate(n_k=ifelse(t-t_sw>.l, 2^(.pars$lbd_2*(t-t_sw-.l)), 1))
      ))
  .gc <- tibble(t=seq(0, t_sw, .t_step)) %>% 
    mutate(n=.pars$N_max/.pars$dilution * 2^(.pars$lbd_1*t)) %>% 
    bind_rows(.gcs %>% unnest() %>% group_by(t) %>% 
                summarise(n=sum(n_k)/length(n_k) * .pars$N_max*.pars$F_sw)) %>% 
    mutate(t=t-t_sw)
}

# gc_sim_params %>%
#   modify_at("gr_lags", ~
#             mycells_switching %>% ungroup() %>%
#               filter(!date %in% discarded_dates) %>%
#               filter(!discard_arrested) %>%
#               filter(str_detect(condition, '^switch_[0-9]+h$')) %>%
#               filter(switch_idx==1) %>%
#               mutate(growth_lag=ifelse(growth_lag>240*60, Inf, growth_lag) ) %>%
#               pull(growth_lag)
#             # ggplot(aes(growth_lag/60, y=..density..)) +
#             # stat_density(adjust = 1/1.2) +
#             # geom_freqpoly(binwidth=3, col='red') +
#             # NULL) %>%
#   ) %>%
#   simul_gc() %>%
#   filter(n<2e9) %>%
#   ggplot(aes(t, n)) +
#   geom_line() +
#   scale_x_hours(4) +
#   scale_y_log10() +
#   NULL
my_simgcs <- bind_rows(  
  tibble(type = 'gluc > lac (full memory)',
         pars = list(gc_sim_params %>% 
           modify_at("gr_lags", ~0)) ,
  ),
  tibble(type = 'gluc > lac (naive)',
         pars = list(gc_sim_params %>% 
           modify_at("gr_lags", ~
                       mycells_switching %>% ungroup() %>% 
                       filter(!date %in% discarded_dates) %>%
                       filter(!discard_arrested) %>% 
                       filter(str_detect(condition, '^switch_[0-9]+h$')) %>%
                       filter(switch_idx==1) %>%
                       mutate(growth_lag=ifelse(growth_lag>240*60, Inf, growth_lag) ) %>% 
                       pull(growth_lag) )),
  ),
  tibble(type = 'gluc + lac > lac',
         pars = list(gc_sim_params %>% 
               modify_at("gr_lags", ~
                mycells_switching %>% ungroup() %>% 
                filter(!date %in% discarded_dates) %>%
                filter(!discard_arrested) %>% 
                filter(str_detect(condition, 'switch_glcLac_lac')) %>%
                filter(switch_idx==1) %>%
                mutate(growth_lag=ifelse(growth_lag>240*60, Inf, growth_lag) ) %>% 
                pull(growth_lag) )),
  ),
  tibble(type = 'glyc > lac',
         pars = list(gc_sim_params %>% 
               modify_at("gr_lags", ~
                mycells_switching %>% ungroup() %>% 
                filter(!date %in% discarded_dates) %>%
                filter(str_detect(condition, 'switch_gly_lac')) %>%
                filter(switch_idx==1) %>%
                mutate(growth_lag=ifelse(growth_lag>240*60, Inf, growth_lag) ) %>% 
                pull(growth_lag) )),
  ),
  tibble(type = 'gluc > lac (short only)',
         pars = list(gc_sim_params %>% 
           modify_at("gr_lags", ~
                mycells_switching %>% ungroup() %>% 
                filter(!date %in% discarded_dates) %>%
                filter(!discard_arrested) %>% 
                filter(str_detect(condition, 'switch_glcLac_lac')) %>%
                filter(switch_idx==1, growth_lag<50*60) %>%
                mutate(growth_lag=ifelse(growth_lag>240*60, Inf, growth_lag) ) %>% 
                pull(growth_lag) )),
  ),
  tibble(type = 'gluc > lac (long only)',
         pars = list(gc_sim_params %>% 
           modify_at("gr_lags", ~
                mycells_switching %>% ungroup() %>% 
                filter(!date %in% discarded_dates) %>%
                filter(!discard_arrested) %>% 
                filter(str_detect(condition, 'switch_glcLac_lac')) %>%
                filter(switch_idx==1, growth_lag>=50*60) %>%
                mutate(growth_lag=ifelse(growth_lag>240*60, Inf, growth_lag) ) %>% 
                pull(growth_lag) )),
  ),
) %>% 
  mutate(simul=map(pars, simul_gc))
(myplots[['simul_gcs']] <- 
   my_simgcs %>% 
   mutate(type=fct_relevel(type, 'gluc > lac (naive)', 'gluc > lac (full memory)', 
                           'gluc + lac > lac',  'glyc > lac',  'gluc > lac (short only)'),
          pars=NULL) %>% 
   unnest(simul) %>% 
   filter(between(n, 8e7, 1.2e9)) %>%
   ggplot(aes(t/60, n, col=type)) +
   geom_line() +
   # geom_point() +
   # geom_hline(yintercept = 7e8) +
   scale_y_log10() +
   coord_cartesian(xlim=c(-40, 200), ylim=c(1.5e8, 1e9)) +
   scale_color_manual(values=c( # match the colour of single-cell lags plot
     'gluc > lac (naive)'=ggCustomTJ::qual_cols[2], 'gluc > lac (full memory)'=ggCustomTJ::qual_cols[4], 
     'gluc + lac > lac'=ggCustomTJ::qual_cols[1],  'glyc > lac'=ggCustomTJ::qual_cols[3],  
     'gluc > lac (short only)'=ggCustomTJ::qual_cols[5], 'gluc > lac (long only)'=ggCustomTJ::qual_cols[7]),
          labels=c('gluc \u2794 lac (naive)', 'gluc \u2794 lac (full memory)', 
              'gluc + lac \u2794 lac',  'glyc \u2794 lac',  'gluc \u2794 lac (short only)', 
              'gluc \u2794 lac (long only)')) +
   labs(x='time (min)', y='population size') +
   NULL)

(myplots[['simul_lags']] <- 
   my_simgcs %>% 
   mutate(type=fct_relevel(type, 'gluc > lac (naive)', 'gluc + lac > lac', 'glyc > lac', 
            'gluc > lac (full memory)', 'gluc > lac (short only)', 'gluc > lac (long only)') ) %>% 
   mutate(
     mod = map(simul, ~ lm(log(n)~t, filter(.x, between(n, 1e10, 1e11)))),
     # i = map_dbl(mod, ~ coefficients(.x)[1]),
     # s = map_dbl(mod, ~ coefficients(.x)[2]),
     # mod_intercept = -i/mean(s),
     mod_intercept = map_dbl(mod, ~ -coefficients(.x)[1] / coefficients(.x)[2]),
     lag = mod_intercept - mod_intercept[type=='gluc > lac (full memory)'],
     p_short = map_dbl(pars, ~ sum(.x$gr_lags/60 < 50, na.rm=T) / sum(!is.na(.x$gr_lags)) ),
   ) %>% 
   # filter(lag > 0) %>% 
   ggplot(aes(p_short, lag/60 / 58, col=type)) +
   geom_point(size=3) +
   expand_limits(x = 0, y = 0) + 
   scale_color_manual(values=c( # match the colour of single-cell lags plot
     'gluc > lac (naive)'=ggCustomTJ::qual_cols[2], 'gluc + lac > lac'=ggCustomTJ::qual_cols[1],  
     'glyc > lac'=ggCustomTJ::qual_cols[3], 'gluc > lac (full memory)'=ggCustomTJ::qual_cols[4], 
     'gluc > lac (short only)'=ggCustomTJ::qual_cols[5], 'gluc > lac (long only)'=ggCustomTJ::qual_cols[7]),
     labels=c('gluc \u2794 lac', 'gluc + lac \u2794 lac',  'glyc \u2794 lac',  
              'gluc \u2794 lac (no arrest)', 'gluc \u2794 lac (short only)', 'gluc \u2794 lac (long only)')) +
   labs(x = 'fraction of short growth lags', y = 'population growth lag \n(doublings in lactose)') +
   NULL)