1. load libraries

#Differential Expression Analysis

2. load seurat object


All_samples_Merged <- readRDS("/home/nabbasi/isilon/PHD_3rd_YEAR_Analysis/0-Seurat_RDS_OBJECT_FINAL/All_samples_Merged_Harmony_integrated_Cell_line_renamed_03-07-2025.rds")

Set Up Identifiers for Clustering

# Assign cluster identities to the Seurat object
Idents(All_samples_Merged) <- "seurat_clusters"

DimPlot(All_samples_Merged, reduction = "umap", group.by = "cell_line",label = T, label.box = T)

DimPlot(All_samples_Merged, reduction = "umap", group.by = "seurat_clusters",label = T, label.box = T)

#Differential Expression Analysis # 3. Pairwise Comparisons

# Perform comparisons dynamically for each cell line pair
p1_comparison <- perform_comparison_and_volcano(All_samples_Merged, "L1", "L2", expression_data_RNA)
Avis : One or more p-values is 0. Converting to 10^-1 * current lowest non-zero p-value...

p2_comparison <- perform_comparison_and_volcano(All_samples_Merged, "L3", "L4", expression_data_RNA)
Avis : One or more p-values is 0. Converting to 10^-1 * current lowest non-zero p-value...

p3_comparison_L5L6 <- perform_comparison_and_volcano(All_samples_Merged, "L5", "L6", expression_data_RNA)
Avis : One or more p-values is 0. Converting to 10^-1 * current lowest non-zero p-value...

p3_comparison_L5L7 <- perform_comparison_and_volcano(All_samples_Merged, "L5", "L7", expression_data_RNA)
Avis : One or more p-values is 0. Converting to 10^-1 * current lowest non-zero p-value...

p3_comparison_L6L7 <- perform_comparison_and_volcano(All_samples_Merged, "L6", "L7", expression_data_RNA)
Avis : One or more p-values is 0. Converting to 10^-1 * current lowest non-zero p-value...

# Print the first few rows of each result
head(p1_comparison)
head(p2_comparison)
head(p3_comparison_L5L6)
head(p3_comparison_L5L7)
head(p3_comparison_L6L7)

4. Pairwise Comparisons Filtering

library(dplyr)

# Function to summarize DE markers
summarize_markers <- function(markers, comparison_name) {
  num_pval0 <- sum(markers$p_val_adj == 0)
  num_pval1 <- sum(markers$p_val_adj == 1)
  num_significant <- sum(markers$p_val_adj < 0.05)
  num_upregulated <- sum(markers$avg_log2FC > 1)
  num_downregulated <- sum(markers$avg_log2FC < -1)
  
  cat("\nSummary for", comparison_name, ":\n")
  cat("Number of genes with p_val_adj = 0:", num_pval0, "\n")
  cat("Number of genes with p_val_adj = 1:", num_pval1, "\n")
  cat("Number of significant genes (p_val_adj < 0.05):", num_significant, "\n")
  cat("Number of upregulated genes (avg_log2FC > 1):", num_upregulated, "\n")
  cat("Number of downregulated genes (avg_log2FC < -1):", num_downregulated, "\n")
}

# Function to filter DE markers and save results
filter_and_save <- function(markers, ident1, ident2) {
  comparison_name <- paste(ident1, "vs", ident2)
  
  # Summary before filtering
  summarize_markers(markers, comparison_name)
  
  # Apply the expression filter
  markers_filtered <- markers %>%
    filter(!(mean_expr_ident1 < 0.2 & mean_expr_ident2 < 0.2))

  # Save filtered results
  output_filename <- paste0("comparison_", ident1, "_vs_", ident2, "_with_mean_expression_filtered.csv")
  write.csv(markers_filtered, file = output_filename, row.names = FALSE)
  
  cat("Filtered results saved to:", output_filename, "\n")
  
  return(markers_filtered)
}

# Apply the function to all comparisons
p1_filtered <- filter_and_save(p1_comparison, "L1", "L2")

Summary for L1 vs L2 :
Number of genes with p_val_adj = 0: 1301 
Number of genes with p_val_adj = 1: 2209 
Number of significant genes (p_val_adj < 0.05): 10169 
Number of upregulated genes (avg_log2FC > 1): 1297 
Number of downregulated genes (avg_log2FC < -1): 3216 
Filtered results saved to: comparison_L1_vs_L2_with_mean_expression_filtered.csv 
p2_filtered <- filter_and_save(p2_comparison, "L3", "L4")

Summary for L3 vs L4 :
Number of genes with p_val_adj = 0: 389 
Number of genes with p_val_adj = 1: 2998 
Number of significant genes (p_val_adj < 0.05): 8391 
Number of upregulated genes (avg_log2FC > 1): 943 
Number of downregulated genes (avg_log2FC < -1): 1537 
Filtered results saved to: comparison_L3_vs_L4_with_mean_expression_filtered.csv 
p3_filtered_L5L6 <- filter_and_save(p3_comparison_L5L6, "L5", "L6")

Summary for L5 vs L6 :
Number of genes with p_val_adj = 0: 375 
Number of genes with p_val_adj = 1: 3837 
Number of significant genes (p_val_adj < 0.05): 7656 
Number of upregulated genes (avg_log2FC > 1): 1350 
Number of downregulated genes (avg_log2FC < -1): 1700 
Filtered results saved to: comparison_L5_vs_L6_with_mean_expression_filtered.csv 
p3_filtered_L5L7 <- filter_and_save(p3_comparison_L5L7, "L5", "L7")

Summary for L5 vs L7 :
Number of genes with p_val_adj = 0: 189 
Number of genes with p_val_adj = 1: 4450 
Number of significant genes (p_val_adj < 0.05): 5982 
Number of upregulated genes (avg_log2FC > 1): 1063 
Number of downregulated genes (avg_log2FC < -1): 1129 
Filtered results saved to: comparison_L5_vs_L7_with_mean_expression_filtered.csv 
p3_filtered_L6L7 <- filter_and_save(p3_comparison_L6L7, "L6", "L7")

Summary for L6 vs L7 :
Number of genes with p_val_adj = 0: 172 
Number of genes with p_val_adj = 1: 4312 
Number of significant genes (p_val_adj < 0.05): 6485 
Number of upregulated genes (avg_log2FC > 1): 1113 
Number of downregulated genes (avg_log2FC < -1): 929 
Filtered results saved to: comparison_L6_vs_L7_with_mean_expression_filtered.csv 
LS0tCnRpdGxlOiAiU8OpemFyeSBTeW5kcm9tZSBDZWxsIExpbmUgZGVyaXZlZCBmcm9tIHBhdGllbnQgQW5hbHlzaXNfTmV3VU1BUF9XaWxjb3hfUk5BX0Fzc2F5IgphdXRob3I6IE5hc2lyIE1haG1vb2QgQWJiYXNpCmRhdGU6ICJgciBTeXMuRGF0ZSgpYCIKb3V0cHV0OgogICMgcGRmX2RvY3VtZW50OiBkZWZhdWx0CiAgIyB3b3JkX2RvY3VtZW50OiBkZWZhdWx0CiAgIyBodG1sX2RvY3VtZW50OiBkZWZhdWx0CiAgI3JtZGZvcm1hdHM6OnJlYWR0aGVkb3duCiAgaHRtbF9ub3RlYm9vazoKICAgIHRvYzogdHJ1ZQogICAgdG9jX2Zsb2F0OiB0cnVlCiAgICB0b2NfY29sbGFwc2VkOiB0cnVlCi0tLQoKIyAxLiBsb2FkIGxpYnJhcmllcwpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0KCgpsaWJyYXJ5KFNldXJhdCkKbGlicmFyeShkcGx5cikKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KHBoZWF0bWFwKQpsaWJyYXJ5KGNsdXN0ZXJQcm9maWxlcikKbGlicmFyeShvcmcuSHMuZWcuZGIpCmxpYnJhcnkoZW5yaWNocGxvdCkKbGlicmFyeShlbnJpY2hwbG90KQoKCgpgYGAKI0RpZmZlcmVudGlhbCBFeHByZXNzaW9uIEFuYWx5c2lzCgojIDIuIGxvYWQgc2V1cmF0IG9iamVjdApgYGB7ciBsb2FkX3NldXJhdH0KCkFsbF9zYW1wbGVzX01lcmdlZCA8LSByZWFkUkRTKCIvaG9tZS9uYWJiYXNpL2lzaWxvbi9QSERfM3JkX1lFQVJfQW5hbHlzaXMvMC1TZXVyYXRfUkRTX09CSkVDVF9GSU5BTC9BbGxfc2FtcGxlc19NZXJnZWRfSGFybW9ueV9pbnRlZ3JhdGVkX0NlbGxfbGluZV9yZW5hbWVkXzAzLTA3LTIwMjUucmRzIikKCgoKYGBgCgojIyAgU2V0IFVwIElkZW50aWZpZXJzIGZvciBDbHVzdGVyaW5nCmBgYHtyfQojIEFzc2lnbiBjbHVzdGVyIGlkZW50aXRpZXMgdG8gdGhlIFNldXJhdCBvYmplY3QKSWRlbnRzKEFsbF9zYW1wbGVzX01lcmdlZCkgPC0gInNldXJhdF9jbHVzdGVycyIKCkRpbVBsb3QoQWxsX3NhbXBsZXNfTWVyZ2VkLCByZWR1Y3Rpb24gPSAidW1hcCIsIGdyb3VwLmJ5ID0gImNlbGxfbGluZSIsbGFiZWwgPSBULCBsYWJlbC5ib3ggPSBUKQpEaW1QbG90KEFsbF9zYW1wbGVzX01lcmdlZCwgcmVkdWN0aW9uID0gInVtYXAiLCBncm91cC5ieSA9ICJzZXVyYXRfY2x1c3RlcnMiLGxhYmVsID0gVCwgbGFiZWwuYm94ID0gVCkKCmBgYAoKCiNEaWZmZXJlbnRpYWwgRXhwcmVzc2lvbiBBbmFseXNpcwojIDMuIFBhaXJ3aXNlIENvbXBhcmlzb25zCmBgYHtyICwgZmlnLmhlaWdodD0xMiwgZmlnLndpZHRoPTE0fQpsaWJyYXJ5KFNldXJhdCkKbGlicmFyeShkcGx5cikKbGlicmFyeSh0aWJibGUpCmxpYnJhcnkoRW5oYW5jZWRWb2xjYW5vKQoKRGVmYXVsdEFzc2F5KEFsbF9zYW1wbGVzX01lcmdlZCkgPC0gIlJOQSIKCgpBbGxfc2FtcGxlc19NZXJnZWQgPC0gTm9ybWFsaXplRGF0YSgKICBBbGxfc2FtcGxlc19NZXJnZWQsIAogIGFzc2F5ID0gIlJOQSIsIAogIG5vcm1hbGl6YXRpb24ubWV0aG9kID0gIkxvZ05vcm1hbGl6ZSIsIAogIHNjYWxlLmZhY3RvciA9IDEwMDAwCikKCgojIEV4dHJhY3Qgbm9ybWFsaXplZCBleHByZXNzaW9uIHZhbHVlcyBmb3IgUk5BIGFzc2F5CmV4cHJlc3Npb25fZGF0YV9STkEgPC0gR2V0QXNzYXlEYXRhKEFsbF9zYW1wbGVzX01lcmdlZCwgYXNzYXkgPSAiUk5BIiwgc2xvdCA9ICJkYXRhIikgICMgUk5BLW5vcm1hbGl6ZWQgY291bnRzCgojIEZ1bmN0aW9uIHRvIGNhbGN1bGF0ZSBtZWFuIGV4cHJlc3Npb24gZm9yIHRoZSBzcGVjaWZpYyBjb21wYXJpc29uIGdyb3VwcwpjYWxjdWxhdGVfbWVhbl9leHByZXNzaW9uIDwtIGZ1bmN0aW9uKG1hcmtlcnMsIGlkZW50MV9jZWxscywgaWRlbnQyX2NlbGxzLCBleHByZXNzaW9uX2RhdGEpIHsKICBncm91cDFfbWVhbiA8LSByb3dNZWFucyhleHByZXNzaW9uX2RhdGFbLCBpZGVudDFfY2VsbHMsIGRyb3AgPSBGQUxTRV0sIG5hLnJtID0gVFJVRSkKICBncm91cDJfbWVhbiA8LSByb3dNZWFucyhleHByZXNzaW9uX2RhdGFbLCBpZGVudDJfY2VsbHMsIGRyb3AgPSBGQUxTRV0sIG5hLnJtID0gVFJVRSkKICAKICBtYXJrZXJzIDwtIG1hcmtlcnMgJT4lCiAgICByb3duYW1lc190b19jb2x1bW4oImdlbmUiKSAlPiUKICAgIG11dGF0ZShtZWFuX2V4cHJfaWRlbnQxID0gZ3JvdXAxX21lYW5bZ2VuZV0sCiAgICAgICAgICAgbWVhbl9leHByX2lkZW50MiA9IGdyb3VwMl9tZWFuW2dlbmVdKQogIAogIHJldHVybihtYXJrZXJzKQp9CgojIEZ1bmN0aW9uIHRvIHBlcmZvcm0gREUgYW5hbHlzaXMsIGNvbXB1dGUgbWVhbiBleHByZXNzaW9uLCBnZW5lcmF0ZSB2b2xjYW5vIHBsb3QsIGFuZCBzYXZlIHJlc3VsdHMKcGVyZm9ybV9jb21wYXJpc29uX2FuZF92b2xjYW5vIDwtIGZ1bmN0aW9uKEFsbF9zYW1wbGVzX01lcmdlZCwgaWRlbnQxLCBpZGVudDIsIGV4cHJlc3Npb25fZGF0YSkgewogIElkZW50cyhBbGxfc2FtcGxlc19NZXJnZWQpIDwtICJjZWxsX2xpbmUiCiAgCiAgIyBHZXQgY2VsbHMgYmVsb25naW5nIHRvIGVhY2ggaWRlbnRpdHkKICBpZGVudDFfY2VsbHMgPC0gV2hpY2hDZWxscyhBbGxfc2FtcGxlc19NZXJnZWQsIGlkZW50cyA9IGlkZW50MSkKICBpZGVudDJfY2VsbHMgPC0gV2hpY2hDZWxscyhBbGxfc2FtcGxlc19NZXJnZWQsIGlkZW50cyA9IGlkZW50MikKICAKICAjIFBlcmZvcm0gZGlmZmVyZW50aWFsIGV4cHJlc3Npb24gYW5hbHlzaXMgdXNpbmcgUk5BIGFzc2F5CiAgbWFya2VycyA8LSBGaW5kTWFya2VycyhBbGxfc2FtcGxlc19NZXJnZWQsIGlkZW50LjEgPSBpZGVudDEsIGlkZW50LjIgPSBpZGVudDIsIGFzc2F5ID0gIlJOQSIpCiAgCiAgIyBDb21wdXRlIG1lYW4gZXhwcmVzc2lvbiBmb3IgdGhlIHR3byBjb21wYXJlZCBncm91cHMgdXNpbmcgUk5BLW5vcm1hbGl6ZWQgY291bnRzCiAgbWFya2Vyc193aXRoX21lYW4gPC0gY2FsY3VsYXRlX21lYW5fZXhwcmVzc2lvbihtYXJrZXJzLCBpZGVudDFfY2VsbHMsIGlkZW50Ml9jZWxscywgZXhwcmVzc2lvbl9kYXRhKQogIAogICMgU2F2ZSByZXN1bHRzIHRvIENTVgogIG91dHB1dF9maWxlbmFtZSA8LSBwYXN0ZTAoImNvbXBhcmlzb25fIiwgaWRlbnQxLCAiX3ZzXyIsIGlkZW50MiwgIl93aXRoX21lYW5fZXhwcmVzc2lvbi5jc3YiKQogIHdyaXRlLmNzdihtYXJrZXJzX3dpdGhfbWVhbiwgZmlsZSA9IG91dHB1dF9maWxlbmFtZSwgcm93Lm5hbWVzID0gRkFMU0UpCiAgCiAgIyBDcmVhdGUgdm9sY2FubyBwbG90CiAgdm9sY2Fub19wbG90IDwtIEVuaGFuY2VkVm9sY2FubyhtYXJrZXJzX3dpdGhfbWVhbiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYiA9IG1hcmtlcnNfd2l0aF9tZWFuJGdlbmUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB4ID0gJ2F2Z19sb2cyRkMnLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeSA9ICdwX3ZhbF9hZGonLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGl0bGUgPSBwYXN0ZShpZGVudDEsICd2cycsIGlkZW50MiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwQ3V0b2ZmID0gMC4wNSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEZDY3V0b2ZmID0gMSkKICAKICBwcmludCh2b2xjYW5vX3Bsb3QpCiAgcG5nKHBhc3RlMCgidm9sY2Fub18iLCBpZGVudDEsICJfdnNfIiwgaWRlbnQyLCAiLnBuZyIpLCB3aWR0aCA9IDEyLCBoZWlnaHQgPSAxMCwgdW5pdHMgPSAiaW4iLCByZXMgPSAzMDApCiAgcHJpbnQodm9sY2Fub19wbG90KQogIGRldi5vZmYoKQogIAogIHJldHVybihtYXJrZXJzX3dpdGhfbWVhbikKfQoKIyBQZXJmb3JtIGNvbXBhcmlzb25zIGR5bmFtaWNhbGx5IGZvciBlYWNoIGNlbGwgbGluZSBwYWlyCnAxX2NvbXBhcmlzb24gPC0gcGVyZm9ybV9jb21wYXJpc29uX2FuZF92b2xjYW5vKEFsbF9zYW1wbGVzX01lcmdlZCwgIkwxIiwgIkwyIiwgZXhwcmVzc2lvbl9kYXRhX1JOQSkKcDJfY29tcGFyaXNvbiA8LSBwZXJmb3JtX2NvbXBhcmlzb25fYW5kX3ZvbGNhbm8oQWxsX3NhbXBsZXNfTWVyZ2VkLCAiTDMiLCAiTDQiLCBleHByZXNzaW9uX2RhdGFfUk5BKQpwM19jb21wYXJpc29uX0w1TDYgPC0gcGVyZm9ybV9jb21wYXJpc29uX2FuZF92b2xjYW5vKEFsbF9zYW1wbGVzX01lcmdlZCwgIkw1IiwgIkw2IiwgZXhwcmVzc2lvbl9kYXRhX1JOQSkKcDNfY29tcGFyaXNvbl9MNUw3IDwtIHBlcmZvcm1fY29tcGFyaXNvbl9hbmRfdm9sY2FubyhBbGxfc2FtcGxlc19NZXJnZWQsICJMNSIsICJMNyIsIGV4cHJlc3Npb25fZGF0YV9STkEpCnAzX2NvbXBhcmlzb25fTDZMNyA8LSBwZXJmb3JtX2NvbXBhcmlzb25fYW5kX3ZvbGNhbm8oQWxsX3NhbXBsZXNfTWVyZ2VkLCAiTDYiLCAiTDciLCBleHByZXNzaW9uX2RhdGFfUk5BKQoKIyBQcmludCB0aGUgZmlyc3QgZmV3IHJvd3Mgb2YgZWFjaCByZXN1bHQKaGVhZChwMV9jb21wYXJpc29uKQpoZWFkKHAyX2NvbXBhcmlzb24pCmhlYWQocDNfY29tcGFyaXNvbl9MNUw2KQpoZWFkKHAzX2NvbXBhcmlzb25fTDVMNykKaGVhZChwM19jb21wYXJpc29uX0w2TDcpCmBgYAojIDQuIFBhaXJ3aXNlIENvbXBhcmlzb25zIEZpbHRlcmluZyAKYGBge3IgLCBmaWcuaGVpZ2h0PTgsIGZpZy53aWR0aD0xMn0KbGlicmFyeShkcGx5cikKCiMgRnVuY3Rpb24gdG8gc3VtbWFyaXplIERFIG1hcmtlcnMKc3VtbWFyaXplX21hcmtlcnMgPC0gZnVuY3Rpb24obWFya2VycywgY29tcGFyaXNvbl9uYW1lKSB7CiAgbnVtX3B2YWwwIDwtIHN1bShtYXJrZXJzJHBfdmFsX2FkaiA9PSAwKQogIG51bV9wdmFsMSA8LSBzdW0obWFya2VycyRwX3ZhbF9hZGogPT0gMSkKICBudW1fc2lnbmlmaWNhbnQgPC0gc3VtKG1hcmtlcnMkcF92YWxfYWRqIDwgMC4wNSkKICBudW1fdXByZWd1bGF0ZWQgPC0gc3VtKG1hcmtlcnMkYXZnX2xvZzJGQyA+IDEpCiAgbnVtX2Rvd25yZWd1bGF0ZWQgPC0gc3VtKG1hcmtlcnMkYXZnX2xvZzJGQyA8IC0xKQogIAogIGNhdCgiXG5TdW1tYXJ5IGZvciIsIGNvbXBhcmlzb25fbmFtZSwgIjpcbiIpCiAgY2F0KCJOdW1iZXIgb2YgZ2VuZXMgd2l0aCBwX3ZhbF9hZGogPSAwOiIsIG51bV9wdmFsMCwgIlxuIikKICBjYXQoIk51bWJlciBvZiBnZW5lcyB3aXRoIHBfdmFsX2FkaiA9IDE6IiwgbnVtX3B2YWwxLCAiXG4iKQogIGNhdCgiTnVtYmVyIG9mIHNpZ25pZmljYW50IGdlbmVzIChwX3ZhbF9hZGogPCAwLjA1KToiLCBudW1fc2lnbmlmaWNhbnQsICJcbiIpCiAgY2F0KCJOdW1iZXIgb2YgdXByZWd1bGF0ZWQgZ2VuZXMgKGF2Z19sb2cyRkMgPiAxKToiLCBudW1fdXByZWd1bGF0ZWQsICJcbiIpCiAgY2F0KCJOdW1iZXIgb2YgZG93bnJlZ3VsYXRlZCBnZW5lcyAoYXZnX2xvZzJGQyA8IC0xKToiLCBudW1fZG93bnJlZ3VsYXRlZCwgIlxuIikKfQoKIyBGdW5jdGlvbiB0byBmaWx0ZXIgREUgbWFya2VycyBhbmQgc2F2ZSByZXN1bHRzCmZpbHRlcl9hbmRfc2F2ZSA8LSBmdW5jdGlvbihtYXJrZXJzLCBpZGVudDEsIGlkZW50MikgewogIGNvbXBhcmlzb25fbmFtZSA8LSBwYXN0ZShpZGVudDEsICJ2cyIsIGlkZW50MikKICAKICAjIFN1bW1hcnkgYmVmb3JlIGZpbHRlcmluZwogIHN1bW1hcml6ZV9tYXJrZXJzKG1hcmtlcnMsIGNvbXBhcmlzb25fbmFtZSkKICAKICAjIEFwcGx5IHRoZSBleHByZXNzaW9uIGZpbHRlcgogIG1hcmtlcnNfZmlsdGVyZWQgPC0gbWFya2VycyAlPiUKICAgIGZpbHRlcighKG1lYW5fZXhwcl9pZGVudDEgPCAwLjIgJiBtZWFuX2V4cHJfaWRlbnQyIDwgMC4yKSkKCiAgIyBTYXZlIGZpbHRlcmVkIHJlc3VsdHMKICBvdXRwdXRfZmlsZW5hbWUgPC0gcGFzdGUwKCJjb21wYXJpc29uXyIsIGlkZW50MSwgIl92c18iLCBpZGVudDIsICJfd2l0aF9tZWFuX2V4cHJlc3Npb25fZmlsdGVyZWQuY3N2IikKICB3cml0ZS5jc3YobWFya2Vyc19maWx0ZXJlZCwgZmlsZSA9IG91dHB1dF9maWxlbmFtZSwgcm93Lm5hbWVzID0gRkFMU0UpCiAgCiAgY2F0KCJGaWx0ZXJlZCByZXN1bHRzIHNhdmVkIHRvOiIsIG91dHB1dF9maWxlbmFtZSwgIlxuIikKICAKICByZXR1cm4obWFya2Vyc19maWx0ZXJlZCkKfQoKIyBBcHBseSB0aGUgZnVuY3Rpb24gdG8gYWxsIGNvbXBhcmlzb25zCnAxX2ZpbHRlcmVkIDwtIGZpbHRlcl9hbmRfc2F2ZShwMV9jb21wYXJpc29uLCAiTDEiLCAiTDIiKQpwMl9maWx0ZXJlZCA8LSBmaWx0ZXJfYW5kX3NhdmUocDJfY29tcGFyaXNvbiwgIkwzIiwgIkw0IikKcDNfZmlsdGVyZWRfTDVMNiA8LSBmaWx0ZXJfYW5kX3NhdmUocDNfY29tcGFyaXNvbl9MNUw2LCAiTDUiLCAiTDYiKQpwM19maWx0ZXJlZF9MNUw3IDwtIGZpbHRlcl9hbmRfc2F2ZShwM19jb21wYXJpc29uX0w1TDcsICJMNSIsICJMNyIpCnAzX2ZpbHRlcmVkX0w2TDcgPC0gZmlsdGVyX2FuZF9zYXZlKHAzX2NvbXBhcmlzb25fTDZMNywgIkw2IiwgIkw3IikKCgoKYGBgCgo=