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 General Statistics 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, unless a level asks for them to be dropped.
  3. Rows for a level that do 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.

Usage

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

So, with these sample and library filename prefixes for a patient:

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

The following configuration produces one row named 101 carrying Concordance, TissueA Median, TissueB Median, TissueB (filtered) % Aligned and so on, and moves any per-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.

And your report will look like:

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

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 unless keep_rows is false. Omit it, and omit table, to fold the row's columns onto the group row unchanged.
levels[].keep_rows Whether rows of a labelled level stay beneath the group row. Set it to false to keep only the folded columns on the group row. Allowed only alongside label. Default true.
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. Tables sit directly under General Statistics in the order their levels are listed.
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.

Dropping Labelled Rows

When the group row already says everything you need, set keep_rows: false on a labelled level. Its columns still fold onto the group row, renamed and titled as before, but the original rows no longer sit beneath it. They are removed from General Statistics only, so each module's own section still shows them.

sample_pivot:
  group: '^(?P<group>[^. ]+)\.'
  levels:
    - match: '\.subject$'
    - match: '\.(?P<analyte>tissueA|tissueB)$'
      label: '{analyte}'
      keep_rows: false

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.2.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.2.0
File Size Uploaded
multiqc_pivot-0.2.0.tar.gz 1.1 MB Details

Built distribution (wheel)

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

Total release size: 1.1 MB

Release files / multiqc_pivot-0.2.0.tar.gz

Download URL multiqc_pivot-0.2.0.tar.gz
Size 1.1 MB
Tags Source
SHA-256 checksum
How to use checksums
88f75d5d9ef496f93dc33fca5ce114b55a3a37f194205745371fb83991a247b6
BLAKE2b-256 checksum
How to use checksums
6de76b6ecb1be2b048b8abbc525e94ae75422e684930b54730b9e9bc7b12f2fb
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.11.16 {"installer":{"name":"uv","version":"0.11.16","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

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

Download URL multiqc_pivot-0.2.0-py3-none-any.whl
Size 11.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
a4ea3908ae47a87110118d7968925bd8254369802abdf1a3248e5b42d35b254d
BLAKE2b-256 checksum
How to use checksums
86f6c24d4e056f99c71f63a4153951c64c9879605b206373ee50e1493e7f0467
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.11.16 {"installer":{"name":"uv","version":"0.11.16","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release history Release notifications | RSS feed

This release

0.2.0 This release

2 release files

0.1.1

2 release files

0.1.0

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