Introduction

  1. File (path to *sis)
  2. ImageSet (image batch *czi)
  3. ROI (blank)
  4. Type (Segment)
  5. fmito (Mito Child, Nucleus Child, PV1 child, RBC, RBC area Filter, RBC segmented, Touching Edge Filter RBC)
  6. Image Set
  7. Id (C3, Field P1 - Experiment-161.czi)
  8. Name (Segment #001 (RBC segmented))
  9. Position, Well (well C3, C4)
  10. Field, Well
  11. Area, 2D Oriented Bounds (µm²)
  12. no. Children
  13. Children Ids
  14. Children Names
  15. Parent Ids
  16. Parent Names
  17. Min, Intensities #1
  18. Max, Intensities #1
  19. Mean, Intensities #1
  20. Sum, Intensities #1
  21. SD, Intensities #1
  22. SNR (Mean/SD), Intensities #1
  23. Min, Intensities #2
  24. Max, Intensities #2
  25. Mean, Intensities #2
  26. Sum, Intensities #2
  27. SD, Intensities #2
  28. SNR (Mean/SD), Intensities #2
  29. Min, Intensities #3
  30. Max, Intensities #3
  31. Mean, Intensities #3
  32. Sum, Intensities #3
  33. SD, Intensities #3
  34. SNR (Mean/SD), Intensities #3
  35. Min, Intensities #4
  36. Max, Intensities #4
  37. Mean, Intensities #4
  38. Sum, Intensities #4
  39. SD, Intensities #4
  40. SNR (Mean/SD), Intensities #4

fmito entries (E3):

  • iRBC filter (child only), Mito Child, Nucleus Child, PV1 child, RBC, RBC area Filter, RBC segmented, Touching Edge Filter RBC (512)
  • Mito Child, Nucleus Child, PV1 child, RBC, RBC area Filter, RBC segmented, Touching Edge Filter RBC (1440)
  • Mito, Mito Child, Mito Segmenter, Mito size filter, Mito within RBC (594)
  • Nuclei, Nuclei Segmenter, Nucleus Child, Nucleus size filter, Nucleus within RBC (421)
  • PV1, PV1 child, PV1 Segmenter, PV1 size filter, PV1 within RBC, PV1 within RBC inside (521)
  • PV1, PV1 child, PV1 Segmenter, PV1 size filter, PV1 within RBC, PV1 within RBC intersecting (49)

The desired format is:

  1. Treatment group (Well C3,D3)
  2. RBC area um^2 (#1, mean)
  3. RBC count (number of entries with (#1, no. entries)
  4. iRBC area um^2 (#2, mean)
  5. iRBC count (#2, no. entries)
  6. PV1 area um^2 (#2, mean)
  7. PV1 intensity RLU (#2, mean)
  8. PV1 count (#2, no. entries)
  9. Mitochondria area um^2 (#3)
  10. Mitochondria intensity RLU (#3)
  11. Mitochondria count (#3)
  12. Nucleus area um^2 (#4)
  13. Nucleus intensity RLU (#4)
  14. Nucleus count (#4)
library("kableExtra")
library("DT")

Example with well C3

x <- read.csv("oliver_test_data.tsv",header=TRUE,sep="\t")

myt <- as.data.frame(table(x$fmito) )

myt |> kbl(caption="Frequency of features across all wells") |> kable_paper("hover", full_width = F)
Frequency of features across all wells
Var1 Freq
iRBC filter (child only), Mito Child, Nucleus Child, PV1 child, RBC, RBC area Filter, RBC segmented, Touching Edge Filter RBC 12449
Mito Child, Nucleus Child, PV1 child, RBC, RBC area Filter, RBC segmented, Touching Edge Filter RBC 37639
Mito, Mito Child, Mito Segmenter, Mito size filter, Mito within RBC 14331
Nuclei, Nuclei Segmenter, Nucleus Child, Nucleus size filter, Nucleus within RBC 10193
PV1, PV1 child, PV1 Segmenter, PV1 size filter, PV1 within RBC, PV1 within RBC inside 12422
PV1, PV1 child, PV1 Segmenter, PV1 size filter, PV1 within RBC, PV1 within RBC intersecting 1135
WELL="C3"
y <- subset(x,Position..Well==WELL)

myt <- table(y$fmito)

myt |> kbl(caption="Frequency of features in well C3") |> kable_paper("hover", full_width = F)
Frequency of features in well C3
Var1 Freq
iRBC filter (child only), Mito Child, Nucleus Child, PV1 child, RBC, RBC area Filter, RBC segmented, Touching Edge Filter RBC 512
Mito Child, Nucleus Child, PV1 child, RBC, RBC area Filter, RBC segmented, Touching Edge Filter RBC 1440
Mito, Mito Child, Mito Segmenter, Mito size filter, Mito within RBC 594
Nuclei, Nuclei Segmenter, Nucleus Child, Nucleus size filter, Nucleus within RBC 421
PV1, PV1 child, PV1 Segmenter, PV1 size filter, PV1 within RBC, PV1 within RBC inside 521
PV1, PV1 child, PV1 Segmenter, PV1 size filter, PV1 within RBC, PV1 within RBC intersecting 49
# here is the important code for one well (C3)
rbc <- y[which(y$Parent.Names==""),]
RBC_count <- nrow(rbc)
RBC_area <- mean(rbc$Area..2D.Oriented.Bounds...µm...)
irbc <- subset(y,fmito=="iRBC filter (child only), Mito Child, Nucleus Child, PV1 child, RBC, RBC area Filter, RBC segmented, Touching Edge Filter RBC")
iRBC_count <- nrow(irbc)
iRBC_area <- mean(irbc$Area..2D.Oriented.Bounds...µm...)
pv1 <- subset(y, fmito == "PV1, PV1 child, PV1 Segmenter, PV1 size filter, PV1 within RBC, PV1 within RBC inside" | fmito =="PV1, PV1 child, PV1 Segmenter, PV1 size filter, PV1 within RBC, PV1 within RBC intersecting" )
PV1_area <- mean(pv1$Area..2D.Oriented.Bounds...µm...)
PV1_intensity <- mean(pv1$Mean..Intensities..2)
PV1_count <- nrow(pv1)
mito <- subset(y, fmito == "Mito, Mito Child, Mito Segmenter, Mito size filter, Mito within RBC")
Mito_area <- mean(mito$Area..2D.Oriented.Bounds...µm...)
Mito_intensity <- mean(mito$Mean..Intensities..1)
Mito_count <- nrow(mito)
nucleus <- subset(y, fmito == "Nuclei, Nuclei Segmenter, Nucleus Child, Nucleus size filter, Nucleus within RBC")
Nucleus_area <- mean(nucleus$Area..2D.Oriented.Bounds...µm...)
Nucleus_intensity <- mean(nucleus$Mean..Intensities..3)
Nucleus_count <- nrow(nucleus)

res <- c("RBC count"=RBC_count,
  "RBC area"=RBC_area,
  "iRBC count"=iRBC_count,
  "iRBC area"=iRBC_area,
  "PV1_area"=PV1_area,
  "PV1_intensity"=PV1_intensity,
  "PV1_count"=PV1_count,
  "Mito_area"=Mito_area,
  "Mito_intensity"=Mito_intensity,
  "Mito_count"=Mito_count,
  "Nucleus_area"=Nucleus_area,
  "Nucleus_intensity"=Nucleus_intensity,
  "Nucleus_count"=Nucleus_count)

res
##         RBC count          RBC area        iRBC count         iRBC area 
##       1952.000000         64.551561        512.000000         61.146490 
##          PV1_area     PV1_intensity         PV1_count         Mito_area 
##         10.693673       5097.183027        570.000000          7.618147 
##    Mito_intensity        Mito_count      Nucleus_area Nucleus_intensity 
##       4247.137581        594.000000          4.976730       5143.493189 
##     Nucleus_count 
##        421.000000
WELLS <- unique(x$Position..Well)

Make a function and run for all wells

Now put it in a function so we can iterate over all wells.

# define the function
smry <- function(y) {
  rbc <- y[which(y$Parent.Names==""),]
  RBC_count <- nrow(rbc)
  RBC_area <- mean(rbc$Area..2D.Oriented.Bounds...µm...)
  irbc <- subset(y,fmito=="iRBC filter (child only), Mito Child, Nucleus Child, PV1 child, RBC, RBC area Filter, RBC segmented, Touching Edge Filter RBC")
  iRBC_count <- nrow(irbc)
  iRBC_area <- mean(irbc$Area..2D.Oriented.Bounds...µm...)
  pv1 <- subset(y, fmito == "PV1, PV1 child, PV1 Segmenter, PV1 size filter, PV1 within RBC, PV1 within RBC inside" | fmito =="PV1, PV1 child, PV1 Segmenter, PV1 size filter, PV1 within RBC, PV1 within RBC intersecting" )
  PV1_area <- mean(pv1$Area..2D.Oriented.Bounds...µm...)
  PV1_intensity <- mean(pv1$Mean..Intensities..2)
  PV1_count <- nrow(pv1)
  mito <- subset(y, fmito == "Mito, Mito Child, Mito Segmenter, Mito size filter, Mito within RBC")
  Mito_area <- mean(mito$Area..2D.Oriented.Bounds...µm...)
  Mito_intensity <- mean(mito$Mean..Intensities..1)
  Mito_count <- nrow(mito)
  nucleus <- subset(y, fmito == "Nuclei, Nuclei Segmenter, Nucleus Child, Nucleus size filter, Nucleus within RBC")
  Nucleus_area <- mean(nucleus$Area..2D.Oriented.Bounds...µm...)
  Nucleus_intensity <- mean(nucleus$Mean..Intensities..3)
  Nucleus_count <- nrow(nucleus)

  res <- c("RBC count"=RBC_count,
    "RBC area"=RBC_area,
    "iRBC count"=iRBC_count,
    "iRBC area"=iRBC_area,
    "PV1_area"=PV1_area,
    "PV1_intensity"=PV1_intensity,
    "PV1_count"=PV1_count,
    "Mito_area"=Mito_area,
    "Mito_intensity"=Mito_intensity,
    "Mito_count"=Mito_count,
    "Nucleus_area"=Nucleus_area,
    "Nucleus_intensity"=Nucleus_intensity,
    "Nucleus_count"=Nucleus_count)

  res
}

# get a vector of all wells
WELLS <- unique(x$Position..Well)

# now run the function for all wells
z <- lapply(WELLS, function(w) {
  y <- subset(x,Position..Well==w)
  smry(y)
} )

# z is a list of vectors, which we can convert to a matrix
z <- do.call(rbind,z)
rownames(z) <- WELLS
# peek at the ddata format
head(z,2)
##    RBC count RBC area iRBC count iRBC area PV1_area PV1_intensity PV1_count
## C3      1952 64.55156        512  61.14649 10.69367      5097.183       570
## C4      2227 64.60427        577  61.01230 10.43024      5899.082       637
##    Mito_area Mito_intensity Mito_count Nucleus_area Nucleus_intensity
## C3  7.618147       4247.138        594     4.976730          5143.493
## C4  7.712100       4445.221        662     4.763474          5189.557
##    Nucleus_count
## C3           421
## C4           472

Show the data as a kableExtra table.

z |> kbl(caption="Summarised data by well") |> kable_paper("hover", full_width = F)
Summarised data by well
RBC count RBC area iRBC count iRBC area PV1_area PV1_intensity PV1_count Mito_area Mito_intensity Mito_count Nucleus_area Nucleus_intensity Nucleus_count
C3 1952 64.55156 512 61.14649 10.693673 5097.183 570 7.618147 4247.138 594 4.976730 5143.493 421
C4 2227 64.60427 577 61.01230 10.430245 5899.082 637 7.712100 4445.221 662 4.763474 5189.557 472
C5 2261 64.33012 561 60.48136 10.097040 5793.136 619 7.488116 4277.949 646 4.599478 5007.931 478
C6 2322 63.98964 582 60.35993 10.346849 5781.102 644 7.595071 4174.015 690 4.886240 5235.380 479
C7 2072 64.21877 529 61.44124 9.144504 5593.618 579 5.886563 2359.781 617 4.205364 4996.555 433
C8 2242 62.07106 609 59.43098 10.455854 5829.638 667 7.329269 3509.225 683 4.249529 5294.991 528
C9 1985 63.65847 525 60.95739 10.060376 5768.832 576 6.788316 3101.107 620 4.595539 5273.504 436
C10 2099 61.98346 525 59.86089 10.636563 5864.385 563 7.503530 3467.763 583 4.834560 5103.976 440
D10 1966 62.89270 517 60.58253 8.458539 6906.092 571 6.546429 2841.230 579 4.904023 4986.232 392
D9 2015 63.68069 455 61.48634 9.527112 5389.428 508 6.553710 2712.983 554 4.802154 4562.559 400
D8 1953 62.90741 515 61.16515 10.506702 5858.268 584 7.320431 3509.489 629 4.740049 4796.523 470
D7 2003 62.85836 498 60.43396 8.889386 5652.899 532 5.195398 1258.581 514 3.953006 3967.657 403
D6 1907 63.84892 491 61.15527 10.924333 5847.784 526 7.117806 2916.189 555 4.537111 4767.919 408
D5 2180 63.52832 572 60.80384 10.536259 5944.877 620 7.351318 3222.293 661 4.595413 4767.129 490
D4 1927 63.54403 463 60.88463 10.700550 5866.457 501 7.330652 3004.190 522 4.694505 4940.218 397
D3 1975 62.83318 478 59.81675 8.412840 4690.740 535 5.605180 1706.638 533 3.844165 3540.236 275
E3 1847 64.74527 456 62.42482 6.113163 6223.997 492 3.634959 1739.665 505 4.009939 5135.462 369
E4 1927 64.80283 452 62.99633 9.704202 5911.293 473 6.139468 1905.633 585 5.362923 5324.734 279
E5 1722 65.53842 433 63.12797 10.151727 5873.605 470 6.684500 2521.291 482 3.389333 3319.673 418
E6 2009 64.60793 466 62.98430 9.180280 5935.371 501 5.787044 1762.050 537 4.323832 4731.645 374
E7 1795 63.21864 412 62.14004 8.661620 6120.790 441 5.521780 1873.815 483 4.249830 5243.697 363
E8 1933 63.16007 481 61.50979 9.647022 6132.141 513 6.455526 2029.555 512 4.396398 4900.484 382
E9 2007 63.87617 476 62.25220 9.419651 6024.532 501 6.159465 1971.045 610 4.694328 4755.309 380
E10 1739 63.92836 418 62.58780 9.407335 5834.904 452 5.335990 1487.146 455 4.164987 5131.638 322
E11 2023 58.71564 446 60.04436 8.984136 6109.175 482 6.325914 2309.390 520 4.523514 5070.129 384

Show as data.table. This function allows you to download as an Excel file.

DT::datatable(
  { head(z,1000) },

  extensions = 'Buttons',
  filter = list(position = 'top', clear = FALSE),

  options = list(
    paging = TRUE,
    searching = TRUE,
    fixedColumns = TRUE,
    autoWidth = TRUE,
    ordering = TRUE,
    dom = 'tB',
    buttons = c('copy', 'csv', 'excel'),
    pageLength = 50,
    search = list(regex = TRUE, caseInsensitive = TRUE)),

  rownames= TRUE)

Principal component analysis

pca <- prcomp(z, scale=TRUE)

scree <- pca$sdev
names(scree) <- 1:length(scree)
barplot(scree, main="Screeplot")

biplot(pca, main="PCA")

More variations on biplot clusstering here: https://www.geeksforgeeks.org/how-to-create-a-biplot-in-r/

Session information

For reproucibility

sessionInfo()
## R version 4.5.0 (2025-04-11)
## Platform: x86_64-pc-linux-gnu
## Running under: Ubuntu 22.04.5 LTS
## 
## Matrix products: default
## BLAS:   /usr/lib/x86_64-linux-gnu/blas/libblas.so.3.10.0 
## LAPACK: /usr/lib/x86_64-linux-gnu/lapack/liblapack.so.3.10.0  LAPACK version 3.10.0
## 
## locale:
##  [1] LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C              
##  [3] LC_TIME=en_US.UTF-8        LC_COLLATE=en_US.UTF-8    
##  [5] LC_MONETARY=en_US.UTF-8    LC_MESSAGES=en_US.UTF-8   
##  [7] LC_PAPER=en_US.UTF-8       LC_NAME=C                 
##  [9] LC_ADDRESS=C               LC_TELEPHONE=C            
## [11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C       
## 
## time zone: Australia/Melbourne
## tzcode source: system (glibc)
## 
## attached base packages:
## [1] stats     graphics  grDevices utils     datasets  methods   base     
## 
## other attached packages:
## [1] DT_0.33          kableExtra_1.4.0
## 
## loaded via a namespace (and not attached):
##  [1] vctrs_0.6.5        svglite_2.1.3      cli_3.6.5          knitr_1.50        
##  [5] rlang_1.1.6        xfun_0.52          stringi_1.8.7      jsonlite_2.0.0    
##  [9] glue_1.8.0         htmltools_0.5.8.1  sass_0.4.10        scales_1.4.0      
## [13] rmarkdown_2.29     crosstalk_1.2.1    jquerylib_0.1.4    evaluate_1.0.3    
## [17] fastmap_1.2.0      yaml_2.3.10        lifecycle_1.0.4    stringr_1.5.1     
## [21] compiler_4.5.0     RColorBrewer_1.1-3 htmlwidgets_1.6.4  rstudioapi_0.17.1 
## [25] systemfonts_1.2.2  farver_2.1.2       digest_0.6.37      viridisLite_0.4.2 
## [29] R6_2.6.1           dichromat_2.0-0.1  pillar_1.10.2      magrittr_2.0.3    
## [33] bslib_0.9.0        tools_4.5.0        cachem_1.1.0       xml2_1.3.8