---
title: "Quantifying antibody kinetics and RNA detection during early-phase SARS-CoV-2 infection by time since symptom onset"
author: "Borremans Benny, Gamble Amandine, Prager KC, Helman Sarah K, McClain Abby M, Cox Caitlin, Savage Van, Lloyd-Smith James O"
output:
  html_document: 
    code_folding: hide
    number_sections: yes
    theme: united
    toc: yes
    toc_float: yes
  pdf_document:
    toc: yes
---


```{r global_options, include = FALSE}
knitr::opts_chunk$set(echo = TRUE, warning = FALSE, message = FALSE)
library(ggplot2)
library(kableExtra)
library(dplyr)
library(easyPubMed)
library(readxl)
library(RColorBrewer)
library(patchwork)
library(binom)
library(lme4)
library(tidyr)
library(ggridges)

# define MCMC JAGS Gompertz

library(rjags)
library(R2OpenBUGS)


jags.gompertz.mod = function(){
       
       # priors
       for(j in 1:N.id){
              peak.titer[j] ~ dnorm(peak.titer.mean.hyper, peak.titer.tau.hyper)
              displacement[j] ~ dnorm(displacement.mean.hyper,displacement.tau.hyper)
              growth.rate[j] ~ dnorm(growth.rate.mean.hyper,growth.rate.tau.hyper)
       }
       
       sigma ~ dunif(0,50)
       tau <- 1/(sigma*sigma)
       
       
       #hyperpriors
       peak.titer.mean.hyper ~ dunif(0,5)
       peak.titer.sd.hyper ~ dgamma(1,1)
       peak.titer.tau.hyper <- 1/(peak.titer.sd.hyper*peak.titer.sd.hyper)
       
       displacement.mean.hyper ~ dnorm(100,1/(10*10))
       displacement.sd.hyper ~ dunif(0,200)
       displacement.tau.hyper <- 1/(displacement.sd.hyper*displacement.sd.hyper)
       
       growth.rate.mean.hyper ~ dunif(0,5)
       growth.rate.sd.hyper ~ dunif(0,100)
       growth.rate.tau.hyper <- 1/(growth.rate.sd.hyper*growth.rate.sd.hyper)
       
       # likelihood
       for(i in 1:length(time)){
              titer.pred[i] <- peak.titer[id[i]] * exp(-displacement[id[i]] * exp(-growth.rate[id[i]]*time[i]))
              titer[i] ~ dnorm(titer.pred[i], tau)
       }
}


model.file = "jags_gompertz.txt"
write.model(jags.gompertz.mod,model.file)






# load custom functions


# create IgG and IgM long data for bootstrap


# create new dataframe, prepare for boostrapping
# for each individual:
# id
# exact time when given
# start and stop time when given
# mean and sd when given
# assay used
# antigen used
# species
# location
# severity
# time units (symptom vs exposure)


create.long.df.for.bootstrap.IgG.IgM = function(alldata){
       
       
       sc0 = data.frame(marker = NA, id = NA, start.time = NA, stop.time = NA, mean.time = NA, sd.time = NA, assay = NA, antigen = NA, host = NA, location = NA, severity = NA, time.units = NA, time.period = NA)
       sc0 = sc0[F,]
       
       uid = unique(alldata$id)
       idx.sc0 = 1
       for(i in 1:length(uid)){
              
              s0a = alldata[which(alldata$id == uid[i]),]
              
              
              
              if(any(s0a$marker %in% c("IgG","IgM","NT Ab","IgG_IgM","Total Ab"))){    # only keep individuals with IgG or IgM data
                     
                     
                     
                     
                     # for IgG     
                     if("IgG" %in% s0a$marker) {
                            s0 = s0a[which(s0a$marker == "IgG"),]
                            
                            # for individuals that do not have proportion positive data
                            if(is.na(s0$prop.pos[1])) {   
                                   
                                   # explicit reporting of seroconversion time for one individual. can be period.
                                   if(nrow(s0) == 1 & is.na(s0$test.type[1]) & (s0$first.detection[1] == "yes" & !is.na(s0$first.detection[1]))) {
                                          
                                          # create empty rows to fill, one for each individual (sample size)
                                          sc0[idx.sc0:(idx.sc0+s0$sample.size-1),] = NA    
                                          
                                          # fill empty rows
                                          sc0[idx.sc0:(idx.sc0+s0$sample.size-1),] = rep(c(s0$marker, s0$id, s0$time.start, s0$time.stop, NA, NA, s0$assay, s0$antigen, s0$host, s0$location, s0$severity, s0$time.cat, s0$time.period),each=s0$sample.size)
                                          
                                          # change index to next empty row to fill
                                          idx.sc0 = idx.sc0 + s0$sample.size
                                          
                                   }
                                   
                                   
                                   
                                   
                                   # explicit reporting of seroconversion time for multiple individuals, mean value
                                   if(nrow(s0) == 1 & s0$sample.size[1] > 1 & (s0$first.detection[1] == "yes" & !is.na(s0$first.detection[1])) & s0$test.type[1] == "mean") {
                                          
                                          # create empty rows to fill, one for each individual (sample size)
                                          sc0[idx.sc0:(idx.sc0+s0$sample.size-1),] = NA    
                                          
                                          # fill empty rows
                                          sc0[idx.sc0:(idx.sc0+s0$sample.size-1),] = rep(c(s0$marker, s0$id, NA, NA, s0$time.start, s0$time.error, s0$assay, s0$antigen, s0$host, s0$location, s0$severity, s0$time.cat, s0$time.period),each=s0$sample.size)
                                          
                                          # change index to next empty row to fill
                                          idx.sc0 = idx.sc0 + s0$sample.size
                                          
                                   }
                                   
                                   
                                   
                                   
                                   # get seroconversion time from individual time series. periods may be too long, check later!
                                   # must start with 0, that will filter out some results with periods spanning day 0 to time t, but probably not all
                                   # for exact times and periods. (not for means/medians)
                                   if(nrow(s0) > 1 & all(s0$sample.size == 1) & s0$time.estimate.cat[1] %in% c("Exact","Period")) {
                                          
                                          # sort time
                                          s0 = s0[order(s0$time.start),]
                                          
                                          # skip if the first sample is positive
                                          if(s0$test.pos.neg[1] == "NEG" & any(s0$test.pos.neg == "POS")) {
                                                 
                                                 # get the index of the first positive sample
                                                 idx.first.pos = which(s0$test.pos.neg == "POS")[1]
                                                 
                                                 # create empty row to fill
                                                 sc0[idx.sc0,] = NA   
                                                 
                                                 # fill empty row. seroconversion time estimated to be between the end time of the preceding sample, and the end time of the current sample.    
                                                 sc0[idx.sc0,] = c(s0$marker[1], s0$id[1], s0$time.stop[idx.first.pos-1], s0$time.stop[idx.first.pos], NA, NA, s0$assay[1], s0$antigen[1], s0$host[1], s0$location[1], s0$severity[1], s0$time.cat[1], (s0$time.stop[idx.first.pos] - s0$time.stop[idx.first.pos-1]))
                                                 
                                                 # change index to next empty row to fill
                                                 idx.sc0 = idx.sc0 + 1
                                          }
                                   }   
                            }
                            
                            
                            
                            
                            # for cumulative seroconversion curves
                            if(!is.na(s0$cumul.seroconv[1])) {
                                   if(s0$cumul.seroconv[1] == "yes") { 
                                          
                                          
                                          # sort time
                                          s0 = s0[order(s0$time.start),]
                                          
                                          for(iii in 2:nrow(s0)){
                                                 
                                                 
                                                 # how many seroconverted since the last 
                                                 N.seroconv = round((s0$sample.size[1]*sum(s0$prop.pos[iii]))-(s0$sample.size[1]*sum(s0$prop.pos[iii-1])))
                                                 if(N.seroconv > 0) {
                                                        
                                                        
                                                        
                                                        for(iiii in idx.sc0:(idx.sc0+N.seroconv-1)) {
                                                               
                                                               # create empty row(s) to fill
                                                               
                                                               sc0[idx.sc0,] = NA   
                                                               
                                                               sc0[idx.sc0,] = c(s0$marker[1], s0$id[1], s0$time.start[iii],  s0$time.start[iii], NA, NA, s0$assay[1], s0$antigen[1], s0$host[1], s0$location[1], s0$severity[1], s0$time.cat[1], (s0$time.stop[iii] - s0$time.stop[iii-1]))
                                                               # change index to next empty row to fill
                                                               idx.sc0 = idx.sc0 + 1
                                                               
                                                        }
                                                        
                                                        
                                                 }
                                                 
                                          }
                                          
                                          
                                          
                                   }
                            }
                            
                            
                     }
                     
                     
                     
                     # for IgM    
                     if("IgM" %in% s0a$marker) {
                            s0 = s0a[which(s0a$marker == "IgM"),]
                            
                            
                            # for individuals that do not have proportion positive data
                            if(is.na(s0$prop.pos[1])) { 
                                   
                                   # explicit reporting of seroconversion time for one individual. can be period.
                                   if(nrow(s0) == 1 & is.na(s0$test.type[1]) & (s0$first.detection[1] == "yes" & !is.na(s0$first.detection[1]))) {
                                          
                                          # create empty rows to fill, one for each individual (sample size)
                                          sc0[idx.sc0:(idx.sc0+s0$sample.size-1),] = NA    
                                          
                                          # fill empty rows
                                          sc0[idx.sc0:(idx.sc0+s0$sample.size-1),] = rep(c(s0$marker, s0$id, s0$time.start, s0$time.stop, NA, NA, s0$assay, s0$antigen, s0$host, s0$location, s0$severity, s0$time.cat, s0$time.period),each=s0$sample.size)
                                          
                                          # change index to next empty row to fill
                                          idx.sc0 = idx.sc0 + s0$sample.size
                                          
                                   }
                                   
                                   
                                   
                                   
                                   # explicit reporting of seroconversion time for multiple individuals, mean value
                                   if(nrow(s0) == 1 & s0$sample.size[1] > 1 & (s0$first.detection[1] == "yes" & !is.na(s0$first.detection[1])) & s0$test.type[1] == "mean") {
                                          
                                          # create empty rows to fill, one for each individual (sample size)
                                          sc0[idx.sc0:(idx.sc0+s0$sample.size-1),] = NA    
                                          
                                          # fill empty rows
                                          sc0[idx.sc0:(idx.sc0+s0$sample.size-1),] = rep(c(s0$marker, s0$id, NA, NA, s0$time.start, s0$time.error, s0$assay, s0$antigen, s0$host, s0$location, s0$severity, s0$time.cat, s0$time.period),each=s0$sample.size)
                                          
                                          # change index to next empty row to fill
                                          idx.sc0 = idx.sc0 + s0$sample.size
                                          
                                   }
                                   
                                   
                                   
                                   
                                   # get seroconversion time from individual time series. periods may be too long, check later!
                                   # must start with 0, that will filter out some results with periods spanning day 0 to time t, but probably not all
                                   # for exact times and periods. (not for means/medians)
                                   if(nrow(s0) > 1 & all(s0$sample.size == 1) & s0$time.estimate.cat[1] %in% c("Exact","Period")) {
                                          
                                          # sort time
                                          s0 = s0[order(s0$time.start),]
                                          
                                          # skip if the first sample is positive
                                          if(s0$test.pos.neg[1] == "NEG" & any(s0$test.pos.neg == "POS")) {
                                                 
                                                 # get the index of the first positive sample
                                                 idx.first.pos = which(s0$test.pos.neg == "POS")[1]
                                                 
                                                 # create empty row to fill
                                                 sc0[idx.sc0,] = NA   
                                                 
                                                 # fill empty row. seroconversion time estimated to be between the end time of the preceding sample, and the end time of the current sample.    
                                                 sc0[idx.sc0,] = c(s0$marker[1], s0$id[1], s0$time.stop[idx.first.pos-1], s0$time.stop[idx.first.pos], NA, NA, s0$assay[1], s0$antigen[1], s0$host[1], s0$location[1], s0$severity[1], s0$time.cat[1], (s0$time.stop[idx.first.pos] - s0$time.stop[idx.first.pos-1]))
                                                 
                                                 # change index to next empty row to fill
                                                 idx.sc0 = idx.sc0 + 1
                                          }
                                   }
                            }
                            
                            # for cumulative seroconversion curves
                            if(!is.na(s0$cumul.seroconv[1])) {
                                   if(s0$cumul.seroconv[1] == "yes") { 
                                          
                                          
                                          # sort time
                                          s0 = s0[order(s0$time.start),]
                                          
                                          for(iii in 2:nrow(s0)){
                                                 
                                                 
                                                 # how many seroconverted since the last 
                                                 N.seroconv = round((s0$sample.size[1]*sum(s0$prop.pos[iii]))-(s0$sample.size[1]*sum(s0$prop.pos[iii-1])))
                                                 if(N.seroconv > 0) {
                                                        
                                                        
                                                        
                                                        for(iiii in idx.sc0:(idx.sc0+N.seroconv-1)) {
                                                               
                                                               # create empty row(s) to fill
                                                               
                                                               sc0[idx.sc0,] = NA   
                                                               
                                                               sc0[idx.sc0,] = c(s0$marker[1], s0$id[1], s0$time.start[iii],  s0$time.start[iii], NA, NA, s0$assay[1], s0$antigen[1], s0$host[1], s0$location[1], s0$severity[1], s0$time.cat[1], (s0$time.stop[iii] - s0$time.stop[iii-1]))
                                                               # change index to next empty row to fill
                                                               idx.sc0 = idx.sc0 + 1
                                                               
                                                        }
                                                        
                                                        
                                                 }
                                                 
                                          }
                                          
                                          
                                          
                                   }
                            }
                            
                            
                            
                            
                     }
                     
                     
                     # for NT Ab   
                     if("NT Ab" %in% s0a$marker) {
                            s0 = s0a[which(s0a$marker == "NT Ab"),]
                            
                            # for individuals that do not have proportion positive data
                            if(is.na(s0$prop.pos[1])) { 
                                   
                                   # explicit reporting of seroconversion time for one individual. can be period.
                                   if(nrow(s0) == 1 & is.na(s0$test.type[1]) & (s0$first.detection[1] == "yes" & !is.na(s0$first.detection[1]))) {
                                          
                                          # create empty rows to fill, one for each individual (sample size)
                                          sc0[idx.sc0:(idx.sc0+s0$sample.size-1),] = NA    
                                          
                                          # fill empty rows
                                          sc0[idx.sc0:(idx.sc0+s0$sample.size-1),] = rep(c(s0$marker, s0$id, s0$time.start, s0$time.stop, NA, NA, s0$assay, s0$antigen, s0$host, s0$location, s0$severity, s0$time.cat, s0$time.period),each=s0$sample.size)
                                          
                                          # change index to next empty row to fill
                                          idx.sc0 = idx.sc0 + s0$sample.size
                                          
                                   }
                                   
                                   
                                   
                                   
                                   # explicit reporting of seroconversion time for multiple individuals, mean value
                                   if(nrow(s0) == 1 & s0$sample.size[1] > 1 & (s0$first.detection[1] == "yes" & !is.na(s0$first.detection[1])) & s0$test.type[1] == "mean") {
                                          
                                          # create empty rows to fill, one for each individual (sample size)
                                          sc0[idx.sc0:(idx.sc0+s0$sample.size-1),] = NA    
                                          
                                          # fill empty rows
                                          sc0[idx.sc0:(idx.sc0+s0$sample.size-1),] = rep(c(s0$marker, s0$id, NA, NA, s0$time.start, s0$time.error, s0$assay, s0$antigen, s0$host, s0$location, s0$severity, s0$time.cat, s0$time.period),each=s0$sample.size)
                                          
                                          # change index to next empty row to fill
                                          idx.sc0 = idx.sc0 + s0$sample.size
                                          
                                   }
                                   
                                   
                                   
                                   
                                   # get seroconversion time from individual time series. periods may be too long, check later!
                                   # must start with 0, that will filter out some results with periods spanning day 0 to time t, but probably not all
                                   # for exact times and periods. (not for means/medians)
                                   if(nrow(s0) > 1 & all(s0$sample.size == 1) & s0$time.estimate.cat[1] %in% c("Exact","Period")) {
                                          
                                          # sort time
                                          s0 = s0[order(s0$time.start),]
                                          
                                          # skip if the first sample is positive
                                          if(s0$test.pos.neg[1] == "NEG" & any(s0$test.pos.neg == "POS")) {
                                                 
                                                 # get the index of the first positive sample
                                                 idx.first.pos = which(s0$test.pos.neg == "POS")[1]
                                                 
                                                 # create empty row to fill
                                                 sc0[idx.sc0,] = NA   
                                                 
                                                 # fill empty row. seroconversion time estimated to be between the end time of the preceding sample, and the end time of the current sample.    
                                                 sc0[idx.sc0,] = c(s0$marker[1], s0$id[1], s0$time.stop[idx.first.pos-1], s0$time.stop[idx.first.pos], NA, NA, s0$assay[1], s0$antigen[1], s0$host[1], s0$location[1], s0$severity[1], s0$time.cat[1], (s0$time.stop[idx.first.pos] - s0$time.stop[idx.first.pos-1]))
                                                 
                                                 # change index to next empty row to fill
                                                 idx.sc0 = idx.sc0 + 1
                                          }
                                   }
                            }
                            
                            
                            # for cumulative seroconversion curves
                            if(!is.na(s0$cumul.seroconv[1])) {
                                   if(s0$cumul.seroconv[1] == "yes") { 
                                          
                                          
                                          # sort time
                                          s0 = s0[order(s0$time.start),]
                                          
                                          for(iii in 2:nrow(s0)){
                                                 
                                                 
                                                 # how many seroconverted since the last 
                                                 N.seroconv = round((s0$sample.size[1]*sum(s0$prop.pos[iii]))-(s0$sample.size[1]*sum(s0$prop.pos[iii-1])))
                                                 if(N.seroconv > 0) {
                                                        
                                                        
                                                        
                                                        for(iiii in idx.sc0:(idx.sc0+N.seroconv-1)) {
                                                               
                                                               # create empty row(s) to fill
                                                               
                                                               sc0[idx.sc0,] = NA   
                                                               
                                                               sc0[idx.sc0,] = c(s0$marker[1], s0$id[1], s0$time.start[iii],  s0$time.start[iii], NA, NA, s0$assay[1], s0$antigen[1], s0$host[1], s0$location[1], s0$severity[1], s0$time.cat[1], (s0$time.stop[iii] - s0$time.stop[iii-1]))
                                                               # change index to next empty row to fill
                                                               idx.sc0 = idx.sc0 + 1
                                                               
                                                        }
                                                        
                                                        
                                                 }
                                                 
                                          }
                                          
                                          
                                          
                                   }
                            }
                     }
                     
                     
                     
                     # for Total Ab   
                     if("Total Ab" %in% s0a$marker) {
                            s0 = s0a[which(s0a$marker == "Total Ab"),]
                            
                            # for individuals that do not have proportion positive data
                            if(is.na(s0$prop.pos[1])) { 
                                   
                                   # explicit reporting of seroconversion time for one individual. can be period.
                                   if(nrow(s0) == 1 & is.na(s0$test.type[1]) & (s0$first.detection[1] == "yes" & !is.na(s0$first.detection[1]))) {
                                          
                                          # create empty rows to fill, one for each individual (sample size)
                                          sc0[idx.sc0:(idx.sc0+s0$sample.size-1),] = NA    
                                          
                                          # fill empty rows
                                          sc0[idx.sc0:(idx.sc0+s0$sample.size-1),] = rep(c(s0$marker, s0$id, s0$time.start, s0$time.stop, NA, NA, s0$assay, s0$antigen, s0$host, s0$location, s0$severity, s0$time.cat, s0$time.period),each=s0$sample.size)
                                          
                                          # change index to next empty row to fill
                                          idx.sc0 = idx.sc0 + s0$sample.size
                                          
                                   }
                                   
                                   
                                   
                                   
                                   # explicit reporting of seroconversion time for multiple individuals, mean value
                                   if(nrow(s0) == 1 & s0$sample.size[1] > 1 & (s0$first.detection[1] == "yes" & !is.na(s0$first.detection[1])) & s0$test.type[1] == "mean") {
                                          
                                          # create empty rows to fill, one for each individual (sample size)
                                          sc0[idx.sc0:(idx.sc0+s0$sample.size-1),] = NA    
                                          
                                          # fill empty rows
                                          sc0[idx.sc0:(idx.sc0+s0$sample.size-1),] = rep(c(s0$marker, s0$id, NA, NA, s0$time.start, s0$time.error, s0$assay, s0$antigen, s0$host, s0$location, s0$severity, s0$time.cat, s0$time.period),each=s0$sample.size)
                                          
                                          # change index to next empty row to fill
                                          idx.sc0 = idx.sc0 + s0$sample.size
                                          
                                   }
                                   
                                   
                                   
                                   
                                   # get seroconversion time from individual time series. periods may be too long, check later!
                                   # must start with 0, that will filter out some results with periods spanning day 0 to time t, but probably not all
                                   # for exact times and periods. (not for means/medians)
                                   if(nrow(s0) > 1 & all(s0$sample.size == 1) & s0$time.estimate.cat[1] %in% c("Exact","Period")) {
                                          
                                          # sort time
                                          s0 = s0[order(s0$time.start),]
                                          
                                          # skip if the first sample is positive
                                          if(s0$test.pos.neg[1] == "NEG" & any(s0$test.pos.neg == "POS")) {
                                                 
                                                 # get the index of the first positive sample
                                                 idx.first.pos = which(s0$test.pos.neg == "POS")[1]
                                                 
                                                 # create empty row to fill
                                                 sc0[idx.sc0,] = NA   
                                                 
                                                 # fill empty row. seroconversion time estimated to be between the end time of the preceding sample, and the end time of the current sample.    
                                                 sc0[idx.sc0,] = c(s0$marker[1], s0$id[1], s0$time.stop[idx.first.pos-1], s0$time.stop[idx.first.pos], NA, NA, s0$assay[1], s0$antigen[1], s0$host[1], s0$location[1], s0$severity[1], s0$time.cat[1], (s0$time.stop[idx.first.pos] - s0$time.stop[idx.first.pos-1]))
                                                 
                                                 # change index to next empty row to fill
                                                 idx.sc0 = idx.sc0 + 1
                                          }
                                   }
                            }
                            
                            
                            # for cumulative seroconversion curves
                            
                            if(!is.na(s0$cumul.seroconv[1])) {
                                   if(s0$cumul.seroconv[1] == "yes") { 
                                          
                                          
                                          # sort time
                                          s0 = s0[order(s0$time.start),]
                                          
                                          for(iii in 2:nrow(s0)){
                                                 
                                                 
                                                 # how many seroconverted since the last 
                                                 N.seroconv = round((s0$sample.size[1]*sum(s0$prop.pos[iii]))-(s0$sample.size[1]*sum(s0$prop.pos[iii-1])))
                                                 if(N.seroconv > 0) {
                                                        
                                                        
                                                        
                                                        for(iiii in idx.sc0:(idx.sc0+N.seroconv-1)) {
                                                               
                                                               # create empty row(s) to fill
                                                               
                                                               sc0[idx.sc0,] = NA   
                                                               
                                                               sc0[idx.sc0,] = c(s0$marker[1], s0$id[1], s0$time.start[iii],  s0$time.start[iii], NA, NA, s0$assay[1], s0$antigen[1], s0$host[1], s0$location[1], s0$severity[1], s0$time.cat[1], (s0$time.stop[iii] - s0$time.stop[iii-1]))
                                                               # change index to next empty row to fill
                                                               idx.sc0 = idx.sc0 + 1
                                                               
                                                        }
                                                        
                                                        
                                                 }
                                                 
                                          }
                                          
                                          
                                          
                                   }
                            }
                     }
                     
                     
                     
                     
                     # for IgG_IgM   
                     if("IgG_IgM" %in% s0a$marker) {
                            s0 = s0a[which(s0a$marker == "IgG_IgM"),]
                            
                            # for individuals that do not have proportion positive data
                            if(is.na(s0$prop.pos[1])) { 
                                   
                                   # explicit reporting of seroconversion time for one individual. can be period.
                                   if(nrow(s0) == 1 & is.na(s0$test.type[1]) & (s0$first.detection[1] == "yes" & !is.na(s0$first.detection[1]))) {
                                          
                                          # create empty rows to fill, one for each individual (sample size)
                                          sc0[idx.sc0:(idx.sc0+s0$sample.size-1),] = NA    
                                          
                                          # fill empty rows
                                          sc0[idx.sc0:(idx.sc0+s0$sample.size-1),] = rep(c(s0$marker, s0$id, s0$time.start, s0$time.stop, NA, NA, s0$assay, s0$antigen, s0$host, s0$location, s0$severity, s0$time.cat, s0$time.period),each=s0$sample.size)
                                          
                                          # change index to next empty row to fill
                                          idx.sc0 = idx.sc0 + s0$sample.size
                                          
                                   }
                                   
                                   
                                   
                                   
                                   # explicit reporting of seroconversion time for multiple individuals, mean value
                                   if(nrow(s0) == 1 & s0$sample.size[1] > 1 & (s0$first.detection[1] == "yes" & !is.na(s0$first.detection[1])) & s0$test.type[1] == "mean") {
                                          
                                          # create empty rows to fill, one for each individual (sample size)
                                          sc0[idx.sc0:(idx.sc0+s0$sample.size-1),] = NA    
                                          
                                          # fill empty rows
                                          sc0[idx.sc0:(idx.sc0+s0$sample.size-1),] = rep(c(s0$marker, s0$id, NA, NA, s0$time.start, s0$time.error, s0$assay, s0$antigen, s0$host, s0$location, s0$severity, s0$time.cat, s0$time.period),each=s0$sample.size)
                                          
                                          # change index to next empty row to fill
                                          idx.sc0 = idx.sc0 + s0$sample.size
                                          
                                   }
                                   
                                   
                                   
                                   
                                   # get seroconversion time from individual time series. periods may be too long, check later!
                                   # must start with 0, that will filter out some results with periods spanning day 0 to time t, but probably not all
                                   # for exact times and periods. (not for means/medians)
                                   if(nrow(s0) > 1 & all(s0$sample.size == 1) & s0$time.estimate.cat[1] %in% c("Exact","Period")) {
                                          
                                          # sort time
                                          s0 = s0[order(s0$time.start),]
                                          
                                          # skip if the first sample is positive
                                          if(s0$test.pos.neg[1] == "NEG" & any(s0$test.pos.neg == "POS")) {
                                                 
                                                 # get the index of the first positive sample
                                                 idx.first.pos = which(s0$test.pos.neg == "POS")[1]
                                                 
                                                 # create empty row to fill
                                                 sc0[idx.sc0,] = NA   
                                                 
                                                 # fill empty row. seroconversion time estimated to be between the end time of the preceding sample, and the end time of the current sample.    
                                                 sc0[idx.sc0,] = c(s0$marker[1], s0$id[1], s0$time.stop[idx.first.pos-1], s0$time.stop[idx.first.pos], NA, NA, s0$assay[1], s0$antigen[1], s0$host[1], s0$location[1], s0$severity[1], s0$time.cat[1], (s0$time.stop[idx.first.pos] - s0$time.stop[idx.first.pos-1]))
                                                 
                                                 # change index to next empty row to fill
                                                 idx.sc0 = idx.sc0 + 1
                                          }
                                   }
                            }
                            
                            
                            # for cumulative seroconversion curves
                            if(!is.na(s0$cumul.seroconv[1])) {
                                   if(s0$cumul.seroconv[1] == "yes") { 
                                          
                                          
                                          # sort time
                                          s0 = s0[order(s0$time.start),]
                                          
                                          for(iii in 2:nrow(s0)){
                                                 
                                                 
                                                 # how many seroconverted since the last 
                                                 N.seroconv = round((s0$sample.size[1]*sum(s0$prop.pos[iii]))-(s0$sample.size[1]*sum(s0$prop.pos[iii-1])))
                                                 if(N.seroconv > 0) {
                                                        
                                                        
                                                        
                                                        for(iiii in idx.sc0:(idx.sc0+N.seroconv-1)) {
                                                               
                                                               # create empty row(s) to fill
                                                               
                                                               sc0[idx.sc0,] = NA   
                                                               
                                                               sc0[idx.sc0,] = c(s0$marker[1], s0$id[1], s0$time.start[iii],  s0$time.start[iii], NA, NA, s0$assay[1], s0$antigen[1], s0$host[1], s0$location[1], s0$severity[1], s0$time.cat[1], (s0$time.stop[iii] - s0$time.stop[iii-1]))
                                                               # change index to next empty row to fill
                                                               idx.sc0 = idx.sc0 + 1
                                                               
                                                        }
                                                        
                                                        
                                                 }
                                                 
                                          }
                                          
                                          
                                          
                                   }
                            }
                     }
                     
                     
                     
              }
       }
       
       
       # convert some characters to numbers
       sc0 = sc0 %>% 
              mutate_at(vars(c(3:6,13)),as.numeric)
       
       return(sc0)
}




# boostrap first detection data hierarchical
# iteratively implements prior weights using rounds of increasing data set sizes
# in steps of 2 days, a new distribution is estimated and used as prior weights for the next round


bootstrap.first.detection.hierarchical = function(boot.dat, boot.iterations,lower.limit=0,max.period) {
       
       require(MASS)
       utp = sort(unique(boot.dat$time.period[which(boot.dat$time.period<=max.period)]))
       
       samp.days = 0:100
       prior.weights = data.frame(day = samp.days, prob = 1)
       
       
       for(tp in 1:length(utp)) {
              
              
              
              
              not.earlier.than.first.exact = F
              
              boot.samples = numeric(boot.iterations)
              
              boot0 = boot.dat[which(boot.dat$time.period <= utp[tp]),]
              
              set.seed(1234)
              for(i in 1:boot.iterations) {
                     
                     cur.idx = sample(1:nrow(boot0),1)
                     
                     # sample from time interval
                     if(!is.na(boot0$start.time[cur.idx])){
                            
                            cur.vec = boot0$start.time[cur.idx]:boot0$stop.time[cur.idx]
                            
                            cur.vec = cur.vec[!cur.vec<lower.limit]
                            
                            rescaled.weights = prior.weights$prob[which(prior.weights$day %in% cur.vec)] = prior.weights$prob[which(prior.weights$day %in% cur.vec)]/sum(prior.weights$prob[which(prior.weights$day %in% cur.vec)])
                            
                            cur.time = cur.vec[sample(length(cur.vec),1,prob = rescaled.weights)]    
                            # this is a workaround to avoid the quirky behavior of sample() when the length of the vector is 1. when that happens it samples from the sequence of the vector value to the number of samples, so e.g. if start time:stop time is 18, it samples from 18:1.   
                     }
                     
                     
                     # sample from mean +- SD time
                     if(!is.na(boot0$mean.time[cur.idx])){
                            
                            while(not.earlier.than.first.exact == T) {
                                   
                                   cur.norm = dnorm(prior.weights$day, mean = boot0$mean.time[cur.idx], sd = boot0$sd.time[cur.idx])
                                   prod.norm = cur.norm * prior.weights$prob
                                   
                                   rescaled.prod.norm = prod.norm/sum(prod.norm)
                                   
                                   cur.time = sample(prior.weights$day,1, prob = rescaled.prod.norm)
                                   
                                   if(cur.time < lower.limit) { 
                                          not.earlier.than.first.exact = T 
                                   } else {
                                          not.earlier.than.first.exact = F
                                   }
                            }
                     }
                     boot.samples[i] = cur.time
              }
              
              boot.samples.df = as.data.frame(boot.samples)
              
              # fit normal distribution
              norm.fit = MASS::fitdistr(boot.samples.df$boot.samples,densfun="normal")
              
              # for each possible day get prob dens from fitted normal distribution
              prior.weights = dnorm(x = samp.days, mean = norm.fit$estimate[1], sd = norm.fit$estimate[2])
              prior.weights = data.frame(day = samp.days, prob = prior.weights)
              
       }
       boot.samples.df = as.data.frame(boot.samples)
       return(boot.samples.df)
}


# wrapper function to get binomial confidence intervals for proportions


binom.wrap.fun = function(xx) { 
       bincidat = binom.confint(x = c(xx[1]), n = xx[2], conf.level = .95, methods = "exact")
       output = c(bincidat$lower, bincidat$upper)
       return(output)
}



# detection prob for every single day until day 30, then groups of 3 days to improve sample size
detection.prob = function(alldata){
       
       
       # sequence of days for which data are available
       all.days = seq(0:max(c(max(c(alldata$time.start,alldata$time.stop),na.rm=T))))
       
       # create empty dataframe
       probdat = data.frame(day = all.days, npos = 0, nneg = 0)
       
       uid = unique(alldata$id)
       
       for(i in 1:length(uid)){
              
              
              if(any(is.na(probdat[,2]))) break
              s0 = alldata[which(alldata$id == uid[i]),]
              
              # for which days is presence or absence known for this individual?
              
              
              # individual results
              if(s0$sample.size[1]==1) {
                     
                     
                     # no time series
                     if(nrow(s0)==1){
                            
                            
                            # Exact time    
                            if(s0$time.estimate.cat == "Exact") {
                                   
                                   # Exact times with reported presence/absence, one individual          
                                   # (e.g. individual A was positive on day X)  
                                   # Used as is  
                                   
                                   probdat$npos[which(probdat$day == s0$time.start)] = probdat$npos[which(probdat$day == s0$time.start)] + (s0$test.pos.neg=="POS")
                                   
                                   probdat$nneg[which(probdat$day == s0$time.start)] = probdat$nneg[which(probdat$day == s0$time.start)] + (s0$test.pos.neg=="NEG")
                                   
                            }
                            
                            
                            # Period   
                            if(s0$time.estimate.cat == "Period") {
                                   
                                   
                                   halfway.time = round((s0$time.stop+s0$time.start)/2)
                                   
                                   probdat$npos[which(probdat$day == halfway.time)] = probdat$npos[which(probdat$day == halfway.time)] + (s0$test.pos.neg=="POS")
                                   
                                   probdat$nneg[which(probdat$day == halfway.time)] = probdat$nneg[which(probdat$day == halfway.time)] + (s0$test.pos.neg=="NEG")
                                   
                            }
                            
                            
                     }
                     
                     
                     
                     #  time series
                     if(nrow(s0) > 1){
                            
                            # exact times
                            
                            pos.days = c()
                            neg.days = c()
                            
                            for(ii in 1:nrow(s0)){
                                   
                                   
                                   if(ii == 1) {
                                          
                                          if(all(s0$time.estimate.cat[ii:(ii+1)] == "Exact")) {
                                                 
                                                 # add result at current exact time
                                                 if(s0$test.pos.neg[ii]=="POS") pos.days = c(pos.days,s0$time.start[ii])
                                                 if(s0$test.pos.neg[ii]=="NEG") neg.days = c(neg.days,s0$time.start[ii])
                                                 
                                                 # fill results up to next time point if they have the same result
                                                 if(s0$test.pos.neg[ii] == s0$test.pos.neg[ii+1]) {
                                                        
                                                        if(s0$test.pos.neg[ii]=="POS") pos.days = c(pos.days, s0$time.start[ii]:s0$time.start[ii+1])
                                                        if(s0$test.pos.neg[ii]=="NEG") neg.days = c(neg.days, s0$time.start[ii]:s0$time.start[ii+1])
                                                        
                                                 }
                                                 
                                          }
                                          
                                   }
                                   
                                   if(ii > 1 & ii < nrow(s0)) {
                                          
                                          # add result at current exact time
                                          if(s0$test.pos.neg[ii]=="POS") pos.days = c(pos.days,s0$time.start[ii])
                                          if(s0$test.pos.neg[ii]=="NEG") neg.days = c(neg.days,s0$time.start[ii])
                                          
                                          if(all(s0$time.estimate.cat[ii:(ii+1)] == "Exact")) {
                                                 
                                                 if(s0$test.pos.neg[ii] == s0$test.pos.neg[ii+1]) {
                                                        
                                                        if(s0$test.pos.neg[ii]=="POS") pos.days = c(pos.days, s0$time.start[ii]:s0$time.start[ii+1])
                                                        if(s0$test.pos.neg[ii]=="NEG") neg.days = c(neg.days, s0$time.start[ii]:s0$time.start[ii+1])
                                                        
                                                 }
                                                 
                                          }
                                   }
                                   
                                   if(ii > 1 & ii == nrow(s0)) {
                                          
                                          # add result at current exact time
                                          if(s0$test.pos.neg[ii]=="POS") pos.days = c(pos.days,s0$time.start[ii])
                                          if(s0$test.pos.neg[ii]=="NEG") neg.days = c(neg.days,s0$time.start[ii])
                                          
                                   }
                                   
                                   
                                   probdat$npos[which(probdat$day %in% pos.days)] = probdat$npos[which(probdat$day %in% pos.days)] + 1
                                   
                                   probdat$nneg[which(probdat$day %in% neg.days)] = probdat$nneg[which(probdat$day %in% neg.days)] + 1
                                   
                            }
                            
                            
                            # periods
                            
                            pos.days = c()
                            neg.days = c()
                            for(ii in 1:nrow(s0)){
                                   
                                   
                                   
                                   if(ii == 1) {
                                          
                                          if(s0$time.estimate.cat[ii] == "Period") {
                                                 
                                                 # add result at halfway point current time period
                                                 halfway.time = round((s0$time.stop[ii]+s0$time.start[ii])/2)
                                                 
                                                 if(s0$test.pos.neg[ii]=="POS") pos.days = c(pos.days,halfway.time)
                                                 if(s0$test.pos.neg[ii]=="NEG") neg.days = c(neg.days,halfway.time)
                                                 
                                                 
                                                 # if this period and the next period have the same result, fill results up from the halfway point of the current period to the halfway point of the next period
                                                 if(s0$test.pos.neg[ii] == s0$test.pos.neg[ii+1]) {
                                                        
                                                        halfway.time.1 = round((s0$time.stop[ii]+s0$time.start[ii])/2)
                                                        halfway.time.2 = round((s0$time.stop[ii+1]+s0$time.start[ii+1])/2)
                                                        
                                                        if(s0$test.pos.neg[ii]=="POS") pos.days = c(pos.days, halfway.time.1:halfway.time.2)
                                                        if(s0$test.pos.neg[ii]=="NEG") neg.days = c(neg.days, halfway.time.1:halfway.time.2)
                                                        
                                                 }
                                                 
                                          }
                                          
                                   }
                                   
                                   if(ii > 1 & ii < nrow(s0)) {
                                          
                                          
                                          if(s0$time.estimate.cat[ii] == "Period") {
                                                 
                                                 # add result at halfway point current time period
                                                 halfway.time = round((s0$time.stop[ii]+s0$time.start[ii])/2)
                                                 
                                                 if(s0$test.pos.neg[ii]=="POS") pos.days = c(pos.days,halfway.time)
                                                 if(s0$test.pos.neg[ii]=="NEG") neg.days = c(neg.days,halfway.time)
                                                 
                                                 # if this period and the next period have the same result, fill results up from the halfway point of the current period to the halfway point of the next period
                                                 
                                                 if(s0$test.pos.neg[ii] == s0$test.pos.neg[ii+1]) {
                                                        
                                                        halfway.time.1 = round((s0$time.stop[ii]+s0$time.start[ii])/2)
                                                        halfway.time.2 = round((s0$time.stop[ii+1]+s0$time.start[ii+1])/2)
                                                        
                                                        if(s0$test.pos.neg[ii]=="POS") pos.days = c(pos.days, halfway.time.1:halfway.time.2)
                                                        if(s0$test.pos.neg[ii]=="NEG") neg.days = c(neg.days, halfway.time.1:halfway.time.2)
                                                        
                                                 }
                                                 
                                          }
                                   }
                                   
                                   if(ii > 1 & ii == nrow(s0)) {
                                          
                                          
                                          if(s0$time.estimate.cat[ii] == "Period") {
                                                 # add result at halfway point current time period
                                                 halfway.time = round((s0$time.stop[ii]+s0$time.start[ii])/2)
                                                 
                                                 if(s0$test.pos.neg[ii]=="POS") pos.days = c(pos.days,halfway.time)
                                                 if(s0$test.pos.neg[ii]=="NEG") neg.days = c(neg.days,halfway.time)
                                          }
                                   }
                            }
                     }
              }
              
              
              # group results
              if(s0$sample.size[1] > 1) {
                     
                     
                     
                     # a group ID can have multiple times / time periods if part of a cross-sectional survey at multiple time points. each time is treated independently
                     for(ii in 1:nrow(s0)){
                            
                            s1 = s0[ii,]
                            
                            # Exact times with reported proportion positive      
                            # (e.g. 30% of 20 individuals were positive on day X)       
                            # ==> use as is for each individual.    
                            # for example: consider 6 individuals as being positive, 14 as negative. 
                            
                            if(s1$time.estimate.cat == "Exact" & !is.na(s1$prop.pos)) {
                                   
                                   probdat$npos[which(probdat$day == s1$time.start)] = probdat$npos[which(probdat$day == s1$time.start)] + round(s1$sample.size*s1$prop.pos)
                                   
                                   probdat$nneg[which(probdat$day == s1$time.start)] = probdat$nneg[which(probdat$day == s1$time.start)] + round(s1$sample.size*(1-s1$prop.pos))
                                   
                            }
                            
                            # Periods with reported proportion positive       
                            # (e.g. 40% of N individuals were positive in the period between day X and Y) 
                            # ==> use halfway point    
                            # dismiss if end time not defined
                            # dismiss if no proportion reported
                            if((s1$time.estimate.cat == "Period") & !is.na(s1$time.stop) & !is.na(s1$prop.pos)) {
                                   
                                   halfway.time = round((s1$time.stop+s1$time.start)/2)
                                   
                                   probdat$npos[which(probdat$day == halfway.time)] = probdat$npos[which(probdat$day == halfway.time)] + round(s1$sample.size*s1$prop.pos)
                                   
                                   probdat$nneg[which(probdat$day == halfway.time)] = probdat$nneg[which(probdat$day == halfway.time)] + round(s1$sample.size*(1-s1$prop.pos))
                                   
                            }
                     }
              }
       }
       
       
       
       
       
       
       
       # merge days after day 25
       # groups of 3 days
       new.times = seq(26,max(probdat$day),3)
       
       
       for(i in new.times) {
              
              probdat$npos [ which(probdat$day == i) ] = sum(probdat$npos[which(probdat$day %in% c(i-1,i,i+1))])
              probdat$nneg [ which(probdat$day == i) ] = sum(probdat$nneg[which(probdat$day %in% c(i-1,i,i+1))])
              
              # remove days adjacent to group days
              probdat = probdat[!(probdat$day %in% c(i-1,i+1)),]
              
       }
       
       
       
       probdat$N = probdat$npos + probdat$nneg
       probdat$prob = round(probdat$npos / probdat$N ,2)
       
       # remove rows where N = 0
       probdat = probdat[!is.nan(probdat$prob),]
       
       # add binomial confidence intervals
       
       confints = apply(probdat[,c("npos","N")], 1,binom.wrap.fun) 
       
       probdat$lowerci = confints[1,]
       probdat$upperci = confints[2,]
       
       
       
       
       return(probdat)
       
       
}


# get peak titer timing

get.peak.titer.time = function(titers, days, perc = 0.95) {
       
       max.titer = max(titers)
       
       titers = titers[order(sort(days))]
       days = sort(days)
       
       
       time.perc.peak.titer = days[which(titers>(max.titer*perc))[1]]
       
       return(time.perc.peak.titer)
}


# get peak titer times from MCMC raw data

get.posterior.peak.titer.times = function(dat) {
       get.peak.titer.time(titers = titer.gompertz.fun(times = 0:40,peak.titer = 1,displacement = dat[1],growth.rate = dat[2]), days = 0:40)
}


# make colors transparent


makeTransparent = function(..., alpha=0.5) {
       # source : https://stackoverflow.com/questions/8047668/transparent-equivalent-of-given-color
       
       alpha = floor(255 * alpha)  
       newColor = col2rgb(col = unlist(list(...)), alpha=FALSE)
       
       .makeTransparent = function(col, alpha) {
              rgb(red=col[1], green=col[2], blue=col[3], alpha=alpha, maxColorValue=255)
       }
       
       newColor = apply(newColor, 2, .makeTransparent, alpha=alpha)
       
       return(newColor)
       
}






# function to get the maximum density (mode) of a posterior distribution

maxdens.fun = function(x) round(density(x)$x[which.max(density(x)$y)],2)



# function to fit titers in apply function


fit.titers.fun = function(dat) titer.gompertz.fun(times = plot.times, peak.titer = 1, displacement = dat[3], growth.rate = dat[1])

fit.titers.fun.2 = function(dat) titer.gompertz.fun(times = plot.times, peak.titer = peak.titer.overall.mean, displacement = dat[3], growth.rate = dat[1])




# Gompertz function

titer.gompertz.fun = function(times, peak.titer, displacement, growth.rate) {
       
       predicted.titer = peak.titer * exp(-displacement * exp(-growth.rate*times))
       
       return(predicted.titer)
}



# function to convert a list of chains to a dataframe, for plotting ------
mcmclist.to.dataframe=function(mcmclist){
       
       output=as.data.frame(as.matrix(mcmclist[[1]]))
       output$chain=1
       output$iteration=attributes(mcmclist[[1]])$mcpar[1]:attributes(mcmclist[[1]])$mcpar[2]
       if(length(mcmclist)>1){
              for(i in 2:length(mcmclist)){
                     chain.df=as.data.frame(as.matrix(mcmclist[[i]]))
                     chain.df$chain=i
                     chain.df$iteration=attributes(mcmclist[[i]])$mcpar[1]:attributes(mcmclist[[i]])$mcpar[2]
                     output=rbind(output,chain.df)
              }
       }
       
       return(output)
}



# wrapper output function posterior

plot.MCMC.posterior = function(input.data, column.to.plot,x.axis.label,title="") {
       
       colname.to.plot = colnames(input.data)[column.to.plot]
       colnames(input.data)[column.to.plot] = "plot.col"
       
       
       dens = density(input.data[,"plot.col"])
       
       posterior.mean.overall = mean(input.data[,"plot.col"])
       
       hpd.int.toi = HDInterval::hdi(dens,credMass = 0.95,allowSplit=F)  
       
       
       thinning.for.plots = 50
       
       iterations.to.keep.after.thinning = seq(0,max(input.data$iteration),thinning.for.plots)
       
       input.data.thin = input.data[which(input.data$iteration %in% iterations.to.keep.after.thinning),]
       
       plot1 = ggplot(data=input.data.thin,aes(x=plot.col)) +
              geom_density(color="#9E0142",fill="#9E0142",alpha=0.3) +
              geom_vline(xintercept=posterior.mean.overall,col="#9E0142",size=1,alpha=0.8) +
              geom_vline(xintercept=hpd.int.toi[1],col="#9E0142",size=1,linetype="dashed",alpha=0.7) +
              geom_vline(xintercept=hpd.int.toi[2],col="#9E0142",size=1,linetype="dashed",alpha=0.7) +
              theme_classic(base_family = "Avenir Next") +
              ggtitle(title) +
              xlab(x.axis.label) +
              theme(plot.title = element_text(size = 12),text=element_text(size=12),axis.text=element_text(size=12),axis.title.y = element_text(margin = ggplot2::margin(r=10)),legend.position = "none",panel.background = element_rect(fill = 'grey90'))
       
       
       
       
       plot1
       
       
}



# wrapper output function chains

plot.MCMC.chains = function(input.data, column.to.plot,y.axis.label,thinning,title="") {
       
       colname.to.plot = colnames(input.data)[column.to.plot]
       colnames(input.data)[column.to.plot] = "plot.col"
       
       
       dens = density(input.data[,"plot.col"])
       
       posterior.mean.overall = mean(input.data[,"plot.col"])
       
       hpd.int.toi = HDInterval::hdi(dens,credMass = 0.95,allowSplit=F)  
       
       
       iterations.to.keep.after.thinning = seq(0,max(input.data$iteration),thinning)
       
       input.data.thin = input.data[which(input.data$iteration %in% iterations.to.keep.after.thinning) ,]
       
       
       plot1 = ggplot(data=input.data.thin,aes(y=plot.col,x=iteration,col=chain,group=chain)) +
              geom_line(alpha=0.5) +
              scale_color_gradientn(colours = brewer.pal(11,"Spectral")) +
              geom_hline(yintercept=posterior.mean.overall,col="#9E0142",size=1,alpha=0.8) +
              geom_hline(yintercept=hpd.int.toi[1],col="#9E0142",size=1,linetype="dashed",alpha=0.7) +
              geom_hline(yintercept=hpd.int.toi[2],col="#9E0142",size=1,linetype="dashed",alpha=0.7) +
              theme_classic(base_family = "Avenir Next") +
              ggtitle(title) +
              ylab(y.axis.label) +
              theme(plot.title = element_text(size =12),text=element_text(size=12),axis.text=element_text(size=12),axis.title.y = element_text(margin = ggplot2::margin(r=10)),legend.position = "none",panel.background = element_rect(fill = 'grey90'))
       
       
       
       plot1
       
       
}





```



<br>


***     

R code to generate output shown in the accompanying manuscript and supplementary information.

***    

<br>


# Load Data     


```{r results='hide', fig.show='hide'}

d0 = read.csv("Supplementary_Information_S2.csv",header = T, stringsAsFactors = F)


# set exclude.preprints to T if you want to exclude data from preprints

exclude.preprints = F   

preprint.doi = c("10.1101/2020.04.15.20066407","10.1101/2020.03.28.20043059","10.1101/2020.03.18.20038018")

if(exclude.preprints == T) d0 = droplevels(d0[-which(d0$doi %in% preprint.doi),])


```



```{r}

# set colors for figures

col.igg = "#3288BD"
col.igm = "#9E0142"
col.rna = "#C4961A"
col.ntab = "#FDAE61"
col.mild.igg = makeTransparent(col.igg,alpha=0.9)
col.severe.igg = makeTransparent("#A6BDDB",alpha=0.7) 
col.mild.igm = makeTransparent(col.igm,alpha=0.9)
col.severe.igm = makeTransparent("#EF6548",alpha=0.5)
col.mclia = "#D16103"
col.elisa = "#52854C"
col.latflow = "#C4961A"
col.ifa = "#4E84C4"
# "#5E4FA2"
# "#F46D43"

col.rna2 = "#D16103"
col.rna3 = "#52854C"
col.rna4 = "#4E84C4"

```


<br>

***      

<br>


# Seroconversion      
<br>

```{r}
# number of bootstrap samples

boot.iterations = 50000

```

## IgG       



```{r}

# since symptom onset only, any assay/antigen

# remove duplicate samples, remove Spike antigen when there is a duplicate
d1 = d0[-which(d0$duplicated == 1 & d0$antigen=="Spike"),]
d1 = d1[-which(d1$duplicated == 1 & d1$assay=="Lateral flow assay"),]

sc0 = create.long.df.for.bootstrap.IgG.IgM(d1)

sc0.igg = sc0 %>%
       filter(marker == "IgG" & time.units == "Symptom onset")



# only exact times
boot.samples.df.tp0 = bootstrap.first.detection.hierarchical(sc0.igg, boot.iterations,max.period = 0)

norm.fit.tp0 = MASS::fitdistr(boot.samples.df.tp0$boot.samples,densfun="normal")


# only time periods up to (incl) 3 days
boot.samples.df.tp3 = bootstrap.first.detection.hierarchical(sc0.igg, boot.iterations,max.period = 3)

norm.fit.tp3 = MASS::fitdistr(boot.samples.df.tp3$boot.samples,densfun="normal")


# only time periods up to (incl) 7 days
boot.samples.df.tp7 = bootstrap.first.detection.hierarchical(sc0.igg, boot.iterations,max.period = 7)

norm.fit.tp7 = MASS::fitdistr(boot.samples.df.tp7$boot.samples,densfun="normal")


# only time periods up to (incl) 14 days
boot.samples.df.tp14 = bootstrap.first.detection.hierarchical(sc0.igg, boot.iterations,max.period = 14)

norm.fit.tp14 = MASS::fitdistr(boot.samples.df.tp14$boot.samples,densfun="normal")


# only time periods up to (incl) 21 days
boot.samples.df.tp21 = bootstrap.first.detection.hierarchical(sc0.igg, boot.iterations,max.period = 21)

norm.fit.tp21 = MASS::fitdistr(boot.samples.df.tp21$boot.samples,densfun="normal")



# all time periods
boot.samples.df = bootstrap.first.detection.hierarchical(sc0.igg, boot.iterations,max.period = 1000)

norm.fit = MASS::fitdistr(boot.samples.df$boot.samples,densfun="normal")





# asymptomatic cases
# not enough data



# mild/moderate cases
sc0.igg.mild.all = sc0[which(sc0$marker == "IgG" & sc0$time.units == "Symptom onset" & sc0$severity=="Mild_Moderate"),]

boot.samples.df.igg.mild.all = bootstrap.first.detection.hierarchical(sc0.igg.mild.all, boot.iterations,max.period = 1000)
# setting lower.limit = 1 bcs not enough samples

norm.fit.igg.mild.all = MASS::fitdistr(boot.samples.df.igg.mild.all$boot.samples,densfun="normal")




# mild/moderate cases ELISA NP only
sc0.igg.mild.elisa.np = sc0[which(sc0$marker == "IgG" & sc0$time.units == "Symptom onset" & sc0$severity=="Mild_Moderate" & sc0$assay == "ELISA" & sc0$antigen == "NP"),]

boot.samples.df.igg.mild.elisa.np = bootstrap.first.detection.hierarchical(sc0.igg.mild.elisa.np, boot.iterations,max.period = 1000)
# setting lower.limit = 1 bcs not enough samples

norm.fit.igg.mild.elisa.np = MASS::fitdistr(boot.samples.df.igg.mild.elisa.np$boot.samples,densfun="normal")



# mild/moderate cases ELISA NP or Spike
sc0.igg.mild.elisa.np.spike = sc0[which(sc0$marker == "IgG" & sc0$time.units == "Symptom onset" & sc0$severity=="Mild_Moderate" & sc0$assay == "ELISA" & sc0$antigen %in% c("NP","Spike")),]

boot.samples.df.igg.mild.elisa.np.spike = bootstrap.first.detection.hierarchical(sc0.igg.mild.elisa.np.spike, boot.iterations,max.period = 1000)
# setting lower.limit = 1 bcs not enough samples

norm.fit.igg.mild.elisa.np.spike = MASS::fitdistr(boot.samples.df.igg.mild.elisa.np.spike$boot.samples,densfun="normal")




# severe cases
sc0.igg.severe.all = sc0[which(sc0$marker == "IgG" & sc0$time.units == "Symptom onset" & sc0$severity=="Severe_Critical"),]


boot.samples.df.igg.severe.all = bootstrap.first.detection.hierarchical(sc0.igg.severe.all, boot.iterations, max.period = 1000)
# setting lower.limit = 1 bcs not enough samples

norm.fit.igg.severe.all = MASS::fitdistr(boot.samples.df.igg.severe.all$boot.samples,densfun="normal")



# severe cases ELISA NP only
sc0.igg.severe.elisa.np = sc0[which(sc0$marker == "IgG" & sc0$time.units == "Symptom onset" & sc0$severity=="Severe_Critical" & sc0$assay == "ELISA" & sc0$antigen == "NP"),]


boot.samples.df.igg.severe.elisa.np = bootstrap.first.detection.hierarchical(sc0.igg.severe.elisa.np, boot.iterations, max.period = 1000)
# setting lower.limit = 1 bcs not enough samples

norm.fit.igg.severe.elisa.np = MASS::fitdistr(boot.samples.df.igg.severe.elisa.np$boot.samples,densfun="normal")


# severe cases ELISA NP or Spike
sc0.igg.severe.elisa.np.spike = sc0[which(sc0$marker == "IgG" & sc0$time.units == "Symptom onset" & sc0$severity=="Severe_Critical" & sc0$assay == "ELISA" & sc0$antigen %in% c("NP","Spike")),]


boot.samples.df.igg.severe.elisa.np.spike = bootstrap.first.detection.hierarchical(sc0.igg.severe.elisa.np.spike, boot.iterations, max.period = 1000)
# setting lower.limit = 1 bcs not enough samples

norm.fit.igg.severe.elisa.np.spike = MASS::fitdistr(boot.samples.df.igg.severe.elisa.np.spike$boot.samples,densfun="normal")





# ELISA Spike
sc0 = create.long.df.for.bootstrap.IgG.IgM(d0)

sc0.igg.elisa.spike = sc0 %>%
       filter(marker == "IgG" & time.units == "Symptom onset" & assay == "ELISA" & antigen=="Spike")

# all time periods
boot.samples.df.igg.elisa.spike = bootstrap.first.detection.hierarchical(sc0.igg.elisa.spike, boot.iterations,max.period = 1000)

norm.fit.igg.elisa.spike = MASS::fitdistr(boot.samples.df.igg.elisa.spike$boot.samples,densfun="normal")




# ELISA NP
sc0 = create.long.df.for.bootstrap.IgG.IgM(d0)

sc0.igg.elisa.np = sc0 %>%
       filter(marker == "IgG" & time.units == "Symptom onset" & assay == "ELISA" & antigen=="NP")

# all time periods
boot.samples.df.igg.elisa.np = bootstrap.first.detection.hierarchical(sc0.igg.elisa.np, boot.iterations,max.period = 1000)

norm.fit.igg.elisa.np = MASS::fitdistr(boot.samples.df.igg.elisa.np$boot.samples,densfun="normal")



# ELISA NP or Spike
sc0 = create.long.df.for.bootstrap.IgG.IgM(d0)

sc0.igg.elisa.np.spike = sc0 %>%
       filter(marker == "IgG" & time.units == "Symptom onset" & assay == "ELISA" & antigen %in% c("NP","Spike"))

# all time periods
boot.samples.df.igg.elisa.np.spike = bootstrap.first.detection.hierarchical(sc0.igg.elisa.np.spike, boot.iterations,max.period = 1000)

norm.fit.igg.elisa.np.spike = MASS::fitdistr(boot.samples.df.igg.elisa.np.spike$boot.samples,densfun="normal")





# IgG MCLIA
sc0 = create.long.df.for.bootstrap.IgG.IgM(d0)

sc0.igg.mclia = sc0 %>%
       filter(marker == "IgG" & time.units == "Symptom onset" & assay == "MCLIA")

# all time periods
boot.samples.df.igg.mclia = bootstrap.first.detection.hierarchical(sc0.igg.mclia, boot.iterations,max.period = 1000)

norm.fit.igg.mclia = MASS::fitdistr(boot.samples.df.igg.mclia$boot.samples,densfun="normal")




```


### Distribution of seroconversion times      

#### Effect of excluding time periods       


```{r fig.height=4,fig.width=8}
plot1 = ggplot(data = boot.samples.df.tp0, aes(x = boot.samples)) +
       geom_histogram(aes(y  =  ..density..),binwidth  =  1, fill  =  "grey", color  =  col.igm) +
       stat_function(fun = dnorm, args = list(mean = norm.fit.tp0$estimate[1], sd = norm.fit.tp0$estimate[2]),col=col.igm,size=1.3,alpha=1) +
       scale_x_continuous(breaks = seq(0,(max(boot.samples.df.tp0$boot.samples)+2),5),limits=c(0,max(boot.samples.df.tp0$boot.samples+2))) +
       xlab("Seroconversion time") +
       ggtitle("Exact times only") +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size = 12),
             text = element_text(size = 12),
             axis.text = element_text(size = 12),
             axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),
             legend.position  =  "none",
             panel.background  =  element_rect(fill  =  'white'))


plot2 = ggplot(data = boot.samples.df.tp3, aes(x = boot.samples)) +
       geom_histogram(aes(y  =  ..density..),binwidth  =  1, fill  =  "grey", color  =  col.mild.igg) +
       stat_function(fun = dnorm, args = list(mean = norm.fit.tp3$estimate[1], sd = norm.fit.tp3$estimate[2]),col=col.mild.igg,size=1.3,alpha=1) +
       scale_x_continuous(breaks = seq(0,(max(boot.samples.df.tp3$boot.samples)+2),5),limits=c(0,max(boot.samples.df.tp3$boot.samples+2))) +
       xlab("Seroconversion time") +
       ggtitle("< 4 days") +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size = 12),
             text = element_text(size = 12),
             axis.text = element_text(size = 12),
             axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),
             legend.position  =  "none",
             panel.background  =  element_rect(fill  =  'white'))


plot3 = ggplot(data = boot.samples.df.tp7, aes(x = boot.samples)) +
       geom_histogram(aes(y  =  ..density..),binwidth  =  1, fill  =  "grey", color  =  col.igg) +
       stat_function(fun = dnorm, args = list(mean = norm.fit.tp7$estimate[1], sd = norm.fit.tp7$estimate[2]),col=col.igg,size=1.3,alpha=1) +
       scale_x_continuous(breaks = seq(0,(max(boot.samples.df.tp7$boot.samples)+2),5),limits=c(0,max(boot.samples.df.tp7$boot.samples+2))) +
       xlab("Seroconversion time") +
       ggtitle("< 8 days") +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size = 12),
             text = element_text(size = 12),
             axis.text = element_text(size = 12),
             axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),
             legend.position  =  "none",
             panel.background  =  element_rect(fill  =  'white'))


plot4 = ggplot(data = boot.samples.df.tp14, aes(x = boot.samples)) +
       geom_histogram(aes(y  =  ..density..),binwidth  =  1, fill  =  "grey", color  =  "#FEE08B") +
       stat_function(fun = dnorm, args = list(mean = norm.fit.tp14$estimate[1], sd = norm.fit.tp14$estimate[2]),col="#FEE08B",size=1.3,alpha=1) +
       scale_x_continuous(breaks = seq(0,(max(boot.samples.df.tp14$boot.samples)+2),5),limits=c(0,max(boot.samples.df.tp14$boot.samples+2))) +
       xlab("Seroconversion time") +
       ggtitle("< 15 days") +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size = 12),
             text = element_text(size = 12),
             axis.text = element_text(size = 12),
             axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),
             legend.position  =  "none",
             panel.background  =  element_rect(fill  =  'white'))


plot5 = ggplot(data = boot.samples.df.tp21, aes(x = boot.samples)) +
       geom_histogram(aes(y  =  ..density..),binwidth  =  1, fill  =  "grey", color  =  "#5E4FA2") +
       stat_function(fun = dnorm, args = list(mean = norm.fit.tp21$estimate[1], sd = norm.fit.tp21$estimate[2]),col="#5E4FA2",size=1.3,alpha=1) +
       scale_x_continuous(breaks = seq(0,(max(boot.samples.df.tp21$boot.samples)+2),5),limits=c(0,max(boot.samples.df.tp21$boot.samples+2))) +
       xlab("Seroconversion time") +
       ggtitle("< 22 days") +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size = 12),
             text = element_text(size = 12),
             axis.text = element_text(size = 12),
             axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),
             legend.position  =  "none",
             panel.background  =  element_rect(fill  =  'white'))


plot6 = ggplot(data = boot.samples.df, aes(x = boot.samples)) +
       geom_histogram(aes(y  =  ..density..),binwidth  =  1, fill  =  "grey", color  =  "#D53E4F") +
       stat_function(fun = dnorm, args = list(mean = norm.fit$estimate[1], sd = norm.fit$estimate[2]),col="#D53E4F",size=1.3,alpha=1) +
       scale_x_continuous(breaks = seq(0,(max(boot.samples.df$boot.samples)+2),5),limits=c(0,max(boot.samples.df$boot.samples+2))) +
       xlab("Seroconversion time") +
       ggtitle("All time periods") +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size = 12),
             text = element_text(size = 12),
             axis.text = element_text(size = 12),
             axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),
             legend.position  =  "none",
             panel.background  =  element_rect(fill  =  'white'))


plot1 + plot2 + plot3
plot4 + plot5 + plot6
```


```{r fig.height=3,fig.width=4}
ggplot(data.frame(x = c(0,25)),aes(x=x)) +
       stat_function(fun = dnorm, args = list(mean = norm.fit.tp0$estimate[1], sd = norm.fit.tp0$estimate[2]),col=col.igm,size=1.3,alpha=0.8) +
       stat_function(fun = dnorm, args = list(mean = norm.fit.tp3$estimate[1], sd = norm.fit.tp3$estimate[2]),col=col.mild.igg,size=1.3,alpha=0.8) +
       stat_function(fun = dnorm, args = list(mean = norm.fit.tp7$estimate[1], sd = norm.fit.tp7$estimate[2]),col=col.igg,size=1.3,alpha=0.8) +
       stat_function(fun = dnorm, args = list(mean = norm.fit.tp14$estimate[1], sd = norm.fit.tp14$estimate[2]),col="#FEE08B",size=1.3,alpha=0.8) +
       stat_function(fun = dnorm, args = list(mean = norm.fit.tp21$estimate[1], sd = norm.fit.tp21$estimate[2]),col="#5E4FA2",size=1.3,alpha=0.8) +
       stat_function(fun = dnorm, args = list(mean = norm.fit$estimate[1], sd = norm.fit$estimate[2]),col="#D53E4F",size=1.3,alpha=0.8) +
       ylab("density") +
       xlab("Seroconversion time") +
       ggtitle("All combined") +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size = 12),
             text = element_text(size = 12),
             axis.text = element_text(size = 12),
             axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),
             legend.position  =  "none",
             panel.background  =  element_rect(fill  =  'white'))


```



Combine histograms + distributions  


```{r fig.height=6, fig.width=3}
boot.samples.df.tp0$time.periods = 0
boot.samples.df.tp3$time.periods = 3
boot.samples.df.tp7$time.periods = 7
boot.samples.df.tp14$time.periods = 14
boot.samples.df.tp21$time.periods = 21
boot.samples.df$time.periods = "all"

plot.data = rbind(boot.samples.df.tp0,boot.samples.df.tp3,boot.samples.df.tp7,boot.samples.df.tp14,boot.samples.df.tp21,boot.samples.df)

time.range = seq(0,max(plot.data$boot.samples),0.1)
fit1 = data.frame(time = time.range, fit = with(norm.fit.tp0, dnorm(time.range, mean = estimate[1], sd = estimate[2])))
fit2 = data.frame(time = time.range, fit = with(norm.fit.tp3, dnorm(time.range, mean = estimate[1], sd = estimate[2])))
fit3 = data.frame(time = time.range, fit = with(norm.fit.tp7, dnorm(time.range, mean = estimate[1], sd = estimate[2])))
fit4 = data.frame(time = time.range, fit = with(norm.fit.tp14, dnorm(time.range, mean = estimate[1], sd = estimate[2])))
fit5 = data.frame(time = time.range, fit = with(norm.fit.tp21, dnorm(time.range, mean = estimate[1], sd = estimate[2])))
fit6 = data.frame(time = time.range, fit = with(norm.fit, dnorm(time.range, mean = estimate[1], sd = estimate[2])))


fit1$time.periods = 0
fit2$time.periods = 3
fit3$time.periods = 7
fit4$time.periods = 14
fit5$time.periods = 21
fit6$time.periods = "all"

fit.plot.data = rbind(fit1,fit2,fit3,fit4,fit5,fit6)


norm.fit.df = data.frame(time.periods = c(0,3,7,14,21,"all"), mean = c(norm.fit.tp0$estimate[1],norm.fit.tp3$estimate[1],norm.fit.tp7$estimate[1],norm.fit.tp14$estimate[1],norm.fit.tp21$estimate[1],norm.fit$estimate[1]), sd = c(norm.fit.tp0$estimate[2],norm.fit.tp3$estimate[2],norm.fit.tp7$estimate[2],norm.fit.tp14$estimate[2],norm.fit.tp21$estimate[2],norm.fit$estimate[2]))



norm.fit.times = seq(0,25,0.01)

i=1;norm.fit.plot.tp0 = data.frame(time = norm.fit.times, val = i+(10*dnorm(norm.fit.times, mean = norm.fit.df$mean[i], sd = norm.fit.df$sd[i])),time.periods = "0")
i=2;norm.fit.plot.tp3 = data.frame(time = norm.fit.times, val = i+(10*dnorm(norm.fit.times, mean = norm.fit.df$mean[i], sd = norm.fit.df$sd[i])),time.periods = "3")
i=3;norm.fit.plot.tp7 = data.frame(time = norm.fit.times, val = i+(10*dnorm(norm.fit.times, mean = norm.fit.df$mean[i], sd = norm.fit.df$sd[i])),time.periods = "7")
i=4;norm.fit.plot.tp14 = data.frame(time = norm.fit.times, val = i+(10*dnorm(norm.fit.times, mean = norm.fit.df$mean[i], sd = norm.fit.df$sd[i])),time.periods = "14")
i=5;norm.fit.plot.tp21 = data.frame(time = norm.fit.times, val = i+(10*dnorm(norm.fit.times, mean = norm.fit.df$mean[i], sd = norm.fit.df$sd[i])),time.periods = "21")
i=6;norm.fit.plot.all = data.frame(time = norm.fit.times, val = i+(10*dnorm(norm.fit.times, mean = norm.fit.df$mean[i], sd = norm.fit.df$sd[i])),time.periods = "all")

norm.fit.plot = rbind(norm.fit.plot.tp0,norm.fit.plot.tp3,norm.fit.plot.tp7,norm.fit.plot.tp14,norm.fit.plot.tp21,norm.fit.plot.all)


plot.data$time.periods = factor(plot.data$time.periods, levels = c("0","3","7","14","21","all"))



ggplot() +
       geom_density_ridges(data=plot.data,aes(x = boot.samples, y = time.periods,fill=time.periods),stat="binline",bins=25,scale=0.7, draw_baseline=T,color="grey40") +
       scale_fill_manual(values=c(col.igm,col.mild.igg,col.igg,"#FEE08B","#5E4FA2","#D53E4F"),name = "Time periods",guide = guide_legend(reverse=T)) +
       scale_color_manual(values=c(col.igm,col.mild.igg,col.igg,"#FEE08B","#5E4FA2","#D53E4F"),name = "Time periods",guide = guide_legend(reverse=T)) +
       ylab("Maximum time period included") +
       xlab("Time since symptom onset") +
       ggtitle("IgG") +
       geom_line(data = norm.fit.plot, aes(x=time, y = val,col=time.periods)) +
       scale_x_continuous(limits=c(0,25)) +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size = 12),
             text = element_text(size = 12),
             axis.text = element_text(size = 12),
             axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),
             legend.position  =  "none",
             panel.background  =  element_rect(fill  =  'white'))



```




#### Overall and disease severity       

Fitted normal distributions.     

Mean overall = `r  round(norm.fit$estimate[1],2) `     
SD overall = `r  round(norm.fit$estimate[2],2) `     

Mean mild = `r  round(norm.fit.igg.mild.all$estimate[1],2) `     
SD mild = `r  round(norm.fit.igg.mild.all$estimate[2],2) `     

Mean mild ELISA NP = `r  round(norm.fit.igg.mild.elisa.np$estimate[1],2) `     
SD mild ELISA NP = `r  round(norm.fit.igg.mild.elisa.np$estimate[2],2) `     

Mean severe = `r  round(norm.fit.igg.severe.all$estimate[1],2) `     
SD severe = `r  round(norm.fit.igg.severe.all$estimate[2],2) `    

Mean severe ELISA NP = `r  round(norm.fit.igg.severe.elisa.np$estimate[1],2) `     
SD severe ELISA NP = `r  round(norm.fit.igg.severe.elisa.np$estimate[2],2) `    


Difference between the two distributions:     
(Welch two sample t-test (unequal variances))       


```{r fig.height=4,fig.width=9}
n1 = length(unique(sc0.igg.mild.all$id))
n2 = length(unique(sc0.igg.severe.all$id))
mean1 = norm.fit.igg.mild.all$estimate[1]
mean2 = norm.fit.igg.severe.all$estimate[1]
sd1 = norm.fit.igg.mild.all$estimate[2]
sd2 = norm.fit.igg.severe.all$estimate[2]

set.seed(1234)
z1 = rnorm(n1)
x1 = scale(z1)*sd1+mean1
z2 = rnorm(n2)
x2 = scale(z2)*sd2+mean2
t.test(x1,x2) # Welch-Satterthwaite
```


<br>




```{r fig.height=4,fig.width=11}

plot1 = ggplot(data = boot.samples.df, aes(x = boot.samples)) +
       geom_histogram(aes(y  =  ..density..),binwidth  =  1, fill  =  col.igg, color  =  col.igg,alpha=0.5) +
       stat_function(fun = dnorm, args = list(mean = norm.fit$estimate[1], sd = norm.fit$estimate[2]),col=col.igg,size=1.3,alpha=1) +
       scale_x_continuous(breaks = seq(0,(max(boot.samples.df$boot.samples)+2),5),limits=c(0,max(boot.samples.df$boot.samples+2))) +
       ggtitle("Mild + severe") +
       xlab("Seroconversion time") +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size = 12),
             text = element_text(size = 12),
             axis.text = element_text(size = 12),
             axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),
             legend.position  =  "none",
             panel.background  =  element_rect(fill  =  'white'))


# merge mild / severe results for plotting

boot.samples.df.igg.mild.severe.all = rbind(boot.samples.df.igg.mild.all,boot.samples.df.igg.severe.all)

boot.samples.df.igg.mild.severe.all$Severity = rep(c("Mild/Moderate","Severe/Critical"),each = nrow(boot.samples.df.igg.mild.all) )


plot2 = ggplot(data = boot.samples.df.igg.mild.severe.all, aes(x = boot.samples, fill = Severity)) +
       geom_histogram(aes(y  =  ..density..),binwidth  =  1,color  =  "black", size=0.2,position="identity") +
       scale_fill_manual(values=c(col.mild.igg,col.severe.igg)) +
       stat_function(fun = dnorm, args = list(mean = norm.fit.igg.mild.all$estimate[1], sd = norm.fit.igg.mild.all$estimate[2]),col=col.mild.igg,size=1.3) +
       stat_function(fun = dnorm, args = list(mean = norm.fit.igg.severe.all$estimate[1], sd = norm.fit.igg.severe.all$estimate[2]),col=col.severe.igg,size=1.3) +
       scale_x_continuous(breaks = seq(0,(max(boot.samples.df.igg.mild.severe.all$boot.samples)+2),5),limits=c(0,max(boot.samples.df.igg.mild.severe.all$boot.samples+2))) +
       xlab("Seroconversion time") +
       ggtitle("IgG Disease Severity \n (all assays)") +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size = 12),
             text = element_text(size = 12),
             axis.text = element_text(size = 12),
             axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),
             legend.position  = c(0.7,0.8),
             panel.background  =  element_rect(fill  =  'white'))



# merge mild / severe elisa.np results for plotting

boot.samples.df.igg.mild.severe.elisa.np = rbind(boot.samples.df.igg.mild.elisa.np,boot.samples.df.igg.severe.elisa.np)

boot.samples.df.igg.mild.severe.elisa.np$Severity = rep(c("Mild/Moderate","Severe/Critical"),each = nrow(boot.samples.df.igg.mild.elisa.np) )



plot3 = ggplot(data = boot.samples.df.igg.mild.severe.elisa.np, aes(x = boot.samples, fill = Severity)) +
       geom_histogram(aes(y  =  ..density..),binwidth  =  1,color  =  "black", size=0.2,position="identity") +
       scale_fill_manual(values=c(col.mild.igg,col.severe.igg)) +
       stat_function(fun = dnorm, args = list(mean = norm.fit.igg.mild.elisa.np$estimate[1], sd = norm.fit.igg.mild.elisa.np$estimate[2]),col=col.mild.igg,size=1.3) +
       stat_function(fun = dnorm, args = list(mean = norm.fit.igg.severe.elisa.np$estimate[1], sd = norm.fit.igg.severe.elisa.np$estimate[2]),col=col.severe.igg,size=1.3) +
       scale_x_continuous(breaks = seq(0,(max(boot.samples.df.igg.mild.severe.elisa.np$boot.samples)+2),5),limits=c(0,max(boot.samples.df.igg.mild.severe.elisa.np$boot.samples+2))) +
       xlab("Seroconversion time") +
       ggtitle("IgG Disease Severity \n (ELISA NP)") +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size = 12),
             text = element_text(size = 12),
             axis.text = element_text(size = 12),
             axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),
             legend.position  = c(0.7,0.8),
             panel.background  =  element_rect(fill  =  'white'))



plot1 + plot2 + plot3





plot4 = ggplot(data = boot.samples.df.igg.elisa.np, aes(x = boot.samples)) +
       geom_histogram(aes(y  =  ..density..),binwidth  =  1, fill  =  col.igg, color  =  col.igg,alpha=0.5) +
       stat_function(fun = dnorm, args = list(mean = norm.fit.igg.elisa.np$estimate[1], sd = norm.fit.igg.elisa.np$estimate[2]),col=col.igg,size=1.3,alpha=1) +
       scale_x_continuous(breaks = seq(0,(max(boot.samples.df.igg.elisa.np$boot.samples)+2),5),limits=c(0,max(boot.samples.df.igg.elisa.np$boot.samples+2))) +
       ggtitle("IgG ELISA NP \n (mild + severe)") +
       xlab("Seroconversion time") +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size = 12),
             text = element_text(size = 12),
             axis.text = element_text(size = 12),
             axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),
             legend.position  = 'none',
             panel.background  =  element_rect(fill  =  'white'))



plot5 = ggplot(data = boot.samples.df.igg.elisa.spike, aes(x = boot.samples)) +
       geom_histogram(aes(y  =  ..density..),binwidth  =  1, fill  =  col.igg, color  =  col.igg,alpha=0.5) +
       stat_function(fun = dnorm, args = list(mean = norm.fit.igg.elisa.spike$estimate[1], sd = norm.fit.igg.elisa.spike$estimate[2]),col=col.igg,size=1.3,alpha=1) +
       scale_x_continuous(breaks = seq(0,(max(boot.samples.df.igg.elisa.spike$boot.samples)+2),5),limits=c(0,max(boot.samples.df.igg.elisa.spike$boot.samples+2))) +
       ggtitle("IgG ELISA Spike  \n (mild + severe)") +
       xlab("Seroconversion time") +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size = 12),
             text = element_text(size = 12),
             axis.text = element_text(size = 12),
             axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),
             legend.position  = 'none',
             panel.background  =  element_rect(fill  =  'white'))




plot1 + plot4 + plot5


```



<br>

***

<br>



## IgM       



```{r}

# remove duplicate IgM samples, remove NP antigen
d1 = d0[-which(d0$duplicated == 1 & d0$antigen=="NP"),]
d1 = d1[-which(d1$duplicated == 1 & d1$assay=="Lateral flow assay"),]

sc0 = create.long.df.for.bootstrap.IgG.IgM(d1)


# since symptom onset only

sc0.igm = sc0 %>%
       filter(marker == "IgM" & time.units == "Symptom onset")



# only exact times
boot.samples.df.tp0 = bootstrap.first.detection.hierarchical(sc0.igm, boot.iterations,max.period = 0)

norm.fit.tp0 = MASS::fitdistr(boot.samples.df.tp0$boot.samples,densfun="normal")


# only time periods up to (incl) 3 days
boot.samples.df.tp3 = bootstrap.first.detection.hierarchical(sc0.igm, boot.iterations,max.period = 3)

norm.fit.tp3 = MASS::fitdistr(boot.samples.df.tp3$boot.samples,densfun="normal")


# only time periods up to (incl) 7 days
boot.samples.df.tp7 = bootstrap.first.detection.hierarchical(sc0.igm, boot.iterations,max.period = 7)

norm.fit.tp7 = MASS::fitdistr(boot.samples.df.tp7$boot.samples,densfun="normal")


# only time periods up to (incl) 14 days
boot.samples.df.tp14 = bootstrap.first.detection.hierarchical(sc0.igm, boot.iterations,max.period = 14)

norm.fit.tp14 = MASS::fitdistr(boot.samples.df.tp14$boot.samples,densfun="normal")


# only time periods up to (incl) 21 days
boot.samples.df.tp21 = bootstrap.first.detection.hierarchical(sc0.igm, boot.iterations,max.period = 21)

norm.fit.tp21 = MASS::fitdistr(boot.samples.df.tp21$boot.samples,densfun="normal")



# all time periods
boot.samples.df = bootstrap.first.detection.hierarchical(sc0.igm, boot.iterations,max.period = 1000)

norm.fit = MASS::fitdistr(boot.samples.df$boot.samples,densfun="normal")





# mild/moderate cases
sc0.igm.mild.all = sc0[which(sc0$marker == "IgM" & sc0$time.units == "Symptom onset" & sc0$severity=="Mild_Moderate"),]

boot.samples.df.igm.mild.all = bootstrap.first.detection.hierarchical(sc0.igm.mild.all, boot.iterations,max.period = 1000)
# setting lower.limit = 1 bcs not enough samples

norm.fit.igm.mild.all = MASS::fitdistr(boot.samples.df.igm.mild.all$boot.samples,densfun="normal")





# mild/moderate cases ELISA Spike only
sc0.igm.mild.elisa.spike = sc0[which(sc0$marker == "IgM" & sc0$time.units == "Symptom onset" & sc0$severity=="Mild_Moderate" & sc0$assay == "ELISA" & sc0$antigen == "Spike"),]

boot.samples.df.igm.mild.elisa.spike = bootstrap.first.detection.hierarchical(sc0.igm.mild.elisa.spike, boot.iterations,max.period = 1000)
# setting lower.limit = 1 bcs not enough samples

norm.fit.igm.mild.elisa.spike = MASS::fitdistr(boot.samples.df.igm.mild.elisa.spike$boot.samples,densfun="normal")


# mild/moderate cases ELISA Spike or NP
sc0.igm.mild.elisa.np.spike = sc0[which(sc0$marker == "IgM" & sc0$time.units == "Symptom onset" & sc0$severity=="Mild_Moderate" & sc0$assay == "ELISA" & sc0$antigen %in% c("NP", "Spike")),]

boot.samples.df.igm.mild.elisa.np.spike = bootstrap.first.detection.hierarchical(sc0.igm.mild.elisa.np.spike, boot.iterations,max.period = 1000)
# setting lower.limit = 1 bcs not enough samples

norm.fit.igm.mild.elisa.np.spike = MASS::fitdistr(boot.samples.df.igm.mild.elisa.np.spike$boot.samples,densfun="normal")




# severe cases
sc0.igm.severe.all = sc0[which(sc0$marker == "IgM" & sc0$time.units == "Symptom onset" & sc0$severity=="Severe_Critical"),]


boot.samples.df.igm.severe.all = bootstrap.first.detection.hierarchical(sc0.igm.severe.all, boot.iterations, max.period = 1000)
# setting lower.limit = 1 bcs not enough samples

norm.fit.igm.severe.all = MASS::fitdistr(boot.samples.df.igm.severe.all$boot.samples,densfun="normal")



# severe cases ELISA Spike
sc0.igm.severe.elisa.spike = sc0[which(sc0$marker == "IgM" & sc0$time.units == "Symptom onset" & sc0$severity=="Severe_Critical" & sc0$assay == "ELISA" & sc0$antigen == "Spike"),]


boot.samples.df.igm.severe.elisa.spike = bootstrap.first.detection.hierarchical(sc0.igm.severe.elisa.spike, boot.iterations, max.period = 1000)
# setting lower.limit = 1 bcs not enough samples

norm.fit.igm.severe.elisa.spike = MASS::fitdistr(boot.samples.df.igm.severe.elisa.spike$boot.samples,densfun="normal")


# severe cases ELISA Spike or NP
sc0.igm.severe.elisa.np.spike = sc0[which(sc0$marker == "IgM" & sc0$time.units == "Symptom onset" & sc0$severity=="Severe_Critical" & sc0$assay == "ELISA" & sc0$antigen %in% c("NP", "Spike")),]

boot.samples.df.igm.severe.elisa.np.spike = bootstrap.first.detection.hierarchical(sc0.igm.severe.elisa.np.spike, boot.iterations,max.period = 1000)
# setting lower.limit = 1 bcs not enough samples

norm.fit.igm.severe.elisa.np.spike = MASS::fitdistr(boot.samples.df.igm.severe.elisa.np.spike$boot.samples,densfun="normal")






#

# ELISA Spike
sc0 = create.long.df.for.bootstrap.IgG.IgM(d0)

sc0.igm.elisa.spike = sc0 %>%
       filter(marker == "IgM" & time.units == "Symptom onset" & assay == "ELISA" & antigen=="Spike")

# all time periods
boot.samples.df.igm.elisa.spike = bootstrap.first.detection.hierarchical(sc0.igm.elisa.spike, boot.iterations,max.period = 1000)

norm.fit.igm.elisa.spike = MASS::fitdistr(boot.samples.df.igm.elisa.spike$boot.samples,densfun="normal")




# ELISA NP
sc0 = create.long.df.for.bootstrap.IgG.IgM(d0)

sc0.igm.elisa.np= sc0 %>%
       filter(marker == "IgM" & time.units == "Symptom onset" & assay == "ELISA" & antigen=="Spike")

# all time periods
boot.samples.df.igm.elisa.np = bootstrap.first.detection.hierarchical(sc0.igm.elisa.np, boot.iterations,max.period = 1000)

norm.fit.igm.elisa.np = MASS::fitdistr(boot.samples.df.igm.elisa.np$boot.samples,densfun="normal")



# ELISA NP or Spike
sc0 = create.long.df.for.bootstrap.IgG.IgM(d0)

sc0.igm.elisa.np.spike = sc0 %>%
       filter(marker == "IgM" & time.units == "Symptom onset" & assay == "ELISA" & antigen %in% c("NP","Spike"))

# all time periods
boot.samples.df.igm.elisa.np.spike = bootstrap.first.detection.hierarchical(sc0.igm.elisa.np.spike, boot.iterations,max.period = 1000)

norm.fit.igm.elisa.np.spike = MASS::fitdistr(boot.samples.df.igm.elisa.np.spike$boot.samples,densfun="normal")





# MCLIA
sc0 = create.long.df.for.bootstrap.IgG.IgM(d0)

sc0.igm.mclia = sc0 %>%
       filter(marker == "IgM" & time.units == "Symptom onset" & assay == "MCLIA")

# all time periods
boot.samples.df.igm.mclia = bootstrap.first.detection.hierarchical(sc0.igm.mclia, boot.iterations,max.period = 1000)

norm.fit.igm.mclia = MASS::fitdistr(boot.samples.df.igm.mclia$boot.samples,densfun="normal")






```


### Distribution of seroconversion times      

#### Effect of excluding time periods       


```{r fig.height=4,fig.width=8}
plot1 = ggplot(data = boot.samples.df.tp0, aes(x = boot.samples)) +
       geom_histogram(aes(y  =  ..density..),binwidth  =  1, fill  =  "grey", color  =  col.igm) +
       stat_function(fun = dnorm, args = list(mean = norm.fit.tp0$estimate[1], sd = norm.fit.tp0$estimate[2]),col=col.igm,size=1.3,alpha=1) +
       scale_x_continuous(breaks = seq(0,(max(boot.samples.df.tp0$boot.samples)+2),5),limits=c(0,max(boot.samples.df.tp0$boot.samples+2))) +
       xlab("Seroconversion time") +
       ggtitle("Exact times only") +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size = 12),text = element_text(size = 12),axis.text = element_text(size = 12),axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),legend.position  =  "none",panel.background  =  element_rect(fill  =  'white'))


plot2 = ggplot(data = boot.samples.df.tp3, aes(x = boot.samples)) +
       geom_histogram(aes(y  =  ..density..),binwidth  =  1, fill  =  "grey", color  =  col.mild.igg) +
       stat_function(fun = dnorm, args = list(mean = norm.fit.tp3$estimate[1], sd = norm.fit.tp3$estimate[2]),col=col.mild.igg,size=1.3,alpha=1) +
       scale_x_continuous(breaks = seq(0,(max(boot.samples.df.tp3$boot.samples)+2),5),limits=c(0,max(boot.samples.df.tp3$boot.samples+2))) +
       xlab("Seroconversion time") +
       ggtitle("< 4 days") +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size = 12),text = element_text(size = 12),axis.text = element_text(size = 12),axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),legend.position  =  "none",panel.background  =  element_rect(fill  =  'white'))


plot3 = ggplot(data = boot.samples.df.tp7, aes(x = boot.samples)) +
       geom_histogram(aes(y  =  ..density..),binwidth  =  1, fill  =  "grey", color  =  col.igg) +
       stat_function(fun = dnorm, args = list(mean = norm.fit.tp7$estimate[1], sd = norm.fit.tp7$estimate[2]),col=col.igg,size=1.3,alpha=1) +
       scale_x_continuous(breaks = seq(0,(max(boot.samples.df.tp7$boot.samples)+2),5),limits=c(0,max(boot.samples.df.tp7$boot.samples+2))) +
       xlab("Seroconversion time") +
       ggtitle("< 8 days") +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size = 12),text = element_text(size = 12),axis.text = element_text(size = 12),axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),legend.position  =  "none",panel.background  =  element_rect(fill  =  'white'))


plot4 = ggplot(data = boot.samples.df.tp14, aes(x = boot.samples)) +
       geom_histogram(aes(y  =  ..density..),binwidth  =  1, fill  =  "grey", color  =  "#FEE08B") +
       stat_function(fun = dnorm, args = list(mean = norm.fit.tp14$estimate[1], sd = norm.fit.tp14$estimate[2]),col="#FEE08B",size=1.3,alpha=1) +
       scale_x_continuous(breaks = seq(0,(max(boot.samples.df.tp14$boot.samples)+2),5),limits=c(0,max(boot.samples.df.tp14$boot.samples+2))) +
       xlab("Seroconversion time") +
       ggtitle("< 15 days") +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size = 12),text = element_text(size = 12),axis.text = element_text(size = 12),axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),legend.position  =  "none",panel.background  =  element_rect(fill  =  'white'))


plot5 = ggplot(data = boot.samples.df.tp21, aes(x = boot.samples)) +
       geom_histogram(aes(y  =  ..density..),binwidth  =  1, fill  =  "grey", color  =  "#5E4FA2") +
       stat_function(fun = dnorm, args = list(mean = norm.fit.tp21$estimate[1], sd = norm.fit.tp21$estimate[2]),col="#5E4FA2",size=1.3,alpha=1) +
       scale_x_continuous(breaks = seq(0,(max(boot.samples.df.tp21$boot.samples)+2),5),limits=c(0,max(boot.samples.df.tp21$boot.samples+2))) +
       xlab("Seroconversion time") +
       ggtitle("< 22 days") +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size = 12),text = element_text(size = 12),axis.text = element_text(size = 12),axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),legend.position  =  "none",panel.background  =  element_rect(fill  =  'white'))


plot6 = ggplot(data = boot.samples.df, aes(x = boot.samples)) +
       geom_histogram(aes(y  =  ..density..),binwidth  =  1, fill  =  "grey", color  =  "#D53E4F") +
       stat_function(fun = dnorm, args = list(mean = norm.fit$estimate[1], sd = norm.fit$estimate[2]),col="#D53E4F",size=1.3,alpha=1) +
       scale_x_continuous(breaks = seq(0,(max(boot.samples.df$boot.samples)+2),5),limits=c(0,max(boot.samples.df$boot.samples+2))) +
       xlab("Seroconversion time") +
       ggtitle("All time periods") +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size = 12),text = element_text(size = 12),axis.text = element_text(size = 12),axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),legend.position  =  "none",panel.background  =  element_rect(fill  =  'white'))


plot1 + plot2 + plot3
plot4 + plot5 + plot6
```

```{r fig.height=3,fig.width=4}
ggplot(data.frame(x = c(0,25)),aes(x=x)) +
       stat_function(fun = dnorm, args = list(mean = norm.fit.tp0$estimate[1], sd = norm.fit.tp0$estimate[2]),col=col.igm,size=1.3,alpha=0.8) +
       stat_function(fun = dnorm, args = list(mean = norm.fit.tp3$estimate[1], sd = norm.fit.tp3$estimate[2]),col=col.mild.igg,size=1.3,alpha=0.8) +
       stat_function(fun = dnorm, args = list(mean = norm.fit.tp7$estimate[1], sd = norm.fit.tp7$estimate[2]),col=col.igg,size=1.3,alpha=0.8) +
       stat_function(fun = dnorm, args = list(mean = norm.fit.tp14$estimate[1], sd = norm.fit.tp14$estimate[2]),col="#FEE08B",size=1.3,alpha=0.8) +
       stat_function(fun = dnorm, args = list(mean = norm.fit.tp21$estimate[1], sd = norm.fit.tp21$estimate[2]),col="#5E4FA2",size=1.3,alpha=0.8) +
       stat_function(fun = dnorm, args = list(mean = norm.fit$estimate[1], sd = norm.fit$estimate[2]),col="#D53E4F",size=1.3,alpha=0.8) +
       ylab("density") +
       xlab("Seroconversion time") +
       ggtitle("All combined") +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size  = 12),text = element_text(size = 12),axis.text = element_text(size = 12),axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),legend.position  =  "none",panel.background  =  element_rect(fill  =  'white'))


```



Combine histograms + distributions  


```{r fig.height=6, fig.width=3}
boot.samples.df.tp0$time.periods = 0
boot.samples.df.tp3$time.periods = 3
boot.samples.df.tp7$time.periods = 7
boot.samples.df.tp14$time.periods = 14
boot.samples.df.tp21$time.periods = 21
boot.samples.df$time.periods = "all"

plot.data = rbind(boot.samples.df.tp0,boot.samples.df.tp3,boot.samples.df.tp7,boot.samples.df.tp14,boot.samples.df.tp21,boot.samples.df)

time.range = seq(0,max(plot.data$boot.samples),0.1)
fit1 = data.frame(time = time.range, fit = with(norm.fit.tp0, dnorm(time.range, mean = estimate[1], sd = estimate[2])))
fit2 = data.frame(time = time.range, fit = with(norm.fit.tp3, dnorm(time.range, mean = estimate[1], sd = estimate[2])))
fit3 = data.frame(time = time.range, fit = with(norm.fit.tp7, dnorm(time.range, mean = estimate[1], sd = estimate[2])))
fit4 = data.frame(time = time.range, fit = with(norm.fit.tp14, dnorm(time.range, mean = estimate[1], sd = estimate[2])))
fit5 = data.frame(time = time.range, fit = with(norm.fit.tp21, dnorm(time.range, mean = estimate[1], sd = estimate[2])))
fit6 = data.frame(time = time.range, fit = with(norm.fit, dnorm(time.range, mean = estimate[1], sd = estimate[2])))


fit1$time.periods = 0
fit2$time.periods = 3
fit3$time.periods = 7
fit4$time.periods = 14
fit5$time.periods = 21
fit6$time.periods = "all"

fit.plot.data = rbind(fit1,fit2,fit3,fit4,fit5,fit6)


norm.fit.df = data.frame(time.periods = c(0,3,7,14,21,"all"), mean = c(norm.fit.tp0$estimate[1],norm.fit.tp3$estimate[1],norm.fit.tp7$estimate[1],norm.fit.tp14$estimate[1],norm.fit.tp21$estimate[1],norm.fit$estimate[1]), sd = c(norm.fit.tp0$estimate[2],norm.fit.tp3$estimate[2],norm.fit.tp7$estimate[2],norm.fit.tp14$estimate[2],norm.fit.tp21$estimate[2],norm.fit$estimate[2]))



norm.fit.times = seq(0,25,0.01)

i=1;norm.fit.plot.tp0 = data.frame(time = norm.fit.times, val = i+(10*dnorm(norm.fit.times, mean = norm.fit.df$mean[i], sd = norm.fit.df$sd[i])),time.periods = "0")
i=2;norm.fit.plot.tp3 = data.frame(time = norm.fit.times, val = i+(10*dnorm(norm.fit.times, mean = norm.fit.df$mean[i], sd = norm.fit.df$sd[i])),time.periods = "3")
i=3;norm.fit.plot.tp7 = data.frame(time = norm.fit.times, val = i+(10*dnorm(norm.fit.times, mean = norm.fit.df$mean[i], sd = norm.fit.df$sd[i])),time.periods = "7")
i=4;norm.fit.plot.tp14 = data.frame(time = norm.fit.times, val = i+(10*dnorm(norm.fit.times, mean = norm.fit.df$mean[i], sd = norm.fit.df$sd[i])),time.periods = "14")
i=5;norm.fit.plot.tp21 = data.frame(time = norm.fit.times, val = i+(10*dnorm(norm.fit.times, mean = norm.fit.df$mean[i], sd = norm.fit.df$sd[i])),time.periods = "21")
i=6;norm.fit.plot.all = data.frame(time = norm.fit.times, val = i+(10*dnorm(norm.fit.times, mean = norm.fit.df$mean[i], sd = norm.fit.df$sd[i])),time.periods = "all")

norm.fit.plot = rbind(norm.fit.plot.tp0,norm.fit.plot.tp3,norm.fit.plot.tp7,norm.fit.plot.tp14,norm.fit.plot.tp21,norm.fit.plot.all)


plot.data$time.periods = factor(plot.data$time.periods, levels = c("0","3","7","14","21","all"))



ggplot() +
       geom_density_ridges(data=plot.data,aes(x = boot.samples, y = time.periods,fill=time.periods),stat="binline",bins=25,scale=0.7, draw_baseline=T,color="grey40") +
       scale_fill_manual(values=c(col.igm,col.mild.igg,col.igg,"#FEE08B","#5E4FA2","#D53E4F"),name = "Time periods",guide = guide_legend(reverse=T)) +
       scale_color_manual(values=c(col.igm,col.mild.igg,col.igg,"#FEE08B","#5E4FA2","#D53E4F"),name = "Time periods",guide = guide_legend(reverse=T)) +
       ylab("Maximum time period included") +
       xlab("Time since symptom onset") +
       ggtitle("IgM") +
       geom_line(data = norm.fit.plot, aes(x=time, y = val,col=time.periods)) +
       scale_x_continuous(limits=c(0,25)) +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size  = 12),text = element_text(size = 12),axis.text = element_text(size = 12),axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),legend.position  =  "none",panel.background  =  element_rect(fill  =  'white'))








```

#### Overall and disease severity       

Fitted normal distributions.     

Mean overall = `r  round(norm.fit$estimate[1],2) `     
SD overall = `r  round(norm.fit$estimate[2],2) `     

Mean mild = `r  round(norm.fit.igm.mild.all$estimate[1],2) `     
SD mild = `r  round(norm.fit.igm.mild.all$estimate[2],2) `     

Mean mild ELISA Spike = `r  round(norm.fit.igm.mild.elisa.spike$estimate[1],2) `     
SD mild ELISA Spike = `r  round(norm.fit.igm.mild.elisa.spike$estimate[2],2) `     

Mean severe = `r  round(norm.fit.igm.severe.all$estimate[1],2) `     
SD severe = `r  round(norm.fit.igm.severe.all$estimate[2],2) `    

Mean severe ELISA Spike = `r  round(norm.fit.igm.severe.elisa.spike$estimate[1],2) `     
SD severe ELISA Spike = `r  round(norm.fit.igm.severe.elisa.spike$estimate[2],2) `    


Difference between the two distributions:     
(Welch two sample t-test (unequal variances))       


```{r fig.height=4,fig.width=9}
n1 = length(unique(sc0.igm.mild.all$id))
n2 = length(unique(sc0.igm.severe.all$id))
mean1 = norm.fit.igm.mild.all$estimate[1]
mean2 = norm.fit.igm.severe.all$estimate[1]
sd1 = norm.fit.igm.mild.all$estimate[2]
sd2 = norm.fit.igm.severe.all$estimate[2]

set.seed(1234)
z1 = rnorm(n1)
x1 = scale(z1)*sd1+mean1
z2 = rnorm(n2)
x2 = scale(z2)*sd2+mean2
t.test(x1,x2) # Welch-Satterthwaite
```


<br>




```{r fig.height=4,fig.width=11}
plot1 = ggplot(data = boot.samples.df, aes(x = boot.samples)) +
       geom_histogram(aes(y  =  ..density..),binwidth  =  1, fill  =  col.igm, color  =  col.igm,alpha=0.5) +
       stat_function(fun = dnorm, args = list(mean = norm.fit$estimate[1], sd = norm.fit$estimate[2]),col=col.igm,size=1.3,alpha=1) +
       scale_x_continuous(breaks = seq(0,(max(boot.samples.df$boot.samples)+2),5),limits=c(0,max(boot.samples.df$boot.samples+2))) +
       ggtitle("Mild + severe") +
       xlab("Seroconversion time") +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size = 12),
             text = element_text(size = 12),
             axis.text = element_text(size = 12),
             axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),
             legend.position  =  "none",
             panel.background  =  element_rect(fill  =  'white'))


# merge mild / severe results for plotting

boot.samples.df.igm.mild.severe.all = rbind(boot.samples.df.igm.mild.all,boot.samples.df.igm.severe.all)

boot.samples.df.igm.mild.severe.all$Severity = rep(c("Mild/Moderate","Severe/Critical"),each = nrow(boot.samples.df.igm.mild.all) )


plot2 = ggplot(data = boot.samples.df.igm.mild.severe.all, aes(x = boot.samples, fill = Severity)) +
       geom_histogram(aes(y  =  ..density..),binwidth  =  1,color  =  "black",  size=0.2,position="identity") +
       scale_fill_manual(values=c(col.mild.igm,col.severe.igm)) +
       stat_function(fun = dnorm, args = list(mean = norm.fit.igm.mild.all$estimate[1], sd = norm.fit.igm.mild.all$estimate[2]),col=col.mild.igm,size=1.3) +
       stat_function(fun = dnorm, args = list(mean = norm.fit.igm.severe.all$estimate[1], sd = norm.fit.igm.severe.all$estimate[2]),col=col.severe.igm,size=1.3) +
       scale_x_continuous(breaks = seq(0,(max(boot.samples.df.igm.mild.severe.all$boot.samples)+2),5),limits=c(0,max(boot.samples.df.igm.mild.severe.all$boot.samples+2))) +
       xlab("Seroconversion time") +
       ggtitle("IgM Disease Severity \n (all assays)") +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size = 12),
             text = element_text(size = 12),
             axis.text = element_text(size = 12),
             axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),
             legend.position  = c(0.7,0.8),
             panel.background  =  element_rect(fill  =  'white'))



# merge mild / severe elisa.np results for plotting

boot.samples.df.igm.mild.severe.elisa.spike = rbind(boot.samples.df.igm.mild.elisa.spike,boot.samples.df.igm.severe.elisa.spike)

boot.samples.df.igm.mild.severe.elisa.spike$Severity = rep(c("Mild/Moderate","Severe/Critical"),each = nrow(boot.samples.df.igm.mild.elisa.spike) )





plot3 = ggplot(data = boot.samples.df.igm.mild.severe.elisa.spike, aes(x = boot.samples, fill = Severity)) +
       geom_histogram(aes(y  =  ..density..),binwidth  =  1,color  =  "black", size=0.2,position="identity") +
       scale_fill_manual(values=c(col.mild.igm,col.severe.igm)) +
       stat_function(fun = dnorm, args = list(mean = norm.fit.igm.mild.elisa.spike$estimate[1], sd = norm.fit.igm.mild.elisa.spike$estimate[2]),col=col.mild.igm,size=1.3) +
       stat_function(fun = dnorm, args = list(mean = norm.fit.igm.severe.elisa.spike$estimate[1], sd = norm.fit.igm.severe.elisa.spike$estimate[2]),col=col.severe.igm,size=1.3) +
       scale_x_continuous(breaks = seq(0,(max(boot.samples.df.igm.mild.severe.elisa.spike$boot.samples)+2),5),limits=c(0,max(boot.samples.df.igm.mild.severe.elisa.spike$boot.samples+2))) +
       xlab("Seroconversion time") +
       ggtitle("IgM Disease Severity \n (ELISA Spike)") +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size = 12),
             text = element_text(size = 12),
             axis.text = element_text(size = 12),
             axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),
             legend.position  = c(0.7,0.8),
             panel.background  =  element_rect(fill  =  'white'))



plot1 + plot2 + plot3





plot4 = ggplot(data = boot.samples.df.igm.elisa.np, aes(x = boot.samples)) +
       geom_histogram(aes(y  =  ..density..),binwidth  =  1, fill  =  col.igm, color  =  col.igm,alpha=0.5) +
       stat_function(fun = dnorm, args = list(mean = norm.fit.igm.elisa.np$estimate[1], sd = norm.fit.igm.elisa.np$estimate[2]),col=col.igm,size=1.3,alpha=1) +
       scale_x_continuous(breaks = seq(0,(max(boot.samples.df.igm.elisa.np$boot.samples)+2),5),limits=c(0,max(boot.samples.df.igm.elisa.np$boot.samples+2))) +
       ggtitle("IgM ELISA NP \n (mild + severe)") +
       xlab("Seroconversion time") +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size = 12),
             text = element_text(size = 12),
             axis.text = element_text(size = 12),
             axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),
             legend.position  = 'none',
             panel.background  =  element_rect(fill  =  'white'))



plot5 = ggplot(data = boot.samples.df.igm.elisa.spike, aes(x = boot.samples)) +
       geom_histogram(aes(y  =  ..density..),binwidth  =  1, fill  =  col.igm, color  =  col.igm,alpha=0.5) +
       stat_function(fun = dnorm, args = list(mean = norm.fit.igm.elisa.spike$estimate[1], sd = norm.fit.igm.elisa.spike$estimate[2]),col=col.igm,size=1.3,alpha=1) +
       scale_x_continuous(breaks = seq(0,(max(boot.samples.df.igm.elisa.spike$boot.samples)+2),5),limits=c(0,max(boot.samples.df.igm.elisa.spike$boot.samples+2))) +
       ggtitle("IgM ELISA Spike  \n (mild + severe)") +
       xlab("Seroconversion time") +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size = 12),
             text = element_text(size = 12),
             axis.text = element_text(size = 12),
             axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),
             legend.position  = 'none',
             panel.background  =  element_rect(fill  =  'white'))




plot1 + plot4 + plot5


```




## IgG and IgM combined



```{r fig.height=8,fig.width=8}


boot.samples.df.igg.igm.elisa = rbind(boot.samples.df.igg.elisa.np,boot.samples.df.igm.elisa.spike)

boot.samples.df.igg.igm.elisa$marker = rep(c("IgG - ELISA NP","IgM - ELISA Spike"),each = nrow(boot.samples.df.igg.elisa.np) )


boot.samples.df.igg.igm.mclia = rbind(boot.samples.df.igg.mclia,boot.samples.df.igm.mclia)

boot.samples.df.igg.igm.mclia$marker = rep(c("IgG - MCLIA","IgM - MCLIA"),each = nrow(boot.samples.df.igg.mclia) )






plot1 = ggplot(data = boot.samples.df.igg.igm.elisa, aes(x = boot.samples, fill = marker)) +
       geom_histogram(aes(y  =  ..density..),binwidth  =  1,color  =  "black", alpha=0.6, size=0.2,position="identity") +
       scale_fill_manual(values=c(col.igg,col.igm)) +
       stat_function(fun = dnorm, args = list(mean = norm.fit.igg.elisa.np$estimate[1], sd = norm.fit.igg.elisa.np$estimate[2]),col=col.igg,size=1.3,alpha=0.9) +
       stat_function(fun = dnorm, args = list(mean = norm.fit.igm.elisa.spike$estimate[1], sd = norm.fit.igm.elisa.spike$estimate[2]),col=col.igm,size=1.3,alpha=0.9) +
       scale_x_continuous(breaks = seq(0,40,5),limits=c(0,40)) +
       xlab("") +
       ggtitle("") +
       annotate("text", label = "A", x = 0,y=0.15,size=7) +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size = 12),
             text = element_text(size = 12),
             axis.text = element_text(size = 12),
             axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),
             legend.text= element_text(size = 10),
             legend.position  = c(0.72,0.8),
             legend.background = element_rect(fill = "transparent"),
             legend.title = element_blank(),
             panel.background  =  element_rect(fill  =  'white'))


# ELISA Spike or NP
boot.samples.df.igg.igm.elisa.2 = rbind(boot.samples.df.igg.elisa.np.spike,boot.samples.df.igm.elisa.np.spike)

boot.samples.df.igg.igm.elisa.2$marker = rep(c("IgG - ELISA","IgM - ELISA"),each = nrow(boot.samples.df.igg.elisa.np.spike) )


plot1b = ggplot(data = boot.samples.df.igg.igm.elisa.2, aes(x = boot.samples, fill = marker)) +
       geom_histogram(aes(y  =  ..density..),binwidth  =  1,color  =  "black", alpha=0.6, size=0.2,position="identity") +
       scale_fill_manual(values=c(col.igg,col.igm)) +
       stat_function(fun = dnorm, args = list(mean = norm.fit.igg.elisa.np.spike$estimate[1], sd = norm.fit.igg.elisa.np.spike$estimate[2]),col=col.igg,size=1.3,alpha=0.9) +
       stat_function(fun = dnorm, args = list(mean = norm.fit.igm.elisa.np.spike$estimate[1], sd = norm.fit.igm.elisa.np.spike$estimate[2]),col=col.igm,size=1.3,alpha=0.9) +
       scale_x_continuous(breaks = seq(0,40,5),limits=c(0,40)) +
       xlab("") +
       ggtitle("") +
       annotate("text", label = "A", x = 0,y=0.15,size=7) +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size = 12),
             text = element_text(size = 12),
             axis.text = element_text(size = 12),
             axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),
             legend.text= element_text(size = 10),
             legend.position  = c(0.72,0.8),
             legend.background = element_rect(fill = "transparent"),
             legend.title = element_blank(),
             panel.background  =  element_rect(fill  =  'white'))



plot2 = ggplot(data = boot.samples.df.igg.igm.mclia, aes(x = boot.samples, fill = marker)) +
       geom_histogram(aes(y  =  ..density..),binwidth  =  1,color  =  "black", alpha=0.6, size=0.2,position="identity") +
       scale_fill_manual(values=c(col.igg,col.igm)) +
       stat_function(fun = dnorm, args = list(mean = norm.fit.igg.mclia$estimate[1], sd = norm.fit.igg.mclia$estimate[2]),col=col.igg,size=1.3,alpha=0.9) +
       stat_function(fun = dnorm, args = list(mean = norm.fit.igm.mclia$estimate[1], sd = norm.fit.igm.mclia$estimate[2]),col=col.igm,size=1.3,alpha=0.9) +
       scale_x_continuous(breaks = seq(0,40,5),limits=c(0,40)) +
       xlab("") +
       ggtitle("") +
       annotate("text", label = "B", x = 0,y=0.16,size=7) +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size = 12),
             text = element_text(size = 12),
             axis.text = element_text(size = 12),
             axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),
             legend.position  = c(0.8,0.8),
             legend.text= element_text(size = 10),
             legend.background = element_rect(fill = "transparent"),
             legend.title = element_blank(),
             panel.background  =  element_rect(fill  =  'white'))







plot3 = ggplot(data = boot.samples.df.igm.mild.severe.elisa.spike, aes(x = boot.samples, fill = Severity)) +
       geom_histogram(aes(y  =  ..density..),binwidth  =  1,color  =  "black",  size=0.2,position="identity") +
       scale_fill_manual(values=c(col.mild.igm,col.severe.igm)) +
       stat_function(fun = dnorm, args = list(mean = norm.fit.igm.mild.elisa.spike$estimate[1], sd = norm.fit.igm.mild.elisa.spike$estimate[2]),col=col.mild.igm,size=1.3) +
       stat_function(fun = dnorm, args = list(mean = norm.fit.igm.severe.elisa.spike$estimate[1], sd = norm.fit.igm.severe.elisa.spike$estimate[2]),col=col.severe.igm,size=1.3,alpha=0.4) +
       scale_x_continuous(breaks = seq(0,40,5),limits=c(0,40)) +
       xlab("Seroconversion time \n (days post symptom onset)") +
       ggtitle("IgM - ELISA Spike") +
       theme_classic(base_family = "Avenir Next") +
       annotate("text", label = "C", x = 0,y=0.19,size=7) +
       theme(plot.title  =  element_text(size = 10),
             text = element_text(size = 12),
             axis.text = element_text(size = 12),
             axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),
             legend.background = element_rect(fill = "transparent"),
             legend.text= element_text(size = 10),
             #legend.title = element_blank(),
             legend.position  = c(0.8,0.8),
             panel.background  =  element_rect(fill  =  'white'))



# ELISA NP or Spike

boot.samples.df.igm.mild.severe.elisa.np.spike = rbind(boot.samples.df.igm.mild.elisa.np.spike,boot.samples.df.igm.severe.elisa.np.spike)

boot.samples.df.igm.mild.severe.elisa.np.spike$Severity = rep(c("Mild/Moderate","Severe/Critical"),each = nrow(boot.samples.df.igm.mild.elisa.np.spike) )


plot3b = ggplot(data = boot.samples.df.igm.mild.severe.elisa.np.spike, aes(x = boot.samples, fill = Severity)) +
       geom_histogram(aes(y  =  ..density..),binwidth  =  1,color  =  "black",  size=0.2,position="identity") +
       scale_fill_manual(values=c(col.mild.igm,col.severe.igm)) +
       stat_function(fun = dnorm, args = list(mean = norm.fit.igm.mild.elisa.np.spike$estimate[1], sd = norm.fit.igm.mild.elisa.np.spike$estimate[2]),col=col.mild.igm,size=1.3) +
       stat_function(fun = dnorm, args = list(mean = norm.fit.igm.severe.elisa.np.spike$estimate[1], sd = norm.fit.igm.severe.elisa.np.spike$estimate[2]),col=col.severe.igm,size=1.3,alpha=0.4) +
       scale_x_continuous(breaks = seq(0,40,5),limits=c(0,40)) +
       xlab("Seroconversion time \n (days post symptom onset)") +
       ggtitle("IgM - ELISA") +
       theme_classic(base_family = "Avenir Next") +
       annotate("text", label = "C", x = 0,y=0.19,size=7) +
       theme(plot.title  =  element_text(size = 10),
             text = element_text(size = 12),
             axis.text = element_text(size = 12),
             axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),
             legend.background = element_rect(fill = "transparent"),
             legend.text= element_text(size = 10),
             #legend.title = element_blank(),
             legend.position  = c(0.8,0.8),
             panel.background  =  element_rect(fill  =  'white'))



plot4 = ggplot(data = boot.samples.df.igg.mild.severe.elisa.np, aes(x = boot.samples, fill = Severity)) +
       geom_histogram(aes(y  =  ..density..),binwidth  =  1,color  =  "black",  size=0.2,position="identity") +
       scale_fill_manual(values=c(col.mild.igg,col.severe.igg)) +
       stat_function(fun = dnorm, args = list(mean = norm.fit.igg.mild.elisa.np$estimate[1], sd = norm.fit.igg.mild.elisa.np$estimate[2]),col=col.mild.igg,size=1.3) +
       stat_function(fun = dnorm, args = list(mean = norm.fit.igg.severe.elisa.np$estimate[1], sd = norm.fit.igg.severe.elisa.np$estimate[2]),col=col.severe.igg,size=1.3) +
       scale_x_continuous(breaks = seq(0,40,5),limits=c(0,40)) +
       xlab("Seroconversion time \n (days post symptom onset)") +
       ggtitle("IgG - ELISA NP") +
       theme_classic(base_family = "Avenir Next") +
       annotate("text", label = "D", x = 0,y=0.16,size=7) +
       theme(plot.title  =  element_text(size = 10),
             text = element_text(size = 12),
             axis.text = element_text(size = 12),
             legend.text= element_text(size = 10),
             legend.title = element_blank(),
             legend.background = element_rect(fill = "transparent"),
             axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),
             legend.position  = c(0.8,0.8),
             panel.background  =  element_rect(fill  =  'white'))

# ELISA NP or Spike

boot.samples.df.igg.mild.severe.elisa.np.spike = rbind(boot.samples.df.igg.mild.elisa.np.spike,boot.samples.df.igg.severe.elisa.np.spike)

boot.samples.df.igg.mild.severe.elisa.np.spike$Severity = rep(c("Mild/Moderate","Severe/Critical"),each = nrow(boot.samples.df.igg.mild.elisa.np.spike) )


plot4b = ggplot(data = boot.samples.df.igg.mild.severe.elisa.np.spike, aes(x = boot.samples, fill = Severity)) +
       geom_histogram(aes(y  =  ..density..),binwidth  =  1,color  =  "black",  size=0.2,position="identity") +
       scale_fill_manual(values=c(col.mild.igg,col.severe.igg)) +
       stat_function(fun = dnorm, args = list(mean = norm.fit.igg.mild.elisa.np.spike$estimate[1], sd = norm.fit.igg.mild.elisa.np.spike$estimate[2]),col=col.mild.igg,size=1.3) +
       stat_function(fun = dnorm, args = list(mean = norm.fit.igg.severe.elisa.np.spike$estimate[1], sd = norm.fit.igg.severe.elisa.np.spike$estimate[2]),col=col.severe.igg,size=1.3) +
       scale_x_continuous(breaks = seq(0,40,5),limits=c(0,40)) +
       xlab("Seroconversion time \n (days post symptom onset)") +
       ggtitle("IgG - ELISA") +
       theme_classic(base_family = "Avenir Next") +
       annotate("text", label = "D", x = 0,y=0.16,size=7) +
       theme(plot.title  =  element_text(size = 10),
             text = element_text(size = 12),
             axis.text = element_text(size = 12),
             legend.text= element_text(size = 10),
             legend.title = element_blank(),
             legend.background = element_rect(fill = "transparent"),
             axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),
             legend.position  = c(0.8,0.8),
             panel.background  =  element_rect(fill  =  'white'))



plot1 + plot2 +
       plot3 + plot4

plot1b + plot2 +
       plot3b + plot4b
```




Difference between the IgG and IgM distributions:     
(Welch two sample t-test (unequal variances))       


```{r fig.height=4,fig.width=9}
n1 = length(unique(sc0.igg.elisa.np$id))
n2 = length(unique(sc0.igm.elisa.spike$id))
mean1 = norm.fit.igg.elisa.np$estimate[1]
mean2 = norm.fit.igm.elisa.spike$estimate[1]
sd1 = norm.fit.igg.elisa.np$estimate[2]
sd2 = norm.fit.igm.elisa.spike$estimate[2]

set.seed(1234)
z1 = rnorm(n1)
x1 = scale(z1)*sd1+mean1
z2 = rnorm(n2)
x2 = scale(z2)*sd2+mean2
t.test(x1,x2) # Welch-Satterthwaite
```





<br>

***

<br>



# Antibody and RNA detection probability over time        


<br>

***

<br>



## IgG     



```{r}

# create dataframe

# does not take into account uncertainty on time,
# only uses times for which absence/presence is certain.    


# one row for each day

# columns:
# - day 
# - number of positive individuals    
# - number of negative individuals     



# all assays, antigens
# remove duplicate IgG and IgM samples, remove Spike antigen, remove macaques 
d1 = d0[-which((d0$duplicated==1 & d0$antigen=="Spike") | d0$time.cat == "Exposure" | d0$test.type %in% c("mean","median") | is.na(d0$time.start)),]


d1.igg = d1[which(d1$marker == "IgG"),]
d1.igg = d1.igg[which(d1.igg$assay %in% c("MCLIA","ELISA","IFA")),]

probdat.igg = detection.prob(d1.igg)




d1 = d0 %>%
       filter(assay == "MCLIA" & time.cat == "Symptom onset" & !(test.type %in% c("mean","median")) & !is.na(time.start))

d1.igg = d1[which(d1$marker == "IgG"),]


probdat.igg.mclia = detection.prob(d1.igg)




d1 = d0 %>%
       filter(assay == "ELISA" & antigen == "Spike" & time.cat == "Symptom onset" & !(test.type %in% c("mean","median")) & !is.na(time.start))

d1.igg = d1[which(d1$marker == "IgG"),]


probdat.igg.elisa.spike = detection.prob(d1.igg)



d1 = d0 %>%
       filter(assay == "ELISA" & antigen == "NP" & time.cat == "Symptom onset" & !(test.type %in% c("mean","median")) & !is.na(time.start))

d1.igg = d1[which(d1$marker == "IgG"),]


probdat.igg.elisa.np = detection.prob(d1.igg)




d1 = d0 %>%
       filter(assay == "ELISA" & time.cat == "Symptom onset" & !(test.type %in% c("mean","median")) & !is.na(time.start))

d1.igg = d1[which(d1$marker == "IgG"),]


probdat.igg.elisa = detection.prob(d1.igg)



# mild cases

d1 = d0 %>%
       filter(assay == "ELISA" & time.cat == "Symptom onset" & !(test.type %in% c("mean","median")) & !is.na(time.start) & severity == "Mild_Moderate")

d1.igg.mild = d1[which(d1$marker == "IgG"),]


probdat.igg.mild.elisa = detection.prob(d1.igg.mild)





# severe cases

d1 = d0 %>%
       filter(assay == "ELISA" & time.cat == "Symptom onset" & !(test.type %in% c("mean","median")) & !is.na(time.start) & severity == "Severe_Critical")

d1.igg.severe = d1[which(d1$marker == "IgG"),]


probdat.igg.severe.elisa = detection.prob(d1.igg.severe)



```





```{r fig.height=4, fig.width=6}


smooth.igg = as.data.frame(predict(smooth.spline(probdat.igg$day,probdat.igg$prob,df = 4)))
smooth.igg$y[which(smooth.igg$y>1)] = 1
smooth.igg$y[which(smooth.igg$y<0)] = 0
colnames(smooth.igg) = c("day","prob")

ggplot(data=probdat.igg,aes(x = day, y = prob)) +
       geom_errorbar(aes(ymin = lowerci,ymax = upperci),color = col.igg, alpha = 0.4) +
       geom_point(color = col.igg,size = 1.5) +
       #stat_smooth(method="loess",level=.95,se=F,color=col.igg,alpha = 0.5) +
       geom_line(data = smooth.igg, aes(x = day, y = prob),size=1,color = col.igg) +
       scale_y_continuous(breaks = seq(0,1,0.1),limits=c(0,1)) +
       scale_x_continuous(breaks = seq(0,60,5),limits = c(0,63)) +
       theme_classic(base_family = "Avenir Next") +
       ggtitle("IgG (all assays/antigens)") +
       theme(plot.title  =  element_text(size  = 14),text = element_text(size = 12),axis.text = element_text(size = 12),axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),legend.position  =  "none",panel.background  =  element_rect(fill  =  'white')) +
       xlab("Days post symptom onset") +
       ylab("Detection probability")


smooth.igg.elisa.spike = as.data.frame(predict(smooth.spline(probdat.igg.elisa.spike$day,probdat.igg.elisa.spike$prob,df = 4)))
smooth.igg.elisa.spike$y[which(smooth.igg.elisa.spike$y>1)] = 1
smooth.igg.elisa.spike$y[which(smooth.igg.elisa.spike$y<0)] = 0
colnames(smooth.igg.elisa.spike) = c("day","prob")

ggplot(data=probdat.igg.elisa.spike,aes(x = day, y = prob)) +
       geom_errorbar(aes(ymin = lowerci,ymax = upperci),color = col.igg, alpha = 0.4) +
       geom_point(color = col.igg,size = 1.5) +
       #stat_smooth(method="loess",level=.95,se=F,color=col.igg,alpha = 0.5) +
       geom_line(data = smooth.igg.elisa.spike, aes(x = day, y = prob),size=1,color = col.igg) +
       scale_y_continuous(breaks = seq(0,1,0.1),limits=c(0,1)) +
       scale_x_continuous(breaks = seq(0,60,5),limits = c(0,63)) +
       theme_classic(base_family = "Avenir Next") +
       ggtitle("IgG (ELISA Spike)") +
       theme(plot.title  =  element_text(size  = 14),text = element_text(size = 12),axis.text = element_text(size = 12),axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),legend.position  =  "none",panel.background  =  element_rect(fill  =  'white')) +
       xlab("Days post symptom onset") +
       ylab("Detection probability")

smooth.igg.elisa.np = as.data.frame(predict(smooth.spline(probdat.igg.elisa.np$day,probdat.igg.elisa.np$prob,df = 4)))
smooth.igg.elisa.np$y[which(smooth.igg.elisa.np$y>1)] = 1
smooth.igg.elisa.np$y[which(smooth.igg.elisa.np$y<0)] = 0
colnames(smooth.igg.elisa.np) = c("day","prob")

ggplot(data=probdat.igg.elisa.np,aes(x = day, y = prob)) +
       geom_errorbar(aes(ymin = lowerci,ymax = upperci),color = col.igg, alpha = 0.4) +
       geom_point(color = col.igg,size = 1.5) +
       #stat_smooth(method="loess",level=.95,se=F,color=col.igg,alpha = 0.5) +
       geom_line(data = smooth.igg.elisa.np, aes(x = day, y = prob),size=1,color = col.igg) +
       scale_y_continuous(breaks = seq(0,1,0.1),limits=c(0,1)) +
       scale_x_continuous(breaks = seq(0,60,5),limits = c(0,63)) +
       theme_classic(base_family = "Avenir Next") +
       ggtitle("IgG (ELISA NP)") +
       theme(plot.title  =  element_text(size  = 14),text = element_text(size = 12),axis.text = element_text(size = 12),axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),legend.position  =  "none",panel.background  =  element_rect(fill  =  'white')) +
       xlab("Days post symptom onset") +
       ylab("Detection probability")


smooth.igg.elisa = as.data.frame(predict(smooth.spline(probdat.igg.elisa$day,probdat.igg.elisa$prob,df = 4)))
smooth.igg.elisa$y[which(smooth.igg.elisa$y>1)] = 1
smooth.igg.elisa$y[which(smooth.igg.elisa$y<0)] = 0
colnames(smooth.igg.elisa) = c("day","prob")

ggplot(data=probdat.igg.elisa,aes(x = day, y = prob)) +
       geom_errorbar(aes(ymin = lowerci,ymax = upperci),color = col.igg, alpha = 0.4) +
       geom_point(color = col.igg,size = 1.5) +
       #stat_smooth(method="loess",level=.95,se=F,color=col.igg,alpha = 0.5) +
       geom_line(data = smooth.igg.elisa, aes(x = day, y = prob),size=1,color = col.igg) +
       scale_y_continuous(breaks = seq(0,1,0.1),limits=c(0,1)) +
       scale_x_continuous(breaks = seq(0,60,5),limits = c(0,63)) +
       theme_classic(base_family = "Avenir Next") +
       ggtitle("IgG (ELISA)") +
       theme(plot.title  =  element_text(size  = 14),text = element_text(size = 12),axis.text = element_text(size = 12),axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),legend.position  =  "none",panel.background  =  element_rect(fill  =  'white')) +
       xlab("Days post symptom onset") +
       ylab("Detection probability")

smooth.igg.mclia = as.data.frame(predict(smooth.spline(probdat.igg.mclia$day,probdat.igg.mclia$prob,df = 4)))
smooth.igg.mclia$y[which(smooth.igg.mclia$y>1)] = 1
smooth.igg.mclia$y[which(smooth.igg.mclia$y<0)] = 0
colnames(smooth.igg.mclia) = c("day","prob")

ggplot(data=probdat.igg.mclia,aes(x = day, y = prob)) +
       geom_errorbar(aes(ymin = lowerci,ymax = upperci),color = col.igg, alpha = 0.4) +
       geom_point(color = col.igg,size = 1.5) +
       #stat_smooth(method="loess",level=.95,se=F,color=col.igg,alpha = 0.5) +
       geom_line(data = smooth.igg.mclia, aes(x = day, y = prob),size=1,color = col.igg) +
       scale_y_continuous(breaks = seq(0,1,0.1),limits=c(0,1)) +
       scale_x_continuous(breaks = seq(0,60,5),limits = c(0,63)) +
       theme_classic(base_family = "Avenir Next") +
       ggtitle("IgG (MCLIA)") +
       theme(plot.title  =  element_text(size  = 14),text = element_text(size = 12),axis.text = element_text(size = 12),axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),legend.position  =  "none",panel.background  =  element_rect(fill  =  'white')) +
       xlab("Days post symptom onset") +
       ylab("Detection probability")




```





<br>

***

<br>





## IgM     



```{r}

# create dataframe

# does not take into account uncertainty on time,
# only uses times for which absence/presence is certain.    


# one row for each day

# columns:
# - day 
# - number of positive individuals    
# - number of negative individuals     




# remove duplicate IgG and IgM samples, remove Spike antigen, remove macaques 
d1 = d0[-which((d0$duplicated==1 & d0$antigen=="Spike") | d0$time.cat == "Exposure" | d0$test.type %in% c("median","mean") | is.na(d0$time.start)),]

d1.igm = d1[which(d1$marker == "IgM"),]


d1.igm = d1.igm[which(d1.igm$assay %in% c("MCLIA","ELISA","IFA")),]   # very different results for 'gold immunochromatography'

probdat.igm = detection.prob(d1.igm)





d1 = d0 %>%
       filter(assay == "ELISA" & antigen == "Spike" & time.cat == "Symptom onset" & !(test.type %in% c("mean","median")) & !is.na(time.start))

d1.igm = d1[which(d1$marker == "IgM"),]


probdat.igm.elisa.spike = detection.prob(d1.igm)



d1 = d0 %>%
       filter(assay == "ELISA" & antigen == "NP" & time.cat == "Symptom onset" & !(test.type %in% c("mean","median")) & !is.na(time.start))

d1.igm = d1[which(d1$marker == "IgM"),]


probdat.igm.elisa.np = detection.prob(d1.igm)




d1 = d0 %>%
       filter(assay == "ELISA" & time.cat == "Symptom onset" & !(test.type %in% c("mean","median")) & !is.na(time.start))

d1.igm = d1[which(d1$marker == "IgM"),]


probdat.igm.elisa = detection.prob(d1.igm)



d1 = d0 %>%
       filter(assay == "MCLIA" & time.cat == "Symptom onset" & !(test.type %in% c("mean","median")) & !is.na(time.start))

d1.igm = d1[which(d1$marker == "IgM"),]


probdat.igm.mclia = detection.prob(d1.igm)




# mild cases

d1 = d0 %>%
       filter(assay == "ELISA" & time.cat == "Symptom onset" & !(test.type %in% c("mean","median")) & !is.na(time.start) & severity == "Mild_Moderate")

d1.igm.mild = d1[which(d1$marker == "IgM"),]


probdat.igm.mild.elisa = detection.prob(d1.igm.mild)





# severe cases

d1 = d0 %>%
       filter(assay == "ELISA" & time.cat == "Symptom onset" & !(test.type %in% c("mean","median")) & !is.na(time.start) & severity == "Severe_Critical")

d1.igm.severe = d1[which(d1$marker == "IgM"),]


probdat.igm.severe.elisa = detection.prob(d1.igm.severe)




```






```{r fig.height=4, fig.width=6}


smooth.igm = as.data.frame(predict(smooth.spline(probdat.igm$day,probdat.igm$prob,df=4)))
smooth.igm$y[which(smooth.igm$y>1)] = 1
smooth.igm$y[which(smooth.igm$y<0)] = 0
colnames(smooth.igm) = c("day","prob")

ggplot(data=probdat.igm,aes(x = day, y = prob)) +
       geom_errorbar(aes(ymin = lowerci,ymax = upperci),color = col.igm, alpha = 0.4) +
       geom_point(color = col.igm,size = 1.5) +
       #stat_smooth(method="loess",level=.95,se=F,color=col.igm,alpha = 0.5) +
       geom_line(data = smooth.igm, aes(x = day, y = prob),size=1,color = col.igm) +
       scale_y_continuous(breaks = seq(0,1,0.1),limits=c(0,1)) +
       scale_x_continuous(breaks = seq(0,60,5),limits = c(0,63)) +
       theme_classic(base_family = "Avenir Next") +
       ggtitle("IgM (all assays/antigens)") +
       theme(plot.title  =  element_text(size  = 14),text = element_text(size = 12),axis.text = element_text(size = 12),axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),legend.position  =  "none",panel.background  =  element_rect(fill  =  'white')) +
       xlab("Days post symptom onset") +
       ylab("Detection probability")


smooth.igm.elisa.spike = as.data.frame(predict(smooth.spline(probdat.igm.elisa.spike$day,probdat.igm.elisa.spike$prob,df = 4)))
smooth.igm.elisa.spike$y[which(smooth.igm.elisa.spike$y>1)] = 1
smooth.igm.elisa.spike$y[which(smooth.igm.elisa.spike$y<0)] = 0
colnames(smooth.igm.elisa.spike) = c("day","prob")

ggplot(data=probdat.igm.elisa.spike,aes(x = day, y = prob)) +
       geom_errorbar(aes(ymin = lowerci,ymax = upperci),color = col.igm, alpha = 0.4) +
       geom_point(color = col.igm,size = 1.5) +
       #stat_smooth(method="loess",level=.95,se=F,color=col.igm,alpha = 0.5) +
       geom_line(data = smooth.igm.elisa.spike, aes(x = day, y = prob),size=1,color = col.igm) +
       scale_y_continuous(breaks = seq(0,1,0.1),limits=c(0,1)) +
       scale_x_continuous(breaks = seq(0,60,5),limits = c(0,63)) +
       theme_classic(base_family = "Avenir Next") +
       ggtitle("IgM (ELISA Spike)") +
       theme(plot.title  =  element_text(size  = 14),text = element_text(size = 12),axis.text = element_text(size = 12),axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),legend.position  =  "none",panel.background  =  element_rect(fill  =  'white')) +
       xlab("Days post symptom onset") +
       ylab("Detection probability")

smooth.igm.elisa.np = as.data.frame(predict(smooth.spline(probdat.igm.elisa.np$day,probdat.igm.elisa.np$prob,df = 4)))
smooth.igm.elisa.np$y[which(smooth.igm.elisa.np$y>1)] = 1
smooth.igm.elisa.np$y[which(smooth.igm.elisa.np$y<0)] = 0
colnames(smooth.igm.elisa.np) = c("day","prob")

ggplot(data=probdat.igm.elisa.np,aes(x = day, y = prob)) +
       geom_errorbar(aes(ymin = lowerci,ymax = upperci),color = col.igm, alpha = 0.4) +
       geom_point(color = col.igm,size = 1.5) +
       #stat_smooth(method="loess",level=.95,se=F,color=col.igm,alpha = 0.5) +
       geom_line(data = smooth.igm.elisa.np, aes(x = day, y = prob),size=1,color = col.igm) +
       scale_y_continuous(breaks = seq(0,1,0.1),limits=c(0,1)) +
       scale_x_continuous(breaks = seq(0,60,5),limits = c(0,63)) +
       theme_classic(base_family = "Avenir Next") +
       ggtitle("IgM (ELISA NP)") +
       theme(plot.title  =  element_text(size  = 14),text = element_text(size = 12),axis.text = element_text(size = 12),axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),legend.position  =  "none",panel.background  =  element_rect(fill  =  'white')) +
       xlab("Days post symptom onset") +
       ylab("Detection probability")


smooth.igm.elisa = as.data.frame(predict(smooth.spline(probdat.igm.elisa$day,probdat.igm.elisa$prob,df = 4)))
smooth.igm.elisa$y[which(smooth.igm.elisa$y>1)] = 1
smooth.igm.elisa$y[which(smooth.igm.elisa$y<0)] = 0
colnames(smooth.igm.elisa) = c("day","prob")

ggplot(data=probdat.igm.elisa,aes(x = day, y = prob)) +
       geom_errorbar(aes(ymin = lowerci,ymax = upperci),color = col.igm, alpha = 0.4) +
       geom_point(color = col.igm,size = 1.5) +
       #stat_smooth(method="loess",level=.95,se=F,color=col.igm,alpha = 0.5) +
       geom_line(data = smooth.igm.elisa, aes(x = day, y = prob),size=1,color = col.igm) +
       scale_y_continuous(breaks = seq(0,1,0.1),limits=c(0,1)) +
       scale_x_continuous(breaks = seq(0,60,5),limits = c(0,63)) +
       theme_classic(base_family = "Avenir Next") +
       ggtitle("IgM (ELISA)") +
       theme(plot.title  =  element_text(size  = 14),text = element_text(size = 12),axis.text = element_text(size = 12),axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),legend.position  =  "none",panel.background  =  element_rect(fill  =  'white')) +
       xlab("Days post symptom onset") +
       ylab("Detection probability")

smooth.igm.mclia = as.data.frame(predict(smooth.spline(probdat.igm.mclia$day,probdat.igm.mclia$prob,df = 4)))
smooth.igm.mclia$y[which(smooth.igm.mclia$y>1)] = 1
smooth.igm.mclia$y[which(smooth.igm.mclia$y<0)] = 0
colnames(smooth.igm.mclia) = c("day","prob")

ggplot(data=probdat.igm.mclia,aes(x = day, y = prob)) +
       geom_errorbar(aes(ymin = lowerci,ymax = upperci),color = col.igm, alpha = 0.4) +
       geom_point(color = col.igm,size = 1.5) +
       #stat_smooth(method="loess",level=.95,se=F,color=col.igm,alpha = 0.5) +
       geom_line(data = smooth.igm.mclia, aes(x = day, y = prob),size=1,color = col.igm) +
       scale_y_continuous(breaks = seq(0,1,0.1),limits=c(0,1)) +
       scale_x_continuous(breaks = seq(0,60,5),limits = c(0,63)) +
       theme_classic(base_family = "Avenir Next") +
       ggtitle("IgM (MCLIA)") +
       theme(plot.title  =  element_text(size  = 14),text = element_text(size = 12),axis.text = element_text(size = 12),axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),legend.position  =  "none",panel.background  =  element_rect(fill  =  'white')) +
       xlab("Days post symptom onset") +
       ylab("Detection probability")



```





<br>

***

<br>



## IgG and IgM      


```{r fig.height=4, fig.width=6}


probdat.igg$Antibody = "IgG"
probdat.igm$Antibody = "IgM"

probdat.igg.igm = rbind(probdat.igg,probdat.igm)

probdat.igg.igm$day[which(probdat.igg.igm$Antibody == "IgM")] = probdat.igg.igm$day[which(probdat.igg.igm$Antibody == "IgM")] + 0.3
plot.igg.igm = ggplot(data=probdat.igg.igm,aes(x = day, y = prob,group=Antibody,color = Antibody)) +
       geom_errorbar(aes(ymin = lowerci,ymax = upperci),alpha = 0.4) +
       geom_point(size = 1.5,alpha=0.5) +
       stat_smooth(method="loess",level=.95,se=F,alpha = 0.5) +
       scale_y_continuous(breaks = seq(0,1,0.1),limits=c(0,1)) +
       scale_x_continuous(breaks = seq(0,60,5),limits = c(0,63)) +
       scale_color_manual(values=c(col.igg,col.igm)) +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size  = 12),
             text = element_text(size = 12),
             axis.text = element_text(size = 12),
             axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),
             legend.position  =  c(0.12,0.9),
             legend.text = element_text(size=10),
             legend.title = element_blank(), 
             legend.background = element_rect(fill  =  'transparent'), 
             panel.background  =  element_rect(fill  =  'white')) +
       xlab("Days post symptom onset") +
       ylab("Detection probability")

plot.igg.igm
#  brewer.pal(11,"Spectral")

```



<br>

***

<br>






## RNA     



```{r}

# create dataframe

# one row for each day

# columns:
# - day 
# - number of positive individuals    
# - number of negative individuals     


d1 = d0[which(d0$time.cat == "Symptom onset" & !(d0$test.type %in% c("mean","median"))),]


# any sample type except blood

d1.rna = d1[which(d1$marker == "Virus" & !(d1$sample.type %in% c("Blood","Serum_Plasma"))),]


probdat.rna = detection.prob(d1.rna)



# faeces

d1.rna.faeces = d1[which(d1$marker == "Virus" & d1$sample.type == "Faeces"),]


probdat.rna.faeces = detection.prob(d1.rna.faeces)




# urine

d1.rna.urine = d1[which(d1$marker == "Virus" & d1$sample.type == "Urine"),]
nrow(d1.rna.urine)
# probdat.rna.urine = detection.prob(d1.rna.urine)
# not enough data



# upper respiratory tract
d1.rna.upper.resp = d1[which(d1$marker == "Virus" & d1$sample.type == "Upper_respiratory"),]

probdat.rna.upper.resp = detection.prob(d1.rna.upper.resp)




# lower respiratory tract
d1.rna.lower.resp = d1[which(d1$marker == "Virus" & d1$sample.type == "Lower_respiratory"),]

probdat.rna.lower.resp = detection.prob(d1.rna.lower.resp)



```





```{r fig.height=4, fig.width=6}


probdat.rna.faeces$Sample = "Faeces"
probdat.rna.upper.resp$Sample = "Upper respiratory tract"
probdat.rna.lower.resp$Sample = "Lower respiratory tract"

probdat.rna.df = rbind(probdat.rna.faeces,probdat.rna.upper.resp,probdat.rna.lower.resp)

probdat.rna.df$day[which(probdat.rna.df$Sample == "Lower respiratory tract")] = probdat.rna.df$day[which(probdat.rna.df$Sample == "Lower respiratory tract")] + 0.2

probdat.rna.df$day[which(probdat.rna.df$Sample == "Upper respiratory tract")] = probdat.rna.df$day[which(probdat.rna.df$Sample == "Upper respiratory tract")] + 0.4



smooth.upper.resp = as.data.frame(predict(smooth.spline(probdat.rna.df$day[which(probdat.rna.df$Sample == "Upper respiratory tract")],probdat.rna.df$prob[which(probdat.rna.df$Sample == "Upper respiratory tract")],df = 4)))
smooth.upper.resp$Sample = "Upper respiratory tract"
smooth.upper.resp$y[which(smooth.upper.resp$y>1)] = 1
smooth.upper.resp$y[which(smooth.upper.resp$y<0)] = 0

smooth.lower.resp = as.data.frame(predict(smooth.spline(probdat.rna.df$day[which(probdat.rna.df$Sample == "Lower respiratory tract")],probdat.rna.df$prob[which(probdat.rna.df$Sample == "Lower respiratory tract")],df = 4)))
smooth.lower.resp$Sample = "Lower respiratory tract"
smooth.lower.resp$y[which(smooth.lower.resp$y>1)] = 1
smooth.lower.resp$y[which(smooth.lower.resp$y<0)] = 0


smooth.faeces = as.data.frame(predict(smooth.spline(probdat.rna.df$day[which(probdat.rna.df$Sample == "Faeces")],probdat.rna.df$prob[which(probdat.rna.df$Sample == "Faeces")],df = 4)))
smooth.faeces$Sample = "Faeces"
smooth.faeces$y[which(smooth.faeces$y>1)] = 1
smooth.faeces$y[which(smooth.faeces$y<0)] = 0


smooth.pred = rbind(smooth.upper.resp,smooth.lower.resp,smooth.faeces)

plot.rna.all = ggplot(data=probdat.rna.df,aes(x = day, y = prob,group=Sample,color = Sample)) +
       geom_errorbar(aes(ymin = lowerci,ymax = upperci),alpha = 0.4) +
       geom_point(size = 1.5,alpha=0.5) +
       #stat_smooth(method="loess",level=.95,se=T,alpha = 0.3,fullrange = T) +
       #stat_smooth(method="loess",level=.95,se=F,alpha = 0.5) +
       geom_line(data = smooth.pred, aes(x = x, y = y),size=1) +
       scale_y_continuous(breaks = seq(0,1,0.1),limits=c(-1,1.5)) +
       scale_x_continuous(breaks = seq(0,60,5),limits = c(0,60)) +
       scale_color_manual(values=c(col.rna2,col.rna3,col.rna4)) +
       annotate("text", label = "B", x = 58,y=1,size=7) +
       theme_classic(base_family = "Avenir Next") +
       coord_cartesian(xlim=c(0,60), ylim=c(0,1)) +
       ylim(0,1) +
       theme(plot.title  =  element_text(size  = 12),
             text = element_text(size = 15),
             axis.text = element_text(size = 15),
             axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),
             legend.position  =  c(0.2,0.1),
             legend.text = element_text(size=14),
             legend.title = element_blank(), 
             legend.background = element_rect(fill  =  'transparent', color = "transparent"), 
             legend.key.size = unit(0.1,"cm"),
             panel.background  =  element_rect(fill  =  'white')) +
       xlab("Days post symptom onset") +
       ylab("Detection probability")


plot.rna.all.old = ggplot(data=probdat.rna.df,aes(x = day, y = prob,group=Sample,color = Sample)) +
       geom_errorbar(aes(ymin = lowerci,ymax = upperci),alpha = 0.4) +
       geom_point(size = 1.5,alpha=0.5) +
       #stat_smooth(method="loess",level=.95,se=T,alpha = 0.3,fullrange = T) +
       stat_smooth(method="loess",level=.95,se=F,alpha = 0.5) +
       scale_y_continuous(breaks = seq(0,1,0.1),limits=c(-1,1.5)) +
       scale_x_continuous(breaks = seq(0,60,5),limits = c(0,60)) +
       scale_color_manual(values=c(col.rna2,col.rna3,col.rna4)) +
       annotate("text", label = "B", x = 58,y=1,size=7) +
       theme_classic(base_family = "Avenir Next") +
       coord_cartesian(xlim=c(0,60), ylim=c(0,1)) +
       ylim(0,1) +
       theme(plot.title  =  element_text(size  = 12),
             text = element_text(size = 15),
             axis.text = element_text(size = 15),
             axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),
             legend.position  =  c(0.2,0.1),
             legend.text = element_text(size=14),
             legend.title = element_blank(), 
             legend.background = element_rect(fill  =  'transparent', color = "transparent"), 
             legend.key.size = unit(0.1,"cm"),
             panel.background  =  element_rect(fill  =  'white')) +
       xlab("Days post symptom onset") +
       ylab("Detection probability")



plot.rna.all




```





<br>

***

<br>









## Neutralizing antibody     



```{r}

# create dataframe

# one row for each day

# columns:
# - day 
# - number of positive individuals    
# - number of negative individuals     



d1 = d0[-which((d0$time.cat != "Symptom onset" | d0$test.type %in% c("mean","median") | is.na(d0$time.start))),]

d1.nt = d1[which(d1$marker == "NT Ab"),]


probdat.nt = detection.prob(d1.nt)

```





```{r fig.height=4, fig.width=6}


smooth.nt = as.data.frame(predict(smooth.spline(probdat.nt$day,probdat.nt$prob,df=4)))
smooth.nt$y[which(smooth.nt$y>1)] = 1
smooth.nt$y[which(smooth.nt$y<0)] = 0
colnames(smooth.nt) = c("day","prob")

ggplot(data=probdat.nt,aes(x = day, y = prob)) +
       geom_errorbar(aes(ymin = lowerci,ymax = upperci),color = col.rna, alpha = 0.4) +
       geom_point(color = col.rna,size = 1.5) +
       #stat_smooth(method="loess",level=.95,se=F,color=col.rna,alpha = 0.5) +
       geom_line(data = smooth.nt, aes(x = day, y = prob),size=1,color = col.rna) +
       scale_y_continuous(breaks = seq(0,1,0.1),limits=c(0,1)) +
       scale_x_continuous(breaks = seq(0,60,5)) +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(14),text = element_text(size = 12),axis.text = element_text(size = 12),axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),legend.position  =  "none",panel.background  =  element_rect(fill  =  'white')) +
       xlab("Days post symptom onset") +
       ylab("Detection probability")



```





<br>

***

<br>











## IgG, IgM, Neutralizing Ab        


```{r fig.height=4, fig.width=6}


probdat.igg$Antibody = "IgG"
probdat.igm$Antibody = "IgM"
probdat.nt$Antibody = "NT"

probdat.comb = rbind(probdat.igg,probdat.igm, probdat.nt)

probdat.comb$day [ which(probdat.comb$Antibody == "IgM") ] = probdat.comb$day [ which(probdat.comb$Antibody == "IgM") ] + 0.4
probdat.comb$day [ which(probdat.comb$Antibody == "NT") ] = probdat.comb$day [ which(probdat.comb$Antibody == "NT") ] + 0.2


smooth.igg = as.data.frame(predict(smooth.spline(probdat.comb$day[which(probdat.comb$Antibody == "IgG")],probdat.comb$prob[which(probdat.comb$Antibody == "IgG")],df = 4)))
smooth.igg$Antibody = "IgG"
smooth.igg$y[which(smooth.igg$y>1)] = 1
smooth.igg$y[which(smooth.igg$y<0)] = 0

smooth.igm = as.data.frame(predict(smooth.spline(probdat.comb$day[which(probdat.comb$Antibody == "IgM")],probdat.comb$prob[which(probdat.comb$Antibody == "IgM")],df = 4)))
smooth.igm$Antibody = "IgM"
smooth.igm$y[which(smooth.igm$y>1)] = 1
smooth.igm$y[which(smooth.igm$y<0)] = 0


smooth.nt = as.data.frame(predict(smooth.spline(probdat.comb$day[which(probdat.comb$Antibody == "NT")],probdat.comb$prob[which(probdat.comb$Antibody == "NT")],df = 4)))
smooth.nt$Antibody = "NT"
smooth.nt$y[which(smooth.nt$y>1)] = 1
smooth.nt$y[which(smooth.nt$y<0)] = 0


smooth.pred = rbind(smooth.igg,smooth.igm,smooth.nt)
colnames(smooth.pred) = c("day","prob","Antibody")

plot.igg.igm.nt = ggplot(data=probdat.comb,aes(x = day, y = prob,group=Antibody,color = Antibody)) +
       geom_errorbar(aes(ymin = lowerci,ymax = upperci),alpha = 0.4) +
       geom_point(size = 1.5,alpha=0.5) +
       #stat_smooth(method="loess",level=.95,se=F,alpha = 0.2) +
       geom_line(data = smooth.pred, aes(x = day, y = prob),size=1) +
       scale_y_continuous(breaks = seq(0,1,0.1),limits=c(0,1)) +
       scale_x_continuous(breaks = seq(0,60,5),limits = c(-0.5,63)) +
       scale_color_manual(values=c(col.igg,col.igm,col.ntab)) +
       theme_classic(base_family = "Avenir Next") +
       annotate("text", label = "A", x = -0.5,y=1,size=7) +
       theme(plot.title  =  element_text(size  = 12),
             text = element_text(size = 15),
             axis.text = element_text(size = 15),
             axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),
             legend.position  =  c(0.08,0.8),
             legend.text = element_text(size=14),
             legend.title = element_blank(), 
             legend.background = element_rect(fill  =  'transparent', color = "transparent"), 
             legend.key.size = unit(0.1,"cm"),
             panel.background  =  element_rect(fill  =  'white')) +
       xlab("Days post symptom onset") +
       ylab("Detection probability")

plot.igg.igm.nt
#  brewer.pal(11,"Spectral")

```





```{r fig.height=4, fig.width=6}


probdat.igg.elisa.np$Antibody = "IgG"
probdat.igm.elisa.spike$Antibody = "IgM"


probdat.comb2 = rbind(probdat.igg.elisa.np,probdat.igm.elisa.spike, probdat.nt)

probdat.comb2$day [ which(probdat.comb2$Antibody == "IgM") ] = probdat.comb2$day [ which(probdat.comb2$Antibody == "IgM") ] + 0.4
probdat.comb2$day [ which(probdat.comb2$Antibody == "NT") ] = probdat.comb2$day [ which(probdat.comb2$Antibody == "NT") ] + 0.2

plot.igg.igm.nt.v2 = ggplot(data=probdat.comb2,aes(x = day, y = prob,group=Antibody,color = Antibody)) +
       geom_errorbar(aes(ymin = lowerci,ymax = upperci),alpha = 0.4) +
       geom_point(size = 1.5,alpha=0.5) +
       stat_smooth(method="loess",level=.95,se=F,alpha = 0.2) +
       scale_y_continuous(breaks = seq(0,1,0.1),limits=c(0,1)) +
       scale_x_continuous(breaks = seq(0,60,5),limits = c(-0.5,63)) +
       scale_color_manual(values=c(col.igg,col.igm,col.ntab)) +
       theme_classic(base_family = "Avenir Next") +
       annotate("text", label = "A", x = -0.5,y=1,size=7) +
       theme(plot.title  =  element_text(size  = 12),
             text = element_text(size = 15),
             axis.text = element_text(size = 15),
             axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),
             legend.position  =  c(0.08,0.82),
             legend.text = element_text(size=14),
             legend.title = element_blank(), 
             legend.background = element_rect(fill  =  'transparent', color = "transparent"), 
             legend.key.size = unit(0.1,"cm"),
             panel.background  =  element_rect(fill  =  'white')) +
       xlab("Days post symptom onset") +
       ylab("Detection probability")

plot.igg.igm.nt.v2
#  brewer.pal(11,"Spectral")

```




## IgG, IgM, RNA upper resp     


```{r fig.height=4, fig.width=6}


probdat.igg$Antibody = "IgG"
probdat.igm$Antibody = "IgM"
probdat.rna.upper.resp$Antibody = "RNA (Upper resp.)"

probdat.comb = rbind(probdat.igg,probdat.igm, probdat.rna.upper.resp[,-which(colnames(probdat.rna.upper.resp) == "Sample")])

probdat.comb$day [ which(probdat.comb$Antibody == "IgM") ] = probdat.comb$day [ which(probdat.comb$Antibody == "IgM") ] + 0.4
probdat.comb$day [ which(probdat.comb$Antibody == "RNA (Upper resp.)") ] = probdat.comb$day [ which(probdat.comb$Antibody == "RNA (Upper resp.)") ] + 0.2


ggplot(data=probdat.comb,aes(x = day, y = prob,group=Antibody,color = Antibody)) +
       geom_errorbar(aes(ymin = lowerci,ymax = upperci),alpha = 0.4) +
       geom_point(size = 1.5,alpha=0.5) +
       stat_smooth(method="loess",level=.95,se=F,alpha = 0.2) +
       scale_y_continuous(breaks = seq(0,1,0.1),limits=c(0,1)) +
       scale_x_continuous(breaks = seq(0,60,5),limits = c(0,63)) +
       scale_color_manual(values=c(col.igg,col.igm,col.rna)) +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size  = 12),
             text = element_text(size = 12),
             axis.text = element_text(size = 12),
             axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),
             legend.position  =  c(0.5,0.5),
             legend.text = element_text(size=10),
             legend.title = element_blank(), 
             legend.background = element_rect(fill  =  'transparent', color = "transparent"), 
             legend.key.size = unit(0.1,"cm"),
             panel.background  =  element_rect(fill  =  'white')) +
       xlab("Days since symptom onset") +
       ylab("Detection probability")


probdat.comb.igm.igg.rna = probdat.comb


```



<br>

***

<br>



## Combine figures IgG IgM NT Ab, RNA      


```{r fig.height=5, fig.width=15}



plot.igg.igm.nt + plot.rna.all

plot.igg.igm.nt.v2 + plot.rna.all


plot.igg.igm + plot.rna.all


```











## IgG disease severity      


```{r fig.height=4, fig.width=6}


probdat.igg.mild.elisa$Severity = "Mild/Moderate"
probdat.igg.severe.elisa$Severity = "Severe/Critical"

probdat.igg.mild.severe = rbind(probdat.igg.mild.elisa,probdat.igg.severe.elisa)

probdat.igg.mild.severe$day [ which(probdat.igg.mild.severe$Severity == "Severe/Critical") ] = probdat.igg.mild.severe$day [ which(probdat.igg.mild.severe$Severity == "Severe/Critical") ] + 0.3

ggplot(data=probdat.igg.mild.severe,aes(x = day, y = prob,group=Severity,color = Severity)) +
       geom_errorbar(aes(ymin = lowerci,ymax = upperci),alpha = 0.4) +
       geom_point(size = 1.5,alpha=0.5) +
       stat_smooth(method="loess",level=.95,se=F,alpha = 0.5) +
       scale_y_continuous(breaks = seq(0,1,0.1),limits=c(0,1)) +
       scale_x_continuous(breaks = seq(0,60,5),limits = c(0,63)) +
       scale_color_manual(values=c(col.igg,col.igm)) +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size  = 12),
             text = element_text(size = 12),
             axis.text = element_text(size = 12),
             axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),
             legend.position  =  c(0.12,0.9),
             legend.text = element_text(size=10),
             legend.title = element_blank(), 
             legend.background = element_rect(fill  =  'transparent', color = "transparent"), 
             legend.key.size = unit(0.1,"cm"),
             panel.background  =  element_rect(fill  =  'white')) +
       xlab("Days since symptom onset") +
       ylab("Detection probability")


```




## IgM disease severity      


```{r fig.height=4, fig.width=6}


probdat.igm.mild.elisa$Severity = "Mild/Moderate"
probdat.igm.severe.elisa$Severity = "Severe/Critical"

probdat.igm.mild.severe = rbind(probdat.igm.mild.elisa,probdat.igm.severe.elisa)

probdat.igm.mild.severe$day [ which(probdat.igm.mild.severe$Severity == "Severe/Critical") ] = probdat.igm.mild.severe$day [ which(probdat.igm.mild.severe$Severity == "Severe/Critical") ] + 0.3


ggplot(data=probdat.igm.mild.severe,aes(x = day, y = prob,group=Severity,color = Severity)) +
       geom_errorbar(aes(ymin = lowerci,ymax = upperci),alpha = 0.4) +
       geom_point(size = 1.5,alpha=0.5) +
       stat_smooth(method="loess",level=.95,se=F,alpha = 0.5) +
       scale_y_continuous(breaks = seq(0,1,0.1),limits=c(0,1)) +
       scale_x_continuous(breaks = seq(0,60,5),limits = c(0,63)) +
       scale_color_manual(values=c(col.igg,col.igm)) +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size  = 12),
             text = element_text(size = 12),
             axis.text = element_text(size = 12),
             axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),
             legend.position  =  c(0.12,0.9),
             legend.text = element_text(size=10),
             legend.title = element_blank(), 
             legend.background = element_rect(fill  =  'transparent', color = "transparent"), 
             legend.key.size = unit(0.1,"cm"),
             panel.background  =  element_rect(fill  =  'white')) +
       xlab("Days since symptom onset") +
       ylab("Detection probability")


```




## IgG and IgM disease severity      


```{r fig.height=4, fig.width=9}


probdat.igg.mild.elisa$Severity = "Mild/Moderate"
probdat.igg.mild.elisa$Antibody = "IgG"
probdat.igg.severe.elisa$Severity = "Severe/Critical"
probdat.igg.severe.elisa$Antibody = "IgG"
probdat.igm.mild.elisa$Severity = "Mild/Moderate"
probdat.igm.mild.elisa$Antibody = "IgM"
probdat.igm.severe.elisa$Severity = "Severe/Critical"
probdat.igm.severe.elisa$Antibody = "IgM"


probdat.igg.igm.mild.severe = rbind(probdat.igg.mild.elisa,probdat.igg.severe.elisa,probdat.igm.mild.elisa,probdat.igm.severe.elisa)

ggplot(data=probdat.igg.igm.mild.severe,aes(x = day, y = prob,group=paste(Severity,Antibody),color = paste(Severity,Antibody))) +
       geom_errorbar(aes(ymin = lowerci,ymax = upperci)) +
       geom_point(size = 1.5) +
       stat_smooth(method="loess",level=.95,se=F) +
       scale_y_continuous(breaks = seq(0,1,0.1),limits=c(0,1)) +
       scale_x_continuous(breaks = seq(0,60,5),limits = c(0,63)) +
       scale_color_manual(values=c(col.severe.igg,col.mild.igg,col.severe.igm,col.mild.igm)) +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size  = 12),
             text = element_text(size = 12),
             axis.text = element_text(size = 12),
             axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),
             legend.text = element_text(size=10),
             legend.title = element_blank(), 
             legend.background = element_rect(fill  =  'transparent', color = "transparent"), 
             legend.key.size = unit(0.1,"cm"),
             panel.background  =  element_rect(fill  =  'white')) +
       xlab("Days since symptom onset") +
       ylab("Detection probability")


```




# Titer kinetics over time       


<br>

***

<br>



## IgG       


### ELISA Spike     

Marker = IgG       
Assay = ELISA      
Antigen = Spike       
Disease severity = any     
Minimum number of datapoints per individual = 3    



```{r results='hide',fig.width=11,fig.height=6}


d2 = d0 [ which(d0$marker=="IgG" & !is.na(d0$test.result) & d0$assay == "ELISA" & d0$antigen == "Spike" & d0$time.estimate.cat == "Exact" & d0$time.cat == "Symptom onset"),]

# remove duplicates, only keep Okba duplicates with original Spike antigen
d2 = d2[!(d2$author == "Okba" & d2$antigen.original != "Spike"),]



# only keep individuals that have at least one positive sample
posnegcount = as.data.frame(xtabs(~ id + test.pos.neg,d2))
id.keep = droplevels(posnegcount$id[which(posnegcount$test.pos.neg == "POS" & posnegcount$Freq>1)])
d2 = d2 [ which(d2$id %in% id.keep),]



# only keep individuals that have at least 3 samples in total
id.keep = droplevels(as.data.frame(table(d2$id))$Var1[which(as.data.frame(table(d2$id))$Freq > 2)])
d2 = d2 [ which(d2$id %in% id.keep),]
N.inds = length(unique(d2$id))
N.inds

N.inds.IgG.ELISA.Spike = N.inds


for(i in 1:length(unique(paste0(d2$study,d2$units)))){
       
       d2$test.result[which(paste0(d2$study,d2$units) == unique(paste0(d2$study,d2$units))[i])] = d2$test.result[which(paste0(d2$study,d2$units) == unique(paste0(d2$study,d2$units))[i])]/max(d2$test.result[which(paste0(d2$study,d2$units) == unique(paste0(d2$study,d2$units))[i])])
}



# remove negative point that is unlikely to be correct
d2 = d2[-which(d2$id == "To_BB22196-1" & d2$test.result==0),]



# check for outliers
ggplot() +
       geom_point(data=d2,aes(x = time.start, y = test.result,col=id,group=id),size = 1.5) +
       geom_line(data=d2,aes(x = time.start, y = test.result,col=id,group=id),size=0.7) +
       #scale_x_continuous(breaks = seq(0,max(d2$time.start),2)) +
       scale_y_continuous(limits=c(0,1)) +
       #scale_color_gradientn(colors  =  rev(brewer.pal(11,"Spectral"))) +
       # scale_color_brewer(palette = "Spectral", name = "Marker/Assay") +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size  = 10),
             text = element_text(size = 12),
             axis.text = element_text(size = 12),
             axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),
             panel.background  =  element_rect(fill  =  'white')) +
       xlab("Days post symptom onset") +
       ylab("Antibody level")



# run MCMC or load previous data? 
run.mcmc.again = F

if(run.mcmc.again == T){
       model.jags = jags.model(model.file,
                               data=list('titer'=d2$test.result,
                                         'time'=d2$time.start,
                                         'id'=as.numeric(as.factor(d2$id)),
                                         'N.id'=length(unique(d2$id))
                               ),
                               #inits=list('peak.titer.sd.hyper'=0.5),
                               n.chains=6,
                               n.adapt = 1000)
       
       
       # burn in
       burn.in = 20000
       update(model.jags, n.iter = burn.in, by = 1)
       
       
       # draw samples
       iterations = 50000
       post = coda.samples(model.jags, c("peak.titer.mean.hyper","peak.titer.sd.hyper","peak.titer","displacement.mean.hyper","displacement.sd.hyper","displacement","growth.rate.mean.hyper","growth.rate"), n.iter = iterations, thin = 1)
       
       
       post.df = mcmclist.to.dataframe(post)
       
       saveRDS(post,file = paste0("MCMC_output/MCMC_output_post_",format(Sys.time(),"%Y%m%d_%H%M%S"),".RDS"))
       
       saveRDS(post.df,file = paste0("MCMC_output/MCMC_output_postdf_",format(Sys.time(),"%Y%m%d_%H%M%S"),".RDS"))
       
} else { 
       
       # enter the corresponding mcmc filenames here, as saved in the saveRDS lines above
       # example: post = readRDS("MCMC_output/MCMC_output_post_20200804_163314.RDS")
       post = readRDS("MCMC_output/")
       post.df = readRDS("MCMC_output/")
}



N.inds = length(unique(d2$id))



```


#### Gelman-Rubin convergence diagnostics:    

```{r}
gelman.diag(post)
```

#### Posterior growth rate:     


```{r fig.height = 3, fig.width=4}

plot.MCMC.posterior(input.data = post.df,column.to.plot = which(names(post.df)=="growth.rate.mean.hyper"),x.axis.label = "Growth rate (1/days)",title = "Posterior growth rate")

plot.MCMC.chains(input.data = post.df,column.to.plot = which(names(post.df)=="growth.rate.mean.hyper"),y.axis.label = "Growth rate (1/days)",title = "Posterior growth rate",thinning = 5) 


growth.rate.overall.mean = mean(post.df$growth.rate.mean.hyper)

```


#### Posterior peak titer overall mean:    


```{r fig.height = 3, fig.width=4}
plot.MCMC.posterior(input.data = post.df,column.to.plot = which(colnames(post.df)=="peak.titer.mean.hyper"),x.axis.label = "Peak titer mean",title = "Posterior peak titer mean")

plot.MCMC.chains(input.data = post.df,column.to.plot = which(colnames(post.df)=="peak.titer.mean.hyper"),y.axis.label = "Peak titer mean",title = "Posterior peak titer mean",thinning = 5) 

peak.titer.overall.mean = mean(post.df$peak.titer.mean.hyper)


```




#### Posterior displacement overall mean:      


```{r fig.height = 3, fig.width=4}
plot.MCMC.posterior(input.data = post.df,column.to.plot = which(names(post.df)=="displacement.mean.hyper"),x.axis.label = "Displacement mean",title = "Posterior displacement mean")

plot.MCMC.chains(input.data = post.df,column.to.plot = which(names(post.df)=="displacement.mean.hyper"),y.axis.label = "Displacement mean",title = "Posterior displacement mean",thinning = 5) 

displacement.overall.mean = mean(post.df$displacement.mean.hyper)
```




```{r}
# calculate posterior means

peak.titer.individual.means = as.data.frame(apply(post.df[,(4+N.inds+N.inds):(3+N.inds+N.inds+N.inds)],MARGIN = 2,mean))


displacement.individual.means = as.data.frame(apply(post.df[,(1:N.inds)],MARGIN = 2,mean))


growth.rate.individual.means = as.data.frame(apply(post.df[,(3+N.inds):(2+N.inds+N.inds)],MARGIN = 2,mean))
growth.rate.all.IgG.ELISA.Spike = growth.rate.individual.means



peak.titer.overall.mean.IgG.ELISA.Spike = peak.titer.overall.mean
displacement.overall.mean.IgG.ELISA.Spike = displacement.overall.mean
growth.rate.overall.mean.IgG.ELISA.Spike = growth.rate.overall.mean



```




#### Fitted function using mean posterior estimates       


```{r warning=FALSE, fig.width = 6, fig.height = 4}
plot.times = 0:max(d2$time.start)


observed.data = d2
observed.data$predicted = NA
uid = unique(observed.data$id)
for(i in 1:length(uid)){
       
       observed.data$predicted[which(observed.data$id == uid[i])] = titer.gompertz.fun(times = observed.data$time.start[which(observed.data$id == uid[i])], peak.titer = peak.titer.individual.means[i,1], displacement = displacement.individual.means[i,1], growth.rate = growth.rate.individual.means[i,1])
       
}


fit.dat = data.frame(titer = titer.gompertz.fun(times = plot.times, peak.titer = peak.titer.overall.mean, displacement = displacement.overall.mean, growth.rate = growth.rate.overall.mean), time = plot.times)

fit.dat.mean = fit.dat


observed.data$id = as.factor(observed.data$id)


plot1 = ggplot() +
       geom_point(data=observed.data,aes(x = time.start, y = test.result,col=as.numeric(id),group=id),size = 1.5) +
       geom_line(data=observed.data,aes(x = time.start, y = test.result,col=as.numeric(id),group=id),size=0.7) +
       geom_line(data=fit.dat,aes(x = time, y = titer),col="black",size=1.4,linetype="dashed") +
       #scale_x_continuous(breaks = seq(0,max(d2$time.start),2)) +
       scale_y_continuous(limits=c(0,1)) +
       scale_color_gradientn(colors  =  rev(brewer.pal(11,"Spectral"))) +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size  = 12),
             text = element_text(size = 12),
             axis.text = element_text(size = 12),
             axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),
             legend.position  =  "none",
             panel.background  =  element_rect(fill  =  'white')) +
       xlab("Days post symptom onset") +
       ylab("Antibody level")





```





#### Fitted functions for each individual      


```{r fig.width = 6, fig.height = 4}


fit.dat = data.frame(id = rep(uid, each = length(plot.times)), time = rep(plot.times,length(uid)), titer = NA)

for(i in 1:length(uid)){
       
       fit.dat$titer[which(fit.dat$id == uid[i])] = titer.gompertz.fun(times = plot.times, peak.titer = peak.titer.individual.means[i,1],displacement = displacement.individual.means[i,1],growth.rate = growth.rate.individual.means[i,1])
}


plot2 = ggplot() +
       geom_point(data=observed.data,aes(x = time.start, y = test.result,group=id),col="grey",size = 1.5) +
       geom_line(data=observed.data,aes(x = time.start, y = test.result,group=id),col="grey",size=0.7) +
       geom_line(data = fit.dat, aes(x = time, y = titer, col = as.numeric(id), group = id),size=1.2,alpha=0.5) +
       geom_line(data=fit.dat.mean,aes(x = time, y = titer),col="black",size=1.4,linetype="dashed") +
       #scale_x_continuous(breaks = seq(0,max(d2$time.start),2)) +
       scale_color_gradientn(colors  =  rev(brewer.pal(11,"Spectral"))) +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size  = 10),text = element_text(size = 12),axis.text = element_text(size = 12),axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),legend.position  =  "none",panel.background  =  element_rect(fill  =  'white')) +
       xlab("Days post symptom onset") +
       ylab("Antibody level")


```


```{r fig.height = 4, fig.width=8}

plot1 + plot2
```


#### Peak titer timing mean     



```{r}
peak.titer.time.mean.IgG.ELISA.Spike = get.peak.titer.time(titers = fit.dat.mean$titer, days = fit.dat.mean$time)

peak.titer.time.mean.IgG.ELISA.Spike
```


#### Peak titer timing all     

```{r}


peak.titer.times = data.frame(id = unique(fit.dat$id), peak.titer.time = NA)

for(i in 1:length(unique(fit.dat$id))){
       peak.titer.times$peak.titer.time[i] = get.peak.titer.time(titers = fit.dat$titer[which(fit.dat$id == unique(fit.dat$id)[i])], days = fit.dat$time[which(fit.dat$id == unique(fit.dat$id)[i])])
}

peak.titer.times 

mean_se(peak.titer.times$peak.titer.time)

peak.titer.time.all.IgG.ELISA.Spike = peak.titer.times

```





#### Fitted function with additional functions drawn from credible interval       


```{r warning=FALSE, fig.width = 4, fig.height = 3}




# get more posterior samples from within credible interval, for variation plotting
# use growth rate as main variable to focus on
dens = density(post.df[,"growth.rate.mean.hyper"])
hpd.int.toi = HDInterval::hdi(dens,credMass = 0.95,allowSplit=F)  
lowerlim = hpd.int.toi[1]
upperlim = hpd.int.toi[2]

lowerlim.igg.elisa.spike = lowerlim
upperlim.igg.elisa.spike = upperlim


# randomly sample 100 rows that have a growth rate within the credible interval
ransamp = sample(which(post.df$growth.rate.mean.hyper > lowerlim & post.df$growth.rate.mean.hyper < upperlim),100)

ransamp.df = data.frame(growth.rate = post.df$growth.rate.mean.hyper[ransamp], peak.titer = post.df$peak.titer.mean.hyper[ransamp], displacement = post.df$displacement.mean.hyper[ransamp])


plot.times = 0:max(d2$time.start)


fit.dat = as.data.frame(apply(ransamp.df,1,fit.titers.fun.2))
fit.dat$time = plot.times

fit.dat = reshape2::melt(fit.dat,id.vars="time")


fit.dat.2 = as.data.frame(apply(ransamp.df,1,fit.titers.fun))
fit.dat.2$time = plot.times

fit.dat.2 = reshape2::melt(fit.dat.2,id.vars="time")
fit.dat.IgG.ELISA.Spike = fit.dat.2

main.fit.fun = data.frame(titer = titer.gompertz.fun(times = plot.times, peak.titer = peak.titer.overall.mean, displacement = displacement.overall.mean, growth.rate = growth.rate.overall.mean), time = plot.times)




ggplot() +
       geom_line(data=fit.dat,aes(x = time, y = value,group=variable),col="#D53E4F",size=0.7,alpha=0.1) +
       geom_line(data=main.fit.fun,aes(x = time, y = titer),col="#D53E4F",size=1.6) +
       #scale_x_continuous(breaks = seq(0,max(d2$time.start),2)) +
       #scale_y_continuous(limits=c(0,1)) +
       #scale_color_gradientn(colors  =  rev(brewer.pal(11,"Spectral"))) +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size  = 12),text = element_text(size = 12),axis.text = element_text(size = 12),axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),legend.position  =  "none",panel.background  =  element_rect(fill  =  'white')) +
       xlab("Days post symptom onset") +
       ylab("Antibody level")





```



```{r}

# store posterior growth rates and posterior peak titer times

posterior.growth.rates.IgG.ELISA.Spike = post.df$growth.rate.mean.hyper[which(post.df$iteration %in% 61000:71000)]


posterior.peak.titer.times.IgG.ELISA.Spike = apply(post.df[61000:71000,c("displacement.mean.hyper","growth.rate.mean.hyper")],1,get.posterior.peak.titer.times)



```




<br>

***

<br>   


### ELISA NP     

Marker = IgG       
Assay = ELISA      
Antigen = NP       
Disease severity = any     
Minimum number of datapoints per individual = 3    



```{r results='hide',fig.width=11,fig.height=4}


d2 = d0 [ which(d0$marker=="IgG" & !is.na(d0$test.result) & !is.na(d0$time.start) & d0$assay == "ELISA" & d0$antigen == "NP" & d0$time.estimate.cat == "Exact" & d0$time.cat == "Symptom onset"),]


# only keep individuals that have at least one positive sample
posnegcount = as.data.frame(xtabs(~ id + test.pos.neg,d2))
id.keep = droplevels(posnegcount$id[which(posnegcount$test.pos.neg == "POS" & posnegcount$Freq>1)])
d2 = d2 [ which(d2$id %in% id.keep),]



# only keep individuals that have at least 2 samples in total
id.keep = droplevels(as.data.frame(table(d2$id))$Var1[which(as.data.frame(table(d2$id))$Freq > 2)])
d2 = d2 [ which(d2$id %in% id.keep),]
N.inds = length(unique(d2$id))
N.inds

N.inds.IgG.ELISA.NP = N.inds

for(i in 1:length(unique(paste0(d2$study,d2$units)))){
       
       d2$test.result[which(paste0(d2$study,d2$units) == unique(paste0(d2$study,d2$units))[i])] = d2$test.result[which(paste0(d2$study,d2$units) == unique(paste0(d2$study,d2$units))[i])]/max(d2$test.result[which(paste0(d2$study,d2$units) == unique(paste0(d2$study,d2$units))[i])])
}



# remove very early rising case, as this is likely a wrong Days post symptom onset
d2 = d2[-which(d2$id == "Zhao_Case 18530189"),]


# check for outliers
ggplot() +
       geom_point(data=d2,aes(x = time.start, y = test.result,col=id,group=id),size = 1.5) +
       geom_line(data=d2,aes(x = time.start, y = test.result,col=id,group=id),size=0.7) +
       #scale_x_continuous(breaks = seq(0,max(d2$time.start),2)) +
       scale_y_continuous(limits=c(0,1)) +
       #scale_color_gradientn(colors  =  rev(brewer.pal(11,"Spectral"))) +
       # scale_color_brewer(palette = "Spectral", name = "Marker/Assay") +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size  = 12),text = element_text(size = 12),axis.text = element_text(size = 12),axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),legend.text = element_text(size=9),panel.background  =  element_rect(fill  =  'white')) +
       xlab("Days post symptom onset") +
       ylab("Antibody level")



# run MCMC or load previous data? 
run.mcmc.again = F

if(run.mcmc.again == T){
       model.jags = jags.model(model.file,
                               data=list('titer'=d2$test.result,
                                         'time'=d2$time.start,
                                         'id'=as.numeric(as.factor(d2$id)),
                                         'N.id'=length(unique(d2$id))
                               ),
                               #inits=list('peak.titer.sd.hyper'=0.5),
                               n.chains=6,
                               n.adapt = 1000)
       
       
       # burn in
       burn.in = 20000
       update(model.jags, n.iter = burn.in, by = 1)
       
       
       # draw samples
       iterations = 50000
       post = coda.samples(model.jags, c("peak.titer.mean.hyper","peak.titer.sd.hyper","peak.titer","displacement.mean.hyper","displacement.sd.hyper","displacement","growth.rate.mean.hyper","growth.rate"), n.iter = iterations, thin = 1)
       
       
       post.df = mcmclist.to.dataframe(post)
       
       saveRDS(post,file = paste0("MCMC_output/MCMC_output_post_",format(Sys.time(),"%Y%m%d_%H%M%S"),".RDS"))
       
       saveRDS(post.df,file = paste0("MCMC_output/MCMC_output_postdf_",format(Sys.time(),"%Y%m%d_%H%M%S"),".RDS"))
       
} else { 
       
       # enter the corresponding mcmc filenames here, as saved in the saveRDS lines above
       # example: post = readRDS("MCMC_output/MCMC_output_post_20200804_163314.RDS")
       post = readRDS("MCMC_output/")
       post.df = readRDS("MCMC_output/")
}






N.inds = length(unique(d2$id))
```

#### Gelman-Rubin convergence diagnostics:    

```{r}
gelman.diag(post)
```

#### Posterior growth rate:     


```{r fig.height = 3, fig.width=4}

plot.MCMC.posterior(input.data = post.df,column.to.plot = which(names(post.df)=="growth.rate.mean.hyper"),x.axis.label = "Growth rate (1/days)",title = "Posterior growth rate")

plot.MCMC.chains(input.data = post.df,column.to.plot = which(names(post.df)=="growth.rate.mean.hyper"),y.axis.label = "Growth rate (1/days)",title = "Posterior growth rate",thinning = 5) 


growth.rate.overall.mean = mean(post.df$growth.rate.mean.hyper)

```



#### Posterior peak titer overall mean:    


```{r fig.height = 3, fig.width=4}
plot.MCMC.posterior(input.data = post.df,column.to.plot = which(colnames(post.df)=="peak.titer.mean.hyper"),x.axis.label = "Peak titer mean",title = "Posterior peak titer mean")

plot.MCMC.chains(input.data = post.df,column.to.plot = which(colnames(post.df)=="peak.titer.mean.hyper"),y.axis.label = "Peak titer mean",title = "Posterior peak titer mean",thinning = 5) 

peak.titer.overall.mean = mean(post.df$peak.titer.mean.hyper)


```




#### Posterior displacement overall mean:      


```{r fig.height = 3, fig.width=4}
plot.MCMC.posterior(input.data = post.df,column.to.plot = which(names(post.df)=="displacement.mean.hyper"),x.axis.label = "Displacement mean",title = "Posterior displacement mean")

plot.MCMC.chains(input.data = post.df,column.to.plot = which(names(post.df)=="displacement.mean.hyper"),y.axis.label = "Displacement mean",title = "Posterior displacement mean",thinning = 5) 

displacement.overall.mean = mean(post.df$displacement.mean.hyper)
```




```{r}
# calculate posterior means

peak.titer.individual.means = as.data.frame(apply(post.df[,(4+N.inds+N.inds):(3+N.inds+N.inds+N.inds)],MARGIN = 2,mean))


displacement.individual.means = as.data.frame(apply(post.df[,(1:N.inds)],MARGIN = 2,mean))


growth.rate.individual.means = as.data.frame(apply(post.df[,(3+N.inds):(2+N.inds+N.inds)],MARGIN = 2,mean))

growth.rate.all.IgG.ELISA.NP = growth.rate.individual.means



peak.titer.overall.mean.IgG.ELISA.NP = peak.titer.overall.mean
displacement.overall.mean.IgG.ELISA.NP = displacement.overall.mean
growth.rate.overall.mean.IgG.ELISA.NP = growth.rate.overall.mean


```



#### Fitted function using mean posterior estimates       


```{r warning=FALSE, fig.width = 6, fig.height = 4}
plot.times = 0:max(d2$time.start)


observed.data = d2
observed.data$predicted = NA
uid = unique(observed.data$id)
for(i in 1:length(uid)){
       
       observed.data$predicted[which(observed.data$id == uid[i])] = titer.gompertz.fun(times = observed.data$time.start[which(observed.data$id == uid[i])], peak.titer = peak.titer.individual.means[i,1], displacement = displacement.individual.means[i,1], growth.rate = growth.rate.individual.means[i,1])
       
}


fit.dat = data.frame(titer = titer.gompertz.fun(times = plot.times, peak.titer = peak.titer.overall.mean, displacement = displacement.overall.mean, growth.rate = growth.rate.overall.mean), time = plot.times)

fit.dat.mean = fit.dat


observed.data$id = as.factor(observed.data$id)


plot1 = ggplot() +
       geom_point(data=observed.data,aes(x = time.start, y = test.result,col=as.numeric(id),group=id),size = 1.5) +
       geom_line(data=observed.data,aes(x = time.start, y = test.result,col=as.numeric(id),group=id),size=0.7) +
       geom_line(data=fit.dat,aes(x = time, y = titer),col="black",size=1.4,linetype="dashed") +
       #scale_x_continuous(breaks = seq(0,max(d2$time.start),2)) +
       scale_y_continuous(limits=c(0,1)) +
       scale_color_gradientn(colors  =  rev(brewer.pal(11,"Spectral"))) +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size  = 12),
             text = element_text(size = 12),
             axis.text = element_text(size = 12),
             axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),
             legend.position  =  "none",
             panel.background  =  element_rect(fill  =  'white')) +
       xlab("Days post symptom onset") +
       ylab("Antibody level")





```





#### Fitted functions for each individual      


```{r fig.width = 6, fig.height = 4}


fit.dat = data.frame(id = rep(uid, each = length(plot.times)), time = rep(plot.times,length(uid)), titer = NA)

for(i in 1:length(uid)){
       
       fit.dat$titer[which(fit.dat$id == uid[i])] = titer.gompertz.fun(times = plot.times, peak.titer = peak.titer.individual.means[i,1],displacement = displacement.individual.means[i,1],growth.rate = growth.rate.individual.means[i,1])
}


plot2 = ggplot() +
       geom_point(data=observed.data,aes(x = time.start, y = test.result,group=id),col="grey",size = 1.5) +
       geom_line(data=observed.data,aes(x = time.start, y = test.result,group=id),col="grey",size=0.7) +
       geom_line(data = fit.dat, aes(x = time, y = titer, col = as.numeric(id), group = id),size=1.2,alpha=0.5) +
       geom_line(data=fit.dat.mean,aes(x = time, y = titer),col="black",size=1.4,linetype="dashed") +
       #scale_x_continuous(breaks = seq(0,max(d2$time.start),2)) +
       scale_color_gradientn(colors  =  rev(brewer.pal(11,"Spectral"))) +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size  = 10),text = element_text(size = 12),axis.text = element_text(size = 12),axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),legend.position  =  "none",panel.background  =  element_rect(fill  =  'white')) +
       xlab("Days post symptom onset") +
       ylab("Antibody level")


```


```{r fig.height = 4, fig.width=8}

plot1 + plot2
```



#### Peak titer timing mean     



```{r}
peak.titer.time.mean.IgG.ELISA.NP = get.peak.titer.time(titers = fit.dat.mean$titer, days = fit.dat.mean$time)

peak.titer.time.mean.IgG.ELISA.NP
```


#### Peak titer timing all     

```{r}


peak.titer.times = data.frame(id = unique(fit.dat$id), peak.titer.time = NA)

for(i in 1:length(unique(fit.dat$id))){
       peak.titer.times$peak.titer.time[i] = get.peak.titer.time(titers = fit.dat$titer[which(fit.dat$id == unique(fit.dat$id)[i])], days = fit.dat$time[which(fit.dat$id == unique(fit.dat$id)[i])])
}

peak.titer.times

mean_se(peak.titer.times$peak.titer.time)

peak.titer.time.all.IgG.ELISA.NP = peak.titer.times
```



#### Fitted function with additional functions drawn from credible interval       


```{r warning=FALSE, fig.width = 6, fig.height = 4}




# get more posterior samples from within credible interval, for variation plotting
# use growth rate as main variable to focus on
dens = density(post.df[,"growth.rate.mean.hyper"])
hpd.int.toi = HDInterval::hdi(dens,credMass = 0.95,allowSplit=F)  
lowerlim = hpd.int.toi[1]
upperlim = hpd.int.toi[2]

lowerlim.igg.elisa.np = lowerlim
upperlim.igg.elisa.np = upperlim



# randomly sample 100 rows that have a growth rate within the credible interval
ransamp = sample(which(post.df$growth.rate.mean.hyper > lowerlim & post.df$growth.rate.mean.hyper < upperlim),100)

ransamp.df = data.frame(growth.rate = post.df$growth.rate.mean.hyper[ransamp], peak.titer = post.df$peak.titer.mean.hyper[ransamp], displacement = post.df$displacement.mean.hyper[ransamp])


plot.times = 0:max(d2$time.start)


fit.dat = as.data.frame(apply(ransamp.df,1,fit.titers.fun.2))
fit.dat$time = plot.times

fit.dat = reshape2::melt(fit.dat,id.vars="time")

fit.dat.2 = as.data.frame(apply(ransamp.df,1,fit.titers.fun))
fit.dat.2$time = plot.times

fit.dat.2 = reshape2::melt(fit.dat.2,id.vars="time")
fit.dat.IgG.ELISA.NP = fit.dat.2

main.fit.fun = data.frame(titer = titer.gompertz.fun(times = plot.times, peak.titer = peak.titer.overall.mean, displacement = displacement.overall.mean, growth.rate = growth.rate.overall.mean), time = plot.times)




ggplot() +
       geom_line(data=fit.dat,aes(x = time, y = value,group=variable),col="#D53E4F",size=0.7,alpha=0.1) +
       geom_line(data=main.fit.fun,aes(x = time, y = titer),col="#D53E4F",size=1.6) +
       #scale_x_continuous(breaks = seq(0,max(d2$time.start),2)) +
       #scale_y_continuous(limits=c(0,1)) +
       #scale_color_gradientn(colors  =  rev(brewer.pal(11,"Spectral"))) +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size  = 12),text = element_text(size = 12),axis.text = element_text(size = 12),axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),legend.position  =  "none",panel.background  =  element_rect(fill  =  'white')) +
       xlab("Days post symptom onset") +
       ylab("Antibody level")




```



```{r}

# store posterior growth rates and posterior peak titer times

posterior.growth.rates.IgG.ELISA.NP = post.df$growth.rate.mean.hyper[which(post.df$iteration %in% 61000:71000)]


posterior.peak.titer.times.IgG.ELISA.NP = apply(post.df[61000:71000,c("displacement.mean.hyper","growth.rate.mean.hyper")],1,get.posterior.peak.titer.times)



```


<br>

***

<br>   





### ELISA Spike and NP     

Marker = IgG       
Assay = ELISA      
Antigen = Spike and NP (both in one assay)       
Disease severity = any     
Minimum number of datapoints per individual = 3    




==> not enough samples


```{r results='hide', fig.height = 3, fig.width=4}

d2 = d0 [ which(d0$marker=="IgG" & !is.na(d0$test.result) & !is.na(d0$time.start) & d0$assay == "ELISA" & d0$antigen == "NP and Spike" & d0$time.estimate.cat == "Exact" & d0$time.cat == "Symptom onset"),]

# no individuals surviving selection

```

<br>

***

<br>   




### IFA    

Marker = IgG       
Assay = IFA      
Disease severity = any     
Minimum number of datapoints per individual = 3    

Sample size = 2      

==> not enough samples     


```{r fig.height = 3, fig.width=3}


d2 = d0 [ which(d0$marker=="IgG" & !is.na(d0$test.result) & !is.na(d0$time.start) & d0$assay == "IFA" & d0$time.estimate.cat == "Exact"),]



# length(unique(d2$id))

id.keep = droplevels(as.data.frame(table(d2$id))$Var1[which(as.data.frame(table(d2$id))$Freq > 2)])

d2 = d2 [ which(d2$id %in% id.keep),]
N.inds = length(unique(d2$id))


for(i in 1:length(unique(paste0(d2$study,d2$units)))){
       
       d2$test.result[which(paste0(d2$study,d2$units) == unique(paste0(d2$study,d2$units))[i])] = d2$test.result[which(paste0(d2$study,d2$units) == unique(paste0(d2$study,d2$units))[i])]/max(d2$test.result[which(paste0(d2$study,d2$units) == unique(paste0(d2$study,d2$units))[i])])
}




```


<br>

***

<br>   


### MCLIA    

Marker = IgG       
Assay = MCLIA      
Disease severity = any     
Minimum number of datapoints per individual = 3    



```{r results = 'hide',fig.width=11,fig.height=4}


d2 = d0 [ which(d0$marker=="IgG" & !is.na(d0$test.result) & !is.na(d0$time.start) & d0$assay == "MCLIA" & d0$time.estimate.cat == "Exact" & d0$time.cat == "Symptom onset"),]


# only keep individuals that have at least one positive sample
posnegcount = as.data.frame(xtabs(~ id + test.pos.neg,d2))
id.keep = droplevels(posnegcount$id[which(posnegcount$test.pos.neg == "POS" & posnegcount$Freq>1)])
d2 = d2 [ which(d2$id %in% id.keep),]



# only keep individuals that have at least 2 samples in total
id.keep = droplevels(as.data.frame(table(d2$id))$Var1[which(as.data.frame(table(d2$id))$Freq > 2)])
d2 = d2 [ which(d2$id %in% id.keep),]
N.inds = length(unique(d2$id))
N.inds

for(i in 1:length(unique(paste0(d2$study,d2$units)))){
       
       d2$test.result[which(paste0(d2$study,d2$units) == unique(paste0(d2$study,d2$units))[i])] = d2$test.result[which(paste0(d2$study,d2$units) == unique(paste0(d2$study,d2$units))[i])]/max(d2$test.result[which(paste0(d2$study,d2$units) == unique(paste0(d2$study,d2$units))[i])])
}



# check for outliers
ggplot() +
       geom_point(data=d2,aes(x = time.start, y = test.result,col=id,group=id),size = 1.5) +
       geom_line(data=d2,aes(x = time.start, y = test.result,col=id,group=id),size=0.7) +
       #scale_x_continuous(breaks = seq(0,max(d2$time.start),2)) +
       scale_y_continuous(limits=c(0,1)) +
       #scale_color_gradientn(colors  =  rev(brewer.pal(11,"Spectral"))) +
       # scale_color_brewer(palette = "Spectral", name = "Marker/Assay") +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size  = 12),text = element_text(size = 12),axis.text = element_text(size = 12),axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),legend.text = element_text(size=9),panel.background  =  element_rect(fill  =  'white')) +
       xlab("Days post symptom onset") +
       ylab("Antibody level")



# run MCMC or load previous data? 
run.mcmc.again = F

if(run.mcmc.again == T){
       model.jags = jags.model(model.file,
                               data=list('titer'=d2$test.result,
                                         'time'=d2$time.start,
                                         'id'=as.numeric(as.factor(d2$id)),
                                         'N.id'=length(unique(d2$id))
                               ),
                               #inits=list('peak.titer.sd.hyper'=0.5),
                               n.chains=6,
                               n.adapt = 1000)
       
       
       # burn in
       burn.in = 20000
       update(model.jags, n.iter = burn.in, by = 1)
       
       
       # draw samples
       iterations = 50000
       post = coda.samples(model.jags, c("peak.titer.mean.hyper","peak.titer.sd.hyper","peak.titer","displacement.mean.hyper","displacement.sd.hyper","displacement","growth.rate.mean.hyper","growth.rate"), n.iter = iterations, thin = 1)
       
       
       post.df = mcmclist.to.dataframe(post)
       
       saveRDS(post,file = paste0("MCMC_output/MCMC_output_post_",format(Sys.time(),"%Y%m%d_%H%M%S"),".RDS"))
       
       saveRDS(post.df,file = paste0("MCMC_output/MCMC_output_postdf_",format(Sys.time(),"%Y%m%d_%H%M%S"),".RDS"))
       
} else { 
       
       # enter the corresponding mcmc filenames here, as saved in the saveRDS lines above
       # example: post = readRDS("MCMC_output/MCMC_output_post_20200804_163314.RDS")
       post = readRDS("MCMC_output/")
       post.df = readRDS("MCMC_output/")
}



N.inds = length(unique(d2$id))


```

#### Gelman-Rubin convergence diagnostics:    

```{r}
gelman.diag(post)
```


#### Posterior growth rate:     


```{r fig.height = 3, fig.width=4}

plot.MCMC.posterior(input.data = post.df,column.to.plot = which(names(post.df)=="growth.rate.mean.hyper"),x.axis.label = "Growth rate (1/days)",title = "Posterior growth rate")

plot.MCMC.chains(input.data = post.df,column.to.plot = which(names(post.df)=="growth.rate.mean.hyper"),y.axis.label = "Growth rate (1/days)",title = "Posterior growth rate",thinning = 5) 


growth.rate.overall.mean = mean(post.df$growth.rate.mean.hyper)



```


#### Posterior peak titer overall mean:    


```{r fig.height = 3, fig.width=4}
plot.MCMC.posterior(input.data = post.df,column.to.plot = which(colnames(post.df)=="peak.titer.mean.hyper"),x.axis.label = "Peak titer mean",title = "Posterior peak titer mean")

plot.MCMC.chains(input.data = post.df,column.to.plot = which(colnames(post.df)=="peak.titer.mean.hyper"),y.axis.label = "Peak titer mean",title = "Posterior peak titer mean",thinning = 5) 

peak.titer.overall.mean = mean(post.df$peak.titer.mean.hyper)


```




#### Posterior displacement overall mean:      


```{r fig.height = 3, fig.width=4}
plot.MCMC.posterior(input.data = post.df,column.to.plot = which(names(post.df)=="displacement.mean.hyper"),x.axis.label = "Displacement mean",title = "Posterior displacement mean")

plot.MCMC.chains(input.data = post.df,column.to.plot = which(names(post.df)=="displacement.mean.hyper"),y.axis.label = "Displacement mean",title = "Posterior displacement mean",thinning = 5) 

displacement.overall.mean = mean(post.df$displacement.mean.hyper)
```




```{r}
# calculate posterior means

peak.titer.individual.means = as.data.frame(apply(post.df[,(4+N.inds+N.inds):(3+N.inds+N.inds+N.inds)],MARGIN = 2,mean))


displacement.individual.means = as.data.frame(apply(post.df[,(1:N.inds)],MARGIN = 2,mean))


growth.rate.individual.means = as.data.frame(apply(post.df[,(3+N.inds):(2+N.inds+N.inds)],MARGIN = 2,mean))

growth.rate.all.IgG.MCLIA = growth.rate.individual.means



peak.titer.overall.mean.IgG.MCLIA = peak.titer.overall.mean
displacement.overall.mean.IgG.MCLIA = displacement.overall.mean
growth.rate.overall.mean.IgG.MCLIA = growth.rate.overall.mean



```





#### Fitted function using mean posterior estimates       


```{r warning=FALSE, fig.width = 6, fig.height = 4}
plot.times = 0:max(d2$time.start)


observed.data = d2
observed.data$predicted = NA
uid = unique(observed.data$id)
for(i in 1:length(uid)){
       
       observed.data$predicted[which(observed.data$id == uid[i])] = titer.gompertz.fun(times = observed.data$time.start[which(observed.data$id == uid[i])], peak.titer = peak.titer.individual.means[i,1], displacement = displacement.individual.means[i,1], growth.rate = growth.rate.individual.means[i,1])
       
}


fit.dat = data.frame(titer = titer.gompertz.fun(times = plot.times, peak.titer = peak.titer.overall.mean, displacement = displacement.overall.mean, growth.rate = growth.rate.overall.mean), time = plot.times)

fit.dat.mean = fit.dat


observed.data$id = as.factor(observed.data$id)


plot1 = ggplot() +
       geom_point(data=observed.data,aes(x = time.start, y = test.result,col=as.numeric(id),group=id),size = 1.5) +
       geom_line(data=observed.data,aes(x = time.start, y = test.result,col=as.numeric(id),group=id),size=0.7) +
       geom_line(data=fit.dat,aes(x = time, y = titer),col="black",size=1.4,linetype="dashed") +
       #scale_x_continuous(breaks = seq(0,max(d2$time.start),2)) +
       scale_y_continuous(limits=c(0,1)) +
       scale_color_gradientn(colors  =  rev(brewer.pal(11,"Spectral"))) +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size  = 12),
             text = element_text(size = 12),
             axis.text = element_text(size = 12),
             axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),
             legend.position  =  "none",
             panel.background  =  element_rect(fill  =  'white')) +
       xlab("Days post symptom onset") +
       ylab("Antibody level")





```





#### Fitted functions for each individual      


```{r fig.width = 6, fig.height = 4}


fit.dat = data.frame(id = rep(uid, each = length(plot.times)), time = rep(plot.times,length(uid)), titer = NA)

for(i in 1:length(uid)){
       
       fit.dat$titer[which(fit.dat$id == uid[i])] = titer.gompertz.fun(times = plot.times, peak.titer = peak.titer.individual.means[i,1],displacement = displacement.individual.means[i,1],growth.rate = growth.rate.individual.means[i,1])
}


plot2 = ggplot() +
       geom_point(data=observed.data,aes(x = time.start, y = test.result,group=id),col="grey",size = 1.5) +
       geom_line(data=observed.data,aes(x = time.start, y = test.result,group=id),col="grey",size=0.7) +
       geom_line(data = fit.dat, aes(x = time, y = titer, col = as.numeric(id), group = id),size=1.2,alpha=0.5) +
       geom_line(data=fit.dat.mean,aes(x = time, y = titer),col="black",size=1.4,linetype="dashed") +
       #scale_x_continuous(breaks = seq(0,max(d2$time.start),2)) +
       scale_color_gradientn(colors  =  rev(brewer.pal(11,"Spectral"))) +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size  = 10),text = element_text(size = 12),axis.text = element_text(size = 12),axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),legend.position  =  "none",panel.background  =  element_rect(fill  =  'white')) +
       xlab("Days post symptom onset") +
       ylab("Antibody level")


```

```{r fig.height = 4, fig.width=8}

plot1 + plot2
```



#### Peak titer timing mean     



```{r}
peak.titer.time.mean.IgG.MCLIA = get.peak.titer.time(titers = fit.dat.mean$titer, days = fit.dat.mean$time)

peak.titer.time.mean.IgG.MCLIA
```


#### Peak titer timing all     

```{r}


peak.titer.times = data.frame(id = unique(fit.dat$id), peak.titer.time = NA)

for(i in 1:length(unique(fit.dat$id))){
       peak.titer.times$peak.titer.time[i] = get.peak.titer.time(titers = fit.dat$titer[which(fit.dat$id == unique(fit.dat$id)[i])], days = fit.dat$time[which(fit.dat$id == unique(fit.dat$id)[i])])
}

peak.titer.times
mean_se(peak.titer.times$peak.titer.time)
peak.titer.time.all.IgG.MCLIA = peak.titer.times
```





#### Fitted function with additional functions drawn from credible interval       


```{r warning=FALSE, fig.width = 6, fig.height = 4}




# get more posterior samples from within credible interval, for variation plotting
# use growth rate as main variable to focus on
dens = density(post.df[,"growth.rate.mean.hyper"])
hpd.int.toi = HDInterval::hdi(dens,credMass = 0.95,allowSplit=F)  
lowerlim = hpd.int.toi[1]
upperlim = hpd.int.toi[2]


lowerlim.igg.mclia = lowerlim
upperlim.igg.mclia = upperlim



# randomly sample 100 rows that have a growth rate within the credible interval
ransamp = sample(which(post.df$growth.rate.mean.hyper > lowerlim & post.df$growth.rate.mean.hyper < upperlim),100)

ransamp.df = data.frame(growth.rate = post.df$growth.rate.mean.hyper[ransamp], peak.titer = post.df$peak.titer.mean.hyper[ransamp], displacement = post.df$displacement.mean.hyper[ransamp])


plot.times = 0:max(d2$time.start)


fit.dat = as.data.frame(apply(ransamp.df,1,fit.titers.fun.2))
fit.dat$time = plot.times

fit.dat = reshape2::melt(fit.dat,id.vars="time")

fit.dat.2 = as.data.frame(apply(ransamp.df,1,fit.titers.fun))
fit.dat.2$time = plot.times

fit.dat.2 = reshape2::melt(fit.dat.2,id.vars="time")
fit.dat.IgG.MCLIA = fit.dat.2

main.fit.fun = data.frame(titer = titer.gompertz.fun(times = plot.times, peak.titer = peak.titer.overall.mean, displacement = displacement.overall.mean, growth.rate = growth.rate.overall.mean), time = plot.times)




ggplot() +
       geom_line(data=fit.dat,aes(x = time, y = value,group=variable),col="#D53E4F",size=0.7,alpha=0.1) +
       geom_line(data=main.fit.fun,aes(x = time, y = titer),col="#D53E4F",size=1.6) +
       #scale_x_continuous(breaks = seq(0,max(d2$time.start),2)) +
       #scale_y_continuous(limits=c(0,1)) +
       #scale_color_gradientn(colors  =  rev(brewer.pal(11,"Spectral"))) +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size  = 12),text = element_text(size = 12),axis.text = element_text(size = 12),axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),legend.position  =  "none",panel.background  =  element_rect(fill  =  'white')) +
       xlab("Days post symptom onset") +
       ylab("Antibody level")





```



```{r}

# store posterior growth rates and posterior peak titer times

posterior.growth.rates.IgG.MCLIA = post.df$growth.rate.mean.hyper[which(post.df$iteration %in% 61000:71000)]


posterior.peak.titer.times.IgG.MCLIA = apply(post.df[61000:71000,c("displacement.mean.hyper","growth.rate.mean.hyper")],1,get.posterior.peak.titer.times)



```

<br>

***

<br>   











### Assays combined    


```{r warning=FALSE, fig.width = 6, fig.height = 4}



plot.times = 0:max(d2$time.start)




main.fit.fun.elisa.spike = data.frame(titer = titer.gompertz.fun(times = plot.times, peak.titer = 1, displacement = displacement.overall.mean.IgG.ELISA.Spike, growth.rate = growth.rate.overall.mean.IgG.ELISA.Spike), time = plot.times, assay = "ELISA Spike")


main.fit.fun.elisa.np = data.frame(titer = titer.gompertz.fun(times = plot.times, peak.titer = 1, displacement = displacement.overall.mean.IgG.ELISA.NP, growth.rate = growth.rate.overall.mean.IgG.ELISA.NP), time = plot.times, assay = "ELISA NP")


main.fit.fun.mclia = data.frame(titer = titer.gompertz.fun(times = plot.times, peak.titer = 1, displacement = displacement.overall.mean.IgG.MCLIA, growth.rate = growth.rate.overall.mean.IgG.MCLIA), time = plot.times, assay = "MCLIA NP + Spike")


main.fit.functions = rbind(main.fit.fun.elisa.spike,main.fit.fun.elisa.np,main.fit.fun.mclia)

main.fit.functions = reshape2::melt(main.fit.functions, id.vars = c("time","assay"))



fit.dat.IgG.ELISA.Spike$assay = "ELISA Spike"
fit.dat.IgG.ELISA.NP$assay = "ELISA NP"
fit.dat.IgG.MCLIA$assay = "MCLIA NP + Spike"


fit.dat.all = rbind(fit.dat.IgG.ELISA.Spike,fit.dat.IgG.ELISA.NP,fit.dat.IgG.MCLIA)
fit.dat.all$variable = paste(fit.dat.all$assay, fit.dat.all$variable)


fit.dat.all = reshape2::melt(fit.dat.all, id.vars = c("time","assay","variable"))
colnames(fit.dat.all)[4] = "var2"


fit.dat.all.igg = fit.dat.all






lowerlim.elisa.spike.out = titer.gompertz.fun(times = plot.times,peak.titer = 1, displacement = displacement.overall.mean.IgG.ELISA.Spike, growth.rate = lowerlim.igg.elisa.spike) 
upperlim.elisa.spike.out = titer.gompertz.fun(times = plot.times,peak.titer = 1, displacement = displacement.overall.mean.IgG.ELISA.Spike, growth.rate = upperlim.igg.elisa.spike)

lowerlim.elisa.np.out = titer.gompertz.fun(times = plot.times,peak.titer = 1, displacement = displacement.overall.mean.IgG.ELISA.NP, growth.rate = lowerlim.igg.elisa.np)
upperlim.elisa.np.out = titer.gompertz.fun(times = plot.times,peak.titer = 1, displacement = displacement.overall.mean.IgG.ELISA.NP, growth.rate = upperlim.igg.elisa.np)


lowerlim.mclia.out = titer.gompertz.fun(times = plot.times,peak.titer = 1, displacement = displacement.overall.mean.IgG.MCLIA, growth.rate = lowerlim.igg.mclia)
upperlim.mclia.out = titer.gompertz.fun(times = plot.times,peak.titer = 1, displacement = displacement.overall.mean.IgG.MCLIA, growth.rate = upperlim.igg.mclia)



main.fit.functions$lowerlim = NA
main.fit.functions$upperlim = NA


main.fit.functions$lowerlim [ which(main.fit.functions$assay == "ELISA Spike") ] = lowerlim.elisa.spike.out
main.fit.functions$upperlim [ which(main.fit.functions$assay == "ELISA Spike") ] = upperlim.elisa.spike.out
main.fit.functions$lowerlim [ which(main.fit.functions$assay == "ELISA NP") ] = lowerlim.elisa.np.out
main.fit.functions$upperlim [ which(main.fit.functions$assay == "ELISA NP") ] = upperlim.elisa.np.out
main.fit.functions$lowerlim [ which(main.fit.functions$assay == "MCLIA NP + Spike") ] = lowerlim.mclia.out
main.fit.functions$upperlim [ which(main.fit.functions$assay == "MCLIA NP + Spike") ] = upperlim.mclia.out

main.fit.function.igg = main.fit.functions

ggplot(data=main.fit.functions,aes(x = time, y = value,group=assay,col=assay)) +
       #geom_line(data=fit.dat.all,aes(x = time, y = value,group = variable, col=assay),size=0.5,alpha=0.1) +
       #geom_ribbon(aes(x = plot.times,ymin = lowerlim.elisa.spike,ymax = upperlim.elisa.spike),col=col.rna,fill = col.rna,alpha=0.2) +
       geom_ribbon(aes(ymin = lowerlim,ymax = upperlim),fill = "none",alpha=0.6,linetype="dashed") +
       geom_line(size=1.8) +
       #scale_x_continuous(breaks = seq(0,max(d2$time.start),2)) +
       scale_y_continuous(limits=c(0,1)) +
       #scale_color_gradientn(colors  =  rev(brewer.pal(11,"Spectral"))) +
       # scale_color_brewer(palette = "Spectral", name = "") +
       scale_color_manual(values = c(col.rna,"#D53E4F",col.igg),name="") +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size  = 12),text = element_text(size = 12),axis.text = element_text(size = 12),axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),legend.position  =  c(0.82,0.3),legend.background = element_rect(fill="white"),panel.background  =  element_rect(fill  =  'white')) +
       xlab("Days post symptom onset") +
       ylab("Antibody level")







ggplot(data=main.fit.functions[-which(main.fit.functions$assay == "MCLIA NP + Spike"),],aes(x = time, y = value,group=assay,col=assay)) +
       #geom_line(data=fit.dat.all,aes(x = time, y = value,group = variable, col=assay),size=0.5,alpha=0.1) +
       #geom_ribbon(aes(x = plot.times,ymin = lowerlim.elisa.spike,ymax = upperlim.elisa.spike),col=col.rna,fill = col.rna,alpha=0.2) +
       geom_line(data=fit.dat.all[-which(fit.dat.all$assay == "MCLIA NP + Spike"),],aes(x = time, y = value,group = variable, col=assay),size=0.5,alpha=0.1) +
       geom_ribbon(aes(ymin = lowerlim,ymax = upperlim),fill="none",alpha=0.1,linetype="dashed") +
       geom_line(size=1.8) +
       #scale_x_continuous(breaks = seq(0,max(d2$time.start),2)) +
       scale_y_continuous(limits=c(0,1)) +
       #scale_color_gradientn(colors  =  rev(brewer.pal(11,"Spectral"))) +
       # scale_color_brewer(palette = "Spectral", name = "") +
       scale_color_manual(values = c("#D53E4F",col.igg),name="") +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size  = 12),text = element_text(size = 12),axis.text = element_text(size = 12),axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),legend.position  =  c(0.82,0.3),legend.background = element_rect(fill="white"),panel.background  =  element_rect(fill  =  'white')) +
       xlab("Days post symptom onset") +
       ylab("Antibody level")


```





<br>

***

<br>   







### Growth rate comparison assays    




#### Posterior means and 95% CrI    

IgG ELISA Spike:    

```{r}

dens = density(posterior.growth.rates.IgG.ELISA.Spike)
hpd.post.diffs = HDInterval::hdi(dens,credMass = 0.95,allowSplit=F)  
lowerlim = hpd.post.diffs[1]
upperlim = hpd.post.diffs[2]

print(paste0("Mean = ",round(mean(posterior.growth.rates.IgG.ELISA.Spike),3)))
print(paste0("95% CrI = ",round(lowerlim,3)," to ",round(upperlim,3)))


```


IgG ELISA NP:    

```{r}

dens = density(posterior.growth.rates.IgG.ELISA.NP)
hpd.post.diffs = HDInterval::hdi(dens,credMass = 0.95,allowSplit=F)  
lowerlim = hpd.post.diffs[1]
upperlim = hpd.post.diffs[2]

print(paste0("Mean = ",round(mean(posterior.growth.rates.IgG.ELISA.NP),3)))
print(paste0("95% CrI = ",round(lowerlim,3)," to ",round(upperlim,3)))


```

IgG MCLIA:    

```{r}

dens = density(posterior.growth.rates.IgG.MCLIA)
hpd.post.diffs = HDInterval::hdi(dens,credMass = 0.95,allowSplit=F)  
lowerlim = hpd.post.diffs[1]
upperlim = hpd.post.diffs[2]

print(paste0("Mean = ",round(mean(posterior.growth.rates.IgG.MCLIA),3)))
print(paste0("95% CrI = ",round(lowerlim,3)," to ",round(upperlim,3)))


```


```{r fig.height=4,fig.width=5}




growth.rate.all.IgG.ELISA.Spike$marker = "IgG ELISA Spike"
growth.rate.all.IgG.ELISA.NP$marker = "IgG ELISA NP"
growth.rate.all.IgG.MCLIA$marker = "IgG MCLIA"

means_and_se = rbind(mean_se(growth.rate.all.IgG.ELISA.Spike[,1]),
                     mean_se(growth.rate.all.IgG.ELISA.NP[,1]),
                     mean_se(growth.rate.all.IgG.MCLIA[,1]))

colnames(means_and_se)[1] = c("growth.rate")
means_and_se$marker = c("IgG ELISA Spike","IgG ELISA NP","IgG MCLIA")


means_and_se.igg = means_and_se

growth.rate.igg.df = rbind(growth.rate.all.IgG.ELISA.Spike,growth.rate.all.IgG.ELISA.NP,growth.rate.all.IgG.MCLIA)
colnames(growth.rate.igg.df)[1]="growth.rate"


cols = c("IgG ELISA Spike" = col.elisa, "IgG ELISA NP" = col.igg,"IgG MCLIA" = col.mclia)






# t.test(growth.rate.all.IgG.ELISA.Spike[,1],growth.rate.all.IgG.ELISA.NP[,1])


ggplot(data = growth.rate.igg.df,aes(x=marker, y = growth.rate,col=marker)) +
       geom_point(data = means_and_se, aes(x = marker, y = growth.rate),col="red",shape=19,size=3,alpha=0.5) +
       geom_errorbar(data = means_and_se, aes(ymin = ymin, ymax = ymax),width = 0.1,col="red",alpha=0.5) +
       geom_jitter(width=0.1) +
       #scale_x_continuous(breaks = seq(0,(max(boot.samples.df.tp7$boot.samples)+2),5),limits=c(0,max(boot.samples.df.tp7$boot.samples+2))) +
       ylab("Growth rate (1/days)") +
       scale_color_manual(values = cols) +
       xlab("") +
       ggtitle("") +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size  = 12),text = element_text(size = 12),axis.text = element_text(size = 12),axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),axis.ticks.x = element_blank(),axis.text.x = element_blank(),legend.title = element_blank(),panel.background  =  element_rect(fill  =  'white'))





```


#### Pairwise differences     


IgG ELISA Spike vs IgG ELISA NP    

```{r fig.height = 3, fig.width = 3}

post.diffs = data.frame(diffs = posterior.growth.rates.IgG.ELISA.Spike - posterior.growth.rates.IgG.ELISA.NP)

dens = density(post.diffs$diffs)
hpd.post.diffs = HDInterval::hdi(dens,credMass = 0.95,allowSplit=F)  
lowerlim = hpd.post.diffs[1]
upperlim = hpd.post.diffs[2]

print(paste0("Mean = ",round(mean(post.diffs$diffs),3)))
print(paste0("95% CrI = ",round(lowerlim,3)," to ",round(upperlim,3)))

ggplot(data = post.diffs, aes(x = diffs)) +
       geom_histogram(aes(y  =  ..density..),binwidth  =  0.01, fill  =  col.igg, color  =  col.igg,alpha=0.5) +
       #scale_x_continuous(breaks = seq(0,(max(boot.samples.df$boot.samples)+2),5),limits=c(0,max(boot.samples.df$boot.samples+2))) +
       ggtitle("Growth rate difference between means") +
       xlab("Difference between means (1/days)") +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size = 12),
             text = element_text(size = 12),
             axis.text = element_text(size = 12),
             axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),
             legend.position  =  "none",
             panel.background  =  element_rect(fill  =  'white'))
```




IgG ELISA Spike vs IgG MCLIA    

```{r fig.height = 3, fig.width = 3}

post.diffs = data.frame(diffs = posterior.growth.rates.IgG.ELISA.Spike - posterior.growth.rates.IgG.MCLIA)

dens = density(post.diffs$diffs)
hpd.post.diffs = HDInterval::hdi(dens,credMass = 0.95,allowSplit=F)  
lowerlim = hpd.post.diffs[1]
upperlim = hpd.post.diffs[2]

print(paste0("Mean = ",round(mean(post.diffs$diffs),3)))
print(paste0("95% CrI = ",round(lowerlim,3)," to ",round(upperlim,3)))

ggplot(data = post.diffs, aes(x = diffs)) +
       geom_histogram(aes(y  =  ..density..),binwidth  =  0.01, fill  =  col.igg, color  =  col.igg,alpha=0.5) +
       #scale_x_continuous(breaks = seq(0,(max(boot.samples.df$boot.samples)+2),5),limits=c(0,max(boot.samples.df$boot.samples+2))) +
       ggtitle("Growth rate difference between means") +
       xlab("Difference between means (1/days)") +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size = 12),
             text = element_text(size = 12),
             axis.text = element_text(size = 12),
             axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),
             legend.position  =  "none",
             panel.background  =  element_rect(fill  =  'white'))
```



IgG ELISA NP vs IgG MCLIA    

```{r fig.height = 3, fig.width = 3}

post.diffs = data.frame(diffs = posterior.growth.rates.IgG.ELISA.NP - posterior.growth.rates.IgG.MCLIA)

dens = density(post.diffs$diffs)
hpd.post.diffs = HDInterval::hdi(dens,credMass = 0.95,allowSplit=F)  
lowerlim = hpd.post.diffs[1]
upperlim = hpd.post.diffs[2]

print(paste0("Mean = ",round(mean(post.diffs$diffs),3)))
print(paste0("95% CrI = ",round(lowerlim,3)," to ",round(upperlim,3)))

ggplot(data = post.diffs, aes(x = diffs)) +
       geom_histogram(aes(y  =  ..density..),binwidth  =  0.01, fill  =  col.igg, color  =  col.igg,alpha=0.5) +
       #scale_x_continuous(breaks = seq(0,(max(boot.samples.df$boot.samples)+2),5),limits=c(0,max(boot.samples.df$boot.samples+2))) +
       ggtitle("Growth rate difference between means") +
       xlab("Difference between means (1/days)") +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size = 12),
             text = element_text(size = 12),
             axis.text = element_text(size = 12),
             axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),
             legend.position  =  "none",
             panel.background  =  element_rect(fill  =  'white'))
```





### Peak titer timing comparison      

#### Posterior means and 95% CrI    

IgG ELISA Spike:    

```{r}

dens = density(posterior.peak.titer.times.IgG.ELISA.Spike)
hpd.post.diffs = HDInterval::hdi(dens,credMass = 0.95,allowSplit=F)  
lowerlim = hpd.post.diffs[1]
upperlim = hpd.post.diffs[2]

print(paste0("Mean = ",round(mean(posterior.peak.titer.times.IgG.ELISA.Spike),3)))
print(paste0("95% CrI = ",round(lowerlim,3)," to ",round(upperlim,3)))


```


IgG ELISA NP:    

```{r}

dens = density(posterior.peak.titer.times.IgG.ELISA.NP)
hpd.post.diffs = HDInterval::hdi(dens,credMass = 0.95,allowSplit=F)  
lowerlim = hpd.post.diffs[1]
upperlim = hpd.post.diffs[2]

print(paste0("Mean = ",round(mean(posterior.peak.titer.times.IgG.ELISA.NP),3)))
print(paste0("95% CrI = ",round(lowerlim,3)," to ",round(upperlim,3)))


```

IgG MCLIA:    

```{r}

dens = density(posterior.peak.titer.times.IgG.MCLIA)
hpd.post.diffs = HDInterval::hdi(dens,credMass = 0.95,allowSplit=F)  
lowerlim = hpd.post.diffs[1]
upperlim = hpd.post.diffs[2]

print(paste0("Mean = ",round(mean(posterior.peak.titer.times.IgG.MCLIA),3)))
print(paste0("95% CrI = ",round(lowerlim,3)," to ",round(upperlim,3)))


```


```{r fig.height=4,fig.width=5}




peak.titer.time.all.IgG.ELISA.Spike$marker = "IgG ELISA Spike"
peak.titer.time.all.IgG.ELISA.NP$marker = "IgG ELISA NP"
peak.titer.time.all.IgG.MCLIA$marker = "IgG MCLIA"

means_and_se = rbind(mean_se(peak.titer.time.all.IgG.ELISA.Spike$peak.titer.time),
                     mean_se(peak.titer.time.all.IgG.ELISA.NP$peak.titer.time),
                     mean_se(peak.titer.time.all.IgG.MCLIA$peak.titer.time))

colnames(means_and_se)[1] = c("peak.titer.time")
means_and_se$marker = c("IgG ELISA Spike","IgG ELISA NP","IgG MCLIA")


means_and_se.peak.titer.igg = means_and_se

peak.titer.time.igg.df = rbind(peak.titer.time.all.IgG.ELISA.Spike,peak.titer.time.all.IgG.ELISA.NP,peak.titer.time.all.IgG.MCLIA)



cols = c("IgG ELISA Spike" = col.elisa, "IgG ELISA NP" = col.igg,"IgG MCLIA" = col.mclia)



# t.test(peak.titer.time.all.IgG.ELISA.Spike$peak.titer.time,peak.titer.time.all.IgG.ELISA.NP$peak.titer.time)


ggplot(data = peak.titer.time.igg.df,aes(x=marker, y = peak.titer.time,col=marker)) +
       geom_point(data = means_and_se, aes(x = marker, y = peak.titer.time),col="red",shape=19,size=3,alpha=0.5) +
       geom_errorbar(data = means_and_se, aes(ymin = ymin, ymax = ymax),width = 0.1,col="red",alpha=0.5) +
       geom_jitter(width=0.1) +
       #scale_x_continuous(breaks = seq(0,(max(boot.samples.df.tp7$boot.samples)+2),5),limits=c(0,max(boot.samples.df.tp7$boot.samples+2))) +
       ylab("Peak titer time") +
       scale_color_manual(values = cols) +
       xlab("") +
       ggtitle("") +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size  = 12),text = element_text(size = 12),axis.text = element_text(size = 12),axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),axis.ticks.x = element_blank(),axis.text.x = element_blank(),legend.title = element_blank(),panel.background  =  element_rect(fill  =  'white'))


```




#### Pairwise differences     


IgG ELISA Spike vs IgG ELISA NP    

```{r fig.height = 3, fig.width = 3}

post.diffs = data.frame(diffs = posterior.peak.titer.times.IgG.ELISA.Spike - posterior.peak.titer.times.IgG.ELISA.NP)

dens = density(post.diffs$diffs)
hpd.post.diffs = HDInterval::hdi(dens,credMass = 0.95,allowSplit=F)  
lowerlim = hpd.post.diffs[1]
upperlim = hpd.post.diffs[2]

print(paste0("Mean = ",round(mean(post.diffs$diffs),3)))
print(paste0("95% CrI = ",round(lowerlim,3)," to ",round(upperlim,3)))

ggplot(data = post.diffs, aes(x = diffs)) +
       geom_histogram(aes(y  =  ..density..),binwidth  =  1, fill  =  col.igg, color  =  col.igg,alpha=0.5) +
       #scale_x_continuous(breaks = seq(0,(max(boot.samples.df$boot.samples)+2),5),limits=c(0,max(boot.samples.df$boot.samples+2))) +
       ggtitle("Peak titer time difference between means") +
       xlab("Difference between means (days)") +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size = 12),
             text = element_text(size = 12),
             axis.text = element_text(size = 12),
             axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),
             legend.position  =  "none",
             panel.background  =  element_rect(fill  =  'white'))
```


IgG ELISA Spike vs IgG MCLIA    

```{r fig.height = 3, fig.width = 3}

post.diffs = data.frame(diffs = posterior.peak.titer.times.IgG.ELISA.Spike - posterior.peak.titer.times.IgG.MCLIA)

dens = density(post.diffs$diffs)
hpd.post.diffs = HDInterval::hdi(dens,credMass = 0.95,allowSplit=F)  
lowerlim = hpd.post.diffs[1]
upperlim = hpd.post.diffs[2]

print(paste0("Mean = ",round(mean(post.diffs$diffs),3)))
print(paste0("95% CrI = ",round(lowerlim,3)," to ",round(upperlim,3)))

ggplot(data = post.diffs, aes(x = diffs)) +
       geom_histogram(aes(y  =  ..density..),binwidth  =  1, fill  =  col.igg, color  =  col.igg,alpha=0.5) +
       #scale_x_continuous(breaks = seq(0,(max(boot.samples.df$boot.samples)+2),5),limits=c(0,max(boot.samples.df$boot.samples+2))) +
       ggtitle("Peak titer time difference between means") +
       xlab("Difference between means (days)") +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size = 12),
             text = element_text(size = 12),
             axis.text = element_text(size = 12),
             axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),
             legend.position  =  "none",
             panel.background  =  element_rect(fill  =  'white'))
```



IgG ELISA NP vs IgG MCLIA    

```{r fig.height = 3, fig.width = 3}

post.diffs = data.frame(diffs = posterior.peak.titer.times.IgG.ELISA.NP - posterior.peak.titer.times.IgG.MCLIA)

dens = density(post.diffs$diffs)
hpd.post.diffs = HDInterval::hdi(dens,credMass = 0.95,allowSplit=F)  
lowerlim = hpd.post.diffs[1]
upperlim = hpd.post.diffs[2]

print(paste0("Mean = ",round(mean(post.diffs$diffs),3)))
print(paste0("95% CrI = ",round(lowerlim,3)," to ",round(upperlim,3)))

ggplot(data = post.diffs, aes(x = diffs)) +
       geom_histogram(aes(y  =  ..density..),binwidth  =  1, fill  =  col.igg, color  =  col.igg,alpha=0.5) +
       #scale_x_continuous(breaks = seq(0,(max(boot.samples.df$boot.samples)+2),5),limits=c(0,max(boot.samples.df$boot.samples+2))) +
       ggtitle("Peak titer time difference between means") +
       xlab("Difference between means (days)") +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size = 12),
             text = element_text(size = 12),
             axis.text = element_text(size = 12),
             axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),
             legend.position  =  "none",
             panel.background  =  element_rect(fill  =  'white'))
```




### Disease severity - Mild/Moderate       

Marker = IgG       
Assay = ELISA      
Antigen = NP         
Disease severity = Mild/Moderate          
Minimum number of datapoints per individual = 3    



```{r results='hide',fig.width=11,fig.height=4}


d2 = d0 [ which(d0$marker=="IgG" & !is.na(d0$test.result) & d0$assay == "ELISA" & d0$time.estimate.cat == "Exact" & d0$time.cat == "Symptom onset" & d0$severity == "Mild_Moderate" & d0$antigen == "NP"),]





# only keep individuals that have at least one positive sample
posnegcount = as.data.frame(xtabs(~ id + test.pos.neg,d2))
id.keep = droplevels(posnegcount$id[which(posnegcount$test.pos.neg == "POS" & posnegcount$Freq>1)])
d2 = d2 [ which(d2$id %in% id.keep),]



# only keep individuals that have at least 2 samples in total
id.keep = droplevels(as.data.frame(table(d2$id))$Var1[which(as.data.frame(table(d2$id))$Freq > 2)])
d2 = d2 [ which(d2$id %in% id.keep),]
N.inds = length(unique(d2$id))
N.inds


N.inds.IgG.mild = N.inds

for(i in 1:length(unique(paste0(d2$study,d2$units)))){
       
       d2$test.result[which(paste0(d2$study,d2$units) == unique(paste0(d2$study,d2$units))[i])] = d2$test.result[which(paste0(d2$study,d2$units) == unique(paste0(d2$study,d2$units))[i])]/max(d2$test.result[which(paste0(d2$study,d2$units) == unique(paste0(d2$study,d2$units))[i])])
}



# check for outliers
ggplot() +
       geom_point(data=d2,aes(x = time.start, y = test.result,col=id,group=id),size = 1.5) +
       geom_line(data=d2,aes(x = time.start, y = test.result,col=id,group=id),size=0.7) +
       #scale_x_continuous(breaks = seq(0,max(d2$time.start),2)) +
       scale_y_continuous(limits=c(0,1)) +
       #scale_color_gradientn(colors  =  rev(brewer.pal(11,"Spectral"))) +
       # scale_color_brewer(palette = "Spectral", name = "Marker/Assay") +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size  = 12),text = element_text(size = 12),axis.text = element_text(size = 12),axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),legend.text = element_text(size=9),panel.background  =  element_rect(fill  =  'white')) +
       xlab("Days post symptom onset") +
       ylab("Antibody level")





# run MCMC or load previous data? 
run.mcmc.again = F

if(run.mcmc.again == T){
       model.jags = jags.model(model.file,
                               data=list('titer'=d2$test.result,
                                         'time'=d2$time.start,
                                         'id'=as.numeric(as.factor(d2$id)),
                                         'N.id'=length(unique(d2$id))
                               ),
                               #inits=list('peak.titer.sd.hyper'=0.5),
                               n.chains=6,
                               n.adapt = 1000)
       
       
       # burn in
       burn.in = 20000
       update(model.jags, n.iter = burn.in, by = 1)
       
       
       # draw samples
       iterations = 50000
       post = coda.samples(model.jags, c("peak.titer.mean.hyper","peak.titer.sd.hyper","peak.titer","displacement.mean.hyper","displacement.sd.hyper","displacement","growth.rate.mean.hyper","growth.rate"), n.iter = iterations, thin = 1)
       
       
       post.df = mcmclist.to.dataframe(post)
       
       saveRDS(post,file = paste0("MCMC_output/MCMC_output_post_",format(Sys.time(),"%Y%m%d_%H%M%S"),".RDS"))
       
       saveRDS(post.df,file = paste0("MCMC_output/MCMC_output_postdf_",format(Sys.time(),"%Y%m%d_%H%M%S"),".RDS"))
       
} else { 
       
       # enter the corresponding mcmc filenames here, as saved in the saveRDS lines above
       # example: post = readRDS("MCMC_output/MCMC_output_post_20200804_163314.RDS")
       post = readRDS("MCMC_output/")
       post.df = readRDS("MCMC_output/")
}



N.inds = length(unique(d2$id))


```

#### Gelman-Rubin convergence diagnostics:    

```{r}
gelman.diag(post)
```


#### Posterior growth rate:     


```{r fig.height = 3, fig.width=4}

plot.MCMC.posterior(input.data = post.df,column.to.plot = which(names(post.df)=="growth.rate.mean.hyper"),x.axis.label = "Growth rate (1/days)",title = "Posterior growth rate")

plot.MCMC.chains(input.data = post.df,column.to.plot = which(names(post.df)=="growth.rate.mean.hyper"),y.axis.label = "Growth rate (1/days)",title = "Posterior growth rate",thinning = 5) 


growth.rate.overall.mean = mean(post.df$growth.rate.mean.hyper)



```


#### Posterior peak titer overall mean:    


```{r fig.height = 3, fig.width=4}
plot.MCMC.posterior(input.data = post.df,column.to.plot = which(colnames(post.df)=="peak.titer.mean.hyper"),x.axis.label = "Peak titer mean",title = "Posterior peak titer mean")

plot.MCMC.chains(input.data = post.df,column.to.plot = which(colnames(post.df)=="peak.titer.mean.hyper"),y.axis.label = "Peak titer mean",title = "Posterior peak titer mean",thinning = 5) 

peak.titer.overall.mean = mean(post.df$peak.titer.mean.hyper)


```




#### Posterior displacement overall mean:      


```{r fig.height = 3, fig.width=4}
plot.MCMC.posterior(input.data = post.df,column.to.plot = which(names(post.df)=="displacement.mean.hyper"),x.axis.label = "Displacement mean",title = "Posterior displacement mean")

plot.MCMC.chains(input.data = post.df,column.to.plot = which(names(post.df)=="displacement.mean.hyper"),y.axis.label = "Displacement mean",title = "Posterior displacement mean",thinning = 5) 

displacement.overall.mean = mean(post.df$displacement.mean.hyper)
```




```{r}
# calculate posterior means

peak.titer.individual.means = as.data.frame(apply(post.df[,(4+N.inds+N.inds):(3+N.inds+N.inds+N.inds)],MARGIN = 2,mean))


displacement.individual.means = as.data.frame(apply(post.df[,(1:N.inds)],MARGIN = 2,mean))


growth.rate.individual.means = as.data.frame(apply(post.df[,(3+N.inds):(2+N.inds+N.inds)],MARGIN = 2,mean))

growth.rate.all.IgG.ELISA.NP.mild = growth.rate.individual.means


peak.titer.overall.mean.IgG.ELISA.NP.mild = peak.titer.overall.mean
displacement.overall.mean.IgG.ELISA.NP.mild = displacement.overall.mean
growth.rate.overall.mean.IgG.ELISA.NP.mild = growth.rate.overall.mean



```





#### Fitted function using mean posterior estimates       


```{r warning=FALSE, fig.width = 6, fig.height = 4}
plot.times = 0:max(d2$time.start)


observed.data = d2
observed.data$predicted = NA
uid = unique(observed.data$id)
for(i in 1:length(uid)){
       
       observed.data$predicted[which(observed.data$id == uid[i])] = titer.gompertz.fun(times = observed.data$time.start[which(observed.data$id == uid[i])], peak.titer = peak.titer.individual.means[i,1], displacement = displacement.individual.means[i,1], growth.rate = growth.rate.individual.means[i,1])
       
}


fit.dat = data.frame(titer = titer.gompertz.fun(times = plot.times, peak.titer = peak.titer.overall.mean, displacement = displacement.overall.mean, growth.rate = growth.rate.overall.mean), time = plot.times)

fit.dat.mean = fit.dat


observed.data$id = as.factor(observed.data$id)


plot1 = ggplot() +
       geom_point(data=observed.data,aes(x = time.start, y = test.result,col=as.numeric(id),group=id),size = 1.5) +
       geom_line(data=observed.data,aes(x = time.start, y = test.result,col=as.numeric(id),group=id),size=0.7) +
       geom_line(data=fit.dat,aes(x = time, y = titer),col="black",size=1.4,linetype="dashed") +
       #scale_x_continuous(breaks = seq(0,max(d2$time.start),2)) +
       scale_y_continuous(limits=c(0,1)) +
       scale_color_gradientn(colors  =  rev(brewer.pal(11,"Spectral"))) +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size  = 12),text = element_text(size = 12),axis.text = element_text(size = 12),axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),legend.position  =  "none",panel.background  =  element_rect(fill  =  'white')) +
       xlab("Days post symptom onset") +
       ylab("Antibody level")





```





#### Fitted functions for each individual      


```{r fig.width = 6, fig.height = 4}


fit.dat = data.frame(id = rep(uid, each = length(plot.times)), time = rep(plot.times,length(uid)), titer = NA)

for(i in 1:length(uid)){
       
       fit.dat$titer[which(fit.dat$id == uid[i])] = titer.gompertz.fun(times = plot.times, peak.titer = peak.titer.individual.means[i,1],displacement = displacement.individual.means[i,1],growth.rate = growth.rate.individual.means[i,1])
}


plot2 = ggplot() +
       geom_point(data=observed.data,aes(x = time.start, y = test.result,group=id),col="grey",size = 1.5) +
       geom_line(data=observed.data,aes(x = time.start, y = test.result,group=id),col="grey",size=0.7) +
       geom_line(data = fit.dat, aes(x = time, y = titer, col = as.numeric(id), group = id),size=1.2,alpha=0.5) +
       geom_line(data=fit.dat.mean,aes(x = time, y = titer),col="black",size=1.4,linetype="dashed") +
       #scale_x_continuous(breaks = seq(0,max(d2$time.start),2)) +
       scale_color_gradientn(colors  =  rev(brewer.pal(11,"Spectral"))) +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size  = 10),text = element_text(size = 12),axis.text = element_text(size = 12),axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),legend.position  =  "none",panel.background  =  element_rect(fill  =  'white')) +
       xlab("Days post symptom onset") +
       ylab("Antibody level")



```


```{r fig.height = 4, fig.width=8}

plot1 + plot2
```

#### Peak titer timing mean     



```{r}
peak.titer.time.mean.IgG.mild = get.peak.titer.time(titers = fit.dat.mean$titer, days = fit.dat.mean$time)

peak.titer.time.mean.IgG.mild
```


#### Peak titer timing all     

```{r}


peak.titer.times = data.frame(id = unique(fit.dat$id), peak.titer.time = NA)

for(i in 1:length(unique(fit.dat$id))){
       peak.titer.times$peak.titer.time[i] = get.peak.titer.time(titers = fit.dat$titer[which(fit.dat$id == unique(fit.dat$id)[i])], days = fit.dat$time[which(fit.dat$id == unique(fit.dat$id)[i])])
}

peak.titer.times
mean_se(peak.titer.times$peak.titer.time)
peak.titer.time.all.IgG.mild = peak.titer.times
```




#### Fitted function with additional functions drawn from credible interval       


```{r warning=FALSE, fig.width = 4, fig.height = 3}




# get more posterior samples from within credible interval, for variation plotting
# use growth rate as main variable to focus on
dens = density(post.df[,"growth.rate.mean.hyper"])
hpd.int.toi = HDInterval::hdi(dens,credMass = 0.95,allowSplit=F)  
lowerlim = hpd.int.toi[1]
upperlim = hpd.int.toi[2]

lowerlim.igg.elisa.np.mild = lowerlim
upperlim.igg.elisa.np.mild = upperlim

# randomly sample 100 rows that have a growth rate within the credible interval
ransamp = sample(which(post.df$growth.rate.mean.hyper > lowerlim & post.df$growth.rate.mean.hyper < upperlim),100)

ransamp.df = data.frame(growth.rate = post.df$growth.rate.mean.hyper[ransamp], peak.titer = post.df$peak.titer.mean.hyper[ransamp], displacement = post.df$displacement.mean.hyper[ransamp])


plot.times = 0:max(d2$time.start)


fit.dat = as.data.frame(apply(ransamp.df,1,fit.titers.fun.2))
fit.dat$time = plot.times

fit.dat = reshape2::melt(fit.dat,id.vars="time")

fit.dat.2 = as.data.frame(apply(ransamp.df,1,fit.titers.fun))
fit.dat.2$time = plot.times

fit.dat.2 = reshape2::melt(fit.dat.2,id.vars="time")
fit.dat.IgG.ELISA.np.mild = fit.dat.2

main.fit.fun = data.frame(titer = titer.gompertz.fun(times = plot.times, peak.titer = peak.titer.overall.mean, displacement = displacement.overall.mean, growth.rate = growth.rate.overall.mean), time = plot.times)




ggplot() +
       geom_line(data=fit.dat,aes(x = time, y = value,group=variable),col="#D53E4F",size=0.7,alpha=0.1) +
       geom_line(data=main.fit.fun,aes(x = time, y = titer),col="#D53E4F",size=1.6) +
       #scale_x_continuous(breaks = seq(0,max(d2$time.start),2)) +
       #scale_y_continuous(limits=c(0,1)) +
       #scale_color_gradientn(colors  =  rev(brewer.pal(11,"Spectral"))) +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size  = 12),text = element_text(size = 12),axis.text = element_text(size = 12),axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),legend.position  =  "none",panel.background  =  element_rect(fill  =  'white')) +
       xlab("Days post symptom onset") +
       ylab("Antibody level")





```



```{r}

# store posterior growth rates and posterior peak titer times

posterior.growth.rates.IgG.mild = post.df$growth.rate.mean.hyper[which(post.df$iteration %in% 61000:71000)]


posterior.peak.titer.times.IgG.mild = apply(post.df[61000:71000,c("displacement.mean.hyper","growth.rate.mean.hyper")],1,get.posterior.peak.titer.times)



```

<br>

***

<br>   
















### Disease severity - Severe/Critical       

Marker = IgG       
Assay = ELISA      
Antigen = NP         
Disease severity = Severe/Critical        
Minimum number of datapoints per individual = 3    



```{r results='hide',fig.width=11,fig.height=4}


d2 = d0 [ which(d0$marker=="IgG" & !is.na(d0$test.result) & d0$assay == "ELISA" & d0$time.estimate.cat == "Exact" & d0$time.cat == "Symptom onset" & d0$severity == "Severe_Critical" & d0$antigen == "NP"),]





# only keep individuals that have at least one positive sample
posnegcount = as.data.frame(xtabs(~ id + test.pos.neg,d2))
id.keep = droplevels(posnegcount$id[which(posnegcount$test.pos.neg == "POS" & posnegcount$Freq>1)])
d2 = d2 [ which(d2$id %in% id.keep),]



# only keep individuals that have at least 2 samples in total
id.keep = droplevels(as.data.frame(table(d2$id))$Var1[which(as.data.frame(table(d2$id))$Freq > 2)])
d2 = d2 [ which(d2$id %in% id.keep),]
N.inds = length(unique(d2$id))
N.inds

N.inds.IgG.severe = N.inds

for(i in 1:length(unique(paste0(d2$study,d2$units)))){
       
       d2$test.result[which(paste0(d2$study,d2$units) == unique(paste0(d2$study,d2$units))[i])] = d2$test.result[which(paste0(d2$study,d2$units) == unique(paste0(d2$study,d2$units))[i])]/max(d2$test.result[which(paste0(d2$study,d2$units) == unique(paste0(d2$study,d2$units))[i])])
}



# check for outliers
ggplot() +
       geom_point(data=d2,aes(x = time.start, y = test.result,col=id,group=id),size = 1.5) +
       geom_line(data=d2,aes(x = time.start, y = test.result,col=id,group=id),size=0.7) +
       #scale_x_continuous(breaks = seq(0,max(d2$time.start),2)) +
       scale_y_continuous(limits=c(0,1)) +
       #scale_color_gradientn(colors  =  rev(brewer.pal(11,"Spectral"))) +
       # scale_color_brewer(palette = "Spectral", name = "Marker/Assay") +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size  = 12),text = element_text(size = 12),axis.text = element_text(size = 12),axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),legend.text = element_text(size=9),panel.background  =  element_rect(fill  =  'white')) +
       xlab("Days post symptom onset") +
       ylab("Antibody level")






# run MCMC or load previous data? 
run.mcmc.again = F

if(run.mcmc.again == T){
       model.jags = jags.model(model.file,
                               data=list('titer'=d2$test.result,
                                         'time'=d2$time.start,
                                         'id'=as.numeric(as.factor(d2$id)),
                                         'N.id'=length(unique(d2$id))
                               ),
                               #inits=list('peak.titer.sd.hyper'=0.5),
                               n.chains=6,
                               n.adapt = 1000)
       
       
       # burn in
       burn.in = 20000
       update(model.jags, n.iter = burn.in, by = 1)
       
       
       # draw samples
       iterations = 50000
       post = coda.samples(model.jags, c("peak.titer.mean.hyper","peak.titer.sd.hyper","peak.titer","displacement.mean.hyper","displacement.sd.hyper","displacement","growth.rate.mean.hyper","growth.rate"), n.iter = iterations, thin = 1)
       
       
       post.df = mcmclist.to.dataframe(post)
       
       saveRDS(post,file = paste0("MCMC_output/MCMC_output_post_",format(Sys.time(),"%Y%m%d_%H%M%S"),".RDS"))
       
       saveRDS(post.df,file = paste0("MCMC_output/MCMC_output_postdf_",format(Sys.time(),"%Y%m%d_%H%M%S"),".RDS"))
       
} else { 
       
       # enter the corresponding mcmc filenames here, as saved in the saveRDS lines above
       # example: post = readRDS("MCMC_output/MCMC_output_post_20200804_163314.RDS")
       post = readRDS("MCMC_output/")
       post.df = readRDS("MCMC_output/")
}



N.inds = length(unique(d2$id))


```

#### Gelman-Rubin convergence diagnostics:    

```{r}
gelman.diag(post)
```


#### Posterior growth rate:     


```{r fig.height = 3, fig.width=4}
plot.MCMC.posterior(input.data = post.df,column.to.plot = which(names(post.df)=="growth.rate.mean.hyper"),x.axis.label = "Growth rate (1/days)",title = "Posterior growth rate")

plot.MCMC.chains(input.data = post.df,column.to.plot = which(names(post.df)=="growth.rate.mean.hyper"),y.axis.label = "Growth rate (1/days)",title = "Posterior growth rate",thinning = 5) 


growth.rate.overall.mean = mean(post.df$growth.rate.mean.hyper)


```


#### Posterior peak titer overall mean:    


```{r fig.height = 3, fig.width=4}
plot.MCMC.posterior(input.data = post.df,column.to.plot = which(colnames(post.df)=="peak.titer.mean.hyper"),x.axis.label = "Peak titer mean",title = "Posterior peak titer mean")

plot.MCMC.chains(input.data = post.df,column.to.plot = which(colnames(post.df)=="peak.titer.mean.hyper"),y.axis.label = "Peak titer mean",title = "Posterior peak titer mean",thinning = 5) 

peak.titer.overall.mean = mean(post.df$peak.titer.mean.hyper)


```




#### Posterior displacement overall mean:      


```{r fig.height = 3, fig.width=4}
plot.MCMC.posterior(input.data = post.df,column.to.plot = which(names(post.df)=="displacement.mean.hyper"),x.axis.label = "Displacement mean",title = "Posterior displacement mean")

plot.MCMC.chains(input.data = post.df,column.to.plot = which(names(post.df)=="displacement.mean.hyper"),y.axis.label = "Displacement mean",title = "Posterior displacement mean",thinning = 5) 

displacement.overall.mean = mean(post.df$displacement.mean.hyper)
```




```{r}
# calculate posterior means

peak.titer.individual.means = as.data.frame(apply(post.df[,(4+N.inds+N.inds):(3+N.inds+N.inds+N.inds)],MARGIN = 2,mean))


displacement.individual.means = as.data.frame(apply(post.df[,(1:N.inds)],MARGIN = 2,mean))


growth.rate.individual.means = as.data.frame(apply(post.df[,(3+N.inds):(2+N.inds+N.inds)],MARGIN = 2,mean))

growth.rate.all.IgG.ELISA.NP.severe = growth.rate.individual.means

peak.titer.overall.mean.IgG.ELISA.NP.severe = peak.titer.overall.mean
displacement.overall.mean.IgG.ELISA.NP.severe = displacement.overall.mean
growth.rate.overall.mean.IgG.ELISA.NP.severe = growth.rate.overall.mean



```



#### Fitted function using mean posterior estimates       


```{r warning=FALSE, fig.width = 6, fig.height = 4}
plot.times = 0:max(d2$time.start)


observed.data = d2
observed.data$predicted = NA
uid = unique(observed.data$id)
for(i in 1:length(uid)){
       
       observed.data$predicted[which(observed.data$id == uid[i])] = titer.gompertz.fun(times = observed.data$time.start[which(observed.data$id == uid[i])], peak.titer = peak.titer.individual.means[i,1], displacement = displacement.individual.means[i,1], growth.rate = growth.rate.individual.means[i,1])
       
}


fit.dat = data.frame(titer = titer.gompertz.fun(times = plot.times, peak.titer = peak.titer.overall.mean, displacement = displacement.overall.mean, growth.rate = growth.rate.overall.mean), time = plot.times)

fit.dat.mean = fit.dat


observed.data$id = as.factor(observed.data$id)


plot1 = ggplot() +
       geom_point(data=observed.data,aes(x = time.start, y = test.result,col=as.numeric(id),group=id),size = 1.5) +
       geom_line(data=observed.data,aes(x = time.start, y = test.result,col=as.numeric(id),group=id),size=0.7) +
       geom_line(data=fit.dat,aes(x = time, y = titer),col="black",size=1.4,linetype="dashed") +
       #scale_x_continuous(breaks = seq(0,max(d2$time.start),2)) +
       scale_y_continuous(limits=c(0,1)) +
       scale_color_gradientn(colors  =  rev(brewer.pal(11,"Spectral"))) +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size  = 12),text = element_text(size = 12),axis.text = element_text(size = 12),axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),legend.position  =  "none",panel.background  =  element_rect(fill  =  'white')) +
       xlab("Days post symptom onset") +
       ylab("Antibody level")





```





#### Fitted functions for each individual      


```{r fig.width = 6, fig.height = 4}


fit.dat = data.frame(id = rep(uid, each = length(plot.times)), time = rep(plot.times,length(uid)), titer = NA)

for(i in 1:length(uid)){
       
       fit.dat$titer[which(fit.dat$id == uid[i])] = titer.gompertz.fun(times = plot.times, peak.titer = peak.titer.individual.means[i,1],displacement = displacement.individual.means[i,1],growth.rate = growth.rate.individual.means[i,1])
}


plot2 = ggplot() +
       geom_point(data=observed.data,aes(x = time.start, y = test.result,group=id),col="grey",size = 1.5) +
       geom_line(data=observed.data,aes(x = time.start, y = test.result,group=id),col="grey",size=0.7) +
       geom_line(data = fit.dat, aes(x = time, y = titer, col = as.numeric(id), group = id),size=1.2,alpha=0.5) +
       geom_line(data=fit.dat.mean,aes(x = time, y = titer),col="black",size=1.4,linetype="dashed") +
       #scale_x_continuous(breaks = seq(0,max(d2$time.start),2)) +
       scale_color_gradientn(colors  =  rev(brewer.pal(11,"Spectral"))) +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size  = 10),text = element_text(size = 12),axis.text = element_text(size = 12),axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),legend.position  =  "none",panel.background  =  element_rect(fill  =  'white')) +
       xlab("Days post symptom onset") +
       ylab("Antibody level")



```

```{r fig.height = 4, fig.width=8}

plot1 + plot2
```


#### Peak titer timing mean     



```{r}
peak.titer.time.mean.IgG.severe = get.peak.titer.time(titers = fit.dat.mean$titer, days = fit.dat.mean$time)

peak.titer.time.mean.IgG.severe
```


#### Peak titer timing all     

```{r}


peak.titer.times = data.frame(id = unique(fit.dat$id), peak.titer.time = NA)

for(i in 1:length(unique(fit.dat$id))){
       peak.titer.times$peak.titer.time[i] = get.peak.titer.time(titers = fit.dat$titer[which(fit.dat$id == unique(fit.dat$id)[i])], days = fit.dat$time[which(fit.dat$id == unique(fit.dat$id)[i])])
}

peak.titer.times
mean_se(peak.titer.times$peak.titer.time)
peak.titer.time.all.IgG.severe = peak.titer.times
```




#### Fitted function with additional functions drawn from credible interval       


```{r warning=FALSE, fig.width = 4, fig.height = 3}




# get more posterior samples from within credible interval, for variation plotting
# use growth rate as main variable to focus on
dens = density(post.df[,"growth.rate.mean.hyper"])
hpd.int.toi = HDInterval::hdi(dens,credMass = 0.95,allowSplit=F)  
lowerlim = hpd.int.toi[1]
upperlim = hpd.int.toi[2]

lowerlim.igg.elisa.np.severe = lowerlim
upperlim.igg.elisa.np.severe = upperlim

# randomly sample 100 rows that have a growth rate within the credible interval
ransamp = sample(which(post.df$growth.rate.mean.hyper > lowerlim & post.df$growth.rate.mean.hyper < upperlim),100)

ransamp.df = data.frame(growth.rate = post.df$growth.rate.mean.hyper[ransamp], peak.titer = post.df$peak.titer.mean.hyper[ransamp], displacement = post.df$displacement.mean.hyper[ransamp])


plot.times = 0:max(d2$time.start)


fit.dat = as.data.frame(apply(ransamp.df,1,fit.titers.fun.2))
fit.dat$time = plot.times

fit.dat = reshape2::melt(fit.dat,id.vars="time")

fit.dat.2 = as.data.frame(apply(ransamp.df,1,fit.titers.fun))
fit.dat.2$time = plot.times

fit.dat.2 = reshape2::melt(fit.dat.2,id.vars="time")
fit.dat.IgG.ELISA.np.severe = fit.dat.2

main.fit.fun = data.frame(titer = titer.gompertz.fun(times = plot.times, peak.titer = peak.titer.overall.mean, displacement = displacement.overall.mean, growth.rate = growth.rate.overall.mean), time = plot.times)




ggplot() +
       geom_line(data=fit.dat,aes(x = time, y = value,group=variable),col="#D53E4F",size=0.7,alpha=0.1) +
       geom_line(data=main.fit.fun,aes(x = time, y = titer),col="#D53E4F",size=1.6) +
       #scale_x_continuous(breaks = seq(0,max(d2$time.start),2)) +
       #scale_y_continuous(limits=c(0,1)) +
       #scale_color_gradientn(colors  =  rev(brewer.pal(11,"Spectral"))) +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size  = 12),text = element_text(size = 12),axis.text = element_text(size = 12),axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),legend.position  =  "none",panel.background  =  element_rect(fill  =  'white')) +
       xlab("Days post symptom onset") +
       ylab("Antibody level")





```


```{r}

# store posterior growth rates and posterior peak titer times

posterior.growth.rates.IgG.severe = post.df$growth.rate.mean.hyper[which(post.df$iteration %in% 61000:71000)]


posterior.peak.titer.times.IgG.severe = apply(post.df[61000:71000,c("displacement.mean.hyper","growth.rate.mean.hyper")],1,get.posterior.peak.titer.times)



```




### Disease severity - combined       

Marker = IgG       
Assay = ELISA      
Antigen = NP         
Disease severity = any      
Minimum number of datapoints per individual = 3    



```{r results='hide',fig.width=11,fig.height=4}


d2 = d0 [ which(d0$marker=="IgG" & !is.na(d0$test.result) & d0$assay == "ELISA" & d0$time.estimate.cat == "Exact" & d0$time.cat == "Symptom onset" & !is.na(d0$severity) & d0$antigen == "NP"),]





# only keep individuals that have at least one positive sample
posnegcount = as.data.frame(xtabs(~ id + test.pos.neg,d2))
id.keep = droplevels(posnegcount$id[which(posnegcount$test.pos.neg == "POS" & posnegcount$Freq>1)])
d2 = d2 [ which(d2$id %in% id.keep),]



# only keep individuals that have at least 2 samples in total
id.keep = droplevels(as.data.frame(table(d2$id))$Var1[which(as.data.frame(table(d2$id))$Freq > 2)])
d2 = d2 [ which(d2$id %in% id.keep),]
N.inds = length(unique(d2$id))
N.inds

for(i in 1:length(unique(paste0(d2$study,d2$units)))){
       
       d2$test.result[which(paste0(d2$study,d2$units) == unique(paste0(d2$study,d2$units))[i])] = d2$test.result[which(paste0(d2$study,d2$units) == unique(paste0(d2$study,d2$units))[i])]/max(d2$test.result[which(paste0(d2$study,d2$units) == unique(paste0(d2$study,d2$units))[i])])
}



# check for outliers
ggplot() +
       geom_point(data=d2,aes(x = time.start, y = test.result,col=id,group=id),size = 1.5) +
       geom_line(data=d2,aes(x = time.start, y = test.result,col=id,group=id),size=0.7) +
       #scale_x_continuous(breaks = seq(0,max(d2$time.start),2)) +
       scale_y_continuous(limits=c(0,1)) +
       #scale_color_gradientn(colors  =  rev(brewer.pal(11,"Spectral"))) +
       # scale_color_brewer(palette = "Spectral", name = "Marker/Assay") +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size  = 12),text = element_text(size = 12),axis.text = element_text(size = 12),axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),legend.text = element_text(size=9),panel.background  =  element_rect(fill  =  'white')) +
       xlab("Days post symptom onset") +
       ylab("Antibody level")



id.mild = unique(d2$id[which(d2$severity == "Mild_Moderate")])
id.severe = unique(d2$id[which(d2$severity == "Severe_Critical")])



# run MCMC or load previous data? 
run.mcmc.again = F

if(run.mcmc.again == T){
       model.jags = jags.model(model.file,
                               data=list('titer'=d2$test.result,
                                         'time'=d2$time.start,
                                         'id'=as.numeric(as.factor(d2$id)),
                                         'N.id'=length(unique(d2$id))
                               ),
                               #inits=list('peak.titer.sd.hyper'=0.5),
                               n.chains=6,
                               n.adapt = 1000)
       
       
       # burn in
       burn.in = 20000
       update(model.jags, n.iter = burn.in, by = 1)
       
       
       # draw samples
       iterations = 50000
       post = coda.samples(model.jags, c("peak.titer.mean.hyper","peak.titer.sd.hyper","peak.titer","displacement.mean.hyper","displacement.sd.hyper","displacement","growth.rate.mean.hyper","growth.rate"), n.iter = iterations, thin = 1)
       
       
       post.df = mcmclist.to.dataframe(post)
       
       saveRDS(post,file = paste0("MCMC_output/MCMC_output_post_",format(Sys.time(),"%Y%m%d_%H%M%S"),".RDS"))
       
       saveRDS(post.df,file = paste0("MCMC_output/MCMC_output_postdf_",format(Sys.time(),"%Y%m%d_%H%M%S"),".RDS"))
       
} else { 
       
       # enter the corresponding mcmc filenames here, as saved in the saveRDS lines above
       # example: post = readRDS("MCMC_output/MCMC_output_post_20200804_163314.RDS")
       post = readRDS("MCMC_output/")
       post.df = readRDS("MCMC_output/")
}



N.inds = length(unique(d2$id))


```

#### Gelman-Rubin convergence diagnostics:    

```{r}
gelman.diag(post)
```


#### Posterior growth rate:     


```{r fig.height = 3, fig.width=4}

plot.MCMC.posterior(input.data = post.df,column.to.plot = which(names(post.df)=="growth.rate.mean.hyper"),x.axis.label = "Growth rate (1/days)",title = "Posterior growth rate")

plot.MCMC.chains(input.data = post.df,column.to.plot = which(names(post.df)=="growth.rate.mean.hyper"),y.axis.label = "Growth rate (1/days)",title = "Posterior growth rate",thinning = 5) 


growth.rate.overall.mean = mean(post.df$growth.rate.mean.hyper)


```


#### Posterior peak titer overall mean:    


```{r fig.height = 3, fig.width=4}
plot.MCMC.posterior(input.data = post.df,column.to.plot = which(colnames(post.df)=="peak.titer.mean.hyper"),x.axis.label = "Peak titer mean",title = "Posterior peak titer mean")

plot.MCMC.chains(input.data = post.df,column.to.plot = which(colnames(post.df)=="peak.titer.mean.hyper"),y.axis.label = "Peak titer mean",title = "Posterior peak titer mean",thinning = 5) 

peak.titer.overall.mean = mean(post.df$peak.titer.mean.hyper)


```




#### Posterior displacement overall mean:      


```{r fig.height = 3, fig.width=4}
plot.MCMC.posterior(input.data = post.df,column.to.plot = which(names(post.df)=="displacement.mean.hyper"),x.axis.label = "Displacement mean",title = "Posterior displacement mean")

plot.MCMC.chains(input.data = post.df,column.to.plot = which(names(post.df)=="displacement.mean.hyper"),y.axis.label = "Displacement mean",title = "Posterior displacement mean",thinning = 5) 

displacement.overall.mean = mean(post.df$displacement.mean.hyper)
```




```{r}

# calculate posterior means

peak.titer.individual.means = as.data.frame(apply(post.df[,(4+N.inds+N.inds):(3+N.inds+N.inds+N.inds)],MARGIN = 2,mean))


displacement.individual.means = as.data.frame(apply(post.df[,(1:N.inds)],MARGIN = 2,mean))


growth.rate.individual.means = as.data.frame(apply(post.df[,(3+N.inds):(2+N.inds+N.inds)],MARGIN = 2,mean))

growth.rate.all.IgG.ELISA.NP.mild.severe = growth.rate.individual.means


idx.mild = which(unique(d2$id) %in% id.mild)
idx.severe = which(unique(d2$id) %in% id.severe)


peak.titer.igg.mild = peak.titer.individual.means[idx.mild,1]
peak.titer.igg.severe = peak.titer.individual.means[idx.severe,1]

growth.rate.igg.mild = growth.rate.individual.means[idx.mild,1]
growth.rate.igg.severe = growth.rate.individual.means[idx.severe,1]


peak.titer.overall.mean.IgG.ELISA.NP.mild.severe = peak.titer.overall.mean
displacement.overall.mean.IgG.ELISA.NP.mild.severe = displacement.overall.mean
growth.rate.overall.mean.IgG.ELISA.NP.mild.severe = growth.rate.overall.mean



```




#### Fitted function using mean posterior estimates       


```{r warning=FALSE, fig.width = 6, fig.height = 4}
plot.times = 0:max(d2$time.start)


observed.data = d2
observed.data$predicted = NA
uid = unique(observed.data$id)
for(i in 1:length(uid)){
       
       observed.data$predicted[which(observed.data$id == uid[i])] = titer.gompertz.fun(times = observed.data$time.start[which(observed.data$id == uid[i])], peak.titer = peak.titer.individual.means[i,1], displacement = displacement.individual.means[i,1], growth.rate = growth.rate.individual.means[i,1])
       
}


fit.dat = data.frame(titer = titer.gompertz.fun(times = plot.times, peak.titer = peak.titer.overall.mean, displacement = displacement.overall.mean, growth.rate = growth.rate.overall.mean), time = plot.times)


fit.dat.mean = fit.dat

observed.data$id = as.factor(observed.data$id)


plot1 = ggplot() +
       geom_point(data=observed.data,aes(x = time.start, y = test.result,col=as.numeric(id),group=id),size = 1.5) +
       geom_line(data=observed.data,aes(x = time.start, y = test.result,col=as.numeric(id),group=id),size=0.7) +
       geom_line(data=fit.dat,aes(x = time, y = titer),col="black",size=1.4,linetype="dashed") +
       #scale_x_continuous(breaks = seq(0,max(d2$time.start),2)) +
       scale_y_continuous(limits=c(0,1)) +
       scale_color_gradientn(colors  =  rev(brewer.pal(11,"Spectral"))) +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size  = 12),text = element_text(size = 12),axis.text = element_text(size = 12),axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),legend.position  =  "none",panel.background  =  element_rect(fill  =  'white')) +
       xlab("Days post symptom onset") +
       ylab("Antibody level")





```





#### Fitted functions for each individual      


```{r fig.width = 6, fig.height = 4}


fit.dat = data.frame(id = rep(uid, each = length(plot.times)), time = rep(plot.times,length(uid)), titer = NA)

for(i in 1:length(uid)){
       
       fit.dat$titer[which(fit.dat$id == uid[i])] = titer.gompertz.fun(times = plot.times, peak.titer = peak.titer.individual.means[i,1],displacement = displacement.individual.means[i,1],growth.rate = growth.rate.individual.means[i,1])
}

fit.dat.igg.disease.severity.1 = fit.dat

plot2 = ggplot() +
       geom_point(data=observed.data,aes(x = time.start, y = test.result,group=id),col="grey",size = 1.5) +
       geom_line(data=observed.data,aes(x = time.start, y = test.result,group=id),col="grey",size=0.7) +
       geom_line(data = fit.dat, aes(x = time, y = titer, col = as.numeric(id), group = id),size=1.2,alpha=0.5) +
       geom_line(data=fit.dat.mean,aes(x = time, y = titer),col="black",size=1.4,linetype="dashed") +
       #scale_x_continuous(breaks = seq(0,max(d2$time.start),2)) +
       scale_color_gradientn(colors  =  rev(brewer.pal(11,"Spectral"))) +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size  = 10),text = element_text(size = 12),axis.text = element_text(size = 12),axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),legend.position  =  "none",panel.background  =  element_rect(fill  =  'white')) +
       xlab("Days post symptom onset") +
       ylab("Antibody level")



```


```{r fig.height = 4, fig.width=8}

plot1 + plot2
```


#### Fitted function with additional functions drawn from credible interval       


```{r warning=FALSE, fig.width = 4, fig.height = 3}




# get more posterior samples from within credible interval, for variation plotting
# use growth rate as main variable to focus on
dens = density(post.df[,"growth.rate.mean.hyper"])
hpd.int.toi = HDInterval::hdi(dens,credMass = 0.95,allowSplit=F)  
lowerlim = hpd.int.toi[1]
upperlim = hpd.int.toi[2]

lowerlim.igg.elisa.np.mild.severe = lowerlim
upperlim.igg.elisa.np.mild.severe = upperlim

# randomly sample 100 rows that have a growth rate within the credible interval
ransamp = sample(which(post.df$growth.rate.mean.hyper > lowerlim & post.df$growth.rate.mean.hyper < upperlim),100)

ransamp.df = data.frame(growth.rate = post.df$growth.rate.mean.hyper[ransamp], peak.titer = peak.titer.overall.mean, displacement = displacement.overall.mean)


plot.times = 0:max(d2$time.start)


fit.dat = as.data.frame(apply(ransamp.df,1,fit.titers.fun.2))
fit.dat$time = plot.times

fit.dat = reshape2::melt(fit.dat,id.vars="time")


fit.dat.2 = as.data.frame(apply(ransamp.df,1,fit.titers.fun))
fit.dat.2$time = plot.times

fit.dat.2 = reshape2::melt(fit.dat.2,id.vars="time")
fit.dat.IgG.ELISA.np.mild.severe = fit.dat.2

main.fit.fun = data.frame(titer = titer.gompertz.fun(times = plot.times, peak.titer = peak.titer.overall.mean, displacement = displacement.overall.mean, growth.rate = growth.rate.overall.mean), time = plot.times)




ggplot() +
       geom_line(data=fit.dat,aes(x = time, y = value,group=variable),col="#D53E4F",size=0.7,alpha=0.1) +
       geom_line(data=main.fit.fun,aes(x = time, y = titer),col="#D53E4F",size=1.6) +
       #scale_x_continuous(breaks = seq(0,max(d2$time.start),2)) +
       #scale_y_continuous(limits=c(0,1)) +
       #scale_color_gradientn(colors  =  rev(brewer.pal(11,"Spectral"))) +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size  = 12),text = element_text(size = 12),axis.text = element_text(size = 12),axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),legend.position  =  "none",panel.background  =  element_rect(fill  =  'white')) +
       xlab("Days post symptom onset") +
       ylab("Antibody level")





```



```{r}

# store posterior growth rates and posterior peak titer times

posterior.growth.rates.IgG.mild.severe = post.df$growth.rate.mean.hyper[which(post.df$iteration %in% 61000:71000)]


posterior.peak.titer.times.IgG.mild.severe = apply(post.df[61000:71000,c("displacement.mean.hyper","growth.rate.mean.hyper")],1,get.posterior.peak.titer.times)



```



### Combined disease severity




### Titer kinetics disease severity    


```{r warning=FALSE, fig.width = 6, fig.height = 4}

plot.times = 0:40




main.fit.fun.igg.mild = data.frame(titer = titer.gompertz.fun(times = plot.times, peak.titer = 1, displacement = displacement.overall.mean.IgG.ELISA.NP.mild, growth.rate = growth.rate.overall.mean.IgG.ELISA.NP.mild), time = plot.times, assay = "IgG ELISA Mild/Moderate")


main.fit.fun.igg.severe = data.frame(titer = titer.gompertz.fun(times = plot.times, peak.titer = 1, displacement = displacement.overall.mean.IgG.ELISA.NP.severe, growth.rate = growth.rate.overall.mean.IgG.ELISA.NP.severe), time = plot.times, assay = "IgG ELISA Severe/Critical")



main.fit.functions = rbind(main.fit.fun.igg.mild,main.fit.fun.igg.severe)

main.fit.functions = reshape2::melt(main.fit.functions, id.vars = c("time","assay"))

main.fit.function.igg.disease.severity = main.fit.functions


fit.dat.IgG.ELISA.np.mild$assay = "IgG ELISA Mild/Moderate"
fit.dat.IgG.ELISA.np.severe$assay = "IgG ELISA Severe/Critical"

fit.dat.all = rbind(fit.dat.IgG.ELISA.np.mild,fit.dat.IgG.ELISA.np.severe)
fit.dat.all$variable = paste(fit.dat.all$assay, fit.dat.all$variable)


fit.dat.all = reshape2::melt(fit.dat.all, id.vars = c("time","assay","variable"))
colnames(fit.dat.all)[4] = "var2"


fit.dat.all.igg.disease.severity = fit.dat.all






lowerlim.igg.elisa.np.mild.out = titer.gompertz.fun(times = plot.times,peak.titer = 1, displacement = displacement.overall.mean.IgG.ELISA.NP.mild, growth.rate = lowerlim.igg.elisa.np.mild) 
upperlim.igg.elisa.np.mild.out = titer.gompertz.fun(times = plot.times,peak.titer = 1, displacement = displacement.overall.mean.IgG.ELISA.NP.mild, growth.rate = upperlim.igg.elisa.np.mild) 

lowerlim.igg.elisa.np.severe.out = titer.gompertz.fun(times = plot.times,peak.titer = 1, displacement = displacement.overall.mean.IgG.ELISA.NP.severe, growth.rate = lowerlim.igg.elisa.np.severe) 
upperlim.igg.elisa.np.severe.out = titer.gompertz.fun(times = plot.times,peak.titer = 1, displacement = displacement.overall.mean.IgG.ELISA.NP.severe, growth.rate = upperlim.igg.elisa.np.severe) 




main.fit.functions$lowerlim = NA
main.fit.functions$upperlim = NA


main.fit.functions$lowerlim [ which(main.fit.functions$assay == "IgG ELISA Mild/Moderate") ] = lowerlim.igg.elisa.np.mild.out
main.fit.functions$upperlim [ which(main.fit.functions$assay == "IgG ELISA Mild/Moderate") ] = upperlim.igg.elisa.np.mild.out

main.fit.functions$lowerlim [ which(main.fit.functions$assay == "IgG ELISA Severe/Critical") ] = lowerlim.igg.elisa.np.severe.out
main.fit.functions$upperlim [ which(main.fit.functions$assay == "IgG ELISA Severe/Critical") ] = upperlim.igg.elisa.np.severe.out


main.fit.functions.IgG.severity = main.fit.functions

ggplot(data=main.fit.functions,aes(x = time, y = value,group=assay,col=assay)) +
       #geom_line(data=fit.dat.all,aes(x = time, y = value,group = variable, col=assay),size=0.5,alpha=0.1) +
       #geom_ribbon(aes(x = plot.times,ymin = lowerlim.elisa.spike,ymax = upperlim.elisa.spike),col=col.rna,fill = col.rna,alpha=0.2) +
       geom_ribbon(aes(ymin = lowerlim,ymax = upperlim),fill = "none",linetype="dashed") +
       geom_line(size=1.8) +
       #scale_x_continuous(breaks = seq(0,max(d2$time.start),2)) +
       scale_y_continuous(limits=c(0,1)) +
       #scale_color_gradientn(colors  =  rev(brewer.pal(11,"Spectral"))) +
       # scale_color_brewer(palette = "Spectral", name = "") +
       scale_color_manual(values = c(col.mild.igg,col.severe.igg),name="") +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size  = 12),text = element_text(size = 12),axis.text = element_text(size = 12),axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),legend.position  =  c(0.82,0.3),legend.background = element_rect(fill="white"),panel.background  =  element_rect(fill  =  'white')) +
       xlab("Days post symptom onset") +
       ylab("Antibody level")




```



### Growth rate comparison disease severity



#### Posterior means and 95% CrI    

IgG mild:    

```{r}

dens = density(posterior.growth.rates.IgG.mild)
hpd.post.diffs = HDInterval::hdi(dens,credMass = 0.95,allowSplit=F)  
lowerlim = hpd.post.diffs[1]
upperlim = hpd.post.diffs[2]

print(paste0("Mean = ",round(mean(posterior.growth.rates.IgG.mild),3)))
print(paste0("95% CrI = ",round(lowerlim,3)," to ",round(upperlim,3)))


```


IgG severe:    

```{r}

dens = density(posterior.growth.rates.IgG.severe)
hpd.post.diffs = HDInterval::hdi(dens,credMass = 0.95,allowSplit=F)  
lowerlim = hpd.post.diffs[1]
upperlim = hpd.post.diffs[2]

print(paste0("Mean = ",round(mean(posterior.growth.rates.IgG.severe),3)))
print(paste0("95% CrI = ",round(lowerlim,3)," to ",round(upperlim,3)))


```



```{r fig.height=3,fig.width=5}

growth.rate.all.IgG.ELISA.NP.mild$marker = "Mild/Moderate"
growth.rate.all.IgG.ELISA.NP.severe$marker = "Severe/Critical"


means_and_se = rbind(mean_se(growth.rate.all.IgG.ELISA.NP.mild[,1]),
                     mean_se(growth.rate.all.IgG.ELISA.NP.severe[,1]))

colnames(means_and_se)[1] = c("growth.rate")
means_and_se$marker = c("Mild/Moderate","Severe/Critical")


growth.rate.igg.severity.df = rbind(growth.rate.all.IgG.ELISA.NP.mild,growth.rate.all.IgG.ELISA.NP.severe)
colnames(growth.rate.igg.severity.df)[1]="growth.rate"


cols = c("Mild/Moderate" = col.mild.igg, "Severe/Critical" = col.severe.igg)



# t.test(growth.rate.all.IgG.ELISA.NP.mild[,1],growth.rate.all.IgG.ELISA.NP.severe[,1])


ggplot(data = growth.rate.igg.severity.df,aes(x=marker, y = growth.rate,col=marker)) +
       geom_point(data = means_and_se, aes(x = marker, y = growth.rate),col="red",shape=19,size=3,alpha=0.5) +
       geom_errorbar(data = means_and_se, aes(ymin = ymin, ymax = ymax),width = 0.1,col="red",alpha=0.5) +
       geom_jitter(width=0.1) +
       #scale_x_continuous(breaks = seq(0,(max(boot.samples.df.tp7$boot.samples)+2),5),limits=c(0,max(boot.samples.df.tp7$boot.samples+2))) +
       ylab("Growth rate (1/days)") +
       scale_color_manual(values = cols) +
       xlab("") +
       ggtitle("") +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size  = 12),text = element_text(size = 12),axis.text = element_text(size = 12),axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),axis.ticks.x = element_blank(),axis.text.x = element_blank(),legend.title = element_blank(),panel.background  =  element_rect(fill  =  'white'))


```



#### Pairwise difference     


IgG mild vs IgG severe    

```{r fig.height = 3, fig.width = 3}

post.diffs = data.frame(diffs = posterior.growth.rates.IgG.mild - posterior.growth.rates.IgG.severe)

dens = density(post.diffs$diffs)
hpd.post.diffs = HDInterval::hdi(dens,credMass = 0.95,allowSplit=F)  
lowerlim = hpd.post.diffs[1]
upperlim = hpd.post.diffs[2]

print(paste0("Mean = ",round(mean(post.diffs$diffs),3)))
print(paste0("95% CrI = ",round(lowerlim,3)," to ",round(upperlim,3)))

ggplot(data = post.diffs, aes(x = diffs)) +
       geom_histogram(aes(y  =  ..density..),binwidth  =  0.01, fill  =  col.igg, color  =  col.igg,alpha=0.5) +
       #scale_x_continuous(breaks = seq(0,(max(boot.samples.df$boot.samples)+2),5),limits=c(0,max(boot.samples.df$boot.samples+2))) +
       ggtitle("Growth rate difference between means") +
       xlab("Difference between means (1/days)") +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size = 12),
             text = element_text(size = 12),
             axis.text = element_text(size = 12),
             axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),
             legend.position  =  "none",
             panel.background  =  element_rect(fill  =  'white'))
```


<br>

***

<br>   



### Peak titer comparison disease severity



```{r fig.height=4,fig.width=5}


cols = c("Mild/Moderate IgG" = col.igm, "Severe/Critical IgG" = col.igg)

peak.titer.igg.mild.df = data.frame(Severity = "Mild/Moderate IgG",peak.titer = peak.titer.igg.mild)
peak.titer.igg.severe.df = data.frame(Severity = "Severe/Critical IgG",peak.titer = peak.titer.igg.severe)

peak.titers.plot = rbind(peak.titer.igg.mild.df,peak.titer.igg.severe.df)

means = data.frame(Severity = c("Mild/Moderate IgG","Severe/Critical IgG"), peak.titer = c(mean(peak.titer.igg.mild),mean(peak.titer.igg.severe)),se = c(sd(peak.titer.igg.mild)/sqrt(length(peak.titer.igg.mild)),sd(peak.titer.igg.severe)/sqrt(length(peak.titer.igg.severe))))

t.test(peak.titer.igg.mild,peak.titer.igg.severe)

ggplot(peak.titers.plot,aes(x=Severity, y = peak.titer,col=Severity)) +
       geom_point(data = means, aes(x = Severity, y = peak.titer),col="red",shape=19,size=3,alpha=0.5) +
       geom_errorbar(data = means, aes(ymin = peak.titer - se, ymax = peak.titer + se),width = 0.1,col="red",alpha=0.5) +
       geom_jitter(width=0.1) +
       #scale_x_continuous(breaks = seq(0,(max(boot.samples.df.tp7$boot.samples)+2),5),limits=c(0,max(boot.samples.df.tp7$boot.samples+2))) +
       ylab("Relative peak titer") +
       scale_color_manual(values = cols) +
       xlab("Disease severity") +
       ggtitle("IgG") +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size  = 12),text = element_text(size = 12),axis.text = element_text(size = 12),axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),legend.title = element_blank(),panel.background  =  element_rect(fill  =  'white'))


```




### Peak titer timing comparison      



#### Posterior means and 95% CrI    

IgG mild:    

```{r}

dens = density(posterior.peak.titer.times.IgG.mild)
hpd.post.diffs = HDInterval::hdi(dens,credMass = 0.95,allowSplit=F)  
lowerlim = hpd.post.diffs[1]
upperlim = hpd.post.diffs[2]

print(paste0("Mean = ",round(mean(posterior.peak.titer.times.IgG.mild),3)))
print(paste0("95% CrI = ",round(lowerlim,3)," to ",round(upperlim,3)))


```


IgG severe:    

```{r}

dens = density(posterior.peak.titer.times.IgG.severe)
hpd.post.diffs = HDInterval::hdi(dens,credMass = 0.95,allowSplit=F)  
lowerlim = hpd.post.diffs[1]
upperlim = hpd.post.diffs[2]

print(paste0("Mean = ",round(mean(posterior.peak.titer.times.IgG.severe),3)))
print(paste0("95% CrI = ",round(lowerlim,3)," to ",round(upperlim,3)))


```



```{r fig.height=4,fig.width=5}
peak.titer.times = data.frame(id = unique(fit.dat.igg.disease.severity.1$id), peak.titer.time = NA)

for(i in 1:length(unique(fit.dat.igg.disease.severity.1$id))){
       peak.titer.times$peak.titer.time[i] = get.peak.titer.time(titers = fit.dat.igg.disease.severity.1$titer[which(fit.dat.igg.disease.severity.1$id == unique(fit.dat.igg.disease.severity.1$id)[i])], days = fit.dat.igg.disease.severity.1$time[which(fit.dat.igg.disease.severity.1$id == unique(fit.dat.igg.disease.severity.1$id)[i])])
}



peak.titer.time.all.IgG.severe = peak.titer.times[idx.severe,]
peak.titer.time.all.IgG.mild = peak.titer.times[idx.mild,]
```


Mild peak titer times:     

```{r fig.height=4,fig.width=5}
mean_se(peak.titer.time.all.IgG.mild$peak.titer.time)
peak.titer.time.all.IgG.mild
```


Severe peak titer times:    

```{r fig.height=4,fig.width=5}
mean_se(peak.titer.time.all.IgG.severe$peak.titer.time)
peak.titer.time.all.IgG.severe
```


```{r fig.height=3,fig.width=5}

peak.titer.time.all.IgG.mild$marker = "Mild/Moderate"
peak.titer.time.all.IgG.severe$marker = "Severe/Critical"


means_and_se = rbind(mean_se(peak.titer.time.all.IgG.mild$peak.titer.time),
                     mean_se(peak.titer.time.all.IgG.severe$peak.titer.time))

colnames(means_and_se)[1] = c("peak.titer.time")
means_and_se$marker = c("Mild/Moderate","Severe/Critical")


peak.titer.time.igg.severity.df = rbind(peak.titer.time.all.IgG.mild,peak.titer.time.all.IgG.severe)



cols = c("Mild/Moderate" = col.mild.igg, "Severe/Critical" = col.severe.igg)



# t.test(peak.titer.time.all.IgG.mild$peak.titer.time,peak.titer.time.all.IgG.severe$peak.titer.time)


ggplot(data = peak.titer.time.igg.severity.df,aes(x=marker, y = peak.titer.time,col=marker)) +
       geom_point(data = means_and_se, aes(x = marker, y = peak.titer.time),col="red",shape=19,size=3,alpha=0.5) +
       geom_errorbar(data = means_and_se, aes(ymin = ymin, ymax = ymax),width = 0.1,col="red",alpha=0.5) +
       geom_jitter(width=0.1) +
       #scale_x_continuous(breaks = seq(0,(max(boot.samples.df.tp7$boot.samples)+2),5),limits=c(0,max(boot.samples.df.tp7$boot.samples+2))) +
       ylab("Peak titer time") +
       scale_color_manual(values = cols) +
       xlab("") +
       ggtitle("") +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size  = 12),text = element_text(size = 12),axis.text = element_text(size = 12),axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),axis.ticks.x = element_blank(),axis.text.x = element_blank(),legend.title = element_blank(),panel.background  =  element_rect(fill  =  'white'))


```




#### Pairwise differences     


IgG mild vs IgG severe    

```{r fig.height = 3, fig.width = 3}

post.diffs = data.frame(diffs = posterior.peak.titer.times.IgG.mild - posterior.peak.titer.times.IgG.severe)

dens = density(post.diffs$diffs)
hpd.post.diffs = HDInterval::hdi(dens,credMass = 0.95,allowSplit=F)  
lowerlim = hpd.post.diffs[1]
upperlim = hpd.post.diffs[2]

print(paste0("Mean = ",round(mean(post.diffs$diffs),3)))
print(paste0("95% CrI = ",round(lowerlim,3)," to ",round(upperlim,3)))

ggplot(data = post.diffs, aes(x = diffs)) +
       geom_histogram(aes(y  =  ..density..),binwidth  =  1, fill  =  col.igg, color  =  col.igg,alpha=0.5) +
       #scale_x_continuous(breaks = seq(0,(max(boot.samples.df$boot.samples)+2),5),limits=c(0,max(boot.samples.df$boot.samples+2))) +
       ggtitle("Peak titer time difference between means") +
       xlab("Difference between means (days)") +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size = 12),
             text = element_text(size = 12),
             axis.text = element_text(size = 12),
             axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),
             legend.position  =  "none",
             panel.background  =  element_rect(fill  =  'white'))
```





<br>

***

<br>   






## IgM       


### ELISA Spike     

Marker = IgM       
Assay = ELISA      
Antigen = Spike       
Disease severity = any     
Minimum number of datapoints per individual = 3    



```{r results='hide',fig.width=11,fig.height=4}


d2 = d0 [ which(d0$marker=="IgM" & !is.na(d0$test.result) & d0$assay == "ELISA" & d0$antigen == "Spike" & d0$time.estimate.cat == "Exact" & d0$time.cat == "Symptom onset"),]


# only keep individuals that have at least one positive sample
posnegcount = as.data.frame(xtabs(~ id + test.pos.neg,d2))
id.keep = droplevels(posnegcount$id[which(posnegcount$test.pos.neg == "POS" & posnegcount$Freq>1)])
d2 = d2 [ which(d2$id %in% id.keep),]



# only keep individuals that have at least 2 samples in total
id.keep = droplevels(as.data.frame(table(d2$id))$Var1[which(as.data.frame(table(d2$id))$Freq > 2)])
d2 = d2 [ which(d2$id %in% id.keep),]
N.inds = length(unique(d2$id))
N.inds

N.inds.IgM.ELISA.Spike = N.inds

for(i in 1:length(unique(paste0(d2$study,d2$units)))){
       
       d2$test.result[which(paste0(d2$study,d2$units) == unique(paste0(d2$study,d2$units))[i])] = d2$test.result[which(paste0(d2$study,d2$units) == unique(paste0(d2$study,d2$units))[i])]/max(d2$test.result[which(paste0(d2$study,d2$units) == unique(paste0(d2$study,d2$units))[i])])
}

# remove individual because titers are already very high at day 0, indicating that its time estimate is more wrong than that of the rest of the individuals

d2 = d2[-which(d2$id == "Zhao_Case 18530189"),]


# check for outliers
ggplot() +
       geom_point(data=d2,aes(x = time.start, y = test.result,col=id,group=id),size = 1.5) +
       geom_line(data=d2,aes(x = time.start, y = test.result,col=id,group=id),size=0.7) +
       #scale_x_continuous(breaks = seq(0,max(d2$time.start),2)) +
       scale_y_continuous(limits=c(0,1)) +
       #scale_color_gradientn(colors  =  rev(brewer.pal(11,"Spectral"))) +
       # scale_color_brewer(palette = "Spectral", name = "Marker/Assay") +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size  = 12),text = element_text(size = 12),axis.text = element_text(size = 12),axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),legend.text = element_text(size=9),panel.background  =  element_rect(fill  =  'white')) +
       xlab("Days post symptom onset") +
       ylab("Antibody level")






# run MCMC or load previous data? 
run.mcmc.again = F

if(run.mcmc.again == T){
       model.jags = jags.model(model.file,
                               data=list('titer'=d2$test.result,
                                         'time'=d2$time.start,
                                         'id'=as.numeric(as.factor(d2$id)),
                                         'N.id'=length(unique(d2$id))
                               ),
                               #inits=list('peak.titer.sd.hyper'=0.5),
                               n.chains=6,
                               n.adapt = 1000)
       
       
       # burn in
       burn.in = 20000
       update(model.jags, n.iter = burn.in, by = 1)
       
       
       # draw samples
       iterations = 50000
       post = coda.samples(model.jags, c("peak.titer.mean.hyper","peak.titer.sd.hyper","peak.titer","displacement.mean.hyper","displacement.sd.hyper","displacement","growth.rate.mean.hyper","growth.rate"), n.iter = iterations, thin = 1)
       
       
       post.df = mcmclist.to.dataframe(post)
       
       saveRDS(post,file = paste0("MCMC_output/MCMC_output_post_",format(Sys.time(),"%Y%m%d_%H%M%S"),".RDS"))
       
       saveRDS(post.df,file = paste0("MCMC_output/MCMC_output_postdf_",format(Sys.time(),"%Y%m%d_%H%M%S"),".RDS"))
       
} else { 
       
       # enter the corresponding mcmc filenames here, as saved in the saveRDS lines above
       # example: post = readRDS("MCMC_output/MCMC_output_post_20200804_163314.RDS")
       post = readRDS("MCMC_output/")
       post.df = readRDS("MCMC_output/")
}



N.inds = length(unique(d2$id))


```

#### Gelman-Rubin convergence diagnostics:    

```{r}
gelman.diag(post)
```


#### Posterior growth rate:     


```{r fig.height = 3, fig.width=4}

plot.MCMC.posterior(input.data = post.df,column.to.plot = which(names(post.df)=="growth.rate.mean.hyper"),x.axis.label = "Growth rate (1/days)",title = "Posterior growth rate")

plot.MCMC.chains(input.data = post.df,column.to.plot = which(names(post.df)=="growth.rate.mean.hyper"),y.axis.label = "Growth rate (1/days)",title = "Posterior growth rate",thinning = 5) 


growth.rate.overall.mean = mean(post.df$growth.rate.mean.hyper)

```


#### Posterior peak titer overall mean:    


```{r fig.height = 3, fig.width=4}
plot.MCMC.posterior(input.data = post.df,column.to.plot = which(colnames(post.df)=="peak.titer.mean.hyper"),x.axis.label = "Peak titer mean",title = "Posterior peak titer mean")

plot.MCMC.chains(input.data = post.df,column.to.plot = which(colnames(post.df)=="peak.titer.mean.hyper"),y.axis.label = "Peak titer mean",title = "Posterior peak titer mean",thinning = 5) 

peak.titer.overall.mean = mean(post.df$peak.titer.mean.hyper)


```




#### Posterior displacement overall mean:      


```{r fig.height = 3, fig.width=4}
plot.MCMC.posterior(input.data = post.df,column.to.plot = which(names(post.df)=="displacement.mean.hyper"),x.axis.label = "Displacement mean",title = "Posterior displacement mean")

plot.MCMC.chains(input.data = post.df,column.to.plot = which(names(post.df)=="displacement.mean.hyper"),y.axis.label = "Displacement mean",title = "Posterior displacement mean",thinning = 5) 

displacement.overall.mean = mean(post.df$displacement.mean.hyper)
```



```{r}
# calculate posterior means


peak.titer.individual.means = as.data.frame(apply(post.df[,(4+N.inds+N.inds):(3+N.inds+N.inds+N.inds)],MARGIN = 2,mean))


displacement.individual.means = as.data.frame(apply(post.df[,(1:N.inds)],MARGIN = 2,mean))


growth.rate.individual.means = as.data.frame(apply(post.df[,(3+N.inds):(2+N.inds+N.inds)],MARGIN = 2,mean))

growth.rate.all.IgM.ELISA.Spike = growth.rate.individual.means

peak.titer.overall.mean.IgM.ELISA.Spike = peak.titer.overall.mean
displacement.overall.mean.IgM.ELISA.Spike = displacement.overall.mean
growth.rate.overall.mean.IgM.ELISA.Spike = growth.rate.overall.mean


```




#### Fitted function using mean posterior estimates       


```{r warning=FALSE, fig.width = 6, fig.height = 4}
plot.times = 0:max(d2$time.start)


observed.data = d2
observed.data$predicted = NA
uid = unique(observed.data$id)
for(i in 1:length(uid)){
       
       observed.data$predicted[which(observed.data$id == uid[i])] = titer.gompertz.fun(times = observed.data$time.start[which(observed.data$id == uid[i])], peak.titer = peak.titer.individual.means[i,1], displacement = displacement.individual.means[i,1], growth.rate = growth.rate.individual.means[i,1])
       
}


fit.dat = data.frame(titer = titer.gompertz.fun(times = plot.times, peak.titer = peak.titer.overall.mean, displacement = displacement.overall.mean, growth.rate = growth.rate.overall.mean), time = plot.times)

fit.dat.mean = fit.dat


observed.data$id = as.factor(observed.data$id)


plot1 = ggplot() +
       geom_point(data=observed.data,aes(x = time.start, y = test.result,col=as.numeric(id),group=id),size = 1.5) +
       geom_line(data=observed.data,aes(x = time.start, y = test.result,col=as.numeric(id),group=id),size=0.7) +
       geom_line(data=fit.dat,aes(x = time, y = titer),col="black",size=1.4,linetype="dashed") +
       #scale_x_continuous(breaks = seq(0,max(d2$time.start),2)) +
       scale_y_continuous(limits=c(0,1)) +
       scale_color_gradientn(colors  =  rev(brewer.pal(11,"Spectral"))) +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size  = 12),text = element_text(size = 12),axis.text = element_text(size = 12),axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),legend.position  =  "none",panel.background  =  element_rect(fill  =  'white')) +
       xlab("Days post symptom onset") +
       ylab("Antibody level")





```





#### Fitted functions for each individual      


```{r fig.width = 6, fig.height = 4}


fit.dat = data.frame(id = rep(uid, each = length(plot.times)), time = rep(plot.times,length(uid)), titer = NA)

for(i in 1:length(uid)){
       
       fit.dat$titer[which(fit.dat$id == uid[i])] = titer.gompertz.fun(times = plot.times, peak.titer = peak.titer.individual.means[i,1],displacement = displacement.individual.means[i,1],growth.rate = growth.rate.individual.means[i,1])
}


plot2 = ggplot() +
       geom_point(data=observed.data,aes(x = time.start, y = test.result,group=id),col="grey",size = 1.5) +
       geom_line(data=observed.data,aes(x = time.start, y = test.result,group=id),col="grey",size=0.7) +
       geom_line(data = fit.dat, aes(x = time, y = titer, col = as.numeric(id), group = id),size=1.2,alpha=0.5) +
       geom_line(data=fit.dat.mean,aes(x = time, y = titer),col="black",size=1.4,linetype="dashed") +
       #scale_x_continuous(breaks = seq(0,max(d2$time.start),2)) +
       scale_color_gradientn(colors  =  rev(brewer.pal(11,"Spectral"))) +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size  = 10),text = element_text(size = 12),axis.text = element_text(size = 12),axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),legend.position  =  "none",panel.background  =  element_rect(fill  =  'white')) +
       xlab("Days post symptom onset") +
       ylab("Antibody level")



```


```{r fig.height = 4, fig.width=8}

plot1 + plot2
```

#### Peak titer timing mean     



```{r}
peak.titer.time.mean.IgM.ELISA.Spike = get.peak.titer.time(titers = fit.dat.mean$titer, days = fit.dat.mean$time)

peak.titer.time.mean.IgM.ELISA.Spike
```


#### Peak titer timing all     

```{r}


peak.titer.times = data.frame(id = unique(fit.dat$id), peak.titer.time = NA)

for(i in 1:length(unique(fit.dat$id))){
       peak.titer.times$peak.titer.time[i] = get.peak.titer.time(titers = fit.dat$titer[which(fit.dat$id == unique(fit.dat$id)[i])], days = fit.dat$time[which(fit.dat$id == unique(fit.dat$id)[i])])
}

peak.titer.times
mean_se(peak.titer.times$peak.titer.time)
peak.titer.time.all.IgM.ELISA.Spike = peak.titer.times
```



#### Fitted function with additional functions drawn from credible interval       


```{r warning=FALSE, fig.width = 6, fig.height = 4}




# get more posterior samples from within credible interval, for variation plotting
# use growth rate as main variable to focus on
dens = density(post.df[,"growth.rate.mean.hyper"])
hpd.int.toi = HDInterval::hdi(dens,credMass = 0.95,allowSplit=F)  
lowerlim = hpd.int.toi[1]
upperlim = hpd.int.toi[2]


lowerlim.igm.elisa.spike = lowerlim
upperlim.igm.elisa.spike = upperlim


# randomly sample 100 rows that have a growth rate within the credible interval
ransamp = sample(which(post.df$growth.rate.mean.hyper > lowerlim & post.df$growth.rate.mean.hyper < upperlim),100)

ransamp.df = data.frame(growth.rate = post.df$growth.rate.mean.hyper[ransamp], peak.titer = post.df$peak.titer.mean.hyper[ransamp], displacement = post.df$displacement.mean.hyper[ransamp])


plot.times = 0:max(d2$time.start)


fit.dat = as.data.frame(apply(ransamp.df,1,fit.titers.fun.2))
fit.dat$time = plot.times

fit.dat = reshape2::melt(fit.dat,id.vars="time")

fit.dat.2 = as.data.frame(apply(ransamp.df,1,fit.titers.fun))
fit.dat.2$time = plot.times

fit.dat.2 = reshape2::melt(fit.dat.2,id.vars="time")
fit.dat.IgM.ELISA.Spike = fit.dat.2

main.fit.fun = data.frame(titer = titer.gompertz.fun(times = plot.times, peak.titer = peak.titer.overall.mean, displacement = displacement.overall.mean, growth.rate = growth.rate.overall.mean), time = plot.times)




ggplot() +
       geom_line(data=fit.dat,aes(x = time, y = value,group=variable),col="#D53E4F",size=0.7,alpha=0.1) +
       geom_line(data=main.fit.fun,aes(x = time, y = titer),col="#D53E4F",size=1.6) +
       #scale_x_continuous(breaks = seq(0,max(d2$time.start),2)) +
       #scale_y_continuous(limits=c(0,1)) +
       #scale_color_gradientn(colors  =  rev(brewer.pal(11,"Spectral"))) +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size  = 12),text = element_text(size = 12),axis.text = element_text(size = 12),axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),legend.position  =  "none",panel.background  =  element_rect(fill  =  'white')) +
       xlab("Days post symptom onset") +
       ylab("Antibody level")





```


```{r}

# store posterior growth rates and posterior peak titer times

posterior.growth.rates.IgM.ELISA.Spike = post.df$growth.rate.mean.hyper[which(post.df$iteration %in% 61000:71000)]


posterior.peak.titer.times.IgM.ELISA.Spike = apply(post.df[61000:71000,c("displacement.mean.hyper","growth.rate.mean.hyper")],1,get.posterior.peak.titer.times)



```



<br>

***

<br>   


### ELISA NP     

Marker = IgM       
Assay = ELISA      
Antigen = NP       
Disease severity = any     
Minimum number of datapoints per individual = 3    



```{r results='hide',fig.width=11,fig.height=4}


d2 = d0 [ which(d0$marker=="IgM" & !is.na(d0$test.result) & !is.na(d0$time.start) & d0$assay == "ELISA" & d0$antigen == "NP" & d0$time.estimate.cat == "Exact" & d0$time.cat == "Symptom onset"),]


# only keep individuals that have at least one positive sample
posnegcount = as.data.frame(xtabs(~ id + test.pos.neg,d2))
id.keep = droplevels(posnegcount$id[which(posnegcount$test.pos.neg == "POS" & posnegcount$Freq>1)])
d2 = d2 [ which(d2$id %in% id.keep),]



# only keep individuals that have at least 2 samples in total
id.keep = droplevels(as.data.frame(table(d2$id))$Var1[which(as.data.frame(table(d2$id))$Freq > 2)])
d2 = d2 [ which(d2$id %in% id.keep),]
N.inds = length(unique(d2$id))
N.inds


for(i in 1:length(unique(paste0(d2$study,d2$units)))){
       
       d2$test.result[which(paste0(d2$study,d2$units) == unique(paste0(d2$study,d2$units))[i])] = d2$test.result[which(paste0(d2$study,d2$units) == unique(paste0(d2$study,d2$units))[i])]/max(d2$test.result[which(paste0(d2$study,d2$units) == unique(paste0(d2$study,d2$units))[i])])
}

# remove Zhou_ICU_06012-7 because this 1 individual with only two positive results significantly skews results after normalizing, which means this result is not comparable to others

d2 = d2[-which(d2$id == "Zhou_ICU-06012-7"),]


N.inds = length(unique(d2$id))
N.inds.IgM.ELISA.NP = N.inds


# check for outliers
ggplot() +
       geom_point(data=d2,aes(x = time.start, y = test.result,col=id,group=id),size = 1.5) +
       geom_line(data=d2,aes(x = time.start, y = test.result,col=id,group=id),size=0.7) +
       #scale_x_continuous(breaks = seq(0,max(d2$time.start),2)) +
       scale_y_continuous(limits=c(0,1)) +
       #scale_color_gradientn(colors  =  rev(brewer.pal(11,"Spectral"))) +
       # scale_color_brewer(palette = "Spectral", name = "Marker/Assay") +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size  = 12),text = element_text(size = 12),axis.text = element_text(size = 12),axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),legend.text = element_text(size=9),panel.background  =  element_rect(fill  =  'white')) +
       xlab("Days post symptom onset") +
       ylab("Antibody level")




# run MCMC or load previous data? 
run.mcmc.again = F

if(run.mcmc.again == T){
       model.jags = jags.model(model.file,
                               data=list('titer'=d2$test.result,
                                         'time'=d2$time.start,
                                         'id'=as.numeric(as.factor(d2$id)),
                                         'N.id'=length(unique(d2$id))
                               ),
                               #inits=list('peak.titer.sd.hyper'=0.5),
                               n.chains=6,
                               n.adapt = 1000)
       
       
       # burn in
       burn.in = 20000
       update(model.jags, n.iter = burn.in, by = 1)
       
       
       # draw samples
       iterations = 50000
       post = coda.samples(model.jags, c("peak.titer.mean.hyper","peak.titer.sd.hyper","peak.titer","displacement.mean.hyper","displacement.sd.hyper","displacement","growth.rate.mean.hyper","growth.rate"), n.iter = iterations, thin = 1)
       
       
       post.df = mcmclist.to.dataframe(post)
       
       saveRDS(post,file = paste0("MCMC_output/MCMC_output_post_",format(Sys.time(),"%Y%m%d_%H%M%S"),".RDS"))
       
       saveRDS(post.df,file = paste0("MCMC_output/MCMC_output_postdf_",format(Sys.time(),"%Y%m%d_%H%M%S"),".RDS"))
       
} else { 
       
       # enter the corresponding mcmc filenames here, as saved in the saveRDS lines above
       # example: post = readRDS("MCMC_output/MCMC_output_post_20200804_163314.RDS")
       post = readRDS("MCMC_output/")
       post.df = readRDS("MCMC_output/")
}




```

#### Gelman-Rubin convergence diagnostics:    

```{r}
gelman.diag(post)
```


#### Posterior growth rate:     


```{r fig.height = 3, fig.width=4}

plot.MCMC.posterior(input.data = post.df,column.to.plot = which(names(post.df)=="growth.rate.mean.hyper"),x.axis.label = "Growth rate (1/days)",title = "Posterior growth rate")

plot.MCMC.chains(input.data = post.df,column.to.plot = which(names(post.df)=="growth.rate.mean.hyper"),y.axis.label = "Growth rate (1/days)",title = "Posterior growth rate",thinning = 5) 


growth.rate.overall.mean = mean(post.df$growth.rate.mean.hyper)

```


#### Posterior peak titer overall mean:    


```{r fig.height = 3, fig.width=4}
plot.MCMC.posterior(input.data = post.df,column.to.plot = which(colnames(post.df)=="peak.titer.mean.hyper"),x.axis.label = "Peak titer mean",title = "Posterior peak titer mean")

plot.MCMC.chains(input.data = post.df,column.to.plot = which(colnames(post.df)=="peak.titer.mean.hyper"),y.axis.label = "Peak titer mean",title = "Posterior peak titer mean",thinning = 5) 

peak.titer.overall.mean = mean(post.df$peak.titer.mean.hyper)


```




#### Posterior displacement overall mean:      


```{r fig.height = 3, fig.width=4}
plot.MCMC.posterior(input.data = post.df,column.to.plot = which(names(post.df)=="displacement.mean.hyper"),x.axis.label = "Displacement mean",title = "Posterior displacement mean")

plot.MCMC.chains(input.data = post.df,column.to.plot = which(names(post.df)=="displacement.mean.hyper"),y.axis.label = "Displacement mean",title = "Posterior displacement mean",thinning = 5) 

displacement.overall.mean = mean(post.df$displacement.mean.hyper)
```



```{r}
# calculate posterior means

peak.titer.individual.means = as.data.frame(apply(post.df[,(4+N.inds+N.inds):(3+N.inds+N.inds+N.inds)],MARGIN = 2,mean))


displacement.individual.means = as.data.frame(apply(post.df[,(1:N.inds)],MARGIN = 2,mean))


growth.rate.individual.means = as.data.frame(apply(post.df[,(3+N.inds):(2+N.inds+N.inds)],MARGIN = 2,mean))

growth.rate.all.IgM.ELISA.NP = growth.rate.individual.means


peak.titer.overall.mean.IgM.ELISA.NP = peak.titer.overall.mean
displacement.overall.mean.IgM.ELISA.NP = displacement.overall.mean
growth.rate.overall.mean.IgM.ELISA.NP = growth.rate.overall.mean


```





#### Fitted function using mean posterior estimates       


```{r fig.height = 4, fig.width=5}
plot.times = 0:max(d2$time.start)


observed.data = d2
observed.data$predicted = NA
uid = unique(observed.data$id)
for(i in 1:length(uid)){
       
       observed.data$predicted[which(observed.data$id == uid[i])] = titer.gompertz.fun(times = observed.data$time.start[which(observed.data$id == uid[i])], peak.titer = peak.titer.individual.means[i,1], displacement = displacement.individual.means[i,1], growth.rate = growth.rate.individual.means[i,1])
       
}


fit.dat = data.frame(titer = titer.gompertz.fun(times = plot.times, peak.titer = peak.titer.overall.mean, displacement = displacement.overall.mean, growth.rate = growth.rate.overall.mean), time = plot.times)


fit.dat.mean = fit.dat

observed.data$id = as.factor(observed.data$id)


plot1 = ggplot() +
       geom_point(data=observed.data,aes(x = time.start, y = test.result,col=as.numeric(id),group=id),size = 1.5) +
       geom_line(data=observed.data,aes(x = time.start, y = test.result,col=as.numeric(id),group=id),size=0.7) +
       geom_line(data=fit.dat,aes(x = time, y = titer),col="black",size=1.4,linetype="dashed") +
       #scale_x_continuous(breaks = seq(0,max(d2$time.start),2)) +
       scale_color_gradientn(colors  =  rev(brewer.pal(11,"Spectral"))) +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size  = 12),text = element_text(size = 12),axis.text = element_text(size = 12),axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),legend.position  =  "none",panel.background  =  element_rect(fill  =  'white')) +
       xlab("Days post symptom onset") +
       ylab("Antibody level")





```





#### Fitted functions for each individual      


```{r fig.height = 4, fig.width=5}


fit.dat = data.frame(id = rep(uid, each = length(plot.times)), time = rep(plot.times,length(uid)), titer = NA)

for(i in 1:length(uid)){
       
       fit.dat$titer[which(fit.dat$id == uid[i])] = titer.gompertz.fun(times = plot.times, peak.titer = peak.titer.individual.means[i,1],displacement = displacement.individual.means[i,1],growth.rate = growth.rate.individual.means[i,1])
}


plot2 = ggplot() +
       geom_point(data=observed.data,aes(x = time.start, y = test.result,group=id),col="grey",size = 1.5) +
       geom_line(data=observed.data,aes(x = time.start, y = test.result,group=id),col="grey",size=0.7) +
       geom_line(data = fit.dat, aes(x = time, y = titer, col = as.numeric(id), group = id),size=1.2,alpha=0.5) +
       geom_line(data=fit.dat.mean,aes(x = time, y = titer),col="black",size=1.4,linetype="dashed") +
       #scale_x_continuous(breaks = seq(0,max(d2$time.start),2)) +
       scale_color_gradientn(colors  =  rev(brewer.pal(11,"Spectral"))) +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size  = 10),text = element_text(size = 12),axis.text = element_text(size = 12),axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),legend.position  =  "none",panel.background  =  element_rect(fill  =  'white')) +
       xlab("Days post symptom onset") +
       ylab("Antibody level")



```



```{r fig.height = 4, fig.width=8}

plot1 + plot2
```

#### Peak titer timing mean     



```{r}
peak.titer.time.mean.IgM.ELISA.NP = get.peak.titer.time(titers = fit.dat.mean$titer, days = fit.dat.mean$time)

peak.titer.time.mean.IgM.ELISA.NP
```


#### Peak titer timing all     

```{r}


peak.titer.times = data.frame(id = unique(fit.dat$id), peak.titer.time = NA)

for(i in 1:length(unique(fit.dat$id))){
       peak.titer.times$peak.titer.time[i] = get.peak.titer.time(titers = fit.dat$titer[which(fit.dat$id == unique(fit.dat$id)[i])], days = fit.dat$time[which(fit.dat$id == unique(fit.dat$id)[i])])
}

peak.titer.times
mean_se(peak.titer.times$peak.titer.time)
peak.titer.time.all.IgM.ELISA.NP = peak.titer.times
```





#### Fitted function with additional functions drawn from credible interval       


```{r warning=FALSE, fig.width = 6, fig.height = 4}




# get more posterior samples from within credible interval, for variation plotting
# use growth rate as main variable to focus on
dens = density(post.df[,"growth.rate.mean.hyper"])
hpd.int.toi = HDInterval::hdi(dens,credMass = 0.95,allowSplit=F)  
lowerlim = hpd.int.toi[1]
upperlim = hpd.int.toi[2]

lowerlim.igm.elisa.np = lowerlim
upperlim.igm.elisa.np = upperlim


# randomly sample 100 rows that have a growth rate within the credible interval
ransamp = sample(which(post.df$growth.rate.mean.hyper > lowerlim & post.df$growth.rate.mean.hyper < upperlim),100)

ransamp.df = data.frame(growth.rate = post.df$growth.rate.mean.hyper[ransamp], peak.titer = post.df$peak.titer.mean.hyper[ransamp], displacement = post.df$displacement.mean.hyper[ransamp])


plot.times = 0:max(d2$time.start)



fit.dat = as.data.frame(apply(ransamp.df,1,fit.titers.fun.2))
fit.dat$time = plot.times

fit.dat = reshape2::melt(fit.dat,id.vars="time")

fit.dat.2 = as.data.frame(apply(ransamp.df,1,fit.titers.fun))
fit.dat.2$time = plot.times

fit.dat.2 = reshape2::melt(fit.dat.2,id.vars="time")
fit.dat.IgM.ELISA.NP = fit.dat.2

main.fit.fun = data.frame(titer = titer.gompertz.fun(times = plot.times, peak.titer = peak.titer.overall.mean, displacement = displacement.overall.mean, growth.rate = growth.rate.overall.mean), time = plot.times)




ggplot() +
       geom_line(data=fit.dat,aes(x = time, y = value,group=variable),col="#D53E4F",size=0.7,alpha=0.1) +
       geom_line(data=main.fit.fun,aes(x = time, y = titer),col="#D53E4F",size=1.6) +
       #scale_x_continuous(breaks = seq(0,max(d2$time.start),2)) +
       #scale_y_continuous(limits=c(0,1)) +
       #scale_color_gradientn(colors  =  rev(brewer.pal(11,"Spectral"))) +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size  = 12),text = element_text(size = 12),axis.text = element_text(size = 12),axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),legend.position  =  "none",panel.background  =  element_rect(fill  =  'white')) +
       xlab("Days post symptom onset") +
       ylab("Antibody level")





```

```{r}

# store posterior growth rates and posterior peak titer times

posterior.growth.rates.IgM.ELISA.NP = post.df$growth.rate.mean.hyper[which(post.df$iteration %in% 61000:71000)]


posterior.peak.titer.times.IgM.ELISA.NP = apply(post.df[61000:71000,c("displacement.mean.hyper","growth.rate.mean.hyper")],1,get.posterior.peak.titer.times)



```



<br>

***

<br>   



### IFA    

Marker = IgG       
Assay = IFA      
Disease severity = any     
Minimum number of datapoints per individual = 3    

Sample size = 2  ==> not enough data skipping IFA


```{r fig.height = 3, fig.width=3}


d2 = d0 [ which(d0$marker=="IgG" & !is.na(d0$test.result) & !is.na(d0$time.start) & d0$assay == "IFA" & d0$time.estimate.cat == "Exact"),]



# length(unique(d2$id))

id.keep = droplevels(as.data.frame(table(d2$id))$Var1[which(as.data.frame(table(d2$id))$Freq > 2)])

d2 = d2 [ which(d2$id %in% id.keep),]
N.inds = length(unique(d2$id))


for(i in 1:length(unique(paste0(d2$study,d2$units)))){
       
       d2$test.result[which(paste0(d2$study,d2$units) == unique(paste0(d2$study,d2$units))[i])] = d2$test.result[which(paste0(d2$study,d2$units) == unique(paste0(d2$study,d2$units))[i])]/max(d2$test.result[which(paste0(d2$study,d2$units) == unique(paste0(d2$study,d2$units))[i])])
}




```


<br>

***

<br>   


### MCLIA    

Marker = IgG       
Assay = MCLIA      
Disease severity = any     
Minimum number of datapoints per individual = 3    



```{r results = 'hide',fig.width=11,fig.height=4}


d2 = d0 [ which(d0$marker=="IgM" & !is.na(d0$test.result) & !is.na(d0$time.start) & d0$assay == "MCLIA" & d0$time.estimate.cat == "Exact" & d0$time.cat == "Symptom onset"),]

# only keep individuals that have at least one positive sample
posnegcount = as.data.frame(xtabs(~ id + test.pos.neg,d2))
id.keep = droplevels(posnegcount$id[which(posnegcount$test.pos.neg == "POS" & posnegcount$Freq>1)])
d2 = d2 [ which(d2$id %in% id.keep),]



# only keep individuals that have at least 2 samples in total
id.keep = droplevels(as.data.frame(table(d2$id))$Var1[which(as.data.frame(table(d2$id))$Freq > 2)])
d2 = d2 [ which(d2$id %in% id.keep),]
N.inds = length(unique(d2$id))
N.inds

for(i in 1:length(unique(paste0(d2$study,d2$units)))){
       
       d2$test.result[which(paste0(d2$study,d2$units) == unique(paste0(d2$study,d2$units))[i])] = d2$test.result[which(paste0(d2$study,d2$units) == unique(paste0(d2$study,d2$units))[i])]/max(d2$test.result[which(paste0(d2$study,d2$units) == unique(paste0(d2$study,d2$units))[i])])
}



# check for outliers
ggplot() +
       geom_point(data=d2,aes(x = time.start, y = test.result,col=id,group=id),size = 1.5) +
       geom_line(data=d2,aes(x = time.start, y = test.result,col=id,group=id),size=0.7) +
       #scale_x_continuous(breaks = seq(0,max(d2$time.start),2)) +
       scale_y_continuous(limits=c(0,1)) +
       #scale_color_gradientn(colors  =  rev(brewer.pal(11,"Spectral"))) +
       # scale_color_brewer(palette = "Spectral", name = "Marker/Assay") +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size  = 12),text = element_text(size = 12),axis.text = element_text(size = 12),axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),legend.text = element_text(size=9),panel.background  =  element_rect(fill  =  'white')) +
       xlab("Days post symptom onset") +
       ylab("Antibody level")




# run MCMC or load previous data? 
run.mcmc.again = F

if(run.mcmc.again == T){
       model.jags = jags.model(model.file,
                               data=list('titer'=d2$test.result,
                                         'time'=d2$time.start,
                                         'id'=as.numeric(as.factor(d2$id)),
                                         'N.id'=length(unique(d2$id))
                               ),
                               #inits=list('peak.titer.sd.hyper'=0.5),
                               n.chains=6,
                               n.adapt = 1000)
       
       
       # burn in
       burn.in = 20000
       update(model.jags, n.iter = burn.in, by = 1)
       
       
       # draw samples
       iterations = 50000
       post = coda.samples(model.jags, c("peak.titer.mean.hyper","peak.titer.sd.hyper","peak.titer","displacement.mean.hyper","displacement.sd.hyper","displacement","growth.rate.mean.hyper","growth.rate"), n.iter = iterations, thin = 1)
       
       
       post.df = mcmclist.to.dataframe(post)
       
       saveRDS(post,file = paste0("MCMC_output/MCMC_output_post_",format(Sys.time(),"%Y%m%d_%H%M%S"),".RDS"))
       
       saveRDS(post.df,file = paste0("MCMC_output/MCMC_output_postdf_",format(Sys.time(),"%Y%m%d_%H%M%S"),".RDS"))
       
} else { 
       
       # enter the corresponding mcmc filenames here, as saved in the saveRDS lines above
       # example: post = readRDS("MCMC_output/MCMC_output_post_20200804_163314.RDS")
       post = readRDS("MCMC_output/")
       post.df = readRDS("MCMC_output/")
}



N.inds = length(unique(d2$id))


```

#### Gelman-Rubin convergence diagnostics:    

```{r}
gelman.diag(post)
```


#### Posterior growth rate:     


```{r fig.height = 3, fig.width=4}

plot.MCMC.posterior(input.data = post.df,column.to.plot = which(names(post.df)=="growth.rate.mean.hyper"),x.axis.label = "Growth rate (1/days)",title = "Posterior growth rate")

plot.MCMC.chains(input.data = post.df,column.to.plot = which(names(post.df)=="growth.rate.mean.hyper"),y.axis.label = "Growth rate (1/days)",title = "Posterior growth rate",thinning = 5) 


growth.rate.overall.mean = mean(post.df$growth.rate.mean.hyper)

```


#### Posterior peak titer overall mean:    


```{r fig.height = 3, fig.width=4}
plot.MCMC.posterior(input.data = post.df,column.to.plot = which(colnames(post.df)=="peak.titer.mean.hyper"),x.axis.label = "Peak titer mean",title = "Posterior peak titer mean")

plot.MCMC.chains(input.data = post.df,column.to.plot = which(colnames(post.df)=="peak.titer.mean.hyper"),y.axis.label = "Peak titer mean",title = "Posterior peak titer mean",thinning = 5) 

peak.titer.overall.mean = mean(post.df$peak.titer.mean.hyper)


```




#### Posterior displacement overall mean:      


```{r fig.height = 3, fig.width=4}
plot.MCMC.posterior(input.data = post.df,column.to.plot = which(names(post.df)=="displacement.mean.hyper"),x.axis.label = "Displacement mean",title = "Posterior displacement mean")

plot.MCMC.chains(input.data = post.df,column.to.plot = which(names(post.df)=="displacement.mean.hyper"),y.axis.label = "Displacement mean",title = "Posterior displacement mean",thinning = 5) 

displacement.overall.mean = mean(post.df$displacement.mean.hyper)
```



```{r}
# calculate posterior means
peak.titer.individual.means = as.data.frame(apply(post.df[,(4+N.inds+N.inds):(3+N.inds+N.inds+N.inds)],MARGIN = 2,mean))


displacement.individual.means = as.data.frame(apply(post.df[,(1:N.inds)],MARGIN = 2,mean))


growth.rate.individual.means = as.data.frame(apply(post.df[,(3+N.inds):(2+N.inds+N.inds)],MARGIN = 2,mean))

growth.rate.all.IgM.MCLIA = growth.rate.individual.means


peak.titer.overall.mean.IgM.MCLIA = peak.titer.overall.mean
displacement.overall.mean.IgM.MCLIA = displacement.overall.mean
growth.rate.overall.mean.IgM.MCLIA = growth.rate.overall.mean


```





#### Fitted function using mean posterior estimates       


```{r fig.height = 4, fig.width=5}
plot.times = 0:max(d2$time.start)


observed.data = d2
observed.data$predicted = NA
uid = unique(observed.data$id)
for(i in 1:length(uid)){
       
       observed.data$predicted[which(observed.data$id == uid[i])] = titer.gompertz.fun(times = observed.data$time.start[which(observed.data$id == uid[i])], peak.titer = peak.titer.individual.means[i,1], displacement = displacement.individual.means[i,1], growth.rate = growth.rate.individual.means[i,1])
       
}


fit.dat = data.frame(titer = titer.gompertz.fun(times = plot.times, peak.titer = peak.titer.overall.mean, displacement = displacement.overall.mean, growth.rate = growth.rate.overall.mean), time = plot.times)

fit.dat.mean = fit.dat


observed.data$id = as.factor(observed.data$id)


plot1 = ggplot() +
       geom_point(data=observed.data,aes(x = time.start, y = test.result,col=as.numeric(id),group=id),size = 1.5) +
       geom_line(data=observed.data,aes(x = time.start, y = test.result,col=as.numeric(id),group=id),size=0.7) +
       geom_line(data=fit.dat,aes(x = time, y = titer),col="black",size=1.4,linetype="dashed") +
       #scale_x_continuous(breaks = seq(0,max(d2$time.start),2)) +
       scale_color_gradientn(colors  =  rev(brewer.pal(11,"Spectral"))) +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size  = 12),text = element_text(size = 12),axis.text = element_text(size = 12),axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),legend.position  =  "none",panel.background  =  element_rect(fill  =  'white')) +
       xlab("Days post symptom onset") +
       ylab("Antibody level")





```





#### Fitted functions for each individual      


```{r fig.height = 4, fig.width=5}


fit.dat = data.frame(id = rep(uid, each = length(plot.times)), time = rep(plot.times,length(uid)), titer = NA)

for(i in 1:length(uid)){
       
       fit.dat$titer[which(fit.dat$id == uid[i])] = titer.gompertz.fun(times = plot.times, peak.titer = peak.titer.individual.means[i,1],displacement = displacement.individual.means[i,1],growth.rate = growth.rate.individual.means[i,1])
}


plot2 = ggplot() +
       geom_point(data=observed.data,aes(x = time.start, y = test.result,group=id),col="grey",size = 1.5) +
       geom_line(data=observed.data,aes(x = time.start, y = test.result,group=id),col="grey",size=0.7) +
       geom_line(data = fit.dat, aes(x = time, y = titer, col = as.numeric(id), group = id),size=1.2,alpha=0.5) +
       geom_line(data=fit.dat.mean,aes(x = time, y = titer),col="black",size=1.4,linetype="dashed") +
       #scale_x_continuous(breaks = seq(0,max(d2$time.start),2)) +
       scale_color_gradientn(colors  =  rev(brewer.pal(11,"Spectral"))) +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size  = 10),text = element_text(size = 12),axis.text = element_text(size = 12),axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),legend.position  =  "none",panel.background  =  element_rect(fill  =  'white')) +
       xlab("Days post symptom onset") +
       ylab("Antibody level")



```


```{r fig.height = 4, fig.width=8}

plot1 + plot2
```


#### Peak titer timing mean     



```{r}
peak.titer.time.mean.IgM.MCLIA = get.peak.titer.time(titers = fit.dat.mean$titer, days = fit.dat.mean$time)

peak.titer.time.mean.IgM.MCLIA
```


#### Peak titer timing all     

```{r}


peak.titer.times = data.frame(id = unique(fit.dat$id), peak.titer.time = NA)

for(i in 1:length(unique(fit.dat$id))){
       peak.titer.times$peak.titer.time[i] = get.peak.titer.time(titers = fit.dat$titer[which(fit.dat$id == unique(fit.dat$id)[i])], days = fit.dat$time[which(fit.dat$id == unique(fit.dat$id)[i])])
}

peak.titer.times
mean_se(peak.titer.times$peak.titer.time)
peak.titer.time.all.IgM.MCLIA = peak.titer.times
```



#### Fitted function with additional functions drawn from credible interval       


```{r warning=FALSE, fig.width = 6, fig.height = 4}




# get more posterior samples from within credible interval, for variation plotting
# use growth rate as main variable to focus on
dens = density(post.df[,"growth.rate.mean.hyper"])
hpd.int.toi = HDInterval::hdi(dens,credMass = 0.95,allowSplit=F)  
lowerlim = hpd.int.toi[1]
upperlim = hpd.int.toi[2]

lowerlim.igm.mclia = lowerlim
upperlim.igm.mclia = upperlim


# randomly sample 100 rows that have a growth rate within the credible interval
ransamp = sample(which(post.df$growth.rate.mean.hyper > lowerlim & post.df$growth.rate.mean.hyper < upperlim),100)

ransamp.df = data.frame(growth.rate = post.df$growth.rate.mean.hyper[ransamp], peak.titer = post.df$peak.titer.mean.hyper[ransamp], displacement = post.df$displacement.mean.hyper[ransamp])


plot.times = 0:max(d2$time.start)


fit.dat = as.data.frame(apply(ransamp.df,1,fit.titers.fun.2))
fit.dat$time = plot.times

fit.dat = reshape2::melt(fit.dat,id.vars="time")

fit.dat.2 = as.data.frame(apply(ransamp.df,1,fit.titers.fun))
fit.dat.2$time = plot.times

fit.dat.2 = reshape2::melt(fit.dat.2,id.vars="time")
fit.dat.IgM.MCLIA = fit.dat.2

main.fit.fun = data.frame(titer = titer.gompertz.fun(times = plot.times, peak.titer = peak.titer.overall.mean, displacement = displacement.overall.mean, growth.rate = growth.rate.overall.mean), time = plot.times)




ggplot() +
       geom_line(data=fit.dat,aes(x = time, y = value,group=variable),col="#D53E4F",size=0.7,alpha=0.1) +
       geom_line(data=main.fit.fun,aes(x = time, y = titer),col="#D53E4F",size=1.6) +
       #scale_x_continuous(breaks = seq(0,max(d2$time.start),2)) +
       #scale_y_continuous(limits=c(0,1)) +
       #scale_color_gradientn(colors  =  rev(brewer.pal(11,"Spectral"))) +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size  = 12),text = element_text(size = 12),axis.text = element_text(size = 12),axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),legend.position  =  "none",panel.background  =  element_rect(fill  =  'white')) +
       xlab("Days post symptom onset") +
       ylab("Antibody level")





```


```{r}

# store posterior growth rates and posterior peak titer times

posterior.growth.rates.IgM.MCLIA = post.df$growth.rate.mean.hyper[which(post.df$iteration %in% 61000:71000)]


posterior.peak.titer.times.IgM.MCLIA = apply(post.df[61000:71000,c("displacement.mean.hyper","growth.rate.mean.hyper")],1,get.posterior.peak.titer.times)



```


### Assays combined    


```{r warning=FALSE, fig.width = 6, fig.height = 4}



plot.times = 0:max(d2$time.start)




main.fit.fun.elisa.spike = data.frame(titer = titer.gompertz.fun(times = plot.times, peak.titer = 1, displacement = displacement.overall.mean.IgM.ELISA.Spike, growth.rate = growth.rate.overall.mean.IgM.ELISA.Spike), time = plot.times, assay = "ELISA Spike")


main.fit.fun.elisa.np = data.frame(titer = titer.gompertz.fun(times = plot.times, peak.titer = 1, displacement = displacement.overall.mean.IgM.ELISA.NP, growth.rate = growth.rate.overall.mean.IgM.ELISA.NP), time = plot.times, assay = "ELISA NP")


main.fit.fun.mclia = data.frame(titer = titer.gompertz.fun(times = plot.times, peak.titer = 1, displacement = displacement.overall.mean.IgM.MCLIA, growth.rate = growth.rate.overall.mean.IgM.MCLIA), time = plot.times, assay = "MCLIA NP + Spike")


main.fit.functions = rbind(main.fit.fun.elisa.spike,main.fit.fun.elisa.np,main.fit.fun.mclia)

main.fit.functions = reshape2::melt(main.fit.functions, id.vars = c("time","assay"))



fit.dat.IgM.ELISA.Spike$assay = "ELISA Spike"
fit.dat.IgM.ELISA.NP$assay = "ELISA NP"
fit.dat.IgM.MCLIA$assay = "MCLIA NP + Spike"

fit.dat.all = rbind(fit.dat.IgM.ELISA.Spike,fit.dat.IgM.ELISA.NP,fit.dat.IgM.MCLIA)
fit.dat.all$variable = paste(fit.dat.all$assay, fit.dat.all$variable)


fit.dat.all = reshape2::melt(fit.dat.all, id.vars = c("time","assay","variable"))
colnames(fit.dat.all)[4] = "var2"


fit.dat.all.igm = fit.dat.all






lowerlim.elisa.spike.out = titer.gompertz.fun(times = plot.times,peak.titer = 1, displacement = displacement.overall.mean.IgM.ELISA.Spike, growth.rate = lowerlim.igm.elisa.spike) 
upperlim.elisa.spike.out = titer.gompertz.fun(times = plot.times,peak.titer = 1, displacement = displacement.overall.mean.IgM.ELISA.Spike, growth.rate = upperlim.igm.elisa.spike)

lowerlim.elisa.np.out = titer.gompertz.fun(times = plot.times,peak.titer = 1, displacement = displacement.overall.mean.IgM.ELISA.NP, growth.rate = lowerlim.igm.elisa.np)
upperlim.elisa.np.out = titer.gompertz.fun(times = plot.times,peak.titer = 1, displacement = displacement.overall.mean.IgM.ELISA.NP, growth.rate = upperlim.igm.elisa.np)


lowerlim.mclia.out = titer.gompertz.fun(times = plot.times,peak.titer = 1, displacement = displacement.overall.mean.IgM.MCLIA, growth.rate = lowerlim.igm.mclia)
upperlim.mclia.out = titer.gompertz.fun(times = plot.times,peak.titer = 1, displacement = displacement.overall.mean.IgM.MCLIA, growth.rate = upperlim.igm.mclia)



main.fit.functions$lowerlim = NA
main.fit.functions$upperlim = NA


main.fit.functions$lowerlim [ which(main.fit.functions$assay == "ELISA Spike") ] = lowerlim.elisa.spike.out
main.fit.functions$upperlim [ which(main.fit.functions$assay == "ELISA Spike") ] = upperlim.elisa.spike.out
main.fit.functions$lowerlim [ which(main.fit.functions$assay == "ELISA NP") ] = lowerlim.elisa.np.out
main.fit.functions$upperlim [ which(main.fit.functions$assay == "ELISA NP") ] = upperlim.elisa.np.out
main.fit.functions$lowerlim [ which(main.fit.functions$assay == "MCLIA NP + Spike") ] = lowerlim.mclia.out
main.fit.functions$upperlim [ which(main.fit.functions$assay == "MCLIA NP + Spike") ] = upperlim.mclia.out

main.fit.function.igm = main.fit.functions


ggplot(data=main.fit.functions,aes(x = time, y = value,group=assay,col=assay)) +
       #geom_line(data=fit.dat.all,aes(x = time, y = value,group = variable, col=assay),size=0.5,alpha=0.1) +
       #geom_ribbon(aes(x = plot.times,ymin = lowerlim.elisa.spike,ymax = upperlim.elisa.spike),col=col.rna,fill = col.rna,alpha=0.2) +
       geom_ribbon(aes(ymin = lowerlim,ymax = upperlim),fill = "none",alpha=0.6,linetype="dashed") +
       geom_line(size=1.8) +
       #scale_x_continuous(breaks = seq(0,max(d2$time.start),2)) +
       scale_y_continuous(limits=c(0,1)) +
       #scale_color_gradientn(colors  =  rev(brewer.pal(11,"Spectral"))) +
       # scale_color_brewer(palette = "Spectral", name = "") +
       scale_color_manual(values = c(col.igm,"#D53E4F",col.rna),name="") +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size  = 12),text = element_text(size = 12),axis.text = element_text(size = 12),axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),legend.position  =  c(0.82,0.3),legend.background = element_rect(fill="white"),panel.background  =  element_rect(fill  =  'white')) +
       xlab("Days post symptom onset") +
       ylab("Antibody level")







ggplot(data=main.fit.functions[-which(main.fit.functions$assay == "MCLIA NP + Spike"),],aes(x = time, y = value,group=assay,col=assay)) +
       #geom_line(data=fit.dat.all,aes(x = time, y = value,group = variable, col=assay),size=0.5,alpha=0.1) +
       #geom_ribbon(aes(x = plot.times,ymin = lowerlim.elisa.spike,ymax = upperlim.elisa.spike),col=col.rna,fill = col.rna,alpha=0.2) +
       geom_line(data=fit.dat.all[-which(fit.dat.all$assay == "MCLIA NP + Spike"),],aes(x = time, y = value,group = variable, col=assay),size=0.5,alpha=0.1) +
       geom_ribbon(aes(ymin = lowerlim,ymax = upperlim),fill="none",alpha=0.1,linetype="dashed") +
       geom_line(size=1.8) +
       #scale_x_continuous(breaks = seq(0,max(d2$time.start),2)) +
       scale_y_continuous(limits=c(0,1)) +
       #scale_color_gradientn(colors  =  rev(brewer.pal(11,"Spectral"))) +
       # scale_color_brewer(palette = "Spectral", name = "") +
       scale_color_manual(values = c(col.rna,col.igm),name="") +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size  = 12),text = element_text(size = 12),axis.text = element_text(size = 12),axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),legend.position  =  c(0.82,0.3),legend.background = element_rect(fill="white"),panel.background  =  element_rect(fill  =  'white')) +
       xlab("Days post symptom onset") +
       ylab("Antibody level")


```





<br>

***

<br>   






### Growth rate comparison assays    


#### Posterior means and 95% CrI    


IgM ELISA Spike:    

```{r}

dens = density(posterior.growth.rates.IgM.ELISA.Spike)
hpd.post.diffs = HDInterval::hdi(dens,credMass = 0.95,allowSplit=F)  
lowerlim = hpd.post.diffs[1]
upperlim = hpd.post.diffs[2]

print(paste0("Mean = ",round(mean(posterior.growth.rates.IgM.ELISA.Spike),3)))
print(paste0("95% CrI = ",round(lowerlim,3)," to ",round(upperlim,3)))


```


IgM ELISA NP:    

```{r}

dens = density(posterior.growth.rates.IgM.ELISA.NP)
hpd.post.diffs = HDInterval::hdi(dens,credMass = 0.95,allowSplit=F)  
lowerlim = hpd.post.diffs[1]
upperlim = hpd.post.diffs[2]

print(paste0("Mean = ",round(mean(posterior.growth.rates.IgM.ELISA.NP),3)))
print(paste0("95% CrI = ",round(lowerlim,3)," to ",round(upperlim,3)))


```

IgM MCLIA:    

```{r}

dens = density(posterior.growth.rates.IgM.MCLIA)
hpd.post.diffs = HDInterval::hdi(dens,credMass = 0.95,allowSplit=F)  
lowerlim = hpd.post.diffs[1]
upperlim = hpd.post.diffs[2]

print(paste0("Mean = ",round(mean(posterior.growth.rates.IgM.MCLIA),3)))
print(paste0("95% CrI = ",round(lowerlim,3)," to ",round(upperlim,3)))


```



```{r fig.height=4,fig.width=5}




growth.rate.all.IgM.ELISA.Spike$marker = "IgM ELISA Spike"
growth.rate.all.IgM.ELISA.NP$marker = "IgM ELISA NP"
growth.rate.all.IgM.MCLIA$marker = "IgM MCLIA"

means_and_se = rbind(mean_se(growth.rate.all.IgM.ELISA.Spike[,1]),
                     mean_se(growth.rate.all.IgM.ELISA.NP[,1]),
                     mean_se(growth.rate.all.IgM.MCLIA[,1]))

colnames(means_and_se)[1] = c("growth.rate")
means_and_se$marker = c("IgM ELISA Spike","IgM ELISA NP","IgM MCLIA")


means_and_se.igm = means_and_se

growth.rate.igm.df = rbind(growth.rate.all.IgM.ELISA.Spike,growth.rate.all.IgM.ELISA.NP,growth.rate.all.IgM.MCLIA)
colnames(growth.rate.igm.df)[1]="growth.rate"


cols = c("IgM ELISA Spike" = col.elisa, "IgM ELISA NP" = col.igm,"IgM MCLIA" = col.mclia)



#t.test(growth.rate.all.IgM.ELISA.Spike[,1],growth.rate.all.IgM.ELISA.NP[,1])


ggplot(data = growth.rate.igm.df,aes(x=marker, y = growth.rate,col=marker)) +
       geom_point(data = means_and_se, aes(x = marker, y = growth.rate),col="red",shape=19,size=3,alpha=0.5) +
       geom_errorbar(data = means_and_se, aes(ymin = ymin, ymax = ymax),width = 0.1,col="red",alpha=0.5) +
       geom_jitter(width=0.1) +
       #scale_x_continuous(breaks = seq(0,(max(boot.samples.df.tp7$boot.samples)+2),5),limits=c(0,max(boot.samples.df.tp7$boot.samples+2))) +
       ylab("Growth rate (1/days)") +
       scale_color_manual(values = cols) +
       xlab("") +
       ggtitle("") +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size  = 12),text = element_text(size = 12),axis.text = element_text(size = 12),axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),axis.ticks.x = element_blank(),axis.text.x = element_blank(),legend.title = element_blank(),panel.background  =  element_rect(fill  =  'white'))


```



#### Pairwise differences     


IgM ELISA Spike vs IgM ELISA NP    

```{r fig.height = 3, fig.width = 3}

post.diffs = data.frame(diffs = posterior.growth.rates.IgM.ELISA.Spike - posterior.growth.rates.IgM.ELISA.NP)

dens = density(post.diffs$diffs)
hpd.post.diffs = HDInterval::hdi(dens,credMass = 0.95,allowSplit=F)  
lowerlim = hpd.post.diffs[1]
upperlim = hpd.post.diffs[2]

print(paste0("Mean = ",round(mean(post.diffs$diffs),3)))
print(paste0("95% CrI = ",round(lowerlim,3)," to ",round(upperlim,3)))

ggplot(data = post.diffs, aes(x = diffs)) +
       geom_histogram(aes(y  =  ..density..),binwidth  =  0.05, fill  =  col.igg, color  =  col.igg,alpha=0.5) +
       #scale_x_continuous(breaks = seq(0,(max(boot.samples.df$boot.samples)+2),5),limits=c(0,max(boot.samples.df$boot.samples+2))) +
       ggtitle("Growth rate difference between means") +
       xlab("Difference between means (1/days)") +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size = 12),
             text = element_text(size = 12),
             axis.text = element_text(size = 12),
             axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),
             legend.position  =  "none",
             panel.background  =  element_rect(fill  =  'white'))
```




IgM ELISA Spike vs IgM MCLIA    

```{r fig.height = 3, fig.width = 3}

post.diffs = data.frame(diffs = posterior.growth.rates.IgM.ELISA.Spike - posterior.growth.rates.IgM.MCLIA)

dens = density(post.diffs$diffs)
hpd.post.diffs = HDInterval::hdi(dens,credMass = 0.95,allowSplit=F)  
lowerlim = hpd.post.diffs[1]
upperlim = hpd.post.diffs[2]

print(paste0("Mean = ",round(mean(post.diffs$diffs),3)))
print(paste0("95% CrI = ",round(lowerlim,3)," to ",round(upperlim,3)))

ggplot(data = post.diffs, aes(x = diffs)) +
       geom_histogram(aes(y  =  ..density..),binwidth  =  0.01, fill  =  col.igg, color  =  col.igg,alpha=0.5) +
       #scale_x_continuous(breaks = seq(0,(max(boot.samples.df$boot.samples)+2),5),limits=c(0,max(boot.samples.df$boot.samples+2))) +
       ggtitle("Growth rate difference between means") +
       xlab("Difference between means (1/days)") +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size = 12),
             text = element_text(size = 12),
             axis.text = element_text(size = 12),
             axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),
             legend.position  =  "none",
             panel.background  =  element_rect(fill  =  'white'))
```



IgM ELISA NP vs IgM MCLIA    

```{r fig.height = 3, fig.width = 3}

post.diffs = data.frame(diffs = posterior.growth.rates.IgM.ELISA.NP - posterior.growth.rates.IgM.MCLIA)

dens = density(post.diffs$diffs)
hpd.post.diffs = HDInterval::hdi(dens,credMass = 0.95,allowSplit=F)  
lowerlim = hpd.post.diffs[1]
upperlim = hpd.post.diffs[2]

print(paste0("Mean = ",round(mean(post.diffs$diffs),3)))
print(paste0("95% CrI = ",round(lowerlim,3)," to ",round(upperlim,3)))

ggplot(data = post.diffs, aes(x = diffs)) +
       geom_histogram(aes(y  =  ..density..),binwidth  =  0.01, fill  =  col.igg, color  =  col.igg,alpha=0.5) +
       #scale_x_continuous(breaks = seq(0,(max(boot.samples.df$boot.samples)+2),5),limits=c(0,max(boot.samples.df$boot.samples+2))) +
       ggtitle("Growth rate difference between means") +
       xlab("Difference between means (1/days)") +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size = 12),
             text = element_text(size = 12),
             axis.text = element_text(size = 12),
             axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),
             legend.position  =  "none",
             panel.background  =  element_rect(fill  =  'white'))
```


### Peak titer timing comparison      


#### Posterior means and 95% CrI    

IgM ELISA Spike:    

```{r}

dens = density(posterior.peak.titer.times.IgM.ELISA.Spike)
hpd.post.diffs = HDInterval::hdi(dens,credMass = 0.95,allowSplit=F)  
lowerlim = hpd.post.diffs[1]
upperlim = hpd.post.diffs[2]

print(paste0("Mean = ",round(mean(posterior.peak.titer.times.IgM.ELISA.Spike),3)))
print(paste0("95% CrI = ",round(lowerlim,3)," to ",round(upperlim,3)))


```


IgM ELISA NP:    

```{r}

dens = density(posterior.peak.titer.times.IgM.ELISA.NP)
hpd.post.diffs = HDInterval::hdi(dens,credMass = 0.95,allowSplit=F)  
lowerlim = hpd.post.diffs[1]
upperlim = hpd.post.diffs[2]

print(paste0("Mean = ",round(mean(posterior.peak.titer.times.IgM.ELISA.NP),3)))
print(paste0("95% CrI = ",round(lowerlim,3)," to ",round(upperlim,3)))


```

IgM MCLIA:    

```{r}

dens = density(posterior.peak.titer.times.IgM.MCLIA)
hpd.post.diffs = HDInterval::hdi(dens,credMass = 0.95,allowSplit=F)  
lowerlim = hpd.post.diffs[1]
upperlim = hpd.post.diffs[2]

print(paste0("Mean = ",round(mean(posterior.peak.titer.times.IgM.MCLIA),3)))
print(paste0("95% CrI = ",round(lowerlim,3)," to ",round(upperlim,3)))


```

```{r fig.height=4,fig.width=5}




peak.titer.time.all.IgM.ELISA.Spike$marker = "IgM ELISA Spike"
peak.titer.time.all.IgM.ELISA.NP$marker = "IgM ELISA NP"
peak.titer.time.all.IgM.MCLIA$marker = "IgM MCLIA"

means_and_se = rbind(mean_se(peak.titer.time.all.IgM.ELISA.Spike$peak.titer.time),
                     mean_se(peak.titer.time.all.IgM.ELISA.NP$peak.titer.time),
                     mean_se(peak.titer.time.all.IgM.MCLIA$peak.titer.time))

colnames(means_and_se)[1] = c("peak.titer.time")
means_and_se$marker = c("IgM ELISA Spike","IgM ELISA NP","IgM MCLIA")


means_and_se.peak.titer.igm = means_and_se

peak.titer.time.igm.df = rbind(peak.titer.time.all.IgM.ELISA.Spike,peak.titer.time.all.IgM.ELISA.NP,peak.titer.time.all.IgM.MCLIA)



cols = c("IgM ELISA Spike" = col.elisa, "IgM ELISA NP" = col.igm,"IgM MCLIA" = col.mclia)



#t.test(peak.titer.time.all.IgM.ELISA.Spike$peak.titer.time,peak.titer.time.all.IgM.ELISA.NP$peak.titer.time)


ggplot(data = peak.titer.time.igm.df,aes(x=marker, y = peak.titer.time,col=marker)) +
       geom_point(data = means_and_se, aes(x = marker, y = peak.titer.time),col="red",shape=19,size=3,alpha=0.5) +
       geom_errorbar(data = means_and_se, aes(ymin = ymin, ymax = ymax),width = 0.1,col="red",alpha=0.5) +
       geom_jitter(width=0.1) +
       #scale_x_continuous(breaks = seq(0,(max(boot.samples.df.tp7$boot.samples)+2),5),limits=c(0,max(boot.samples.df.tp7$boot.samples+2))) +
       ylab("Peak titer time") +
       scale_color_manual(values = cols) +
       xlab("") +
       ggtitle("") +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size  = 12),text = element_text(size = 12),axis.text = element_text(size = 12),axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),axis.ticks.x = element_blank(),axis.text.x = element_blank(),legend.title = element_blank(),panel.background  =  element_rect(fill  =  'white'))


```




#### Pairwise differences     


IgM ELISA Spike vs IgM ELISA NP    

```{r fig.height = 3, fig.width = 3}

post.diffs = data.frame(diffs = posterior.peak.titer.times.IgM.ELISA.Spike - posterior.peak.titer.times.IgM.ELISA.NP)

dens = density(post.diffs$diffs)
hpd.post.diffs = HDInterval::hdi(dens,credMass = 0.95,allowSplit=F)  
lowerlim = hpd.post.diffs[1]
upperlim = hpd.post.diffs[2]

print(paste0("Mean = ",round(mean(post.diffs$diffs),3)))
print(paste0("95% CrI = ",round(lowerlim,3)," to ",round(upperlim,3)))

ggplot(data = post.diffs, aes(x = diffs)) +
       geom_histogram(aes(y  =  ..density..),binwidth  =  1, fill  =  col.igm, color  =  col.igm,alpha=0.5) +
       #scale_x_continuous(breaks = seq(0,(max(boot.samples.df$boot.samples)+2),5),limits=c(0,max(boot.samples.df$boot.samples+2))) +
       ggtitle("Peak titer time difference between means") +
       xlab("Difference between means (days)") +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size = 12),
             text = element_text(size = 12),
             axis.text = element_text(size = 12),
             axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),
             legend.position  =  "none",
             panel.background  =  element_rect(fill  =  'white'))
```


IgM ELISA Spike vs IgM MCLIA    

```{r fig.height = 3, fig.width = 3}

post.diffs = data.frame(diffs = posterior.peak.titer.times.IgM.ELISA.Spike - posterior.peak.titer.times.IgM.MCLIA)

dens = density(post.diffs$diffs)
hpd.post.diffs = HDInterval::hdi(dens,credMass = 0.95,allowSplit=F)  
lowerlim = hpd.post.diffs[1]
upperlim = hpd.post.diffs[2]

print(paste0("Mean = ",round(mean(post.diffs$diffs),3)))
print(paste0("95% CrI = ",round(lowerlim,3)," to ",round(upperlim,3)))

ggplot(data = post.diffs, aes(x = diffs)) +
       geom_histogram(aes(y  =  ..density..),binwidth  =  1, fill  =  col.igm, color  =  col.igm,alpha=0.5) +
       #scale_x_continuous(breaks = seq(0,(max(boot.samples.df$boot.samples)+2),5),limits=c(0,max(boot.samples.df$boot.samples+2))) +
       ggtitle("Peak titer time difference between means") +
       xlab("Difference between means (days)") +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size = 12),
             text = element_text(size = 12),
             axis.text = element_text(size = 12),
             axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),
             legend.position  =  "none",
             panel.background  =  element_rect(fill  =  'white'))
```



IgM ELISA NP vs IgM MCLIA    

```{r fig.height = 3, fig.width = 3}

post.diffs = data.frame(diffs = posterior.peak.titer.times.IgM.ELISA.NP - posterior.peak.titer.times.IgM.MCLIA)

dens = density(post.diffs$diffs)
hpd.post.diffs = HDInterval::hdi(dens,credMass = 0.95,allowSplit=F)  
lowerlim = hpd.post.diffs[1]
upperlim = hpd.post.diffs[2]

print(paste0("Mean = ",round(mean(post.diffs$diffs),3)))
print(paste0("95% CrI = ",round(lowerlim,3)," to ",round(upperlim,3)))

ggplot(data = post.diffs, aes(x = diffs)) +
       geom_histogram(aes(y  =  ..density..),binwidth  =  1, fill  =  col.igm, color  =  col.igm,alpha=0.5) +
       #scale_x_continuous(breaks = seq(0,(max(boot.samples.df$boot.samples)+2),5),limits=c(0,max(boot.samples.df$boot.samples+2))) +
       ggtitle("Peak titer time difference between means") +
       xlab("Difference between means (days)") +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size = 12),
             text = element_text(size = 12),
             axis.text = element_text(size = 12),
             axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),
             legend.position  =  "none",
             panel.background  =  element_rect(fill  =  'white'))
```





### Disease severity - Mild/Moderate       

Marker = IgM       
Assay = ELISA      
Antigen = Spike         
Disease severity = Mild/Moderate          
Minimum number of datapoints per individual = 3    



```{r results='hide',fig.width=11,fig.height=4}


d2 = d0 [ which(d0$marker=="IgM" & !is.na(d0$test.result) & d0$assay == "ELISA" & d0$time.estimate.cat == "Exact" & d0$time.cat == "Symptom onset" & d0$severity == "Mild_Moderate" & d0$antigen == "Spike"),]





# only keep individuals that have at least one positive sample
posnegcount = as.data.frame(xtabs(~ id + test.pos.neg,d2))
id.keep = droplevels(posnegcount$id[which(posnegcount$test.pos.neg == "POS" & posnegcount$Freq>1)])
d2 = d2 [ which(d2$id %in% id.keep),]



# only keep individuals that have at least 2 samples in total
id.keep = droplevels(as.data.frame(table(d2$id))$Var1[which(as.data.frame(table(d2$id))$Freq > 2)])
d2 = d2 [ which(d2$id %in% id.keep),]
N.inds = length(unique(d2$id))
N.inds

N.inds.IgM.mild = N.inds

for(i in 1:length(unique(paste0(d2$study,d2$units)))){
       
       d2$test.result[which(paste0(d2$study,d2$units) == unique(paste0(d2$study,d2$units))[i])] = d2$test.result[which(paste0(d2$study,d2$units) == unique(paste0(d2$study,d2$units))[i])]/max(d2$test.result[which(paste0(d2$study,d2$units) == unique(paste0(d2$study,d2$units))[i])])
}



# remove individual because titers are already very high at day 0, indicating that its time estimate is more wrong than that of the rest of the individuals

d2 = d2[-which(d2$id == "Zhao_Case 18530189"),]

# check for outliers
ggplot() +
       geom_point(data=d2,aes(x = time.start, y = test.result,col=id,group=id),size = 1.5) +
       geom_line(data=d2,aes(x = time.start, y = test.result,col=id,group=id),size=0.7) +
       #scale_x_continuous(breaks = seq(0,max(d2$time.start),2)) +
       scale_y_continuous(limits=c(0,1)) +
       #scale_color_gradientn(colors  =  rev(brewer.pal(11,"Spectral"))) +
       # scale_color_brewer(palette = "Spectral", name = "Marker/Assay") +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size  = 12),text = element_text(size = 12),axis.text = element_text(size = 12),axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),legend.text = element_text(size=9),panel.background  =  element_rect(fill  =  'white')) +
       xlab("Days post symptom onset") +
       ylab("Antibody level")





# run MCMC or load previous data? 
run.mcmc.again = F

if(run.mcmc.again == T){
       model.jags = jags.model(model.file,
                               data=list('titer'=d2$test.result,
                                         'time'=d2$time.start,
                                         'id'=as.numeric(as.factor(d2$id)),
                                         'N.id'=length(unique(d2$id))
                               ),
                               #inits=list('peak.titer.sd.hyper'=0.5),
                               n.chains=6,
                               n.adapt = 1000)
       
       
       # burn in
       burn.in = 20000
       update(model.jags, n.iter = burn.in, by = 1)
       
       
       # draw samples
       iterations = 50000
       post = coda.samples(model.jags, c("peak.titer.mean.hyper","peak.titer.sd.hyper","peak.titer","displacement.mean.hyper","displacement.sd.hyper","displacement","growth.rate.mean.hyper","growth.rate"), n.iter = iterations, thin = 1)
       
       
       post.df = mcmclist.to.dataframe(post)
       
       saveRDS(post,file = paste0("MCMC_output/MCMC_output_post_",format(Sys.time(),"%Y%m%d_%H%M%S"),".RDS"))
       
       saveRDS(post.df,file = paste0("MCMC_output/MCMC_output_postdf_",format(Sys.time(),"%Y%m%d_%H%M%S"),".RDS"))
       
} else { 
       
       # enter the corresponding mcmc filenames here, as saved in the saveRDS lines above
       # example: post = readRDS("MCMC_output/MCMC_output_post_20200804_163314.RDS")
       post = readRDS("MCMC_output/")
       post.df = readRDS("MCMC_output/")
}



N.inds = length(unique(d2$id))


```

#### Gelman-Rubin convergence diagnostics:    

```{r}
gelman.diag(post)
```


#### Posterior growth rate:     


```{r fig.height = 3, fig.width=4}


plot.MCMC.posterior(input.data = post.df,column.to.plot = which(names(post.df)=="growth.rate.mean.hyper"),x.axis.label = "Growth rate (1/days)",title = "Posterior growth rate")

plot.MCMC.chains(input.data = post.df,column.to.plot = which(names(post.df)=="growth.rate.mean.hyper"),y.axis.label = "Growth rate (1/days)",title = "Posterior growth rate",thinning = 5) 


growth.rate.overall.mean = mean(post.df$growth.rate.mean.hyper)

```


#### Posterior peak titer overall mean:    


```{r fig.height = 3, fig.width=4}
plot.MCMC.posterior(input.data = post.df,column.to.plot = which(colnames(post.df)=="peak.titer.mean.hyper"),x.axis.label = "Peak titer mean",title = "Posterior peak titer mean")

plot.MCMC.chains(input.data = post.df,column.to.plot = which(colnames(post.df)=="peak.titer.mean.hyper"),y.axis.label = "Peak titer mean",title = "Posterior peak titer mean",thinning = 5) 

peak.titer.overall.mean = mean(post.df$peak.titer.mean.hyper)


```




#### Posterior displacement overall mean:      


```{r fig.height = 3, fig.width=4}
plot.MCMC.posterior(input.data = post.df,column.to.plot = which(names(post.df)=="displacement.mean.hyper"),x.axis.label = "Displacement mean",title = "Posterior displacement mean")

plot.MCMC.chains(input.data = post.df,column.to.plot = which(names(post.df)=="displacement.mean.hyper"),y.axis.label = "Displacement mean",title = "Posterior displacement mean",thinning = 5) 

displacement.overall.mean = mean(post.df$displacement.mean.hyper)
```



```{r}
# calculate posterior means

peak.titer.individual.means = as.data.frame(apply(post.df[,(4+N.inds+N.inds):(3+N.inds+N.inds+N.inds)],MARGIN = 2,mean))


displacement.individual.means = as.data.frame(apply(post.df[,(1:N.inds)],MARGIN = 2,mean))


growth.rate.individual.means = as.data.frame(apply(post.df[,(3+N.inds):(2+N.inds+N.inds)],MARGIN = 2,mean))

growth.rate.all.IgM.ELISA.Spike.mild = growth.rate.individual.means

peak.titer.overall.mean.IgM.ELISA.Spike.mild = peak.titer.overall.mean
displacement.overall.mean.IgM.ELISA.Spike.mild = displacement.overall.mean
growth.rate.overall.mean.IgM.ELISA.Spike.mild = growth.rate.overall.mean



```




#### Fitted function using mean posterior estimates       


```{r warning=FALSE, fig.width = 6, fig.height = 4}
plot.times = 0:max(d2$time.start)


observed.data = d2
observed.data$predicted = NA
uid = unique(observed.data$id)
for(i in 1:length(uid)){
       
       observed.data$predicted[which(observed.data$id == uid[i])] = titer.gompertz.fun(times = observed.data$time.start[which(observed.data$id == uid[i])], peak.titer = peak.titer.individual.means[i,1], displacement = displacement.individual.means[i,1], growth.rate = growth.rate.individual.means[i,1])
       
}


fit.dat = data.frame(titer = titer.gompertz.fun(times = plot.times, peak.titer = peak.titer.overall.mean, displacement = displacement.overall.mean, growth.rate = growth.rate.overall.mean), time = plot.times)

fit.dat.mean = fit.dat


observed.data$id = as.factor(observed.data$id)


plot1 = ggplot() +
       geom_point(data=observed.data,aes(x = time.start, y = test.result,col=as.numeric(id),group=id),size = 1.5) +
       geom_line(data=observed.data,aes(x = time.start, y = test.result,col=as.numeric(id),group=id),size=0.7) +
       geom_line(data=fit.dat,aes(x = time, y = titer),col="black",size=1.4,linetype="dashed") +
       #scale_x_continuous(breaks = seq(0,max(d2$time.start),2)) +
       scale_y_continuous(limits=c(0,1)) +
       scale_color_gradientn(colors  =  rev(brewer.pal(11,"Spectral"))) +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size  = 12),text = element_text(size = 12),axis.text = element_text(size = 12),axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),legend.position  =  "none",panel.background  =  element_rect(fill  =  'white')) +
       xlab("Days post symptom onset") +
       ylab("Antibody level")





```





#### Fitted functions for each individual      


```{r fig.width = 6, fig.height = 4}


fit.dat = data.frame(id = rep(uid, each = length(plot.times)), time = rep(plot.times,length(uid)), titer = NA)

for(i in 1:length(uid)){
       
       fit.dat$titer[which(fit.dat$id == uid[i])] = titer.gompertz.fun(times = plot.times, peak.titer = peak.titer.individual.means[i,1],displacement = displacement.individual.means[i,1],growth.rate = growth.rate.individual.means[i,1])
}


plot2 = ggplot() +
       geom_point(data=observed.data,aes(x = time.start, y = test.result,group=id),col="grey",size = 1.5) +
       geom_line(data=observed.data,aes(x = time.start, y = test.result,group=id),col="grey",size=0.7) +
       geom_line(data = fit.dat, aes(x = time, y = titer, col = as.numeric(id), group = id),size=1.2,alpha=0.5) +
       geom_line(data=fit.dat.mean,aes(x = time, y = titer),col="black",size=1.4,linetype="dashed") +
       #scale_x_continuous(breaks = seq(0,max(d2$time.start),2)) +
       scale_color_gradientn(colors  =  rev(brewer.pal(11,"Spectral"))) +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size  = 10),text = element_text(size = 12),axis.text = element_text(size = 12),axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),legend.position  =  "none",panel.background  =  element_rect(fill  =  'white')) +
       xlab("Days post symptom onset") +
       ylab("Antibody level")



```


```{r fig.height = 4, fig.width=8}

plot1 + plot2
```


#### Peak titer timing mean     



```{r}
peak.titer.time.mean.IgM.mild = get.peak.titer.time(titers = fit.dat.mean$titer, days = fit.dat.mean$time)

peak.titer.time.mean.IgM.mild
```


#### Peak titer timing all     

```{r}


peak.titer.times = data.frame(id = unique(fit.dat$id), peak.titer.time = NA)

for(i in 1:length(unique(fit.dat$id))){
       peak.titer.times$peak.titer.time[i] = get.peak.titer.time(titers = fit.dat$titer[which(fit.dat$id == unique(fit.dat$id)[i])], days = fit.dat$time[which(fit.dat$id == unique(fit.dat$id)[i])])
}

peak.titer.times
mean_se(peak.titer.times$peak.titer.time)
peak.titer.time.all.IgM.mild = peak.titer.times
```




#### Fitted function with additional functions drawn from credible interval       


```{r warning=FALSE, fig.width = 4, fig.height = 3}




# get more posterior samples from within credible interval, for variation plotting
# use growth rate as main variable to focus on
dens = density(post.df[,"growth.rate.mean.hyper"])
hpd.int.toi = HDInterval::hdi(dens,credMass = 0.95,allowSplit=F)  
lowerlim = hpd.int.toi[1]
upperlim = hpd.int.toi[2]

lowerlim.igm.elisa.spike.mild = lowerlim
upperlim.igm.elisa.spike.mild = upperlim

# randomly sample 100 rows that have a growth rate within the credible interval
ransamp = sample(which(post.df$growth.rate.mean.hyper > lowerlim & post.df$growth.rate.mean.hyper < upperlim),100)

ransamp.df = data.frame(growth.rate = post.df$growth.rate.mean.hyper[ransamp], peak.titer = post.df$peak.titer.mean.hyper[ransamp], displacement = post.df$displacement.mean.hyper[ransamp])


plot.times = 0:max(d2$time.start)


fit.dat = as.data.frame(apply(ransamp.df,1,fit.titers.fun.2))
fit.dat$time = plot.times

fit.dat = reshape2::melt(fit.dat,id.vars="time")

fit.dat.2 = as.data.frame(apply(ransamp.df,1,fit.titers.fun))
fit.dat.2$time = plot.times

fit.dat.2 = reshape2::melt(fit.dat.2,id.vars="time")
fit.dat.IgM.ELISA.spike.mild = fit.dat.2

main.fit.fun = data.frame(titer = titer.gompertz.fun(times = plot.times, peak.titer = peak.titer.overall.mean, displacement = displacement.overall.mean, growth.rate = growth.rate.overall.mean), time = plot.times)




ggplot() +
       geom_line(data=fit.dat,aes(x = time, y = value,group=variable),col="#D53E4F",size=0.7,alpha=0.1) +
       geom_line(data=main.fit.fun,aes(x = time, y = titer),col="#D53E4F",size=1.6) +
       #scale_x_continuous(breaks = seq(0,max(d2$time.start),2)) +
       #scale_y_continuous(limits=c(0,1)) +
       #scale_color_gradientn(colors  =  rev(brewer.pal(11,"Spectral"))) +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size  = 12),text = element_text(size = 12),axis.text = element_text(size = 12),axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),legend.position  =  "none",panel.background  =  element_rect(fill  =  'white')) +
       xlab("Days post symptom onset") +
       ylab("Antibody level")





```


```{r}

# store posterior growth rates and posterior peak titer times

posterior.growth.rates.IgM.mild = post.df$growth.rate.mean.hyper[which(post.df$iteration %in% 61000:71000)]


posterior.peak.titer.times.IgM.mild = apply(post.df[61000:71000,c("displacement.mean.hyper","growth.rate.mean.hyper")],1,get.posterior.peak.titer.times)



```
<br>

***

<br>   










### Disease severity - Severe/Critical       

Marker = IgM       
Assay = ELISA      
Antigen = Spike         
Disease severity = Severe/Critical        
Minimum number of datapoints per individual = 3    



```{r results='hide',fig.width=11,fig.height=4}


d2 = d0 [ which(d0$marker=="IgM" & !is.na(d0$test.result) & d0$assay == "ELISA" & d0$time.estimate.cat == "Exact" & d0$time.cat == "Symptom onset" & d0$severity == "Severe_Critical" & d0$antigen == "Spike"),]





# only keep individuals that have at least one positive sample
posnegcount = as.data.frame(xtabs(~ id + test.pos.neg,d2))
id.keep = droplevels(posnegcount$id[which(posnegcount$test.pos.neg == "POS" & posnegcount$Freq>1)])
d2 = d2 [ which(d2$id %in% id.keep),]



# only keep individuals that have at least 2 samples in total
id.keep = droplevels(as.data.frame(table(d2$id))$Var1[which(as.data.frame(table(d2$id))$Freq > 2)])
d2 = d2 [ which(d2$id %in% id.keep),]
N.inds = length(unique(d2$id))
N.inds

N.inds.IgM.severe = N.inds

for(i in 1:length(unique(paste0(d2$study,d2$units)))){
       
       d2$test.result[which(paste0(d2$study,d2$units) == unique(paste0(d2$study,d2$units))[i])] = d2$test.result[which(paste0(d2$study,d2$units) == unique(paste0(d2$study,d2$units))[i])]/max(d2$test.result[which(paste0(d2$study,d2$units) == unique(paste0(d2$study,d2$units))[i])])
}




# removed case with very high titer at day 0, much more likely to have been infected while ago
d2 = d2[-which(d2$id == "Zhao_Case 1430189"),]


# check for outliers
ggplot() +
       geom_point(data=d2,aes(x = time.start, y = test.result,col=id,group=id),size = 1.5) +
       geom_line(data=d2,aes(x = time.start, y = test.result,col=id,group=id),size=0.7) +
       #scale_x_continuous(breaks = seq(0,max(d2$time.start),2)) +
       scale_y_continuous(limits=c(0,1)) +
       #scale_color_gradientn(colors  =  rev(brewer.pal(11,"Spectral"))) +
       # scale_color_brewer(palette = "Spectral", name = "Marker/Assay") +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size  = 12),text = element_text(size = 12),axis.text = element_text(size = 12),axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),legend.text = element_text(size=9),panel.background  =  element_rect(fill  =  'white')) +
       xlab("Days post symptom onset") +
       ylab("Antibody level")



# run MCMC or load previous data? 
run.mcmc.again = F

if(run.mcmc.again == T){
       model.jags = jags.model(model.file,
                               data=list('titer'=d2$test.result,
                                         'time'=d2$time.start,
                                         'id'=as.numeric(as.factor(d2$id)),
                                         'N.id'=length(unique(d2$id))
                               ),
                               #inits=list('peak.titer.sd.hyper'=0.5),
                               n.chains=6,
                               n.adapt = 1000)
       
       
       # burn in
       burn.in = 20000
       update(model.jags, n.iter = burn.in, by = 1)
       
       
       # draw samples
       iterations = 50000
       post = coda.samples(model.jags, c("peak.titer.mean.hyper","peak.titer.sd.hyper","peak.titer","displacement.mean.hyper","displacement.sd.hyper","displacement","growth.rate.mean.hyper","growth.rate"), n.iter = iterations, thin = 1)
       
       
       post.df = mcmclist.to.dataframe(post)
       
       saveRDS(post,file = paste0("MCMC_output/MCMC_output_post_",format(Sys.time(),"%Y%m%d_%H%M%S"),".RDS"))
       
       saveRDS(post.df,file = paste0("MCMC_output/MCMC_output_postdf_",format(Sys.time(),"%Y%m%d_%H%M%S"),".RDS"))
       
} else { 
       
       # enter the corresponding mcmc filenames here, as saved in the saveRDS lines above
       # example: post = readRDS("MCMC_output/MCMC_output_post_20200804_163314.RDS")
       post = readRDS("MCMC_output/")
       post.df = readRDS("MCMC_output/")
}



N.inds = length(unique(d2$id))


```

#### Gelman-Rubin convergence diagnostics:    

```{r}
gelman.diag(post)
```


#### Posterior growth rate:     


```{r fig.height = 3, fig.width=4}


plot.MCMC.posterior(input.data = post.df,column.to.plot = which(names(post.df)=="growth.rate.mean.hyper"),x.axis.label = "Growth rate (1/days)",title = "Posterior growth rate")

plot.MCMC.chains(input.data = post.df,column.to.plot = which(names(post.df)=="growth.rate.mean.hyper"),y.axis.label = "Growth rate (1/days)",title = "Posterior growth rate",thinning = 5) 


growth.rate.overall.mean = mean(post.df$growth.rate.mean.hyper)

```


#### Posterior peak titer overall mean:    


```{r fig.height = 3, fig.width=4}
plot.MCMC.posterior(input.data = post.df,column.to.plot = which(colnames(post.df)=="peak.titer.mean.hyper"),x.axis.label = "Peak titer mean",title = "Posterior peak titer mean")

plot.MCMC.chains(input.data = post.df,column.to.plot = which(colnames(post.df)=="peak.titer.mean.hyper"),y.axis.label = "Peak titer mean",title = "Posterior peak titer mean",thinning = 5) 

peak.titer.overall.mean = mean(post.df$peak.titer.mean.hyper)


```




#### Posterior displacement overall mean:      


```{r fig.height = 3, fig.width=4}
plot.MCMC.posterior(input.data = post.df,column.to.plot = which(names(post.df)=="displacement.mean.hyper"),x.axis.label = "Displacement mean",title = "Posterior displacement mean")

plot.MCMC.chains(input.data = post.df,column.to.plot = which(names(post.df)=="displacement.mean.hyper"),y.axis.label = "Displacement mean",title = "Posterior displacement mean",thinning = 5) 

displacement.overall.mean = mean(post.df$displacement.mean.hyper)
```



```{r}
# calculate posterior means

peak.titer.individual.means = as.data.frame(apply(post.df[,(4+N.inds+N.inds):(3+N.inds+N.inds+N.inds)],MARGIN = 2,mean))


displacement.individual.means = as.data.frame(apply(post.df[,(1:N.inds)],MARGIN = 2,mean))


growth.rate.individual.means = as.data.frame(apply(post.df[,(3+N.inds):(2+N.inds+N.inds)],MARGIN = 2,mean))

growth.rate.all.IgM.ELISA.Spike.severe = growth.rate.individual.means

peak.titer.overall.mean.IgM.ELISA.Spike.severe = peak.titer.overall.mean
displacement.overall.mean.IgM.ELISA.Spike.severe = displacement.overall.mean
growth.rate.overall.mean.IgM.ELISA.Spike.severe = growth.rate.overall.mean



```



#### Fitted function using mean posterior estimates       


```{r warning=FALSE, fig.width = 6, fig.height = 4}
plot.times = 0:max(d2$time.start)


observed.data = d2
observed.data$predicted = NA
uid = unique(observed.data$id)
for(i in 1:length(uid)){
       
       observed.data$predicted[which(observed.data$id == uid[i])] = titer.gompertz.fun(times = observed.data$time.start[which(observed.data$id == uid[i])], peak.titer = peak.titer.individual.means[i,1], displacement = displacement.individual.means[i,1], growth.rate = growth.rate.individual.means[i,1])
       
}


fit.dat = data.frame(titer = titer.gompertz.fun(times = plot.times, peak.titer = peak.titer.overall.mean, displacement = displacement.overall.mean, growth.rate = growth.rate.overall.mean), time = plot.times)

fit.dat.mean = fit.dat


observed.data$id = as.factor(observed.data$id)


plot1 = ggplot() +
       geom_point(data=observed.data,aes(x = time.start, y = test.result,col=as.numeric(id),group=id),size = 1.5) +
       geom_line(data=observed.data,aes(x = time.start, y = test.result,col=as.numeric(id),group=id),size=0.7) +
       geom_line(data=fit.dat,aes(x = time, y = titer),col="black",size=1.4,linetype="dashed") +
       #scale_x_continuous(breaks = seq(0,max(d2$time.start),2)) +
       scale_y_continuous(limits=c(0,1)) +
       scale_color_gradientn(colors  =  rev(brewer.pal(11,"Spectral"))) +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size  = 12),text = element_text(size = 12),axis.text = element_text(size = 12),axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),legend.position  =  "none",panel.background  =  element_rect(fill  =  'white')) +
       xlab("Days post symptom onset") +
       ylab("Antibody level")





```





#### Fitted functions for each individual      


```{r fig.width = 6, fig.height = 4}


fit.dat = data.frame(id = rep(uid, each = length(plot.times)), time = rep(plot.times,length(uid)), titer = NA)

for(i in 1:length(uid)){
       
       fit.dat$titer[which(fit.dat$id == uid[i])] = titer.gompertz.fun(times = plot.times, peak.titer = peak.titer.individual.means[i,1],displacement = displacement.individual.means[i,1],growth.rate = growth.rate.individual.means[i,1])
}


plot2 = ggplot() +
       geom_point(data=observed.data,aes(x = time.start, y = test.result,group=id),col="grey",size = 1.5) +
       geom_line(data=observed.data,aes(x = time.start, y = test.result,group=id),col="grey",size=0.7) +
       geom_line(data = fit.dat, aes(x = time, y = titer, col = as.numeric(id), group = id),size=1.2,alpha=0.5) +
       geom_line(data=fit.dat.mean,aes(x = time, y = titer),col="black",size=1.4,linetype="dashed") +
       #scale_x_continuous(breaks = seq(0,max(d2$time.start),2)) +
       scale_color_gradientn(colors  =  rev(brewer.pal(11,"Spectral"))) +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size  = 10),text = element_text(size = 12),axis.text = element_text(size = 12),axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),legend.position  =  "none",panel.background  =  element_rect(fill  =  'white')) +
       xlab("Days post symptom onset") +
       ylab("Antibody level")



```


```{r fig.height = 4, fig.width=8}

plot1 + plot2
```


#### Peak titer timing mean     



```{r}
peak.titer.time.mean.IgM.severe = get.peak.titer.time(titers = fit.dat.mean$titer, days = fit.dat.mean$time)

peak.titer.time.mean.IgM.severe
```


#### Peak titer timing all     

```{r}


peak.titer.times = data.frame(id = unique(fit.dat$id), peak.titer.time = NA)

for(i in 1:length(unique(fit.dat$id))){
       peak.titer.times$peak.titer.time[i] = get.peak.titer.time(titers = fit.dat$titer[which(fit.dat$id == unique(fit.dat$id)[i])], days = fit.dat$time[which(fit.dat$id == unique(fit.dat$id)[i])])
}

peak.titer.times
mean_se(peak.titer.times$peak.titer.time)
peak.titer.time.all.IgM.severe = peak.titer.times
```




#### Fitted function with additional functions drawn from credible interval       


```{r warning=FALSE, fig.width = 4, fig.height = 3}




# get more posterior samples from within credible interval, for variation plotting
# use growth rate as main variable to focus on
dens = density(post.df[,"growth.rate.mean.hyper"])
hpd.int.toi = HDInterval::hdi(dens,credMass = 0.95,allowSplit=F)  
lowerlim = hpd.int.toi[1]
upperlim = hpd.int.toi[2]

lowerlim.igm.elisa.spike.severe = lowerlim
upperlim.igm.elisa.spike.severe = upperlim

# randomly sample 100 rows that have a growth rate within the credible interval
ransamp = sample(which(post.df$growth.rate.mean.hyper > lowerlim & post.df$growth.rate.mean.hyper < upperlim),100)

ransamp.df = data.frame(growth.rate = post.df$growth.rate.mean.hyper[ransamp], peak.titer = post.df$peak.titer.mean.hyper[ransamp], displacement = post.df$displacement.mean.hyper[ransamp])


plot.times = 0:max(d2$time.start)


fit.dat = as.data.frame(apply(ransamp.df,1,fit.titers.fun.2))
fit.dat$time = plot.times

fit.dat = reshape2::melt(fit.dat,id.vars="time")

fit.dat.2 = as.data.frame(apply(ransamp.df,1,fit.titers.fun))
fit.dat.2$time = plot.times

fit.dat.2 = reshape2::melt(fit.dat.2,id.vars="time")
fit.dat.IgM.ELISA.spike.severe = fit.dat.2

main.fit.fun = data.frame(titer = titer.gompertz.fun(times = plot.times, peak.titer = peak.titer.overall.mean, displacement = displacement.overall.mean, growth.rate = growth.rate.overall.mean), time = plot.times)




ggplot() +
       geom_line(data=fit.dat,aes(x = time, y = value,group=variable),col="#D53E4F",size=0.7,alpha=0.1) +
       geom_line(data=main.fit.fun,aes(x = time, y = titer),col="#D53E4F",size=1.6) +
       #scale_x_continuous(breaks = seq(0,max(d2$time.start),2)) +
       #scale_y_continuous(limits=c(0,1)) +
       #scale_color_gradientn(colors  =  rev(brewer.pal(11,"Spectral"))) +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size  = 12),text = element_text(size = 12),axis.text = element_text(size = 12),axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),legend.position  =  "none",panel.background  =  element_rect(fill  =  'white')) +
       xlab("Days post symptom onset") +
       ylab("Antibody level")





```


```{r}

# store posterior growth rates and posterior peak titer times

posterior.growth.rates.IgM.severe = post.df$growth.rate.mean.hyper[which(post.df$iteration %in% 61000:71000)]


posterior.peak.titer.times.IgM.severe = apply(post.df[61000:71000,c("displacement.mean.hyper","growth.rate.mean.hyper")],1,get.posterior.peak.titer.times)



```
<br>

***

<br>   












### Disease severity - combined       

Marker = IgM       
Assay = ELISA      
Antigen = Spike         
Disease severity = any      
Minimum number of datapoints per individual = 3    



```{r results='hide',fig.width=11,fig.height=4}


d2 = d0 [ which(d0$marker=="IgM" & !is.na(d0$test.result) & d0$assay == "ELISA" & d0$time.estimate.cat == "Exact" & d0$time.cat == "Symptom onset" & !is.na(d0$severity) & d0$antigen == "Spike"),]





# only keep individuals that have at least one positive sample
posnegcount = as.data.frame(xtabs(~ id + test.pos.neg,d2))
id.keep = droplevels(posnegcount$id[which(posnegcount$test.pos.neg == "POS" & posnegcount$Freq>1)])
d2 = d2 [ which(d2$id %in% id.keep),]



# only keep individuals that have at least 2 samples in total
id.keep = droplevels(as.data.frame(table(d2$id))$Var1[which(as.data.frame(table(d2$id))$Freq > 2)])
d2 = d2 [ which(d2$id %in% id.keep),]
N.inds = length(unique(d2$id))
N.inds

for(i in 1:length(unique(paste0(d2$study,d2$units)))){
       
       d2$test.result[which(paste0(d2$study,d2$units) == unique(paste0(d2$study,d2$units))[i])] = d2$test.result[which(paste0(d2$study,d2$units) == unique(paste0(d2$study,d2$units))[i])]/max(d2$test.result[which(paste0(d2$study,d2$units) == unique(paste0(d2$study,d2$units))[i])])
}




d2 = d2[-which(d2$id == "Zhao_Case 18530189"),]


# check for outliers
ggplot() +
       geom_point(data=d2,aes(x = time.start, y = test.result,col=id,group=id),size = 1.5) +
       geom_line(data=d2,aes(x = time.start, y = test.result,col=id,group=id),size=0.7) +
       #scale_x_continuous(breaks = seq(0,max(d2$time.start),2)) +
       scale_y_continuous(limits=c(0,1)) +
       #scale_color_gradientn(colors  =  rev(brewer.pal(11,"Spectral"))) +
       # scale_color_brewer(palette = "Spectral", name = "Marker/Assay") +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size  = 12),text = element_text(size = 12),axis.text = element_text(size = 12),axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),legend.text = element_text(size=9),panel.background  =  element_rect(fill  =  'white')) +
       xlab("Days post symptom onset") +
       ylab("Antibody level")


id.mild = unique(d2$id[which(d2$severity == "Mild_Moderate")])
id.severe = unique(d2$id[which(d2$severity == "Severe_Critical")])


# run MCMC or load previous data? 
run.mcmc.again = F

if(run.mcmc.again == T){
       model.jags = jags.model(model.file,
                               data=list('titer'=d2$test.result,
                                         'time'=d2$time.start,
                                         'id'=as.numeric(as.factor(d2$id)),
                                         'N.id'=length(unique(d2$id))
                               ),
                               #inits=list('peak.titer.sd.hyper'=0.5),
                               n.chains=6,
                               n.adapt = 1000)
       
       
       # burn in
       burn.in = 20000
       update(model.jags, n.iter = burn.in, by = 1)
       
       
       # draw samples
       iterations = 50000
       post = coda.samples(model.jags, c("peak.titer.mean.hyper","peak.titer.sd.hyper","peak.titer","displacement.mean.hyper","displacement.sd.hyper","displacement","growth.rate.mean.hyper","growth.rate"), n.iter = iterations, thin = 1)
       
       
       post.df = mcmclist.to.dataframe(post)
       
       saveRDS(post,file = paste0("MCMC_output/MCMC_output_post_",format(Sys.time(),"%Y%m%d_%H%M%S"),".RDS"))
       
       saveRDS(post.df,file = paste0("MCMC_output/MCMC_output_postdf_",format(Sys.time(),"%Y%m%d_%H%M%S"),".RDS"))
       
} else { 
       
       # enter the corresponding mcmc filenames here, as saved in the saveRDS lines above
       # example: post = readRDS("MCMC_output/MCMC_output_post_20200804_163314.RDS")
       post = readRDS("MCMC_output/")
       post.df = readRDS("MCMC_output/")
}



N.inds = length(unique(d2$id))


```

#### Gelman-Rubin convergence diagnostics:    

```{r}
gelman.diag(post)
```


#### Posterior growth rate:     


```{r fig.height = 3, fig.width=4}

plot.MCMC.posterior(input.data = post.df,column.to.plot = which(names(post.df)=="growth.rate.mean.hyper"),x.axis.label = "Growth rate (1/days)",title = "Posterior growth rate")

plot.MCMC.chains(input.data = post.df,column.to.plot = which(names(post.df)=="growth.rate.mean.hyper"),y.axis.label = "Growth rate (1/days)",title = "Posterior growth rate",thinning = 5) 


growth.rate.overall.mean = mean(post.df$growth.rate.mean.hyper)


```


#### Posterior peak titer overall mean:    


```{r fig.height = 3, fig.width=4}
plot.MCMC.posterior(input.data = post.df,column.to.plot = which(colnames(post.df)=="peak.titer.mean.hyper"),x.axis.label = "Peak titer mean",title = "Posterior peak titer mean")

plot.MCMC.chains(input.data = post.df,column.to.plot = which(colnames(post.df)=="peak.titer.mean.hyper"),y.axis.label = "Peak titer mean",title = "Posterior peak titer mean",thinning = 5) 

peak.titer.overall.mean = mean(post.df$peak.titer.mean.hyper)


```




#### Posterior displacement overall mean:      


```{r fig.height = 3, fig.width=4}
plot.MCMC.posterior(input.data = post.df,column.to.plot = which(names(post.df)=="displacement.mean.hyper"),x.axis.label = "Displacement mean",title = "Posterior displacement mean")

plot.MCMC.chains(input.data = post.df,column.to.plot = which(names(post.df)=="displacement.mean.hyper"),y.axis.label = "Displacement mean",title = "Posterior displacement mean",thinning = 5) 

displacement.overall.mean = mean(post.df$displacement.mean.hyper)
```



```{r}
# calculate posterior means

peak.titer.individual.means = as.data.frame(apply(post.df[,(4+N.inds+N.inds):(3+N.inds+N.inds+N.inds)],MARGIN = 2,mean))


displacement.individual.means = as.data.frame(apply(post.df[,(1:N.inds)],MARGIN = 2,mean))


growth.rate.individual.means = as.data.frame(apply(post.df[,(3+N.inds):(2+N.inds+N.inds)],MARGIN = 2,mean))

growth.rate.all.IgM.ELISA.Spike.mild.severe = growth.rate.individual.means


idx.mild = which(unique(d2$id) %in% id.mild)
idx.severe = which(unique(d2$id) %in% id.severe)
peak.titer.igm.mild = peak.titer.individual.means[idx.mild,1]
peak.titer.igm.severe = peak.titer.individual.means[idx.severe,1]



peak.titer.overall.mean.IgG.ELISA.Spike.mild.severe = peak.titer.overall.mean
displacement.overall.mean.IgG.ELISA.Spike.mild.severe = displacement.overall.mean
growth.rate.overall.mean.IgG.ELISA.Spike.mild.severe = growth.rate.overall.mean



```




#### Fitted function using mean posterior estimates       


```{r warning=FALSE, fig.width = 6, fig.height = 4}
plot.times = 0:max(d2$time.start)


observed.data = d2
observed.data$predicted = NA
uid = unique(observed.data$id)
for(i in 1:length(uid)){
       
       observed.data$predicted[which(observed.data$id == uid[i])] = titer.gompertz.fun(times = observed.data$time.start[which(observed.data$id == uid[i])], peak.titer = peak.titer.individual.means[i,1], displacement = displacement.individual.means[i,1], growth.rate = growth.rate.individual.means[i,1])
       
}


fit.dat = data.frame(titer = titer.gompertz.fun(times = plot.times, peak.titer = peak.titer.overall.mean, displacement = displacement.overall.mean, growth.rate = growth.rate.overall.mean), time = plot.times)


fit.dat.mean = fit.dat

observed.data$id = as.factor(observed.data$id)


plot1 = ggplot() +
       geom_point(data=observed.data,aes(x = time.start, y = test.result,col=as.numeric(id),group=id),size = 1.5) +
       geom_line(data=observed.data,aes(x = time.start, y = test.result,col=as.numeric(id),group=id),size=0.7) +
       geom_line(data=fit.dat,aes(x = time, y = titer),col="black",size=1.4,linetype="dashed") +
       #scale_x_continuous(breaks = seq(0,max(d2$time.start),2)) +
       scale_y_continuous(limits=c(0,1)) +
       scale_color_gradientn(colors  =  rev(brewer.pal(11,"Spectral"))) +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size  = 12),text = element_text(size = 12),axis.text = element_text(size = 12),axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),legend.position  =  "none",panel.background  =  element_rect(fill  =  'white')) +
       xlab("Days post symptom onset") +
       ylab("Antibody level")





```





#### Fitted functions for each individual      


```{r fig.width = 6, fig.height = 4}


fit.dat = data.frame(id = rep(uid, each = length(plot.times)), time = rep(plot.times,length(uid)), titer = NA)

for(i in 1:length(uid)){
       
       fit.dat$titer[which(fit.dat$id == uid[i])] = titer.gompertz.fun(times = plot.times, peak.titer = peak.titer.individual.means[i,1],displacement = displacement.individual.means[i,1],growth.rate = growth.rate.individual.means[i,1])
}

fit.dat.igm.disease.severity.1 = fit.dat

plot2 = ggplot() +
       geom_point(data=observed.data,aes(x = time.start, y = test.result,group=id),col="grey",size = 1.5) +
       geom_line(data=observed.data,aes(x = time.start, y = test.result,group=id),col="grey",size=0.7) +
       geom_line(data = fit.dat, aes(x = time, y = titer, col = as.numeric(id), group = id),size=1.2,alpha=0.5) +
       geom_line(data=fit.dat.mean,aes(x = time, y = titer),col="black",size=1.4,linetype="dashed") +
       #scale_x_continuous(breaks = seq(0,max(d2$time.start),2)) +
       scale_color_gradientn(colors  =  rev(brewer.pal(11,"Spectral"))) +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size  = 10),text = element_text(size = 12),axis.text = element_text(size = 12),axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),legend.position  =  "none",panel.background  =  element_rect(fill  =  'white')) +
       xlab("Days post symptom onset") +
       ylab("Antibody level")



```


```{r fig.height = 4, fig.width=8}

plot1 + plot2
```


#### Fitted function with additional functions drawn from credible interval       


```{r warning=FALSE, fig.width = 4, fig.height = 3}




# get more posterior samples from within credible interval, for variation plotting
# use growth rate as main variable to focus on
dens = density(post.df[,"growth.rate.mean.hyper"])
hpd.int.toi = HDInterval::hdi(dens,credMass = 0.95,allowSplit=F)  
lowerlim = hpd.int.toi[1]
upperlim = hpd.int.toi[2]

lowerlim.igg.elisa.np.severe = lowerlim
upperlim.igg.elisa.np.severe = upperlim

# randomly sample 100 rows that have a growth rate within the credible interval
ransamp = sample(which(post.df$growth.rate.mean.hyper > lowerlim & post.df$growth.rate.mean.hyper < upperlim),100)

ransamp.df = data.frame(growth.rate = post.df$growth.rate.mean.hyper[ransamp], peak.titer = post.df$peak.titer.mean.hyper[ransamp], displacement = post.df$displacement.mean.hyper[ransamp])


plot.times = 0:max(d2$time.start)


fit.dat = as.data.frame(apply(ransamp.df,1,fit.titers.fun.2))
fit.dat$time = plot.times

fit.dat = reshape2::melt(fit.dat,id.vars="time")


fit.dat.2 = as.data.frame(apply(ransamp.df,1,fit.titers.fun))
fit.dat.2$time = plot.times

fit.dat.2 = reshape2::melt(fit.dat.2,id.vars="time")
fit.dat.IgG.ELISA.np.severe = fit.dat.2

main.fit.fun = data.frame(titer = titer.gompertz.fun(times = plot.times, peak.titer = peak.titer.overall.mean, displacement = displacement.overall.mean, growth.rate = growth.rate.overall.mean), time = plot.times)




ggplot() +
       geom_line(data=fit.dat,aes(x = time, y = value,group=variable),col="#D53E4F",size=0.7,alpha=0.1) +
       geom_line(data=main.fit.fun,aes(x = time, y = titer),col="#D53E4F",size=1.6) +
       #scale_x_continuous(breaks = seq(0,max(d2$time.start),2)) +
       #scale_y_continuous(limits=c(0,1)) +
       #scale_color_gradientn(colors  =  rev(brewer.pal(11,"Spectral"))) +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size  = 12),text = element_text(size = 12),axis.text = element_text(size = 12),axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),legend.position  =  "none",panel.background  =  element_rect(fill  =  'white')) +
       xlab("Days post symptom onset") +
       ylab("Antibody level")





```




```{r}

# store posterior growth rates and posterior peak titer times

posterior.growth.rates.IgM.mild.severe = post.df$growth.rate.mean.hyper[which(post.df$iteration %in% 61000:71000)]


posterior.peak.titer.times.IgM.mild.severe = apply(post.df[61000:71000,c("displacement.mean.hyper","growth.rate.mean.hyper")],1,get.posterior.peak.titer.times)



```








### Combined disease severity




### Titer kinetics disease severity    


```{r warning=FALSE, fig.width = 6, fig.height = 4}

plot.times = 0:40




main.fit.fun.igm.mild = data.frame(titer = titer.gompertz.fun(times = plot.times, peak.titer = 1, displacement = displacement.overall.mean.IgM.ELISA.Spike.mild, growth.rate = growth.rate.overall.mean.IgM.ELISA.Spike.mild), time = plot.times, assay = "IgM ELISA Mild/Moderate")


main.fit.fun.igm.severe = data.frame(titer = titer.gompertz.fun(times = plot.times, peak.titer = 1, displacement = displacement.overall.mean.IgM.ELISA.Spike.severe, growth.rate = growth.rate.overall.mean.IgM.ELISA.Spike.severe), time = plot.times, assay = "IgM ELISA Severe/Critical")



main.fit.functions = rbind(main.fit.fun.igm.mild,main.fit.fun.igm.severe)

main.fit.functions = reshape2::melt(main.fit.functions, id.vars = c("time","assay"))

main.fit.function.igm.disease.severity = main.fit.functions


fit.dat.IgM.ELISA.spike.mild$assay = "IgM ELISA Mild/Moderate"
fit.dat.IgM.ELISA.spike.severe$assay = "IgM ELISA Severe/Critical"

fit.dat.all = rbind(fit.dat.IgM.ELISA.spike.mild,fit.dat.IgM.ELISA.spike.severe)
fit.dat.all$variable = paste(fit.dat.all$assay, fit.dat.all$variable)


fit.dat.all = reshape2::melt(fit.dat.all, id.vars = c("time","assay","variable"))
colnames(fit.dat.all)[4] = "var2"


fit.dat.all.igm.disease.severity = fit.dat.all






lowerlim.igm.elisa.spike.mild.out = titer.gompertz.fun(times = plot.times,peak.titer = 1, displacement = displacement.overall.mean.IgM.ELISA.Spike.mild, growth.rate = lowerlim.igm.elisa.spike.mild) 
upperlim.igm.elisa.spike.mild.out = titer.gompertz.fun(times = plot.times,peak.titer = 1, displacement = displacement.overall.mean.IgM.ELISA.Spike.mild, growth.rate = upperlim.igm.elisa.spike.mild) 

lowerlim.igm.elisa.spike.severe.out = titer.gompertz.fun(times = plot.times,peak.titer = 1, displacement = displacement.overall.mean.IgM.ELISA.Spike.severe, growth.rate = lowerlim.igm.elisa.spike.severe) 
upperlim.igm.elisa.spike.severe.out = titer.gompertz.fun(times = plot.times,peak.titer = 1, displacement = displacement.overall.mean.IgM.ELISA.Spike.severe, growth.rate = upperlim.igm.elisa.spike.severe) 




main.fit.functions$lowerlim = NA
main.fit.functions$upperlim = NA


main.fit.functions$lowerlim [ which(main.fit.functions$assay == "IgM ELISA Mild/Moderate") ] = lowerlim.igm.elisa.spike.mild.out
main.fit.functions$upperlim [ which(main.fit.functions$assay == "IgM ELISA Mild/Moderate") ] = upperlim.igm.elisa.spike.mild.out

main.fit.functions$lowerlim [ which(main.fit.functions$assay == "IgM ELISA Severe/Critical") ] = lowerlim.igm.elisa.spike.severe.out
main.fit.functions$upperlim [ which(main.fit.functions$assay == "IgM ELISA Severe/Critical") ] = upperlim.igm.elisa.spike.severe.out



main.fit.functions.IgM.severity = main.fit.functions

ggplot(data=main.fit.functions,aes(x = time, y = value,group=assay,col=assay)) +
       #geom_line(data=fit.dat.all,aes(x = time, y = value,group = variable, col=assay),size=0.5,alpha=0.1) +
       #geom_ribbon(aes(x = plot.times,ymin = lowerlim.elisa.spike,ymax = upperlim.elisa.spike),col=col.rna,fill = col.rna,alpha=0.2) +
       geom_ribbon(aes(ymin = lowerlim,ymax = upperlim),fill = "none",linetype="dashed") +
       geom_line(size=1.8) +
       #scale_x_continuous(breaks = seq(0,max(d2$time.start),2)) +
       scale_y_continuous(limits=c(0,1)) +
       #scale_color_gradientn(colors  =  rev(brewer.pal(11,"Spectral"))) +
       # scale_color_brewer(palette = "Spectral", name = "") +
       scale_color_manual(values = c(col.mild.igm,col.severe.igm),name="") +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size  = 12),text = element_text(size = 12),axis.text = element_text(size = 12),axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),legend.position  =  c(0.82,0.3),legend.background = element_rect(fill="white"),panel.background  =  element_rect(fill  =  'white')) +
       xlab("Days post symptom onset") +
       ylab("Antibody level")




```



### Growth rate comparison disease severity



#### Posterior means and 95% CrI    

IgM mild:    

```{r}

dens = density(posterior.growth.rates.IgM.mild)
hpd.post.diffs = HDInterval::hdi(dens,credMass = 0.95,allowSplit=F)  
lowerlim = hpd.post.diffs[1]
upperlim = hpd.post.diffs[2]

print(paste0("Mean = ",round(mean(posterior.growth.rates.IgM.mild),3)))
print(paste0("95% CrI = ",round(lowerlim,3)," to ",round(upperlim,3)))


```


IgM severe:    

```{r}

dens = density(posterior.growth.rates.IgM.severe)
hpd.post.diffs = HDInterval::hdi(dens,credMass = 0.95,allowSplit=F)  
lowerlim = hpd.post.diffs[1]
upperlim = hpd.post.diffs[2]

print(paste0("Mean = ",round(mean(posterior.growth.rates.IgM.severe),3)))
print(paste0("95% CrI = ",round(lowerlim,3)," to ",round(upperlim,3)))


```


```{r fig.height=3,fig.width=5}

growth.rate.all.IgM.ELISA.Spike.mild$marker = "Mild/Moderate"
growth.rate.all.IgM.ELISA.Spike.severe$marker = "Severe/Critical"


means_and_se = rbind(mean_se(growth.rate.all.IgM.ELISA.Spike.mild[,1]),
                     mean_se(growth.rate.all.IgM.ELISA.Spike.severe[,1]))

colnames(means_and_se)[1] = c("growth.rate")
means_and_se$marker = c("Mild/Moderate","Severe/Critical")


growth.rate.igm.severity.df = rbind(growth.rate.all.IgM.ELISA.Spike.mild,growth.rate.all.IgM.ELISA.Spike.severe)
colnames(growth.rate.igm.severity.df)[1]="growth.rate"


cols = c("Mild/Moderate" = col.mild.igm, "Severe/Critical" = col.severe.igm)



# t.test(growth.rate.all.IgM.ELISA.Spike.mild[,1],growth.rate.all.IgM.ELISA.Spike.severe[,1])


ggplot(data = growth.rate.igm.severity.df,aes(x=marker, y = growth.rate,col=marker)) +
       geom_point(data = means_and_se, aes(x = marker, y = growth.rate),col="red",shape=19,size=3,alpha=0.5) +
       geom_errorbar(data = means_and_se, aes(ymin = ymin, ymax = ymax),width = 0.1,col="red",alpha=0.5) +
       geom_jitter(width=0.1) +
       #scale_x_continuous(breaks = seq(0,(max(boot.samples.df.tp7$boot.samples)+2),5),limits=c(0,max(boot.samples.df.tp7$boot.samples+2))) +
       ylab("Growth rate (1/days)") +
       scale_color_manual(values = cols) +
       xlab("") +
       ggtitle("") +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size  = 12),text = element_text(size = 12),axis.text = element_text(size = 12),axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),axis.ticks.x = element_blank(),axis.text.x = element_blank(),legend.title = element_blank(),panel.background  =  element_rect(fill  =  'white'))


```



#### Pairwise difference     


IgM mild vs IgM severe    

```{r fig.height = 3, fig.width = 3}

post.diffs = data.frame(diffs = posterior.growth.rates.IgM.mild - posterior.growth.rates.IgM.severe)

dens = density(post.diffs$diffs)
hpd.post.diffs = HDInterval::hdi(dens,credMass = 0.95,allowSplit=F)  
lowerlim = hpd.post.diffs[1]
upperlim = hpd.post.diffs[2]

print(paste0("Mean = ",round(mean(post.diffs$diffs),3)))
print(paste0("95% CrI = ",round(lowerlim,3)," to ",round(upperlim,3)))

ggplot(data = post.diffs, aes(x = diffs)) +
       geom_histogram(aes(y  =  ..density..),binwidth  =  0.01, fill  =  col.igg, color  =  col.igg,alpha=0.5) +
       #scale_x_continuous(breaks = seq(0,(max(boot.samples.df$boot.samples)+2),5),limits=c(0,max(boot.samples.df$boot.samples+2))) +
       ggtitle("Growth rate difference between means") +
       xlab("Difference between means (1/days)") +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size = 12),
             text = element_text(size = 12),
             axis.text = element_text(size = 12),
             axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),
             legend.position  =  "none",
             panel.background  =  element_rect(fill  =  'white'))
```


<br>

***

<br>   



### Peak titer comparison disease severity



```{r fig.height=4,fig.width=5}


cols = c("Mild/Moderate IgM" = col.igm, "Severe/Critical IgM" = col.igm)

peak.titer.igm.mild.df = data.frame(Severity = "Mild/Moderate IgM",peak.titer = peak.titer.igm.mild)
peak.titer.igm.severe.df = data.frame(Severity = "Severe/Critical IgM",peak.titer = peak.titer.igm.severe)

peak.titers.plot = rbind(peak.titer.igm.mild.df,peak.titer.igm.severe.df)

means = data.frame(Severity = c("Mild/Moderate IgM","Severe/Critical IgM"), peak.titer = c(mean(peak.titer.igm.mild),mean(peak.titer.igm.severe)),se = c(sd(peak.titer.igm.mild)/sqrt(length(peak.titer.igm.mild)),sd(peak.titer.igm.severe)/sqrt(length(peak.titer.igm.severe))))

t.test(peak.titer.igm.mild,peak.titer.igm.severe)

ggplot(peak.titers.plot,aes(x=Severity, y = peak.titer,col=Severity)) +
       geom_point(data = means, aes(x = Severity, y = peak.titer),col="red",shape=19,size=3,alpha=0.5) +
       geom_errorbar(data = means, aes(ymin = peak.titer - se, ymax = peak.titer + se),width = 0.1,col="red",alpha=0.5) +
       geom_jitter(width=0.1) +
       #scale_x_continuous(breaks = seq(0,(max(boot.samples.df.tp7$boot.samples)+2),5),limits=c(0,max(boot.samples.df.tp7$boot.samples+2))) +
       ylab("Relative peak titer") +
       scale_color_manual(values = cols) +
       xlab("Disease severity") +
       ggtitle("IgM") +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size  = 12),text = element_text(size = 12),axis.text = element_text(size = 12),axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),legend.title = element_blank(),panel.background  =  element_rect(fill  =  'white'))


```




### Peak titer timing comparison      



#### Posterior means and 95% CrI    

IgM mild:    

```{r}

dens = density(posterior.peak.titer.times.IgM.mild)
hpd.post.diffs = HDInterval::hdi(dens,credMass = 0.95,allowSplit=F)  
lowerlim = hpd.post.diffs[1]
upperlim = hpd.post.diffs[2]

print(paste0("Mean = ",round(mean(posterior.peak.titer.times.IgM.mild),3)))
print(paste0("95% CrI = ",round(lowerlim,3)," to ",round(upperlim,3)))


```


IgM severe:    

```{r}

dens = density(posterior.peak.titer.times.IgM.severe)
hpd.post.diffs = HDInterval::hdi(dens,credMass = 0.95,allowSplit=F)  
lowerlim = hpd.post.diffs[1]
upperlim = hpd.post.diffs[2]

print(paste0("Mean = ",round(mean(posterior.peak.titer.times.IgM.severe),3)))
print(paste0("95% CrI = ",round(lowerlim,3)," to ",round(upperlim,3)))


```


```{r fig.height=4,fig.width=5}
peak.titer.times = data.frame(id = unique(fit.dat.igm.disease.severity.1$id), peak.titer.time = NA)

for(i in 1:length(unique(fit.dat.igm.disease.severity.1$id))){
       peak.titer.times$peak.titer.time[i] = get.peak.titer.time(titers = fit.dat.igm.disease.severity.1$titer[which(fit.dat.igm.disease.severity.1$id == unique(fit.dat.igm.disease.severity.1$id)[i])], days = fit.dat.igm.disease.severity.1$time[which(fit.dat.igm.disease.severity.1$id == unique(fit.dat.igm.disease.severity.1$id)[i])])
}



peak.titer.time.all.IgM.severe = peak.titer.times[idx.severe,]
peak.titer.time.all.IgM.mild = peak.titer.times[idx.mild,]
```




```{r fig.height=3,fig.width=5}

peak.titer.time.all.IgM.mild$marker = "Mild/Moderate"
peak.titer.time.all.IgM.severe$marker = "Severe/Critical"


means_and_se = rbind(mean_se(peak.titer.time.all.IgM.mild$peak.titer.time),
                     mean_se(peak.titer.time.all.IgM.severe$peak.titer.time))

colnames(means_and_se)[1] = c("peak.titer.time")
means_and_se$marker = c("Mild/Moderate","Severe/Critical")


peak.titer.time.igm.severity.df = rbind(peak.titer.time.all.IgM.mild,peak.titer.time.all.IgM.severe)



cols = c("Mild/Moderate" = col.mild.igm, "Severe/Critical" = col.severe.igm)



# t.test(peak.titer.time.all.IgM.mild$peak.titer.time,peak.titer.time.all.IgM.severe$peak.titer.time)


ggplot(data = peak.titer.time.igm.severity.df,aes(x=marker, y = peak.titer.time,col=marker)) +
       geom_point(data = means_and_se, aes(x = marker, y = peak.titer.time),col="red",shape=19,size=3,alpha=0.5) +
       geom_errorbar(data = means_and_se, aes(ymin = ymin, ymax = ymax),width = 0.1,col="red",alpha=0.5) +
       geom_jitter(width=0.1) +
       #scale_x_continuous(breaks = seq(0,(max(boot.samples.df.tp7$boot.samples)+2),5),limits=c(0,max(boot.samples.df.tp7$boot.samples+2))) +
       ylab("Peak titer time") +
       scale_color_manual(values = cols) +
       xlab("") +
       ggtitle("") +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size  = 12),text = element_text(size = 12),axis.text = element_text(size = 12),axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),axis.ticks.x = element_blank(),axis.text.x = element_blank(),legend.title = element_blank(),panel.background  =  element_rect(fill  =  'white'))


```




#### Pairwise differences     


IgM mild vs IgM severe    

```{r fig.height = 3, fig.width = 3}

post.diffs = data.frame(diffs = posterior.peak.titer.times.IgM.mild - posterior.peak.titer.times.IgM.severe)

dens = density(post.diffs$diffs)
hpd.post.diffs = HDInterval::hdi(dens,credMass = 0.95,allowSplit=F)  
lowerlim = hpd.post.diffs[1]
upperlim = hpd.post.diffs[2]

print(paste0("Mean = ",round(mean(post.diffs$diffs),3)))
print(paste0("95% CrI = ",round(lowerlim,3)," to ",round(upperlim,3)))

ggplot(data = post.diffs, aes(x = diffs)) +
       geom_histogram(aes(y  =  ..density..),binwidth  =  1, fill  =  col.igg, color  =  col.igg,alpha=0.5) +
       #scale_x_continuous(breaks = seq(0,(max(boot.samples.df$boot.samples)+2),5),limits=c(0,max(boot.samples.df$boot.samples+2))) +
       ggtitle("Peak titer time difference between means") +
       xlab("Difference between means (days)") +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size = 12),
             text = element_text(size = 12),
             axis.text = element_text(size = 12),
             axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),
             legend.position  =  "none",
             panel.background  =  element_rect(fill  =  'white'))
```





<br>

***

<br>   


## IgG/IgM       

### ELISA Spike     

Marker = IgM/IgG            
Assay = ELISA      
Antigen = Spike       
Disease severity = any     
Minimum number of datapoints per individual = 3    



```{r results='hide',fig.width=11,fig.height=4}


d2 = d0 [ which(d0$marker %in% c("IgM","IgG") & !is.na(d0$test.result) & d0$assay == "ELISA" & d0$antigen == "Spike" & d0$time.estimate.cat == "Exact" & d0$time.cat == "Symptom onset"),]


d2$id = paste0(d2$id, d2$marker)


# remove negative point that is unlikely to be correct
d2 = d2[-which(d2$id == "To_BB22196-1IgG" & d2$test.result==0),]

d2 = d2[-which(d2$id == "Zhao_Case 18530189IgM"),]


# remove duplicates, only keep Okba duplicates with original Spike antigen
d2 = d2[!(d2$author == "Okba" & d2$antigen.original != "Spike" & d2$marker=="IgG"),]




# only keep individuals that have at least one positive sample
posnegcount = as.data.frame(xtabs(~ id + test.pos.neg,d2))
id.keep = droplevels(posnegcount$id[which(posnegcount$test.pos.neg == "POS" & posnegcount$Freq>1)])
d2 = d2 [ which(d2$id %in% id.keep),]



# only keep individuals that have at least 2 samples in total
id.keep = droplevels(as.data.frame(table(d2$id))$Var1[which(as.data.frame(table(d2$id))$Freq > 2)])
d2 = d2 [ which(d2$id %in% id.keep),]
N.inds = length(unique(d2$id))
N.inds

N.inds.IgG.IgM.ELISA.Spike = N.inds

for(i in 1:length(unique(paste0(d2$study,d2$units)))){
       
       d2$test.result[which(paste0(d2$study,d2$units) == unique(paste0(d2$study,d2$units))[i])] = d2$test.result[which(paste0(d2$study,d2$units) == unique(paste0(d2$study,d2$units))[i])]/max(d2$test.result[which(paste0(d2$study,d2$units) == unique(paste0(d2$study,d2$units))[i])])
}




# check for outliers
ggplot() +
       geom_point(data=d2,aes(x = time.start, y = test.result,col=id,group=id),size = 1.5) +
       geom_line(data=d2,aes(x = time.start, y = test.result,col=id,group=id),size=0.7) +
       #scale_x_continuous(breaks = seq(0,max(d2$time.start),2)) +
       scale_y_continuous(limits=c(0,1)) +
       #scale_color_gradientn(colors  =  rev(brewer.pal(11,"Spectral"))) +
       # scale_color_brewer(palette = "Spectral", name = "Marker/Assay") +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size  = 12),text = element_text(size = 12),axis.text = element_text(size = 12),axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),legend.text = element_text(size=9),panel.background  =  element_rect(fill  =  'white')) +
       xlab("Days post symptom onset") +
       ylab("Antibody level")






# run MCMC or load previous data? 
run.mcmc.again = F

if(run.mcmc.again == T){
       model.jags = jags.model(model.file,
                               data=list('titer'=d2$test.result,
                                         'time'=d2$time.start,
                                         'id'=as.numeric(as.factor(d2$id)),
                                         'N.id'=length(unique(d2$id))
                               ),
                               #inits=list('peak.titer.sd.hyper'=0.5),
                               n.chains=6,
                               n.adapt = 1000)
       
       
       # burn in
       burn.in = 20000
       update(model.jags, n.iter = burn.in, by = 1)
       
       
       # draw samples
       iterations = 50000
       post = coda.samples(model.jags, c("peak.titer.mean.hyper","peak.titer.sd.hyper","peak.titer","displacement.mean.hyper","displacement.sd.hyper","displacement","growth.rate.mean.hyper","growth.rate"), n.iter = iterations, thin = 1)
       
       
       post.df = mcmclist.to.dataframe(post)
       
       saveRDS(post,file = paste0("MCMC_output/MCMC_output_post_",format(Sys.time(),"%Y%m%d_%H%M%S"),".RDS"))
       
       saveRDS(post.df,file = paste0("MCMC_output/MCMC_output_postdf_",format(Sys.time(),"%Y%m%d_%H%M%S"),".RDS"))
       
} else { 
       
       # enter the corresponding mcmc filenames here, as saved in the saveRDS lines above
       # example: post = readRDS("MCMC_output/MCMC_output_post_20200804_163314.RDS")
       post = readRDS("MCMC_output/")
       post.df = readRDS("MCMC_output/")
}



N.inds = length(unique(d2$id))


```

#### Gelman-Rubin convergence diagnostics:    

```{r}
gelman.diag(post)
```


#### Posterior growth rate:     


```{r fig.height = 3, fig.width=4}

plot.MCMC.posterior(input.data = post.df,column.to.plot = which(names(post.df)=="growth.rate.mean.hyper"),x.axis.label = "Growth rate (1/days)",title = "Posterior growth rate")

plot.MCMC.chains(input.data = post.df,column.to.plot = which(names(post.df)=="growth.rate.mean.hyper"),y.axis.label = "Growth rate (1/days)",title = "Posterior growth rate",thinning = 5) 


growth.rate.overall.mean = mean(post.df$growth.rate.mean.hyper)

```


#### Posterior peak titer overall mean:    


```{r fig.height = 3, fig.width=4}
plot.MCMC.posterior(input.data = post.df,column.to.plot = which(colnames(post.df)=="peak.titer.mean.hyper"),x.axis.label = "Peak titer mean",title = "Posterior peak titer mean")

plot.MCMC.chains(input.data = post.df,column.to.plot = which(colnames(post.df)=="peak.titer.mean.hyper"),y.axis.label = "Peak titer mean",title = "Posterior peak titer mean",thinning = 5) 

peak.titer.overall.mean = mean(post.df$peak.titer.mean.hyper)


```




#### Posterior displacement overall mean:      


```{r fig.height = 3, fig.width=4}
plot.MCMC.posterior(input.data = post.df,column.to.plot = which(names(post.df)=="displacement.mean.hyper"),x.axis.label = "Displacement mean",title = "Posterior displacement mean")

plot.MCMC.chains(input.data = post.df,column.to.plot = which(names(post.df)=="displacement.mean.hyper"),y.axis.label = "Displacement mean",title = "Posterior displacement mean",thinning = 5) 

displacement.overall.mean = mean(post.df$displacement.mean.hyper)
```



```{r}
# calculate posterior means


peak.titer.individual.means = as.data.frame(apply(post.df[,(4+N.inds+N.inds):(3+N.inds+N.inds+N.inds)],MARGIN = 2,mean))


displacement.individual.means = as.data.frame(apply(post.df[,(1:N.inds)],MARGIN = 2,mean))


growth.rate.individual.means = as.data.frame(apply(post.df[,(3+N.inds):(2+N.inds+N.inds)],MARGIN = 2,mean))

growth.rate.all.IgG.IgM.ELISA.Spike = growth.rate.individual.means

peak.titer.overall.mean.IgG.IgM.ELISA.Spike = peak.titer.overall.mean
displacement.overall.mean.IgG.IgM.ELISA.Spike = displacement.overall.mean
growth.rate.overall.mean.IgG.IgM.ELISA.Spike = growth.rate.overall.mean


```




#### Fitted function using mean posterior estimates       


```{r warning=FALSE, fig.width = 6, fig.height = 4}
plot.times = 0:max(d2$time.start)


observed.data = d2
observed.data$predicted = NA
uid = unique(observed.data$id)
for(i in 1:length(uid)){
       
       observed.data$predicted[which(observed.data$id == uid[i])] = titer.gompertz.fun(times = observed.data$time.start[which(observed.data$id == uid[i])], peak.titer = peak.titer.individual.means[i,1], displacement = displacement.individual.means[i,1], growth.rate = growth.rate.individual.means[i,1])
       
}


fit.dat = data.frame(titer = titer.gompertz.fun(times = plot.times, peak.titer = peak.titer.overall.mean, displacement = displacement.overall.mean, growth.rate = growth.rate.overall.mean), time = plot.times)

fit.dat.mean = fit.dat


observed.data$id = as.factor(observed.data$id)


plot1 = ggplot() +
       geom_point(data=observed.data,aes(x = time.start, y = test.result,col=as.numeric(id),group=id),size = 1.5) +
       geom_line(data=observed.data,aes(x = time.start, y = test.result,col=as.numeric(id),group=id),size=0.7) +
       geom_line(data=fit.dat,aes(x = time, y = titer),col="black",size=1.4,linetype="dashed") +
       #scale_x_continuous(breaks = seq(0,max(d2$time.start),2)) +
       scale_y_continuous(limits=c(0,1)) +
       scale_color_gradientn(colors  =  rev(brewer.pal(11,"Spectral"))) +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size  = 12),text = element_text(size = 12),axis.text = element_text(size = 12),axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),legend.position  =  "none",panel.background  =  element_rect(fill  =  'white')) +
       xlab("Days post symptom onset") +
       ylab("Antibody level")





```





#### Fitted functions for each individual      


```{r fig.width = 6, fig.height = 4}


fit.dat = data.frame(id = rep(uid, each = length(plot.times)), time = rep(plot.times,length(uid)), titer = NA)

for(i in 1:length(uid)){
       
       fit.dat$titer[which(fit.dat$id == uid[i])] = titer.gompertz.fun(times = plot.times, peak.titer = peak.titer.individual.means[i,1],displacement = displacement.individual.means[i,1],growth.rate = growth.rate.individual.means[i,1])
}


plot2 = ggplot() +
       geom_point(data=observed.data,aes(x = time.start, y = test.result,group=id),col="grey",size = 1.5) +
       geom_line(data=observed.data,aes(x = time.start, y = test.result,group=id),col="grey",size=0.7) +
       geom_line(data = fit.dat, aes(x = time, y = titer, col = as.numeric(id), group = id),size=1.2,alpha=0.5) +
       geom_line(data=fit.dat.mean,aes(x = time, y = titer),col="black",size=1.4,linetype="dashed") +
       #scale_x_continuous(breaks = seq(0,max(d2$time.start),2)) +
       scale_color_gradientn(colors  =  rev(brewer.pal(11,"Spectral"))) +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size  = 10),text = element_text(size = 12),axis.text = element_text(size = 12),axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),legend.position  =  "none",panel.background  =  element_rect(fill  =  'white')) +
       xlab("Days post symptom onset") +
       ylab("Antibody level")



```


```{r fig.height = 4, fig.width=8}

plot1 + plot2
```

#### Peak titer timing mean     



```{r}
peak.titer.time.mean.IgG.IgM.ELISA.Spike = get.peak.titer.time(titers = fit.dat.mean$titer, days = fit.dat.mean$time)

peak.titer.time.mean.IgG.IgM.ELISA.Spike
```


#### Peak titer timing all     

```{r}


peak.titer.times = data.frame(id = unique(fit.dat$id), peak.titer.time = NA)

for(i in 1:length(unique(fit.dat$id))){
       peak.titer.times$peak.titer.time[i] = get.peak.titer.time(titers = fit.dat$titer[which(fit.dat$id == unique(fit.dat$id)[i])], days = fit.dat$time[which(fit.dat$id == unique(fit.dat$id)[i])])
}

peak.titer.times
mean_se(peak.titer.times$peak.titer.time)
peak.titer.time.all.IgG.IgM.ELISA.Spike = peak.titer.times
```



#### Fitted function with additional functions drawn from credible interval       


```{r warning=FALSE, fig.width = 6, fig.height = 4}




# get more posterior samples from within credible interval, for variation plotting
# use growth rate as main variable to focus on
dens = density(post.df[,"growth.rate.mean.hyper"])
hpd.int.toi = HDInterval::hdi(dens,credMass = 0.95,allowSplit=F)  
lowerlim = hpd.int.toi[1]
upperlim = hpd.int.toi[2]


lowerlim.igg.igm.elisa.spike = lowerlim
upperlim.igg.igm.elisa.spike = upperlim


# randomly sample 100 rows that have a growth rate within the credible interval
ransamp = sample(which(post.df$growth.rate.mean.hyper > lowerlim & post.df$growth.rate.mean.hyper < upperlim),100)

ransamp.df = data.frame(growth.rate = post.df$growth.rate.mean.hyper[ransamp], peak.titer = post.df$peak.titer.mean.hyper[ransamp], displacement = post.df$displacement.mean.hyper[ransamp])


plot.times = 0:max(d2$time.start)


fit.dat = as.data.frame(apply(ransamp.df,1,fit.titers.fun.2))
fit.dat$time = plot.times

fit.dat = reshape2::melt(fit.dat,id.vars="time")


fit.dat.2 = as.data.frame(apply(ransamp.df,1,fit.titers.fun))
fit.dat.2$time = plot.times

fit.dat.2 = reshape2::melt(fit.dat.2,id.vars="time")
fit.dat.IgG.IgM.ELISA.Spike = fit.dat.2

main.fit.fun = data.frame(titer = titer.gompertz.fun(times = plot.times, peak.titer = peak.titer.overall.mean, displacement = displacement.overall.mean, growth.rate = growth.rate.overall.mean), time = plot.times)




ggplot() +
       geom_line(data=fit.dat,aes(x = time, y = value,group=variable),col="#D53E4F",size=0.7,alpha=0.1) +
       geom_line(data=main.fit.fun,aes(x = time, y = titer),col="#D53E4F",size=1.6) +
       #scale_x_continuous(breaks = seq(0,max(d2$time.start),2)) +
       #scale_y_continuous(limits=c(0,1)) +
       #scale_color_gradientn(colors  =  rev(brewer.pal(11,"Spectral"))) +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size  = 12),text = element_text(size = 12),axis.text = element_text(size = 12),axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),legend.position  =  "none",panel.background  =  element_rect(fill  =  'white')) +
       xlab("Days post symptom onset") +
       ylab("Antibody level")





```


```{r}

# store posterior growth rates and posterior peak titer times

posterior.growth.rates.IgG.IgM.ELISA.Spike = post.df$growth.rate.mean.hyper[which(post.df$iteration %in% 61000:71000)]


posterior.peak.titer.times.IgG.IgM.ELISA.Spike = apply(post.df[61000:71000,c("displacement.mean.hyper","growth.rate.mean.hyper")],1,get.posterior.peak.titer.times)



```



<br>

***

<br>   








### ELISA NP     

Marker = IgM/IgG            
Assay = ELISA      
Antigen = NP       
Disease severity = any     
Minimum number of datapoints per individual = 3    



```{r results='hide',fig.width=11,fig.height=4}


d2 = d0 [ which(d0$marker %in% c("IgM","IgG") & !is.na(d0$test.result) & d0$assay == "ELISA" & d0$antigen == "NP" & d0$time.estimate.cat == "Exact" & d0$time.cat == "Symptom onset"),]


d2$id = paste0(d2$id, d2$marker)


d2 = d2[-which(d2$id == "Zhou_ICU-06012-7IgM"),]

d2 = d2[-which(d2$id == "Zhao_Case 18530189IgG"),]







# only keep individuals that have at least one positive sample
posnegcount = as.data.frame(xtabs(~ id + test.pos.neg,d2))
id.keep = droplevels(posnegcount$id[which(posnegcount$test.pos.neg == "POS" & posnegcount$Freq>1)])
d2 = d2 [ which(d2$id %in% id.keep),]



# only keep individuals that have at least 2 samples in total
id.keep = droplevels(as.data.frame(table(d2$id))$Var1[which(as.data.frame(table(d2$id))$Freq > 2)])
d2 = d2 [ which(d2$id %in% id.keep),]
N.inds = length(unique(d2$id))
N.inds

N.inds.IgG.IgM.ELISA.Spike = N.inds

for(i in 1:length(unique(paste0(d2$study,d2$units)))){
       
       d2$test.result[which(paste0(d2$study,d2$units) == unique(paste0(d2$study,d2$units))[i])] = d2$test.result[which(paste0(d2$study,d2$units) == unique(paste0(d2$study,d2$units))[i])]/max(d2$test.result[which(paste0(d2$study,d2$units) == unique(paste0(d2$study,d2$units))[i])])
}




# check for outliers
ggplot() +
       geom_point(data=d2,aes(x = time.start, y = test.result,col=id,group=id),size = 1.5) +
       geom_line(data=d2,aes(x = time.start, y = test.result,col=id,group=id),size=0.7) +
       #scale_x_continuous(breaks = seq(0,max(d2$time.start),2)) +
       scale_y_continuous(limits=c(0,1)) +
       #scale_color_gradientn(colors  =  rev(brewer.pal(11,"Spectral"))) +
       # scale_color_brewer(palette = "Spectral", name = "Marker/Assay") +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size  = 12),text = element_text(size = 12),axis.text = element_text(size = 12),axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),legend.text = element_text(size=9),panel.background  =  element_rect(fill  =  'white')) +
       xlab("Days post symptom onset") +
       ylab("Antibody level")






# run MCMC or load previous data? 
run.mcmc.again = F

if(run.mcmc.again == T){
       model.jags = jags.model(model.file,
                               data=list('titer'=d2$test.result,
                                         'time'=d2$time.start,
                                         'id'=as.numeric(as.factor(d2$id)),
                                         'N.id'=length(unique(d2$id))
                               ),
                               #inits=list('peak.titer.sd.hyper'=0.5),
                               n.chains=6,
                               n.adapt = 1000)
       
       
       # burn in
       burn.in = 20000
       update(model.jags, n.iter = burn.in, by = 1)
       
       
       # draw samples
       iterations = 50000
       post = coda.samples(model.jags, c("peak.titer.mean.hyper","peak.titer.sd.hyper","peak.titer","displacement.mean.hyper","displacement.sd.hyper","displacement","growth.rate.mean.hyper","growth.rate"), n.iter = iterations, thin = 1)
       
       
       post.df = mcmclist.to.dataframe(post)
       
       saveRDS(post,file = paste0("MCMC_output/MCMC_output_post_",format(Sys.time(),"%Y%m%d_%H%M%S"),".RDS"))
       
       saveRDS(post.df,file = paste0("MCMC_output/MCMC_output_postdf_",format(Sys.time(),"%Y%m%d_%H%M%S"),".RDS"))
       
} else { 
       
       # enter the corresponding mcmc filenames here, as saved in the saveRDS lines above
       # example: post = readRDS("MCMC_output/MCMC_output_post_20200804_163314.RDS")
       post = readRDS("MCMC_output/")
       post.df = readRDS("MCMC_output/")
}



N.inds = length(unique(d2$id))


```

#### Gelman-Rubin convergence diagnostics:    

```{r}
gelman.diag(post)
```


#### Posterior growth rate:     


```{r fig.height = 3, fig.width=4}

plot.MCMC.posterior(input.data = post.df,column.to.plot = which(names(post.df)=="growth.rate.mean.hyper"),x.axis.label = "Growth rate (1/days)",title = "Posterior growth rate")

plot.MCMC.chains(input.data = post.df,column.to.plot = which(names(post.df)=="growth.rate.mean.hyper"),y.axis.label = "Growth rate (1/days)",title = "Posterior growth rate",thinning = 5) 


growth.rate.overall.mean = mean(post.df$growth.rate.mean.hyper)

```


#### Posterior peak titer overall mean:    


```{r fig.height = 3, fig.width=4}
plot.MCMC.posterior(input.data = post.df,column.to.plot = which(colnames(post.df)=="peak.titer.mean.hyper"),x.axis.label = "Peak titer mean",title = "Posterior peak titer mean")

plot.MCMC.chains(input.data = post.df,column.to.plot = which(colnames(post.df)=="peak.titer.mean.hyper"),y.axis.label = "Peak titer mean",title = "Posterior peak titer mean",thinning = 5) 

peak.titer.overall.mean = mean(post.df$peak.titer.mean.hyper)


```




#### Posterior displacement overall mean:      


```{r fig.height = 3, fig.width=4}
plot.MCMC.posterior(input.data = post.df,column.to.plot = which(names(post.df)=="displacement.mean.hyper"),x.axis.label = "Displacement mean",title = "Posterior displacement mean")

plot.MCMC.chains(input.data = post.df,column.to.plot = which(names(post.df)=="displacement.mean.hyper"),y.axis.label = "Displacement mean",title = "Posterior displacement mean",thinning = 5) 

displacement.overall.mean = mean(post.df$displacement.mean.hyper)
```



```{r}
# calculate posterior means


peak.titer.individual.means = as.data.frame(apply(post.df[,(4+N.inds+N.inds):(3+N.inds+N.inds+N.inds)],MARGIN = 2,mean))


displacement.individual.means = as.data.frame(apply(post.df[,(1:N.inds)],MARGIN = 2,mean))


growth.rate.individual.means = as.data.frame(apply(post.df[,(3+N.inds):(2+N.inds+N.inds)],MARGIN = 2,mean))

growth.rate.all.IgG.IgM.ELISA.NP = growth.rate.individual.means

peak.titer.overall.mean.IgG.IgM.ELISA.NP = peak.titer.overall.mean
displacement.overall.mean.IgG.IgM.ELISA.NP = displacement.overall.mean
growth.rate.overall.mean.IgG.IgM.ELISA.NP = growth.rate.overall.mean


```




#### Fitted function using mean posterior estimates       


```{r warning=FALSE, fig.width = 6, fig.height = 4}
plot.times = 0:max(d2$time.start)


observed.data = d2
observed.data$predicted = NA
uid = unique(observed.data$id)
for(i in 1:length(uid)){
       
       observed.data$predicted[which(observed.data$id == uid[i])] = titer.gompertz.fun(times = observed.data$time.start[which(observed.data$id == uid[i])], peak.titer = peak.titer.individual.means[i,1], displacement = displacement.individual.means[i,1], growth.rate = growth.rate.individual.means[i,1])
       
}


fit.dat = data.frame(titer = titer.gompertz.fun(times = plot.times, peak.titer = peak.titer.overall.mean, displacement = displacement.overall.mean, growth.rate = growth.rate.overall.mean), time = plot.times)

fit.dat.mean = fit.dat


observed.data$id = as.factor(observed.data$id)


plot1 = ggplot() +
       geom_point(data=observed.data,aes(x = time.start, y = test.result,col=as.numeric(id),group=id),size = 1.5) +
       geom_line(data=observed.data,aes(x = time.start, y = test.result,col=as.numeric(id),group=id),size=0.7) +
       geom_line(data=fit.dat,aes(x = time, y = titer),col="black",size=1.4,linetype="dashed") +
       #scale_x_continuous(breaks = seq(0,max(d2$time.start),2)) +
       scale_y_continuous(limits=c(0,1)) +
       scale_color_gradientn(colors  =  rev(brewer.pal(11,"Spectral"))) +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size  = 12),text = element_text(size = 12),axis.text = element_text(size = 12),axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),legend.position  =  "none",panel.background  =  element_rect(fill  =  'white')) +
       xlab("Days post symptom onset") +
       ylab("Antibody level")





```





#### Fitted functions for each individual      


```{r fig.width = 6, fig.height = 4}


fit.dat = data.frame(id = rep(uid, each = length(plot.times)), time = rep(plot.times,length(uid)), titer = NA)

for(i in 1:length(uid)){
       
       fit.dat$titer[which(fit.dat$id == uid[i])] = titer.gompertz.fun(times = plot.times, peak.titer = peak.titer.individual.means[i,1],displacement = displacement.individual.means[i,1],growth.rate = growth.rate.individual.means[i,1])
}


plot2 = ggplot() +
       geom_point(data=observed.data,aes(x = time.start, y = test.result,group=id),col="grey",size = 1.5) +
       geom_line(data=observed.data,aes(x = time.start, y = test.result,group=id),col="grey",size=0.7) +
       geom_line(data = fit.dat, aes(x = time, y = titer, col = as.numeric(id), group = id),size=1.2,alpha=0.5) +
       geom_line(data=fit.dat.mean,aes(x = time, y = titer),col="black",size=1.4,linetype="dashed") +
       #scale_x_continuous(breaks = seq(0,max(d2$time.start),2)) +
       scale_color_gradientn(colors  =  rev(brewer.pal(11,"Spectral"))) +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size  = 10),text = element_text(size = 12),axis.text = element_text(size = 12),axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),legend.position  =  "none",panel.background  =  element_rect(fill  =  'white')) +
       xlab("Days post symptom onset") +
       ylab("Antibody level")



```


```{r fig.height = 4, fig.width=8}

plot1 + plot2
```

#### Peak titer timing mean     



```{r}
peak.titer.time.mean.IgG.IgM.ELISA.NP = get.peak.titer.time(titers = fit.dat.mean$titer, days = fit.dat.mean$time)

peak.titer.time.mean.IgG.IgM.ELISA.NP
```


#### Peak titer timing all     

```{r}


peak.titer.times = data.frame(id = unique(fit.dat$id), peak.titer.time = NA)

for(i in 1:length(unique(fit.dat$id))){
       peak.titer.times$peak.titer.time[i] = get.peak.titer.time(titers = fit.dat$titer[which(fit.dat$id == unique(fit.dat$id)[i])], days = fit.dat$time[which(fit.dat$id == unique(fit.dat$id)[i])])
}

peak.titer.times
mean_se(peak.titer.times$peak.titer.time)
peak.titer.time.all.IgG.IgM.ELISA.NP = peak.titer.times
```



#### Fitted function with additional functions drawn from credible interval       


```{r warning=FALSE, fig.width = 6, fig.height = 4}




# get more posterior samples from within credible interval, for variation plotting
# use growth rate as main variable to focus on
dens = density(post.df[,"growth.rate.mean.hyper"])
hpd.int.toi = HDInterval::hdi(dens,credMass = 0.95,allowSplit=F)  
lowerlim = hpd.int.toi[1]
upperlim = hpd.int.toi[2]


lowerlim.igg.igm.elisa.np = lowerlim
upperlim.igg.igm.elisa.np = upperlim


# randomly sample 100 rows that have a growth rate within the credible interval
ransamp = sample(which(post.df$growth.rate.mean.hyper > lowerlim & post.df$growth.rate.mean.hyper < upperlim),100)

ransamp.df = data.frame(growth.rate = post.df$growth.rate.mean.hyper[ransamp], peak.titer = post.df$peak.titer.mean.hyper[ransamp], displacement = post.df$displacement.mean.hyper[ransamp])


plot.times = 0:max(d2$time.start)


fit.dat = as.data.frame(apply(ransamp.df,1,fit.titers.fun.2))
fit.dat$time = plot.times

fit.dat = reshape2::melt(fit.dat,id.vars="time")


fit.dat.2 = as.data.frame(apply(ransamp.df,1,fit.titers.fun))
fit.dat.2$time = plot.times

fit.dat.2 = reshape2::melt(fit.dat.2,id.vars="time")

fit.dat.IgG.IgM.ELISA.NP = fit.dat.2

main.fit.fun = data.frame(titer = titer.gompertz.fun(times = plot.times, peak.titer = peak.titer.overall.mean, displacement = displacement.overall.mean, growth.rate = growth.rate.overall.mean), time = plot.times)




ggplot() +
       geom_line(data=fit.dat,aes(x = time, y = value,group=variable),col="#D53E4F",size=0.7,alpha=0.1) +
       geom_line(data=main.fit.fun,aes(x = time, y = titer),col="#D53E4F",size=1.6) +
       #scale_x_continuous(breaks = seq(0,max(d2$time.start),2)) +
       #scale_y_continuous(limits=c(0,1)) +
       #scale_color_gradientn(colors  =  rev(brewer.pal(11,"Spectral"))) +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size  = 12),text = element_text(size = 12),axis.text = element_text(size = 12),axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),legend.position  =  "none",panel.background  =  element_rect(fill  =  'white')) +
       xlab("Days post symptom onset") +
       ylab("Antibody level")





```


```{r}

# store posterior growth rates and posterior peak titer times

posterior.growth.rates.IgG.IgM.ELISA.NP = post.df$growth.rate.mean.hyper[which(post.df$iteration %in% 61000:71000)]


posterior.peak.titer.times.IgG.IgM.ELISA.NP = apply(post.df[61000:71000,c("displacement.mean.hyper","growth.rate.mean.hyper")],1,get.posterior.peak.titer.times)



```



<br>

***

<br>   









## IgM vs IgG vs ELISA Spike vs ELISA NP vs MCLIA       



```{r fig.height = 4, fig.width=5}


titer.kinetics.dat = data.frame(marker = rep(c("IgG","IgM"),each=3), assay = rep(c("ELISA Spike","ELISA NP","MCLIA"),2),peak.titer = NA, growth.rate = NA, displacement = NA)

titer.kinetics.dat$peak.titer [ which(titer.kinetics.dat$marker == "IgG" & titer.kinetics.dat$assay == "ELISA Spike") ] = 0.5
titer.kinetics.dat$growth.rate [ which(titer.kinetics.dat$marker == "IgG" & titer.kinetics.dat$assay == "ELISA Spike") ] = growth.rate.overall.mean.IgG.ELISA.Spike
titer.kinetics.dat$displacement [ which(titer.kinetics.dat$marker == "IgG" & titer.kinetics.dat$assay == "ELISA Spike") ] = displacement.overall.mean.IgG.ELISA.Spike

titer.kinetics.dat$peak.titer [ which(titer.kinetics.dat$marker == "IgG" & titer.kinetics.dat$assay == "ELISA NP") ] = 0.5
titer.kinetics.dat$growth.rate [ which(titer.kinetics.dat$marker == "IgG" & titer.kinetics.dat$assay == "ELISA NP") ] = growth.rate.overall.mean.IgG.ELISA.NP
titer.kinetics.dat$displacement [ which(titer.kinetics.dat$marker == "IgG" & titer.kinetics.dat$assay == "ELISA NP") ] = displacement.overall.mean.IgG.ELISA.NP

titer.kinetics.dat$peak.titer [ which(titer.kinetics.dat$marker == "IgG" & titer.kinetics.dat$assay == "MCLIA") ] = 0.5
titer.kinetics.dat$growth.rate [ which(titer.kinetics.dat$marker == "IgG" & titer.kinetics.dat$assay == "MCLIA") ] = growth.rate.overall.mean.IgG.MCLIA
titer.kinetics.dat$displacement [ which(titer.kinetics.dat$marker == "IgG" & titer.kinetics.dat$assay == "MCLIA") ] = displacement.overall.mean.IgG.MCLIA


titer.kinetics.dat$peak.titer [ which(titer.kinetics.dat$marker == "IgM" & titer.kinetics.dat$assay == "ELISA Spike") ] = 0.5
titer.kinetics.dat$growth.rate [ which(titer.kinetics.dat$marker == "IgM" & titer.kinetics.dat$assay == "ELISA Spike") ] = growth.rate.overall.mean.IgM.ELISA.Spike
titer.kinetics.dat$displacement [ which(titer.kinetics.dat$marker == "IgM" & titer.kinetics.dat$assay == "ELISA Spike") ] = displacement.overall.mean.IgM.ELISA.Spike

titer.kinetics.dat$peak.titer [ which(titer.kinetics.dat$marker == "IgM" & titer.kinetics.dat$assay == "ELISA NP") ] = 0.5
titer.kinetics.dat$growth.rate [ which(titer.kinetics.dat$marker == "IgM" & titer.kinetics.dat$assay == "ELISA NP") ] = growth.rate.overall.mean.IgM.ELISA.NP
titer.kinetics.dat$displacement [ which(titer.kinetics.dat$marker == "IgM" & titer.kinetics.dat$assay == "ELISA NP") ] = displacement.overall.mean.IgM.ELISA.NP

titer.kinetics.dat$peak.titer [ which(titer.kinetics.dat$marker == "IgM" & titer.kinetics.dat$assay == "MCLIA") ] = 0.5
titer.kinetics.dat$growth.rate [ which(titer.kinetics.dat$marker == "IgM" & titer.kinetics.dat$assay == "MCLIA") ] = growth.rate.overall.mean.IgM.MCLIA
titer.kinetics.dat$displacement [ which(titer.kinetics.dat$marker == "IgM" & titer.kinetics.dat$assay == "MCLIA") ] = displacement.overall.mean.IgM.MCLIA


plot.times = 0:30


fit.dat = data.frame(titer = numeric(length(plot.times)*nrow(titer.kinetics.dat)), time = rep(plot.times,nrow(titer.kinetics.dat)),marker = NA, assay = NA)


teller = 1
for(i in 1:nrow(titer.kinetics.dat)){
       
       fit.dat$titer[teller:(teller + length(plot.times) - 1)] = titer.gompertz.fun(times = plot.times, peak.titer = 1, displacement = titer.kinetics.dat$displacement[i], growth.rate = titer.kinetics.dat$growth.rate[i])
       
       fit.dat$marker[teller:(teller + length(plot.times) - 1)] = as.character(titer.kinetics.dat$marker[i])
       fit.dat$assay[teller:(teller + length(plot.times) - 1)] = as.character(titer.kinetics.dat$assay[i])
       
       teller = teller + length(plot.times)
}

fit.dat$marker.assay = paste0(fit.dat$marker, " ",fit.dat$assay)


cols = c("IgG ELISA NP" = col.igg,"IgG ELISA Spike" = col.rna2,"IgG MCLIA" = col.ntab,"IgM ELISA NP" = col.elisa,"IgM ELISA Spike" = col.igm,"IgM MCLIA" = col.rna)

ggplot(fit.dat,aes(x = time, y = titer, group = marker.assay, color = marker.assay)) +
       geom_line(size=1.2) +
       #scale_color_gradientn(colors  =  rev(brewer.pal(11,"Spectral")),name = "Marker", labels = unique(fit.dat$marker.assay)) +
       scale_color_manual(values = cols, name = "") +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size  = 12),text = element_text(size = 14),axis.text = element_text(size = 12),axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),legend.position  =  c(0.8,0.4),panel.background  =  element_rect(fill  =  'white'),legend.background = element_rect(fill="white")) +
       xlab("Days post symptom onset") +
       ylab("Antibody level")






ggplot(fit.dat[-which(fit.dat$marker.assay %in% c("IgM MCLIA","IgG MCLIA")),],aes(x = time, y = titer, group = marker.assay, color = marker.assay)) +
       geom_line(size=1.2) +
       #scale_color_gradientn(colors  =  rev(brewer.pal(11,"Spectral")),name = "Marker", labels = unique(fit.dat$marker.assay)) +
       scale_color_manual(values = cols, name = "") +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size  = 12),text = element_text(size = 14),axis.text = element_text(size = 12),axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),legend.position  =  c(0.8,0.4),panel.background  =  element_rect(fill  =  'white'),legend.background = element_rect(fill="white")) +
       xlab("Days post symptom onset") +
       ylab("Antibody level")








plot.times = 0:30



main.fit.function.igm$assay = paste0("IgM ",main.fit.function.igm$assay)
main.fit.function.igg$assay = paste0("IgG ",main.fit.function.igg$assay)

main.fit.function.igm.igg = rbind(main.fit.function.igm,main.fit.function.igg)






ggplot(data=main.fit.function.igm.igg[-which(main.fit.function.igm.igg$assay %in% c("IgM MCLIA NP + Spike","IgG MCLIA NP + Spike")),],aes(x = time, y = value,group=assay,col=assay)) +
       #geom_line(data=fit.dat.all,aes(x = time, y = value,group = variable, col=assay),size=0.5,alpha=0.1) +
       #geom_ribbon(aes(x = plot.times,ymin = lowerlim.elisa.spike,ymax = upperlim.elisa.spike),col=col.rna,fill = col.rna,alpha=0.2) +
       geom_ribbon(aes(ymin = lowerlim,ymax = upperlim),fill = "none",alpha=0.6,linetype="dashed",show.legend = F) +
       geom_line(size=1.8) +
       #scale_x_continuous(breaks = seq(0,max(d2$time.start),2)) +
       scale_y_continuous(limits=c(0,1)) +
       #scale_color_gradientn(colors  =  rev(brewer.pal(11,"Spectral"))) +
       # scale_color_brewer(palette = "Spectral", name = "") +
       scale_color_manual(values = c(col.igg,col.elisa,col.rna,col.igm),name="") +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size  = 12),
             text = element_text(size = 12),
             axis.text = element_text(size = 12),
             axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),
             legend.position  =  c(0.82,0.3),
             legend.background = element_rect(fill="transparent"),
             panel.background  =  element_rect(fill  =  'white')) +
       xlab("Days post symptom onset") +
       ylab("Antibody level")







plot.main.functions.combined = ggplot() +
       #geom_line(data=fit.dat.all,aes(x = time, y = value,group = variable, col=assay),size=0.5,alpha=0.1) +
       #geom_ribbon(aes(x = plot.times,ymin = lowerlim.elisa.spike,ymax = upperlim.elisa.spike),col=col.rna,fill = col.rna,alpha=0.2) +
       #geom_ribbon(aes(ymin = lowerlim,ymax = upperlim),fill = "none",alpha=0.6,linetype="dashed",show.legend = F) +
       geom_line(data=main.fit.function.igm.igg[-which(main.fit.function.igm.igg$assay %in% c("IgM MCLIA NP + Spike","IgG MCLIA NP + Spike")),],aes(x = time, y = value,group=assay,col=assay),size=1.5,alpha=0.9) +
       geom_line(data=main.fit.function.igm.igg[-which(main.fit.function.igm.igg$assay %in% c("IgM MCLIA NP + Spike","IgG MCLIA NP + Spike")),],aes(x = time, y = upperlim,group=assay,col=assay),linetype="dashed",size=0.85) +
       geom_line(data=main.fit.function.igm.igg[-which(main.fit.function.igm.igg$assay %in% c("IgM MCLIA NP + Spike","IgG MCLIA NP + Spike")),],aes(x = time, y = lowerlim,group=assay,col=assay),linetype="dashed",size=0.85) +
       scale_x_continuous(limits = c(0,35)) +
       scale_y_continuous(limits=c(0,1)) +
       #scale_color_gradientn(colors  =  rev(brewer.pal(11,"Spectral"))) +
       # scale_color_brewer(palette = "Spectral", name = "") +
       scale_color_manual(values = c(col.igg,col.rna,col.elisa,col.igm),name="") +
       theme_classic(base_family = "Avenir Next") +
       annotate("text", label = "A", x = 0,y=1,size=7) +
       theme(plot.title  =  element_text(size  = 12),
             text = element_text(size = 12),
             axis.text = element_text(size = 12),
             axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),
             legend.position  =  c(0.76,0.35),
             legend.background = element_rect(fill="transparent"),
             panel.background  =  element_rect(fill  =  'white')) +
       xlab("Days post symptom onset") +
       ylab("Antibody level")


plot.main.functions.combined








```





## IgG and IgM combined      


IgG ELISA NP    
IgM ELISA Spike    



```{r warning=FALSE, fig.width = 6, fig.height = 4}


plot.times = 0:max(fit.dat.IgG.ELISA.NP$time)

main.fit.fun.igg.elisa.np = data.frame(titer = titer.gompertz.fun(times = plot.times, peak.titer = 1, displacement = displacement.overall.mean.IgG.ELISA.NP, growth.rate = growth.rate.overall.mean.IgG.ELISA.NP), time = plot.times, marker = "IgG ELISA (NP)")

plot.times = 0:max(fit.dat.IgM.ELISA.Spike$time)

main.fit.fun.igm.elisa.spike = data.frame(titer = titer.gompertz.fun(times = plot.times, peak.titer = 1, displacement = displacement.overall.mean.IgM.ELISA.Spike, growth.rate = growth.rate.overall.mean.IgM.ELISA.Spike), time = plot.times, marker = "IgM ELISA (Spike)")


main.fit.functions = rbind(main.fit.fun.igg.elisa.np,main.fit.fun.igm.elisa.spike)

main.fit.functions = reshape2::melt(main.fit.functions, id.vars = c("time","marker"))

main.fit.function.igg.igm.elisa.np.spike = main.fit.functions


fit.dat.IgG.ELISA.NP$marker = "IgG ELISA (NP)"
fit.dat.IgM.ELISA.Spike$marker = "IgM ELISA (Spike)"


fit.dat.all = rbind(fit.dat.IgG.ELISA.NP,fit.dat.IgM.ELISA.Spike)
fit.dat.all$variable = paste(fit.dat.all$marker, fit.dat.all$variable)

fit.dat.all.igg.igm.elisa.np.spike = fit.dat.all


plot.times = 0:max(fit.dat.IgG.ELISA.NP$time)
lowerlim.igg.elisa.out = titer.gompertz.fun(times = plot.times,peak.titer = 1, displacement = displacement.overall.mean.IgG.ELISA.NP, growth.rate = lowerlim.igg.elisa.np) 
upperlim.igg.elisa.out = titer.gompertz.fun(times = plot.times,peak.titer = 1, displacement = displacement.overall.mean.IgG.ELISA.NP, growth.rate = upperlim.igg.elisa.np)

plot.times = 0:max(fit.dat.IgM.ELISA.Spike$time)
lowerlim.igm.elisa.out = titer.gompertz.fun(times = plot.times,peak.titer = 1, displacement = displacement.overall.mean.IgM.ELISA.Spike, growth.rate = lowerlim.igm.elisa.spike)
upperlim.igm.elisa.out = titer.gompertz.fun(times = plot.times,peak.titer = 1, displacement = displacement.overall.mean.IgM.ELISA.Spike, growth.rate = upperlim.igm.elisa.spike)


main.fit.function.igg.igm.elisa.np.spike$lowerlim = NA
main.fit.function.igg.igm.elisa.np.spike$upperlim = NA


main.fit.function.igg.igm.elisa.np.spike$lowerlim [ which(main.fit.function.igg.igm.elisa.np.spike$marker == "IgG ELISA (NP)") ] = lowerlim.igg.elisa.out
main.fit.function.igg.igm.elisa.np.spike$upperlim [ which(main.fit.function.igg.igm.elisa.np.spike$marker == "IgG ELISA (NP)") ] = upperlim.igg.elisa.out
main.fit.function.igg.igm.elisa.np.spike$lowerlim [ which(main.fit.function.igg.igm.elisa.np.spike$marker == "IgM ELISA (Spike)") ] = lowerlim.igm.elisa.out
main.fit.function.igg.igm.elisa.np.spike$upperlim [ which(main.fit.function.igg.igm.elisa.np.spike$marker == "IgM ELISA (Spike)") ] = upperlim.igm.elisa.out






ggplot(data=main.fit.function.igg.igm.elisa.np.spike,aes(x = time, y = value,group=marker,col=marker)) +
       #geom_line(data=fit.dat.all,aes(x = time, y = value,group = variable, col=assay),size=0.5,alpha=0.1) +
       #geom_ribbon(aes(x = plot.times,ymin = lowerlim.elisa.spike,ymax = upperlim.elisa.spike),col=col.rna,fill = col.rna,alpha=0.2) +
       geom_ribbon(aes(ymin = lowerlim,ymax = upperlim),fill = "none",alpha=0.6,linetype="dashed", show.legend=F) +
       geom_line(size=1.8) +
       #scale_x_continuous(breaks = seq(0,max(d2$time.start),2)) +
       scale_y_continuous(limits=c(0,1)) +
       #scale_color_gradientn(colors  =  rev(brewer.pal(11,"Spectral"))) +
       # scale_color_brewer(palette = "Spectral", name = "") +
       scale_color_manual(values = c(col.igg,col.igm),name="") +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size  = 12),
             text = element_text(size = 14),
             axis.text = element_text(size = 12),
             axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),
             legend.position  =  c(0.82,0.3),
             legend.background = element_rect(fill="white"),
             panel.background  =  element_rect(fill  =  'white')) +
       xlab("Days post symptom onset") +
       ylab("Antibody level")




ggplot(data=main.fit.function.igg.igm.elisa.np.spike,aes(x = time, y = value,group=marker,col=marker,fill=marker)) +
       #geom_line(data=fit.dat.all,aes(x = time, y = value,group = variable, col=assay),size=0.5,alpha=0.1) +
       #geom_ribbon(aes(x = plot.times,ymin = lowerlim.elisa.spike,ymax = upperlim.elisa.spike),col=col.rna,fill = col.rna,alpha=0.2) +
       geom_ribbon(aes(ymin = lowerlim,ymax = upperlim),alpha=0.2,linetype="dashed", show.legend=F) +
       geom_line(size=1.8) +
       #scale_x_continuous(breaks = seq(0,max(d2$time.start),2)) +
       scale_y_continuous(limits=c(0,1)) +
       #scale_color_gradientn(colors  =  rev(brewer.pal(11,"Spectral"))) +
       # scale_color_brewer(palette = "Spectral", name = "") +
       scale_fill_manual(values = c(col.igg,col.igm),name="") +
       scale_color_manual(values = c(col.igg,col.igm),name="") +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size  = 12),text = element_text(size = 14),axis.text = element_text(size = 12),axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),legend.position  =  c(0.82,0.3),legend.background = element_rect(fill="white"),panel.background  =  element_rect(fill  =  'white')) +
       xlab("Days post symptom onset") +
       ylab("Antibody level")




ggplot(data=main.fit.function.igg.igm.elisa.np.spike,aes(x = time, y = value,group=marker,col=marker)) +
       #geom_line(data=fit.dat.all,aes(x = time, y = value,group = variable, col=assay),size=0.5,alpha=0.1) +
       #geom_ribbon(aes(x = plot.times,ymin = lowerlim.elisa.spike,ymax = upperlim.elisa.spike),col=col.rna,fill = col.rna,alpha=0.2) +
       geom_line(data=fit.dat.all,aes(x = time, y = value,group = variable, col=marker),size=0.5,alpha=0.1) +
       geom_ribbon(aes(ymin = lowerlim,ymax = upperlim),fill="none",alpha=0.1,linetype="dashed", show.legend=F) +
       geom_line(size=1.8) +
       #scale_x_continuous(breaks = seq(0,max(d2$time.start),2)) +
       scale_y_continuous(limits=c(0,1)) +
       #scale_color_gradientn(colors  =  rev(brewer.pal(11,"Spectral"))) +
       # scale_color_brewer(palette = "Spectral", name = "") +
       scale_color_manual(values = c(col.igg,col.igm),name="") +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size  = 12),text = element_text(size = 14),axis.text = element_text(size = 12),axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),legend.position  =  c(0.82,0.3),legend.background = element_rect(fill="white"),panel.background  =  element_rect(fill  =  'white')) +
       xlab("Days post symptom onset") +
       ylab("Antibody level")




```





IgG ELISA Spike    
IgM ELISA Spike    



```{r warning=FALSE, fig.width = 6, fig.height = 4}


plot.times = 0:max(fit.dat.IgG.ELISA.Spike$time)

main.fit.fun.igg.elisa.spike = data.frame(titer = titer.gompertz.fun(times = plot.times, peak.titer = 1, displacement = displacement.overall.mean.IgG.ELISA.Spike, growth.rate = growth.rate.overall.mean.IgG.ELISA.Spike), time = plot.times, marker = "IgG ELISA (Spike)")

plot.times = 0:max(fit.dat.IgM.ELISA.Spike$time)

main.fit.fun.igm.elisa.spike = data.frame(titer = titer.gompertz.fun(times = plot.times, peak.titer = 1, displacement = displacement.overall.mean.IgM.ELISA.Spike, growth.rate = growth.rate.overall.mean.IgM.ELISA.Spike), time = plot.times, marker = "IgM ELISA (Spike)")


main.fit.functions = rbind(main.fit.fun.igg.elisa.spike,main.fit.fun.igm.elisa.spike)

main.fit.functions = reshape2::melt(main.fit.functions, id.vars = c("time","marker"))

main.fit.function.igg.igm.elisa.spike = main.fit.functions


fit.dat.IgG.ELISA.Spike$marker = "IgG ELISA (Spike)"
fit.dat.IgM.ELISA.Spike$marker = "IgM ELISA (Spike)"


fit.dat.all = rbind(fit.dat.IgG.ELISA.Spike,fit.dat.IgM.ELISA.Spike)
fit.dat.all$variable = paste(fit.dat.all$marker, fit.dat.all$variable)

fit.dat.all.igg.igm.elisa.spike = fit.dat.all


plot.times = 0:max(fit.dat.IgG.ELISA.Spike$time)
lowerlim.igg.elisa.out = titer.gompertz.fun(times = plot.times,peak.titer = 1, displacement = displacement.overall.mean.IgG.ELISA.Spike, growth.rate = lowerlim.igg.elisa.spike) 
upperlim.igg.elisa.out = titer.gompertz.fun(times = plot.times,peak.titer = 1, displacement = displacement.overall.mean.IgG.ELISA.Spike, growth.rate = upperlim.igg.elisa.spike)

plot.times = 0:max(fit.dat.IgM.ELISA.Spike$time)
lowerlim.igm.elisa.out = titer.gompertz.fun(times = plot.times,peak.titer = 1, displacement = displacement.overall.mean.IgM.ELISA.Spike, growth.rate = lowerlim.igm.elisa.spike)
upperlim.igm.elisa.out = titer.gompertz.fun(times = plot.times,peak.titer = 1, displacement = displacement.overall.mean.IgM.ELISA.Spike, growth.rate = upperlim.igm.elisa.spike)


main.fit.function.igg.igm.elisa.spike$lowerlim = NA
main.fit.function.igg.igm.elisa.spike$upperlim = NA


main.fit.function.igg.igm.elisa.spike$lowerlim [ which(main.fit.function.igg.igm.elisa.spike$marker == "IgG ELISA (Spike)") ] = lowerlim.igg.elisa.out
main.fit.function.igg.igm.elisa.spike$upperlim [ which(main.fit.function.igg.igm.elisa.spike$marker == "IgG ELISA (Spike)") ] = upperlim.igg.elisa.out
main.fit.function.igg.igm.elisa.spike$lowerlim [ which(main.fit.function.igg.igm.elisa.spike$marker == "IgM ELISA (Spike)") ] = lowerlim.igm.elisa.out
main.fit.function.igg.igm.elisa.spike$upperlim [ which(main.fit.function.igg.igm.elisa.spike$marker == "IgM ELISA (Spike)") ] = upperlim.igm.elisa.out






ggplot(data=main.fit.function.igg.igm.elisa.spike,aes(x = time, y = value,group=marker,col=marker)) +
       #geom_line(data=fit.dat.all,aes(x = time, y = value,group = variable, col=assay),size=0.5,alpha=0.1) +
       #geom_ribbon(aes(x = plot.times,ymin = lowerlim.elisa.spike,ymax = upperlim.elisa.spike),col=col.rna,fill = col.rna,alpha=0.2) +
       geom_ribbon(aes(ymin = lowerlim,ymax = upperlim),fill = "none",alpha=0.6,linetype="dashed", show.legend=F) +
       geom_line(size=1.8) +
       #scale_x_continuous(breaks = seq(0,max(d2$time.start),2)) +
       scale_y_continuous(limits=c(0,1)) +
       #scale_color_gradientn(colors  =  rev(brewer.pal(11,"Spectral"))) +
       # scale_color_brewer(palette = "Spectral", name = "") +
       scale_color_manual(values = c(col.igg,col.igm),name="") +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size  = 12),
             text = element_text(size = 14),
             axis.text = element_text(size = 12),
             axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),
             legend.position  =  c(0.82,0.3),
             legend.background = element_rect(fill="white"),
             panel.background  =  element_rect(fill  =  'white')) +
       xlab("Days post symptom onset") +
       ylab("Antibody level")




ggplot(data=main.fit.function.igg.igm.elisa.spike,aes(x = time, y = value,group=marker,col=marker,fill=marker)) +
       #geom_line(data=fit.dat.all,aes(x = time, y = value,group = variable, col=assay),size=0.5,alpha=0.1) +
       #geom_ribbon(aes(x = plot.times,ymin = lowerlim.elisa.spike,ymax = upperlim.elisa.spike),col=col.rna,fill = col.rna,alpha=0.2) +
       geom_ribbon(aes(ymin = lowerlim,ymax = upperlim),alpha=0.2,linetype="dashed", show.legend=F) +
       geom_line(size=1.8) +
       #scale_x_continuous(breaks = seq(0,max(d2$time.start),2)) +
       scale_y_continuous(limits=c(0,1)) +
       #scale_color_gradientn(colors  =  rev(brewer.pal(11,"Spectral"))) +
       # scale_color_brewer(palette = "Spectral", name = "") +
       scale_fill_manual(values = c(col.igg,col.igm),name="") +
       scale_color_manual(values = c(col.igg,col.igm),name="") +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size  = 12),text = element_text(size = 14),axis.text = element_text(size = 12),axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),legend.position  =  c(0.82,0.3),legend.background = element_rect(fill="white"),panel.background  =  element_rect(fill  =  'white')) +
       xlab("Days post symptom onset") +
       ylab("Antibody level")




ggplot(data=main.fit.function.igg.igm.elisa.spike,aes(x = time, y = value,group=marker,col=marker)) +
       #geom_line(data=fit.dat.all,aes(x = time, y = value,group = variable, col=assay),size=0.5,alpha=0.1) +
       #geom_ribbon(aes(x = plot.times,ymin = lowerlim.elisa.spike,ymax = upperlim.elisa.spike),col=col.rna,fill = col.rna,alpha=0.2) +
       geom_line(data=fit.dat.all,aes(x = time, y = value,group = variable, col=marker),size=0.5,alpha=0.1) +
       geom_ribbon(aes(ymin = lowerlim,ymax = upperlim),fill="none",alpha=0.1,linetype="dashed", show.legend=F) +
       geom_line(size=1.8) +
       #scale_x_continuous(breaks = seq(0,max(d2$time.start),2)) +
       scale_y_continuous(limits=c(0,1)) +
       #scale_color_gradientn(colors  =  rev(brewer.pal(11,"Spectral"))) +
       # scale_color_brewer(palette = "Spectral", name = "") +
       scale_color_manual(values = c(col.igg,col.igm),name="") +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size  = 12),text = element_text(size = 14),axis.text = element_text(size = 12),axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),legend.position  =  c(0.82,0.3),legend.background = element_rect(fill="white"),panel.background  =  element_rect(fill  =  'white')) +
       xlab("Days post symptom onset") +
       ylab("Antibody level")




```



IgG/IgM ELISA Spike     
IgG/IgM ELISA NP     







### Growth rate comparison IgG, IgM, MCLIA ELISA    


#### Mean and se    

```{r fig.height=3,fig.width=7}

growth.rate.all.IgG.IgM.ELISA.Spike$marker = "IgG/IgM ELISA Spike"
growth.rate.all.IgG.IgM.ELISA.NP$marker = "IgG/IgM ELISA NP"

growth.rates = rbind(growth.rate.all.IgM.MCLIA,growth.rate.all.IgG.MCLIA,growth.rate.all.IgM.ELISA.Spike,growth.rate.all.IgG.ELISA.NP,growth.rate.all.IgM.ELISA.NP,growth.rate.all.IgG.ELISA.Spike)

colnames(growth.rates) = c("growth.rate","marker")


means_and_se = rbind(mean_se(growth.rate.all.IgM.MCLIA[,1]),
                     mean_se(growth.rate.all.IgG.MCLIA[,1]),
                     mean_se(growth.rate.all.IgM.ELISA.Spike[,1]),
                     mean_se(growth.rate.all.IgG.ELISA.NP[,1]),
                     mean_se(growth.rate.all.IgM.ELISA.NP[,1]),
                     mean_se(growth.rate.all.IgG.ELISA.Spike[,1]))

colnames(means_and_se)[1] = c("growth.rate")
means_and_se$marker = c("IgM MCLIA","IgG MCLIA","IgM ELISA Spike","IgG ELISA NP","IgM ELISA NP","IgG ELISA Spike")

means_and_se
```



#### Mean and 95% CrI     


```{r}


posterior.growth.rates = data.frame(marker = c("IgM MCLIA","IgG MCLIA","IgM ELISA Spike","IgG ELISA NP","IgM ELISA NP","IgG ELISA Spike","IgG/IgM ELISA NP","IgG/IgM ELISA Spike"), mean = NA, lowerci = NA, upperci = NA)


posterior.growth.rates$mean[which(posterior.growth.rates$marker == "IgM MCLIA")] = mean(posterior.growth.rates.IgM.MCLIA)
posterior.growth.rates[which(posterior.growth.rates$marker == "IgM MCLIA"),c("lowerci","upperci")] = HDInterval::hdi(density(posterior.growth.rates.IgM.MCLIA),credMass = 0.95,allowSplit=F)

posterior.growth.rates$mean[which(posterior.growth.rates$marker == "IgG MCLIA")] = mean(posterior.growth.rates.IgG.MCLIA)
posterior.growth.rates[which(posterior.growth.rates$marker == "IgG MCLIA"),c("lowerci","upperci")] = HDInterval::hdi(density(posterior.growth.rates.IgG.MCLIA),credMass = 0.95,allowSplit=F)

posterior.growth.rates$mean[which(posterior.growth.rates$marker == "IgM ELISA Spike")] = mean(posterior.growth.rates.IgM.ELISA.Spike)
posterior.growth.rates[which(posterior.growth.rates$marker == "IgM ELISA Spike"),c("lowerci","upperci")] = HDInterval::hdi(density(posterior.growth.rates.IgM.ELISA.Spike),credMass = 0.95,allowSplit=F)

posterior.growth.rates$mean[which(posterior.growth.rates$marker == "IgG ELISA Spike")] = mean(posterior.growth.rates.IgG.ELISA.Spike)
posterior.growth.rates[which(posterior.growth.rates$marker == "IgG ELISA Spike"),c("lowerci","upperci")] = HDInterval::hdi(density(posterior.growth.rates.IgG.ELISA.Spike),credMass = 0.95,allowSplit=F)

posterior.growth.rates$mean[which(posterior.growth.rates$marker == "IgM ELISA NP")] = mean(posterior.growth.rates.IgM.ELISA.NP)
posterior.growth.rates[which(posterior.growth.rates$marker == "IgM ELISA NP"),c("lowerci","upperci")] = HDInterval::hdi(density(posterior.growth.rates.IgM.ELISA.NP),credMass = 0.95,allowSplit=F)

posterior.growth.rates$mean[which(posterior.growth.rates$marker == "IgG ELISA NP")] = mean(posterior.growth.rates.IgG.ELISA.NP)
posterior.growth.rates[which(posterior.growth.rates$marker == "IgG ELISA NP"),c("lowerci","upperci")] = HDInterval::hdi(density(posterior.growth.rates.IgG.ELISA.NP),credMass = 0.95,allowSplit=F)

posterior.growth.rates$mean[which(posterior.growth.rates$marker == "IgG/IgM ELISA NP")] = mean(posterior.growth.rates.IgG.IgM.ELISA.NP)
posterior.growth.rates[which(posterior.growth.rates$marker == "IgG/IgM ELISA NP"),c("lowerci","upperci")] = HDInterval::hdi(density(posterior.growth.rates.IgG.IgM.ELISA.NP),credMass = 0.95,allowSplit=F)

posterior.growth.rates$mean[which(posterior.growth.rates$marker == "IgG/IgM ELISA Spike")] = mean(posterior.growth.rates.IgG.IgM.ELISA.Spike)
posterior.growth.rates[which(posterior.growth.rates$marker == "IgG/IgM ELISA Spike"),c("lowerci","upperci")] = HDInterval::hdi(density(posterior.growth.rates.IgG.IgM.ELISA.Spike),credMass = 0.95,allowSplit=F)


posterior.growth.rates


```



#### Pairwise difference of means     



```{r}


posterior.growth.rate.differences = data.frame(markers = c("IgM MCLIA - IgG MCLIA",
                                                           "IgM MCLIA - IgG ELISA Spike",
                                                           "IgM MCLIA - IgM ELISA Spike",
                                                           "IgM MCLIA - IgG ELISA NP",
                                                           "IgM MCLIA - IgM ELISA NP",
                                                           "IgG MCLIA - IgG ELISA Spike",
                                                           "IgG MCLIA - IgM ELISA Spike",
                                                           "IgG MCLIA - IgG ELISA NP",
                                                           "IgG MCLIA - IgM ELISA NP",
                                                           "IgM ELISA Spike - IgG ELISA Spike",
                                                           "IgM ELISA Spike - IgG ELISA NP",
                                                           "IgM ELISA Spike - IgM ELISA NP",
                                                           "IgG ELISA Spike - IgG ELISA NP",
                                                           "IgG ELISA Spike - IgM ELISA NP",
                                                           "IgG ELISA NP - IgM ELISA NP",
                                                           "IgG/IGM ELISA NP - IgG/IgM ELISA Spike"),difference.means = NA, lowerci = NA, upperci = NA)


post.diffs = data.frame(diffs = posterior.growth.rates.IgM.MCLIA - posterior.growth.rates.IgG.MCLIA)
posterior.growth.rate.differences[which(posterior.growth.rate.differences$markers == "IgM MCLIA - IgG MCLIA"),c("lowerci","upperci")] = HDInterval::hdi(density(post.diffs$diffs),credMass = 0.95,allowSplit=F)  
posterior.growth.rate.differences[which(posterior.growth.rate.differences$markers == "IgM MCLIA - IgG MCLIA"),c("difference.means")] = mean(post.diffs$diffs)

post.diffs = data.frame(diffs = posterior.growth.rates.IgM.MCLIA - posterior.growth.rates.IgG.ELISA.Spike)
posterior.growth.rate.differences[which(posterior.growth.rate.differences$markers == "IgM MCLIA - IgG ELISA Spike"),c("lowerci","upperci")] = HDInterval::hdi(density(post.diffs$diffs),credMass = 0.95,allowSplit=F)  
posterior.growth.rate.differences[which(posterior.growth.rate.differences$markers == "IgM MCLIA - IgG ELISA Spike"),c("difference.means")] = mean(post.diffs$diffs)

post.diffs = data.frame(diffs = posterior.growth.rates.IgM.MCLIA - posterior.growth.rates.IgM.ELISA.Spike)
posterior.growth.rate.differences[which(posterior.growth.rate.differences$markers == "IgM MCLIA - IgM ELISA Spike"),c("lowerci","upperci")] = HDInterval::hdi(density(post.diffs$diffs),credMass = 0.95,allowSplit=F)  
posterior.growth.rate.differences[which(posterior.growth.rate.differences$markers == "IgM MCLIA - IgM ELISA Spike"),c("difference.means")] = mean(post.diffs$diffs)

post.diffs = data.frame(diffs = posterior.growth.rates.IgM.MCLIA - posterior.growth.rates.IgG.ELISA.NP)
posterior.growth.rate.differences[which(posterior.growth.rate.differences$markers == "IgM MCLIA - IgG ELISA NP"),c("lowerci","upperci")] = HDInterval::hdi(density(post.diffs$diffs),credMass = 0.95,allowSplit=F)  
posterior.growth.rate.differences[which(posterior.growth.rate.differences$markers == "IgM MCLIA - IgG ELISA NP"),c("difference.means")] = mean(post.diffs$diffs)

post.diffs = data.frame(diffs = posterior.growth.rates.IgM.MCLIA - posterior.growth.rates.IgM.ELISA.NP)
posterior.growth.rate.differences[which(posterior.growth.rate.differences$markers == "IgM MCLIA - IgM ELISA NP"),c("lowerci","upperci")] = HDInterval::hdi(density(post.diffs$diffs),credMass = 0.95,allowSplit=F)  
posterior.growth.rate.differences[which(posterior.growth.rate.differences$markers == "IgM MCLIA - IgM ELISA NP"),c("difference.means")] = mean(post.diffs$diffs)

post.diffs = data.frame(diffs = posterior.growth.rates.IgG.MCLIA - posterior.growth.rates.IgG.ELISA.Spike)
posterior.growth.rate.differences[which(posterior.growth.rate.differences$markers == "IgG MCLIA - IgG ELISA Spike"),c("lowerci","upperci")] = HDInterval::hdi(density(post.diffs$diffs),credMass = 0.95,allowSplit=F)  
posterior.growth.rate.differences[which(posterior.growth.rate.differences$markers == "IgG MCLIA - IgG ELISA Spike"),c("difference.means")] = mean(post.diffs$diffs)

post.diffs = data.frame(diffs = posterior.growth.rates.IgG.MCLIA - posterior.growth.rates.IgM.ELISA.Spike)
posterior.growth.rate.differences[which(posterior.growth.rate.differences$markers == "IgG MCLIA - IgM ELISA Spike"),c("lowerci","upperci")] = HDInterval::hdi(density(post.diffs$diffs),credMass = 0.95,allowSplit=F)  
posterior.growth.rate.differences[which(posterior.growth.rate.differences$markers == "IgG MCLIA - IgM ELISA Spike"),c("difference.means")] = mean(post.diffs$diffs)

post.diffs = data.frame(diffs = posterior.growth.rates.IgG.MCLIA - posterior.growth.rates.IgG.ELISA.NP)
posterior.growth.rate.differences[which(posterior.growth.rate.differences$markers == "IgG MCLIA - IgG ELISA NP"),c("lowerci","upperci")] = HDInterval::hdi(density(post.diffs$diffs),credMass = 0.95,allowSplit=F)  
posterior.growth.rate.differences[which(posterior.growth.rate.differences$markers == "IgG MCLIA - IgG ELISA NP"),c("difference.means")] = mean(post.diffs$diffs)

post.diffs = data.frame(diffs = posterior.growth.rates.IgG.MCLIA - posterior.growth.rates.IgM.ELISA.NP)
posterior.growth.rate.differences[which(posterior.growth.rate.differences$markers == "IgG MCLIA - IgM ELISA NP"),c("lowerci","upperci")] = HDInterval::hdi(density(post.diffs$diffs),credMass = 0.95,allowSplit=F)  
posterior.growth.rate.differences[which(posterior.growth.rate.differences$markers == "IgG MCLIA - IgM ELISA NP"),c("difference.means")] = mean(post.diffs$diffs)

post.diffs = data.frame(diffs = posterior.growth.rates.IgM.ELISA.Spike - posterior.growth.rates.IgG.ELISA.Spike)
posterior.growth.rate.differences[which(posterior.growth.rate.differences$markers == "IgM ELISA Spike - IgG ELISA Spike"),c("lowerci","upperci")] = HDInterval::hdi(density(post.diffs$diffs),credMass = 0.95,allowSplit=F)  
posterior.growth.rate.differences[which(posterior.growth.rate.differences$markers == "IgM ELISA Spike - IgG ELISA Spike"),c("difference.means")] = mean(post.diffs$diffs)

post.diffs = data.frame(diffs = posterior.growth.rates.IgM.ELISA.Spike - posterior.growth.rates.IgG.ELISA.NP)
posterior.growth.rate.differences[which(posterior.growth.rate.differences$markers == "IgM ELISA Spike - IgG ELISA NP"),c("lowerci","upperci")] = HDInterval::hdi(density(post.diffs$diffs),credMass = 0.95,allowSplit=F)  
posterior.growth.rate.differences[which(posterior.growth.rate.differences$markers == "IgM ELISA Spike - IgG ELISA NP"),c("difference.means")] = mean(post.diffs$diffs)

post.diffs = data.frame(diffs = posterior.growth.rates.IgM.ELISA.Spike - posterior.growth.rates.IgM.ELISA.NP)
posterior.growth.rate.differences[which(posterior.growth.rate.differences$markers == "IgM ELISA Spike - IgM ELISA NP"),c("lowerci","upperci")] = HDInterval::hdi(density(post.diffs$diffs),credMass = 0.95,allowSplit=F)  
posterior.growth.rate.differences[which(posterior.growth.rate.differences$markers == "IgM ELISA Spike - IgM ELISA NP"),c("difference.means")] = mean(post.diffs$diffs)

post.diffs = data.frame(diffs = posterior.growth.rates.IgG.ELISA.Spike - posterior.growth.rates.IgG.ELISA.NP)
posterior.growth.rate.differences[which(posterior.growth.rate.differences$markers == "IgG ELISA Spike - IgG ELISA NP"),c("lowerci","upperci")] = HDInterval::hdi(density(post.diffs$diffs),credMass = 0.95,allowSplit=F)  
posterior.growth.rate.differences[which(posterior.growth.rate.differences$markers == "IgG ELISA Spike - IgG ELISA NP"),c("difference.means")] = mean(post.diffs$diffs)

post.diffs = data.frame(diffs = posterior.growth.rates.IgG.ELISA.Spike - posterior.growth.rates.IgM.ELISA.NP)
posterior.growth.rate.differences[which(posterior.growth.rate.differences$markers == "IgG ELISA Spike - IgM ELISA NP"),c("lowerci","upperci")] = HDInterval::hdi(density(post.diffs$diffs),credMass = 0.95,allowSplit=F)  
posterior.growth.rate.differences[which(posterior.growth.rate.differences$markers == "IgG ELISA Spike - IgM ELISA NP"),c("difference.means")] = mean(post.diffs$diffs)

post.diffs = data.frame(diffs = posterior.growth.rates.IgG.ELISA.NP - posterior.growth.rates.IgM.ELISA.NP)
posterior.growth.rate.differences[which(posterior.growth.rate.differences$markers == "IgG ELISA NP - IgM ELISA NP"),c("lowerci","upperci")] = HDInterval::hdi(density(post.diffs$diffs),credMass = 0.95,allowSplit=F)  
posterior.growth.rate.differences[which(posterior.growth.rate.differences$markers == "IgG ELISA NP - IgM ELISA NP"),c("difference.means")] = mean(post.diffs$diffs)

post.diffs = data.frame(diffs = posterior.growth.rates.IgG.IgM.ELISA.NP - posterior.growth.rates.IgG.IgM.ELISA.Spike)
posterior.growth.rate.differences[which(posterior.growth.rate.differences$markers == "IgG/IGM ELISA NP - IgG/IgM ELISA Spike"),c("lowerci","upperci")] = HDInterval::hdi(density(post.diffs$diffs),credMass = 0.95,allowSplit=F)  
posterior.growth.rate.differences[which(posterior.growth.rate.differences$markers == "IgG/IGM ELISA NP - IgG/IgM ELISA Spike"),c("difference.means")] = mean(post.diffs$diffs)


posterior.growth.rate.differences

```




#### ANOVA   


```{r}

growth.rates$antibody = NA
growth.rates$antibody [grep("IgG",growth.rates$marker)] = "IgG"
growth.rates$antibody [grep("IgM",growth.rates$marker)] = "IgM"
growth.rates$assay = NA
growth.rates$assay [grep("NP",growth.rates$marker)] = "ELISA NP"
growth.rates$assay [grep("Spike",growth.rates$marker)] = "ELISA Spike"
growth.rates$assay [grep("MCLIA",growth.rates$marker)] = "MCLIA"



# glm binomial or lm normal?
# glm1 = glm(growth.rate~antibody + assay, data = growth.rates, family="binomial")
# lm1 = lm(growth.rate~antibody + assay, data = growth.rates)
# plot(lm1)  # ==> good fit, nice residuals, and fits interpretation when looking at figures
# plot(glm1)

lm1 = lm(growth.rate~assay + antibody + antibody*assay, data = growth.rates)
summary(lm1)

lm1 = lm(growth.rate~assay + antibody + antibody*assay, data = growth.rates[-which(growth.rates$assay=="MCLIA"),])
summary(lm1)




```


#### T tests    

```{r fig.height=3,fig.width=7}
t.test(growth.rate.all.IgM.MCLIA[,1],growth.rate.all.IgG.MCLIA[,1])
t.test(growth.rate.all.IgM.MCLIA[,1],growth.rate.all.IgM.ELISA.Spike[,1])
t.test(growth.rate.all.IgM.MCLIA[,1],growth.rate.all.IgG.ELISA.NP[,1])
t.test(growth.rate.all.IgM.ELISA.Spike[,1],growth.rate.all.IgM.ELISA.NP[,1])
t.test(growth.rate.all.IgM.ELISA.Spike[,1],growth.rate.all.IgG.ELISA.Spike[,1])

t.test(growth.rate.all.IgG.MCLIA[,1],growth.rate.all.IgM.ELISA.Spike[,1])
t.test(growth.rate.all.IgG.MCLIA[,1],growth.rate.all.IgG.ELISA.NP[,1])
t.test(growth.rate.all.IgG.MCLIA[,1],growth.rate.all.IgM.ELISA.NP[,1])
t.test(growth.rate.all.IgG.MCLIA[,1],growth.rate.all.IgG.ELISA.Spike[,1])

t.test(growth.rate.all.IgM.ELISA.Spike[,1],growth.rate.all.IgG.ELISA.NP[,1])
t.test(growth.rate.all.IgM.ELISA.Spike[,1],growth.rate.all.IgM.ELISA.NP[,1])
t.test(growth.rate.all.IgM.ELISA.Spike[,1],growth.rate.all.IgG.ELISA.Spike[,1])

t.test(growth.rate.all.IgG.ELISA.NP[,1],growth.rate.all.IgM.ELISA.NP[,1])
t.test(growth.rate.all.IgG.ELISA.NP[,1],growth.rate.all.IgG.ELISA.Spike[,1])

t.test(growth.rate.all.IgM.ELISA.NP[,1],growth.rate.all.IgG.ELISA.Spike[,1])

t.test(growth.rates$growth.rate[which(growth.rates$assay == "ELISA Spike")],growth.rates$growth.rate[which(growth.rates$assay == "ELISA NP")])

mean_se(growth.rates$growth.rate[which(growth.rates$assay == "ELISA Spike")])
mean_se(growth.rates$growth.rate[which(growth.rates$assay == "ELISA NP")])

cols = c("IgM MCLIA" = col.ntab, "IgG MCLIA" = col.mclia, "IgM ELISA Spike" = col.severe.igm, "IgG ELISA NP" = col.igg,"IgM ELISA NP" = col.elisa, "IgG ELISA Spike" = col.mild.igm)


ggplot(data = growth.rates,aes(x=marker, y = growth.rate,col=marker)) +
       geom_jitter(width=0.1) +
       geom_point(data = means_and_se, aes(x = marker, y = growth.rate),col="red",shape=19,size=3,alpha=0.5) +
       geom_errorbar(data = means_and_se, aes(ymin = ymin, ymax = ymax),width = 0.1,col="red",alpha=0.5) +
       
       #scale_x_continuous(breaks = seq(0,(max(boot.samples.df.tp7$boot.samples)+2),5),limits=c(0,max(boot.samples.df.tp7$boot.samples+2))) +
       ylab("Growth rate (1/days)") +
       scale_color_manual(values = cols) +
       xlab("") +
       ggtitle("") +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size  = 12),text = element_text(size = 12),axis.text = element_text(size = 12),axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),axis.ticks.x = element_blank(),axis.text.x = element_blank(),legend.title = element_blank(),panel.background  =  element_rect(fill  =  'white'))



```


```{r fig.height=3,fig.width=7}

growth.rates = rbind(growth.rate.all.IgM.ELISA.NP,growth.rate.all.IgG.ELISA.Spike,growth.rate.all.IgM.ELISA.Spike,growth.rate.all.IgG.ELISA.NP)

colnames(growth.rates) = c("growth.rate","marker")


means_and_se = rbind(mean_se(growth.rate.all.IgM.ELISA.NP[,1]),
                     mean_se(growth.rate.all.IgG.ELISA.Spike[,1]),
                     mean_se(growth.rate.all.IgM.ELISA.Spike[,1]),
                     mean_se(growth.rate.all.IgG.ELISA.NP[,1]))

colnames(means_and_se)[1] = c("growth.rate")
means_and_se$marker = c("IgM ELISA NP","IgG ELISA Spike","IgM ELISA Spike","IgG ELISA NP")



cols = c("IgM ELISA NP" = col.rna3, "IgG ELISA Spike" = col.rna, "IgM ELISA Spike" = col.igm, "IgG ELISA NP" = col.igg)


plot.growth = ggplot(data = growth.rates,aes(x=marker, y = growth.rate,col=marker)) +
       geom_jitter(width=0.1,alpha=0.8) +
       geom_point(data = means_and_se, aes(x = marker, y = growth.rate),col="red",shape=19,size=3,alpha=0.5) +
       geom_errorbar(data = means_and_se, aes(ymin = ymin, ymax = ymax),width = 0.1,col="red",alpha=0.5) +
       
       #scale_x_continuous(breaks = seq(0,(max(boot.samples.df.tp7$boot.samples)+2),5),limits=c(0,max(boot.samples.df.tp7$boot.samples+2))) +
       scale_y_continuous(breaks = seq(0.2,1,0.1)) +
       ylab("Growth rate (1/days)") +
       annotate("text", label = "B", x = 0.55,y=0.95,size=7) +
       scale_color_manual(values = cols) +
       xlab("") +
       ggtitle("") +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size  = 12),text = element_text(size = 12),axis.text = element_text(size = 12),axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),axis.ticks.x = element_blank(),axis.text.x = element_blank(),legend.position = c(0.85,0.85),legend.key = element_rect(color = "transparent"),legend.title = element_blank(),panel.background  =  element_rect(fill  =  'white'))



plot.growth

```







```{r fig.width=11, fig.height=4}

plot.main.functions.combined + plot.growth  
```









### Peak titer timing comparison IgG, IgM, ELISA NP vs Spike      


```{r fig.height=4,fig.width=7}
means_and_se = rbind(means_and_se.peak.titer.igg,means_and_se.peak.titer.igm)
means_and_se



cols = c("IgM ELISA Spike" = col.igm, "IgM ELISA NP" = col.rna3,"IgG ELISA Spike" = col.rna, "IgG ELISA NP" = col.igg)

peak.titer.time.igg.igm.df = rbind(peak.titer.time.igg.df,peak.titer.time.igm.df)

peak.titer.time.igg.igm.df



```



#### Mean and 95% CrI     


```{r}


posterior.peak.titer.times = data.frame(marker = c("IgM MCLIA","IgG MCLIA","IgM ELISA Spike","IgG ELISA NP","IgM ELISA NP","IgG ELISA Spike","IgG/IgM ELISA NP","IgG/IgM ELISA Spike"), mean = NA, lowerci = NA, upperci = NA)


posterior.peak.titer.times$mean[which(posterior.peak.titer.times$marker == "IgM MCLIA")] = mean(posterior.peak.titer.times.IgM.MCLIA)
posterior.peak.titer.times[which(posterior.peak.titer.times$marker == "IgM MCLIA"),c("lowerci","upperci")] = HDInterval::hdi(density(posterior.peak.titer.times.IgM.MCLIA),credMass = 0.95,allowSplit=F)

posterior.peak.titer.times$mean[which(posterior.peak.titer.times$marker == "IgG MCLIA")] = mean(posterior.peak.titer.times.IgG.MCLIA)
posterior.peak.titer.times[which(posterior.peak.titer.times$marker == "IgG MCLIA"),c("lowerci","upperci")] = HDInterval::hdi(density(posterior.peak.titer.times.IgG.MCLIA),credMass = 0.95,allowSplit=F)

posterior.peak.titer.times$mean[which(posterior.peak.titer.times$marker == "IgM ELISA Spike")] = mean(posterior.peak.titer.times.IgM.ELISA.Spike)
posterior.peak.titer.times[which(posterior.peak.titer.times$marker == "IgM ELISA Spike"),c("lowerci","upperci")] = HDInterval::hdi(density(posterior.peak.titer.times.IgM.ELISA.Spike),credMass = 0.95,allowSplit=F)

posterior.peak.titer.times$mean[which(posterior.peak.titer.times$marker == "IgG ELISA Spike")] = mean(posterior.peak.titer.times.IgG.ELISA.Spike)
posterior.peak.titer.times[which(posterior.peak.titer.times$marker == "IgG ELISA Spike"),c("lowerci","upperci")] = HDInterval::hdi(density(posterior.peak.titer.times.IgG.ELISA.Spike),credMass = 0.95,allowSplit=F)

posterior.peak.titer.times$mean[which(posterior.peak.titer.times$marker == "IgM ELISA NP")] = mean(posterior.peak.titer.times.IgM.ELISA.NP)
posterior.peak.titer.times[which(posterior.peak.titer.times$marker == "IgM ELISA NP"),c("lowerci","upperci")] = HDInterval::hdi(density(posterior.peak.titer.times.IgM.ELISA.NP),credMass = 0.95,allowSplit=F)

posterior.peak.titer.times$mean[which(posterior.peak.titer.times$marker == "IgG ELISA NP")] = mean(posterior.peak.titer.times.IgG.ELISA.NP)
posterior.peak.titer.times[which(posterior.peak.titer.times$marker == "IgG ELISA NP"),c("lowerci","upperci")] = HDInterval::hdi(density(posterior.peak.titer.times.IgG.ELISA.NP),credMass = 0.95,allowSplit=F)

posterior.peak.titer.times$mean[which(posterior.peak.titer.times$marker == "IgG/IgM ELISA NP")] = mean(posterior.peak.titer.times.IgG.IgM.ELISA.NP)
posterior.peak.titer.times[which(posterior.peak.titer.times$marker == "IgG/IgM ELISA NP"),c("lowerci","upperci")] = HDInterval::hdi(density(posterior.peak.titer.times.IgG.IgM.ELISA.NP),credMass = 0.95,allowSplit=F)

posterior.peak.titer.times$mean[which(posterior.peak.titer.times$marker == "IgG/IgM ELISA Spike")] = mean(posterior.peak.titer.times.IgG.IgM.ELISA.Spike)
posterior.peak.titer.times[which(posterior.peak.titer.times$marker == "IgG/IgM ELISA Spike"),c("lowerci","upperci")] = HDInterval::hdi(density(posterior.peak.titer.times.IgG.IgM.ELISA.Spike),credMass = 0.95,allowSplit=F)


posterior.peak.titer.times


```



#### Pairwise difference of means     



```{r}


posterior.peak.titer.time.differences = data.frame(markers = c("IgM MCLIA - IgG MCLIA",
                                                               "IgM MCLIA - IgG ELISA Spike",
                                                               "IgM MCLIA - IgM ELISA Spike",
                                                               "IgM MCLIA - IgG ELISA NP",
                                                               "IgM MCLIA - IgM ELISA NP",
                                                               "IgG MCLIA - IgG ELISA Spike",
                                                               "IgG MCLIA - IgM ELISA Spike",
                                                               "IgG MCLIA - IgG ELISA NP",
                                                               "IgG MCLIA - IgM ELISA NP",
                                                               "IgM ELISA Spike - IgG ELISA Spike",
                                                               "IgM ELISA Spike - IgG ELISA NP",
                                                               "IgM ELISA Spike - IgM ELISA NP",
                                                               "IgG ELISA Spike - IgG ELISA NP",
                                                               "IgG ELISA Spike - IgM ELISA NP",
                                                               "IgG ELISA NP - IgM ELISA NP",
                                                               "IgG/IGM ELISA NP - IgG/IgM ELISA Spike"),difference.means = NA, lowerci = NA, upperci = NA)


post.diffs = data.frame(diffs = posterior.peak.titer.times.IgM.MCLIA - posterior.peak.titer.times.IgG.MCLIA)
posterior.peak.titer.time.differences[which(posterior.peak.titer.time.differences$markers == "IgM MCLIA - IgG MCLIA"),c("lowerci","upperci")] = HDInterval::hdi(density(post.diffs$diffs),credMass = 0.95,allowSplit=F)  
posterior.peak.titer.time.differences[which(posterior.peak.titer.time.differences$markers == "IgM MCLIA - IgG MCLIA"),c("difference.means")] = mean(post.diffs$diffs)

post.diffs = data.frame(diffs = posterior.peak.titer.times.IgM.MCLIA - posterior.peak.titer.times.IgG.ELISA.Spike)
posterior.peak.titer.time.differences[which(posterior.peak.titer.time.differences$markers == "IgM MCLIA - IgG ELISA Spike"),c("lowerci","upperci")] = HDInterval::hdi(density(post.diffs$diffs),credMass = 0.95,allowSplit=F)  
posterior.peak.titer.time.differences[which(posterior.peak.titer.time.differences$markers == "IgM MCLIA - IgG ELISA Spike"),c("difference.means")] = mean(post.diffs$diffs)

post.diffs = data.frame(diffs = posterior.peak.titer.times.IgM.MCLIA - posterior.peak.titer.times.IgM.ELISA.Spike)
posterior.peak.titer.time.differences[which(posterior.peak.titer.time.differences$markers == "IgM MCLIA - IgM ELISA Spike"),c("lowerci","upperci")] = HDInterval::hdi(density(post.diffs$diffs),credMass = 0.95,allowSplit=F)  
posterior.peak.titer.time.differences[which(posterior.peak.titer.time.differences$markers == "IgM MCLIA - IgM ELISA Spike"),c("difference.means")] = mean(post.diffs$diffs)

post.diffs = data.frame(diffs = posterior.peak.titer.times.IgM.MCLIA - posterior.peak.titer.times.IgG.ELISA.NP)
posterior.peak.titer.time.differences[which(posterior.peak.titer.time.differences$markers == "IgM MCLIA - IgG ELISA NP"),c("lowerci","upperci")] = HDInterval::hdi(density(post.diffs$diffs),credMass = 0.95,allowSplit=F)  
posterior.peak.titer.time.differences[which(posterior.peak.titer.time.differences$markers == "IgM MCLIA - IgG ELISA NP"),c("difference.means")] = mean(post.diffs$diffs)

post.diffs = data.frame(diffs = posterior.peak.titer.times.IgM.MCLIA - posterior.peak.titer.times.IgM.ELISA.NP)
posterior.peak.titer.time.differences[which(posterior.peak.titer.time.differences$markers == "IgM MCLIA - IgM ELISA NP"),c("lowerci","upperci")] = HDInterval::hdi(density(post.diffs$diffs),credMass = 0.95,allowSplit=F)  
posterior.peak.titer.time.differences[which(posterior.peak.titer.time.differences$markers == "IgM MCLIA - IgM ELISA NP"),c("difference.means")] = mean(post.diffs$diffs)

post.diffs = data.frame(diffs = posterior.peak.titer.times.IgG.MCLIA - posterior.peak.titer.times.IgG.ELISA.Spike)
posterior.peak.titer.time.differences[which(posterior.peak.titer.time.differences$markers == "IgG MCLIA - IgG ELISA Spike"),c("lowerci","upperci")] = HDInterval::hdi(density(post.diffs$diffs),credMass = 0.95,allowSplit=F)  
posterior.peak.titer.time.differences[which(posterior.peak.titer.time.differences$markers == "IgG MCLIA - IgG ELISA Spike"),c("difference.means")] = mean(post.diffs$diffs)

post.diffs = data.frame(diffs = posterior.peak.titer.times.IgG.MCLIA - posterior.peak.titer.times.IgM.ELISA.Spike)
posterior.peak.titer.time.differences[which(posterior.peak.titer.time.differences$markers == "IgG MCLIA - IgM ELISA Spike"),c("lowerci","upperci")] = HDInterval::hdi(density(post.diffs$diffs),credMass = 0.95,allowSplit=F)  
posterior.peak.titer.time.differences[which(posterior.peak.titer.time.differences$markers == "IgG MCLIA - IgM ELISA Spike"),c("difference.means")] = mean(post.diffs$diffs)

post.diffs = data.frame(diffs = posterior.peak.titer.times.IgG.MCLIA - posterior.peak.titer.times.IgG.ELISA.NP)
posterior.peak.titer.time.differences[which(posterior.peak.titer.time.differences$markers == "IgG MCLIA - IgG ELISA NP"),c("lowerci","upperci")] = HDInterval::hdi(density(post.diffs$diffs),credMass = 0.95,allowSplit=F)  
posterior.peak.titer.time.differences[which(posterior.peak.titer.time.differences$markers == "IgG MCLIA - IgG ELISA NP"),c("difference.means")] = mean(post.diffs$diffs)

post.diffs = data.frame(diffs = posterior.peak.titer.times.IgG.MCLIA - posterior.peak.titer.times.IgM.ELISA.NP)
posterior.peak.titer.time.differences[which(posterior.peak.titer.time.differences$markers == "IgG MCLIA - IgM ELISA NP"),c("lowerci","upperci")] = HDInterval::hdi(density(post.diffs$diffs),credMass = 0.95,allowSplit=F)  
posterior.peak.titer.time.differences[which(posterior.peak.titer.time.differences$markers == "IgG MCLIA - IgM ELISA NP"),c("difference.means")] = mean(post.diffs$diffs)

post.diffs = data.frame(diffs = posterior.peak.titer.times.IgM.ELISA.Spike - posterior.peak.titer.times.IgG.ELISA.Spike)
posterior.peak.titer.time.differences[which(posterior.peak.titer.time.differences$markers == "IgM ELISA Spike - IgG ELISA Spike"),c("lowerci","upperci")] = HDInterval::hdi(density(post.diffs$diffs),credMass = 0.95,allowSplit=F)  
posterior.peak.titer.time.differences[which(posterior.peak.titer.time.differences$markers == "IgM ELISA Spike - IgG ELISA Spike"),c("difference.means")] = mean(post.diffs$diffs)

post.diffs = data.frame(diffs = posterior.peak.titer.times.IgM.ELISA.Spike - posterior.peak.titer.times.IgG.ELISA.NP)
posterior.peak.titer.time.differences[which(posterior.peak.titer.time.differences$markers == "IgM ELISA Spike - IgG ELISA NP"),c("lowerci","upperci")] = HDInterval::hdi(density(post.diffs$diffs),credMass = 0.95,allowSplit=F)  
posterior.peak.titer.time.differences[which(posterior.peak.titer.time.differences$markers == "IgM ELISA Spike - IgG ELISA NP"),c("difference.means")] = mean(post.diffs$diffs)

post.diffs = data.frame(diffs = posterior.peak.titer.times.IgM.ELISA.Spike - posterior.peak.titer.times.IgM.ELISA.NP)
posterior.peak.titer.time.differences[which(posterior.peak.titer.time.differences$markers == "IgM ELISA Spike - IgM ELISA NP"),c("lowerci","upperci")] = HDInterval::hdi(density(post.diffs$diffs),credMass = 0.95,allowSplit=F)  
posterior.peak.titer.time.differences[which(posterior.peak.titer.time.differences$markers == "IgM ELISA Spike - IgM ELISA NP"),c("difference.means")] = mean(post.diffs$diffs)

post.diffs = data.frame(diffs = posterior.peak.titer.times.IgG.ELISA.Spike - posterior.peak.titer.times.IgG.ELISA.NP)
posterior.peak.titer.time.differences[which(posterior.peak.titer.time.differences$markers == "IgG ELISA Spike - IgG ELISA NP"),c("lowerci","upperci")] = HDInterval::hdi(density(post.diffs$diffs),credMass = 0.95,allowSplit=F)  
posterior.peak.titer.time.differences[which(posterior.peak.titer.time.differences$markers == "IgG ELISA Spike - IgG ELISA NP"),c("difference.means")] = mean(post.diffs$diffs)

post.diffs = data.frame(diffs = posterior.peak.titer.times.IgG.ELISA.Spike - posterior.peak.titer.times.IgM.ELISA.NP)
posterior.peak.titer.time.differences[which(posterior.peak.titer.time.differences$markers == "IgG ELISA Spike - IgM ELISA NP"),c("lowerci","upperci")] = HDInterval::hdi(density(post.diffs$diffs),credMass = 0.95,allowSplit=F)  
posterior.peak.titer.time.differences[which(posterior.peak.titer.time.differences$markers == "IgG ELISA Spike - IgM ELISA NP"),c("difference.means")] = mean(post.diffs$diffs)

post.diffs = data.frame(diffs = posterior.peak.titer.times.IgG.ELISA.NP - posterior.peak.titer.times.IgM.ELISA.NP)
posterior.peak.titer.time.differences[which(posterior.peak.titer.time.differences$markers == "IgG ELISA NP - IgM ELISA NP"),c("lowerci","upperci")] = HDInterval::hdi(density(post.diffs$diffs),credMass = 0.95,allowSplit=F)  
posterior.peak.titer.time.differences[which(posterior.peak.titer.time.differences$markers == "IgG ELISA NP - IgM ELISA NP"),c("difference.means")] = mean(post.diffs$diffs)

post.diffs = data.frame(diffs = posterior.peak.titer.times.IgG.IgM.ELISA.NP - posterior.peak.titer.times.IgG.IgM.ELISA.Spike)
posterior.peak.titer.time.differences[which(posterior.peak.titer.time.differences$markers == "IgG/IGM ELISA NP - IgG/IgM ELISA Spike"),c("lowerci","upperci")] = HDInterval::hdi(density(post.diffs$diffs),credMass = 0.95,allowSplit=F)  
posterior.peak.titer.time.differences[which(posterior.peak.titer.time.differences$markers == "IgG/IGM ELISA NP - IgG/IgM ELISA Spike"),c("difference.means")] = mean(post.diffs$diffs)


posterior.peak.titer.time.differences

```





#### ANOVA    

```{r fig.height=4,fig.width=7}
peak.titer.time.igg.igm.df$antibody = NA
peak.titer.time.igg.igm.df$antibody [grep("IgG",peak.titer.time.igg.igm.df$marker)] = "IgG"
peak.titer.time.igg.igm.df$antibody [grep("IgM",peak.titer.time.igg.igm.df$marker)] = "IgM"
peak.titer.time.igg.igm.df$assay = NA
peak.titer.time.igg.igm.df$assay [grep("NP",peak.titer.time.igg.igm.df$marker)] = "ELISA NP"
peak.titer.time.igg.igm.df$assay [grep("Spike",peak.titer.time.igg.igm.df$marker)] = "ELISA Spike"
peak.titer.time.igg.igm.df$assay [grep("MCLIA",peak.titer.time.igg.igm.df$marker)] = "MCLIA"

mean_se(peak.titer.time.igg.igm.df$peak.titer.time[which(peak.titer.time.igg.igm.df$antibody=="IgG" & peak.titer.time.igg.igm.df$assay %in% c("ELISA NP","ELISA Spike"))])
mean_se(peak.titer.time.igg.igm.df$peak.titer.time[which(peak.titer.time.igg.igm.df$antibody=="IgM" & peak.titer.time.igg.igm.df$assay %in% c("ELISA NP","ELISA Spike"))])
mean_se(peak.titer.time.igg.igm.df$peak.titer.time[which(peak.titer.time.igg.igm.df$assay %in% c("ELISA Spike"))])
mean_se(peak.titer.time.igg.igm.df$peak.titer.time[which(peak.titer.time.igg.igm.df$assay %in% c("ELISA NP"))])



lm1 = lm(peak.titer.time~assay + antibody + antibody*assay, data = peak.titer.time.igg.igm.df)
lm2 = lm(peak.titer.time~assay + antibody, data = peak.titer.time.igg.igm.df)
#plot(lm1)    # residuals look good
anova(lm1,lm2)   # no significant interaction ==> remove


summary(lm2)


```




```{r fig.height=3,fig.width=7}
cols = c("IgM MCLIA" = col.ntab, "IgG MCLIA" = col.mclia, "IgM ELISA Spike" = col.severe.igm, "IgG ELISA NP" = col.igg,"IgM ELISA NP" = col.elisa, "IgG ELISA Spike" = col.mild.igm)


ggplot(data = peak.titer.time.igg.igm.df,aes(x=marker, y = peak.titer.time,col=marker)) +
       geom_jitter(width=0.1) +
       geom_point(data = means_and_se, aes(x = marker, y = peak.titer.time),col="red",shape=19,size=3,alpha=0.5) +
       geom_errorbar(data = means_and_se, aes(ymin = ymin, ymax = ymax),width = 0.1,col="red",alpha=0.5) +
       
       #scale_x_continuous(breaks = seq(0,(max(boot.samples.df.tp7$boot.samples)+2),5),limits=c(0,max(boot.samples.df.tp7$boot.samples+2))) +
       ylab("Peak titer time") +
       scale_color_manual(values = cols) +
       xlab("") +
       ggtitle("") +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size  = 12),text = element_text(size = 12),axis.text = element_text(size = 12),axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),axis.ticks.x = element_blank(),axis.text.x = element_blank(),legend.title = element_blank(),panel.background  =  element_rect(fill  =  'white'))





```






```{r fig.height=4,fig.width=7}


peak.titer.time.igg.igm.df = peak.titer.time.igg.igm.df[-which(peak.titer.time.igg.igm.df$marker %in% c("IgM MCLIA","IgG MCLIA")),]

means_and_se = rbind(means_and_se.peak.titer.igg[1:2,],means_and_se.peak.titer.igm[1:2,])


t.test(peak.titer.time.all.IgM.ELISA.Spike$peak.titer.time,peak.titer.time.all.IgG.ELISA.NP$peak.titer.time)
t.test(peak.titer.time.all.IgM.ELISA.Spike$peak.titer.time,peak.titer.time.all.IgM.ELISA.NP$peak.titer.time)
t.test(peak.titer.time.all.IgM.ELISA.Spike$peak.titer.time,peak.titer.time.all.IgG.ELISA.Spike$peak.titer.time)
t.test(peak.titer.time.all.IgG.ELISA.NP$peak.titer.time,peak.titer.time.all.IgG.ELISA.Spike$peak.titer.time)
t.test(peak.titer.time.all.IgG.ELISA.NP$peak.titer.time,peak.titer.time.all.IgM.ELISA.NP$peak.titer.time)
t.test(peak.titer.time.igg.igm.df$peak.titer.time[which(peak.titer.time.igg.igm.df$antibody=="IgG" & peak.titer.time.igg.igm.df$assay %in% c("ELISA NP","ELISA Spike"))],peak.titer.time.igg.igm.df$peak.titer.time[which(peak.titer.time.igg.igm.df$antibody=="IgM" & peak.titer.time.igg.igm.df$assay %in% c("ELISA NP","ELISA Spike"))])
t.test(peak.titer.time.igg.igm.df$peak.titer.time[which(peak.titer.time.igg.igm.df$assay %in% c("ELISA Spike"))],peak.titer.time.igg.igm.df$peak.titer.time[which(peak.titer.time.igg.igm.df$assay %in% c("ELISA NP"))])



ggplot(data = peak.titer.time.igg.igm.df,aes(x=marker, y = peak.titer.time,col=marker)) +
       geom_point(data = means_and_se, aes(x = marker, y = peak.titer.time),col="red",shape=19,size=3,alpha=0.5) +
       geom_errorbar(data = means_and_se, aes(ymin = ymin, ymax = ymax),width = 0.1,col="red",alpha=0.5) +
       geom_jitter(width=0.1) +
       #scale_x_continuous(breaks = seq(0,(max(boot.samples.df.tp7$boot.samples)+2),5),limits=c(0,max(boot.samples.df.tp7$boot.samples+2))) +
       ylab("Peak titer time") +
       scale_color_manual(values = cols) +
       xlab("") +
       ggtitle("") +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size  = 12),text = element_text(size = 12),axis.text = element_text(size = 12),axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),axis.ticks.x = element_blank(),axis.text.x = element_blank(),legend.title = element_blank(),panel.background  =  element_rect(fill  =  'white'))


```

# Antibody kinetics assays and disease severity combined     


```{r fig.height = 4, fig.width = 11}


main.fit.functions.IgM.severity$assay = recode(main.fit.functions.IgM.severity$assay, 'IgM ELISA Mild/Moderate' = "IgM ELISA Mild",'IgM ELISA Severe/Critical' = "IgM ELISA Severe")

main.fit.functions.IgG.severity$assay = recode(main.fit.functions.IgG.severity$assay, 'IgG ELISA Mild/Moderate' = "IgG ELISA Mild",'IgG ELISA Severe/Critical' = "IgG ELISA Severe")



plot2 = ggplot(data=main.fit.functions.IgM.severity,aes(x = time, y = value,group=assay,col=assay)) +
       #geom_line(data=fit.dat.all,aes(x = time, y = value,group = variable, col=assay),size=0.5,alpha=0.1) +
       #geom_ribbon(aes(x = plot.times,ymin = lowerlim.elisa.spike,ymax = upperlim.elisa.spike),col=col.rna,fill = col.rna,alpha=0.2) +
       geom_ribbon(aes(ymin = lowerlim,ymax = upperlim),fill = "none",linetype="dashed") +
       geom_line(size=1.8) +
       scale_x_continuous(limits = c(0,35)) +
       scale_y_continuous(limits=c(0,1)) +
       annotate("text", label = "B", x = 0,y=1,size=7) +
       #scale_color_gradientn(colors  =  rev(brewer.pal(11,"Spectral"))) +
       # scale_color_brewer(palette = "Spectral", name = "") +
       scale_color_manual(values = c(col.mild.igm,col.severe.igm),name="") +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size  = 12),text = element_text(size = 12),axis.text = element_text(size = 12),axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),legend.position  =  c(0.75,0.3),legend.background = element_rect(fill="white"),panel.background  =  element_rect(fill  =  'white')) +
       xlab("Days post symptom onset") +
       ylab("Antibody level")


plot3 = ggplot(data=main.fit.functions.IgG.severity,aes(x = time, y = value,group=assay,col=assay)) +
       #geom_line(data=fit.dat.all,aes(x = time, y = value,group = variable, col=assay),size=0.5,alpha=0.1) +
       #geom_ribbon(aes(x = plot.times,ymin = lowerlim.elisa.spike,ymax = upperlim.elisa.spike),col=col.rna,fill = col.rna,alpha=0.2) +
       geom_ribbon(aes(ymin = lowerlim,ymax = upperlim),fill = "none",linetype="dashed") +
       geom_line(size=1.8) +
       scale_x_continuous(limits = c(0,35)) +
       scale_y_continuous(limits=c(0,1)) +
       annotate("text", label = "C", x = 0,y=1,size=7) +
       #scale_color_gradientn(colors  =  rev(brewer.pal(11,"Spectral"))) +
       # scale_color_brewer(palette = "Spectral", name = "") +
       scale_color_manual(values = c(col.mild.igg,col.severe.igg),name="") +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size  = 12),text = element_text(size = 12),axis.text = element_text(size = 12),axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 10)),legend.position  =  c(0.76,0.3),legend.background = element_rect(fill="white"),panel.background  =  element_rect(fill  =  'white')) +
       xlab("Days post symptom onset") +
       ylab("Antibody level")

plot.main.functions.combined + plot2 + plot3

```

# Overall combined figure       




```{r fig.width = 5, fig.height=7}
plot.times = 1:30

# probdat.rna$marker = "RNA"
# probdat.igg.elisa.np$marker = "IgG"
# probdat.igm.elisa.spike$marker = "IgM"
# 
# probdat.igg.elisa.np$Antibody = NULL
# probdat.igm.elisa.spike$Antibody = NULL
# 
# probdat.rna$smooth.prob = NA
# probdat.igg.elisa.np$smooth.prob = NA
# probdat.igm.elisa.spike$smooth.prob = NA
# 
# 
# probdat.rna$smooth.prob[1:24] = predict(smooth.spline(probdat.rna$prob))$y[1:24]
# probdat.rna$day[25:30]=25:30
# probdat.rna$smooth.prob[25:30]= predict(smooth.spline(probdat.rna$prob))$y[25:30]
# 
# probdat.igg.elisa.np$smooth.prob[1:24] = predict(smooth.spline(probdat.igg.elisa.np$prob))$y[1:24]
# probdat.igg.elisa.np$day[25:30]=25:30
# probdat.igg.elisa.np$smooth.prob[25:30]= predict(smooth.spline(probdat.igg.elisa.np$prob))$y[25:30]
# 
# 
# probdat.igm.elisa.spike$smooth.prob[1:24] = predict(smooth.spline(probdat.igm.elisa.spike$prob))$y[1:24]
# probdat.igm.elisa.spike$day[25:30]=25:30
# probdat.igm.elisa.spike$smooth.prob[25:30]= predict(smooth.spline(probdat.igm.elisa.spike$prob))$y[25:30]
# 
# 
# 
# probdat.all = rbind(probdat.rna,probdat.igg.elisa.np,probdat.igm.elisa.spike)





plot2 = ggplot(data=main.fit.function.igg.igm.elisa.spike,aes(x = time, y = value,group=marker,col=marker,fill=marker)) +
       #geom_line(data=fit.dat.all,aes(x = time, y = value,group = variable, col=assay),size=0.5,alpha=0.1) +
       #geom_ribbon(aes(x = plot.times,ymin = lowerlim.elisa.spike,ymax = upperlim.elisa.spike),col=col.rna,fill = col.rna,alpha=0.2) +
       geom_ribbon(aes(ymin = lowerlim,ymax = upperlim),alpha=0.2,linetype="dashed",show.legend=F) +
       geom_line(size=1.5) +
       scale_x_continuous(breaks = seq(0,max(plot.times)+1,5),limits=c(0.5,max(plot.times)+0.5)) +
       scale_y_continuous(limits=c(0,1)) +
       #scale_color_gradientn(colors  =  rev(brewer.pal(11,"Spectral"))) +
       # scale_color_brewer(palette = "Spectral", name = "") +
       scale_fill_manual(values = c(col.igg,col.igm),name="") +
       scale_color_manual(values = c(col.igg,col.igm),name="") +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size  = 12),
             text = element_text(size = 12),
             axis.text = element_text(size = 12),
             axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 6)),
             legend.position  =  c(0.82,0.3),
             legend.background = element_rect(fill="white"),
             legend.key.size = unit(0.4,"cm"),
             legend.text=element_text(size=9),
             panel.background  =  element_rect(fill  =  'white'),
             axis.title.x = element_text(margin = margin(t = 8, r = 0, b = 0, l = 0)),
             plot.margin = unit(c(0,0,0,0), "cm")) +
       xlab("") +
       ylab("Antibody \n level")





seroconvdens1 = data.frame(time = seq(0,max(plot.times),0.01), seroconv = dnorm(seq(0,max(plot.times),0.01),mean = norm.fit.igg.elisa.spike$estimate[1], sd = norm.fit.igg.elisa.spike$estimate[2]),marker = "IgG")

seroconvdens2 = data.frame(time = seq(0,max(plot.times),0.01), seroconv = dnorm(seq(0,max(plot.times),0.01),mean = norm.fit.igm.elisa.spike$estimate[1], sd = norm.fit.igm.elisa.spike$estimate[2]),marker = "IgM")

seroconvdens = rbind(seroconvdens1,seroconvdens2)





plot3 = ggplot(data.frame(time = plot.times), aes(x = time)) +
       stat_function(fun = dnorm, args = list(mean = norm.fit.igg.elisa.np.spike$estimate[1], sd = norm.fit.igg.elisa.np.spike$estimate[2]),aes(color = "IgG ELISA"),size=1.5,alpha=1) +
       stat_function(fun = dnorm, args = list(mean = norm.fit.igm.elisa.np.spike$estimate[1], sd = norm.fit.igm.elisa.np.spike$estimate[2]),aes(color = "IgM ELISA"),size=1.5,alpha=1) +
       theme_classic() +
       scale_color_manual( values = c(col.igg,col.igm),name="") +
       scale_x_continuous(breaks = seq(0,max(plot.times)+1,5),limits=c(0.5,max(plot.times)+0.5)) +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size  = 12),
             text = element_text(size = 12),
             axis.text = element_text(size = 12),
             #axis.ticks = element_blank(),
             axis.title.x = element_text(margin = margin(t = 10, r = 0, b = 0, l = 0)),
             legend.position = c(0.8,0.75),
             legend.background = element_rect(fill="transparent"),
             legend.key.size = unit(0.4,"cm"),
             legend.text=element_text(size=9),
             plot.margin = unit(c(0,0,1,0), "cm")
       ) +
       xlab("Days post symptom onset") +
       ylab("Seroconversion \n probability density")





smooth.rna = as.data.frame(predict(smooth.spline(probdat.rna$day,probdat.rna$prob,df = 4)))
smooth.rna$y[which(smooth.rna$y>1)] = 1
smooth.rna$y[which(smooth.rna$y<0)] = 0



probdat.rna$marker = "RNA"
probdat.rna$smooth.prob = smooth.rna$y
probdat.igg.elisa$marker = "IgG"
probdat.igg.elisa$smooth.prob = smooth.igg.elisa$prob
probdat.igm.elisa$marker = "IgM"
probdat.igm.elisa$smooth.prob = smooth.igm.elisa$prob

probdat.all = rbind(probdat.rna,probdat.igg.elisa,probdat.igm.elisa)



plot1c = ggplot(data=probdat.all,aes(x = day, y = smooth.prob,group=marker,color = marker)) +
       #geom_errorbar(aes(ymin = lowerci,ymax = upperci),alpha = 0.4) +
       #geom_point(size = 1.5,alpha=0.5) +
       stat_smooth(method="loess",level=.95,se=F,alpha = 0.2,size=1.5) +
       scale_y_continuous(breaks = seq(0,1,0.5),limits=c(-0.1,1.05)) +
       scale_x_continuous(breaks = seq(0,max(plot.times)+1,5),limits=c(0,max(plot.times))) +
       scale_color_manual(values=c(col.igg,col.igm,col.rna)) +
       theme_classic(base_family = "Avenir Next") +
       theme(plot.title  =  element_text(size  = 12),
             text = element_text(size = 12),
             axis.text = element_text(size = 12),
             axis.title.y  =  element_text(margin  =  ggplot2::margin(r = 6)),
             legend.position  =  c(0.85,0.6),
             legend.text = element_text(size=9),
             legend.title = element_blank(), 
             legend.background = element_rect(fill  =  'transparent', color = "transparent"), 
             legend.key.size = unit(0.4,"cm"),
             plot.margin = unit(c(1,0,-0.4,0), "cm"),
             panel.background  =  element_rect(fill  =  'white')) +
       xlab("") +
       ylab("Detection \n probability")
```


```{r fig.width = 5, fig.height=7}
plot1c + plot2 + plot3 + plot_layout(ncol=1, heights=c(0.8,2,1))



```








