getKDEQuantileError = function(q, p, bw, x) { #This is a function for calculating quantile error given a quantile (q), a lower tail probability (p), KDE bandwidth (bw) and log(MFI) data (x) thisP = 0.0 for(i in 1:length(x)) { thisP = thisP + pnorm(q, x[i], bw, lower.tail = FALSE)/length(x) } return(abs(p - thisP)) } getThreshold = function(nonSpecificRawMFIValues, upperQuantile = 0.99) { # This function works out the threshold for positivity # (1 - upperQuantile) is the allowable probability of a false positive (0.01 by default) # nonSpecificRawMFIValues is a vector of raw MFI values for samples that should give a negative result under this test (used to determine the distribution of MFI noise for negative samples) if(min(nonSpecificRawMFIValues) <= 0) { cat("ERROR: One or more Raw MFI values in nonSpecificRawMFIValues is less than or equal to zero. MFI values must be positive. Returning NULL. \n") return(NULL) } else { nonSpecificRawMFIValues = log(nonSpecificRawMFIValues) mfiDensity = density(nonSpecificRawMFIValues) nsd = qnorm(upperQuantile) mfiQuantile = optim(par = mean(nonSpecificRawMFIValues), fn = getKDEQuantileError, p = (1 - upperQuantile), bw = mfiDensity$bw, x = nonSpecificRawMFIValues, method = "Brent", lower = min(nonSpecificRawMFIValues), upper = max(nonSpecificRawMFIValues) + 2*nsd*mfiDensity$bw, control = list(abstol = 1E-6)) cat("NOTE: Check that optimConvergenceCode equals 0 for correct results. If optimConvergenceCode does not equal 0, then consult the covergence codes in function optim() documentation for further information. \n") return(list(thresholdForPositivity = exp(mfiQuantile$par), optimConvergenceCode = mfiQuantile$convergence)) } } ########################### USAGE EXAMPLE ########################## # #Raw MFI Data in rawMFI vector # rawMFI = c(569, 243, 456, 908, 198, 354, 587, 776, 264, 812) # # #Now determine the threshold for positivity # MFI_Threshold = getThreshold(rawMFI) # MFI_Threshold ####################################################################