Skip to main content

multiqc-pivot

CI Python Versions basedpyright mypy Ruff

A MultiQC plugin that folds related samples into one General Statistics row per group.

Installation

pip install multiqc-pivot

Introduction

MultiQC gives every sample its own row. When one subject yields several samples that are measured by different methods, say a tumour and a normal, or two tissues and a paired-genotype check, the General Statistics table ends up with a block of half-empty rows per subject. MultiQC's own sample grouping only fills the group's row for the handful of modules that know how to merge their metrics.

This plugin runs after every module has reported and rebuilds the table:

  1. Rows for one group fold into a single row, and every folded column is prefixed by which method it came from.
  2. The original rows stay beneath the group row, so they still can be viewed.
  3. Rows for a level that does not belong in the table, such as per-library read QC, move out into their own table under General Statistics with whatever grouping they already had.
  4. Hover text, color scales, formats and hidden-by-default state carry over from the module that produced each column.

Example

The report below comes from the test fixtures and the configuration shown in the usage section:

General Statistics with one row per subject and a Library statistics table beneath it

sample_pivot:
  group: '^(?P<group>[^. ]+)\.'
  levels:
    - match: '\.subject$'
    - match: '\.(?P<analyte>tissueA|tissueB)$'
      label: '{analyte}'
    - match: '\.(?P<analyte>tissueA|tissueB) \(filtered\)$'
      label: '{analyte} (filtered)'
    - match: '\.library\.'
      table: Library statistics
  label_order: [tissueA, tissueB, tissueB (filtered)]
  tables:
    Library statistics:
      description: Per-library read QC.

Usage

Add a sample_pivot block to any MultiQC config, for example with --config my_config.yml.

So, with these sample names:

101.subject
101.tissueA
101.tissueB
101.tissueB (filtered data, though)
101.tissueA.library.L1
101.tissueA.library.L2

This configuration produces one row named 101 carrying Concordance, TissueA Median, TissueB Median, TissueB (filtered) % Aligned and so on, and moves the library rows into a separate table:

sample_pivot:
  group: '^(?P<group>[^. ]+)\.'
  levels:
    - match: '\.subject$'
    - match: '\.(?P<analyte>tissueA|tissueB)$'
      label: '{analyte}'
    - match: '\.(?P<analyte>tissueA|tissueB) \(filtered\)$'
      label: '{analyte} (filtered)'
    - match: '\.library\.'
      table: Library statistics
  label_order: [tissueA, tissueB, tissueB (filtered)]
  tables:
    Library statistics:
      description: Per-library read QC; read pairs nest under their library.

YAML Configuration Reference

Key Meaning
group A regular expression searched in every matched sample name. Its (?P<group>...) capture names the folded row. Required.
levels An ordered list; the first level whose match is found in a sample name wins. Required.
levels[].match A regular expression searched in the sample name. Named captures are available to label.
levels[].label A format string built from the captures of match. Columns of matching rows are renamed with it and folded onto the group row; the row itself stays beneath. Omit it, and omit table, to fold the row's columns onto the group row unchanged.
levels[].table The name of a table that receives matching rows instead of General Statistics. Rows keep their grouping, so paired reads stay nested under their library.
column_title How a pivoted column is titled. {label} is the label as written, {Label} has its first letter upper-cased, {title} is the module's title. Default {Label} {title}.
label_order Labels in the order their column blocks should appear. Labels not listed follow in order of first appearance.
tables Presentation of the tables named by levels[].table, currently a description each.

[!TIP] A sample that matches no level is left where it was. A sample that matches a level but not group is left alone as well, with a warning in the log. Columns that a module did not declare a header for are dropped from folded rows, as MultiQC would have dropped them anyway.

Limitations

  1. Sample names are matched after MultiQC has cleaned them, so you must write patterns against the names you see in an un-pivoted report.
  2. Only one level of nesting exists in a MultiQC table. Rows moved into a secondary table keep the nesting they already had; rows folded into a group row become its children, and cannot nest further.
  3. Two rows in the same group that resolve to the same label collide. The first value is kept and a warning is logged, so make labels specific enough to tell such rows apart.

Development and Testing

See the contributing guide for more information.

Metadata

Release files for multiqc-pivot 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for multiqc-pivot 0.1.0
File Size Uploaded
multiqc_pivot-0.1.0.tar.gz 274.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for multiqc-pivot 0.1.0
File Interpreter ABI Platform
multiqc_pivot-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 285.4 kB

Release files / multiqc_pivot-0.1.0.tar.gz

Download URL multiqc_pivot-0.1.0.tar.gz
Size 274.5 kB
Tags Source
SHA-256 checksum
How to use checksums
f295cdb3635625dec983a207d6a619da12a7547a373f0b61f8f533abb6f7dc6a
BLAKE2b-256 checksum
How to use checksums
d62446bd8bfb6af71e5bd8d86cc2abaf7feed240a071d67f5b319cc1c8a8b50d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 9, 2026.

Transparency log

Release files / multiqc_pivot-0.1.0-py3-none-any.whl

Download URL multiqc_pivot-0.1.0-py3-none-any.whl
Size 10.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
2429df02018f03981b15281a9f8dd190c4c1cf9917483415334541b8d4937df8
BLAKE2b-256 checksum
How to use checksums
44290a0f40eaf306118883e57ba4d0dc318def47bc94dc428b3c98fd0a42db5e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 9, 2026.

Transparency log

Release history Release notifications | RSS feed

0.1.1

2 release files

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page