Author: Audrey Kauffmann, Wolfgang Huber
Date: 2026-04-28

# Advanced topics: Customizing arrayQualityMetrics reports and programmatic processing of the output

Audrey Kauffmann, Wolfgang Huber

#### 28 April 2026

# Contents

## 0.1 Introduction

If you are new to this package, then please consult the vignette Introduction: microarray quality assessment with arrayQualityMetrics.

This vignette addresses advanced topics. It explains how to customize the report by selecting specific modules and sections, or by adding your own ones. Furthermore, we will see how to (programmatically) postprocess the results of the outlier detection, or how to adapt the detection criteria to your needs.

Terminology: In the documentation of this package, we refer to a module as a self-contained element of a report that investigates one particular quality metric. A module consists of a figure and an explanatory text. It may also contain a data structure (an object of class `outlierDetection`) that marks a subset of the arrays in the dataset as outliers according to the particular metric investigated in the module. We refer to a section as a collection of one or more modules that are thematically related.

For the following examples, let us load the needed packages and some data.

    library("arrayQualityMetrics")
    library("ALLMLL")
    data("MLL.A")

## 0.2 Data preparation

Some of the computations that are needed for the modules are common between several modules, and thus we perform them once, beforehand. These functions are called `prepdata()` and `prepaffy()`, and we refer to their manual page for details. For example,

    preparedData = prepdata(expressionset = MLL.A,
                            intgroup = c(),
                            do.logtransform = TRUE)

The arguments `intgroup` and `do.logtransform` are the same as for `arrayQualityMetrics()`, but in `prepdata()` they have no defaults, so we need to set them explicitely.

## 0.3 Module generating functions

The package contains a variety of functions that compute modules, and they are listed on a manual page which you can access by typing:

    ?aqm.boxplot

Here, let us create a report with only two quality metrics modules: boxplots and density plots.

    bo = aqm.boxplot(preparedData)
    de = aqm.density(preparedData)
    qm = list("Boxplot" = bo, "Density" = de)

The objects `bo` and `de` are of class `aqmReportModule`; please consult the class’ manual page for more information.

If you want to create your own modules, please have a look at the code for the various existing functions for this purpose, and adapt it. The function `aqm.pca()` is a good place to start.

## 0.4 Outlier detection

Some of the modules perform outlier detection. For instance, in the default report produced by `arrayQualityMetrics()`, the module headed Boxplots is followed by one headed Outlier detection for Boxplots. In the corresponding `aqmReportModule` object, this is reflected by a non-trivial value for the slot named `outliers`:

    bo@outliers

    ## An object of class "outlierDetection"
    ## Slot "statistic":
    ##    JD-ALD009-v5-U133A.CEL    JD-ALD051-v5-U133A.CEL    JD-ALD052-v5-U133A.CEL
    ##                 0.0710800                 0.1020375                 0.1615500
    ##    JD-ALD057-v5-U133A.CEL    JD-ALD078-v5-U133A.CEL    JD-ALD180-v5-U133A.CEL
    ##                 0.0595700                 0.1177300                 0.2328175
    ## JD-ALD226-NA-v5-U133A.CEL    JD-ALD232-v5-U133A.CEL    JD-ALD237-v5-U133A.CEL
    ##                 0.2193350                 0.0916325                 0.1482000
    ##    JD-ALD244-v5-U133A.CEL    JD-ALD294-v5-U133A.CEL    JD-ALD380-v5-U133A.CEL
    ##                 0.1346450                 0.3771975                 0.0509700
    ##    JD-ALD381-v5-U133A.CEL    JD-ALD384-v5-U133A.CEL    JD-ALD385-v5-U133A.CEL
    ##                 0.0947675                 0.4404900                 0.1667850
    ##    JD-ALD420-v5-U133A.CEL    JD-ALD421-v5-U133A.CEL    JD-ALD431-v5-U133A.CEL
    ##                 0.1073025                 0.1258150                 0.1938550
    ##    JD-ALD433-v5-U133A.CEL    JD-ALD520-v5-U133A.CEL
    ##                 0.1505600                 0.0589050
    ##
    ## Slot "threshold":
    ## JD-ALD385-v5-U133A.CEL
    ##                  0.311
    ##
    ## Slot "which":
    ## JD-ALD294-v5-U133A.CEL JD-ALD384-v5-U133A.CEL
    ##                     11                     14
    ##
    ## Slot "description":
    ## [1] "Kolmogorov-Smirnov statistic <i>K<sub>a</sub></i>"
    ## [2] "data-driven"

The slot named `statistic` contains, for each array, a single number based on which outlier detection is performed. For instance, in the case of `bo`, the slot `bo@outliers@statistic` is the Kolmogorov-Smirnov statistic for the comparison between each array’s intensity distribution and the distribution of the pooled data. The slot `threshold` contains the threshold against which the valuess of `statistic` were compared. Arrays with a value of `statistic` greater than `threshold` are called outliers. Their indices are listed in the vector `which`. Finally, the slot `description` contains a textual description of the definition of `statistic` and indicates how the `threshold` was chosen. The actual details of outlier detection are different for each report module, and are documented in the figure caption of the report module. For more information, please look at the code of the report module generating function of interest – for instance, at the first few lines of the `boxplot` function. The code there uses the helper functions `outliers` and `boxplotOutliers`, which are documented in their manual pages.

## 0.5 Rendering the report

A report is rendered by calling the function `aqm.writereport()` with a list of `aqmReportModule` objects.

    outdir = tempdir()
    aqm.writereport(modules = qm, reporttitle = "My example", outdir = outdir,
                    arrayTable = pData(MLL.A))
    outdir

    ## [1] "/tmp/RtmpVnSvo9"

Point your browser to the `index.html` file in that directory.

## 0.6 Session Info

    ## R version 4.6.0 RC (2026-04-17 r89917)
    ## Platform: x86_64-pc-linux-gnu
    ## Running under: Ubuntu 24.04.4 LTS
    ##
    ## Matrix products: default
    ## BLAS:   /home/biocbuild/bbs-3.23-bioc/R/lib/libRblas.so
    ## LAPACK: /usr/lib/x86_64-linux-gnu/lapack/liblapack.so.3.12.0  LAPACK version 3.12.0
    ##
    ## locale:
    ##  [1] LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C
    ##  [3] LC_TIME=en_GB              LC_COLLATE=C
    ##  [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: America/New_York
    ## tzcode source: system (glibc)
    ##
    ## attached base packages:
    ## [1] stats     graphics  grDevices utils     datasets  methods   base
    ##
    ## other attached packages:
    ## [1] ALLMLL_1.51.0              affy_1.90.0
    ## [3] Biobase_2.72.0             BiocGenerics_0.58.0
    ## [5] generics_0.1.4             arrayQualityMetrics_3.68.0
    ## [7] BiocStyle_2.40.0
    ##
    ## loaded via a namespace (and not attached):
    ##   [1] DBI_1.3.0             deldir_2.0-4          gridExtra_2.3
    ##   [4] rlang_1.2.0           magrittr_2.0.5        otel_0.2.0
    ##   [7] matrixStats_1.5.0     compiler_4.6.0        RSQLite_2.4.6
    ##  [10] png_0.1-9             systemfonts_1.3.2     vctrs_0.7.3
    ##  [13] reshape2_1.4.5        stringr_1.6.0         pkgconfig_2.0.3
    ##  [16] crayon_1.5.3          fastmap_1.2.0         backports_1.5.1
    ##  [19] XVector_0.52.0        rmarkdown_2.31        preprocessCore_1.74.0
    ##  [22] bit_4.6.0             xfun_0.57             cachem_1.1.0
    ##  [25] jsonlite_2.0.0        blob_1.3.0            BeadDataPackR_1.64.0
    ##  [28] beadarray_2.62.0      jpeg_0.1-11           cluster_2.1.8.2
    ##  [31] R6_2.6.1              bslib_0.10.0          stringi_1.8.7
    ##  [34] RColorBrewer_1.1-3    limma_3.68.0          genefilter_1.94.0
    ##  [37] rpart_4.1.27          GenomicRanges_1.64.0  jquerylib_0.1.4
    ##  [40] Rcpp_1.1.1-1.1        Seqinfo_1.2.0         bookdown_0.46
    ##  [43] knitr_1.51            gcrma_2.84.0          base64enc_0.1-6
    ##  [46] IRanges_2.46.0        Matrix_1.7-5          splines_4.6.0
    ##  [49] nnet_7.3-20           tidyselect_1.2.1      rstudioapi_0.18.0
    ##  [52] dichromat_2.0-0.1     yaml_2.3.12           codetools_0.2-20
    ##  [55] hwriter_1.3.2.1       lattice_0.22-9        tibble_3.3.1
    ##  [58] plyr_1.8.9            KEGGREST_1.52.0       S7_0.2.2
    ##  [61] evaluate_1.0.5        foreign_0.8-91        survival_3.8-6
    ##  [64] Biostrings_2.80.0     pillar_1.11.1         affyio_1.82.0
    ##  [67] BiocManager_1.30.27   MatrixGenerics_1.24.0 checkmate_2.3.4
    ##  [70] stats4_4.6.0          S4Vectors_0.50.0      ggplot2_4.0.3
    ##  [73] scales_1.4.0          xtable_1.8-8          glue_1.8.1
    ##  [76] Hmisc_5.2-5           tools_4.6.0           interp_1.1-6
    ##  [79] hexbin_1.28.5         data.table_1.18.2.1   vsn_3.80.0
    ##  [82] affyPLM_1.88.0        annotate_1.90.0       XML_3.99-0.23
    ##  [85] grid_4.6.0            latticeExtra_0.6-31   AnnotationDbi_1.74.0
    ##  [88] colorspace_2.1-2      htmlTable_2.5.0       Formula_1.2-5
    ##  [91] cli_3.6.6             textshaping_1.0.5     gridSVG_1.7-7
    ##  [94] setRNG_2024.2-1       svglite_2.2.2         dplyr_1.2.1
    ##  [97] gtable_0.3.6          sass_0.4.10           digest_0.6.39
    ## [100] htmlwidgets_1.6.4     farver_2.1.2          memoise_2.0.1
    ## [103] htmltools_0.5.9       lifecycle_1.0.5       httr_1.4.8
    ## [106] statmod_1.5.1         bit64_4.8.0