## ----setup, include = FALSE---------------------------------------------------
knitr::opts_chunk$set(collapse = TRUE, comment = "#>", warning = FALSE,
                      message = FALSE)

## ----install, eval = FALSE----------------------------------------------------
# if (!requireNamespace("BiocManager", quietly = TRUE))
#     install.packages("BiocManager")
# BiocManager::install("quantMSImageR")

## ----quickstart, eval = FALSE-------------------------------------------------
# library(quantMSImageR)
# res <- runExample()          # both groups; imaging report + calibration demo
# res$calibrated                # the calibrated object

## ----data-model---------------------------------------------------------------
library(quantMSImageR)

p   <- system.file("extdata", "example.raw", "section01.RDS",
                   package = "quantMSImageR")
obj <- as(readRDS(p), "quant_MSImagingExperiment")

dim(obj)                        # features x pixels
names(spectraData(obj))         # available layers

## ----data-model-fdata---------------------------------------------------------
DT::datatable(as.data.frame(fData(obj)), rownames = FALSE,
              options = list(pageLength = 5, scrollX = TRUE))

## ----data-model-pdata---------------------------------------------------------
DT::datatable(head(as.data.frame(pData(obj)), 100), rownames = FALSE,
              options = list(pageLength = 5, scrollX = TRUE))

## ----read-mrm, eval = FALSE---------------------------------------------------
# obj <- readMRM(
#   name         = "my_acquisition",        # .raw folder name, without the suffix
#   folder       = "path/to/raw",           # directory containing my_acquisition.raw
#   lib_ion_path = "path/to/ion_library.csv"
# )

## ----bind-panels, eval = FALSE------------------------------------------------
# pos <- readMRM("acq_section1_pos", folder = "path/to/raw",
#                 lib_ion_path = "path/to/ion_library.csv")
# neg <- readMRM("acq_section1_neg", folder = "path/to/raw",
#                 lib_ion_path = "path/to/ion_library.csv")
# 
# # Pixels are matched on (x, y), so the two runs need not have identical grids;
# # pixels present in only one are dropped.
# both <- bindPanels(pos, neg, label = "S1")

## ----load---------------------------------------------------------------------
library(quantMSImageR)
library(ggplot2)

sections <- sprintf("section%02d", 1:6)
objs <- lapply(sections, function(s)
  readRDS(system.file("extdata", "example.raw", paste0(s, ".RDS"),
                      package = "quantMSImageR")))
combined <- do.call(combineMSIs, objs)

groups <- c("A", "A", "A", "B", "B", "B")   # sections 01-03 = A, 04-06 = B
combined

## ----load-check---------------------------------------------------------------
dim(combined)                       # features x (pixels from all six sections)
table(pData(combined)$run)

## ----select, eval = FALSE-----------------------------------------------------
# selectTissuePixels(
#   name         = "my_acquisition",          # .raw folder name (no suffix)
#   data_path    = "path/to/raw",
#   lib_ion_path = "path/to/ion_library.csv"
# )

## ----mask-table---------------------------------------------------------------
mask_tbl <- as.data.frame(pData(combined))[, c("run", "x", "y", "sample_name")]

DT::datatable(head(mask_tbl, 500), rownames = FALSE,
              options = list(pageLength = 5, scrollX = TRUE))

## ----mask-plot, fig.wide = TRUE, fig.cap = "Tissue masks for all six sections. Green pixels are labelled tissue_pixels and contribute to every downstream summary; grey pixels are background_pixels and are used to estimate the noise level in int2SNR()."----
ggplot(mask_tbl, aes(x, -y, fill = sample_name)) +
  geom_tile() +
  facet_wrap(~ run, ncol = 3) +
  coord_equal() +
  scale_fill_manual(values = c(tissue_pixels     = "#1b7837",
                               background_pixels = "grey85")) +
  labs(x = NULL, y = NULL, fill = NULL) +
  theme_minimal() +
  theme(axis.text = element_blank(), panel.grid = element_blank(),
        strip.text = element_text(size = 7),
        legend.text = element_text(size = 7))

## ----palettes-----------------------------------------------------------------
names(quantPalettes())
quantPalettes("heatmap0")

## ----image, fig.wide = TRUE, fig.cap = "Ion image of the first feature across all six sections, before SNR filtering. Sections 01-03 are group A (circular tissue), 04-06 are group B (square)."----
imageR(combined, feat_ind = 1, sample_lab = "run", scale = "suppress",
       palette = "heatmap0") +
  facet_wrap(~ sample, ncol = 3) +
  theme(strip.text = element_text(size = 7),
        legend.text = element_text(size = 7))

## ----image-scales, fig.wide = TRUE, fig.height = 3, fig.cap = "The same feature and section under the three colour-scale treatments. Only `suppress` keeps the colour scale linear in response; the others trade that for visible structure."----
.one <- combined[, pData(combined)$run == "section01"]
.p <- lapply(c("suppress", "histogram", "sqrt"), function(sc)
  imageR(.one, feat_ind = 1, sample_lab = "run", scale = sc) +
    labs(title = sc) +
    theme(legend.position = "none",
          plot.title = element_text(size = 9, face = "bold"),
          strip.text = element_blank()))
patchwork::wrap_plots(.p, nrow = 1)

## ----ion-lib------------------------------------------------------------------
lib <- read.csv(system.file("extdata", "example_ion_library.csv",
                            package = "quantMSImageR"), check.names = FALSE)

DT::datatable(lib, rownames = FALSE,
              options = list(pageLength = 10, scrollX = TRUE))

## ----meta---------------------------------------------------------------------
fm <- buildFeatureMeta(combined, lib)

DT::datatable(fm[, c("name", "precursor_mz", "product_mz", "Type", "Met-1",
                     "IS_norm")],
              rownames = FALSE,
              options = list(pageLength = 10, scrollX = TRUE))

## ----heatmap-median, fig.wide = TRUE, fig.cap = "Median (50th percentile) feature intensity per section. Rows are sections grouped by study group; columns are features split by Met-1 class."----
feature_split <- fm[["Met-1"]]

quantileHm(combined, quant_val = 0.5,
            heatmap_order = sections, heatmap_labs = groups,
            feature_split = feature_split, feature_split_name = "Met-1",
            cell_size = 10, fontsize = 7)

## ----heatmap-95, fig.wide = TRUE, fig.cap = "The same summary at the 95th percentile, which emphasises hot-spots rather than the bulk of the tissue."----
quantileHm(combined, quant_val = 0.95,
            heatmap_order = sections, heatmap_labs = groups,
            feature_split = feature_split, feature_split_name = "Met-1",
            cell_size = 10, fontsize = 7)

## ----heatmap-contribution, fig.wide = TRUE, fig.cap = "The same median summary as a group mean, with each sample's contribution to that mean drawn as opacity. A solid block is a group effect; a lone opaque tile is a mean resting on one section."----
contributionHm(combined, quant_val = 0.5,
                heatmap_order = sections, heatmap_labs = groups,
                feature_split = feature_split, feature_split_name = "Met-1",
                cell_size = 10, fontsize = 7)

## ----snr-apply----------------------------------------------------------------
combined <- int2SNR(combined, val_slot = "intensity", snr_thresh = 3)
combined <- applySNR(combined, val_slot = "intensity")

## ----snr-check----------------------------------------------------------------
names(spectraData(combined))                            # snr layer added
mean(is.na(spectra(combined, "intensity"))) |> round(3) # fraction now masked

## ----snr-after, fig.wide = TRUE, fig.cap = "The same feature after applySNR(). Sub-threshold pixels are now NA, so the low-signal background has been removed and only tissue signal remains (compare to previous ion images)."----
imageR(combined, feat_ind = 1, sample_lab = "run", val_slot = "intensity",
       scale = "suppress") +
  facet_wrap(~ sample, ncol = 3) +
  theme(strip.text = element_text(size = 7),
        legend.text = element_text(size = 7))

## ----yaml-template, eval = FALSE----------------------------------------------
# file.show(system.file("config_template.yaml", package = "quantMSImageR"))

## ----run-study, eval = FALSE--------------------------------------------------
# runStudy("path/to/study_config.yaml")

## ----validate, eval = FALSE---------------------------------------------------
# validateConfig("path/to/study_config.yaml")

## ----session------------------------------------------------------------------
sessionInfo()

