Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### `Fixed`

- [#216](https://github.com/IntGenomicsLab/lrsomatic/pull/216) - `--download_sigprofiler_genome` failed on CHM13 with `CHM13-T2T failed the SigProfilerMatrixGenerator checksum verification`. The published payload had been replaced by the archive rebuilt after [SigProfilerMatrixGenerator#251](https://github.com/SigProfilerSuite/SigProfilerMatrixGenerator/issues/251), which counts transcript-end bases correctly, while the image still carried the old checksums. The SigProfiler modules now use `ghcr.io/ljwharbers/sigprofiler:1.3.6-chm13-7894689` (`oras://ghcr.io/ljwharbers/sigprofiler-sif:1.3.6-chm13-7894689`), and the CHM13 `sigprofiler_genome_url` points at the versioned `chm13_release_2026-09` payload. The new SigProfilerMatrixGenerator also includes upstream's corrected GRCh38 payload, which the AlexandrovLab FTP has served as `GRCh38.tar.gz` since 2026-09-25; the old one is now `GRCh38_Legacy`. **GRCh38 and CHM13-T2T volumes installed before this change fail verification and must be reinstalled.** A volume passed with `--sigprofiler_genome_dir` is now checked once, up front, by the new `SIGPROFILER_VERIFY` step, which stops with reinstall instructions instead of failing in every `SIGPROFILER_MATRIXGENERATOR` task. Its error names the cause: missing chromosome files, a checksum mismatch (stale or corrupted payload), or a genome the image has no checksums for. Stub nf-tests (tag `small`) now cover `PREPARE_SIGNATURES`, the volume reaching every `SIGPROFILER_MATRIXGENERATOR` sample, and the pinned image in `SIGPROFILER_MATRIXGENERATOR` and `SIGPROFILER_ASSIGNMENT`. Transcribed-strand matrices (SBS288, SBS384) change slightly; SBS96 and the COSMIC fits are not expected to change (@ljwharbers).
- [#206](https://github.com/IntGenomicsLab/lrsomatic/pull/206) - A remote (http, https or ftp) ClinVar is now downloaded once per run by the new `VEPPLUGIN_CLINVAR` step in `PREPARE_VEP_PLUGINS`, instead of being staged by Nextflow as a foreign file; local and cloud-storage paths are staged as before. `GERMLINE_VEP` and `SOMATIC_VEP` re-checked the foreign file on its host for every sample, and NCBI answered the burst from a multi-sample GRCh38 run with HTTP 503, so `SOMATIC_VEP` failed with `Can't stage file ...clinvar_20260829.vcf.gz`; `-resume` could not recover, since the failed check changed the staging cache key. The download is checked against the new `--vep_clinvar_md5` and `--vep_clinvar_tbi_md5`, set by default to the checksums NCBI (GRCh38, VCF only) and Ensembl (CHM13, VCF and index) publish, so the pinned release cannot change silently. Resuming a run that already finished re-runs `GERMLINE_VEP` and `SOMATIC_VEP` once, since ClinVar now comes from a task rather than the stage cache. The ClinVar sizes in `docs/usage.md` are also corrected, and `docs/output.md` now documents `vep_plugins/` (@AmberVerhasselt).
- [#203](https://github.com/IntGenomicsLab/lrsomatic/pull/203) - `CLAIRS` no longer runs with `--haplotagged_tumor_bam_provided_so_skip_intermediate_phasing_and_haplotagging`. Since somatic calling was moved ahead of `PHASING_HAPLOTYPING` (v1.1.0), ClairS has received the untagged minimap2 BAM, so the flag made it skip its own phasing and haplotagging and call every paired sample without haplotype information: the full-alignment model saw no `HP` tags and the haplotype filtering step had nothing to filter on, the same as `--disable_phasing`. ClairS now runs Clair3 on the normal and tumour BAMs and phases the tumour itself. **Paired somatic calls change** (fewer false positives expected), and `CLAIRS` takes longer and uses more work-directory space (@ljwharbers).
- [#203](https://github.com/IntGenomicsLab/lrsomatic/pull/203) - `docs/output.md` now lists the ClairS SNV output as `snvs.vcf.gz`, the name the pipeline publishes, instead of `snv.vcf.gz` (@ljwharbers).
Expand Down
2 changes: 1 addition & 1 deletion conf/igenomes.config
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ params.genomes = [
// SigProfilerMatrixGenerator CHM13-T2T payload (SigProfilerSuite/SigProfilerMatrixGenerator#250);
// not yet hosted on the AlexandrovLab FTP, so it is fetched from the IntGenomicsLab Globus collection
sigprofiler_genome : "CHM13-T2T",
sigprofiler_genome_url : "https://g-608c0c.273595.03c0.data.globus.org/chm13_release_2026-08/CHM13-T2T.tar.gz",
sigprofiler_genome_url : "https://g-608c0c.273595.03c0.data.globus.org/chm13_release_2026-09/CHM13-T2T.tar.gz",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No CI coverage: No small nf-test runs this code. The test profile sets skip_signatures = true, and all tests are GRCh38 anyway. So CI checks neither the new URL, the new image tags, nor the image's embedded CHM13 checksums against this payload. Before merging, please run the Slurm test array or the standalone CHM13 --download_sigprofiler_genome run listed in the PR's to-do, plus the old-vs-new BL1 matrix/fit comparison. Please also run a GRCh38 signatures run on the new image: the image changed for every genome, not just CHM13, and nothing here tests the GRCh38 checksums in the rebuilt SPMG fork.

gnomad : "${params.igenomes_base}/Homo_sapiens/ClairSTO/CHM13/Annotation/ClairSTO-pon/final_gnomad.vcf.gz",
dbsnp : "${params.igenomes_base}/Homo_sapiens/ClairSTO/CHM13/Annotation/ClairSTO-pon/final_dbsnp.vcf.gz",
onekgenomes : "${params.igenomes_base}/Homo_sapiens/ClairSTO/CHM13/Annotation/ClairSTO-pon/final_1kgenomes.vcf.gz",
Expand Down
5 changes: 5 additions & 0 deletions conf/modules.config
Original file line number Diff line number Diff line change
Expand Up @@ -795,6 +795,11 @@ process {
]
}

withName: 'SIGPROFILER_VERIFY' {
// Passes the user's volume through unchanged; never publish a copy of it
publishDir = [ enabled: false ]
}

withName : '.*:SIGNATURES_BCFTOOLS_VIEW' {
// SigProfilerMatrixGenerator ignores FILTER and reads plain-text VCF only
ext.args = { "--apply-filters PASS --types snps,mnps,indels --exclude 'ALT=\"*\"' --output-type v" }
Expand Down
5 changes: 5 additions & 0 deletions docs/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,11 @@ Mutational signature analysis runs [SigProfilerMatrixGenerator](https://github.c

Running with neither, and without `--skip_signatures`, stops the pipeline at start-up.

A volume passed with `--sigprofiler_genome_dir` is checked once per run against the chromosome checksums of the pipeline's SigProfilerMatrixGenerator (`SIGPROFILER_VERIFY`). If a chromosome file is missing or a checksum differs, the run stops before any sample is processed, and the error says which of the two it found. A genome the image has no checksums for is rejected too.

> [!WARNING]
> GRCh38 and CHM13-T2T payloads installed before this release no longer pass that check. SigProfilerMatrixGenerator corrected how both are encoded, and the payloads it now downloads differ from the earlier ones. Reinstall once with `--download_sigprofiler_genome`, or with `SigProfilerMatrixGenerator install <genome> --volume <dir>` from the same image, and pass the new volume on later runs. Mutation counts and COSMIC fits are unaffected. Only the strand-split matrices (for example SBS288 and SBS384) change, slightly.

| Parameter | Description |
| ------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--sigprofiler_genome_dir` | Full path to a SigProfilerMatrixGenerator volume containing `tsb/<sigprofiler_genome>/`. Default = `null` |
Expand Down
4 changes: 2 additions & 2 deletions modules/local/sigprofiler/assignment/main.nf
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ process SIGPROFILER_ASSIGNMENT {

// No conda: the image uses CHM13-T2T forks of SigProfilerMatrixGenerator (#250) and SigProfilerAssignment; see meta.yml
container "${(workflow.containerEngine == 'singularity' || workflow.containerEngine == 'apptainer') && !task.ext.singularity_pull_docker_container
? 'oras://ghcr.io/ljwharbers/sigprofiler-sif:1.3.6-chm13-28a9ce8'
: 'ghcr.io/ljwharbers/sigprofiler:1.3.6-chm13-28a9ce8'}"
? 'oras://ghcr.io/ljwharbers/sigprofiler-sif:1.3.6-chm13-7894689'
: 'ghcr.io/ljwharbers/sigprofiler:1.3.6-chm13-7894689'}"

input:
tuple val(meta), path(sbs96), path(dbs78), path(id83) // SigProfilerMatrixGenerator matrices; dbs78/id83 may be []
Expand Down
40 changes: 40 additions & 0 deletions modules/local/sigprofiler/assignment/tests/main.nf.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
nextflow_process {

name "Test Process SIGPROFILER_ASSIGNMENT"
script "../main.nf"
process "SIGPROFILER_ASSIGNMENT"

tag "modules"
tag "modules_local"
tag "sigprofiler"
tag "sigprofiler_assignment"
tag "small"

// Under -stub; the versions eval still runs in the pinned image, so its tag must resolve under each profile

test("stub") {

options "-stub"

when {
process {
"""
// any file stands in for the SBS96 matrix; the stub does not read it
def matrix = file("\${projectDir}/tests/fixtures/sigprofiler_stub_volume/tsb/CHM13-T2T/1.txt", checkIfExists: true)
input[0] = [ [ id:'sample1' ], matrix, [], [] ]
input[1] = 'CHM13-T2T'
input[2] = 3.6
"""
}
}

then {
assertAll(
{ assert process.success },
{ assert process.out.activities.size() == 1 },
{ assert process.out.versions_sigprofilerassignment.size() == 1 },
{ assert process.out.versions_sigprofilerassignment[0][2] ==~ /\d+\.\d+.*/ }
)
}
}
}
4 changes: 2 additions & 2 deletions modules/local/sigprofiler/install/main.nf
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ process SIGPROFILER_INSTALL {

// No conda: the image uses CHM13-T2T forks of SigProfilerMatrixGenerator (#250) and SigProfilerAssignment; see meta.yml
container "${(workflow.containerEngine == 'singularity' || workflow.containerEngine == 'apptainer') && !task.ext.singularity_pull_docker_container
? 'oras://ghcr.io/ljwharbers/sigprofiler-sif:1.3.6-chm13-28a9ce8'
: 'ghcr.io/ljwharbers/sigprofiler:1.3.6-chm13-28a9ce8'}"
? 'oras://ghcr.io/ljwharbers/sigprofiler-sif:1.3.6-chm13-7894689'
: 'ghcr.io/ljwharbers/sigprofiler:1.3.6-chm13-7894689'}"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Image registry: REVIEW.md asks for custom images to use the oras://docker.io/...-sif / docker.io/... pair, with Docker Hub rather than ghcr for large Apptainer images. This PR builds and pins new 1.3.6-chm13-7894689 tags on ghcr.io in all three SigProfiler modules (install, matrixgenerator, assignment). Since new images are being published anyway, please push them to Docker Hub too and point the singularity/docker ternary at oras://docker.io/ljwharbers/sigprofiler-sif:1.3.6-chm13-7894689 / docker.io/ljwharbers/sigprofiler:1.3.6-chm13-7894689. If that changes, the ghcr.io/ljwharbers/sigprofiler mention in docs/usage.md:392 needs the same update.


input:
val(genome) // SigProfilerMatrixGenerator genome name, e.g. GRCh38 or CHM13-T2T
Expand Down
4 changes: 2 additions & 2 deletions modules/local/sigprofiler/matrixgenerator/main.nf
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ process SIGPROFILER_MATRIXGENERATOR {

// No conda: the image uses CHM13-T2T forks of SigProfilerMatrixGenerator (#250) and SigProfilerAssignment; see meta.yml
container "${(workflow.containerEngine == 'singularity' || workflow.containerEngine == 'apptainer') && !task.ext.singularity_pull_docker_container
? 'oras://ghcr.io/ljwharbers/sigprofiler-sif:1.3.6-chm13-28a9ce8'
: 'ghcr.io/ljwharbers/sigprofiler:1.3.6-chm13-28a9ce8'}"
? 'oras://ghcr.io/ljwharbers/sigprofiler-sif:1.3.6-chm13-7894689'
: 'ghcr.io/ljwharbers/sigprofiler:1.3.6-chm13-7894689'}"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Old CHM13 volumes passed with --sigprofiler_genome_dir are not caught. The PR says volumes installed before this change "no longer pass verification with the new image and must be reinstalled". The only verification, though, is the is_genome_installed assert in SIGPROFILER_INSTALL. When the user passes --sigprofiler_genome_dir, PREPARE_SIGNATURES (subworkflows/local/prepare_signatures.nf:34-41) only checks that tsb/<genome>/ exists and holds 24 .txt files. That includes the published <outdir>/cache/sigprofiler/volume from earlier runs, which docs/usage.md tells users to reuse. A stale chm13_release_2026-08 volume passes that check and goes straight to this image, with one of two results:

  • this process fails late with an unclear checksum error from the tool, or
  • the tool doesn't re-verify, and the strand matrices (SBS288/SBS384 etc.) are built from the old payload without any warning.

Neither result is documented outside the CHANGELOG. Suggested fixes:

  • run the same rgm.ReferenceGenomeManager(...).is_genome_installed(genome) check on the user-supplied volume, either in a small validation step or at the top of this script, so a stale volume fails up front with a "reinstall with --download_sigprofiler_genome" message
  • at the least, add a note to the --sigprofiler_genome_dir help_text in nextflow_schema.json and to docs/usage.md saying that CHM13 volumes installed before this release must be reinstalled


input:
tuple val(meta), path(vcf) // somatic small-variant VCF (plain or bgzipped)
Expand Down
55 changes: 55 additions & 0 deletions modules/local/sigprofiler/matrixgenerator/tests/main.nf.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
nextflow_process {

name "Test Process SIGPROFILER_MATRIXGENERATOR"
script "../main.nf"
process "SIGPROFILER_MATRIXGENERATOR"

tag "modules"
tag "modules_local"
tag "sigprofiler"
tag "sigprofiler_matrixgenerator"
tag "small"

// No real payload fits in CI (~3 GB per genome), so this runs under -stub. The volume comes from
// PREPARE_SIGNATURES and is wired as in workflows/lrsomatic.nf, so every sample must receive it.
// The versions eval still runs in the pinned image, so its tag must resolve under each profile.

test("stub - the verified volume reaches every sample") {

options "-stub"

setup {
run("PREPARE_SIGNATURES") {
script "../../../../../subworkflows/local/prepare_signatures.nf"
workflow {
"""
input[0] = 'CHM13-T2T'
input[1] = null
input[2] = "\${projectDir}/tests/fixtures/sigprofiler_stub_volume"
input[3] = false
"""
}
}
}

when {
process {
"""
def vcf = file("\${projectDir}/tests/fixtures/vcfsplit_indel.vcf", checkIfExists: true)
input[0] = channel.of([ [ id:'sample1' ], vcf ], [ [ id:'sample2' ], vcf ])
input[1] = PREPARE_SIGNATURES.out.volume.map { volume -> [ [:], volume ] }
input[2] = 'CHM13-T2T'
"""
}
}

then {
assertAll(
{ assert process.success },
{ assert process.out.sbs96.collect { meta, _matrix -> meta.id }.sort() == ['sample1', 'sample2'] },
{ assert process.out.versions_sigprofilermatrixgenerator.size() == 2 },
{ assert process.out.versions_sigprofilermatrixgenerator.every { _proc, _tool, version -> version ==~ /\d+\.\d+.*/ } }
)
}
}
}
68 changes: 68 additions & 0 deletions modules/local/sigprofiler/verify/main.nf
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
process SIGPROFILER_VERIFY {
tag "$genome"
label 'process_single'

// No conda: the image uses CHM13-T2T forks of SigProfilerMatrixGenerator (#250) and SigProfilerAssignment; see meta.yml
container "${(workflow.containerEngine == 'singularity' || workflow.containerEngine == 'apptainer') && !task.ext.singularity_pull_docker_container
? 'oras://ghcr.io/ljwharbers/sigprofiler-sif:1.3.6-chm13-7894689'
: 'ghcr.io/ljwharbers/sigprofiler:1.3.6-chm13-7894689'}"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Registry convention (still open from the first review). The new SIGPROFILER_VERIFY module and the three bumped modules still pull the custom image from ghcr.io. REVIEW.md asks for the oras://docker.io/...-sif / docker.io/... pair for custom images, and says "Docker Hub, not ghcr, for large Apptainer images". This bundled SigProfiler SIF is one of those large images. Please push 1.3.6-chm13-7894689 to Docker Hub and point all four modules there, or say in the PR why ghcr is acceptable here.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We won't address this in this PR. The SigProfiler image stays on ghcr (ghcr.io/ljwharbers/sigprofiler / oras://ghcr.io/ljwharbers/sigprofiler-sif), the registry it has used since #190.


input:
path(volume, stageAs: 'genome_volume') // SigProfilerMatrixGenerator volume containing tsb/<genome>/
val(genome) // SigProfilerMatrixGenerator genome name, e.g. GRCh38 or CHM13-T2T

output:
val(true) , emit: verified
tuple val("${task.process}"), val('sigprofilermatrixgenerator'), eval("python -c 'import importlib.metadata as m; print(m.version(\"SigProfilerMatrixGenerator\"))'"), topic: versions, emit: versions_sigprofilermatrixgenerator

when:
task.ext.when == null || task.ext.when

script:
if (workflow.profile.tokenize(',').intersect(['conda', 'mamba']).size() >= 1) {
error "SIGPROFILER_VERIFY does not support Conda. Please use Docker / Singularity / Apptainer instead."
}
"""
# SIGPROFILER_MATRIXGENERATOR re-checks the payload for every sample; checking once here fails a stale or damaged
# volume before any sample work, with the reinstall instructions instead of a per-sample checksum error
python - <<'PY'
import sys
from SigProfilerMatrixGenerator.scripts import reference_genome_manager as rgm

genome = "${genome}"
if genome not in rgm.CHECKSUMS:
sys.exit(
f"ERROR: this pipeline's SigProfilerMatrixGenerator has no checksums for {genome} (registered: "
f"{', '.join(sorted(rgm.CHECKSUMS))}). Set --sigprofiler_genome to one of them or use --skip_signatures."
)

manager = rgm.ReferenceGenomeManager("genome_volume")
if not manager.is_genome_installed(genome):
manager.print_genome_checksum_verification_report(genome)
tsb = manager.reference_dir.get_tsb_dir() / genome
expected = rgm.CHECKSUMS[genome]
missing = [chrom for chrom in expected if not (tsb / f"{chrom}.txt").is_file()]
if missing:
cause = (
f"is an incomplete install: {len(missing)} of {len(expected)} chromosome files are missing "
f"({', '.join(missing)})."
)
else:
cause = (
"does not match the checksums of this pipeline's SigProfilerMatrixGenerator. Either it is a stale "
"payload (GRCh38 and CHM13-T2T installed for lrsomatic < 1.2.0 are a superseded revision) or the "

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The error points at the wrong version. No released lrsomatic has a SigProfiler payload. Signatures came in with #190, under v1.2.0dev, and manifest.version is still 1.1.0. So "installed for lrsomatic < 1.2.0" describes no real volume.

Stale volumes come from two places: 1.2.0dev builds from before #216 (image 1.3.6-chm13-28a9ce8), and a standalone SigProfilerMatrixGenerator install GRCh38 run before 2026-09-25. Someone who installed their volume from a dev commit last month thinks of it as 1.2.0. They will read this message as "not stale, so my copy must be corrupted", which is the wrong cause.

The same wording is in the sigprofiler_genome_dir help_text in nextflow_schema.json (line 484). Something like this would fit both places:

Suggested change
"payload (GRCh38 and CHM13-T2T installed for lrsomatic < 1.2.0 are a superseded revision) or the "
"payload (GRCh38 and CHM13-T2T volumes installed before SigProfilerMatrixGenerator 7894689 / lrsomatic "
"#216, i.e. with an earlier 1.2.0dev build or an upstream GRCh38 install before 2026-09-25, are a "
"superseded revision) or the "

"copy is corrupted."
)
sys.exit(
f"ERROR: the {genome} payload in --sigprofiler_genome_dir {cause} Reinstall it with "
"--download_sigprofiler_genome (published to <outdir>/cache/sigprofiler/volume) and pass that directory "
"on later runs."
)
PY
"""

stub:
"""
echo "stub: skipping checksum verification of genome_volume/tsb/${genome}"
"""
}
58 changes: 58 additions & 0 deletions modules/local/sigprofiler/verify/meta.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
---
# yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/modules/meta-schema.json
name: "sigprofiler_verify"
description: Check a user-supplied SigProfilerMatrixGenerator volume against the chromosome checksums of the pipeline's SigProfilerMatrixGenerator, so a stale or damaged payload fails before any sample is processed
keywords:
- mutational signatures
- reference genome
- sigprofiler
- checksum
tools:
- "sigprofilermatrixgenerator":
description: "SigProfilerMatrixGenerator creates mutational matrices for all types of somatic mutations"
homepage: "https://github.com/SigProfilerSuite/SigProfilerMatrixGenerator"
documentation: "https://sigprofilersuite.github.io/SigProfilerMatrixGenerator/"
tool_dev_url: "https://github.com/SigProfilerSuite/SigProfilerMatrixGenerator"
doi: "10.1186/s12864-019-6041-2"
licence: ["BSD-2-Clause"]

input:
- volume:
type: directory
description: SigProfilerMatrixGenerator volume containing tsb/<genome>/ (e.g. from --sigprofiler_genome_dir)
- genome:
type: string
description: SigProfilerMatrixGenerator genome name, e.g. GRCh38 or CHM13-T2T

output:
verified:
- "true":
type: boolean
description: Emitted once the volume's chromosome files match the registered checksums; the task fails otherwise
versions_sigprofilermatrixgenerator:
- - ${task.process}:
type: string
description: The process the versions were collected from
- sigprofilermatrixgenerator:
type: string
description: The tool name
- 'python -c ''import importlib.metadata as m; print(m.version("SigProfilerMatrixGenerator"))''':
type: string
description: The command used to generate the version of the tool

topics:
versions:
- - ${task.process}:
type: string
description: The process the versions were collected from
- sigprofilermatrixgenerator:
type: string
description: The tool name
- 'python -c ''import importlib.metadata as m; print(m.version("SigProfilerMatrixGenerator"))''':
type: string
description: The command used to generate the version of the tool

authors:
- "@ljwharbers"
maintainers:
- "@ljwharbers"
Loading
Loading