├── .Rbuildignore ├── .github └── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── .gitignore ├── DESCRIPTION ├── LICENSE ├── NAMESPACE ├── R ├── biotekCytationFunctions.R ├── biotekNeo2Functions.R ├── flowCoreMisc.R ├── flowCytometryFunctions.R ├── plateReaderFunctions.R ├── tecanInfiniteFunctions.R └── tecanSparkFunctions.R ├── README.Rmd ├── README.md ├── examples ├── csv_save.png ├── flow_cytometry │ └── DATA │ │ ├── 20191121 │ │ ├── 20191121_beads.fcs │ │ ├── 20191121_plate_layout.csv │ │ ├── pMed_None_0_1.fcs │ │ ├── pMed_None_0_10.fcs │ │ ├── pMed_None_0_2.fcs │ │ ├── pMed_None_0_3.fcs │ │ ├── pMed_None_0_4.fcs │ │ ├── pMed_None_0_5.fcs │ │ ├── pMed_None_0_6.fcs │ │ ├── pMed_None_0_7.fcs │ │ ├── pMed_None_0_8.fcs │ │ ├── pMed_None_0_9.fcs │ │ ├── pNeg_None_0_1.fcs │ │ ├── pNeg_None_0_2.fcs │ │ ├── pNeg_None_0_3.fcs │ │ ├── pNeg_None_0_4.fcs │ │ ├── pNeg_None_0_5.fcs │ │ ├── pNeg_None_0_6.fcs │ │ ├── pNeg_None_0_7.fcs │ │ ├── pNeg_None_0_8.fcs │ │ ├── pStrong_None_0_1.fcs │ │ ├── pStrong_None_0_10.fcs │ │ ├── pStrong_None_0_11.fcs │ │ ├── pStrong_None_0_12.fcs │ │ ├── pStrong_None_0_2.fcs │ │ ├── pStrong_None_0_3.fcs │ │ ├── pStrong_None_0_4.fcs │ │ ├── pStrong_None_0_5.fcs │ │ ├── pStrong_None_0_6.fcs │ │ ├── pStrong_None_0_7.fcs │ │ ├── pStrong_None_0_8.fcs │ │ ├── pStrong_None_0_9.fcs │ │ ├── pWeak_None_0_1.fcs │ │ ├── pWeak_None_0_10.fcs │ │ ├── pWeak_None_0_11.fcs │ │ ├── pWeak_None_0_12.fcs │ │ ├── pWeak_None_0_1_processed.fcs │ │ ├── pWeak_None_0_1_processed.pdf │ │ ├── pWeak_None_0_2.fcs │ │ ├── pWeak_None_0_3.fcs │ │ ├── pWeak_None_0_4.fcs │ │ ├── pWeak_None_0_5.fcs │ │ ├── pWeak_None_0_7.fcs │ │ ├── pWeak_None_0_8.fcs │ │ └── pWeak_None_0_9.fcs │ │ └── 20191121_processed │ │ ├── 20191121_beads_BL1-H_calibration.pdf │ │ ├── 20191121_beads_singlet_beads.pdf │ │ ├── data_summary.csv │ │ ├── pMed_None_0_1.fcs │ │ ├── pMed_None_0_10.fcs │ │ ├── pMed_None_0_10_processed.pdf │ │ ├── pMed_None_0_1_processed.pdf │ │ ├── pMed_None_0_2.fcs │ │ ├── pMed_None_0_2_processed.pdf │ │ ├── pMed_None_0_3.fcs │ │ ├── pMed_None_0_3_processed.pdf │ │ ├── pMed_None_0_4.fcs │ │ ├── pMed_None_0_4_processed.pdf │ │ ├── pMed_None_0_5.fcs │ │ ├── pMed_None_0_5_processed.pdf │ │ ├── pMed_None_0_6.fcs │ │ ├── pMed_None_0_6_processed.pdf │ │ ├── pMed_None_0_7.fcs │ │ ├── pMed_None_0_7_processed.pdf │ │ ├── pMed_None_0_8.fcs │ │ ├── pMed_None_0_8_processed.pdf │ │ ├── pMed_None_0_9.fcs │ │ └── pMed_None_0_9_processed.pdf └── plate_reader │ ├── biotek_cytation │ ├── 231031_pr_calibration_lid.xlsx │ ├── 231031_pr_calibration_lid_parsed.csv │ ├── 231031_pr_calibration_lid_parsed_absorbance_cfs.pdf │ ├── 231031_pr_calibration_lid_parsed_cfs.csv │ ├── 231031_pr_calibration_lid_parsed_fluorescence_cfs.pdf │ ├── 231031_pr_calibration_membrane.xlsx │ ├── 231031_pr_calibration_membrane_parsed.csv │ ├── 231031_pr_calibration_membrane_parsed_absorbance_cfs.pdf │ ├── 231031_pr_calibration_membrane_parsed_cfs.csv │ ├── 231031_pr_calibration_membrane_parsed_fluorescence_cfs.pdf │ ├── 231031_pr_calibration_nolid.xlsx │ └── plate_layout.csv │ ├── biotek_neo2 │ ├── biotek-neo2_example_data.xlsx │ └── biotek-neo2_example_data_parsed.csv │ └── tecan_spark │ ├── 191219_calibration_membrane.csv │ ├── 191219_calibration_membrane_parsed.csv │ ├── 191219_calibration_membrane_parsed_absorbance_cfs.pdf │ ├── 191219_calibration_membrane_parsed_cfs.csv │ ├── 191219_calibration_membrane_parsed_fluorescence_cfs.pdf │ ├── 200228_example_data.csv │ ├── 200228_example_data_parsed.csv │ ├── 200228_example_data_parsed_GFP.pdf │ ├── 200228_example_data_parsed_OD.pdf │ ├── 200228_example_data_parsed_mCherry.pdf │ ├── 200228_example_data_parsed_norm-curve_GFP.pdf │ ├── 200228_example_data_parsed_norm-curve_mCherry.pdf │ ├── 200228_example_data_parsed_processed.csv │ ├── 200228_example_layout.csv │ └── calibration_plate_layout.csv ├── flopr.Rproj └── man ├── biotek_parse.Rd ├── calibrate_flu.Rd ├── calibrate_od.Rd ├── cytation_parse.Rd ├── ff_append_cols.Rd ├── flu_norm.Rd ├── generate_cfs.Rd ├── get_bacteria.Rd ├── get_calibration.Rd ├── get_singlets.Rd ├── infinite_parse.Rd ├── next_blank.Rd ├── next_blank_cell.Rd ├── next_blank_row.Rd ├── next_filled.Rd ├── next_filled_cell.Rd ├── next_filled_row.Rd ├── od_norm.Rd ├── plot_trimming.Rd ├── prep_flow_frame.Rd ├── process_fcs.Rd ├── process_fcs_dir.Rd ├── process_plate.Rd ├── sparkParse.Rd ├── spark_parse.Rd ├── summarise_data.Rd └── to_mef.Rd /.Rbuildignore: -------------------------------------------------------------------------------- 1 | ^.*\.Rproj$ 2 | ^\.Rproj\.user$ 3 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | - OS: [e.g. iOS] 28 | - Browser [e.g. chrome, safari] 29 | - Version [e.g. 22] 30 | 31 | 32 | **Additional context** 33 | Add any other context about the problem here. 34 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .Rproj.user 2 | .Rhistory 3 | .RData 4 | .Ruserdata 5 | .DS_Store 6 | -------------------------------------------------------------------------------- /DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: flopr 2 | Type: Package 3 | Title: A package for the normalisation and calibration of flow cytometry and plate reader spectrophotometry data 4 | Version: 0.4.03 5 | Authors@R: c( 6 | person("Fedorec", "Alex J H", email = "alexander.fedorec.13@ucl.ac.uk", role = c("aut", "cre")), 7 | person("Robinson", "Clare", role = c("aut"))) 8 | Description: something 9 | URL: https://github.com/ucl-cssb/flopr 10 | BugReports: https://github.com/ucl-cssb/flopr/issues 11 | License: GPL-3 12 | Encoding: UTF-8 13 | LazyData: true 14 | Imports: 15 | ggplot2, 16 | gridExtra, 17 | grid, 18 | gtable, 19 | stats, 20 | utils, 21 | dplyr, 22 | rlang, 23 | tidyr, 24 | broom, 25 | mgcv, 26 | tidyselect, 27 | checkmate, 28 | readxl 29 | Suggests: 30 | flowCore, 31 | flowClust, 32 | flowStats 33 | RoxygenNote: 7.2.3 34 | -------------------------------------------------------------------------------- /NAMESPACE: -------------------------------------------------------------------------------- 1 | # Generated by roxygen2: do not edit by hand 2 | 3 | export(biotek_parse) 4 | export(cytation_parse) 5 | export(generate_cfs) 6 | export(infinite_parse) 7 | export(process_fcs) 8 | export(process_fcs_dir) 9 | export(process_plate) 10 | export(sparkParse) 11 | export(spark_parse) 12 | importFrom(dplyr,"%>%") 13 | importFrom(rlang,":=") 14 | importFrom(rlang,.data) 15 | -------------------------------------------------------------------------------- /R/biotekCytationFunctions.R: -------------------------------------------------------------------------------- 1 | #' Parser for Biotek Cytation plate reader data 2 | #' 3 | #' @param data_xl path to xls or xlsx file from Biotek Cytation plate reader 4 | #' @param layout_csv path to csv file containing plate layout information 5 | #' @param timeseries Boolean flag indicating whether the data is a timeseries or 6 | #' single recording. Currently only works for timeseries=T. 7 | #' 8 | #' @return a data.frame containing the parsed plate reader data 9 | #' @export 10 | #' @importFrom rlang .data 11 | #' @importFrom dplyr %>% 12 | #' 13 | cytation_parse <- function(data_csv, layout_csv, timeseries=T) { 14 | if(stringr::str_ends(data_csv, ".xlsx") | stringr::str_ends(data_csv, ".xls")){ 15 | data <- as.data.frame(readxl::read_excel(path = data_csv, 16 | col_names = F, 17 | col_types = "text")) 18 | } else if(stringr::str_ends(data_csv, ".csv")){ 19 | data <- utils::read.table(data_csv, sep = ",", 20 | na.strings = c(""), 21 | header = F, 22 | stringsAsFactors = F) 23 | } else { 24 | stop("data_csv is must be a .csv, .xls or .xlsx file.") 25 | } 26 | 27 | plate_layout <- utils::read.csv(layout_csv) 28 | 29 | if(timeseries == TRUE){ 30 | 31 | # find start of data blocks 32 | end_kinetic_idx <- which(data[, 1] == "End Kinetic") 33 | 34 | # find where the next block starts 35 | next_blank_idx <- next_blank_cell(end_kinetic_idx, data, col=1) 36 | next_block_start_idx <- next_filled_cell(next_blank_idx, data, col=1) 37 | 38 | end_of_file <- F 39 | all_data <- c() 40 | while (!end_of_file) { 41 | # find what is being measured 42 | block_name <- data[next_block_start_idx, 1] 43 | 44 | # start of data 45 | next_block_start_idx <- next_filled_cell(next_block_start_idx, data, col=2) 46 | 47 | # find where the end of the current measurement block is 48 | block_end_idx <- next_blank_row(next_block_start_idx, data) 49 | if(is.na(block_end_idx)){ # if we're on the last block, there is no blank row at the end, so the last row is the end of the block 50 | block_end_idx <- nrow(data) 51 | end_of_file <- T 52 | } 53 | 54 | # grab the data only for that measurement 55 | new_block <- data[(next_block_start_idx):(block_end_idx - 1), ] 56 | 57 | # manipulate the data 58 | wells <- new_block[1, -c(1,3)] 59 | new_block <- new_block[-1,-c(1,3)] 60 | names(new_block) <- wells 61 | names(new_block)[1] <- "time" 62 | new_block <- new_block %>% 63 | tidyr::pivot_longer(cols = 2:ncol(new_block), 64 | names_to = "well", 65 | values_to = "value", 66 | values_transform = list(value = as.numeric)) %>% 67 | dplyr::mutate(time = as.numeric(time), 68 | time = time*24*60*60, 69 | time = round(time/600)*600) # round to nearest 10 minute 70 | 71 | # add info for each well 72 | joined_block <- dplyr::full_join(plate_layout, new_block) 73 | joined_block$measure <- block_name 74 | 75 | # 76 | all_data <- rbind(all_data, joined_block) 77 | 78 | # 79 | next_block_start_idx <- next_filled_cell(block_end_idx + 1, data, col=1) 80 | 81 | # if we're at the end 82 | if(is.na(next_block_start_idx)){ 83 | end_of_file <- T 84 | } 85 | } 86 | 87 | # rearrange data ---------------------------------------------------------- 88 | out_data <- all_data %>% 89 | tidyr::pivot_wider(names_from = .data$measure, values_from = .data$value) %>% # reshape so we have a column for each measurement type 90 | dplyr::mutate(row = substr(x = .data$well, start = 1, stop = 1)) %>% # make a "row" column from the "well" column 91 | dplyr::mutate(column = as.numeric(substr(x = .data$well, start = 2, # and make a "column" column 92 | stop = nchar(.data$well)))) %>% 93 | dplyr::arrange_at(dplyr::vars(.data$time, # order the rows 94 | .data$row, 95 | .data$column)) 96 | 97 | # write parsed data to csv ------------------------------------------------ 98 | if(stringr::str_ends(data_csv, ".xlsx")){ 99 | out_name <- gsub(".xlsx", "_parsed.csv", data_csv) 100 | } else if(stringr::str_ends(data_csv, ".xls")){ 101 | out_name <- gsub(".xls", "_parsed.csv", data_csv) 102 | } else if(stringr::str_ends(data_csv, ".csv")){ 103 | out_name <- gsub(".xls", "_parsed.csv", data_csv) 104 | } 105 | utils::write.csv(x = out_data, file = out_name, row.names = FALSE) 106 | 107 | return(out_data) 108 | } 109 | else if (timeseries == FALSE){ 110 | # get start and end block idxs 111 | start_block_idx <- which(data[, 2] == "Well") 112 | end_block_idx <- next_blank_row(start_idx = start_block_idx, data = data) 113 | if(is.na(end_block_idx)){ 114 | end_block_idx <- nrow(data) 115 | } 116 | 117 | # grab the data 118 | all_data <- data[start_block_idx:end_block_idx, 2:ncol(data)] 119 | 120 | # simplify names 121 | all_data <- all_data %>% 122 | dplyr::rowwise() %>% 123 | dplyr::mutate(...2 = unlist(strsplit(.data$...2, split = ':'))[1]) %>% # take first section of name 124 | dplyr::ungroup() 125 | 126 | # transpose the data 127 | all_data <- as.data.frame(t(as.matrix(all_data))) 128 | 129 | # 1st row contains column names 130 | names(all_data) <- all_data[1,] 131 | all_data <- all_data[-1,] 132 | all_data <- all_data[, -length(all_data)] 133 | 134 | # convert to numeric 135 | all_data <- all_data %>% 136 | dplyr::mutate(dplyr::across(!Well, as.numeric)) %>% 137 | dplyr::rename(well = Well) 138 | 139 | # join to plate layout csv 140 | joined_block <- dplyr::full_join(plate_layout, all_data, by = 'well') 141 | 142 | # split row and column from well 143 | joined_block$row <- substr(x = joined_block$well, start = 1, stop = 1) 144 | joined_block$column <- as.numeric(substr(x = joined_block$well, start = 2, 145 | stop = nchar(joined_block$well))) 146 | joined_block <- dplyr::arrange_at(joined_block, dplyr::vars(.data$row, 147 | .data$column)) 148 | 149 | # write parsed data to csv ------------------------------------------------ 150 | 151 | if(stringr::str_ends(data_csv, ".xlsx")){ 152 | out_name <- gsub(".xlsx", "_parsed.csv", data_csv) 153 | } else if(stringr::str_ends(data_csv, ".xls")){ 154 | out_name <- gsub(".xls", "_parsed.csv", data_csv) 155 | } else if(stringr::str_ends(data_csv, ".csv")){ 156 | out_name <- gsub(".xls", "_parsed.csv", data_csv) 157 | } 158 | utils::write.csv(x = joined_block, file = out_name, row.names = FALSE) 159 | 160 | return(joined_block) 161 | } 162 | } 163 | -------------------------------------------------------------------------------- /R/biotekNeo2Functions.R: -------------------------------------------------------------------------------- 1 | #' Parser for Biotek Neo 2 plate reader data 2 | #' 3 | #' @param data_xl path to xls or xlsx file from Biotek Neo 2 plate reader 4 | #' @param layout_csv path to csv file containing plate layout information 5 | #' @param timeseries Boolean flag indicating whether the data is a timeseries or 6 | #' single recording. Currently only works for timeseries=T. 7 | #' 8 | #' @return a data.frame containing the parsed plate reader data 9 | #' @export 10 | #' @importFrom rlang .data 11 | #' @importFrom dplyr %>% 12 | #' 13 | biotek_parse <- function(data_xl, layout_csv, timeseries=T) { 14 | data <- readxl::read_excel(path = data_xl, 15 | col_names = F, 16 | trim_ws = T) 17 | 18 | plate_layout <- utils::read.csv(layout_csv) 19 | 20 | if(timeseries == TRUE){ 21 | start_time_idx <- which(data[, 1] == "End Kinetic") 22 | 23 | next_block_start_idx <- start_time_idx + 2 24 | 25 | end_of_file <- F 26 | all_data <- c() 27 | measure_times <- c() 28 | while (!end_of_file) { 29 | # find what is being measured 30 | block_name <- unlist(data[next_block_start_idx, 1]) 31 | 32 | # check if we are at the end of the file 33 | if (block_name == "Results") { 34 | end_of_file <- T 35 | break 36 | } 37 | 38 | # find where the end of the current measurement block is 39 | block_start_idx <- next_block_start_idx + 2 40 | block_end_idx <- block_start_idx + 1 41 | while (!is.na(data[block_end_idx, 2])) { 42 | block_end_idx <- block_end_idx + 1 43 | } 44 | 45 | # grab the data only for that measurement 46 | new_block <- data[(block_start_idx):(block_end_idx - 1), -1] 47 | 48 | # trim unnecessary readings i.e. temp 49 | # and rename columns 50 | wells <- new_block[1, -2] 51 | trimmed_new_block <- new_block[-1, -2] 52 | names(trimmed_new_block) <- wells 53 | names(trimmed_new_block)[1] <- "time" 54 | 55 | # hack to unify times of readings across different measurements 56 | if(length(measure_times) == 0){ 57 | measure_times <- trimmed_new_block[1] 58 | } 59 | trimmed_new_block[1] <- measure_times 60 | 61 | long_trimmed_new_block <- tidyr::pivot_longer(data = trimmed_new_block, 62 | cols = 2:ncol(trimmed_new_block), 63 | names_to = "well") 64 | 65 | # add metadata for each well 66 | joined_block <- dplyr::full_join(plate_layout, long_trimmed_new_block, by="well") 67 | joined_block$measure <- block_name 68 | 69 | # 70 | all_data <- rbind(all_data, joined_block) 71 | 72 | # 73 | next_block_start_idx <- block_end_idx + 1 74 | } 75 | 76 | all_data$value <- as.numeric(all_data$value) 77 | all_data$time <- as.numeric(all_data$time) * 86400 # conversion to seconds - coefficient calculated empirically 78 | 79 | # rearrange data ---------------------------------------------------------- 80 | # includes a bit of a hack to get around duplicate rows (there seems to be 81 | # lots of empty rows with time = 0) 82 | out_data <- all_data %>% 83 | dplyr::group_by(.data$measure) %>% 84 | dplyr::mutate(id = dplyr::row_number()) %>% 85 | tidyr::pivot_wider(names_from = .data$measure, 86 | values_from = .data$value) %>% 87 | dplyr::select(-.data$id) 88 | 89 | # get split row and column names for convenience 90 | out_data$row <- substr(x = out_data$well, start = 1, stop = 1) 91 | out_data$column <- as.numeric(substr(x = out_data$well, start = 2, 92 | stop = nchar(out_data$well))) 93 | 94 | # write parsed data to csv ------------------------------------------------ 95 | out_name <- paste(tools::file_path_sans_ext(data_xl), "_parsed.csv", sep="") 96 | utils::write.csv(x = out_data, file = out_name, row.names = FALSE) 97 | 98 | return(out_data) 99 | } 100 | else if (timeseries == FALSE){ 101 | stop("We can currently only parse timeseries from Biotek Neo 2 plate 102 | readers. Please send me some single timepoint data so I can update the 103 | parser.") 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /R/flowCoreMisc.R: -------------------------------------------------------------------------------- 1 | ### FUNCTIONS FOR APPENDING COLUMNS TO FLOW FRAME 2 | ### from updated version of flowCore not available to R < 4.0 3 | 4 | #' Append data columns to a flowFrame 5 | #' 6 | #' Append data columns to a flowFrame 7 | #' 8 | #' It is used to add extra data columns to the existing flowFrame. It handles 9 | #' keywords and parameters properly to ensure the new flowFrame can be written 10 | #' as a valid FCS through the function \code{write.FCS} . 11 | #' 12 | #' @param fr A \code{\link[flowCore:flowFrame-class]{flowFrame}}. 13 | #' @param cols A numeric matrix containing the new data columns to be added. 14 | #' Must has column names to be used as new channel names. 15 | #' 16 | #' @name ff_append_cols 17 | #' @aliases ff_append_cols 18 | #' @usage 19 | #' ff_append_cols(fr, cols) 20 | #' @return 21 | #' 22 | #' A \code{\linkS4class{flowFrame}} 23 | #' @author Mike Jiang 24 | #' @keywords IO 25 | ff_append_cols <- function(fr, cols){ 26 | new_pd <- cols_to_pd(fr, cols) 27 | pd <- flowCore::pData(flowCore::parameters(fr)) 28 | pd <- rbind(pd, new_pd) 29 | #add to exprs 30 | fr@exprs <- cbind(flowCore::exprs(fr), cols) 31 | flowCore::pData(flowCore::parameters(fr)) <- pd 32 | 33 | update_kw_from_pd(fr, new_pd) 34 | } 35 | 36 | update_kw_from_pd <- function(fr, new_pd) 37 | { 38 | new_pid <- rownames(new_pd) 39 | #take care of flowCore_$PnRmax 40 | trans <- flowCore::keyword(fr)[["transformation"]] 41 | if(!is.null(trans) && trans == "custom"){ 42 | flowCore::keyword(fr)[paste0("flowCore_", new_pid, "Rmax")] <- new_pd[new_pid, "maxRange"] 43 | flowCore::keyword(fr)[paste0("flowCore_", new_pid, "Rmin")] <- new_pd[new_pid, "minRange"] 44 | } 45 | fr 46 | } 47 | #' generate new pData of flowFrame based on the new cols added 48 | #' @param fr A \code{\link[flowCore:flowFrame-class]{flowFrame}}. 49 | #' @param cols A numeric matrix containing the new data columns to be added. 50 | #' Must has column names to be used as new channel names. 51 | #' @noRd 52 | cols_to_pd <- function(fr, cols){ 53 | checkmate::checkClass(cols, "matrix") 54 | ncol <- ncol(cols) 55 | cn <- colnames(cols) 56 | if(length(cn) != ncol) 57 | stop("All columns in 'cols' must have colnames!") 58 | #add to pdata 59 | pd <- flowCore::pData(flowCore::parameters(fr)) 60 | ncol_old <- ncol(fr) 61 | new_pid <- max(as.integer(gsub("\\$P", "", rownames(pd)))) + 1 62 | new_pid <- seq(new_pid, length.out = ncol) 63 | new_pid <- paste0("$P", new_pid) 64 | 65 | new_pd <- do.call(rbind, lapply(cn, function(i){ 66 | vec <- cols[,i] 67 | rg <- range(vec) 68 | data.frame(name = i, desc = NA, range = diff(rg) + 1, minRange = rg[1], maxRange = rg[2]) 69 | })) 70 | rownames(new_pd) <- new_pid 71 | new_pd 72 | } 73 | -------------------------------------------------------------------------------- /R/plateReaderFunctions.R: -------------------------------------------------------------------------------- 1 | #' Plate reader normalisation and calibration 2 | #' 3 | #' @param data_csv path to a .csv file containing parsed plate reader data 4 | #' @param blank_well the well coordinates of one or more media blanks 5 | #' @param neg_well the well coordinates of a non-fluorescent control 6 | #' @param od_name the column name for the optical density data 7 | #' @param flu_names the column names for the fluorescence data 8 | #' @param af_model model used to fit negative control autofluorescence. 9 | #' For now these include "polynomial", "invers_poly", "exponential", "spline" and "loess". 10 | #' @param to_MEFL a Boolean to determine whether to attempt to convert OD and 11 | #' GFP reading to calibrated units 12 | #' @param flu_gains if to_MEFL=T, the gain values at which the fluorophores 13 | #' specified in flu_names was recorded. If there isn't calibration data for a 14 | #' fluorophore, do not speficy a gain value 15 | #' @param conversion_factors_csv if to_MEFL=T, path of the csv file containing 16 | #' conversion factors from plate reader calibration 17 | #' 18 | #' @return a data.frame with columns for raw plate reader data, normalised data 19 | #' and, if to_MEFL = T, calibrated OD and GFP data 20 | #' @export 21 | #' @importFrom rlang .data 22 | #' 23 | #' @examples 24 | process_plate <- function(data_csv, blank_well = "A1", neg_well = "A2", 25 | od_name = "OD", flu_names = c("GFP"), 26 | af_model = "spline", to_MEFL = F, 27 | flu_gains, conversion_factors_csv) { 28 | 29 | pr_data <- utils::read.csv(data_csv, check.names = F) 30 | 31 | od_norm_pr_data <- od_norm(pr_data, blank_well, od_name) 32 | 33 | plt_od <- ggplot2::ggplot(od_norm_pr_data) + 34 | ggplot2::geom_line(ggplot2::aes(x = .data$time, y = .data[[od_name]], 35 | colour = "raw"), size = 0.2) + 36 | ggplot2::geom_line(ggplot2::aes(x = .data$time, y = .data$normalised_OD, 37 | colour = "normalised"), size = 0.2) + 38 | ggplot2::scale_x_continuous("time") + 39 | ggplot2::scale_colour_discrete("") + 40 | ggplot2::facet_grid(row~column) + 41 | ggplot2::theme_bw(base_size = 8) 42 | ggplot2::ggsave(filename = gsub(".csv", "_OD.pdf", data_csv), 43 | plot = plt_od, height = 160, 44 | width = 240, units = "mm") 45 | 46 | flu_norm_pr_data <- od_norm_pr_data 47 | if(!is.na(flu_names)){ 48 | if(length(flu_names) >= 1){ 49 | for (flu_idx in seq_len(length(flu_names))) { 50 | flu_norm_pr_data <- flu_norm(flu_norm_pr_data, neg_well, blank_well, 51 | flu_names[flu_idx], af_model, data_csv) 52 | 53 | plt_flu <- ggplot2::ggplot(flu_norm_pr_data) + 54 | ggplot2::geom_line(ggplot2::aes(x = .data$time, y = .data[[flu_names[flu_idx]]], 55 | colour = "raw"), size = 0.2) + 56 | ggplot2::geom_line(ggplot2::aes(x = .data$time, 57 | y = .data[[paste("normalised_", 58 | flu_names[flu_idx], 59 | sep = "")]], 60 | colour = "normalised"), 61 | size = 0.2) + 62 | ggplot2::scale_x_continuous("time") + 63 | ggplot2::scale_colour_discrete("") + 64 | ggplot2::facet_grid(row~column) + 65 | ggplot2::theme_bw(base_size = 8) 66 | ggplot2::ggsave(filename = gsub(".csv", 67 | paste("_", flu_names[flu_idx], ".pdf", sep = ""), 68 | data_csv), 69 | plot = plt_flu, height = 160, 70 | width = 240, units = "mm") 71 | } 72 | } 73 | } 74 | 75 | out_data <- flu_norm_pr_data 76 | 77 | if (to_MEFL) { 78 | out_data <- calibrate_od(out_data, od_name, 79 | conversion_factors_csv) 80 | 81 | if(!is.na(flu_names)){ 82 | for (flu_idx in seq_len(length(flu_names))) { 83 | if(length(flu_gains) >= flu_idx){ 84 | out_data <- calibrate_flu(out_data, flu_names[flu_idx], 85 | flu_gains[flu_idx], od_name, 86 | conversion_factors_csv) 87 | } 88 | else {break} 89 | } 90 | } 91 | } 92 | 93 | utils::write.csv(x = out_data, 94 | file = gsub(".csv", "_processed.csv", data_csv), 95 | row.names = FALSE) 96 | return(out_data) 97 | } 98 | 99 | 100 | #' Normalisation absorbance against blank well 101 | #' 102 | #' @param pr_data a long data.frame containing you plate reader data 103 | #' @param blank_well the well coordinates of one or more media blanks 104 | #' @param od_name the column name for the optical density data 105 | #' 106 | #' @return an updated data.frame with an additional column "normalised_OD" 107 | #' 108 | #' @importFrom dplyr %>% 109 | #' @importFrom rlang .data 110 | od_norm <- function(pr_data, blank_well, od_name) { 111 | pr_data$normalised_OD <- pr_data[, od_name] 112 | 113 | # remove background absorbance signal ------------------------------------- 114 | 115 | pr_data <- pr_data %>% 116 | dplyr::group_by(.data$time) %>% 117 | dplyr::mutate(normalised_OD = .data$normalised_OD - 118 | mean(.data$normalised_OD[.data$well %in% blank_well])) 119 | 120 | return(as.data.frame(pr_data)) 121 | } 122 | 123 | 124 | #' Normalise fluorescence against negative well 125 | #' 126 | #' @param pr_data a long data.frame containing you plate reader data with OD 127 | #' normalised 128 | #' @param neg_well the well coordinates of a non-fluorescent control 129 | #' @param blank_well the well coordinates of a media blank 130 | #' @param flu_name the column name of the fluorescence chanel to normalise 131 | #' @param af_model model used to fit negative control autofluorescence. 132 | #' For now these include "polynomial", "invers_poly", "exponential", "spline" or "loess". 133 | #' @param data_csv path to the original data. Used for saving normalisation curve plots. 134 | #' 135 | #' @return 136 | #' 137 | #' @importFrom dplyr %>% 138 | #' @importFrom rlang .data 139 | flu_norm <- function(pr_data, neg_well, blank_well, flu_name, af_model, data_csv) { 140 | pr_data$v1 <- pr_data[, flu_name] 141 | 142 | # fit autofluorescence model to negative control -------------------------- 143 | 144 | negative_data <- pr_data %>% dplyr::filter(.data$well %in% neg_well) 145 | 146 | if (af_model == "polynomial") { 147 | model <- stats::nls(v1 ~ (a * normalised_OD + b * normalised_OD ^ 2 + c), 148 | start = c(a = 1, b = 1, c = 1), data = negative_data) 149 | 150 | } else if (af_model == "inverse_poly") { 151 | model <- stats::nls(normalised_OD ~ (a * v1 + b * v1 ^ 2 + c), 152 | start = c(a = 1, b = 1, c = 1), data = negative_data) 153 | 154 | } else if (af_model == "exponential") { 155 | ## ae^(bx) + c 156 | ## intial parameter estimation 157 | model_0 <- stats::lm(log(v1) ~ normalised_OD, data = negative_data) 158 | start <- list(a = exp(stats::coef(model_0)[1]), 159 | b = stats::coef(model_0)[2], 160 | c = -1) 161 | 162 | model <- stats::nls(v1 ~ (a * exp(b * normalised_OD) + c), 163 | start = start, data = negative_data) 164 | 165 | } else if (af_model == "bi_exponential") { 166 | ## a exp(bx) + c exp(dx) + e 167 | 168 | model_0 <- stats::lm(log(v1) ~ normalised_OD, data = negative_data) 169 | start <- list(a = exp(stats::coef(model_0)[1]*0.2), 170 | b = stats::coef(model_0)[2]*0.2, 171 | c = exp(stats::coef(model_0)[1])*0.8, 172 | d = stats::coef(model_0)[2]*0.8, 173 | e = 1) 174 | 175 | model <- stats::nls(v1 ~ (a * exp(b * normalised_OD) + 176 | c * exp(d * normalised_OD) + e), 177 | start = start, 178 | data = negative_data) 179 | 180 | } else if (af_model == "linear_exponential") { 181 | ## ax + be^cx + d 182 | 183 | model_01 <- stats::lm(v1 ~ normalised_OD, data = negative_data) 184 | model_02 <- stats::lm(log(v1) ~ normalised_OD, data = negative_data) 185 | start <- list(a = stats::coef(model_01)[2], 186 | b = exp(stats::coef(model_02)[1]), 187 | c = stats::coef(model_02)[2], 188 | d = 1) 189 | 190 | model <- stats::nls(v1 ~ (a * normalised_OD + 191 | b * exp(c * normalised_OD) + d), 192 | start = start, 193 | data = negative_data) 194 | 195 | } else if (af_model == "power") { 196 | ## ax^b + c 197 | model_0 <- stats::lm(log(v1) ~ log(normalised_OD), data = negative_data) 198 | start <- list(a = exp(stats::coef(model_0)[1]), 199 | b = stats::coef(model_0)[2], 200 | c = 1) 201 | 202 | model <- stats::nls(v1 ~ (a * normalised_OD ^ b + c), 203 | start = start, data = negative_data) 204 | 205 | } else if (af_model == "linear_power") { 206 | ## ax + bx^c + d 207 | model_01 <- stats::lm(v1 ~ normalised_OD, data = negative_data) 208 | model_02 <- stats::lm(log(v1) ~ log(normalised_OD), data = negative_data) 209 | start <- list(a = stats::coef(model_01)[2], 210 | b = exp(stats::coef(model_02)[1]), 211 | c = stats::coef(model_02)[2], 212 | d = 1) 213 | 214 | model <- stats::nls(v1 ~ (a * normalised_OD + b * normalised_OD ^ c + d), 215 | start = start, 216 | data = negative_data) 217 | } else if (af_model == "loess") { 218 | model <- stats::loess(v1 ~ normalised_OD, 219 | data = negative_data, 220 | span = 0.5) 221 | } else if (af_model == "spline") { 222 | model <- mgcv::gam(v1 ~ s(normalised_OD), data = negative_data) 223 | } 224 | 225 | # plot model fit curves --------------------------------------------------- 226 | 227 | if (af_model == "polynomial" | af_model == "power" | 228 | af_model == "exponential" | af_model == "bi_exponential" | 229 | af_model == "linear_exponential" | af_model == "linear_power" | 230 | af_model == "loess") { 231 | plt <- ggplot2::ggplot() + 232 | ggplot2::geom_line(ggplot2::aes(x = negative_data$normalised_OD, 233 | y = stats::predict(model, 234 | negative_data))) + 235 | ggplot2::geom_point(ggplot2::aes(x = negative_data$normalised_OD, 236 | y = negative_data$v1)) + 237 | ggplot2::scale_x_continuous("normalised_OD") + 238 | ggplot2::scale_y_continuous(flu_name) + 239 | ggplot2::theme_bw() 240 | } else if (af_model == "spline") { 241 | plt <- ggplot2::ggplot() + 242 | ggplot2::geom_line(ggplot2::aes(x = negative_data$normalised_OD, 243 | y = mgcv::predict.gam(model, negative_data))) + 244 | ggplot2::geom_point(ggplot2::aes(x = negative_data$normalised_OD, 245 | y = negative_data$v1)) + 246 | ggplot2::scale_x_continuous("normalised_OD") + 247 | ggplot2::scale_y_continuous(flu_name) + 248 | ggplot2::theme_bw() 249 | } 250 | else if (af_model == "inverse_poly") { 251 | plt <- ggplot2::ggplot() + 252 | ggplot2::geom_line(ggplot2::aes(x = negative_data$normalised_OD, 253 | y = ((- (stats::coef(model)[1]) + 254 | sqrt((stats::coef(model)[1]) ^ 2 - 255 | 4 * 256 | (stats::coef(model)[2]) * 257 | (stats::coef(model)[3]) + 258 | 4 * 259 | (stats::coef(model)[2]) * 260 | negative_data$normalised_OD)) / 261 | (2 * (stats::coef(model)[2]))))) + 262 | ggplot2::geom_point(ggplot2::aes(y = negative_data$v1, 263 | x = negative_data$normalised_OD)) + 264 | ggplot2::scale_x_continuous("normalised_OD") + 265 | ggplot2::scale_y_continuous(flu_name) + 266 | ggplot2::theme_bw() 267 | } 268 | ggplot2::ggsave(filename = gsub(".csv", 269 | paste("_norm-curve_", flu_name, ".pdf", sep = ""), 270 | data_csv), 271 | plot = plt) 272 | 273 | # normalise fluorescence data --------------------------------------------- 274 | 275 | if (af_model == "polynomial" | af_model == "power" | 276 | af_model == "exponential" | af_model == "bi_exponential" | 277 | af_model == "linear_exponential" | af_model == "linear_power" | 278 | af_model == "loess") { 279 | pr_data$v1 <- pr_data$v1 - stats::predict(model, pr_data) 280 | } else if (af_model == "spline") { 281 | pr_data$v1 <- pr_data$v1 - mgcv::predict.gam(model, pr_data) 282 | } 283 | else if (af_model == "inverse_poly") { 284 | pr_data$v1 <- pr_data$v1 - ((- (stats::coef(model)[1]) + 285 | sqrt((stats::coef(model)[1]) ^ 2 - 4 * 286 | (stats::coef(model)[2]) * 287 | (stats::coef(model)[3]) + 288 | 4 * (stats::coef(model)[2]) * 289 | pr_data$normalised_OD)) / 290 | (2 * (stats::coef(model)[2]))) 291 | } 292 | 293 | # rename normalised fluorescence column 294 | names(pr_data)[ncol(pr_data)] <- paste("normalised_", flu_name, sep = "") 295 | 296 | return(pr_data) 297 | } 298 | 299 | #' Convert arbitrary absorbance units to calibrated units 300 | #' 301 | #' @param pr_data a data.frame of parsed plate reader data 302 | #' @param od_name the column name for the optical density data 303 | #' @param conversion_factors_csv if to_MEFL=T, path of the csv file containing 304 | #' conversion factors from plate reader calibration 305 | #' 306 | #' @importFrom dplyr %>% 307 | #' @importFrom rlang .data 308 | #' 309 | #' @return 310 | calibrate_od <- function(pr_data, od_name, conversion_factors_csv) { 311 | conversion_factors <- utils::read.csv(conversion_factors_csv) 312 | 313 | # Get conversion factor for OD -------------------------------------------- 314 | 315 | od_cf <- unlist(conversion_factors %>% 316 | dplyr::filter(.data$measure == od_name) %>% 317 | dplyr::select(.data$cf)) 318 | 319 | pr_data$calibrated_OD <- pr_data$normalised_OD / od_cf 320 | 321 | return(pr_data) 322 | } 323 | 324 | 325 | #' Convert arbitrary fluorescence units to calibrated units 326 | #' 327 | #' @param pr_data a data.frame of parsed plate reader data 328 | #' @param flu_name name of fluorophore to be calibrated 329 | #' @param flu_gain gain at which the fluorophore was measured 330 | #' @param od_name the column name for the optical density data 331 | #' @param conversion_factors_csv if to_MEFL=T, path of the csv file containing 332 | #' conversion factors from plate reader calibration 333 | #' 334 | #' @importFrom dplyr %>% 335 | #' @importFrom rlang .data 336 | #' 337 | #' @return 338 | calibrate_flu <- function(pr_data, flu_name, flu_gain, od_name, conversion_factors_csv) { 339 | conversion_factors <- utils::read.csv(conversion_factors_csv) 340 | 341 | 342 | # Get conversion factor for fluorophore ------------------------------------ 343 | flu_cfs <- conversion_factors %>% 344 | dplyr::filter(.data$fluorophore == flu_name) 345 | 346 | # if there is no calibration for the fluorophore 347 | if(nrow(flu_cfs) == 0) { 348 | return(pr_data) 349 | } 350 | 351 | tryCatch(this_cf <- flu_cfs[which(flu_cfs$measure == paste(flu_name, flu_gain)),]$cf, 352 | finally = this_cf <- NA) 353 | 354 | 355 | # if a conversion factor doesn't exist at the measured gain, try a -------- 356 | if(is.na(this_cf)){ 357 | flu_cfs$gain <- as.numeric(gsub(paste(flu_name, " ", sep=""), "", flu_cfs$measure)) 358 | 359 | # Fit cf to Gain relation to get cf for specific gain --------------------- 360 | model <- stats::lm(log10(cf) ~ poly(gain, 2), data = flu_cfs) 361 | this_cf <- 10 ^ stats::predict(model, data.frame(gain = flu_gain)) 362 | ggplot2::ggplot() + 363 | ggplot2::geom_line(ggplot2::aes(x = flu_cfs$gain, 364 | y = 10^stats::predict(model, flu_cfs))) + 365 | ggplot2::geom_point(ggplot2::aes(x = flu_cfs$gain, 366 | y = flu_cfs$cf)) + 367 | ggplot2::geom_vline(xintercept = flu_gain, linetype = 2) + 368 | ggplot2::geom_hline(yintercept = 10 ^ stats::predict(model, data.frame(gain = flu_gain)), 369 | linetype = 2) + 370 | ggplot2::geom_point(ggplot2::aes(x = flu_gain, 371 | y = 10 ^ stats::predict(model, data.frame(gain = flu_gain))), 372 | colour = "red", shape = 1, size = 2) + 373 | ggplot2::scale_x_continuous("Gain") + 374 | ggplot2::scale_y_continuous("Conversion factor (MEFL/a.u.)", 375 | trans = "log10") + 376 | ggplot2::theme_bw() 377 | } 378 | 379 | pr_data[,paste("calibrated_", flu_name, sep="")] <- 380 | (pr_data[,paste("normalised_", flu_name, sep="")] / this_cf) 381 | 382 | return(pr_data) 383 | } 384 | 385 | 386 | #' Generate Conversion Factors 387 | #' 388 | #' @param calibration_csv path of a .csv file of your calibration data 389 | #' 390 | #' @export 391 | #' @importFrom dplyr %>% 392 | #' @importFrom rlang .data := 393 | generate_cfs <- function(calibration_csv) { 394 | calibration_data <- utils::read.csv(calibration_csv, header = T, check.names = F) 395 | 396 | 397 | # get types of measure ---------------------------------------------------- 398 | well_idx <- which(names(calibration_data) == "well") 399 | row_idx <- which(names(calibration_data) == "row") 400 | measures <- names(calibration_data)[(well_idx+1):(row_idx-1)] 401 | 402 | 403 | # remove saturated values ------------------------------------------------- 404 | # using similar approach to Beal et al. 2019 bioRxiv to assess validitiy of measurements 405 | 406 | non_sat_values <- c() 407 | for(calib in unique(calibration_data$calibrant)){ 408 | # get values only for this calibrant 409 | temp_calib_values <- calibration_data %>% 410 | dplyr::filter(.data$calibrant == calib) %>% 411 | dplyr::arrange(desc(concentration)) 412 | 413 | # get concentrations at which we have measurements 414 | concentrations <- sort(unique(temp_calib_values$concentration), decreasing = T) 415 | 416 | # calculate fold dilution used 417 | fold_dilution <- concentrations[2] / concentrations[3] 418 | 419 | # points are considered saturated if they have less than 75% measurement change relative to the fold_dilution 420 | high_saturation_threshold <- fold_dilution * 0.75 421 | 422 | # work out dilution order from concentrations 423 | temp_calib_values$dilution_ratio <- 1 / fold_dilution 424 | temp_calib_values$max_concentration <- max(concentrations) 425 | temp_calib_values$dilution_idx <- - log(temp_calib_values$max_concentration / temp_calib_values$concentration) / log(temp_calib_values$dilution_ratio) 426 | 427 | for(meas in measures){ 428 | blank_mean <- mean(temp_calib_values[temp_calib_values$concentration == 0,][[meas]], na.rm = T) 429 | blank_sd <- stats::sd(temp_calib_values[temp_calib_values$concentration == 0,][[meas]], na.rm = T) 430 | 431 | for(rplct in unique(temp_calib_values$replicate)){ 432 | 433 | values <- temp_calib_values[temp_calib_values$replicate == rplct, meas] 434 | saturated_1 <- values[1:(length(values)-1)] <= values[2:(length(values))] * high_saturation_threshold 435 | saturated_2 <- values[2:(length(values))] >= values[1:(length(values)-1)] / high_saturation_threshold 436 | saturated_3 <- values[1:(length(values)-1)] <= blank_mean + 2 * blank_sd 437 | saturated_4 <- is.na(values[1:(length(values)-1)]) 438 | saturated <- saturated_1 | saturated_2 | saturated_3 | saturated_4 439 | 440 | temp_calib_values[temp_calib_values$concentration %in% concentrations[1:(length(concentrations)-1)][saturated] & temp_calib_values$replicate == rplct, meas] <- NA 441 | } 442 | } 443 | non_sat_values <- rbind(non_sat_values, temp_calib_values) 444 | } 445 | 446 | 447 | # calculate mean of 4 replicates ------------- 448 | 449 | summ_values <- non_sat_values %>% 450 | dplyr::group_by(.data$calibrant, .data$fluorophore, .data$media, 451 | .data$concentration, .data$dilution_ratio, 452 | .data$max_concentration, .data$dilution_idx, .drop = F) %>% 453 | dplyr::summarise_at(measures, mean, na.rm = TRUE) %>% 454 | dplyr::filter(!is.na(.data$concentration)) 455 | 456 | 457 | # normalise data ---------------------------------------------------------- 458 | 459 | norm_values <- summ_values 460 | for(meas in measures){ 461 | norm_values <- norm_values %>% 462 | dplyr::group_by(.data$calibrant) %>% 463 | dplyr::mutate({{meas}} := .data[[meas]] - 464 | .data[[meas]][.data$concentration == 0]) 465 | } 466 | norm_values <- norm_values %>% dplyr::filter(.data$concentration != 0) 467 | 468 | 469 | # fit pipetting error model for conversion factors ------------------------ 470 | # error model from Beal et al. 2019 bioRxiv 471 | 472 | long_values <- stats::na.omit(norm_values %>% 473 | tidyr::pivot_longer(tidyselect::all_of(measures), 474 | names_to = "measure", 475 | values_to = "normalised_value")) 476 | 477 | fit_values <- c() 478 | for(calib in unique(long_values$calibrant)){ 479 | temp_calib_values <- long_values %>% dplyr::filter(.data$calibrant == calib) 480 | for(meas in unique(temp_calib_values$measure)){ 481 | temp_meas_calib_values <- temp_calib_values %>% 482 | dplyr::filter(.data$measure == meas) 483 | 484 | if(nrow(temp_meas_calib_values) < 3){ 485 | next 486 | } 487 | 488 | model <- 0 489 | 490 | error_func <- function(x){ 491 | data <- temp_meas_calib_values 492 | 493 | cf <- x[1] 494 | beta <- x[2] 495 | error <- 0 496 | 497 | for(i in data$dilution_idx){ 498 | data_i <- data[data$dilution_idx == i,] 499 | 500 | b_i <- data_i$max_concentration * (1 - data_i$dilution_ratio - beta) * 501 | (data_i$dilution_ratio + beta) ^ (data_i$dilution_idx - 1) 502 | 503 | e_i <- abs(log10(cf * b_i / data_i$normalised_value))^2 504 | 505 | error <- error + e_i 506 | } 507 | 508 | return(error) 509 | } 510 | 511 | 512 | for(init_cf in c(1e-9, 1e-10, 1e-11, 1e-12, 1e-13, 1e-14)){ 513 | res <- stats::optim(c(init_cf, 0), error_func) 514 | 515 | if(res$convergence == 0){ 516 | new_fit <- data.frame(cf = res$par[1], beta = res$par[2], 517 | calibrant = calib, 518 | fluorophore = temp_meas_calib_values$fluorophore[1], 519 | measure = meas) 520 | fit_values <- rbind(fit_values, new_fit) 521 | break 522 | } 523 | } 524 | } 525 | } 526 | 527 | long_values <- dplyr::full_join(long_values, fit_values) 528 | 529 | 530 | # plot the mean normalized values ----------------------------------------- 531 | 532 | abs_plt <- 533 | ggplot2::ggplot(data = long_values %>% 534 | dplyr::filter(.data$calibrant == "microspheres")) + 535 | ggplot2::geom_point(ggplot2::aes(x = dilution_idx, 536 | y = normalised_value)) + 537 | ggplot2::geom_line(ggplot2::aes(x = dilution_idx, 538 | y = cf * max_concentration * 539 | (1 - dilution_ratio - beta) * 540 | (dilution_ratio + beta) ^ (dilution_idx - 1))) + 541 | ggplot2::scale_y_continuous("Normalised Absorbance", trans = "log10") + 542 | ggplot2::scale_x_continuous("Microspheres dilution") + 543 | ggplot2::facet_wrap(~measure) + 544 | ggplot2::theme_bw(base_size = 12) 545 | 546 | ggplot2::ggsave(gsub(".csv", "_absorbance_cfs.pdf", calibration_csv), 547 | plot = abs_plt) 548 | 549 | flu_plt <- 550 | ggplot2::ggplot(data = long_values %>% 551 | dplyr::filter(.data$calibrant %in% c("fluorescein", 'FITC'))) + 552 | ggplot2::geom_point(ggplot2::aes(x = dilution_idx, 553 | y = normalised_value)) + 554 | ggplot2::geom_line(ggplot2::aes(x = dilution_idx, 555 | y = cf * max_concentration * 556 | (1 - dilution_ratio - beta) * 557 | (dilution_ratio + beta) ^ (dilution_idx - 1))) + 558 | ggplot2::scale_y_continuous("Normalised Fluorescence", trans = "log10") + 559 | ggplot2::scale_x_continuous("Fluorescein dilution") + 560 | ggplot2::facet_wrap(~measure) + 561 | ggplot2::theme_bw(base_size = 12) 562 | 563 | ggplot2::ggsave(gsub(".csv", "_fluorescence_cfs.pdf", calibration_csv), 564 | plot = flu_plt) 565 | 566 | 567 | # save conversion factors to a csv ---------------------------------------- 568 | 569 | utils::write.csv(fit_values, gsub(".csv", "_cfs.csv", calibration_csv), row.names = FALSE) 570 | } 571 | -------------------------------------------------------------------------------- /R/tecanInfiniteFunctions.R: -------------------------------------------------------------------------------- 1 | #' Find next blank line 2 | #' 3 | #' @param start_idx 4 | #' @param data 5 | #' 6 | #' @return row index of next blank line 7 | next_blank <- function(start_idx, data){ 8 | next_start_idx <- start_idx 9 | while (!is.na(data[next_start_idx, 1])) { 10 | next_start_idx <- next_start_idx + 1 11 | } 12 | return(next_start_idx) 13 | } 14 | 15 | #' Find next non-blank line 16 | #' 17 | #' @param start_idx 18 | #' @param data 19 | #' 20 | #' @return row index of next non-blank line 21 | next_filled <- function(start_idx, data){ 22 | next_start_idx <- start_idx 23 | while (is.na(data[next_start_idx, 1])) { 24 | next_start_idx <- next_start_idx + 1 25 | } 26 | return(next_start_idx) 27 | } 28 | 29 | #' Parser for Tecan Infinite plate reader data 30 | #' 31 | #' @param data_csv path to .csv, .xls or .xlsx file from Tecan Infinit plate reader 32 | #' @param layout_csv path to csv file containing plate layout information 33 | #' @param timeseries Boolean flag indicating whether the data is a timeseries or 34 | #' single recording. The Tecan software outputs the two scenarios differently. 35 | #' 36 | #' @return a data.frame containing the parsed plate reader data 37 | #' @export 38 | #' @importFrom rlang .data 39 | #' 40 | infinite_parse <- function(data_csv, layout_csv, timeseries=F) { 41 | 42 | if(stringr::str_ends(data_csv, ".xlsx") | stringr::str_ends(data_csv, ".xls")){ 43 | data <- as.data.frame(readxl::read_excel(path = data_csv, 44 | col_names = F, 45 | col_types = "text")) 46 | } else if(stringr::str_ends(data_csv, ".csv")){ 47 | data <- utils::read.table(data_csv, sep = ",", 48 | na.strings = c(""), 49 | header = F, 50 | stringsAsFactors = F) 51 | } else { 52 | stop("data_csv is must be a .csv, .xls or .xlsx file.") 53 | } 54 | 55 | plate_layout <- utils::read.csv(layout_csv) 56 | 57 | if(timeseries == TRUE){ 58 | start_time_idx <- which(data[, 1] == "Start Time:") 59 | if (length(start_time_idx) > 1) { 60 | start_time_idx <- start_time_idx[length(start_time_idx)] 61 | } 62 | 63 | # find where the next block starts 64 | next_block_start_idx <- next_filled(start_time_idx + 1, data) 65 | 66 | end_of_file <- F 67 | all_data <- c() 68 | while (!end_of_file) { 69 | # find what is being measured 70 | block_name <- data[next_block_start_idx, 1] 71 | 72 | # check if we are at the end of the file 73 | if (block_name == "End Time:") { 74 | end_of_file <- T 75 | break 76 | } 77 | 78 | # find where the end of the current measurement block is 79 | block_end_idx <- next_blank(next_block_start_idx, data) 80 | 81 | # grab the data only for that measurement 82 | new_block <- data[(next_block_start_idx + 1):(block_end_idx - 1), ] 83 | # new_block <- new_block[-c(1,3), ] # remove cycle no. and temp. 84 | 85 | # trim unnecessary readings i.e. temp and cycle number 86 | # and rename columns 87 | times <- as.character(new_block[2,]) 88 | new_block <- new_block[-c(1:3), ] 89 | names(new_block) <- times 90 | names(new_block)[1] <- "well" 91 | new_block <- new_block[,names(new_block) != "NA"] # remove erroneous NA columns 92 | 93 | # reshape time into long data 94 | new_block <- new_block %>% 95 | tidyr::pivot_longer(cols = 2:ncol(new_block), 96 | names_to = "time", names_transform = as.numeric, 97 | values_to = "value", values_transform = as.numeric) 98 | 99 | # add info for each well 100 | joined_block <- dplyr::full_join(plate_layout, new_block) 101 | joined_block$measure <- block_name 102 | 103 | # 104 | all_data <- rbind(all_data, joined_block) 105 | 106 | # 107 | next_block_start_idx <- next_filled(block_end_idx + 1, data) 108 | } 109 | 110 | # rearrange data ---------------------------------------------------------- 111 | layout_cols <- ncol(plate_layout) 112 | out_data <- all_data %>% 113 | tidyr::pivot_wider(names_from = .data$measure, values_from = .data$value) %>% # reshape so we have a column for each measurement type 114 | dplyr::mutate(row = substr(x = .data$well, start = 1, stop = 1)) %>% # make a "row" column from the "well" column 115 | dplyr::mutate(column = as.numeric(substr(x = .data$well, start = 2, # and make a "column" column 116 | stop = nchar(.data$well)))) %>% 117 | dplyr::arrange_at(dplyr::vars(.data$time, # order the rows 118 | .data$row, 119 | .data$column)) 120 | 121 | # write parsed data to csv ------------------------------------------------ 122 | out_name <- gsub(".csv", "_parsed.csv", data_csv) 123 | out_name <- gsub(".xlsx", "_parsed.csv", out_name) 124 | utils::write.csv(x = out_data, file = out_name, row.names = FALSE) 125 | 126 | return(out_data) 127 | } 128 | # else if (timeseries == FALSE){ 129 | # start_time_idx <- which(data[, 1] == "Start Time") # get start and end time ids 130 | # end_idx <- which(data[, 1] == "End Time") 131 | # names_idx <- which(data[, 1] == "Name") 132 | # names_idx <- names_idx[2:length(names_idx)] # remove the first start time entry which just details plate type 133 | # 134 | # all_data <- c() 135 | # for (i in seq_len(length(start_time_idx))) { 136 | # block_name <- data[names_idx[i], 2] # record name of what is being measured 137 | # 138 | # block_start <- start_time_idx[i] + 4 # find start and end of measurement block 139 | # block_end_idx <- end_idx[i] - 3 140 | # 141 | # new_block <- data[(block_start):(block_end_idx), 1:2] # grab and name the data 142 | # names(new_block)[1] <- "well" 143 | # names(new_block)[2] <- "value" 144 | # 145 | # new_block$value <- as.numeric(new_block$value) 146 | # 147 | # joined_block <- dplyr::full_join(plate_layout, new_block) # join to plate layout csv, add measurement category 148 | # joined_block$measure <- block_name 149 | # 150 | # all_data <- rbind(all_data, joined_block) # add to all data 151 | # } 152 | # 153 | # # rearrange data ---------------------------------------------------------- 154 | # spread_data <- tidyr::pivot_wider(all_data, names_from = .data$measure, 155 | # values_from = .data$value) 156 | # spread_data$row <- substr(x = spread_data$well, start = 1, stop = 1) 157 | # spread_data$column <- as.numeric(substr(x = spread_data$well, start = 2, 158 | # stop = nchar(spread_data$well))) 159 | # spread_data <- dplyr::arrange_at(spread_data, dplyr::vars(.data$row, 160 | # .data$column)) 161 | # 162 | # # write parsed data to csv ------------------------------------------------ 163 | # out_name <- gsub(".csv", "_parsed.csv", data_csv) 164 | # utils::write.csv(x = spread_data, file = out_name, row.names = FALSE) 165 | # 166 | # return(spread_data) 167 | # } 168 | } 169 | -------------------------------------------------------------------------------- /R/tecanSparkFunctions.R: -------------------------------------------------------------------------------- 1 | #' Find next blank line 2 | #' 3 | #' @param start_idx 4 | #' @param data 5 | #' 6 | #' @return row index of next blank line 7 | next_blank_row <- function(start_idx, data){ 8 | next_start_idx <- start_idx 9 | while (any(!is.na(data[next_start_idx, ]))) { 10 | next_start_idx <- next_start_idx + 1 11 | if(next_start_idx >= nrow(data)){ 12 | return(NA) 13 | } 14 | } 15 | return(next_start_idx) 16 | } 17 | 18 | #' Find next blank line 19 | #' 20 | #' @param start_idx 21 | #' @param data 22 | #' 23 | #' @return row index of next blank line 24 | next_blank_cell <- function(start_idx, data, col){ 25 | next_start_idx <- start_idx 26 | while (!is.na(data[next_start_idx, col])) { 27 | next_start_idx <- next_start_idx + 1 28 | if(next_start_idx >= nrow(data)){ 29 | return(NA) 30 | } 31 | } 32 | return(next_start_idx) 33 | } 34 | 35 | #' Find next non-blank line 36 | #' 37 | #' @param start_idx 38 | #' @param data 39 | #' 40 | #' @return row index of next non-blank line 41 | next_filled_row <- function(start_idx, data){ 42 | next_start_idx <- start_idx 43 | while (any(is.na(data[next_start_idx, ]))) { 44 | next_start_idx <- next_start_idx + 1 45 | if(next_start_idx >= nrow(data)){ 46 | return(NA) 47 | } 48 | } 49 | return(next_start_idx) 50 | } 51 | 52 | #' Find next non-blank line 53 | #' 54 | #' @param start_idx 55 | #' @param data 56 | #' 57 | #' @return row index of next non-blank line 58 | next_filled_cell <- function(start_idx, data, col){ 59 | next_start_idx <- start_idx 60 | while (is.na(data[next_start_idx, col])) { 61 | next_start_idx <- next_start_idx + 1 62 | if(next_start_idx >= nrow(data)){ 63 | return(NA) 64 | } 65 | } 66 | return(next_start_idx) 67 | } 68 | 69 | #' Parser for Tecan Spark plate reader data 70 | #' 71 | #' @param data_csv path to .csv, .xls or .xlsx file from Tecan Spark plate reader 72 | #' @param layout_csv path to csv file containing plate layout information 73 | #' @param timeseries Boolean flag indicating whether the data is a timeseries or 74 | #' single recording. The Tecan software outputs the two scenarios differently. 75 | #' @param wells_as_columns Boolean flag indicating whether blocks of data are 76 | #' oriented with wells as columns or rows 77 | #' 78 | #' @return a data.frame containing the parsed plate reader data 79 | #' @export 80 | #' @importFrom rlang .data 81 | #' 82 | spark_parse <- function(data_csv, layout_csv, timeseries=F, wells_as_columns=F) { 83 | 84 | if(stringr::str_ends(data_csv, ".xlsx") | stringr::str_ends(data_csv, ".xls")){ 85 | data <- as.data.frame(readxl::read_excel(path = data_csv, 86 | col_names = F, 87 | col_types = "text")) 88 | } else if(stringr::str_ends(data_csv, ".csv")){ 89 | data <- utils::read.table(data_csv, sep = ",", 90 | na.strings = c(""), 91 | header = F, 92 | stringsAsFactors = F) 93 | } else { 94 | stop("data_csv is must be a .csv, .xls or .xlsx file.") 95 | } 96 | 97 | plate_layout <- utils::read.csv(layout_csv) 98 | 99 | if(timeseries == TRUE){ 100 | start_time_idx <- which(data[, 1] == "Start Time") 101 | if (length(start_time_idx) > 1) { 102 | start_time_idx <- start_time_idx[length(start_time_idx)] 103 | } 104 | 105 | # find where the next block starts 106 | next_block_start_idx <- next_filled_cell(start_time_idx + 1, data, col=1) 107 | 108 | end_of_file <- F 109 | all_data <- c() 110 | while (!end_of_file) { 111 | # find what is being measured 112 | block_name <- data[next_block_start_idx, 1] 113 | 114 | # check if we are at the end of the file 115 | if (block_name == "End Time") { 116 | end_of_file <- T 117 | break 118 | } 119 | 120 | # find where the end of the current measurement block is 121 | block_end_idx <- next_blank_cell(next_block_start_idx, data, col=1) 122 | 123 | # grab the data only for that measurement 124 | new_block <- data[(next_block_start_idx + 1):(block_end_idx - 1), ] 125 | # new_block <- new_block[-c(1,3), ] # remove cycle no. and temp. 126 | 127 | if(!wells_as_columns){ 128 | # trim unnecessary readings i.e. temp and cycle number 129 | # and rename columns 130 | times <- as.character(new_block[2,]) 131 | new_block <- new_block[-c(1:3), ] 132 | names(new_block) <- times 133 | names(new_block)[1] <- "well" 134 | new_block <- new_block %>% 135 | tidyr::pivot_longer(cols = 2:ncol(new_block), 136 | names_to = "time", 137 | values_to = "value", 138 | values_transform = list(value = as.numeric)) %>% 139 | dplyr::mutate(time = as.numeric(time)) 140 | } else if(wells_as_columns){ 141 | wells <- new_block[1, -c(1,3)] 142 | new_block <- new_block[-1,-c(1,3)] 143 | names(new_block) <- wells 144 | names(new_block)[1] <- "time" 145 | new_block <- new_block %>% 146 | tidyr::pivot_longer(cols = 2:ncol(new_block), 147 | names_to = "well", 148 | values_to = "value", 149 | values_transform = list(value = as.numeric)) %>% 150 | dplyr::mutate(time = as.numeric(time)) 151 | } 152 | 153 | # add info for each well 154 | joined_block <- dplyr::full_join(plate_layout, new_block) 155 | joined_block$measure <- block_name 156 | 157 | # 158 | all_data <- rbind(all_data, joined_block) 159 | 160 | # 161 | next_block_start_idx <- next_filled(block_end_idx + 1, data) 162 | } 163 | 164 | # rearrange data ---------------------------------------------------------- 165 | out_data <- all_data %>% 166 | tidyr::pivot_wider(names_from = .data$measure, values_from = .data$value) %>% # reshape so we have a column for each measurement type 167 | dplyr::mutate(row = substr(x = .data$well, start = 1, stop = 1)) %>% # make a "row" column from the "well" column 168 | dplyr::mutate(column = as.numeric(substr(x = .data$well, start = 2, # and make a "column" column 169 | stop = nchar(.data$well)))) %>% 170 | dplyr::arrange_at(dplyr::vars(.data$time, # order the rows 171 | .data$row, 172 | .data$column)) 173 | 174 | # write parsed data to csv ------------------------------------------------ 175 | out_name <- gsub(".csv", "_parsed.csv", data_csv) 176 | out_name <- gsub(".xlsx", "_parsed.csv", out_name) 177 | utils::write.csv(x = out_data, file = out_name, row.names = FALSE) 178 | 179 | return(out_data) 180 | } 181 | else if (timeseries == FALSE){ 182 | start_time_idx <- which(data[, 1] == "Start Time") # get start and end time ids 183 | end_idx <- which(data[, 1] == "End Time") 184 | names_idx <- which(data[, 1] == "Name") 185 | names_idx <- names_idx[2:length(names_idx)] # remove the first start time entry which just details plate type 186 | 187 | all_data <- c() 188 | for (i in seq_len(length(start_time_idx))) { 189 | block_name <- data[names_idx[i], 2] # record name of what is being measured 190 | 191 | block_start <- start_time_idx[i] + 4 # find start and end of measurement block 192 | block_end_idx <- end_idx[i] - 3 193 | 194 | new_block <- data[(block_start):(block_end_idx), 1:2] # grab and name the data 195 | names(new_block)[1] <- "well" 196 | names(new_block)[2] <- "value" 197 | 198 | new_block$value <- as.numeric(new_block$value) 199 | 200 | joined_block <- dplyr::full_join(plate_layout, new_block) # join to plate layout csv, add measurement category 201 | joined_block$measure <- block_name 202 | 203 | all_data <- rbind(all_data, joined_block) # add to all data 204 | } 205 | 206 | # rearrange data ---------------------------------------------------------- 207 | spread_data <- tidyr::pivot_wider(all_data, names_from = .data$measure, 208 | values_from = .data$value) 209 | spread_data$row <- substr(x = spread_data$well, start = 1, stop = 1) 210 | spread_data$column <- as.numeric(substr(x = spread_data$well, start = 2, 211 | stop = nchar(spread_data$well))) 212 | spread_data <- dplyr::arrange_at(spread_data, dplyr::vars(.data$row, 213 | .data$column)) 214 | 215 | # write parsed data to csv ------------------------------------------------ 216 | out_name <- gsub(".csv", "_parsed.csv", data_csv) 217 | utils::write.csv(x = spread_data, file = out_name, row.names = FALSE) 218 | 219 | return(spread_data) 220 | } 221 | } 222 | 223 | #' Parser for Tecan Spark plate reader data 224 | #' 225 | #' @param data_csv path to csv file from Tecan Spark plate reader 226 | #' @param layout_csv path to csv file containing plate layout information 227 | #' 228 | #' @return a data.frame containing the parsed plate reader data 229 | #' @export 230 | #' 231 | sparkParse <- function(data_csv, layout_csv) { 232 | return(spark_parse(data_csv, layout_csv)) 233 | } 234 | -------------------------------------------------------------------------------- /README.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Using FlopR" 3 | author: "Alex J H Fedorec" 4 | date: "02/06/2021" 5 | output: 6 | github_document: 7 | html_preview: false 8 | toc: true 9 | df_print: kable 10 | --- 11 | 12 | ```{r setup, include=FALSE} 13 | knitr::opts_chunk$set(echo = TRUE) 14 | ``` 15 | 16 | 17 | ## Prerequisite Knowledge 18 | 19 | We have attempted to make our software usable with minimal prior knowledge of the R programming language or programming in general. You will need to be familiar with the idea of running commands from a console or writing basic scripts. For R beginners, [this](https://moderndive.netlify.app/1-getting-started.html) is a great starting point, there are some good resources [here](https://education.rstudio.com/learn/beginner/) and we suggest using the [RStudio application](https://rstudio.com/products/rstudio/). It provides an environment for writing and running R code. 20 | 21 | ## Installation 22 | 23 | FlopR relies on several other R packages. Most of them are available through the "Comprehensive R Archive Network (CRAN)" which just means that they can be automatically installed. There are, however, a couple that need to be manually installed if you are using the flow cytometry processing functions. To do this use the following commands: 24 | 25 | ```{r eval=FALSE, message=FALSE, warning=FALSE, results='hide'} 26 | install.packages("devtools", repos = "https://cloud.r-project.org/") 27 | 28 | if (!requireNamespace("BiocManager", quietly = TRUE)) 29 | install.packages("BiocManager") 30 | 31 | BiocManager::install(c("flowCore", "flowClust", "flowStats")) 32 | ``` 33 | 34 | Once those packages have been installed we are ready to install FlopR. 35 | 36 | ```{r eval=FALSE, message=FALSE, warning=FALSE, results='hide'} 37 | devtools::install_github("ucl-cssb/flopr") 38 | ``` 39 | 40 | This grabs the latest version of FlopR from GitHub and builds it on your computer. If it installed successfully we should now be able to load the FlopR package in R. 41 | 42 | ```{r eval=FALSE, message=FALSE, warning=FALSE, results='hide'} 43 | library(flopr) 44 | ``` 45 | 46 | The examples in this document can be run using the data in the "example" folder. Download the whole folder and make sure that you have set your current working directory (you can use the `setwd()` command in R) to the location where you saved it on your computer 47 | 48 | ## A Quick Note on .csv Files 49 | This package makes extensive use of .csv (comma separated variables) files for data and meta-data. Unfortunately, not all .csv are created equal. 50 | 51 | - When using a Windows OS computer we recommend that you save your .csv files explicitly with a UTF-8 file encoding (as shown below). This means that your files can be used by someone running a different operating system without error. 52 | - Some parts of the world use decimal commas instead of decimal points. In these places, .csv files use ";" as a separator instead of ",". Unfortunately, we are unable to automatically detect which format your .csv files are in. As such, you will have to ensure that your files are saved using "," as the separator and decimal points for the decimal mark. [This article](https://support.collaborativedrug.com/hc/en-us/articles/115004985746-CSV-files-comma-separator-and-decimal-number-format) has some help for doing so. 53 | 54 | ![From Microsoft Excel, save as UTF-8 encoded .csv file](examples/csv_save.png) 55 | 56 | ## Plate Reader Calibration 57 | 58 | The experimental protocols for producing absorbance and fluorescence calibration data can be found [here](https://www.protocols.io/workspaces/igem-measurement) and [here](https://pubs.acs.org/doi/full/10.1021/acssynbio.0c00296). 59 | 60 | The data produced by plate readers from different manufacturers comes in different formats. The first step we need to do is to "parse" the data from the plate reader into a standard format. We have written an example parsers for use with data from Tecan plate readers and the Biotek Neo 2. If you need help writing a parser for your plate reader, please contact us and we'll see what we can do. 61 | 62 | For a Tecan plate reader, the data is saved as an Excel .xls file. As of flopR version 0.4.02, the spark_parse function accepts Excel files (.xls and .xlsx). If you are using an earlier version, the data first needs to be saved as a .csv file (open in Excel and "Save As" .csv) that can be read by R. We also need a .csv file telling us what is in each well of our microtitre plate. An example can be found in the "examples/plate_reader/tecan_spark" folder, but the first few rows looks like this: 63 | 64 | ```{r echo=FALSE} 65 | head(read.csv("examples/plate_reader/tecan_spark/calibration_plate_layout.csv")) 66 | ``` 67 | 68 | Once we have the calibration data and layout .csv files we can parse the data. 69 | 70 | ```{r eval=FALSE} 71 | flopr::spark_parse(data_csv = "examples/plate_reader/tecan_spark/191219_calibration_membrane.csv", 72 | layout_csv = "examples/plate_reader/tecan_spark/calibration_plate_layout.csv", 73 | timeseries = FALSE) 74 | ``` 75 | 76 | The `data_csv` argument takes the path to the calibration data. `layout_csv` is the path to the plate layout .csv file. Finally, the Tecan plate readers save timeseries data differently from single timepoint data, so we have a Boolean flag, `timeseries`, that lets the parser know that this is not a timeseries. 77 | 78 | The `spark_parse()` function saves the parsed calibration data in a new .csv file, in the same location as the calibration data, with "_parsed" appended to the filename. The first few rows look like this: 79 | 80 | ```{r echo=FALSE} 81 | head(read.csv("examples/plate_reader/tecan_spark/191219_calibration_membrane_parsed.csv", check.names = FALSE)) 82 | ``` 83 | 84 | The parser has extracted the information we need from the calibration data and merged it with the plate layout information so that we now have columns containing each of the measurements for each well. 85 | 86 | Now we can actually calculate our calibration coefficients. To do this we just need to use one function and give it our parsed data. 87 | 88 | ```{r eval=FALSE} 89 | flopr::generate_cfs(calibration_csv = "examples/plate_reader/tecan_spark/191219_calibration_membrane_parsed.csv") 90 | ``` 91 | 92 | For details about how this process works, you can read our paper [here](https://pubs.acs.org/doi/full/10.1021/acssynbio.0c00296). At the end, there should be two .pdf images showing the calibration curves for absorbance and fluorescence, along with a new .csv file, appended with "_cfs", containing the parameters for use in the future, the first few rows of which look like this: 93 | 94 | ```{r echo=FALSE} 95 | head(read.csv("examples/plate_reader/tecan_spark/191219_calibration_membrane_parsed_cfs.csv", check.names = FALSE)) 96 | ``` 97 | 98 | The "cf" column contains the calibration coefficients that will be used to calibrate our data in later experiments. 99 | 100 | Before we get too excited we need to check the images to make sure that the calibration curves look sensible. The software attempts to remove data points which it deems are invalid, but this process isn't perfect and occasionally may need you to remove data points from the "*_parsed.csv" file. Using the example data, you can see ([here](examples/plate_reader/tecan_spark/191219_calibration_membrane_parsed_absorbance_cfs.pdf)) that some of the fluorescein wells are considered valid absorbance measurements. In this case, it isn't the end of the world since we would never use the parameters produced from those two curves. 101 | 102 | n.b. Currently the software is setup to work with "microspheres" for calibrating cell number and "fluorescein" for calibrating GFP fluorescence. We hope to extend it in the near future to work with other calibrants. 103 | 104 | 105 | ## Processing Plate Reader Data 106 | 107 | As mentioned above, because plate readers from different manufacturers save the data in different formats, the first step we need to do is parse our raw data. The parser that we provide takes Tecan plate reader data in the form of a .csv file. We also need a .csv file telling us what is in each well of you microtitre plate. This can include any information that you wish; we include as much meta-data as possible as it makes our data analysis later much smoother. (Before version 0.4.01: The only requirement is that **the last column must be named "well"** and include an identifier (usually the well id i.e. B2) that can be matched to the same identifier in the plate reader data.) Here's an example where we include information about the strains, plasmids, media, inducers, etc.: 108 | 109 | ```{r echo=FALSE} 110 | head(read.csv("examples/plate_reader/tecan_spark/200228_example_layout.csv", check.names = FALSE), n = 2) 111 | ``` 112 | 113 | Now we can use our parsing function. 114 | 115 | ```{r eval=FALSE} 116 | flopr::spark_parse(data_csv = "examples/plate_reader/tecan_spark/200228_example_data.csv", 117 | layout_csv = "examples/plate_reader/tecan_spark/200228_example_layout.csv", 118 | timeseries = TRUE) 119 | ``` 120 | 121 | The data is extracted and the meta-data from the layout is attached. Note that this time the data a timeseries so we set the `timeseries` flag to `TRUE`. A new .csv file is produced containing the parsed data with "_parsed" appended to the filename. 122 | 123 | Now we can start processing our data. There is one function that does all the work for: `process_plate()`. There are a few arguments that we need to give the function which will control what happens. 124 | 125 | ```{r eval=FALSE} 126 | flopr::process_plate(data_csv = "examples/plate_reader/tecan_spark/200228_example_data_parsed.csv", 127 | blank_well = c("C12", "D12"), 128 | neg_well = c("C6", "D6", "E6"), 129 | od_name = "OD700", 130 | flu_names = c("GFP", "mCherry"), 131 | af_model = "spline", 132 | to_MEFL = TRUE, 133 | flu_gains = 135, 134 | conversion_factors_csv = "examples/plate_reader/tecan_spark/191219_calibration_membrane_parsed_cfs.csv") 135 | ``` 136 | 137 | Let's walk through what each of the arguments do: 138 | 139 | - `data_csv` is the path to our parsed data. 140 | - `blank_well` are the well identifiers of wells containing media blanks. These are used for normalising absorbance. If you only have one blank well you can specify it using `blank_well = "C12"` for example. 141 | - `neg_well` are the well identifiers of wells containing negative controls. These are used for normalising fluorescence. As above, if you only have one negative control well you can specify it using `neg_well = "C6"` for example. 142 | - `od_name` is the name of the column containing our absorbance values in the parsed data .csv file. Currently we can only use one absorbance column, so if you record absorbance at multiple wavelengths (like I do), you will have to pick one. 143 | - `flu_names` are the names of the columns containing our fluorescence values. You can include as many or as few of you fluorescence columns as you like. Whichever columns are named in here, we will attempt to normalise. 144 | - `af_model` allows you to choose the type of model that we are going to use for fluorescence normalisation. We'll discuss the available choices below. 145 | - `to_MEFL` is a Boolean flag that lets you tell the function if you want to convert the fluorescence data into calibrated units. You can only do this if you have carried out the calibration as detailed above. 146 | - `flu_gains` is where you specify the gain at which your fluorescence data was recorded for each fluorescence channel. Here we only have calibration parameters for "GFP" so we only specify one gain value. 147 | - `conversion_factors_csv` is the path to the calibration parameters that you generated using the protocol detailed above. 148 | 149 | When we run this function the absorbance is normalised, then the fluorescence and finally (if desired) the absorbance and fluorescence values are calibrated. Finally, the processed data is saved in a new .csv file with "_processed" appended to the filename and with additional columns for each of the processed values. 150 | 151 | We also save some .pdf images comparing the raw and normalised data, and images showing the fluorescence normalisation curves. Using these plots, there are a few checks that we should make before celebrating. 152 | 153 | - Check that none of the blank wells you used showed any contamination (it happens to the best of us). If there is growth in a blank well it will throw off the absorbance normalisation. 154 | - Check that the fluorescence normalisation curves fit the data. Read below for more detail on possible issues. 155 | 156 | ### Autofluorescence normalisation details 157 | 158 | Autofluorescence is the fluorescence produced by anything other than the fluorophores that we are interested in measuring. A small amount usually comes from growth media and can be minimised by choosing certain medias. A large contribution comes from molecules produced and secreted by our cells. Some of these molecules show particularly strong emission at similar wavelengths to GFP. We observe that the level of autofluorescence is not simply proportional to the number of cells or optical density of our culture. As cells enter stationary phase, autofluorescence increases, perhaps due increased production of the autofluorescent molecules and changes in cell size. 159 | 160 | In order to remove this autofluorescence from our sample data we fit a curve to our negative control data. We provide four different models that the user can choose to fit their data (and if desired more models can be added). There are two smoothing models: "loess" and "spline". The primary difference to the user between these two models is that the "spline" is able to extrapolate beyond the negative control data provided. This means that if the range of absorbance values at which you have measurements of your negative control is smaller than the range of your samples, we can still make an attempt at normalisation. However, this extrapolation is very crude (linear from the last data point) and can produce poor normalisation in the extrapolated range. Fortunately, negative controls tend to grow better than fluorescent samples, so extrapolation is often not an issue. We also provide a second-order polynomial and an exponential model, specified by "polynomial" and "exponential" repsectively. These are inherently able to make predictions beyond the range of normalised data and therefore may be good starting points. 161 | 162 | Prolonged periods in stationary phase can cause autofluorescence to increase while absorbance remains stable and in some cases absorbance can start decreasing while autofluorescence does not. In these circumstances, none of the models perform particularly well. The performance of each of them should be checked and if none of them perform satisfactorily it may be necessary to trim the data to remove confounding timepoints. 163 | 164 | ## Flow Cytometry Processing 165 | 166 | We have two functions for processing flow cytometry data: 167 | 168 | - `process_fcs` takes a single .fcs file, removes debris and doublets and saves the trimmed data in a new .fcs file. 169 | - `process_fcs_dir` takes a folder of .fcs files and performs the same trimming on each. It can also perform fluorescence normalisation if you have a negative control and fluorescence calibration if you have measured a calibrant. 170 | 171 | ### Process a single .fcs file 172 | To process a single .fcs file we can run the following command: 173 | 174 | ```{r eval=FALSE} 175 | flopr::process_fcs(fcs_file = "examples/flow_cytometry/DATA/20191121/pWeak_None_0_1.fcs", 176 | flu_channels = "BL1-H", 177 | pre_cleaned = TRUE, 178 | do_plot = TRUE) 179 | ``` 180 | 181 | We need to give the function four bits of information 182 | 183 | - `fcs_file` is the path to the .fcs file that we want to process. 184 | - `flu_channels` are the names of the fluorescence channels that we recorded. When processing a single .fcs file like this we don't actually do anything with the fluorescence data. However, if you include the channel names you can see the data in a plot that is saved. If you have more than one fluorescence channel, the argument needs to be a vector, which will look something like this: `flu_channels = c("BL1-H", "BL2-H", YL2-H")` 185 | - `pre_cleaned` lets the function know if you have gated out debris on the flow cytometer. Most people do this when running their experiments by setting a threshold on forward-scatter and side-scatter. But some people like to record everything and process the data later. 186 | - `do_plot` lets the function know if you want a plot to be saved of the trimming process. 187 | 188 | In the end we have a new .fcs file with "_processed" appended to the filename, and if you asked the function to save a plot we will have a .pdf that looks something like [this](examples/flow_cytometry/DATA/20191121/pWeak_None_0_1_processed.pdf). 189 | 190 | ### Process a folder of .fcs files 191 | It's much more likely that we have more than one sample that we want to process. This is where the other function comes in handy. 192 | 193 | ```{r eval=FALSE} 194 | flopr::process_fcs_dir(dir_path = "examples/flow_cytometry/DATA/20191121", 195 | pattern = "*Med*.fcs", 196 | flu_channels = "BL1-H", 197 | pre_cleaned = TRUE, 198 | do_plot = TRUE, 199 | neg_fcs = "pNeg_None_0_1.fcs", 200 | calibrate = TRUE, 201 | mef_peaks = list(list(channel = "BL1-H", 202 | peaks = c(0, 822, 2114, 5911, 17013, 41837, 145365, 287558)))) 203 | ``` 204 | 205 | There are a few more arguments to this function and some of them look a bit complicated so let's go through them. 206 | 207 | - `dir_path` is the path to the folder with your .fcs files in. 208 | - `pattern` allows us to just process a subset of the .fcs files in the folder. Here we are just going to process files with "Med" in the filename. Without going into too much detail, this uses a simplified version of "regular expressions" called ["globbing patterns"](https://en.wikipedia.org/wiki/Glob_%28programming%29). We can use "wildcard" symbols to represent any character (? is a place holder for an single character and * is a place holder for 0 to any number of characters). In this example all we know is that "Med" appears somewhere in the filenames and they all end with ".fcs". So we use the * character to show that there are some unknown characters before "Med" and between "Med" and ".fcs". If you want to process all .fcs files in your folder, the pattern would be "*.fcs". 209 | - `flu_channels` is as above. 210 | - `pre_cleaned` is as above. 211 | - `do_plot` is as above. 212 | - `neg_fcs` is the filename of your negative control sample. It must be in the folder with the other .fcs files. This is used to normalise autofluorescence. If you don't specify a filename here, the processing will be carried out without any normalisation steps. 213 | - `calibrate` tells the function whether you want to calibrate the fluorescence measurements. To be able to calibrate you must have an .fcs file with data from calibration beads and it must have "beads" somewhere in the filename. For discussion about calibration beads, read our paper or check out [TASBE](https://tasbe.github.io/) and [FlowCal](https://taborlab.github.io/FlowCal/). 214 | - `mef_peaks` is where we tell the function what the true fluorophore values are for our beads. These will be available from the bead manufacturer. We need to specify peaks for each of the channels that we want to calibrate and the channel name needs to correspond to one given in `flu_channels`. Here we are just calibrating the "BL1-H" channel which corresponds to GFP on our flow cytometer. If you wanted to calibrate two channels it would look something like this: 215 | ```{r eval=FALSE} 216 | mef_peaks = list(list(channel = "BL1-H", 217 | peaks = c(0, 822, 2114, 5911, 17013, 41837, 145365, 287558)), 218 | list(channel = "YL2-H", 219 | peaks = c(0, 218, 581, 1963, 6236, 15267, 68766, 181945))) 220 | ``` 221 | 222 | The function carries out the trimming as described above. Then, if a negative control file is given, it performs fluorescence normalisation by negating the geometric mean of the negative control's fluorescence in each channel from each of the other samples. Finally, if the files are going to be calibrated, a calibration curve is fit to the bead peaks in each of the fluorescence channels in `mef_peaks`. We use a model developed for FlowCal for our calibration curve. We then calibrate both the raw and normalised data since normalisation can produce fluorescence values less than or equal to 0, which get removed during calibration due to working with logged data (the output will contain a both sets of calibration). The new data, any plots produced, and a data_summary.csv file (containing geometric statistics for each .fcs file) will be saved to a new folder with the same name as the original but with "_processed" appended. 223 | 224 | There are a few checks that should be made to reassure yourself that everything has worked. 225 | 226 | - To confirm correct trimming, we recommend setting `do_plot = TRUE` so that you can see which events have been removed during processing. Check that the debris, if there is any, and doublets have been correctly identified and removed. 227 | - For each fluorescence calibration channel, a plot will be saved showing the bead peaks that have been identified and the calibration curve that we have fit to them. Sometime the bead peaks aren't identified correctly. In this case, there is another argument that the function can take `beads_dens_bw`, which has a default value of `0.025`. To identify the beads we use something called a Gaussian kernel to smooth the fluorescence data and pick the highest points. Sometimes this smoothing isn't quite right; we might not smooth enough and one peak is identified as two, or we smooth too much and lose peaks. In the former case we need to increase `beads_dens_bw` and in the latter we decrease it. If tweaking this value doesn't work, we also provide a way to manually specify identify the peaks using the `manual_peaks` argument. For this data, a manually specified set of peaks would look like this: 228 | 229 | ```{r eval=FALSE} 230 | manual_peaks = list(list(channel = "BL1-H", 231 | peaks = c(1.9, 2.5, 2.9, 3.3, 3.7, 4.2, 4.6, 4.95))) 232 | ``` 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Using FlopR 2 | ================ 3 | Alex J H Fedorec 4 | 02/06/2021 5 | 6 | - [Prerequisite Knowledge](#prerequisite-knowledge) 7 | - [Installation](#installation) 8 | - [A Quick Note on .csv Files](#a-quick-note-on-csv-files) 9 | - [Plate Reader Calibration](#plate-reader-calibration) 10 | - [Processing Plate Reader Data](#processing-plate-reader-data) 11 | - [Autofluorescence normalisation 12 | details](#autofluorescence-normalisation-details) 13 | - [Flow Cytometry Processing](#flow-cytometry-processing) 14 | - [Process a single .fcs file](#process-a-single-fcs-file) 15 | - [Process a folder of .fcs files](#process-a-folder-of-fcs-files) 16 | 17 | ## Prerequisite Knowledge 18 | 19 | We have attempted to make our software usable with minimal prior 20 | knowledge of the R programming language or programming in general. You 21 | will need to be familiar with the idea of running commands from a 22 | console or writing basic scripts. For R beginners, 23 | [this](https://moderndive.netlify.app/1-getting-started.html) is a great 24 | starting point, there are some good resources 25 | [here](https://education.rstudio.com/learn/beginner/) and we suggest 26 | using the [RStudio application](https://rstudio.com/products/rstudio/). 27 | It provides an environment for writing and running R code. 28 | 29 | ## Installation 30 | 31 | FlopR relies on several other R packages. Most of them are available 32 | through the “Comprehensive R Archive Network (CRAN)” which just means 33 | that they can be automatically installed. There are, however, a couple 34 | that need to be manually installed if you are using the flow cytometry 35 | processing functions. To do this use the following commands: 36 | 37 | ``` r 38 | install.packages("devtools", repos = "https://cloud.r-project.org/") 39 | 40 | if (!requireNamespace("BiocManager", quietly = TRUE)) 41 | install.packages("BiocManager") 42 | 43 | BiocManager::install(c("flowCore", "flowClust", "flowStats")) 44 | ``` 45 | 46 | Once those packages have been installed we are ready to install FlopR. 47 | 48 | ``` r 49 | devtools::install_github("ucl-cssb/flopr") 50 | ``` 51 | 52 | This grabs the latest version of FlopR from GitHub and builds it on your 53 | computer. If it installed successfully we should now be able to load the 54 | FlopR package in R. 55 | 56 | ``` r 57 | library(flopr) 58 | ``` 59 | 60 | The examples in this document can be run using the data in the “example” 61 | folder. Download the whole folder and make sure that you have set your 62 | current working directory (you can use the `setwd()` command in R) to 63 | the location where you saved it on your computer 64 | 65 | ## A Quick Note on .csv Files 66 | 67 | This package makes extensive use of .csv (comma separated variables) 68 | files for data and meta-data. Unfortunately, not all .csv are created 69 | equal. 70 | 71 | - When using a Windows OS computer we recommend that you save your 72 | .csv files explicitly with a UTF-8 file encoding (as shown below). 73 | This means that your files can be used by someone running a 74 | different operating system without error. 75 | - Some parts of the world use decimal commas instead of decimal 76 | points. In these places, .csv files use “;” as a separator instead 77 | of “,”. Unfortunately, we are unable to automatically detect which 78 | format your .csv files are in. As such, you will have to ensure that 79 | your files are saved using “,” as the separator and decimal points 80 | for the decimal mark. [This 81 | article](https://support.collaborativedrug.com/hc/en-us/articles/115004985746-CSV-files-comma-separator-and-decimal-number-format) 82 | has some help for doing so. 83 | 84 | ![From Microsoft Excel, save as UTF-8 encoded .csv 85 | file](examples/csv_save.png) 86 | 87 | ## Plate Reader Calibration 88 | 89 | The experimental protocols for producing absorbance and fluorescence 90 | calibration data can be found 91 | [here](https://www.protocols.io/workspaces/igem-measurement) and 92 | [here](https://pubs.acs.org/doi/full/10.1021/acssynbio.0c00296). 93 | 94 | The data produced by plate readers from different manufacturers comes in 95 | different formats. The first step we need to do is to “parse” the data 96 | from the plate reader into a standard format. We have written an example 97 | parsers for use with data from Tecan plate readers and the Biotek Neo 2. 98 | If you need help writing a parser for your plate reader, please contact 99 | us and we’ll see what we can do. 100 | 101 | For a Tecan plate reader, the data is saved as an Excel .xls file. As of 102 | flopR version 0.4.02, the spark\_parse function accepts Excel files 103 | (.xls and .xlsx). If you are using an earlier version, the data first 104 | needs to be saved as a .csv file (open in Excel and “Save As” .csv) that 105 | can be read by R. We also need a .csv file telling us what is in each 106 | well of our microtitre plate. An example can be found in the 107 | “examples/plate\_reader/tecan\_spark” folder, but the first few rows 108 | looks like this: 109 | 110 |
111 | 112 | | calibrant | fluorophore | media | concentration | replicate | well | 113 | |:------------|:------------|:------|--------------:|----------:|:-----| 114 | | fluorescein | GFP | PBS | 7.53000e+14 | 1 | A1 | 115 | | fluorescein | GFP | PBS | 3.76500e+14 | 1 | A2 | 116 | | fluorescein | GFP | PBS | 1.88250e+14 | 1 | A3 | 117 | | fluorescein | GFP | PBS | 9.41250e+13 | 1 | A4 | 118 | | fluorescein | GFP | PBS | 4.70625e+13 | 1 | A5 | 119 | | fluorescein | GFP | PBS | 2.35313e+13 | 1 | A6 | 120 | 121 |
122 | 123 | Once we have the calibration data and layout .csv files we can parse the 124 | data. 125 | 126 | ``` r 127 | flopr::spark_parse(data_csv = "examples/plate_reader/tecan_spark/191219_calibration_membrane.csv", 128 | layout_csv = "examples/plate_reader/tecan_spark/calibration_plate_layout.csv", 129 | timeseries = FALSE) 130 | ``` 131 | 132 | The `data_csv` argument takes the path to the calibration data. 133 | `layout_csv` is the path to the plate layout .csv file. Finally, the 134 | Tecan plate readers save timeseries data differently from single 135 | timepoint data, so we have a Boolean flag, `timeseries`, that lets the 136 | parser know that this is not a timeseries. 137 | 138 | The `spark_parse()` function saves the parsed calibration data in a new 139 | .csv file, in the same location as the calibration data, with "\_parsed" 140 | appended to the filename. The first few rows look like this: 141 | 142 |
143 | 144 | | calibrant | fluorophore | media | concentration | replicate | well | OD600 | OD700 | GFP 40 | GFP 50 | GFP 60 | GFP 70 | GFP 80 | GFP 90 | GFP 100 | GFP 110 | GFP 120 | row | column | 145 | |:------------|:------------|:------|--------------:|----------:|:-----|-------:|-------:|-------:|-------:|-------:|-------:|-------:|-------:|--------:|--------:|--------:|:----|-------:| 146 | | fluorescein | GFP | PBS | 10.0000 | 1 | A1 | 0.0921 | 0.0831 | 1830 | 9811 | 36911 | NA | NA | NA | NA | NA | NA | A | 1 | 147 | | fluorescein | GFP | PBS | 5.0000 | 1 | A2 | 0.0942 | 0.0852 | 932 | 4993 | 19221 | 54510 | NA | NA | NA | NA | NA | A | 2 | 148 | | fluorescein | GFP | PBS | 2.5000 | 1 | A3 | 0.1015 | 0.0928 | 453 | 2434 | 9448 | 27864 | NA | NA | NA | NA | NA | A | 3 | 149 | | fluorescein | GFP | PBS | 1.2500 | 1 | A4 | 0.0985 | 0.0899 | 232 | 1253 | 4853 | 14513 | 36349 | NA | NA | NA | NA | A | 4 | 150 | | fluorescein | GFP | PBS | 0.6250 | 1 | A5 | 0.0957 | 0.0905 | 114 | 617 | 2404 | 7128 | 18282 | 41812 | NA | NA | NA | A | 5 | 151 | | fluorescein | GFP | PBS | 0.3125 | 1 | A6 | 0.1027 | 0.0965 | 54 | 294 | 1137 | 3388 | 8672 | 20095 | 42244 | NA | NA | A | 6 | 152 | 153 |
154 | 155 | The parser has extracted the information we need from the calibration 156 | data and merged it with the plate layout information so that we now have 157 | columns containing each of the measurements for each well. 158 | 159 | Now we can actually calculate our calibration coefficients. To do this 160 | we just need to use one function and give it our parsed data. 161 | 162 | ``` r 163 | flopr::generate_cfs(calibration_csv = "examples/plate_reader/tecan_spark/191219_calibration_membrane_parsed.csv") 164 | ``` 165 | 166 | For details about how this process works, you can read our paper 167 | [here](https://pubs.acs.org/doi/full/10.1021/acssynbio.0c00296). At the 168 | end, there should be two .pdf images showing the calibration curves for 169 | absorbance and fluorescence, along with a new .csv file, appended with 170 | "\_cfs", containing the parameters for use in the future, the first few 171 | rows of which look like this: 172 | 173 |
174 | 175 | | cf | beta | calibrant | fluorophore | measure | 176 | |-----------:|-----------:|:------------|:------------|:--------| 177 | | 184.7274 | 0.0057476 | fluorescein | GFP | GFP 40 | 178 | | 996.4472 | -0.0035424 | fluorescein | GFP | GFP 50 | 179 | | 3821.0497 | -0.0004737 | fluorescein | GFP | GFP 60 | 180 | | 11298.9531 | 0.0002015 | fluorescein | GFP | GFP 70 | 181 | | 29128.3783 | -0.0007481 | fluorescein | GFP | GFP 80 | 182 | | 65834.9342 | 0.0012751 | fluorescein | GFP | GFP 90 | 183 | 184 |
185 | 186 | The “cf” column contains the calibration coefficients that will be used 187 | to calibrate our data in later experiments. 188 | 189 | Before we get too excited we need to check the images to make sure that 190 | the calibration curves look sensible. The software attempts to remove 191 | data points which it deems are invalid, but this process isn’t perfect 192 | and occasionally may need you to remove data points from the 193 | "\*\_parsed.csv" file. Using the example data, you can see 194 | ([here](examples/plate_reader/tecan_spark/191219_calibration_membrane_parsed_absorbance_cfs.pdf)) 195 | that some of the fluorescein wells are considered valid absorbance 196 | measurements. In this case, it isn’t the end of the world since we would 197 | never use the parameters produced from those two curves. 198 | 199 | n.b. Currently the software is setup to work with “microspheres” for 200 | calibrating cell number and “fluorescein” for calibrating GFP 201 | fluorescence. We hope to extend it in the near future to work with other 202 | calibrants. 203 | 204 | ## Processing Plate Reader Data 205 | 206 | As mentioned above, because plate readers from different manufacturers 207 | save the data in different formats, the first step we need to do is 208 | parse our raw data. The parser that we provide takes Tecan plate reader 209 | data in the form of a .csv file. We also need a .csv file telling us 210 | what is in each well of you microtitre plate. This can include any 211 | information that you wish; we include as much meta-data as possible as 212 | it makes our data analysis later much smoother. (Before version 0.4.01: 213 | The only requirement is that **the last column must be named “well”** 214 | and include an identifier (usually the well id i.e. B2) that can be 215 | matched to the same identifier in the plate reader data.) Here’s an 216 | example where we include information about the strains, plasmids, media, 217 | inducers, etc.: 218 | 219 |
220 | 221 | | strain | host | plasmid | plasmid\_2 | strain\_2 | media | sugar | amino\_acids | inducer | concentration | init\_ratio | init\_dilution | well | 222 | |:-------|:-----|:--------|:-----------|:----------|:------|:------|:-------------|:--------|--------------:|------------:|---------------:|:-----| 223 | | | | | | | | | | | NA | NA | NA | A1 | 224 | | | | | | | | | | | NA | NA | NA | A2 | 225 | 226 |
227 | 228 | Now we can use our parsing function. 229 | 230 | ``` r 231 | flopr::spark_parse(data_csv = "examples/plate_reader/tecan_spark/200228_example_data.csv", 232 | layout_csv = "examples/plate_reader/tecan_spark/200228_example_layout.csv", 233 | timeseries = TRUE) 234 | ``` 235 | 236 | The data is extracted and the meta-data from the layout is attached. 237 | Note that this time the data a timeseries so we set the `timeseries` 238 | flag to `TRUE`. A new .csv file is produced containing the parsed data 239 | with "\_parsed" appended to the filename. 240 | 241 | Now we can start processing our data. There is one function that does 242 | all the work for: `process_plate()`. There are a few arguments that we 243 | need to give the function which will control what happens. 244 | 245 | ``` r 246 | flopr::process_plate(data_csv = "examples/plate_reader/tecan_spark/200228_example_data_parsed.csv", 247 | blank_well = c("C12", "D12"), 248 | neg_well = c("C6", "D6", "E6"), 249 | od_name = "OD700", 250 | flu_names = c("GFP", "mCherry"), 251 | af_model = "spline", 252 | to_MEFL = TRUE, 253 | flu_gains = 135, 254 | conversion_factors_csv = "examples/plate_reader/tecan_spark/191219_calibration_membrane_parsed_cfs.csv") 255 | ``` 256 | 257 | Let’s walk through what each of the arguments do: 258 | 259 | - `data_csv` is the path to our parsed data. 260 | - `blank_well` are the well identifiers of wells containing media 261 | blanks. These are used for normalising absorbance. If you only have 262 | one blank well you can specify it using `blank_well = "C12"` for 263 | example. 264 | - `neg_well` are the well identifiers of wells containing negative 265 | controls. These are used for normalising fluorescence. As above, if 266 | you only have one negative control well you can specify it using 267 | `neg_well = "C6"` for example. 268 | - `od_name` is the name of the column containing our absorbance values 269 | in the parsed data .csv file. Currently we can only use one 270 | absorbance column, so if you record absorbance at multiple 271 | wavelengths (like I do), you will have to pick one. 272 | - `flu_names` are the names of the columns containing our fluorescence 273 | values. You can include as many or as few of you fluorescence 274 | columns as you like. Whichever columns are named in here, we will 275 | attempt to normalise. 276 | - `af_model` allows you to choose the type of model that we are going 277 | to use for fluorescence normalisation. We’ll discuss the available 278 | choices below. 279 | - `to_MEFL` is a Boolean flag that lets you tell the function if you 280 | want to convert the fluorescence data into calibrated units. You can 281 | only do this if you have carried out the calibration as detailed 282 | above. 283 | - `flu_gains` is where you specify the gain at which your fluorescence 284 | data was recorded for each fluorescence channel. Here we only have 285 | calibration parameters for “GFP” so we only specify one gain value. 286 | - `conversion_factors_csv` is the path to the calibration parameters 287 | that you generated using the protocol detailed above. 288 | 289 | When we run this function the absorbance is normalised, then the 290 | fluorescence and finally (if desired) the absorbance and fluorescence 291 | values are calibrated. Finally, the processed data is saved in a new 292 | .csv file with "\_processed" appended to the filename and with 293 | additional columns for each of the processed values. 294 | 295 | We also save some .pdf images comparing the raw and normalised data, and 296 | images showing the fluorescence normalisation curves. Using these plots, 297 | there are a few checks that we should make before celebrating. 298 | 299 | - Check that none of the blank wells you used showed any contamination 300 | (it happens to the best of us). If there is growth in a blank well 301 | it will throw off the absorbance normalisation. 302 | - Check that the fluorescence normalisation curves fit the data. Read 303 | below for more detail on possible issues. 304 | 305 | ### Autofluorescence normalisation details 306 | 307 | Autofluorescence is the fluorescence produced by anything other than the 308 | fluorophores that we are interested in measuring. A small amount usually 309 | comes from growth media and can be minimised by choosing certain medias. 310 | A large contribution comes from molecules produced and secreted by our 311 | cells. Some of these molecules show particularly strong emission at 312 | similar wavelengths to GFP. We observe that the level of 313 | autofluorescence is not simply proportional to the number of cells or 314 | optical density of our culture. As cells enter stationary phase, 315 | autofluorescence increases, perhaps due increased production of the 316 | autofluorescent molecules and changes in cell size. 317 | 318 | In order to remove this autofluorescence from our sample data we fit a 319 | curve to our negative control data. We provide four different models 320 | that the user can choose to fit their data (and if desired more models 321 | can be added). There are two smoothing models: “loess” and “spline”. The 322 | primary difference to the user between these two models is that the 323 | “spline” is able to extrapolate beyond the negative control data 324 | provided. This means that if the range of absorbance values at which you 325 | have measurements of your negative control is smaller than the range of 326 | your samples, we can still make an attempt at normalisation. However, 327 | this extrapolation is very crude (linear from the last data point) and 328 | can produce poor normalisation in the extrapolated range. Fortunately, 329 | negative controls tend to grow better than fluorescent samples, so 330 | extrapolation is often not an issue. We also provide a second-order 331 | polynomial and an exponential model, specified by “polynomial” and 332 | “exponential” repsectively. These are inherently able to make 333 | predictions beyond the range of normalised data and therefore may be 334 | good starting points. 335 | 336 | Prolonged periods in stationary phase can cause autofluorescence to 337 | increase while absorbance remains stable and in some cases absorbance 338 | can start decreasing while autofluorescence does not. In these 339 | circumstances, none of the models perform particularly well. The 340 | performance of each of them should be checked and if none of them 341 | perform satisfactorily it may be necessary to trim the data to remove 342 | confounding timepoints. 343 | 344 | ## Flow Cytometry Processing 345 | 346 | We have two functions for processing flow cytometry data: 347 | 348 | - `process_fcs` takes a single .fcs file, removes debris and doublets 349 | and saves the trimmed data in a new .fcs file. 350 | - `process_fcs_dir` takes a folder of .fcs files and performs the same 351 | trimming on each. It can also perform fluorescence normalisation if 352 | you have a negative control and fluorescence calibration if you have 353 | measured a calibrant. 354 | 355 | ### Process a single .fcs file 356 | 357 | To process a single .fcs file we can run the following command: 358 | 359 | ``` r 360 | flopr::process_fcs(fcs_file = "examples/flow_cytometry/DATA/20191121/pWeak_None_0_1.fcs", 361 | flu_channels = "BL1-H", 362 | pre_cleaned = TRUE, 363 | do_plot = TRUE) 364 | ``` 365 | 366 | We need to give the function four bits of information 367 | 368 | - `fcs_file` is the path to the .fcs file that we want to process. 369 | - `flu_channels` are the names of the fluorescence channels that we 370 | recorded. When processing a single .fcs file like this we don’t 371 | actually do anything with the fluorescence data. However, if you 372 | include the channel names you can see the data in a plot that is 373 | saved. If you have more than one fluorescence channel, the argument 374 | needs to be a vector, which will look something like this: 375 | `flu_channels = c("BL1-H", "BL2-H", YL2-H")` 376 | - `pre_cleaned` lets the function know if you have gated out debris on 377 | the flow cytometer. Most people do this when running their 378 | experiments by setting a threshold on forward-scatter and 379 | side-scatter. But some people like to record everything and process 380 | the data later. 381 | - `do_plot` lets the function know if you want a plot to be saved of 382 | the trimming process. 383 | 384 | In the end we have a new .fcs file with "\_processed" appended to the 385 | filename, and if you asked the function to save a plot we will have a 386 | .pdf that looks something like 387 | [this](examples/flow_cytometry/DATA/20191121/pWeak_None_0_1_processed.pdf). 388 | 389 | ### Process a folder of .fcs files 390 | 391 | It’s much more likely that we have more than one sample that we want to 392 | process. This is where the other function comes in handy. 393 | 394 | ``` r 395 | flopr::process_fcs_dir(dir_path = "examples/flow_cytometry/DATA/20191121", 396 | pattern = "*Med*.fcs", 397 | flu_channels = "BL1-H", 398 | pre_cleaned = TRUE, 399 | do_plot = TRUE, 400 | neg_fcs = "pNeg_None_0_1.fcs", 401 | calibrate = TRUE, 402 | mef_peaks = list(list(channel = "BL1-H", 403 | peaks = c(0, 822, 2114, 5911, 17013, 41837, 145365, 287558)))) 404 | ``` 405 | 406 | There are a few more arguments to this function and some of them look a 407 | bit complicated so let’s go through them. 408 | 409 | - `dir_path` is the path to the folder with your .fcs files in. 410 | - `pattern` allows us to just process a subset of the .fcs files in 411 | the folder. Here we are just going to process files with “Med” in 412 | the filename. Without going into too much detail, this uses a 413 | simplified version of “regular expressions” called [“globbing 414 | patterns”](https://en.wikipedia.org/wiki/Glob_%28programming%29). We 415 | can use “wildcard” symbols to represent any character (? is a place 416 | holder for an single character and \* is a place holder for 0 to any 417 | number of characters). In this example all we know is that “Med” 418 | appears somewhere in the filenames and they all end with “.fcs”. So 419 | we use the \* character to show that there are some unknown 420 | characters before “Med” and between “Med” and “.fcs”. If you want to 421 | process all .fcs files in your folder, the pattern would be 422 | "\*.fcs". 423 | - `flu_channels` is as above. 424 | - `pre_cleaned` is as above. 425 | - `do_plot` is as above. 426 | - `neg_fcs` is the filename of your negative control sample. It must 427 | be in the folder with the other .fcs files. This is used to 428 | normalise autofluorescence. If you don’t specify a filename here, 429 | the processing will be carried out without any normalisation steps. 430 | - `calibrate` tells the function whether you want to calibrate the 431 | fluorescence measurements. To be able to calibrate you must have an 432 | .fcs file with data from calibration beads and it must have “beads” 433 | somewhere in the filename. For discussion about calibration beads, 434 | read our paper or check out [TASBE](https://tasbe.github.io/) and 435 | [FlowCal](https://taborlab.github.io/FlowCal/). 436 | - `mef_peaks` is where we tell the function what the true fluorophore 437 | values are for our beads. These will be available from the bead 438 | manufacturer. We need to specify peaks for each of the channels that 439 | we want to calibrate and the channel name needs to correspond to one 440 | given in `flu_channels`. Here we are just calibrating the “BL1-H” 441 | channel which corresponds to GFP on our flow cytometer. If you 442 | wanted to calibrate two channels it would look something like this: 443 | 444 | ``` r 445 | mef_peaks = list(list(channel = "BL1-H", 446 | peaks = c(0, 822, 2114, 5911, 17013, 41837, 145365, 287558)), 447 | list(channel = "YL2-H", 448 | peaks = c(0, 218, 581, 1963, 6236, 15267, 68766, 181945))) 449 | ``` 450 | 451 | The function carries out the trimming as described above. Then, if a 452 | negative control file is given, it performs fluorescence normalisation 453 | by negating the geometric mean of the negative control’s fluorescence in 454 | each channel from each of the other samples. Finally, if the files are 455 | going to be calibrated, a calibration curve is fit to the bead peaks in 456 | each of the fluorescence channels in `mef_peaks`. We use a model 457 | developed for FlowCal for our calibration curve. We then calibrate both 458 | the raw and normalised data since normalisation can produce fluorescence 459 | values less than or equal to 0, which get removed during calibration due 460 | to working with logged data (the output will contain a both sets of 461 | calibration). The new data, any plots produced, and a data\_summary.csv 462 | file (containing geometric statistics for each .fcs file) will be saved 463 | to a new folder with the same name as the original but with 464 | "\_processed" appended. 465 | 466 | There are a few checks that should be made to reassure yourself that 467 | everything has worked. 468 | 469 | - To confirm correct trimming, we recommend setting `do_plot = TRUE` 470 | so that you can see which events have been removed during 471 | processing. Check that the debris, if there is any, and doublets 472 | have been correctly identified and removed. 473 | - For each fluorescence calibration channel, a plot will be saved 474 | showing the bead peaks that have been identified and the calibration 475 | curve that we have fit to them. Sometime the bead peaks aren’t 476 | identified correctly. In this case, there is another argument that 477 | the function can take `beads_dens_bw`, which has a default value of 478 | `0.025`. To identify the beads we use something called a Gaussian 479 | kernel to smooth the fluorescence data and pick the highest points. 480 | Sometimes this smoothing isn’t quite right; we might not smooth 481 | enough and one peak is identified as two, or we smooth too much and 482 | lose peaks. In the former case we need to increase `beads_dens_bw` 483 | and in the latter we decrease it. If tweaking this value doesn’t 484 | work, we also provide a way to manually specify identify the peaks 485 | using the `manual_peaks` argument. For this data, a manually 486 | specified set of peaks would look like this: 487 | 488 | ``` r 489 | manual_peaks = list(list(channel = "BL1-H", 490 | peaks = c(1.9, 2.5, 2.9, 3.3, 3.7, 4.2, 4.6, 4.95))) 491 | ``` 492 | -------------------------------------------------------------------------------- /examples/csv_save.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucl-cssb/flopr/94a5eefef52c6d4aed8fd9ce4608a26004cb73c7/examples/csv_save.png -------------------------------------------------------------------------------- /examples/flow_cytometry/DATA/20191121/20191121_beads.fcs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucl-cssb/flopr/94a5eefef52c6d4aed8fd9ce4608a26004cb73c7/examples/flow_cytometry/DATA/20191121/20191121_beads.fcs -------------------------------------------------------------------------------- /examples/flow_cytometry/DATA/20191121/20191121_plate_layout.csv: -------------------------------------------------------------------------------- 1 | strain,plasmid,name,media,replicate,well,row,col 2 | ,,,,,A1,A,1 3 | DH5alpha,Bba_I20270,Pos,LB,1,A2,A,2 4 | DH5alpha,Bba_J364000,J23101,LB,1,A3,A,3 5 | DH5alpha,Bba_J364001,J23106,LB,1,A4,A,4 6 | DH5alpha,Bba_J364002,J23117,LB,1,A5,A,5 7 | DH5alpha,Bba_R0040,Neg,LB,1,A6,A,6 8 | DH5alpha,Bba_I20270,Pos,LB,1,A7,A,7 9 | DH5alpha,Bba_J364000,J23101,LB,1,A8,A,8 10 | DH5alpha,Bba_J364001,J23106,LB,1,A9,A,9 11 | DH5alpha,Bba_J364002,J23117,LB,1,A10,A,10 12 | ,,,,,A11,A,11 13 | ,,,,,A12,A,12 14 | ,,,,,B1,B,1 15 | DH5alpha,Bba_I20270,Pos,LB,2,B2,B,2 16 | DH5alpha,Bba_J364000,J23101,LB,2,B3,B,3 17 | DH5alpha,Bba_J364001,J23106,LB,2,B4,B,4 18 | DH5alpha,Bba_J364002,J23117,LB,2,B5,B,5 19 | DH5alpha,Bba_R0040,Neg,LB,2,B6,B,6 20 | DH5alpha,Bba_I20270,Pos,LB,2,B7,B,7 21 | DH5alpha,Bba_J364000,J23101,LB,2,B8,B,8 22 | DH5alpha,Bba_J364001,J23106,LB,2,B9,B,9 23 | DH5alpha,Bba_J364002,J23117,LB,2,B10,B,10 24 | ,,,,,B11,B,11 25 | ,,,,,B12,B,12 26 | ,,,,,C1,C,1 27 | DH5alpha,Bba_I20270,Pos,LB,3,C2,C,2 28 | DH5alpha,Bba_J364000,J23101,LB,3,C3,C,3 29 | DH5alpha,Bba_J364001,J23106,LB,3,C4,C,4 30 | DH5alpha,Bba_J364002,J23117,LB,3,C5,C,5 31 | DH5alpha,Bba_R0040,Neg,LB,3,C6,C,6 32 | DH5alpha,Bba_I20270,Pos,LB,3,C7,C,7 33 | DH5alpha,Bba_J364000,J23101,LB,3,C8,C,8 34 | DH5alpha,Bba_J364001,J23106,LB,3,C9,C,9 35 | DH5alpha,Bba_J364002,J23117,LB,3,C10,C,10 36 | ,,,,,C11,C,11 37 | ,,,,,C12,C,12 38 | ,,,,,D1,D,1 39 | DH5alpha,Bba_I20270,Pos,LB,4,D2,D,2 40 | DH5alpha,Bba_J364000,J23101,LB,4,D3,D,3 41 | DH5alpha,Bba_J364001,J23106,LB,4,D4,D,4 42 | DH5alpha,Bba_J364002,J23117,LB,4,D5,D,5 43 | DH5alpha,Bba_R0040,Neg,LB,4,D6,D,6 44 | DH5alpha,Bba_I20270,Pos,LB,4,D7,D,7 45 | DH5alpha,Bba_J364000,J23101,LB,4,D8,D,8 46 | DH5alpha,Bba_J364001,J23106,LB,4,D9,D,9 47 | DH5alpha,Bba_J364002,J23117,LB,4,D10,D,10 48 | ,,,,,D11,D,11 49 | ,,,,,D12,D,12 50 | ,,,,,E1,E,1 51 | ,,,,,E2,E,2 52 | blank,blank,,LB,1,E3,E,3 53 | ,,,,,E4,E,4 54 | ,,,,,E5,E,5 55 | ,,,,,E6,E,6 56 | ,,,,,E7,E,7 57 | ,,,,,E8,E,8 58 | ,,,,,E9,E,9 59 | ,,,,,E10,E,10 60 | ,,,,,E11,E,11 61 | ,,,,,E12,E,12 62 | ,,,,,F1,F,1 63 | ,,,,,F2,F,2 64 | blank,blank,,LB,2,F3,F,3 65 | ,,,,,F4,F,4 66 | ,,,,,F5,F,5 67 | ,,,,,F6,F,6 68 | ,,,,,F7,F,7 69 | ,,,,,F8,F,8 70 | ,,,,,F9,F,9 71 | ,,,,,F10,F,10 72 | ,,,,,F11,F,11 73 | ,,,,,F12,F,12 74 | ,,,,,G1,G,1 75 | ,,,,,G2,G,2 76 | blank,blank,,LB,3,G3,G,3 77 | ,,,,,G4,G,4 78 | ,,,,,G5,G,5 79 | ,,,,,G6,G,6 80 | ,,,,,G7,G,7 81 | ,,,,,G8,G,8 82 | ,,,,,G9,G,9 83 | ,,,,,G10,G,10 84 | ,,,,,G11,G,11 85 | ,,,,,G12,G,12 86 | ,,,,,H1,H,1 87 | ,,,,,H2,H,2 88 | ,,,,,H3,H,3 89 | ,,,,,H4,H,4 90 | ,,,,,H5,H,5 91 | ,,,,,H6,H,6 92 | ,,,,,H7,H,7 93 | ,,,,,H8,H,8 94 | ,,,,,H9,H,9 95 | ,,,,,H10,H,10 96 | ,,,,,H11,H,11 97 | ,,,,,H12,H,12 -------------------------------------------------------------------------------- /examples/flow_cytometry/DATA/20191121/pMed_None_0_1.fcs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucl-cssb/flopr/94a5eefef52c6d4aed8fd9ce4608a26004cb73c7/examples/flow_cytometry/DATA/20191121/pMed_None_0_1.fcs -------------------------------------------------------------------------------- /examples/flow_cytometry/DATA/20191121/pMed_None_0_10.fcs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucl-cssb/flopr/94a5eefef52c6d4aed8fd9ce4608a26004cb73c7/examples/flow_cytometry/DATA/20191121/pMed_None_0_10.fcs -------------------------------------------------------------------------------- /examples/flow_cytometry/DATA/20191121/pMed_None_0_2.fcs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucl-cssb/flopr/94a5eefef52c6d4aed8fd9ce4608a26004cb73c7/examples/flow_cytometry/DATA/20191121/pMed_None_0_2.fcs -------------------------------------------------------------------------------- /examples/flow_cytometry/DATA/20191121/pMed_None_0_3.fcs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucl-cssb/flopr/94a5eefef52c6d4aed8fd9ce4608a26004cb73c7/examples/flow_cytometry/DATA/20191121/pMed_None_0_3.fcs -------------------------------------------------------------------------------- /examples/flow_cytometry/DATA/20191121/pMed_None_0_4.fcs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucl-cssb/flopr/94a5eefef52c6d4aed8fd9ce4608a26004cb73c7/examples/flow_cytometry/DATA/20191121/pMed_None_0_4.fcs -------------------------------------------------------------------------------- /examples/flow_cytometry/DATA/20191121/pMed_None_0_5.fcs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucl-cssb/flopr/94a5eefef52c6d4aed8fd9ce4608a26004cb73c7/examples/flow_cytometry/DATA/20191121/pMed_None_0_5.fcs -------------------------------------------------------------------------------- /examples/flow_cytometry/DATA/20191121/pMed_None_0_6.fcs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucl-cssb/flopr/94a5eefef52c6d4aed8fd9ce4608a26004cb73c7/examples/flow_cytometry/DATA/20191121/pMed_None_0_6.fcs -------------------------------------------------------------------------------- /examples/flow_cytometry/DATA/20191121/pMed_None_0_7.fcs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucl-cssb/flopr/94a5eefef52c6d4aed8fd9ce4608a26004cb73c7/examples/flow_cytometry/DATA/20191121/pMed_None_0_7.fcs -------------------------------------------------------------------------------- /examples/flow_cytometry/DATA/20191121/pMed_None_0_8.fcs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucl-cssb/flopr/94a5eefef52c6d4aed8fd9ce4608a26004cb73c7/examples/flow_cytometry/DATA/20191121/pMed_None_0_8.fcs -------------------------------------------------------------------------------- /examples/flow_cytometry/DATA/20191121/pMed_None_0_9.fcs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucl-cssb/flopr/94a5eefef52c6d4aed8fd9ce4608a26004cb73c7/examples/flow_cytometry/DATA/20191121/pMed_None_0_9.fcs -------------------------------------------------------------------------------- /examples/flow_cytometry/DATA/20191121/pNeg_None_0_1.fcs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucl-cssb/flopr/94a5eefef52c6d4aed8fd9ce4608a26004cb73c7/examples/flow_cytometry/DATA/20191121/pNeg_None_0_1.fcs -------------------------------------------------------------------------------- /examples/flow_cytometry/DATA/20191121/pNeg_None_0_2.fcs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucl-cssb/flopr/94a5eefef52c6d4aed8fd9ce4608a26004cb73c7/examples/flow_cytometry/DATA/20191121/pNeg_None_0_2.fcs -------------------------------------------------------------------------------- /examples/flow_cytometry/DATA/20191121/pNeg_None_0_3.fcs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucl-cssb/flopr/94a5eefef52c6d4aed8fd9ce4608a26004cb73c7/examples/flow_cytometry/DATA/20191121/pNeg_None_0_3.fcs -------------------------------------------------------------------------------- /examples/flow_cytometry/DATA/20191121/pNeg_None_0_4.fcs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucl-cssb/flopr/94a5eefef52c6d4aed8fd9ce4608a26004cb73c7/examples/flow_cytometry/DATA/20191121/pNeg_None_0_4.fcs -------------------------------------------------------------------------------- /examples/flow_cytometry/DATA/20191121/pNeg_None_0_5.fcs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucl-cssb/flopr/94a5eefef52c6d4aed8fd9ce4608a26004cb73c7/examples/flow_cytometry/DATA/20191121/pNeg_None_0_5.fcs -------------------------------------------------------------------------------- /examples/flow_cytometry/DATA/20191121/pNeg_None_0_6.fcs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucl-cssb/flopr/94a5eefef52c6d4aed8fd9ce4608a26004cb73c7/examples/flow_cytometry/DATA/20191121/pNeg_None_0_6.fcs -------------------------------------------------------------------------------- /examples/flow_cytometry/DATA/20191121/pNeg_None_0_7.fcs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucl-cssb/flopr/94a5eefef52c6d4aed8fd9ce4608a26004cb73c7/examples/flow_cytometry/DATA/20191121/pNeg_None_0_7.fcs -------------------------------------------------------------------------------- /examples/flow_cytometry/DATA/20191121/pNeg_None_0_8.fcs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucl-cssb/flopr/94a5eefef52c6d4aed8fd9ce4608a26004cb73c7/examples/flow_cytometry/DATA/20191121/pNeg_None_0_8.fcs -------------------------------------------------------------------------------- /examples/flow_cytometry/DATA/20191121/pStrong_None_0_1.fcs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucl-cssb/flopr/94a5eefef52c6d4aed8fd9ce4608a26004cb73c7/examples/flow_cytometry/DATA/20191121/pStrong_None_0_1.fcs -------------------------------------------------------------------------------- /examples/flow_cytometry/DATA/20191121/pStrong_None_0_10.fcs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucl-cssb/flopr/94a5eefef52c6d4aed8fd9ce4608a26004cb73c7/examples/flow_cytometry/DATA/20191121/pStrong_None_0_10.fcs -------------------------------------------------------------------------------- /examples/flow_cytometry/DATA/20191121/pStrong_None_0_11.fcs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucl-cssb/flopr/94a5eefef52c6d4aed8fd9ce4608a26004cb73c7/examples/flow_cytometry/DATA/20191121/pStrong_None_0_11.fcs -------------------------------------------------------------------------------- /examples/flow_cytometry/DATA/20191121/pStrong_None_0_12.fcs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucl-cssb/flopr/94a5eefef52c6d4aed8fd9ce4608a26004cb73c7/examples/flow_cytometry/DATA/20191121/pStrong_None_0_12.fcs -------------------------------------------------------------------------------- /examples/flow_cytometry/DATA/20191121/pStrong_None_0_2.fcs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucl-cssb/flopr/94a5eefef52c6d4aed8fd9ce4608a26004cb73c7/examples/flow_cytometry/DATA/20191121/pStrong_None_0_2.fcs -------------------------------------------------------------------------------- /examples/flow_cytometry/DATA/20191121/pStrong_None_0_3.fcs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucl-cssb/flopr/94a5eefef52c6d4aed8fd9ce4608a26004cb73c7/examples/flow_cytometry/DATA/20191121/pStrong_None_0_3.fcs -------------------------------------------------------------------------------- /examples/flow_cytometry/DATA/20191121/pStrong_None_0_4.fcs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucl-cssb/flopr/94a5eefef52c6d4aed8fd9ce4608a26004cb73c7/examples/flow_cytometry/DATA/20191121/pStrong_None_0_4.fcs -------------------------------------------------------------------------------- /examples/flow_cytometry/DATA/20191121/pStrong_None_0_5.fcs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucl-cssb/flopr/94a5eefef52c6d4aed8fd9ce4608a26004cb73c7/examples/flow_cytometry/DATA/20191121/pStrong_None_0_5.fcs -------------------------------------------------------------------------------- /examples/flow_cytometry/DATA/20191121/pStrong_None_0_6.fcs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucl-cssb/flopr/94a5eefef52c6d4aed8fd9ce4608a26004cb73c7/examples/flow_cytometry/DATA/20191121/pStrong_None_0_6.fcs -------------------------------------------------------------------------------- /examples/flow_cytometry/DATA/20191121/pStrong_None_0_7.fcs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucl-cssb/flopr/94a5eefef52c6d4aed8fd9ce4608a26004cb73c7/examples/flow_cytometry/DATA/20191121/pStrong_None_0_7.fcs -------------------------------------------------------------------------------- /examples/flow_cytometry/DATA/20191121/pStrong_None_0_8.fcs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucl-cssb/flopr/94a5eefef52c6d4aed8fd9ce4608a26004cb73c7/examples/flow_cytometry/DATA/20191121/pStrong_None_0_8.fcs -------------------------------------------------------------------------------- /examples/flow_cytometry/DATA/20191121/pStrong_None_0_9.fcs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucl-cssb/flopr/94a5eefef52c6d4aed8fd9ce4608a26004cb73c7/examples/flow_cytometry/DATA/20191121/pStrong_None_0_9.fcs -------------------------------------------------------------------------------- /examples/flow_cytometry/DATA/20191121/pWeak_None_0_1.fcs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucl-cssb/flopr/94a5eefef52c6d4aed8fd9ce4608a26004cb73c7/examples/flow_cytometry/DATA/20191121/pWeak_None_0_1.fcs -------------------------------------------------------------------------------- /examples/flow_cytometry/DATA/20191121/pWeak_None_0_10.fcs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucl-cssb/flopr/94a5eefef52c6d4aed8fd9ce4608a26004cb73c7/examples/flow_cytometry/DATA/20191121/pWeak_None_0_10.fcs -------------------------------------------------------------------------------- /examples/flow_cytometry/DATA/20191121/pWeak_None_0_11.fcs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucl-cssb/flopr/94a5eefef52c6d4aed8fd9ce4608a26004cb73c7/examples/flow_cytometry/DATA/20191121/pWeak_None_0_11.fcs -------------------------------------------------------------------------------- /examples/flow_cytometry/DATA/20191121/pWeak_None_0_12.fcs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucl-cssb/flopr/94a5eefef52c6d4aed8fd9ce4608a26004cb73c7/examples/flow_cytometry/DATA/20191121/pWeak_None_0_12.fcs -------------------------------------------------------------------------------- /examples/flow_cytometry/DATA/20191121/pWeak_None_0_1_processed.fcs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucl-cssb/flopr/94a5eefef52c6d4aed8fd9ce4608a26004cb73c7/examples/flow_cytometry/DATA/20191121/pWeak_None_0_1_processed.fcs -------------------------------------------------------------------------------- /examples/flow_cytometry/DATA/20191121/pWeak_None_0_1_processed.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucl-cssb/flopr/94a5eefef52c6d4aed8fd9ce4608a26004cb73c7/examples/flow_cytometry/DATA/20191121/pWeak_None_0_1_processed.pdf -------------------------------------------------------------------------------- /examples/flow_cytometry/DATA/20191121/pWeak_None_0_2.fcs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucl-cssb/flopr/94a5eefef52c6d4aed8fd9ce4608a26004cb73c7/examples/flow_cytometry/DATA/20191121/pWeak_None_0_2.fcs -------------------------------------------------------------------------------- /examples/flow_cytometry/DATA/20191121/pWeak_None_0_3.fcs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucl-cssb/flopr/94a5eefef52c6d4aed8fd9ce4608a26004cb73c7/examples/flow_cytometry/DATA/20191121/pWeak_None_0_3.fcs -------------------------------------------------------------------------------- /examples/flow_cytometry/DATA/20191121/pWeak_None_0_4.fcs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucl-cssb/flopr/94a5eefef52c6d4aed8fd9ce4608a26004cb73c7/examples/flow_cytometry/DATA/20191121/pWeak_None_0_4.fcs -------------------------------------------------------------------------------- /examples/flow_cytometry/DATA/20191121/pWeak_None_0_5.fcs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucl-cssb/flopr/94a5eefef52c6d4aed8fd9ce4608a26004cb73c7/examples/flow_cytometry/DATA/20191121/pWeak_None_0_5.fcs -------------------------------------------------------------------------------- /examples/flow_cytometry/DATA/20191121/pWeak_None_0_7.fcs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucl-cssb/flopr/94a5eefef52c6d4aed8fd9ce4608a26004cb73c7/examples/flow_cytometry/DATA/20191121/pWeak_None_0_7.fcs -------------------------------------------------------------------------------- /examples/flow_cytometry/DATA/20191121/pWeak_None_0_8.fcs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucl-cssb/flopr/94a5eefef52c6d4aed8fd9ce4608a26004cb73c7/examples/flow_cytometry/DATA/20191121/pWeak_None_0_8.fcs -------------------------------------------------------------------------------- /examples/flow_cytometry/DATA/20191121/pWeak_None_0_9.fcs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucl-cssb/flopr/94a5eefef52c6d4aed8fd9ce4608a26004cb73c7/examples/flow_cytometry/DATA/20191121/pWeak_None_0_9.fcs -------------------------------------------------------------------------------- /examples/flow_cytometry/DATA/20191121_processed/20191121_beads_BL1-H_calibration.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucl-cssb/flopr/94a5eefef52c6d4aed8fd9ce4608a26004cb73c7/examples/flow_cytometry/DATA/20191121_processed/20191121_beads_BL1-H_calibration.pdf -------------------------------------------------------------------------------- /examples/flow_cytometry/DATA/20191121_processed/20191121_beads_singlet_beads.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucl-cssb/flopr/94a5eefef52c6d4aed8fd9ce4608a26004cb73c7/examples/flow_cytometry/DATA/20191121_processed/20191121_beads_singlet_beads.pdf -------------------------------------------------------------------------------- /examples/flow_cytometry/DATA/20191121_processed/data_summary.csv: -------------------------------------------------------------------------------- 1 | "","file","channel","mean","sd" 2 | "1","pMed_None_0_1.fcs","BL1-H",14065.6856135571,3.69713174089346 3 | "2","pMed_None_0_1.fcs","normalised_BL1-H",17772.439416889,1.75375962404867 4 | "3","pMed_None_0_1.fcs","calibrated_BL1-H",42704.351632172,3.81842449628054 5 | "4","pMed_None_0_1.fcs","calibrated_normalised_BL1-H",54270.7967240767,1.77825127253438 6 | "5","pMed_None_0_10.fcs","BL1-H",4105.50782199545,12.8683957548119 7 | "6","pMed_None_0_10.fcs","normalised_BL1-H",14082.2843664163,2.99120031272887 8 | "7","pMed_None_0_10.fcs","calibrated_BL1-H",12091.3633934326,13.7061670007658 9 | "8","pMed_None_0_10.fcs","calibrated_normalised_BL1-H",42755.9914300549,3.0732156097424 10 | "9","pMed_None_0_2.fcs","BL1-H",13353.1050496398,2.02389307488439 11 | "10","pMed_None_0_2.fcs","normalised_BL1-H",13756.8784235517,1.70349519617632 12 | "11","pMed_None_0_2.fcs","calibrated_BL1-H",40488.9092430635,2.05942809142663 13 | "12","pMed_None_0_2.fcs","calibrated_normalised_BL1-H",41743.9086372191,1.72604529864676 14 | "13","pMed_None_0_3.fcs","BL1-H",16272.0637294663,2.32711470166975 15 | "14","pMed_None_0_3.fcs","normalised_BL1-H",17485.7527168965,1.65530050403779 16 | "15","pMed_None_0_3.fcs","calibrated_BL1-H",49581.0983720343,2.37614904749194 17 | "16","pMed_None_0_3.fcs","calibrated_normalised_BL1-H",53373.9230353711,1.67602469808081 18 | "17","pMed_None_0_4.fcs","BL1-H",12240.7466324196,2.5952189354505 19 | "18","pMed_None_0_4.fcs","normalised_BL1-H",13504.2071564739,1.78026888040504 20 | "19","pMed_None_0_4.fcs","calibrated_BL1-H",37036.4334453882,2.6570455920304 21 | "20","pMed_None_0_4.fcs","calibrated_normalised_BL1-H",40958.4532405383,1.80579944296022 22 | "21","pMed_None_0_5.fcs","BL1-H",15218.8311348887,3.2821869492828 23 | "22","pMed_None_0_5.fcs","normalised_BL1-H",18258.5901578027,1.73399025156251 24 | "23","pMed_None_0_5.fcs","calibrated_BL1-H",46295.3474101075,3.3799182917839 25 | "24","pMed_None_0_5.fcs","calibrated_normalised_BL1-H",55792.4894437666,1.75771380866814 26 | "25","pMed_None_0_6.fcs","BL1-H",10666.7346454101,3.99955747104834 27 | "26","pMed_None_0_6.fcs","normalised_BL1-H",13918.1751456708,1.92363380923118 28 | "27","pMed_None_0_6.fcs","calibrated_BL1-H",32164.5143385943,4.1387980369343 29 | "28","pMed_None_0_6.fcs","calibrated_normalised_BL1-H",42245.503281852,1.95495484799477 30 | "29","pMed_None_0_7.fcs","BL1-H",16428.9312607474,2.28010775306535 31 | "30","pMed_None_0_7.fcs","normalised_BL1-H",17539.5653717219,1.67265273778469 32 | "31","pMed_None_0_7.fcs","calibrated_BL1-H",50070.9331424297,2.32697901959676 33 | "32","pMed_None_0_7.fcs","calibrated_normalised_BL1-H",53542.2436147167,1.69403025189602 34 | "33","pMed_None_0_8.fcs","BL1-H",12138.5174725072,2.90883258339255 35 | "34","pMed_None_0_8.fcs","normalised_BL1-H",13768.1973610868,1.89005342936667 36 | "35","pMed_None_0_8.fcs","calibrated_BL1-H",36719.5185366871,2.98652996859113 37 | "36","pMed_None_0_8.fcs","calibrated_normalised_BL1-H",41779.1031380375,1.91999276253171 38 | "37","pMed_None_0_9.fcs","BL1-H",11660.9843416416,4.39079813506934 39 | "38","pMed_None_0_9.fcs","normalised_BL1-H",15800.9312060012,1.98836217924825 40 | "39","pMed_None_0_9.fcs","calibrated_BL1-H",35240.0263994794,4.55414017787882 41 | "40","pMed_None_0_9.fcs","calibrated_normalised_BL1-H",48110.6445470602,2.02238885015184 42 | -------------------------------------------------------------------------------- /examples/flow_cytometry/DATA/20191121_processed/pMed_None_0_1.fcs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucl-cssb/flopr/94a5eefef52c6d4aed8fd9ce4608a26004cb73c7/examples/flow_cytometry/DATA/20191121_processed/pMed_None_0_1.fcs -------------------------------------------------------------------------------- /examples/flow_cytometry/DATA/20191121_processed/pMed_None_0_10.fcs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucl-cssb/flopr/94a5eefef52c6d4aed8fd9ce4608a26004cb73c7/examples/flow_cytometry/DATA/20191121_processed/pMed_None_0_10.fcs -------------------------------------------------------------------------------- /examples/flow_cytometry/DATA/20191121_processed/pMed_None_0_10_processed.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucl-cssb/flopr/94a5eefef52c6d4aed8fd9ce4608a26004cb73c7/examples/flow_cytometry/DATA/20191121_processed/pMed_None_0_10_processed.pdf -------------------------------------------------------------------------------- /examples/flow_cytometry/DATA/20191121_processed/pMed_None_0_1_processed.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucl-cssb/flopr/94a5eefef52c6d4aed8fd9ce4608a26004cb73c7/examples/flow_cytometry/DATA/20191121_processed/pMed_None_0_1_processed.pdf -------------------------------------------------------------------------------- /examples/flow_cytometry/DATA/20191121_processed/pMed_None_0_2.fcs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucl-cssb/flopr/94a5eefef52c6d4aed8fd9ce4608a26004cb73c7/examples/flow_cytometry/DATA/20191121_processed/pMed_None_0_2.fcs -------------------------------------------------------------------------------- /examples/flow_cytometry/DATA/20191121_processed/pMed_None_0_2_processed.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucl-cssb/flopr/94a5eefef52c6d4aed8fd9ce4608a26004cb73c7/examples/flow_cytometry/DATA/20191121_processed/pMed_None_0_2_processed.pdf -------------------------------------------------------------------------------- /examples/flow_cytometry/DATA/20191121_processed/pMed_None_0_3.fcs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucl-cssb/flopr/94a5eefef52c6d4aed8fd9ce4608a26004cb73c7/examples/flow_cytometry/DATA/20191121_processed/pMed_None_0_3.fcs -------------------------------------------------------------------------------- /examples/flow_cytometry/DATA/20191121_processed/pMed_None_0_3_processed.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucl-cssb/flopr/94a5eefef52c6d4aed8fd9ce4608a26004cb73c7/examples/flow_cytometry/DATA/20191121_processed/pMed_None_0_3_processed.pdf -------------------------------------------------------------------------------- /examples/flow_cytometry/DATA/20191121_processed/pMed_None_0_4.fcs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucl-cssb/flopr/94a5eefef52c6d4aed8fd9ce4608a26004cb73c7/examples/flow_cytometry/DATA/20191121_processed/pMed_None_0_4.fcs -------------------------------------------------------------------------------- /examples/flow_cytometry/DATA/20191121_processed/pMed_None_0_4_processed.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucl-cssb/flopr/94a5eefef52c6d4aed8fd9ce4608a26004cb73c7/examples/flow_cytometry/DATA/20191121_processed/pMed_None_0_4_processed.pdf -------------------------------------------------------------------------------- /examples/flow_cytometry/DATA/20191121_processed/pMed_None_0_5.fcs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucl-cssb/flopr/94a5eefef52c6d4aed8fd9ce4608a26004cb73c7/examples/flow_cytometry/DATA/20191121_processed/pMed_None_0_5.fcs -------------------------------------------------------------------------------- /examples/flow_cytometry/DATA/20191121_processed/pMed_None_0_5_processed.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucl-cssb/flopr/94a5eefef52c6d4aed8fd9ce4608a26004cb73c7/examples/flow_cytometry/DATA/20191121_processed/pMed_None_0_5_processed.pdf -------------------------------------------------------------------------------- /examples/flow_cytometry/DATA/20191121_processed/pMed_None_0_6.fcs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucl-cssb/flopr/94a5eefef52c6d4aed8fd9ce4608a26004cb73c7/examples/flow_cytometry/DATA/20191121_processed/pMed_None_0_6.fcs -------------------------------------------------------------------------------- /examples/flow_cytometry/DATA/20191121_processed/pMed_None_0_6_processed.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucl-cssb/flopr/94a5eefef52c6d4aed8fd9ce4608a26004cb73c7/examples/flow_cytometry/DATA/20191121_processed/pMed_None_0_6_processed.pdf -------------------------------------------------------------------------------- /examples/flow_cytometry/DATA/20191121_processed/pMed_None_0_7.fcs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucl-cssb/flopr/94a5eefef52c6d4aed8fd9ce4608a26004cb73c7/examples/flow_cytometry/DATA/20191121_processed/pMed_None_0_7.fcs -------------------------------------------------------------------------------- /examples/flow_cytometry/DATA/20191121_processed/pMed_None_0_7_processed.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucl-cssb/flopr/94a5eefef52c6d4aed8fd9ce4608a26004cb73c7/examples/flow_cytometry/DATA/20191121_processed/pMed_None_0_7_processed.pdf -------------------------------------------------------------------------------- /examples/flow_cytometry/DATA/20191121_processed/pMed_None_0_8.fcs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucl-cssb/flopr/94a5eefef52c6d4aed8fd9ce4608a26004cb73c7/examples/flow_cytometry/DATA/20191121_processed/pMed_None_0_8.fcs -------------------------------------------------------------------------------- /examples/flow_cytometry/DATA/20191121_processed/pMed_None_0_8_processed.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucl-cssb/flopr/94a5eefef52c6d4aed8fd9ce4608a26004cb73c7/examples/flow_cytometry/DATA/20191121_processed/pMed_None_0_8_processed.pdf -------------------------------------------------------------------------------- /examples/flow_cytometry/DATA/20191121_processed/pMed_None_0_9.fcs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucl-cssb/flopr/94a5eefef52c6d4aed8fd9ce4608a26004cb73c7/examples/flow_cytometry/DATA/20191121_processed/pMed_None_0_9.fcs -------------------------------------------------------------------------------- /examples/flow_cytometry/DATA/20191121_processed/pMed_None_0_9_processed.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucl-cssb/flopr/94a5eefef52c6d4aed8fd9ce4608a26004cb73c7/examples/flow_cytometry/DATA/20191121_processed/pMed_None_0_9_processed.pdf -------------------------------------------------------------------------------- /examples/plate_reader/biotek_cytation/231031_pr_calibration_lid.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucl-cssb/flopr/94a5eefef52c6d4aed8fd9ce4608a26004cb73c7/examples/plate_reader/biotek_cytation/231031_pr_calibration_lid.xlsx -------------------------------------------------------------------------------- /examples/plate_reader/biotek_cytation/231031_pr_calibration_lid_parsed.csv: -------------------------------------------------------------------------------- 1 | "calibrant","fluorophore","media","volume_uL","concentration","concentration_M","replicate","well","OD600","OD700","GFP 30","GFP 40","GFP 50","GFP 60","GFP 70","GFP 80","GFP 90","GFP 100","GFP 110","GFP 120","GFP 130","GFP 140","GFP 150","GFP 30 TOP","GFP 40 TOP","GFP 50 TOP","GFP 60 TOP","GFP 70 TOP","GFP 80 TOP","GFP 90 TOP","GFP 100 TOP","GFP 110 TOP","GFP 120 TOP","GFP 130 TOP","GFP 140 TOP","GFP 150 TOP","row","column" 2 | "FITC","GFP","ddH20",125,7.5e+17,0.00997,1,"A1",NA,NA,845,8126,44144,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,989,9452,51005,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"A",1 3 | "FITC","GFP","ddH20",125,3.75e+17,0.00498,1,"A2",NA,NA,505,4873,26791,97416,NA,NA,NA,NA,NA,NA,NA,NA,NA,587,5613,30815,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"A",2 4 | "FITC","GFP","ddH20",125,1.88e+17,0.00249,1,"A3",NA,NA,281,2734,15135,56530,NA,NA,NA,NA,NA,NA,NA,NA,NA,325,3170,17523,65176,NA,NA,NA,NA,NA,NA,NA,NA,NA,"A",3 5 | "FITC","GFP","ddH20",125,9.38e+16,0.00125,1,"A4",NA,NA,151,1473,8208,31150,90859,NA,NA,NA,NA,NA,NA,NA,NA,178,1715,9550,36030,NA,NA,NA,NA,NA,NA,NA,NA,NA,"A",4 6 | "FITC","GFP","ddH20",125,4.69e+16,0.000623,1,"A5",NA,NA,79,754,4215,16074,47547,NA,NA,NA,NA,NA,NA,NA,NA,90,875,4866,18551,54952,NA,NA,NA,NA,NA,NA,NA,NA,"A",5 7 | "FITC","GFP","ddH20",125,2.34e+16,0.000311,1,"A6",NA,NA,42,386,2166,8294,24696,62644,NA,NA,NA,NA,NA,NA,NA,47,450,2516,9554,28481,72428,NA,NA,NA,NA,NA,NA,NA,"A",6 8 | "FITC","GFP","ddH20",125,1.17e+16,0.000156,1,"A7",NA,NA,23,193,1094,4165,12479,31892,72830,NA,NA,NA,NA,NA,NA,25,228,1276,4872,14564,37141,85171,NA,NA,NA,NA,NA,NA,"A",7 9 | "FITC","GFP","ddH20",125,5.86e+15,7.79e-05,1,"A8",NA,NA,9,100,547,2078,6218,15954,36522,78495,NA,NA,NA,NA,NA,11,114,633,2410,7246,18449,42574,91706,NA,NA,NA,NA,NA,"A",8 10 | "FITC","GFP","ddH20",125,2.93e+15,3.89e-05,1,"A9",NA,NA,5,50,280,1070,3195,8225,18818,40613,82648,NA,NA,NA,NA,5,60,331,1261,3775,9681,22378,48380,NA,NA,NA,NA,NA,"A",9 11 | "FITC","GFP","ddH20",125,1.47e+15,1.95e-05,1,"A10",NA,NA,1,24,144,543,1631,4155,9568,20705,42595,81977,NA,NA,NA,3,29,167,649,1936,4951,11490,24912,50847,NA,NA,NA,NA,"A",10 12 | "FITC","GFP","ddH20",125,7.33e+14,9.73e-06,1,"A11",NA,NA,0,16,74,296,881,2262,5204,11198,22864,44816,83711,NA,NA,0,15,91,351,1037,2685,6152,13368,27210,53606,NA,NA,NA,"A",11 13 | "FITC","GFP","ddH20",125,0,0,1,"A12",NA,NA,0,0,3,14,36,91,204,465,922,1793,3373,5814,10778,0,0,3,15,34,91,221,458,956,1761,3509,6035,10594,"A",12 14 | "FITC","GFP","ddH20",125,7.5e+17,0.00997,2,"B1",NA,NA,859,8254,44347,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,1032,9824,52473,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"B",1 15 | "FITC","GFP","ddH20",125,3.75e+17,0.00498,2,"B2",NA,NA,500,4799,26294,95675,NA,NA,NA,NA,NA,NA,NA,NA,NA,582,5549,30277,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"B",2 16 | "FITC","GFP","ddH20",125,1.88e+17,0.00249,2,"B3",NA,NA,278,2670,14760,55078,NA,NA,NA,NA,NA,NA,NA,NA,NA,342,3262,17990,66722,NA,NA,NA,NA,NA,NA,NA,NA,NA,"B",3 17 | "FITC","GFP","ddH20",125,9.38e+16,0.00125,2,"B4",NA,NA,151,1456,8082,30645,89602,NA,NA,NA,NA,NA,NA,NA,NA,176,1724,9570,36188,NA,NA,NA,NA,NA,NA,NA,NA,NA,"B",4 18 | "FITC","GFP","ddH20",125,4.69e+16,0.000623,2,"B5",NA,NA,76,750,4173,15954,47321,NA,NA,NA,NA,NA,NA,NA,NA,93,890,4964,18862,55496,NA,NA,NA,NA,NA,NA,NA,NA,"B",5 19 | "FITC","GFP","ddH20",125,2.34e+16,0.000311,2,"B6",NA,NA,38,384,2138,8172,24347,61822,NA,NA,NA,NA,NA,NA,NA,47,452,2524,9628,28820,73063,NA,NA,NA,NA,NA,NA,NA,"B",6 20 | "FITC","GFP","ddH20",125,1.17e+16,0.000156,2,"B7",NA,NA,18,195,1091,4145,12387,31811,72572,NA,NA,NA,NA,NA,NA,27,229,1284,4869,14622,37274,85415,NA,NA,NA,NA,NA,NA,"B",7 21 | "FITC","GFP","ddH20",125,5.86e+15,7.79e-05,2,"B8",NA,NA,10,98,555,2119,6352,16318,37329,80508,NA,NA,NA,NA,NA,12,123,666,2532,7625,19483,44845,NA,NA,NA,NA,NA,NA,"B",8 22 | "FITC","GFP","ddH20",125,2.93e+15,3.89e-05,2,"B9",NA,NA,7,50,284,1077,3217,8278,19006,40904,83268,NA,NA,NA,NA,5,61,339,1287,3855,9901,22891,49412,NA,NA,NA,NA,NA,"B",9 23 | "FITC","GFP","ddH20",125,1.47e+15,1.95e-05,2,"B10",NA,NA,0,26,144,550,1648,4234,9616,21007,43179,84327,NA,NA,NA,6,31,174,670,1997,5116,11840,25645,52251,NA,NA,NA,NA,"B",10 24 | "FITC","GFP","ddH20",125,7.33e+14,9.73e-06,2,"B11",NA,NA,4,15,79,300,901,2347,5335,11503,23498,46042,86074,NA,NA,3,17,93,360,1070,2752,6404,13716,28248,55672,NA,NA,NA,"B",11 25 | "FITC","GFP","ddH20",125,0,0,2,"B12",NA,NA,1,0,1,11,39,89,207,437,874,1759,3251,5753,10370,0,3,4,12,34,89,216,436,890,1847,3275,5698,10281,"B",12 26 | "FITC","GFP","ddH20",125,7.5e+17,0.00997,3,"C1",NA,NA,853,8228,44293,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,1024,9720,51852,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"C",1 27 | "FITC","GFP","ddH20",125,3.75e+17,0.00498,3,"C2",NA,NA,503,4857,26522,96524,NA,NA,NA,NA,NA,NA,NA,NA,NA,592,5685,31068,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"C",2 28 | "FITC","GFP","ddH20",125,1.88e+17,0.00249,3,"C3",NA,NA,278,2688,14770,55104,NA,NA,NA,NA,NA,NA,NA,NA,NA,325,3150,17250,64285,NA,NA,NA,NA,NA,NA,NA,NA,NA,"C",3 29 | "FITC","GFP","ddH20",125,9.38e+16,0.00125,3,"C4",NA,NA,145,1423,7859,29872,87104,NA,NA,NA,NA,NA,NA,NA,NA,176,1695,9336,35481,NA,NA,NA,NA,NA,NA,NA,NA,NA,"C",4 30 | "FITC","GFP","ddH20",125,4.69e+16,0.000623,3,"C5",NA,NA,78,736,4102,15558,46146,NA,NA,NA,NA,NA,NA,NA,NA,91,869,4828,18329,54184,NA,NA,NA,NA,NA,NA,NA,NA,"C",5 31 | "FITC","GFP","ddH20",125,2.34e+16,0.000311,3,"C6",NA,NA,39,377,2079,7922,23646,60323,NA,NA,NA,NA,NA,NA,NA,48,442,2455,9318,27867,71272,NA,NA,NA,NA,NA,NA,NA,"C",6 32 | "FITC","GFP","ddH20",125,1.17e+16,0.000156,3,"C7",NA,NA,19,191,1063,4082,12141,31032,71140,NA,NA,NA,NA,NA,NA,24,230,1265,4832,14346,36791,84311,NA,NA,NA,NA,NA,NA,"C",7 33 | "FITC","GFP","ddH20",125,5.86e+15,7.79e-05,3,"C8",NA,NA,10,95,532,2020,6038,15414,35501,76114,NA,NA,NA,NA,NA,10,111,622,2389,7114,18274,41755,90684,NA,NA,NA,NA,NA,"C",8 34 | "FITC","GFP","ddH20",125,2.93e+15,3.89e-05,3,"C9",NA,NA,8,50,272,1029,3094,7860,18220,39579,80097,NA,NA,NA,NA,6,58,321,1227,3702,9458,21733,46817,95663,NA,NA,NA,NA,"C",9 35 | "FITC","GFP","ddH20",125,1.47e+15,1.95e-05,3,"C10",NA,NA,3,26,139,530,1602,4087,9366,20289,41328,80389,NA,NA,NA,5,33,167,631,1904,4858,11116,24328,49494,NA,NA,NA,NA,"C",10 36 | "FITC","GFP","ddH20",125,7.33e+14,9.73e-06,3,"C11",NA,NA,2,13,74,276,835,2122,4938,10689,21711,42498,79231,NA,NA,5,15,89,333,984,2550,5871,12706,25674,50206,NA,NA,NA,"C",11 37 | "FITC","GFP","ddH20",125,0,0,3,"C12",NA,NA,0,2,5,10,34,89,197,434,940,1736,3187,5659,9772,0,1,3,13,34,78,192,430,850,1763,3146,5739,9343,"C",12 38 | "FITC","GFP","ddH20",125,7.5e+17,0.00997,4,"D1",NA,NA,900,8616,46251,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,1107,10540,55639,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"D",1 39 | "FITC","GFP","ddH20",125,3.75e+17,0.00498,4,"D2",NA,NA,540,5198,28238,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,649,6168,33327,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"D",2 40 | "FITC","GFP","ddH20",125,1.88e+17,0.00249,4,"D3",NA,NA,306,2932,16154,60444,NA,NA,NA,NA,NA,NA,NA,NA,NA,364,3487,19076,71156,NA,NA,NA,NA,NA,NA,NA,NA,NA,"D",3 41 | "FITC","GFP","ddH20",125,9.38e+16,0.00125,4,"D4",NA,NA,165,1594,8781,33285,96845,NA,NA,NA,NA,NA,NA,NA,NA,196,1895,10472,39451,NA,NA,NA,NA,NA,NA,NA,NA,NA,"D",4 42 | "FITC","GFP","ddH20",125,4.69e+16,0.000623,4,"D5",NA,NA,87,809,4467,17044,50369,NA,NA,NA,NA,NA,NA,NA,NA,101,965,5330,20279,59993,NA,NA,NA,NA,NA,NA,NA,NA,"D",5 43 | "FITC","GFP","ddH20",125,2.34e+16,0.000311,4,"D6",NA,NA,43,416,2305,8746,26093,66402,NA,NA,NA,NA,NA,NA,NA,51,492,2751,10435,31064,78753,NA,NA,NA,NA,NA,NA,NA,"D",6 44 | "FITC","GFP","ddH20",125,1.17e+16,0.000156,4,"D7",NA,NA,23,205,1157,4410,13139,33836,77513,NA,NA,NA,NA,NA,NA,27,247,1378,5293,15739,40295,91768,NA,NA,NA,NA,NA,NA,"D",7 45 | "FITC","GFP","ddH20",125,5.86e+15,7.79e-05,4,"D8",NA,NA,10,105,585,2227,6674,17038,39092,84282,NA,NA,NA,NA,NA,12,129,694,2657,7889,20312,46830,NA,NA,NA,NA,NA,NA,"D",8 46 | "FITC","GFP","ddH20",125,2.93e+15,3.89e-05,4,"D9",NA,NA,9,53,291,1111,3342,8605,19819,42658,86306,NA,NA,NA,NA,6,61,349,1337,4024,10342,23640,51478,NA,NA,NA,NA,NA,"D",9 47 | "FITC","GFP","ddH20",125,1.47e+15,1.95e-05,4,"D10",NA,NA,2,27,152,580,1731,4462,10223,22188,45503,87988,NA,NA,NA,2,35,177,692,2064,5330,12319,26647,53898,NA,NA,NA,NA,"D",10 48 | "FITC","GFP","ddH20",125,7.33e+14,9.73e-06,4,"D11",NA,NA,2,15,82,301,929,2371,5363,11776,23971,46800,87237,NA,NA,1,17,94,366,1078,2782,6521,13997,28983,55496,NA,NA,NA,"D",11 49 | "FITC","GFP","ddH20",125,0,0,4,"D12",NA,NA,2,0,2,10,37,84,205,454,897,1726,3064,5683,10033,0,0,3,10,34,91,200,441,906,1903,3414,5779,10426,"D",12 50 | "microspheres","","ddH20",125,891346154,1.18e-11,1,"E1",1.47,1.238,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"E",1 51 | "microspheres","","ddH20",125,534807692,7.1e-12,1,"E2",1.054,0.846,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"E",2 52 | "microspheres","","ddH20",125,320884615,4.26e-12,1,"E3",0.718,0.567,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"E",3 53 | "microspheres","","ddH20",125,192530769,2.56e-12,1,"E4",0.495,0.393,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"E",4 54 | "microspheres","","ddH20",125,115518461,1.53e-12,1,"E5",0.359,0.289,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"E",5 55 | "microspheres","","ddH20",125,69311077,9.21e-13,1,"E6",0.253,0.21,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"E",6 56 | "microspheres","","ddH20",125,41586646,5.52e-13,1,"E7",0.186,0.158,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"E",7 57 | "microspheres","","ddH20",125,24951988,3.31e-13,1,"E8",0.153,0.131,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"E",8 58 | "microspheres","","ddH20",125,14971193,1.99e-13,1,"E9",0.128,0.113,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"E",9 59 | "microspheres","","ddH20",125,8982716,1.19e-13,1,"E10",0.113,0.1,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"E",10 60 | "microspheres","","ddH20",125,5389630,7.16e-14,1,"E11",0.102,0.087,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"E",11 61 | "microspheres","","ddH20",125,0,0,1,"E12",0.081,0.078,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"E",12 62 | "microspheres","","ddH20",125,891346154,1.18e-11,2,"F1",1.497,1.274,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"F",1 63 | "microspheres","","ddH20",125,534807692,7.1e-12,2,"F2",1.062,0.855,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"F",2 64 | "microspheres","","ddH20",125,320884615,4.26e-12,2,"F3",0.725,0.572,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"F",3 65 | "microspheres","","ddH20",125,192530769,2.56e-12,2,"F4",0.497,0.395,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"F",4 66 | "microspheres","","ddH20",125,115518461,1.53e-12,2,"F5",0.357,0.29,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"F",5 67 | "microspheres","","ddH20",125,69311077,9.21e-13,2,"F6",0.254,0.209,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"F",6 68 | "microspheres","","ddH20",125,41586646,5.52e-13,2,"F7",0.189,0.161,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"F",7 69 | "microspheres","","ddH20",125,24951988,3.31e-13,2,"F8",0.154,0.132,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"F",8 70 | "microspheres","","ddH20",125,14971193,1.99e-13,2,"F9",0.134,0.118,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"F",9 71 | "microspheres","","ddH20",125,8982716,1.19e-13,2,"F10",0.113,0.101,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"F",10 72 | "microspheres","","ddH20",125,5389630,7.16e-14,2,"F11",0.106,0.089,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"F",11 73 | "microspheres","","ddH20",125,0,0,2,"F12",0.086,0.083,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"F",12 74 | "microspheres","","ddH20",125,891346154,1.18e-11,3,"G1",1.435,1.198,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"G",1 75 | "microspheres","","ddH20",125,534807692,7.1e-12,3,"G2",1.04,0.83,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"G",2 76 | "microspheres","","ddH20",125,320884615,4.26e-12,3,"G3",0.716,0.565,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"G",3 77 | "microspheres","","ddH20",125,192530769,2.56e-12,3,"G4",0.499,0.401,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"G",4 78 | "microspheres","","ddH20",125,115518461,1.53e-12,3,"G5",0.348,0.277,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"G",5 79 | "microspheres","","ddH20",125,69311077,9.21e-13,3,"G6",0.262,0.213,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"G",6 80 | "microspheres","","ddH20",125,41586646,5.52e-13,3,"G7",0.19,0.16,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"G",7 81 | "microspheres","","ddH20",125,24951988,3.31e-13,3,"G8",0.154,0.129,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"G",8 82 | "microspheres","","ddH20",125,14971193,1.99e-13,3,"G9",0.127,0.109,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"G",9 83 | "microspheres","","ddH20",125,8982716,1.19e-13,3,"G10",0.109,0.094,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"G",10 84 | "microspheres","","ddH20",125,5389630,7.16e-14,3,"G11",0.117,0.14,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"G",11 85 | "microspheres","","ddH20",125,0,0,3,"G12",0.08,0.077,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"G",12 86 | "microspheres","","ddH20",125,891346154,1.18e-11,4,"H1",1.458,1.229,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"H",1 87 | "microspheres","","ddH20",125,534807692,7.1e-12,4,"H2",1.056,0.846,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"H",2 88 | "microspheres","","ddH20",125,320884615,4.26e-12,4,"H3",0.706,0.556,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"H",3 89 | "microspheres","","ddH20",125,192530769,2.56e-12,4,"H4",0.485,0.387,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"H",4 90 | "microspheres","","ddH20",125,115518461,1.53e-12,4,"H5",0.345,0.281,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"H",5 91 | "microspheres","","ddH20",125,69311077,9.21e-13,4,"H6",0.24,0.201,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"H",6 92 | "microspheres","","ddH20",125,41586646,5.52e-13,4,"H7",0.17,0.148,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"H",7 93 | "microspheres","","ddH20",125,24951988,3.31e-13,4,"H8",0.136,0.12,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"H",8 94 | "microspheres","","ddH20",125,14971193,1.99e-13,4,"H9",0.115,0.105,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"H",9 95 | "microspheres","","ddH20",125,8982716,1.19e-13,4,"H10",0.102,0.094,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"H",10 96 | "microspheres","","ddH20",125,5389630,7.16e-14,4,"H11",0.098,0.092,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"H",11 97 | "microspheres","","ddH20",125,0,0,4,"H12",0.093,0.089,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"H",12 98 | -------------------------------------------------------------------------------- /examples/plate_reader/biotek_cytation/231031_pr_calibration_lid_parsed_absorbance_cfs.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucl-cssb/flopr/94a5eefef52c6d4aed8fd9ce4608a26004cb73c7/examples/plate_reader/biotek_cytation/231031_pr_calibration_lid_parsed_absorbance_cfs.pdf -------------------------------------------------------------------------------- /examples/plate_reader/biotek_cytation/231031_pr_calibration_lid_parsed_cfs.csv: -------------------------------------------------------------------------------- 1 | "cf","beta","calibrant","fluorophore","measure" 2 | 1.73411407582599e-15,2.46476510092312e-10,"FITC","GFP","GFP 30" 3 | 1.58206584654132e-14,2.28051952205029e-10,"FITC","GFP","GFP 40" 4 | 8.72349620423461e-14,2.09924902425371e-10,"FITC","GFP","GFP 50" 5 | 3.4171812813719e-13,2.04751511913593e-10,"FITC","GFP","GFP 60" 6 | 1.07314591295955e-12,1.87544535531197e-10,"FITC","GFP","GFP 70" 7 | 2.80481604754579e-12,1.90037751716375e-10,"FITC","GFP","GFP 80" 8 | 6.48422213271198e-12,1.74671525158919e-10,"FITC","GFP","GFP 90" 9 | 1.41135422745713e-11,2.29248723370256e-10,"FITC","GFP","GFP 100" 10 | 2.91248205816367e-11,1.95386169356061e-10,"FITC","GFP","GFP 110" 11 | 2.05528760803502e-15,2.43219430207211e-10,"FITC","GFP","GFP 30 TOP" 12 | 1.85869508571003e-14,2.26649190451653e-10,"FITC","GFP","GFP 40 TOP" 13 | 1.02974795089581e-13,2.23479764191819e-10,"FITC","GFP","GFP 50 TOP" 14 | 4.17851686710777e-13,2.0422505265513e-10,"FITC","GFP","GFP 60 TOP" 15 | 1.28605365753111e-12,1.89214569330215e-10,"FITC","GFP","GFP 70 TOP" 16 | 3.33242845217621e-12,2.24208990515285e-10,"FITC","GFP","GFP 80 TOP" 17 | 7.75059228617403e-12,1.98039381867784e-10,"FITC","GFP","GFP 90 TOP" 18 | 1.67632544878864e-11,1.93897487700451e-10,"FITC","GFP","GFP 100 TOP" 19 | 3.45350759103888e-11,1.70041463384405e-10,"FITC","GFP","GFP 110 TOP" 20 | 3.38335914611817e-09,4.27744674682617e-10,"microspheres","","OD600" 21 | 3.08515658620745e-09,5.50387836806476e-10,"microspheres","","OD700" 22 | -------------------------------------------------------------------------------- /examples/plate_reader/biotek_cytation/231031_pr_calibration_lid_parsed_fluorescence_cfs.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucl-cssb/flopr/94a5eefef52c6d4aed8fd9ce4608a26004cb73c7/examples/plate_reader/biotek_cytation/231031_pr_calibration_lid_parsed_fluorescence_cfs.pdf -------------------------------------------------------------------------------- /examples/plate_reader/biotek_cytation/231031_pr_calibration_membrane.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucl-cssb/flopr/94a5eefef52c6d4aed8fd9ce4608a26004cb73c7/examples/plate_reader/biotek_cytation/231031_pr_calibration_membrane.xlsx -------------------------------------------------------------------------------- /examples/plate_reader/biotek_cytation/231031_pr_calibration_membrane_parsed.csv: -------------------------------------------------------------------------------- 1 | "calibrant","fluorophore","media","volume_uL","concentration","concentration_M","replicate","well","OD600","OD700","GFP 30","GFP 40","GFP 50","GFP 60","GFP 70","GFP 80","GFP 90","GFP 100","GFP 110","GFP 120","GFP 130","GFP 140","GFP 150","GFP 30 TOP","GFP 40 TOP","GFP 50 TOP","GFP 60 TOP","GFP 70 TOP","GFP 80 TOP","GFP 90 TOP","GFP 100 TOP","GFP 110 TOP","GFP 120 TOP","GFP 130 TOP","GFP 140 TOP","GFP 150 TOP","row","column" 2 | "FITC","GFP","ddH20",125,7.5e+17,0.00997,1,"A1",NA,NA,791,7649,41529,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,375,3659,20287,75143,NA,NA,NA,NA,NA,NA,NA,NA,NA,"A",1 3 | "FITC","GFP","ddH20",125,3.75e+17,0.00498,1,"A2",NA,NA,480,4635,25309,92305,NA,NA,NA,NA,NA,NA,NA,NA,NA,229,2198,12273,46427,NA,NA,NA,NA,NA,NA,NA,NA,NA,"A",2 4 | "FITC","GFP","ddH20",125,1.88e+17,0.00249,1,"A3",NA,NA,273,2662,14652,54956,NA,NA,NA,NA,NA,NA,NA,NA,NA,127,1229,6840,26058,76632,NA,NA,NA,NA,NA,NA,NA,NA,"A",3 5 | "FITC","GFP","ddH20",125,9.38e+16,0.00125,1,"A4",NA,NA,150,1466,8094,30754,90276,NA,NA,NA,NA,NA,NA,NA,NA,74,685,3850,14733,43709,NA,NA,NA,NA,NA,NA,NA,NA,"A",4 6 | "FITC","GFP","ddH20",125,4.69e+16,0.000623,1,"A5",NA,NA,80,760,4216,16127,47910,NA,NA,NA,NA,NA,NA,NA,NA,40,374,2058,7908,23580,59895,NA,NA,NA,NA,NA,NA,NA,"A",5 7 | "FITC","GFP","ddH20",125,2.34e+16,0.000311,1,"A6",NA,NA,40,388,2166,8314,24806,62827,NA,NA,NA,NA,NA,NA,NA,17,179,1008,3867,11572,29755,68013,NA,NA,NA,NA,NA,NA,"A",6 8 | "FITC","GFP","ddH20",125,1.17e+16,0.000156,1,"A7",NA,NA,21,202,1116,4272,12850,32745,75024,NA,NA,NA,NA,NA,NA,11,94,526,2005,5966,15243,35092,75787,NA,NA,NA,NA,NA,"A",7 9 | "FITC","GFP","ddH20",125,5.86e+15,7.79e-05,1,"A8",NA,NA,12,96,551,2109,6324,16253,37323,80018,NA,NA,NA,NA,NA,6,49,264,1012,3007,7696,17711,38499,78752,NA,NA,NA,NA,"A",8 10 | "FITC","GFP","ddH20",125,2.93e+15,3.89e-05,1,"A9",NA,NA,3,52,281,1075,3211,8192,19011,40782,83143,NA,NA,NA,NA,2,25,138,527,1581,4008,9278,20086,41130,79934,NA,NA,NA,"A",9 11 | "FITC","GFP","ddH20",125,1.47e+15,1.95e-05,1,"A10",NA,NA,5,25,145,548,1633,4210,9594,20937,42735,83170,NA,NA,NA,0,12,73,280,842,2156,4982,10643,22060,42533,80674,NA,NA,"A",10 12 | "FITC","GFP","ddH20",125,7.33e+14,9.73e-06,1,"A11",NA,NA,4,14,78,297,881,2249,5243,11279,22849,44954,84041,NA,NA,2,5,44,153,452,1193,2732,5807,11734,23058,43489,77073,NA,"A",11 13 | "FITC","GFP","ddH20",125,0,0,1,"A12",NA,NA,0,4,2,10,39,106,224,486,1014,1931,3693,6495,11769,0,0,3,6,27,68,160,343,677,1323,2576,4510,7419,"A",12 14 | "FITC","GFP","ddH20",125,7.5e+17,0.00997,2,"B1",NA,NA,808,7716,41416,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,382,3677,20230,75028,NA,NA,NA,NA,NA,NA,NA,NA,NA,"B",1 15 | "FITC","GFP","ddH20",125,3.75e+17,0.00498,2,"B2",NA,NA,458,4404,24176,88778,NA,NA,NA,NA,NA,NA,NA,NA,NA,206,1979,11027,41661,NA,NA,NA,NA,NA,NA,NA,NA,NA,"B",2 16 | "FITC","GFP","ddH20",125,1.88e+17,0.00249,2,"B3",NA,NA,262,2515,14007,52413,NA,NA,NA,NA,NA,NA,NA,NA,NA,121,1164,6433,24542,72213,NA,NA,NA,NA,NA,NA,NA,NA,"B",3 17 | "FITC","GFP","ddH20",125,9.38e+16,0.00125,2,"B4",NA,NA,149,1434,7941,30094,88672,NA,NA,NA,NA,NA,NA,NA,NA,70,669,3758,14380,42468,NA,NA,NA,NA,NA,NA,NA,NA,"B",4 18 | "FITC","GFP","ddH20",125,4.69e+16,0.000623,2,"B5",NA,NA,78,753,4209,15925,47403,NA,NA,NA,NA,NA,NA,NA,NA,39,371,2068,7872,23501,59846,NA,NA,NA,NA,NA,NA,NA,"B",5 19 | "FITC","GFP","ddH20",125,2.34e+16,0.000311,2,"B6",NA,NA,39,390,2171,8304,24740,63016,NA,NA,NA,NA,NA,NA,NA,21,182,1008,3865,11533,29509,67746,NA,NA,NA,NA,NA,NA,"B",6 20 | "FITC","GFP","ddH20",125,1.17e+16,0.000156,2,"B7",NA,NA,20,200,1121,4282,12790,32779,75004,NA,NA,NA,NA,NA,NA,10,92,507,1940,5809,14967,34242,73675,NA,NA,NA,NA,NA,"B",7 21 | "FITC","GFP","ddH20",125,5.86e+15,7.79e-05,2,"B8",NA,NA,10,103,573,2176,6517,16628,38194,82236,NA,NA,NA,NA,NA,6,53,268,1032,3096,7944,18390,39413,80718,NA,NA,NA,NA,"B",8 22 | "FITC","GFP","ddH20",125,2.93e+15,3.89e-05,2,"B9",NA,NA,3,50,280,1077,3202,8303,18978,40950,83629,NA,NA,NA,NA,2,23,142,545,1623,4168,9616,20802,42515,82838,NA,NA,NA,"B",9 23 | "FITC","GFP","ddH20",125,1.47e+15,1.95e-05,2,"B10",NA,NA,2,27,145,551,1669,4247,9870,21111,43306,84285,NA,NA,NA,2,17,72,275,819,2107,4874,10517,21690,41882,78744,NA,NA,"B",10 24 | "FITC","GFP","ddH20",125,7.33e+14,9.73e-06,2,"B11",NA,NA,2,15,77,295,884,2266,5223,11274,23218,45335,85040,NA,NA,1,7,42,157,469,1181,2770,5912,12243,23991,44474,79251,NA,"B",11 25 | "FITC","GFP","ddH20",125,0,0,2,"B12",NA,NA,0,0,3,14,37,94,215,487,961,1947,3669,6457,11088,0,1,4,9,23,70,155,343,651,1309,2483,4540,7822,"B",12 26 | "FITC","GFP","ddH20",125,7.5e+17,0.00997,3,"C1",NA,NA,793,7577,40883,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,382,3670,20306,75463,NA,NA,NA,NA,NA,NA,NA,NA,NA,"C",1 27 | "FITC","GFP","ddH20",125,3.75e+17,0.00498,3,"C2",NA,NA,464,4437,24354,89579,NA,NA,NA,NA,NA,NA,NA,NA,NA,224,2143,11929,44860,NA,NA,NA,NA,NA,NA,NA,NA,NA,"C",2 28 | "FITC","GFP","ddH20",125,1.88e+17,0.00249,3,"C3",NA,NA,261,2524,13944,51970,NA,NA,NA,NA,NA,NA,NA,NA,NA,122,1182,6594,24900,73079,NA,NA,NA,NA,NA,NA,NA,NA,"C",3 29 | "FITC","GFP","ddH20",125,9.38e+16,0.00125,3,"C4",NA,NA,144,1372,7613,28815,84592,NA,NA,NA,NA,NA,NA,NA,NA,66,636,3579,13616,40180,NA,NA,NA,NA,NA,NA,NA,NA,"C",4 30 | "FITC","GFP","ddH20",125,4.69e+16,0.000623,3,"C5",NA,NA,77,737,4103,15619,46358,NA,NA,NA,NA,NA,NA,NA,NA,37,352,1967,7486,22284,56880,NA,NA,NA,NA,NA,NA,NA,"C",5 31 | "FITC","GFP","ddH20",125,2.34e+16,0.000311,3,"C6",NA,NA,39,381,2105,8055,24002,61479,NA,NA,NA,NA,NA,NA,NA,16,171,971,3701,11033,28277,65110,NA,NA,NA,NA,NA,NA,"C",6 32 | "FITC","GFP","ddH20",125,1.17e+16,0.000156,3,"C7",NA,NA,20,197,1090,4155,12391,31927,72940,NA,NA,NA,NA,NA,NA,10,91,509,1950,5787,14901,34185,73669,NA,NA,NA,NA,NA,"C",7 33 | "FITC","GFP","ddH20",125,5.86e+15,7.79e-05,3,"C8",NA,NA,10,99,540,2056,6173,15748,36108,77909,NA,NA,NA,NA,NA,2,48,259,1008,2981,7668,17670,38017,77752,NA,NA,NA,NA,"C",8 34 | "FITC","GFP","ddH20",125,2.93e+15,3.89e-05,3,"C9",NA,NA,4,50,273,1047,3111,7992,18516,39797,80937,NA,NA,NA,NA,2,27,137,523,1568,4020,9261,20072,40703,80253,NA,NA,NA,"C",9 35 | "FITC","GFP","ddH20",125,1.47e+15,1.95e-05,3,"C10",NA,NA,2,23,138,530,1584,4048,9382,20310,41438,80601,NA,NA,NA,0,13,66,259,766,1999,4532,9805,20061,38990,73807,NA,NA,"C",10 36 | "FITC","GFP","ddH20",125,7.33e+14,9.73e-06,3,"C11",NA,NA,1,13,75,282,832,2151,5006,10691,21914,42676,80009,NA,NA,0,7,39,143,432,1109,2575,5510,11377,22128,41352,72439,NA,"C",11 37 | "FITC","GFP","ddH20",125,0,0,3,"C12",NA,NA,0,0,5,11,38,104,230,487,1005,1889,3535,6477,11296,0,2,0,10,25,72,159,316,694,1329,2635,4472,7449,"C",12 38 | "FITC","GFP","ddH20",125,7.5e+17,0.00997,4,"D1",NA,NA,832,7887,42286,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,429,4051,22455,82613,NA,NA,NA,NA,NA,NA,NA,NA,NA,"D",1 39 | "FITC","GFP","ddH20",125,3.75e+17,0.00498,4,"D2",NA,NA,481,4586,25054,92019,NA,NA,NA,NA,NA,NA,NA,NA,NA,229,2218,12244,46248,NA,NA,NA,NA,NA,NA,NA,NA,NA,"D",2 40 | "FITC","GFP","ddH20",125,1.88e+17,0.00249,4,"D3",NA,NA,281,2698,14878,55801,NA,NA,NA,NA,NA,NA,NA,NA,NA,134,1286,7153,27168,80093,NA,NA,NA,NA,NA,NA,NA,NA,"D",3 41 | "FITC","GFP","ddH20",125,9.38e+16,0.00125,4,"D4",NA,NA,158,1507,8309,31510,92237,NA,NA,NA,NA,NA,NA,NA,NA,76,716,4020,15332,45530,NA,NA,NA,NA,NA,NA,NA,NA,"D",4 42 | "FITC","GFP","ddH20",125,4.69e+16,0.000623,4,"D5",NA,NA,83,790,4318,16475,48706,NA,NA,NA,NA,NA,NA,NA,NA,41,374,2088,7935,23707,60428,NA,NA,NA,NA,NA,NA,NA,"D",5 43 | "FITC","GFP","ddH20",125,2.34e+16,0.000311,4,"D6",NA,NA,43,415,2287,8752,26172,66265,NA,NA,NA,NA,NA,NA,NA,18,190,1065,4051,12076,31022,70957,NA,NA,NA,NA,NA,NA,"D",6 44 | "FITC","GFP","ddH20",125,1.17e+16,0.000156,4,"D7",NA,NA,24,211,1166,4460,13314,34066,77991,NA,NA,NA,NA,NA,NA,10,98,555,2113,6333,16217,37375,79851,NA,NA,NA,NA,NA,"D",7 45 | "FITC","GFP","ddH20",125,5.86e+15,7.79e-05,4,"D8",NA,NA,12,107,585,2241,6719,17181,39548,84764,NA,NA,NA,NA,NA,9,52,285,1089,3271,8415,19197,41479,84934,NA,NA,NA,NA,"D",8 46 | "FITC","GFP","ddH20",125,2.93e+15,3.89e-05,4,"D9",NA,NA,5,51,290,1098,3271,8435,19444,41987,85603,NA,NA,NA,NA,2,28,147,561,1674,4289,9857,21524,43692,84923,NA,NA,NA,"D",9 47 | "FITC","GFP","ddH20",125,1.47e+15,1.95e-05,4,"D10",NA,NA,3,26,148,574,1716,4425,10160,21877,44788,86917,NA,NA,NA,2,14,72,286,858,2223,5138,11121,22791,44249,82461,NA,NA,"D",10 48 | "FITC","GFP","ddH20",125,7.33e+14,9.73e-06,4,"D11",NA,NA,2,17,79,302,918,2352,5415,11632,23899,46717,86934,NA,NA,1,8,42,158,469,1215,2798,6114,12435,24034,45118,80748,NA,"D",11 49 | "FITC","GFP","ddH20",125,0,0,4,"D12",NA,NA,0,0,5,11,38,101,229,482,1029,1963,3691,6503,10751,0,0,4,8,30,66,151,349,665,1398,2321,4457,7820,"D",12 50 | "microspheres","","ddH20",125,891346154,1.18e-11,1,"E1",1.388,1.221,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"E",1 51 | "microspheres","","ddH20",125,534807692,7.1e-12,1,"E2",1.024,0.864,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"E",2 52 | "microspheres","","ddH20",125,320884615,4.26e-12,1,"E3",0.716,0.595,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"E",3 53 | "microspheres","","ddH20",125,192530769,2.56e-12,1,"E4",0.551,0.435,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"E",4 54 | "microspheres","","ddH20",125,115518461,1.53e-12,1,"E5",0.393,0.335,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"E",5 55 | "microspheres","","ddH20",125,69311077,9.21e-13,1,"E6",0.294,0.257,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"E",6 56 | "microspheres","","ddH20",125,41586646,5.52e-13,1,"E7",0.244,0.22,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"E",7 57 | "microspheres","","ddH20",125,24951988,3.31e-13,1,"E8",0.214,0.196,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"E",8 58 | "microspheres","","ddH20",125,14971193,1.99e-13,1,"E9",0.17,0.156,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"E",9 59 | "microspheres","","ddH20",125,8982716,1.19e-13,1,"E10",0.182,0.172,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"E",10 60 | "microspheres","","ddH20",125,5389630,7.16e-14,1,"E11",0.177,0.169,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"E",11 61 | "microspheres","","ddH20",125,0,0,1,"E12",0.147,0.14,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"E",12 62 | "microspheres","","ddH20",125,891346154,1.18e-11,2,"F1",1.427,1.267,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"F",1 63 | "microspheres","","ddH20",125,534807692,7.1e-12,2,"F2",1.05,0.892,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"F",2 64 | "microspheres","","ddH20",125,320884615,4.26e-12,2,"F3",0.722,0.599,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"F",3 65 | "microspheres","","ddH20",125,192530769,2.56e-12,2,"F4",0.517,0.427,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"F",4 66 | "microspheres","","ddH20",125,115518461,1.53e-12,2,"F5",0.405,0.344,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"F",5 67 | "microspheres","","ddH20",125,69311077,9.21e-13,2,"F6",0.303,0.269,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"F",6 68 | "microspheres","","ddH20",125,41586646,5.52e-13,2,"F7",0.236,0.212,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"F",7 69 | "microspheres","","ddH20",125,24951988,3.31e-13,2,"F8",0.196,0.179,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"F",8 70 | "microspheres","","ddH20",125,14971193,1.99e-13,2,"F9",0.178,0.165,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"F",9 71 | "microspheres","","ddH20",125,8982716,1.19e-13,2,"F10",0.159,0.149,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"F",10 72 | "microspheres","","ddH20",125,5389630,7.16e-14,2,"F11",0.164,0.157,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"F",11 73 | "microspheres","","ddH20",125,0,0,2,"F12",0.141,0.135,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"F",12 74 | "microspheres","","ddH20",125,891346154,1.18e-11,3,"G1",1.362,1.194,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"G",1 75 | "microspheres","","ddH20",125,534807692,7.1e-12,3,"G2",1.018,0.86,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"G",2 76 | "microspheres","","ddH20",125,320884615,4.26e-12,3,"G3",0.721,0.605,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"G",3 77 | "microspheres","","ddH20",125,192530769,2.56e-12,3,"G4",0.518,0.433,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"G",4 78 | "microspheres","","ddH20",125,115518461,1.53e-12,3,"G5",0.414,0.359,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"G",5 79 | "microspheres","","ddH20",125,69311077,9.21e-13,3,"G6",0.298,0.26,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"G",6 80 | "microspheres","","ddH20",125,41586646,5.52e-13,3,"G7",0.235,0.21,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"G",7 81 | "microspheres","","ddH20",125,24951988,3.31e-13,3,"G8",0.2,0.182,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"G",8 82 | "microspheres","","ddH20",125,14971193,1.99e-13,3,"G9",0.178,0.166,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"G",9 83 | "microspheres","","ddH20",125,8982716,1.19e-13,3,"G10",0.18,0.169,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"G",10 84 | "microspheres","","ddH20",125,5389630,7.16e-14,3,"G11",0.186,0.166,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"G",11 85 | "microspheres","","ddH20",125,0,0,3,"G12",0.149,0.142,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"G",12 86 | "microspheres","","ddH20",125,891346154,1.18e-11,4,"H1",1.421,1.26,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"H",1 87 | "microspheres","","ddH20",125,534807692,7.1e-12,4,"H2",1.05,0.891,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"H",2 88 | "microspheres","","ddH20",125,320884615,4.26e-12,4,"H3",0.719,0.606,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"H",3 89 | "microspheres","","ddH20",125,192530769,2.56e-12,4,"H4",0.514,0.433,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"H",4 90 | "microspheres","","ddH20",125,115518461,1.53e-12,4,"H5",0.379,0.323,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"H",5 91 | "microspheres","","ddH20",125,69311077,9.21e-13,4,"H6",0.296,0.257,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"H",6 92 | "microspheres","","ddH20",125,41586646,5.52e-13,4,"H7",0.24,0.216,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"H",7 93 | "microspheres","","ddH20",125,24951988,3.31e-13,4,"H8",0.208,0.192,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"H",8 94 | "microspheres","","ddH20",125,14971193,1.99e-13,4,"H9",0.191,0.178,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"H",9 95 | "microspheres","","ddH20",125,8982716,1.19e-13,4,"H10",0.171,0.16,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"H",10 96 | "microspheres","","ddH20",125,5389630,7.16e-14,4,"H11",0.151,0.142,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"H",11 97 | "microspheres","","ddH20",125,0,0,4,"H12",0.15,0.143,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"H",12 98 | -------------------------------------------------------------------------------- /examples/plate_reader/biotek_cytation/231031_pr_calibration_membrane_parsed_absorbance_cfs.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucl-cssb/flopr/94a5eefef52c6d4aed8fd9ce4608a26004cb73c7/examples/plate_reader/biotek_cytation/231031_pr_calibration_membrane_parsed_absorbance_cfs.pdf -------------------------------------------------------------------------------- /examples/plate_reader/biotek_cytation/231031_pr_calibration_membrane_parsed_cfs.csv: -------------------------------------------------------------------------------- 1 | "cf","beta","calibrant","fluorophore","measure" 2 | 1.64032913776628e-15,2.43505349358509e-10,"FITC","GFP","GFP 30" 3 | 1.54149836181872e-14,2.23647775549191e-10,"FITC","GFP","GFP 40" 4 | 8.53241735961217e-14,2.09524794743675e-10,"FITC","GFP","GFP 50" 5 | 3.38099989260685e-13,2.03482049982522e-10,"FITC","GFP","GFP 60" 6 | 1.07103257669161e-12,1.88314181870328e-10,"FITC","GFP","GFP 70" 7 | 2.81891594477139e-12,1.94261699870685e-10,"FITC","GFP","GFP 80" 8 | 6.53563566229361e-12,1.6520988310458e-10,"FITC","GFP","GFP 90" 9 | 1.41256719827646e-11,2.29518724232912e-10,"FITC","GFP","GFP 100" 10 | 2.90396267315367e-11,2.00431090424536e-10,"FITC","GFP","GFP 110" 11 | 8.61358795753689e-16,2.40623076743591e-10,"FITC","GFP","GFP 30 TOP" 12 | 7.4202969911514e-15,2.24451790754604e-10,"FITC","GFP","GFP 40 TOP" 13 | 4.13200631656152e-14,2.19057472855282e-10,"FITC","GFP","GFP 50 TOP" 14 | 1.5724138549382e-13,2.00583524389911e-10,"FITC","GFP","GFP 60 TOP" 15 | 5.04982958084896e-13,1.84873346850286e-10,"FITC","GFP","GFP 70 TOP" 16 | 1.35686301800826e-12,2.05906767202396e-10,"FITC","GFP","GFP 80 TOP" 17 | 3.15825842699207e-12,1.98941823623681e-10,"FITC","GFP","GFP 90 TOP" 18 | 6.91681598072984e-12,1.77886026754186e-10,"FITC","GFP","GFP 100 TOP" 19 | 1.44093716080527e-11,2.17673925977579e-10,"FITC","GFP","GFP 110 TOP" 20 | 2.8493703237836e-11,2.0345069856221e-10,"FITC","GFP","GFP 120 TOP" 21 | 2.92192580957781e-09,4.01769679511199e-10,"microspheres","","OD600" 22 | 2.40078125e-09,5.46484375e-10,"microspheres","","OD700" 23 | -------------------------------------------------------------------------------- /examples/plate_reader/biotek_cytation/231031_pr_calibration_membrane_parsed_fluorescence_cfs.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucl-cssb/flopr/94a5eefef52c6d4aed8fd9ce4608a26004cb73c7/examples/plate_reader/biotek_cytation/231031_pr_calibration_membrane_parsed_fluorescence_cfs.pdf -------------------------------------------------------------------------------- /examples/plate_reader/biotek_cytation/231031_pr_calibration_nolid.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucl-cssb/flopr/94a5eefef52c6d4aed8fd9ce4608a26004cb73c7/examples/plate_reader/biotek_cytation/231031_pr_calibration_nolid.xlsx -------------------------------------------------------------------------------- /examples/plate_reader/biotek_cytation/plate_layout.csv: -------------------------------------------------------------------------------- 1 | calibrant,fluorophore,media,volume_uL,concentration,concentration_M,replicate,well 2 | FITC,GFP,ddH20,125,7.50E+14,9.97E-03,1,A1 3 | FITC,GFP,ddH20,125,3.75E+14,4.98E-03,1,A2 4 | FITC,GFP,ddH20,125,1.88E+14,2.49E-03,1,A3 5 | FITC,GFP,ddH20,125,9.38E+13,1.25E-03,1,A4 6 | FITC,GFP,ddH20,125,4.69E+13,6.23E-04,1,A5 7 | FITC,GFP,ddH20,125,2.34E+13,3.11E-04,1,A6 8 | FITC,GFP,ddH20,125,1.17E+13,1.56E-04,1,A7 9 | FITC,GFP,ddH20,125,5.86E+12,7.79E-05,1,A8 10 | FITC,GFP,ddH20,125,2.93E+12,3.89E-05,1,A9 11 | FITC,GFP,ddH20,125,1.46E+12,1.95E-05,1,A10 12 | FITC,GFP,ddH20,125,7.32E+11,9.73E-06,1,A11 13 | FITC,GFP,ddH20,125,0.00E+00,0.00E+00,1,A12 14 | FITC,GFP,ddH20,125,7.50E+14,9.97E-03,2,B1 15 | FITC,GFP,ddH20,125,3.75E+14,4.98E-03,2,B2 16 | FITC,GFP,ddH20,125,1.88E+14,2.49E-03,2,B3 17 | FITC,GFP,ddH20,125,9.38E+13,1.25E-03,2,B4 18 | FITC,GFP,ddH20,125,4.69E+13,6.23E-04,2,B5 19 | FITC,GFP,ddH20,125,2.34E+13,3.11E-04,2,B6 20 | FITC,GFP,ddH20,125,1.17E+13,1.56E-04,2,B7 21 | FITC,GFP,ddH20,125,5.86E+12,7.79E-05,2,B8 22 | FITC,GFP,ddH20,125,2.93E+12,3.89E-05,2,B9 23 | FITC,GFP,ddH20,125,1.46E+12,1.95E-05,2,B10 24 | FITC,GFP,ddH20,125,7.32E+11,9.73E-06,2,B11 25 | FITC,GFP,ddH20,125,0.00E+00,0.00E+00,2,B12 26 | FITC,GFP,ddH20,125,7.50E+14,9.97E-03,3,C1 27 | FITC,GFP,ddH20,125,3.75E+14,4.98E-03,3,C2 28 | FITC,GFP,ddH20,125,1.88E+14,2.49E-03,3,C3 29 | FITC,GFP,ddH20,125,9.38E+13,1.25E-03,3,C4 30 | FITC,GFP,ddH20,125,4.69E+13,6.23E-04,3,C5 31 | FITC,GFP,ddH20,125,2.34E+13,3.11E-04,3,C6 32 | FITC,GFP,ddH20,125,1.17E+13,1.56E-04,3,C7 33 | FITC,GFP,ddH20,125,5.86E+12,7.79E-05,3,C8 34 | FITC,GFP,ddH20,125,2.93E+12,3.89E-05,3,C9 35 | FITC,GFP,ddH20,125,1.46E+12,1.95E-05,3,C10 36 | FITC,GFP,ddH20,125,7.32E+11,9.73E-06,3,C11 37 | FITC,GFP,ddH20,125,0.00E+00,0.00E+00,3,C12 38 | FITC,GFP,ddH20,125,7.50E+14,9.97E-03,4,D1 39 | FITC,GFP,ddH20,125,3.75E+14,4.98E-03,4,D2 40 | FITC,GFP,ddH20,125,1.88E+14,2.49E-03,4,D3 41 | FITC,GFP,ddH20,125,9.38E+13,1.25E-03,4,D4 42 | FITC,GFP,ddH20,125,4.69E+13,6.23E-04,4,D5 43 | FITC,GFP,ddH20,125,2.34E+13,3.11E-04,4,D6 44 | FITC,GFP,ddH20,125,1.17E+13,1.56E-04,4,D7 45 | FITC,GFP,ddH20,125,5.86E+12,7.79E-05,4,D8 46 | FITC,GFP,ddH20,125,2.93E+12,3.89E-05,4,D9 47 | FITC,GFP,ddH20,125,1.46E+12,1.95E-05,4,D10 48 | FITC,GFP,ddH20,125,7.32E+11,9.73E-06,4,D11 49 | FITC,GFP,ddH20,125,0.00E+00,0.00E+00,4,D12 50 | microspheres,,ddH20,125,8.91E+08,1.18E-11,1,E1 51 | microspheres,,ddH20,125,5.35E+08,7.10E-12,1,E2 52 | microspheres,,ddH20,125,3.21E+08,4.26E-12,1,E3 53 | microspheres,,ddH20,125,1.93E+08,2.56E-12,1,E4 54 | microspheres,,ddH20,125,1.16E+08,1.53E-12,1,E5 55 | microspheres,,ddH20,125,6.93E+07,9.21E-13,1,E6 56 | microspheres,,ddH20,125,4.16E+07,5.52E-13,1,E7 57 | microspheres,,ddH20,125,2.50E+07,3.31E-13,1,E8 58 | microspheres,,ddH20,125,1.50E+07,1.99E-13,1,E9 59 | microspheres,,ddH20,125,8.98E+06,1.19E-13,1,E10 60 | microspheres,,ddH20,125,5.39E+06,7.16E-14,1,E11 61 | microspheres,,ddH20,125,0.00E+00,0.00E+00,1,E12 62 | microspheres,,ddH20,125,8.91E+08,1.18E-11,2,F1 63 | microspheres,,ddH20,125,5.35E+08,7.10E-12,2,F2 64 | microspheres,,ddH20,125,3.21E+08,4.26E-12,2,F3 65 | microspheres,,ddH20,125,1.93E+08,2.56E-12,2,F4 66 | microspheres,,ddH20,125,1.16E+08,1.53E-12,2,F5 67 | microspheres,,ddH20,125,6.93E+07,9.21E-13,2,F6 68 | microspheres,,ddH20,125,4.16E+07,5.52E-13,2,F7 69 | microspheres,,ddH20,125,2.50E+07,3.31E-13,2,F8 70 | microspheres,,ddH20,125,1.50E+07,1.99E-13,2,F9 71 | microspheres,,ddH20,125,8.98E+06,1.19E-13,2,F10 72 | microspheres,,ddH20,125,5.39E+06,7.16E-14,2,F11 73 | microspheres,,ddH20,125,0.00E+00,0.00E+00,2,F12 74 | microspheres,,ddH20,125,8.91E+08,1.18E-11,3,G1 75 | microspheres,,ddH20,125,5.35E+08,7.10E-12,3,G2 76 | microspheres,,ddH20,125,3.21E+08,4.26E-12,3,G3 77 | microspheres,,ddH20,125,1.93E+08,2.56E-12,3,G4 78 | microspheres,,ddH20,125,1.16E+08,1.53E-12,3,G5 79 | microspheres,,ddH20,125,6.93E+07,9.21E-13,3,G6 80 | microspheres,,ddH20,125,4.16E+07,5.52E-13,3,G7 81 | microspheres,,ddH20,125,2.50E+07,3.31E-13,3,G8 82 | microspheres,,ddH20,125,1.50E+07,1.99E-13,3,G9 83 | microspheres,,ddH20,125,8.98E+06,1.19E-13,3,G10 84 | microspheres,,ddH20,125,5.39E+06,7.16E-14,3,G11 85 | microspheres,,ddH20,125,0.00E+00,0.00E+00,3,G12 86 | microspheres,,ddH20,125,8.91E+08,1.18E-11,4,H1 87 | microspheres,,ddH20,125,5.35E+08,7.10E-12,4,H2 88 | microspheres,,ddH20,125,3.21E+08,4.26E-12,4,H3 89 | microspheres,,ddH20,125,1.93E+08,2.56E-12,4,H4 90 | microspheres,,ddH20,125,1.16E+08,1.53E-12,4,H5 91 | microspheres,,ddH20,125,6.93E+07,9.21E-13,4,H6 92 | microspheres,,ddH20,125,4.16E+07,5.52E-13,4,H7 93 | microspheres,,ddH20,125,2.50E+07,3.31E-13,4,H8 94 | microspheres,,ddH20,125,1.50E+07,1.99E-13,4,H9 95 | microspheres,,ddH20,125,8.98E+06,1.19E-13,4,H10 96 | microspheres,,ddH20,125,5.39E+06,7.16E-14,4,H11 97 | microspheres,,ddH20,125,0.00E+00,0.00E+00,4,H12 98 | -------------------------------------------------------------------------------- /examples/plate_reader/biotek_neo2/biotek-neo2_example_data.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucl-cssb/flopr/94a5eefef52c6d4aed8fd9ce4608a26004cb73c7/examples/plate_reader/biotek_neo2/biotek-neo2_example_data.xlsx -------------------------------------------------------------------------------- /examples/plate_reader/biotek_neo2/biotek-neo2_example_data_parsed.csv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucl-cssb/flopr/94a5eefef52c6d4aed8fd9ce4608a26004cb73c7/examples/plate_reader/biotek_neo2/biotek-neo2_example_data_parsed.csv -------------------------------------------------------------------------------- /examples/plate_reader/tecan_spark/191219_calibration_membrane_parsed.csv: -------------------------------------------------------------------------------- 1 | "calibrant","fluorophore","media","concentration","replicate","well","OD600","OD700","GFP 40","GFP 50","GFP 60","GFP 70","GFP 80","GFP 90","GFP 100","GFP 110","GFP 120","row","column" 2 | "fluorescein","GFP","PBS",10,1,"A1",0.0921,0.0831,1830,9811,36911,NA,NA,NA,NA,NA,NA,"A",1 3 | "fluorescein","GFP","PBS",5,1,"A2",0.0942,0.0852,932,4993,19221,54510,NA,NA,NA,NA,NA,"A",2 4 | "fluorescein","GFP","PBS",2.5,1,"A3",0.1015,0.0928,453,2434,9448,27864,NA,NA,NA,NA,NA,"A",3 5 | "fluorescein","GFP","PBS",1.25,1,"A4",0.0985,0.0899,232,1253,4853,14513,36349,NA,NA,NA,NA,"A",4 6 | "fluorescein","GFP","PBS",0.625,1,"A5",0.0957,0.0905,114,617,2404,7128,18282,41812,NA,NA,NA,"A",5 7 | "fluorescein","GFP","PBS",0.3125,1,"A6",0.1027,0.0965,54,294,1137,3388,8672,20095,42244,NA,NA,"A",6 8 | "fluorescein","GFP","PBS",0.15625,1,"A7",0.0984,0.0918,27,149,581,1733,4464,10204,21665,43374,NA,"A",7 9 | "fluorescein","GFP","PBS",0.078125,1,"A8",0.0966,0.0949,14,76,296,883,2255,5224,11013,22278,42802,"A",8 10 | "fluorescein","GFP","PBS",0.0390625,1,"A9",0.1007,0.0955,7,39,153,454,1160,2681,5671,11383,22231,"A",9 11 | "fluorescein","GFP","PBS",0.01953125,1,"A10",0.0998,0.0953,3,19,76,227,578,1330,2842,5695,11008,"A",10 12 | "fluorescein","GFP","PBS",0.009765625,1,"A11",0.1058,0.1008,2,11,42,124,316,729,1562,3143,6020,"A",11 13 | "fluorescein","GFP","PBS",0,1,"A12",0.1086,0.102,0,2,7,20,52,119,246,491,969,"A",12 14 | "fluorescein","GFP","PBS",10,2,"B1",0.0905,0.084,2170,11542,42376,NA,NA,NA,NA,NA,NA,"B",1 15 | "fluorescein","GFP","PBS",5,2,"B2",0.0911,0.0854,928,4936,18887,53645,NA,NA,NA,NA,NA,"B",2 16 | "fluorescein","GFP","PBS",2.5,2,"B3",0.09,0.0838,468,2522,9739,28562,NA,NA,NA,NA,NA,"B",3 17 | "fluorescein","GFP","PBS",1.25,2,"B4",0.0932,0.0889,231,1247,4823,14304,35869,NA,NA,NA,NA,"B",4 18 | "fluorescein","GFP","PBS",0.625,2,"B5",0.0923,0.0874,112,597,2314,6901,17604,40521,NA,NA,NA,"B",5 19 | "fluorescein","GFP","PBS",0.3125,2,"B6",0.0939,0.0892,56,299,1158,3443,8880,20403,42963,NA,NA,"B",6 20 | "fluorescein","GFP","PBS",0.15625,2,"B7",0.1007,0.0946,27,150,578,1722,4417,10297,21574,43215,NA,"B",7 21 | "fluorescein","GFP","PBS",0.078125,2,"B8",0.0957,0.0908,13,73,286,857,2162,5080,10684,21470,41483,"B",8 22 | "fluorescein","GFP","PBS",0.0390625,2,"B9",0.0957,0.0952,7,38,148,445,1127,2627,5554,11165,21597,"B",9 23 | "fluorescein","GFP","PBS",0.01953125,2,"B10",0.1103,0.1055,4,19,74,223,563,1308,2794,5592,10697,"B",10 24 | "fluorescein","GFP","PBS",0.009765625,2,"B11",0.1093,0.1044,2,10,41,121,312,726,1534,3068,5909,"B",11 25 | "fluorescein","GFP","PBS",0,2,"B12",0.1027,0.0982,0,2,7,20,52,122,252,513,956,"B",12 26 | "fluorescein","GFP","PBS",10,3,"C1",0.1468,0.1185,1671,8769,33015,NA,NA,NA,NA,NA,NA,"C",1 27 | "fluorescein","GFP","PBS",5,3,"C2",0.1016,0.1176,936,4985,19136,54613,NA,NA,NA,NA,NA,"C",2 28 | "fluorescein","GFP","PBS",2.5,3,"C3",0.0897,0.0877,487,2619,10078,29570,NA,NA,NA,NA,NA,"C",3 29 | "fluorescein","GFP","PBS",1.25,3,"C4",0.0966,0.089,250,1330,5127,15429,38751,NA,NA,NA,NA,"C",4 30 | "fluorescein","GFP","PBS",0.625,3,"C5",0.1054,0.0991,124,664,2559,7651,19627,44688,NA,NA,NA,"C",5 31 | "fluorescein","GFP","PBS",0.3125,3,"C6",0.0995,0.0941,61,333,1280,3853,9783,22754,47388,NA,NA,"C",6 32 | "fluorescein","GFP","PBS",0.15625,3,"C7",0.0997,0.0959,32,174,670,2011,5184,11869,24938,50197,NA,"C",7 33 | "fluorescein","GFP","PBS",0.078125,3,"C8",0.1003,0.0948,16,87,338,1018,2588,6013,12642,25441,49472,"C",8 34 | "fluorescein","GFP","PBS",0.0390625,3,"C9",0.097,0.0913,9,47,182,545,1390,3230,6844,13771,26431,"C",9 35 | "fluorescein","GFP","PBS",0.01953125,3,"C10",0.0995,0.0942,5,24,95,282,724,1680,3530,7183,13821,"C",10 36 | "fluorescein","GFP","PBS",0.009765625,3,"C11",0.1004,0.096,2,13,51,152,390,906,1913,3850,7460,"C",11 37 | "fluorescein","GFP","PBS",0,3,"C12",0.1063,0.1,0,2,7,20,52,117,244,498,978,"C",12 38 | "fluorescein","GFP","PBS",10,4,"D1",0.0883,0.0834,1901,9994,37406,NA,NA,NA,NA,NA,NA,"D",1 39 | "fluorescein","GFP","PBS",5,4,"D2",0.0919,0.0871,944,4965,19101,54386,NA,NA,NA,NA,NA,"D",2 40 | "fluorescein","GFP","PBS",2.5,4,"D3",0.0928,0.0866,470,2486,9732,28393,NA,NA,NA,NA,NA,"D",3 41 | "fluorescein","GFP","PBS",1.25,4,"D4",0.0968,0.0925,219,1156,4510,13505,33991,NA,NA,NA,NA,"D",4 42 | "fluorescein","GFP","PBS",0.625,4,"D5",0.1003,0.0947,115,614,2392,7088,18110,41487,NA,NA,NA,"D",5 43 | "fluorescein","GFP","PBS",0.3125,4,"D6",0.0963,0.091,56,298,1172,3468,8910,20564,43074,NA,NA,"D",6 44 | "fluorescein","GFP","PBS",0.15625,4,"D7",0.0949,0.0898,27,146,576,1684,4333,9989,21188,42712,NA,"D",7 45 | "fluorescein","GFP","PBS",0.078125,4,"D8",0.0963,0.0912,14,74,291,863,2223,5099,10898,21882,42137,"D",8 46 | "fluorescein","GFP","PBS",0.0390625,4,"D9",0.0984,0.0927,7,37,147,437,1121,2581,5476,11030,21377,"D",9 47 | "fluorescein","GFP","PBS",0.01953125,4,"D10",0.0992,0.0936,3,19,77,225,577,1326,2807,5709,11010,"D",10 48 | "fluorescein","GFP","PBS",0.009765625,4,"D11",0.1098,0.1048,2,10,40,118,307,702,1494,2994,5801,"D",11 49 | "fluorescein","GFP","PBS",0,4,"D12",0.1049,0.0997,0,2,6,19,50,115,243,491,946,"D",12 50 | "microspheres","","ddH20",807692307.7,1,"E1",0.9082,0.772,0,2,7,23,56,135,277,570,1102,"E",1 51 | "microspheres","","ddH20",484615384.6,1,"E2",0.5497,0.4572,0,2,8,23,60,141,305,597,1176,"E",2 52 | "microspheres","","ddH20",290769230.8,1,"E3",0.445,0.3738,0,2,8,23,60,139,293,589,1150,"E",3 53 | "microspheres","","ddH20",174461538.5,1,"E4",0.2943,0.2496,0,2,8,22,59,135,284,576,1107,"E",4 54 | "microspheres","","ddH20",104676923.1,1,"E5",0.1999,0.1722,0,2,7,22,57,131,277,565,1090,"E",5 55 | "microspheres","","ddH20",62806153.85,1,"E6",0.161,0.1421,0,2,7,22,56,131,268,547,1078,"E",6 56 | "microspheres","","ddH20",37683692.31,1,"E7",0.1362,0.1224,1,2,8,22,55,131,273,552,1022,"E",7 57 | "microspheres","","ddH20",22610215.38,1,"E8",0.1239,0.1139,0,2,7,23,56,132,288,538,1096,"E",8 58 | "microspheres","","ddH20",13566129.23,1,"E9",0.1167,0.1084,0,2,7,21,55,128,269,528,1011,"E",9 59 | "microspheres","","ddH20",8139677.538,1,"E10",0.1052,0.0983,0,2,7,22,57,134,277,542,1076,"E",10 60 | "microspheres","","ddH20",4883806.523,1,"E11",0.1017,0.0957,0,2,7,21,56,128,267,535,1050,"E",11 61 | "microspheres","","ddH20",0,1,"E12",0.1007,0.0959,0,2,7,21,54,123,265,528,1001,"E",12 62 | "microspheres","","ddH20",807692307.7,2,"F1",0.8487,0.7162,0,2,8,21,56,129,273,547,1073,"F",1 63 | "microspheres","","ddH20",484615384.6,2,"F2",0.5781,0.4821,1,2,8,23,60,136,288,582,1130,"F",2 64 | "microspheres","","ddH20",290769230.8,2,"F3",0.3934,0.3286,0,2,8,24,61,142,298,598,1142,"F",3 65 | "microspheres","","ddH20",174461538.5,2,"F4",0.2767,0.2339,0,2,7,23,58,135,284,571,1133,"F",4 66 | "microspheres","","ddH20",104676923.1,2,"F5",0.2097,0.1817,0,2,8,23,58,136,292,566,1109,"F",5 67 | "microspheres","","ddH20",62806153.85,2,"F6",0.1654,0.1462,0,2,7,22,57,129,279,553,1079,"F",6 68 | "microspheres","","ddH20",37683692.31,2,"F7",0.1362,0.1241,0,2,7,22,56,127,268,536,1055,"F",7 69 | "microspheres","","ddH20",22610215.38,2,"F8",0.1315,0.1214,0,2,7,21,54,130,269,536,1066,"F",8 70 | "microspheres","","ddH20",13566129.23,2,"F9",0.1113,0.1027,0,2,7,22,55,130,264,561,1088,"F",9 71 | "microspheres","","ddH20",8139677.538,2,"F10",0.1076,0.1001,0,2,7,22,57,131,277,559,1082,"F",10 72 | "microspheres","","ddH20",4883806.523,2,"F11",0.0997,0.0934,0,2,7,20,52,124,261,502,991,"F",11 73 | "microspheres","","ddH20",0,2,"F12",0.1036,0.0994,0,2,7,20,54,124,260,522,999,"F",12 74 | "microspheres","","ddH20",807692307.7,3,"G1",0.8686,0.7304,0,2,7,22,56,131,281,553,1096,"G",1 75 | "microspheres","","ddH20",484615384.6,3,"G2",0.5947,0.4927,0,2,7,23,58,135,283,578,1112,"G",2 76 | "microspheres","","ddH20",290769230.8,3,"G3",0.3973,0.3322,0,2,8,23,60,137,299,576,1121,"G",3 77 | "microspheres","","ddH20",174461538.5,3,"G4",0.2801,0.2385,0,2,8,24,62,142,308,596,1171,"G",4 78 | "microspheres","","ddH20",104676923.1,3,"G5",0.2072,0.1792,0,2,8,24,59,145,299,593,1192,"G",5 79 | "microspheres","","ddH20",62806153.85,3,"G6",0.1572,0.1383,0,1,8,23,59,138,283,575,1088,"G",6 80 | "microspheres","","ddH20",37683692.31,3,"G7",0.1364,0.123,0,2,8,22,57,132,280,562,1080,"G",7 81 | "microspheres","","ddH20",22610215.38,3,"G8",0.1215,0.1119,0,1,7,22,58,136,286,557,1090,"G",8 82 | "microspheres","","ddH20",13566129.23,3,"G9",0.1137,0.1059,0,2,7,22,56,132,277,559,1082,"G",9 83 | "microspheres","","ddH20",8139677.538,3,"G10",0.1002,0.0939,1,2,7,21,52,119,260,504,990,"G",10 84 | "microspheres","","ddH20",4883806.523,3,"G11",0.1013,0.0953,0,2,7,21,54,123,259,516,1026,"G",11 85 | "microspheres","","ddH20",0,3,"G12",0.0994,0.0942,0,2,6,20,51,121,258,508,977,"G",12 86 | "microspheres","","ddH20",807692307.7,4,"H1",0.8752,0.7372,0,2,7,22,55,133,277,557,1106,"H",1 87 | "microspheres","","ddH20",484615384.6,4,"H2",0.5622,0.4682,0,2,7,23,58,135,290,579,1107,"H",2 88 | "microspheres","","ddH20",290769230.8,4,"H3",0.3919,0.3268,1,2,7,22,58,135,285,562,1101,"H",3 89 | "microspheres","","ddH20",174461538.5,4,"H4",0.2847,0.2423,0,2,7,23,57,133,292,567,1098,"H",4 90 | "microspheres","","ddH20",104676923.1,4,"H5",0.2058,0.1776,0,2,8,23,60,140,294,595,1130,"H",5 91 | "microspheres","","ddH20",62806153.85,4,"H6",0.1632,0.1441,0,2,7,22,56,134,276,545,1054,"H",6 92 | "microspheres","","ddH20",37683692.31,4,"H7",0.1349,0.1214,0,2,9,27,68,166,335,670,1321,"H",7 93 | "microspheres","","ddH20",22610215.38,4,"H8",0.1323,0.1216,0,2,10,28,73,169,354,706,1391,"H",8 94 | "microspheres","","ddH20",13566129.23,4,"H9",0.12,0.1121,1,2,8,24,65,146,313,626,1215,"H",9 95 | "microspheres","","ddH20",8139677.538,4,"H10",0.1097,0.1031,0,2,7,22,57,133,279,561,1059,"H",10 96 | "microspheres","","ddH20",4883806.523,4,"H11",0.105,0.0985,0,2,7,22,57,132,276,550,1073,"H",11 97 | "microspheres","","ddH20",0,4,"H12",0.1005,0.0953,0,2,7,22,55,128,275,541,1064,"H",12 98 | -------------------------------------------------------------------------------- /examples/plate_reader/tecan_spark/191219_calibration_membrane_parsed_absorbance_cfs.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucl-cssb/flopr/94a5eefef52c6d4aed8fd9ce4608a26004cb73c7/examples/plate_reader/tecan_spark/191219_calibration_membrane_parsed_absorbance_cfs.pdf -------------------------------------------------------------------------------- /examples/plate_reader/tecan_spark/191219_calibration_membrane_parsed_cfs.csv: -------------------------------------------------------------------------------- 1 | "cf","beta","calibrant","fluorophore","measure" 2 | 184.727423380549,0.00574759624626908,"fluorescein","GFP","GFP 40" 3 | 996.447161301119,-0.00354235187381888,"fluorescein","GFP","GFP 50" 4 | 3821.04972156311,-0.000473714337673158,"fluorescein","GFP","GFP 60" 5 | 11298.953070981,0.000201527635187288,"fluorescein","GFP","GFP 70" 6 | 29128.3782889558,-0.000748121513265721,"fluorescein","GFP","GFP 80" 7 | 65834.9342365029,0.00127508170363757,"fluorescein","GFP","GFP 90" 8 | 139940.146694077,0.000982238741907277,"fluorescein","GFP","GFP 100" 9 | 288001.553550677,-0.000879790172713573,"fluorescein","GFP","GFP 110" 10 | 567984.42938174,-0.00242703741977703,"fluorescein","GFP","GFP 120" 11 | 2.64499346746598e-08,4.77318409341387e-09,"microspheres","","GFP 40" 12 | 1.5168920457363e-09,8.13779775053263e-09,"microspheres","","OD600" 13 | 1.21544813615036e-09,7.88761279867322e-09,"microspheres","","OD700" 14 | -------------------------------------------------------------------------------- /examples/plate_reader/tecan_spark/191219_calibration_membrane_parsed_fluorescence_cfs.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucl-cssb/flopr/94a5eefef52c6d4aed8fd9ce4608a26004cb73c7/examples/plate_reader/tecan_spark/191219_calibration_membrane_parsed_fluorescence_cfs.pdf -------------------------------------------------------------------------------- /examples/plate_reader/tecan_spark/200228_example_data_parsed_GFP.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucl-cssb/flopr/94a5eefef52c6d4aed8fd9ce4608a26004cb73c7/examples/plate_reader/tecan_spark/200228_example_data_parsed_GFP.pdf -------------------------------------------------------------------------------- /examples/plate_reader/tecan_spark/200228_example_data_parsed_OD.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucl-cssb/flopr/94a5eefef52c6d4aed8fd9ce4608a26004cb73c7/examples/plate_reader/tecan_spark/200228_example_data_parsed_OD.pdf -------------------------------------------------------------------------------- /examples/plate_reader/tecan_spark/200228_example_data_parsed_mCherry.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucl-cssb/flopr/94a5eefef52c6d4aed8fd9ce4608a26004cb73c7/examples/plate_reader/tecan_spark/200228_example_data_parsed_mCherry.pdf -------------------------------------------------------------------------------- /examples/plate_reader/tecan_spark/200228_example_data_parsed_norm-curve_GFP.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucl-cssb/flopr/94a5eefef52c6d4aed8fd9ce4608a26004cb73c7/examples/plate_reader/tecan_spark/200228_example_data_parsed_norm-curve_GFP.pdf -------------------------------------------------------------------------------- /examples/plate_reader/tecan_spark/200228_example_data_parsed_norm-curve_mCherry.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucl-cssb/flopr/94a5eefef52c6d4aed8fd9ce4608a26004cb73c7/examples/plate_reader/tecan_spark/200228_example_data_parsed_norm-curve_mCherry.pdf -------------------------------------------------------------------------------- /examples/plate_reader/tecan_spark/200228_example_layout.csv: -------------------------------------------------------------------------------- 1 | strain,host,plasmid,plasmid_2,strain_2,media,sugar,amino_acids,inducer,concentration,init_ratio,init_dilution,well 2 | ,,,,,,,,,,,,A1 3 | ,,,,,,,,,,,,A2 4 | ,,,,,,,,,,,,A3 5 | ,,,,,,,,,,,,A4 6 | ,,,,,,,,,,,,A5 7 | ,,,,,,,,,,,,A6 8 | ,,,,,,,,,,,,A7 9 | ,,,,,,,,,,,,A8 10 | ,,,,,,,,,,,,A9 11 | ,,,,,,,,,,,,A10 12 | ,,,,,,,,,,,,A11 13 | ,,,,,,,,,,,,A12 14 | ,,,,,,,,,,,,B1 15 | ,,,,,,,,,,,,B2 16 | ,,,,,,,,,,,,B3 17 | ,,,,,,,,,,,,B4 18 | ,,,,,,,,,,,,B5 19 | ,,,,,,,,,,,,B6 20 | ,,,,,,,,,,,,B7 21 | ,,,,,,,,,,,,B8 22 | ,,,,,,,,,,,,B9 23 | ,,,,,,,,,,,,B10 24 | ,,,,,,,,,,,,B11 25 | ,,,,,,,,,,,,B12 26 | JW_SPoCK634301,JW3910,p63_AF043,pMPES_AF01,MG-Gm-CFP,M9,0.4% glycerol,casamino acids,AHL,0,1,0.140625,C1 27 | JW_SPoCK634301,JW3910,p63_AF043,pMPES_AF01,MG-Gm-CFP,M9,0.4% glycerol,casamino acids,AHL,0,0.8,0.140625,C2 28 | JW_SPoCK634301,JW3910,p63_AF043,pMPES_AF01,MG-Gm-CFP,M9,0.4% glycerol,casamino acids,AHL,0,0.6,0.140625,C3 29 | JW_SPoCK634301,JW3910,p63_AF043,pMPES_AF01,MG-Gm-CFP,M9,0.4% glycerol,casamino acids,AHL,0,0.4,0.140625,C4 30 | JW_SPoCK634301,JW3910,p63_AF043,pMPES_AF01,MG-Gm-CFP,M9,0.4% glycerol,casamino acids,AHL,0,0.2,0.140625,C5 31 | JW_SPoCK634301,JW3910,p63_AF043,pMPES_AF01,MG-Gm-CFP,M9,0.4% glycerol,casamino acids,AHL,0,0,0.140625,C6 32 | ,,,,,,,,,,,,C7 33 | ,,,,,,,,,,,,C8 34 | ,,,,,,,,,,,,C9 35 | ,,,,,,,,,,,,C10 36 | ,,,,,,,,,,,,C11 37 | ,,,,,M9,0.4% glycerol,casamino acids,AHL,0,,,C12 38 | JW_SPoCK634301,JW3910,p63_AF043,pMPES_AF01,MG-Gm-CFP,M9,0.4% glycerol,casamino acids,AHL,0,1,0.052734375,D1 39 | JW_SPoCK634301,JW3910,p63_AF043,pMPES_AF01,MG-Gm-CFP,M9,0.4% glycerol,casamino acids,AHL,0,0.8,0.052734375,D2 40 | JW_SPoCK634301,JW3910,p63_AF043,pMPES_AF01,MG-Gm-CFP,M9,0.4% glycerol,casamino acids,AHL,0,0.6,0.052734375,D3 41 | JW_SPoCK634301,JW3910,p63_AF043,pMPES_AF01,MG-Gm-CFP,M9,0.4% glycerol,casamino acids,AHL,0,0.4,0.052734375,D4 42 | JW_SPoCK634301,JW3910,p63_AF043,pMPES_AF01,MG-Gm-CFP,M9,0.4% glycerol,casamino acids,AHL,0,0.2,0.052734375,D5 43 | JW_SPoCK634301,JW3910,p63_AF043,pMPES_AF01,MG-Gm-CFP,M9,0.4% glycerol,casamino acids,AHL,0,0,0.052734375,D6 44 | ,,,,,,,,,,,,D7 45 | ,,,,,,,,,,,,D8 46 | ,,,,,,,,,,,,D9 47 | ,,,,,,,,,,,,D10 48 | ,,,,,,,,,,,,D11 49 | ,,,,,M9,0.4% glycerol,casamino acids,AHL,0,,,D12 50 | JW_SPoCK634301,JW3910,p63_AF043,pMPES_AF01,MG-Gm-CFP,M9,0.4% glycerol,casamino acids,AHL,0,1,0.019775391,E1 51 | JW_SPoCK634301,JW3910,p63_AF043,pMPES_AF01,MG-Gm-CFP,M9,0.4% glycerol,casamino acids,AHL,0,0.8,0.019775391,E2 52 | JW_SPoCK634301,JW3910,p63_AF043,pMPES_AF01,MG-Gm-CFP,M9,0.4% glycerol,casamino acids,AHL,0,0.6,0.019775391,E3 53 | JW_SPoCK634301,JW3910,p63_AF043,pMPES_AF01,MG-Gm-CFP,M9,0.4% glycerol,casamino acids,AHL,0,0.4,0.019775391,E4 54 | JW_SPoCK634301,JW3910,p63_AF043,pMPES_AF01,MG-Gm-CFP,M9,0.4% glycerol,casamino acids,AHL,0,0.2,0.019775391,E5 55 | JW_SPoCK634301,JW3910,p63_AF043,pMPES_AF01,MG-Gm-CFP,M9,0.4% glycerol,casamino acids,AHL,0,0,0.019775391,E6 56 | ,,,,,,,,,,,,E7 57 | ,,,,,,,,,,,,E8 58 | ,,,,,,,,,,,,E9 59 | ,,,,,,,,,,,,E10 60 | ,,,,,,,,,,,,E11 61 | ,,,,,M9,0.4% glycerol,casamino acids,AHL,0,,,E12 62 | ,,,,,,,,,,,,F1 63 | ,,,,,,,,,,,,F2 64 | ,,,,,,,,,,,,F3 65 | ,,,,,,,,,,,,F4 66 | ,,,,,,,,,,,,F5 67 | ,,,,,,,,,,,,F6 68 | ,,,,,,,,,,,,F7 69 | ,,,,,,,,,,,,F8 70 | ,,,,,,,,,,,,F9 71 | ,,,,,,,,,,,,F10 72 | ,,,,,,,,,,,,F11 73 | ,,,,,,,,,,,,F12 74 | ,,,,,,,,,,,,G1 75 | ,,,,,,,,,,,,G2 76 | ,,,,,,,,,,,,G3 77 | ,,,,,,,,,,,,G4 78 | ,,,,,,,,,,,,G5 79 | ,,,,,,,,,,,,G6 80 | ,,,,,,,,,,,,G7 81 | ,,,,,,,,,,,,G8 82 | ,,,,,,,,,,,,G9 83 | ,,,,,,,,,,,,G10 84 | ,,,,,,,,,,,,G11 85 | ,,,,,,,,,,,,G12 86 | ,,,,,,,,,,,,H1 87 | ,,,,,,,,,,,,H2 88 | ,,,,,,,,,,,,H3 89 | ,,,,,,,,,,,,H4 90 | ,,,,,,,,,,,,H5 91 | ,,,,,,,,,,,,H6 92 | ,,,,,,,,,,,,H7 93 | ,,,,,,,,,,,,H8 94 | ,,,,,,,,,,,,H9 95 | ,,,,,,,,,,,,H10 96 | ,,,,,,,,,,,,H11 97 | ,,,,,,,,,,,,H12 98 | -------------------------------------------------------------------------------- /examples/plate_reader/tecan_spark/calibration_plate_layout.csv: -------------------------------------------------------------------------------- 1 | calibrant,fluorophore,media,concentration,replicate,well 2 | fluorescein,GFP,PBS,7.53E+14,1,A1 3 | fluorescein,GFP,PBS,3.765E+14,1,A2 4 | fluorescein,GFP,PBS,1.8825E+14,1,A3 5 | fluorescein,GFP,PBS,9.4125E+13,1,A4 6 | fluorescein,GFP,PBS,4.70625E+13,1,A5 7 | fluorescein,GFP,PBS,2.35313E+13,1,A6 8 | fluorescein,GFP,PBS,1.17656E+13,1,A7 9 | fluorescein,GFP,PBS,5.88281E+12,1,A8 10 | fluorescein,GFP,PBS,2.94141E+12,1,A9 11 | fluorescein,GFP,PBS,1.4707E+12,1,A10 12 | fluorescein,GFP,PBS,7.35352E+11,1,A11 13 | fluorescein,GFP,PBS,0,1,A12 14 | fluorescein,GFP,PBS,7.53E+14,2,B1 15 | fluorescein,GFP,PBS,3.765E+14,2,B2 16 | fluorescein,GFP,PBS,1.8825E+14,2,B3 17 | fluorescein,GFP,PBS,9.4125E+13,2,B4 18 | fluorescein,GFP,PBS,4.70625E+13,2,B5 19 | fluorescein,GFP,PBS,2.35313E+13,2,B6 20 | fluorescein,GFP,PBS,1.17656E+13,2,B7 21 | fluorescein,GFP,PBS,5.88281E+12,2,B8 22 | fluorescein,GFP,PBS,2.94141E+12,2,B9 23 | fluorescein,GFP,PBS,1.4707E+12,2,B10 24 | fluorescein,GFP,PBS,7.35352E+11,2,B11 25 | fluorescein,GFP,PBS,0,2,B12 26 | fluorescein,GFP,PBS,7.53E+14,3,C1 27 | fluorescein,GFP,PBS,3.765E+14,3,C2 28 | fluorescein,GFP,PBS,1.8825E+14,3,C3 29 | fluorescein,GFP,PBS,9.4125E+13,3,C4 30 | fluorescein,GFP,PBS,4.70625E+13,3,C5 31 | fluorescein,GFP,PBS,2.35313E+13,3,C6 32 | fluorescein,GFP,PBS,1.17656E+13,3,C7 33 | fluorescein,GFP,PBS,5.88281E+12,3,C8 34 | fluorescein,GFP,PBS,2.94141E+12,3,C9 35 | fluorescein,GFP,PBS,1.4707E+12,3,C10 36 | fluorescein,GFP,PBS,7.35352E+11,3,C11 37 | fluorescein,GFP,PBS,0,3,C12 38 | fluorescein,GFP,PBS,7.53E+14,4,D1 39 | fluorescein,GFP,PBS,3.765E+14,4,D2 40 | fluorescein,GFP,PBS,1.8825E+14,4,D3 41 | fluorescein,GFP,PBS,9.4125E+13,4,D4 42 | fluorescein,GFP,PBS,4.70625E+13,4,D5 43 | fluorescein,GFP,PBS,2.35313E+13,4,D6 44 | fluorescein,GFP,PBS,1.17656E+13,4,D7 45 | fluorescein,GFP,PBS,5.88281E+12,4,D8 46 | fluorescein,GFP,PBS,2.94141E+12,4,D9 47 | fluorescein,GFP,PBS,1.4707E+12,4,D10 48 | fluorescein,GFP,PBS,7.35352E+11,4,D11 49 | fluorescein,GFP,PBS,0,4,D12 50 | microspheres,,ddH20,807692307.7,1,E1 51 | microspheres,,ddH20,484615384.6,1,E2 52 | microspheres,,ddH20,290769230.8,1,E3 53 | microspheres,,ddH20,174461538.5,1,E4 54 | microspheres,,ddH20,104676923.1,1,E5 55 | microspheres,,ddH20,62806153.85,1,E6 56 | microspheres,,ddH20,37683692.31,1,E7 57 | microspheres,,ddH20,22610215.38,1,E8 58 | microspheres,,ddH20,13566129.23,1,E9 59 | microspheres,,ddH20,8139677.538,1,E10 60 | microspheres,,ddH20,4883806.523,1,E11 61 | microspheres,,ddH20,0,1,E12 62 | microspheres,,ddH20,807692307.7,2,F1 63 | microspheres,,ddH20,484615384.6,2,F2 64 | microspheres,,ddH20,290769230.8,2,F3 65 | microspheres,,ddH20,174461538.5,2,F4 66 | microspheres,,ddH20,104676923.1,2,F5 67 | microspheres,,ddH20,62806153.85,2,F6 68 | microspheres,,ddH20,37683692.31,2,F7 69 | microspheres,,ddH20,22610215.38,2,F8 70 | microspheres,,ddH20,13566129.23,2,F9 71 | microspheres,,ddH20,8139677.538,2,F10 72 | microspheres,,ddH20,4883806.523,2,F11 73 | microspheres,,ddH20,0,2,F12 74 | microspheres,,ddH20,807692307.7,3,G1 75 | microspheres,,ddH20,484615384.6,3,G2 76 | microspheres,,ddH20,290769230.8,3,G3 77 | microspheres,,ddH20,174461538.5,3,G4 78 | microspheres,,ddH20,104676923.1,3,G5 79 | microspheres,,ddH20,62806153.85,3,G6 80 | microspheres,,ddH20,37683692.31,3,G7 81 | microspheres,,ddH20,22610215.38,3,G8 82 | microspheres,,ddH20,13566129.23,3,G9 83 | microspheres,,ddH20,8139677.538,3,G10 84 | microspheres,,ddH20,4883806.523,3,G11 85 | microspheres,,ddH20,0,3,G12 86 | microspheres,,ddH20,807692307.7,4,H1 87 | microspheres,,ddH20,484615384.6,4,H2 88 | microspheres,,ddH20,290769230.8,4,H3 89 | microspheres,,ddH20,174461538.5,4,H4 90 | microspheres,,ddH20,104676923.1,4,H5 91 | microspheres,,ddH20,62806153.85,4,H6 92 | microspheres,,ddH20,37683692.31,4,H7 93 | microspheres,,ddH20,22610215.38,4,H8 94 | microspheres,,ddH20,13566129.23,4,H9 95 | microspheres,,ddH20,8139677.538,4,H10 96 | microspheres,,ddH20,4883806.523,4,H11 97 | microspheres,,ddH20,0,4,H12 98 | -------------------------------------------------------------------------------- /flopr.Rproj: -------------------------------------------------------------------------------- 1 | Version: 1.0 2 | 3 | RestoreWorkspace: Default 4 | SaveWorkspace: Default 5 | AlwaysSaveHistory: Default 6 | 7 | EnableCodeIndexing: Yes 8 | UseSpacesForTab: Yes 9 | NumSpacesForTab: 2 10 | Encoding: UTF-8 11 | 12 | RnwWeave: Sweave 13 | LaTeX: pdfLaTeX 14 | 15 | StripTrailingWhitespace: Yes 16 | 17 | BuildType: Package 18 | PackageUseDevtools: Yes 19 | PackageInstallArgs: --no-multiarch --with-keep.source 20 | PackageRoxygenize: rd,collate,namespace,vignette 21 | -------------------------------------------------------------------------------- /man/biotek_parse.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/biotekNeo2Functions.R 3 | \name{biotek_parse} 4 | \alias{biotek_parse} 5 | \title{Parser for Biotek Neo 2 plate reader data} 6 | \usage{ 7 | biotek_parse(data_xl, layout_csv, timeseries = T) 8 | } 9 | \arguments{ 10 | \item{data_xl}{path to xls or xlsx file from Biotek Neo 2 plate reader} 11 | 12 | \item{layout_csv}{path to csv file containing plate layout information} 13 | 14 | \item{timeseries}{Boolean flag indicating whether the data is a timeseries or 15 | single recording. Currently only works for timeseries=T.} 16 | } 17 | \value{ 18 | a data.frame containing the parsed plate reader data 19 | } 20 | \description{ 21 | Parser for Biotek Neo 2 plate reader data 22 | } 23 | -------------------------------------------------------------------------------- /man/calibrate_flu.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/plateReaderFunctions.R 3 | \name{calibrate_flu} 4 | \alias{calibrate_flu} 5 | \title{Convert arbitrary fluorescence units to calibrated units} 6 | \usage{ 7 | calibrate_flu(pr_data, flu_name, flu_gain, od_name, conversion_factors_csv) 8 | } 9 | \arguments{ 10 | \item{pr_data}{a data.frame of parsed plate reader data} 11 | 12 | \item{flu_name}{name of fluorophore to be calibrated} 13 | 14 | \item{flu_gain}{gain at which the fluorophore was measured} 15 | 16 | \item{od_name}{the column name for the optical density data} 17 | 18 | \item{conversion_factors_csv}{if to_MEFL=T, path of the csv file containing 19 | conversion factors from plate reader calibration} 20 | } 21 | \description{ 22 | Convert arbitrary fluorescence units to calibrated units 23 | } 24 | -------------------------------------------------------------------------------- /man/calibrate_od.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/plateReaderFunctions.R 3 | \name{calibrate_od} 4 | \alias{calibrate_od} 5 | \title{Convert arbitrary absorbance units to calibrated units} 6 | \usage{ 7 | calibrate_od(pr_data, od_name, conversion_factors_csv) 8 | } 9 | \arguments{ 10 | \item{pr_data}{a data.frame of parsed plate reader data} 11 | 12 | \item{od_name}{the column name for the optical density data} 13 | 14 | \item{conversion_factors_csv}{if to_MEFL=T, path of the csv file containing 15 | conversion factors from plate reader calibration} 16 | } 17 | \description{ 18 | Convert arbitrary absorbance units to calibrated units 19 | } 20 | -------------------------------------------------------------------------------- /man/cytation_parse.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/biotekCytationFunctions.R 3 | \name{cytation_parse} 4 | \alias{cytation_parse} 5 | \title{Parser for Biotek Cytation plate reader data} 6 | \usage{ 7 | cytation_parse(data_csv, layout_csv, timeseries = T) 8 | } 9 | \arguments{ 10 | \item{layout_csv}{path to csv file containing plate layout information} 11 | 12 | \item{timeseries}{Boolean flag indicating whether the data is a timeseries or 13 | single recording. Currently only works for timeseries=T.} 14 | 15 | \item{data_xl}{path to xls or xlsx file from Biotek Cytation plate reader} 16 | } 17 | \value{ 18 | a data.frame containing the parsed plate reader data 19 | } 20 | \description{ 21 | Parser for Biotek Cytation plate reader data 22 | } 23 | -------------------------------------------------------------------------------- /man/ff_append_cols.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/flowCoreMisc.R 3 | \name{ff_append_cols} 4 | \alias{ff_append_cols} 5 | \title{Append data columns to a flowFrame} 6 | \usage{ 7 | ff_append_cols(fr, cols) 8 | } 9 | \arguments{ 10 | \item{fr}{A \code{\link[flowCore:flowFrame-class]{flowFrame}}.} 11 | 12 | \item{cols}{A numeric matrix containing the new data columns to be added. 13 | Must has column names to be used as new channel names.} 14 | } 15 | \value{ 16 | A \code{\linkS4class{flowFrame}} 17 | } 18 | \description{ 19 | Append data columns to a flowFrame 20 | } 21 | \details{ 22 | It is used to add extra data columns to the existing flowFrame. It handles 23 | keywords and parameters properly to ensure the new flowFrame can be written 24 | as a valid FCS through the function \code{write.FCS} . 25 | } 26 | \author{ 27 | Mike Jiang 28 | } 29 | \keyword{IO} 30 | -------------------------------------------------------------------------------- /man/flu_norm.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/plateReaderFunctions.R 3 | \name{flu_norm} 4 | \alias{flu_norm} 5 | \title{Normalise fluorescence against negative well} 6 | \usage{ 7 | flu_norm(pr_data, neg_well, blank_well, flu_name, af_model, data_csv) 8 | } 9 | \arguments{ 10 | \item{pr_data}{a long data.frame containing you plate reader data with OD 11 | normalised} 12 | 13 | \item{neg_well}{the well coordinates of a non-fluorescent control} 14 | 15 | \item{blank_well}{the well coordinates of a media blank} 16 | 17 | \item{flu_name}{the column name of the fluorescence chanel to normalise} 18 | 19 | \item{af_model}{model used to fit negative control autofluorescence. 20 | For now these include "polynomial", "invers_poly", "exponential", "spline" or "loess".} 21 | 22 | \item{data_csv}{path to the original data. Used for saving normalisation curve plots.} 23 | } 24 | \description{ 25 | Normalise fluorescence against negative well 26 | } 27 | -------------------------------------------------------------------------------- /man/generate_cfs.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/plateReaderFunctions.R 3 | \name{generate_cfs} 4 | \alias{generate_cfs} 5 | \title{Generate Conversion Factors} 6 | \usage{ 7 | generate_cfs(calibration_csv) 8 | } 9 | \arguments{ 10 | \item{calibration_csv}{path of a .csv file of your calibration data} 11 | } 12 | \description{ 13 | Generate Conversion Factors 14 | } 15 | -------------------------------------------------------------------------------- /man/get_bacteria.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/flowCytometryFunctions.R 3 | \name{get_bacteria} 4 | \alias{get_bacteria} 5 | \title{Remove background debris events} 6 | \usage{ 7 | get_bacteria(flow_frame, pre_cleaned) 8 | } 9 | \arguments{ 10 | \item{flow_frame}{a \code{flowFrame} for processing} 11 | 12 | \item{pre_cleaned}{a flag to identify if debris has already been manually 13 | gated} 14 | } 15 | \description{ 16 | Remove background debris events 17 | } 18 | -------------------------------------------------------------------------------- /man/get_calibration.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/flowCytometryFunctions.R 3 | \name{get_calibration} 4 | \alias{get_calibration} 5 | \title{Get fluorescence calibration curve parameters} 6 | \usage{ 7 | get_calibration(bead_file, flu_channels, mef_peaks, manual_peaks, bead_dens_bw) 8 | } 9 | \arguments{ 10 | \item{bead_file}{path to beads .fcs file.} 11 | 12 | \item{flu_channels}{a vector of strings of the fluorescence channels to keep 13 | in the processed data and plotting. Defaults to \code{"BL1-H"}.} 14 | 15 | \item{mef_peaks}{a list of lists in the form \code{list(list(channel="BL1-H", 16 | peaks=c(0, 200, ...)} of MEF fluorescence values for the calibration beads. 17 | Default values for BL1-H and YL2-H.} 18 | 19 | \item{manual_peaks}{if bead peaks are not being found by the EM algorithm, 20 | one can manually specify the positions of the bead peaks (on a log10 scale). 21 | A list of lists in the form 22 | \code{list(list(channel="BL1-H", peaks=c(2.1, 2.8, ...)} of log10 23 | fluorescence values for the calibration beads.} 24 | 25 | \item{bead_dens_bw}{the bandwidth for the kernel density of the bead peak 26 | data. Default = 0.025. Increase if erroneous peaks are being found, decrease 27 | if not enough peaks are found.} 28 | } 29 | \description{ 30 | Get fluorescence calibration curve parameters 31 | } 32 | -------------------------------------------------------------------------------- /man/get_singlets.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/flowCytometryFunctions.R 3 | \name{get_singlets} 4 | \alias{get_singlets} 5 | \title{Remove doublet events} 6 | \usage{ 7 | get_singlets(flow_frame) 8 | } 9 | \arguments{ 10 | \item{flow_frame}{a \code{flowFrame} for processing} 11 | } 12 | \description{ 13 | Remove doublet events 14 | } 15 | -------------------------------------------------------------------------------- /man/infinite_parse.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/tecanInfiniteFunctions.R 3 | \name{infinite_parse} 4 | \alias{infinite_parse} 5 | \title{Parser for Tecan Infinite plate reader data} 6 | \usage{ 7 | infinite_parse(data_csv, layout_csv, timeseries = F) 8 | } 9 | \arguments{ 10 | \item{data_csv}{path to .csv, .xls or .xlsx file from Tecan Infinit plate reader} 11 | 12 | \item{layout_csv}{path to csv file containing plate layout information} 13 | 14 | \item{timeseries}{Boolean flag indicating whether the data is a timeseries or 15 | single recording. The Tecan software outputs the two scenarios differently.} 16 | } 17 | \value{ 18 | a data.frame containing the parsed plate reader data 19 | } 20 | \description{ 21 | Parser for Tecan Infinite plate reader data 22 | } 23 | -------------------------------------------------------------------------------- /man/next_blank.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/tecanInfiniteFunctions.R 3 | \name{next_blank} 4 | \alias{next_blank} 5 | \title{Find next blank line} 6 | \usage{ 7 | next_blank(start_idx, data) 8 | } 9 | \arguments{ 10 | \item{data}{} 11 | } 12 | \value{ 13 | row index of next blank line 14 | } 15 | \description{ 16 | Find next blank line 17 | } 18 | -------------------------------------------------------------------------------- /man/next_blank_cell.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/tecanSparkFunctions.R 3 | \name{next_blank_cell} 4 | \alias{next_blank_cell} 5 | \title{Find next blank line} 6 | \usage{ 7 | next_blank_cell(start_idx, data, col) 8 | } 9 | \arguments{ 10 | \item{data}{} 11 | } 12 | \value{ 13 | row index of next blank line 14 | } 15 | \description{ 16 | Find next blank line 17 | } 18 | -------------------------------------------------------------------------------- /man/next_blank_row.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/tecanSparkFunctions.R 3 | \name{next_blank_row} 4 | \alias{next_blank_row} 5 | \title{Find next blank line} 6 | \usage{ 7 | next_blank_row(start_idx, data) 8 | } 9 | \arguments{ 10 | \item{data}{} 11 | } 12 | \value{ 13 | row index of next blank line 14 | } 15 | \description{ 16 | Find next blank line 17 | } 18 | -------------------------------------------------------------------------------- /man/next_filled.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/tecanInfiniteFunctions.R 3 | \name{next_filled} 4 | \alias{next_filled} 5 | \title{Find next non-blank line} 6 | \usage{ 7 | next_filled(start_idx, data) 8 | } 9 | \arguments{ 10 | \item{data}{} 11 | } 12 | \value{ 13 | row index of next non-blank line 14 | } 15 | \description{ 16 | Find next non-blank line 17 | } 18 | -------------------------------------------------------------------------------- /man/next_filled_cell.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/tecanSparkFunctions.R 3 | \name{next_filled_cell} 4 | \alias{next_filled_cell} 5 | \title{Find next non-blank line} 6 | \usage{ 7 | next_filled_cell(start_idx, data, col) 8 | } 9 | \arguments{ 10 | \item{data}{} 11 | } 12 | \value{ 13 | row index of next non-blank line 14 | } 15 | \description{ 16 | Find next non-blank line 17 | } 18 | -------------------------------------------------------------------------------- /man/next_filled_row.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/tecanSparkFunctions.R 3 | \name{next_filled_row} 4 | \alias{next_filled_row} 5 | \title{Find next non-blank line} 6 | \usage{ 7 | next_filled_row(start_idx, data) 8 | } 9 | \arguments{ 10 | \item{data}{} 11 | } 12 | \value{ 13 | row index of next non-blank line 14 | } 15 | \description{ 16 | Find next non-blank line 17 | } 18 | -------------------------------------------------------------------------------- /man/od_norm.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/plateReaderFunctions.R 3 | \name{od_norm} 4 | \alias{od_norm} 5 | \title{Normalisation absorbance against blank well} 6 | \usage{ 7 | od_norm(pr_data, blank_well, od_name) 8 | } 9 | \arguments{ 10 | \item{pr_data}{a long data.frame containing you plate reader data} 11 | 12 | \item{blank_well}{the well coordinates of one or more media blanks} 13 | 14 | \item{od_name}{the column name for the optical density data} 15 | } 16 | \value{ 17 | an updated data.frame with an additional column "normalised_OD" 18 | } 19 | \description{ 20 | Normalisation absorbance against blank well 21 | } 22 | -------------------------------------------------------------------------------- /man/plot_trimming.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/flowCytometryFunctions.R 3 | \name{plot_trimming} 4 | \alias{plot_trimming} 5 | \title{Plot trimming process} 6 | \usage{ 7 | plot_trimming( 8 | flow_frame, 9 | bacteria_flow_frame, 10 | singlet_flow_frame, 11 | normalised_flow_frame, 12 | calibrated_flow_frame, 13 | flu_channels, 14 | out_name, 15 | normalised, 16 | calibrate 17 | ) 18 | } 19 | \arguments{ 20 | \item{flow_frame}{the original \code{flowFrame}} 21 | 22 | \item{bacteria_flow_frame}{the \code{flowFrame} with debris removed} 23 | 24 | \item{singlet_flow_frame}{the \code{flowFrame} with debris and doublets removed} 25 | 26 | \item{normalised_flow_frame}{the normalised \code{flowFrame}} 27 | 28 | \item{calibrated_flow_frame}{the calibrated \code{flowFrame} with debris and doublets 29 | removed} 30 | 31 | \item{flu_channels}{a vector of strings of the fluorescence channels to keep 32 | in the processed data and plotting. Defaults to "BL1-H".} 33 | 34 | \item{out_name}{the filename for the outputted \code{flowFrame}} 35 | 36 | \item{normalised}{a Boolean flag to determine whether to normalise} 37 | 38 | \item{calibrate}{a Boolean flag to determine whether to convert fluorescence 39 | to MEF values. Requires an .fcs file with named \code{"*beads*.fcs"}. 40 | Defaults to \code{FALSE}.} 41 | } 42 | \description{ 43 | Plot trimming process 44 | } 45 | -------------------------------------------------------------------------------- /man/prep_flow_frame.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/flowCytometryFunctions.R 3 | \name{prep_flow_frame} 4 | \alias{prep_flow_frame} 5 | \title{Log10 transform and remove -Inf values from \code{flowFrame}} 6 | \usage{ 7 | prep_flow_frame(flow_frame, flu_channels) 8 | } 9 | \arguments{ 10 | \item{flow_frame}{a \code{flowFrame} for processing} 11 | 12 | \item{flu_channels}{a vector of strings of the fluorescence channels to keep 13 | in the processed data and plotting. Defaults to \code{"BL1-H"}.} 14 | } 15 | \description{ 16 | Log10 transform and remove -Inf values from \code{flowFrame} 17 | } 18 | -------------------------------------------------------------------------------- /man/process_fcs.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/flowCytometryFunctions.R 3 | \name{process_fcs} 4 | \alias{process_fcs} 5 | \title{Process an .fcs files to remove debris and doublets} 6 | \usage{ 7 | process_fcs(fcs_file, flu_channels = c("BL1-H"), do_plot = F, pre_cleaned = F) 8 | } 9 | \arguments{ 10 | \item{fcs_file}{path of an .fcs files to be processed.} 11 | 12 | \item{flu_channels}{a vector of strings of the fluorescence channels to keep 13 | in the processed data and plotting. Defaults to "BL1-H".} 14 | 15 | \item{do_plot}{a Boolean flag to determine whether to produce plots showing 16 | the trimming of each \code{flowFrame} Defaults to \code{FALSE}.} 17 | 18 | \item{pre_cleaned}{have you pre removed background debris.} 19 | } 20 | \value{ 21 | nothing is returned. A processed .fcs file is produced and a plot if 22 | \code{do_plot = TRUE}. 23 | } 24 | \description{ 25 | \code{process_fcs} uses mixture models to cluster bacteria from background 26 | debris and fits a linear model to SSC-H vs SSC-A to remove doublets. 27 | } 28 | -------------------------------------------------------------------------------- /man/process_fcs_dir.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/flowCytometryFunctions.R 3 | \name{process_fcs_dir} 4 | \alias{process_fcs_dir} 5 | \title{Process .fcs files within a directory to remove debris and doublets, and 6 | optionally calibrate} 7 | \usage{ 8 | process_fcs_dir( 9 | dir_path, 10 | pattern = "*.fcs", 11 | flu_channels = c("BL1-H"), 12 | do_plot = F, 13 | pre_cleaned = F, 14 | neg_fcs = NA, 15 | calibrate = F, 16 | mef_peaks = NA, 17 | bead_dens_bw = 0.025, 18 | manual_peaks = NA 19 | ) 20 | } 21 | \arguments{ 22 | \item{dir_path}{a directory path containing the .fcs files to be parsed or 23 | folders to be recursed through.} 24 | 25 | \item{pattern}{a regex pattern to match particular .fcs files. Default is 26 | \code{"*.fcs"} matching all .fcs files.} 27 | 28 | \item{flu_channels}{a vector of strings of the fluorescence channels to keep 29 | in the processed data and plotting. Defaults to "BL1-H".} 30 | 31 | \item{do_plot}{a Boolean flag to determine whether to produce plots showing 32 | the trimming of each \code{flowFrame}. Defaults to \code{FALSE}.} 33 | 34 | \item{pre_cleaned}{have you pre removed background debris} 35 | 36 | \item{neg_fcs}{filename of .fcs file for a negative control used for 37 | fluorescence normalisation.} 38 | 39 | \item{calibrate}{a Boolean flag to determine whether to convert fluorescence 40 | to MEF values. Requires an .fcs file with named \code{"*beads*.fcs"}. 41 | Defaults to \code{FALSE}.} 42 | 43 | \item{mef_peaks}{a list of lists in the form \code{list(list(channel="BL1-H", 44 | peaks=c(0, 200, ...)} of MEF fluorescence values for the calibration beads. 45 | Default values for BL1-H and YL2-H.} 46 | 47 | \item{bead_dens_bw}{the bandwidth for the kernel density of the bead peak 48 | data. Default = 0.025. Increase if erroneous peaks are being found, decrease 49 | if not enough peaks are found.} 50 | 51 | \item{manual_peaks}{if bead peaks are not being found by the EM algorithm, 52 | one can manually specify the positions of the bead peaks (on a log10 scale). 53 | A list of lists in the form 54 | \code{list(list(channel="BL1-H", peaks=c(2.1, 2.8, ...)} of log10 55 | fluorescence values for the calibration beads.} 56 | } 57 | \value{ 58 | nothing is returned. A new folder is created with the processed .fcs 59 | files and plot if \code{do_plot = TRUE}. 60 | } 61 | \description{ 62 | \code{process_fcs_dir} uses mixture models to cluster bacteria from 63 | background debris and fits a linear model to SSC-H vs SSC-A to remove doublets. 64 | } 65 | -------------------------------------------------------------------------------- /man/process_plate.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/plateReaderFunctions.R 3 | \name{process_plate} 4 | \alias{process_plate} 5 | \title{Plate reader normalisation and calibration} 6 | \usage{ 7 | process_plate( 8 | data_csv, 9 | blank_well = "A1", 10 | neg_well = "A2", 11 | od_name = "OD", 12 | flu_names = c("GFP"), 13 | af_model = "spline", 14 | to_MEFL = F, 15 | flu_gains, 16 | conversion_factors_csv 17 | ) 18 | } 19 | \arguments{ 20 | \item{data_csv}{path to a .csv file containing parsed plate reader data} 21 | 22 | \item{blank_well}{the well coordinates of one or more media blanks} 23 | 24 | \item{neg_well}{the well coordinates of a non-fluorescent control} 25 | 26 | \item{od_name}{the column name for the optical density data} 27 | 28 | \item{flu_names}{the column names for the fluorescence data} 29 | 30 | \item{af_model}{model used to fit negative control autofluorescence. 31 | For now these include "polynomial", "invers_poly", "exponential", "spline" and "loess".} 32 | 33 | \item{to_MEFL}{a Boolean to determine whether to attempt to convert OD and 34 | GFP reading to calibrated units} 35 | 36 | \item{flu_gains}{if to_MEFL=T, the gain values at which the fluorophores 37 | specified in flu_names was recorded. If there isn't calibration data for a 38 | fluorophore, do not speficy a gain value} 39 | 40 | \item{conversion_factors_csv}{if to_MEFL=T, path of the csv file containing 41 | conversion factors from plate reader calibration} 42 | } 43 | \value{ 44 | a data.frame with columns for raw plate reader data, normalised data 45 | and, if to_MEFL = T, calibrated OD and GFP data 46 | } 47 | \description{ 48 | Plate reader normalisation and calibration 49 | } 50 | -------------------------------------------------------------------------------- /man/sparkParse.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/tecanSparkFunctions.R 3 | \name{sparkParse} 4 | \alias{sparkParse} 5 | \title{Parser for Tecan Spark plate reader data} 6 | \usage{ 7 | sparkParse(data_csv, layout_csv) 8 | } 9 | \arguments{ 10 | \item{data_csv}{path to csv file from Tecan Spark plate reader} 11 | 12 | \item{layout_csv}{path to csv file containing plate layout information} 13 | } 14 | \value{ 15 | a data.frame containing the parsed plate reader data 16 | } 17 | \description{ 18 | Parser for Tecan Spark plate reader data 19 | } 20 | -------------------------------------------------------------------------------- /man/spark_parse.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/tecanSparkFunctions.R 3 | \name{spark_parse} 4 | \alias{spark_parse} 5 | \title{Parser for Tecan Spark plate reader data} 6 | \usage{ 7 | spark_parse(data_csv, layout_csv, timeseries = F, wells_as_columns = F) 8 | } 9 | \arguments{ 10 | \item{data_csv}{path to .csv, .xls or .xlsx file from Tecan Spark plate reader} 11 | 12 | \item{layout_csv}{path to csv file containing plate layout information} 13 | 14 | \item{timeseries}{Boolean flag indicating whether the data is a timeseries or 15 | single recording. The Tecan software outputs the two scenarios differently.} 16 | 17 | \item{wells_as_columns}{Boolean flag indicating whether blocks of data are 18 | oriented with wells as columns or rows} 19 | } 20 | \value{ 21 | a data.frame containing the parsed plate reader data 22 | } 23 | \description{ 24 | Parser for Tecan Spark plate reader data 25 | } 26 | -------------------------------------------------------------------------------- /man/summarise_data.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/flowCytometryFunctions.R 3 | \name{summarise_data} 4 | \alias{summarise_data} 5 | \title{Get geometric mean and standard deviation of fluorescence channels of a flow frame} 6 | \usage{ 7 | summarise_data(flow_frame, flu_channels) 8 | } 9 | \arguments{ 10 | \item{flow_frame}{a flow frame to be summarised} 11 | 12 | \item{flu_channels}{channels to summarise} 13 | } 14 | \description{ 15 | Get geometric mean and standard deviation of fluorescence channels of a flow frame 16 | } 17 | -------------------------------------------------------------------------------- /man/to_mef.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/flowCytometryFunctions.R 3 | \name{to_mef} 4 | \alias{to_mef} 5 | \title{Calibrate fluorescence measurements} 6 | \usage{ 7 | to_mef(flow_frame, flu_channels, calibration_parameters, normalise) 8 | } 9 | \arguments{ 10 | \item{flow_frame}{a \code{flowFrame} for processing} 11 | 12 | \item{flu_channels}{a vector of strings of the fluorescence channels to keep 13 | in the processed data and plotting. Defaults to "BL1-H".} 14 | 15 | \item{calibration_parameters}{parameters of a model returned by 16 | get_calibration(...)} 17 | 18 | \item{normalise}{Boolean flag to indicate if data has been normalised} 19 | } 20 | \description{ 21 | Calibrate fluorescence measurements 22 | } 23 | --------------------------------------------------------------------------------