|
| 1 | +--- |
| 2 | +title: "Generate manifest file for uploading on the CLUE data library" |
| 3 | +output: github_document |
| 4 | +--- |
| 5 | + |
| 6 | +The clue.io manifest file requires the following fields |
| 7 | + |
| 8 | +``` |
| 9 | +file_name |
| 10 | +assay_protocol |
| 11 | +data_level |
| 12 | +level_code |
| 13 | +level_desc |
| 14 | +size |
| 15 | +md5 |
| 16 | +``` |
| 17 | + |
| 18 | +This notebook generates the manifest file. |
| 19 | + |
| 20 | +All data files should be available locally in order to compute `size` and `md5`. |
| 21 | + |
| 22 | +```{r, kable-alias, eval=TRUE, echo=FALSE} |
| 23 | +show_table <- knitr::kable |
| 24 | +``` |
| 25 | + |
| 26 | +```{r, load-tidyverse, message=FALSE} |
| 27 | +library(tidyverse) |
| 28 | +``` |
| 29 | + |
| 30 | +# Define batch and versioned github.qkg1.topmit hash |
| 31 | + |
| 32 | +```{r, set-constants} |
| 33 | +rep_batch <- "2016_04_01_a549_48hr_batch1" |
| 34 | +commit_hash <- "1306dc468a8871e7f401db9a4b10debeae37ac0d" |
| 35 | +``` |
| 36 | + |
| 37 | + |
| 38 | +# Define data levels |
| 39 | + |
| 40 | +```{r, define-data-levels} |
| 41 | +cell_painting_data_levels <- |
| 42 | + tribble(~data_level, ~level_code, ~level_desc, |
| 43 | + "Level1", "CPLevel1", "Raw unprocessed images from microscopes", |
| 44 | + "Level2a", "CPLevel2a", "Per-cell level measurements stored across multiple CSVs", |
| 45 | + "Level2b", "CPLevel2b", "Per-cell level measurements stored in a single backend file per assay plate", |
| 46 | + "Level3", "CPLevel3", "Per-well level median-aggregated measurements", |
| 47 | + "Level4a", "CPLevel4a", "Morphological profiles computed using z-scores relative to the plate population", |
| 48 | + "Level4b", "CPLevel4b", "Feature selection applied to Level4b", |
| 49 | + "Level5_median", "CPLevel5_median", "Median-aggregated perturbation signatures", |
| 50 | + "Level5_modz", "CPLevel5_modz", "MODZ-aggregated perturbation signatures" |
| 51 | +) |
| 52 | +cell_painting_data_levels$assay_protocol <- "CellPaintingv2" |
| 53 | +cell_painting_data_levels %>% show_table |
| 54 | +``` |
| 55 | + |
| 56 | + |
| 57 | +Specify suffixes for each data level |
| 58 | + |
| 59 | +```{r, define-suffixes} |
| 60 | +l2_suffix <- ".sqlite" |
| 61 | +l3_suffix <- "_augmented.csv.gz" |
| 62 | +l4a_suffix <- "_normalized.csv.gz" |
| 63 | +l4b_suffix <- "_normalized_feature_select.csv.gz" |
| 64 | +l5_median_suffix <- "_consensus_median.csv.gz" |
| 65 | +l5_modz_suffix <- "_consensus_modz.csv.gz" |
| 66 | +``` |
| 67 | + |
| 68 | + |
| 69 | +# Create a list of plates in this experiment |
| 70 | + |
| 71 | +```{r, create-platelist} |
| 72 | +all_rep_plates <- |
| 73 | + read_csv(sprintf("../platemaps/%s/barcode_platemap.csv", rep_batch)) %>% |
| 74 | + distinct(Assay_Plate_Barcode) |
| 75 | +
|
| 76 | +# remove some missing plates |
| 77 | +missing_rep_plates <- |
| 78 | + tribble(~Assay_Plate_Barcode, |
| 79 | + "SQ00015225", |
| 80 | + "SQ00015226", |
| 81 | + "SQ00015227", |
| 82 | + "SQ00015228") |
| 83 | +
|
| 84 | +rep_plates <- |
| 85 | + setdiff(all_rep_plates, missing_rep_plates) |
| 86 | +
|
| 87 | +rep_plates %>% |
| 88 | + head %>% |
| 89 | + show_table |
| 90 | +
|
| 91 | +rep_plates %>% |
| 92 | + count %>% |
| 93 | + show_table |
| 94 | +``` |
| 95 | + |
| 96 | +# Get URLs to files |
| 97 | + |
| 98 | +## Level 3 and Level 4 |
| 99 | + |
| 100 | +Generate local paths to Level 3 and Level 4 data |
| 101 | + |
| 102 | +```{r, local-paths-levels34} |
| 103 | +path_local <- paste0("../../profiles/", rep_batch) |
| 104 | +
|
| 105 | +level_3_4_files_local <- |
| 106 | + rep_plates$Assay_Plate_Barcode %>% |
| 107 | + map_df(function(plate) { |
| 108 | + tibble(plate = plate, |
| 109 | + CPLevel3 = file.path(path_local, plate, paste0(plate, l3_suffix)), |
| 110 | + CPLevel4a = file.path(path_local, plate, paste0(plate, l4a_suffix)), |
| 111 | + CPLevel4b = file.path(path_local, plate, paste0(plate, l4b_suffix)) |
| 112 | + ) |
| 113 | + }) |
| 114 | +``` |
| 115 | + |
| 116 | +Generate remote paths to Level 3 and Level 4 data |
| 117 | + |
| 118 | +```{r, remote-paths-levels34} |
| 119 | +path_url <- paste0( |
| 120 | + "https://media.githubusercontent.com/media/broadinstitute/lincs-cell-painting/", |
| 121 | + commit_hash, |
| 122 | + "/profiles/", |
| 123 | + rep_batch |
| 124 | +) |
| 125 | +
|
| 126 | +level_3_4_files_url <- |
| 127 | + rep_plates$Assay_Plate_Barcode %>% |
| 128 | + map_df(function(plate) { |
| 129 | + tibble(plate = plate, |
| 130 | + CPLevel3 = file.path(path_url, plate, paste0(plate, l3_suffix)), |
| 131 | + CPLevel4a = file.path(path_url, plate, paste0(plate, l4a_suffix)), |
| 132 | + CPLevel4b = file.path(path_url, plate, paste0(plate, l4b_suffix)) |
| 133 | + ) |
| 134 | + }) |
| 135 | +``` |
| 136 | + |
| 137 | +## Level 5 |
| 138 | + |
| 139 | +Generate local paths to Level 5 data |
| 140 | + |
| 141 | +```{r, local-paths-level5} |
| 142 | +path_local <- "../../consensus" |
| 143 | +
|
| 144 | +level_5_files_local <- |
| 145 | + tibble(batch = rep_batch, |
| 146 | + CPLevel5_median = file.path(path_local, rep_batch, paste0(rep_batch, l5_median_suffix)), |
| 147 | + CPLevel5_modz = file.path(path_local, rep_batch, paste0(rep_batch, l5_modz_suffix))) |
| 148 | +``` |
| 149 | + |
| 150 | +Generate remote paths to Level 5 data |
| 151 | + |
| 152 | +```{r, remote-paths-level5} |
| 153 | +path_url <- paste0( |
| 154 | + "https://media.githubusercontent.com/media/broadinstitute/lincs-cell-painting/", |
| 155 | + commit_hash, |
| 156 | + "/consensus" |
| 157 | +) |
| 158 | +
|
| 159 | +level_5_files_url <- |
| 160 | + tibble(batch = rep_batch, |
| 161 | + CPLevel5_median = file.path(path_url, rep_batch, paste0(rep_batch, l5_median_suffix)), |
| 162 | + CPLevel5_modz = file.path(path_url, rep_batch, paste0(rep_batch, l5_modz_suffix))) |
| 163 | +``` |
| 164 | + |
| 165 | +# Create manifest file |
| 166 | + |
| 167 | +Note: this step requires the files to be locally available because it checks the size and computes `md5`. |
| 168 | + |
| 169 | +## Level 3 and 4 |
| 170 | + |
| 171 | +```{r, manifest-file-levels34} |
| 172 | +manifest_3_4_url <- |
| 173 | + level_3_4_files_url %>% |
| 174 | + pivot_longer(-plate, |
| 175 | + names_to = "level_code", |
| 176 | + values_to = "file_name") %>% |
| 177 | + inner_join(cell_painting_data_levels, by = "level_code") %>% |
| 178 | + select(plate, file_name, assay_protocol, data_level, level_code, level_desc) %>% |
| 179 | + arrange(plate, data_level) |
| 180 | +
|
| 181 | +manifest_3_4_local <- |
| 182 | + level_3_4_files_local %>% |
| 183 | + pivot_longer(-plate, |
| 184 | + names_to = "level_code", |
| 185 | + values_to = "file_name") %>% |
| 186 | + arrange(plate) %>% |
| 187 | + rowwise() %>% |
| 188 | + mutate(size = file.size(file_name)) %>% |
| 189 | + mutate(md5 = unname(tools::md5sum(file_name))) |
| 190 | + |
| 191 | +manifest_3_4 <- |
| 192 | + inner_join( |
| 193 | + manifest_3_4_url, |
| 194 | + manifest_3_4_local %>% select(-file_name), |
| 195 | + by = c("plate", "level_code")) %>% |
| 196 | + select(-plate) |
| 197 | +``` |
| 198 | + |
| 199 | +## Level 5 |
| 200 | + |
| 201 | +```{r, manifest-file-level5} |
| 202 | +manifest_5_url <- |
| 203 | + level_5_files_url %>% |
| 204 | + pivot_longer(-batch, |
| 205 | + names_to = "level_code", |
| 206 | + values_to = "file_name") %>% |
| 207 | + inner_join(cell_painting_data_levels, by = "level_code") %>% |
| 208 | + select(batch, file_name, assay_protocol, data_level, level_code, level_desc) %>% |
| 209 | + arrange(batch, data_level) |
| 210 | +
|
| 211 | +manifest_5_local <- |
| 212 | + level_5_files_local %>% |
| 213 | + pivot_longer(-batch, |
| 214 | + names_to = "level_code", |
| 215 | + values_to = "file_name") %>% |
| 216 | + arrange(batch) %>% |
| 217 | + rowwise() %>% |
| 218 | + mutate(size = file.size(file_name)) %>% |
| 219 | + mutate(md5 = unname(tools::md5sum(file_name))) |
| 220 | + |
| 221 | +manifest_5 <- |
| 222 | + inner_join( |
| 223 | + manifest_5_url, |
| 224 | + manifest_5_local %>% select(-file_name), |
| 225 | + by = c("batch", "level_code")) %>% |
| 226 | + select(-batch) |
| 227 | +``` |
| 228 | + |
| 229 | +## Combine 3,4,5 |
| 230 | + |
| 231 | +```{r, bind-manifest-files} |
| 232 | +manifest <- |
| 233 | + bind_rows( |
| 234 | + manifest_3_4, |
| 235 | + manifest_5 |
| 236 | + ) |
| 237 | +``` |
| 238 | + |
| 239 | +# Check if URLs exist |
| 240 | + |
| 241 | +```{r, check-manifest-file} |
| 242 | +check_file_exists <- function(url) { |
| 243 | + response <- httr::GET(url) |
| 244 | + if (response$status_code == 200) { |
| 245 | + exists <- TRUE |
| 246 | + } else { |
| 247 | + exists <- FALSE |
| 248 | + } |
| 249 | + return(exists) |
| 250 | +} |
| 251 | +
|
| 252 | +manifest_check <- |
| 253 | + manifest %>% |
| 254 | + rowwise() %>% |
| 255 | + mutate( |
| 256 | + url_exists = check_file_exists(file_name), |
| 257 | + na_md5 = is.na(md5), |
| 258 | + na_size = is.na(size) |
| 259 | + ) %>% |
| 260 | + ungroup() |
| 261 | +``` |
| 262 | + |
| 263 | + |
| 264 | +```{r, confirm-zero-rows} |
| 265 | +manifest_check %>% |
| 266 | + filter(!url_exists | na_md5 | na_size) %>% |
| 267 | + show_table |
| 268 | +``` |
| 269 | + |
| 270 | +# Write manifest |
| 271 | + |
| 272 | +```{r, write-manifest} |
| 273 | +manifest %>% |
| 274 | + write_tsv("cell_painting_lincs_pilot_1_manifest.txt") |
| 275 | +``` |
| 276 | + |
0 commit comments