diff --git a/.gitattributes b/.gitattributes index 7a2dabc2..1cdf81cf 100644 --- a/.gitattributes +++ b/.gitattributes @@ -2,3 +2,4 @@ *.nf.test linguist-language=nextflow modules/nf-core/** linguist-generated subworkflows/nf-core/** linguist-generated +assets/lrsomatic_report/** linguist-vendored diff --git a/.nf-core.yml b/.nf-core.yml index 8c2b79f6..9bd50445 100644 --- a/.nf-core.yml +++ b/.nf-core.yml @@ -9,6 +9,9 @@ lint: - .github/workflows/awsfulltest.yml - .github/CONTRIBUTING.md files_unchanged: + # Exempt: carries `assets/lrsomatic_report/** linguist-vendored`, which keeps the + # vendored tool source out of GitHub's language statistics + - .gitattributes - CODE_OF_CONDUCT.md - assets/nf-core-lrsomatic_logo_light.png - docs/images/nf-core-lrsomatic_logo_light.png diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index f51e1a28..7795beca 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -15,6 +15,7 @@ repos: .*ro-crate-metadata.json$| modules/(?!local/).*| subworkflows/(?!local/).*| + assets/lrsomatic_report/.*| .*\.snap$ )$ - id: end-of-file-fixer @@ -23,6 +24,7 @@ repos: .*ro-crate-metadata.json$| modules/(?!local/).*| subworkflows/(?!local/).*| + assets/lrsomatic_report/.*| .*\.snap$ )$ - repo: https://github.com/seqeralabs/nf-lint-pre-commit diff --git a/.prettierignore b/.prettierignore index 63cde500..1d1daf74 100644 --- a/.prettierignore +++ b/.prettierignore @@ -12,3 +12,5 @@ bin/ ro-crate-metadata.json modules/nf-core/ subworkflows/nf-core/ +# Vendored upstream tool source -- see assets/lrsomatic_report/VENDORED.md +assets/lrsomatic_report/ diff --git a/CHANGELOG.md b/CHANGELOG.md index 2107ec86..229b18a7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,12 +5,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## v1.2.0dev +### `Added` + +- [#176](https://github.com/IntGenomicsLab/lrsomatic/pull/176) - Added `LRSOMATICREPORT` as the final pipeline step: a self-contained per-sample HTML report covering small variants, structural variants, copy number and QC. Skip it with `--skip_report`; choose the gene panel selected on load with `--report_gene_panel` (@ljwharbers). +- [#176](https://github.com/IntGenomicsLab/lrsomatic/pull/176) - Vendored the [lrsomatic_report](https://github.com/ljwharbers/lrsomatic_report) v1.3.2 tool source at `assets/lrsomatic_report`, so `nextflow run IntGenomicsLab/lrsomatic` ships it without a submodule checkout (@ljwharbers). +- [#176](https://github.com/IntGenomicsLab/lrsomatic/pull/176) - Added a `solution_dirs` output to the WAKHAN module so its per-solution copy-number plots can be staged downstream (@ljwharbers). + ### `Changed` +- [#186](https://github.com/IntGenomicsLab/lrsomatic/pull/186) - Re-synced the vendored [lrsomatic_report](https://github.com/ljwharbers/lrsomatic_report) to v1.3.0, which adds tickbox dropdown filters on the categorical columns of both variant tables and turns the report's gene panel selector into checkboxes (@ljwharbers). +- [#176](https://github.com/IntGenomicsLab/lrsomatic/pull/176) - Re-synced the vendored [lrsomatic_report](https://github.com/ljwharbers/lrsomatic_report) to v1.3.2: facet dropdown counts follow the active filters, opening a facet menu no longer resets the table's horizontal scroll, a flatter clinical theme, and inline code comments trimmed to one line (@ljwharbers). +- [#186](https://github.com/IntGenomicsLab/lrsomatic/pull/186) - `--report_gene_panel` now takes a comma-separated list, so several panels can be applied at once: a variant or SV is kept if it hits any of them. Panel values are also validated at launch instead of failing inside the report task (@ljwharbers). - [#184](https://github.com/IntGenomicsLab/lrsomatic/pull/184) - Replaced the CHM13 Severus panel of normals with the merged 1000 Genomes + ASAP panel (@AmberVerhasselt). ### `Fixed` +- [#186](https://github.com/IntGenomicsLab/lrsomatic/pull/186) - Stopped snapshotting the md5 of sample4's merged tumour BAM and its index in the `clair_only` nf-test: `samtools merge` gives the colliding `@PG` IDs of the two replicates a random hex suffix, so neither digest is reproducible. The alignment records are, and are now asserted with `bam().getReadsMD5()` instead (@ljwharbers). - [#182](https://github.com/IntGenomicsLab/lrsomatic/pull/182) - Added `--vcf` to the default `vep_args` so VEP writes VCF output rather than its default tab-delimited format (@AmberVerhasselt). ## v1.1.0 - [2026-04-28] diff --git a/CITATIONS.md b/CITATIONS.md index d92c057f..811a1ea9 100644 --- a/CITATIONS.md +++ b/CITATIONS.md @@ -50,6 +50,10 @@ > Lin JH, Chen LC, Yu SC, Huang YT. LongPhase: an ultra-fast chromosome-scale phasing algorithm for small and large variants. Bioinformatics. 2022 Apr 28;38(9):2452-2455. doi: 10.1093/bioinformatics/btac126. PubMed PMID: 35253834; PubMed Central PMCID: PMC9048675. +- [lrsomatic_report](https://github.com/ljwharbers/lrsomatic_report) + + > Standalone R/Quarto reporting tool that renders the pipeline's final per-sample HTML report. https://github.com/ljwharbers/lrsomatic_report + - [minimap2](https://pubmed.ncbi.nlm.nih.gov/29750242/) > Li H. Minimap2: pairwise alignment for nucleotide sequences. Bioinformatics. 2018 Sep 15;34(18):3094-3100. doi: 10.1093/bioinformatics/bty191. PubMed PMID: 29750242; PubMed Central PMCID: PMC6137996. diff --git a/README.md b/README.md index 6125f8a2..9c3f6b9d 100644 --- a/README.md +++ b/README.md @@ -104,7 +104,7 @@ IntGenomicsLab/lr_somatic was originally written by Luuk Harbers, Robert Forsyth ## Pipeline output -This pipeline produces a series of different output files. The main output is an aligned and phased tumour bam file. This bam file can be used by any typical downstream tool that uses bam files as input. Furthermore, we have sample-specific QC outputs from `cramino` (fastq), `cramino` (bam), `mosdepth`, `samtools` (stats/flagstat/idxstats), and optionally `fibertools`. Finally, we have a `multiqc` report from that combines the output from `mosdepth` and `samtools` into one html report. +This pipeline produces a series of different output files. The main output is an aligned and phased tumour bam file. This bam file can be used by any typical downstream tool that uses bam files as input. Furthermore, we have sample-specific QC outputs from `cramino` (fastq), `cramino` (bam), `mosdepth`, `samtools` (stats/flagstat/idxstats), and optionally `fibertools`. Finally, we have a `multiqc` report that combines the output from `mosdepth` and `samtools` into one HTML report, and a self-contained per-sample HTML report (`/report/_report.html`) covering small variants, structural variants, copy number and QC in one place — disable it with `--skip_report`. Besides QC and the aligned and phased bam file, we have output from (structural) variant and copy number callers, of which some are optional. The output from these variant callers can be found in their respective folders. For small and structural variant callers (`clairS`, `clairS-TO`, and `severus`) these will contain, among others, `vcf` files with called variants. For `ascat` these contain files with final copy number information and plots of the copy number profiles. @@ -128,6 +128,7 @@ Example output directory structure: │ │ ├── germline │ │ ├── somatic │ │ ├── SVs +│ ├── report │ ├── Sample 2 │ ├── ascat diff --git a/assets/lrsomatic_report/LICENSE b/assets/lrsomatic_report/LICENSE new file mode 100644 index 00000000..8d542e4f --- /dev/null +++ b/assets/lrsomatic_report/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 Luuk Harbers + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/assets/lrsomatic_report/R/circos.R b/assets/lrsomatic_report/R/circos.R new file mode 100644 index 00000000..e608409d --- /dev/null +++ b/assets/lrsomatic_report/R/circos.R @@ -0,0 +1,263 @@ +suppressPackageStartupMessages({ + library(circlize) + library(data.table) +}) + +# Colour palettes — keep in sync with --circos-* in assets/styles/report.scss + +# SBS-6 SNV palette (SigProfiler/COSMIC standard, softened slightly toward report ink/paper) +SNV_COLOURS = c( + "C>A" = "#2EBAED", + "C>G" = "#1b1e22", + "C>T" = "#b3402f", + "T>A" = "#c7c2b8", + "T>C" = "#ADCC54", + "T>G" = "#F0D0CE" +) + +# SV colours — saturated, hue-matched to --sv-* table tokens +SV_COLOURS = c( + INS = "#cf5b46", + DEL = "#2f6db3", + INV = "#c08a1e", + DUP = "#3f7d4e" +) + +SV_YPOS = c(INS = 1.0, DEL = 0.66, INV = 0.33, DUP = 0.05) + +# CNV colours — tied to the report spine +CNV_COLOURS = c( + major = "#b3402f", # brick = "more" + minor = "#0d5c75", # teal = "less" + total = "#1b1e22" # ink +) + +# BND/translocation link colour +BND_COLOUR = "#8a5fa3" + +# Classify SNV into 6 SBS categories (C/T-ref normalised) +.classify_mut = function(ref, alt) { + comp = c(A = "T", T = "A", C = "G", G = "C") + ref = toupper(ref); alt = toupper(alt) + use_comp = !(ref %in% c("C", "T")) + norm_ref = ifelse(use_comp, comp[ref], ref) + norm_alt = ifelse(use_comp, comp[alt], alt) + paste0(norm_ref, ">", norm_alt) +} + +# Draw a circos plot to output_path (SVG or PNG by extension) +draw_circos = function(snv_data = NULL, + sv_nontrans = NULL, + sv_trans = NULL, + cnv_data = NULL, + cytobands, + chrom_lengths, + chromosomes, + output_path) { + + # Filter cytobands and lengths to displayed chromosomes + cyto_filt = cytobands[cytobands$chrom %in% chromosomes, ] + lens_filt = chrom_lengths[names(chrom_lengths) %in% chromosomes] + lens_filt = lens_filt[chromosomes[chromosomes %in% names(lens_filt)]] + + # Prepare SNV data + if (!is.null(snv_data) && nrow(snv_data) > 0) { + snv = as.data.table(snv_data)[nchar(ref) == 1 & nchar(alt) == 1] + snv = snv[chrom %in% chromosomes] + snv[, mut_cat := .classify_mut(ref, alt)] + snv[, circos_col := SNV_COLOURS[mut_cat]] + snv[is.na(circos_col), circos_col := "#AAAAAA"] + } else { + snv = data.table(chrom = character(), pos = integer(), + mut_cat = character(), circos_col = character()) + } + + # Prepare SV (non-BND) data + if (!is.null(sv_nontrans) && nrow(sv_nontrans) > 0) { + sv_nt = as.data.table(sv_nontrans)[chrom %in% chromosomes] + } else { + sv_nt = data.table(chrom = character(), pos = integer(), end = integer(), + svtype = character(), circos_pos = numeric(), circos_col = character()) + } + + # Prepare translocation (BND) data + if (!is.null(sv_trans) && nrow(sv_trans) > 0) { + sv_tr = as.data.table(sv_trans)[chrom %in% chromosomes & chrom2 %in% chromosomes] + } else { + sv_tr = data.table(chrom = character(), pos = integer(), + chrom2 = character(), pos2 = integer()) + } + + # Prepare CNV data + if (!is.null(cnv_data) && nrow(cnv_data) > 0) { + cnv = as.data.table(cnv_data)[chr %in% chromosomes] + cnv = cnv[order(chr, startpos)] + } else { + cnv = data.table(chr = character(), startpos = integer(), endpos = integer(), + major_cn = numeric(), minor_cn = numeric(), total_cn = numeric()) + } + + # Open device + ext = tolower(tools::file_ext(output_path)) + if (ext == "svg") { + svglite::svglite(output_path, width = 8, height = 8) + } else { + png(output_path, width = 2400, height = 2400, res = 300) + } + + plot.new() + circos.clear() + + n_chr = length(chromosomes) + gap_degrees = c(rep(1.5, n_chr - 1), 7) + + # Single quiet track surface; colours match the report.scss border/surface tokens + track_bg = "#fbfaf6" + track_border = "#e4e0d6" + + circos.par( + "start.degree" = 90, + "gap.degree" = gap_degrees, + "track.margin" = c(0.006, 0.006), + "cell.padding" = c(0, 0, 0, 0) + ) + + # Build cytobands list as expected by circos.initializeWithIdeogram + cyto_list = list( + df = cyto_filt, + chromosome = chromosomes[chromosomes %in% unique(cyto_filt$chrom)], + chr.len = lens_filt + ) + + circos.initializeWithIdeogram(cyto_list$df, + chromosome.index = cyto_list$chromosome, + plotType = c("ideogram", "labels"), + labels.cex = 0.8) + + # Pre-compute jitter once so it varies per chromosome but stays reproducible + set.seed(42) + + # ---- Track 1: SNV dots (coloured by mutation category) ------------------ + circos.trackPlotRegion( + factors = chromosomes, + ylim = c(0, 1), + bg.border = track_border, + bg.col = track_bg, + track.height = 0.16, + panel.fun = function(region, value, ...) { + chr = get.cell.meta.data("sector.index") + sub_snv = snv[chrom == chr] + if (nrow(sub_snv) == 0) return(invisible(NULL)) + y_jitter = runif(nrow(sub_snv), 0.05, 0.95) + # Translucent so a dense cloud reads as a tint, not confetti. + circos.points( + x = sub_snv$pos, + y = y_jitter, + col = adjustcolor(sub_snv$circos_col, alpha.f = 0.65), + pch = 19, + cex = 0.18 + ) + } + ) + + # ---- Track 2: Non-BND SVs (DEL/DUP/INV/INS as horizontal segments) ----- + circos.trackPlotRegion( + factors = chromosomes, + ylim = c(0, 1), + bg.border = track_border, + bg.col = track_bg, + track.height = 0.10, + panel.fun = function(region, value, ...) { + chr = get.cell.meta.data("sector.index") + sub_sv = sv_nt[chrom == chr & !is.na(circos_pos)] + if (nrow(sub_sv) == 0) return(invisible(NULL)) + for (i in seq_len(nrow(sub_sv))) { + x1 = sub_sv$pos[i] + x2 = if (!is.na(sub_sv$end[i]) && sub_sv$end[i] > x1) sub_sv$end[i] else x1 + 1L + circos.segments( + x0 = x1, x1 = x2, + y0 = sub_sv$circos_pos[i], y1 = sub_sv$circos_pos[i], + col = sub_sv$circos_col[i], + lwd = 2.5 + ) + } + } + ) + + # Y-axis labels for SV track + tryCatch( + circos.yaxis( + side = "left", + at = c(0.05, 0.33, 0.66, 1.0), + labels = c("DUP", "INV", "DEL", "INS"), + track.index = 3, + sector.index = chromosomes[1], + labels.niceFacing = TRUE, + labels.cex = 0.45 + ), + error = function(e) NULL + ) + + # ---- Track 3: ASCAT copy-number ----------------------------------------- + circos.trackPlotRegion( + factors = chromosomes, + ylim = c(0, 4), + bg.border = track_border, + bg.col = track_bg, + track.height = 0.18, + panel.fun = function(region, value, ...) { + chr = get.cell.meta.data("sector.index") + sub_cnv = cnv[chr == get.cell.meta.data("sector.index")] + if (nrow(sub_cnv) == 0) return(invisible(NULL)) + + xmax = lens_filt[chr] + if (!is.na(xmax)) { + for (y_ref in c(1, 2, 3)) { + circos.lines(c(0, xmax), c(y_ref, y_ref), + col = track_border, lwd = 0.4, lty = "dotted") + } + } + + circos.yaxis( + side = "left", + at = c(0, 1, 2, 3, 4), + labels = c("0", "1", "2", "3", "4+"), + sector.index = chromosomes[1], + labels.niceFacing = TRUE, + labels.cex = 0.40 + ) + + for (i in seq_len(nrow(sub_cnv))) { + xl = sub_cnv$startpos[i]; xr = sub_cnv$endpos[i] + maj = sub_cnv$major_cn[i] + circos.rect(xl, maj + 0.02, xr, maj + 0.12, + col = CNV_COLOURS["major"], border = CNV_COLOURS["major"], lwd = 0.05) + min_cn = sub_cnv$minor_cn[i] + circos.rect(xl, min_cn - 0.12, xr, min_cn - 0.02, + col = CNV_COLOURS["minor"], border = CNV_COLOURS["minor"], lwd = 0.05) + tot = sub_cnv$total_cn[i] + circos.rect(xl, tot - 0.03, xr, tot + 0.03, + col = CNV_COLOURS["total"], border = CNV_COLOURS["total"], lwd = 0.05) + } + } + ) + + # ---- Translocation links (BND): one arc per mate-collapsed rearrangement ---- + if (nrow(sv_tr) > 0) { + for (i in seq_len(nrow(sv_tr))) { + tryCatch( + circos.link( + sector.index1 = sv_tr$chrom[i], point1 = sv_tr$pos[i], + sector.index2 = sv_tr$chrom2[i], point2 = sv_tr$pos2[i], + col = adjustcolor(BND_COLOUR, alpha.f = 0.45), + lwd = 0.9 + ), + error = function(e) NULL + ) + } + } + + circos.clear() + dev.off() + invisible(output_path) +} diff --git a/assets/lrsomatic_report/R/circos_bnd.R b/assets/lrsomatic_report/R/circos_bnd.R new file mode 100644 index 00000000..67646aa2 --- /dev/null +++ b/assets/lrsomatic_report/R/circos_bnd.R @@ -0,0 +1,136 @@ +suppressPackageStartupMessages({ + library(data.table) +}) + +# Breakend-only circos cross-linked to the SV table; R selects the data, assets/js/bnd_circos.js draws it so sectors re-lay-out per filter + +# Payload cap: real samples carry 50-115 arcs, an unfiltered run can carry ~13k +BND_CIRCOS_MAX_LINKS = 2000L + +# BND classes with two loci to draw between (a single breakend has no partner) +BND_CIRCOS_CLASSES = c("translocation", "intra-chr breakend") + +# ---- Data selection ------------------------------------------------------ + +# Drawable rearrangements: BNDs with both loci on plotted chromosomes; feeds both bnd_panel_genes() and bnd_circos_data() +bnd_links = function(sv_table, chromosomes) { + cols = c("id", "svclass", "chrom_a", "pos_a", "chrom_b", "pos_b") + empty = data.table(id = character(), svclass = character(), + chrom_a = character(), pos_a = integer(), + chrom_b = character(), pos_b = integer()) + if (is.null(sv_table) || nrow(sv_table) == 0 || !all(cols %in% names(sv_table))) + return(empty) + + b = as.data.table(sv_table)[, ..cols] + b = b[svclass %in% BND_CIRCOS_CLASSES & + !is.na(chrom_a) & !is.na(pos_a) & !is.na(chrom_b) & !is.na(pos_b) & + chrom_a %in% chromosomes & chrom_b %in% chromosomes] + if (nrow(b) == 0) return(empty) + + # Deterministic order, so the payload is byte-identical across renders of the same data. + setorder(b, chrom_a, pos_a, chrom_b, pos_b, id) + b[] +} + +# Panel genes within `window` of a drawn breakend, using the same test as sv_panel_hits() so the two cannot drift +bnd_panel_genes = function(links, all_panels, window = SV_PANEL_WINDOW_BND) { + empty = data.table(chrom = character(), start = integer(), end = integer(), + gene = character(), panels = character()) + if (is.null(links) || nrow(links) == 0) return(empty) + if (is.null(all_panels) || length(all_panels) == 0) return(empty) + + q = rbindlist(list( + data.table(chrom = links$chrom_a, pos = as.numeric(links$pos_a)), + data.table(chrom = links$chrom_b, pos = as.numeric(links$pos_b)) + )) + q = unique(q[!is.na(chrom) & !is.na(pos)]) + if (nrow(q) == 0) return(empty) + q[, `:=`(start = pmax(pos - window, 0), end = pos + window)] + + out = list() + for (nm in names(all_panels)) { + iv = panel_intervals(all_panels[[nm]]) + if (is.null(iv) || nrow(iv) == 0) next + iv = copy(iv)[, `:=`(start = as.numeric(start), end = as.numeric(end))] + setkey(iv, chrom, start, end) + ov = data.table::foverlaps(q[, .(chrom, start, end)], iv, + by.x = c("chrom", "start", "end"), + type = "any", nomatch = NULL) + if (nrow(ov) == 0) next + out[[nm]] = unique(ov[, .(chrom, start, end, gene, panel = nm)]) + } + if (length(out) == 0) return(empty) + + g = rbindlist(out) + g = g[, .(panels = paste(sort(unique(panel)), collapse = ",")), + by = .(chrom, start, end, gene)] + setorder(g, chrom, start, gene) + g[, `:=`(start = as.integer(start), end = as.integer(end))] + g[, .(chrom, start, end, gene, panels)] +} + + +# ---- Payload for the client-side plot ------------------------------------- + +# Payload for the client-side breakend circos: list(data, n_links, n_genes, chroms, reason); data is NULL when there is nothing, or too much, to draw +bnd_circos_data = function(links, genes = NULL, cytobands, chrom_lengths, chromosomes) { + + fail = function(reason) list(data = NULL, n_links = 0L, n_genes = 0L, + chroms = character(0), reason = reason) + + if (is.null(links) || nrow(links) == 0) + return(fail("No breakends with two mapped loci — nothing to draw arcs between.")) + if (nrow(links) > BND_CIRCOS_MAX_LINKS) + return(fail(sprintf(paste("%s breakend arcs is more than this plot can show", + "(limit %s). Select a gene panel above for a filtered", + "report, or read the table below."), + nrow(links), BND_CIRCOS_MAX_LINKS))) + + b = copy(as.data.table(links)) + chroms = chromosomes[chromosomes %in% unique(c(b$chrom_a, b$chrom_b))] + chroms = chroms[chroms %in% unique(cytobands$chrom)] + b = b[chrom_a %in% chroms & chrom_b %in% chroms] + if (nrow(b) == 0 || length(chroms) == 0) + return(fail("No breakends on the chromosomes this report plots.")) + chroms = chromosomes[chromosomes %in% unique(c(b$chrom_a, b$chrom_b))] + + lens = chrom_lengths[chroms] + # Clamp a locus past its sector end rather than dropping the row + b[, `:=`(pos_a = pmin(pmax(as.numeric(pos_a), 1), lens[chrom_a]), + pos_b = pmin(pmax(as.numeric(pos_b), 1), lens[chrom_b]))] + + cy = as.data.table(cytobands)[chrom %in% chroms] + setorder(cy, chrom, start) + + g = if (is.null(genes)) data.table() else as.data.table(genes)[chrom %in% chroms] + if (nrow(g) > 0) setorder(g, chrom, start, gene) + + list( + data = list( + chromosomes = js_vec(chroms), + lengths = js_vec(as.numeric(lens)), + cytobands = js_rows(cy, c("chrom", "start", "end", "stain")), + links = js_rows(b, c("id", "svclass", "chrom_a", "pos_a", "chrom_b", "pos_b")), + genes = if (nrow(g) > 0) js_rows(g, c("chrom", "start", "end", "gene", "panels")) + else "[]" + ), + n_links = nrow(b), + n_genes = nrow(g), + chroms = chroms, + reason = NULL + ) +} + +# The ") +} diff --git a/assets/lrsomatic_report/R/locate_outputs.R b/assets/lrsomatic_report/R/locate_outputs.R new file mode 100644 index 00000000..09de5948 --- /dev/null +++ b/assets/lrsomatic_report/R/locate_outputs.R @@ -0,0 +1,110 @@ +# Locate per-tool output files under sample_dir by filename suffix (recursive); missing optional files are NULL + +locate_outputs = function(sample_dir, sample_id) { + d = sample_dir # shorthand + + # First recursive hit under `root` matching a filename pattern + find1 = function(pattern, root = d) { + hits = list.files(root, pattern = pattern, recursive = TRUE, full.names = TRUE) + if (length(hits) > 0) hits[1] else NULL + } + + # Same, but excluding anything under a normal/ subtree (tumor-side QC) + find1_tumor = function(pattern) { + hits = list.files(d, pattern = pattern, recursive = TRUE, full.names = TRUE) + hits = hits[!grepl("/normal/", hits)] + if (length(hits) > 0) hits[1] else NULL + } + + # Normal-side files, matched on the path component since their directory has moved over time + find1_normal = function(pattern) { + hits = list.files(d, pattern = pattern, recursive = TRUE, full.names = TRUE) + hits = hits[grepl("/normal/", hits)] + if (length(hits) > 0) hits[1] else NULL + } + + # --- small variants ------------------------------------------------------- + vep_somatic = find1("_SOMATIC_VEP\\.vcf\\.gz$") + + # VAF/depth/phasing come from the VCF VEP annotated: prefer the phased somatic VCF, fall back to raw ClairS(-TO) output (may be several paths) + somatic_vaf_vcf = { + phased = file.path(d, "variants", "phased", "somatic_smallvariants.vcf.gz") + if (file.exists(phased)) phased else { + vcfs = list.files(d, pattern = "\\.vcf\\.gz$", recursive = TRUE, full.names = TRUE) + named = vcfs[grepl("/clairs(to)?/somatic\\.vcf\\.gz$", vcfs)] + any_c = vcfs[grepl("/clairs(to)?/", vcfs) & !grepl("/germline\\.vcf\\.gz$", vcfs)] + if (length(named) > 0) named[1] else if (length(any_c) > 0) any_c else NULL + } + } + + # --- structural variants: located by R/sections/sv.R --- + + # --- ASCAT ---------------------------------------------------------------- + ascat_segments_raw = find1("\\.segments_raw\\.txt$") + ascat_purityploidy = find1("\\.purityploidy\\.txt$") + ascat_plots = list( + profile = find1("\\.tumour\\.ASCATprofile\\.png$"), + rawprofile = find1("\\.tumour\\.rawprofile\\.png$"), + sunrise = find1("\\.tumour\\.sunrise\\.png$"), + aspcf = find1("\\.tumour\\.ASPCF\\.png$"), + before_gc = find1("\\.before_correction\\..*\\.tumour\\.tumour\\.png$"), + after_gc = find1("\\.after_correction_gc.*\\.tumour\\.tumour\\.png$"), + tumour_sep = find1("^tumorSep.*\\.tumour\\.png$") + ) + + # --- QC (tumor side) -------------------------------------------------------- + mosdepth_summary = find1_tumor("\\.mosdepth\\.summary\\.txt$") + mosdepth_dist = find1_tumor("\\.mosdepth\\.global\\.dist\\.txt$") + cramino_aln = find1_tumor("_cramino\\.txt$") + flagstat = find1_tumor("\\.flagstat$") + samtools_stats = find1_tumor("\\.stats$") + + # --- Normal-side QC (matched mode only) ----------------------------------- + normal_mosdepth_summary = find1_normal("\\.mosdepth\\.summary\\.txt$") + normal_mosdepth_dist = find1_normal("\\.mosdepth\\.global\\.dist\\.txt$") + normal_cramino = find1_normal("_cramino\\.txt$") + normal_flagstat = find1_normal("\\.flagstat$") + normal_samtools_stats = find1_normal("\\.stats$") + + # Driven by what was found: the QC comparison renders only if there is normal data + has_normal = !is.null(normal_mosdepth_summary) || !is.null(normal_cramino) + + # Run mode derived from the same evidence; its only consumer is the header badge + mode = if (has_normal) "matched" else "tumour-only" + + # --- Wakhan (optional) ----------------------------------------------------- + wakhan_dir = file.path(d, "wakhan") + has_wakhan = dir.exists(wakhan_dir) + wakhan_solutions = if (has_wakhan) { + f = file.path(wakhan_dir, "solutions_ranks.tsv") + if (file.exists(f)) f else NULL + } else NULL + wakhan_heatmap = if (has_wakhan) { + hits = Sys.glob(file.path(wakhan_dir, "*heatmap_ploidy_purity.html")) + if (length(hits) > 0) hits[1] else NULL + } else NULL + + list( + mode = mode, + vep_somatic = vep_somatic, + somatic_vaf_vcf = somatic_vaf_vcf, + ascat_segments = ascat_segments_raw, + ascat_purityploidy = ascat_purityploidy, + mosdepth_summary = mosdepth_summary, + mosdepth_dist = mosdepth_dist, + cramino = cramino_aln, + flagstat = flagstat, + samtools_stats = samtools_stats, + has_normal = has_normal, + ascat_plots = ascat_plots, + normal_mosdepth_summary = normal_mosdepth_summary, + normal_mosdepth_dist = normal_mosdepth_dist, + normal_cramino = normal_cramino, + normal_flagstat = normal_flagstat, + normal_samtools_stats = normal_samtools_stats, + has_wakhan = has_wakhan, + wakhan_dir = wakhan_dir, + wakhan_solutions = wakhan_solutions, + wakhan_heatmap = wakhan_heatmap + ) +} diff --git a/assets/lrsomatic_report/R/parse_ascat.R b/assets/lrsomatic_report/R/parse_ascat.R new file mode 100644 index 00000000..eff2d60c --- /dev/null +++ b/assets/lrsomatic_report/R/parse_ascat.R @@ -0,0 +1,57 @@ +suppressPackageStartupMessages({ + library(data.table) +}) + +# Parse ASCAT raw segments (segments_raw.txt) +parse_ascat_segments = function(segments_file) { + if (is.null(segments_file) || !file.exists(segments_file)) return(NULL) + dt = fread(segments_file, sep = "\t", header = TRUE) + + # Normalise column names to lowercase + setnames(dt, tolower(names(dt))) + + # Add chr prefix if missing + dt[, chr := ensure_chr_prefix(as.character(chr))] + + # Column names after tolower(): naraw, nbraw + dt[, total_cn := pmin(naraw + nbraw, 4)] + dt[, major_cn := pmin(naraw, 4)] + dt[, minor_cn := pmin(nbraw, 4)] + + dt +} + +# Parse ASCAT purity/ploidy file +parse_ascat_purityploidy = function(pp_file) { + if (is.null(pp_file) || !file.exists(pp_file)) return(list(purity = NA_real_, ploidy = NA_real_)) + dt = fread(pp_file, sep = "\t", header = TRUE) + setnames(dt, tolower(names(dt))) + list( + purity = round(as.numeric(dt$aberrantcellfraction[1]), 3), + ploidy = round(as.numeric(dt$ploidy[1]), 3) + ) +} + +# Parse Wakhan's ranked purity/ploidy solutions table (wakhan/solutions_ranks.tsv) +parse_wakhan_solutions = function(tsv_file) { + if (is.null(tsv_file) || !file.exists(tsv_file)) return(NULL) + dt = fread(tsv_file, sep = "\t", header = TRUE) + if (nrow(dt) == 0) return(NULL) + setorder(dt, solution_rank) + dt +} + +# Locate each solution's genome copy-number plot; try solution_/ first to avoid the aliased duplicate directory +locate_wakhan_cn_plots = function(wakhan_dir, solutions_dt) { + if (is.null(wakhan_dir) || is.null(solutions_dt) || nrow(solutions_dt) == 0) return(list()) + out = lapply(seq_len(nrow(solutions_dt)), function(i) { + row = solutions_dt[i] + sdir = file.path(wakhan_dir, paste0("solution_", row$solution_rank)) + if (!dir.exists(sdir)) sdir = file.path(wakhan_dir, row$repository_name) + if (!dir.exists(sdir)) return(NULL) + hits = list.files(sdir, pattern = "genome_copynumbers_breakpoints\\.html$", full.names = TRUE) + if (length(hits) == 0) return(NULL) + list(rank = row$solution_rank, purity = row$cell_purity, ploidy = row$ploidy, plot = hits[1]) + }) + Filter(Negate(is.null), out) +} diff --git a/assets/lrsomatic_report/R/parse_qc.R b/assets/lrsomatic_report/R/parse_qc.R new file mode 100644 index 00000000..7bf42bc0 --- /dev/null +++ b/assets/lrsomatic_report/R/parse_qc.R @@ -0,0 +1,111 @@ +suppressPackageStartupMessages({ + library(data.table) +}) + +# Parse mosdepth summary; `keep_chroms` avoids a bare "^chr" match (admits decoys, empty on chr-less references) +parse_mosdepth_summary = function(summary_file, keep_chroms = NULL) { + if (is.null(summary_file) || !file.exists(summary_file)) { + return(list(mean_depth = NA_real_, table = data.table())) + } + dt = fread(summary_file, sep = "\t", header = TRUE) + setnames(dt, tolower(names(dt))) + total_row = dt[chrom == "total"] + mean_depth = if (nrow(total_row) > 0) total_row$mean[1] else NA_real_ + + # Keep per-chromosome rows (exclude region-level and total) + chr_rows = dt[chrom != "total" & !grepl("_region", chrom)] + if (!is.null(keep_chroms) && length(keep_chroms) > 0) { + chr_rows = chr_rows[ensure_chr_prefix(chrom) %in% ensure_chr_prefix(keep_chroms)] + } else { + chr_rows = chr_rows[grepl("^chr", chrom)] + } + total_length = if (nrow(total_row) > 0) total_row$length[1] else NA_real_ + total_bases = if (nrow(total_row) > 0) total_row$bases[1] else NA_real_ + list(mean_depth = round(mean_depth, 2), total_length = total_length, total_bases = total_bases, table = chr_rows) +} + +# Parse mosdepth global distribution (*.mosdepth.global.dist.txt) +parse_mosdepth_dist = function(dist_file) { + if (is.null(dist_file) || !file.exists(dist_file)) return(NULL) + dt = fread(dist_file, sep = "\t", header = FALSE, + col.names = c("chrom", "coverage", "fraction")) + dt +} + +# Parse cramino alignment report +parse_cramino = function(cramino_file) { + if (is.null(cramino_file) || !file.exists(cramino_file)) { + return(list(n50 = NA_real_, yield_gb = NA_real_, + mapped_pct = NA_real_, n_reads = NA_integer_)) + } + lines = readLines(cramino_file, warn = FALSE) + get_val = function(pattern) { + hit = grep(pattern, lines, value = TRUE, ignore.case = TRUE) + if (length(hit) == 0) return(NA_character_) + trimws(sub(paste0(".*", pattern, "\\s*"), "", hit[1], ignore.case = TRUE)) + } + + # Cramino outputs key\tvalue pairs + dt = tryCatch( + fread(cramino_file, sep = "\t", header = FALSE, col.names = c("key", "value"), fill = TRUE), + error = function(e) NULL + ) + if (is.null(dt)) return(list(n50 = NA_real_, yield_gb = NA_real_, + mapped_pct = NA_real_, n_reads = NA_integer_)) + + get_field = function(pattern) { + row = dt[grepl(pattern, key, ignore.case = TRUE)] + if (nrow(row) == 0) NA_character_ else as.character(row$value[1]) + } + + list( + n50 = suppressWarnings(as.numeric(get_field("N50"))), + yield_gb = suppressWarnings(as.numeric(get_field("Yield"))), + mapped_pct = suppressWarnings(as.numeric(sub("%", "", get_field("% from total")))), + n_reads = suppressWarnings(as.integer(get_field("Number of reads"))) + ) +} + +# Parse samtools flagstat +parse_flagstat = function(flagstat_file) { + if (is.null(flagstat_file) || !file.exists(flagstat_file)) return(list()) + lines = readLines(flagstat_file, warn = FALSE) + out = list() + for (line in lines) { + count = suppressWarnings(as.integer(sub(" .*", "", trimws(line)))) + if (grepl("in total", line)) out$total = count + if (grepl("mapped \\(", line)) out$mapped = count + if (grepl("paired in seq", line)) out$paired = count + if (grepl("secondary", line)) out$secondary = count + if (grepl("supplementary", line)) out$supplementary = count + if (grepl("duplicate", line)) out$duplicate = count + } + out +} + +# Parse samtools stats (*.stats), SN summary lines only +parse_samtools_stats = function(stats_file) { + if (is.null(stats_file) || !file.exists(stats_file)) return(NULL) + lines = readLines(stats_file, warn = FALSE) + sn = lines[startsWith(lines, "SN\t")] + get_sn = function(key) { + hit = grep(paste0("^SN\t", key, ":\t"), sn, value = TRUE) + if (length(hit) == 0) return(NA_real_) + suppressWarnings(as.numeric(trimws(sub(paste0("^SN\t", key, ":\t([^\t#]+).*"), "\\1", hit[1])))) + } + reads_total = get_sn("raw total sequences") + reads_mapped = get_sn("reads mapped") + mapped_pct = if (!is.na(reads_total) && reads_total > 0) + round(reads_mapped / reads_total * 100, 2) else NA_real_ + list( + reads_total = reads_total, + reads_mapped = reads_mapped, + mapped_pct = mapped_pct, + total_length = get_sn("total length"), + bases_mapped = get_sn("bases mapped \\(cigar\\)"), + error_rate = get_sn("error rate"), + avg_length = get_sn("average length"), + max_length = get_sn("maximum length"), + avg_quality = get_sn("average quality") + ) +} diff --git a/assets/lrsomatic_report/R/parse_severus.R b/assets/lrsomatic_report/R/parse_severus.R new file mode 100644 index 00000000..73004dc0 --- /dev/null +++ b/assets/lrsomatic_report/R/parse_severus.R @@ -0,0 +1,452 @@ +suppressPackageStartupMessages({ + library(data.table) +}) + +# Severus writes both mates as separate records and tags single breakends "sBND"; both are collapsed here so downstream sees one row per rearrangement +BND_SVTYPES = c("BND", "sBND") + +# BND-derived svclass values (two loci, no span/size); BND_CIRCOS_CLASSES is this set minus "single breakend" +SV_JUNCTION_CLASSES = c("translocation", "intra-chr breakend", "single breakend") + +# Panel-matching windows: single source of truth for sv_panel_hits() and the client-side filter +SV_PANEL_WINDOW_BND = 1e6 # distance from either breakend of a BND +SV_PANEL_WINDOW_OTHER = 1e5 # distance from the span of a DEL/DUP/INV/INS + +# Read a VCF's data records; empty data.table for a header-only VCF +.severus_read_vcf = function(vcf_file, col_names) { + con = gzfile(vcf_file, "rb") + skip_n = 0L + repeat { + line = readLines(con, n = 1, warn = FALSE) + if (length(line) == 0) break + if (startsWith(line, "#CHROM")) break + skip_n = skip_n + 1L + } + close(con) + + # fread() errors when skip lands on the last line (no records) + dt = tryCatch( + fread(vcf_file, skip = skip_n + 1L, sep = "\t", header = FALSE), + error = function(e) data.table() + ) + if (nrow(dt) == 0) return(data.table()) + + # Name columns positionally: a VCF without FORMAT/SAMPLE columns must not read as zero SVs + n = min(ncol(dt), length(col_names)) + setnames(dt, seq_len(n), col_names[seq_len(n)]) + for (nm in setdiff(col_names, names(dt))) dt[, (nm) := NA_character_] + dt[, ..col_names] +} + +# One INFO sub-field per record, NA where absent (length-preserving, unlike bare regmatches()) +.info_val = function(info_vec, key) { + m = regexpr(paste0("(?:^|;)", key, "=([^;]+)"), info_vec, perl = TRUE) + out = rep(NA_character_, length(info_vec)) + hit = m > 0 + if (any(hit)) out[hit] = sub(".*=", "", regmatches(info_vec, m)) + out +} + +# Partner locus from ALT bracket notation (all four forms, with or without "chr"); NA for a single breakend +.bnd_partner = function(alt) { + pat = "^.*?[\\[\\]]([^\\[\\]:]+):([0-9]+)[\\[\\]].*$" + has = grepl(pat, alt, perl = TRUE) + list( + chrom = ensure_chr_prefix(ifelse(has, sub(pat, "\\1", alt, perl = TRUE), NA_character_)), + pos = ifelse(has, suppressWarnings(as.integer(sub(pat, "\\2", alt, perl = TRUE))), + NA_integer_) + ) +} + +# Parse the somatic Severus VCF into one row per rearrangement: id, id_b, svtype, svclass, chrom_a, pos_a, chrom_b, pos_b, sv_len, vaf +parse_severus_somatic_records = function(vcf_file) { + if (is.null(vcf_file) || !file.exists(vcf_file)) return(data.table()) + + dt = .severus_read_vcf(vcf_file, c("CHROM", "POS", "ID", "REF", "ALT", "QUAL", + "FILTER", "INFO", "FORMAT", "SAMPLE1")) + if (nrow(dt) == 0) return(data.table()) + + dt[, CHROM := ensure_chr_prefix(CHROM)] + dt[, SVTYPE := .info_val(INFO, "SVTYPE")] + dt[, is_bnd := SVTYPE %in% BND_SVTYPES] + + # END and SVLEN are optional; create the columns unconditionally + dt[, `:=`(END = NA_integer_, SVLEN = NA_integer_)] + dt[grepl("END=", INFO, fixed = TRUE), END := as.integer(.info_val(INFO, "END"))] + dt[grepl("SVLEN=", INFO, fixed = TRUE), SVLEN := as.integer(.info_val(INFO, "SVLEN"))] + dt[is.na(END), END := POS] + + # Partner locus: from ALT for a BND, the SV's own end otherwise + partner = .bnd_partner(dt$ALT) + dt[, `:=`(chrom_b = fifelse(is_bnd, partner$chrom, CHROM), + pos_b = fifelse(is_bnd, partner$pos, as.integer(END)))] + + dt[, mate_id := .info_val(INFO, "MATE_ID")] + + # Group mates on the unordered {ID, MATE_ID} pair (fallback: shared `_1`/`_2` stem); non-pairs stay as singletons + dt[, pair_key := fifelse(!is.na(mate_id), + paste(pmin(ID, mate_id), pmax(ID, mate_id), sep = "|"), + sub("_[12]$", "", ID))] + dt[, side_rank := fifelse(grepl("_1$", ID), 1L, 2L)] + dt[, n_in_pair := .N, by = pair_key] + if (any(dt$n_in_pair > 2L)) { + message("Severus VCF: ", sum(dt$n_in_pair > 2L), + " records share a mate group with more than two members; kept unpaired.") + dt[n_in_pair > 2L, pair_key := ID] + dt[, n_in_pair := .N, by = pair_key] + } + setorder(dt, pair_key, side_rank, ID) + dt = dt[dt[, .I[1L], by = pair_key]$V1] + + # The mate's record ID, which is what the per-side VEP annotation is keyed on. + dt[, id_b := fifelse(n_in_pair == 2L & !is.na(mate_id), mate_id, NA_character_)] + + dt[, svclass := fcase( + is_bnd & is.na(chrom_b), "single breakend", + is_bnd & chrom_b != CHROM, "translocation", + is_bnd, "intra-chr breakend", + default = SVTYPE + )] + + # VAF from FORMAT/SAMPLE1, split format-group by format-group as in parse_caller_vcf() + fmt_groups = unique(dt$FORMAT) + vaf_list = rep(NA_real_, nrow(dt)) + for (fmt in fmt_groups) { + idx_rows = which(dt$FORMAT == fmt) + fields = strsplit(fmt, ":", fixed = TRUE)[[1]] + vaf_idx = match("VAF", fields) + if (is.na(vaf_idx)) next + split_s = strsplit(dt$SAMPLE1[idx_rows], ":", fixed = TRUE) + vaf_list[idx_rows] = vapply(split_s, function(x) + if (length(x) >= vaf_idx) suppressWarnings(as.numeric(x[vaf_idx])) else NA_real_, + numeric(1)) + } + dt[, VAF := vaf_list] + + dt[, .(id = ID, id_b, svtype = SVTYPE, svclass, + chrom_a = CHROM, pos_a = POS, chrom_b, pos_b, + sv_len = SVLEN, vaf = VAF)] +} + +# Circos tracks from the collapsed records: BND links and a non-BND track with colour/y-position +severus_circos_tracks = function(records) { + empty = list(translocations = data.table(), nontrans = data.table()) + if (is.null(records) || nrow(records) == 0) return(empty) + + is_bnd = records$svtype %in% BND_SVTYPES + + trans = records[is_bnd & !is.na(chrom_b) & !is.na(pos_b), + .(chrom = chrom_a, pos = pos_a, chrom2 = chrom_b, pos2 = pos_b)] + # Dedup on the unordered endpoint pair so a VCF without MATE_ID cannot draw an arc twice + if (nrow(trans) > 0) { + a = paste(trans$chrom, trans$pos, sep = ":") + b = paste(trans$chrom2, trans$pos2, sep = ":") + trans = unique(trans[, .link_key := paste(pmin(a, b), pmax(a, b))], + by = ".link_key")[, .link_key := NULL] + } + + SV_COL = c(INS = "#f97e02", DEL = "#020272", INV = "#e7cc02", DUP = "#e41a1c") + SV_YPOS = c(INS = 1.0, DEL = 0.66, INV = 0.33, DUP = 0.05) + nontrans = records[!is_bnd, + .(chrom = chrom_a, pos = pos_a, end = pos_b, svtype, svlen = sv_len, + circos_pos = unname(SV_YPOS[svtype]), circos_col = unname(SV_COL[svtype]))] + + list(translocations = trans, nontrans = nontrans) +} + +# SV display table: mate-collapsed records plus per-breakend VEP symbols, joined on record ID (locus only as fallback); panel matching is on coordinates, see sv_panel_hits() +build_sv_table_from_vep = function(records, vep_sv_vcf) { + if (is.character(records)) records = parse_severus_somatic_records(records) + if (is.null(records) || nrow(records) == 0) return(data.table()) + + sv = copy(records) + out_cols = c("id", "svclass", "svtype", "chrom_a", "pos_a", "gene_a", + "chrom_b", "pos_b", "gene_b", "sv_len", "vaf", + "consequence", "impact") + + vep = parse_vep_vcf(vep_sv_vcf) + if (is.null(vep) || nrow(vep) == 0) { + sv[, `:=`(gene_a = NA_character_, gene_b = NA_character_, + consequence = NA_character_, impact = NA_character_)] + return(sv[, ..out_cols]) + } + + # Highest-impact annotation first, so annot[1] below is the one that survives. + impact_rank = c(HIGH = 1L, MODERATE = 2L, LOW = 3L, MODIFIER = 4L) + vep[, impact_rank := impact_rank[impact]] + vep[is.na(impact_rank), impact_rank := 5L] + setorder(vep, impact_rank) + + collapse_genes = function(x) { + g = unique(x[!is.na(x) & nzchar(x)]) + if (length(g) == 0) NA_character_ else paste(g, collapse = ",") + } + + by_id = if ("id" %in% names(vep) && any(!is.na(vep$id))) { + vep[!is.na(id) & nzchar(id), .(gene = collapse_genes(symbol), + consequence = consequence[1], impact = impact[1]), + by = .(id)] + } else NULL + + by_locus = vep[, .(gene = collapse_genes(symbol), + consequence = consequence[1], impact = impact[1]), + by = .(chrom, pos)] + + # Key choice is made once for the whole table, not per side + use_id = !is.null(by_id) && any(c(sv$id, sv$id_b) %in% by_id$id) + + # Records filtered out on the annotation side simply get no symbols + side_annot = function(ids, chroms, positions) { + src = if (use_id) by_id else by_locus + m = if (use_id) match(ids, by_id$id) + else match(paste(chroms, positions), paste(by_locus$chrom, by_locus$pos)) + res = data.table(gene = NA_character_, consequence = NA_character_, + impact = NA_character_)[rep(1L, length(chroms))] + hit = !is.na(m) + if (any(hit)) res[hit, `:=`(gene = src$gene[m[hit]], + consequence = src$consequence[m[hit]], + impact = src$impact[m[hit]])] + res + } + + a = side_annot(sv$id, sv$chrom_a, sv$pos_a) + b = side_annot(sv$id_b, sv$chrom_b, sv$pos_b) + + sv[, `:=`(gene_a = a$gene, gene_b = b$gene)] + # Consequence/impact describe the rearrangement, taken from the higher-impact side. + rank_of = function(x) { r = unname(impact_rank[x]); r[is.na(r)] = 5L; r } + use_b = rank_of(b$impact) < rank_of(a$impact) + sv[, `:=`(consequence = fifelse(use_b, b$consequence, a$consequence), + impact = fifelse(use_b, b$impact, a$impact))] + + sv[, ..out_cols] +} + +# Readable locus/size/genes columns: span (DEL/DUP/INV/INS) vs junction (BND) is decided by svclass, not by chromosome; returns locus, locus_sort, size, size_bp, genes +sv_display_columns = function(sv_table, chrom_levels = NULL) { + empty = data.table(locus = character(), locus_sort = character(), + size = character(), size_bp = numeric(), genes = character()) + if (is.null(sv_table) || nrow(sv_table) == 0) return(empty) + + d = as.data.table(sv_table) + need = c("svclass", "chrom_a", "pos_a", "chrom_b", "pos_b", "sv_len", + "gene_a", "gene_b") + absent = setdiff(need, names(d)) + if (length(absent) > 0) + stop("sv_display_columns(): sv_table is missing ", paste(absent, collapse = ", ")) + + is_junction = d$svclass %in% SV_JUNCTION_CLASSES + pa = suppressWarnings(as.numeric(d$pos_a)) + pb = suppressWarnings(as.numeric(d$pos_b)) + + # formatC(), not format(): format() pads to a common width + bp = function(x) formatC(x, format = "d", big.mark = ",") + at = function(chrom, pos) paste0(chrom, ":", bp(pos)) + + locus = fcase( + is.na(pa) | is.na(d$chrom_a), NA_character_, + d$svclass == "single breakend", paste0(at(d$chrom_a, pa), " (unpaired)"), + is_junction, + # An arrow, not a dash: the two loci are joined, not a span; both sides named so a per-column search matches either + fifelse(is.na(pb) | is.na(d$chrom_b), + paste0(at(d$chrom_a, pa), " (unpaired)"), + paste0(at(d$chrom_a, pa), + fifelse(d$svclass == "translocation", " → ", " ↔ "), + at(d$chrom_b, pb))), + # A contiguous type: one span. An INS has END == POS, so it is a single point. + default = fifelse(is.na(pb) | pb <= pa, + at(d$chrom_a, pa), + paste0(at(d$chrom_a, pa), "–", bp(pb))) + ) + + # SVLEN where Severus wrote one — an INS's length is *not* its span — else the span. + len = suppressWarnings(as.numeric(d$sv_len)) + size_bp = fifelse(is_junction, NA_real_, fifelse(!is.na(len), abs(len), pb - pa)) + # as.character(): fmt_bp() is ifelse()-based and returns logical on an all-NA size_bp + size = as.character(fmt_bp(size_bp)) + + split_genes = function(x) { + if (is.na(x) || !nzchar(x)) return(character()) + g = trimws(strsplit(x, ",", fixed = TRUE)[[1]]) + unique(g[nzchar(g)]) + } + # Middot rather than spaces: DT escapes   and HTML collapses whitespace + genes = vapply(seq_len(nrow(d)), function(i) { + a = split_genes(d$gene_a[i]); b = split_genes(d$gene_b[i]) + if (!is_junction[i]) return(paste(unique(c(a, b)), collapse = ", ")) + sides = c(if (length(a)) paste0("A: ", paste(a, collapse = ",")), + if (length(b)) paste0("B: ", paste(b, collapse = ","))) + paste(sides, collapse = " · ") + }, character(1)) + + rank = if (length(chrom_levels)) match(d$chrom_a, chrom_levels) + else rep(NA_integer_, nrow(d)) + rank[is.na(rank)] = 999L + locus_sort = fifelse(is.na(pa), "", sprintf("%03d:%011.0f", rank, pa)) + + data.table(locus = fifelse(is.na(locus), "", locus), + locus_sort = locus_sort, + size = fifelse(is.na(size), "", size), + size_bp = size_bp, + genes = genes) +} + +# Panel hits per SV row as "GENE (side, how)" labels ("" = none): coordinate panels match within the windows, symbol-only panels on VEP symbols; several panels union and add a " [name]" suffix. Mirrored by svPanelHits() in templates/per_sample.qmd +sv_panel_hits = function(sv_table, panels, + bnd_window = SV_PANEL_WINDOW_BND, + other_window = SV_PANEL_WINDOW_OTHER) { + n = if (is.null(sv_table)) 0L else nrow(sv_table) + if (n == 0) return(character(0)) + + ps = .as_panel_list(panels) + if (length(ps) == 0) return(rep("", n)) + if (length(ps) == 1) return(.sv_panel_hits_one(sv_table, ps[[1]], "", bnd_window, other_window)) + + per_panel = lapply(names(ps), function(nm) + .sv_panel_hits_one(sv_table, ps[[nm]], paste0(" [", nm, "]"), bnd_window, other_window)) + vapply(seq_len(n), function(i) { + parts = unique(unlist(lapply(per_panel, `[[`, i), use.names = FALSE)) + paste(parts[nzchar(parts)], collapse = ", ") + }, character(1)) +} + +# A panel object and a list of panels are both plain lists; tell them apart by load_gene_panel()'s fields +.as_panel_list = function(panels) { + if (is.null(panels) || length(panels) == 0) return(list()) + if (!is.null(panels$genes) || !is.null(panels$has_coords)) { + nm = if (!is.null(panels$name)) as.character(panels$name)[1] else "panel" + return(setNames(list(panels), nm)) + } + ps = panels[!vapply(panels, is.null, logical(1))] + if (is.null(names(ps))) names(ps) = paste0("panel", seq_along(ps)) + ps +} + +# One panel's per-row labels. `tag` is appended to every label ("" for a lone panel). +.sv_panel_hits_one = function(sv_table, panel, tag = "", + bnd_window = SV_PANEL_WINDOW_BND, + other_window = SV_PANEL_WINDOW_OTHER) { + n = nrow(sv_table) + if (is.null(panel)) return(rep("", n)) + + label = function(genes, side, how) paste0(genes, " (", side, ", ", how, ")", tag) + + if (!isTRUE(panel$has_coords)) { + symbols = toupper(panel$genes) + hit_side = function(col) { + if (!col %in% names(sv_table)) return(rep("", n)) + vapply(sv_table[[col]], function(cell) { + if (is.na(cell) || !nzchar(cell)) return("") + g = trimws(unlist(strsplit(toupper(as.character(cell)), "[;,]+"))) + g = unique(g[g %in% symbols]) + if (length(g) == 0) "" else paste(g, collapse = ",") + }, character(1), USE.NAMES = FALSE) + } + ha = hit_side("gene_a"); hb = hit_side("gene_b") + # A VEP symbol sits on the breakend itself, so a symbol hit is always direct + return(vapply(seq_len(n), function(i) { + parts = c(if (nzchar(ha[i])) label(ha[i], "A", "direct"), + if (nzchar(hb[i])) label(hb[i], "B", "direct")) + paste(parts, collapse = ", ") + }, character(1))) + } + + iv = panel_intervals(panel) + if (is.null(iv) || nrow(iv) == 0) return(rep("", n)) + + is_bnd = sv_table$svtype %in% BND_SVTYPES + # `start`/`end` are window-padded for foverlaps(); `qlo`/`qhi` carry the unpadded locus for the distance + q = rbindlist(list( + # Each BND breakend gets its own window (the sides may be on different contigs) + data.table(row = which(is_bnd), side = "A", + chrom = sv_table$chrom_a[is_bnd], + start = sv_table$pos_a[is_bnd] - bnd_window, + end = sv_table$pos_a[is_bnd] + bnd_window, + qlo = sv_table$pos_a[is_bnd], + qhi = sv_table$pos_a[is_bnd]), + data.table(row = which(is_bnd), side = "B", + chrom = sv_table$chrom_b[is_bnd], + start = sv_table$pos_b[is_bnd] - bnd_window, + end = sv_table$pos_b[is_bnd] + bnd_window, + qlo = sv_table$pos_b[is_bnd], + qhi = sv_table$pos_b[is_bnd]), + # Other types are contiguous: one window around the whole span. + data.table(row = which(!is_bnd), side = "span", + chrom = sv_table$chrom_a[!is_bnd], + start = pmin(sv_table$pos_a[!is_bnd], sv_table$pos_b[!is_bnd]) - other_window, + end = pmax(sv_table$pos_a[!is_bnd], sv_table$pos_b[!is_bnd]) + other_window, + qlo = pmin(sv_table$pos_a[!is_bnd], sv_table$pos_b[!is_bnd]), + qhi = pmax(sv_table$pos_a[!is_bnd], sv_table$pos_b[!is_bnd])) + )) + q = q[!is.na(chrom) & !is.na(start) & !is.na(end)] + if (nrow(q) == 0) return(rep("", n)) + q[, start := pmax(as.numeric(start), 0)] + q[, end := as.numeric(end)] + q[, `:=`(qlo = as.numeric(qlo), qhi = as.numeric(qhi))] + iv = copy(iv) + iv[, `:=`(start = as.numeric(start), end = as.numeric(end))] + setkey(iv, chrom, start, end) + + ov = data.table::foverlaps(q, iv, by.x = c("chrom", "start", "end"), + type = "any", nomatch = NULL) + if (nrow(ov) == 0) return(rep("", n)) + + # `start`/`end` are the gene's interval here (foverlaps() renamed the query to i.start/i.end) + ov[, gap := pmax(0, pmax(start - qhi, qlo - end))] + ov[, how := fifelse(gap == 0, "direct", fmt_bp(gap))] + + per_row = ov[, .(hit = paste(unique(label(gene, side, how)), collapse = ", ")), by = row] + out = rep("", n) + out[per_row$row] = per_row$hit + out +} + +# Parse the gene-annotated Severus TSV (filtered_SV2/SV_filtered_with_gene_annotations.tsv) +parse_severus_gene_tsv = function(tsv_file) { + if (is.null(tsv_file) || !file.exists(tsv_file)) return(NULL) + dt = fread(tsv_file, sep = "\t", header = TRUE, fill = TRUE) + setnames(dt, toupper(names(dt))) + + if ("START_CHROM" %in% names(dt)) dt[, START_CHROM := ensure_chr_prefix(START_CHROM)] + if ("END_CHROM" %in% names(dt)) dt[, END_CHROM := ensure_chr_prefix(END_CHROM)] + + # Gene column: prefer NHL hits + gene_col = if ("NHL_GENE_HITS" %in% names(dt)) "NHL_GENE_HITS" + else if ("COSMIC_GENE_HITS" %in% names(dt)) "COSMIC_GENE_HITS" + else NULL + dt[, gene_hits := if (!is.null(gene_col)) get(gene_col) else NA_character_] + dt +} + +# SV display table from the gene-annotated Severus TSV, mapped onto the same column contract as the VEP path +build_sv_table = function(sv_tsv) { + if (is.null(sv_tsv) || nrow(sv_tsv) == 0) return(data.table()) + + col = function(nm, default = NA) if (nm %in% names(sv_tsv)) sv_tsv[[nm]] else default + chrom_a = ensure_chr_prefix(as.character(col("START_CHROM", NA_character_))) + chrom_b = ensure_chr_prefix(as.character(col("END_CHROM", NA_character_))) + svtype = as.character(col("SVTYPE", NA_character_)) + + data.table( + id = as.character(col("ID", NA_character_)), + svclass = fcase( + is.na(chrom_a) | is.na(chrom_b), svtype, + svtype %in% BND_SVTYPES & chrom_a != chrom_b, "translocation", + svtype %in% BND_SVTYPES, "intra-chr breakend", + default = svtype + ), + svtype = svtype, + chrom_a = chrom_a, + pos_a = suppressWarnings(as.integer(col("START_POS", NA_integer_))), + # The TSV's gene hits are span-level, with no per-breakend split — hence side A only. + gene_a = as.character(if ("NHL_GENE_HITS" %in% names(sv_tsv)) sv_tsv$NHL_GENE_HITS + else col("COSMIC_GENE_HITS", NA_character_)), + chrom_b = chrom_b, + pos_b = suppressWarnings(as.integer(col("END_POS", NA_integer_))), + gene_b = NA_character_, + sv_len = suppressWarnings(as.integer(col("SV_LEN", NA_integer_))), + vaf = suppressWarnings(as.numeric(col("VAF", NA_real_))), + consequence = as.character(col("DETAILED_TYPE", NA_character_)), + impact = NA_character_ + ) +} diff --git a/assets/lrsomatic_report/R/parse_smallvariants.R b/assets/lrsomatic_report/R/parse_smallvariants.R new file mode 100644 index 00000000..d829c210 --- /dev/null +++ b/assets/lrsomatic_report/R/parse_smallvariants.R @@ -0,0 +1,476 @@ +suppressPackageStartupMessages({ + library(data.table) + library(dplyr) +}) + +# INFO/CALLER values that denote a somatic caller (the merged VEP VCF is mostly germline records); ClairS is "clairs" or "clairs-to" +SOMATIC_CALLERS = c("clairs", "clairs-to", "clairsto", "deepsomatic") + +# Derive dbsnp/cosmic columns from VEP's Existing_variation list +derive_dbsnp_cosmic = function(dt) { + dt[, dbsnp := sub("(rs[0-9]+).*", "\\1", existing)] + dt[!grepl("^rs", dbsnp, perl = TRUE), dbsnp := NA_character_] + + dt[, cosmic := sub(".*(COS[VM][0-9]+).*", "\\1", existing)] + dt[!grepl("^COS", cosmic, perl = TRUE), cosmic := NA_character_] + dt +} + +# Dispatch on file contents: VEP text output (#Uploaded_variation header) vs VCF with CSQ (#CHROM header) +parse_vep = function(vep_file) { + if (is.null(vep_file) || !file.exists(vep_file)) return(NULL) + + con = gzfile(vep_file, "rb") + is_vcf = FALSE + repeat { + line = readLines(con, n = 1, warn = FALSE) + if (length(line) == 0) break + if (startsWith(line, "#Uploaded_variation")) break + if (startsWith(line, "#CHROM")) { is_vcf = TRUE; break } + } + close(con) + + if (is_vcf) parse_vep_vcf(vep_file) else parse_vep_text(vep_file) +} + +# Parse VEP default text output (tab-delimited, not a VCF); one row per consequence per variant +parse_vep_text = function(vep_file) { + if (is.null(vep_file) || !file.exists(vep_file)) return(NULL) + + # Count meta-lines (start with ##) to find the column-header line + con = gzfile(vep_file, "rb") + skip_n = 0L + repeat { + line = readLines(con, n = 1, warn = FALSE) + if (length(line) == 0) break + if (startsWith(line, "#Uploaded_variation")) break + skip_n = skip_n + 1L + } + close(con) + + dt = tryCatch( + fread(vep_file, skip = skip_n, sep = "\t", header = TRUE, + col.names = function(x) gsub("^#", "", x)), + error = function(e) { + message("Failed to parse VEP file: ", conditionMessage(e)) + NULL + } + ) + if (is.null(dt) || nrow(dt) == 0) return(NULL) + + setnames(dt, old = "Uploaded_variation", new = "variant_id", skip_absent = TRUE) + setnames(dt, old = "Gene", new = "gene_id", skip_absent = TRUE) + setnames(dt, old = "Consequence", new = "consequence", skip_absent = TRUE) + + # Coordinates and alleles both from variant_id where it has the canonical shape; Location is off by one for dash-form insertions, so it is only the fallback + vid = "^.+_[0-9]+_[^_]+/[^_]+$" + dt[, from_vid := grepl(vid, variant_id)] + + dt[, chrom := ifelse(from_vid, sub("_[0-9]+_[^_]+$", "", variant_id), + sub(":.*", "", Location))] + dt[, pos := as.integer(ifelse(from_vid, sub(".*_([0-9]+)_[^_]+$", "\\1", variant_id), + sub(".*:(\\d+).*", "\\1", Location)))] + dt[, chrom := ensure_chr_prefix(chrom)] + + dt[, ref := sub(".*_([^/]+)/.*", "\\1", variant_id)] + dt[, alt := sub(".*/", "", variant_id)] + + # Parse VEP Extra key=value field + dt[, symbol := extract_extra_key(Extra, "SYMBOL")] + dt[, impact := extract_extra_key(Extra, "IMPACT")] + dt[, existing := extract_extra_key(Extra, "Existing_variation")] + dt[, sift := extract_extra_key(Extra, "SIFT")] + dt[, polyphen := extract_extra_key(Extra, "PolyPhen")] + dt[, hgvsp := extract_extra_key(Extra, "HGVSp")] + + # dbSNP / COSMIC IDs, derived from Existing_variation + dt = derive_dbsnp_cosmic(dt) + + # No per-variant caller in the text format; kept for contract parity with parse_vep_vcf() + dt[, caller := NA_character_] + + # Record identity for parity with parse_vep_vcf(): VEP's own Uploaded_variation name, never a caller ID + dt[, id := variant_id] + + # chrom/pos/ref/alt are in VEP notation (indels shifted, possibly dash-form); see coord_space in build_variant_table() + dt[, coord_space := "vep"] + + dt +} + +# Parse a VCF with VEP CSQ annotation; same column contract as parse_vep_text() +parse_vep_vcf = function(vep_file) { + if (is.null(vep_file) || !file.exists(vep_file)) return(NULL) + + # Skip header to #CHROM, capturing the CSQ field order and whether a CALLER tag exists + con = gzfile(vep_file, "rb") + skip_n = 0L + csq_format = NULL + has_caller_info = FALSE + repeat { + line = readLines(con, n = 1, warn = FALSE) + if (length(line) == 0) break + if (startsWith(line, "##INFO= 0) csq_format = strsplit(sub("^Format: ", "", m), "|", fixed = TRUE)[[1]] + } + if (startsWith(line, "##INFO= 0) { + if (length(not_normal) > 1L || is.null(sample_id)) + warning("VCF '", vcf_file, "' has samples [", paste(samples, collapse = ", "), + "]; reading '", samples[not_normal[1]], "'.") + return(not_normal[1]) + } + warning("VCF '", vcf_file, "' has samples [", paste(samples, collapse = ", "), + "] and none looks like a tumour; reading '", samples[1], "'.") + 1L +} + +# Allele fraction from whichever FORMAT tag is present: LRSomatic renames AF/VAF per caller (STANDARDIZE_AF); AD is the last resort +allele_fraction = function(field, fields) { + for (tag in c("AF", "VAF")) { + if (tag %in% fields) { + # Multi-allelic: the first value pairs with the first ALT, which is all this table joins on + v = suppressWarnings(as.numeric(sub(",.*$", "", field(tag)))) + if (any(!is.na(v))) return(v) + } + } + if ("AD" %in% fields) { + ad = strsplit(field("AD"), ",", fixed = TRUE) + return(vapply(ad, function(x) { + n = suppressWarnings(as.numeric(x)) + if (length(n) < 2L || anyNA(n[1:2]) || sum(n[1:2]) == 0) return(NA_real_) + n[2] / sum(n[1:2]) + }, numeric(1))) + } + rep(NA_real_, length(field("GT"))) +} + +# Parse raw caller VCF(s) into chrom, pos, ref, alt, vaf, dp, gt, ps, caller; several paths are stacked (ClairS splits snvs/indels). `sample_id` selects the column by name so a matched VCF never reports the normal's values +parse_caller_vcf = function(vcf_file, caller_name = "unknown", sample_id = NULL) { + if (is.null(vcf_file)) return(NULL) + if (length(vcf_file) > 1) { + parts = lapply(vcf_file, parse_caller_vcf, caller_name = caller_name, + sample_id = sample_id) + parts = parts[!vapply(parts, is.null, logical(1))] + return(if (length(parts) > 0) rbindlist(parts) else NULL) + } + if (!file.exists(vcf_file)) return(NULL) + + # Count header lines, keeping the #CHROM line itself — it carries the sample names. + con = gzfile(vcf_file, "rb") + skip_n = 0L + chrom_line = NULL + repeat { + line = readLines(con, n = 1, warn = FALSE) + if (length(line) == 0) break + if (startsWith(line, "#CHROM")) { chrom_line = line; break } + skip_n = skip_n + 1L + } + close(con) + if (is.null(chrom_line)) return(NULL) + + header = strsplit(chrom_line, "\t", fixed = TRUE)[[1]] + samples = if (length(header) > 9L) header[10:length(header)] else character(0) + # Sites-only VCF: no genotypes, return NULL + if (length(samples) == 0) return(NULL) + + sample_col = pick_sample_column(samples, sample_id, vcf_file) + + # 1:9 are the fixed VCF columns; the chosen sample sits at 9 + its index. + col_names = c("CHROM", "POS", "ID", "REF", "ALT", "QUAL", "FILTER", "INFO", "FORMAT", + "SAMPLE1") + dt = tryCatch( + fread(vcf_file, skip = skip_n + 1L, sep = "\t", header = FALSE, + select = c(1:9, 9L + sample_col), col.names = col_names), + error = function(e) { + warning("Could not read VCF '", vcf_file, "': ", conditionMessage(e)) + NULL + }) + if (is.null(dt) || nrow(dt) == 0) return(NULL) + + dt[, CHROM := ensure_chr_prefix(CHROM)] + + # Extract AF/DP/GT/PS from FORMAT + SAMPLE, format-group by format-group + fmt_groups = unique(dt$FORMAT) + vaf_list = rep(NA_real_, nrow(dt)) + dp_list = rep(NA_integer_, nrow(dt)) + gt_list = rep(NA_character_, nrow(dt)) + ps_list = rep(NA_character_, nrow(dt)) + + for (fmt in fmt_groups) { + idx_rows = which(dt$FORMAT == fmt) + fields = strsplit(fmt, ":", fixed = TRUE)[[1]] + split_s = strsplit(dt$SAMPLE1[idx_rows], ":", fixed = TRUE) + + # One FORMAT field, by name, across this group's rows + field = function(name) { + i = match(name, fields) + if (is.na(i)) return(rep(NA_character_, length(split_s))) + vapply(split_s, function(x) if (length(x) >= i) x[i] else NA_character_, + character(1)) + } + + vaf_list[idx_rows] = allele_fraction(field, fields) + dp_list[idx_rows] = suppressWarnings(as.integer(field("DP"))) + gt_list[idx_rows] = field("GT") + ps_list[idx_rows] = field("PS") + } + + # Blank the unphased placeholders ("." PS, "/" GT) so cells render empty + ps_list[!is.na(ps_list) & ps_list == "."] = NA_character_ + gt_list[!is.na(gt_list) & gt_list %in% c(".", "./.")] = NA_character_ + + data.table(chrom = dt$CHROM, pos = dt$POS, ref = dt$REF, alt = dt$ALT, + vaf = vaf_list, dp = dp_list, gt = gt_list, ps = ps_list, + caller = caller_name) +} + +# Header-only provenance for the VCF(s) supplying VAF/DP/GT/PS (after a consensus merge the FORMAT fields need not match the `callers` column); NULL when there is nothing to describe +vaf_provenance = function(vcf_files, sample_dir = NULL, sample_id = NULL) { + if (is.null(vcf_files) || length(vcf_files) == 0) return(NULL) + vcf_files = vcf_files[!is.na(vcf_files) & nzchar(vcf_files)] + if (length(vcf_files) == 0) return(NULL) + + # Paths read better relative to the sample directory the caller passed in. + rel = function(p) { + if (is.null(sample_dir) || !nzchar(sample_dir)) return(p) + root = sub("/+$", "", normalizePath(sample_dir, mustWork = FALSE)) + full = normalizePath(p, mustWork = FALSE) + if (startsWith(full, paste0(root, "/"))) substring(full, nchar(root) + 2L) else p + } + + # "##source=..." is optional colour; many VCFs carry none + read_sources = function(p) { + if (!file.exists(p)) return(character(0)) + con = gzfile(p, "rb") + on.exit(close(con), add = TRUE) + out = character(0) + repeat { + line = readLines(con, n = 1, warn = FALSE) + if (length(line) == 0) break + if (!startsWith(line, "##")) break # #CHROM or a malformed header ends the scan + if (startsWith(line, "##source=")) out = c(out, sub("^##source=", "", line)) + } + out + } + + # Which sample column parse_caller_vcf() read; named in the footnote because a wrong pick is otherwise invisible + read_sample = function(p) { + if (!file.exists(p)) return(NA_character_) + con = gzfile(p, "rb") + on.exit(close(con), add = TRUE) + repeat { + line = readLines(con, n = 1, warn = FALSE) + if (length(line) == 0) return(NA_character_) + if (startsWith(line, "#CHROM")) { + header = strsplit(line, "\t", fixed = TRUE)[[1]] + if (length(header) <= 9L) return(NA_character_) + samples = header[10:length(header)] + # Only worth reporting when there was a choice to get wrong. + if (length(samples) == 1L) return(NA_character_) + return(samples[suppressWarnings(pick_sample_column(samples, sample_id, p))]) + } + if (!startsWith(line, "##")) return(NA_character_) + } + } + chosen = unique(unlist(lapply(vcf_files, read_sample))) + chosen = chosen[!is.na(chosen)] + + list( + paths = unname(vapply(vcf_files, rel, character(1))), + sources = unique(unlist(lapply(vcf_files, read_sources))), + sample = chosen + ) +} + +# Canonical variant key joining VEP rows to VCF records: VEP reports indels at anchor + 1 with raw or dash-trimmed alleles; all forms reconcile as trimmed alleles at anchor + 1, SNVs/MNVs verbatim. `space` is "vcf" or "vep" +variant_key = function(chrom, pos, ref, alt, space = c("vcf", "vep")) { + space = match.arg(space) + ref = toupper(as.character(ref)); alt = toupper(as.character(alt)) + pos = as.integer(pos) + + trim = function(x) { t = substr(x, 2L, nchar(x)); ifelse(t == "", "-", t) } + + dash = ref == "-" | alt == "-" # already trimmed by VEP + is_indel = dash | nchar(ref) != nchar(alt) + + # Raw allele pairs still need the anchor base dropped; dash forms are already trimmed. + need_trim = is_indel & !dash + + # Only the VCF side needs shifting — VEP has already done it. + key_pos = ifelse(space == "vcf" & is_indel, pos + 1L, pos) + key_ref = ifelse(need_trim, trim(ref), ref) + key_alt = ifelse(need_trim, trim(alt), alt) + + paste(chrom, key_pos, key_ref, key_alt, sep = "|") +} + +# Classify SNV into 6 SBS mutation categories (C/T-ref normalised) +classify_mut = function(ref, alt) { + comp = c(A = "T", T = "A", C = "G", G = "C") + ref = toupper(ref); alt = toupper(alt) + use_comp = !(ref %in% c("C", "T")) + norm_ref = ifelse(use_comp, comp[ref], ref) + norm_alt = ifelse(use_comp, comp[alt], alt) + paste0(norm_ref, ">", norm_alt) +} + +# Small-variant display table: VEP rows with VAF/depth/phasing joined from the annotated VCF; gene_panel filters symbols (NULL = all) +build_variant_table = function(vep_data, vaf_data, gene_panel = NULL) { + if (is.null(vep_data) || nrow(vep_data) == 0) return(NULL) + + # Impact ranking for deduplication + impact_rank = c(HIGH = 1L, MODERATE = 2L, LOW = 3L, MODIFIER = 4L) + vep_data[, impact_rank := impact_rank[impact]] + vep_data[is.na(impact_rank), impact_rank := 5L] + + # Filter to gene panel (by gene symbol or Ensembl ID fallback) + if (!is.null(gene_panel)) { + if (length(gene_panel) > 0) { + vep_data = vep_data[symbol %in% gene_panel | gene_id %in% gene_panel] + } else { + vep_data = vep_data[FALSE] # Empty panel → empty result + } + } + if (nrow(vep_data) == 0) return(data.table()) + + # Keep best consequence per variant×gene (lowest impact rank) + key_cols = c("chrom", "pos", "ref", "alt", "symbol") + setorder(vep_data, impact_rank) + vep_data = unique(vep_data, by = key_cols) + + # Join on the canonical key; the coordinate space is declared by each parser (text = vep, CSQ = vcf), never assumed + vep_space = if ("coord_space" %in% names(vep_data)) unique(vep_data$coord_space) else "vep" + stopifnot(length(vep_space) == 1L, vep_space %in% c("vep", "vcf")) + vep_data[, join_key := variant_key(chrom, pos, ref, alt, space = vep_space)] + + if (!is.null(vaf_data) && nrow(vaf_data) > 0) { + vdt = vaf_data[, .(join_key = variant_key(chrom, pos, ref, alt, space = "vcf"), + vaf, dp, gt, ps)] + vdt = unique(vdt, by = "join_key") + vep_data = merge(vep_data, vdt, by = "join_key", all.x = TRUE) + } else { + vep_data[, `:=`(vaf = NA_real_, dp = NA_integer_, + gt = NA_character_, ps = NA_character_)] + } + + # Which caller reported each variant (INFO/CALLER); empty on the VEP text path + if ("caller" %in% names(vep_data) && any(!is.na(vep_data$caller))) { + vep_data[, callers := caller] + } else { + vep_data[, callers := ""] + } + + # Mutation category for SNVs + vep_data[nchar(ref) == 1 & nchar(alt) == 1, + mut_cat := classify_mut(ref, alt)] + + display_cols = c("symbol", "chrom", "pos", "ref", "alt", + "consequence", "impact", "hgvsp", + "vaf", "dp", "gt", "ps", + "callers", "cosmic", "dbsnp", "sift", "polyphen") + display_cols = display_cols[display_cols %in% names(vep_data)] + vep_data[, ..display_cols] +} diff --git a/assets/lrsomatic_report/R/references.R b/assets/lrsomatic_report/R/references.R new file mode 100644 index 00000000..8d6c579a --- /dev/null +++ b/assets/lrsomatic_report/R/references.R @@ -0,0 +1,69 @@ +suppressPackageStartupMessages({ + library(data.table) +}) + +# Load cytobands for a given reference; returns data.frame suitable for circlize +load_cytobands = function(reference, assets_dir) { + ref = tolower(reference) + path = file.path(assets_dir, "references", ref, "cytobands.tsv") + if (!file.exists(path)) stop("No cytobands for reference '", ref, "': ", path) + dt = fread(path, header = FALSE, sep = "\t", + col.names = c("chrom", "start", "end", "name", "stain")) + as.data.frame(dt) +} + +# Load chromosome lengths; returns named integer vector (name = chrom, value = length) +load_chrom_lengths = function(reference, assets_dir) { + ref = tolower(reference) + path = file.path(assets_dir, "references", ref, "chrom_lengths.tsv") + if (!file.exists(path)) stop("No chrom_lengths for reference '", ref, "': ", path) + dt = fread(path, header = FALSE, sep = "\t", col.names = c("chrom", "length")) + setNames(as.integer(dt$length), dt$chrom) +} + +# Auto-detect reference from VCF/VEP headers (chr1 length: CHM13v2 248387328, GRCh38 248956422; assembly/genome_build lines) +detect_reference = function(vcf_file) { + if (!file.exists(vcf_file)) { + message("Cannot auto-detect reference: file not found, defaulting to t2t") + return("t2t") + } + con = gzfile(vcf_file, "rb") + on.exit(close(con)) + header_lines = character(0) + for (i in seq_len(2000)) { + line = tryCatch(readLines(con, n = 1, warn = FALSE), error = function(e) character(0)) + if (length(line) == 0 || !startsWith(line, "##")) break + header_lines = c(header_lines, line) + } + + # 1. Check VEP "## assembly version" line + asm_line = grep("assembly version|genome_build|assembly=", header_lines, + value = TRUE, ignore.case = TRUE) + if (length(asm_line) > 0) { + asm = tolower(paste(asm_line, collapse = " ")) + if (grepl("t2t|chm13", asm)) return("t2t") + if (grepl("grch38|hg38|38", asm)) return("hg38") + } + + # 2. Check ##contig chr1 length (standard VCF) + contig_chr1 = grep("ID=chr1[^0-9].*length=|ID=1[^0-9].*length=", + header_lines, value = TRUE, perl = TRUE) + if (length(contig_chr1) > 0) { + len = as.integer(sub(".*length=([0-9]+).*", "\\1", contig_chr1[1])) + if (!is.na(len)) { + if (abs(len - 248387328L) < 1000L) return("t2t") + if (abs(len - 248956422L) < 1000L) return("hg38") + } + } + + message("Could not determine reference from file headers, defaulting to t2t") + "t2t" +} + +# Build the chromosome list for plotting based on sex +chromosomes_for_sex = function(sex) { + sex = tolower(trimws(sex)) + autosomes = paste0("chr", 1:22) + if (sex %in% c("male", "xy")) c(autosomes, "chrX", "chrY") + else c(autosomes, "chrX") +} diff --git a/assets/lrsomatic_report/R/sections.R b/assets/lrsomatic_report/R/sections.R new file mode 100644 index 00000000..5aab2eb6 --- /dev/null +++ b/assets/lrsomatic_report/R/sections.R @@ -0,0 +1,21 @@ +# Section-module contract: id, title, locate(sample_dir, sample_id), parse(inputs, section_data); see CLAUDE.md + +SECTIONS = list() + +register_section = function(descriptor) { + SECTIONS[[descriptor$id]] <<- descriptor +} + +# Quiet "nothing to show" notice; `warn` marks a genuine failure +section_notice = function(msg, warn = FALSE) { + tags$div(class = if (warn) "section-notice section-notice--warn" else "section-notice", msg) +} + +# Collapsed provenance/caveats under a table; `summary` names the contents +table_details = function(..., summary = "Details") { + tags$details( + class = "table-details", + tags$summary(summary), + tags$div(class = "table-footnote", ...) + ) +} diff --git a/assets/lrsomatic_report/R/sections/sv.R b/assets/lrsomatic_report/R/sections/sv.R new file mode 100644 index 00000000..0e8d2f08 --- /dev/null +++ b/assets/lrsomatic_report/R/sections/sv.R @@ -0,0 +1,63 @@ +# Structural variants section (reference implementation of the section-module contract), keyed by caller + +register_section(list( + id = "sv", + title = "Structural variants", + + locate = function(sample_dir, sample_id) { + d = sample_dir + + find1 = function(pattern) { + hits = list.files(d, pattern = pattern, recursive = TRUE, full.names = TRUE) + if (length(hits) > 0) hits[1] else NULL + } + + severus_vcf = find1("^severus_somatic\\.vcf\\.gz$") + severus_gene_tsv = find1("^SV_filtered_with_gene_annotations\\.tsv$") + # VEP SV VCF is the usual annotation source; the gene-annotated TSV is the fallback + severus_vep_vcf = find1("_SV_VEP\\.vcf\\.gz$") + + list(callers = list( + severus = list(vcf = severus_vcf, gene_tsv = severus_gene_tsv, vep_vcf = severus_vep_vcf) + )) + }, + + parse = function(inputs, section_data) { + tabs = list() + circ = list(nontrans = data.table(), translocations = data.table()) + annotation_path = NULL + + for (nm in names(inputs$callers)) { + caller_inputs = inputs$callers[[nm]] + + # One parse feeds both the table and the circos tracks + records = parse_severus_somatic_records(caller_inputs$vcf) + + if (nrow(records) > 0) { + # A missing VEP SV VCF only empties the symbol columns; panel matching is on coordinates + t = build_sv_table_from_vep(records, caller_inputs$vep_vcf) + if (!is.null(caller_inputs$vep_vcf)) annotation_path = caller_inputs$vep_vcf + } else { + # No caller VCF: fall back to the gene-annotated TSV + t = build_sv_table(parse_severus_gene_tsv(caller_inputs$gene_tsv)) + if (nrow(t) > 0) annotation_path = caller_inputs$gene_tsv + } + + if (!is.null(t) && nrow(t) > 0) { + t[, caller := nm] + tabs[[nm]] = t + } + # Circos tracks from the same collapsed records; last-write-wins is a no-op with one caller + circ = severus_circos_tracks(records) + } + + tbl = if (length(tabs) > 0) rbindlist(tabs, fill = TRUE) else data.table() + + list( + table = tbl, + circos = circ, + annotation_path = annotation_path, + annotation_found = !is.null(annotation_path) + ) + } +)) diff --git a/assets/lrsomatic_report/R/sections/whatshap.R b/assets/lrsomatic_report/R/sections/whatshap.R new file mode 100644 index 00000000..1000651a --- /dev/null +++ b/assets/lrsomatic_report/R/sections/whatshap.R @@ -0,0 +1,50 @@ +# Phasing section (WhatsHap stats from qc/whatshap_stats/); these are germline statistics + +register_section(list( + id = "whatshap", + title = "Phasing", + + locate = function(sample_dir, sample_id) { + d = sample_dir + + find1 = function(pattern) { + hits = list.files(d, pattern = pattern, recursive = TRUE, full.names = TRUE) + if (length(hits) > 0) hits[1] else NULL + } + + # qc/whatshap_stats/ is not tumour/normal-scoped, so a plain recursive match is correct + list(stats_tsv = find1("_whatshap_stats\\.tsv$")) + }, + + parse = function(inputs, section_data) { + f = inputs$stats_tsv + if (is.null(f) || !file.exists(f)) return(NULL) + + dt = tryCatch( + fread(f, sep = "\t", header = TRUE), + error = function(e) { + message("Failed to parse WhatsHap stats: ", conditionMessage(e)) + NULL + } + ) + if (is.null(dt) || nrow(dt) == 0) return(NULL) + + # The header line is "#sample\tchromosome\t..." — fread keeps the leading "#". + setnames(dt, sub("^#", "", names(dt))) + if (!"chromosome" %in% names(dt)) { + message("WhatsHap stats has no 'chromosome' column; skipping section") + return(NULL) + } + + # bp_per_block_sum reads as integer64, which DT renders badly; widen to double + for (col in names(dt)) { + if (inherits(dt[[col]], "integer64")) dt[, (col) := as.numeric(get(col))] + } + + list( + per_chrom = dt[chromosome != "ALL"], + all = if (any(dt$chromosome == "ALL")) as.list(dt[chromosome == "ALL"][1]) else NULL, + vcf = if ("file_name" %in% names(dt)) dt$file_name[1] else NA_character_ + ) + } +)) diff --git a/assets/lrsomatic_report/R/utils.R b/assets/lrsomatic_report/R/utils.R new file mode 100644 index 00000000..8ed78deb --- /dev/null +++ b/assets/lrsomatic_report/R/utils.R @@ -0,0 +1,504 @@ +suppressPackageStartupMessages({ + library(data.table) +}) + +# Type-stable: fread() may read CHROM as integer and ifelse() on all-NA returns logical +ensure_chr_prefix = function(x) { + x = as.character(x) + out = as.character(ifelse(startsWith(x, "chr"), x, paste0("chr", x))) + out[is.na(x)] = NA_character_ + out +} + +strip_chr_prefix = function(x) { + sub("^chr", "", x) +} + +# Parse VEP "Extra" key=value semicolon-delimited field into a named character vector +parse_extra_kv = function(extra_string) { + if (is.na(extra_string) || extra_string == "" || extra_string == "-") return(character(0)) + pairs = strsplit(extra_string, ";", fixed = TRUE)[[1]] + kv = strsplit(pairs, "=", fixed = TRUE) + keys = vapply(kv, `[`, character(1), 1) + vals = vapply(kv, function(x) if (length(x) >= 2) paste(x[-1], collapse = "=") else "", character(1)) + setNames(vals, keys) +} + +# Vectorised: extract one key from VEP Extra column for each row +extract_extra_key = function(extra_vec, key) { + vapply(extra_vec, function(x) { + kv = parse_extra_kv(x) + if (key %in% names(kv)) kv[[key]] else NA_character_ + }, character(1), USE.NAMES = FALSE) +} + +# ---- Gene panels: plain lists (they round-trip through Quarto execute_params) of name, path, reference, has_coords, genes and, when has_coords, parallel chrom/start/end/interval_gene ---- + +# Canonical reference names; a coordinate panel declares one and it is checked against the render +normalise_reference_name = function(x) { + if (is.null(x) || length(x) != 1 || is.na(x) || !nzchar(trimws(x))) return(NA_character_) + x = tolower(trimws(x)) + if (x %in% c("t2t", "chm13", "chm13v2", "chm13v2.0", "t2t-chm13")) return("t2t") + if (x %in% c("hg38", "grch38", "hg38-noalt")) return("hg38") + x +} + +# Reference suffix of a builtin panel filename; list(name, reference), reference NA if unsuffixed +.split_panel_filename = function(path) { + stem = tools::file_path_sans_ext(basename(path)) + parts = strsplit(stem, ".", fixed = TRUE)[[1]] + if (length(parts) >= 2) { + ref = normalise_reference_name(parts[length(parts)]) + if (!is.na(ref) && ref %in% c("t2t", "hg38")) + return(list(name = paste(parts[-length(parts)], collapse = "."), reference = ref)) + } + list(name = stem, reference = NA_character_) +} + +# Read the leading "#" comment block of a panel TSV (may declare "# reference: hg38") +.panel_header = function(path) { + lines = readLines(path, warn = FALSE) + n_comment = 0L + declared = NA_character_ + for (ln in lines) { + if (!startsWith(ln, "#")) break + n_comment = n_comment + 1L + m = regmatches(ln, regexpr("^#\\s*reference\\s*:\\s*\\S+", ln)) + if (length(m) > 0) declared = sub("^#\\s*reference\\s*:\\s*", "", m) + } + list(n_comment = n_comment, reference = declared) +} + +# Load a gene panel TSV: `gene` column required; chrom/start/end all-or-nothing; a coordinate panel declaring another reference errors, one declaring none loads as "" +load_gene_panel = function(path, reference = NULL) { + if (!file.exists(path)) stop("Gene panel file not found: ", path) + + hdr = .panel_header(path) + dt = tryCatch( + fread(path, header = TRUE, sep = "\t", fill = TRUE, skip = hdr$n_comment), + error = function(e) fread(path, header = FALSE, sep = "\t", fill = TRUE, + skip = hdr$n_comment) + ) + if (nrow(dt) == 0 && ncol(dt) == 0) stop("Gene panel file is empty: ", path) + + # copy(): setnames() rewrites the names vector in place + orig_names = copy(names(dt)) + setnames(dt, tolower(names(dt))) + setnames(dt, old = c("chr", "chromosome"), new = c("chrom", "chrom"), skip_absent = TRUE) + + if ("gene" %in% names(dt)) { + genes = as.character(dt[["gene"]]) + } else if (ncol(dt) == 1) { + # Headerless one-column list: fread consumed the first symbol as the column name, put it back + genes = c(orig_names[1], as.character(dt[[1]])) + } else { + genes = as.character(dt[[1]]) + } + genes = trimws(genes) + keep = nzchar(genes) & !is.na(genes) & genes != "-" + + coord_cols = c("chrom", "start", "end") + present = intersect(coord_cols, names(dt)) + if (length(present) > 0 && length(present) < 3) { + stop("Gene panel ", path, " carries coordinate column(s) ", + paste(present, collapse = ", "), " but not all of ", + paste(coord_cols, collapse = ", "), + ". Supply all three, or none for symbol-only matching.") + } + has_coords = length(present) == 3 + + # A `reference` column is an alternative to the "# reference:" comment line. + declared = hdr$reference + if (is.na(declared) && "reference" %in% names(dt)) { + vals = unique(trimws(as.character(dt[["reference"]]))) + vals = vals[nzchar(vals) & !is.na(vals)] + if (length(vals) > 1) + stop("Gene panel ", path, " declares more than one reference: ", + paste(vals, collapse = ", ")) + if (length(vals) == 1) declared = vals + } + declared_norm = normalise_reference_name(declared) + want = normalise_reference_name(reference) + + # Only coordinate panels are reference-specific; a symbol-only panel is agnostic. + if (has_coords && !is.na(declared_norm) && !is.na(want) && declared_norm != want) { + stop("Gene panel ", path, " declares reference '", declared_norm, + "' but the report is being rendered against '", want, + "'. Panel coordinates are only valid for the reference they were built on.") + } + + out = list( + name = .split_panel_filename(path)$name, + path = path, + reference = if (is.na(declared_norm)) "" else declared_norm, + has_coords = has_coords, + genes = unique(genes[keep]) + ) + + if (has_coords) { + chrom = ensure_chr_prefix(trimws(as.character(dt[["chrom"]]))) + start = suppressWarnings(as.integer(dt[["start"]])) + end = suppressWarnings(as.integer(dt[["end"]])) + bad = keep & (is.na(chrom) | !nzchar(chrom) | is.na(start) | is.na(end)) + if (any(bad)) + stop("Gene panel ", path, " has missing or non-numeric coordinates for: ", + paste(utils::head(genes[bad], 5), collapse = ", "), + if (sum(bad) > 5) paste0(" (and ", sum(bad) - 5L, " more)") else "") + out$chrom = chrom[keep] + out$start = start[keep] + out$end = end[keep] + # `genes` is deduplicated; the interval vectors are not (one symbol can carry several loci) + out$interval_gene = genes[keep] + } + + out +} + +# Panel intervals as a keyed data.table, or NULL for a symbol-only panel. +panel_intervals = function(panel) { + if (is.null(panel) || !isTRUE(panel$has_coords)) return(NULL) + dt = data.table(gene = as.character(panel$interval_gene), + chrom = as.character(panel$chrom), + start = as.integer(panel$start), + end = as.integer(panel$end)) + setkey(dt, chrom, start, end) + dt +} + +# Is a --gene-panel argument the "no filtering" sentinel? +is_no_gene_panel = function(panel_arg) { + is.null(panel_arg) || length(panel_arg) != 1 || is.na(panel_arg) || + identical(tolower(trimws(panel_arg)), "none") +} + +# Path of a builtin panel, preferring the `reference`-specific variant; NULL if none +builtin_panel_path = function(assets_dir, name, reference = NULL) { + ref = normalise_reference_name(reference) + dir = file.path(assets_dir, "gene_lists") + candidates = c(if (!is.na(ref)) file.path(dir, paste0(name, ".", ref, ".tsv")), + file.path(dir, paste0(name, ".tsv"))) + hit = candidates[file.exists(candidates)] + if (length(hit) > 0) hit[1] else NULL +} + +# Resolve a --gene-panel arg: "none", a builtin name, or a TSV path; anything else errors +resolve_gene_panel = function(panel_arg, assets_dir, reference = NULL) { + if (is_no_gene_panel(panel_arg)) return(NULL) + builtin = builtin_panel_path(assets_dir, panel_arg, reference) + if (!is.null(builtin)) return(load_gene_panel(builtin, reference)) + if (file.exists(panel_arg)) return(load_gene_panel(panel_arg, reference)) + stop("Gene panel not found (tried builtin '", panel_arg, "' and as file path)") +} + +# Load all builtin panels, resolving reference-specific files to one entry and skipping panels not shipped for this reference +load_all_gene_panels = function(assets_dir, reference = NULL) { + tsv_files = Sys.glob(file.path(assets_dir, "gene_lists", "*.tsv")) + if (length(tsv_files) == 0) return(list()) + + meta = lapply(tsv_files, .split_panel_filename) + ref = normalise_reference_name(reference) + + panels = list() + for (nm in unique(vapply(meta, `[[`, character(1), "name"))) { + idx = which(vapply(meta, `[[`, character(1), "name") == nm) + refs = vapply(meta[idx], function(m) m$reference, character(1)) + pick = if (!is.na(ref) && any(refs == ref, na.rm = TRUE)) idx[which(refs == ref)[1]] + else if (any(is.na(refs))) idx[which(is.na(refs))[1]] + else NA_integer_ + if (is.na(pick)) { + message("Gene panel '", nm, "' ships only for reference(s) ", + paste(unique(refs), collapse = ", "), " — not offered for ", + if (is.na(ref)) "an unknown reference" else ref) + next + } + p = tryCatch(load_gene_panel(tsv_files[pick], reference), + error = function(e) { + message("Skipping gene panel '", nm, "': ", conditionMessage(e)); NULL }) + if (!is.null(p)) panels[[nm]] = p + } + panels +} + +# Non-colliding key for a user panel: the first collision gets "-custom", further ones are numbered +unique_panel_name = function(nm, taken) { + if (!(nm %in% taken)) return(nm) + cand = paste0(nm, "-custom") + i = 1L + while (cand %in% taken) { + i = i + 1L + cand = paste0(nm, "-custom", i) + } + cand +} + +# Resolve selected panel keys to panel objects, re-read from disk (the YAML round trip list-ifies the vectors); not tryCatch-wrapped so an unresolvable panel fails the render +resolve_selected_panels = function(keys, all_panels, assets_dir, reference = NULL) { + keys = setdiff(as.character(unlist(keys)), "__all__") + keys = keys[!is.na(keys) & nzchar(keys)] + if (length(keys) == 0) return(list()) + out = list() + for (k in unique(keys)) { + p = if (!is.null(all_panels)) all_panels[[k]] else NULL + path = if (!is.null(p) && !is.null(p$path)) as.character(p$path)[1] else NA_character_ + out[[k]] = if (!is.na(path) && file.exists(path)) load_gene_panel(path, reference) + else resolve_gene_panel(k, assets_dir, reference) + } + out[!vapply(out, is.null, logical(1))] +} + +# Pull every occurrence of a repeatable flag out of argv (optparse has no action="append"); accepts `--flag value` and `--flag=value` +extract_repeated_option = function(args, flag) { + args = as.character(args) + vals = character(0) + rest = character(0) + i = 1L + while (i <= length(args)) { + a = args[i] + if (identical(a, flag)) { + if (i == length(args)) stop(flag, " requires a value") + vals = c(vals, args[i + 1L]) + i = i + 2L + } else if (startsWith(a, paste0(flag, "="))) { + vals = c(vals, substring(a, nchar(flag) + 2L)) + i = i + 1L + } else { + rest = c(rest, a) + i = i + 1L + } + } + list(values = vals, rest = rest) +} + +# ---- Small JS serialisation helpers: the R table and the JS indexing it are generated from the same object ---- + +js_quote = function(x) paste0('"', gsub('"', '\\\\"', as.character(x)), '"') + +# {"col":0,"other":1} — column name to zero-based index, for a rownames=FALSE DT. +js_col_index_map = function(nms) { + if (length(nms) == 0) return("{}") + paste0("{", paste0(js_quote(nms), ":", seq_along(nms) - 1L, collapse = ","), "}") +} + +# One JS number literal per element; element-wise so format() cannot pad or switch to scientific notation +js_num = function(x) { + vapply(x, function(v) { + if (is.na(v)) "null" else format(v, scientific = FALSE, trim = TRUE) + }, character(1), USE.NAMES = FALSE) +} + +.js_cell = function(v) if (is.numeric(v)) js_num(v) else ifelse(is.na(v), "null", js_quote(v)) + +# JS array literal from an atomic vector (numbers bare, NA as null); hand-written to avoid a jsonlite dependency +js_vec = function(x) { + if (length(x) == 0) return("[]") + paste0("[", paste(.js_cell(x), collapse = ","), "]") +} + +# JS array of arrays, one per row of `dt`, columns in `cols` order (row-major to keep the payload small) +js_rows = function(dt, cols) { + if (is.null(dt) || nrow(dt) == 0) return("[]") + cells = lapply(cols, function(cl) .js_cell(dt[[cl]])) + rows = do.call(paste, c(cells, sep = ",")) + paste0("[[", paste(rows, collapse = "],["), "]]") +} + +# VEP impact severity order, as used by the styleEqual() palettes +IMPACT_LEVELS = c("HIGH", "MODERATE", "LOW", "MODIFIER") + +# Distinct-value bounds for offering a dropdown; outside them a column keeps its text filter +FACET_MIN_VALUES = 2L +FACET_MAX_VALUES = 200L + +# Distinct values with row counts for the tickbox column filters (assets/js/facet_filter.js): `seps` splits a column into tokens, `levels` fixes value order; returns a JS object literal {col: {sep, values: [[value, n], ...]}} with null as the "(none)" bucket. Columns absent or outside the FACET_*_VALUES bounds are omitted with a message +js_facet_defs = function(dt, cols, seps = character(0), levels = list()) { + if (is.null(dt) || nrow(dt) == 0 || length(cols) == 0) return("{}") + entries = character(0) + + for (nm in cols) { + if (!nm %in% names(dt)) { + message("Facet column '", nm, "' is not in the table - no value filter for it.") + next + } + sp = if (nm %in% names(seps)) seps[[nm]] else NA_character_ + v = as.character(dt[[nm]]) + + if (!is.na(sp) && nzchar(sp)) { + lst = strsplit(v, sp, fixed = TRUE) + lens = lengths(lst) + # A cell that splits into nothing at all still contributes its row to the NA bucket. + lst[lens == 0L] = NA_character_ + d = data.table(row = rep.int(seq_along(v), pmax(lens, 1L)), + tok = trimws(unlist(lst, use.names = FALSE))) + d = unique(d, by = c("row", "tok")) # "a,a" counts its row once + } else { + d = data.table(row = seq_along(v), tok = trimws(v)) + } + d[is.na(tok) | !nzchar(tok), tok := NA_character_] + + cnt = d[, .N, by = tok] + n_val = nrow(cnt[!is.na(tok)]) + if (n_val < FACET_MIN_VALUES || n_val > FACET_MAX_VALUES) { + message("Facet column '", nm, "': ", n_val, + " distinct value(s) - keeping the plain text filter.") + next + } + + # Fixed levels first, then descending count, then alphabetical; the NA bucket sorts last + lv = intersect(as.character(levels[[nm]]), cnt$tok[!is.na(cnt$tok)]) + rank = ifelse(is.na(cnt$tok), length(lv) + 2L, + ifelse(cnt$tok %in% lv, match(cnt$tok, lv), length(lv) + 1L)) + cnt = cnt[order(rank, -N, tok)] + + vals = sprintf("[%s,%s]", + ifelse(is.na(cnt$tok), "null", js_quote(cnt$tok)), + js_num(cnt$N)) + entries = c(entries, + sprintf('%s:{"sep":%s,"values":[%s]}', + js_quote(nm), + if (is.na(sp) || !nzchar(sp)) "null" else js_quote(sp), + paste(vals, collapse = ","))) + } + + paste0("{", paste(entries, collapse = ","), "}") +} + +# Format a number for human-readable display +fmt_bp = function(x) { + x = as.numeric(x) + ifelse(abs(x) >= 1e6, paste0(round(x / 1e6, 1), " Mb"), + ifelse(abs(x) >= 1e3, paste0(round(x / 1e3, 1), " kb"), + paste0(x, " bp"))) +} + +# Embed a PNG as a framed figure (.report-figure in report.scss) with an optional caption +embed_png = function(path, max_width = "900px", caption = NULL) { + if (is.null(path) || !file.exists(path)) return(NULL) + b64 = base64enc::base64encode(path) + htmltools::tags$figure( + class = "report-figure", + htmltools::tags$img( + src = paste0("data:image/png;base64,", b64), + style = paste0("max-width:", max_width, "; display:block; margin:auto;") + ), + if (!is.null(caption)) htmltools::tags$figcaption(class = "report-figure__caption", caption) + ) +} + +# data: URI for a Wakhan Plotly HTML file, with a resize script injected so the plot fills the iframe +wakhan_plot_datauri = function(path) { + html = paste(readLines(path, warn = FALSE), collapse = "\n") + # Clear Plotly's inline fixed div size before relayout({autosize:true}) + Plots.resize() + resize_script = " + +" + if (grepl("", html, fixed = TRUE)) { + html = sub("", paste0(resize_script, ""), html, fixed = TRUE) + } else { + html = paste0(html, resize_script) + } + paste0("data:text/html;base64,", base64enc::base64encode(charToRaw(html))) +} + +# Embed a self-contained HTML file (e.g. a standalone Plotly plot) as an inline iframe. +embed_html_iframe = function(path, height = "780px") { + if (is.null(path) || !file.exists(path)) return(NULL) + htmltools::tags$iframe( + class = "report-figure__frame", + src = wakhan_plot_datauri(path), + style = paste0("width:100%; height:", height, "; border:none;") + ) +} + +# Wakhan ranked CN plots as a self-contained tab widget (Quarto's panel-tabset breaks on raw iframe HTML before a heading); panes after the first load lazily via data-src +render_wakhan_cn_tabs = function(plots) { + if (length(plots) == 0) return(NULL) + + ids = paste0("wakhan-cn-pane-", seq_along(plots)) + + buttons = lapply(seq_along(plots), function(i) { + p = plots[[i]] + htmltools::tags$button( + class = if (i == 1) "wakhan-cn-tab active" else "wakhan-cn-tab", + `data-target` = ids[i], + paste0("Rank ", p$rank, " — purity ", p$purity, ", ploidy ", p$ploidy) + ) + }) + + panes = lapply(seq_along(plots), function(i) { + p = plots[[i]] + uri = wakhan_plot_datauri(p$plot) + iframe = if (i == 1) { + htmltools::tags$iframe(class = "report-figure__frame", src = uri, + style = "width:100%; height:780px; border:none;") + } else { + htmltools::tags$iframe(class = "report-figure__frame", `data-src` = uri, + style = "width:100%; height:780px; border:none;") + } + htmltools::tags$div( + class = if (i == 1) "wakhan-cn-pane active" else "wakhan-cn-pane", + id = ids[i], + iframe + ) + }) + + # Styled by the .wakhan-cn-tab* rules in report.scss + htmltools::tagList( + htmltools::tags$div(class = "wakhan-cn-tabs__nav", buttons), + htmltools::tags$div(class = "wakhan-cn-tabs__panes", panes), + htmltools::tags$script(htmltools::HTML(" + document.querySelectorAll('.wakhan-cn-tabs__nav').forEach(function (nav) { + nav.querySelectorAll('.wakhan-cn-tab').forEach(function (btn) { + btn.addEventListener('click', function () { + const container = nav.nextElementSibling; + nav.querySelectorAll('.wakhan-cn-tab').forEach(function (b) { b.classList.remove('active'); }); + btn.classList.add('active'); + container.querySelectorAll('.wakhan-cn-pane').forEach(function (p) { p.classList.remove('active'); }); + const pane = document.getElementById(btn.dataset.target); + pane.classList.add('active'); + const iframe = pane.querySelector('iframe[data-src]'); + if (iframe) { + iframe.src = iframe.dataset.src; + iframe.removeAttribute('data-src'); + } + }); + }); + }); + ")) + ) +} + +# Coding TMB from a variant_table; consequence may be comma-joined; denominator_mb defaults to 30 +compute_tmb = function(variant_table, denominator_mb = 30) { + nonsyn_terms = c( + "missense_variant", "frameshift_variant", "stop_gained", "stop_lost", + "start_lost", "inframe_insertion", "inframe_deletion", + "splice_acceptor_variant", "splice_donor_variant", "protein_altering_variant" + ) + if (is.null(variant_table) || nrow(variant_table) == 0) { + return(list(n_nonsyn = NA_integer_, tmb = NA_real_, denominator_mb = denominator_mb)) + } + is_nonsyn = vapply(variant_table$consequence, function(csq) { + if (is.na(csq) || csq == "") return(FALSE) + any(trimws(unlist(strsplit(csq, ","))) %in% nonsyn_terms) + }, logical(1)) + n_nonsyn = sum(is_nonsyn, na.rm = TRUE) + list( + n_nonsyn = n_nonsyn, + tmb = round(n_nonsyn / denominator_mb, 2), + denominator_mb = denominator_mb + ) +} diff --git a/assets/lrsomatic_report/README.md b/assets/lrsomatic_report/README.md new file mode 100644 index 00000000..4664f78a --- /dev/null +++ b/assets/lrsomatic_report/README.md @@ -0,0 +1,281 @@ +# lrsomatic_report + +Standalone reporting tool for the [LRSomatic](https://github.com/nf-core/lrsomatic) Nextflow pipeline. Generates a self-contained HTML report per sample with: + +- **Summary header**: purity, ploidy, coverage, N50, variant counts +- **Circos plot**: somatic SNVs (6-class SBS colours), non-BND SVs, ASCAT copy number, translocation links +- **Breakend circos**: a second circos over just the chromosomes a breakend touches, with panel gene bodies and names; selecting a row in the SV table highlights that rearrangement's arc, and the gene-panel filter dims the arcs it hides +- **Interactive variant table**: VEP-annotated somatic small variants, optionally filtered to a gene panel, with VAF, depth and phasing +- **Interactive SV table**: Severus structural variants, one row per rearrangement with both breakend loci, sharing the same gene-panel filter (matched on breakend position) +- **QC details**: mosdepth coverage, samtools flagstat, cramino read stats, and per-chromosome WhatsHap phasing statistics (germline) + +## Quick start + +```bash +S=/path/to/sample-dir + +Rscript bin/render_report.R \ + --sample-dir $S \ + --sample-id SAMPLE_ID \ + --sex male \ + --reference auto # auto-detects t2t vs hg38 from VCF headers +``` + +The output file `SAMPLE_ID_report.html` will be written to the current directory. + +Matched and tumour-only runs take the same command: the run mode and every input file +are discovered from the sample directory. + +Tables render unfiltered. Add `--gene-panel lymphoid` (or a path to your own TSV) to have a +panel applied when the report opens, and pass the option more than once to apply several at +the same time — see [Gene panels](#gene-panels). + +## All options + +``` +--sample-dir Path to the sample output directory (required) +--sample-id Sample identifier (default: directory name) +--reference t2t | hg38 | auto (default: auto) +--sex male | female | XY | XX (required) +--gene-panel none | builtin panel name (e.g. lymphoid) | path to a custom TSV + (default: none — tables render unfiltered). Repeatable: pass it + several times to apply several panels at once (union). +--output Output HTML path (default: _report.html in current dir) +--title Report title +``` + +> **Changed in v1.1.0:** +> - `--mode` and `--somatic-vcf` were removed. Run mode is derived from whether normal-side +> QC is present, and the VCF supplying VAF is now discovered (see below), so neither needs +> to be declared. Scripts passing them will fail on an unknown option. +> - `--gene-panel` now defaults to `none` instead of `lymphoid`: reports open unfiltered +> unless a panel is asked for. Pass `--gene-panel lymphoid` to restore the old default. + +> **Changed in v1.2.1:** +> - The SV table is **one row per rearrangement**, not one per breakend record: Severus's +> `_1`/`_2` mate records are collapsed, and each row carries both loci +> (`chrom_a`/`pos_a`, `chrom_b`/`pos_b`) plus a `svclass` separating interchromosomal +> translocations from intra-chromosomal breakends. The SV count and the circos links +> halve accordingly — they were double-counting. The single `gene_hits` column is +> replaced by per-breakend `gene_a`/`gene_b`, and a `panel_hit` column names which panel +> gene matched, on which side, and how: each entry reads `GENE (side, how)` — for +> example `RB1 (span, direct)` when the span overlaps the gene, or `RB1 (B, 188.5 kb)` +> when breakend B only fell inside the search window. The windows are wide (1 Mb around a +> BND), so that second token is what separates a disrupted gene from a nearby one. +> - SVs are matched against a gene panel by **coordinate**, not gene symbol, whenever the +> panel carries `chrom`/`start`/`end` — see [Gene panels](#gene-panels). The bundled +> `lymphoid.tsv` is replaced by `lymphoid.hg38.tsv` and `lymphoid.t2t.tsv`; a custom +> symbol-only TSV still works and still matches on symbols. + +> **Changed in v1.3.0:** +> - The categorical columns of both variant tables now filter by **tickbox dropdown** +> instead of a free-text box: `consequence`, `impact` and `callers` on the small-variant +> table, `svclass`, `svtype`, `impact`, `consequence` and `caller` on the SV table. Each +> dropdown lists the values actually present in that sample with a row count, so it also +> answers "what is even in this column?". Every other column keeps its text box, and the +> table's own search box still does substring across all columns. +> - Ticking several values in one column is **OR**; ticking values in two columns is +> **AND**. A ticked term matches a cell holding several — ticking `missense_variant` also +> shows a row whose consequence is `missense_variant,splice_region_variant`. Counts are +> over all rows and do not change as you filter, and `(none)` selects the rows with no +> value in that column. +> - A column with fewer than two distinct values keeps its plain text box rather than +> offering an empty dropdown. That is expected for `callers` when VEP produced its default +> text output (which carries no per-variant caller) and for the SV `caller` column, which +> has one value today. +> - Ticks survive changing the gene panel, are reflected in the "N shown" count, and are +> honoured by the copy/CSV buttons. **Clear value filters** in the panel bar resets them — +> it appears only while something is ticked, since a filter set on a header that has been +> scrolled past is otherwise easy to lose track of. +> - Fixed: the "N small variants · N SVs shown" line went stale when a per-column filter was +> used, having only followed the gene-panel selector. +> - `--gene-panel` is now **repeatable**, and the report's panel selector is a row of +> checkboxes rather than a dropdown: tick any number and a row is kept if it hits **any** +> of them. No box ticked is the unfiltered state, so the "All genes" entry is gone. With +> two or more ticked, each `panel_hit` entry ends with the panel it matched in square +> brackets — with one, the labels read exactly as before. `--gene-panel none` combined +> with a real panel is now an error rather than a case where one quietly wins. +> - The SV table's footnote about how the panel matches now follows the ticked boxes; it +> previously described the load-time panel and went stale the moment a reader switched. + +> **Changed in v1.3.1:** +> - A calmer look. The page texture, gradients, card animations and shadows are gone; +> every card, table and plot frame shares one flat surface. The summary numbers are +> grouped into **Tumour**, **Somatic variants** and **Sequencing** instead of one row of +> eleven differently-coloured cards. The circos drops the per-chromosome Mb axes and the +> alternating track bands, and its legend sits beside the plate. ASCAT plots are framed +> and captioned, and the QC tables match the variant tables. Nothing about the data, +> filters or exports changed. +> - The tickbox dropdown counts are now **live**: each value's count is measured over the +> rows passing every *other* filter (gene panel, text boxes, the other dropdowns), so it +> says how many rows ticking it would leave. Values with no rows left grey out in place; +> the unfiltered count moves into the tooltip. +> - Fixed: opening a dropdown on a right-hand column of a wide table no longer snaps the +> table back to its first column. + +## Gene panels + +Reports are **unfiltered by default**. `--gene-panel` only chooses which panels are ticked when +the report opens; the rendered HTML always contains every variant and every builtin panel, so a +reader can tick and untick panels (or paste a custom gene list) in the browser without +re-rendering. In the report the panels are checkboxes: tick any number and a variant or SV is +kept if it hits **any** of them, and with none ticked the tables are unfiltered. + +Built-in panels live in `assets/gene_lists/`. Each is a TSV with a `gene` column (HGNC symbols) +and, optionally, `chrom`/`start`/`end` — which changes how structural variants are matched: + +| Panel columns | Small variants | Structural variants | +|---|---|---| +| `gene` only | symbol match | symbol match on the annotated breakend genes — no positional window | +| `gene, chrom, start, end` | symbol match | within **1 Mb of either breakend** of a BND, or **100 kb of the span** of any other type | + +Coordinate matching is the reliable mode: whether VEP annotates a breakend with a gene symbol +at all depends on the sample's VEP invocation (1.6%–90% of breakend rows across the samples +measured), so a symbol-only panel can hide exactly the translocations it exists to find. The +note under the SV table says which mode is in force. + +Because coordinates are only valid for one genome, a coordinate panel must declare its +reference (a leading `# reference: hg38` line, or a `reference` column) and a mismatch with the +rendered reference is a hard error. Builtins ship one file per reference and are offered as a +single entry, resolved against the detected one. + +| Panel | Description | +|---|---| +| `lymphoid` | 72 recurrently mutated genes in B-cell lymphomas (DLBCL, FL, CLL, MCL, BL, MALT), as `lymphoid.hg38.tsv` and `lymphoid.t2t.tsv` | + +```bash +--gene-panel lymphoid # open with the builtin lymphoid panel applied +--gene-panel /path/to/my_genes.tsv # must have a 'gene' column or be a single-column file + +# Repeatable — open with both applied, a row kept if it hits either: +--gene-panel lymphoid --gene-panel /path/to/my_genes.tsv +``` + +With more than one panel ticked, each `panel_hit` entry ends with the panel it matched in +square brackets (`MYC (A, direct) [lymphoid]`); with one, there is no suffix. Two TSVs sharing +a basename both stay selectable — the second is registered as `-custom`. + +A `--gene-panel` value that is neither `none`, a builtin name, nor an existing file is an error — +a typo will not silently produce an unfiltered report. `none` combined with a real panel is an +error too, rather than a case where one of the two quietly wins. See +[`assets/gene_lists/README.md`](assets/gene_lists/README.md) for the full file format. + +## Expected input layout + +The `--sample-dir` must be the root of a single-sample LRSomatic output. Files are discovered +**recursively** by their distinctive filename suffix, so they can be nested in any directory +structure underneath it — for example: + +``` +/ +├── *_SOMATIC_VEP.vcf.gz VEP-annotated somatic small variants +├── variants/phased/somatic_smallvariants.vcf.gz VAF / depth / phasing source +├── severus_somatic.vcf.gz Severus SV calls +├── *_SV_VEP.vcf.gz VEP-annotated SVs +├── *.segments_raw.txt, *.purityploidy.txt ASCAT +├── *.mosdepth.summary.txt, *.mosdepth.global.dist.txt mosdepth (tumour) +├── *_cramino.txt, *.flagstat, *.stats cramino / samtools (tumour) +├── qc/whatshap_stats/*_whatshap_stats.tsv phasing statistics (germline) +├── wakhan/ Wakhan copy-number solutions +└── **/normal/** same QC file set, normal side + (matched mode; e.g. qc/normal/) +``` + +Normal-side QC is picked up from any `normal/` directory in the tree, wherever the pipeline +nests it, and is also what determines the run mode. + +**Small variants come from the VEP annotation only.** `*_SOMATIC_VEP.vcf.gz` defines the +variant set; VAF, depth, genotype and phase set are joined from the VCF that VEP annotated — +`variants/phased/somatic_smallvariants.vcf.gz`. Runs predating `variants/phased/` fall back to +`variants/clairs{,to}/somatic.vcf.gz` (then any non-germline VCF in those directories), which +yields VAF and depth but no phase set. If none is found the table still renders, without +those columns. + +A footnote under the variant table names the file those columns actually came from and how +many variants they cover. **One VCF supplies them for the whole table**, so if the run +combined several somatic callers by consensus, the VAF, depth, genotype and phase set come +from whichever caller won each merge and need not match the `callers` column beside them. +Variants reported by more than one caller are highlighted in that column, and the footnote +says so. (Only the joined columns are ambiguous — the variant *set* is taken per record from +the VEP file.) + +VEP writes indels at a different position and sometimes in a different allele notation than +the VCF it was given, so the join is made on a normalised key — see `variant_key()` in +`R/parse_smallvariants.R`. + +`*_SOMATIC_VEP.vcf.gz` ships in two formats. Usually it is VEP *default text output* despite +the `.vcf.gz` name. If VEP was run with `--vcf` it is a genuine VCF with a `CSQ` field, and +may be a *merged* multi-caller VCF carrying germline calls (DeepVariant, Clair3) alongside +somatic ones, tagged in `INFO/CALLER`; the report then keeps only `PASS` records from a +somatic caller (ClairS, ClairS-TO, DeepSomatic). Both formats are detected automatically. + +Missing files are handled gracefully: the corresponding report section shows a "not available" notice. + +### Not covered: methylation + +There is no methylation section. The only methylation output the pipeline publishes is +`methylation//modkit_pileup/.bed.gz` — measured at 38–42 GB gzipped per sample, +unfiltered and with no tabix index, which cannot be read at render time. + +`modkit pileup` already runs with `--bgzf`, so emitting a `tabix -p bed` index next to the +`.bed.gz` would be enough to unblock this: region queries on an indexed pileup measured +~0.16 s per Mb, making a binned genome-wide profile or per-locus lookup practical. + +## Supported references + +| `--reference` | Cytobands source | chr1 length | +|---|---|---| +| `t2t` | CHM13v2.0 | 248,387,328 bp | +| `hg38` | GRCh38 (UCSC) | 248,956,422 bp | + +Auto-detection reads `##contig` lines from the VEP somatic VCF. + +## R package requirements + +`recipe/meta.yaml` is the source of truth for runtime dependencies — it is what the +Bioconda package and the pipeline's container are built from. The list below mirrors it; +if the two ever disagree, the recipe is right. + +Install in your R environment if missing: + +```r +install.packages(c("data.table", "dplyr", "DT", "htmltools", "optparse", + "quarto", "yaml", "ggplot2", "svglite", "knitr", + "R.utils", "base64enc")) +BiocManager::install("circlize") +``` + +Plus the `quarto` CLI itself. `R.utils` is not called directly — `data.table::fread()` +requires it to read the gzipped VCFs. + +Tested with R 4.4.1 and Quarto 1.5.57. + +## Repository structure + +``` +lrsomatic_report/ +├── bin/render_report.R CLI entrypoint +├── R/ +│ ├── utils.R Shared helpers (gene panel, Extra-field parser) +│ ├── references.R Cytoband + chrom-length loading, reference auto-detection +│ ├── locate_outputs.R Discover per-tool output files in a sample directory +│ ├── parse_smallvariants.R VEP text + raw caller VCF parsers; build variant table +│ ├── parse_severus.R Severus VCF parsing (mate-collapsed), SV table, panel matching +│ ├── parse_ascat.R ASCAT segments + purity/ploidy parsers +│ ├── parse_qc.R Mosdepth, cramino, flagstat parsers +│ ├── circos.R draw_circos() — the genome-wide circos SVG +│ └── circos_bnd.R Breakend circos: selects and serialises it for the browser +├── templates/per_sample.qmd Quarto template (HTML report) +├── assets/ +│ ├── references/{t2t,hg38}/ Cytobands + chrom lengths (bundled, no network needed) +│ ├── gene_lists/ lymphoid.{hg38,t2t}.tsv + README +│ ├── styles/ report.scss (the report theme) +│ └── js/ bnd_circos.js (breakend circos), facet_filter.js (tickbox +│ column filters) — inlined at render time +└── tests/ testthat unit tests + tests/js (node, no dependencies) +``` + +## Roadmap + +- **v2**: Cohort report (oncoprint, recurrence tables across multiple samples) +- **v2**: Wakhan haplotype-resolved copy-number integration diff --git a/assets/lrsomatic_report/VENDORED.md b/assets/lrsomatic_report/VENDORED.md new file mode 100644 index 00000000..0039cff0 --- /dev/null +++ b/assets/lrsomatic_report/VENDORED.md @@ -0,0 +1,73 @@ +# Vendored: lrsomatic_report + +This directory is a **vendored copy** of the standalone report tool, not a git submodule. +Do not edit it here — fix upstream, tag a release, and re-sync. + +| | | +|---|---| +| Upstream | | +| Release | `v1.3.2` (`75c65b2b68968f3d742dbfd1ca7ef780dbdaf770`) | +| Vendored commit | `75c65b2b68968f3d742dbfd1ca7ef780dbdaf770` (the tag itself) | +| License | MIT (see `LICENSE`) | + +## Why vendored rather than a submodule + +`nextflow run IntGenomicsLab/lrsomatic` clones the pipeline repository but does **not** +fetch git submodules, so a gitlink here would be an empty directory for every user who +did not hand-clone with `--recurse-submodules` — and for CI, whose checkout steps do not +pass `submodules: recursive`. Real tracked files work for both. + +The tool's *dependencies* (R, Quarto and its R packages) are handled separately, by the +Wave multi-package container declared in `modules/local/lrsomaticreport/main.nf` and +built from that module's `environment.yml`. + +## What is included + +Only what `bin/render_report.R` needs at run time: + +``` +bin/ R/ templates/ assets/ LICENSE README.md +``` + +Upstream `docs/`, `tests/` (both `tests/testthat/` and `tests/js/`), `recipe/` and +`CLAUDE.md` are deliberately excluded. (Upstream marks `docs/` and `tests/` +`export-ignore` in its `.gitattributes`; `recipe/` and `CLAUDE.md` are not marked, so +they must be left behind by hand when copying.) + +## Re-syncing on the next upstream release + +```bash +TAG=v1.4.0 +git clone --depth 1 --branch "$TAG" https://github.com/ljwharbers/lrsomatic_report.git "$TMPDIR/lrr" +rm -rf assets/lrsomatic_report/{bin,R,templates,assets,LICENSE,README.md} +cp -a "$TMPDIR"/lrr/{bin,R,templates,assets,LICENSE,README.md} assets/lrsomatic_report/ +``` + +The `rm -rf` before the copy is not optional: it is what removes files *deleted* upstream. +Copying over the top would have left the pre-v1.2.1 `assets/gene_lists/lymphoid.tsv` behind, +where `load_all_gene_panels()` would glob it as a second, reference-less `lymphoid` panel +alongside the `lymphoid.hg38.tsv` / `lymphoid.t2t.tsv` pair that replaced it. + +Then update the table above, and: + +- `modules/local/lrsomaticreport/environment.yml` — if upstream `recipe/meta.yaml` gained a + dependency. The two files are kept in exact agreement; check with a `library()`/`require()` + grep over the upstream `R/`, `bin/` and `templates/` rather than trusting the README. +- `modules/local/lrsomaticreport/main.nf` — the hard-coded version topic (the tool has no + `--version` flag), and the container digests **only if `environment.yml` changed**. +- `modules/local/lrsomaticreport/meta.yml` — the same version string, in two places. +- `modules/local/lrsomaticreport/tests/main.nf.test.snap` — regenerate. +- `tests/{default,clair_only,deep_only,consensus,union}.nf.test.snap` — the + `"lrsomatic_report": ""` line in each. +- `CHANGELOG.md` — the vendored version named in the `#176` entry. + +Nothing checks these for consistency; miss one and the snapshots go stale silently. + +Rebuild the containers after any `environment.yml` change so the images and the file agree. +**Two** builds are needed and both must be updated in `main.nf`: `--singularity` produces a +Singularity-native SIF (the `oras://` reference), the default build a genuine OCI image. + +```bash +wave --conda-file modules/local/lrsomaticreport/environment.yml --freeze --await +wave --conda-file modules/local/lrsomaticreport/environment.yml --freeze --await --singularity +``` diff --git a/assets/lrsomatic_report/assets/gene_lists/README.md b/assets/lrsomatic_report/assets/gene_lists/README.md new file mode 100644 index 00000000..bd4419b5 --- /dev/null +++ b/assets/lrsomatic_report/assets/gene_lists/README.md @@ -0,0 +1,100 @@ +# Gene Panel Lists + +Each file is a TSV with a required `gene` column (HGNC symbol). Coordinate columns +`chrom` (or `chr`), `start` and `end` are optional but **all-or-nothing** — a file with +some but not all three is rejected rather than quietly falling back to symbol matching. + +| Panel columns | Small-variant filter | SV filter | +|---|---|---| +| `gene` only | symbol match | direct-hit symbol match on either breakend's VEP gene — no windows | +| `gene, chrom, start, end` | symbol match | coordinate match: within 1 Mb of a breakend (BND) or 100 kb of the SV span (other types) | + +Coordinate matching is what makes breakend filtering reliable: whether a BND carries a +VEP gene symbol at all depends on the sample's VEP invocation (1.6%–90% of breakends +across the samples measured), so a symbol-only panel can hide the very translocations it +exists to find. Matching on coordinates needs no annotation on the row. + +Optional metadata columns (`panel`, `notes`) are ignored by the loader and kept for the +reader. + +## Reference declaration + +Panel coordinates are only valid for the reference they were built on — matching an hg38 +panel against a T2T sample produces wrong hits with no error anywhere. A +coordinate-carrying panel must therefore declare its reference, either as a leading +comment line: + +``` +# reference: hg38 +gene chrom start end +MYC chr8 127735434 127742951 +``` + +or as a `reference` column. A panel whose declared reference differs from the one the +report is rendered against is a **hard error**. A panel that declares none loads, but the +SV section footnote says "reference unverified". Symbol-only panels are +reference-agnostic and need no declaration. + +Builtin panels ship one file per reference (`lymphoid.hg38.tsv`, `lymphoid.t2t.tsv`) and +are presented as a single selectable `lymphoid` entry, resolved against the detected +reference. + +## Supplying a custom panel + +```bash +Rscript bin/render_report.R \ + --sample-dir /path/to/sample \ + --sample-id MySample \ + --gene-panel /path/to/my_genes.tsv +``` + +A one-column file of symbols (with or without a `gene` header) is accepted, and gives +symbol-only matching. The report's "Custom…" textarea takes bare symbols, so it is +symbol-only too. + +`--gene-panel` is repeatable, so several panels can be applied at once — a builtin and your +own list together, say. A variant or SV is kept if it hits any of them: + +```bash + --gene-panel lymphoid --gene-panel /path/to/my_genes.tsv +``` + +Each panel is registered under its filename stem; two files sharing a basename both stay +selectable, the second as `-custom`. Every registered panel is a checkbox in the +report, so the reader can retick them without re-rendering. + +## Bundled panels + +| File | Contents | +|---|---| +| `lymphoid.hg38.tsv` | 72 recurrently mutated genes in B-cell lymphomas (DLBCL, FL, MCL, CLL, BL, MALT), GENCODE v46 gene spans | +| `lymphoid.t2t.tsv` | the same 72 genes, spans from the CHM13v2.0 RefSeq Liftoff v5.1 annotation | +| `sarcoma.hg38.tsv` | 140 soft-tissue and bone sarcoma genes — tumour suppressors, amplification targets and recurrent fusion partners — GENCODE v46 gene spans | +| `sarcoma.t2t.tsv` | the same 140 genes, spans from the CHM13v2.0 RefSeq Liftoff v5.1 annotation | + +Regenerating them is mechanical — gene spans keyed on `gene_name`, taken from +`gene` features (GENCODE) or the min/max of `transcript` features (Liftoff, which has no +`gene` feature), restricted to `chr1`–`chr22`, `chrX`, `chrY`: + +- hg38: `references/GRCh38.alt-masked-V2/annotation/gencode.v46.basic.annotation.gtf.gz` +- t2t: `references/chm13_v2.0_maskedY.rCRS/annotation/chm13v2.0_RefSeq_Liftoff_v5.1.gtf` + +Neither annotation is keyed on current HGNC symbols throughout, so aliases in the source +gene lists were mapped by hand. For `lymphoid`: `CD20`→`MS4A1` (already present, so the +rows merged), `GEF1`→`ARHGEF1`, `HIST1H1E`→`H1-4`. For `sarcoma`, from an input list of +151 lines: `VEGFR2`→`KDR`, `VEGFR3`→`FLT4`, `MKL2`→`MRTFB`, `MGEA5`→`OGA`, plus +`HER2`→`ERBB2`, `SYT`→`SS18`, `H3F3A`→`H3-3A` and `H3F3B`→`H3-3B`, whose targets were +already listed — those merged, as did seven verbatim duplicates, leaving 140 genes. + +Two `sarcoma` symbols need the T2T annotation handled specially, and both are recorded in +that file's comment header: + +- `POU2AF3` — the Liftoff annotation predates the rename and carries it as `COLCA2`. +- `DUX4L10` — the Liftoff annotation has no D4Z4 paralogs at all (only `DUX4` itself), so + this span comes from `GCF_009914755.1_T2T-CHM13v2.0_genomic.gtf.gz`, whose chromosomes + are NCBI accessions (`NC_060925.1` = `chr1` … `NC_060948.1` = `chrY`). Its 10q26 + position agrees with the hg38 locus, so this is a genuine match rather than a guess. + +A missing coordinate is a **hard error** in `load_gene_panel()`, not a per-row downgrade to +symbol matching, so a gene that resolves in one annotation and not the other has to be +either mapped or dropped from that reference's file — it cannot be left blank. diff --git a/assets/lrsomatic_report/assets/gene_lists/lymphoid.hg38.tsv b/assets/lrsomatic_report/assets/gene_lists/lymphoid.hg38.tsv new file mode 100644 index 00000000..3317ff37 --- /dev/null +++ b/assets/lrsomatic_report/assets/gene_lists/lymphoid.hg38.tsv @@ -0,0 +1,76 @@ +# reference: hg38 +# gene spans from gencode.v46.basic.annotation.gtf.gz +# coordinates are 1-based inclusive gene spans; only valid for the reference declared above +gene chrom start end panel notes +TNFRSF14 chr1 2555639 2565382 lymphoid Immune checkpoint; FL +PIK3CD chr1 9629889 9729114 lymphoid PI3K catalytic subunit delta +SPEN chr1 15836095 15940456 lymphoid Transcriptional repressor +ID3 chr1 23557926 23559501 lymphoid BL; inhibits E-proteins/TCF3 +ARID1A chr1 26693236 26782104 lymphoid SWI/SNF chromatin remodeling +BCL10 chr1 85265776 85276632 lymphoid CBM complex; NF-kB +NRAS chr1 114704469 114716771 lymphoid RAS signaling +CD58 chr1 116514534 116571039 lymphoid Immune evasion +PTEN chr10 87862638 87971930 lymphoid PI3K pathway tumour suppressor +MS4A1 chr11 60455846 60470752 lymphoid CD20; B-cell surface marker; rituximab target +CCND1 chr11 69641156 69654474 lymphoid Cyclin D1; t(11;14) in MCL +FAT3 chr11 92224818 92896473 lymphoid Tumour suppressor +BIRC3 chr11 102317484 102339403 lymphoid IAP; NF-kB; CLL +ATM chr11 108222804 108369102 lymphoid DNA damage response; CLL/MCL +KRAS chr12 25205246 25250936 lymphoid RAS signaling +KMT2D chr12 49018975 49060794 lymphoid Histone methyltransferase (MLL4) +BTG1 chr12 92140278 92145846 lymphoid Anti-proliferative; DLBCL +DTX1 chr12 113056730 113098028 lymphoid Notch pathway effector +FOXO1 chr13 40555667 40666641 lymphoid Transcription factor; BCL6 target +RB1 chr13 48303744 48599436 lymphoid Tumour suppressor; cell cycle +B2M chr15 44711358 44718851 lymphoid HLA class I; immune evasion +MAP2K1 chr15 66386837 66491656 lymphoid ERK signaling +CREBBP chr16 3725054 3880713 lymphoid Acetyltransferase; loss-of-function in FL/DLBCL +CIITA chr16 10866222 10943021 lymphoid MHC class II transactivator +PRKCB chr16 23835983 24220611 lymphoid Protein kinase C beta +CD19 chr16 28931965 28939342 lymphoid BCR coreceptor; therapy target +TP53 chr17 7661779 7687546 lymphoid Tumour suppressor +CD79B chr17 63928738 63932336 lymphoid BCR co-receptor signaling +GNA13 chr17 65009289 65056740 lymphoid G-protein; germinal center exit +MALT1 chr18 58671465 58754477 lymphoid Paracaspase; NF-kB; MALT lymphoma +BCL2 chr18 63123346 63320128 lymphoid Anti-apoptotic; t(14;18) in FL/DLBCL +RPS15 chr19 1438358 1440495 lymphoid Ribosomal; CLL +TCF3 chr19 1609291 1652615 lymphoid BL; E-box transcription factor +SMARCA4 chr19 10960932 11079426 lymphoid Chromatin remodeling +MEF2B chr19 19145567 19192131 lymphoid Transcription factor; FL/DLBCL +ARHGEF1 chr19 41883173 41930150 lymphoid Guanine nucleotide exchange +SOX11 chr2 5692384 5701385 lymphoid MCL marker +BCL11A chr2 60450520 60554467 lymphoid Transcription factor; lymphoma +DUSP2 chr2 96143169 96145440 lymphoid MAP kinase phosphatase +CXCR4 chr2 136114349 136119177 lymphoid Chemokine receptor; CLL/WM +SF3B1 chr2 197388515 197435079 lymphoid Splicing factor; CLL +SAMHD1 chr20 36890229 36951893 lymphoid dNTP hydrolase; CLL +EP300 chr22 41092510 41180077 lymphoid Acetyltransferase +MYD88 chr3 38138552 38143024 lymphoid TLR signaling adaptor; L265P hotspot +SETD2 chr3 47016428 47164113 lymphoid H3K36 methyltransferase +RHOA chr3 49359139 49412998 lymphoid Rho GTPase; AITL G17V hotspot +TBL1XR1 chr3 177019340 177228000 lymphoid Transcription corepressor +PIK3CA chr3 179148114 179240093 lymphoid PI3K catalytic subunit alpha +KLHL6 chr3 183487551 183555706 lymphoid BCR signaling ubiquitin adaptor +BCL6 chr3 187721377 187745725 lymphoid Transcription factor; t(3;14) in DLBCL +FBXW7 chr4 152320544 152536092 lymphoid Ubiquitin E3 ligase +FAT1 chr4 186587794 186726722 lymphoid Tumour suppressor; Hippo pathway +IRF4 chr6 391739 411443 lymphoid Transcription factor; MYC target +H1-4 chr6 26156329 26157115 lymphoid Linker histone H1; DLBCL +HLA-A chr6 29941260 29949572 lymphoid Immune evasion +HLA-C chr6 31268749 31272130 lymphoid Immune evasion +HLA-B chr6 31353872 31367067 lymphoid Immune evasion +PIM1 chr6 37170152 37175428 lymphoid Kinase; BCR/TLR signaling +CCND3 chr6 41934934 42050357 lymphoid Cyclin D3; DLBCL hotspot +SGK1 chr6 134169248 134318112 lymphoid Kinase; germinal center +TNFAIP3 chr6 137867214 137883314 lymphoid A20; NF-kB negative regulator +CARD11 chr7 2906142 3044228 lymphoid NF-kB signaling scaffold +PCLO chr7 82754012 83162930 lymphoid Pepe-scaffold; recurrently mutated +BRAF chr7 140719327 140924929 lymphoid MAPK kinase; HCL V600E +EZH2 chr7 148807257 148884321 lymphoid Histone methyltransferase; Y641/A677/A687 hotspots +LYN chr8 55879835 56014169 lymphoid Src family kinase; BCR signaling +MYC chr8 127735434 127742951 lymphoid Proto-oncogene, BCL translocations +CDKN2A chr9 21967752 21995301 lymphoid Cell cycle regulator (p16/p14ARF) +SYK chr9 90801787 90898549 lymphoid BCR/FcR signaling kinase +NOTCH1 chr9 136494433 136546048 lymphoid Notch pathway; CLL +DDX3X chrX 41333348 41364472 lymphoid RNA helicase; Burkitt/DLBCL +BTK chrX 101349338 101390796 lymphoid BCR kinase; ibrutinib target diff --git a/assets/lrsomatic_report/assets/gene_lists/lymphoid.t2t.tsv b/assets/lrsomatic_report/assets/gene_lists/lymphoid.t2t.tsv new file mode 100644 index 00000000..ca05a853 --- /dev/null +++ b/assets/lrsomatic_report/assets/gene_lists/lymphoid.t2t.tsv @@ -0,0 +1,76 @@ +# reference: t2t +# gene spans from chm13v2.0_RefSeq_Liftoff_v5.1.gtf +# coordinates are 1-based inclusive gene spans; only valid for the reference declared above +gene chrom start end panel notes +TNFRSF14 chr1 1995878 2005473 lymphoid Immune checkpoint; FL +PIK3CD chr1 9170040 9271897 lymphoid PI3K catalytic subunit delta +SPEN chr1 15288973 15381736 lymphoid Transcriptional repressor +ID3 chr1 23392495 23394070 lymphoid BL; inhibits E-proteins/TCF3 +ARID1A chr1 26533960 26620059 lymphoid SWI/SNF chromatin remodeling +BCL10 chr1 85106896 85117748 lymphoid CBM complex; NF-kB +NRAS chr1 114715929 114728216 lymphoid RAS signaling +CD58 chr1 116524958 116581474 lymphoid Immune evasion +PTEN chr10 88747528 88855830 lymphoid PI3K pathway tumour suppressor +MS4A1 chr11 60406975 60421883 lymphoid CD20; B-cell surface marker; rituximab target +CCND1 chr11 69658031 69671351 lymphoid Cyclin D1; t(11;14) in MCL +FAT3 chr11 92147480 92825282 lymphoid Tumour suppressor +BIRC3 chr11 102319603 102341520 lymphoid IAP; NF-kB; CLL +ATM chr11 108230609 108376596 lymphoid DNA damage response; CLL/MCL +KRAS chr12 25076496 25122152 lymphoid RAS signaling +KMT2D chr12 48981150 49022967 lymphoid Histone methyltransferase (MLL4) +BTG1 chr12 92117840 92123409 lymphoid Anti-proliferative; DLBCL +DTX1 chr12 113033383 113074667 lymphoid Notch pathway effector +FOXO1 chr13 39774673 39885620 lymphoid Transcription factor; BCL6 target +RB1 chr13 47524085 47702182 lymphoid Tumour suppressor; cell cycle +B2M chr15 42519493 42526121 lymphoid HLA class I; immune evasion +MAP2K1 chr15 64208363 64313019 lymphoid ERK signaling +CREBBP chr16 3752324 3907918 lymphoid Acetyltransferase; loss-of-function in FL/DLBCL +CIITA chr16 10902174 10978998 lymphoid MHC class II transactivator +PRKCB chr16 24111361 24497130 lymphoid Protein kinase C beta +CD19 chr16 29213087 29220458 lymphoid BCR coreceptor; therapy target +TP53 chr17 7572544 7591594 lymphoid Tumour suppressor +CD79B chr17 64799505 64803094 lymphoid BCR co-receptor signaling +GNA13 chr17 65879260 65926708 lymphoid G-protein; germinal center exit +MALT1 chr18 58872604 58955588 lymphoid Paracaspase; NF-kB; MALT lymphoma +BCL2 chr18 63326497 63525151 lymphoid Anti-apoptotic; t(14;18) in FL/DLBCL +RPS15 chr19 1408393 1410492 lymphoid Ribosomal; CLL +TCF3 chr19 1580117 1623781 lymphoid BL; E-box transcription factor +SMARCA4 chr19 11088037 11189277 lymphoid Chromatin remodeling +MEF2B chr19 19282103 19306796 lymphoid Transcription factor; FL/DLBCL +ARHGEF1 chr19 44702671 44749424 lymphoid Guanine nucleotide exchange +SOX11 chr2 5713811 5722812 lymphoid MCL marker +BCL11A chr2 60456325 60559492 lymphoid Transcription factor; lymphoma +DUSP2 chr2 96649773 96652044 lymphoid MAP kinase phosphatase +CXCR4 chr2 136558831 136562630 lymphoid Chemokine receptor; CLL/WM +SF3B1 chr2 197873439 197918732 lymphoid Splicing factor; CLL +SAMHD1 chr20 38614121 38676051 lymphoid dNTP hydrolase; CLL +EP300 chr22 41567504 41655012 lymphoid Acetyltransferase +MYD88 chr3 38144330 38148691 lymphoid TLR signaling adaptor; L265P hotspot +SETD2 chr3 47032799 47181207 lymphoid H3K36 methyltransferase +RHOA chr3 49388518 49441355 lymphoid Rho GTPase; AITL G17V hotspot +TBL1XR1 chr3 179822332 180004917 lymphoid Transcription corepressor +PIK3CA chr3 181951954 182043930 lymphoid PI3K catalytic subunit alpha +KLHL6 chr3 186295709 186363954 lymphoid BCR signaling ubiquitin adaptor +BCL6 chr3 190538887 190562977 lymphoid Transcription factor; t(3;14) in DLBCL +FBXW7 chr4 155643699 155859255 lymphoid Ubiquitin E3 ligase +FAT1 chr4 189934525 190073402 lymphoid Tumour suppressor; Hippo pathway +IRF4 chr6 250136 269771 lymphoid Transcription factor; MYC target +H1-4 chr6 26024465 26025251 lymphoid Linker histone H1; DLBCL +HLA-A chr6 29806459 29809798 lymphoid Immune evasion +HLA-C chr6 31134915 31138246 lymphoid Immune evasion +HLA-B chr6 31209767 31213072 lymphoid Immune evasion +PIM1 chr6 36993698 36998970 lymphoid Kinase; BCR/TLR signaling +CCND3 chr6 41763493 41877153 lymphoid Cyclin D3; DLBCL hotspot +SGK1 chr6 135357191 135506235 lymphoid Kinase; germinal center +TNFAIP3 chr6 139054770 139071725 lymphoid A20; NF-kB negative regulator +CARD11 chr7 3019747 3157416 lymphoid NF-kB signaling scaffold +PCLO chr7 84005231 84414103 lymphoid Pepe-scaffold; recurrently mutated +BRAF chr7 142027505 142239131 lymphoid MAPK kinase; HCL V600E +EZH2 chr7 149989157 150066070 lymphoid Histone methyltransferase; Y641/A677/A687 hotspots +LYN chr8 56256887 56391325 lymphoid Src family kinase; BCR signaling +MYC chr8 128862888 128870405 lymphoid Proto-oncogene, BCL translocations +CDKN2A chr9 21982052 22009697 lymphoid Cell cycle regulator (p16/p14ARF) +SYK chr9 102966952 103064392 lymphoid BCR/FcR signaling kinase +NOTCH1 chr9 148723532 148777907 lymphoid Notch pathway; CLL +DDX3X chrX 40735393 40766556 lymphoid RNA helicase; Burkitt/DLBCL +BTK chrX 99793571 99834908 lymphoid BCR kinase; ibrutinib target diff --git a/assets/lrsomatic_report/assets/gene_lists/sarcoma.hg38.tsv b/assets/lrsomatic_report/assets/gene_lists/sarcoma.hg38.tsv new file mode 100644 index 00000000..0529c1b9 --- /dev/null +++ b/assets/lrsomatic_report/assets/gene_lists/sarcoma.hg38.tsv @@ -0,0 +1,144 @@ +# reference: hg38 +# gene spans from gencode.v46.basic.annotation.gtf.gz +# coordinates are 1-based inclusive gene spans; only valid for the reference declared above +gene chrom start end panel notes +CAMTA1 chr1 6785454 7769706 sarcoma WWTR1-CAMTA1; epithelioid haemangioendothelioma +SDHB chr1 17018664 17054151 sarcoma SDH-deficient GIST and paraganglioma +PAX7 chr1 18630846 18748866 sarcoma PAX7-FOXO1; alveolar rhabdomyosarcoma +MEAF6 chr1 37489993 37514766 sarcoma MEAF6-PHF1; ossifying fibromyxoid tumour +JUN chr1 58776845 58784048 sarcoma 1p32 amplification in DDLPS +TGFBR3 chr1 91680343 91906335 sarcoma TGFBR3-OGA lipofibromatosis-like neural tumour +CSF1 chr1 109910242 109930992 sarcoma COL6A3-CSF1; tenosynovial giant cell tumour +NRAS chr1 114704469 114716771 sarcoma RAS signalling +TPM3 chr1 154155308 154194648 sarcoma TPM3-NTRK1 / ALK fusion partner +NTRK1 chr1 156815636 156881850 sarcoma Kinase fusions; infantile fibrosarcoma-like +SDHC chr1 161314381 161363206 sarcoma SDH-deficient GIST; Carney triad +MDM4 chr1 204516379 204558120 sarcoma p53 negative regulator; 1q32 amplification +H3-3A chr1 226061851 226072019 sarcoma H3F3A G34W; giant cell tumour of bone +EPC1 chr10 32267751 32378798 sarcoma EPC1-PHF1; endometrial stromal sarcoma +RET chr10 43077064 43130351 sarcoma Kinase fusions +PTEN chr10 87862638 87971930 sarcoma PI3K pathway tumour suppressor +OGA chr10 101784443 101818465 sarcoma MGEA5; TGFBR3-OGA lipofibromatosis-like tumour +FGFR2 chr10 121478332 121598458 sarcoma RTK fusion and amplification +DUX4L10 chr10 133743332 133744598 sarcoma 10q26 D4Z4 paralog; CIC-DUX4L partner +WT1 chr11 32387775 32435564 sarcoma EWSR1-WT1; desmoplastic small round cell tumour +CREB3L1 chr11 46277662 46321409 sarcoma FUS-CREB3L1; low-grade fibromyxoid sarcoma +SDHAF2 chr11 61430042 61446839 sarcoma SDH complex assembly; SDH-deficient GIST +CCND1 chr11 69641156 69654474 sarcoma Cyclin D1 amplification +EED chr11 86201212 86278813 sarcoma PRC2; MPNST loss +MAML2 chr11 95976598 96343195 sarcoma MAML2 fusions +YAP1 chr11 102110447 102233424 sarcoma YAP1-TFE3 / YAP1-MRTFB haemangioendothelioma +POU2AF3 chr11 111298546 111308735 sarcoma COLCA2; EWSR1-POU2AF3 sarcoma +SDHD chr11 112086824 112120016 sarcoma SDH-deficient GIST and paraganglioma +KMT2A chr11 118436456 118526832 sarcoma MLL; rare sarcoma fusion partner +FLI1 chr11 128686535 128813267 sarcoma EWSR1-FLI1; Ewing sarcoma +CCND2 chr12 4269771 4305353 sarcoma Cyclin D2 amplification +ETV6 chr12 11649674 11895377 sarcoma ETV6-NTRK3; infantile fibrosarcoma +KRAS chr12 25205246 25250936 sarcoma RAS signalling +KMT2D chr12 49018975 49060794 sarcoma Histone methyltransferase; tumour suppressor +ATF1 chr12 50763710 50821162 sarcoma EWSR1-ATF1; clear cell sarcoma, AFH +TFCP2 chr12 51093656 51173135 sarcoma FUS/EWSR1-TFCP2 epithelioid rhabdomyosarcoma +NAB2 chr12 57089043 57095476 sarcoma NAB2-STAT6; solitary fibrous tumour +STAT6 chr12 57095408 57132139 sarcoma NAB2-STAT6; solitary fibrous tumour +GLI1 chr12 57459785 57472268 sarcoma GLI1-altered soft tissue tumour; 12q13 amplicon +DDIT3 chr12 57516588 57521737 sarcoma FUS/EWSR1-DDIT3; myxoid liposarcoma +CDK4 chr12 57747727 57756013 sarcoma 12q13-14; co-amplified with MDM2 in DDLPS +HMGA2 chr12 65824460 65966291 sarcoma 12q14-15; lipoma and DDLPS fusions +MDM2 chr12 68808177 68845544 sarcoma 12q15 amplification; WDLPS/DDLPS hallmark +BRCA2 chr13 32315086 32400268 sarcoma Homologous recombination repair +FOXO1 chr13 40555667 40666641 sarcoma PAX3/PAX7-FOXO1; alveolar rhabdomyosarcoma +RB1 chr13 48303744 48599436 sarcoma Cell cycle; leiomyosarcoma/osteosarcoma +GPC5 chr13 91398621 92873682 sarcoma 13q31 amplification; rhabdomyosarcoma +FOS chr14 75278826 75282230 sarcoma FOS rearrangement; osteoblastoma, epithelioid haemangioma +NUTM1 chr15 34343315 34357737 sarcoma NUTM1 fusions +TCF12 chr15 56918623 57299281 sarcoma TCF12 fusions; ossifying fibromyxoid tumour +NTRK3 chr15 87859751 88256791 sarcoma ETV6-NTRK3; infantile fibrosarcoma +MRTFB chr16 14071319 14266773 sarcoma MKL2; MRTFB-YAP1 haemangioendothelioma +PRKCB chr16 23835983 24220611 sarcoma PRKC fusion partner +FUS chr16 31180138 31196963 sarcoma FET family; FUS-DDIT3 myxoid liposarcoma +YWHAE chr17 1344275 1400222 sarcoma YWHAE-NUTM2; endometrial stromal sarcoma +USP6 chr17 5116032 5175034 sarcoma Aneurysmal bone cyst, nodular fasciitis +TP53 chr17 7661779 7687546 sarcoma Li-Fraumeni; osteosarcoma, leiomyosarcoma +TOP3A chr17 18271428 18315007 sarcoma 17p11 amplicon +NF1 chr17 31094927 31382116 sarcoma MPNST; RAS-MAPK tumour suppressor +SUZ12 chr17 31937007 32001038 sarcoma PRC2; JAZF1-SUZ12 ESS, MPNST loss +TAF15 chr17 35809482 35864615 sarcoma FET family; Ewing-like sarcoma +ERBB2 chr17 39687914 39730426 sarcoma HER2; RTK amplification +BRCA1 chr17 43044295 43170245 sarcoma Homologous recombination repair +ETV4 chr17 43527844 43579620 sarcoma ETV4 rearrangement +COL1A1 chr17 50184101 50201632 sarcoma COL1A1-PDGFB; dermatofibrosarcoma protuberans +PRKCA chr17 66302613 66810743 sarcoma PRKC fusions; chordoid-type tumours +H3-3B chr17 75776434 75785893 sarcoma H3F3B K36M; chondroblastoma +SS18 chr18 26016253 26091217 sarcoma SS18-SSX; synovial sarcoma +SMARCA4 chr19 10960932 11079426 sarcoma SWI/SNF; SMARCA4-deficient sarcoma +TPM4 chr19 16067021 16103002 sarcoma TPM4-ALK fusion partner +CIC chr19 42268537 42295797 sarcoma CIC-DUX4 round cell sarcoma +FOSB chr19 45467995 45475179 sarcoma FOSB rearrangement; pseudomyogenic haemangioendothelioma +MYCN chr2 15940550 15947007 sarcoma Amplification; rhabdomyosarcoma +NCOA1 chr2 24491254 24770702 sarcoma PAX3-NCOA1; rhabdomyosarcoma +ALK chr2 29192774 29921586 sarcoma Kinase fusions; inflammatory myofibroblastic tumour +EML4 chr2 42169353 42332548 sarcoma Kinase fusion partner (NTRK3/ALK) +GLI2 chr2 120735623 120992653 sarcoma Hedgehog pathway effector +CREB1 chr2 207529737 207605988 sarcoma EWSR1-CREB1; angiomatoid fibrous histiocytoma +FN1 chr2 215360440 215436073 sarcoma FN1 fusions; calcifying aponeurotic fibroma +FEV chr2 218981087 218985184 sarcoma EWSR1-FEV; Ewing sarcoma +PAX3 chr2 222199887 222298998 sarcoma PAX3-FOXO1; alveolar rhabdomyosarcoma +COL6A3 chr2 237324003 237414328 sarcoma COL6A3-CSF1; tenosynovial giant cell tumour +ERG chr21 38380027 38661780 sarcoma FUS-ERG / EWSR1-ERG; Ewing sarcoma +SMARCB1 chr22 23786931 23838009 sarcoma INI1; epithelioid sarcoma, rhabdoid tumour +EWSR1 chr22 29268009 29300525 sarcoma FET family; Ewing sarcoma and many other fusions +NF2 chr22 29603553 29698598 sarcoma Schwannoma and mesothelioma tumour suppressor +PATZ1 chr22 31325804 31346346 sarcoma EWSR1-PATZ1 round cell sarcoma +PDGFB chr22 39223359 39244982 sarcoma COL1A1-PDGFB; dermatofibrosarcoma protuberans +RAF1 chr3 12582101 12664201 sarcoma Kinase fusion; MAPK activation +CTNNB1 chr3 41194741 41260096 sarcoma Beta-catenin; desmoid fibromatosis +PRKCD chr3 53156009 53192717 sarcoma PRKC fusion partner +VGLL3 chr3 86876388 86991149 sarcoma 3p12 amplification +TFG chr3 100709295 100748964 sarcoma Kinase fusion partner (NTRK1/ROS1/ALK) +WWTR1 chr3 149517235 149736714 sarcoma WWTR1-CAMTA1; epithelioid haemangioendothelioma +LPP chr3 188153284 188890671 sarcoma HMGA2-LPP; lipoma, chondroid hamartoma +FGFR3 chr4 1793293 1808872 sarcoma RTK fusion and amplification +PDGFRA chr4 54229280 54298245 sarcoma GIST; imatinib target +KIT chr4 54657267 54740783 sarcoma GIST; imatinib target +KDR chr4 55078481 55125595 sarcoma VEGFR2; angiosarcoma +DUX4 chr4 190173774 190185942 sarcoma CIC-DUX4; round cell sarcoma +SDHA chr5 218303 257082 sarcoma SDH-deficient GIST and paraganglioma +TERT chr5 1253147 1295068 sarcoma Promoter and structural activation +TRIO chr5 14143342 14532128 sarcoma TRIO-TERT; undifferentiated sarcoma +APC chr5 112707518 112846239 sarcoma Wnt pathway; desmoid fibromatosis +PDGFRB chr5 150113839 150155872 sarcoma Kinase fusions in myofibroblastic tumours +CDX1 chr5 150166778 150184558 sarcoma Rare fusion partner +NPM1 chr5 171387116 171411810 sarcoma Fusion partner +FGFR4 chr5 177086905 177098144 sarcoma Rhabdomyosarcoma; RTK +FLT4 chr5 180601506 180649624 sarcoma VEGFR3; angiosarcoma +PHF1 chr6 33410399 33416453 sarcoma PHF1 fusions; ossifying fibromyxoid tumour, ESS +FOXO3 chr6 108559835 108684774 sarcoma FOXO family transcription factor +VGLL2 chr6 117265558 117273565 sarcoma VGLL2 fusions; infantile spindle cell RMS +ROS1 chr6 117287353 117425942 sarcoma Kinase fusions +ETV1 chr7 13891229 13991425 sarcoma ETV1 rearrangement +JAZF1 chr7 27830573 28180795 sarcoma JAZF1-SUZ12; endometrial stromal sarcoma +EGFR chr7 55019017 55211628 sarcoma Receptor tyrosine kinase amplification +CDK6 chr7 92604921 92836573 sarcoma Cell cycle kinase amplification +MET chr7 116672196 116798377 sarcoma Receptor tyrosine kinase amplification +BRAF chr7 140719327 140924929 sarcoma MAPK activation +CNTNAP2 chr7 146116002 148420998 sarcoma 7q35 deletion +FGFR1 chr8 38400215 38468834 sarcoma RTK fusion and amplification +PLAG1 chr8 56160909 56211324 sarcoma PLAG1 fusions; lipoblastoma, myoepithelioma +MYBL1 chr8 66562175 66614247 sarcoma Transcription factor; rare rearrangement +NCOA2 chr8 70109782 70403808 sarcoma NCOA2 fusions; congenital spindle cell RMS +HEY1 chr8 79762371 79767857 sarcoma HEY1-NCOA2; mesenchymal chondrosarcoma +MYC chr8 127735434 127742951 sarcoma 8q24 amplification; radiation-associated angiosarcoma +PTPRD chr9 8314246 10613002 sarcoma Deletion; tumour suppressor +CDKN2A chr9 21967752 21995301 sarcoma CDK4/6 inhibitor; deleted in MPNST/DDLPS +CDKN2B chr9 22002903 22009305 sarcoma Co-deleted with CDKN2A +VCP chr9 35053928 35072668 sarcoma Fusion partner +NTRK2 chr9 84668375 85095751 sarcoma Kinase fusions +NR4A3 chr9 99821855 99866891 sarcoma EWSR1-NR4A3; extraskeletal myxoid chondrosarcoma +BCOR chrX 40049815 40177329 sarcoma BCOR-CCNB3 / BCOR-ITD round cell sarcoma +SSX1 chrX 48255392 48267444 sarcoma SS18-SSX1; synovial sarcoma +SSX4 chrX 48383516 48393347 sarcoma SS18-SSX4; synovial sarcoma +TFE3 chrX 49028726 49043410 sarcoma ASPSCR1-TFE3 alveolar soft part sarcoma; PEComa +CCNB3 chrX 50202713 50351914 sarcoma BCOR-CCNB3 round cell sarcoma +SSX2 chrX 52696896 52707178 sarcoma SS18-SSX2; synovial sarcoma +FOXO4 chrX 71095851 71103532 sarcoma FOXO family transcription factor +OGT chrX 71533087 71575892 sarcoma OGT-PHF1; endometrial stromal sarcoma diff --git a/assets/lrsomatic_report/assets/gene_lists/sarcoma.t2t.tsv b/assets/lrsomatic_report/assets/gene_lists/sarcoma.t2t.tsv new file mode 100644 index 00000000..77fe19a2 --- /dev/null +++ b/assets/lrsomatic_report/assets/gene_lists/sarcoma.t2t.tsv @@ -0,0 +1,144 @@ +# reference: t2t +# gene spans from chm13v2.0_RefSeq_Liftoff_v5.1.gtf, except DUX4L10 (absent there) from GCF_009914755.1_T2T-CHM13v2.0_genomic.gtf.gz +# coordinates are 1-based inclusive gene spans; only valid for the reference declared above +gene chrom start end panel notes +CAMTA1 chr1 6313294 7300752 sarcoma WWTR1-CAMTA1; epithelioid haemangioendothelioma +SDHB chr1 16829151 16864469 sarcoma SDH-deficient GIST and paraganglioma +PAX7 chr1 18450908 18568930 sarcoma PAX7-FOXO1; alveolar rhabdomyosarcoma +MEAF6 chr1 37354747 37379496 sarcoma MEAF6-PHF1; ossifying fibromyxoid tumour +JUN chr1 58659236 58662492 sarcoma 1p32 amplification in DDLPS +TGFBR3 chr1 91524931 91750857 sarcoma TGFBR3-OGA lipofibromatosis-like neural tumour +CSF1 chr1 109920643 109941109 sarcoma COL6A3-CSF1; tenosynovial giant cell tumour +NRAS chr1 114715929 114728216 sarcoma RAS signalling +TPM3 chr1 153292536 153329333 sarcoma TPM3-NTRK1 / ALK fusion partner +NTRK1 chr1 155952603 156018667 sarcoma Kinase fusions; infantile fibrosarcoma-like +SDHC chr1 160451814 160512783 sarcoma SDH-deficient GIST; Carney triad +MDM4 chr1 203780802 203822528 sarcoma p53 negative regulator; 1q32 amplification +H3-3A chr1 225249743 225259926 sarcoma H3F3A G34W; giant cell tumour of bone +EPC1 chr10 32296867 32407873 sarcoma EPC1-PHF1; endometrial stromal sarcoma +RET chr10 43954542 44007848 sarcoma Kinase fusions +PTEN chr10 88747528 88855830 sarcoma PI3K pathway tumour suppressor +OGA chr10 102667945 102701933 sarcoma MGEA5; TGFBR3-OGA lipofibromatosis-like tumour +FGFR2 chr10 122374405 122494614 sarcoma RTK fusion and amplification +DUX4L10 chr10 134694717 134695995 sarcoma 10q26 D4Z4 paralog; CIC-DUX4L partner +WT1 chr11 32523264 32571024 sarcoma EWSR1-WT1; desmoplastic small round cell tumour +CREB3L1 chr11 46433747 46477484 sarcoma FUS-CREB3L1; low-grade fibromyxoid sarcoma +SDHAF2 chr11 61419022 61435631 sarcoma SDH complex assembly; SDH-deficient GIST +CCND1 chr11 69658031 69671351 sarcoma Cyclin D1 amplification +EED chr11 86186227 86230015 sarcoma PRC2; MPNST loss +MAML2 chr11 95983995 96349198 sarcoma MAML2 fusions +YAP1 chr11 102112538 102235509 sarcoma YAP1-TFE3 / YAP1-MRTFB haemangioendothelioma +POU2AF3 chr11 111308735 111318916 sarcoma COLCA2; EWSR1-POU2AF3 sarcoma +SDHD chr11 112097127 112106049 sarcoma SDH-deficient GIST and paraganglioma +KMT2A chr11 118455794 118546121 sarcoma MLL; rare sarcoma fusion partner +FLI1 chr11 128718579 128845984 sarcoma EWSR1-FLI1; Ewing sarcoma +CCND2 chr12 4280521 4312135 sarcoma Cyclin D2 amplification +ETV6 chr12 11518944 11764496 sarcoma ETV6-NTRK3; infantile fibrosarcoma +KRAS chr12 25076496 25122152 sarcoma RAS signalling +KMT2D chr12 48981150 49022967 sarcoma Histone methyltransferase; tumour suppressor +ATF1 chr12 50726620 50784323 sarcoma EWSR1-ATF1; clear cell sarcoma, AFH +TFCP2 chr12 51056573 51136022 sarcoma FUS/EWSR1-TFCP2 epithelioid rhabdomyosarcoma +NAB2 chr12 57056986 57063348 sarcoma NAB2-STAT6; solitary fibrous tumour +STAT6 chr12 57063280 57079195 sarcoma NAB2-STAT6; solitary fibrous tumour +GLI1 chr12 57428074 57440557 sarcoma GLI1-altered soft tissue tumour; 12q13 amplicon +DDIT3 chr12 57484816 57489926 sarcoma FUS/EWSR1-DDIT3; myxoid liposarcoma +CDK4 chr12 57716081 57720660 sarcoma 12q13-14; co-amplified with MDM2 in DDLPS +HMGA2 chr12 65803963 65945820 sarcoma 12q14-15; lipoma and DDLPS fusions +MDM2 chr12 68787755 68830265 sarcoma 12q15 amplification; WDLPS/DDLPS hallmark +BRCA2 chr13 31532753 31617510 sarcoma Homologous recombination repair +FOXO1 chr13 39774673 39885620 sarcoma PAX3/PAX7-FOXO1; alveolar rhabdomyosarcoma +RB1 chr13 47524085 47702182 sarcoma Cell cycle; leiomyosarcoma/osteosarcoma +GPC5 chr13 90601154 92070908 sarcoma 13q31 amplification; rhabdomyosarcoma +FOS chr14 69488228 69491630 sarcoma FOS rearrangement; osteoblastoma, epithelioid haemangioma +NUTM1 chr15 32141620 32158194 sarcoma NUTM1 fusions +TCF12 chr15 54721353 55094637 sarcoma TCF12 fusions; ossifying fibromyxoid tumour +NTRK3 chr15 85614325 86011346 sarcoma ETV6-NTRK3; infantile fibrosarcoma +MRTFB chr16 14032048 14304042 sarcoma MKL2; MRTFB-YAP1 haemangioendothelioma +PRKCB chr16 24111361 24497130 sarcoma PRKC fusion partner +FUS chr16 31567541 31582292 sarcoma FET family; FUS-DDIT3 myxoid liposarcoma +YWHAE chr17 1232983 1288946 sarcoma YWHAE-NUTM2; endometrial stromal sarcoma +USP6 chr17 5009412 5068339 sarcoma Aneurysmal bone cyst, nodular fasciitis +TP53 chr17 7572544 7591594 sarcoma Li-Fraumeni; osteosarcoma, leiomyosarcoma +TOP3A chr17 18218234 18261800 sarcoma 17p11 amplicon +NF1 chr17 32040661 32323039 sarcoma MPNST; RAS-MAPK tumour suppressor +SUZ12 chr17 32882881 32946915 sarcoma PRC2; JAZF1-SUZ12 ESS, MPNST loss +TAF15 chr17 36757395 36795152 sarcoma FET family; Ewing-like sarcoma +ERBB2 chr17 40551660 40592218 sarcoma HER2; RTK amplification +BRCA1 chr17 43902857 43983996 sarcoma Homologous recombination repair +ETV4 chr17 44380321 44398821 sarcoma ETV4 rearrangement +COL1A1 chr17 51051162 51068680 sarcoma COL1A1-PDGFB; dermatofibrosarcoma protuberans +PRKCA chr17 67172339 67686559 sarcoma PRKC fusions; chordoid-type tumours +H3-3B chr17 76669660 76673005 sarcoma H3F3B K36M; chondroblastoma +SS18 chr18 26210888 26285880 sarcoma SS18-SSX; synovial sarcoma +SMARCA4 chr19 11088037 11189277 sarcoma SWI/SNF; SMARCA4-deficient sarcoma +TPM4 chr19 16201542 16237074 sarcoma TPM4-ALK fusion partner +CIC chr19 45087903 45115169 sarcoma CIC-DUX4 round cell sarcoma +FOSB chr19 48295244 48302427 sarcoma FOSB rearrangement; pseudomyogenic haemangioendothelioma +MYCN chr2 15972182 15978635 sarcoma Amplification; rhabdomyosarcoma +NCOA1 chr2 24525913 24805480 sarcoma PAX3-NCOA1; rhabdomyosarcoma +ALK chr2 29236229 29965553 sarcoma Kinase fusions; inflammatory myofibroblastic tumour +EML4 chr2 42174851 42337951 sarcoma Kinase fusion partner (NTRK3/ALK) +GLI2 chr2 121171586 121428571 sarcoma Hedgehog pathway effector +CREB1 chr2 208003958 208080006 sarcoma EWSR1-CREB1; angiomatoid fibrous histiocytoma +FN1 chr2 215845895 215921094 sarcoma FN1 fusions; calcifying aponeurotic fibroma +FEV chr2 219469462 219473559 sarcoma EWSR1-FEV; Ewing sarcoma +PAX3 chr2 222684993 222784124 sarcoma PAX3-FOXO1; alveolar rhabdomyosarcoma +COL6A3 chr2 237815093 237905193 sarcoma COL6A3-CSF1; tenosynovial giant cell tumour +ERG chr21 36750675 37045540 sarcoma FUS-ERG / EWSR1-ERG; Ewing sarcoma +SMARCB1 chr22 24234168 24285193 sarcoma INI1; epithelioid sarcoma, rhabdoid tumour +EWSR1 chr22 29731759 29763936 sarcoma FET family; Ewing sarcoma and many other fusions +NF2 chr22 30066918 30161963 sarcoma Schwannoma and mesothelioma tumour suppressor +PATZ1 chr22 31789769 31810306 sarcoma EWSR1-PATZ1 round cell sarcoma +PDGFB chr22 39694033 39715652 sarcoma COL1A1-PDGFB; dermatofibrosarcoma protuberans +RAF1 chr3 12582405 12665632 sarcoma Kinase fusion; MAPK activation +CTNNB1 chr3 41214904 41255840 sarcoma Beta-catenin; desmoid fibromatosis +PRKCD chr3 53194119 53225596 sarcoma PRKC fusion partner +VGLL3 chr3 87012305 87065510 sarcoma 3p12 amplification +TFG chr3 103415045 103454716 sarcoma Kinase fusion partner (NTRK1/ROS1/ALK) +WWTR1 chr3 152268462 152476040 sarcoma WWTR1-CAMTA1; epithelioid haemangioendothelioma +LPP chr3 190970544 191707297 sarcoma HMGA2-LPP; lipoma, chondroid hamartoma +FGFR3 chr4 1791772 1807344 sarcoma RTK fusion and amplification +PDGFRA chr4 57718046 57786996 sarcoma GIST; imatinib target +KIT chr4 58146698 58229411 sarcoma GIST; imatinib target +KDR chr4 58566962 58614067 sarcoma VEGFR2; angiosarcoma +DUX4 chr4 193541579 193553139 sarcoma CIC-DUX4; round cell sarcoma +SDHA chr5 209363 258771 sarcoma SDH-deficient GIST and paraganglioma +TERT chr5 1160074 1202878 sarcoma Promoter and structural activation +TRIO chr5 14080499 14449245 sarcoma TRIO-TERT; undifferentiated sarcoma +APC chr5 113218062 113356772 sarcoma Wnt pathway; desmoid fibromatosis +PDGFRB chr5 150650431 150692448 sarcoma Kinase fusions in myofibroblastic tumours +CDX1 chr5 150703382 150721163 sarcoma Rare fusion partner +NPM1 chr5 171927442 171951228 sarcoma Fusion partner +FGFR4 chr5 177630123 177641352 sarcoma Rhabdomyosarcoma; RTK +FLT4 chr5 181157398 181206988 sarcoma VEGFR3; angiosarcoma +PHF1 chr6 33231774 33237801 sarcoma PHF1 fusions; ossifying fibromyxoid tumour, ESS +FOXO3 chr6 109737167 109862124 sarcoma FOXO family transcription factor +VGLL2 chr6 118449447 118457522 sarcoma VGLL2 fusions; infantile spindle cell RMS +ROS1 chr6 118471267 118609847 sarcoma Kinase fusions +ETV1 chr7 14023217 14123457 sarcoma ETV1 rearrangement +JAZF1 chr7 27968286 28318176 sarcoma JAZF1-SUZ12; endometrial stromal sarcoma +EGFR chr7 55178937 55372056 sarcoma Receptor tyrosine kinase amplification +CDK6 chr7 93846868 94078562 sarcoma Cell cycle kinase amplification +MET chr7 117987305 118113574 sarcoma Receptor tyrosine kinase amplification +BRAF chr7 142027505 142239131 sarcoma MAPK activation +CNTNAP2 chr7 147296849 149602894 sarcoma 7q35 deletion +FGFR1 chr8 38688107 38745588 sarcoma RTK fusion and amplification +PLAG1 chr8 56537883 56588262 sarcoma PLAG1 fusions; lipoblastoma, myoepithelioma +MYBL1 chr8 66987925 67038972 sarcoma Transcription factor; rare rearrangement +NCOA2 chr8 70539621 70886370 sarcoma NCOA2 fusions; congenital spindle cell RMS +HEY1 chr8 80195346 80199104 sarcoma HEY1-NCOA2; mesenchymal chondrosarcoma +MYC chr8 128862888 128870405 sarcoma 8q24 amplification; radiation-associated angiosarcoma +PTPRD chr9 8320802 10622316 sarcoma Deletion; tumour suppressor +CDKN2A chr9 21982052 22009697 sarcoma CDK4/6 inhibitor; deleted in MPNST/DDLPS +CDKN2B chr9 22017276 22023690 sarcoma Co-deleted with CDKN2A +VCP chr9 35075243 35091804 sarcoma Fusion partner +NTRK2 chr9 96818888 97177857 sarcoma Kinase fusions +NR4A3 chr9 111993520 112038527 sarcoma EWSR1-NR4A3; extraskeletal myxoid chondrosarcoma +BCOR chrX 39452491 39578567 sarcoma BCOR-CCNB3 / BCOR-ITD round cell sarcoma +SSX1 chrX 47664400 47676453 sarcoma SS18-SSX1; synovial sarcoma +SSX4 chrX 47811050 47820861 sarcoma SS18-SSX4; synovial sarcoma +TFE3 chrX 48440314 48454961 sarcoma ASPSCR1-TFE3 alveolar soft part sarcoma; PEComa +CCNB3 chrX 49520371 49623348 sarcoma BCOR-CCNB3 round cell sarcoma +SSX2 chrX 52036147 52046488 sarcoma SS18-SSX2; synovial sarcoma +FOXO4 chrX 69529947 69537628 sarcoma FOXO family transcription factor +OGT chrX 69966355 70009143 sarcoma OGT-PHF1; endometrial stromal sarcoma diff --git a/assets/lrsomatic_report/assets/js/bnd_circos.js b/assets/lrsomatic_report/assets/js/bnd_circos.js new file mode 100644 index 00000000..2d83a4ae --- /dev/null +++ b/assets/lrsomatic_report/assets/js/bnd_circos.js @@ -0,0 +1,280 @@ +// Breakend circos drawn in the browser from window.BND_DATA (see R/circos_bnd.R) so sectors re-lay-out per filter; 1000x1000 user space scaled by viewBox +(function () { + "use strict"; + + var SVG_NS = "http://www.w3.org/2000/svg"; + + // Geometry in the 1000x1000 user space, ordered outward; the ring stays inside the box to leave room for labels + var CX = 500, CY = 500; + var R_LINK = 314; // arcs terminate here, just inside the ideogram + var R_IDEO = 322; // ideogram ring, inner edge + var R_IDEO2 = 344; // ideogram ring, outer edge + var R_TICK = 352; // gene connector, inner end + var R_LABEL = 378; // gene labels sit on this radius + var R_CHROM = 300; // chromosome names, inside the ring + + var GAP_DEG = 2; // between adjacent sectors + var GAP_LAST_DEG = 6; // after the last, so the ring has a visible seam + var START_DEG = 90; // 12 o'clock, matching the genome-wide circos + var MIN_LABEL_SEP_DEG = 3.4; // greedy de-overlap target for gene labels + + // Giemsa stains, as circlize draws them. + var STAIN = { + gneg: "#f5f2ec", gpos25: "#d5cfc4", gpos50: "#b3aa9a", gpos75: "#8d8271", + gpos100: "#6b6153", gpos: "#6b6153", acen: "#b8593f", gvar: "#9d94c4", + stalk: "#8fa2b8" + }; + + function el(name, attrs) { + var n = document.createElementNS(SVG_NS, name); + for (var k in attrs) if (attrs[k] !== null && attrs[k] !== undefined) { + n.setAttribute(k, attrs[k]); + } + return n; + } + + // --- Layout ------------------------------------------------------------ + + // Angular extent per visible chromosome, proportional to length after the inter-sector gaps + function layout(chroms, lenOf) { + var total = 0, i; + for (i = 0; i < chroms.length; i++) total += lenOf(chroms[i]); + var gaps = GAP_DEG * Math.max(chroms.length - 1, 0) + GAP_LAST_DEG; + var usable = 360 - gaps; + if (total <= 0 || usable <= 0) return {}; + + var out = {}, at = START_DEG; + for (i = 0; i < chroms.length; i++) { + var span = usable * (lenOf(chroms[i]) / total); + // Angles run clockwise from 12 o'clock, which is how circlize lays these out. + out[chroms[i]] = { start: at, span: span, len: lenOf(chroms[i]) }; + at -= span + GAP_DEG; + } + return out; + } + + function angleOf(sectors, chrom, pos) { + var s = sectors[chrom]; + if (!s) return null; + var f = s.len > 0 ? Math.min(Math.max(pos / s.len, 0), 1) : 0; + return s.start - f * s.span; + } + + function pt(deg, r) { + var rad = deg * Math.PI / 180; + return [CX + r * Math.cos(rad), CY - r * Math.sin(rad)]; + } + + // Annular sector between two angles, as a filled path. + function ringPath(a0, a1, r0, r1) { + var p0 = pt(a0, r1), p1 = pt(a1, r1), p2 = pt(a1, r0), p3 = pt(a0, r0); + var large = Math.abs(a1 - a0) > 180 ? 1 : 0; + // sweep 1 = clockwise on the outer edge, because angles decrease as we go round. + return "M" + p0[0] + "," + p0[1] + + "A" + r1 + "," + r1 + " 0 " + large + " 1 " + p1[0] + "," + p1[1] + + "L" + p2[0] + "," + p2[1] + + "A" + r0 + "," + r0 + " 0 " + large + " 0 " + p3[0] + "," + p3[1] + "Z"; + } + + // Push labels apart until none is closer than MIN_LABEL_SEP_DEG (forward then backward pass); connectors show the displacement + function deoverlap(items) { + if (items.length < 2) return items; + items.sort(function (a, b) { return b.angle - a.angle; }); + var i; + for (i = 1; i < items.length; i++) { + var minA = items[i - 1].angle - MIN_LABEL_SEP_DEG; + if (items[i].angle > minA) items[i].angle = minA; + } + for (i = items.length - 2; i >= 0; i--) { + var maxA = items[i + 1].angle + MIN_LABEL_SEP_DEG; + if (items[i].angle < maxA) items[i].angle = maxA; + } + return items; + } + + // --- Drawing ----------------------------------------------------------- + + function draw(host, D, visibleIds, visibleGenes, selected) { + while (host.firstChild) host.removeChild(host.firstChild); + + var lenOf = {}, i; + for (i = 0; i < D.chromosomes.length; i++) lenOf[D.chromosomes[i]] = D.lengths[i]; + + // Only the links this filter leaves visible; null means "no filter yet". + var links = D.links.filter(function (l) { + return visibleIds === null || visibleIds.has(l.id); + }); + + var touched = {}; + links.forEach(function (l) { touched[l.chromA] = 1; touched[l.chromB] = 1; }); + var chroms = D.chromosomes.filter(function (c) { return touched[c]; }); + + if (!chroms.length) { + var note = document.createElement("p"); + note.className = "bnd-circos-empty"; + note.textContent = "No breakends match the current filter."; + host.appendChild(note); + return { arcs: 0, genes: 0, chroms: 0 }; + } + + var sectors = layout(chroms, function (c) { return lenOf[c] || 0; }); + + var svg = el("svg", { + viewBox: "0 0 1000 1000", + preserveAspectRatio: "xMidYMid meet", + role: "img", + "aria-label": "Breakend circos over " + chroms.length + " chromosomes" + }); + + var gBands = el("g", { class: "bnd-bands" }); + var gBodies = el("g", { class: "bnd-bodies" }); + var gLines = el("g", { class: "bnd-lines" }); + var gLabels = el("g", { class: "bnd-labels" }); + var gChrom = el("g", { class: "bnd-chroms" }); + var gLinks = el("g", { class: "bnd-links" }); + // Arcs last so they sit above the ring; labels above those again. + [gLinks, gBands, gBodies, gLines, gChrom, gLabels].forEach(function (g) { + svg.appendChild(g); + }); + + // Ideogram bands. + D.cytobands.forEach(function (b) { + if (!sectors[b.chrom]) return; + var a0 = angleOf(sectors, b.chrom, b.start); + var a1 = angleOf(sectors, b.chrom, b.end); + if (a0 === null || a1 === null || a0 === a1) return; + gBands.appendChild(el("path", { + d: ringPath(a0, a1, R_IDEO, R_IDEO2), + class: "bnd-band", + fill: STAIN[b.stain] || STAIN.gneg, + "data-chrom": b.chrom + })); + }); + + // Sector outline, so a chromosome with sparse banding still reads as one block. + chroms.forEach(function (c) { + var s = sectors[c]; + gBands.appendChild(el("path", { + d: ringPath(s.start, s.start - s.span, R_IDEO, R_IDEO2), + class: "bnd-sector", + "data-chrom": c + })); + }); + + // Chromosome names, inside the ring, upright. + chroms.forEach(function (c) { + var s = sectors[c]; + var p = pt(s.start - s.span / 2, R_CHROM); + var t = el("text", { + x: p[0], y: p[1], class: "bnd-chrom-label", "data-chrom": c, + "text-anchor": "middle", "dominant-baseline": "middle" + }); + t.textContent = c.replace(/^chr/, ""); + gChrom.appendChild(t); + }); + + // Gene track: only the genes the visible rows actually name. + var genes = D.genes.filter(function (g) { + return sectors[g.chrom] && visibleGenes.has(g.gene); + }); + + // Gene bodies get a floor of ~half a degree: they are markers, not spans to scale + var placed = deoverlap(genes.map(function (g) { + var mid = (g.start + g.end) / 2; + return { + gene: g.gene, panels: g.panels, chrom: g.chrom, + at: angleOf(sectors, g.chrom, mid), + angle: angleOf(sectors, g.chrom, mid), + a0: angleOf(sectors, g.chrom, g.start), + a1: angleOf(sectors, g.chrom, g.end) + }; + }).filter(function (g) { return g.at !== null; })); + + placed.forEach(function (g) { + var half = Math.max(Math.abs(g.a0 - g.a1) / 2, 0.25); + gBodies.appendChild(el("path", { + d: ringPath(g.at + half, g.at - half, R_IDEO, R_IDEO2), + class: "bnd-gene-body", + "data-gene": g.gene, "data-panels": g.panels + })); + + // Connector from the locus out to wherever de-overlapping moved the label. + var p0 = pt(g.at, R_TICK), p1 = pt(g.angle, R_LABEL - 6); + gLines.appendChild(el("polyline", { + points: p0[0] + "," + p0[1] + " " + p1[0] + "," + p1[1], + class: "bnd-gene-line", "data-gene": g.gene + })); + + // Labels read outward on the right half and inward on the left, so each needs its own rotate() + var flip = Math.cos(g.angle * Math.PI / 180) < 0; + var lp = pt(g.angle, R_LABEL); + var rot = flip ? (180 - g.angle) : -g.angle; + var t = el("text", { + x: lp[0], y: lp[1], + class: "bnd-gene-label", + "data-gene": g.gene, "data-panels": g.panels, + "text-anchor": flip ? "end" : "start", + "dominant-baseline": "middle", + transform: "rotate(" + rot + " " + lp[0] + " " + lp[1] + ")" + }); + t.textContent = g.gene; + gLabels.appendChild(t); + }); + + // Arcs: quadratic Bezier with the control point at the centre (circlize-style bundling) + links.forEach(function (l) { + var aA = angleOf(sectors, l.chromA, l.posA); + var aB = angleOf(sectors, l.chromB, l.posB); + if (aA === null || aB === null) return; + var pA = pt(aA, R_LINK), pB = pt(aB, R_LINK); + var picked = selected.has(l.id); + var arc = el("path", { + d: "M" + pA[0] + "," + pA[1] + "Q" + CX + "," + CY + " " + pB[0] + "," + pB[1], + class: "bnd-link" + (picked ? " is-selected" : ""), + "data-svid": l.id, + "data-svclass": l.svclass, + "data-chrom-a": l.chromA, + "data-chrom-b": l.chromB + }); + // Selected arcs go last within the group so they draw over their neighbours. + if (picked) gLinks.appendChild(arc); else gLinks.insertBefore(arc, gLinks.firstChild); + }); + + host.appendChild(svg); + return { arcs: links.length, genes: placed.length, chroms: chroms.length }; + } + + // --- Public surface ---------------------------------------------------- + + function normalise(raw) { + return { + chromosomes: raw.chromosomes || [], + lengths: raw.lengths || [], + cytobands: (raw.cytobands || []).map(function (r) { + return { chrom: r[0], start: r[1], end: r[2], stain: r[3] }; + }), + links: (raw.links || []).map(function (r) { + return { id: r[0], svclass: r[1], chromA: r[2], posA: r[3], + chromB: r[4], posB: r[5] }; + }), + genes: (raw.genes || []).map(function (r) { + return { chrom: r[0], start: r[1], end: r[2], gene: r[3], panels: r[4] }; + }) + }; + } + + var DATA = null; + + window.bndCircos = { + // Draw into `host` for a filter state (visibleIds/visibleGenes/selected Sets, null = everything); returns {arcs, genes, chroms} + render: function (host, visibleIds, visibleGenes, selected) { + if (!host) return { arcs: 0, genes: 0, chroms: 0 }; + if (!DATA) { + if (!window.BND_DATA) return { arcs: 0, genes: 0, chroms: 0 }; + DATA = normalise(window.BND_DATA); + } + return draw(host, DATA, visibleIds, visibleGenes || new Set(), + selected || new Set()); + } + }; +})(); diff --git a/assets/lrsomatic_report/assets/js/facet_filter.js b/assets/lrsomatic_report/assets/js/facet_filter.js new file mode 100644 index 00000000..2b450898 --- /dev/null +++ b/assets/lrsomatic_report/assets/js/facet_filter.js @@ -0,0 +1,659 @@ +// Checkbox-dropdown ("tickbox") column filters for the SNV and SV tables. R publishes values and column maps (window.*_FACETS / window.*_COLS); the menu lives in as position:fixed because DT's scroll containers clip it; no ids or document-delegated handlers (DT clones the header every draw); ticked state lives in a closure; this predicate must stay LAST in ext.search so the live counts measure the rows every other filter leaves +(function () { + "use strict"; + + // consequence is ~30 terms; impact is 4. Below this a find box is just clutter. + var SEARCH_THRESHOLD = 12; + // One draw over 167k rows runs two ext.search predicates per row, so coalesce rapid ticks. + var DRAW_DEBOUNCE_MS = 120; + var LABEL_MAX = 16; + + // Tables that get facets, keyed on the globals they publish (same test as the gene-panel predicate) + var TABLES = [ + { key: "snv", + elem: function () { return window.snvTableElem; }, + cols: function () { return window.SNV_COLS; }, + facets: function () { return window.SNV_FACETS; }, + requested: function () { return window.SNV_FACET_COLS; } }, + { key: "sv", + elem: function () { return window.svTableElem; }, + cols: function () { return window.SV_COLS; }, + facets: function () { return window.SV_FACETS; }, + requested: function () { return window.SV_FACET_COLS; } } + ]; + + // key -> { colName -> Set of ticked tokens }; null is the "(none)" bucket, an absent column is unconstrained + var STATE = { snv: {}, sv: {} }; + var ATTACHED = {}; + var WIDGETS = []; // every built widget, for the "clear all" control + var PENDING = {}; // per-table draw debounce timers + var OPEN = null; // the one open menu + + // Counting machinery keyed by table; FCOLS = facet columns resolved in *_COLS, everything else parallel to it + var FCOLS = {}; // key -> [colName] + var VOCAB = {}; // key -> colName -> { strs: [token|null], map: Map, noneId: int } + var CIDX = {}; // key -> colName -> { starts: Int32Array, ids: Int32Array } + var COUNTS = {}; // key -> colName -> [rows per vocabulary id] + var TOUCHED = {}; // key -> has the predicate run since the last flush? + + // Per-pass scratch indexed by FCOLS position, reused across rows + var SC_SRC = [], SC_LO = [], SC_HI = [], SC_TMP = []; + + function tableFor(node) { + for (var i = 0; i < TABLES.length; i++) if (TABLES[i].elem() === node) return TABLES[i]; + return null; + } + + function esc(s) { + return String(s).replace(/&/g, "&").replace(//g, ">").replace(/"/g, """); + } + + // ---- matching: separators come from R so tokens mirror how the cell was built; NA and "" fall in the null bucket ---- + function tokens(v, sep) { + if (v === null || v === undefined) return [null]; + var s = String(v).trim(); + if (s === "") return [null]; + if (!sep) return [s]; + var out = s.split(sep).map(function (x) { return x.trim(); }) + .filter(function (x) { return x.length > 0; }); + return out.length ? out : [null]; + } + + // ---- vocabulary: tokens interned to integer ids, seeded in payload order, auto-extending for the fallback split path ---- + function addTok(v, tok) { + var id = v.strs.length; + v.strs.push(tok); + if (tok === null) v.noneId = id; else v.map.set(tok, id); + return id; + } + + function idOf(v, tok) { + if (tok === null || tok === undefined) { + return v.noneId >= 0 ? v.noneId : addTok(v, null); + } + var id = v.map.get(tok); + return id === undefined ? addTok(v, tok) : id; + } + + function newVocab(def) { + var v = { strs: [], map: new Map(), noneId: -1 }; + var vals = (def && def.values) || []; + for (var i = 0; i < vals.length; i++) addTok(v, vals[i][0]); + return v; + } + + // Distinct ids of one cell into `out`, deduplicated per row like js_facet_defs() + function idsInto(voc, toks, out) { + var n = 0; + for (var i = 0; i < toks.length; i++) { + var id = idOf(voc, toks[i]), dup = false; + for (var k = 0; k < n; k++) if (out[k] === id) { dup = true; break; } + if (!dup) out[n++] = id; + } + return n; + } + + function resetCounts(key) { + var cnt = COUNTS[key], voc = VOCAB[key]; + if (!cnt) return; + Object.keys(cnt).forEach(function (nm) { + var a = cnt[nm], n = voc[nm].strs.length; + a.length = n; + for (var i = 0; i < n; i++) a[i] = 0; + }); + } + + // Set up counting structures for a table on first sight (from the predicate or attach()) + function ensureTable(t) { + if (FCOLS[t.key]) return FCOLS[t.key].length > 0; + var defs = t.facets(), cols = t.cols(); + if (!defs || !cols) return false; // not published yet — retry on the next row + var names = [], voc = {}, cnt = {}; + Object.keys(defs).forEach(function (nm) { + if (cols[nm] === undefined) return; // renamed column: attach() warns loudly + names.push(nm); + voc[nm] = newVocab(defs[nm]); + cnt[nm] = []; + }); + FCOLS[t.key] = names; + VOCAB[t.key] = voc; + COUNTS[t.key] = cnt; + resetCounts(t.key); + return names.length > 0; + } + + function bump(arr, src, lo, hi) { + for (var k = lo; k < hi; k++) { + var id = src[k]; + arr[id] = (arr[id] || 0) + 1; + } + } + + // Tokenise every row of every facet column once into a CSR index keyed by DataTables row index (~6 MB for 167k rows) + function buildIndex(t, api) { + var names = FCOLS[t.key]; + if (!names || !names.length) return; + var defs = t.facets(), cols = t.cols(); + var idxs = api.rows().indexes().toArray(); + var data = api.rows().data(); + var maxRow = -1, k; + for (k = 0; k < idxs.length; k++) if (idxs[k] > maxRow) maxRow = idxs[k]; + if (maxRow < 0) return; + + var byIdx = new Array(maxRow + 1); + for (k = 0; k < idxs.length; k++) byIdx[idxs[k]] = data[k]; + + var idx = {}, scratch = []; + for (var c = 0; c < names.length; c++) { + var nm = names[c], voc = VOCAB[t.key][nm], sep = defs[nm].sep, col = cols[nm]; + var starts = new Int32Array(maxRow + 2); + var buf = new Int32Array(Math.max(16, (maxRow + 1) * 2)); + var total = 0; + for (var r = 0; r <= maxRow; r++) { + var row = byIdx[r]; + var n = (row === undefined) ? 0 : idsInto(voc, tokens(row[col], sep), scratch); + if (total + n > buf.length) { + var grown = new Int32Array(Math.max(buf.length * 2, total + n)); + grown.set(buf); + buf = grown; + } + for (var q = 0; q < n; q++) buf[total + q] = scratch[q]; + total += n; + starts[r + 1] = total; + } + idx[nm] = { starts: starts, ids: buf.subarray(0, total) }; + } + CIDX[t.key] = idx; + } + + // One ext.search predicate for both tables: OR within a column, AND across (DataTables ANDs it with the panel and text filters); a token rule rather than a regex avoids escaping bugs. Also accumulates the exclude-own-column counts; `counter` restarts at 0 per pass + function facetPredicate(settings, searchData, index, rowData, counter) { + var t = tableFor(settings.nTable); + if (!t) return true; // another DT table in the report + if (!ensureTable(t)) return true; // no facet column on this table + + var key = t.key; + if (counter === 0 || !TOUCHED[key]) resetCounts(key); + TOUCHED[key] = true; + + var names = FCOLS[key], sel = STATE[key], voc = VOCAB[key], cnt = COUNTS[key]; + var cols = t.cols(), defs = t.facets(), idx = CIDX[key]; + // Use rowData (typed), not searchData (rendered): the SV table renders locus/size differently + var row = rowData || searchData; + var fails = 0, failed = -1, i; + + for (i = 0; i < names.length; i++) { + var nm = names[i], chosen = sel[nm]; + var hasSel = !!(chosen && chosen.size); + // After one failed column, only that column can still be counted for this row + if (!hasSel && fails > 0) { SC_LO[i] = SC_HI[i] = 0; continue; } + + var src, lo, hi; + var ci = idx && idx[nm]; + if (ci && index >= 0 && index + 1 < ci.starts.length) { + src = ci.ids; lo = ci.starts[index]; hi = ci.starts[index + 1]; + } else { + var out = SC_TMP[i] || (SC_TMP[i] = []); + hi = idsInto(voc[nm], tokens(row[cols[nm]], defs[nm].sep), out); + src = out; lo = 0; + } + SC_SRC[i] = src; SC_LO[i] = lo; SC_HI[i] = hi; + + if (hasSel) { + var hit = false, strs = voc[nm].strs; + for (var k = lo; k < hi; k++) { + if (chosen.has(strs[src[k]])) { hit = true; break; } + } + if (!hit) { + fails++; failed = i; + if (fails > 1) break; // counts for nobody; stop reading + } + } + } + + if (fails > 1) return false; + if (fails === 1) { // AND across columns + bump(cnt[names[failed]], SC_SRC[failed], SC_LO[failed], SC_HI[failed]); + return false; + } + for (i = 0; i < names.length; i++) { + bump(cnt[names[i]], SC_SRC[i], SC_LO[i], SC_HI[i]); + } + return true; + } + + $.fn.dataTable.ext.search.push(facetPredicate); + + function scheduleDraw(w) { + clearTimeout(PENDING[w.key]); + PENDING[w.key] = setTimeout(function () { + // resetPaging default: a filter change returns to the top + w.api.draw(); + }, DRAW_DEBOUNCE_MS); + } + + // ---- the open menu ------------------------------------------------------- + var EDGE = 8; // keep this much clear of every viewport edge + + function closeOpen() { + if (!OPEN) return; + var w = OPEN; + w.$menu.prop("hidden", true); + w.$btn.attr("aria-expanded", "false"); + OPEN = null; + } + + // Fixed menu placed from the button's viewport rect: left-aligned, flipped right/up and clamped when there is no room + function placeMenu(w) { + var b = w.$btn[0].getBoundingClientRect(); + var menu = w.$menu[0]; + var mw = menu.offsetWidth, mh = menu.offsetHeight; + + var left = b.left; + if (left + mw > window.innerWidth - EDGE) left = b.right - mw; + left = Math.max(EDGE, Math.min(left, window.innerWidth - EDGE - mw)); + + var top = b.bottom + 4; + if (top + mh > window.innerHeight - EDGE) { + var above = b.top - 4 - mh; + top = above >= EDGE ? above + : Math.max(EDGE, window.innerHeight - EDGE - mh); + } + + menu.style.left = Math.round(left) + "px"; + menu.style.top = Math.round(top) + "px"; + } + + function openMenu(w) { + if (OPEN === w) { closeOpen(); return; } + closeOpen(); + w.$menu.prop("hidden", false); // measurable only once it is not display:none + w.$btn.attr("aria-expanded", "true"); + OPEN = w; + placeMenu(w); + // preventScroll: letting the browser reveal the focused field would jump the table + if (w.$find.length) w.$find[0].focus({ preventScroll: true }); + } + + // A fixed menu must follow its button: one capturing document scroll listener covers the page and the scroll containers + function followButton() { + if (!OPEN) return; + var w = OPEN; + var b = w.$btn[0].getBoundingClientRect(); + var clip = w.clip ? w.clip.getBoundingClientRect() : null; + // Column scrolled out from under the menu: close it + if ((b.width === 0 && b.height === 0) || + b.bottom < 0 || b.top > window.innerHeight || + (clip && (b.right <= clip.left || b.left >= clip.right))) { + closeOpen(); + return; + } + placeMenu(w); + } + + // ---- widget: button in the header cell, menu appended to (see the header note) ---- + function buttonMarkup(name) { + return '
' + + '' + + '
'; + } + + function menuMarkup(name, def) { + var withFind = def.values.length > SEARCH_THRESHOLD; + var opts = def.values.map(function (v) { + var tok = v[0], n = v[1]; + var isNone = (tok === null); + var label = isNone ? "(none)" : tok; + return ''; + }).join(""); + + return ''; + } + + function tokenOf($cb) { + return $cb.data("none") ? null : String($cb.attr("data-tok")); + } + + // A column with nothing ticked is absent from STATE, keeping the per-row fast path cheap + var NO_SELECTION = new Set(); + + function readSel(w) { + return STATE[w.key][w.name] || NO_SELECTION; + } + + function ensureSel(w) { + var sel = STATE[w.key][w.name]; + if (!sel) { sel = new Set(); STATE[w.key][w.name] = sel; } + return sel; + } + + function pruneSel(w) { + var sel = STATE[w.key][w.name]; + if (sel && sel.size === 0) delete STATE[w.key][w.name]; + } + + function trunc(s) { + return s.length > LABEL_MAX ? s.slice(0, LABEL_MAX - 1) + "…" : s; + } + + function refreshLabel(w) { + var sel = readSel(w), n = sel.size, text, title = ""; + if (n === 0) { + text = "All"; + } else if (n === 1) { + var only = sel.values().next().value; + var lab = (only === null) ? "(none)" : only; + text = trunc(lab); + title = lab; + } else { + text = n + " selected"; + title = Array.from(sel).map(function (v) { return v === null ? "(none)" : v; }) + .join(", "); + } + w.$label.text(text); + w.$btn.attr("title", title || ("Filter " + w.name + " by value")); + w.$container.toggleClass("facet--active", n > 0); + } + + // Paint the counts from the last filtering pass, touching only changed numbers + function flushCounts(key) { + var cnt = COUNTS[key]; + if (!cnt) return; + for (var i = 0; i < WIDGETS.length; i++) { + var w = WIDGETS[i]; + if (w.key !== key) continue; + var arr = cnt[w.name]; + if (!arr) continue; + for (var j = 0; j < w.optIds.length; j++) { + var n = arr[w.optIds[j]] || 0; + if (w.optLast[j] === n) continue; + w.optLast[j] = n; + w.numNodes[j].textContent = n.toLocaleString(); + // The baseline count moves into the tooltip + w.optNodes[j].title = w.optLabel[j] + " — " + n.toLocaleString() + " of " + + w.optBase[j].toLocaleString() + " rows"; + w.optNodes[j].classList.toggle("facet__opt--empty", n === 0); + } + } + } + + function anyActive() { + return TABLES.some(function (t) { + return Object.keys(STATE[t.key]).some(function (c) { + return STATE[t.key][c] && STATE[t.key][c].size > 0; + }); + }); + } + + // Reset lives in the report's control bar (a ticked filter can be scrolled out of sight); guarded for older templates + function syncClearButton() { + var el = document.getElementById("facet-clear"); + if (el) el.hidden = !anyActive(); + } + + function clearAll() { + WIDGETS.forEach(function (w) { + delete STATE[w.key][w.name]; + w.$menu.find('input[type="checkbox"]').prop("checked", false); + refreshLabel(w); + }); + syncClearButton(); + TABLES.forEach(function (t) { + var node = t.elem(); + if (node && $.fn.dataTable.isDataTable(node)) $(node).DataTable().draw(); + }); + } + + function build(t, api, $td, name, def) { + var $wrap = $td.children("div").first(); // DT's div.form-group.has-feedback + var $input = $wrap.children("input"); + + // Hidden, not removed: DT holds a reference to this input; we never write to it + $input.hide().attr("tabindex", "-1").attr("aria-hidden", "true"); + $wrap.children("span.glyphicon").hide(); + + var $container = $(buttonMarkup(name)); + $wrap.append($container); // inside $wrap, see note 1 at the top + var $menu = $(menuMarkup(name, def)).appendTo(document.body); + + // What clips the button, so an open menu can tell its column scrolled away + var $cont = $(api.table().container()); + var $clip = $cont.find(".dataTables_scrollHead").first(); + + var w = { + key: t.key, name: name, api: api, + clip: ($clip.length ? $clip : $cont)[0], + $container: $container, + $btn: $container.find(".facet__btn"), + $label: $container.find(".facet__label"), + $menu: $menu, + $find: $menu.find(".facet__find"), + $list: $menu.find(".facet__list") + }; + + // Option rows in payload order, paired with vocabulary ids; cached raw nodes for flushCounts() + var voc = VOCAB[t.key][name]; + w.optNodes = w.$list.children(".facet__opt").toArray(); + w.numNodes = w.optNodes.map(function (el) { return el.querySelector(".facet__n"); }); + w.optIds = def.values.map(function (v) { return idOf(voc, v[0]); }); + w.optBase = def.values.map(function (v) { return Number(v[1]) || 0; }); + w.optLabel = def.values.map(function (v) { return v[0] === null ? "(none)" : v[0]; }); + w.optLast = def.values.map(function () { return -1; }); // -1: nothing painted yet + + WIDGETS.push(w); + + w.$btn.on("click", function (e) { + e.stopPropagation(); + openMenu(w); + }); + + // Delegated within our own node, never from `document` (the header clone would match too) + w.$menu.on("change", 'input[type="checkbox"]', function () { + var sel = ensureSel(w), tok = tokenOf($(this)); + if (this.checked) sel.add(tok); else sel.delete(tok); + pruneSel(w); + refreshLabel(w); + syncClearButton(); + scheduleDraw(w); + }); + + w.$menu.find(".facet__all, .facet__none").on("click", function () { + var on = $(this).hasClass("facet__all"); + var sel = ensureSel(w); + // Act only on the values currently shown by the find box + w.$list.children(".facet__opt").not(".facet__opt--hidden") + .find('input[type="checkbox"]').each(function () { + this.checked = on; + var tok = tokenOf($(this)); + if (on) sel.add(tok); else sel.delete(tok); + }); + pruneSel(w); + refreshLabel(w); + syncClearButton(); + scheduleDraw(w); + }); + + if (w.$find.length) { + w.$find.on("input", function () { + var q = this.value.trim().toLowerCase(); + w.$list.children(".facet__opt").each(function () { + var txt = $(this).find(".facet__v").text().toLowerCase(); + $(this).toggleClass("facet__opt--hidden", q.length > 0 && txt.indexOf(q) < 0); + }); + }); + } + + // Bound to both nodes: Escape must work from the find box and the button + w.$container.add(w.$menu).on("keydown", function (e) { + if (e.key === "Escape" || e.keyCode === 27) { + closeOpen(); + w.$btn.trigger("focus"); + } + }); + + refreshLabel(w); + return w; + } + + // ---- attach: re-push the predicate so it filters last ---- + function moveToEnd() { + var list = $.fn.dataTable.ext.search; + var at = list.indexOf(facetPredicate); + if (at >= 0 && at !== list.length - 1) { + list.splice(at, 1); + list.push(facetPredicate); + } + } + + function attach(t) { + if (ATTACHED[t.key]) return; + var node = t.elem(); + if (!node || !$.fn.dataTable.isDataTable(node)) return; + var defs = t.facets(), cols = t.cols(); + if (!defs || !cols) return; + + var api = $(node).DataTable(); + var $head = $(api.table().header()); // the live thead, wherever DT moved it + var $rows = $head.children("tr"); + if ($rows.length < 2) return; // no filter row: nothing to replace + ATTACHED[t.key] = true; + ensureTable(t); + moveToEnd(); + + var $label = $rows.first().children("th,td"); + var $filter = $rows.last().children("td"); + var visIdx = api.columns(":visible").indexes().toArray(); + + if ($filter.length !== visIdx.length) { + console.warn("facet_filter: " + t.key + " filter row has " + $filter.length + + " cells for " + visIdx.length + + " visible columns — leaving the text filters alone."); + return; + } + + // R drops columns it cannot offer a dropdown for and knitr swallows the message, so log it here (info: expected for `callers`/`caller`) + var requested = t.requested() || []; + var missing = requested.filter(function (n) { return !(n in defs); }); + if (missing.length) { + console.info("facet_filter: no value list for " + t.key + " column(s) " + + missing.join(", ") + " (fewer than " + + "2 distinct values, or not in the table) — they keep their text filter."); + } + + Object.keys(defs).forEach(function (name) { + var idx = cols[name]; + if (idx === undefined) { + console.warn("facet_filter: '" + name + "' is not in " + t.key.toUpperCase() + + "_COLS — was the column renamed?"); + return; + } + var pos = visIdx.indexOf(idx); + if (pos < 0) { + console.warn("facet_filter: '" + name + "' is a hidden column."); + return; + } + // Cross-check: the header label above the chosen cell must be the expected column + var got = $.trim($label.eq(pos).text()); + if (got !== name) { + console.warn("facet_filter: header mismatch for '" + name + "' at visible column " + + pos + " (found '" + got + "') — skipping."); + return; + } + var $td = $filter.eq(pos); + if ($td.attr("data-type") !== "character") { + // Factor/logical columns already carry DT's selectize control + console.warn("facet_filter: '" + name + "' has data-type '" + + $td.attr("data-type") + "' — leaving DT's own filter in place."); + return; + } + build(t, api, $td, name, defs[name]); + }); + + syncClearButton(); + + // Speed only: the predicate splits live until the index exists; a failure here must not break the filter + try { + buildIndex(t, api); + } catch (err) { + console.warn("facet_filter: could not index " + t.key + + " tokens, falling back to splitting per draw.", err); + } + + // DataTables fires `search` right after the pass that filled the counts + $(node).on("search.dt", function (e) { + if (e.target !== node) return; + if (!TOUCHED[t.key]) resetCounts(t.key); + TOUCHED[t.key] = false; + flushCounts(t.key); + }); + + // R's counts are the unfiltered baseline and --gene-panel can pre-filter, so force one pass now + api.draw(false); + } + + // Defer a tick so DT's own filter-row handlers exist; the load sweep covers tables initialised before this script + $(document).on("init.dt", function (e, settings) { + var t = tableFor(settings.nTable); + if (t) setTimeout(function () { attach(t); }, 0); + }); + + $(window).on("load", function () { + TABLES.forEach(function (t) { if (t.elem()) attach(t); }); + var clear = document.getElementById("facet-clear"); + if (clear) clear.addEventListener("click", clearAll); + syncClearButton(); + }); + + // Single outside-click handler on document, testing containment against the widget's two nodes + $(document).on("mousedown", function (e) { + if (!OPEN) return; + if (OPEN.$container[0].contains(e.target) || OPEN.$menu[0].contains(e.target)) return; + closeOpen(); + }); + + // Re-place the fixed menu on any scroll (capturing) + document.addEventListener("scroll", followButton, true); + window.addEventListener("resize", followButton); + + // Ticked state, exposed for the console and tests/js/test-facet-predicate.js + window.facetFilterState = STATE; + + // Live counts of the last pass as { table: { column: [[token, n], ...] } } + window.facetFilterCounts = function () { + var out = {}; + Object.keys(COUNTS).forEach(function (key) { + var cnt = COUNTS[key], voc = VOCAB[key]; + out[key] = {}; + Object.keys(cnt).forEach(function (nm) { + // Iterate the vocabulary, not the count array: unmatched values are 0, not gaps + var strs = voc[nm].strs, pairs = []; + for (var id = 0; id < strs.length; id++) pairs.push([strs[id], cnt[nm][id] || 0]); + out[key][nm] = pairs; + }); + }); + return out; + }; +})(); diff --git a/assets/lrsomatic_report/assets/references/hg38/chrom_lengths.tsv b/assets/lrsomatic_report/assets/references/hg38/chrom_lengths.tsv new file mode 100644 index 00000000..bbd5557d --- /dev/null +++ b/assets/lrsomatic_report/assets/references/hg38/chrom_lengths.tsv @@ -0,0 +1,25 @@ +chr1 248956422 +chr2 242193529 +chr3 198295559 +chr4 190214555 +chr5 181538259 +chr6 170805979 +chr7 159345973 +chr8 145138636 +chr9 138394717 +chr10 133797422 +chr11 135086622 +chr12 133275309 +chr13 114364328 +chr14 107043718 +chr15 101991189 +chr16 90338345 +chr17 83257441 +chr18 80373285 +chr19 58617616 +chr20 64444167 +chr21 46709983 +chr22 50818468 +chrX 156040895 +chrY 57227415 +chrM 16569 diff --git a/assets/lrsomatic_report/assets/references/hg38/cytobands.tsv b/assets/lrsomatic_report/assets/references/hg38/cytobands.tsv new file mode 100644 index 00000000..0dc94f07 --- /dev/null +++ b/assets/lrsomatic_report/assets/references/hg38/cytobands.tsv @@ -0,0 +1,1549 @@ +chr1 0 2300000 p36.33 gneg +chr1 2300000 5300000 p36.32 gpos25 +chr1 5300000 7100000 p36.31 gneg +chr1 7100000 9100000 p36.23 gpos25 +chr1 9100000 12500000 p36.22 gneg +chr1 12500000 15900000 p36.21 gpos50 +chr1 15900000 20100000 p36.13 gneg +chr1 20100000 23600000 p36.12 gpos25 +chr1 23600000 27600000 p36.11 gneg +chr1 27600000 29900000 p35.3 gpos25 +chr1 29900000 32300000 p35.2 gneg +chr1 32300000 34300000 p35.1 gpos25 +chr1 34300000 39600000 p34.3 gneg +chr1 39600000 43700000 p34.2 gpos25 +chr1 43700000 46300000 p34.1 gneg +chr1 46300000 50200000 p33 gpos75 +chr1 50200000 55600000 p32.3 gneg +chr1 55600000 58500000 p32.2 gpos50 +chr1 58500000 60800000 p32.1 gneg +chr1 60800000 68500000 p31.3 gpos50 +chr1 68500000 69300000 p31.2 gneg +chr1 69300000 84400000 p31.1 gpos100 +chr1 84400000 87900000 p22.3 gneg +chr1 87900000 91500000 p22.2 gpos75 +chr1 91500000 94300000 p22.1 gneg +chr1 94300000 99300000 p21.3 gpos75 +chr1 99300000 101800000 p21.2 gneg +chr1 101800000 106700000 p21.1 gpos100 +chr1 106700000 111200000 p13.3 gneg +chr1 111200000 115500000 p13.2 gpos50 +chr1 115500000 117200000 p13.1 gneg +chr1 117200000 120400000 p12 gpos50 +chr1 120400000 121700000 p11.2 gneg +chr1 121700000 123400000 p11.1 acen +chr1 123400000 125100000 q11 acen +chr1 125100000 143200000 q12 gvar +chr1 143200000 147500000 q21.1 gneg +chr1 147500000 150600000 q21.2 gpos50 +chr1 150600000 155100000 q21.3 gneg +chr1 155100000 156600000 q22 gpos50 +chr1 156600000 159100000 q23.1 gneg +chr1 159100000 160500000 q23.2 gpos50 +chr1 160500000 165500000 q23.3 gneg +chr1 165500000 167200000 q24.1 gpos50 +chr1 167200000 170900000 q24.2 gneg +chr1 170900000 173000000 q24.3 gpos75 +chr1 173000000 176100000 q25.1 gneg +chr1 176100000 180300000 q25.2 gpos50 +chr1 180300000 185800000 q25.3 gneg +chr1 185800000 190800000 q31.1 gpos100 +chr1 190800000 193800000 q31.2 gneg +chr1 193800000 198700000 q31.3 gpos100 +chr1 198700000 207100000 q32.1 gneg +chr1 207100000 211300000 q32.2 gpos25 +chr1 211300000 214400000 q32.3 gneg +chr1 214400000 223900000 q41 gpos100 +chr1 223900000 224400000 q42.11 gneg +chr1 224400000 226800000 q42.12 gpos25 +chr1 226800000 230500000 q42.13 gneg +chr1 230500000 234600000 q42.2 gpos50 +chr1 234600000 236400000 q42.3 gneg +chr1 236400000 243500000 q43 gpos75 +chr1 243500000 248956422 q44 gneg +chr10 0 3000000 p15.3 gneg +chr10 3000000 3800000 p15.2 gpos25 +chr10 3800000 6600000 p15.1 gneg +chr10 6600000 12200000 p14 gpos75 +chr10 12200000 17300000 p13 gneg +chr10 17300000 18300000 p12.33 gpos75 +chr10 18300000 18400000 p12.32 gneg +chr10 18400000 22300000 p12.31 gpos75 +chr10 22300000 24300000 p12.2 gneg +chr10 24300000 29300000 p12.1 gpos50 +chr10 29300000 31100000 p11.23 gneg +chr10 31100000 34200000 p11.22 gpos25 +chr10 34200000 38000000 p11.21 gneg +chr10 38000000 39800000 p11.1 acen +chr10 39800000 41600000 q11.1 acen +chr10 41600000 45500000 q11.21 gneg +chr10 45500000 48600000 q11.22 gpos25 +chr10 48600000 51100000 q11.23 gneg +chr10 51100000 59400000 q21.1 gpos100 +chr10 59400000 62800000 q21.2 gneg +chr10 62800000 68800000 q21.3 gpos100 +chr10 68800000 73100000 q22.1 gneg +chr10 73100000 75900000 q22.2 gpos50 +chr10 75900000 80300000 q22.3 gneg +chr10 80300000 86100000 q23.1 gpos100 +chr10 86100000 87700000 q23.2 gneg +chr10 87700000 91100000 q23.31 gpos75 +chr10 91100000 92300000 q23.32 gneg +chr10 92300000 95300000 q23.33 gpos50 +chr10 95300000 97500000 q24.1 gneg +chr10 97500000 100100000 q24.2 gpos50 +chr10 100100000 101200000 q24.31 gneg +chr10 101200000 103100000 q24.32 gpos25 +chr10 103100000 104000000 q24.33 gneg +chr10 104000000 110100000 q25.1 gpos100 +chr10 110100000 113100000 q25.2 gneg +chr10 113100000 117300000 q25.3 gpos75 +chr10 117300000 119900000 q26.11 gneg +chr10 119900000 121400000 q26.12 gpos50 +chr10 121400000 125700000 q26.13 gneg +chr10 125700000 128800000 q26.2 gpos50 +chr10 128800000 133797422 q26.3 gneg +chr10_GL383545v1_alt 0 179254 gneg +chr10_GL383546v1_alt 0 309802 gneg +chr10_KI270824v1_alt 0 181496 gneg +chr10_KI270825v1_alt 0 188315 gneg +chr11 0 2800000 p15.5 gneg +chr11 2800000 11700000 p15.4 gpos50 +chr11 11700000 13800000 p15.3 gneg +chr11 13800000 16900000 p15.2 gpos50 +chr11 16900000 22000000 p15.1 gneg +chr11 22000000 26200000 p14.3 gpos100 +chr11 26200000 27200000 p14.2 gneg +chr11 27200000 31000000 p14.1 gpos75 +chr11 31000000 36400000 p13 gneg +chr11 36400000 43400000 p12 gpos100 +chr11 43400000 48800000 p11.2 gneg +chr11 48800000 51000000 p11.12 gpos75 +chr11 51000000 53400000 p11.11 acen +chr11 53400000 55800000 q11 acen +chr11 55800000 60100000 q12.1 gpos75 +chr11 60100000 61900000 q12.2 gneg +chr11 61900000 63600000 q12.3 gpos25 +chr11 63600000 66100000 q13.1 gneg +chr11 66100000 68700000 q13.2 gpos25 +chr11 68700000 70500000 q13.3 gneg +chr11 70500000 75500000 q13.4 gpos50 +chr11 75500000 77400000 q13.5 gneg +chr11 77400000 85900000 q14.1 gpos100 +chr11 85900000 88600000 q14.2 gneg +chr11 88600000 93000000 q14.3 gpos100 +chr11 93000000 97400000 q21 gneg +chr11 97400000 102300000 q22.1 gpos100 +chr11 102300000 103000000 q22.2 gneg +chr11 103000000 110600000 q22.3 gpos100 +chr11 110600000 112700000 q23.1 gneg +chr11 112700000 114600000 q23.2 gpos50 +chr11 114600000 121300000 q23.3 gneg +chr11 121300000 124000000 q24.1 gpos50 +chr11 124000000 127900000 q24.2 gneg +chr11 127900000 130900000 q24.3 gpos50 +chr11 130900000 135086622 q25 gneg +chr11_GL383547v1_alt 0 154407 gneg +chr11_JH159136v1_alt 0 200998 gneg +chr11_JH159137v1_alt 0 191409 gneg +chr11_KI270721v1_random 0 100316 gneg +chr11_KI270826v1_alt 0 186169 gneg +chr11_KI270827v1_alt 0 67707 gneg +chr11_KI270829v1_alt 0 204059 gneg +chr11_KI270830v1_alt 0 177092 gneg +chr11_KI270831v1_alt 0 296895 gneg +chr11_KI270832v1_alt 0 210133 gneg +chr11_KI270902v1_alt 0 106711 gneg +chr11_KI270903v1_alt 0 214625 gneg +chr11_KI270927v1_alt 0 218612 gneg +chr12 0 3200000 p13.33 gneg +chr12 3200000 5300000 p13.32 gpos25 +chr12 5300000 10000000 p13.31 gneg +chr12 10000000 12600000 p13.2 gpos75 +chr12 12600000 14600000 p13.1 gneg +chr12 14600000 19800000 p12.3 gpos100 +chr12 19800000 21100000 p12.2 gneg +chr12 21100000 26300000 p12.1 gpos100 +chr12 26300000 27600000 p11.23 gneg +chr12 27600000 30500000 p11.22 gpos50 +chr12 30500000 33200000 p11.21 gneg +chr12 33200000 35500000 p11.1 acen +chr12 35500000 37800000 q11 acen +chr12 37800000 46000000 q12 gpos100 +chr12 46000000 48700000 q13.11 gneg +chr12 48700000 51100000 q13.12 gpos25 +chr12 51100000 54500000 q13.13 gneg +chr12 54500000 56200000 q13.2 gpos25 +chr12 56200000 57700000 q13.3 gneg +chr12 57700000 62700000 q14.1 gpos75 +chr12 62700000 64700000 q14.2 gneg +chr12 64700000 67300000 q14.3 gpos50 +chr12 67300000 71100000 q15 gneg +chr12 71100000 75300000 q21.1 gpos75 +chr12 75300000 79900000 q21.2 gneg +chr12 79900000 86300000 q21.31 gpos100 +chr12 86300000 88600000 q21.32 gneg +chr12 88600000 92200000 q21.33 gpos100 +chr12 92200000 95800000 q22 gneg +chr12 95800000 101200000 q23.1 gpos75 +chr12 101200000 103500000 q23.2 gneg +chr12 103500000 108600000 q23.3 gpos50 +chr12 108600000 111300000 q24.11 gneg +chr12 111300000 111900000 q24.12 gpos25 +chr12 111900000 113900000 q24.13 gneg +chr12 113900000 116400000 q24.21 gpos50 +chr12 116400000 117700000 q24.22 gneg +chr12 117700000 120300000 q24.23 gpos50 +chr12 120300000 125400000 q24.31 gneg +chr12 125400000 128700000 q24.32 gpos50 +chr12 128700000 133275309 q24.33 gneg +chr12_GL383549v1_alt 0 120804 gneg +chr12_GL383550v2_alt 0 169178 gneg +chr12_GL383551v1_alt 0 184319 gneg +chr12_GL383552v1_alt 0 138655 gneg +chr12_GL383553v2_alt 0 152874 gneg +chr12_GL877875v1_alt 0 167313 gneg +chr12_GL877876v1_alt 0 408271 gneg +chr12_KI270833v1_alt 0 76061 gneg +chr12_KI270834v1_alt 0 119498 gneg +chr12_KI270835v1_alt 0 238139 gneg +chr12_KI270836v1_alt 0 56134 gneg +chr12_KI270837v1_alt 0 40090 gneg +chr12_KI270904v1_alt 0 572349 gneg +chr13 0 4600000 p13 gvar +chr13 4600000 10100000 p12 stalk +chr13 10100000 16500000 p11.2 gvar +chr13 16500000 17700000 p11.1 acen +chr13 17700000 18900000 q11 acen +chr13 18900000 22600000 q12.11 gneg +chr13 22600000 24900000 q12.12 gpos25 +chr13 24900000 27200000 q12.13 gneg +chr13 27200000 28300000 q12.2 gpos25 +chr13 28300000 31600000 q12.3 gneg +chr13 31600000 33400000 q13.1 gpos50 +chr13 33400000 34900000 q13.2 gneg +chr13 34900000 39500000 q13.3 gpos75 +chr13 39500000 44600000 q14.11 gneg +chr13 44600000 45200000 q14.12 gpos25 +chr13 45200000 46700000 q14.13 gneg +chr13 46700000 50300000 q14.2 gpos50 +chr13 50300000 54700000 q14.3 gneg +chr13 54700000 59000000 q21.1 gpos100 +chr13 59000000 61800000 q21.2 gneg +chr13 61800000 65200000 q21.31 gpos75 +chr13 65200000 68100000 q21.32 gneg +chr13 68100000 72800000 q21.33 gpos100 +chr13 72800000 74900000 q22.1 gneg +chr13 74900000 76700000 q22.2 gpos50 +chr13 76700000 78500000 q22.3 gneg +chr13 78500000 87100000 q31.1 gpos100 +chr13 87100000 89400000 q31.2 gneg +chr13 89400000 94400000 q31.3 gpos100 +chr13 94400000 97500000 q32.1 gneg +chr13 97500000 98700000 q32.2 gpos25 +chr13 98700000 101100000 q32.3 gneg +chr13 101100000 104200000 q33.1 gpos100 +chr13 104200000 106400000 q33.2 gneg +chr13 106400000 109600000 q33.3 gpos100 +chr13 109600000 114364328 q34 gneg +chr13_KI270838v1_alt 0 306913 gneg +chr13_KI270839v1_alt 0 180306 gneg +chr13_KI270840v1_alt 0 191684 gneg +chr13_KI270841v1_alt 0 169134 gneg +chr13_KI270842v1_alt 0 37287 gneg +chr13_KI270843v1_alt 0 103832 gneg +chr14 0 3600000 p13 gvar +chr14 3600000 8000000 p12 stalk +chr14 8000000 16100000 p11.2 gvar +chr14 16100000 17200000 p11.1 acen +chr14 17200000 18200000 q11.1 acen +chr14 18200000 24100000 q11.2 gneg +chr14 24100000 32900000 q12 gpos100 +chr14 32900000 34800000 q13.1 gneg +chr14 34800000 36100000 q13.2 gpos50 +chr14 36100000 37400000 q13.3 gneg +chr14 37400000 43000000 q21.1 gpos100 +chr14 43000000 46700000 q21.2 gneg +chr14 46700000 50400000 q21.3 gpos100 +chr14 50400000 53600000 q22.1 gneg +chr14 53600000 55000000 q22.2 gpos25 +chr14 55000000 57600000 q22.3 gneg +chr14 57600000 61600000 q23.1 gpos75 +chr14 61600000 64300000 q23.2 gneg +chr14 64300000 67400000 q23.3 gpos50 +chr14 67400000 69800000 q24.1 gneg +chr14 69800000 73300000 q24.2 gpos50 +chr14 73300000 78800000 q24.3 gneg +chr14 78800000 83100000 q31.1 gpos100 +chr14 83100000 84400000 q31.2 gneg +chr14 84400000 89300000 q31.3 gpos100 +chr14 89300000 91400000 q32.11 gneg +chr14 91400000 94200000 q32.12 gpos25 +chr14 94200000 95800000 q32.13 gneg +chr14 95800000 100900000 q32.2 gpos50 +chr14 100900000 102700000 q32.31 gneg +chr14 102700000 103500000 q32.32 gpos50 +chr14 103500000 107043718 q32.33 gneg +chr14_GL000009v2_random 0 201709 gneg +chr14_GL000194v1_random 0 191469 gneg +chr14_GL000225v1_random 0 211173 gneg +chr14_KI270722v1_random 0 194050 gneg +chr14_KI270723v1_random 0 38115 gneg +chr14_KI270724v1_random 0 39555 gneg +chr14_KI270725v1_random 0 172810 gneg +chr14_KI270726v1_random 0 43739 gneg +chr14_KI270844v1_alt 0 322166 gneg +chr14_KI270845v1_alt 0 180703 gneg +chr14_KI270846v1_alt 0 1351393 gneg +chr14_KI270847v1_alt 0 1511111 gneg +chr15 0 4200000 p13 gvar +chr15 4200000 9700000 p12 stalk +chr15 9700000 17500000 p11.2 gvar +chr15 17500000 19000000 p11.1 acen +chr15 19000000 20500000 q11.1 acen +chr15 20500000 25500000 q11.2 gneg +chr15 25500000 27800000 q12 gpos50 +chr15 27800000 30000000 q13.1 gneg +chr15 30000000 30900000 q13.2 gpos50 +chr15 30900000 33400000 q13.3 gneg +chr15 33400000 39800000 q14 gpos75 +chr15 39800000 42500000 q15.1 gneg +chr15 42500000 43300000 q15.2 gpos25 +chr15 43300000 44500000 q15.3 gneg +chr15 44500000 49200000 q21.1 gpos75 +chr15 49200000 52600000 q21.2 gneg +chr15 52600000 58800000 q21.3 gpos75 +chr15 58800000 59000000 q22.1 gneg +chr15 59000000 63400000 q22.2 gpos25 +chr15 63400000 66900000 q22.31 gneg +chr15 66900000 67000000 q22.32 gpos25 +chr15 67000000 67200000 q22.33 gneg +chr15 67200000 72400000 q23 gpos25 +chr15 72400000 74900000 q24.1 gneg +chr15 74900000 76300000 q24.2 gpos25 +chr15 76300000 78000000 q24.3 gneg +chr15 78000000 81400000 q25.1 gpos50 +chr15 81400000 84700000 q25.2 gneg +chr15 84700000 88500000 q25.3 gpos50 +chr15 88500000 93800000 q26.1 gneg +chr15 93800000 98000000 q26.2 gpos50 +chr15 98000000 101991189 q26.3 gneg +chr15_GL383554v1_alt 0 296527 gneg +chr15_GL383555v2_alt 0 388773 gneg +chr15_KI270727v1_random 0 448248 gneg +chr15_KI270848v1_alt 0 327382 gneg +chr15_KI270849v1_alt 0 244917 gneg +chr15_KI270850v1_alt 0 430880 gneg +chr15_KI270851v1_alt 0 263054 gneg +chr15_KI270852v1_alt 0 478999 gneg +chr15_KI270905v1_alt 0 5161414 gneg +chr15_KI270906v1_alt 0 196384 gneg +chr16 0 7800000 p13.3 gneg +chr16 7800000 10400000 p13.2 gpos50 +chr16 10400000 12500000 p13.13 gneg +chr16 12500000 14700000 p13.12 gpos50 +chr16 14700000 16700000 p13.11 gneg +chr16 16700000 21200000 p12.3 gpos50 +chr16 21200000 24200000 p12.2 gneg +chr16 24200000 28500000 p12.1 gpos50 +chr16 28500000 35300000 p11.2 gneg +chr16 35300000 36800000 p11.1 acen +chr16 36800000 38400000 q11.1 acen +chr16 38400000 47000000 q11.2 gvar +chr16 47000000 52600000 q12.1 gneg +chr16 52600000 56000000 q12.2 gpos50 +chr16 56000000 57300000 q13 gneg +chr16 57300000 66600000 q21 gpos100 +chr16 66600000 70800000 q22.1 gneg +chr16 70800000 72800000 q22.2 gpos50 +chr16 72800000 74100000 q22.3 gneg +chr16 74100000 79200000 q23.1 gpos75 +chr16 79200000 81600000 q23.2 gneg +chr16 81600000 84100000 q23.3 gpos50 +chr16 84100000 87000000 q24.1 gneg +chr16 87000000 88700000 q24.2 gpos25 +chr16 88700000 90338345 q24.3 gneg +chr16_GL383556v1_alt 0 192462 gneg +chr16_GL383557v1_alt 0 89672 gneg +chr16_KI270728v1_random 0 1872759 gneg +chr16_KI270853v1_alt 0 2659700 gneg +chr16_KI270854v1_alt 0 134193 gneg +chr16_KI270855v1_alt 0 232857 gneg +chr16_KI270856v1_alt 0 63982 gneg +chr17 0 3400000 p13.3 gneg +chr17 3400000 6500000 p13.2 gpos50 +chr17 6500000 10800000 p13.1 gneg +chr17 10800000 16100000 p12 gpos75 +chr17 16100000 22700000 p11.2 gneg +chr17 22700000 25100000 p11.1 acen +chr17 25100000 27400000 q11.1 acen +chr17 27400000 33500000 q11.2 gneg +chr17 33500000 39800000 q12 gpos50 +chr17 39800000 40200000 q21.1 gneg +chr17 40200000 42800000 q21.2 gpos25 +chr17 42800000 46800000 q21.31 gneg +chr17 46800000 49300000 q21.32 gpos25 +chr17 49300000 52100000 q21.33 gneg +chr17 52100000 59500000 q22 gpos75 +chr17 59500000 60200000 q23.1 gneg +chr17 60200000 63100000 q23.2 gpos75 +chr17 63100000 64600000 q23.3 gneg +chr17 64600000 66200000 q24.1 gpos50 +chr17 66200000 69100000 q24.2 gneg +chr17 69100000 72900000 q24.3 gpos75 +chr17 72900000 76800000 q25.1 gneg +chr17 76800000 77200000 q25.2 gpos25 +chr17 77200000 83257441 q25.3 gneg +chr17_GL000205v2_random 0 185591 gneg +chr17_GL000258v2_alt 0 1821992 gneg +chr17_GL383563v3_alt 0 375691 gneg +chr17_GL383564v2_alt 0 133151 gneg +chr17_GL383565v1_alt 0 223995 gneg +chr17_GL383566v1_alt 0 90219 gneg +chr17_JH159146v1_alt 0 278131 gneg +chr17_JH159147v1_alt 0 70345 gneg +chr17_JH159148v1_alt 0 88070 gneg +chr17_KI270729v1_random 0 280839 gneg +chr17_KI270730v1_random 0 112551 gneg +chr17_KI270857v1_alt 0 2877074 gneg +chr17_KI270858v1_alt 0 235827 gneg +chr17_KI270859v1_alt 0 108763 gneg +chr17_KI270860v1_alt 0 178921 gneg +chr17_KI270861v1_alt 0 196688 gneg +chr17_KI270862v1_alt 0 391357 gneg +chr17_KI270907v1_alt 0 137721 gneg +chr17_KI270908v1_alt 0 1423190 gneg +chr17_KI270909v1_alt 0 325800 gneg +chr17_KI270910v1_alt 0 157099 gneg +chr18 0 2900000 p11.32 gneg +chr18 2900000 7200000 p11.31 gpos50 +chr18 7200000 8500000 p11.23 gneg +chr18 8500000 10900000 p11.22 gpos25 +chr18 10900000 15400000 p11.21 gneg +chr18 15400000 18500000 p11.1 acen +chr18 18500000 21500000 q11.1 acen +chr18 21500000 27500000 q11.2 gneg +chr18 27500000 35100000 q12.1 gpos100 +chr18 35100000 39500000 q12.2 gneg +chr18 39500000 45900000 q12.3 gpos75 +chr18 45900000 50700000 q21.1 gneg +chr18 50700000 56200000 q21.2 gpos75 +chr18 56200000 58600000 q21.31 gneg +chr18 58600000 61300000 q21.32 gpos50 +chr18 61300000 63900000 q21.33 gneg +chr18 63900000 69100000 q22.1 gpos100 +chr18 69100000 71000000 q22.2 gneg +chr18 71000000 75400000 q22.3 gpos25 +chr18 75400000 80373285 q23 gneg +chr18_GL383567v1_alt 0 289831 gneg +chr18_GL383568v1_alt 0 104552 gneg +chr18_GL383569v1_alt 0 167950 gneg +chr18_GL383570v1_alt 0 164789 gneg +chr18_GL383571v1_alt 0 198278 gneg +chr18_GL383572v1_alt 0 159547 gneg +chr18_KI270863v1_alt 0 167999 gneg +chr18_KI270864v1_alt 0 111737 gneg +chr18_KI270911v1_alt 0 157710 gneg +chr18_KI270912v1_alt 0 174061 gneg +chr19 0 6900000 p13.3 gneg +chr19 6900000 12600000 p13.2 gpos25 +chr19 12600000 13800000 p13.13 gneg +chr19 13800000 16100000 p13.12 gpos25 +chr19 16100000 19900000 p13.11 gneg +chr19 19900000 24200000 p12 gvar +chr19 24200000 26200000 p11 acen +chr19 26200000 28100000 q11 acen +chr19 28100000 31900000 q12 gvar +chr19 31900000 35100000 q13.11 gneg +chr19 35100000 37800000 q13.12 gpos25 +chr19 37800000 38200000 q13.13 gneg +chr19 38200000 42900000 q13.2 gpos25 +chr19 42900000 44700000 q13.31 gneg +chr19 44700000 47500000 q13.32 gpos25 +chr19 47500000 50900000 q13.33 gneg +chr19 50900000 53100000 q13.41 gpos25 +chr19 53100000 55800000 q13.42 gneg +chr19 55800000 58617616 q13.43 gpos25 +chr19_GL000209v2_alt 0 177381 gneg +chr19_GL383573v1_alt 0 385657 gneg +chr19_GL383574v1_alt 0 155864 gneg +chr19_GL383575v2_alt 0 170222 gneg +chr19_GL383576v1_alt 0 188024 gneg +chr19_GL949746v1_alt 0 987716 gneg +chr19_GL949747v2_alt 0 729520 gneg +chr19_GL949748v2_alt 0 1064304 gneg +chr19_GL949749v2_alt 0 1091841 gneg +chr19_GL949750v2_alt 0 1066390 gneg +chr19_GL949751v2_alt 0 1002683 gneg +chr19_GL949752v1_alt 0 987100 gneg +chr19_GL949753v2_alt 0 796479 gneg +chr19_KI270865v1_alt 0 52969 gneg +chr19_KI270866v1_alt 0 43156 gneg +chr19_KI270867v1_alt 0 233762 gneg +chr19_KI270868v1_alt 0 61734 gneg +chr19_KI270882v1_alt 0 248807 gneg +chr19_KI270883v1_alt 0 170399 gneg +chr19_KI270884v1_alt 0 157053 gneg +chr19_KI270885v1_alt 0 171027 gneg +chr19_KI270886v1_alt 0 204239 gneg +chr19_KI270887v1_alt 0 209512 gneg +chr19_KI270888v1_alt 0 155532 gneg +chr19_KI270889v1_alt 0 170698 gneg +chr19_KI270890v1_alt 0 184499 gneg +chr19_KI270891v1_alt 0 170680 gneg +chr19_KI270914v1_alt 0 205194 gneg +chr19_KI270915v1_alt 0 170665 gneg +chr19_KI270916v1_alt 0 184516 gneg +chr19_KI270917v1_alt 0 190932 gneg +chr19_KI270918v1_alt 0 123111 gneg +chr19_KI270919v1_alt 0 170701 gneg +chr19_KI270920v1_alt 0 198005 gneg +chr19_KI270921v1_alt 0 282224 gneg +chr19_KI270922v1_alt 0 187935 gneg +chr19_KI270923v1_alt 0 189352 gneg +chr19_KI270929v1_alt 0 186203 gneg +chr19_KI270930v1_alt 0 200773 gneg +chr19_KI270931v1_alt 0 170148 gneg +chr19_KI270932v1_alt 0 215732 gneg +chr19_KI270933v1_alt 0 170537 gneg +chr19_KI270938v1_alt 0 1066800 gneg +chr1_GL383518v1_alt 0 182439 gneg +chr1_GL383519v1_alt 0 110268 gneg +chr1_GL383520v2_alt 0 366580 gneg +chr1_KI270706v1_random 0 175055 gneg +chr1_KI270707v1_random 0 32032 gneg +chr1_KI270708v1_random 0 127682 gneg +chr1_KI270709v1_random 0 66860 gneg +chr1_KI270710v1_random 0 40176 gneg +chr1_KI270711v1_random 0 42210 gneg +chr1_KI270712v1_random 0 176043 gneg +chr1_KI270713v1_random 0 40745 gneg +chr1_KI270714v1_random 0 41717 gneg +chr1_KI270759v1_alt 0 425601 gneg +chr1_KI270760v1_alt 0 109528 gneg +chr1_KI270761v1_alt 0 165834 gneg +chr1_KI270762v1_alt 0 354444 gneg +chr1_KI270763v1_alt 0 911658 gneg +chr1_KI270764v1_alt 0 50258 gneg +chr1_KI270765v1_alt 0 185285 gneg +chr1_KI270766v1_alt 0 256271 gneg +chr1_KI270892v1_alt 0 162212 gneg +chr2 0 4400000 p25.3 gneg +chr2 4400000 6900000 p25.2 gpos50 +chr2 6900000 12000000 p25.1 gneg +chr2 12000000 16500000 p24.3 gpos75 +chr2 16500000 19000000 p24.2 gneg +chr2 19000000 23800000 p24.1 gpos75 +chr2 23800000 27700000 p23.3 gneg +chr2 27700000 29800000 p23.2 gpos25 +chr2 29800000 31800000 p23.1 gneg +chr2 31800000 36300000 p22.3 gpos75 +chr2 36300000 38300000 p22.2 gneg +chr2 38300000 41500000 p22.1 gpos50 +chr2 41500000 47500000 p21 gneg +chr2 47500000 52600000 p16.3 gpos100 +chr2 52600000 54700000 p16.2 gneg +chr2 54700000 61000000 p16.1 gpos100 +chr2 61000000 63900000 p15 gneg +chr2 63900000 68400000 p14 gpos50 +chr2 68400000 71300000 p13.3 gneg +chr2 71300000 73300000 p13.2 gpos50 +chr2 73300000 74800000 p13.1 gneg +chr2 74800000 83100000 p12 gpos100 +chr2 83100000 91800000 p11.2 gneg +chr2 91800000 93900000 p11.1 acen +chr2 93900000 96000000 q11.1 acen +chr2 96000000 102100000 q11.2 gneg +chr2 102100000 105300000 q12.1 gpos50 +chr2 105300000 106700000 q12.2 gneg +chr2 106700000 108700000 q12.3 gpos25 +chr2 108700000 112200000 q13 gneg +chr2 112200000 118100000 q14.1 gpos50 +chr2 118100000 121600000 q14.2 gneg +chr2 121600000 129100000 q14.3 gpos50 +chr2 129100000 131700000 q21.1 gneg +chr2 131700000 134300000 q21.2 gpos25 +chr2 134300000 136100000 q21.3 gneg +chr2 136100000 141500000 q22.1 gpos100 +chr2 141500000 143400000 q22.2 gneg +chr2 143400000 147900000 q22.3 gpos100 +chr2 147900000 149000000 q23.1 gneg +chr2 149000000 149600000 q23.2 gpos25 +chr2 149600000 154000000 q23.3 gneg +chr2 154000000 158900000 q24.1 gpos75 +chr2 158900000 162900000 q24.2 gneg +chr2 162900000 168900000 q24.3 gpos75 +chr2 168900000 177100000 q31.1 gneg +chr2 177100000 179700000 q31.2 gpos50 +chr2 179700000 182100000 q31.3 gneg +chr2 182100000 188500000 q32.1 gpos75 +chr2 188500000 191100000 q32.2 gneg +chr2 191100000 196600000 q32.3 gpos75 +chr2 196600000 202500000 q33.1 gneg +chr2 202500000 204100000 q33.2 gpos50 +chr2 204100000 208200000 q33.3 gneg +chr2 208200000 214500000 q34 gpos100 +chr2 214500000 220700000 q35 gneg +chr2 220700000 224300000 q36.1 gpos75 +chr2 224300000 225200000 q36.2 gneg +chr2 225200000 230100000 q36.3 gpos100 +chr2 230100000 234700000 q37.1 gneg +chr2 234700000 236400000 q37.2 gpos50 +chr2 236400000 242193529 q37.3 gneg +chr20 0 5100000 p13 gneg +chr20 5100000 9200000 p12.3 gpos75 +chr20 9200000 12000000 p12.2 gneg +chr20 12000000 17900000 p12.1 gpos75 +chr20 17900000 21300000 p11.23 gneg +chr20 21300000 22300000 p11.22 gpos25 +chr20 22300000 25700000 p11.21 gneg +chr20 25700000 28100000 p11.1 acen +chr20 28100000 30400000 q11.1 acen +chr20 30400000 33500000 q11.21 gneg +chr20 33500000 35800000 q11.22 gpos25 +chr20 35800000 39000000 q11.23 gneg +chr20 39000000 43100000 q12 gpos75 +chr20 43100000 43500000 q13.11 gneg +chr20 43500000 47800000 q13.12 gpos25 +chr20 47800000 51200000 q13.13 gneg +chr20 51200000 56400000 q13.2 gpos75 +chr20 56400000 57800000 q13.31 gneg +chr20 57800000 59700000 q13.32 gpos50 +chr20 59700000 64444167 q13.33 gneg +chr20_GL383577v2_alt 0 128386 gneg +chr20_KI270869v1_alt 0 118774 gneg +chr20_KI270870v1_alt 0 183433 gneg +chr20_KI270871v1_alt 0 58661 gneg +chr21 0 3100000 p13 gvar +chr21 3100000 7000000 p12 stalk +chr21 7000000 10900000 p11.2 gvar +chr21 10900000 12000000 p11.1 acen +chr21 12000000 13000000 q11.1 acen +chr21 13000000 15000000 q11.2 gneg +chr21 15000000 22600000 q21.1 gpos100 +chr21 22600000 25500000 q21.2 gneg +chr21 25500000 30200000 q21.3 gpos75 +chr21 30200000 34400000 q22.11 gneg +chr21 34400000 36400000 q22.12 gpos50 +chr21 36400000 38300000 q22.13 gneg +chr21 38300000 41200000 q22.2 gpos50 +chr21 41200000 46709983 q22.3 gneg +chr21_GL383578v2_alt 0 63917 gneg +chr21_GL383579v2_alt 0 201197 gneg +chr21_GL383580v2_alt 0 74653 gneg +chr21_GL383581v2_alt 0 116689 gneg +chr21_KI270872v1_alt 0 82692 gneg +chr21_KI270873v1_alt 0 143900 gneg +chr21_KI270874v1_alt 0 166743 gneg +chr22 0 4300000 p13 gvar +chr22 4300000 9400000 p12 stalk +chr22 9400000 13700000 p11.2 gvar +chr22 13700000 15000000 p11.1 acen +chr22 15000000 17400000 q11.1 acen +chr22 17400000 21700000 q11.21 gneg +chr22 21700000 23100000 q11.22 gpos25 +chr22 23100000 25500000 q11.23 gneg +chr22 25500000 29200000 q12.1 gpos50 +chr22 29200000 31800000 q12.2 gneg +chr22 31800000 37200000 q12.3 gpos50 +chr22 37200000 40600000 q13.1 gneg +chr22 40600000 43800000 q13.2 gpos50 +chr22 43800000 48100000 q13.31 gneg +chr22 48100000 49100000 q13.32 gpos50 +chr22 49100000 50818468 q13.33 gneg +chr22_GL383582v2_alt 0 162811 gneg +chr22_GL383583v2_alt 0 96924 gneg +chr22_KB663609v1_alt 0 74013 gneg +chr22_KI270731v1_random 0 150754 gneg +chr22_KI270732v1_random 0 41543 gneg +chr22_KI270733v1_random 0 179772 gneg +chr22_KI270734v1_random 0 165050 gneg +chr22_KI270735v1_random 0 42811 gneg +chr22_KI270736v1_random 0 181920 gneg +chr22_KI270737v1_random 0 103838 gneg +chr22_KI270738v1_random 0 99375 gneg +chr22_KI270739v1_random 0 73985 gneg +chr22_KI270875v1_alt 0 259914 gneg +chr22_KI270876v1_alt 0 263666 gneg +chr22_KI270877v1_alt 0 101331 gneg +chr22_KI270878v1_alt 0 186262 gneg +chr22_KI270879v1_alt 0 304135 gneg +chr22_KI270928v1_alt 0 176103 gneg +chr2_GL383521v1_alt 0 143390 gneg +chr2_GL383522v1_alt 0 123821 gneg +chr2_GL582966v2_alt 0 96131 gneg +chr2_KI270715v1_random 0 161471 gneg +chr2_KI270716v1_random 0 153799 gneg +chr2_KI270767v1_alt 0 161578 gneg +chr2_KI270768v1_alt 0 110099 gneg +chr2_KI270769v1_alt 0 120616 gneg +chr2_KI270770v1_alt 0 136240 gneg +chr2_KI270771v1_alt 0 110395 gneg +chr2_KI270772v1_alt 0 133041 gneg +chr2_KI270773v1_alt 0 70887 gneg +chr2_KI270774v1_alt 0 223625 gneg +chr2_KI270775v1_alt 0 138019 gneg +chr2_KI270776v1_alt 0 174166 gneg +chr2_KI270893v1_alt 0 161218 gneg +chr2_KI270894v1_alt 0 214158 gneg +chr3 0 2800000 p26.3 gpos50 +chr3 2800000 4000000 p26.2 gneg +chr3 4000000 8100000 p26.1 gpos50 +chr3 8100000 11600000 p25.3 gneg +chr3 11600000 13200000 p25.2 gpos25 +chr3 13200000 16300000 p25.1 gneg +chr3 16300000 23800000 p24.3 gpos100 +chr3 23800000 26300000 p24.2 gneg +chr3 26300000 30800000 p24.1 gpos75 +chr3 30800000 32000000 p23 gneg +chr3 32000000 36400000 p22.3 gpos50 +chr3 36400000 39300000 p22.2 gneg +chr3 39300000 43600000 p22.1 gpos75 +chr3 43600000 44100000 p21.33 gneg +chr3 44100000 44200000 p21.32 gpos50 +chr3 44200000 50600000 p21.31 gneg +chr3 50600000 52300000 p21.2 gpos25 +chr3 52300000 54400000 p21.1 gneg +chr3 54400000 58600000 p14.3 gpos50 +chr3 58600000 63800000 p14.2 gneg +chr3 63800000 69700000 p14.1 gpos50 +chr3 69700000 74100000 p13 gneg +chr3 74100000 79800000 p12.3 gpos75 +chr3 79800000 83500000 p12.2 gneg +chr3 83500000 87100000 p12.1 gpos75 +chr3 87100000 87800000 p11.2 gneg +chr3 87800000 90900000 p11.1 acen +chr3 90900000 94000000 q11.1 acen +chr3 94000000 98600000 q11.2 gvar +chr3 98600000 100300000 q12.1 gneg +chr3 100300000 101200000 q12.2 gpos25 +chr3 101200000 103100000 q12.3 gneg +chr3 103100000 106500000 q13.11 gpos75 +chr3 106500000 108200000 q13.12 gneg +chr3 108200000 111600000 q13.13 gpos50 +chr3 111600000 113700000 q13.2 gneg +chr3 113700000 117600000 q13.31 gpos75 +chr3 117600000 119300000 q13.32 gneg +chr3 119300000 122200000 q13.33 gpos75 +chr3 122200000 124100000 q21.1 gneg +chr3 124100000 126100000 q21.2 gpos25 +chr3 126100000 129500000 q21.3 gneg +chr3 129500000 134000000 q22.1 gpos25 +chr3 134000000 136000000 q22.2 gneg +chr3 136000000 139000000 q22.3 gpos25 +chr3 139000000 143100000 q23 gneg +chr3 143100000 149200000 q24 gpos100 +chr3 149200000 152300000 q25.1 gneg +chr3 152300000 155300000 q25.2 gpos50 +chr3 155300000 157300000 q25.31 gneg +chr3 157300000 159300000 q25.32 gpos50 +chr3 159300000 161000000 q25.33 gneg +chr3 161000000 167900000 q26.1 gpos100 +chr3 167900000 171200000 q26.2 gneg +chr3 171200000 176000000 q26.31 gpos75 +chr3 176000000 179300000 q26.32 gneg +chr3 179300000 183000000 q26.33 gpos75 +chr3 183000000 184800000 q27.1 gneg +chr3 184800000 186300000 q27.2 gpos25 +chr3 186300000 188200000 q27.3 gneg +chr3 188200000 192600000 q28 gpos75 +chr3 192600000 198295559 q29 gneg +chr3_GL000221v1_random 0 155397 gneg +chr3_GL383526v1_alt 0 180671 gneg +chr3_JH636055v2_alt 0 173151 gneg +chr3_KI270777v1_alt 0 173649 gneg +chr3_KI270778v1_alt 0 248252 gneg +chr3_KI270779v1_alt 0 205312 gneg +chr3_KI270780v1_alt 0 224108 gneg +chr3_KI270781v1_alt 0 113034 gneg +chr3_KI270782v1_alt 0 162429 gneg +chr3_KI270783v1_alt 0 109187 gneg +chr3_KI270784v1_alt 0 184404 gneg +chr3_KI270895v1_alt 0 162896 gneg +chr3_KI270924v1_alt 0 166540 gneg +chr3_KI270934v1_alt 0 163458 gneg +chr3_KI270935v1_alt 0 197351 gneg +chr3_KI270936v1_alt 0 164170 gneg +chr3_KI270937v1_alt 0 165607 gneg +chr4 0 4500000 p16.3 gneg +chr4 4500000 6000000 p16.2 gpos25 +chr4 6000000 11300000 p16.1 gneg +chr4 11300000 15000000 p15.33 gpos50 +chr4 15000000 17700000 p15.32 gneg +chr4 17700000 21300000 p15.31 gpos75 +chr4 21300000 27700000 p15.2 gneg +chr4 27700000 35800000 p15.1 gpos100 +chr4 35800000 41200000 p14 gneg +chr4 41200000 44600000 p13 gpos50 +chr4 44600000 48200000 p12 gneg +chr4 48200000 50000000 p11 acen +chr4 50000000 51800000 q11 acen +chr4 51800000 58500000 q12 gneg +chr4 58500000 65500000 q13.1 gpos100 +chr4 65500000 69400000 q13.2 gneg +chr4 69400000 75300000 q13.3 gpos75 +chr4 75300000 78000000 q21.1 gneg +chr4 78000000 81500000 q21.21 gpos50 +chr4 81500000 83200000 q21.22 gneg +chr4 83200000 86000000 q21.23 gpos25 +chr4 86000000 87100000 q21.3 gneg +chr4 87100000 92800000 q22.1 gpos75 +chr4 92800000 94200000 q22.2 gneg +chr4 94200000 97900000 q22.3 gpos75 +chr4 97900000 100100000 q23 gneg +chr4 100100000 106700000 q24 gpos50 +chr4 106700000 113200000 q25 gneg +chr4 113200000 119900000 q26 gpos75 +chr4 119900000 122800000 q27 gneg +chr4 122800000 127900000 q28.1 gpos50 +chr4 127900000 130100000 q28.2 gneg +chr4 130100000 138500000 q28.3 gpos100 +chr4 138500000 140600000 q31.1 gneg +chr4 140600000 145900000 q31.21 gpos25 +chr4 145900000 147500000 q31.22 gneg +chr4 147500000 150200000 q31.23 gpos25 +chr4 150200000 154600000 q31.3 gneg +chr4 154600000 160800000 q32.1 gpos100 +chr4 160800000 163600000 q32.2 gneg +chr4 163600000 169200000 q32.3 gpos100 +chr4 169200000 171000000 q33 gneg +chr4 171000000 175400000 q34.1 gpos75 +chr4 175400000 176600000 q34.2 gneg +chr4 176600000 182300000 q34.3 gpos100 +chr4 182300000 186200000 q35.1 gneg +chr4 186200000 190214555 q35.2 gpos25 +chr4_GL000008v2_random 0 209709 gneg +chr4_GL000257v2_alt 0 586476 gneg +chr4_GL383527v1_alt 0 164536 gneg +chr4_GL383528v1_alt 0 376187 gneg +chr4_KI270785v1_alt 0 119912 gneg +chr4_KI270786v1_alt 0 244096 gneg +chr4_KI270787v1_alt 0 111943 gneg +chr4_KI270788v1_alt 0 158965 gneg +chr4_KI270789v1_alt 0 205944 gneg +chr4_KI270790v1_alt 0 220246 gneg +chr4_KI270896v1_alt 0 378547 gneg +chr4_KI270925v1_alt 0 555799 gneg +chr5 0 4400000 p15.33 gneg +chr5 4400000 6300000 p15.32 gpos25 +chr5 6300000 9900000 p15.31 gneg +chr5 9900000 15000000 p15.2 gpos50 +chr5 15000000 18400000 p15.1 gneg +chr5 18400000 23300000 p14.3 gpos100 +chr5 23300000 24600000 p14.2 gneg +chr5 24600000 28900000 p14.1 gpos100 +chr5 28900000 33800000 p13.3 gneg +chr5 33800000 38400000 p13.2 gpos25 +chr5 38400000 42500000 p13.1 gneg +chr5 42500000 46100000 p12 gpos50 +chr5 46100000 48800000 p11 acen +chr5 48800000 51400000 q11.1 acen +chr5 51400000 59600000 q11.2 gneg +chr5 59600000 63600000 q12.1 gpos75 +chr5 63600000 63900000 q12.2 gneg +chr5 63900000 67400000 q12.3 gpos75 +chr5 67400000 69100000 q13.1 gneg +chr5 69100000 74000000 q13.2 gpos50 +chr5 74000000 77600000 q13.3 gneg +chr5 77600000 82100000 q14.1 gpos50 +chr5 82100000 83500000 q14.2 gneg +chr5 83500000 93000000 q14.3 gpos100 +chr5 93000000 98900000 q15 gneg +chr5 98900000 103400000 q21.1 gpos100 +chr5 103400000 105100000 q21.2 gneg +chr5 105100000 110200000 q21.3 gpos100 +chr5 110200000 112200000 q22.1 gneg +chr5 112200000 113800000 q22.2 gpos50 +chr5 113800000 115900000 q22.3 gneg +chr5 115900000 122100000 q23.1 gpos100 +chr5 122100000 127900000 q23.2 gneg +chr5 127900000 131200000 q23.3 gpos100 +chr5 131200000 136900000 q31.1 gneg +chr5 136900000 140100000 q31.2 gpos25 +chr5 140100000 145100000 q31.3 gneg +chr5 145100000 150400000 q32 gpos75 +chr5 150400000 153300000 q33.1 gneg +chr5 153300000 156300000 q33.2 gpos50 +chr5 156300000 160500000 q33.3 gneg +chr5 160500000 169000000 q34 gpos100 +chr5 169000000 173300000 q35.1 gneg +chr5 173300000 177100000 q35.2 gpos25 +chr5 177100000 181538259 q35.3 gneg +chr5_GL000208v1_random 0 92689 gneg +chr5_GL339449v2_alt 0 1612928 gneg +chr5_GL383530v1_alt 0 101241 gneg +chr5_GL383531v1_alt 0 173459 gneg +chr5_GL383532v1_alt 0 82728 gneg +chr5_GL949742v1_alt 0 226852 gneg +chr5_KI270791v1_alt 0 195710 gneg +chr5_KI270792v1_alt 0 179043 gneg +chr5_KI270793v1_alt 0 126136 gneg +chr5_KI270794v1_alt 0 164558 gneg +chr5_KI270795v1_alt 0 131892 gneg +chr5_KI270796v1_alt 0 172708 gneg +chr5_KI270897v1_alt 0 1144418 gneg +chr5_KI270898v1_alt 0 130957 gneg +chr6 0 2300000 p25.3 gneg +chr6 2300000 4200000 p25.2 gpos25 +chr6 4200000 7100000 p25.1 gneg +chr6 7100000 10600000 p24.3 gpos50 +chr6 10600000 11600000 p24.2 gneg +chr6 11600000 13400000 p24.1 gpos25 +chr6 13400000 15200000 p23 gneg +chr6 15200000 25200000 p22.3 gpos75 +chr6 25200000 27100000 p22.2 gneg +chr6 27100000 30500000 p22.1 gpos50 +chr6 30500000 32100000 p21.33 gneg +chr6 32100000 33500000 p21.32 gpos25 +chr6 33500000 36600000 p21.31 gneg +chr6 36600000 40500000 p21.2 gpos25 +chr6 40500000 46200000 p21.1 gneg +chr6 46200000 51800000 p12.3 gpos100 +chr6 51800000 53000000 p12.2 gneg +chr6 53000000 57200000 p12.1 gpos100 +chr6 57200000 58500000 p11.2 gneg +chr6 58500000 59800000 p11.1 acen +chr6 59800000 62600000 q11.1 acen +chr6 62600000 62700000 q11.2 gneg +chr6 62700000 69200000 q12 gpos100 +chr6 69200000 75200000 q13 gneg +chr6 75200000 83200000 q14.1 gpos50 +chr6 83200000 84200000 q14.2 gneg +chr6 84200000 87300000 q14.3 gpos50 +chr6 87300000 92500000 q15 gneg +chr6 92500000 98900000 q16.1 gpos100 +chr6 98900000 100000000 q16.2 gneg +chr6 100000000 105000000 q16.3 gpos100 +chr6 105000000 114200000 q21 gneg +chr6 114200000 117900000 q22.1 gpos75 +chr6 117900000 118100000 q22.2 gneg +chr6 118100000 125800000 q22.31 gpos100 +chr6 125800000 126800000 q22.32 gneg +chr6 126800000 130000000 q22.33 gpos75 +chr6 130000000 130900000 q23.1 gneg +chr6 130900000 134700000 q23.2 gpos50 +chr6 134700000 138300000 q23.3 gneg +chr6 138300000 142200000 q24.1 gpos75 +chr6 142200000 145100000 q24.2 gneg +chr6 145100000 148500000 q24.3 gpos75 +chr6 148500000 152100000 q25.1 gneg +chr6 152100000 155200000 q25.2 gpos50 +chr6 155200000 160600000 q25.3 gneg +chr6 160600000 164100000 q26 gpos50 +chr6 164100000 170805979 q27 gneg +chr6_GL000250v2_alt 0 4672374 gneg +chr6_GL000251v2_alt 0 4795265 gneg +chr6_GL000252v2_alt 0 4604811 gneg +chr6_GL000253v2_alt 0 4677643 gneg +chr6_GL000254v2_alt 0 4827813 gneg +chr6_GL000255v2_alt 0 4606388 gneg +chr6_GL000256v2_alt 0 4929269 gneg +chr6_GL383533v1_alt 0 124736 gneg +chr6_KB021644v2_alt 0 185823 gneg +chr6_KI270758v1_alt 0 76752 gneg +chr6_KI270797v1_alt 0 197536 gneg +chr6_KI270798v1_alt 0 271782 gneg +chr6_KI270799v1_alt 0 152148 gneg +chr6_KI270800v1_alt 0 175808 gneg +chr6_KI270801v1_alt 0 870480 gneg +chr6_KI270802v1_alt 0 75005 gneg +chr7 0 2800000 p22.3 gneg +chr7 2800000 4500000 p22.2 gpos25 +chr7 4500000 7200000 p22.1 gneg +chr7 7200000 13700000 p21.3 gpos100 +chr7 13700000 16500000 p21.2 gneg +chr7 16500000 20900000 p21.1 gpos100 +chr7 20900000 25500000 p15.3 gneg +chr7 25500000 27900000 p15.2 gpos50 +chr7 27900000 28800000 p15.1 gneg +chr7 28800000 34900000 p14.3 gpos75 +chr7 34900000 37100000 p14.2 gneg +chr7 37100000 43300000 p14.1 gpos75 +chr7 43300000 45400000 p13 gneg +chr7 45400000 49000000 p12.3 gpos75 +chr7 49000000 50500000 p12.2 gneg +chr7 50500000 53900000 p12.1 gpos75 +chr7 53900000 58100000 p11.2 gneg +chr7 58100000 60100000 p11.1 acen +chr7 60100000 62100000 q11.1 acen +chr7 62100000 67500000 q11.21 gneg +chr7 67500000 72700000 q11.22 gpos50 +chr7 72700000 77900000 q11.23 gneg +chr7 77900000 86700000 q21.11 gpos100 +chr7 86700000 88500000 q21.12 gneg +chr7 88500000 91500000 q21.13 gpos75 +chr7 91500000 93300000 q21.2 gneg +chr7 93300000 98400000 q21.3 gpos75 +chr7 98400000 104200000 q22.1 gneg +chr7 104200000 104900000 q22.2 gpos50 +chr7 104900000 107800000 q22.3 gneg +chr7 107800000 115000000 q31.1 gpos75 +chr7 115000000 117700000 q31.2 gneg +chr7 117700000 121400000 q31.31 gpos75 +chr7 121400000 124100000 q31.32 gneg +chr7 124100000 127500000 q31.33 gpos75 +chr7 127500000 129600000 q32.1 gneg +chr7 129600000 130800000 q32.2 gpos25 +chr7 130800000 132900000 q32.3 gneg +chr7 132900000 138500000 q33 gpos50 +chr7 138500000 143400000 q34 gneg +chr7 143400000 148200000 q35 gpos75 +chr7 148200000 152800000 q36.1 gneg +chr7 152800000 155200000 q36.2 gpos25 +chr7 155200000 159345973 q36.3 gneg +chr7_GL383534v2_alt 0 119183 gneg +chr7_KI270803v1_alt 0 1111570 gneg +chr7_KI270804v1_alt 0 157952 gneg +chr7_KI270805v1_alt 0 209988 gneg +chr7_KI270806v1_alt 0 158166 gneg +chr7_KI270807v1_alt 0 126434 gneg +chr7_KI270808v1_alt 0 271455 gneg +chr7_KI270809v1_alt 0 209586 gneg +chr7_KI270899v1_alt 0 190869 gneg +chr8 0 2300000 p23.3 gneg +chr8 2300000 6300000 p23.2 gpos75 +chr8 6300000 12800000 p23.1 gneg +chr8 12800000 19200000 p22 gpos100 +chr8 19200000 23500000 p21.3 gneg +chr8 23500000 27500000 p21.2 gpos50 +chr8 27500000 29000000 p21.1 gneg +chr8 29000000 36700000 p12 gpos75 +chr8 36700000 38500000 p11.23 gneg +chr8 38500000 39900000 p11.22 gpos25 +chr8 39900000 43200000 p11.21 gneg +chr8 43200000 45200000 p11.1 acen +chr8 45200000 47200000 q11.1 acen +chr8 47200000 51300000 q11.21 gneg +chr8 51300000 51700000 q11.22 gpos75 +chr8 51700000 54600000 q11.23 gneg +chr8 54600000 60600000 q12.1 gpos50 +chr8 60600000 61300000 q12.2 gneg +chr8 61300000 65100000 q12.3 gpos50 +chr8 65100000 67100000 q13.1 gneg +chr8 67100000 69600000 q13.2 gpos50 +chr8 69600000 72000000 q13.3 gneg +chr8 72000000 74600000 q21.11 gpos100 +chr8 74600000 74700000 q21.12 gneg +chr8 74700000 83500000 q21.13 gpos75 +chr8 83500000 85900000 q21.2 gneg +chr8 85900000 92300000 q21.3 gpos100 +chr8 92300000 97900000 q22.1 gneg +chr8 97900000 100500000 q22.2 gpos25 +chr8 100500000 105100000 q22.3 gneg +chr8 105100000 109500000 q23.1 gpos75 +chr8 109500000 111100000 q23.2 gneg +chr8 111100000 116700000 q23.3 gpos100 +chr8 116700000 118300000 q24.11 gneg +chr8 118300000 121500000 q24.12 gpos50 +chr8 121500000 126300000 q24.13 gneg +chr8 126300000 130400000 q24.21 gpos50 +chr8 130400000 135400000 q24.22 gneg +chr8 135400000 138900000 q24.23 gpos75 +chr8 138900000 145138636 q24.3 gneg +chr8_KI270810v1_alt 0 374415 gneg +chr8_KI270811v1_alt 0 292436 gneg +chr8_KI270812v1_alt 0 282736 gneg +chr8_KI270813v1_alt 0 300230 gneg +chr8_KI270814v1_alt 0 141812 gneg +chr8_KI270815v1_alt 0 132244 gneg +chr8_KI270816v1_alt 0 305841 gneg +chr8_KI270817v1_alt 0 158983 gneg +chr8_KI270818v1_alt 0 145606 gneg +chr8_KI270819v1_alt 0 133535 gneg +chr8_KI270820v1_alt 0 36640 gneg +chr8_KI270821v1_alt 0 985506 gneg +chr8_KI270822v1_alt 0 624492 gneg +chr8_KI270900v1_alt 0 318687 gneg +chr8_KI270901v1_alt 0 136959 gneg +chr8_KI270926v1_alt 0 229282 gneg +chr9 0 2200000 p24.3 gneg +chr9 2200000 4600000 p24.2 gpos25 +chr9 4600000 9000000 p24.1 gneg +chr9 9000000 14200000 p23 gpos75 +chr9 14200000 16600000 p22.3 gneg +chr9 16600000 18500000 p22.2 gpos25 +chr9 18500000 19900000 p22.1 gneg +chr9 19900000 25600000 p21.3 gpos100 +chr9 25600000 28000000 p21.2 gneg +chr9 28000000 33200000 p21.1 gpos100 +chr9 33200000 36300000 p13.3 gneg +chr9 36300000 37900000 p13.2 gpos25 +chr9 37900000 39000000 p13.1 gneg +chr9 39000000 40000000 p12 gpos50 +chr9 40000000 42200000 p11.2 gneg +chr9 42200000 43000000 p11.1 acen +chr9 43000000 45500000 q11 acen +chr9 45500000 61500000 q12 gvar +chr9 61500000 65000000 q13 gneg +chr9 65000000 69300000 q21.11 gpos25 +chr9 69300000 71300000 q21.12 gneg +chr9 71300000 76600000 q21.13 gpos50 +chr9 76600000 78500000 q21.2 gneg +chr9 78500000 81500000 q21.31 gpos50 +chr9 81500000 84300000 q21.32 gneg +chr9 84300000 87800000 q21.33 gpos50 +chr9 87800000 89200000 q22.1 gneg +chr9 89200000 91200000 q22.2 gpos25 +chr9 91200000 93900000 q22.31 gneg +chr9 93900000 96500000 q22.32 gpos25 +chr9 96500000 99800000 q22.33 gneg +chr9 99800000 105400000 q31.1 gpos100 +chr9 105400000 108500000 q31.2 gneg +chr9 108500000 112100000 q31.3 gpos25 +chr9 112100000 114900000 q32 gneg +chr9 114900000 119800000 q33.1 gpos75 +chr9 119800000 123100000 q33.2 gneg +chr9 123100000 127500000 q33.3 gpos25 +chr9 127500000 130600000 q34.11 gneg +chr9 130600000 131100000 q34.12 gpos25 +chr9 131100000 133100000 q34.13 gneg +chr9 133100000 134500000 q34.2 gpos25 +chr9 134500000 138394717 q34.3 gneg +chr9_GL383539v1_alt 0 162988 gneg +chr9_GL383540v1_alt 0 71551 gneg +chr9_GL383541v1_alt 0 171286 gneg +chr9_GL383542v1_alt 0 60032 gneg +chr9_KI270717v1_random 0 40062 gneg +chr9_KI270718v1_random 0 38054 gneg +chr9_KI270719v1_random 0 176845 gneg +chr9_KI270720v1_random 0 39050 gneg +chr9_KI270823v1_alt 0 439082 gneg +chrM 0 16569 gneg +chrUn_GL000195v1 0 182896 gneg +chrUn_GL000213v1 0 164239 gneg +chrUn_GL000214v1 0 137718 gneg +chrUn_GL000216v2 0 176608 gneg +chrUn_GL000218v1 0 161147 gneg +chrUn_GL000219v1 0 179198 gneg +chrUn_GL000220v1 0 161802 gneg +chrUn_GL000224v1 0 179693 gneg +chrUn_GL000226v1 0 15008 gneg +chrUn_KI270302v1 0 2274 gneg +chrUn_KI270303v1 0 1942 gneg +chrUn_KI270304v1 0 2165 gneg +chrUn_KI270305v1 0 1472 gneg +chrUn_KI270310v1 0 1201 gneg +chrUn_KI270311v1 0 12399 gneg +chrUn_KI270312v1 0 998 gneg +chrUn_KI270315v1 0 2276 gneg +chrUn_KI270316v1 0 1444 gneg +chrUn_KI270317v1 0 37690 gneg +chrUn_KI270320v1 0 4416 gneg +chrUn_KI270322v1 0 21476 gneg +chrUn_KI270329v1 0 1040 gneg +chrUn_KI270330v1 0 1652 gneg +chrUn_KI270333v1 0 2699 gneg +chrUn_KI270334v1 0 1368 gneg +chrUn_KI270335v1 0 1048 gneg +chrUn_KI270336v1 0 1026 gneg +chrUn_KI270337v1 0 1121 gneg +chrUn_KI270338v1 0 1428 gneg +chrUn_KI270340v1 0 1428 gneg +chrUn_KI270362v1 0 3530 gneg +chrUn_KI270363v1 0 1803 gneg +chrUn_KI270364v1 0 2855 gneg +chrUn_KI270366v1 0 8320 gneg +chrUn_KI270371v1 0 2805 gneg +chrUn_KI270372v1 0 1650 gneg +chrUn_KI270373v1 0 1451 gneg +chrUn_KI270374v1 0 2656 gneg +chrUn_KI270375v1 0 2378 gneg +chrUn_KI270376v1 0 1136 gneg +chrUn_KI270378v1 0 1048 gneg +chrUn_KI270379v1 0 1045 gneg +chrUn_KI270381v1 0 1930 gneg +chrUn_KI270382v1 0 4215 gneg +chrUn_KI270383v1 0 1750 gneg +chrUn_KI270384v1 0 1658 gneg +chrUn_KI270385v1 0 990 gneg +chrUn_KI270386v1 0 1788 gneg +chrUn_KI270387v1 0 1537 gneg +chrUn_KI270388v1 0 1216 gneg +chrUn_KI270389v1 0 1298 gneg +chrUn_KI270390v1 0 2387 gneg +chrUn_KI270391v1 0 1484 gneg +chrUn_KI270392v1 0 971 gneg +chrUn_KI270393v1 0 1308 gneg +chrUn_KI270394v1 0 970 gneg +chrUn_KI270395v1 0 1143 gneg +chrUn_KI270396v1 0 1880 gneg +chrUn_KI270411v1 0 2646 gneg +chrUn_KI270412v1 0 1179 gneg +chrUn_KI270414v1 0 2489 gneg +chrUn_KI270417v1 0 2043 gneg +chrUn_KI270418v1 0 2145 gneg +chrUn_KI270419v1 0 1029 gneg +chrUn_KI270420v1 0 2321 gneg +chrUn_KI270422v1 0 1445 gneg +chrUn_KI270423v1 0 981 gneg +chrUn_KI270424v1 0 2140 gneg +chrUn_KI270425v1 0 1884 gneg +chrUn_KI270429v1 0 1361 gneg +chrUn_KI270435v1 0 92983 gneg +chrUn_KI270438v1 0 112505 gneg +chrUn_KI270442v1 0 392061 gneg +chrUn_KI270448v1 0 7992 gneg +chrUn_KI270465v1 0 1774 gneg +chrUn_KI270466v1 0 1233 gneg +chrUn_KI270467v1 0 3920 gneg +chrUn_KI270468v1 0 4055 gneg +chrUn_KI270507v1 0 5353 gneg +chrUn_KI270508v1 0 1951 gneg +chrUn_KI270509v1 0 2318 gneg +chrUn_KI270510v1 0 2415 gneg +chrUn_KI270511v1 0 8127 gneg +chrUn_KI270512v1 0 22689 gneg +chrUn_KI270515v1 0 6361 gneg +chrUn_KI270516v1 0 1300 gneg +chrUn_KI270517v1 0 3253 gneg +chrUn_KI270518v1 0 2186 gneg +chrUn_KI270519v1 0 138126 gneg +chrUn_KI270521v1 0 7642 gneg +chrUn_KI270522v1 0 5674 gneg +chrUn_KI270528v1 0 2983 gneg +chrUn_KI270529v1 0 1899 gneg +chrUn_KI270530v1 0 2168 gneg +chrUn_KI270538v1 0 91309 gneg +chrUn_KI270539v1 0 993 gneg +chrUn_KI270544v1 0 1202 gneg +chrUn_KI270548v1 0 1599 gneg +chrUn_KI270579v1 0 31033 gneg +chrUn_KI270580v1 0 1553 gneg +chrUn_KI270581v1 0 7046 gneg +chrUn_KI270582v1 0 6504 gneg +chrUn_KI270583v1 0 1400 gneg +chrUn_KI270584v1 0 4513 gneg +chrUn_KI270587v1 0 2969 gneg +chrUn_KI270588v1 0 6158 gneg +chrUn_KI270589v1 0 44474 gneg +chrUn_KI270590v1 0 4685 gneg +chrUn_KI270591v1 0 5796 gneg +chrUn_KI270593v1 0 3041 gneg +chrUn_KI270741v1 0 157432 gneg +chrUn_KI270742v1 0 186739 gneg +chrUn_KI270743v1 0 210658 gneg +chrUn_KI270744v1 0 168472 gneg +chrUn_KI270745v1 0 41891 gneg +chrUn_KI270746v1 0 66486 gneg +chrUn_KI270747v1 0 198735 gneg +chrUn_KI270748v1 0 93321 gneg +chrUn_KI270749v1 0 158759 gneg +chrUn_KI270750v1 0 148850 gneg +chrUn_KI270751v1 0 150742 gneg +chrUn_KI270752v1 0 27745 gneg +chrUn_KI270753v1 0 62944 gneg +chrUn_KI270754v1 0 40191 gneg +chrUn_KI270755v1 0 36723 gneg +chrUn_KI270756v1 0 79590 gneg +chrUn_KI270757v1 0 71251 gneg +chrX 0 4400000 p22.33 gneg +chrX 4400000 6100000 p22.32 gpos50 +chrX 6100000 9600000 p22.31 gneg +chrX 9600000 17400000 p22.2 gpos50 +chrX 17400000 19200000 p22.13 gneg +chrX 19200000 21900000 p22.12 gpos50 +chrX 21900000 24900000 p22.11 gneg +chrX 24900000 29300000 p21.3 gpos100 +chrX 29300000 31500000 p21.2 gneg +chrX 31500000 37800000 p21.1 gpos100 +chrX 37800000 42500000 p11.4 gneg +chrX 42500000 47600000 p11.3 gpos75 +chrX 47600000 50100000 p11.23 gneg +chrX 50100000 54800000 p11.22 gpos25 +chrX 54800000 58100000 p11.21 gneg +chrX 58100000 61000000 p11.1 acen +chrX 61000000 63800000 q11.1 acen +chrX 63800000 65400000 q11.2 gneg +chrX 65400000 68500000 q12 gpos50 +chrX 68500000 73000000 q13.1 gneg +chrX 73000000 74700000 q13.2 gpos50 +chrX 74700000 76800000 q13.3 gneg +chrX 76800000 85400000 q21.1 gpos100 +chrX 85400000 87000000 q21.2 gneg +chrX 87000000 92700000 q21.31 gpos100 +chrX 92700000 94300000 q21.32 gneg +chrX 94300000 99100000 q21.33 gpos75 +chrX 99100000 103300000 q22.1 gneg +chrX 103300000 104500000 q22.2 gpos50 +chrX 104500000 109400000 q22.3 gneg +chrX 109400000 117400000 q23 gpos75 +chrX 117400000 121800000 q24 gneg +chrX 121800000 129500000 q25 gpos100 +chrX 129500000 131300000 q26.1 gneg +chrX 131300000 134500000 q26.2 gpos25 +chrX 134500000 138900000 q26.3 gneg +chrX 138900000 141200000 q27.1 gpos75 +chrX 141200000 143000000 q27.2 gneg +chrX 143000000 148000000 q27.3 gpos100 +chrX 148000000 156040895 q28 gneg +chrX_KI270880v1_alt 0 284869 gneg +chrX_KI270881v1_alt 0 144206 gneg +chrX_KI270913v1_alt 0 274009 gneg +chrY 0 300000 p11.32 gneg +chrY 300000 600000 p11.31 gpos50 +chrY 600000 10300000 p11.2 gneg +chrY 10300000 10400000 p11.1 acen +chrY 10400000 10600000 q11.1 acen +chrY 10600000 12400000 q11.21 gneg +chrY 12400000 17100000 q11.221 gpos50 +chrY 17100000 19600000 q11.222 gneg +chrY 19600000 23800000 q11.223 gpos50 +chrY 23800000 26600000 q11.23 gneg +chrY 26600000 57227415 q12 gvar +chrY_KI270740v1_random 0 37240 gneg +chr8_KZ208915v1_fix 0 6367528 gneg +chr15_KN538374v1_fix 0 4998962 gneg +chr15_KQ031389v1_alt 0 2365364 gneg +chr16_KV880768v1_fix 0 1927115 gneg +chr12_KZ208916v1_fix 0 1046838 gneg +chr14_KZ208920v1_fix 0 690932 gneg +chr7_KZ208913v1_alt 0 680662 gneg +chr5_KV575244v1_fix 0 673059 gneg +chr7_KZ208912v1_fix 0 589656 gneg +chr1_KV880763v1_alt 0 551020 gneg +chr12_KN538369v1_fix 0 541038 gneg +chr2_KQ983256v1_alt 0 535088 gneg +chr2_KQ031384v1_fix 0 481245 gneg +chr7_KV880765v1_fix 0 468267 gneg +chr1_KQ031383v1_fix 0 467143 gneg +chr1_KN538360v1_fix 0 460100 gneg +chr3_KN196475v1_fix 0 451168 gneg +chr4_KV766193v1_alt 0 420675 gneg +chr10_KN538367v1_fix 0 420164 gneg +chr3_KN538364v1_fix 0 415308 gneg +chr3_KV766192v1_fix 0 411654 gneg +chr18_KQ090028v1_fix 0 407387 gneg +chr19_KQ458386v1_fix 0 405389 gneg +chr3_KQ031385v1_fix 0 373699 gneg +chr19_KN196484v1_fix 0 370917 gneg +chr2_KN538363v1_fix 0 365499 gneg +chr5_KV575243v1_alt 0 362221 gneg +chr13_KN538372v1_fix 0 356766 gneg +chr1_KQ458383v1_alt 0 349938 gneg +chr9_KN196479v1_fix 0 330164 gneg +chr1_KZ208906v1_fix 0 330031 gneg +chr6_KQ031387v1_fix 0 320750 gneg +chr12_KQ759760v1_fix 0 315610 gneg +chr3_KN196476v1_fix 0 305979 gneg +chr1_KN538361v1_fix 0 305542 gneg +chr19_KV575249v1_alt 0 293522 gneg +chr17_KV766196v1_fix 0 281919 gneg +chr1_KQ983255v1_alt 0 278659 gneg +chr10_KN196480v1_fix 0 277797 gneg +chr17_KV766198v1_alt 0 276292 gneg +chr6_KN196478v1_fix 0 268330 gneg +chr16_KQ090027v1_alt 0 267463 gneg +chr8_KV880767v1_fix 0 265876 gneg +chr10_KQ090021v1_fix 0 264545 gneg +chr17_KV766197v1_alt 0 246895 gneg +chr6_KQ090016v1_fix 0 245716 gneg +chr6_KZ208911v1_fix 0 242796 gneg +chr19_KV575250v1_alt 0 241058 gneg +chr4_KQ090015v1_alt 0 236512 gneg +chr4_KQ983257v1_fix 0 230434 gneg +chr19_KV575256v1_alt 0 223118 gneg +chr1_KQ458384v1_alt 0 212205 gneg +chr12_KN196482v1_fix 0 211377 gneg +chrY_KZ208924v1_fix 0 209722 gneg +chr2_KN538362v1_fix 0 208149 gneg +chr13_KN538371v1_fix 0 206320 gneg +chr4_KQ983258v1_alt 0 205407 gneg +chr18_KQ458385v1_alt 0 205101 gneg +chr11_KN538368v1_alt 0 203552 gneg +chr11_KQ759759v1_fix 0 196940 gneg +chrX_KV766199v1_alt 0 188004 gneg +chr1_KN196472v1_fix 0 186494 gneg +chr10_KQ090020v1_alt 0 185507 gneg +chr11_KQ090022v1_fix 0 181958 gneg +chr2_KZ208907v1_alt 0 181658 gneg +chr7_KQ031388v1_fix 0 179932 gneg +chr19_KV575252v1_alt 0 178197 gneg +chr3_KZ208909v1_alt 0 175849 gneg +chr12_KZ208918v1_alt 0 174808 gneg +chr22_KQ458388v1_alt 0 174749 gneg +chr14_KZ208919v1_alt 0 171798 gneg +chr19_KV575259v1_alt 0 171263 gneg +chr19_KV575247v1_alt 0 170206 gneg +chr16_KQ031390v1_alt 0 169136 gneg +chr13_KQ090024v1_alt 0 168146 gneg +chr19_KV575248v1_alt 0 168131 gneg +chr19_KV575253v1_alt 0 166713 gneg +chr1_KN196473v1_fix 0 166200 gneg +chr1_KZ208904v1_alt 0 166136 gneg +chr3_KQ031386v1_fix 0 165718 gneg +chr8_KZ208914v1_fix 0 165120 gneg +chr19_KV575246v1_alt 0 163926 gneg +chr9_KQ090018v1_alt 0 163882 gneg +chr4_KQ090014v1_alt 0 163749 gneg +chr19_KV575255v1_alt 0 161095 gneg +chr19_KV575251v1_alt 0 159285 gneg +chr8_KV880766v1_fix 0 156998 gneg +chr19_KV575258v1_alt 0 156965 gneg +chr22_KN196485v1_alt 0 156562 gneg +chr22_KQ458387v1_alt 0 155930 gneg +chr17_KV575245v1_fix 0 154723 gneg +chr22_KN196486v1_alt 0 153027 gneg +chr13_KN538373v1_fix 0 148762 gneg +chr19_KV575260v1_alt 0 145691 gneg +chr22_KQ759761v1_alt 0 145162 gneg +chr7_KV880764v1_fix 0 142129 gneg +chr1_KQ458382v1_alt 0 141019 gneg +chr11_KV766195v1_fix 0 140877 gneg +chr2_KZ208908v1_alt 0 140361 gneg +chr1_KZ208905v1_alt 0 140355 gneg +chr6_KV766194v1_fix 0 139427 gneg +chr5_KN196477v1_alt 0 139087 gneg +chr5_KZ208910v1_alt 0 135987 gneg +chr9_KQ090019v1_alt 0 134099 gneg +chr13_KQ090025v1_alt 0 123480 gneg +chr1_KN196474v1_fix 0 122022 gneg +chr12_KQ090023v1_alt 0 109323 gneg +chr11_KN196481v1_fix 0 108875 gneg +chrY_KN196487v1_fix 0 101150 gneg +chr22_KQ759762v1_fix 0 101037 gneg +chr19_KV575257v1_alt 0 100553 gneg +chr19_KV575254v1_alt 0 99845 gneg +chr18_KZ208922v1_fix 0 93070 gneg +chr4_KQ090013v1_alt 0 90922 gneg +chr12_KN538370v1_fix 0 86533 gneg +chr10_KN538366v1_fix 0 85284 gneg +chr6_KQ090017v1_alt 0 82315 gneg +chr16_KZ208921v1_alt 0 78609 gneg +chr12_KZ208917v1_fix 0 64689 gneg +chr16_KQ090026v1_alt 0 59016 gneg +chrY_KZ208923v1_fix 0 48370 gneg +chr13_KN196483v1_fix 0 35455 gneg +chr10_KN538365v1_fix 0 14347 gneg +chr16_KZ559113v1_fix 0 480415 gneg +chr11_KZ559108v1_fix 0 305244 gneg +chr3_KZ559103v1_alt 0 302885 gneg +chr11_KZ559110v1_alt 0 301637 gneg +chr11_KZ559109v1_fix 0 279644 gneg +chr18_KZ559115v1_fix 0 230843 gneg +chr3_KZ559102v1_alt 0 197752 gneg +chr3_KZ559105v1_alt 0 195063 gneg +chr11_KZ559111v1_alt 0 181167 gneg +chr7_KZ559106v1_alt 0 172555 gneg +chr3_KZ559101v1_alt 0 164041 gneg +chr18_KZ559116v1_alt 0 163186 gneg +chr12_KZ559112v1_alt 0 154139 gneg +chr17_KZ559114v1_alt 0 116753 gneg +chr3_KZ559104v1_fix 0 105527 gneg +chr8_KZ559107v1_alt 0 103072 gneg +chr1_KZ559100v1_fix 0 44955 gneg +chr15_ML143371v1_fix 0 5500449 gneg +chr21_ML143377v1_fix 0 519485 gneg +chr19_ML143376v1_fix 0 493165 gneg +chr22_ML143378v1_fix 0 461303 gneg +chr10_ML143354v1_fix 0 454963 gneg +chr22_ML143380v1_fix 0 412368 gneg +chr13_ML143366v1_fix 0 409912 gneg +chrX_ML143381v1_fix 0 403128 gneg +chr14_ML143367v1_fix 0 399183 gneg +chr15_ML143372v1_fix 0 396515 gneg +chr15_ML143370v1_fix 0 369264 gneg +chr4_ML143345v1_fix 0 341066 gneg +chr12_ML143361v1_fix 0 297568 gneg +chr10_ML143355v1_fix 0 292944 gneg +chr4_ML143349v1_fix 0 276109 gneg +chr16_ML143373v1_fix 0 270967 gneg +chr11_ML143358v1_fix 0 270122 gneg +chr14_ML143368v1_alt 0 264228 gneg +chr7_ML143352v1_fix 0 254759 gneg +chr4_ML143344v1_fix 0 235734 gneg +chr11_ML143359v1_fix 0 217075 gneg +chr3_ML143343v1_alt 0 215443 gneg +chr12_ML143362v1_fix 0 192531 gneg +chr4_ML143347v1_fix 0 176674 gneg +chr11_ML143360v1_fix 0 170928 gneg +chr11_ML143357v1_fix 0 165419 gneg +chr13_ML143364v1_fix 0 158944 gneg +chr2_ML143341v1_fix 0 145975 gneg +chr17_ML143374v1_fix 0 137908 gneg +chr4_ML143348v1_fix 0 125549 gneg +chr15_ML143369v1_fix 0 97763 gneg +chr5_ML143350v1_fix 0 89956 gneg +chr2_ML143342v1_fix 0 84043 gneg +chr6_ML143351v1_fix 0 73265 gneg +chrX_ML143383v1_fix 0 68192 gneg +chr13_ML143365v1_fix 0 65394 gneg +chr17_ML143375v1_fix 0 56695 gneg +chr4_ML143346v1_fix 0 53476 gneg +chr11_ML143356v1_fix 0 45257 gneg +chrX_ML143382v1_fix 0 28824 gneg +chr9_ML143353v1_fix 0 25408 gneg +chrX_ML143385v1_fix 0 17435 gneg +chrX_ML143384v1_fix 0 14678 gneg +chr22_ML143379v1_fix 0 12295 gneg +chr13_ML143363v1_fix 0 7309 gneg +chr5_MU273354v1_fix 0 2101585 gneg +chr1_MU273333v1_fix 0 1572686 gneg +chr15_MU273374v1_fix 0 1154574 gneg +chr21_MU273391v1_fix 0 1020778 gneg +chr2_MU273342v1_fix 0 955087 gneg +chrY_MU273398v1_fix 0 865743 gneg +chr1_MU273331v1_alt 0 847441 gneg +chr14_MU273373v1_fix 0 722645 gneg +chrX_MU273395v1_alt 0 619716 gneg +chr9_MU273366v1_fix 0 569668 gneg +chr17_MU273380v1_fix 0 538541 gneg +chr2_MU273338v1_alt 0 535251 gneg +chr1_MU273330v1_alt 0 516764 gneg +chr5_MU273355v1_fix 0 508332 gneg +chr2_MU273339v1_alt 0 500581 gneg +chr2_MU273343v1_fix 0 489404 gneg +chr9_MU273365v1_fix 0 482250 gneg +chr3_MU273348v1_fix 0 475876 gneg +chr3_MU273346v1_fix 0 469342 gneg +chr7_MU273358v1_alt 0 464417 gneg +chr11_MU273369v1_fix 0 434831 gneg +chr2_MU273337v1_alt 0 431782 gneg +chr8_MU273362v1_fix 0 429744 gneg +chr6_MU273357v1_alt 0 383128 gneg +chr17_MU273378v1_alt 0 372839 gneg +chr20_MU273389v1_fix 0 355731 gneg +chr11_MU273370v1_fix 0 344606 gneg +chr9_MU273364v1_fix 0 340717 gneg +chr21_MU273390v1_fix 0 336752 gneg +chr1_MU273332v1_alt 0 335159 gneg +chr16_MU273377v1_fix 0 334997 gneg +chr19_MU273384v1_fix 0 333754 gneg +chrX_MU273397v1_alt 0 330493 gneg +chr4_MU273349v1_alt 0 308682 gneg +chr5_MU273356v1_alt 0 302485 gneg +chr3_MU273347v1_fix 0 301310 gneg +chrX_MU273396v1_alt 0 294119 gneg +chr2_MU273340v1_alt 0 284971 gneg +chr20_MU273388v1_fix 0 273725 gneg +chr11_MU273368v1_alt 0 261194 gneg +chr1_MU273336v1_fix 0 250447 gneg +chr2_MU273344v1_fix 0 244725 gneg +chr17_MU273379v1_fix 0 234878 gneg +chr19_MU273386v1_fix 0 226166 gneg +chr1_MU273335v1_fix 0 211934 gneg +chr1_MU273334v1_fix 0 210426 gneg +chr5_MU273353v1_fix 0 208405 gneg +chr8_MU273363v1_fix 0 207371 gneg +chr4_MU273351v1_fix 0 205691 gneg +chr11_KQ759759v2_fix 0 204999 gneg +chr15_MU273375v1_alt 0 204007 gneg +chr10_MU273367v1_fix 0 196262 gneg +chr21_MU273392v1_fix 0 189707 gneg +chr17_MU273382v1_fix 0 187626 gneg +chr2_MU273345v1_fix 0 174385 gneg +chr17_MU273383v1_fix 0 172609 gneg +chr8_MU273359v1_fix 0 150302 gneg +chr17_MU273381v1_fix 0 144689 gneg +chrX_MU273394v1_fix 0 140567 gneg +chr19_MU273385v1_fix 0 137818 gneg +chr11_MU273371v1_fix 0 122722 gneg +chr2_MU273341v1_fix 0 120381 gneg +chr4_MU273350v1_fix 0 113364 gneg +chr8_MU273361v1_fix 0 106905 gneg +chr12_MU273372v1_fix 0 104537 gneg +chr22_KQ759762v2_fix 0 101040 gneg +chr19_MU273387v1_alt 0 89211 gneg +chr16_MU273376v1_fix 0 87715 gneg +chrX_MU273393v1_fix 0 68810 gneg +chr8_MU273360v1_fix 0 39290 gneg +chr5_MU273352v1_fix 0 34400 gneg diff --git a/assets/lrsomatic_report/assets/references/t2t/chrom_lengths.tsv b/assets/lrsomatic_report/assets/references/t2t/chrom_lengths.tsv new file mode 100644 index 00000000..fe82530e --- /dev/null +++ b/assets/lrsomatic_report/assets/references/t2t/chrom_lengths.tsv @@ -0,0 +1,25 @@ +chr1 248387328 +chr2 242696752 +chr3 201105948 +chr4 193574945 +chr5 182045439 +chr6 172126628 +chr7 160567428 +chr8 146259331 +chr9 150617247 +chr10 134758134 +chr11 135127769 +chr12 133324548 +chr13 113566686 +chr14 101161492 +chr15 99753195 +chr16 96330374 +chr17 84276897 +chr18 80542538 +chr19 61707364 +chr20 66210255 +chr21 45090682 +chr22 51324926 +chrX 154259566 +chrY 62460029 +chrM 16569 diff --git a/assets/lrsomatic_report/assets/references/t2t/cytobands.tsv b/assets/lrsomatic_report/assets/references/t2t/cytobands.tsv new file mode 100644 index 00000000..33e192b1 --- /dev/null +++ b/assets/lrsomatic_report/assets/references/t2t/cytobands.tsv @@ -0,0 +1,862 @@ +chr1 0 1735965 p36.33 gneg +chr1 1735965 4816989 p36.32 gpos25 +chr1 4816989 6629068 p36.31 gneg +chr1 6629068 8634052 p36.23 gpos25 +chr1 8634052 12044143 p36.22 gneg +chr1 12044143 15341266 p36.21 gpos50 +chr1 15341266 19923637 p36.13 gneg +chr1 19923637 23434574 p36.12 gpos25 +chr1 23434574 27441306 p36.11 gneg +chr1 27441306 29743244 p35.3 gpos25 +chr1 29743244 32157918 p35.2 gneg +chr1 32157918 34161711 p35.1 gpos25 +chr1 34161711 39468378 p34.3 gneg +chr1 39468378 43570492 p34.2 gpos25 +chr1 43570492 46177222 p34.1 gneg +chr1 46177222 50078974 p33 gpos75 +chr1 50078974 55482505 p32.3 gneg +chr1 55482505 58377946 p32.2 gpos50 +chr1 58377946 60678767 p32.1 gneg +chr1 60678767 68377386 p31.3 gpos50 +chr1 68377386 69177517 p31.2 gneg +chr1 69177517 84240464 p31.1 gpos100 +chr1 84240464 87743231 p22.3 gneg +chr1 87743231 91344645 p22.2 gpos75 +chr1 91344645 94148241 p22.1 gneg +chr1 94148241 99148340 p21.3 gpos75 +chr1 99148340 101649187 p21.2 gneg +chr1 101649187 106737488 p21.1 gpos100 +chr1 106737488 111214805 p13.3 gneg +chr1 111214805 115511187 p13.2 gpos50 +chr1 115511187 117210493 p13.1 gneg +chr1 117210493 120413269 p12 gpos50 +chr1 120413269 121796048 p11.2 gneg +chr1 121796048 124048267 p11.1 acen +chr1 124048267 126300487 q11 acen +chr1 126300487 142241659 q12 gvar +chr1 142241659 147308041 q21.1 gneg +chr1 147308041 149724009 q21.2 gpos50 +chr1 149724009 154239365 q21.3 gneg +chr1 154239365 155736378 q22 gpos50 +chr1 155736378 158237044 q23.1 gneg +chr1 158237044 159637083 q23.2 gpos50 +chr1 159637083 164846435 q23.3 gneg +chr1 164846435 166547042 q24.1 gpos50 +chr1 166547042 170256335 q24.2 gneg +chr1 170256335 172358116 q24.3 gpos75 +chr1 172358116 175455343 q25.1 gneg +chr1 175455343 179655381 q25.2 gpos50 +chr1 179655381 185154686 q25.3 gneg +chr1 185154686 190146214 q31.1 gpos100 +chr1 190146214 193148937 q31.2 gneg +chr1 193148937 197959914 q31.3 gpos100 +chr1 197959914 206365243 q32.1 gneg +chr1 206365243 210545587 q32.2 gpos25 +chr1 210545587 213639518 q32.3 gneg +chr1 213639518 223089723 q41 gpos100 +chr1 223089723 223588804 q42.11 gneg +chr1 223588804 225987880 q42.12 gpos25 +chr1 225987880 229880334 q42.13 gneg +chr1 229880334 233990393 q42.2 gpos50 +chr1 233990393 235800112 q42.3 gneg +chr1 235800112 242911804 q43 gpos75 +chr1 242911804 248387328 q44 gneg +chr2 0 4423386 p25.3 gneg +chr2 4423386 6921497 p25.2 gpos50 +chr2 6921497 12028815 p25.1 gneg +chr2 12028815 16531703 p24.3 gpos75 +chr2 16531703 19032774 p24.2 gneg +chr2 19032774 23835087 p24.1 gpos75 +chr2 23835087 27743068 p23.3 gneg +chr2 27743068 29843598 p23.2 gpos25 +chr2 29843598 31845058 p23.1 gneg +chr2 31845058 36306629 p22.3 gpos75 +chr2 36306629 38306895 p22.2 gneg +chr2 38306895 41509232 p22.1 gpos50 +chr2 41509232 47505052 p21 gneg +chr2 47505052 52596301 p16.3 gpos100 +chr2 52596301 54694000 p16.2 gneg +chr2 54694000 61005834 p16.1 gpos100 +chr2 61005834 63907559 p15 gneg +chr2 63907559 68410570 p14 gpos50 +chr2 68410570 71311026 p13.3 gneg +chr2 71311026 73312998 p13.2 gpos50 +chr2 73312998 74808844 p13.1 gneg +chr2 74808844 83100333 p12 gpos100 +chr2 83100333 92333543 p11.2 gneg +chr2 92333543 93503283 p11.1 acen +chr2 93503283 94673023 q11.1 acen +chr2 94673023 102558292 q11.2 gneg +chr2 102558292 105761211 q12.1 gpos50 +chr2 105761211 107161426 q12.2 gneg +chr2 107161426 109160598 q12.3 gpos25 +chr2 109160598 112626870 q13 gneg +chr2 112626870 118533173 q14.1 gpos50 +chr2 118533173 122035284 q14.2 gneg +chr2 122035284 129528325 q14.3 gpos50 +chr2 129528325 132134645 q21.1 gneg +chr2 132134645 134739485 q21.2 gpos25 +chr2 134739485 136544463 q21.3 gneg +chr2 136544463 141946261 q22.1 gpos100 +chr2 141946261 143848187 q22.2 gneg +chr2 143848187 148350462 q22.3 gpos100 +chr2 148350462 149450376 q23.1 gneg +chr2 149450376 150050446 q23.2 gpos25 +chr2 150050446 154452841 q23.3 gneg +chr2 154452841 159362096 q24.1 gpos75 +chr2 159362096 163356865 q24.2 gneg +chr2 163356865 169374490 q24.3 gpos75 +chr2 169374490 177582181 q31.1 gneg +chr2 177582181 180183173 q31.2 gpos50 +chr2 180183173 182589080 q31.3 gneg +chr2 182589080 188988809 q32.1 gpos75 +chr2 188988809 191589136 q32.2 gneg +chr2 191589136 197084040 q32.3 gpos75 +chr2 197084040 202981065 q33.1 gneg +chr2 202981065 204581908 q33.2 gpos50 +chr2 204581908 208679779 q33.3 gneg +chr2 208679779 214984516 q34 gpos100 +chr2 214984516 221185014 q35 gneg +chr2 221185014 224783144 q36.1 gpos75 +chr2 224783144 225681833 q36.2 gneg +chr2 225681833 230582566 q36.3 gpos100 +chr2 230582566 235189048 q37.1 gneg +chr2 235189048 236890330 q37.2 gpos50 +chr2 236890330 242696752 q37.3 gneg +chr3 0 2794029 p26.3 gpos50 +chr3 2794029 3995951 p26.2 gneg +chr3 3995951 8091216 p26.1 gpos50 +chr3 8091216 11595822 p25.3 gneg +chr3 11595822 13200348 p25.2 gpos25 +chr3 13200348 16301213 p25.1 gneg +chr3 16301213 23804776 p24.3 gpos100 +chr3 23804776 26302605 p24.2 gneg +chr3 26302605 30802486 p24.1 gpos75 +chr3 30802486 32002957 p23 gneg +chr3 32002957 36401366 p22.3 gpos50 +chr3 36401366 39312902 p22.2 gneg +chr3 39312902 43615563 p22.1 gpos75 +chr3 43615563 44115566 p21.33 gneg +chr3 44115566 44215563 p21.32 gpos50 +chr3 44215563 50629881 p21.31 gneg +chr3 50629881 52332899 p21.2 gpos25 +chr3 52332899 54433863 p21.1 gneg +chr3 54433863 58640379 p14.3 gpos50 +chr3 58640379 63843624 p14.2 gneg +chr3 63843624 69736880 p14.1 gpos50 +chr3 69736880 74141615 p13 gneg +chr3 74141615 79855975 p12.3 gpos75 +chr3 79855975 83556432 p12.2 gneg +chr3 83556432 87174355 p12.1 gpos75 +chr3 87174355 91738002 p11.2 gneg +chr3 91738002 94076514 p11.1 acen +chr3 94076514 96415026 q11.1 acen +chr3 96415026 101303688 q11.2 gvar +chr3 101303688 103005343 q12.1 gneg +chr3 103005343 103905942 q12.2 gpos25 +chr3 103905942 105816831 q12.3 gneg +chr3 105816831 109218980 q13.11 gpos75 +chr3 109218980 110919781 q13.12 gneg +chr3 110919781 114320814 q13.13 gpos50 +chr3 114320814 116421198 q13.2 gneg +chr3 116421198 120319753 q13.31 gpos75 +chr3 120319753 122019706 q13.32 gneg +chr3 122019706 124919592 q13.33 gpos75 +chr3 124919592 126826138 q21.1 gneg +chr3 126826138 128832394 q21.2 gpos25 +chr3 128832394 132244475 q21.3 gneg +chr3 132244475 136745163 q22.1 gpos25 +chr3 136745163 138745773 q22.2 gneg +chr3 138745773 141741001 q22.3 gpos25 +chr3 141741001 145847398 q23 gneg +chr3 145847398 151950769 q24 gpos100 +chr3 151950769 155067896 q25.1 gneg +chr3 155067896 158073984 q25.2 gpos50 +chr3 158073984 160074579 q25.31 gneg +chr3 160074579 162074354 q25.32 gpos50 +chr3 162074354 163774734 q25.33 gneg +chr3 163774734 170683909 q26.1 gpos100 +chr3 170683909 173984304 q26.2 gneg +chr3 173984304 178794975 q26.31 gpos75 +chr3 178794975 182103836 q26.32 gneg +chr3 182103836 185805095 q26.33 gpos75 +chr3 185805095 187615802 q27.1 gneg +chr3 187615802 189115680 q27.2 gpos25 +chr3 189115680 191017553 q27.3 gneg +chr3 191017553 195295941 q28 gpos75 +chr3 195295941 201105948 q29 gneg +chr4 0 4469440 p16.3 gneg +chr4 4469440 5971735 p16.2 gpos25 +chr4 5971735 11276065 p16.1 gneg +chr4 11276065 14981780 p15.33 gpos50 +chr4 14981780 17682307 p15.32 gneg +chr4 17682307 21281575 p15.31 gpos75 +chr4 21281575 27685358 p15.2 gneg +chr4 27685358 35768949 p15.1 gpos100 +chr4 35768949 41173799 p14 gneg +chr4 41173799 44566953 p13 gpos50 +chr4 44566953 49705154 p12 gneg +chr4 49705154 52452474 p11 acen +chr4 52452474 55199795 q11 acen +chr4 55199795 61991213 q12 gneg +chr4 61991213 68936809 q13.1 gpos100 +chr4 68936809 72734812 q13.2 gneg +chr4 72734812 78640131 q13.3 gpos75 +chr4 78640131 81340837 q21.1 gneg +chr4 81340837 84829707 q21.21 gpos50 +chr4 84829707 86530115 q21.22 gneg +chr4 86530115 89329480 q21.23 gpos25 +chr4 89329480 90429379 q21.3 gneg +chr4 90429379 96127729 q22.1 gpos75 +chr4 96127729 97515472 q22.2 gneg +chr4 97515472 101214669 q22.3 gpos75 +chr4 101214669 103415497 q23 gneg +chr4 103415497 110005081 q24 gpos50 +chr4 110005081 116508718 q25 gneg +chr4 116508718 123205172 q26 gpos75 +chr4 123205172 126104099 q27 gneg +chr4 126104099 131203026 q28.1 gpos50 +chr4 131203026 133404460 q28.2 gneg +chr4 133404460 141823705 q28.3 gpos100 +chr4 141823705 143919702 q31.1 gneg +chr4 143919702 149216051 q31.21 gpos25 +chr4 149216051 150824125 q31.22 gneg +chr4 150824125 153521681 q31.23 gpos25 +chr4 153521681 157931811 q31.3 gneg +chr4 157931811 164150415 q32.1 gpos100 +chr4 164150415 166947399 q32.2 gneg +chr4 166947399 172559730 q32.3 gpos100 +chr4 172559730 174357423 q33 gneg +chr4 174357423 178738596 q34.1 gpos75 +chr4 178738596 179939101 q34.2 gneg +chr4 179939101 185641813 q34.3 gpos100 +chr4 185641813 189540361 q35.1 gneg +chr4 189540361 193574945 q35.2 gpos25 +chr5 0 4327607 p15.33 gneg +chr5 4327607 6228676 p15.32 gpos25 +chr5 6228676 9839807 p15.31 gneg +chr5 9839807 14939449 p15.2 gpos50 +chr5 14939449 18401838 p15.1 gneg +chr5 18401838 23407694 p14.3 gpos100 +chr5 23407694 24705214 p14.2 gneg +chr5 24705214 29005224 p14.1 gpos100 +chr5 29005224 33919872 p13.3 gneg +chr5 33919872 38649069 p13.2 gpos25 +chr5 38649069 42755507 p13.1 gneg +chr5 42755507 47039134 p12 gpos50 +chr5 47039134 48317879 p11 acen +chr5 48317879 49596625 q11.1 acen +chr5 49596625 60418219 q11.2 gneg +chr5 60418219 64420173 q12.1 gpos75 +chr5 64420173 64720135 q12.2 gneg +chr5 64720135 68222153 q12.3 gpos75 +chr5 68222153 69922486 q13.1 gneg +chr5 69922486 74481328 q13.2 gpos50 +chr5 74481328 78082577 q13.3 gneg +chr5 78082577 82584664 q14.1 gpos50 +chr5 82584664 83988771 q14.2 gneg +chr5 83988771 93484055 q14.3 gpos100 +chr5 93484055 99403284 q15 gneg +chr5 99403284 103908183 q21.1 gpos100 +chr5 103908183 105604211 q21.2 gneg +chr5 105604211 110710493 q21.3 gpos100 +chr5 110710493 112710455 q22.1 gneg +chr5 112710455 114312885 q22.2 gpos50 +chr5 114312885 116412397 q22.3 gneg +chr5 116412397 122616882 q23.1 gpos100 +chr5 122616882 128419736 q23.2 gneg +chr5 128419736 131718996 q23.3 gpos100 +chr5 131718996 137422646 q31.1 gneg +chr5 137422646 140625098 q31.2 gpos25 +chr5 140625098 145634538 q31.3 gneg +chr5 145634538 150936541 q32 gpos75 +chr5 150936541 153833148 q33.1 gneg +chr5 153833148 156818817 q33.2 gpos50 +chr5 156818817 161028563 q33.3 gneg +chr5 161028563 169535680 q34 gpos100 +chr5 169535680 173840079 q35.1 gneg +chr5 173840079 177643208 q35.2 gpos25 +chr5 177643208 182045439 q35.3 gneg +chr6 0 2163637 p25.3 gneg +chr6 2163637 4069276 p25.2 gpos25 +chr6 4069276 6969513 p25.1 gneg +chr6 6969513 10467733 p24.3 gpos50 +chr6 10467733 11468370 p24.2 gneg +chr6 11468370 13273264 p24.1 gpos25 +chr6 13273264 15073193 p23 gneg +chr6 15073193 25065737 p22.3 gpos75 +chr6 25065737 26968681 p22.2 gneg +chr6 26968681 30364188 p22.1 gpos50 +chr6 30364188 31953196 p21.33 gneg +chr6 31953196 33321362 p21.32 gpos25 +chr6 33321362 36420643 p21.31 gneg +chr6 36420643 40327879 p21.2 gpos25 +chr6 40327879 46035128 p21.1 gneg +chr6 46035128 51643048 p12.3 gpos100 +chr6 51643048 52839576 p12.2 gneg +chr6 52839576 57039025 p12.1 gpos100 +chr6 57039025 58286706 p11.2 gneg +chr6 58286706 59672548 p11.1 acen +chr6 59672548 61058390 q11.1 acen +chr6 61058390 63845066 q11.2 gneg +chr6 63845066 70378649 q12 gpos100 +chr6 70378649 76377151 q13 gneg +chr6 76377151 84423242 q14.1 gpos50 +chr6 84423242 85423294 q14.2 gneg +chr6 85423294 88508804 q14.3 gpos50 +chr6 88508804 93711666 q15 gneg +chr6 93711666 100074369 q16.1 gpos100 +chr6 100074369 101173694 q16.2 gneg +chr6 101173694 106176013 q16.3 gpos100 +chr6 106176013 115383115 q21 gneg +chr6 115383115 119084265 q22.1 gpos75 +chr6 119084265 119285071 q22.2 gneg +chr6 119285071 126988674 q22.31 gpos100 +chr6 126988674 127988742 q22.32 gneg +chr6 127988742 131194763 q22.33 gpos75 +chr6 131194763 132095087 q23.1 gneg +chr6 132095087 135888233 q23.2 gpos50 +chr6 135888233 139488489 q23.3 gneg +chr6 139488489 143392072 q24.1 gpos75 +chr6 143392072 146292619 q24.2 gneg +chr6 146292619 149696304 q24.3 gpos75 +chr6 149696304 153301308 q25.1 gneg +chr6 153301308 156401943 q25.2 gpos50 +chr6 156401943 161852984 q25.3 gneg +chr6 161852984 165464819 q26 gpos50 +chr6 165464819 172126628 q27 gneg +chr7 0 2913569 p22.3 gneg +chr7 2913569 4616674 p22.2 gpos25 +chr7 4616674 7319206 p22.1 gneg +chr7 7319206 13832042 p21.3 gpos100 +chr7 13832042 16629717 p21.2 gneg +chr7 16629717 21036083 p21.1 gpos100 +chr7 21036083 25635438 p15.3 gneg +chr7 25635438 28037762 p15.2 gpos50 +chr7 28037762 28937489 p15.1 gneg +chr7 28937489 35040677 p14.3 gpos75 +chr7 35040677 37240409 p14.2 gneg +chr7 37240409 43458167 p14.1 gpos75 +chr7 43458167 45560768 p13 gneg +chr7 45560768 49160858 p12.3 gpos75 +chr7 49160858 50661224 p12.2 gneg +chr7 50661224 54061627 p12.1 gpos75 +chr7 54061627 60414372 p11.2 gneg +chr7 60414372 62064435 p11.1 acen +chr7 62064435 63714499 q11.1 acen +chr7 63714499 68720114 q11.21 gneg +chr7 68720114 73918537 q11.22 gpos50 +chr7 73918537 79151921 q11.23 gneg +chr7 79151921 87949894 q21.11 gpos100 +chr7 87949894 89750628 q21.12 gneg +chr7 89750628 92747879 q21.13 gpos75 +chr7 92747879 94542054 q21.2 gneg +chr7 94542054 99630796 q21.3 gpos75 +chr7 99630796 105514255 q22.1 gneg +chr7 105514255 106214835 q22.2 gpos50 +chr7 106214835 109118351 q22.3 gneg +chr7 109118351 116314793 q31.1 gpos75 +chr7 116314793 119015389 q31.2 gneg +chr7 119015389 122715324 q31.31 gpos75 +chr7 122715324 125416714 q31.32 gneg +chr7 125416714 128811644 q31.33 gpos75 +chr7 128811644 130913119 q32.1 gneg +chr7 130913119 132117533 q32.2 gpos25 +chr7 132117533 134221510 q32.3 gneg +chr7 134221510 139809728 q33 gpos50 +chr7 139809728 144755427 q34 gneg +chr7 144755427 149379963 q35 gpos75 +chr7 149379963 153973252 q36.1 gneg +chr7 153973252 156375514 q36.2 gpos25 +chr7 156375514 160567428 q36.3 gneg +chr8 0 2084125 p23.3 gneg +chr8 2084125 6054502 p23.2 gpos75 +chr8 6054502 13066163 p23.1 gneg +chr8 13066163 19465021 p22 gpos100 +chr8 19465021 23774881 p21.3 gneg +chr8 23774881 27777347 p21.2 gpos50 +chr8 27777347 29278158 p21.1 gneg +chr8 29278158 36976053 p12 gpos75 +chr8 36976053 38776976 p11.23 gneg +chr8 38776976 40177151 p11.22 gpos25 +chr8 40177151 44215832 p11.21 gneg +chr8 44215832 45270456 p11.1 acen +chr8 45270456 46325080 q11.1 acen +chr8 46325080 51673061 q11.21 gneg +chr8 51673061 52073547 q11.22 gpos75 +chr8 52073547 54977464 q11.23 gneg +chr8 54977464 61023743 q12.1 gpos50 +chr8 61023743 61723740 q12.2 gneg +chr8 61723740 65525777 q12.3 gpos50 +chr8 65525777 67526469 q13.1 gneg +chr8 67526469 70029827 q13.2 gpos50 +chr8 70029827 72435109 q13.3 gneg +chr8 72435109 75029437 q21.11 gpos100 +chr8 75029437 75129430 q21.12 gneg +chr8 75129430 83931590 q21.13 gpos75 +chr8 83931590 87017433 q21.2 gneg +chr8 87017433 93425090 q21.3 gpos100 +chr8 93425090 99025482 q22.1 gneg +chr8 99025482 101626041 q22.2 gpos25 +chr8 101626041 106227505 q22.3 gneg +chr8 106227505 110628554 q23.1 gpos75 +chr8 110628554 112228628 q23.2 gneg +chr8 112228628 117826624 q23.3 gpos100 +chr8 117826624 119428452 q24.11 gneg +chr8 119428452 122630227 q24.12 gpos50 +chr8 122630227 127427152 q24.13 gneg +chr8 127427152 131526643 q24.21 gpos50 +chr8 131526643 136517853 q24.22 gneg +chr8 136517853 140019529 q24.23 gpos75 +chr8 140019529 146259331 q24.3 gneg +chr9 0 2202472 p24.3 gneg +chr9 2202472 4603652 p24.2 gpos25 +chr9 4603652 9006617 p24.1 gneg +chr9 9006617 14209493 p23 gpos75 +chr9 14209493 16611825 p22.3 gneg +chr9 16611825 18513245 p22.2 gpos25 +chr9 18513245 19913875 p22.1 gneg +chr9 19913875 25610359 p21.3 gpos100 +chr9 25610359 28010599 p21.2 gneg +chr9 28010599 33218700 p21.1 gpos100 +chr9 33218700 36322011 p13.3 gneg +chr9 36322011 37923910 p13.2 gpos25 +chr9 37923910 39013701 p13.1 gneg +chr9 39013701 40014198 p12 gpos50 +chr9 40014198 44951775 p11.2 gneg +chr9 44951775 46267185 p11.1 acen +chr9 46267185 47582595 q11 acen +chr9 47582595 76694047 q12 gvar +chr9 76694047 77166639 q13 gneg +chr9 77166639 81466639 q21.11 gpos25 +chr9 81466639 83449676 q21.12 gneg +chr9 83449676 88756405 q21.13 gpos50 +chr9 88756405 90657183 q21.2 gneg +chr9 90657183 93652149 q21.31 gpos50 +chr9 93652149 96450330 q21.32 gneg +chr9 96450330 99953385 q21.33 gpos50 +chr9 99953385 101362780 q22.1 gneg +chr9 101362780 103366144 q22.2 gpos25 +chr9 103366144 106067989 q22.31 gneg +chr9 106067989 108671778 q22.32 gpos25 +chr9 108671778 111971620 q22.33 gneg +chr9 111971620 117574632 q31.1 gpos100 +chr9 117574632 120669232 q31.2 gneg +chr9 120669232 124271384 q31.3 gpos25 +chr9 124271384 127092454 q32 gneg +chr9 127092454 131993831 q33.1 gpos75 +chr9 131993831 135297230 q33.2 gneg +chr9 135297230 139706950 q33.3 gpos25 +chr9 139706950 142804928 q34.11 gneg +chr9 142804928 143308266 q34.12 gpos25 +chr9 143308266 145314130 q34.13 gneg +chr9 145314130 146716800 q34.2 gpos25 +chr9 146716800 150617247 q34.3 gneg +chr10 0 2999810 p15.3 gneg +chr10 2999810 3803899 p15.2 gpos25 +chr10 3803899 6600140 p15.1 gneg +chr10 6600140 12211271 p14 gpos75 +chr10 12211271 17318428 p13 gneg +chr10 17318428 18319354 p12.33 gpos75 +chr10 18319354 18419356 p12.32 gneg +chr10 18419356 22319034 p12.31 gpos75 +chr10 22319034 24318538 p12.2 gneg +chr10 24318538 29331681 p12.1 gpos50 +chr10 29331681 31131269 p11.23 gneg +chr10 31131269 34228529 p11.22 gpos25 +chr10 34228529 39633793 p11.21 gneg +chr10 39633793 40649191 p11.1 acen +chr10 40649191 41664589 q11.1 acen +chr10 41664589 46381004 q11.21 gneg +chr10 46381004 49449041 q11.22 gpos25 +chr10 49449041 51948621 q11.23 gneg +chr10 51948621 60254318 q21.1 gpos100 +chr10 60254318 63658144 q21.2 gneg +chr10 63658144 69669152 q21.3 gpos100 +chr10 69669152 73971392 q22.1 gneg +chr10 73971392 76774110 q22.2 gpos50 +chr10 76774110 81169099 q22.3 gneg +chr10 81169099 86980090 q23.1 gpos100 +chr10 86980090 88583858 q23.2 gneg +chr10 88583858 91983671 q23.31 gpos75 +chr10 91983671 93182363 q23.32 gneg +chr10 93182363 96179180 q23.33 gpos50 +chr10 96179180 98380193 q24.1 gneg +chr10 98380193 100984294 q24.2 gpos50 +chr10 100984294 102083356 q24.31 gneg +chr10 102083356 103986242 q24.32 gpos25 +chr10 103986242 104887391 q24.33 gneg +chr10 104887391 110983867 q25.1 gpos100 +chr10 110983867 113991312 q25.2 gneg +chr10 113991312 118194477 q25.3 gpos75 +chr10 118194477 120797529 q26.11 gneg +chr10 120797529 122296091 q26.12 gpos50 +chr10 122296091 126582419 q26.13 gneg +chr10 126582419 129725246 q26.2 gpos50 +chr10 129725246 134758134 q26.3 gneg +chr11 0 2889344 p15.5 gneg +chr11 2889344 11789203 p15.4 gpos50 +chr11 11789203 13892569 p15.3 gneg +chr11 13892569 16997372 p15.2 gpos50 +chr11 16997372 22120532 p15.1 gneg +chr11 22120532 26340879 p14.3 gpos100 +chr11 26340879 27340466 p14.2 gneg +chr11 27340466 31136090 p14.1 gpos75 +chr11 31136090 36542448 p13 gneg +chr11 36542448 43555411 p12 gpos100 +chr11 43555411 48958062 p11.2 gneg +chr11 48958062 51035789 p11.12 gpos75 +chr11 51035789 52743313 p11.11 acen +chr11 52743313 54450838 q11 acen +chr11 54450838 60051280 q12.1 gpos75 +chr11 60051280 61888804 q12.2 gneg +chr11 61888804 63589288 q12.3 gpos25 +chr11 63589288 66094130 q13.1 gneg +chr11 66094130 68706120 q13.2 gpos25 +chr11 68706120 70520423 q13.3 gneg +chr11 70520423 75429506 q13.4 gpos50 +chr11 75429506 77332929 q13.5 gneg +chr11 77332929 85836684 q14.1 gpos100 +chr11 85836684 88519134 q14.2 gneg +chr11 88519134 92928863 q14.3 gpos100 +chr11 92928863 97406624 q21 gneg +chr11 97406624 102302118 q22.1 gpos100 +chr11 102302118 103003764 q22.2 gneg +chr11 103003764 110610246 q22.3 gpos100 +chr11 110610246 112710438 q23.1 gneg +chr11 112710438 114610447 q23.2 gpos50 +chr11 114610447 121325059 q23.3 gneg +chr11 121325059 124028615 q24.1 gpos50 +chr11 124028615 127933253 q24.2 gneg +chr11 127933253 130935758 q24.3 gpos50 +chr11 130935758 135127769 q25 gneg +chr12 0 3215744 p13.33 gneg +chr12 3215744 5306179 p13.32 gpos25 +chr12 5306179 9886155 p13.31 gneg +chr12 9886155 12469144 p13.2 gpos75 +chr12 12469144 14477435 p13.1 gneg +chr12 14477435 19678338 p12.3 gpos100 +chr12 19678338 20978622 p12.2 gneg +chr12 20978622 26172544 p12.1 gpos100 +chr12 26172544 27471672 p11.23 gneg +chr12 27471672 30374680 p11.22 gpos50 +chr12 30374680 34620838 p11.21 gneg +chr12 34620838 35911664 p11.1 acen +chr12 35911664 37202490 q11 acen +chr12 37202490 45959545 q12 gpos100 +chr12 45959545 48662027 q13.11 gneg +chr12 48662027 51062917 q13.12 gpos25 +chr12 51062917 54466577 q13.13 gneg +chr12 54466577 56167601 q13.2 gpos25 +chr12 56167601 57668365 q13.3 gneg +chr12 57668365 62678775 q14.1 gpos75 +chr12 62678775 64679035 q14.2 gneg +chr12 64679035 67279394 q14.3 gpos50 +chr12 67279394 71079501 q15 gneg +chr12 71079501 75274601 q21.1 gpos75 +chr12 75274601 79878671 q21.2 gneg +chr12 79878671 86280942 q21.31 gpos100 +chr12 86280942 88581935 q21.32 gneg +chr12 88581935 92177463 q21.33 gpos100 +chr12 92177463 95779143 q22 gneg +chr12 95779143 101161710 q23.1 gpos75 +chr12 101161710 103460805 q23.2 gneg +chr12 103460805 108574599 q23.3 gpos50 +chr12 108574599 111279651 q24.11 gneg +chr12 111279651 111876909 q24.12 gpos25 +chr12 111876909 113875849 q24.13 gneg +chr12 113875849 116381153 q24.21 gpos50 +chr12 116381153 117687226 q24.22 gneg +chr12 117687226 120287197 q24.23 gpos50 +chr12 120287197 125408188 q24.31 gneg +chr12 125408188 128730796 q24.32 gpos50 +chr12 128730796 133324548 q24.33 gneg +chr13 0 5751447 p13 gvar +chr13 5751447 9368750 p12 stalk +chr13 9368750 15547593 p11.2 gvar +chr13 15547593 16522942 p11.1 acen +chr13 16522942 17498291 q11 acen +chr13 17498291 21797623 q12.11 gneg +chr13 21797623 24108235 q12.12 gpos25 +chr13 24108235 26420720 q12.13 gneg +chr13 26420720 27522230 q12.2 gpos25 +chr13 27522230 30823418 q12.3 gneg +chr13 30823418 32617334 q13.1 gpos50 +chr13 32617334 34118269 q13.2 gneg +chr13 34118269 38718394 q13.3 gpos75 +chr13 38718394 43819777 q14.11 gneg +chr13 43819777 44420051 q14.12 gpos25 +chr13 44420051 45921251 q14.13 gneg +chr13 45921251 49520618 q14.2 gpos50 +chr13 49520618 53916044 q14.3 gneg +chr13 53916044 58219746 q21.1 gpos100 +chr13 58219746 61020124 q21.2 gneg +chr13 61020124 64418827 q21.31 gpos75 +chr13 64418827 67322320 q21.32 gneg +chr13 67322320 72021474 q21.33 gpos100 +chr13 72021474 74123996 q22.1 gneg +chr13 74123996 75923712 q22.2 gpos50 +chr13 75923712 77725243 q22.3 gneg +chr13 77725243 86303655 q31.1 gpos100 +chr13 86303655 88604095 q31.2 gneg +chr13 88604095 93603590 q31.3 gpos100 +chr13 93603590 96706317 q32.1 gneg +chr13 96706317 97909939 q32.2 gpos25 +chr13 97909939 100315089 q32.3 gneg +chr13 100315089 103418692 q33.1 gpos100 +chr13 103418692 105620405 q33.2 gneg +chr13 105620405 108828306 q33.3 gpos100 +chr13 108828306 113566686 q34 gneg +chr14 0 2077628 p13 gvar +chr14 2077628 2840421 p12 stalk +chr14 2840421 10092112 p11.2 gvar +chr14 10092112 11400261 p11.1 acen +chr14 11400261 12708411 q11.1 acen +chr14 12708411 18298312 q11.2 gneg +chr14 18298312 27096896 q12 gpos100 +chr14 27096896 28999171 q13.1 gneg +chr14 28999171 30288797 q13.2 gpos50 +chr14 30288797 31589055 q13.3 gneg +chr14 31589055 37191028 q21.1 gpos100 +chr14 37191028 40898832 q21.2 gneg +chr14 40898832 44606207 q21.3 gpos100 +chr14 44606207 47808271 q22.1 gneg +chr14 47808271 49205176 q22.2 gpos25 +chr14 49205176 51806957 q22.3 gneg +chr14 51806957 55806586 q23.1 gpos75 +chr14 55806586 58507715 q23.2 gneg +chr14 58507715 61607123 q23.3 gpos50 +chr14 61607123 64007668 q24.1 gneg +chr14 64007668 67506518 q24.2 gpos50 +chr14 67506518 73008616 q24.3 gneg +chr14 73008616 77312020 q31.1 gpos100 +chr14 77312020 78613483 q31.2 gneg +chr14 78613483 83523641 q31.3 gpos100 +chr14 83523641 85625240 q32.11 gneg +chr14 85625240 88427273 q32.12 gpos25 +chr14 88427273 90031477 q32.13 gneg +chr14 90031477 95135433 q32.2 gpos50 +chr14 95135433 96936346 q32.31 gneg +chr14 96936346 97736032 q32.32 gpos50 +chr14 97736032 101161492 q32.33 gneg +chr15 0 2484618 p13 gvar +chr15 2484618 4728636 p12 stalk +chr15 4728636 16678794 p11.2 gvar +chr15 16678794 17186630 p11.1 acen +chr15 17186630 17694466 q11.1 acen +chr15 17694466 23236963 q11.2 gneg +chr15 23236963 25542506 q12 gpos50 +chr15 25542506 27791711 q13.1 gneg +chr15 27791711 28693986 q13.2 gpos50 +chr15 28693986 31196487 q13.3 gneg +chr15 31196487 37605195 q14 gpos75 +chr15 37605195 40306040 q15.1 gneg +chr15 40306040 41107300 q15.2 gpos25 +chr15 41107300 42307677 q15.3 gneg +chr15 42307677 47008200 q21.1 gpos75 +chr15 47008200 50408265 q21.2 gneg +chr15 50408265 56602018 q21.3 gpos75 +chr15 56602018 56802078 q22.1 gneg +chr15 56802078 61204679 q22.2 gpos25 +chr15 61204679 64721821 q22.31 gneg +chr15 64721821 64821874 q22.32 gpos25 +chr15 64821874 65021911 q22.33 gneg +chr15 65021911 70217331 q23 gpos25 +chr15 70217331 72769881 q24.1 gneg +chr15 72769881 74171079 q24.2 gpos25 +chr15 74171079 75862542 q24.3 gneg +chr15 75862542 79264071 q25.1 gpos50 +chr15 79264071 82452409 q25.2 gneg +chr15 82452409 86254599 q25.3 gpos50 +chr15 86254599 91561911 q26.1 gneg +chr15 91561911 95765652 q26.2 gpos50 +chr15 95765652 99753195 q26.3 gneg +chr16 0 7831635 p13.3 gneg +chr16 7831635 10435669 p13.2 gpos50 +chr16 10435669 12537038 p13.13 gneg +chr16 12537038 14730876 p13.12 gpos50 +chr16 14730876 16712187 p13.11 gneg +chr16 16712187 21130950 p12.3 gpos50 +chr16 21130950 24476520 p12.2 gneg +chr16 24476520 28752507 p12.1 gpos50 +chr16 28752507 35848286 p11.2 gneg +chr16 35848286 36838903 p11.1 acen +chr16 36838903 37829521 q11.1 acen +chr16 37829521 52219471 q11.2 gvar +chr16 52219471 58397876 q12.1 gneg +chr16 58397876 61794998 q12.2 gpos50 +chr16 61794998 63095972 q13 gneg +chr16 63095972 72394295 q21 gpos100 +chr16 72394295 76611172 q22.1 gneg +chr16 76611172 78617811 q22.2 gpos50 +chr16 78617811 79917729 q22.3 gneg +chr16 79917729 85256228 q23.1 gpos75 +chr16 85256228 87661662 q23.2 gneg +chr16 87661662 90166083 q23.3 gpos50 +chr16 90166083 93070234 q24.1 gneg +chr16 93070234 94769136 q24.2 gpos25 +chr16 94769136 96330374 q24.3 gneg +chr17 0 3288940 p13.3 gneg +chr17 3288940 6400012 p13.2 gpos50 +chr17 6400012 10707908 p13.1 gneg +chr17 10707908 16002309 p12 gpos75 +chr17 16002309 23892419 p11.2 gneg +chr17 23892419 25689679 p11.1 acen +chr17 25689679 27486939 q11.1 acen +chr17 27486939 34446012 q11.2 gneg +chr17 34446012 40663561 q12 gpos50 +chr17 40663561 41063885 q21.1 gneg +chr17 41063885 43657141 q21.2 gpos25 +chr17 43657141 47661458 q21.31 gneg +chr17 47661458 50163080 q21.32 gpos25 +chr17 50163080 52967757 q21.33 gneg +chr17 52967757 60368167 q22 gpos75 +chr17 60368167 61068949 q23.1 gneg +chr17 61068949 63970246 q23.2 gpos75 +chr17 63970246 65469760 q23.3 gneg +chr17 65469760 67070785 q24.1 gpos50 +chr17 67070785 69976574 q24.2 gneg +chr17 69976574 73787784 q24.3 gpos75 +chr17 73787784 77692007 q25.1 gneg +chr17 77692007 78093613 q25.2 gpos25 +chr17 78093613 84276897 q25.3 gneg +chr18 0 3055502 p11.32 gneg +chr18 3055502 7363114 p11.31 gpos50 +chr18 7363114 8663156 p11.23 gneg +chr18 8663156 11062106 p11.22 gpos25 +chr18 11062106 15965699 p11.21 gneg +chr18 15965699 18449624 p11.1 acen +chr18 18449624 20933550 q11.1 acen +chr18 20933550 27694024 q11.2 gneg +chr18 27694024 35291319 q12.1 gpos100 +chr18 35291319 39695477 q12.2 gneg +chr18 39695477 46090953 q12.3 gpos75 +chr18 46090953 50901745 q21.1 gneg +chr18 50901745 56402692 q21.2 gpos75 +chr18 56402692 58801152 q21.31 gneg +chr18 58801152 61503246 q21.32 gpos50 +chr18 61503246 64105093 q21.33 gneg +chr18 64105093 69316653 q22.1 gpos100 +chr18 69316653 71221701 q22.2 gneg +chr18 71221701 75629292 q22.3 gpos25 +chr18 75629292 80542538 q23 gneg +chr19 0 6889318 p13.3 gneg +chr19 6889318 12724341 p13.2 gpos25 +chr19 12724341 13926177 p13.13 gneg +chr19 13926177 16234072 p13.12 gpos25 +chr19 16234072 20037734 p13.11 gneg +chr19 20037734 25817676 p12 gvar +chr19 25817676 27792923 p11 acen +chr19 27792923 29768171 q11 acen +chr19 29768171 34418519 q12 gvar +chr19 34418519 37644588 q13.11 gneg +chr19 37644588 40601536 q13.12 gpos25 +chr19 40601536 41002157 q13.13 gneg +chr19 41002157 45718957 q13.2 gpos25 +chr19 45718957 47524747 q13.31 gneg +chr19 47524747 50330819 q13.32 gpos25 +chr19 50330819 53989630 q13.33 gneg +chr19 53989630 56182556 q13.41 gpos25 +chr19 56182556 58899358 q13.42 gneg +chr19 58899358 61707364 q13.43 gpos25 +chr20 0 5139422 p13 gneg +chr20 5139422 9242915 p12.3 gpos75 +chr20 9242915 12043277 p12.2 gneg +chr20 12043277 17951106 p12.1 gpos75 +chr20 17951106 21359369 p11.23 gneg +chr20 21359369 22357561 p11.22 gpos25 +chr20 22357561 26925852 p11.21 gneg +chr20 26925852 28012753 p11.1 acen +chr20 28012753 29099655 q11.1 acen +chr20 29099655 35226553 q11.21 gneg +chr20 35226553 37520975 q11.22 gpos25 +chr20 37520975 40730034 q11.23 gneg +chr20 40730034 44834038 q12 gpos75 +chr20 44834038 45233263 q13.11 gneg +chr20 45233263 49539094 q13.12 gpos25 +chr20 49539094 52970605 q13.13 gneg +chr20 52970605 58177493 q13.2 gpos75 +chr20 58177493 59578060 q13.31 gneg +chr20 59578060 61484264 q13.32 gpos50 +chr20 61484264 66210255 q13.33 gneg +chr21 0 3084882 p13 gvar +chr21 3084882 5633495 p12 stalk +chr21 5633495 10962853 p11.2 gvar +chr21 10962853 11134529 p11.1 acen +chr21 11134529 11306205 q11.1 acen +chr21 11306205 13355188 q11.2 gneg +chr21 13355188 20956835 q21.1 gpos100 +chr21 20956835 23857586 q21.2 gneg +chr21 23857586 28565933 q21.3 gpos75 +chr21 28565933 32782056 q22.11 gneg +chr21 32782056 34782581 q22.12 gpos50 +chr21 34782581 36683433 q22.13 gneg +chr21 36683433 39588333 q22.2 gpos50 +chr21 39588333 45090682 q22.3 gneg +chr22 0 4770731 p13 gvar +chr22 4770731 5743502 p12 stalk +chr22 5743502 12788180 p11.2 gvar +chr22 12788180 14249622 p11.1 acen +chr22 14249622 15711065 q11.1 acen +chr22 15711065 22113480 q11.21 gneg +chr22 22113480 23522872 q11.22 gpos25 +chr22 23522872 25961147 q11.23 gneg +chr22 25961147 29663505 q12.1 gpos50 +chr22 29663505 32264007 q12.2 gneg +chr22 32264007 37659920 q12.3 gpos50 +chr22 37659920 41071957 q13.1 gneg +chr22 41071957 44282889 q13.2 gpos50 +chr22 44282889 48592476 q13.31 gneg +chr22 48592476 49604335 q13.32 gpos50 +chr22 49604335 51324926 q13.33 gneg +chrX 0 3944795 p22.33 gneg +chrX 3944795 5652276 p22.32 gpos50 +chrX 5652276 9182594 p22.31 gneg +chrX 9182594 16982597 p22.2 gpos50 +chrX 16982597 18782737 p22.13 gneg +chrX 18782737 21483312 p22.12 gpos50 +chrX 21483312 24484237 p22.11 gneg +chrX 24484237 28892068 p21.3 gpos100 +chrX 28892068 31098156 p21.2 gneg +chrX 31098156 37203573 p21.1 gpos100 +chrX 37203573 41906024 p11.4 gneg +chrX 41906024 47009888 p11.3 gpos75 +chrX 47009888 49417662 p11.23 gneg +chrX 49417662 54090881 p11.22 gpos25 +chrX 54090881 57820107 p11.21 gneg +chrX 57820107 59373565 p11.1 acen +chrX 59373565 60927025 q11.1 acen +chrX 60927025 63825591 q11.2 gneg +chrX 63825591 66933457 q12 gpos50 +chrX 66933457 71433508 q13.1 gneg +chrX 71433508 73133628 q13.2 gpos50 +chrX 73133628 75233853 q13.3 gneg +chrX 75233853 83828518 q21.1 gpos100 +chrX 83828518 85427981 q21.2 gneg +chrX 85427981 91150234 q21.31 gpos100 +chrX 91150234 92745170 q21.32 gneg +chrX 92745170 97541699 q21.33 gpos75 +chrX 97541699 101746979 q22.1 gneg +chrX 101746979 102931146 q22.2 gpos50 +chrX 102931146 107847498 q22.3 gneg +chrX 107847498 115776569 q23 gpos75 +chrX 115776569 120099927 q24 gneg +chrX 120099927 127818782 q25 gpos100 +chrX 127818782 129624103 q26.1 gneg +chrX 129624103 132825159 q26.2 gpos25 +chrX 132825159 137210433 q26.3 gneg +chrX 137210433 139517370 q27.1 gpos75 +chrX 139517370 141308643 q27.2 gneg +chrX 141308643 146265526 q27.3 gpos100 +chrX 146265526 154259566 q28 gneg +chrY 0 127375 p11.32 gneg +chrY 127375 454123 p11.31 gpos50 +chrY 454123 10565750 p11.2 gneg +chrY 10565750 10724418 p11.1 acen +chrY 10724418 10883085 q11.1 acen +chrY 10883085 13307633 q11.21 gneg +chrY 13307633 18006518 q11.221 gpos50 +chrY 18006518 20506564 q11.222 gneg +chrY 20506564 25062557 q11.223 gpos50 +chrY 25062557 27449937 q11.23 gneg +chrY 27449937 62460029 q12 gvar diff --git a/assets/lrsomatic_report/assets/styles/_fonts.scss b/assets/lrsomatic_report/assets/styles/_fonts.scss new file mode 100644 index 00000000..fe61a495 --- /dev/null +++ b/assets/lrsomatic_report/assets/styles/_fonts.scss @@ -0,0 +1,85 @@ +/* AUTO-GENERATED: base64-embedded latin-subset webfonts. Do not edit by hand. */ + +@font-face { + + font-family: 'Spectral'; + font-style: normal; + font-weight: 600; + font-display: swap; + src: url(data:font/woff2;base64,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) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} + +@font-face { + + font-family: 'IBM Plex Sans'; + font-style: normal; + font-weight: 400; + font-stretch: 100%; + font-display: swap; + src: url(data:font/woff2;base64,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) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} + +@font-face { + + font-family: 'IBM Plex Sans'; + font-style: normal; + font-weight: 500; + font-stretch: 100%; + font-display: swap; + src: url(data:font/woff2;base64,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) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} + +@font-face { + + font-family: 'IBM Plex Sans'; + font-style: normal; + font-weight: 600; + font-stretch: 100%; + font-display: swap; + src: url(data:font/woff2;base64,d09GMgABAAAAALKQABgAAAABgPQAALIPAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGoZPG4KgchyEYj9IVkFShDM/TVZBUmIGYD9TVEFUgTInKgCEfCsiCCoJnwMvahEMCoG5GIGaWwuEHgAwgctGATYCJAOIOAQgBYhUB4htDIEoW/BtkUDYxm6DT0uK9BSTBOrrfMcXUTDdHLzcNqpH5LpZHig7SiDoDmCP9J7cZf////8vSCYyZndBk6QtpSAgMFTZ76GSGcyDUrBRMjbKJXqkiqQRkQfLmlqPEalMNGrN/aOh5zYvtKL0ERT87BJCS4kSm5FtcusUO0VUhGDpFiYY6UTJE0KwdUbW6SgwFweVVhV/VDrhJunycnYaj925acHEqz5C8psn7TxLBe/jdC8fKLY0O0IRYcLLhExVUHz9Yv+IGpgxv+g5i+0GdvNf2Rd+fGGxQIWTXxuegzTIk1yFnd8Vg3KZFmmQXVZRd3GRDTsPNLR1Pl//hOQwfDMiYMhOU4m9iudfRco8kE2jY1E7kQzVeiTEpWQqBCl0xMeitsMeDdtg+BbaslFFXqCw1Wy71sA6aOf/pKyqZLjU+YKTCdplJ6N15awdMj5saFAYHRTOPWlIPSx1efNWKWmnqp2DNdPh5DdaipJjHPEr2D0ex3jueGDGpSu5WGWV2z1MvfQn76538hDYgMuAIZmW9nElz5MvD9/z+5a/9rnP6HZovIGHSqCnZ2hUw1ATYsaIE6aRIUZ1xIg6P19sQsSJODEnU8SJE/GJ6P553k3/vMt7D7iiCDwQUJCKEH4UQUAyOnUHB+DMbmtNp2aYdGy7M4eaxiy7HLPTNbKIiGMCyl9pVudKeHq8yDeTn2ThQIteYDqyanUH+G32TsBCUaeooESktMALWsInCIpVm1Gr0nWcf38Rrdttu3TVV7Wqi0XPQJfl0p0TG0QOyc1uOey2a9ll0yV2iTe6fF/ywRuEQ9IVDhEJ4nujS8QuyUsQa3fw7bIiR24tX+Rql9zbJcUub+lqK54kPVPcNv6BqKlpkU6bW4kj2XyR4pOJAghywiUAWEry/0XbfNGFsLHdBoIhJUv+kIuMoLkdfSxuYco7QdBgyC41YzV0o7FIz8fF9j7wkZxBGvEZBRiladNMAkFNFDa94XWzf0mwYIGAN4jVaU9c9+/DcsPyv89/E53+eCJKaelhElwPAh74F+byHaTX5SAHGbQdkmK9GYeWoEaoP2+ufLUMoc3/JcLrJROnt/be1ysQ7ksWaNgeMpDAliwZaHj9/2zvyobWmpaOpubQWW1Sp0Z0EZsGmyY2yCIPWeRFJnITeJH75e4HYsFkf0Dc1FbU2hCv/OeBQAkdy0+haowcW8g951+n/94YBXQlXQFZbIFJtiMnL/CJYSpQqtdl6DT0dFg+ALYPyQG0E7NsQ7xkemjaVjxITvbuf5EgL4PrCrl+Scxnzic/Bvg3J3pp27HhEUxHaBzrW9azpB91/r+y4wA/Qtg+DPPfJuXe33aYu7dz144fAJNLATuJSbKtI4usQaeWkEWThJAEwiBwoTjBJRbBaU5yd9y3PiwM+zvz3zD/D9sP65W2bDesd5/O/FkWrMgrWUYMky51NyMflIEyrwf8BFwhlf/PXL/3XlPbdpkiWiR/QjLMlyPiGfpFYZX5RVcQkyIW9MjlGNRuRy6n9R/m2jb2Jh+xP9FLXBULBcjR4mk8B59HJKupsszoCHrbXYB3A1Y8xowuia9/p7krWcnMrl5dsgMHyGF8YEuZuD4fqwzWr9TfQ2T//5dZ3vd+iPV/VXW3urs6KYUzU5sTnwVsAiCr/WyDbY2NjEaHO+iYGVlmzhpmZ8kJqwEbAbb9H7heff7XLO+u5ecrJKs6W6Fqb2PMEC5/nsB+oHGBoSRHmU+n/f8Aa4SWE9txssklgqL6UNRUk6Rs9U//e6AKqHpAvHuXgxuzgIeH92+fWECJ5XLugljb7bO9Jd8lLQ0o/1M1IzdFrivNwOFjfmdoXYesFbkxfXAdAMVx0eXSvrvfVQ8XKXeX/v9eNd2+yy9qQHEKwfGcIVxJ28yh3JmylzTFvSqt7nPeu+9//v/+BchPkJRQVEBiCkBMAQhKA5KamB8EYpCUfIaa2l3oqnFrH6TkUFOh4tKltDrOOV6ltbpZue3iZVZ2Vsk6i523WeVkWXdZ7bNf5ngX+P/ar7Tz+8zLnT8LHURHJEyPayUj5ODS260OoosikKAAdWxUyqc8kN1aIUwqQtnowPP/pvpvO5f72547dMClGkByeh3fYqPn1zdzDxwws3/S/KQBHCTCiaADSThR6huScv4xVbZLly5NIZ6cnq22AOLjcP5/NntL6xpllh11GauNr4wtO0gchU7Clv7MsUYy9MjUGjin9bHGX3NOtUylMTAtZMDR8us2lbnmzwJSEAFGlG20G6WbRAuP50fNS0gtN24rqkbU6kXUfdz3+d8wNT9I0F5O5Um1Go+qagj7lzL4h1BKiOKwGY2rvd3eftf7/73VmZn7dck8Ih9xRETEtrVWSilLKa1te57wvyG0e//PQUc4hISIiPPR0NQQweP8BM2TMr7arS9TjBHGGCOEuKzLXF3GtEyAKp0KxZwF2an3a1xj6f+gpomvzfFz9yfWeCCgoiyCQkRtIaLWqohM0GbOdBGxxRtqfHxXZbWCrpzZd8WMEeuQHC9PYBFqx45AaAQraqe9m8gu7QifcSH86C+sKFHHQoCqj0L5rrD3dTIQOUD5H0jxrt+uPzXWh3F1ejXb7e83j8tzJD8JxGR2ebwt9LRSK53pqqpqOM01POeh1wMKUrCjEgP8BIAwVGgww4QIBAly4lKcuawVsIQlz/coVIK8dXO/CQYryU5xMmCUCg1k1GfjmZvcOQ2yYrRpYkUlUkGmJXQJqqKWJZV2jdfvWlq45z1515ObF5+Ou8WXNnOX3bf2dhTCB2NGxScicmwRxQMyZCCcAA5J0SxAkCmQhs7r6ZPTjvI+m3xlzZ4zxUVVVlXXVKlarf/f1pxeuBaQrlOdMlXqtBLsw8xk2GVu1a/cHD+e3n5wCIECIIQFx0YAHCQKjSDB4AAqCGEVx3ExbDQ8eswM2fPO5MydV/byVyhV/upv1fjPPYVXKsGC5ODDSaMIky8awSDZOSiu8kLL27exHfRpR0/92X9kHC/DRjXm+kkiFVSoFGX6qVKtRkNRmq8QfMEb3xPPRBEhJpGiiZVYi604FCmuihaaoFahulJVhUrV1EodqlJX9XO6WXtLLLVgmTWzVr2xZ97QK+2v9vAaQCD84Np5ZL7kOzhZrebgopZX+yAQ9zUBHyZuyo7CNjR/bpNUy+t5F0XQR3QA2Py3EALosN7HyO079x+Scv3jR+9gvXn0xtvp7njs8SPkSEBOKQI5Wp21OgDKp26/cfSIlE67TzPaumI/hQoQZO9nIaBmAz8yNcWBgsYLPrav6Gjr/kBCcIHA4WIDBqt719rxL+PL8Kys5BUuf2u68fINNlCmV2rr+TKylBV3MRRT0RVlCSm1uC/pJDOUjoRzP964Y8/FaI3aiIQvzOELaagiNAD+5BqfqwZ82ZwmTWpV252kiqg8h1VWl44hgSqGS8dQQFWuLYMwUKI5Bqq43KLau+Z7D5aI2t5erz50eApn6WO0Ly4d4zesG40crxTbenJIJ7FVUgblx17IW0YV6hi+FPQXOmNQM9WcRJ/GbNXDt9WKcOGsDb1nialskTylZuC0XLoyfVwSK9ebw8o6llNdreJ9P2jSjevO7topP8pW6yC7x/Upqv3Nbc2fpcjDtY077To6HmNP4NR+9ZBpmUZkY/l2zIPyhuYY/XygIe5vTLlYJ0V8Wsvh6t0LOPkrb9dx1usB+Cpz6aC/rHLMGU0mUwMv22EKW6K/q6qbBR9RtD1dTqOv48C6+BBibGGs+A44yOC44+Kd7CtMzq4wO3+oRZt2CT5bsczgiuWGP+8KwcD6pnPYicflfueDRf+tH/0G/NVf6MfwV3C36y/e2dZQ7+nfC5926DZuMz2MDJpuvHyDZessXbJYtUW7sZv54U9i4wwdMli0QbMxm+hgaCAtjhfEcqKRsGl3PS6hgzAJ7Rp4GeC48nYZ6S9oQBlc2gcEcmWbWN/jE9gM0oInLjwLTJxQcDqbxivZZ20zuQHyAyrBeREBjXfBtdAszPQxWLamjrSnuLzMALKlAKeTiCSFJz9ukRktCrDAIIxmuRSqBlQVI7WCOvHpki/kRX94PHTmZRZf1Kss1ESzEUvKfCm8AQq8LGqiWdYgi+5D1Cww+ohEU6DoJQJlUaGbngM9Z6UmB0+MHIKisFRHwk/RJt8AMSFpIpWi0Kp+OOT2W48Tlv6hYQi5zaSiBJCyQ0v0oiIL8jupiyAE9vTDroKwBRPgYsQKEcdqiV0OMDqk2jLvOy/Rh9qs8plhhS5yeQIBNBAAgfA7Lg5Wa3eJxUNAQAuKPikgXpStODjaG53MD6VPZPBPyj+V/n4i0Kd7TJ/4nC1jF1ZOxyKUS913yT8YwpYsFdglA4uNDSVLEdpGGwk94hEi22zHQIKJ9cSaDqu6JH1myeSTpCzZkJxCsReao1Ccx7RceVhuZuQqA3vKFyIHIlsIaNjQsGckvxdSQaEUFlKRFFdYsL5AJPyMkLU3u/4fkeLR3/bu2npZnc//bGjt5jwbdvQ1ZfX36lloeVtL9UVcOHEl4Tiii1g+FRAOW0DE8DEWpzyktdZdQ7F8v1wlHoeNCAgWIh3cfVRGh41c8v4/zaYftTlw6qR5UI7zpheSD8zZzN8QhRbSV9BiPRkFwMmOGOSzAw2zxe2o+fSd4QMn3swPRh9hoSCDAJj9Pnzp6aFVxgYbueTdnim+1puV8UMcuv2L8ujwon7zq3T7eAEKrbCs38SuZxXfl6VjqVn43bxlAJOncAinJxZsmlmBuy4ekJfg0Lx13x5f/RzcfWYit+ju+r9XIUvR9+YYIsD+HuXkfPdDFszJOVWHPl3wWXaUbn6g2I89cfjS13s36eBWz6IILPdtRS/hk79ed9jIJa/MAjmRaNy7HMzaEx9bgpMfW6UP6KyGX2puYPgr5C4Fz92J09ON2qZrH5rKf/F7c5olkGXmd27dYSOXvIslyS/Mpsevhru13OnrgNGv//2jPMARY+mJMA7aIyYa5liTKXhoqh5PmgbHazFI54HAHQNd0rOE4zKAjVzyLpaAI8M2fa/u4prnSWGfCXB0o8kCNod51uvS+PvjpWf6LJEBbOSSd7EkI2y06ebVDBVG+DqP17jBiZNG02MgiPSETc17VunauAB2rLBsXsRRchVfUqmkH7zHu2nm5QZ3DBfzTB8e+y+1MZ4b7eEKPO6WAs+Xro4t2nQV8tje9cnn4MTMFqbKuN7mVXurFAU9MfTolscl8PGf2NQN7mwM2/dRWTDH3loZzh7+Nh+Cpi+vzILinANHdNjIJW/hBhHbKdDL6frrvOcjX/1+9NBqGuy+gKUE//gkm2SQt/ux49cGwn14vebzxmoT6ZVm8kvtat5JGMNI0afRv3mYLrsCbY9eegu0+X54XIsQPAZqcjK3U+wdjhNnFOUKdXTvgjr2H8twCLwC0fi/2PazRN31sCU40vMQGH0npDhP4m6utneNjFGtvD9Oep5rn5HRYbuYQ3nsCDsOnOYazMOnOZLBna+QQmqT9eLYY2SzjXK2/3SEtTnVEgmxLh99ZoyUUchTaYuNXbvFxidODDQ1OJm//08k9jZd2qfMgtESMwdXlXfYy8o03EbmqNf61gzhjTmC+Fci41NCuKvn4WDR9Pt+PGjel55uUuklyd9hM4L0eEG2Yxs3chzF9rPEJo/bptx2I9xGeYwpu+pTFhEWIwhTw2ZnFSpUqFDloARlk9vUnIIKFSpU64FM28OxBL7i6+UTlDGXkpUZ2Q7boBy2ZwhzqJjbV4pEVNSoyjrr8dfEM7+1YtPztW5DPf3sHNhvMJcoVqidyly+eJA/MXdlUmHj9MczjOop0LZY/IRrurkiIPg4l87PC66Xp9IcHRFrxh2HgOYal2G6ZndTTVZ8RvuslGrGq2+kjkiypTowbDY24SLMLlRpLE1EKUTuK9yY2xCSAWMhB6JA2a2lz9cvyHh00SpwbUVJcX1mElCz0u4f6xeR+rgMXk21ovaBxpC8tOvMccOW3B+14/W5K+aKogpKWW0nZBcRuce3mc9MrSYeL1wZfM1e5n3z+xRzJjIMtb/0LFVTtTSVIY525SOH5VRLY6nCDXqd48vwo6hdj7S5l6a2tdV8PWKLbXZMriDz8ExotUPr2y/fkvPTovmziaN/KiOtMn/FCsPQkJo/J3EjlCVj90s9w2IAPf3S83Bfu/41L65sWMvkROH3nRSPvHHSq+KxER9CpNelZ5AruMo4kMyW52ScbPNveCh2ov2dio7DV1hrWpxTB5tWWX5zFiaEGeVPN8uMHmNVbC7sCZba4vjj0zfG8FsQ+BG/byOxMzb/fHPt6yRckfPXaKuwMkljrIN46ZhvnODG55xdLzBbJ39hsu6epofR4zi0HrDzMrREVV/OZt1ex3URR7EWj0mXj1ASVx3rhGPUJvFvqJwV8b3Bla17ZrJhNJQSz+DPmII5XZa4UHXaDwOCBO5nEjVJztgu4VX2O98c9SFfz0Uj8wZef90LGTRb3bT1Nt/T40j7pFyQXynDiIX5P9omXMdwusbsW69Q2TyeXr/YQT39UQuKTlfsfamZQoUdXVGueeot3/5p/rq5xMallliuo2OYJj/BZ7jvY/xS8u5MMGJjly+koWDLYJvHfHg23KefS2U8v+OQ3vRtWs/byCTyOlmLORttbucV1r0edLRJOjJ6AXGdNKa55/LrPMTY/HFN8WKOaMoB6yPuOqT8xELMjxddSyD+gziwzSnLq8PXsTWhns9zaxeO574Aefbry001YEYSeUz+p5eLPJr0fe5jFqbdynEfdWXQAiXac5mKOfRPqyxU0LLRVM6ieNhoiqzHL3zVuC4Irr3nNOcG2+LPW8x4XDGPU2rdhiUY10dmi+xF3uGRPIvvcsWqmhO87rW6eKdguSj4U7IGPETt8lG4demOWVmutliGHFl7XCJ1Q6xoDK+znguTNmQQjUQMFLGAyUTcyzp2ZxIKs3kOWFeEXyWlSt8Rlo6jgRvER/yOUXFsntlPeB5hvWAlZowkjIGQgrK7OIOSYB3FC6QyXL0VylEa4xyWZHldFhrpmWKW4Wx37UTJFYxHauUvymw67inUR0pCTBgNyYKiSLY2wxG4WVj2fMWcAmTXoeJfh6/ztfgtotl63n4G5hgzxw9xpqnf132lIGKGrntcwjEDmMyTK/ZsJWZDwwpmRpTPJQZTCLXyG3Kvf8ej/gbcNuHyYyzrnudr4yNUVh6OSLliX3tFGrCWdf90VLuPRv5pXv+Q8xDaFq2C+pjPnxoPX2VVVOnYQ+75BmoHX/JbP0bvlXLWtIS3/VWiF3z4ISksVSp8/zTWj9d0r+JKjmVNa8wN6TuG9DSumJA5xtAq2RA9mB1+u3t1F1zZpE/qpdmBGdp2ZtTj+lrq2vZa5kYLpM2sTTe4X8L4oP+FqUnym9jcE3IWKtWZ/6TQGLzq28N6RNpxCibvFwvrLwQH+S2gVTwjHpmOu+02A5poH5xPvM/sbrfU9m0F4IUCfOYzL6qOus3Om/mqbGP7nAmIIOWtEqQJy0Yx4u8iM1W428I6N0tjj+1RcRFXvWaUcCGN9u5HB/gd4QADZi1T4qNnVBcyCz8n53H6A6Yhbo5JwqIgphqlbPsWTtzUZpvl76p/aMVsJvPKrn41r13YW8cjvH4tY1hHY1JTI8ch79En1y3QiOfzGOfNqNX2k2c0aqOUSOJwl9pJyw0UY8hu9n5dPAujYR9uWhoxpSXM7EHkJ5vZYvBbzyfhO6kegVY+wgkdAMt3Iv9fnLtt1CbnjPm57fYq38omy4vnmZLHUOWxG/0WyvU5563yWi6/lglqA/GscornIWPZbcvG4IVTeZhnMCKQb8AyTGZfmTeJIq/Zk/5waCjWN0xqFfNTabV4pSoooMs05OU7lTW8TZf1GZJoHjtH8646+6rqknqebSrIWqjKU0XiTtEHuT+n54pwEdEnDsik2VhIvkpONZ6dSRxhKLK0WDjFkBvpHjJqOkfQ0FGI6XwPvXhRzPlLJLDSfQUFLFVFvdoo/wMeoQe/ZiH9kJ3Oj+/5B9o97DPdNus17HkXubwGMY+Bwm63AOuIbsw5S68DftVkvsBv5mnP382yl4En6p+z+LI5+r8zqzewOk6T6FFymAbnG/GRT0PQ1k3YZmuIXm3TG6Jr9HFnjbZuotZ//Omgz/2k2y92y/GhRac907NnzHbID446ORVLr3r/85XVvb2jBdJyeqO1Ubqf9F90TcvuY5A04QeaKbbfeauvmf8vsGikftKf6UejumV1xZfywK/9gKtOyN+BULP0PUXGBIHDFjjGcQggOK2UC5gCiGYQgAF48oLWEvgv8dvf/gEHhjco6PxJ1SM/sEHFE6WIV2rwIL5UUuRPWlEGNHp0coDHH7NlJQbHOZ4WuGgfAzAQV5ePy1BvHx/g4wAdCteC+2rbBAAFaEUkQHqXRlB6WBzbFMkBAPMa/VusM7OFSe33b+05o0j+k1nikqvUxiUWSOkvPzClWlVKfGMLHsRba1x/0gFlQZNHJwd4XIcfWGk41HGeI1/JJEjV53omqyQZFjKIZFBvHxeQ08TFmp/xbqYcL4nZdLv/iH+170ef2jvF/d4Nq4rre1e/q9X5s1P4GfnesawvcIyzn7ObbOs2hwUqB78HyqznrERLuTmuYFXBcNMJQ6z+gN6pe6sLak9qQfWej/0Vq/qUN5SHZD/LYsV7xEmieqFTsE4w70uA9zvvNB1ArSE+hqcDD+JyHpOF0zgHOET2LeYBZiOz8ALnGq5+/5HHae8Un5oROo5j3JBgROgfxT+x2kl/8X4Utcz3o381Puu5h7GU95tOhNfhbzqcSfDmFNJp5SG+jcVJea25JURDzqLsKfi7S5xF/b+cjk5y1YlU+e+QM/tn9MzH6WX7c62IJkjwa19QY7xC1N6ttBKtZrLWejbFys9WqkzOa1NwxNvlvR6F15Xr64GNCDjmIQS49gIEHzyPtP0YQkEXdvIiJ7V3H1fBSBGKuSlJpFaRsdw2C9/vJSiYNRncNyRnxjFmhvjBlPezzNntcSyHq0MSstGxFb72s251cMwwkJERk5CSkVuEsISKmoYWAASBIVCY3WF5AoUo46pAY7A4vNAdWe2ELrq96HgJLnNFV+IxQ/zuwNZ87fBASapB9zrDDpV3V0RRMFLkz9J0HpZl3TWTgwO7hWfVEDF89DAKMEcmUW1q14xpo76EKv0q0FMpaYcajJ4z+rG+VAr//sy9qMIwqJERk5CSkVucsYxo1ayVhhYABIEhUJjdYXkyhShRgcZgcXj7lI4wMbNw5sJVEReL8BJc5oou3k+EUHtvQQJ1QodTcstbYs4YUDBSxEbil/xPpMkBV89yaz35+sVloyF0avetf4Uqqu0vtYktsdZyog8f5e2+s9LqytsXi1WbS91aX7wRLbnFY+KqQRSLw5ZGRU1DCwCCwBAozG6fPK5ClKFVoDFYHN4+kCNMzCycuXD1cz6/wFe+eWP8XeRs/z/K4TfcWaMN9u/29XT++Af2t0XmCNeoudKk/B8U2NIVO/VyMKRau1yQfaTQ31OKj8y2+dBnKQ7v9z5E3Vbr1Xbs2Gcndind9mIf9DPAIEMMe/GYl+AyV3SdvIEs7ODLRwTY96hr2HMKKVDQFznJ9fu4CjpFvJYmDmG01pevwN45j4cPi8DfcwcFYI5MrVRbiJOgOCIGfTIMGrbFl7M7+9UL96c/B/v6Oh+qKUcY0ciISUjJyC2gtIKahhYABIEhUJg8kwIlKtAYLA5vnyztpeuDoERx4qTMLJy5cBXOlf6fGhDw7pNInu+5DR08yBv2osFvAQWjjVjtnvNxUilYK1nEqH8F9rwgttsRlFtfRVOubqCFtwdjtutRY+ZNbMBqtlJa4mCH4WEjIyYhJSO3OG8FNQ0tAAgCQ6Awu5PyoApxHO/D43CCz0eteTMkL5jdqwPUafQUlPaA6Z0TqO4JdMrODMcNQfYMXCfSWChOa7fHo8Okec+Rcqa0l5qyc9tWnLZn31WK9D0kLkkXGTEJKRm5xXlLqKhpaAFAEBgChclDK1CiAo3B4vCWoCOZndBFt64041JJu22vuty1EVXCbvu1DFErYvCUHN41TQRm55+8XotqO2jg7W8uVcSol4MB7Npe8jpSyop/091CwNq5c7e7Trrb2MNe9rGfAx4KYe2C7UqHnUoX3fY69kE/AwwyxLCuECY8Q42/T0j7VQVxu5SmLbmn+KriNrPjLxT43RyZLKN6CbN0W59dTcyJPixzY61IfGKIJNS7ukwtMdeyHX9BGxwgNDJiElIycrtZeQiFKFGBxmBxePso7iN6EI6cHB0nmFk4c+Eq28UcXoLLXNGV6e4yBNjysOSZt5+PAgWNANFBDrZ9Nlb7DNzY/m0KjCMuuhWwkuI9/8wyJmyyWZbWNSnDA0ZCTEJKRm4xawkVNQ0tAAgCQ6AweVAFSlSgMVgcXgQdaeyELrq9mMxLcJkrulL+R7mI1LIZSi5dRLKjUQ36w2x42004iWUvLjeDyLadwR/2iwNCUTB1LATbHka0JqP3xRnLOAmZ/6kUf/NBMgyhR7tlXuwC7bYXncu82CayrlRb0lzpabPtiEE/GzEk89XTWcDt2JpcegwiiGiYw0iJSUjJyC3iWga1atZKQ+t9Ah+y+ig88eyrI5gSCggMgcLswskTK0SJCjQGi8Pb53ZfhwfhyMnRcYKZhTMXrnf/AUKAzS9SNG/+dFF+KDAHYcpGytfd8nkysi2vIIe3/IdwNhE8uumbFFkWXTTJ1aDNfihGeDBrPN13TfNrlegkKrfOhmeMjJiElIzch8M+whPPdjvk5xWiRAUag8Xh3Uf0AEdO399/iBAJKofSFx4js8y7UQ16Zie5yMmOFuJ+OAhTlPiJWQhCHyiY2gi1n48QrcmMNmLVcl6SWiCE3ZqTkYLVAzLU5peQJxd0MRxs/rSIWZHNdo4Eg2qbNajbsTa7BY+YTr1oiD0bKWnMX3fT81jgzU+QgNl8lnVBoCC0YTIjJSYhJSO3SGAZ3apZKw2t95l8SO+j8MSzr45gSiggMAQKswvnphS3wo43OQqUqEBjsDi8fTXu03sQjpwcHSeYWThz4aoOdJV4hWjHgDBZP70PATY8AjomU3MoqkFvOLyYmQ3c4yDM+gKCkSL/IIHjgqfaja+qHo8gbzg8KIdKt3Lk1gwjEhxU20GTmNtFvnZw87pTL7Mx2b1sAhsOM6Oid86zrUPkYD3sLHaddLexh73sYz8HPBiRQx5uHhGOcswTaayEKqo95VgDpznDWc5x3rqU1mMDNkITzbTQSpvtWe2owE6hi257HfugnwEGGWJYVyl3UMQYGFUVWPeSAuv/KzbohnMZL8OdQr925Jr1SJHf64yZ3tetHerWPbNb96pu+dFu5Nstsy9TM+TaiiZZaXtG1p16edyIWjuHGX/9f7Hw9SgJYP0XWcHwLx08ySEPN4+IR+GYJ8JZaVRR7SnHGjjNGc5yjvPWhbYeG7ARmmimhVbabI9uRyY7hS667XXsg34GGGSIYV1ZdyiGX7xSQVo2U2u3fgcFRlZVB95ec5Y4h8svvzAjHUV29dvPlOs6upGfdGt/mYcGBus2Gup2qc2OzUa4HEz4C+elhXbOZ+swpqSunbuOudvYw172sZ8DnghhJVRRbd1h67EBG6GJZlpopc2OcHZCF926Av0xis0fNcnXXIkCCQW9Z8PDHzvJk2WBDwfhr/0yHiY+JPAVcZDA7VHDvrnm18I5t/ZeEXCYtG5Hdem1Ale/oFhTHjv1cjCAtX8TMA+fOmOuudKOqN34bexH5tnplF3A3cYe9rKP/RzgIIc4zBGOcswTOayEKqo9mYxT1HgaznCWc5y3NpZ1ia0X27Ejq53YpXTbi33QzwCDDDGsK/eEvFp25TWNB/Rohz5f2cxjbYsgsjBvvvp4nAyyMh8gZzylRJ+BGkWRPmpuhAb7MQvDPoyapjTbwgLqay8w/JLqNRzgAAc4wAEO9PZEFCuhimprd1gn1osN2AhNNNNCK212xLUTuujWFe6xOGzUmrM4ALhN0IvhhxAXCdxI31nzVuFgxj0OXo6vEnk5PhvUiBjM47MXuYavO/XylAFcdZuE9DFN6O3HZHae8cRWK5Uqqq11rDtgvdhwxkZoopkWWmmz/ZgdIewUuui217EP+hlgkCGGdQX9p8sRYHgQOi6zFHI/+guqQZ9nwysehLMf0OGqgpEi/yCBV7/MOHnNWwszPDgUDxoNCtUMy3RXDfZUFrKhQ+vlwcrJULfiQd3wYE+gIktipGTkFmuWh62atdLQAoAgMAQKsxN5dIUoUYHGYHF49/k8wJHT+L+Y7b+R5YqNOGDWYBQXI7jKihnvmJtsZEkDzmrjvNlLU/GB5a6e0gFPw7A+/PYoG1OIeHl0cbiYWl1ol1OT+PDV1I/F7HpqabkI3E19P/eAH2StTZ0obPic9DQyyQDbxSyw5rzsJucDK8ezg6EfcDSc5op5csinvN/D/nhKHvqfmCjabPBq9aMUv1+vFAw+3bZ9lhu3aWVYjRHEJKRk5BZYQkVNQ+t9Qb4i6ISAwBAozM2sW9jxJq9VgRIVaAz2xIUf99KP8FwVzyOwdYfejOaLCet5mrEajuPENTi5Nk+hdDxdNB6bcZyV83Ng+qj52m28qit9HPvjsM/Cpmaxdgbi7lDsestlDF1OYxw9zGV3Gvx6j0PAq3dC4H6TkA+goBv2ctlRnBcrzuEqUEUkycuDpKn+MNmtwV/IQRreqdjaRFajRkMMeg3LxZh4PB6s+DJTckjKzGsIErrVkIZ1cU7yfvCoFEi9mI4p78vAdjELrJ4k++M5iUEp+66Io+E0d8o8uZhP2XhS4bwWnr/zdcmeWqUZQ1Jl6X0+m5OpelvY90Vs22o5gKwMqjFMaSTEJKRk5BaVWUJFTUMLAILAECjM7rC8aIUoBYXGYHXgS+8dew4cOTEyMbNw5sLVzxfmF/jKN2/XNvjcMY1SY98aLDCD4fwsvOKcuXpzvuG/uAB69ls0YD8PEjUGehjpFDLRLeuABMrOOq4HHx7BLG9z4688bJTRg3BWXvH2KONE6bUiWz5tYDqnZ+8i5BjofWxediGWg5l+5ZKHtysfFgjULpAasemxKOlBUZyQqtNlH+JB/1kDZKQ57E2S505vfOSf+wK3vc/NkuGbiWDpSWndA71hpam+X5Q93lZrjfBYgBusuGgMFY7zegKsQsRHe7tMV/tYMzDzLCqYw4sv+ccvCpqXHY6dAblJkoNFT9eaYsLctYAVh/CGnPa959eu2L8CS999TS3/Fw0jG5UmmmmhlTZdsz9PISJJJVD+JQkWWP5byAwSoTrp9mE2WDQNJ73Xj6viqSGIZz/HM7gbQvR+Gx8sPSVUFCwrdBTtk0HxgmGmTJSvNRGPrCigyLYbF/nYCajlWAtKQ0xTT2N4x/2FkXLZJ4WpNObV8s9L2F1i3efO0O7K525lD3vZx34OeDCohyJ6uHlEOcoxj0fnxFOV1Mv+RRXd0tFObr/kQShfRr76glmhgcAQKMwuops1t8KON2URKtAYLA5vX4ojTMwsnLlwVU1cNd0HMQYC5hcKwcny6Q4cePFu3Kd4TIsWCIeXvlPqWrSMjquAjU461FlvEj8rdpyadKbu2njJS18QEzHow95Jvx5fY+j9+AYkjGxYsNFoopkWWmmzfdZe6KOfAQYZYhjXuPJlRW5GA1DQt3mYxZeEZI+CThGNpGk0YVPN+PZRbsYG0IR/oKaiAEsLRI5U02hrIQb9bMrMh80Jj5GQz3O8g1s9BIc5wlGOeTKKp5o1cNozcJZznPfDcH5kfMwn1kW0HhuC2ghNNNNCK222h7YX+uhngEGGGNaV6S6LGSzs6az2DQ+XvIzIkw2a6bLmRvz3aEODTZiB5eSMJid/3cXbWcDUp6ukXHxcFe+3bSViIQnPlvaT+EPj+C4qNCn+4q77XWNtN/W7rxbuvVytrudgTQtm/rkVvPDyd48XT4KYEvUYS7L+EEmabeVKXeRq9c8NL7qPNnxyKPaPgW2I9OInKHONRdkxO2tlI87HE+TyYR7T/NuEpNhNIv9anJ3n+Aqdqz2kmbYHWVrN9pZDjm7f4oHPvqLNiy6Wpt4cS88CL7pnlcacsVMvg4HSyvjRgPgssynTajDnXw6wYBxvQWXn/SCT9EE4w9BGRkxCSkZuGdeXBHZr8ogKU6ICjcHi8PZB3SfwIBw5OTpOMLNw5sJVjBfzeQkuc0UXVyi2jeFk35f0tLTu56tIk5k0U9ZyM0tadaEIHLDgR7gk2fhzI1aGcGaxCHZCUHT3NRnVKG0iNTgHY1oV9mw/x6g8Vzq+WCqmznqxYc1Go4lmWmilzY7ddkIX3br2rT8StJx/E7RvPxUpUNAIEF1KUuW36M5YGni7YBIDY0eKyRX9tlaWJfTz1e0sYMH9hLTqHlbQSRkeMDJiElIycoszllBR09ACgCAwBAqTB1WgjKsCjcHi8PoOV+j/G+FMYMJlSYmyANLw5++2AZ5zXjGY/U6l8Pz1KjHzD6jCzJtnBEzr44bnNWAUzP4Rz9TlGJj1p/gW1Pzdy1QWnIO7n22qptMLh1nMzBUJOM+fFwvexref+wh+Z14AzIv45ScPpAoA0wjTSgRp1jJFnihbmFDz9krsmvIyKUvp4bTMqaB1+PMOK863yV+UzuMjeNfNuyereXdf7CY3ZsaZurs5A23Xj1axKB5gFUiV18zcw6a7v5ypKVH0UfP2XFc0wqJ3jIDcRVHGwGNzXy7dv44ShwQKGgGigziVN8deLiUCSTpyeKeUQw7mNcyXy8CGUqS2ttQT6Fkl6VBs6qVJbIpzUvrhODmtBEIKpM5pmM70izJDXHVGWyNzk+MPFMXsqMGfcIDTXN88u5ifyOMKv5918NwrNoDZR5WCufdR9lF8ucL0RkJMQkpGblGBJVTUNLQAIAgMgcLc1OcWdrzJUVCkH1BoDBaHty/UESZmFs5cuL521JHk8EI39wfd3G+38xqrPDq+xQP/54J27vlVLNTG+TAf/7TAQshrLXaV9wM5KSHrbty09v4swlS2nPwy+syeq3OFmCwo+Eop3N8q+/m1nTW4SsI98LumrC/V8y+45CKb9ZGi7FeY2c+OpafwDdTsWcGzbxiUMDVMdx89yWzdOLf0XmaF6urNeZZ5wbrMckWVRbXFL6KL9dQOKcowTlhOcbmVnOOp2M851xc9n5ICBX2Rk9aVgTvzQDnmZ+S9QlHgKxRFDWYWJxjCYqS98yZ3RQQ1P6zIz7H1InNHS1BzrM2avimGUY8IpNblLlG9J0V+M+23mLUsX5XwfbZPsYL2GYnpea/krFmFlAek3k/LlPdLz5xmMK9KFGxmynEW3L4kWz6cg+l/AjtZ+50c4DR31jw5n5/MphTUm4V6UhRsy+1LQymfLKNrf8Q2WNg7Y2VYqxHEJKRk5E1RsYSKmobWe46f/Ela5uUaeBU4QkQGhkBhbi7DLex4k1+PAiUq0Bgs7thHc1R/VY4wMbNw5sJ1vKkX44yW+uYogVaBpp6PrVKgfSmQJj76qpmKc/bEfDlv5i3l/6TyYjpPryoZsFjOVVJuoJ//syjknQM1iWDwgiu/C++Z4gTk2vZAvIW8PL08nTS7dAb5T5nZxYTqOi0xq9csKU0kpGXjJa0DcSjOlMlKfnfakLbtxNDnDA++O0//W8EzLi/wtKHnVdTmGZe3MH2vg7sZl7sZl/OMl2yz97ihjr94IxJ8WYv+0bDILiCgO2T6hTatXE5jMv5XQ19nRgOSwPT7SEvj8C3T1BylvBIjzuCOuQtGy2sAvky/ikDtvJm9KoVdzrj93UyBQXBvEm/NgKmfNKtnrzDXzO9nrOJtje/F+HfyuzBi0QA75Lv3shM1TsxlkztdyCyIBbj7Egw+s8qXRKWyJA8soxNfd462xjO5mbhvxaqjQqw3Rc/AcF708pQvZhr5g9PGuux0FQoiyvhY9GfHXCBmFjh4APqaDfrPfPUSjj4UjDbCw4sMQ6R4WcnUU1JQvYIMNf1v/VcthM8R4HBQZEt0J6P1tummqDHV28GM6uobsv0n2nsJoJxmzSoAat0QMyEpqXjpkTMXypRbGwu2nkJVrwj0FGb6lwvTFRobTnOnzNOLBWD63yga19UVRJrIlAZyGb3G0++D5+Mm74yVQTLDlEZCTEJKRm5RkGU1Vs1aaWgBQBAYAoXZHZYHVYiyRBVoDBb3xlfRrbn97uc1Wue114r61NJYpN0Frl6xhKfcEe1VCh5sbHHfx0hSczPL1FXmvP4W8ZkzXJmiUyWTttykowUCKNNdZaXE2phkg0xzj6XWjpl4FWx1+xTfphV3JzDlDnaYYelulDhN7eNL5y7LUx+1papw8CsXY/s4ofJudotiOT8Z3T2mlzxurhbnR/ok+XfbLYiLDoGnkeIxMIk0S7pyNNBO+dNlvsLh3NJ1wi1bsaSc/OZVtp3TFzDxEUsye/+DvIx3jZacDp5yNOMv4kMm709307ltFuMyR3Z/Hp78e3xwNy/EZPH9QJFeDwzW4GJLm2I0XejIe15DYFro3BdZPvrTmqNWDAYuKE3nuCrgLHfVgY2Ggx4tY5njbTGRh0jVzdTbdJvp8hqCGU3cxLRu4O154FwsenVeqA7N4jSl449jZ1Q6ES+tHzv7mC/Bdr/GqGV7FynSZ/44lk96UyfOB/Q3F0Zp8bVegOodmHwvJuLj/aRgckch15foLNriyZtza18iq+bJkwZkmYiV3oGKM/4n51ADF82D4gXFl/RbCRRjsJRveQfLenwoYp5wy4YZzO14LKejg+abY2Bin3FqcWI0TLoPp7SZrrrzFCKN91Ol0sNSyR8b9E12qsOGo30HhWsX+QluFaoAhapoQYaN2B/TjpKkmrAV95GOzC+FtFy3zI68sau/HAvpdvlArvKHrsTSU6bJEdOJPtjaphvi0YE+KqXhrQFsF3NQk25gx4HTXGfMQyS7POlJxeBKX//KsSCfYQVGSkxCSkZukdgyq1WzVhpa7yP6iqATAgJDoDC7EG7KcivseJOjQIkKNAaLO/axmvXFOcLEzMKZy8k1UkbSUROi9CzBwOfXWiaSk7fz/Wkw8aiZ2vnh2ZxbzQUymc9b0Wbenhd9vPY37WBuThUVS5+Pqz3p9rMg5Qvme7WddJ664Y8wzQukoaGHLRNZt01JVsXlhMtG3iQ93NSipzE2TlyKutu+kfXIWZm9INLC+EVv1UHhTX5SMSW1DP8SXrofxh30zvHQ7iE2bx8OORY8lS5p6jPwNi4AL+NR1Ej+0YE6pMVRhBwX+EkWX7QTyNHx7/WRggmTWMD4b0rku050SUvgScWg+pARMP7T3KjueBT0PZNHHMNxnHOcB5+LNIEjhyErqk9oXOPwzNRF1vuYGsmU8DO8ZiNbsgPkG82GdxuF3iZO0cYdL2NW9uuXBWz7laIqFo17xucT20jYD2jnpWdYURmG7aId9E3hNLczj6Z4lTArfd+rLGHF7IxlLdYdth4bztsITTTTQittukJsRjRFMmzMcTYmPIwxzsRhMkR+UHmKlbwt0SW0yxiyUNNF/QjZc/jZ4RoNFVyfE70XskBctgT9e5/Iz/icBdV/0K7v2CFJqahuFPjJ/gdZl0SL2s2lmQ/3y/JRB2GkkpfuDBUXZ/piscXFUFuKubafZ7GpmBebvo27XoXn/mWF39+KzXmNl+DpIzvoL898CTz55jT6UaXayfSp7zX+qi4WeEzcouIcO9DietTaWJL1vSbOo//LfUcL9NQGnHqs15lOXa/K98uoNQl6rzOF6fnYNOjbb2bKWXOOxrsf9xJfp1/KAnCRHYproqYtL0+SmIj4JU3RtGezpVrIBJ+g6+1ThungVPZr3fmFaV2J6alxSntNUPY0Zcvs3cL03vxu+b3fNRuiLt486uWrRq/w5xhLA5WeUm1tP1+/gGJWmDTw/iYodyJypEFBI0B0Jc7ekvwB/juhdz8t6L5pskKj7y6qPundIipv7TS6bFw25Gh75sRSKVTnhcL0xsWG0/xlC/W4DB53EvnHWe9gZXHeEipqGloAEASGQGHKBCrQGCwO7y2N8o5FnMdhmAg7pIfUEshdH7uGnkFzXM2jejso0H3TAOh3XKjDxUZgFPfQXffbb1itSimJ9pfdL+CuHEbJVOheGcaG8U31c/eXRdZ5M857iqz7w8J0ndnSYuKts+3ZThTYzwptboCGhbTnGeH7TUD6dvBgRA7MAiiH1nqkQUHfZIOyHoc9rcVFwUgRg3j4r15FglWWiABlHkXCltGA7hYtKDMZs1P0LKB5RELWR1ClV5P8giRSTlJjdJaNUGmNXwFsF7Mw427L/nAOdbecna5bxdFwmjs15pXw05dsWY27YtuC5QrbyiCNYWIjISYhJSO3SGkJFTUNLQAIAkOgMLvDyoJUgsZgcXj3JXqAIydvhEmSb6NVmQx7nBZhii1Md2GBRi3QU6B0FbfU9dXHsDabLwot9ctug1DsHNPFSPb3swBc9t8dfBrTP8OU5zV0DrDYITHDWMbeznxxOe7n1h0FgXNnq/BbpwulcosdLt24S7l5S2HG3TzDHT9vO0LjXqSVVgqtR2Uebrx9VBWa8ALamRXo+EiBCafkwvSnJ5DmNt4lT8jc20dZk2xXUYFTc/7JS1/sOMkKOD6wGzzDTmrc0sS4J2yzqSuS7cXVZ79NNS+br9vZi5KBtgM09fYwJX3aTHsfVscEGm991GgSNV4PnKhngdqs5rd1rQ7upnlzlLJ1jYd/0jAZYxrXxxomyiSmTNE5s8lZmGvm31G38mb6bQr0BFojugKtN2+hB4f0rUqdxkSmpj/G2hhtMuSSTOMW1TEVuQ6X+lrSN7s6HZy0cUGz/mIRet8K1F+1Ldr7JPpFA2GVgcODhsY9tf70TlfX+lPX+lPX/FGnZTq9o2t9tQZzePEl//hb5MbTYyLwxwj9Hn2Iu0yqt58QolYafvNR6na1X3etk5NenbAyM8SmxxhjnIk0VX+JR4macvPpMZU5TDN/Tw0vZfnwX8vCtJ4749f/kr1qYDoDbYfsLdQHjI+S52oiaQbXptzE3vtxvGSGSZb1j63qP4K9q3h0NQLqW7WA5jvrsBkglqi12gn5y8kcFYrblQHM7Pk5uP573n3zjIWFJnCkKKFYdd1pR2H8SWPStkf5JLVKddkc4tpC+472lapYp4VjR07JtbcLv/HJ6oC1j4blxqQo48QSbwd2tde6huR545P4k3TKOJNqb29qfNksp8rN8UmFOvzcKjdXoPGkhVTrCjQ+W6T4+jL6RrUtimOLtkf8KqDR9brMEjFMohAtC0rdCjR6ihTZYCrHG8jUKr7M86WYRooy3VD7xjQeG8a6UdXQq2r2B1eY+tML7PAl8Dw75EZK4Tc2FvDMBVSXLpOKUOkCBYCWVeHOFNT+da8iZFcavXMIygn92nfpyRQbdE+BMlpEeCzHQaDcROCMokv1z+MC9bcXXM0ZwAdFjunUuxctaZegfu6/gbq+nwmvHGLGlBwWnLJbgpCylRUq66O6pbVLUFathdRKpvLi0vxAskXSK7raK0VXomPDaa5jnh7WYOofvq7M9Q+LrIoqoJK+7L70mI6TWeSgtGrWYkNq118tmPlXwklLOPKaHh3gCA0EhkBhdmeUpagEjcHi8OMNYfqswIV3hksjV+NFWXhFV3/6Slnfb1Jjid1z7dNAmQllLm/mJwJen9atC6PNYk4s988vs4Klh/pIumdBrqQzibR+x1ROXj+NvdT8vdGhz7FLnYHXSVcKXc9CGAKZkZ1+qll/FW+Hlolgp06U4nwfQfhJglzbVUOn0rKxbuoo1VUdXflJVy525SeXNN3UFrTvUNsT6NRU9Bo+/L9/nxZcarHrafYPd9/XcK9Blr4eJrNdQk3AZ1QW4vCIh8q/97H7wi+7+1ycMlq7wVOuDhkjUxp/vcoEt2K3SYBTs8fTicrNOPMsjHOWvOUUnzOjplWVIH9bDnQx+TTGp7FCt1NKPenq8HnHyMxsZxktXVzs9QecAdOd/+rirT2BztmOBbp4Xk+g4qw/e1GpT5L/80+oc90ZuMV2KJZcv2KTg4OQx51UV+gZq3HKl3AlzPjr0dITYCBrxsC0tlo2/Tnwrxa/1/T392v6cQF+uUziWqVc5h7no7jF5BL44itAGh8/TfmMgQXQtQTeHag+o7Rkk4WvrjBqz/gunRpIZwvWEvgy4UWBKexMl54FWrLzVWOAN/mN71PuMwpNJtHnBN+bdNqp/+myMbr29Smv82l97I+khVql+Y87dCP32WO/+3m4Hl7mtl5js6Spa0Y35U2y8fszeuLHc5zHehoP0ShsmBt035/M+q87tO9v175Yb6/X18vqQRWovZ5v8OlH/3Y80zimWrD5/nFuyO7XgMAe925OpLRGEauQA41vstBRb111e+THEd2HuXq+mpdt6SukslbKKq6KrnC50qFqClzySlrcTU+i4bZdzVn4AfnfjURzWJBoDQEbSBATMyFCkdTENHTkYsRRMjKKYmKlliiNjp1dHCcngwIFjIqsFm+ttczWW8+iVJkEO52wTLWT0p1Sa5U67Zw+022dXheUcHEpNSKgDMvTCHbgBmUgMaNKAjvBTXAb3AX3wSp1YOecXACOg5MgAjFIQAoykIMCkABplURIjCRIimRIjhTIC0CmjszoODqJSmSggE1gRnbgBF4QYE2kjXVAD/TBAAzBCIzBBEzBDMzBAlwF10GExViCpViG5ViByczAyTUyTURj18UhVi0bTLbVFFZSR86mOne4gMuMxMRaJY42tkSl42JGPyHVUGRitcWEX2eng4rIIYYEUsggh4JEQq5FQmQAoMAmbIMTq8ZT6MJyXQfpCvSgDwMYwgjGMIEpzGAOC/mPTUgfypE+1z/SgQoVqhTZLlF7Dvs4Dw6vKKNjqpzl1bvCB3zCN/zAH/vHZxyoxtAEPRIJxJBAChnkUJAUrXg7sfELcATq/hYGYWUBbhDgg/x14sgPfPiKWn5yHhUqVKhQoer1kKlHhyd4VtIB4WgQFzW7anbBIi9TFDbHbyFWHTcXfWUB9GEAQxjBGCYwhRnMYUGn2QIddNBxIiJ3YHgNeTxIz/6Uo7Z+YdWssoIfO4PCtgGzDCvN15xwF6YaU43lZ1B4IOT4SRBjNRd3hFTSmckQIgg4TcmTSFLpjEpTSkBS1aEmJT0FmyY+W1l/H2r9hhhXdl5F1IuFxGY9h8GKQtSAij9UqAMDx+H91lGYR0hbWVa4wau4S+4VjJTgFhiDCZiKz8DHP/LTlbAW3QAbeUKiAXLthhzEqnMQSFmiPCUKDpF14QoQVKKWy7cNpdxhux6mUp6RMmPotVGGJHRIXy9f5AjzROrSpSheBz9RhNjFUrWESmqGkXn42agIZRojxyjN5IsXqPrA1qSTs0OKQyqlRZ2Y5SOdrhIr9kiahbQGquBKv6TUkEcrHeEyiDAk5AOkNYCP/UXmQkKsgguSlTj060wTUdkQGQhNVSk6d+JawhfUlxy+DF+Br8LXkB6fAjNZPqhzw6lUE9B05OOEIu9gejoSn9ohBvRtWZSy2x7G92jnMjrbKJXDdszTtntg9el2fL1AH/TDAAzCEAzHJiiXhGTQ5M+D+Dyqwwzxp8EEeXNOLg4Cp2ZpRqV8ulueZwgX1l41heAcGzS2xtHY9RyV3/2UAj+t0E8pqqTPvWEWbuRWGLKCT9TXoFEE/7WGxtIYTRyVICwej9j5QUVkc/8IwsFFTZzGRpGW6igDVC4xdaTfE+v6/gkENg4hjkTD1VINZaEnmJ/ZYbmXzjZIk2vyNclpWxAK8T2lrr/+zqNW3nDkcXey3DT62OvF3nHrzY+lPXLizlEqErE6FFAgKNxQicbBcOOdwaM84NCE1HVJGLMMymaMe3TcyYBRRS3qIS8WhOc3f/jTX2pizWselyMkLmcqEYR+qNUYNBmljIIVnB2NJtciNAUpmaLlZkJSc0kCT7fq0vogiNKEMhWus6ORcjMHCYrqW1kYIZJP9Cd/Dv+v/qBfqKv+rAkxALUz04KOZyMuyTgzitKOF75ywjIPgbYHYDSVKivEchmKM1Oh+2cEUA8Rqwv9I6YhKktSc1kRgs42QE22+LQSC92/OtwJ088tFgADAN+XjZg0uAoYgiyQObc85NJqyep6lwaChKJsFzGLgkvNIXltCikb5KUnCApAjpsToDn4ebrkNHFFGzF4gt+JGlaMhZqVmXR6LJqKcjoJBCazUBUOW61cblxc9rPBDxsmS4z35w9nlCozp5RZLsZLquAbAVOKBAuLQInFZ9a0DS7NSnJNpBZyHYvD5bRleO12BfAaQY5f7+b/qNKK65qilRVIVUNz1f7VorG6CIOpgIyQ/4MCidJircWetnJbzO33n89QflP5gZLDhsPmI8YjvkHPWXdJX+97o3pr/HDhetGBuEyuba4d7o3uTe697lPtru9k1w4sBqzBpZAlNBcWRjZFtsa0sYX4VMKUMCem08oMK6PJ6HOinCZnyYvzU3lrQV2q0+WSsqQuK8q6ijdYrpqrl/K8EIuni3csN0u+7C8Hy/1jtNo/no7vXZusTdd12k9PrT+zobOTG3sbT22m+T1bpGxXpyekPTsFXa2fzpH5DzEjAGRw5+VeUX+uVjaGeN7fDFaHzv0fqLbunKCFYvmsDQ4C1YRjQ3HiyA1jBYnAqVtuPk6FTjO7TV3IWL3e//szsP9YmqjzdK1MjIPWBuUDpel5/YcOxHfcF8YWUTrrVb1UUDUGbgaWAGDP1vu39VHlRM771x+oPSYy2oh/A5RaeR/Qhu73wDrwAVxgGXT3zbccDw64+4bjt4QU8UG1fMChgLxks2K50qwUJ4oQC4JiCNyLFbEet1rJ2WJl6RqOX1FW+5fHz1C9/BJL4yCgHL8kYjcvdgkVi1wiY4zRAU8duhemv6cEADre+Nkw8YHTDy1541kaNxJXGZYYRDR+stxSbb+HUHgMVrToWk/orb3mbh4jr5xotPEmzjbsQ6Ca2y6qcapO1UB7Wntme057QXtNe6S9vX2uz5/94t6yiuZM/Jfo/5dGm9FKidZ50svOZGXkluOOHID17mnhPhPaU9qDT8rq9toP8SbIBCBvA8g/AP8amjyczEkH4J+/Af/8+vdZb/xbYAOAy8fknOSVbMnl9R8//foBr68buWnkIJgSfQhZwC3AKPBs+0Hshb7YXkyhib60sT4e8u8B0bBGth3e9bhEWdbbYLvn2SRLV2yVTK96xWvWSbLRYx72rDS3EFhIFBobxyOe8KjnIt5qb3nHm97zpKdc94zNCr0RSKmvbfWiUR43XfW01/3AbYsi//Fv/7VWswaNWjVp0abdVz73hS9169Cpy2d6DOjVZ0i/lwy64qJLLnO5oNZeu+y23x77HHDQMYcdcVS1EypVOeR9Z5xS45zTXnbWJz70kY/V+UC9Yef96hc/+00Ou1wOTnkIoGCw36APNN/gIShKI/70v686riPuQpcaXnkfwo/YlA4gs787sti+HP9+QwT/g3oCzc7PVq1cMXPG9L7eaVOnTJ40ccL4cWPHjB7V093V2dHe1toyckRzU2NDfV1tTXVVZUV5tKw0Ei4JBYuRIr/PW+hxu5wOuw3mUt7xXiyFg/m7qJSJreHSUDt7R9HDWR7K3Md6mfVrwy5H0Kdi98+k7BprvWEbDYHJ8nRaHGj3peWZKjvAj2HxxfbPef+0Fiq15Ylk+kVEz+p5mGx8R0CZj2LUjZPX2pgZaOOTkDYhoCoToKLmUAJHlpLaJLzv3c2e59jlPKPj2LIMeWNSAG7fRdjalsfVcr4NyniTQMee2b3mBtGYWsBbI7/DTAJJHEedN7BWfHi8TQG8SwRPcu9EtM9iS5io/0zYaacFTiPJ+6b3T2AeJrab7URQlwQ+rSadP63XMkkA+NOG/EpIWavj0+oyF4xruo4wwKc63pZN5VM1CnAjZqL7tILYDxkkCw1CfHngQ1hGwaQUTfEi0DKmaYHAlgXBArN+DQR1Sd4PIAQI9UM4Qafc3MslVwc61DGVKU34U/0qPb8jQIhw1sUy5lih1RJfsXjHy6QTBPDlFxQY1wq5W0EwmYqVnfVGVzS5n6hq+S0GgelFNO3O4bVststEOwdYpbmNgGSG4VDwhp+Zo0jwWvhc8AaDsd44vnsMNWs/SXho2KcFC/RcmZJka1+z01rP5H50as+p4FTdUMkiXDwWY+DI3T5XoT7IYNKo3TjSvyJpdZjiNUxFpaMaYUfPgUUPnr6DCZnMt2Xb3iF5sS2JYQeR6CTeZXu2vc5j/gbgIsBrLrmk1nvtco8I+kTGZuQjeNdbvNbIRMckBnXW+lY+1KYywU7XHcfunyZ97E5uJGHYSmqGaXhGxX782KJrDVt9fU0x3PXYVikcqzkqNBtKj7QUZ1IjHGlQHHsKJglQ51e4rvGzL2rR+JBYnHMJnZfKiPSjsRlvNO+DnehutnPDsopZy2QENg33qOyPnqMbDp3AvR84MIvGZxx7asRweWHeK0veNEzrJJeDJp6sqLZxsppYGnh1CUPFZpSYY1VMEhxJeZMmmyP1KKTQl6H2aHDEMbs6tQUw+UAGYUVUn83ihMEp79IXiig6pDzhx3yWBWGbbSv3I1Z0o2GyPb0TEewVkvSM9WDqzW7VNi7F3qzkkjjj6ElzOhIbsxYkm5KFokLBGxUKrOpYQ+DGaBQVC00unbSFr/5aKBq1fsyG3pM28BuzXZEh2x3GyUOKnYLlRvYAfVUAqTHCWMwTVd3GEFwFT+2uGI475zgOwVtVWRyQTPQEFRhklDIlW58VJ4QRhTbUECw/v5MFFW3C/uDgyg2dZ/hGnf0B+4sMmOpfiXy2VFBFcnai2aEA7F3k+Ceg52oIJZLK42tROO3S/nkZk6j/rMtJAcOtCVATVNLJ95lrnU+itPhhBRsewdqeiZiUUHCWu1rh7OizyTaESQI10kJsa+8WC5mYLCKR7Q91totXLTJKJO+oxSxkgXPGAX/HSLP9pnSxk4+BisNnTuh87dGzCEOUWOdSeMJCNGxPA0msPXZ6TEc+ZZmm93cvI8KBERdYNgWlILakS/qBjcXP2QMxYKJ5rItot/6uV1TyyOcXk/XmTHOFbgKXnPT+AjT5oYeYuNGRPw1IY8ixw+xYcEAQmrPeUaK+5k86nWg4N3JwkO18mgHKioS6Uy/bFfwJ0OCeZUCNTOWjIhstdt3HwSKwIMbzcyLjFl0vKDS/x/GvBBiIhxsWjkyEvsVFhiirWI1Nl01/GLylc08EsCF9mkdBsJDCbrWvmKW8hsymM7m68CR4VZ6kLphqBvbV4djtg2gHyd26kkKUBcljgBf0Zl8guAhMUBILKDraIZKW6EKoha/gtHTie2DX4BRTaw80NcxUX41Zi6X9a4MzGquNUvYtlOQj+FZyKGGxbpXDUCmXgpjchC+kERTJTGi1nFUFj/5WaxGCzzxKMTAcmvR6eJaYugDQw73QRppBKDUTPeWVXZ1UeNgVMgZRaHmATo8tvkmbhXgsktLDlPAt383MZMRJKAouZCadzW3pQKaAIx9DOaiWrb93dFP1KF/VuYw2qYlsPwaZCYDOHMvLhFx/pHDbbba7L0BQTpxxIYFWPaODu8s3+cLoC8OlzEbZ1AXHJTuUft4DuPLr//YGASgilDp3J3ASNrUQ2Dy7ZJG7yOoVO1J/rLjvv5CvCFL0f1sCjG1lT8r83mRFUr8Hzjon1/7asXSfFncPyel9BMtQhFvhEeVtYgotDVxUTTtjR/z/+hzGaqnw/tnEeHf1WrigfEu2JZ3LGEuMLCEwKZnxjzyw9bX3X9gq+eazt085F8p5sZHnZM1z8bZ9JFojmTjOxUZ4CkNs4t5vDA5ynlohM3XOttVizFpSakmZs6sL/HYgzSbScUCBg/zBiiFtd/NHm+FJgvPX0haYM3bbq+GLLRZRfVdyka99OIiuyLqig8fSSn5m8Y9SLba/9j4IYStafhMu4L3bfJ4/uh5qWBj3XuQmbKwfXweiahEZJWbpPt3Ddgmjj8+l6jzgM8uiQ3JRt6oP8TcnoGEGG/59zKfE+NVKrpJEAfHhKmpgF4h6NNSyQ2xoQsRAtKJT3UdTV3Q3lIds6IleF63Rh5DDhfM/UN8AYDCzGEx46V8Hj0J1UtgjTp28EtqFiE6xMAYDGlozEUKk2QjUoyl0Zm94InRtGlW+14nArshQmlM0V+4AukmS1JpeJyk3o1VQZbZzrMlc2Ztmk1JKe4HVYNpPqyohTlNOdVE8jAoCOkwCsXZu18a0SJtdfTmk3A1GXK08t6pjRpojS68vtMGkS9kdJJy9ToltnOC0sMFWD2lcEOvzB5FBqHEBLoM4kWG872U63u95y+OSyL1c+nOWXM5aBB/VaG5JLWoTntVJQecMIh/eXCY6tUSx9r6naP9yLpm3TUVjqjkaFsh2VHqRlKS3rHuX9C6beQdb+nIasSq8cdNI5DqWUjh8UOzoW2G9y56yHDua7IgdkVuKpXJXNJrIuUOELMcaU7MWzWlC/UjdKy5llbp/qCYsmEo/qfIP47iCInACcRJt4xRJDNVHZgx/FO1Tq076nFiAxXpsAcBj5HaTBNKxfLjCrBGzGDmhExMYkidyIQ6Agh22+Gza0Hso8rw50wlMrNptkqL5Whw/zleFxTfJHbIQF9czo/MUL+EE7Ip81jXeA1hCywOhFogwlC/YJuQKBhkIbL/1TV1u4w6GdAEeCDC8FuAVGs4wjijECh2uc4GR3ldBkXN5nJAhIdrniYCLjPLiP4rI+QBs95diOB9H7RGvj6fr4tOztCV0hugHyIZrkHKRww64HNs51oDDCWXnKXIifI1FPYGNYZklTwIPvQRZEWZySeCTfzBn3Enb/DbyFMuaLGoJDGlZdklNqf6inf0ILX82W2/W6MmK87bSp8xAZDW7E1Xdx4VUFyPWNP8CxEiYfj6p44j8vxSyf968Mm3RSpR3S+wi4sdGFqjXUZut/w+saLzNCUGDrBQ8Ib4bF68B0pqkZF/zXoInzk7BLxVs8s4RIZtelvUSLq52UcAKkVSjXEk5zhbZvSNiAUX2aCzsr69LfDEPON5OEobBk4cGz3uFhHlJJc9ovzNHHVjPjhiVjuWOqwmUdB0BLpzWMT0SSaRdnOK05Cr4nnBhQraStmuRw5Zo+624yA6hAEpwTiTkldZm+5dVjk3Ck9BHoEHOipUP5fTzkwFPS4JszM94msBKXsLkAIJCnUpF5GpSbZDnLn8O2cKwQXY7wQ+Fz0fCer1vrVC9KzRCQGN1/bdbjMLePL/pAaNYbccJ4tFQ9B/Pa3xP+a39RglyCJM5tsSEKhLkQOLXObJZ9n3+Ni7pAfI0Ya/HYRNnsu2UEWQPfwcuBqqxg2uAoKQUWmSfYSRZZ172qUuM1Ds/T18qfe5tp03tOvpP3NwA57fhN5OHiLGtmQShi6vZYiAvI+wA3AwfpU91CbhnRvtE7fPK56Yl/C4sU15p9R4WFLigPwbBhnZ8Ys0R9/Ja4LGJmO5HrJ9afG5aSB9frklvQo9IULNIIZ2uadOu4XOX3IB08YVqpxrBQNv4VLXOmub5xycdve4qxPiBeLt6ovehUyzmfANlGCC8wDmcju1JBUcFI1tFezOrN1ab37NWM91oowkY+ukTTJ7UN/4SKgqs8KBnYn8dyZfS0W7EAfOcF/pks5+dr6r5EBu6H2fNuVlM7Nd4pkYzS4IxqOcokIrQ56xn9XdtyEOGTDyk2qQWFLvf2ZfIGLXNzzRIdv74Ue9mmMvK8cP8xm5+BUZOJ72QH3zGxg56Ka9IHz8v3XKeShmohHNcQsillB/WOeFJGF+C6BhbpRhdGwv78WmAW1+MHQwCR6MP0Vt7X9ObE/AAOYNIiv7iPP3JRAELO9P3gyrQF8OzvuRKQ3XqysWXV2YOKSrlrlAlIljoD8nF9YeXUSY/uDK/7YE8o9LdV1gkF9UcWUebfP/yuNb74rSORy4LzWRPbn/DPX2IQfHb2rpeTx3tlF11lgAqoVJbpiHoNu5Qy7SWLQAYa24SHdJ5jPsFT6ArBoQCzC6ssYr04pd6tIbvRD5ZfgcoQ/b7rMUiNFyPUKuBIjDt823a4YcBI3eryqu2KpBQ2TYYIZ8vrDis40EVarkrWi+7TshGgEFtPvmcY5kySn6pOjTJLpPWQVaZMCTJNiI3smwEUl7mm+KnFo8ybT4XonX+gZWibGLV0Y3jZdH+heNywrJDc6FZ+ih/rZ9cFNG67EJa9hndr0yvVFlFlLhIv0FPWbYwvxwL8BXkldT0LnE55sH0Zr6DH/vDd+jzHWEFIyM5WVaZLQIYHqKr1VEQhieZZXKzKOYrV0v1IRMYzxOK62YMMtzftI4d53zr4jVtdRp049qN9j3uagWnjeW5UoBbvIELvncRrGPKI+niVYXhO01i5h2j3MqigoHWv/Z3Iog8YZmTRoYvl5oayQ/T+w8fLIJ335In/kP8OwJY8WSMcNKddjvX84kE2eSiXqJA72YOZBxyqa2kpulyBLohlbSJLTxe8PSUt3aT+1mDhUJGjkxtNLXe8R4VW0G6er1tmSLpzB9vGnRasExeN/NmCw9gWNkeWSWnmyNyMa+vxw3E15a9oD2wnzuhGxSye51UVeYEkSHX7uO0gpPnNBPfW9Ik5f7F5+p1vzan2JgjY6HDKwotp2yTZzjlCM9ydh7T913Rje7uNkj988e7viHDcCBB0BvFeJrdH0OB540LbpwqZWsyfg6BJClwJ3cJ6yjDgRNaumDdk02pBrPbLmsMGJyysxfLLnPDjiZNp7yeLzRovewKuHxyQK5eVyVJeVh85u4TUM+4eu7663ia4BwYZwxTTygvpchx+oM0F7iBayUpa1aw2kW2SVZBzOLVDlnDUcrAGai8becfO7JQ5u4ACVjLFUevkUU0Fs4f0GGt5+TqzbVeKEyrBw4ZozTchSQDExfeCvO78aTtTVpfNhm+dBds3chUru6uTCk5x6dFul6IJxedjPQoDgD36Nq9MADWKtIfFKdd1hi5riIQpkvm26eEs6rQCifUnVxmDWJHVgcXkhVazieHWt2cxMKhD1SNrvtSWWSbdI2sy+t6VVumbbZkqt7UBhFIHygo0r6s2ko5rlP7c/f6mWXLNqEcCpivuyMlJ99WINtMoI3KsVqo5eLryCBaz1CYvhtHnEYRPapb/A6HDkXW2E0B8ZbdFD7kle9ncFlk8n35PCz7eXgQy9p1EU2cuNhA1fDX9mZ4e7EHtVEy60lGAds31+3jAdvu8QQGIDs8XhSV4xpWVlNOyriTNG50bX1DdNjQd8b6jNN5xWsvT3KvfQWJKebozkhNXpVcqqcuo6a9EVHHUSjxjxkfC6XqQKTILpNYK+muekX+gEn8xvreXqqHo42lgTz9nE3N4Cs2nj1WzD3DJxrXIug2p0RlLrfIxwaK5GPonTCrPGIpGvGhb+hZx0y00yT9AAsoRKASaKqFU3zbp0RLPWKVJWqRjykKyMfCQhaVU9KGRvr0oAeD49Ig86yedJpmOsPKxLaMWTxhgvzDqcUTBRAr7TuzQGKzB8ESwB6yySCRa8WMamtG9U9M6bvtwcrCwg1W7ZhAADh9+8BQjVnV4WB35QC+ErvMLtLN6m2y2L8XWDksWBRPwoppwE1Wx0kERhpV+VZtIdzW3waJk7R4TfhBCrZSi3y1pO+5/FNhbKSTyMlpQt+U+9UqiTck1OUlOhLJR6geuJp2lAzwlBJfSKhPWbJ+xo6c7FOM1sqg3QlRbht2zanOoUuMTsDBO4Ao9inywAjLZP8ThO/BrDf7Yn+updOe++E2rZ3c4VdE+ZLwFoAKna+svtzlM0K6Ze/UZXpaPWnCBMKYzJTMMQRi4/pr2miZgPah8cjUGT5EpbLqlPD4j1nfNdnFt31jy9CFocWrq06ev5pftSPOXXiM8reNd5K52LfGjdvsQ/sQdPx3BkWx1Bb7g9tk9ZaU1xFUwXpKdy5/TYRUkJbSJ6DJck7JkwcpGws1WnVjAgHLqRJ6FICwxe8NOAP3mMUc2HF4JWQgQxd8iJ494bw+1A3irBnKU+MnfOEGymbV8QdDBWZWZJBP8UkEtzAEwjOsrUotmn/DwZMp5nLJI9jT77qou6SeRqeXb85QOrzxFrZcpmOx6K96ipNtdr1cZCtmkwS1vFOspmJYSmQSK+0LO+COMU2kpQj6tlln8Za3HvRL9+npdT40iRk9hPKFP43fxZjaSj9tu+2zUYXqX9V/xJr+MP9qs/5asN0plX/k/+qahaqxvRKujhWstr1i4E+ijnyqrk+hZp4KH34zEJZPP4tadJaE3zSh3Ht3/J4Nn7N5sJ/dcjrbN748uwhD2rsAYI7Lgyca+FMVuc0l0EUieBX/O3DSvD70nhTEDPz+byJadJASrKkKKD2emjjqn5uPC7XiUp9SeR94e5mpOcWgM05pmJcEt7+g3e2n0Cn9d2mSALZkos+6pqfHumEiUhIa7aXaAS5UbLZEaqeNaBxROy4ChEG7lUe1TyjOiA4+DE1xQ/09PVD/FHdouWOFLqSQVUKdkKwqJNetyIjfMbjDGXxodVr/Ccr2I4PrnO6HEqeERKtHna41+4qnBRzrerod66YXhcsnIjQA5I0uL7AaoxpFPdQBKeortVaZlyYFFFC/83EDZ7ihyoAMIsoqJTKoQnLganE1fDkMuVUDIEYvD4bFen91KAV2pa+epVLrLcCu5xnv7wWrWx68s9TbsaiaMdfeNKD4+AWkHydG3u08XHSwvfclMAUDThEeIwcD3/VgdN1bJAt3d4Tp+Y6B+XhZ70f9b0dgsOrbg1SFjfQF7Ot6eiynysijhrDTWKpR1kHdkLK+NN9oKMsH/Fy6rkyTsR8ZzCoISoUlJqMwDL9HBV/C77+k3Z1HVVLn3aUp3kXhBt4ehs0X3xMs+F8L059kzYZVrSF3UrF4dTiYu08gHH8VjEGROGR222qA1LWKihWCDbbwTvqlgYpFxphXXTeH5UZXoc1A+/+CH+Y9DUlELpVJizQKQG+7tuHJ0YDICLi1Gtr51QPzAFyxgutSmrXRZgWJ1fZrO9L+qzMNHxpA9lkpEbvIZLKc7rzWfcjqOmlfW0E0OqJA3FeXUV1/byDSWeHGYAoxXRWhjNzo9oGw06tFx5rRIW8l4jWjUHpUoTd4YCAaKS34tGj5VJL8Vf1LsG4PPvYAvvK3ojt1dUeYscaD4kcyn22uHPCihkNR+c+GlOJwvncvYUxy/uBeysgVYIuai2XrOjtl65uRIqQJAeGXWtdUXGTPt+jIjUAnSG6YEvlqqw4jYCeQcPw/nAzGeedX8vi9G9HHdvW2H6JkOpzngn9dTbbUyZN1BTaL2QpcdeZ9r3SGJQBYoZBFDGp2GPQOHd9GObbYbYMt8vh8UK1RA+LQb7lFXppGX8HVeLSAxz8RHbTyeXaVQRdpVtgMCH1z9Nk2WG52ugBjgslldQagId9sv5Nxd+KjOrgOefZ+O+1g/D0wKc9IjI/3y5mGqEJVAYL5DY06p85Pn+55ts0sL7A5XVAS5HTZpNUhODFnMk2ItTeaNaOLCoUznR3BYP9Ih6q5ERo73GdJvvCGbyhTKCutoLaxQQvbxWYa3SJJkNAtZpr46RCwEiNJHfxprnPnnHkCrHeEUl2qtXmQ3xOqzYjB113e2Ggdn8FHqhN+Lzg2bcOjWem1O7wWPV7/7HbcC+yIBdSoUlXQbUGbocwBnu7mVDc13P3dLw8Efkjb8Mp0NJg1o+9/ztlnvCkdvtirOi9FA1UopCGVkucwK+QqvlcsEbr8QrXcyeJbRWI+YFcdW73tTmowdxZoa872xMxcVD1NUMdNzoz/Qf18ls5Nzl2+UWSnV13GDJ7d/dcBTmq+s8CxRW+837Wzrvzo+AmVJ/Y2j7L18htLjYsbIVqnGyqQpEJozm6x2CuRVDldkkqvRCweeRkNQlLOjjyJpLJIXOKbNtsetPfIikvEoyC9TdhTVNwltiV9ybjVTB5HDH3HVImUPqUo34HGBDEJnES0G51wL/Fr99cJWZvewG8SZmIpVwgpxN8o1MvEFMLppJnd1NNEHFdSswn4zd6pFGTiiFdwq8/bc+y43geUK0QcT1K9CfjV0akQZuKIp3HznuCeT+/0F9kJ7w4un9rsNrk9M5fFximmOw56rCDu2OGS89kqLpzFH0v5jchJmng5a/2xjHW+MlfwNunPbs6TL4wRsRTRmtUIIjk60rPJjyqzFeAUZoNKB1r3O3IHVY6gkO0juBzyp3quBc8pHSGhyRQWS4t0jK4tPsayeTXRA/lVkh3+WXx3lX+mcDkchEUrPgor3ImBmdLdCe8q3PEwQnBXIC8J4M2Ub2aHm8/l/D0nxMzeNG1TQQW6Ik3/6rumZOJshDuZ/lwwkl/IHyl4zpjERYT3W8qojYfTDm3qob6tIPE4HDOJ0Uif/JDUnk2H0g5vHEWpQvCtsKcVjbcndRIoapoF3BkAktGevwY8CZPlsIgZMpsth41yBfTg8FYYpDCDbWAzwqTVRfNhbD4vxcnZ4DQw4eRysBqF/aZL+BElk8ElbL0oSBB91/UtS/Mbl9D7Q+KfXkD0hibVOJTxGK5ZKJVms1DHe11H2PlPeS0P3vxZ0fCaXhsYp2JbBN/lzTaNu9LxovMGm8Hv3rctgam+qVK9WPZPHVIrwmp8JyMhlRoEAawD24bN7k2KrgyVrGtrK1m/MhgtXxEk4b3XrQhF9YWjIWBsoaHwzu/TCp8OaXFTYbCpJBxsLJRbJHELtxtJgltCi+A7AdX30I8BZZInPHVYpYrq9KoystWP1jK9ThX1ColBAQfmZnE5sNgkFkE+h2+3xNk+7tUIeXheTjROiogEXokUO5iUlTSIlap2bpA/jIjuiMLHH0iyC8A+FNBnyBZPGhZAB/oXC03frtqG5Ro6KYmcKs/ZUiRWzhCoPHKbLY9bzKL/vGXxA4sg32S3GHeaog7u0ewkwl0SewNJ+23I4a9AEBtyIC+7QrhZYBJsFgoOS44pwoMWidtHPDIZcNookbo8Dp/30xtC7WRy+wnyO4OfOtaZX+DEff4QxixMnynDW+eyYsMdY3xjY4015mLFhh5460xZekIn40I/MnPWFMOc3K2TR4secKT+C4/ZXDaFV5p2JvQX9rtYtsuDNvQg1nypI5i04RGrT/J5EYUgrsRqWkSspWknkKChoGIi3m90X/0K/OoqqobLxF0DryX4V7qHdjSEer8sj1O558rWbFhmiAkpIW+1+2T68cyszON0xs7bpXfSe5+jhMyutp18Sn1Y3vjaJ1uQkjMJG5LC2LtCMpdO2vDM5O0m4ZsBYIQwTzgCuNaekOmBvpgPXkuQjeJDWcvr6j42Nb1LtXI41nq3WR/31vLC9vETs3hWHWy2Llx36+6HUi/tgJvCyVXz2zuq55UkN8ENN3xm7z9f8sB5tXOzVviLzbd3/q5VBPgzeOClk/ixJRMC1nU9PZLTD5wSXYRhBSvMHDBkMfsqy7HuYQAmR5qDAYYluyvLvdYwHDLz3WZbGVeScrx2McnNT8khRmDb+gyAZ1KX16vsnnpD5pOZDlG+2WVzsNPNa7+HvyXEYjXC8HXMSIrLb+pOrE7svty5/tKWU2zqqZuiC2ACV2wjz+TQ96y9HwFSwjK+U5Gf72sUObztBbKL0xCVwenRi5i/7pxVaksNy7h2lckQaZbS4hftW1y0eB+wrxI9Zg1ay/foMNt10Yc9KzaDZFZ8U2ho38mrJ1/PHA9C1PKkGRj2uoxnN0k5Z/hE79IZdZA3v/5eXfVSDgudM/vqzYDaz8YE41R3/BxdYVkRLJeCVUxHvTR/QC+7V/ROE9XDeiv3DhAXfOFlKa0VZsWS/Q0pzUz1RK2Ilf7XwJ0gUGI2oxfTl8gTSVXUvNvpZO7b3bNzrmRlLEjDLVt+MNlSmdi4sGvCmMWcKc8TPPmrXG3ihSVR3cT6AgCut+R3ud2W02GBZRbFE9kqqPF9Yf59SPbAKowdfz8blz1O8IIBS6xSBvRCoBOQ1CrZh18Y54VnJscM7UFmy7vBeTlfWIumEcL5i9Ysnp1wxOiO74t0ECPqPD6c8+38rAXs4mn6Em3stHVVYyRpefPnsslUQaMuNj+VYsnWzXPncp+C+WP6zCB3UYCnGF+txbJUvi1rlW50HFJpBMEas7rd+XtHttwmco7prWN9I9Quc1UWI4Ziwb2Ktc+4EgGXfHbW3dkWSpMUrHD7YzAHrQ7qkNuX6uvuAgwsb6jQQJDl9Nsj2Cjh7/2TxFpiv+VIKwBkyNAun3LR/fuKtf7iH3UXgrUDfzpDDwEn8E/Iub0tZV/JSVtg3KzwxSeD7UWFsryphZgORP9Z2+LyVcGp9HvNXt5i8qB+m22eDVVhFUEiT1/cB1QaWVORudIUPwfCMxZIt8FKs/wQu+vl5CN9ZjxLv4TawE4zv2DLxhs/23EIjiNVzpmLRkY51pJTSdqvO7SjoftNScr7flvOtu/zetrGN3Y3tE2w7EcGkUVfLuaOCht90NvF782jyKlz79GgTUO+C38HNGmpy1kt+X4pWMrEIvyAikNYJ6wuqLq0zNqu225LoRqnXMCTWWQ8QfCvuwzQjpO3JMeFS5R19dGC6mz1OHmadmrjEC43joij0mWjiw68NJgsBqlAaVlb6SR10rhsTxaawCeTRt9Yn3BdpnHIRMwfXqLwuVyZR2fJ/577x825dHZlXhypiS1SJNsN9s+VG/8rfqORak6dRk89RaEPyA8m9aFv6uhKyKDOd8Kg6kzOF3dG0NkIBUMtYhP/2KFOuUg5ZAUcbkAlDFsAFAKKvIEfpV+fYikAgyrfDX0qNdIxjKkM+mIGhr6Es8YOLDX9D1SPSlOmHbfCDoOYeYGL/sFFEYAKkwlUCCiuH9CaE0yxwwD9xCASEglEBp0/VOXTdrJbcpNzW9isicOiExlGiUoQNlszEaAyj8N72UqrSalxg+k2Dve8TsY0elyZEHdhTmCAnQkKlskelZjsZPx+lpRgR02BdRtOJoy9FjUD6p6TgJkugXEucyfIHE+uu0t89s2lS8+Lg4upmMon4JOnQ10cXO/z5M+wCbfWXUP0v5qQlJK2+3H89d/pyJf+/5v96nfV2glgDki41EQYg8fi30Findu4LrIDuAyP1fea1uQj27OZduq101Xum/e61gUnu+c5J2mPBQUFVM9fNNpfHirN6G9rjJmKiFnEx7nB7xeGMEBYlYVlFPTolB31qKz0pKxVKcv+UhxTYY9h8y8ZrhcYXilP9Zm1d4FedMrYwv70qGDpyIm3tA3c7YRVeCx+FYE4C3/MsxLia8JNa+KQ7UtY9Z6+KxJhYQc6HIimHuWZ41+5cx+DOeDTlZsbxssuwgnbw5j8LxNm45Pxs5lq7Dp37LpIkkC4vkSUd0li/nN6UurGrasrLhA8gO9aPAzQLIRTCfG1qFa7y5i+K3IaJ+aNrtkl54knfLXys9TsjMD4R86Dw3cgJ9Aa7n3IgWv37HrkAw8M7Zx3z7OveLSHs+DTW77xDQOcvOR8+Isw7FyUfqAKJR86AK10YKH0SCTWbCgZbAF1RAJwvLYinbY6S49g8lZSnaOnX5HYu/plkGu55Hf1MVBAwcWGkinbFrY5dUL73s37kN5Or6e30m+5Bp3dfKW30+vc8uMMlt/s4PS285vOG3ZrPtRf+DYFz71leju9nt7iGmHZzU96O73OLcKzmzeuo4h3JmUh98/zd81pVH93J/80MO45e6cms5D7h7to4p3XZSH3D3dZ2v77KmLineEs5P5J7/I38fHO/Czk/uEuCe07/3R3GawqiVEfmRshzSrv8t08VuEj/aprf9m+tut2k1tT7VIvPgBJBU5v+M3b0O/qfwBHPWDz+L7coZhnFXgERgcWn0e/XBAXcqjclh4Pc5fFx8bPaekX6jzLaO+K5oiLGWWh8ctv3r0gHlUGLY+XYgTd1kZe+r3yMdGJl/TqJtbiFTGG6scAvRyi9MobDuDXtvL7sZi5tstbB0TnDh5wz2xBzF9xUVPeQA7RorxnyeWXOI6zd7cDOdGJ0ituCvJA/oOeD4aBclt1GLb1ZZNgV1ZMI9hxSxm0Yba5NhT2v+W0sAW7rzcOCUvUrclWNMSDDSEpD3lTNc3K3CHakPX/zHBRiIDVcEgX9Vt7Jol0MCjbZaq7VTvKIIyA9PDMLX3vIar1cWPvEZpob1++h6nZ/va+Le2zrcLmBZj+EL/7+8c2JAm+4KTvxaG7HJqVrKwubBcS9vKFhC8ktXI69Za7HaFMh1CWk9Zh+rbbhJDH3qTNaTwdAyzopbi9nMNqpGz0MTXUwlKF5kpY0eMRS+WO0Lxwc70Fvpj1pMOuIOUPA40WaVJ+snsSk7ZErKpvK/svr7n6yu5SU2qz5UwPodjimBoz47GWuTKMwbKYWqwu8RjBeisOOPsWDX78cbdDHX3j5vHxjz902aCqdHQsg2LkjoPQeJX5qxS/o81ZdH3dtmPilf6HH0alcWABw5m3vvRfMY5q7kYvBFEZJDCpdDddMkvsFupqzyl1YRlRv8oXgZQwgYmYBgwjvW6Rj4bOpBijGD0LOkzTUC2ryhtKa6lFI5yFmIhJTHnJM9YxYzfCq3Dkxu2d7o+9Wsg6JzenpDtSKM8LF7HkUM9ZjRpIeTaOAi2uApcddhOoGB354rhUM/BgO+6ILWbKxcHgqGRM1AmGw1Yw3eJwYkFsjOili20/g0OXkgqFB5CqicQ1jFULl7NUu3Tk+hoxVX2XrAzY5VqufZwqRstr0mQSGYoxPswhROdsJOmOMjNSxgVGSsXWdo7Gpg6OF4EIWgilk7lu0FJ2Z8hsa839rfJrTBfDyyFfDWkYq6VaWoA5JDV+w9PpMKD8G6E9xioR91sB15Rc3sx55ujqyG6F/7E455VXTL4wTes0941j08J6nWO6+lDihP7u4qau7WEMq8XMJvBJU2ZgmzxZlbuG9MzQ7YWuUJJZSWW+r5NFSd3cCJRiy97Vs1NKc65lv01Hb0GlQ8FZ7lEjgGHvIAWQR7PcJpJWZWTO0uSbAY2Leh7HEEYzYlW96ao4OO0Pq6glS1ZTeol+FPk8XkReB02P4ul1xVhVIsO26QHnLz6Zwg0nlKQKo/eo997JFcn5AWgF6Oc4yboGt+AfgADu9KQaLdZMmCKOvTLjoe8gh8z97rnjcDmfPqKxvRUmpbSA0tgMYd0QuDTwmzlASHpdaCj2QvPKamB9kikuBCIO9oBV6KyufpDPHCslCOxlAhMlDLbl6ZLOsZxLFPQCodfGsFKWOTRxUc/sPs1jBkOQg8m8gMNRA9s0SX/KRLucWvTc0KP+bwPXhvrP3zGt9Hc/gZ4beN5f9Nwbz9ZLUmq7y8JP25XRjoUEFkbGKEQIcPSorsWxw1Cfn4Mn68UihRO4y0nZHVZcy2GzVMRQN9a6od0m92dgIPdPH9DWeNJBuX+hlBCajBL6X5lN1dg73nT1UMN1TaZnpxHODk9Zndipi8vFYUAtybL1bd0oLfRSoR8vcutFTrO8aabO7Zix3cVB1ur5ubUsa96z+fxezdiHly+co8vNubem8Fp19GWFMhry+lH3ERC9ooPWu+i8Wumff54OVfUCfzhEWsPXrrD267bChAfJJIwv8g0T+lsjsf1O0W2oaOaDBcKDHxG3NiLJ2i+O5mkArftZ1rbAqDegetr8WuKyp8EXgrSuRCG+7FcJw4RIVJZHE7it+8craIm1zqHTJfsIdL2RvPwGTjOALVHq9x6msUOH9vmyBONTCXnL0aSY2OtZ6XdaCoySUXW6tAbcn3jTLLXqi06hayhHV1KUk5NMgAAREsTfsW6F67vng2HCsWbJF/ubs/0e7s/oEEmK+1dRmxPVIMZK8GrU+ChijX8XBv3H8Rey/V0+HNFRV+WkXa8rIuunygpxSUIrJAu9tudKiFRzX4rM6D0/1+lxd2NuKtO23NuuMhsgNdOsi1SrVLbfNzuOR9cdmyY7rlaczWUj3sEhSf2X2LrcM+T198Vsikd0yBrqvCMjhCSaoiSLl0WOxfLfJJP0fpe1KOF0KToxiMlzcSPWQjQiSbzjDQzh/qxCDtKJnhQsROMmIKCLIidb743SyN1fDbCZpjKhS3mXS3qrq6Lvz8xaw3FRuBuLBR6E2T8IlAOFUBnWWlbwRfrSoFLJTO/LYjX/kxpFwqKI60KfBtAV0AXoVVZPy30fhBUSB82OlvyL3BhJKQlZeeCpCcmGt5rrNx5PpYQyBMJ3lTZIrHRim0cLuIjg9kNT0TcobUy+NQr5bg75vCy3YKKUpDnvygZoIU7AiQR4RYLuNHSp6zpZt2rIFt4SDiRxzhJxRwobYCg4w8aITsZjva5zP6dqUSzAPMuSYMCjJOETKn7Vaep7DG4hPKr8FZ5K35MvbR5MMSeihVfqbHZxcaaoep37qJBGb8bj8WnitDiPlD8uR7V3mtV2DJEJVuIa2EkdaTG7YVno5V2f1aG5luv39OpFe2uumgdvlv7yizVZRN8F9MJQb14YmPvFWy7rNe/w6mGhrUP9gp9NyruThZLuinXpi2nQ9Yn9UmX7paXD/V5rxQxeOshAGF/4jB6NlXvMi6xW+N6FhMRHzssFrWwWDR7jpqzqa9hIbvtT864wSjEM0zI+9SMhzuMQ0ILloaJ7WRe67O2kpZ3PfsEsadtO+11CivPNBUaxow54TWfP7m92pbtcg7S+ucvzxs19vBR27hHYykjZwmu9NClHMBiO9rQDhb3kt3hSN8VGdF2KxTtNuEwyu7Acu6HRxZLUWBgf445OTJywltDdUnp21K5uJcbKVrCNsJml6t2zKdtExnHWt7+hYl1+KWnr/DyKmMHLa1JetqVTw24OZ5MsHvEp8xrSS/AjYjfWnW465wtW75K50zYcHHWaxVcx+0sN88NkexV1vAMdbwMttiu3xeGk0wFmA2bbXEcDwEXOl3SKBv9u0BVit8InNpKpXMaH5IsMJcsRSG7cCxOj4iUvOMtyzeia3TL+QSLXSylxVij4MUl6gahHHyKW0gm3zSbRm9M4d/214ZHGAhozJCUPYYoDirFEUovk12v1B05ELtoRfa1EWRECkhMqHV174oBmpjKDySC4Z7y1LpRF58d0s1lv7pL2mxcbeLypvWWePA9LdtP6nw4WZk+VFyYlIRSlThA107utUM5y1wxjuBnksomIhdQ3NSQE8+K/fJEvs8h55I4AQzOmRovLWZ+EpuRiyglutTIYuL3Rug0O2cdUCh1H6R1A4rdK/R9/Fa+iiHFeSLutRmdLpqbQmF8zMX8iwPwJW60Xx5fHYnUMnxRifs3w4E47ehBZK1rTVmUg5k8QzK8CMA+5VbatDjrgTzIxv0bL+WALK6CEHwBLDJ2WRJJEwfIea+c+1480a/056BS0CegcCPTjaRx7cxrFTfc0i9FLgC4Ne041Rt2JZ8e9H5lkgN4mFI1kDcE50aVhPct9hGWmfMXAwMDxIHhIJBRwvukSWWbXQZUsR9eyUyfGU+7ZS+ANU3pAn7DB1lDv6idCACDUT156Cwf2lu2vFjBX5tplk9JIDXHxkwrxvf6wtXTZ0sKNozvDzljP8sLuN9+xD1z95KPfjoCJ78CceHgPcUZaxCGcSjoXLLPLkOTVHGGtuH5lxDRb2wmTK0TAGlsit5V1p1p0Yh8xsGf29SW5k/VQFOxET9arSOfaQbfJPPVfBHuAgr2H38eCMGHQfyG6RiSNrBu1tvmRZD19GPJDwRPiJG51GQP7iD1kP99qBXrAp/WoG6nvu4WEld/7/NAxmhw5bBn1bddBZI/YBevnv0FrxGstKS9PKN2WuDW33pEmapDndV0U1oAbF1Q5nMZMALF0w/7/4AICQGCAX7ESAPAbAEj4Cte0AxwlMVBBuarcXq7VO3m1dbXHalPmvz23/qD6rgM2VjUOnVcnd5FmbnNcc9t9df9/0Na8J/KMPGfzTvuzxLrEKf4tP4SWuTriw6QVgYu3kfwz7E1eia+nXqP+LHmFvW9dAgX9Mv1XKfeFHOePcKdiP3Y6dW96PO3f/RWfhzbM4KPpTelj0rdnDzOb2I+zg5y/fnhgeG/j18b1xioewvMSQrg7Y3fOCUfiq5mTM5flMdksmkM344P4CvyrI/UtU/pUTh39c/aLY33l3y2fChu7ak99jXCs7VKLtEgbzUGJCHE08UviLeLfucm5qtyy3Jbcn/JEeX15t0nNpK2kF2QUOZ1MIYvIerKD/JzSRPmD8ozygYqlEqh8qoYKUxFqNXUsdSZ1OXUjdT/1FE1NA2nX6D76JvoB+mn6JfrP9If014w4RiaDzpAyTAw3YzLjDRNgeplR5gjmWOZM5nLmRuZ+5inmReZPzAfMVywMawJrDutPNp0tZZvYbnaE3cjeyr7DSeDYONs4Z7h4bj23j/uW5+bN4e3mPeZ7+C38AUGSgCtYI3gu+PQ+oZAktAu7hAeEp0UoESwKi0aKpovWiH4T48Q0ca24RTxKPFk8S7xYfEj8k4Qt6ZCckLyTmqR+aa10ovRr6T2ZXDZRVumn/3uPB9CnogAPjUCDEvUS547yse8g7yL0u1nooZ9o9V8FdaLWhmPy78jaLloaIblu+VElz09yDK3TcEcAYbFLPN7ZnskFGxvXEDDGtS7b/vzbqPLiKZWFNLC5pI5UII0FKF19V32owHqo1xnFnyfHjFO3odCMsiwKi8g4zZKbWvbY3EAs8FvE7hmuaVR4Un1tAHgr3iim5WOCxFOo86SyWQYDZfibIlyh4nZ7Vem6NfS2KKRMAoIX3mssjimqrVEKhZ6Y6l3p92jR9UfGdAfbtz4DxBj5QLbjfp8p9CLViqYtAHpuyy5dxb1UL36CVVelRaFA0kW8yCrmijmLTu5K71uk8GYZcYr1/Uv+ABgYOYPIuD+u6paWDAGGHl3pvdgUL5fsvpdNGd7uFcATnt082SHx6bgndxERrajb7PX7kyCM+b183p+HaayjDkY6KnIwqGFi5NBa7gq+l0d35dTja+dpWa5BHg1nW+20HXk1F83leHY45DZ3jAtPiYfzsZJWHTApSLRCW7Q3I4cS8mskl9lmdyWbhseaGNBBV/REzc4qXC01fZcB3vg1uvjRI6ybyRgsMZVt5eaqmnVflCj8BKusJas3ODnsMRpWpTweoiP5Kdmbp8KqmPngCK8D3EcFQrlU0SrQVVVKs7897rpy+dA7Cu/jwoSeOXhcR8nFmYNHGicXcJu5MA27CK1ZjFzRqHIyHKBLzYotlJvuWxxI5TtsadwHfo5UcIBnLxwRaEQBBthXlL257zvlMCzmqAEGKWRtaCjiUJWLhLIYs4IN0pvu97JwAuyoHiGUCUnCcJHntaCzC6F4tArMO1jCHEf3a1MChg3auRdgngOEhAhBhM4CQaH+/8v6ob6/Nrf5wWzMAK6vhNwbz4GNq+a9uVhTt/rxokH5KhqnIu5Bye9Cxn7sy6q4VFxWda48ReGhEmjbEwiNe09ZiXa9zCg4CRKs6JTiM2u9XW+hG7/FyE8H5c8P3e6RWEDG6X4PCaerbhgF93FPVaMKIZgFMqu1YlCKWtsJUKl/AJ0kT9TjXFlAhS4VraFcRGJuT2O9No+3krvZiFrUnrw3w8kqN5YqkxeqM3nCVGmjIl15GCOfsFJQaBJ2oCg1NgoSvlKvFxrbaNbi4jqOp/ks8wKJ5yFXamZr4BkSrLmXAliQg7kEYnGP7pSxjeKvch/xNmglpHIGVhwlVw5PmQKhtKP7oqj5kRcZ1Y7EVDXtg4TQ7fpCeROMUzzwu3EWDtvN7sh2oFNGlMbALCrIk8WqDpUhdCO4wGACMh7YxZ3bBMBFRHqNuT0lBL79yHsD9MhMkkOHBuBOFqfilSFsI+gHbwT3RFTCWsfzztkU2CJQXrPakY6g+woYGiBloj5QWmU00x5AH83iTYqoybSfBBmuzaQqgCqJDWMnvawLK4exAPSVBYhwn/pKsb18lGf9PG+fZchaQ2MlZEApZY9+v+kCgE4ED7yRA9cTspSvtJ5fJQe41OwrFKsTqB4zPfLBJmw6fD8e5DwIRr3A0nPAx6nN1od8JMGqYti/AjRrNaGAotdi9q76C4tCKb8TwEkHlf/ng+exo6RB0WL7HoYetwnlZcDvV1Zcjup3YS1z1v6BBlo/3Tm9/kPXo+/elNk2AFS1fumonhV5VGFCdpgyd/Lo4J0a8F8M86BfpVtsO8alvihA8o8sZF0a3CKLkF3uANZVz+L2CnM4pGC+Qy6pDBPQ2Hm/aEwtXWRts0AR/HL1l1TKKiaOZ8T3RVLyEg+Uihu67GRsXqb2KgdWI0opqKoSYlsShkVy92HuDh2u9H3ONM0LyWqLPz4fHJpbyNqdzijrhCWOqdwK/bY4W0w8LV2tAghTikpCmJyaQihb4n6k66HIdSL+8pfVjKwDeZ141r8uEddDPgUNS1aDa0KX+odFLyWQYYHZDEF4dhFSQb40Yy/Nh3uSzSc1SwMB6r5eUk5XszEg0I/GTMzh+agpzTntb6UhXLPNodJVrlRotir5omK+RgaVqA4QKuSGFRRH0VIHrR/eGDOXz3fVqdpufSXUwf+LpWCbof26tdv/rRUmOOD0G9nEdAcDzaKUh2i5FGAUvyNtmtW7D2tnCx0kbU4zwywNA9tOku5lHgRbbFTmIGsyxU+Xu6riFhFEuAO6YdvH5SjvTCWlPAdHsh3NyQpuIKhcN1E6j7+ArJ+DE7TslL/f1WGtyBoqqipDGryEMIHuudQM1YgigC6OTsPR4QE2auEQTzGzhBR2R5OE5Y2B5UUYQIX2ACXXJ1o8anAA/jIDcTHuylo0vlvwaVwAayNU83Zm8KJ87kxM3ZQZhx2WGkTgm+JPD99SQTim8ehnzl5vYEBXncZs757btIitspjSy87PHVLEL7HdURqcfkG4XB8vivxhcngDeyXQXv8zLuYxedUKBKSQuuVJ3bB4VrolfqX8EQ702iMJkGHkvVKNoowYZuPbvQfFOWyWhQLxEYJhiI8a79OweWrgfYupT8M4Yqove++TFNujzvZAAMJhCn8oZP+4wFkkfw56yFDw/zfP/vk/N8KDT7detlUDbT8FnafnQuXzzeYsLtMJMpB9K5SHKj9qz0N3yd24Da0118uNVsRgFSgwouDf3/Z+1L3LWOy5DjD0lePicWbZJPvALBAZ8gMePCnwW0Nwy+atUBk+GMwEd56cq4lfHCn2lthKfavCdh1rteNS+a7LRjME+OZWxvbJEhxOxmH5tk3bfnmd5ikmfAPMvk2xpbzPl7UNyaQ71913YB9//9bzHwab8Thb5fzkXUBBk9LgfKIVsXE4dob89IcfDDSt3bnNoee5l+sLlc5L+LYCPKyu4TxoUbGxtndc/kuJBEgTaQuGgbR/3RCzLwYP7I3/+tkz5Z6jTn8OVp+qHbM2Pqieojb9hrpSDwoo3/LkJxj4MTfw94XMi1qnCrqIEUahst0XR1sLKVk+O37i2g+Xv8Q1GYLLoPWuEQxeAfvHN89+nHg/t7TYrIND9yLRqIRBTJML2Gu1XKPZHIotLZew0lGB3cAvgsU5+oNNxFMDvg4peBEH6Ubi0vgJjBomtdnvuvklfFPtbKlRnhcHG+SS73IG34JQtrxAGw7FyiyZ82XpMiK60DKczRTARdsWAh+MNQDC3lgYleQ2mJaCy9rXtJt9cqxOty61bm7meBigMwPQDR2VrIXINfbQCmY3BLtF13GuZUKQ41pAhNM4g9Qj/RFKP2mqrjD17qjfHEgZWFLpOKHpx+daVpheRWAq4uv4HXoTWJg4XdnLdefvxhkqEoDw6j0MQwwd5rfdGrorTgPb08pPiftArD9k1z+BFG8kbQGCUWiHWqtTJ4eX8k49VPQHhmuLIdDP0eDhkVFwuRBovxmwuzdoCssd+fXVbMKQKlK3GAYRvkrm3nLRpkMrctspwg5Wl+eH9eccZUW+0ab2AjpSRMr+mk5T944r/blXEbsKUF2eHTLPaSti1wcK/p6vyhGHrGpTgqOrFm7o3Ohtsks6bcbVapp+pradnoFXIsCF/L0nlhODCImbbPVoNpJGM1dN9G+vA9qk2NFPZl+s8nnE0lTIEsc0LDXUjpdPw3F2lSSTyqU/CEnWx1WgYOSoZLGgjbHJy6L4+/ZM2ssMsB5cvFrfIM+Kb9AeZgrcnXCx+HfY/xpz6VNNMMWQCx3d0nj0u0EMjgHtqOjOJtvCx656NKh0bAYDmifFI/3Ebl+172cE+BDkefV5sQ3dyWv50blq5QRvj36BONyZUVCLtRrXJJz0hbzIlVezBolL9ebtUs/CW/JjIGsyqYyrQ9Uw7GULmUfnXUh1rn1g46fmHvbzCGyIN3jsZ+AlZIu1RERtV3oFGDbGtzY9rk6NcnDDoD2m6m0jFOo88C6vAF8iUSQOJA6Rwe7Pq7jC7GDpkzEyV9heMwRCwkNz6H4tPMwPtI4m31DEXi/1j63XBBGuxadf5TTxDA8U06CXfF+zQc7velDeVCh+kWhwyZK250F9G3NUJruhF3653OnDR+bOf/v7Ozt7s/Iou3jWnfEe9hNUNziWejLzquJ0JOLqFfdu3nxqNyMJq/EV8nhjPnqzAcC30X/Xrt0Yf9bWVj/DFeywm2nGXB0EZVnq9DQnTFCoaWJpPW3cTDQcAFFWhmAclwgGHyr0/aG3YPkVvPOpfBP82kC/W5GmCGxKiHIwsxzNYjj961LrZzhoXzVo80/mZ+7F/riEEPgEvPaqJdbquH0WV2zzMQtbi+UJpVC60PkJw6gBYgSW/lyuKNO+J1Wq4D+87RCuPaTQz+t816/b9+Z50dnSWFwKO7MRdUJ/KHmsylZEKwD9dqsf+3DQsnGxfS1axEirXlx4RBhha/+3a61gwwcyEZV331fq9Sa3CTwmxlv3u6y8e9B+by8IM7uNtd/opuU78UCW3k2dh6+b3+bWeCEnNpYqStN4of2+YSxJ72mggXbQ++lyH1iedecu+Aj6F/0cFBjkH0pEwX4QWXnT7nu9e8Twctz7edblawV/TP6yIXAxeDtFrQnHRsV6f2z3m4ByVHCHc6LRr1Y9AsOipRVb2sGEhdgnamPWZGHnf2z52NDpoyRn+MBQN3o/tW4M6ol1wtR1taGzNosdczCcyyl7VDEzbXvwBbw8PCzkRl+wG6h0plboMY1b1rF3dDcEZXcrvAaqokLTiTtsrIEUk6OLa9kiQS7Vp8hUOypmQRE7tveT4wxrkDTtLb117KiQYbMhsAK7nyJ/J3JFNRSF+wLIsZw9wWRr9E3wSiW5mzjr/SRJ203xQBG/TFq8MELrJ/TGg4/Wr/XX0OJ3vJGUMe8mUVI270MSFSsWpnjjtMaTpKQUea0FY9hd1O6iSswmdriIroofeOC/BeEPcO73mvOA7H0EfRvx21vnP9wJt6/JF11VntK7IH4yFi8uwn/ZQATR+suxmvv9Tsro0R/BVMsLx8mnlCgrNNtqRrlgcHDB1OlbMTCwoBfVAsMtvdmFHxJhI5eXmei1y+XuN3X240hSyqPJLTF9vyLoPXBYBL0LDHtH7X+fGSwygPxlJMThX/oFrr9+/tZ+ofA/WIFAR15v5dcNzyeHk15h3ncZu29uAt+oyiJYxAgs7btiJPmiZuZQVHy96B+srIImScAx8/srgFUeeLen33FpW6+ujln4Q4wbuw7d5bAu3B0mEVsgC9XTV0TZt4H8azoqf5+2Hs49bvd74LwFDK3BEde1irgKvKBMowzp+2e1gAL/jW8D1Cwh2c6QY8UlzwH/FOixpBTj09yFBj4lTlTUb7cSjnqhG4QNgRiaGsLA31stTY+Bc2/H4zHJlWxb7lWLdr11w+X1sSzq9+aFhFzkesO+TndNZ+f04v/j84TUFusDS+Y2ZvOrSKGhxoztzl7Z/vKXac/Jcvdr178/O7s6hlEYp6FXFD39fN4qXq4We+qhGJKwpSGvVUrvkx/ALn45wUTuLCc5PRd3RGyYfTEwXX9lqofzl2o26yavT62JeTKfQuaMLAq+1D39R7FlcrNqHVRq9SSl0JPaeq2xFDmh9BEH1KJ25YgzUHpVreFVxB5JIM1pnaJ8P8lotWi5O7ZpXG7bnpxBNBYmcW5zQYaNg/KnZcFiO6ncRpnKdkofnFHcTrKfnl+HMuic72jFET5cb/Nx18Zmx8ta5J31IK7vR6FbrTGsSQh+iLN8uQXxRjqJpWoaskHToygzQmI7BM6FUbBVDZpRgpX7/KCLatBWuTsbEDJF5oIvQHZ1rr9r4syCfv5g96GvLN8axTEAa8sJC2f8S+/OE/6vDeFvzfghSM1/9/9vC3eqD2CW1o1Bpw+5SGakqoMh0o7kf4jP0SDCr+DV0twTFRhty1dpTtZcORDRWoyy222cYC729DcE6nCmVOhA4JhA00yHap0Cr1a2vcdTcDnBH64InK1jaQmjDx+y1PS3mEQ8R9M4u33IjcPa5dxlLPIZB1FEzQHbNEL9kDNaR0KtVlfpmAj6jKJFtdWXYq1BGbqtBFppQprOp34YF3jMqFbEC5MFvmidMY1+mD3CFllDFx7V0LzYv5UOIGVEqMUQed/9koTbzlrBf3/dddQ0mhQLTUMl8b1WoAcL0oiQ1GiDx31W9SypPUqs41gUrFlc2QZPHg0HO9jbfldF9X4IGAbJD/jL33Ka3BYO5PVXt35/R+sIh627wBVa0WbwFOo6oQa6LsGIAC9TRRHiSUwBhQ+lCC5MMgAHdyQElwsXSuQNGYgG7I70H/M+GIcxTKEfphtmYCQL1lP3FuOZDKxZOIvHO1/CU+MiQTJKhcyBDjpvn9SYwuDBLH3w+IFUwKVTCnB46UR8sfGgzgDnI2/owyuME3fnE6VGN3vBppSNElx2aXSrw0fgRIuZTFIbktaTTdB961yWtTpt32zoimohEIS3Ly7jwVy1wlXK+SBCYJlIrQxZGcWj5raqcKxPevQ6Fokd5FyLsUl/QG7O+kVFKtpXoSEdUKmaoSv/eeWzXrveVk3dskwqcNY1Q3WS6jKaHk7ljh+i44nsaofgKGZZOGW8IIjsNZgauXF5yhDAmiFb5CtEXY4Gp1KLJWIxC9U9TMA0iSvbh3KdEU02g7dl6eDV1+rdlkCrRV1zfAKnt+7UFNcHT69UavXzYeg3J60L90t+OTUQQm50mSTsUcoYiKbUmsWHIaIExeBycaPlOVs8yNFT9wxWwrVveTl2PC3qfbHeC+81AatJaNakKj/peS6dKqUo6BLhETEm1k7w6snwEM4pvc9vpa1uvxKGaLZhiLuLSjH1SouUscqx9jr81qhAxyjyeS+NfdqiXihbW3h4GGqhFFLfS3Se/zVCZgxcK7Q0LLQsnekgQb3Wx7cmEn4tTqa+1JxNOTZiq10ZI+qSuoWZDCLEM89TZEW1JJoK1ylB7S3XdZyXI1NTU3V4sCG+0Ws1/azcfwB9J+bAwZseBnIMvrAjpF2FCGm5apJEjISox8ch8NFUlkTnwFbvIIWQSdvdbzlRg6tqE+oPbqPRw3xD3uxqk2eS9o9S9W/DIWmlxmFDSxd5DHLw5BNlw0XNIokrnpGI80dSoIzQLePSDqRWEbKOz4NxHEcguJjWeoCKYGpUwQTDDS2p7CFsKx8hkdUcgRpgtCgYOxZGBBIlxDijYVode6Do+t7xEMnAS1+L1WAqRlEOIkEkzCz5v5EzH6F7joDF5aEKuqMFRsSLeAf2hNY6kZFO71+p9FBe6G/s1PlbxiBodALMq13unhAAHfRRsnSDkqXldo01gCVi841vt0+paNs45UkiqZbI+sDu5DYIV20IOttWc+h7aFoyA/25gCLvAL+l3Tki5sCTN2FwakhAWN4Q0+d67cAHf8HRnUOYbGrbUo60DwpPzbQeXPbyZct2HZasyy4x1Ldbp5I7lHzPmrpuWDs4B7CbOm4ZRg21sv4pnCsEPbURDQvfehyNJPz4uFdK4A2Y1xfU4BsqirzwyHYiG8Ctp2K8wyl0sKNZ8qu1htKOZG0mvalvQ9blkTcIRAK1b/cjKioV1akh77Ul3oojJtCbOq6vd1QnQ+eGOllGWO3UBHCBG3PFtGDGyOaeQmA8lO9CBfyGYtzx3LTfn7sNLJCFDn/Y8UY+nRC/reqyy6IG7bT8vPbyaHBXq921ZMXx0nIzrGY/+KvfABaL6ZsD4G+XbQRLIUdh3q5OHftAhTherrUGfpU9ffFj3TSIEBkH72JHr/3HqCLo2sm1yzyQcPMbRgAyzjZmkathvTVdjbJQc6Os8Kz9tQFc7T6teKj8zOsrL/v8AmTYfDoRXhocECrxsdZF7XDfBnRk2DcjO+NAO4Vp9TnMnc7BEoB07KiD3eQd6s8xifncJy3/pqfF3prgSpJLcxp0/XrQLk8PYhBvXfyI4we3G8W2fGsJR8E7B/nBOrWHuNKi9rooQl5eFFvHtLk3y5dyAm7gdCIO8Bu9UQnuvmCw46Ds2r6cjkd4IHmpE+1yOvHhlx/LGvRvgHf5/yi+adhpcTsZD0eH9bM8xhLc5OERoFHAD0yvWxnP5KnDX2gCQQTNOmnVlS2ghu7vgrf/r/ySTfTgd1JHMR4gy6vteqgJcrykoCARJtR7KKe9PbronNI9b30qwougzVpOG4iWlHL+vsXuUmWsVDfknGPrWBkhh2LbD5WBjpeodLY0HiLxClH6sGHEy3zUqVVXlowOioGU1hOJxG5Zp4ArO71dzGGdeNAv5atJKcdKvFgoHgiYJJHwyYT6ds7fKHNJD49zmCmPtZw7sbSeP1/2BvLinvebW8CVI0cOWtROqJZI3duJ6nUg40SlMnYWc+sk4++PLdLVSA+ztCwLFmsIwazIj0iGpZ6qeFZ86wjDTwhdAlMsaI/CyLKtzj9h5Moa0MqN3O1uVO+2BJ7A581R1g/XGi2wFO36HF62coYMcxmO9wXC6SDvWPARLpmWESefiNvEUURL3cg34E1OjS0ecYgSxxuz4WhUJ02RjJXP8n6mQQsh2NYCK9EqOxq9WwQTWCT513ZPYiSKuPVbsLw8OdThCg/MgV/kTRTHGx6rPNjcKg6Y+xGAAEownqyRpeqzJjU+WdO01uZGrdbo/2M1ANUhaTuQsO6KxuGnTP9U1vapXDiOFNNXtW890niGcTqogfNg85p9DJq5xZ8MJ8bEdcgYXKrLH+KCcHEYR4HAuJJ8XA3GOXs4LviMWqPpnn2jSVWzESYCKoiSJAp8H5OFae5ydWcN3QH8iJR4PCcqWCWDFOP3W9+RGnq2VBybw2QfGzVsrV+gGMZHkmz/zcURI5y5uC4E501tk+qPLpCIRK/6GaP6CB7TnlrcPXtPTOf5pkyH/c/vC47DrjLe37nxzMaK/mbltz/sCfr3hfnTDBCL2LntmplgKRa51fcMxk8GTCs7a1Myj6p5Ytz2pxrdyjLoETL8PWI+YahfvbzWLqt9NZjokdrfCLz/e+DbXdC20XxNEbN4XLIthqjebocL0u3urqfPJMtDM4tiZdgHaZsCn7I1CPTF5ebigoYyfnhwsd6Z6VK1eaIf1g1QCFjujExNYXgTIS2Y8IEbE1eIbJknsh1155e1+W5k0Ey3pxH+3HXOCUAZ08U7i9O7wd2ge88FjSJt4Rt+inDWenrirtx4F0Xkta83Vx+BP53qZGrqxzEZJN8huRTS9XTv/AmGmDEBuk/3/ZLhHPDivG11umcn7vDhfELvpOmQj8thKYXKVmqQliUtrs+rFK1xwL/zllTDmNq6temPWuyJGrEBJUgvg4Ze1XRJEJMJOGdUb5QOisPf+eu7rsd91+MEnrTHrmsbugR5PD4wQA8vHv+QPK6cZzSJ8mJpWjZEbCoGimbZXhDI1XRNXNvQVCpVAlsYmU8HWS5UZEmJiG9bDlY2hI7NelGq+8M9UWY1FyrBx55ry0rHspT9RdQfB6WUhuM3d+IJp1MdhIYo6SQKqUd8y8NQU8SMcxF4ru2emDTTGweG5MeO5pceVY4OJREJgmxYBg9pU6yggzFCJAP+qYbOhSq18hI8QcuB82xA04W5/v954rHHfkWNBngFtdbiSTckY7apvzL2Dr+P5l54Q23KwukLI8FW678jkwb9oRpIFiZjkrm0HYWsCNQNs9fUeqZBh0Yr10br7L/qzXbbcKtMRW7cZus95fzXBL0l6/Hyq7sa+A8taAMQ+AQys3enuBNRNnZTQ8xa2WpmSlp1XKcdjVvEDpodFHtyfFqtaXWTvE5mAuxuDgXCk2IOU7bH0kpwnCwx5+mEqozvDUeUZXFfhYd1odXLsy4QRWxQUQHBDAUz0X1j8dFg4oEpC0iLML7LSiCHZLXGLjeeiaoWbuWrXVgC+APemni3KcumeTlv+rnUm8bRg9Qo2LBzt4XmM75CW9Warwsfn82scEx2MYBTTxpCcY8QA049lkNjDRU5RBqYhd42hISkoggJCHWjiDfjbB1dvFuX+aFl3fVxV6frjbZOa4PgZmQYW2HXeTBL+/a5u3jeroX1YnVVoRfYHmuL8w4aqnDl6bGiDXR85VWbTlclIasNhTaMmXzCPIbe7nSNF7yqTsW2vlPmVu9dRKBUJtEcRBVhWbvmlO7SmUR0VavY4sUkQf9tHRW1+87VYdZHInNvfvB1rfwuPfIGye9NRONf7eUELAFMJoD6wwmc4yaexjNr4027je/bZG+3+CC27lIuCwPszrvNqdMtuXS33+FIUmMMvqnMzvah++dLWjvewQRvmyPTYwKzLOKkR2efoCgMdpJkhpL+8baA6jTAJLM0ayq/1P7MQXyFB7KTKktbdotLArWEQD+amQgtQajgF5Eo676ZzT0mCO+/cerApKi8TKvuwnQVQxxCVsyWFTKqyKkhvaizZUdutUMdsFuRHkcLEjdE2N5FvrG9w++ltl4dxWdSdiBEuGnvOxfBDq/lbpJgGIsdx9E95iKpQZ2xyI7x9yIDwCcyMUo/HCJI+nY1EcTfJupgCqaiqjtzqb+x+qs55CzyhHFxhYwP2hUAvRmI6E0C0Rxe/iuxN8mWWRvw03yzyZl2NfKOwKgFWXgfZIZtHNfHgiCoP+z7v4J1hYS4rLxs9kLrCaD5LBOJ7z1fhQiGL6aIn7zyygf/fvzxp7+X5eskh1j3ffALoqxTtZetBt8bjXp8wwpy9Ycjll6pr7fERPAnu9Zljlkffu1yyYbdH0z6T2fgathIpH0+9p/79/e2uh2XXN/qNm/mTfbi3y9mShswYG58EG3kZ2xCTbyR3bHWyD7hTHbSRC6+tSd2ldvIdMYwNzK0HOdO1GOKmbDpkt6mjz1wGViMY8FW719PflL/1wtfKaf//lZ3jSl8GTJtdq28+UM3++D3hCyRqJixZd67aN9eYcIWJdRX2QNytjbCcAz/Xpi5ioYnuP5IOllSZDIcapXLRv503j66vRoUis1++cuZjh7mMBc4pY5XyWRfr5ZE8SZftpohltykqJJpKELJUEshdkXPo8BzkPHDHTt8zXddDyDGjIsSzMxBcPCbpiyFguanHkmBlceOQk3owlhV5cuhxxXMHZn1JV/WdG96cvXomRyfWTh9Qo+BfwLUFJ6ewMkZ0DSI/c3YPoAz85WbOhyfAf8Up97JpAhcwAstd7SEEG/SpmvzK/MfRz+eg5+6e6FI7oPN/mAFD4EVDGH8zBC2QGnnPvocHNlcTZPg+/AiOLjQwiNQlcIFOLS5noagsnNAJ+G8T7fq1eYOcTa2AsH14vpprGijKOCnJXlQg3chRry0GqtnvNd3WVHnR5q0Fu7uimR4lb1KUnFnWsBaN2gGygzo8V1QcpCsbnU6mrwzPEy2bjp2GgQjiK0RqySGVbSaF5ygZldz/GOaelPH9tW3rsHfmRwein7orIvktM4AhrmHfvdyJTHPLEzZu2hsfCc2fXuT/2l1/jtQQyM8+Xh8e8Fi1KiX54cO6MYl9bqaeZl2g3/4hWiH/hmUk+/YlW68YDdce2HJynq3kZtg7sT9AayY1YmswhA/cOiVspTIM9PcBHp3HqGkQQEegZrsCJ5orIB8q2Qhi2ntf/lP4NNWe9/myh294XXjDnt24QR8WPxXEnCdwYNez3Gxq2xropF3tcXMN7p/L0MT9czij2Lwt+z0ZINX8Tzz6mZOmbuslAivUuQ2oyIt2wbf0nSDq+mas9TocrN8PCI2kxsDNOBXXlYqULkrRVYDpuU5PxGF3JxEHq4Z2GWFjMoTfxiMZNF6wDfAinb1t/Sq0I4z3j7bZMPx1TW0IAgVx5poUbYQIqJdyqkIoyARiCKdFjMU7sPDaJb7dYFiAwMdXjGHC+hdRjybGkKlPWl0yZScUsBtuM3avXEYQDq63ok/YumasQ2Xe3ZK1OLYVq2W+HB1+uYC7R+i0QSSCQevAbiqy3tbvfTTDze3RIyNe/Lm+v2bmJMfZvMlZGR2bYY+ksRhc4rCCy46qK5FSZJlFmldiu8RCDFpmGPwXla4HJelmCr19vs2JGpVcIwG7fR7dzDnBx/8iytuVvBZHScraPdcw/3qXatVq1br+fJ3d6g02r2ZwRzE781jJx2merifFy8dTx9JuLWYv645Z6ei1h3XZnOFs+jvq7tuoMu0vhGfB/2bIT7/GtPpdW+ApcMnU3QgkRAoRSRXBTmjLuQe7EbN2JxIuS5c4xS896RX4as3atPDNcq7hbPCsZ22wCq1o1CyFsqWhBzxGhHcQvuGZbU6ujW4ucnAMt343hv9cOKO1XU2ApZmcRNuz/XyKBpCbfP42k9UTBa4ysX1tXRAc4VEEygf20jU5L3LAuVsrpCnnkuhyzhvLPlFjhYWTLCGKTZ7IuIwSl8cJajGcFL0/+5cUmiFfOj+5apUOD4azM/OFnX9vmCy+XXSGzMG/CorikwQL/Lv6o0eGVKeNPOZruKYjaCl1y/iue/e/QP6bl/zfbW2630EqkhkUm8gVk4Q1rHMIgw+qF9azdXchZfbe6+65sEolMP7VE2/P5eVvVoeuBAOXJxqN7mkv1AZljhv0iNkb5DIxBZKIEazkOaBXbQJbRwu8xw9b81N8wGpAtZ6lhu+lsYCVERCYh6vVk5U07JEnmyB2uNep299xyLLpW06mAXUAy4MUsfBunTgjfRQhqsc1CXiqoMa6jXt0Kcc4hP9N32H+X5reebnR38/ugwQTCGvGNnT+QPx0WSFRaMVNadLertWai+PRmMqRGN6J35Tkzdf3SJ5tLugjVm7+CDRLrrWor7KasxG6Zwu523FLbClIwWYdBSEnLpx/0u5Xv/zE/+JadDU93ukN8/+XhNvgkuo6owzH8xOE5sHm4DT4a4AW9OdnBeHZYLTpZ3pP12ZlzcNlxO1ZLJ8T43XH9MToiLJDfQ6FQuPZ86i9MbBZwG8jTuF1jxGK78IeB9fhsN6WBuvjqyV5o4kWd3Zkn4voaydK62nur6A7bspxF6Pu7rFWtuwihBdLX0qHh4I3rEzui4btdo0tVsgBnaKDK0vfC0hMHgxEBBurGOTkqDcp2rVjAM8VoX24V4W7+TphZ+SVm700Ms11Z5dtARmRvrwdPMBErlOdt7/vdz/rhjxvXab5F3l0gaaenXmOzAIxbyEUeYmYY+WhNTfPB9iG9suGDc8Mthju9GKxWaTAemppLJOYkoo0+OpXoKOiucqjVfHzLJ4hyLplASdGzXvHPfO9fvDBtTZPeA64F14d7Y3eVwP02MYOYamqeWJs5IItcrLEkg6CK9uOTayp/O9nudIsbrZUWtSlq6jNa0Qp62dvmHYv0C8aEAjTJlMUL7xJscb9kCFcAJgImJbWOQn2sBxMb/Dm8KeoH9fL+BEr0tJSsY3e6a1jFJWrQJ3sgl0va33KBnmFBNLUS73Ft6peydLrn8dOMQOvKiRsvdZodpY21KtQ7eHO2Gr/YNBwjGbhKyk1ep0ULMHdcprsGbCwDjwsy5umxYx1Lq/3LZ3PI9e9wiOhu3molZTU1q01IulHLyob4zocU06vbh0rb1Aboe2qzLg7QHmvuoEeckc0a+zud374t5BRyJrFuWMrS2nv+TN9x3Qw2iq/WVYcqNHjbybA1trV9rkM8POVszgHGL64diicBFrTW66xkus9+J7urmDln4OSPnoHO5OdXmFP1efMQqh5SOfnaJgzmYKzfw48D8qxe0DD/DX30D8OfS+KuKg/vmDiqLIoyHnlx/HR/VoKc0jlF4uD+Stoe7ikxYC6AZ0QHvWaZ/Jkrq8cMlUZbyjhGXQmSRZQvzc2a2mMJRmX9dhfqXKrbcGtp1P5Qp4KBcWnHHq7hboOpGU4QbEqM8J6LuJ4610MGicI+8gvFsbzhrX1/YBkRSnhXfLEYyXbcoSjitowKdhpjRapPKryQPDWDSbFAqHdetZEoal67khIJGj9rGOxPT+Chcowo5UiKCk36OXA2lnr3f36vQ0fKoPTmRSL86WbnQ6c58WoHQUYCbMnKGiCh3jQ3lHPixvZoaxAN4rXTkIQ/RAxGhpam1BZds/PhHybHdiEQYfcQs9nOzkv25FMrbSlIl7qOLQtFqFDn2a5Op3clixiQ7z73VHz34y8O4Z50oS+TwI72FG1AjT1NYwD7b741PGVDXjk0USOFoE42RnvlQkP+12u+h5D2bCsmS0HvT7Nj5HQCTfUDigG8YtcSGtj5Dh+Q89OvWb0YGGKXeUbxq00OCfv1qPpaQVdmA5eEuj8MaktP2WdTE9D8FKxAqtuEPLIx9St4T0REURcAhXRA6ejiGmxiItEvlXSFgzwnq6RjYMpQvb8jQOLXt5oe3QDR2ENWzo+Mi2pTVq9o30SdbUCbU0t6U9d2dZDX6XW6MGQ8yUTNzp8dNuQkxnrXMX4awfEk0y98eQWP5OJ1wweEcqZip1HJ9u8ikPXds0jeAX7uu6uYtSvwDkfbQPby6B5lNQBrzmIuj+QyMGLWOqxN4F5+PT+egT+7+e/7w18rmWsvq4BL+ATGMWdlt+Kvca8cQGb45UlEewtBd+4xvhsFA48HkUHvsmAksEjYd98+YN2mOpz+8FPwf2RWcMeqBz2lmsbPvTSaI50sLRroUyfBg6u8CtSRTFGm5YNU3OKc7yaOO1XJlQbjmu8jAe9VmAuIjX37sgYbKBkmO7FiDjg7zaBe5lumiEsqj5UDBu0yXF+MUZDV3LIttizSyl27ZEIZfOFp83Vkv4s4KH8mLUygDGxHBo+dXJQuwLLLqIRoJFbJU/2DmDmhHB4CZ3doAu6s3Z5D43zgFgAJMi+IS3j4woenU0D9G5nwdyPtqHNzfRnU8BEbBNcx+tnggHpAdb83zSIiDOdrenQ7bJ1i40V9kSMcqXDoi7RqoElgEXbdmFMNnXyszRSMbY9ac3FotV6PO2mJSDQv2e4wUVZo6yGPhQITP6Z69fdp/MjvCjg6Cz5eXkdPBaOo3obc3Z5yV5NLpOA7SOOaRW1H1wrhZq+37517Ec5zu1EorD7jhLGyMO1CLyu3FuEYxALIwX3AGZaWOBAX66aElXC5LBQDsZqXc/JRncJZ1qFT+dzoqjAH7wj1n5EoVQxqKLCoyXrFO5TkeIcQE8UluiKBFVfChGcSAQMJJbIxwD3cgliV/R889ur4Xhr5bairSSn61PcvnFjx6gKD0ixfFEd9WkC1WCEOHBG/bnlhagIwL6hnFiGLqLB1f24uLc4DPbWZ6GxmxCVx2hRbSwNCotsmm2swPXiCjte/T7RciMtO44TYseclgamhbZNJXRgavCLlv7zLe+3jpNehaY5nFsbqNjPxekfbQPb86Dpp8Ac26lhLphDLL64h7ftgtDYxQ4ngwne6q6Z6NQiNA3tWFEmKsfLaTNZkbYTDKjL1MaDterwgAdBR6NkTVumHumYVYf30XpmUIRX38O0UP+TWnNK8BI4hwLvyIM90z2eOBLobyZFilg0ScNA9kGgn10zSh02rlHQ6S9fDvzNp8ZFS2yJGoTQ4qpNRmSYDt9EJoYG+MDB28a5Y7jIWvaB5okLBgBFaR0rOrbfnKRLwAmekq3WG+7T5xENG+RLAe64d8DYW7q9dppd3/1t3r3uJ+B3a3fbf4yWUapM/XsNLU6cNaqiToW0Ba/ARY7leoKiiDmgQensaCUSKJIvxNly6rlkaByArRDeT3HTIeYMnwQQJ+I884l3DE1Wxi+MmJDE1unNsvioOAc8djKvZ5sWXJ8uSpWjs1hnyLKRrOs6ZD2+HHWIG9sWan1CEbV18pE6dCJBRtjxyfrGU/Ub1YlXFfBqEK+VtxDLb3DRSXo1GmcV8JGOa47oGuIyeNgg2GzHDvhZwgciERNn29O3WARmpPY1rJt+o4ESiosD2xT8Rgp45tnbzrHmRGLx2B2MRqpvxvgXwHr/WG4KvTxbL6Njt0HfOz+LFD3P7w9Aaolt71en3mYlutqVlWlIYyfsqzTO7hCpU29TQm2f9rqwDmwde7qOi/jej8NL3oe6oMkO9wOeCYQOHYoyqzlan2R+oxFFxfCR9Jxwo0cyOhMXVHHNXa0teJxjeXvrumiSKp/mLoor+Ph827VG3oQS6pTNPQ/KnxC00VSZ6HF+kyMKFwtqz8qxK1dkqyNp7KHvM1ssgA3bVr2KlxD9PzclnZ7aoUPGH/XAVJ1ifUZraRdcUsmvRxtoA6m+CmhFPdVNK0bzmjYpkkG9B2uIi+FcSOJp185kCF/K/zqXHSe7bmNAjJ6ig8c0opwPvF7G18cBqtrjMHms+iW47oP2JZivt3eypX2qyfSSqkRoxhSvNUGS6GmLWkQxVKWarcvTSKfDgsQZtriQNObnkDkEEFyyQx8dMCKAsn9RrGwLsF4zxajHDoYmIu5nXmWzhQUgQzz1kQQgqnMszND+jnUEmZ+R+KcDDu5/s0/FLC3pm6a2A79umMtjGaMmZzNslFr89ywicZVcd7sIxhi6mmFcuRbLu/64u0TSTdVNuRg6RgqCVRTScDC95cAR8IjiYm8cJWiGl5ZIk7ujBdYDhsYhOM81uc4Hsf+SveggwIWRupFzx2zWcgcyImfAFMsmgqhyDNWyTansijqODX7YbXUi0008s+wcFpS34k+NMzf1c48BsDG0UGJPjal2n8kFALrBm7QbiinqdaWY9nlcpoqsBz7if2yeaSEEvX1aN1Os4hDLVmKSBEpXdxSREqVIlJEPh6Km5O6q+MAOrDKwKbomGMJqDwRAPldYYEKMlPoFmYpE5jvZNp46P7loTNfffXvv1+e3bv0LObj1CmYTHVhIGCbirFNNRaqM3vTuHauFYYAICUFm4TjJsT41jtifv9iy7p1+639XueWL37vXWLq2aV7z57u+O/MmaHL94ekw+NzB/bsGbAGpuiBc4/NTuDikrApKZmBYCvXbjtQCyKVlV7Lm9FIgRlh6/afeid6bkHMKDb9QZlFFZhONi1EMy8iy+OoEEnVKnLr6XELc2wr5eJF5OmNuWSC9qbvzkXZ7lXUZYsQwlsQcyjLFmEdUz7ZW2BfwjBsq3hcF+izJLwyg4tZmXP7Adz04daagUVYHJwhZxoBBmXLQN6rUYDo6Z1InMyWFGWaxHEeMTF69MFXogu1EQE1XHQCyJ+uA53v9yzfEXMxNnbg/q+DNnXS9feFhC0ACigvsQy2HyhE46bzqeV+/Ci9Tqvu3z9FdMT+/mUCNfPMlmK8s3Nddfd+2sduaf3AL2wDbB0u9DnNRICl545p76ACJjuv7nsWs6EbZ+o6FLrGmzZ11qO+Vh1gFewmuE2MAdUBCvYKryZZ2DZr2ALqeMMwb5g9F0WzyFqG08Ukn3vVKhgW3iu8l43fP8XSssqRrexXVY84R+48V4OwQWYt4lHaqwhWb7DprZ3qBKk7DqLUHZsmDSFFyJxlL9ZtU7F8VpLkzCtndopSV1HiCRbWwm9vL2uN2vc8FzFeqdNp7AskY/YJIvrp19+SzqCUh/T3P35bVOjmMm45L64bj07abl52HXVqhD2knDnzu8cbyGGjLFYOet5FWEbKYxzKQz9eZ/n3YumiqJSQlhsIMS2PYsWZ51WqqHOWhAv5KOozvQ6TSj1AgpSR5eBAx71TBWM5HuVYNVxTU1e1uaeZEnlmtatTXvZcqkB1uiQlwAZ78MzqqQEKrM3HpUl1rycTrIqoMmJq2yvO9MwxwMGBvTBf/KWDmJihYrrOLvH1NYy5rDs7j4VuBkSsSQKTkgSBShkaFrOgNOvp2+9XqXdY1V2H0ONgxFdzJ/s3RH6zUwE7F2EAs4ooUFp7iWXp9Zw3uG2TiA+10Hk0VEf5qCijtaDtV+5amHKarAU6Ptz/fLt3eNtgLbbls/5a7J5nr6/FZmPba3v/zTdfLv9olDXRJKthZ6ul7ffLluyC0ZeAR1pPkHURYOxA+RRZlLYtA0FG3MvZWl7M9Wo3hCpQqMYK1W2F2ZcafBWs+c6TAho0RihUM4TKVqg2ClVXYfYRijLEA+epo4wcjUoQ96S6T54FtPKm99R0Pn/WVu608pWnRR8Y/P4DD1H13KMrcDVcXd7MXbAtc1VTJSS9xchQT94uAa0qxpheULC9cTb9n5rbwSuBHNltCg72RaAHiI9HyeIIBSOo/pyjt0TAKkL33StOsK90wpvKJDOMM77k67l8giTeNebhqDGcOuEbgSNwmqeTxZygPIUqVqgGCpWu0AuWbfTBZRdx5dx5ah5yu6MuobohxN8pxDcjVHEJEwtacu1tath13EnMw6qujEdTy9IZrQWKLkYSpWOt1em1fDdKx1rMbLCrEqVjLYirrjI+CDqhIIBqzYnV75v+veca/lhC1RXAvavqq4Afnq7Y1N53z1qYRUADAghQi3/9gerKCtuLFq52L9ETl6iKRGxJYRoyBfGKYbA0M4tcRQkVU0Sx8nIF/pTVkSi9CiLNVzU1FA1J6XaBTW9seb3yPdHxMMXhcMRjwgpgVvxFHD8RhMc95Q1hZZ8NpcXKcnpWthEk6ugtG/SIRe6LOyLKS+mLFw2VUH0V6uu10MYeKg4HZGm5j6R8aHWpwlQvY8om0uIUXLaLLqvdF2CGVFgKWsgOJU9p5RA9IuOzaGIsjLRbdMVz8QTKCJVZMWQGM1S1ZI7G+3FRG0d/uvRobHgDfowKqYOH3yi61VII0ffHEhGcXtdpwi8s7PJYKcW22NB6XxSRiIi+juu9dY5M9dnWaYmh83KNxSmrzGOpOKzhoyuHqeKAe4n9YmNSkh8tj/NmBkSXy+GCCe6vTEbl+sFeiwkBezzmyZq+J7WEBTGUbVaWPPeVQpayQVRZRpEbUwlf9YjMFX8Mgxt9/gRz9CYpqzfgdRNwQTzWqRuq87EKijwSTnNIzBsEYkokqz3IXIqdIwDmkwsIISyxVwxmLk0lBqq5HMOccgnE3jYoiHFi4wmqWCtKkKaZWC/6MV8XdpHxwmtNzxUNJad6kqqy6/0uJ60sXIHReBvO1NfAXeis3wNfsj99IVzJFEgNEFAP/fA3+KBzOW64nOmUq9CXtJ6/ZPNt4Iv7GpxcxfdQdQVGgOhRgGJHQkIZVIPY2tuLhQDmRA0WojYOeFgpG9oJ8pLUjoSUoXaWlfFnO2lpeNop8vi8naaNg6eGsIS7LQJ0xUG0F5zY3V5Rha69hgmmvS7W9fYGbKG9KUoXtfzoaO/E09LeJdre9m6hXmnvoZPf3osjq72PSmzlQo6rLqpczKtyCRdaGhsdlcv9V67wWbnST/sqWBRbfRSJWhP1+F0bgoHrbFHmUZutssOjSj3lMTkbKm+ipYo+VMlePZmmk2RztMwmL8iziG6n30S3KBWjL42i8tbNZZ6CgfJsIBtKLvWssqE0qsrKXuAJT9qxL42mUpfoDuXNFK5pebbRfE/mPZt7VZQZdLwW1rrVSgZRjD6m3KJb7Qh/nO3xUnFRVk9kL55dmiwfKndNP+FZpS1arnChcmu1JduTilkcE6P4X3pUokfVrEE1mR66t8G+bM/uUanenj3ZFlu9qDwaIRU2r6CyoeTg1Vb1qyTyVqkiI2cop+3B0nOJT8ZB2i8pb+E+TdGj2vaIlSpNugzOtAVK5ifnVNkbOZtMvgKFH5gfrFHrLGjpG0TT0FpC51+WihFLL46B8/+uiZlFAqtlllthpXvd534izH9ahaZSS1tHV4+PIfW4g6zS3UOSIAtgHHHUIYd97RsnnbLdDhuhbUAXSmaypVyl4SovxiWocN8Ms8w1xzz/t0ZvkCNFHIsqOM8s9VyFamjsDTNt8rm+ZNPFW+G0JiOM1KxVi3XaPNSuU5cO3+k2ymg9KcYYa7wJxllvov1me2qSKaaa7LFBZw2ptluNPRapTfVAnTPOOe/Chxzl9U3V8K9bbK99nrjhpka3PLIy9LdwDU+Ix+vj6wfiCUSIRKZQaZcxSs64vji74H5wGYt1ehrsM+JweXyBUFMklki1tHV09WT6Boa35C83MmfeIVmij6q+f2QwwGgY0h+p6Hl9GBLXGlgnfHx9SPqv7Dwg1wlenboI9KcLwtKWbSvr5kw0jCazpS3bVtbMGg4/9V37cPM1OR7erhefLwLm1DdbxfC14W04/VklwIwPI1haGw2gZbNJvnycfXEVBjcj91eE++ibSOjl+x9phEk8PF/ffOGyTYoEmXb6lbySqIweLo5t45PCLfchy798MT1xVeT1SW9ohuRhyKk8/AG8d/8A1IdGV//ydus6yaqsKvD6ftx9+WjjfnG53pjTLPevNKP+pWbi1/I4L+Vh/0LT759ruv0zTad/qokNaC7kXs5yyiEvMucXAgK4gPgGGm6/8XvnPoLKXuBTK+tdSp/W8PoloVnfSEJ8lX97+RJW7GjIeVOXXx24ZPlElFXf+JizqZMN7GQbyoCwWw==) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} + +@font-face { + + font-family: 'IBM Plex Sans'; + font-style: normal; + font-weight: 700; + font-stretch: 100%; + font-display: swap; + src: url(data:font/woff2;base64,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) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} + +@font-face { + + font-family: 'IBM Plex Mono'; + font-style: normal; + font-weight: 400; + font-display: swap; + src: url(data:font/woff2;base64,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) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} + +@font-face { + + font-family: 'IBM Plex Mono'; + font-style: normal; + font-weight: 500; + font-display: swap; + src: url(data:font/woff2;base64,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) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} + +@font-face { + + font-family: 'IBM Plex Mono'; + font-style: normal; + font-weight: 600; + font-display: swap; + src: url(data:font/woff2;base64,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) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} diff --git a/assets/lrsomatic_report/assets/styles/report.scss b/assets/lrsomatic_report/assets/styles/report.scss new file mode 100644 index 00000000..9260b9ae --- /dev/null +++ b/assets/lrsomatic_report/assets/styles/report.scss @@ -0,0 +1,1343 @@ +// ============================================================ +// LRSomatic Report theme: Spectral headings, IBM Plex Sans body, IBM Plex Mono data; +// fonts base64-embedded in _fonts.scss; scss:defaults then scss:rules (Quarto convention) +// ============================================================ + +/*-- scss:defaults --*/ + +// ── Core palette — warm paper + ink + a single confident accent ── +$report-primary: #0d5c75; // deep cyan-teal — clinical spine accent +$report-primary-light: #128aa6; // brighter teal +$report-primary-muted: #e8f1f4; // pale teal wash — quiet fills + +$report-success: #3f7d4e; // muted clinical green +$report-warning: #a9781a; // ochre / amber +$report-danger: #b3402f; // brick red + +$report-text: #1b1e22; // warm near-black ink +$report-text-muted: #6a6f76; +$report-bg: #f6f4ee; // warm archival paper +$report-surface: #ffffff; +$report-border: #e4e0d6; // warm hairline + +// ── Bootstrap SCSS variable overrides ───────────────────────── +$primary: $report-primary; +$success: $report-success; +$warning: $report-warning; +$danger: $report-danger; +$body-bg: $report-bg; +$body-color: $report-text; +$border-color: $report-border; +$link-color: $report-primary; + +// Typography — embedded webfonts, graceful system fallbacks +$font-family-sans-serif: "IBM Plex Sans", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif; +$font-family-monospace: "IBM Plex Mono", ui-monospace, "SF Mono", Menlo, Consolas, monospace; +$headings-font-family: "Spectral", Georgia, "Times New Roman", serif; + +$font-size-base: 0.92rem; +$headings-color: $report-text; +$headings-font-weight: 600; +$line-height-base: 1.6; + +$border-radius: 6px; +$border-radius-sm: 4px; +$border-radius-lg: 8px; + +/*-- scss:rules --*/ + +@import "fonts"; + +// ============================================================ +// CSS custom properties — light mode +// ============================================================ +:root { + --color-primary: #{$report-primary}; + --color-primary-light: #{$report-primary-light}; + --color-primary-muted: #{$report-primary-muted}; + --color-success: #{$report-success}; + --color-warning: #{$report-warning}; + --color-danger: #{$report-danger}; + --color-text: #{$report-text}; + --color-text-muted: #{$report-text-muted}; + --color-bg: #{$report-bg}; + --color-surface: #{$report-surface}; + --color-surface-alt: #faf8f2; + --color-border: #{$report-border}; + + --font-sans: "IBM Plex Sans", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif; + --font-mono: "IBM Plex Mono", ui-monospace, "SF Mono", Menlo, Consolas, monospace; + --font-display: "Spectral", Georgia, "Times New Roman", serif; + + // One surface for every card, table, plate and menu: background, hairline border, this radius + --card-radius: 8px; + + // Impact colour tokens (values match formatStyle in _smallvariants.qmd) + --impact-high: #f7e3df; + --impact-moderate: #f6edd6; + --impact-low: #e4efe3; + --impact-modifier: #f3f1ea; + + // SV-type colour tokens (values match formatStyle in _sv.qmd) + --sv-del: #dbeafe; + --sv-dup: #dcfce7; + --sv-inv: #fef9c3; + --sv-ins: #fee2e2; + --sv-bnd: #f3e8ff; + + // Circos ring palette, kept in sync with R/circos.R (SNV colours are softened SBS-6) + --circos-snv-ca: #2EBAED; + --circos-snv-cg: #1b1e22; + --circos-snv-ct: #b3402f; + --circos-snv-ta: #c7c2b8; + --circos-snv-tc: #ADCC54; + --circos-snv-tg: #F0D0CE; + // SV (hue-matched to --sv-* table tokens) + --circos-sv-ins: #cf5b46; + --circos-sv-del: #2f6db3; + --circos-sv-inv: #c08a1e; + --circos-sv-dup: #3f7d4e; + // CNV (tied to report spine) + --circos-cnv-major: #b3402f; + --circos-cnv-minor: #0d5c75; + --circos-cnv-total: #1b1e22; + // BND/translocation + --circos-bnd: #8a5fa3; + // Breakend circos only: the selected arc and the panel-gene bodies + --circos-bnd-selected: #d7263d; + --circos-bnd-gene: #0d5c75; +} + +// ============================================================ +// Dark mode — warm-neutral ink +// ============================================================ +@media (prefers-color-scheme: dark) { + :root { + --color-primary: #3fb0cc; + --color-primary-light: #5cc7e0; + --color-primary-muted: #16323d; + --color-success: #5fb874; + --color-warning: #d6a23c; + --color-danger: #e0715f; + --color-text: #e8e6df; + --color-text-muted: #9aa0a6; + --color-bg: #14161a; + --color-surface: #1d2025; + --color-surface-alt: #21252b; + --color-border: #31363d; + // Circos legend swatches that would be invisible on dark bg — lighten to match --color-text + --circos-snv-cg: #e8e6df; + --circos-cnv-total: #e8e6df; + // Circos plates stay light; only captions and the selected-row tint go dark + } + + body { background: var(--color-bg) !important; color: var(--color-text) !important; } + + // DT dark-mode reset (overrides DT inline backgrounds) + table.dataTable tbody tr { + background: var(--color-surface) !important; + td { + background-color: var(--color-surface) !important; + color: var(--color-text) !important; + border-color: var(--color-border) !important; + } + &:hover td { background-color: var(--color-primary-muted) !important; } + } + + .callout { background: var(--color-surface) !important; border-color: var(--color-border) !important; } + .callout-header { background: transparent !important; } + .quarto-title-block, .quarto-title-meta { color: var(--color-text) !important; } + #TOC, .sidebar-navigation { background: transparent !important; } +} + +// ============================================================ +// Page +// ============================================================ +body { + font-family: var(--font-sans); + font-feature-settings: "ss01", "cv05"; + background-color: var(--color-bg); + counter-reset: section-counter; +} + +p { line-height: 1.65; } + +// ============================================================ +// Masthead — Quarto's auto title block becomes a slim eyebrow +// ============================================================ +.quarto-title-block .quarto-title .title, +header#title-block-header .title { + font-family: var(--font-sans); + font-size: 0.72rem !important; + font-weight: 600; + letter-spacing: 0.2em; + text-transform: uppercase; + color: var(--color-primary); + margin-bottom: 0; +} + +// The render date is in the footer line; saying it twice is one more thing to read. +.quarto-title-block .quarto-title-meta, +header#title-block-header .quarto-title-meta, +.quarto-title-meta-heading { display: none; } + +// ============================================================ +// Hero — sample identity band +// ============================================================ +.report-hero { + margin: 0.3rem 0 2rem; + padding: 0.9rem 0 1.3rem; + border-bottom: 1px solid var(--color-border); +} + +.report-hero__title { + font-family: var(--font-display); + font-weight: 600; + font-size: clamp(1.8rem, 3.2vw, 2.5rem); + line-height: 1.08; + letter-spacing: -0.01em; + color: var(--color-text); + margin: 0 0 0.75rem; + word-break: break-word; +} + +.report-hero__badges { display: flex; flex-wrap: wrap; gap: 7px; } + +// ============================================================ +// Section headings — numbered rules +// ============================================================ +h2 { + font-family: var(--font-display); + font-weight: 600; + font-size: 1.55rem; + letter-spacing: -0.005em; + color: var(--color-text); + margin-top: 2.6rem; + margin-bottom: 1rem; + padding-bottom: 0.45rem; + border-bottom: 1px solid var(--color-border); + display: flex; + align-items: baseline; + gap: 0.7rem; + + &::before { + counter-increment: section-counter; + content: counter(section-counter, decimal-leading-zero); + font-family: var(--font-mono); + font-size: 0.8rem; + font-weight: 600; + color: var(--color-primary); + letter-spacing: 0.04em; + transform: translateY(-0.15em); + flex: none; + } +} + +h3 { + font-family: var(--font-sans); + font-weight: 600; + font-size: 1.05rem; + letter-spacing: 0.01em; + color: var(--color-text); +} + +code, pre { font-family: var(--font-mono); } +code:not(pre code) { + background: var(--color-primary-muted); + color: var(--color-primary); + padding: 0.08em 0.38em; + border-radius: 4px; + font-size: 0.86em; +} + +blockquote { + border-left: 3px solid var(--color-primary); + background: var(--color-surface); + margin: 0 0 1.4rem; + padding: 0.85rem 1.1rem; + border-radius: 0 var(--card-radius) var(--card-radius) 0; + font-size: 0.88rem; + color: var(--color-text-muted); + + p { margin: 0; } + strong { color: var(--color-text); } +} + +// ============================================================ +// Badges (run mode / reference / sex) +// ============================================================ +.report-badge { + display: inline-flex; + align-items: center; + padding: 4px 12px; + border-radius: 999px; + font-family: var(--font-mono); + font-size: 0.66rem; + font-weight: 600; + letter-spacing: 0.1em; + text-transform: uppercase; + + &.is-matched { + color: var(--color-success); + background: color-mix(in srgb, var(--color-success) 12%, transparent); + box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--color-success) 35%, transparent); + } + &.is-tumour-only { + color: var(--color-warning); + background: color-mix(in srgb, var(--color-warning) 12%, transparent); + box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--color-warning) 35%, transparent); + } + &.is-meta { + color: var(--color-text-muted); + background: color-mix(in srgb, var(--color-text-muted) 10%, transparent); + box-shadow: inset 0 0 0 1px var(--color-border); + } +} + +// ============================================================ +// Summary metrics — three labelled groups of flat cards +// ============================================================ +.metric-groups { + display: flex; + flex-direction: column; + gap: 18px; + margin: 0 0 30px; +} + +.metric-group__title { + font-family: var(--font-sans); + font-size: 0.64rem; + font-weight: 600; + letter-spacing: 0.14em; + text-transform: uppercase; + color: var(--color-text-muted); + margin-bottom: 8px; +} + +.metric-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); + gap: 10px; +} + +// One surface, no per-card accent: the group title says what a number is about +.metric-card { + background: var(--color-surface); + border: 1px solid var(--color-border); + border-radius: var(--card-radius); + padding: 12px 14px 11px; + min-width: 0; +} + +.metric-card__label { + font-family: var(--font-sans); + font-size: 0.64rem; + font-weight: 600; + letter-spacing: 0.1em; + text-transform: uppercase; + color: var(--color-text-muted); + margin-bottom: 6px; + + // Opt-out of uppercase for a single character (e.g. the trailing "s" in "SNVs") + .lc { text-transform: none; } +} + +.metric-card__value { + font-family: var(--font-mono); + font-size: 1.4rem; + font-weight: 500; + font-feature-settings: "tnum" 1; + color: var(--color-text); + line-height: 1.1; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.metric-card__subtitle { + font-family: var(--font-mono); + font-size: 0.66rem; + color: var(--color-text-muted); + margin-top: 5px; +} + +// ============================================================ +// Notices — "nothing to show", quietly +// ============================================================ +.section-notice { + margin: 0 0 1rem; + padding: 0.7rem 1rem; + border: 1px dashed var(--color-border); + border-radius: var(--card-radius); + background: var(--color-surface); + color: var(--color-text-muted); + font-size: 0.86rem; + max-width: 78ch; + + &--warn { + border-style: solid; + border-left: 3px solid var(--color-warning); + color: var(--color-text); + } +} + +// ============================================================ +// Figures — tool-generated plots in the report's own frame +// ============================================================ +// `display: block` is load-bearing: Quarto's inline-block `figure` class would shrink the frame +.report-figure { + display: block; + margin: 0 0 1rem; + padding: 12px; + background: var(--color-surface); + border: 1px solid var(--color-border); + border-radius: var(--card-radius); + + img { max-width: 100%; display: block; margin: auto; } +} + +.report-figure__caption { + font-family: var(--font-sans); + font-size: 0.76rem; + color: var(--color-text-muted); + text-align: center; + margin: 0.55rem 0 0; +} + +// A Plotly page in an iframe: the frame is the surface, the page inside is white. +.report-figure__frame { + display: block; + border: 1px solid var(--color-border); + border-radius: var(--card-radius); + background: #fff; +} + +// ============================================================ +// Panel controls (gene-panel selector) +// ============================================================ +.panel-controls { + display: flex; + align-items: center; + flex-wrap: wrap; + gap: 12px; + margin-bottom: 12px; + padding: 12px 16px; + background: var(--color-surface); + border: 1px solid var(--color-border); + border-radius: var(--card-radius); +} + +.panel-controls__label { + font-weight: 600; + font-size: 0.8rem; + letter-spacing: 0.04em; + text-transform: uppercase; + color: var(--color-text-muted); + white-space: nowrap; +} + +.panel-controls__toggles { + display: flex; + align-items: center; + flex-wrap: wrap; + gap: 8px; +} + +// `.is-on` is toggled from JS, not styled off :checked, so chip and checkbox agree after a Clear +.panel-toggle { + display: inline-flex; + align-items: center; + gap: 6px; + margin: 0; + padding: 5px 11px; + border-radius: 999px; + border: 1px solid var(--color-border); + background: var(--color-bg); + color: var(--color-text); + font-family: var(--font-sans); + font-size: 0.85rem; + font-weight: 500; + cursor: pointer; + user-select: none; + transition: border-color 0.15s, background 0.15s, box-shadow 0.15s; + + &:hover { border-color: var(--color-primary); } + + &.is-on { + border-color: var(--color-primary); + background: color-mix(in srgb, var(--color-primary) 14%, transparent); + } + + input { + margin: 0; + cursor: pointer; + accent-color: var(--color-primary); + } + + &:focus-within { + box-shadow: 0 0 0 3px color-mix(in srgb, var(--color-primary) 22%, transparent); + } +} + +// Shared by #panel-clear and #facet-clear (the latter hidden until a facet is set) +.panel-controls__clear { + padding: 5px 11px; + border-radius: 6px; + border: 1px solid var(--color-border); + background: transparent; + color: var(--color-text-muted); + font-family: var(--font-sans); + font-size: 0.78rem; + cursor: pointer; + transition: border-color 0.15s, color 0.15s, box-shadow 0.15s; + + &:hover { + border-color: var(--color-primary); + color: var(--color-text); + } + + &:focus-visible { + outline: none; + box-shadow: 0 0 0 3px color-mix(in srgb, var(--color-primary) 22%, transparent); + } +} + +.panel-controls__count { + font-family: var(--font-mono); + font-size: 0.76rem; + color: var(--color-text-muted); + margin-left: auto; +} + +.panel-controls__custom-area { + padding: 12px 16px; + background: var(--color-surface); + border: 1px solid var(--color-border); + border-radius: var(--card-radius); + margin-bottom: 14px; + + label { + font-weight: 600; + font-size: 0.78rem; + letter-spacing: 0.03em; + text-transform: uppercase; + color: var(--color-text-muted); + display: block; + margin-bottom: 8px; + } + + textarea { + width: 440px; + max-width: 100%; + font-family: var(--font-mono); + font-size: 0.82rem; + padding: 10px; + border: 1px solid var(--color-border); + border-radius: 6px; + background: var(--color-bg); + color: var(--color-text); + resize: vertical; + + &:focus { + outline: none; + border-color: var(--color-primary); + box-shadow: 0 0 0 3px color-mix(in srgb, var(--color-primary) 22%, transparent); + } + } +} + +// ============================================================ +// DT tables +// ============================================================ +.datatables, div.dataTables_wrapper { + border-radius: var(--card-radius); + overflow: hidden; + border: 1px solid var(--color-border); + background: var(--color-surface); + padding: 4px 12px 8px; +} + +table.dataTable { + border-collapse: collapse !important; + border-spacing: 0 !important; + font-family: var(--font-sans); + + thead th { + background: var(--color-surface-alt) !important; + color: var(--color-text-muted) !important; + border-bottom: 1.5px solid var(--color-border) !important; + font-family: var(--font-sans); + font-size: 0.7rem; + font-weight: 600; + letter-spacing: 0.06em; + text-transform: uppercase; + padding: 10px 12px !important; + white-space: nowrap; + } + + thead input, thead select { + border: 1px solid var(--color-border) !important; + border-radius: 5px !important; + font-family: var(--font-mono) !important; + font-size: 0.72rem !important; + padding: 3px 7px !important; + background: var(--color-bg) !important; + color: var(--color-text) !important; + font-weight: 400; + text-transform: none; + letter-spacing: 0; + } + + // Hairline rows, no zebra: the impact/svtype tints are the only row colour + tbody { + tr td { + font-size: 0.8rem; + padding: 7px 12px !important; + border-bottom: 1px solid var(--color-border) !important; + color: var(--color-text) !important; + background: var(--color-surface) !important; + } + tr td:first-child { font-weight: 500; } + tr:hover td { background: var(--color-primary-muted) !important; } + } +} + +// DT Buttons toolbar +div.dt-buttons { + margin-bottom: 10px !important; + + button.dt-button { + background: var(--color-surface) !important; + border: 1px solid var(--color-border) !important; + border-radius: 6px !important; + color: var(--color-text-muted) !important; + font-family: var(--font-sans) !important; + font-size: 0.72rem !important; + font-weight: 600 !important; + letter-spacing: 0.04em; + text-transform: uppercase; + padding: 5px 14px !important; + margin-right: 5px !important; + box-shadow: none !important; + transition: background 0.15s, border-color 0.15s, color 0.15s !important; + + &:hover { + background: var(--color-primary-muted) !important; + border-color: var(--color-primary) !important; + color: var(--color-primary) !important; + } + } +} + +.dataTables_info, +.dataTables_length, +.dataTables_paginate { + font-family: var(--font-mono) !important; + font-size: 0.74rem !important; + color: var(--color-text-muted) !important; +} + +.dataTables_paginate .paginate_button.current { + border-radius: 5px !important; + color: var(--color-primary) !important; + font-weight: 600; +} + +.dataTables_filter input { + border: 1px solid var(--color-border) !important; + border-radius: 6px !important; + font-family: var(--font-mono) !important; + font-size: 0.76rem !important; + padding: 4px 10px !important; + background: var(--color-bg) !important; + color: var(--color-text) !important; + + &:focus { + outline: none; + border-color: var(--color-primary) !important; + box-shadow: 0 0 0 3px color-mix(in srgb, var(--color-primary) 20%, transparent) !important; + } +} + +// ============================================================ +// Static (kable) tables — the metric/value lists in the QC blocks +// ============================================================ +// Same header treatment and hairlines as the DT tables beside them +.callout-body table.table { + width: auto; + min-width: 320px; + max-width: 100%; + margin: 0.4rem 0 0.8rem; + font-size: 0.8rem; + border-collapse: collapse; + background: var(--color-surface); + border: 1px solid var(--color-border); + border-radius: var(--card-radius); + overflow: hidden; + + thead th { + background: var(--color-surface-alt); + color: var(--color-text-muted); + border-bottom: 1.5px solid var(--color-border); + font-size: 0.7rem; + font-weight: 600; + letter-spacing: 0.06em; + text-transform: uppercase; + padding: 8px 12px; + } + + tbody td { + padding: 6px 12px; + border-top: 1px solid var(--color-border); + color: var(--color-text); + vertical-align: baseline; + } + tbody td:first-child { color: var(--color-text-muted); } + tbody td:last-child { font-family: var(--font-mono); font-feature-settings: "tnum" 1; } + tbody tr:hover td { background: var(--color-primary-muted); } +} + +// "Tumour"/"Normal" labels above paired QC tables (matched loosely: widget tagList vs bare markdown) +.callout-body p > strong:only-child { + display: inline-block; + font-family: var(--font-sans); + font-size: 0.68rem; + font-weight: 600; + letter-spacing: 0.12em; + text-transform: uppercase; + color: var(--color-text-muted); + margin-top: 0.4rem; +} + +// ============================================================ +// Column facet filters (tickbox dropdowns) +// ============================================================ +// Replaces DT's text input inside its own div.form-group (see facet_filter.js); palette tokens only, so no separate dark rules +.facet { + position: relative; + display: block; + text-transform: none; + letter-spacing: 0; +} + +// Typography matches the `thead input` rule above +.facet__btn { + display: flex; + align-items: center; + gap: 6px; + width: 100%; + padding: 3px 7px; + border: 1px solid var(--color-border); + border-radius: 5px; + background: var(--color-bg); + color: var(--color-text); + font-family: var(--font-mono); + font-size: 0.72rem; + font-weight: 400; + text-align: left; + cursor: pointer; + + &:focus-visible { + outline: none; + border-color: var(--color-primary); + box-shadow: 0 0 0 3px color-mix(in srgb, var(--color-primary) 22%, transparent); + } +} + +.facet__label { + flex: 1 1 auto; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.facet__caret { + flex: 0 0 auto; + color: var(--color-text-muted); + font-size: 0.7rem; +} + +// A set filter has to stay visible in the header +.facet--active .facet__btn { + border-color: var(--color-primary); + color: var(--color-primary); + font-weight: 500; +} + +// A fixed child of , positioned by the script (DT's scroll containers would clip it); above Bootstrap sticky/fixed, below modal; the theme's one shadow +.facet__menu { + position: fixed; + top: 0; + left: 0; + z-index: 1040; + min-width: 210px; + max-width: 320px; + max-height: calc(100vh - 16px); + padding: 6px; + background: var(--color-surface); + border: 1px solid var(--color-border); + border-radius: var(--card-radius); + box-shadow: 0 6px 20px -8px rgba(27, 30, 34, 0.25); + text-align: left; + font-weight: 400; + + // The base rule below sets display, so [hidden] needs saying explicitly. + &[hidden] { display: none; } +} + +.facet__tools { + display: flex; + align-items: center; + gap: 4px; + padding: 2px 2px 6px; + border-bottom: 1px solid var(--color-border); + + .facet__find { + flex: 1 1 auto; + min-width: 0; + padding: 3px 7px; + border: 1px solid var(--color-border); + border-radius: 5px; + background: var(--color-bg); + color: var(--color-text); + font-family: var(--font-mono); + font-size: 0.7rem; + } + + .facet__all, + .facet__none { + flex: 0 0 auto; + padding: 3px 7px; + border: 1px solid var(--color-border); + border-radius: 5px; + background: var(--color-bg); + color: var(--color-text-muted); + font-family: var(--font-sans); + font-size: 0.68rem; + cursor: pointer; + + &:hover { color: var(--color-primary); border-color: var(--color-primary); } + } +} + +.facet__list { + max-height: 240px; // consequence is ~30 VEP terms + overflow-y: auto; + padding-top: 4px; +} + +.facet__opt { + display: flex; + align-items: center; + gap: 7px; + margin: 0; + padding: 3px 5px; + border-radius: 4px; + font-weight: 400; + cursor: pointer; + + &:hover { background: var(--color-surface-alt); } + + // The menu left the header, so the `thead input` padding no longer applies; a checkbox is not a text box + input[type="checkbox"] { + flex: 0 0 auto; + margin: 0; + padding: 0 !important; + width: auto !important; + cursor: pointer; + } + + &--hidden { display: none; } + &--none .facet__v { color: var(--color-text-muted); font-style: italic; } + + // No rows left under the other filters: dimmed in place so nothing moves and it stays tickable + &--empty { opacity: 0.45; } +} + +.facet__v { + flex: 1 1 auto; + min-width: 0; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + font-family: var(--font-mono); + font-size: 0.72rem; + color: var(--color-text); +} + +.facet__n { + flex: 0 0 auto; + font-family: var(--font-mono); + font-size: 0.68rem; + color: var(--color-text-muted); +} + +.facet__foot { + margin: 6px 0 2px; + padding: 0 4px; + font-family: var(--font-sans); + font-size: 0.64rem; + color: var(--color-text-muted); +} + +// ============================================================ +// Tab strips — Quarto's panel-tabset and the Wakhan rank tabs, one look +// ============================================================ +.panel-tabset > .nav-tabs { + border-bottom: 1px solid var(--color-border); + gap: 2px; + margin-bottom: 0.9rem; + + .nav-link { + font-family: var(--font-sans); + font-size: 0.82rem; + font-weight: 600; + letter-spacing: 0.02em; + color: var(--color-text-muted); + border: none; + border-bottom: 2px solid transparent; + border-radius: 0; + padding: 8px 14px; + background: transparent; + transition: color 0.15s, border-color 0.15s; + + &:hover { color: var(--color-primary); } + &.active { + color: var(--color-primary); + background: transparent; + border-bottom-color: var(--color-primary); + } + } +} + +// Built by render_wakhan_cn_tabs() in R/utils.R; same underline treatment as the tabset +.wakhan-cn-tabs__nav { + display: flex; + flex-wrap: wrap; + gap: 2px; + margin-bottom: 0.9rem; + border-bottom: 1px solid var(--color-border); +} + +.wakhan-cn-tab { + font-family: var(--font-sans); + font-size: 0.82rem; + font-weight: 600; + letter-spacing: 0.02em; + color: var(--color-text-muted); + border: none; + border-bottom: 2px solid transparent; + border-radius: 0; + padding: 8px 14px; + background: transparent; + cursor: pointer; + transition: color 0.15s, border-color 0.15s; + + &:hover { color: var(--color-primary); } + &.active { color: var(--color-primary); border-bottom-color: var(--color-primary); } +} + +.wakhan-cn-pane { display: none; } +.wakhan-cn-pane.active { display: block; } + +// ============================================================ +// TOC / sidebar +// ============================================================ +#TOC { + font-family: var(--font-sans); + font-size: 0.8rem; + padding-right: 14px; + + ul { list-style: none; padding-left: 0; } + li { margin: 1px 0; } + + a { + color: var(--color-text-muted); + text-decoration: none; + display: block; + padding: 4px 10px; + border-radius: 6px; + border-left: 2px solid transparent; + transition: color 0.12s, background 0.12s, border-color 0.12s; + + &:hover { color: var(--color-primary); background: var(--color-primary-muted); } + &.active { + color: var(--color-primary); + font-weight: 600; + border-left-color: var(--color-primary); + background: color-mix(in srgb, var(--color-primary) 8%, transparent); + } + } +} + +.sidebar nav[role="doc-toc"] > h2, +#toc-title { + font-family: var(--font-sans); + font-size: 0.66rem; + font-weight: 600; + letter-spacing: 0.16em; + text-transform: uppercase; + color: var(--color-text-muted); + border: none; + padding: 0 0 0.4rem 10px; + margin: 0; +} + +// ============================================================ +// Circos — plate with the legend beside it +// ============================================================ +.circos-figure { + display: grid; + grid-template-columns: minmax(0, 1fr) 190px; + gap: 20px; + align-items: start; + margin-bottom: 1rem; +} + +@media (max-width: 900px) { + .circos-figure { grid-template-columns: minmax(0, 1fr); } +} + +// Both circos plates stay light in dark mode: their colours are calibrated for paper +.circos-container, +.bnd-circos { + background: #fcfbf7; + border: 1px solid #d8d3c8; + border-radius: var(--card-radius); + color: #1b1e22; +} + +.circos-container { + display: block; // see .report-figure: Quarto's `figure` class is inline-block + margin: 0; + padding: 18px; + + .report-figure__caption { color: #6b6153; } +} + +@media (prefers-color-scheme: dark) { + .circos-container, .bnd-circos { border-color: #4a4540; } +} + +.circos-eyebrow { + font-family: var(--font-mono); + font-size: 0.68rem; + font-weight: 500; + letter-spacing: 0.16em; + text-transform: uppercase; + color: var(--color-text-muted); + margin-bottom: 0.6rem; +} + +// Legend: vertical beside the genome-wide plate, horizontal under the breakend plate +.circos-legend { + display: flex; + flex-direction: column; + gap: 16px; + padding-top: 6px; + font-family: var(--font-mono); + font-size: 0.68rem; +} + +.bnd-circos ~ .circos-legend { + flex-direction: row; + flex-wrap: wrap; + gap: 16px 28px; + margin-top: 1rem; + padding-top: 0.85rem; + border-top: 1px solid var(--color-border); +} + +@media (max-width: 900px) { + .circos-figure .circos-legend { + flex-direction: row; + flex-wrap: wrap; + gap: 16px 28px; + } +} + +.circos-legend__group { + display: flex; + flex-direction: column; + gap: 4px; + min-width: 110px; +} + +.circos-legend__title { + font-size: 0.6rem; + font-weight: 600; + letter-spacing: 0.12em; + text-transform: uppercase; + color: var(--color-text-muted); + margin-bottom: 3px; +} + +.circos-legend__item { + display: flex; + align-items: center; + gap: 7px; + color: var(--color-text); + line-height: 1.3; +} + +// SNV swatches — round dots +.circos-swatch--dot { + width: 9px; + height: 9px; + border-radius: 50%; + flex-shrink: 0; + background: var(--_swatch); +} + +// SV / CNV swatches — short horizontal bar +.circos-swatch--bar { + width: 18px; + height: 3px; + border-radius: 2px; + flex-shrink: 0; + background: var(--_swatch); +} + +// BND/translocation — curved arc glyph via border trick +.circos-swatch--arc { + width: 14px; + height: 7px; + border-radius: 14px 14px 0 0; + border: 2px solid var(--_swatch); + border-bottom: none; + flex-shrink: 0; + background: transparent; +} + +@media print { + .circos-legend { border-top-color: #ccc; } + .circos-eyebrow { color: #666; } +} + +// ============================================================ +// Breakend circos — drawn client-side, cross-linked to the SV table +// ============================================================ +// Built by assets/js/bnd_circos.js and redrawn per filter; the JS sets geometry only, all styling is here +.bnd-circos { + padding: 18px 18px 10px; + max-width: 640px; + margin: 0 auto; + + // aspect-ratio: an inline without width/height falls back to 150px in some engines + svg { width: 100%; height: auto; aspect-ratio: 1 / 1; display: block; } + + .bnd-link { + fill: none; + stroke: var(--circos-bnd); + stroke-width: 1; + opacity: 0.5; + transition: opacity 0.12s ease, stroke 0.12s ease, stroke-width 0.12s ease; + } + // Filtered-out arcs are not drawn at all, so there is no dim state to style. + .bnd-link.is-selected { + stroke: var(--circos-bnd-selected); + stroke-width: 2.4; + opacity: 1; + } + + // Ideogram bands carry their Giemsa fill inline (data); the outline keeps sparse chromosomes reading as a block + .bnd-sector { fill: none; stroke: #b0a99c; stroke-width: 0.6; } + .bnd-band { stroke: none; } + + .bnd-gene-body { fill: var(--circos-bnd-gene); stroke: none; } + .bnd-gene-line { fill: none; stroke: #b8b2a6; stroke-width: 0.8; } + + .bnd-gene-label { + font-family: var(--font-sans); + font-size: 15px; // user-space units: the viewBox is 1000 wide + font-weight: 600; + fill: var(--circos-bnd-gene); + } + .bnd-chrom-label { + font-family: var(--font-sans); + font-size: 17px; + font-weight: 600; + fill: currentColor; + } + + .bnd-circos-empty { + text-align: center; + font-size: 0.8rem; + color: #6b6153; + padding: 3rem 0; + margin: 0; + } +} + +.bnd-circos-caption { + font-family: var(--font-mono); + font-size: 0.7rem; + letter-spacing: 0.04em; + color: var(--color-text-muted); + text-align: center; + margin: 0.55rem 0 0; +} + +// Rows picked in the SV table — the ones whose arcs are highlighted +#sv-table table.dataTable tbody tr { cursor: pointer; } +#sv-table table.dataTable tbody tr.bnd-selected td { + background: var(--color-primary-muted) !important; + box-shadow: inset 3px 0 0 var(--circos-bnd-selected); +} + +// ============================================================ +// Table footnote — provenance / caveats printed under a data table +// ============================================================ +.table-footnote { + font-size: 0.78rem; + line-height: 1.5; + color: var(--color-text-muted); + margin: 0.6rem 0 0; + max-width: 78ch; + + code { + font-size: 0.95em; + background: color-mix(in srgb, var(--color-text-muted) 10%, transparent); + padding: 0.05em 0.35em; + border-radius: 3px; + } + + // The consensus caveat is the one line a reader must not skim past. + .table-footnote__warn { color: var(--color-text); font-weight: 500; } +} + +// Footnotes fold away by default; the disclosure stays quiet until hovered +.table-details { + margin: 0.6rem 0 0; + + > summary { + cursor: pointer; + width: fit-content; + font-size: 0.72rem; + font-weight: 600; + letter-spacing: 0.06em; + text-transform: uppercase; + color: var(--color-text-muted); + opacity: 0.75; + list-style: none; // suppress the default triangle; ::before draws it + user-select: none; + + &::-webkit-details-marker { display: none; } + + &::before { + content: "▸"; + display: inline-block; + margin-right: 0.4em; + font-size: 0.9em; + transition: transform 0.12s ease; + } + + &:hover { opacity: 1; } + } + + &[open] > summary::before { transform: rotate(90deg); } + + // The body is a .table-footnote; its own top margin would double the gap. + > .table-footnote { margin-top: 0.4rem; } +} + +@media print { + .table-footnote { color: #666; } + // Print is static: a collapsed disclosure would drop the provenance + .table-details > .table-footnote { display: block !important; } + .table-details > summary { display: none; } +} + +// ============================================================ +// Callouts — the collapsible QC blocks and the ASCAT diagnostics +// ============================================================ +// Quarto's note callout without the icon and the blue: one surface, a teal left rule +.callout { + border-radius: var(--card-radius) !important; + border: 1px solid var(--color-border) !important; + border-left: 3px solid var(--color-primary) !important; + background: var(--color-surface) !important; + font-size: 0.88rem !important; + margin: 0 0 0.9rem !important; +} + +.callout .callout-header { + background: transparent !important; + padding: 0.6rem 0.9rem !important; + align-items: center; +} + +.callout .callout-icon-container { display: none !important; } + +.callout .callout-title, +.callout-header { + font-family: var(--font-sans); + font-weight: 600; + letter-spacing: 0.01em; +} + +.callout .callout-title-container h3 { + font-size: 0.95rem; + margin: 0; +} + +.callout .callout-body-container { padding: 0.2rem 0.9rem 0.6rem !important; } + +.callout .callout-toggle { opacity: 0.6; } + +// Footer line +main > p:last-child em, +.quarto-document-content > p:last-child em { + font-family: var(--font-mono); + font-style: normal; + font-size: 0.72rem; + letter-spacing: 0.03em; + color: var(--color-text-muted); +} + +// ============================================================ +// Max-width guard for full-page-layout +// ============================================================ +.page-full .quarto-title-block, +.page-full > .column-body { + max-width: 1400px; +} + +// ============================================================ +// Print stylesheet +// ============================================================ +@media print { + #TOC, .sidebar-navigation, .quarto-sidebar, + .dt-buttons, div.dt-buttons, .panel-controls, + // .facet__menu is a child of , so it has to be hidden separately from .facet + #custom-gene-panel, .facet, .facet__menu, .dataTables_filter, .dataTables_length, + .dataTables_paginate, .dataTables_info { display: none !important; } + + body { + background: #fff !important; + color: #000 !important; + } + + .dataTables_scrollBody { + height: auto !important; + max-height: none !important; + overflow: visible !important; + } + + table.dataTable { + thead th { background: #f0f0ec !important; color: #000 !important; } + tbody tr td { color: #000 !important; } + } + + .metric-card, .report-figure, .section-notice { + break-inside: avoid; + border: 1px solid #ddd !important; + } + + .metric-grid { grid-template-columns: repeat(4, 1fr) !important; } + .report-hero { border-color: #ccc; } + .circos-figure { grid-template-columns: minmax(0, 1fr) !important; } + + h2 { page-break-after: avoid; } + section { page-break-inside: avoid; } +} diff --git a/assets/lrsomatic_report/bin/render_report.R b/assets/lrsomatic_report/bin/render_report.R new file mode 100755 index 00000000..c638c1a8 --- /dev/null +++ b/assets/lrsomatic_report/bin/render_report.R @@ -0,0 +1,164 @@ +#!/usr/bin/env Rscript +suppressPackageStartupMessages({ + library(optparse) + library(quarto) + library(yaml) +}) + +# Repo root relative to this script: normalizePath() the script file (resolving a bin/ symlink) before dirname() +script_file = normalizePath(sub("--file=", "", commandArgs()[grep("--file=", commandArgs())])) +repo_dir = normalizePath(file.path(dirname(script_file), "..")) + +# Source helpers (needed for detect_reference and locate_outputs below) +source(file.path(repo_dir, "R/utils.R")) +source(file.path(repo_dir, "R/references.R")) +source(file.path(repo_dir, "R/locate_outputs.R")) + +# ---- CLI argument parsing ----------------------------------------------- +option_list = list( + make_option("--sample-dir", type = "character", default = NULL, + help = "Path to the sample output directory (required)"), + make_option("--sample-id", type = "character", default = NULL, + help = "Sample identifier, e.g. SAMPLE_ID (required)"), + make_option("--reference", type = "character", default = "auto", + help = "Reference genome: t2t | hg38 | auto (default: auto)"), + make_option("--sex", type = "character", default = NULL, + help = "Biological sex: male | female | XY | XX (required)"), + make_option("--gene-panel", type = "character", default = "none", + help = paste("Gene panel applied on load: none | builtin name (lymphoid) | path to TSV", + "(default: none, i.e. unfiltered). Repeatable — pass it several times to", + "open with several panels applied at once; a variant or SV is kept if it", + "hits any of them.")), + make_option("--output", type = "character", default = NULL, + help = "Output HTML path (default: _report.html in current dir)"), + make_option("--title", type = "character", default = NULL, + help = "Report title (default: 'LRSomatic Report – ')") +) + +# --gene-panel is repeatable (optparse has no action="append"): strip it from argv before parse_args() +argv = commandArgs(trailingOnly = TRUE) +gene_panel_args = extract_repeated_option(argv, "--gene-panel") +opt = parse_args(OptionParser(option_list = option_list), args = gene_panel_args$rest) +gene_panels = if (length(gene_panel_args$values) == 0) "none" else gene_panel_args$values + +# ---- Validate required arguments ---------------------------------------- +abort = function(...) { cat("ERROR:", ..., "\n"); quit(status = 1) } + +if (is.null(opt[["sample-dir"]])) abort("--sample-dir is required") +if (is.null(opt[["sex"]])) abort("--sex is required") + +sample_dir = normalizePath(opt[["sample-dir"]], mustWork = TRUE) +sample_id = if (!is.null(opt[["sample-id"]])) opt[["sample-id"]] else basename(sample_dir) +sex = tolower(trimws(opt[["sex"]])) +sex = switch(sex, xy = "male", xx = "female", sex) # normalise XY/XX + +output = if (!is.null(opt[["output"]])) opt[["output"]] else + file.path(getwd(), paste0(sample_id, "_report.html")) +title = if (!is.null(opt[["title"]])) opt[["title"]] else + paste0("LRSomatic Report – ", sample_id) + +# ---- Locate per-tool outputs --------------------------------------------- +message("Locating outputs in: ", sample_dir) +outputs = locate_outputs(sample_dir, sample_id) +message("Run mode: ", outputs$mode) +message("VEP somatic: ", ifelse(is.null(outputs$vep_somatic), "NOT FOUND", outputs$vep_somatic)) +message("Somatic VAF VCF: ", ifelse(is.null(outputs$somatic_vaf_vcf), "NOT FOUND", + paste(outputs$somatic_vaf_vcf, collapse = ", "))) +message("ASCAT segments: ", ifelse(is.null(outputs$ascat_segments), "NOT FOUND", outputs$ascat_segments)) + +# ---- Auto-detect reference (before the reference-specific gene panels) ---- +reference = opt[["reference"]] +if (reference == "auto") { + # Reuse already-resolved paths rather than a fixed vep/somatic/* glob + vep_file = outputs$vep_somatic + sv_file = if (is.null(vep_file)) { + hits = list.files(sample_dir, pattern = "severus_somatic\\.vcf\\.gz$", recursive = TRUE, full.names = TRUE) + if (length(hits) > 0) hits[1] else NA_character_ + } else NA_character_ + probe = if (!is.null(vep_file)) vep_file else if (!is.na(sv_file)) sv_file else NA_character_ + reference = if (!is.na(probe)) detect_reference(probe) else "t2t" + message("Auto-detected reference: ", reference) +} +reference = tolower(reference) + +# ---- Load all gene panels: every builtin ships in the report, --gene-panel only sets which are checked on load; "__all__" is the internal sentinel for none ---- +assets_dir = file.path(repo_dir, "assets") +all_panels = load_all_gene_panels(assets_dir, reference) + +# "none" combined with a real panel is contradictory +if (any(vapply(gene_panels, is_no_gene_panel, logical(1))) && length(gene_panels) > 1) { + abort("--gene-panel none cannot be combined with other panels; drop the 'none'.") +} +# Deduplicate by resolved path +gene_panels = unique(vapply(gene_panels, function(g) + if (file.exists(g)) normalizePath(g) else g, character(1))) + +default_panels = character(0) +for (gp in gene_panels) { + if (is_no_gene_panel(gp)) next + if (!is.null(builtin_panel_path(assets_dir, gp, reference))) { + # Load here so a builtin that fails against this reference aborts before the render + invisible(tryCatch(resolve_gene_panel(gp, assets_dir, reference), + error = function(e) abort(conditionMessage(e)))) + default_panels = c(default_panels, gp) + } else if (file.exists(gp)) { + # User-supplied TSV: register alongside the builtins so it is selectable in the report + nm = unique_panel_name(tools::file_path_sans_ext(basename(gp)), names(all_panels)) + all_panels[[nm]] = tryCatch(load_gene_panel(gp, reference), + error = function(e) abort(conditionMessage(e))) + default_panels = c(default_panels, nm) + } else { + abort(paste0("--gene-panel not found: tried builtin '", gp, + "' and as a file path. Use 'none' for no filtering.")) + } +} +default_panels = unique(default_panels) +# Sentinel rather than character(0): an empty vector round-trips through execute_params as NULL +if (length(default_panels) == 0) default_panels = "__all__" +message("Gene panels selected on load: ", paste(default_panels, collapse = ", ")) + +# ---- Render: copy templates/ and assets/ to a writable dir (the repo may be read-only and Quarto writes next to the .qmd) ---- +work = file.path(getwd(), "._render") +unlink(work, recursive = TRUE) +dir.create(work, recursive = TRUE) +invisible(file.copy(file.path(repo_dir, "templates"), work, recursive = TRUE)) +invisible(file.copy(file.path(repo_dir, "assets"), work, recursive = TRUE)) +template = file.path(work, "templates", "per_sample.qmd") +if (!file.exists(template)) abort("Quarto template not found: ", template) + +message("Rendering report to: ", output) +quarto::quarto_render( + input = template, + output_file = basename(output), + output_format = "html", + execute_params = list( + sample_id = sample_id, + sample_dir = sample_dir, + reference = reference, + sex = sex, + default_panels = default_panels, + all_panels = all_panels, + title = title, + repo_dir = repo_dir, + outputs = outputs + ), + quiet = FALSE +) + +# Move output if Quarto wrote it next to the template +rendered = file.path(dirname(template), basename(output)) +if (file.exists(rendered)) { + dest = normalizePath(output, mustWork = FALSE) + src = normalizePath(rendered, mustWork = FALSE) + if (src != dest) { + ok = file.copy(rendered, output, overwrite = TRUE) + if (ok) file.remove(rendered) + } +} +unlink(work, recursive = TRUE) + +if (file.exists(output)) { + message("Report written to: ", output) +} else { + abort("Rendering completed but output file not found at: ", output) +} diff --git a/assets/lrsomatic_report/templates/per_sample.qmd b/assets/lrsomatic_report/templates/per_sample.qmd new file mode 100644 index 00000000..f59d5e77 --- /dev/null +++ b/assets/lrsomatic_report/templates/per_sample.qmd @@ -0,0 +1,425 @@ +--- +title: "LRSomatic — per-sample genomics report" +date: today +format: + html: + self-contained: true + toc: true + toc-depth: 3 + toc-location: left + theme: [flatly, ../assets/styles/report.scss] + code-fold: true + page-layout: full +params: + sample_id: "SAMPLE" + sample_dir: "" + reference: "t2t" + sex: "female" + default_panels: "__all__" # panel keys checked on load; "__all__" = none checked + all_panels: NULL # named list from load_all_gene_panels() + title: "LRSomatic Report" + repo_dir: "." + outputs: NULL # named list from locate_outputs() +--- + +```{r setup, include=FALSE} +knitr::opts_chunk$set(echo = FALSE, message = FALSE, warning = FALSE) +suppressPackageStartupMessages({ + library(data.table) + library(dplyr) + library(DT) + library(htmltools) + library(ggplot2) +}) + +repo_dir = params$repo_dir +source(file.path(repo_dir, "R/utils.R")) +source(file.path(repo_dir, "R/references.R")) +source(file.path(repo_dir, "R/locate_outputs.R")) +source(file.path(repo_dir, "R/parse_smallvariants.R")) +source(file.path(repo_dir, "R/parse_severus.R")) +source(file.path(repo_dir, "R/parse_ascat.R")) +source(file.path(repo_dir, "R/parse_qc.R")) +source(file.path(repo_dir, "R/circos.R")) +source(file.path(repo_dir, "R/circos_bnd.R")) + +source(file.path(repo_dir, "R/sections.R")) +for (f in list.files(file.path(repo_dir, "R/sections"), pattern = "\\.R$", full.names = TRUE)) { + source(f) +} + +outputs = params$outputs +sample_id = params$sample_id +sample_dir = params$sample_dir + +# Section-module contract: each section owns locate() and parse(); see CLAUDE.md +SECTION_DATA = list() +for (s in SECTIONS) { + SECTION_DATA[[s$id]] = s$parse(s$locate(sample_dir, sample_id), SECTION_DATA) +} + +# Load reference data +cytobands = load_cytobands(params$reference, file.path(repo_dir, "assets")) +chrom_lens = load_chrom_lengths(params$reference, file.path(repo_dir, "assets")) +chromosomes = chromosomes_for_sex(params$sex) +chromosomes = chromosomes[chromosomes %in% unique(cytobands$chrom)] + +# Panels checked on load (empty for --gene-panel none); only the summary cards use them, the tables filter client-side. Not tryCatch-wrapped: an unresolvable panel must fail the render +panels = resolve_selected_panels(params$default_panels, params$all_panels, + file.path(repo_dir, "assets"), params$reference) +panel_genes = unique(unlist(lapply(panels, `[[`, "genes"), use.names = FALSE)) + +# Parse ASCAT +ascat_segments = parse_ascat_segments(outputs$ascat_segments) +ascat_pp = parse_ascat_purityploidy(outputs$ascat_purityploidy) + +# Parse Wakhan +wakhan_solutions = parse_wakhan_solutions(outputs$wakhan_solutions) +wakhan_cn_plots = locate_wakhan_cn_plots(outputs$wakhan_dir, wakhan_solutions) + +# Parse QC +qc_mosdepth = parse_mosdepth_summary(outputs$mosdepth_summary, names(chrom_lens)) +qc_mosdist = parse_mosdepth_dist(outputs$mosdepth_dist) +qc_cramino = parse_cramino(outputs$cramino) +qc_flagstat = parse_flagstat(outputs$flagstat) +samtools_stats = parse_samtools_stats(outputs$samtools_stats) +qc_normal_mosdepth = parse_mosdepth_summary(outputs$normal_mosdepth_summary, names(chrom_lens)) +qc_normal_cramino = parse_cramino(outputs$normal_cramino) +qc_normal_flagstat = parse_flagstat(outputs$normal_flagstat) +qc_normal_samtools_stats = parse_samtools_stats(outputs$normal_samtools_stats) + +# Parse VEP + raw callers +vep_data = parse_vep(outputs$vep_somatic) + +vaf_data = parse_caller_vcf(outputs$somatic_vaf_vcf, "somatic", sample_id = params$sample_id) + +# Source of the VAF/DP/GT/PS columns, for the footnote (ambiguous after a consensus merge) +vaf_prov = vaf_provenance(outputs$somatic_vaf_vcf, sample_dir, sample_id = params$sample_id) + +variant_table = build_variant_table(vep_data, vaf_data, gene_panel = NULL) +tmb_info = compute_tmb(variant_table) + +# Join coverage: a silently failing variant_key() shows up here as a near-zero count +n_vaf = if (!is.null(variant_table) && "vaf" %in% names(variant_table)) + sum(!is.na(variant_table$vaf)) else NA_integer_ +# Variants reported by more than one caller; always 0 on the VEP text path +n_multi = if (!is.null(variant_table) && "callers" %in% names(variant_table)) + sum(grepl(",", variant_table$callers, fixed = TRUE)) else 0L + +# SNV data for circos (from VEP file — contains all somatic variants) +snv_circos = NULL +if (!is.null(vep_data) && nrow(vep_data) > 0) { + snv_circos = unique(vep_data[, .(chrom, pos, ref, alt)]) +} + +# Draw circos to temp file, then embed as base64 +circos_tmp = tempfile(fileext = ".svg") +tryCatch({ + draw_circos( + snv_data = snv_circos, + sv_nontrans = SECTION_DATA$sv$circos$nontrans, + sv_trans = SECTION_DATA$sv$circos$translocations, + cnv_data = ascat_segments, + cytobands = cytobands, + chrom_lengths = chrom_lens, + chromosomes = chromosomes, + output_path = circos_tmp + ) +}, error = function(e) { + message("Circos plot failed: ", e$message) + circos_tmp <<- NULL +}) + +# Summary counts +sv_table = SECTION_DATA$sv$table +n_snv = if (!is.null(vep_data)) nrow(unique(vep_data[, .(chrom, pos, ref, alt)])) else NA_integer_ +# One rearrangement per row (mates already collapsed) +n_sv = if (!is.null(sv_table) && nrow(sv_table) > 0) nrow(sv_table) else + if (!is.null(SECTION_DATA$sv)) + nrow(SECTION_DATA$sv$circos$nontrans) + + nrow(SECTION_DATA$sv$circos$translocations) else NA_integer_ +# Interchromosomal breakends, apart from the intra-chromosomal ones +n_trans = if (!is.null(sv_table) && "svclass" %in% names(sv_table)) + sum(sv_table$svclass == "translocation", na.rm = TRUE) else NA_integer_ +n_intra_bnd = if (!is.null(sv_table) && "svclass" %in% names(sv_table)) + sum(sv_table$svclass == "intra-chr breakend", na.rm = TRUE) else NA_integer_ +# No panel checked: cards read "N/A" rather than a misleading "0"; several panels union +have_panel = length(panels) > 0 && length(panel_genes) > 0 +n_panel_vars = if (!have_panel) NA_integer_ else + if (!is.null(variant_table)) + sum(variant_table$symbol %in% panel_genes, na.rm = TRUE) else 0L +# Same test and windows as the client-side filter (sv_panel_hits()) +sv_panel_hit = if (!is.null(sv_table) && nrow(sv_table) > 0) + sv_panel_hits(sv_table, panels) else character(0) +n_panel_svs = if (!have_panel) NA_integer_ else sum(nzchar(sv_panel_hit)) +``` + +```{r panel-js-data, results='asis'} +all_p = if (!is.null(params$all_panels) && length(params$all_panels) > 0) + params$all_panels else list() + +# Each panel ships symbols and, if coordinate-carrying, intervals; windows come from R (SV_PANEL_WINDOW_*) so card and filter agree +panel_defs = vapply(names(all_p), function(nm) { + p = all_p[[nm]] + syms = paste0("new Set([", + paste(js_quote(toupper(as.character(p$genes))), collapse = ","), "])") + ivs = if (isTRUE(p$has_coords)) + paste0("[", paste(sprintf("[%s,%s,%s,%s]", + js_quote(p$chrom), as.integer(p$start), as.integer(p$end), + js_quote(toupper(as.character(p$interval_gene)))), + collapse = ","), "]") + else "[]" + sprintf("%s: {symbols: %s, hasCoords: %s, intervals: %s}", + js_quote(nm), syms, if (isTRUE(p$has_coords)) "true" else "false", ivs) +}, character(1)) + +cat("\n") +``` + +{{< include sections/_header.qmd >}} + +{{< include sections/_circos.qmd >}} + +{{< include sections/_ascat.qmd >}} + +{{< include sections/_gene_filter.qmd >}} + +{{< include sections/_smallvariants.qmd >}} + +{{< include sections/_sv.qmd >}} + +{{< include sections/_qc.qmd >}} + +*Report generated `r format(Sys.time(), "%Y-%m-%d %H:%M")` · LRSomatic report v1.3.1* + +```{=html} + +``` + +```{r facet-filter-js, results='asis'} +# Tickbox column filters, inlined from facet_filter.js (lintable JS, self-contained report); reads window.*_FACETS / *_COLS when a table announces itself +cat("\n") +``` diff --git a/assets/lrsomatic_report/templates/sections/_ascat.qmd b/assets/lrsomatic_report/templates/sections/_ascat.qmd new file mode 100644 index 00000000..e63b0f05 --- /dev/null +++ b/assets/lrsomatic_report/templates/sections/_ascat.qmd @@ -0,0 +1,106 @@ +## Copy number profile + +```{r cn-setup} +has_any_ascat_plot = !is.null(outputs$ascat_plots) && + any(vapply(outputs$ascat_plots, function(x) !is.null(x) && file.exists(x), logical(1))) +``` + +```{r cn-outer-tabset-open, results='asis'} +cat("::: {.panel-tabset}\n\n") +cat("### ASCAT\n\n") +``` + +```{r ascat-unavailable} +if (!has_any_ascat_plot) { + section_notice("No ASCAT plots found for this sample — ASCAT may have failed or was not run.") +} +``` + +```{r ascat-inner-tabset-open, results='asis', eval=has_any_ascat_plot} +cat("::: {.panel-tabset}\n\n") +cat("#### Fitted CN profile\n\n") +``` + +```{r ascat-profile, eval=has_any_ascat_plot} +p = embed_png(outputs$ascat_plots$profile, caption = "ASCAT fitted copy-number profile") +if (!is.null(p)) p else section_notice("Plot not produced — ASCAT may have failed for this sample.") +``` + +```{r ascat-inner-rawprofile-header, results='asis', eval=has_any_ascat_plot} +cat("\n#### Raw logR + BAF\n\n") +``` + +```{r ascat-rawprofile, eval=has_any_ascat_plot} +p = embed_png(outputs$ascat_plots$aspcf, caption = "Raw logR and BAF, segmented (ASPCF)") +if (!is.null(p)) p else section_notice("Plot not produced — ASCAT may have failed for this sample.") +``` + +```{r ascat-inner-sunrise-header, results='asis', eval=has_any_ascat_plot} +cat("\n#### Sunrise (purity × ploidy)\n\n") +``` + +```{r ascat-sunrise, eval=has_any_ascat_plot} +p = embed_png(outputs$ascat_plots$sunrise, caption = "Sunrise plot: goodness of fit over purity × ploidy") +if (!is.null(p)) p else section_notice("Plot not produced — ASCAT may have failed for this sample.") +``` + +```{r ascat-inner-tabset-close, results='asis', eval=has_any_ascat_plot} +cat("\n:::\n\n") +``` + +```{r ascat-diag-open, results='asis', eval=has_any_ascat_plot} +cat('::: {.callout-note collapse="true" title="Diagnostic plots"}\n\n') +``` + +```{r ascat-diagnostics, eval=has_any_ascat_plot} +# Each diagnostic is its own captioned figure; a NULL (file absent) simply drops out. +htmltools::tagList( + embed_png(outputs$ascat_plots$before_gc, max_width = "700px", caption = "Pre-GC correction"), + embed_png(outputs$ascat_plots$after_gc, max_width = "700px", caption = "Post-GC correction"), + embed_png(outputs$ascat_plots$tumour_sep, max_width = "700px", caption = "Tumour separation") +) +``` + +```{r ascat-diag-close, results='asis', eval=has_any_ascat_plot} +cat("\n:::\n\n") +``` + +```{r cn-wakhan-tab-header, results='asis'} +cat("\n### Wakhan\n\n") +``` + +```{r wakhan-status} +if (!outputs$has_wakhan) { + section_notice("Wakhan was not run for this sample.") +} else if (is.null(wakhan_solutions) && is.null(outputs$wakhan_heatmap) && length(wakhan_cn_plots) == 0) { + section_notice("Wakhan output directory found, but no recognised solutions table or plots inside it.") +} +``` + +```{r wakhan-solutions-table} +if (!is.null(wakhan_solutions)) { + DT::datatable( + wakhan_solutions, + rownames = FALSE, + options = list(dom = "t", pageLength = nrow(wakhan_solutions)) + ) +} +``` + +```{r wakhan-heatmap} +p = embed_html_iframe(outputs$wakhan_heatmap, height = "600px") +if (!is.null(p)) htmltools::tags$figure(class = "report-figure", p, + htmltools::tags$figcaption(class = "report-figure__caption", "Ploidy × purity solutions")) +``` + +```{r wakhan-cn-plots-header, results='asis', eval=length(wakhan_cn_plots) > 0} +cat('\n

Genome copy number + breakpoints, one tab per ranked solution

\n\n') +``` + +```{r wakhan-cn-plots, eval=length(wakhan_cn_plots) > 0} +render_wakhan_cn_tabs(wakhan_cn_plots) +``` + +```{r cn-outer-tabset-close, results='asis'} +cat("\n:::\n\n") +``` diff --git a/assets/lrsomatic_report/templates/sections/_circos.qmd b/assets/lrsomatic_report/templates/sections/_circos.qmd new file mode 100644 index 00000000..4f3eb518 --- /dev/null +++ b/assets/lrsomatic_report/templates/sections/_circos.qmd @@ -0,0 +1,76 @@ +## Circos overview + +```{r circos-plot, fig.align='center'} +#| echo: false +if (!is.null(circos_tmp) && file.exists(circos_tmp)) { + + img_b64 = base64enc::base64encode(circos_tmp) + + # HTML legend — four groups, swatches use --circos-* CSS vars + snv_items = list( + list(label = "C→A", var = "--circos-snv-ca"), + list(label = "C→G", var = "--circos-snv-cg"), + list(label = "C→T", var = "--circos-snv-ct"), + list(label = "T→A", var = "--circos-snv-ta"), + list(label = "T→C", var = "--circos-snv-tc"), + list(label = "T→G", var = "--circos-snv-tg") + ) + sv_items = list( + list(label = "INS", var = "--circos-sv-ins"), + list(label = "DEL", var = "--circos-sv-del"), + list(label = "INV", var = "--circos-sv-inv"), + list(label = "DUP", var = "--circos-sv-dup") + ) + cnv_items = list( + list(label = "Major", var = "--circos-cnv-major"), + list(label = "Minor", var = "--circos-cnv-minor"), + list(label = "Total", var = "--circos-cnv-total") + ) + + make_items = function(items, swatch_type) { + lapply(items, function(x) { + tags$div(class = "circos-legend__item", + tags$span(class = paste0("circos-swatch--", swatch_type), + style = paste0("--_swatch: var(", x$var, ")")), + x$label + ) + }) + } + + # Plate and legend side by side (.circos-figure grid); the track order is the caption + tags$div(class = "circos-figure", + tags$figure(class = "circos-container", + tags$img(src = paste0("data:image/svg+xml;base64,", img_b64), + style = "max-width:680px; display:block; margin:auto;"), + tags$figcaption(class = "report-figure__caption", + "Tracks, outer to inner: ideogram · SNV (SBS-6) · SV · copy number") + ), + tags$div(class = "circos-legend", + tags$div(class = "circos-legend__group", + tags$div(class = "circos-legend__title", "SNV type"), + make_items(snv_items, "dot") + ), + tags$div(class = "circos-legend__group", + tags$div(class = "circos-legend__title", "Structural variants"), + make_items(sv_items, "bar") + ), + tags$div(class = "circos-legend__group", + tags$div(class = "circos-legend__title", "Copy number"), + make_items(cnv_items, "bar") + ), + tags$div(class = "circos-legend__group", + tags$div(class = "circos-legend__title", "Translocation"), + tags$div(class = "circos-legend__item", + tags$span(class = "circos-swatch--arc", + style = "--_swatch: var(--circos-bnd)"), + "BND link" + ) + ) + ) + ) + +} else { + section_notice(paste("Circos plot could not be generated. Check that ASCAT and Severus", + "output files are present."), warn = TRUE) +} +``` diff --git a/assets/lrsomatic_report/templates/sections/_gene_filter.qmd b/assets/lrsomatic_report/templates/sections/_gene_filter.qmd new file mode 100644 index 00000000..56c082f1 --- /dev/null +++ b/assets/lrsomatic_report/templates/sections/_gene_filter.qmd @@ -0,0 +1,60 @@ +## Gene panel filter + +```{r gene-filter-note} +table_details( + summary = "What the panel filter applies to", + "Applies to both the small-variant and structural-variant tables below. Tick any number", + "of panels: a variant or SV is kept if it hits", tags$strong("any"), "of them, and with none", + "ticked the tables are unfiltered. Small variants match on gene symbol; SVs match on", + "breakend position when the panel carries coordinates — see the note under the SV table", + "for which mode each ticked panel is in.", + tags$br(), + "With more than one panel ticked, each panel_hit entry names the panel it matched in", + "square brackets.", + tags$br(), + "A custom list is bare symbols, which carry no coordinates, so its SVs are matched on", + "the annotated breakend genes only — no positional window." +) +``` + +```{r gene-filter-ui, results='asis'} +# One checkbox per registered panel; no box ticked is the unfiltered state; load-time ticks are params$default_panels +all_p = if (!is.null(params$all_panels) && length(params$all_panels) > 0) + params$all_panels else list() +selected = setdiff(as.character(unlist(params$default_panels)), "__all__") + +chip = function(value, label) { + paste0(' \n') +} + +chips = "" +for (nm in names(all_p)) { + label = paste0(toupper(substr(nm, 1, 1)), substr(nm, 2, nchar(nm))) + chips = paste0(chips, chip(nm, label)) +} +chips = paste0(chips, chip("__custom__", "Custom…")) + +cat(paste0(' +
+ Gene panels: +
+', chips, '
+ + + + +
+ +')) +``` diff --git a/assets/lrsomatic_report/templates/sections/_header.qmd b/assets/lrsomatic_report/templates/sections/_header.qmd new file mode 100644 index 00000000..a180b614 --- /dev/null +++ b/assets/lrsomatic_report/templates/sections/_header.qmd @@ -0,0 +1,82 @@ +```{r report-hero} +mode_css = if (outputs$mode == "matched") "is-matched" else "is-tumour-only" +tags$header( + class = "report-hero", + # No eyebrow: Quarto's own title line directly above already says what this document is. + div(class = "report-hero__title", params$sample_id), + div(class = "report-hero__badges", + tags$span(class = paste("report-badge", mode_css), toupper(outputs$mode)), + tags$span(class = "report-badge is-meta", toupper(params$reference)), + tags$span(class = "report-badge is-meta", toupper(params$sex)) + ) +) +``` + +```{r summary-cards} +fmt_val = function(x, digits = 2) { + if (is.na(x)) return("N/A") + if (is.numeric(x) && !is.integer(x)) return(round(x, digits)) + as.character(x) +} + +card = function(label, value, css_class = "", subtitle = NULL) { + div( + class = paste("metric-card", css_class), + div(class = "metric-card__label", label), + div(class = "metric-card__value", value), + if (!is.null(subtitle)) + div(class = "metric-card__subtitle", subtitle) + ) +} + +# One HTML string, not nested tags: htmltools' newlines rendered the label as "SNV s" +lc_plural = function(text) { + stopifnot(endsWith(text, "s")) + HTML(paste0(htmlEscape(substr(text, 1, nchar(text) - 1L)), + 's')) +} + +# Three labelled groups instead of one grid of eleven numbers +metric_group = function(title, ...) { + div(class = "metric-group", + div(class = "metric-group__title", title), + div(class = "metric-grid", ...) + ) +} + +div(class = "metric-groups", + metric_group("Tumour", + card("Purity", fmt_val(ascat_pp$purity), "metric-purity"), + card("Ploidy", fmt_val(ascat_pp$ploidy), "metric-ploidy"), + card("Coding TMB", + if (!is.na(tmb_info$tmb)) fmt_val(tmb_info$tmb) else "N/A", + "metric-tmb", + subtitle = if (!is.na(tmb_info$n_nonsyn)) + paste0("mut/Mb · ", tmb_info$n_nonsyn, " non-syn / ", tmb_info$denominator_mb, " Mb") + else if (!is.na(tmb_info$tmb)) "mut/Mb" else NULL) + ), + metric_group("Somatic variants", + card(lc_plural("SNVs"), fmt_val(n_snv, 0), "metric-snvs"), + # One row per rearrangement, not per breakend record — see the note under the SV table. + card(lc_plural("SVs"), fmt_val(n_sv, 0), "metric-svs", + subtitle = if (!is.na(n_trans) && !is.na(n_intra_bnd)) + paste0(n_trans, " interchrom · ", n_intra_bnd, " intrachrom BND") else NULL), + card("Panel variants",fmt_val(n_panel_vars, 0), "metric-panel-vars"), + card(lc_plural("Panel SVs"), fmt_val(n_panel_svs, 0), "metric-panel-svs") + ), + metric_group("Sequencing", + card("Mean coverage", paste0(fmt_val(qc_mosdepth$mean_depth), "×"), "metric-coverage"), + card("Read N50", if (!is.na(qc_cramino$n50)) fmt_bp(qc_cramino$n50) else "N/A", "metric-n50"), + card("Error rate", + if (!is.null(samtools_stats) && !is.na(samtools_stats$error_rate)) + paste0(formatC(samtools_stats$error_rate * 100, format = "f", digits = 3), "%") else "N/A", + "metric-error"), + card("Phased variants", + { w = SECTION_DATA$whatshap$all + if (!is.null(w) && !is.na(w$phased_fraction)) + paste0(fmt_val(w$phased_fraction * 100, 1), "%") else "N/A" }, + "metric-phased", + subtitle = "germline, WhatsHap") + ) +) +``` diff --git a/assets/lrsomatic_report/templates/sections/_qc.qmd b/assets/lrsomatic_report/templates/sections/_qc.qmd new file mode 100644 index 00000000..f8e91219 --- /dev/null +++ b/assets/lrsomatic_report/templates/sections/_qc.qmd @@ -0,0 +1,74 @@ +## QC details + +::: {.callout-note collapse="true"} +### Coverage summary + +```{r coverage-table} +# The widget must be the chunk's value, not print()ed: under quarto_render() print.htmlwidget writes to a temp file and emits nothing +cov_dt = function(x) DT::datatable(x, rownames = FALSE, + options = list(pageLength = 30, dom = "ft", + scrollY = "300px")) +show_normal_cov = outputs$has_normal && !is.null(qc_normal_mosdepth) && nrow(qc_normal_mosdepth$table) > 0 +have_cov = !is.null(qc_mosdepth$table) && nrow(qc_mosdepth$table) > 0 + +htmltools::tagList( + if (show_normal_cov) tags$p(tags$strong("Tumour")), + if (have_cov) cov_dt(qc_mosdepth$table) else section_notice("Mosdepth summary not available."), + if (show_normal_cov) tags$p(tags$strong("Normal")), + if (show_normal_cov) cov_dt(qc_normal_mosdepth$table) +) +``` +::: + +::: {.callout-note collapse="true"} +### Alignment statistics (samtools flagstat) + +```{r flagstat-table, results='asis'} +show_normal_fs = outputs$has_normal && length(qc_normal_flagstat) > 0 +if (show_normal_fs) cat("**Tumour**\n\n") +if (length(qc_flagstat) > 0) { + fs = data.frame(metric = names(qc_flagstat), value = unlist(qc_flagstat)) + print(knitr::kable(fs, row.names = FALSE)) +} else { + cat("Flagstat file not available.\n") +} +if (show_normal_fs) { + cat("\n\n**Normal**\n\n") + fs_n = data.frame(metric = names(qc_normal_flagstat), value = unlist(qc_normal_flagstat)) + print(knitr::kable(fs_n, row.names = FALSE)) +} +``` +::: + +::: {.callout-note collapse="true"} +### Read quality + alignment statistics + +```{r cramino-table, results='asis'} +make_quality_df = function(cr, st) { + rows = list() + rows[["N50 (bp)"]] = fmt_val(cr$n50, 0) + rows[["Yield (Gb)"]] = fmt_val(cr$yield_gb) + rows[["% mapped"]] = fmt_val(cr$mapped_pct) + rows[["# reads"]] = fmt_val(cr$n_reads, 0) + if (!is.null(st)) { + rows[["Avg read length (bp)"]] = fmt_val(st$avg_length, 0) + rows[["Max read length (bp)"]] = fmt_val(st$max_length, 0) + rows[["Avg base quality"]] = fmt_val(st$avg_quality) + rows[["Bases mapped (Gb)"]] = fmt_val(st$bases_mapped / 1e9) + rows[["Error rate"]] = if (!is.na(st$error_rate)) + paste0(formatC(st$error_rate * 100, format = "f", digits = 3), "%") else "N/A" + } + data.frame(metric = names(rows), value = unlist(rows), row.names = NULL) +} + +show_normal_cr = outputs$has_normal +if (show_normal_cr) cat("**Tumour**\n\n") +print(knitr::kable(make_quality_df(qc_cramino, samtools_stats), row.names = FALSE)) +if (show_normal_cr) { + cat("\n\n**Normal**\n\n") + print(knitr::kable(make_quality_df(qc_normal_cramino, qc_normal_samtools_stats), row.names = FALSE)) +} +``` +::: + +{{< include sections/_whatshap.qmd >}} diff --git a/assets/lrsomatic_report/templates/sections/_smallvariants.qmd b/assets/lrsomatic_report/templates/sections/_smallvariants.qmd new file mode 100644 index 00000000..b0322c68 --- /dev/null +++ b/assets/lrsomatic_report/templates/sections/_smallvariants.qmd @@ -0,0 +1,113 @@ +## Small variants + +```{r small-variant-prepare, results='asis'} +if (!is.null(variant_table) && nrow(variant_table) > 0) { + # Format the VAF as a percentage + dt_display = copy(variant_table) + if ("vaf" %in% names(dt_display)) { + dt_display[, vaf := round(vaf * 100, 1)] + setnames(dt_display, "vaf", "VAF%") + } + # The panel filter reads the symbol column by name, not by a hard-coded position. + cat("\n", + sep = "") + + # Tickbox facet values for the SNV table (see js_facet_defs() in R/utils.R), built from the display frame so names match SNV_COLS; the requested list is published too, since knitr swallows the omission message + snv_facet_cols = c("consequence", "impact", "callers") + cat("\n", sep = "") + cat("\n", sep = "") +} +``` + +```{r small-variant-table} +if (!is.null(variant_table) && nrow(variant_table) > 0) { + + # Flag cells whose VAF/DP/GT/PS came from a consensus winner; styleEqual() needs literal values + mc_vals = if ("callers" %in% names(dt_display)) + unique(grep(",", dt_display$callers, fixed = TRUE, value = TRUE)) else + character(0) + + snv_dt = DT::datatable( + dt_display, + rownames = FALSE, + filter = "top", + elementId = "snv-table", + extensions = c("Buttons", "Scroller"), + options = list( + dom = "Bfrtip", + buttons = c("copy", "csv"), + scrollX = TRUE, + scrollY = "400px", + scroller = TRUE, + deferRender = TRUE, + pageLength = 25, + columnDefs = list(list(className = "dt-left", targets = "_all")), + initComplete = JS("function() { window.snvTableElem = this.api().table().node(); }") + ) + ) |> + DT::formatStyle( + columns = "impact", + target = "cell", + backgroundColor = DT::styleEqual( + c("HIGH", "MODERATE", "LOW", "MODIFIER"), + c("#f7e3df", "#f6edd6", "#e4efe3", "#f3f1ea") + ) + ) + + if (length(mc_vals) > 0) { + snv_dt = DT::formatStyle( + snv_dt, + columns = "callers", + target = "cell", + # Outside the impact palette so two columns do not read as one scale + backgroundColor = DT::styleEqual(mc_vals, rep("#e6ecf5", length(mc_vals))) + ) + } + + # Provenance footnote: which VCF supplied VAF/DP/GT/PS, its coverage, and the ambiguous multi-caller rows (n_multi is 0 on the VEP text path) + footnote = table_details( + summary = "VAF provenance", + tags$p( + if (!is.null(vaf_prov)) { + tagList( + "VAF, depth, genotype and phase set are joined from ", + lapply(seq_along(vaf_prov$paths), function(i) { + tagList(if (i > 1) ", ", tags$code(vaf_prov$paths[i])) + }), + # Punctuation rides with the preceding element (adjacent tagList members render with a space) + if (length(vaf_prov$sources) > 0) + paste0(" (", paste(vaf_prov$sources, collapse = ", "), ");") else ";", + "the variant set itself comes from the VEP annotation.", + # Named only when the VCF held more than one sample + if (length(vaf_prov$sample) > 0) + sprintf("Read from sample %s.", paste(vaf_prov$sample, collapse = ", ")) else NULL, + if (!is.na(n_vaf)) + sprintf("%s of %s variants carry a VAF.", + format(n_vaf, big.mark = ","), + format(nrow(variant_table), big.mark = ",")) else NULL + ) + } else { + "No VAF source VCF was found, so the VAF, depth, genotype and phase set columns are empty." + }, + if (length(mc_vals) > 0) tagList( + tags$br(), + tags$span( + class = "table-footnote__warn", + sprintf(paste("%s variants were reported by more than one caller (highlighted).", + "Their VAF, depth, genotype and phase set come from whichever caller", + "won the consensus merge, so those columns need not correspond to the", + "callers column beside them."), + format(n_multi, big.mark = ",")) + ) + ) + ) + ) + + tagList(snv_dt, footnote) +} +``` diff --git a/assets/lrsomatic_report/templates/sections/_sv.qmd b/assets/lrsomatic_report/templates/sections/_sv.qmd new file mode 100644 index 00000000..02e5d632 --- /dev/null +++ b/assets/lrsomatic_report/templates/sections/_sv.qmd @@ -0,0 +1,409 @@ +## Structural variants + +```{r sv-info} +# Built from the caller VCF, so it survives a missing VEP SV VCF +if (is.null(sv_table) || nrow(sv_table) == 0) { + section_notice("No somatic structural variants detected.") +} +``` + +```{r sv-bnd-circos} +# Breakend circos: R selects and serialises the data, assets/js/bnd_circos.js draws it so it re-lays-out per filter (see R/circos_bnd.R) +bnd_res = NULL +if (!is.null(sv_table) && nrow(sv_table) > 0) { + bnd_res = tryCatch({ + # One filtered set feeds both calls + bnd_drawn = bnd_links(sv_table, chromosomes) + bnd_circos_data(bnd_drawn, + bnd_panel_genes(bnd_drawn, params$all_panels), + cytobands, chrom_lens, chromosomes) + }, error = function(e) { + message("Breakend circos failed: ", conditionMessage(e)) + NULL + }) +} + +if (!is.null(bnd_res) && !is.null(bnd_res$data)) { + legend_item = function(swatch, var, label) { + tags$div(class = "circos-legend__item", + tags$span(class = paste0("circos-swatch--", swatch), + style = paste0("--_swatch: var(", var, ")")), + label) + } + tagList( + # The chromosome count is filled in by the plot, since it changes with the filter. + tags$p(class = "circos-eyebrow", + tags$span(id = "bnd-eyebrow", "Breakends"), + " · select a row below to highlight its arc"), + tags$div(class = "bnd-circos", id = "bnd-circos"), + tags$div(class = "circos-legend", + tags$div(class = "circos-legend__group", + tags$div(class = "circos-legend__title", "Breakend circos"), + legend_item("arc", "--circos-bnd", "Rearrangement"), + legend_item("arc", "--circos-bnd-selected", "Selected in the table"), + legend_item("bar", "--circos-bnd-gene", "Panel gene") + ) + ), + tags$p(class = "bnd-circos-caption", tags$span(id = "bnd-shown-count")) + ) +} else if (!is.null(bnd_res)) { + section_notice(bnd_res$reason) +} +``` + +```{r sv-bnd-circos-data, results='asis'} +# Payload, then the drawing code inlined from bnd_circos.js (lintable JS, self-contained report) +if (!is.null(bnd_res) && !is.null(bnd_res$data)) { + cat(bnd_circos_script(bnd_res), "\n") + cat("\n") +} +``` + +```{r sv-prepare, results='asis'} +# Column positions published from R, not scraped from the header +if (!is.null(sv_table) && nrow(sv_table) > 0) { + sv_display = copy(sv_table) + # Populated client-side by the panel filter; load-time hits are already in sv_panel_hit + sv_display[, panel_hit := ""] + # Readable locus/size/gene columns; the raw bedpe columns stay (hidden, exported, read by the JS). See sv_display_columns() + sv_display = cbind(sv_display, sv_display_columns(sv_display, chromosomes)) + setcolorder(sv_display, c("id", "panel_hit", "svclass", "svtype", + "locus", "size", "genes", + "vaf", "consequence", "impact", "caller")) + cat("\n", + sep = "") + + # Tickbox facet values (facet_filter.js), emitted after setcolorder; `caller` has one value and is omitted + sv_facet_cols = c("svclass", "svtype", "impact", "consequence", "caller") + cat("\n", sep = "") + cat("\n", sep = "") +} +``` + +```{r sv-table} +if (!is.null(sv_table) && nrow(sv_table) > 0) { + idx0 = function(nm) which(names(sv_display) == nm) - 1L + + # Truncate the display only; sort/search/export renderings return the full list + gene_render = JS( + "function(data, type) {", + " if (type !== 'display' || !data) return data;", + " const g = String(data).split(',');", + " if (g.length <= 6) return data;", + " return '' +", + " g.slice(0, 6).join(',') + ' +' + (g.length - 6) + ' more';", + "}") + + # Same predicate as the row filter, so the column always agrees with what is shown. + panel_hit_render = JS( + "function(data, type, row) {", + " return window.svPanelHitLabel ? window.svPanelHitLabel(row, window.SV_COLS) : '';", + "}") + + # Sort `locus`/`size` on their hidden numeric keys; display/filter/export keep the readable string + orthogonal_render = function(key) JS( + "function(data, type, row) {", + " if (type !== 'sort' && type !== 'type') return data;", + " const cols = window.SV_COLS || {};", + sprintf(" const k = cols['%s'];", key), + " return k === undefined ? data : row[k];", + "}") + + # Hidden, not dropped: the JS by-name lookups and the CSV export read these columns + hidden = c("chrom_a", "pos_a", "chrom_b", "pos_b", "gene_a", "gene_b", + "sv_len", "size_bp", "locus_sort") + + exp_opts = list(orthogonal = "export", + columns = seq_len(ncol(sv_display)) - 1L) + + dtbl = DT::datatable( + sv_display, + rownames = FALSE, + filter = "top", + elementId = "sv-table", + # Explicit selection: none. The breakend circos owns row selection below + selection = "none", + extensions = c("Buttons", "Scroller"), + options = list( + dom = "Bfrtip", + # "export" falls through to the full readable string; the explicit column list keeps the hidden raw columns in the download + buttons = list(list(extend = "copy", exportOptions = exp_opts), + list(extend = "csv", exportOptions = exp_opts)), + scrollX = TRUE, + scrollY = "350px", + scroller = TRUE, + deferRender = TRUE, + pageLength = 25, + columnDefs = list( + list(targets = idx0("panel_hit"), render = panel_hit_render), + list(targets = idx0("genes"), render = gene_render), + list(targets = idx0("locus"), render = orthogonal_render("locus_sort")), + list(targets = idx0("size"), render = orthogonal_render("size_bp")), + list(targets = vapply(hidden, idx0, integer(1), USE.NAMES = FALSE), + visible = FALSE) + ), + initComplete = JS("function() { window.svTableElem = this.api().table().node(); }") + ) + ) |> + DT::formatStyle( + columns = "svtype", + target = "cell", + backgroundColor = DT::styleEqual( + c("DEL", "DUP", "INV", "INS", "BND", "sBND"), + c("#dbeafe", "#dcfce7", "#fef9c3", "#fee2e2", "#f3e8ff", "#f3e8ff") + ) + ) + dtbl +} +``` + +```{r sv-bnd-circos-js, results='asis'} +# Cross-link table and circos: this owns row selection; row identity comes from the DataTables API (Scroller recycles s), so the class is re-applied per draw; every filter change redraws from window.BND_DATA +if (!is.null(bnd_res) && !is.null(bnd_res$data)) { + cat("\n") +} +``` + +```{r sv-footnote} +# Provenance footnote: where the breakend symbols came from, and which panel matching mode, reference and windows are active +if (!is.null(sv_table) && nrow(sv_table) > 0) { + rel = function(p) { + if (is.null(p)) return(NULL) + root = sub("/+$", "", normalizePath(sample_dir, mustWork = FALSE)) + full = normalizePath(p, mustWork = FALSE) + if (startsWith(full, paste0(root, "/"))) substring(full, nchar(root) + 2L) else p + } + + # One HTML string, not a tagList (htmltools' newlines would render as " ,") + code = function(x) paste0("", htmltools::htmlEscape(x), "") + + # One note per registered panel, hidden unless ticked (updatePanelNotes() toggles `hidden`) + panel_body = function(p) { + if (isTRUE(p$has_coords)) { + sprintf(paste("Panel %s matches on breakend coordinates (%s intervals,", + "within %s of either breakend of a BND or %s of the span of any other", + "type)%s Each %s entry names the gene, the side it matched on (%s, %s,", + "or %s for a contiguous type), and then either %s — the breakend or span", + "overlaps the gene itself — or the distance to it. Those windows are wide,", + "so a hit is not on its own a disrupted gene: read the second token."), + code(basename(as.character(p$path)[1])), length(unlist(p$start)), + fmt_bp(SV_PANEL_WINDOW_BND), fmt_bp(SV_PANEL_WINDOW_OTHER), + if (nzchar(as.character(p$reference)[1])) + paste0(", built on ", as.character(p$reference)[1], ".") + else paste(", whose reference is unverified — the panel declares none, so", + "nothing checks it against this report's."), + code("panel_hit"), code("A"), code("B"), code("span"), code("direct")) + } else { + sprintf(paste("Panel %s carries no coordinates, so SVs are matched on gene", + "symbol only: a breakend VEP did not annotate cannot match,", + "whatever it is near. Every %s entry therefore reads %s — a symbol sits", + "on the breakend itself, and there is no distance to report. Add %s, %s", + "and %s columns to match on position instead."), + code(basename(as.character(p$path)[1])), code("panel_hit"), code("direct"), + code("chrom"), code("start"), code("end")) + } + } + + note_span = function(key, body, shown) { + sprintf('%s', + htmltools::htmlEscape(key, attribute = TRUE), + if (shown) "" else " hidden", body) + } + + all_p = if (!is.null(params$all_panels)) params$all_panels else list() + selected = setdiff(as.character(unlist(params$default_panels)), "__all__") + + panel_note = paste(c( + note_span("__none__", + "No gene panel is ticked; tick one above to filter both tables.", + length(selected) == 0), + vapply(names(all_p), function(nm) + note_span(nm, panel_body(all_p[[nm]]), nm %in% selected), + character(1)), + note_span("__custom__", + paste("The custom list is bare symbols, so its SVs are matched on the", + "annotated breakend genes only — no positional window."), + FALSE), + note_span("__multi__", + sprintf(paste("With more than one panel ticked a row is kept if it hits", + "any of them, and each %s entry ends with the", + "panel it matched in square brackets."), code("panel_hit")), + length(selected) >= 2) + ), collapse = " ") + + annot_note = if (!is.null(SECTION_DATA$sv$annotation_path)) + sprintf(paste("Breakend genes are from %s, joined on record ID; records that", + "annotation dropped (it keeps only FILTER PASS) have none."), + code(rel(SECTION_DATA$sv$annotation_path))) + else + "No SV annotation file was found, so the gene column is empty." + + # The locus/size convention: a contiguous type is one span, a breakend two joined loci + locus_note = sprintf(paste("%s reads as a span (%s) for a contiguous type and as two", + "joined loci (%s or %s) for a breakend, which is also why %s", + "is blank for a breakend: its two loci bound no interval, so", + "there is no length to report. The underlying %s columns are", + "hidden rather than dropped — they are still what the panel", + "filter matches on, and the copy and CSV buttons still export", + "them. %s merges both sides for a contiguous type and labels", + "them %s and %s for a breakend, where which partner carries", + "which gene is the point."), + code("locus"), code("chr13:48,303,151–48,915,700"), + code("→"), code("↔"), code("size"), + paste(code("chrom_a"), code("pos_a"), code("chrom_b"), + code("pos_b"), sep = ", "), + code("genes"), code("A:"), code("B:")) + + # What the circos shows, only when there is a plot + circos_note = if (!is.null(bnd_res) && !is.null(bnd_res$data)) + sprintf(paste("The circos above draws one arc per breakend with both loci mapped, and", + "is redrawn whenever the filter changes — it shows only the chromosomes", + "the visible rows touch, out of the %d these %d arc%s span in total.", + "Gene bodies are the panel genes within %s of a breakend — the same test", + "that fills the %s column, so a gene is drawn exactly when a visible row", + "names it, and a panel carrying no coordinates draws none. Bodies are", + "markers at a minimum visible width, not spans to scale."), + length(bnd_res$chroms), bnd_res$n_links, + if (bnd_res$n_links == 1) "" else "s", + fmt_bp(SV_PANEL_WINDOW_BND), code("panel_hit")) + else NULL + + table_details( + summary = "How these rows and this plot are built", + HTML(paste( + sprintf("%s rearrangement%s, one row each — Severus writes both sides of a breakend as two records, and mate pairs are collapsed here%s.", + nrow(sv_table), if (nrow(sv_table) == 1) "" else "s", + if (!is.na(n_trans) && !is.na(n_intra_bnd)) + sprintf(" (%s interchromosomal, %s intra-chromosomal breakend%s)", + n_trans, n_intra_bnd, if (n_intra_bnd == 1) "" else "s") + else ""), + locus_note, annot_note, panel_note, circos_note)) + ) +} +``` + +```{r sv-panel-notes-js, results='asis'} +# Show the notes for the ticked panels; defined here because the spans are written above +cat(r"----( +)----") +``` diff --git a/assets/lrsomatic_report/templates/sections/_whatshap.qmd b/assets/lrsomatic_report/templates/sections/_whatshap.qmd new file mode 100644 index 00000000..e124dcce --- /dev/null +++ b/assets/lrsomatic_report/templates/sections/_whatshap.qmd @@ -0,0 +1,50 @@ +::: {.callout-note collapse="true"} +### Phasing + +```{r whatshap-info} +whatshap = SECTION_DATA[["whatshap"]] +if (is.null(whatshap)) { + section_notice("WhatsHap phasing statistics not found.") +} +``` + +```{r whatshap-table} +if (!is.null(whatshap) && nrow(whatshap$per_chrom) > 0) { + show_cols = c("chromosome", "variants", "heterozygous_variants", "phased", "unphased", + "singletons", "blocks", "phased_fraction", "bp_per_block_median", + "block_n50") + show_cols = show_cols[show_cols %in% names(whatshap$per_chrom)] + + wt = whatshap$per_chrom[, ..show_cols] + if ("phased_fraction" %in% names(wt)) { + wt[, phased_fraction := round(phased_fraction * 100, 1)] + setnames(wt, "phased_fraction", "phased%") + } + + htmltools::tagList( + DT::datatable( + wt, + rownames = FALSE, + filter = "top", + extensions = c("Buttons", "Scroller"), + options = list( + dom = "Bfrtip", + buttons = c("copy", "csv"), + scrollX = TRUE, + scrollY = "350px", + scroller = TRUE, + deferRender = TRUE, + pageLength = 25, + columnDefs = list(list(className = "dt-left", targets = "_all")) + ) + ), + # Germline, not somatic, statistics; see table_details() in R/sections.R + table_details( + summary = "Source", + sprintf("Germline phasing statistics, from %s.", + if (!is.na(whatshap$vcf)) whatshap$vcf else "the phased germline VCF") + ) + ) +} +``` +::: diff --git a/conf/modules.config b/conf/modules.config index 9f7d3c34..ab3a9f04 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -558,6 +558,28 @@ process { ] } + withName : '.*:LRSOMATICREPORT' { + ext.prefix = { "${meta.id}" } + // One --gene-panel flag per --report_gene_panel entry (builtin name, or gene_panels/ for a staged file); textual because file() is out of scope here, mirrors reportGenePanelIsFile() + ext.args = { + ((params.report_gene_panel ?: '') as String) + .split(',') + .collect { tok -> tok.trim() } + .findAll { tok -> tok } + .collect { tok -> + tok.contains('/') || tok.toLowerCase().endsWith('.tsv') + ? "--gene-panel 'gene_panels/${tok.tokenize('/').last()}'" + : "--gene-panel '${tok}'" + } + .join(' ') + } + publishDir = [ + path: { "${params.outdir}/${meta.id}/report" }, + mode: params.publish_dir_mode, + saveAs: { filename -> filename.equals('versions.yml') ? null : filename } + ] + } + withName : '.*:WGET' { ext.args = { [ diff --git a/docs/output.md b/docs/output.md index 61d82b28..8166202c 100644 --- a/docs/output.md +++ b/docs/output.md @@ -38,7 +38,8 @@ The pipeline produces per-sample output directories. Two modes exist depending o │ ├── vep │ │ ├── somatic │ │ └── SVs -│ └── wakhan +│ ├── wakhan +│ └── report ``` **Paired tumor + normal sample**: @@ -81,7 +82,8 @@ The pipeline produces per-sample output directories. Two modes exist depending o │ │ ├── germline │ │ ├── somatic │ │ └── SVs -│ └── wakhan +│ ├── wakhan +│ └── report ├── pipeline_info └── multiqc ``` @@ -516,6 +518,38 @@ Phased variant calls produced by Longphase. Present in all samples. +### `report` + +
+Output files + +``` +├── report +│ ├── {sample}_report.html +``` + +| File | Description | +| ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `{sample}_report.html` | Self-contained per-sample HTML report ([lrsomatic_report](https://github.com/ljwharbers/lrsomatic_report)): circos plot, small/structural variant tables, copy-number summary, and QC. Any section whose upstream data is unavailable (e.g. a skipped tool) shows a "not available" notice instead. | + +
+ +This is the final step of the pipeline, run after SNV/SV calling, ASCAT, WAKHAN and QC. Disable it with `--skip_report`. + +Sections: + +- **Small variants** — the VEP-annotated somatic SNVs/indels, with VAF, depth and phase set taken from the phased somatic VCF that VEP annotated. A footnote under the table names the file those VAF columns came from and how many rows they joined to; after a consensus run it also flags that the VAF of a multi-caller variant comes from whichever caller won the merge, so it need not match the `callers` column beside it. Unfiltered by default; see `--report_gene_panel` in [usage](usage.md#report-options) for panel filtering. +- **Structural variants** — SEVERUS breakpoints, annotated from the VEP SV VCF (`{sample}_SV_VEP.vcf.gz`), one row per rearrangement. Breakends additionally get their own circos plot, cross-linked to the SV table and redrawn as the table is filtered. Skipping VEP leaves the SV table unannotated but still drawn on the circos plot. +- **Copy number** — ASCAT purity/ploidy plus its diagnostic plots, and, when WAKHAN ran, its ranked purity/ploidy solutions with the interactive per-solution genome copy-number/breakpoint plots and the ploidy/purity heatmap. +- **QC** — mosdepth, cramino and samtools statistics; for a matched tumour/normal pair both sides are shown side by side. Phasing statistics (WhatsHap) are a collapsible block within this section. + +Filtering in the browser: + +- **Gene panels** are checkboxes in the panel bar. Tick any number and a row is kept if it hits any of them (a union); with none ticked the tables are unfiltered. `--report_gene_panel` only sets which are ticked on load — see [usage](usage.md#applying-several-panels-at-once). With two or more ticked, each `panel_hit` entry names the panel it matched in square brackets. +- **Categorical columns** filter by tickbox dropdown rather than a text box: `consequence`, `impact` and `callers` on the small-variant table, and `svclass`, `svtype`, `impact`, `consequence` and `caller` on the SV table. Each dropdown lists the values actually present in that sample with a row count. Ticking several values in one column is OR; ticking values in two columns is AND. A column with fewer than two distinct values keeps a plain text box. Every other column keeps its text box, and the table's own search box still does substring across all columns. + +The report is one self-contained file — plots and tables are embedded, so it can be copied or emailed on its own. + ### `multiqc`
diff --git a/docs/usage.md b/docs/usage.md index d0546eb0..9fa3feb6 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -153,6 +153,7 @@ For structural variants, the CHM13 panel of normals is a merged panel combining | `--skip_modcall` | A boolean to skip modkit methylation calling. Default = `false` | | `--skip_modkit` | A boolean to skip the modkit pileup step. Default = `false` | | `--skip_whatshapstats` | A boolean to skip WhatsHap phasing statistics. Default = `false` | +| `--skip_report` | A boolean to skip the final per-sample HTML report. Default = `false` | #### LONGPHASE options: @@ -210,6 +211,73 @@ For structural variants, the CHM13 panel of normals is a merged panel combining | ---------------------- | ------------------------------------------------------------------------------------ | | `--severus_minsupport` | Minimum number of supporting reads required for SEVERUS to call an SV. Default = `3` | +#### Report Options + +| Parameter | Description | +| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `--report_src` | Override the report tool source tree (bin/, R/, templates/, assets/). Not needed for normal runs: a copy of [lrsomatic_report](https://github.com/ljwharbers/lrsomatic_report) ships inside the pipeline. Point it at a local checkout to render with an unreleased version of the tool. Default = `${projectDir}/assets/lrsomatic_report` | +| `--report_gene_panel` | Gene panel(s) applied when the report opens, as a comma-separated list. Each entry is `none` (no filtering), a builtin panel name (`lymphoid` or `sarcoma`), or a path to a TSV file with a `gene` column. Default = `null`, i.e. unfiltered | + +Gene panel filtering is a view, not a filter on the data: every builtin panel is embedded in +the rendered report and the reader can tick and untick them (or clear them all for the +unfiltered table) in the browser. `--report_gene_panel` only decides which ones are ticked on +load. A custom panel is a tab-separated file with a header row containing at least a `gene` +column: + +```tsv +gene panel note +TP53 mypanel Tumour suppressor +KRAS mypanel Oncogene +``` + +A panel may also carry `chrom`, `start` and `end` columns — all three or none. With +coordinates, structural variants are matched on position (within 1 Mb of a breakend, or +100 kb of the SV span) rather than on the VEP gene symbol, which is what makes breakend +filtering reliable: whether a breakend carries a gene symbol at all depends on the VEP +invocation. A coordinate-carrying panel must declare the reference its coordinates are +valid for, either as a leading `# reference: hg38` comment or as a `reference` column; a +panel declaring a reference other than the one the sample was called against is a hard +error rather than a silently wrong filter. Symbol-only panels need no declaration. The +builtin panels ship one file per reference and are selected by their bare name +(`lymphoid`, `sarcoma`), resolved against the detected reference. + +```bash +nextflow run IntGenomicsLab/lrsomatic \ + -profile \ + --input samplesheet.csv \ + --outdir results \ + --report_gene_panel /path/to/mypanel.tsv +``` + +##### Applying several panels at once + +Pass a comma-separated list to open the report with several panels applied. They are +**unioned**: a variant or SV is kept if it hits any of them. Builtin names and custom paths +can be mixed freely. + +```bash + --report_gene_panel lymphoid,sarcoma + --report_gene_panel 'lymphoid,/path/to/mypanel.tsv' +``` + +With two or more panels active, each `panel_hit` entry in the SV table gains a trailing +`[panel]` naming which one matched — under a union that is all that distinguishes two hits +on the same gene. With a single panel the labels read exactly as they always have. + +An entry is read as a panel **file** if it contains a `/` or ends in `.tsv`, and as a +builtin panel name otherwise. In practice that means a custom panel needs a path or a +`.tsv` name — `--report_gene_panel mypanel` is looked up as a builtin even if a file called +`mypanel` sits next to you. + +Three things are checked before the run starts, so a mistake costs seconds rather than a +full pipeline: + +- `none` means unfiltered and cannot be combined with a real panel. +- A panel file that does not exist, and a builtin name that is not one of the bundled + panels, are both errors — a typo cannot quietly produce an unfiltered report. +- Two panel files sharing a base name cannot be combined, whatever directories they live + in — they are staged side by side and would collide. Rename one. + #### WAKHAN Options | Parameter | Description | diff --git a/modules/local/lrsomaticreport/environment.yml b/modules/local/lrsomaticreport/environment.yml new file mode 100644 index 00000000..c13bee5c --- /dev/null +++ b/modules/local/lrsomaticreport/environment.yml @@ -0,0 +1,21 @@ +--- +# yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/modules/environment-schema.json +channels: + - conda-forge + - bioconda +dependencies: + - "conda-forge::r-base=4.4.*" + - "conda-forge::quarto=1.5.*" + - "conda-forge::r-base64enc" + - "conda-forge::r-data.table" + - "conda-forge::r-dplyr" + - "conda-forge::r-dt" + - "conda-forge::r-htmltools" + - "conda-forge::r-optparse" + - "conda-forge::r-quarto" + - "conda-forge::r-yaml" + - "conda-forge::r-ggplot2" + - "conda-forge::r-svglite" + - "conda-forge::r-circlize" + - "conda-forge::r-knitr" + - "conda-forge::r-r.utils" diff --git a/modules/local/lrsomaticreport/main.nf b/modules/local/lrsomaticreport/main.nf new file mode 100644 index 00000000..6e68db78 --- /dev/null +++ b/modules/local/lrsomaticreport/main.nf @@ -0,0 +1,89 @@ +process LRSOMATICREPORT { + tag "$meta.id" + label 'process_medium' + + conda "${moduleDir}/environment.yml" + // Dependencies only (the tool is vendored at assets/lrsomatic_report); when environment.yml changes rebuild both images with `wave --conda-file modules/local/lrsomaticreport/environment.yml --freeze --await [--singularity]` + container "${workflow.containerEngine == 'singularity' + ? 'oras://community.wave.seqera.io/library/r-base_quarto_r-base64enc_r-data.table_pruned:dc62d809aa6fd497' + : 'community.wave.seqera.io/library/r-base_quarto_r-base64enc_r-data.table_pruned:c1049dbaf31bf178'}" + + input: + // Every path input is optional (`[]` when skipped); tumor/normal QC stage into separate dirs because a matched pair shares meta.id + tuple val(meta), path(vep_somatic), path(sv_vep), path(severus_vcf), path(somatic_vcf), path(ascat_files), path(qc_tumor_files, stageAs: 'qc_tumor/*'), path(qc_normal_files, stageAs: 'qc_normal/*'), path(wakhan_files, stageAs: 'wakhan/*') + path(report_src) // lrsomatic_report source tree (bin/, R/, templates/, assets/) + // User-supplied gene panel TSVs (`[]` for builtins); the matching `--gene-panel gene_panels/` args are built in conf/modules.config + path(gene_panels, stageAs: 'gene_panels/*') + + output: + tuple val(meta), path("*_report.html"), emit: report + // WARN: Manually update to match the vendored release in assets/lrsomatic_report/VENDORED.md + tuple val("${task.process}"), val('lrsomatic_report'), val('1.3.2'), topic: versions, emit: versions_lrsomaticreport + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + def prefix = task.ext.prefix ?: "${meta.id}" + def sex = meta.sex ?: 'male' + + // Discovery is recursive and matches on base name, so suffix-distinct files can be linked flat + def flat_inputs = [vep_somatic, sv_vep, severus_vcf, ascat_files].flatten().findAll { f -> f } + def link_flat = flat_inputs ? """ + for f in ${flat_inputs.collect { f -> "\"${f}\"" }.join(' ')}; do ln -s "\$PWD/\$f" "sample_dir/\$f"; done + """ : '' + + // The VAF/depth/phasing source is looked up at a literal path + def link_somatic = somatic_vcf ? """ + mkdir -p sample_dir/variants/phased + ln -s "\$PWD/${somatic_vcf}" sample_dir/variants/phased/somatic_smallvariants.vcf.gz + """ : '' + + """ + # Quarto/Deno write under \$HOME and \$TMPDIR, which clusters may mount read-only + export HOME=\$PWD + export TMPDIR=\$PWD/tmp TMP=\$PWD/tmp TEMP=\$PWD/tmp + mkdir -p "\$TMPDIR" + + # The Wave container doesn't source conda's activation hooks (quarto needs QUARTO_SHARE_PATH); -profile conda may already set CONDA_PREFIX + export CONDA_PREFIX="\${CONDA_PREFIX:-/opt/conda}" + for f in "\$CONDA_PREFIX"/etc/conda/activate.d/*.sh; do + [ -f "\$f" ] && source "\$f" + done + + mkdir -p sample_dir + ${link_flat} + ${link_somatic} + + # Link file by file: R's list.files(recursive = TRUE) does not descend into symlinked dirs + if [ -d qc_tumor ]; then + mkdir -p sample_dir/qc/tumor + for f in qc_tumor/*; do ln -s "\$PWD/\$f" "sample_dir/qc/tumor/\$(basename "\$f")"; done + fi + if [ -d qc_normal ]; then + mkdir -p sample_dir/qc/normal + for f in qc_normal/*; do ln -s "\$PWD/\$f" "sample_dir/qc/normal/\$(basename "\$f")"; done + fi + + # Wakhan is addressed by fixed path: sample_dir/wakhan must hold solutions_ranks.tsv, the heatmap and solution_/ + if [ -d wakhan ]; then + mkdir -p sample_dir/wakhan + for f in wakhan/*; do ln -s "\$PWD/\$f" "sample_dir/wakhan/\$(basename "\$f")"; done + fi + + Rscript "${report_src}/bin/render_report.R" \\ + --sample-dir sample_dir \\ + --sample-id "${prefix}" \\ + --sex "${sex}" \\ + --reference auto \\ + --output "${prefix}_report.html" \\ + ${args} + """ + + stub: + def prefix = task.ext.prefix ?: "${meta.id}" + """ + touch ${prefix}_report.html + """ +} diff --git a/modules/local/lrsomaticreport/meta.yml b/modules/local/lrsomaticreport/meta.yml new file mode 100644 index 00000000..d1bd67e2 --- /dev/null +++ b/modules/local/lrsomaticreport/meta.yml @@ -0,0 +1,98 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/modules/meta-schema.json +name: "lrsomaticreport" +description: Render a self-contained per-sample HTML report (circos plot, small/structural variant tables, ASCAT copy-number, QC) from the pipeline's key final outputs, using the lrsomatic_report R/Quarto tool. +keywords: + - report + - quarto + - somatic + - long-read +tools: + - "lrsomatic_report": + description: "Standalone R/Quarto reporting tool for the LRSomatic pipeline" + homepage: "https://github.com/ljwharbers/lrsomatic_report" + documentation: "https://github.com/ljwharbers/lrsomatic_report/blob/main/README.md" + tool_dev_url: "https://github.com/ljwharbers/lrsomatic_report" + doi: "" + licence: ["MIT"] + identifier: "" + +input: + - - meta: + type: map + description: | + Groovy Map containing sample information, e.g. `[ id:'sample1' ]` + - vep_somatic: + type: file + description: VEP-annotated somatic small-variant VCF (SOMATIC_VEP output), or `[]` if VEP was skipped + pattern: "*_SOMATIC_VEP.vcf.gz" + - sv_vep: + type: file + description: VEP-annotated structural-variant VCF (SV_VEP output); the report's primary SV annotation source, or `[]` if VEP was skipped + pattern: "*_SV_VEP.vcf.gz" + - severus_vcf: + type: file + description: Severus somatic structural-variant VCF (raw breakpoints, used for the circos tracks), or `[]` if not available + pattern: "severus_somatic.vcf.gz" + - somatic_vcf: + type: file + description: Phased somatic small-variant VCF (the VCF that VEP annotated); source of the VAF, depth and phase-set columns, or `[]` if not available + pattern: "*.vcf.gz" + - ascat_files: + type: file + description: Collected ASCAT copy-number output files (segments_raw, purityploidy, diagnostic PNGs), or `[]` if ASCAT was skipped + - qc_tumor_files: + type: file + description: Collected tumor QC files (mosdepth summary/dist, cramino, samtools stats/flagstat), or `[]` if QC was skipped + - qc_normal_files: + type: file + description: Collected normal-sample QC files (matched mode only), or `[]` for tumor-only samples or if QC was skipped + - wakhan_files: + type: file + description: Collected Wakhan outputs (solutions_ranks.tsv, the ploidy/purity heatmap HTML and the per-solution `solution_/` directories), or `[]` if Wakhan was skipped + - - report_src: + type: directory + description: lrsomatic_report source tree (bin/, R/, templates/, assets/), shared across all samples; defaults to the vendored copy at `assets/lrsomatic_report` + - - gene_panels: + type: file + description: Optional user-supplied gene panel TSVs (each with a `gene` column) to apply on load, staged into `gene_panels/` so they are bound into the container; `[]` when `--report_gene_panel` names only builtin panels or is unset. Several panels can be active at once and are unioned. Panel files sharing a base name cannot be combined + pattern: "*.tsv" + +output: + report: + - - meta: + type: map + description: | + Groovy Map containing sample information, e.g. `[ id:'sample1' ]` + - "*_report.html": + type: file + description: Self-contained per-sample HTML report + pattern: "*_report.html" + versions_lrsomaticreport: + - - "${task.process}": + type: string + description: The name of the process + - "lrsomatic_report": + type: string + description: The name of the tool + - "1.3.2": + type: string + description: | + Manually pinned version (the tool has no CLI version flag); matches the + vendored release recorded in assets/lrsomatic_report/VENDORED.md + +topics: + versions: + - - ${task.process}: + type: string + description: The name of the process + - lrsomatic_report: + type: string + description: The name of the tool + - "1.3.2": + type: string + description: Manually pinned version (tool has no CLI version flag) + +authors: + - "@ljwharbers" +maintainers: + - "@ljwharbers" diff --git a/modules/local/lrsomaticreport/tests/gene_panel.config b/modules/local/lrsomaticreport/tests/gene_panel.config new file mode 100644 index 00000000..3bae7b2c --- /dev/null +++ b/modules/local/lrsomaticreport/tests/gene_panel.config @@ -0,0 +1,6 @@ +// conf/modules.config is not loaded in module-level nf-test, so reproduce its --gene-panel argument (staged TSVs live at gene_panels/) +process { + withName: 'LRSOMATICREPORT' { + ext.args = "--gene-panel 'gene_panels/test_panel.tsv'" + } +} diff --git a/modules/local/lrsomaticreport/tests/main.nf.test b/modules/local/lrsomaticreport/tests/main.nf.test new file mode 100644 index 00000000..15177230 --- /dev/null +++ b/modules/local/lrsomaticreport/tests/main.nf.test @@ -0,0 +1,170 @@ +nextflow_process { + + name "Test Process LRSOMATICREPORT" + script "../main.nf" + process "LRSOMATICREPORT" + + tag "modules" + tag "modules_local" + tag "lrsomaticreport" + + test("no optional inputs - stub") { + + options "-stub" + + when { + process { + """ + input[0] = [ + [ id:'test', paired_data: null, sex: 'male' ], + [], // vep_somatic + [], // sv_vep + [], // severus_vcf + [], // somatic_vcf + [], // ascat_files + [], // qc_tumor_files + [], // qc_normal_files + [] // wakhan_files + ] + input[1] = file("${projectDir}/assets/lrsomatic_report", checkIfExists: true) + input[2] = [] // gene_panels + """ + } + } + + then { + assert process.success + assertAll( + { assert snapshot(process.out).match() } + ) + } + + } + + // Renders for real (no -stub), so a broken container, an incomplete vendored tool tree + // or CLI drift against render_report.R is caught + test("vep somatic vcf - real render") { + + when { + process { + """ + input[0] = [ + [ id:'test', paired_data: null, sex: 'male' ], + file("${projectDir}/modules/local/lrsomaticreport/tests/test_SOMATIC_VEP.vcf.gz", checkIfExists: true), + [], // sv_vep + [], // severus_vcf + [], // somatic_vcf + [], // ascat_files + [], // qc_tumor_files + [], // qc_normal_files + [] // wakhan_files + ] + input[1] = file("${projectDir}/assets/lrsomatic_report", checkIfExists: true) + input[2] = [] // gene_panels + """ + } + } + + then { + assert process.success + assertAll( + { assert process.out.report.get(0).get(1).endsWith("test_report.html") }, + // The rendered HTML is not snapshotted (Quarto embeds timestamps and + // per-render element ids); assert on content that must be there instead. + { assert path(process.out.report.get(0).get(1)).readLines().size() > 0 }, + { assert path(process.out.report.get(0).get(1)).text.contains("TP53") }, + { assert snapshot(process.out.versions_lrsomaticreport).match("versions") } + ) + } + + } + + // A user-supplied panel TSV lives outside the task work dir, so it only reaches + // render_report.R if the `gene_panels` input stages it into the container + test("custom gene panel tsv - real render") { + + config "./gene_panel.config" + + when { + process { + """ + input[0] = [ + [ id:'test', paired_data: null, sex: 'male' ], + file("${projectDir}/modules/local/lrsomaticreport/tests/test_SOMATIC_VEP.vcf.gz", checkIfExists: true), + [], // sv_vep + [], // severus_vcf + [], // somatic_vcf + [], // ascat_files + [], // qc_tumor_files + [], // qc_normal_files + [] // wakhan_files + ] + input[1] = file("${projectDir}/assets/lrsomatic_report", checkIfExists: true) + input[2] = [ file("${projectDir}/modules/local/lrsomaticreport/tests/test_panel.tsv", checkIfExists: true) ] + """ + } + } + + then { + assert process.success + assertAll( + // The custom panel is registered alongside the builtins under its file + // base name, so its presence in the HTML proves the TSV was read. + { assert path(process.out.report.get(0).get(1)).text.contains("test_panel") }, + { assert path(process.out.report.get(0).get(1)).text.contains("TP53") } + ) + } + + } + + // Two staged TSVs plus a builtin, covering the union path: each hit is labelled with the + // panel it came from, which only happens when more than one panel is active + test("several gene panels - real render") { + + config "./multi_gene_panel.config" + + when { + process { + """ + input[0] = [ + [ id:'test', paired_data: null, sex: 'male' ], + file("${projectDir}/modules/local/lrsomaticreport/tests/test_SOMATIC_VEP.vcf.gz", checkIfExists: true), + [], // sv_vep + [], // severus_vcf + [], // somatic_vcf + [], // ascat_files + [], // qc_tumor_files + [], // qc_normal_files + [] // wakhan_files + ] + input[1] = file("${projectDir}/assets/lrsomatic_report", checkIfExists: true) + input[2] = [ + file("${projectDir}/modules/local/lrsomaticreport/tests/test_panel.tsv", checkIfExists: true), + file("${projectDir}/modules/local/lrsomaticreport/tests/test_panel_b.tsv", checkIfExists: true) + ] + """ + } + } + + then { + assert process.success + def report_text = path(process.out.report.get(0).get(1)).text + // Had only the last --gene-panel flag survived, this would name a single panel + def matcher = (report_text =~ /const DEFAULT_PANELS = (\[[^\]]*\])/) + assert matcher.find() + def default_panels = matcher.group(1) + assertAll( + { assert default_panels.contains("test_panel") }, + { assert default_panels.contains("test_panel_b") }, + { assert default_panels.contains("lymphoid") }, + // SMAD4 and VHL appear in no builtin panel, so their presence proves + // test_panel_b was read off disk rather than merely named. + { assert report_text.contains("SMAD4") }, + { assert report_text.contains("VHL") }, + { assert report_text.contains("TP53") } + ) + } + + } + +} diff --git a/modules/local/lrsomaticreport/tests/main.nf.test.snap b/modules/local/lrsomaticreport/tests/main.nf.test.snap new file mode 100644 index 00000000..6c4bea5d --- /dev/null +++ b/modules/local/lrsomaticreport/tests/main.nf.test.snap @@ -0,0 +1,63 @@ +{ + "no optional inputs - stub": { + "content": [ + { + "0": [ + [ + { + "id": "test", + "paired_data": null, + "sex": "male" + }, + "test_report.html:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "1": [ + [ + "LRSOMATICREPORT", + "lrsomatic_report", + "1.3.2" + ] + ], + "report": [ + [ + { + "id": "test", + "paired_data": null, + "sex": "male" + }, + "test_report.html:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "versions_lrsomaticreport": [ + [ + "LRSOMATICREPORT", + "lrsomatic_report", + "1.3.2" + ] + ] + } + ], + "timestamp": "2026-08-28T14:51:14.481830202", + "meta": { + "nf-test": "0.9.4", + "nextflow": "26.04.3" + } + }, + "versions": { + "content": [ + [ + [ + "LRSOMATICREPORT", + "lrsomatic_report", + "1.3.2" + ] + ] + ], + "timestamp": "2026-08-28T14:51:33.53813418", + "meta": { + "nf-test": "0.9.4", + "nextflow": "26.04.3" + } + } +} \ No newline at end of file diff --git a/modules/local/lrsomaticreport/tests/multi_gene_panel.config b/modules/local/lrsomaticreport/tests/multi_gene_panel.config new file mode 100644 index 00000000..bf78cc1d --- /dev/null +++ b/modules/local/lrsomaticreport/tests/multi_gene_panel.config @@ -0,0 +1,6 @@ +// conf/modules.config is not loaded in module-level nf-test, so reproduce its arguments for --report_gene_panel 'test_panel.tsv,test_panel_b.tsv,lymphoid' +process { + withName: 'LRSOMATICREPORT' { + ext.args = "--gene-panel 'gene_panels/test_panel.tsv' --gene-panel 'gene_panels/test_panel_b.tsv' --gene-panel 'lymphoid'" + } +} diff --git a/modules/local/lrsomaticreport/tests/test_SOMATIC_VEP.vcf.gz b/modules/local/lrsomaticreport/tests/test_SOMATIC_VEP.vcf.gz new file mode 100644 index 00000000..0f7d3518 Binary files /dev/null and b/modules/local/lrsomaticreport/tests/test_SOMATIC_VEP.vcf.gz differ diff --git a/modules/local/lrsomaticreport/tests/test_panel.tsv b/modules/local/lrsomaticreport/tests/test_panel.tsv new file mode 100644 index 00000000..13ce7bbc --- /dev/null +++ b/modules/local/lrsomaticreport/tests/test_panel.tsv @@ -0,0 +1,3 @@ +gene panel notes +TP53 testpanel Tumour suppressor +KRAS testpanel Proto-oncogene diff --git a/modules/local/lrsomaticreport/tests/test_panel_b.tsv b/modules/local/lrsomaticreport/tests/test_panel_b.tsv new file mode 100644 index 00000000..3f39d883 --- /dev/null +++ b/modules/local/lrsomaticreport/tests/test_panel_b.tsv @@ -0,0 +1,3 @@ +gene panel notes +SMAD4 testpanelb Tumour suppressor +VHL testpanelb Tumour suppressor diff --git a/modules/local/wakhan/main.nf b/modules/local/wakhan/main.nf index f704df4b..ad7aba5e 100644 --- a/modules/local/wakhan/main.nf +++ b/modules/local/wakhan/main.nf @@ -36,6 +36,9 @@ process WAKHAN { tuple val(meta), path("phasing_output/*rephased.vcf.gz.csi") , emit: rephased_vcf_index tuple val(meta), path("snps_loh_plots/*_genome_snps_ratio_loh.html") , emit: snps_loh_plot, optional: true tuple val(meta), path("solutions_ranks.tsv") , emit: solutions_ranks + // Whole directories, not the plots inside: every solution's plot has the same basename, + // and LRSOMATICREPORT resolves them by solution_/ path + tuple val(meta), path("solution_*", type: 'dir') , emit: solution_dirs, optional: true // WARN: Manually update version information as tool does not provide on CLI tuple val("${task.process}"), val('wakhan'), val("0.4.3"), topic: versions, emit: versions_wakhan diff --git a/nextflow.config b/nextflow.config index cb53306c..7ed3cbe8 100644 --- a/nextflow.config +++ b/nextflow.config @@ -59,6 +59,7 @@ params { skip_modkit = false use_gpu = false skip_whatshapstats = false + skip_report = false // minimap2 options minimap2_ont_model = null @@ -86,6 +87,10 @@ params { // Wakhan options wakhan_chroms = null + // Report options + report_src = "${projectDir}/assets/lrsomatic_report" + report_gene_panel = null + //TODO: // Once iGenomes is udpated we can update our iGenomes.config to automatically assign genome version // and allele/loci(/gc/rt) files. For now they need to be specified for anything else but GRCh38 and CHM13 diff --git a/nextflow_schema.json b/nextflow_schema.json index bdc64a04..6feef257 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -303,6 +303,22 @@ } } }, + "report_options": { + "title": "Report options", + "type": "object", + "description": "Options for the final per-sample HTML report", + "default": "", + "properties": { + "report_src": { + "type": "string", + "description": "Override the report tool source tree (bin/, R/, templates/, assets/). Defaults to the copy vendored in this repository; point it at a local checkout of lrsomatic_report to render with an unreleased version of the tool." + }, + "report_gene_panel": { + "type": "string", + "description": "Gene panel(s) applied when the report opens, as a comma-separated list: 'none' for no filtering, builtin panel names (e.g. 'lymphoid'), and/or paths to TSVs with a 'gene' column. Several panels are applied at once and unioned -- a variant or SV is kept if it hits any of them. Every builtin panel is always embedded in the report and panels are checkboxes there, so the reader can retick them without re-rendering; this only sets the initial selection. An entry is read as a panel file if it contains a '/' or ends in '.tsv', and as a builtin panel name otherwise. 'none' cannot be combined with a real panel, and two panel files sharing a base name cannot be combined. Default (unset) is unfiltered." + } + } + }, "skip_options": { "title": "Skip options", "type": "object", @@ -364,6 +380,10 @@ "use_gpu": { "type": "boolean", "description": "Use GPU for supported tools (e.g. DeepVariant, DeepSomatic, Clair3)" + }, + "skip_report": { + "type": "boolean", + "description": "Skip the final per-sample HTML report" } } }, @@ -552,6 +572,9 @@ { "$ref": "#/$defs/wakhan_options" }, + { + "$ref": "#/$defs/report_options" + }, { "$ref": "#/$defs/skip_options" }, diff --git a/nf-test.config b/nf-test.config index b5bc0b87..d1220b10 100644 --- a/nf-test.config +++ b/nf-test.config @@ -34,5 +34,7 @@ config { // load the necessary plugins plugins { load "nft-utils@0.0.3" + // bam() assertions for sample4's merged BAM (see tests/.nftignore) + load "nft-bam@0.7.0" } } diff --git a/ro-crate-metadata.json b/ro-crate-metadata.json index b086228d..6fe08cd4 100644 --- a/ro-crate-metadata.json +++ b/ro-crate-metadata.json @@ -23,7 +23,7 @@ "@type": "Dataset", "creativeWorkStatus": "InProgress", "datePublished": "2026-04-29T11:16:38+00:00", - "description": "# IntGenomicsLab/lrsomatic\n\n[![Open in GitHub Codespaces](https://img.shields.io/badge/Open_In_GitHub_Codespaces-black?labelColor=grey&logo=github)](https://github.com/codespaces/new/IntGenomicsLab/lrsomatic)\n[![GitHub Actions CI Status](https://github.com/IntGenomicsLab/lrsomatic/actions/workflows/nf-test.yml/badge.svg)](https://github.com/IntGenomicsLab/lrsomatic/actions/workflows/nf-test.yml)\n[![GitHub Actions Linting Status](https://github.com/IntGenomicsLab/lrsomatic/actions/workflows/linting.yml/badge.svg)](https://github.com/IntGenomicsLab/lrsomatic/actions/workflows/linting.yml)[![Cite with Zenodo](http://img.shields.io/badge/DOI-10.5281/zenodo.17751829-1073c8?labelColor=000000)](https://doi.org/10.5281/zenodo.17751829)\n[![nf-test](https://img.shields.io/badge/unit_tests-nf--test-337ab7.svg)](https://www.nf-test.com)\n\n[![Nextflow](https://img.shields.io/badge/version-%E2%89%A525.04.0-green?style=flat&logo=nextflow&logoColor=white&color=%230DC09D&link=https%3A%2F%2Fnextflow.io)](https://www.nextflow.io/)\n[![nf-core template version](https://img.shields.io/badge/nf--core_template-4.0.2-green?style=flat&logo=nfcore&logoColor=white&color=%2324B064&link=https%3A%2F%2Fnf-co.re)](https://github.com/nf-core/tools/releases/tag/4.0.2)\n[![run with conda](http://img.shields.io/badge/run%20with-conda-3EB049?labelColor=000000&logo=anaconda)](https://docs.conda.io/en/latest/)\n[![run with docker](https://img.shields.io/badge/run%20with-docker-0db7ed?labelColor=000000&logo=docker)](https://www.docker.com/)\n[![run with singularity](https://img.shields.io/badge/run%20with-singularity-1d355c.svg?labelColor=000000)](https://sylabs.io/docs/)\n[![Launch on Seqera Platform](https://img.shields.io/badge/Launch%20%F0%9F%9A%80-Seqera%20Platform-%234256e7)](https://cloud.seqera.io/launch?pipeline=https://github.com/IntGenomicsLab/lrsomatic)\n\n## Introduction\n\n**IntGenomicsLab/lrsomatic** is a robust bioinformatics pipeline designed for processing and analyzing **somatic DNA sequencing** data for long-read sequencing technologies from **Oxford Nanopore** and **PacBio**. It supports both canonical base DNA and modified base calling, including specialized applications such as **Fiber-seq**.\n\nThis **end-to-end pipeline** handles the entire workflow \u2014 **from raw read processing and alignment, to comprehensive somatic variant calling**, including single nucleotide variants, indels, structural variants, copy number alterations, and modified bases.\n\nIt can be run in both **matched tumour-normal** and **tumour-only mode**, offering flexibility depending on the users study design.\n\nDeveloped using **Nextflow DSL2**, it offers high portability and scalability across diverse computing environments. By leveraging Docker or Singularity containers, installation is streamlined and results are highly reproducible. Each process runs in an isolated container, simplifying dependency management and updates. Where applicable, pipeline components are sourced from **nf-core/modules**, promoting reuse, interoperability, and consistency within the broader Nextflow and nf-core ecosystems.\n\nFor more information on how to run the pipeline, you can also go [here](https://intgenomicslab.github.io/lrsomatic).\n\n## Pipeline summary\n\n![image](./assets/lrsomatic_1.0.png)\n\n**1) Pre-processing:**\n\na. Raw read QC ([`cramino`](https://github.com/wdecoster/cramino))\n\nb. Alignment to the reference genome ([`minimap2`](https://github.com/lh3/minimap2))\n\nc. Post alignment QC ([`cramino`](https://github.com/wdecoster/cramino), [`samtools idxstats`](https://github.com/samtools/samtools), [`samtools flagstats`](https://github.com/samtools/samtools), [`samtools stats`](https://github.com/samtools/samtools))\n\nd. Specific for calling modified base calling ([`Modkit`](https://github.com/nanoporetech/modkit), [`Fibertools`](https://github.com/fiberseq/fibertools-rs))\n\n**2i) Matched mode: small variant calling:**\n\na. Calling Germline SNPs ([`Clair3`](https://github.com/HKU-BAL/Clair3))\n\nb. Phasing and Haplotagging the SNPs in the normal and tumour BAM ([`LongPhase`](https://github.com/twolinin/longphase))\n\nc. Calling somatic SNVs ([`ClairS`](https://github.com/HKU-BAL/ClairS))\n\n**2ii) Tumour only mode: small variant calling:**\n\na. Calling Germline SNPs and somatic SNVs ([`ClairS-TO`](https://github.com/HKU-BAL/ClairS-TO))\n\nb. Phasing and Haplotagging germline SNPs in tumour BAM ([`LongPhase`](https://github.com/twolinin/longphase))\n\n**3) Large variant calling:**\n\na. Somatic structural variant calling ([`Severus`](https://github.com/KolmogorovLab/Severus))\n\nb. Copy number alterion calling; long read version of ([`ASCAT`](https://github.com/VanLoo-lab/ascat))\n\n**4) Annotation:**\n\na. Small variant annotation ([`VEP`](https://github.com/Ensembl/ensembl-vep))\n\nb. Structural variant annotation ([`VEP`](https://github.com/Ensembl/ensembl-vep))\n\n\n\n## Usage\n\n> [!NOTE]\n> If you are new to Nextflow and nf-core, please refer to [this page](https://nf-co.re/docs/usage/installation) on how to set-up Nextflow. Make sure to [test your setup](https://nf-co.re/docs/usage/introduction#how-to-run-a-pipeline) with `-profile test` before running the workflow on actual data.\n\nFirst prepare a samplesheet with your input data that looks as follows:\n\n```csv\nsample,bam_tumor,bam_normal,platform,sex,fiber\nsample1,tumour.bam,normal.bam,ont,female,n\nsample2,tumour.bam,,ont,female,y\nsample3,tumour.bam,,pb,male,n\nsample4,tumour.bam,normal.bam,pb,male,y\n```\n\nEach row represents a sample. The bam files should always be unaligned bam files. All fields except for `bam_normal` are required. If `bam_normal` is empty, the pipeline will run in tumour only mode. `platform` should be either `ont` or `pb` for Oxford Nanopore Sequencing or PacBio sequencing, respectively. `sex` refers to the biological sex of the sample and should be either `female` or `male`. Finally, `fiber` specifies whether your sample is Fiber-seq data or not and should have either `y` for Yes or `n` for No.\n\nNow, you can run the pipeline using:\n\n```bash\nnextflow run IntGenomicsLab/lrsomatic \\\n -profile \\\n --input samplesheet.csv \\\n --outdir \n```\n\nMore detail is given in our [usage documentation](/docs/usage.md)\n\n> [!WARNING]\n> Please provide pipeline parameters via the CLI or Nextflow `-params-file` option. Custom config files including those provided by the `-c` Nextflow option can be used to provide any configuration _**except for parameters**_; see [docs](https://nf-co.re/docs/running/run-pipelines#using-parameter-files).\n\n## Credits\n\nIntGenomicsLab/lr_somatic was originally written by Luuk Harbers, Robert Forsyth, Alexandra Pan\u010d\u00edkov\u00e1, Marios Eftychiou, Ruben Cools, Laurens Lambrechts, and Jonas Demeulemeester.\n\n## Pipeline output\n\nThis pipeline produces a series of different output files. The main output is an aligned and phased tumour bam file. This bam file can be used by any typical downstream tool that uses bam files as input. Furthermore, we have sample-specific QC outputs from `cramino` (fastq), `cramino` (bam), `mosdepth`, `samtools` (stats/flagstat/idxstats), and optionally `fibertools`. Finally, we have a `multiqc` report from that combines the output from `mosdepth` and `samtools` into one html report.\n\nBesides QC and the aligned and phased bam file, we have output from (structural) variant and copy number callers, of which some are optional. The output from these variant callers can be found in their respective folders. For small and structural variant callers (`clairS`, `clairS-TO`, and `severus`) these will contain, among others, `vcf` files with called variants. For `ascat` these contain files with final copy number information and plots of the copy number profiles.\n\nExample output directory structure:\n\n```\n\u251c\u2500\u2500 Sample 1\n\u2502 \u251c\u2500\u2500 ascat\n\u2502 \u251c\u2500\u2500 bamfiles\n\u2502 \u251c\u2500\u2500 qc\n\u2502 \u2502 \u251c\u2500\u2500 tumor\n\u2502 \u2502 \u2502 \u251c\u2500\u2500 cramino_aln\n\u2502 \u2502 \u2502 \u251c\u2500\u2500 cramino_ubam\n\u2502 \u2502 \u2502 \u251c\u2500\u2500 fibertoolsrs\n\u2502 \u2502 \u2502 \u251c\u2500\u2500 mosdepth\n\u2502 \u2502 \u2502 \u251c\u2500\u2500 samtools\n\u2502 \u251c\u2500\u2500 variants\n\u2502 \u2502 \u251c\u2500\u2500clairS-TO\n\u2502 \u2502 \u251c\u2500\u2500severus\n\u2502 \u251c\u2500\u2500 vep\n\u2502 \u2502 \u251c\u2500\u2500 germline\n\u2502 \u2502 \u251c\u2500\u2500 somatic\n\u2502 \u2502 \u251c\u2500\u2500 SVs\n\u2502\n\u251c\u2500\u2500 Sample 2\n\u2502 \u251c\u2500\u2500 ascat\n\u2502 \u251c\u2500\u2500 bamfiles\n\u2502 \u251c\u2500\u2500 qc\n\u2502 \u2502 \u251c\u2500\u2500 tumor\n\u2502 \u2502 \u2502 \u251c\u2500\u2500 cramino_aln\n\u2502 \u2502 \u2502 \u251c\u2500\u2500 cramino_ubam\n\u2502 \u2502 \u2502 \u251c\u2500\u2500 fibertoolsrs\n\u2502 \u2502 \u2502 \u251c\u2500\u2500 mosdepth\n\u2502 \u2502 \u2502 \u251c\u2500\u2500 samtools\n\u2502 \u2502 \u251c\u2500\u2500 normal\n\u2502 \u2502 \u2502 \u251c\u2500\u2500 cramino_aln\n\u2502 \u2502 \u2502 \u251c\u2500\u2500 cramino_ubam\n\u2502 \u2502 \u2502 \u251c\u2500\u2500 fibertoolsrs\n\u2502 \u2502 \u2502 \u251c\u2500\u2500 mosdepth\n\u2502 \u2502 \u2502 \u251c\u2500\u2500 samtools\n\u2502 \u251c\u2500\u2500 variants\n\u2502 \u2502 \u251c\u2500\u2500 clair3\n\u2502 \u2502 \u251c\u2500\u2500 clairS\n\u2502 \u2502 \u251c\u2500\u2500 severus\n\u2502 \u251c\u2500\u2500 vep\n\u2502 \u2502 \u251c\u2500\u2500 germline\n\u2502 \u2502 \u251c\u2500\u2500 somatic\n\u2502 \u2502 \u251c\u2500\u2500 SVs\n\u251c\u2500\u2500 pipeline_info\n```\n\nmore detail is given in our [output documentation](/docs/output.md)\n\n## Contributions and Support\n\nIf you would like to contribute to this pipeline, please see the [contributing guidelines](docs/CONTRIBUTING.md).\n\n## Citations\n\nIf you use `IntGenomicsLab/lrsomatic` for your analysis, please cite it using the following:\n\n> LRSomatic: a highly scalable and robust pipeline for somatic variant calling in long-read sequencing data\n>\n> Robert A. Forsyth*, Luuk Harbers*, Amber Verhasselt, Ana-Luc\u00eda Rocha Iraiz\u00f3s, Sidi Yang, Joris Vande Velde, Christopher Davies, Nischalan Pillay, Laurens Lambrechts, Jonas Demeulemeester\n>\n> bioRxiv 2026.02.26.707772; doi: https://doi.org/10.64898/2026.02.26.707772\n\nAn extensive list of references for the tools used by the pipeline can be found in the [`CITATIONS.md`](CITATIONS.md) file.\n\nThis pipeline uses code and infrastructure developed and maintained by the [nf-core](https://nf-co.re) community, reused here under the [MIT license](https://github.com/nf-core/tools/blob/main/LICENSE).\n\n> **The nf-core framework for community-curated bioinformatics pipelines.**\n>\n> Philip Ewels, Alexander Peltzer, Sven Fillinger, Harshil Patel, Johannes Alneberg, Andreas Wilm, Maxime Ulysse Garcia, Paolo Di Tommaso & Sven Nahnsen.\n>\n> _Nat Biotechnol._ 2020 Feb 13. doi: [10.1038/s41587-020-0439-x](https://dx.doi.org/10.1038/s41587-020-0439-x).\n", + "description": "# IntGenomicsLab/lrsomatic\n\n[![Open in GitHub Codespaces](https://img.shields.io/badge/Open_In_GitHub_Codespaces-black?labelColor=grey&logo=github)](https://github.com/codespaces/new/IntGenomicsLab/lrsomatic)\n[![GitHub Actions CI Status](https://github.com/IntGenomicsLab/lrsomatic/actions/workflows/nf-test.yml/badge.svg)](https://github.com/IntGenomicsLab/lrsomatic/actions/workflows/nf-test.yml)\n[![GitHub Actions Linting Status](https://github.com/IntGenomicsLab/lrsomatic/actions/workflows/linting.yml/badge.svg)](https://github.com/IntGenomicsLab/lrsomatic/actions/workflows/linting.yml)[![Cite with Zenodo](http://img.shields.io/badge/DOI-10.5281/zenodo.17751829-1073c8?labelColor=000000)](https://doi.org/10.5281/zenodo.17751829)\n[![nf-test](https://img.shields.io/badge/unit_tests-nf--test-337ab7.svg)](https://www.nf-test.com)\n\n[![Nextflow](https://img.shields.io/badge/version-%E2%89%A525.04.0-green?style=flat&logo=nextflow&logoColor=white&color=%230DC09D&link=https%3A%2F%2Fnextflow.io)](https://www.nextflow.io/)\n[![nf-core template version](https://img.shields.io/badge/nf--core_template-4.0.2-green?style=flat&logo=nfcore&logoColor=white&color=%2324B064&link=https%3A%2F%2Fnf-co.re)](https://github.com/nf-core/tools/releases/tag/4.0.2)\n[![run with conda](http://img.shields.io/badge/run%20with-conda-3EB049?labelColor=000000&logo=anaconda)](https://docs.conda.io/en/latest/)\n[![run with docker](https://img.shields.io/badge/run%20with-docker-0db7ed?labelColor=000000&logo=docker)](https://www.docker.com/)\n[![run with singularity](https://img.shields.io/badge/run%20with-singularity-1d355c.svg?labelColor=000000)](https://sylabs.io/docs/)\n[![Launch on Seqera Platform](https://img.shields.io/badge/Launch%20%F0%9F%9A%80-Seqera%20Platform-%234256e7)](https://cloud.seqera.io/launch?pipeline=https://github.com/IntGenomicsLab/lrsomatic)\n\n## Introduction\n\n**IntGenomicsLab/lrsomatic** is a robust bioinformatics pipeline designed for processing and analyzing **somatic DNA sequencing** data for long-read sequencing technologies from **Oxford Nanopore** and **PacBio**. It supports both canonical base DNA and modified base calling, including specialized applications such as **Fiber-seq**.\n\nThis **end-to-end pipeline** handles the entire workflow \u2014 **from raw read processing and alignment, to comprehensive somatic variant calling**, including single nucleotide variants, indels, structural variants, copy number alterations, and modified bases.\n\nIt can be run in both **matched tumour-normal** and **tumour-only mode**, offering flexibility depending on the users study design.\n\nDeveloped using **Nextflow DSL2**, it offers high portability and scalability across diverse computing environments. By leveraging Docker or Singularity containers, installation is streamlined and results are highly reproducible. Each process runs in an isolated container, simplifying dependency management and updates. Where applicable, pipeline components are sourced from **nf-core/modules**, promoting reuse, interoperability, and consistency within the broader Nextflow and nf-core ecosystems.\n\nFor more information on how to run the pipeline, you can also go [here](https://intgenomicslab.github.io/lrsomatic).\n\n## Pipeline summary\n\n![image](./assets/lrsomatic_1.0.png)\n\n**1) Pre-processing:**\n\na. Raw read QC ([`cramino`](https://github.com/wdecoster/cramino))\n\nb. Alignment to the reference genome ([`minimap2`](https://github.com/lh3/minimap2))\n\nc. Post alignment QC ([`cramino`](https://github.com/wdecoster/cramino), [`samtools idxstats`](https://github.com/samtools/samtools), [`samtools flagstats`](https://github.com/samtools/samtools), [`samtools stats`](https://github.com/samtools/samtools))\n\nd. Specific for calling modified base calling ([`Modkit`](https://github.com/nanoporetech/modkit), [`Fibertools`](https://github.com/fiberseq/fibertools-rs))\n\n**2i) Matched mode: small variant calling:**\n\na. Calling Germline SNPs ([`Clair3`](https://github.com/HKU-BAL/Clair3))\n\nb. Phasing and Haplotagging the SNPs in the normal and tumour BAM ([`LongPhase`](https://github.com/twolinin/longphase))\n\nc. Calling somatic SNVs ([`ClairS`](https://github.com/HKU-BAL/ClairS))\n\n**2ii) Tumour only mode: small variant calling:**\n\na. Calling Germline SNPs and somatic SNVs ([`ClairS-TO`](https://github.com/HKU-BAL/ClairS-TO))\n\nb. Phasing and Haplotagging germline SNPs in tumour BAM ([`LongPhase`](https://github.com/twolinin/longphase))\n\n**3) Large variant calling:**\n\na. Somatic structural variant calling ([`Severus`](https://github.com/KolmogorovLab/Severus))\n\nb. Copy number alterion calling; long read version of ([`ASCAT`](https://github.com/VanLoo-lab/ascat))\n\n**4) Annotation:**\n\na. Small variant annotation ([`VEP`](https://github.com/Ensembl/ensembl-vep))\n\nb. Structural variant annotation ([`VEP`](https://github.com/Ensembl/ensembl-vep))\n\n\n\n## Usage\n\n> [!NOTE]\n> If you are new to Nextflow and nf-core, please refer to [this page](https://nf-co.re/docs/usage/installation) on how to set-up Nextflow. Make sure to [test your setup](https://nf-co.re/docs/usage/introduction#how-to-run-a-pipeline) with `-profile test` before running the workflow on actual data.\n\nFirst prepare a samplesheet with your input data that looks as follows:\n\n```csv\nsample,bam_tumor,bam_normal,platform,sex,fiber\nsample1,tumour.bam,normal.bam,ont,female,n\nsample2,tumour.bam,,ont,female,y\nsample3,tumour.bam,,pb,male,n\nsample4,tumour.bam,normal.bam,pb,male,y\n```\n\nEach row represents a sample. The bam files should always be unaligned bam files. All fields except for `bam_normal` are required. If `bam_normal` is empty, the pipeline will run in tumour only mode. `platform` should be either `ont` or `pb` for Oxford Nanopore Sequencing or PacBio sequencing, respectively. `sex` refers to the biological sex of the sample and should be either `female` or `male`. Finally, `fiber` specifies whether your sample is Fiber-seq data or not and should have either `y` for Yes or `n` for No.\n\nNow, you can run the pipeline using:\n\n```bash\nnextflow run IntGenomicsLab/lrsomatic \\\n -profile \\\n --input samplesheet.csv \\\n --outdir \n```\n\nMore detail is given in our [usage documentation](/docs/usage.md)\n\n> [!WARNING]\n> Please provide pipeline parameters via the CLI or Nextflow `-params-file` option. Custom config files including those provided by the `-c` Nextflow option can be used to provide any configuration _**except for parameters**_; see [docs](https://nf-co.re/docs/running/run-pipelines#using-parameter-files).\n\n## Credits\n\nIntGenomicsLab/lr_somatic was originally written by Luuk Harbers, Robert Forsyth, Alexandra Pan\u010d\u00edkov\u00e1, Marios Eftychiou, Ruben Cools, Laurens Lambrechts, and Jonas Demeulemeester.\n\n## Pipeline output\n\nThis pipeline produces a series of different output files. The main output is an aligned and phased tumour bam file. This bam file can be used by any typical downstream tool that uses bam files as input. Furthermore, we have sample-specific QC outputs from `cramino` (fastq), `cramino` (bam), `mosdepth`, `samtools` (stats/flagstat/idxstats), and optionally `fibertools`. Finally, we have a `multiqc` report from that combines the output from `mosdepth` and `samtools` into one html report, and a self-contained per-sample HTML report (`/report/_report.html`) covering small variants, structural variants, copy number and QC in one place \u2014 disable it with `--skip_report`.\n\nBesides QC and the aligned and phased bam file, we have output from (structural) variant and copy number callers, of which some are optional. The output from these variant callers can be found in their respective folders. For small and structural variant callers (`clairS`, `clairS-TO`, and `severus`) these will contain, among others, `vcf` files with called variants. For `ascat` these contain files with final copy number information and plots of the copy number profiles.\n\nExample output directory structure:\n\n```\n\u251c\u2500\u2500 Sample 1\n\u2502 \u251c\u2500\u2500 ascat\n\u2502 \u251c\u2500\u2500 bamfiles\n\u2502 \u251c\u2500\u2500 qc\n\u2502 \u2502 \u251c\u2500\u2500 tumor\n\u2502 \u2502 \u2502 \u251c\u2500\u2500 cramino_aln\n\u2502 \u2502 \u2502 \u251c\u2500\u2500 cramino_ubam\n\u2502 \u2502 \u2502 \u251c\u2500\u2500 fibertoolsrs\n\u2502 \u2502 \u2502 \u251c\u2500\u2500 mosdepth\n\u2502 \u2502 \u2502 \u251c\u2500\u2500 samtools\n\u2502 \u251c\u2500\u2500 variants\n\u2502 \u2502 \u251c\u2500\u2500clairS-TO\n\u2502 \u2502 \u251c\u2500\u2500severus\n\u2502 \u251c\u2500\u2500 vep\n\u2502 \u2502 \u251c\u2500\u2500 germline\n\u2502 \u2502 \u251c\u2500\u2500 somatic\n\u2502 \u2502 \u251c\u2500\u2500 SVs\n\u2502 \u251c\u2500\u2500 report\n\u2502\n\u251c\u2500\u2500 Sample 2\n\u2502 \u251c\u2500\u2500 ascat\n\u2502 \u251c\u2500\u2500 bamfiles\n\u2502 \u251c\u2500\u2500 qc\n\u2502 \u2502 \u251c\u2500\u2500 tumor\n\u2502 \u2502 \u2502 \u251c\u2500\u2500 cramino_aln\n\u2502 \u2502 \u2502 \u251c\u2500\u2500 cramino_ubam\n\u2502 \u2502 \u2502 \u251c\u2500\u2500 fibertoolsrs\n\u2502 \u2502 \u2502 \u251c\u2500\u2500 mosdepth\n\u2502 \u2502 \u2502 \u251c\u2500\u2500 samtools\n\u2502 \u2502 \u251c\u2500\u2500 normal\n\u2502 \u2502 \u2502 \u251c\u2500\u2500 cramino_aln\n\u2502 \u2502 \u2502 \u251c\u2500\u2500 cramino_ubam\n\u2502 \u2502 \u2502 \u251c\u2500\u2500 fibertoolsrs\n\u2502 \u2502 \u2502 \u251c\u2500\u2500 mosdepth\n\u2502 \u2502 \u2502 \u251c\u2500\u2500 samtools\n\u2502 \u251c\u2500\u2500 variants\n\u2502 \u2502 \u251c\u2500\u2500 clair3\n\u2502 \u2502 \u251c\u2500\u2500 clairS\n\u2502 \u2502 \u251c\u2500\u2500 severus\n\u2502 \u251c\u2500\u2500 vep\n\u2502 \u2502 \u251c\u2500\u2500 germline\n\u2502 \u2502 \u251c\u2500\u2500 somatic\n\u2502 \u2502 \u251c\u2500\u2500 SVs\n\u251c\u2500\u2500 pipeline_info\n```\n\nmore detail is given in our [output documentation](/docs/output.md)\n\n## Contributions and Support\n\nIf you would like to contribute to this pipeline, please see the [contributing guidelines](docs/CONTRIBUTING.md).\n\n## Citations\n\nIf you use `IntGenomicsLab/lrsomatic` for your analysis, please cite it using the following:\n\n> LRSomatic: a highly scalable and robust pipeline for somatic variant calling in long-read sequencing data\n>\n> Robert A. Forsyth*, Luuk Harbers*, Amber Verhasselt, Ana-Luc\u00eda Rocha Iraiz\u00f3s, Sidi Yang, Joris Vande Velde, Christopher Davies, Nischalan Pillay, Laurens Lambrechts, Jonas Demeulemeester\n>\n> bioRxiv 2026.02.26.707772; doi: https://doi.org/10.64898/2026.02.26.707772\n\nAn extensive list of references for the tools used by the pipeline can be found in the [`CITATIONS.md`](CITATIONS.md) file.\n\nThis pipeline uses code and infrastructure developed and maintained by the [nf-core](https://nf-co.re) community, reused here under the [MIT license](https://github.com/nf-core/tools/blob/main/LICENSE).\n\n> **The nf-core framework for community-curated bioinformatics pipelines.**\n>\n> Philip Ewels, Alexander Peltzer, Sven Fillinger, Harshil Patel, Johannes Alneberg, Andreas Wilm, Maxime Ulysse Garcia, Paolo Di Tommaso & Sven Nahnsen.\n>\n> _Nat Biotechnol._ 2020 Feb 13. doi: [10.1038/s41587-020-0439-x](https://dx.doi.org/10.1038/s41587-020-0439-x).\n", "hasPart": [ { "@id": "main.nf" diff --git a/subworkflows/local/utils_nfcore_lrsomatic_pipeline/main.nf b/subworkflows/local/utils_nfcore_lrsomatic_pipeline/main.nf index 1afcfa01..873fb629 100644 --- a/subworkflows/local/utils_nfcore_lrsomatic_pipeline/main.nf +++ b/subworkflows/local/utils_nfcore_lrsomatic_pipeline/main.nf @@ -240,6 +240,82 @@ workflow PIPELINE_COMPLETION { // def validateInputParameters() { genomeExistsError() + validateReportGenePanels() +} + +// +// Split --report_gene_panel into panel tokens (mirrored in conf/modules.config) +// +def reportGenePanelTokens(panel_spec) { + if (!panel_spec) { + return [] + } + return panel_spec.toString().split(',').collect { it.trim() }.findAll { it } +} + +// +// Does a --report_gene_panel entry name a file rather than a builtin? Textual because conf/modules.config makes the same call without file() +// +def reportGenePanelIsFile(tok) { + return tok.contains('/') || tok.toLowerCase().endsWith('.tsv') +} + +// +// Builtin panel names bundled with the report tool, reference suffix dropped +// +def reportBuiltinGenePanels() { + def gene_lists_dir = file("${params.report_src}/assets/gene_lists") + if (!gene_lists_dir.exists()) { + return [] + } + return gene_lists_dir + .list() + .findAll { it.endsWith('.tsv') } + .collect { it.replaceFirst(/(\.(hg38|t2t))?\.tsv$/, '') } + .unique() + .sort() +} + +// +// Validate --report_gene_panel at launch so a typo fails before alignment and calling run +// +def validateReportGenePanels() { + if (params.skip_report) { + return + } + def tokens = reportGenePanelTokens(params.report_gene_panel) + if (!tokens) { + return + } + + // "none" means unfiltered, so combining it with a real panel is contradictory + if (tokens.size() > 1 && tokens.any { it.toLowerCase() == 'none' }) { + error("--report_gene_panel: 'none' means unfiltered and cannot be combined with other panels, got '${params.report_gene_panel}'. Drop the 'none'.") + } + + def named = tokens.findAll { tok -> tok.toLowerCase() != 'none' && !reportGenePanelIsFile(tok) } + def panel_files = tokens.findAll { tok -> reportGenePanelIsFile(tok) } + + def missing = panel_files.findAll { tok -> !file(tok).exists() } + if (missing) { + error("--report_gene_panel: panel file not found: '${missing.join("', '")}'.") + } + + def builtins = reportBuiltinGenePanels() + def unknown = named.findAll { tok -> !builtins.contains(tok) } + if (unknown) { + error("--report_gene_panel: '${unknown.join("', '")}' is not a builtin panel. Builtin panels: ${builtins ? builtins.join(', ') : ''}. To use a panel file give its path, or a name ending in '.tsv'; use 'none' for no filtering.") + } + + // Panel files are staged side by side into gene_panels/, so equal base names collide + def duplicates = panel_files + .collect { tok -> file(tok).name } + .countBy { name -> name } + .findAll { _name, count -> count > 1 } + .keySet() + if (duplicates) { + error("--report_gene_panel: panel files sharing a base name cannot be used together ('${duplicates.join("', '")}'). Rename one of them.") + } } // diff --git a/tests/.nftignore b/tests/.nftignore index a1de7635..baa4d5de 100644 --- a/tests/.nftignore +++ b/tests/.nftignore @@ -27,3 +27,7 @@ pipeline_info/*.{html,json,txt,yml} */qc/{tumor,normal}/mosdepth/*.txt */variants/deepsomatic/*.{vcf.gz,vcf.gz.tbi} */variants/deepvariant/*.{vcf.gz,vcf.gz.tbi} +*/report/*.html +# samtools merge gives sample4's colliding @PG IDs a random suffix, so this BAM's md5 differs every run (reads asserted in tests/clair_only.nf.test) +sample4/bamfiles/sample4_tumor.bam +sample4/bamfiles/sample4_tumor.bam.bai diff --git a/tests/clair_only.nf.test b/tests/clair_only.nf.test index c6ac517e..9bf57991 100644 --- a/tests/clair_only.nf.test +++ b/tests/clair_only.nf.test @@ -139,6 +139,15 @@ nextflow_pipeline { } }, + // ── sample4: merged BAM content ────────────────────────────── + { + // sample4's merged BAM has an unstable md5 (see tests/.nftignore), so + // assert the reads instead + assert snapshot( + bam("$launchDir/output/sample4/bamfiles/sample4_tumor.bam", stringency: 'silent').getReadsMD5() + ).match("sample4_merged_reads") + }, + // ── Snapshot ───────────────────────────────────────────────── { assert snapshot( removeNextflowVersion("$outputDir/pipeline_info/lrsomatic_software_mqc_versions.yml"), diff --git a/tests/clair_only.nf.test.snap b/tests/clair_only.nf.test.snap index 50bca67b..6ad17ecd 100644 --- a/tests/clair_only.nf.test.snap +++ b/tests/clair_only.nf.test.snap @@ -1,4 +1,14 @@ { + "sample4_merged_reads": { + "content": [ + "88c8d3cf9cb49fdbc53372b2275d5f3e" + ], + "timestamp": "2026-09-02T10:24:37.511974063", + "meta": { + "nf-test": "0.9.4", + "nextflow": "26.04.3" + } + }, "-profile test, clair only, extended samplesheet": { "content": [ { @@ -46,6 +56,9 @@ "LONGPHASE_PHASE_SOMATIC": { "longphase": "2.0.1" }, + "LRSOMATICREPORT": { + "lrsomatic_report": "1.3.2" + }, "METAEXTRACT": { "samtools": 1.21 }, @@ -271,6 +284,8 @@ "sample1/qc/whatshap_stats/sample1_whatshap_stats.gtf", "sample1/qc/whatshap_stats/sample1_whatshap_stats.log", "sample1/qc/whatshap_stats/sample1_whatshap_stats.tsv", + "sample1/report", + "sample1/report/sample1_report.html", "sample1/variants", "sample1/variants/clair3", "sample1/variants/clair3/merge_output.vcf.gz", @@ -386,6 +401,8 @@ "sample2/qc/whatshap_stats/sample2_whatshap_stats.gtf", "sample2/qc/whatshap_stats/sample2_whatshap_stats.log", "sample2/qc/whatshap_stats/sample2_whatshap_stats.tsv", + "sample2/report", + "sample2/report/sample2_report.html", "sample2/variants", "sample2/variants/clair3", "sample2/variants/clair3/merge_output.vcf.gz", @@ -468,6 +485,8 @@ "sample3/qc/whatshap_stats/sample3_whatshap_stats.gtf", "sample3/qc/whatshap_stats/sample3_whatshap_stats.log", "sample3/qc/whatshap_stats/sample3_whatshap_stats.tsv", + "sample3/report", + "sample3/report/sample3_report.html", "sample3/variants", "sample3/variants/clairsto", "sample3/variants/clairsto/germline.vcf.gz", @@ -561,6 +580,8 @@ "sample4/qc/whatshap_stats/sample4_whatshap_stats.gtf", "sample4/qc/whatshap_stats/sample4_whatshap_stats.log", "sample4/qc/whatshap_stats/sample4_whatshap_stats.tsv", + "sample4/report", + "sample4/report/sample4_report.html", "sample4/variants", "sample4/variants/clairsto", "sample4/variants/clairsto/germline.vcf.gz", @@ -644,6 +665,8 @@ "sample5/qc/whatshap_stats/sample5_whatshap_stats.gtf", "sample5/qc/whatshap_stats/sample5_whatshap_stats.log", "sample5/qc/whatshap_stats/sample5_whatshap_stats.tsv", + "sample5/report", + "sample5/report/sample5_report.html", "sample5/variants", "sample5/variants/clairsto", "sample5/variants/clairsto/germline.vcf.gz", @@ -741,8 +764,6 @@ "read_qual.txt:md5,b918430d35354dad1d7f02f21e4cd4ed", "breakpoint_clusters.tsv:md5,d36a70de292ee130ef30da4a58bced18", "breakpoint_clusters_list.tsv:md5,0c0ce62e329f8de492487e8414c30a50", - "sample4_tumor.bam:md5,598d3f6c6c1dd30edc5b96a34932d3ac", - "sample4_tumor.bam.bai:md5,39d022831f9927574898140340a75111", "sample4.flagstat:md5,5710382ba31b23172ca19f9407f689b4", "sample4.idxstats:md5,3bf4793a1667f41f0b31d578f99e3955", "sample4.stats:md5,b998982ea897721c529959e39b693ec6", @@ -771,10 +792,10 @@ "breakpoint_clusters_list.tsv:md5,0c0ce62e329f8de492487e8414c30a50" ] ], + "timestamp": "2026-09-02T10:24:40.426465897", "meta": { - "nf-test": "0.9.3", - "nextflow": "26.04.1" - }, - "timestamp": "2026-06-03T11:04:06.530937361" + "nf-test": "0.9.4", + "nextflow": "26.04.3" + } } } \ No newline at end of file diff --git a/tests/consensus.nf.test.snap b/tests/consensus.nf.test.snap index d4a6c508..2a50355a 100644 --- a/tests/consensus.nf.test.snap +++ b/tests/consensus.nf.test.snap @@ -79,6 +79,9 @@ "LONGPHASE_PHASE_SOMATIC": { "longphase": "2.0.1" }, + "LRSOMATICREPORT": { + "lrsomatic_report": "1.3.2" + }, "METAEXTRACT": { "samtools": 1.21 }, @@ -301,6 +304,8 @@ "sample1/qc/whatshap_stats/sample1_whatshap_stats.gtf", "sample1/qc/whatshap_stats/sample1_whatshap_stats.log", "sample1/qc/whatshap_stats/sample1_whatshap_stats.tsv", + "sample1/report", + "sample1/report/sample1_report.html", "sample1/variants", "sample1/variants/clair3", "sample1/variants/clair3/merge_output.vcf.gz", @@ -422,6 +427,8 @@ "sample2/qc/whatshap_stats/sample2_whatshap_stats.gtf", "sample2/qc/whatshap_stats/sample2_whatshap_stats.log", "sample2/qc/whatshap_stats/sample2_whatshap_stats.tsv", + "sample2/report", + "sample2/report/sample2_report.html", "sample2/variants", "sample2/variants/clair3", "sample2/variants/clair3/merge_output.vcf.gz", @@ -510,6 +517,8 @@ "sample3/qc/whatshap_stats/sample3_whatshap_stats.gtf", "sample3/qc/whatshap_stats/sample3_whatshap_stats.log", "sample3/qc/whatshap_stats/sample3_whatshap_stats.tsv", + "sample3/report", + "sample3/report/sample3_report.html", "sample3/variants", "sample3/variants/clairsto", "sample3/variants/clairsto/germline.vcf.gz", diff --git a/tests/deep_only.nf.test.snap b/tests/deep_only.nf.test.snap index e1087305..8acb6d4f 100644 --- a/tests/deep_only.nf.test.snap +++ b/tests/deep_only.nf.test.snap @@ -55,6 +55,9 @@ "LONGPHASE_PHASE_SOMATIC": { "longphase": "2.0.1" }, + "LRSOMATICREPORT": { + "lrsomatic_report": "1.3.2" + }, "METAEXTRACT": { "samtools": 1.21 }, @@ -271,6 +274,8 @@ "sample1/qc/whatshap_stats/sample1_whatshap_stats.gtf", "sample1/qc/whatshap_stats/sample1_whatshap_stats.log", "sample1/qc/whatshap_stats/sample1_whatshap_stats.tsv", + "sample1/report", + "sample1/report/sample1_report.html", "sample1/variants", "sample1/variants/deepsomatic", "sample1/variants/deepsomatic/sample1_somatic.vcf.gz", @@ -384,6 +389,8 @@ "sample2/qc/whatshap_stats/sample2_whatshap_stats.gtf", "sample2/qc/whatshap_stats/sample2_whatshap_stats.log", "sample2/qc/whatshap_stats/sample2_whatshap_stats.tsv", + "sample2/report", + "sample2/report/sample2_report.html", "sample2/variants", "sample2/variants/deepsomatic", "sample2/variants/deepsomatic/sample2_somatic.vcf.gz", @@ -464,6 +471,8 @@ "sample3/qc/whatshap_stats/sample3_whatshap_stats.gtf", "sample3/qc/whatshap_stats/sample3_whatshap_stats.log", "sample3/qc/whatshap_stats/sample3_whatshap_stats.tsv", + "sample3/report", + "sample3/report/sample3_report.html", "sample3/variants", "sample3/variants/deepsomatic", "sample3/variants/deepsomatic/sample3_somatic.vcf.gz", diff --git a/tests/default.nf.test b/tests/default.nf.test index 98934f64..f2d04df9 100644 --- a/tests/default.nf.test +++ b/tests/default.nf.test @@ -10,6 +10,8 @@ nextflow_pipeline { when { params { outdir = "$outputDir" + // A builtin plus a panel file, covering the comma-separated form end to end + report_gene_panel = "lymphoid,$projectDir/modules/local/lrsomaticreport/tests/test_panel.tsv" } } @@ -44,6 +46,14 @@ nextflow_pipeline { assert file("$launchDir/output/sample3/variants/clairsto/somatic.vcf.gz").exists() assert file("$launchDir/output/sample3/variants/clairsto/germline.vcf.gz").exists() }, + { // both panels named in --report_gene_panel are ticked on load + def report = file("$launchDir/output/sample1/report/sample1_report.html") + assert report.exists() + def matcher = (report.text =~ /const DEFAULT_PANELS = (\[[^\]]*\])/) + assert matcher.find() + assert matcher.group(1).contains("lymphoid") + assert matcher.group(1).contains("test_panel") + }, { assert snapshot( // pipeline versions.yml file for multiqc from which Nextflow version is removed because we test pipelines on multiple Nextflow versions removeNextflowVersion("$outputDir/pipeline_info/lrsomatic_software_mqc_versions.yml"), diff --git a/tests/default.nf.test.snap b/tests/default.nf.test.snap index c3ba2e30..b9c829c5 100644 --- a/tests/default.nf.test.snap +++ b/tests/default.nf.test.snap @@ -46,6 +46,9 @@ "LONGPHASE_PHASE_SOMATIC": { "longphase": "2.0.1" }, + "LRSOMATICREPORT": { + "lrsomatic_report": "1.3.2" + }, "METAEXTRACT": { "samtools": 1.21 }, @@ -265,6 +268,8 @@ "sample1/qc/whatshap_stats/sample1_whatshap_stats.gtf", "sample1/qc/whatshap_stats/sample1_whatshap_stats.log", "sample1/qc/whatshap_stats/sample1_whatshap_stats.tsv", + "sample1/report", + "sample1/report/sample1_report.html", "sample1/variants", "sample1/variants/clair3", "sample1/variants/clair3/merge_output.vcf.gz", @@ -380,6 +385,8 @@ "sample2/qc/whatshap_stats/sample2_whatshap_stats.gtf", "sample2/qc/whatshap_stats/sample2_whatshap_stats.log", "sample2/qc/whatshap_stats/sample2_whatshap_stats.tsv", + "sample2/report", + "sample2/report/sample2_report.html", "sample2/variants", "sample2/variants/clair3", "sample2/variants/clair3/merge_output.vcf.gz", @@ -462,6 +469,8 @@ "sample3/qc/whatshap_stats/sample3_whatshap_stats.gtf", "sample3/qc/whatshap_stats/sample3_whatshap_stats.log", "sample3/qc/whatshap_stats/sample3_whatshap_stats.tsv", + "sample3/report", + "sample3/report/sample3_report.html", "sample3/variants", "sample3/variants/clairsto", "sample3/variants/clairsto/germline.vcf.gz", @@ -561,10 +570,10 @@ "breakpoint_clusters_list.tsv:md5,0c0ce62e329f8de492487e8414c30a50" ] ], + "timestamp": "2026-07-16T19:16:20.692019944", "meta": { - "nf-test": "0.9.3", - "nextflow": "26.04.1" - }, - "timestamp": "2026-06-01T15:01:21.469856129" + "nf-test": "0.9.4", + "nextflow": "26.04.3" + } } } \ No newline at end of file diff --git a/tests/union.nf.test.snap b/tests/union.nf.test.snap index df520c8d..d7753bf9 100644 --- a/tests/union.nf.test.snap +++ b/tests/union.nf.test.snap @@ -76,6 +76,9 @@ "LONGPHASE_PHASE_SOMATIC": { "longphase": "2.0.1" }, + "LRSOMATICREPORT": { + "lrsomatic_report": "1.3.2" + }, "METAEXTRACT": { "samtools": 1.21 }, @@ -301,6 +304,8 @@ "sample1/qc/whatshap_stats/sample1_whatshap_stats.gtf", "sample1/qc/whatshap_stats/sample1_whatshap_stats.log", "sample1/qc/whatshap_stats/sample1_whatshap_stats.tsv", + "sample1/report", + "sample1/report/sample1_report.html", "sample1/variants", "sample1/variants/clair3", "sample1/variants/clair3/merge_output.vcf.gz", @@ -422,6 +427,8 @@ "sample2/qc/whatshap_stats/sample2_whatshap_stats.gtf", "sample2/qc/whatshap_stats/sample2_whatshap_stats.log", "sample2/qc/whatshap_stats/sample2_whatshap_stats.tsv", + "sample2/report", + "sample2/report/sample2_report.html", "sample2/variants", "sample2/variants/clair3", "sample2/variants/clair3/merge_output.vcf.gz", @@ -510,6 +517,8 @@ "sample3/qc/whatshap_stats/sample3_whatshap_stats.gtf", "sample3/qc/whatshap_stats/sample3_whatshap_stats.log", "sample3/qc/whatshap_stats/sample3_whatshap_stats.tsv", + "sample3/report", + "sample3/report/sample3_report.html", "sample3/variants", "sample3/variants/clairsto", "sample3/variants/clairsto/germline.vcf.gz", diff --git a/tower.yml b/tower.yml index 787aedfe..316af346 100644 --- a/tower.yml +++ b/tower.yml @@ -1,5 +1,7 @@ reports: multiqc_report.html: display: "MultiQC HTML report" + "**/report/*_report.html": + display: "Per-sample LRSomatic HTML report" samplesheet.csv: display: "Auto-created samplesheet with collated metadata and FASTQ paths" diff --git a/workflows/lrsomatic.nf b/workflows/lrsomatic.nf index 211552df..16bb2ab2 100644 --- a/workflows/lrsomatic.nf +++ b/workflows/lrsomatic.nf @@ -9,6 +9,8 @@ include { paramsSummaryMultiqc } from '../subworkflows/nf-core/utils_nfcore_pi include { softwareVersionsToYAML } from '../subworkflows/nf-core/utils_nfcore_pipeline' include { methodsDescriptionText } from '../subworkflows/local/utils_nfcore_lrsomatic_pipeline' include { getGenomeAttribute } from '../subworkflows/local/utils_nfcore_lrsomatic_pipeline' +include { reportGenePanelTokens } from '../subworkflows/local/utils_nfcore_lrsomatic_pipeline' +include { reportGenePanelIsFile } from '../subworkflows/local/utils_nfcore_lrsomatic_pipeline' // // IMPORT MODULES @@ -26,6 +28,7 @@ include { ASCAT } from '../modules/nf-core/ascat/mai include { SEVERUS } from '../modules/nf-core/severus/main.nf' include { METAEXTRACT } from '../modules/local/metaextract/main' include { WAKHAN } from '../modules/local/wakhan/main' +include { LRSOMATICREPORT } from '../modules/local/lrsomaticreport/main' include { FIBERTOOLSRS_PREDICTM6A } from '../modules/local/fibertoolsrs/predictm6a' include { FIBERTOOLSRS_FIRE } from '../modules/local/fibertoolsrs/fire' include { FIBERTOOLSRS_NUCLEOSOMES } from '../modules/local/fibertoolsrs/nucleosomes' @@ -540,8 +543,8 @@ workflow LRSOMATIC { ch_index_minimap .branch { meta, _bams, _bais -> - paired: meta.paired_data // meta.paired_data is the normal sample ID for tumors, or the tumor ID for normals - tumor_only: !meta.paired_data // meta.paired_data is null/false for tumor-only samples + paired: meta.paired_data + tumor_only: !meta.paired_data } .set { branched_minimap } @@ -706,6 +709,8 @@ workflow LRSOMATIC { } + ch_somatic_vep_vcf = channel.empty() + if (!params.skip_vep) { // @@ -756,6 +761,8 @@ workflow LRSOMATIC { vep_custom, vep_custom_tbi ) + + ch_somatic_vep_vcf = SOMATIC_VEP.out.vcf } // Build SEVERUS input by combining tumor-only and T/N paired samples with phased germline VCFs @@ -808,6 +815,8 @@ workflow LRSOMATIC { .set { sv_vep } // sv_vep: [meta, severus_all_vcf, []] -- all SVs ready for VEP annotation + ch_sv_vep_vcf = channel.empty() + if(!params.skip_vep) { // // MODULE: SV_VEP (ENSEMBLVEP_VEP alias; label: process_medium) @@ -825,10 +834,13 @@ workflow LRSOMATIC { vep_custom, vep_custom_tbi ) + + ch_sv_vep_vcf = SV_VEP.out.vcf } ch_nanoplot_post_txt = channel.empty() + ch_cramino_post_txt = channel.empty() if (!params.skip_qc && !params.skip_cramino) { @@ -841,6 +853,8 @@ workflow LRSOMATIC { CRAMINO_POST ( ch_minimap_bam ) + ch_cramino_post_txt = CRAMINO_POST.out.txt + if (!params.skip_nanoplot) { // @@ -918,6 +932,8 @@ workflow LRSOMATIC { // Output: .png plots, .segments, .purity_ploidy -- copy number results // + ch_ascat_files = channel.empty() + if (!params.skip_ascat) { // ASCAT expects [normal, tumor] order; rearrange from severus_input [tumor, normal] order severus_input @@ -939,6 +955,14 @@ workflow LRSOMATIC { ) ch_versions = ch_versions.mix(ASCAT.out.versions) + + // Collect all ASCAT copy-number files (segments_raw, purityploidy, diagnostic PNGs) per sample + // for the final report module -- it globs by suffix, so exact grouping doesn't matter. + ch_ascat_files = ASCAT.out.segments_raw + .mix(ASCAT.out.purityploidy, ASCAT.out.png) + .groupTuple() + .map { meta, files -> [meta, files.flatten()] } + // ch_ascat_files: [meta, [file, file, ...]] } // @@ -950,6 +974,8 @@ workflow LRSOMATIC { // Output: WAKHAN assembly reports (written to outdir) // + ch_wakhan_files = channel.empty() + if (!params.skip_wakhan) { // Attach SEVERUS SV VCF to the severus_input channel (dropping the phased TBI) @@ -967,6 +993,108 @@ workflow LRSOMATIC { ch_fasta, file(params.centromere_bed) ) + + // The subset of WAKHAN's outputs the report renders: the ranked purity/ploidy + // solutions, the ploidy/purity heatmap and each solution's plot directory + ch_wakhan_files = WAKHAN.out.solutions_ranks + .mix(WAKHAN.out.heatmap_html, WAKHAN.out.solution_dirs) + .groupTuple() + .map { meta, files -> [meta, files.flatten()] } // solution_dirs contributes a list + // ch_wakhan_files: [meta, [file_or_dir, ...]] + } + + // + // MODULE: LRSOMATICREPORT (final per-sample HTML report; every input is optional, so the joins use `remainder: true` keyed on the tumor sample id) + // + + if (!params.skip_report) { + + // Report identity: the tumor sample's id, carrying the meta to attach to the module call + severus_input + .map { meta, _tumor_bam, _tumor_bai, _normal_bam, _normal_bai, _phased_vcf, _phased_tbi -> + return [meta.id, meta] + } + .set { report_id_meta } + // report_id_meta: [id, meta] + + ch_somatic_vep_vcf + .map { meta, vcf -> [meta.id, vcf] } + .set { report_vep_ch } + + ch_sv_vep_vcf + .map { meta, vcf -> [meta.id, vcf] } + .set { report_sv_vep_ch } + + SEVERUS.out.somatic_vcf + .map { meta, vcf -> [meta.id, vcf] } + .set { report_severus_ch } + + PHASING_HAPLOTYPING.out.phased_somatic_vcf + .map { meta, vcf, _tbi -> [meta.id, vcf] } + .set { report_somatic_ch } + + ch_ascat_files + .map { meta, files -> [meta.id, files] } + .set { report_ascat_ch } + + ch_wakhan_files + .map { meta, files -> [meta.id, files] } + .set { report_wakhan_ch } + + // Tumor-side QC: keyed by the sample's own id, which for tumor rows is already the report id + ch_mosdepth_summary + .mix(ch_mosdepth_global, ch_cramino_post_txt, ch_bam_stats, ch_bam_flagstat) + .filter { meta, _f -> meta.type == 'tumor' } + .map { meta, f -> [meta.id, f] } + .groupTuple() + .set { report_qc_tumor_ch } + + // Normal-side QC (matched mode only): both rows of a pair share meta.id, so this is + // already keyed by the report id + ch_mosdepth_summary + .mix(ch_mosdepth_global, ch_cramino_post_txt, ch_bam_stats, ch_bam_flagstat) + .filter { meta, _f -> meta.type == 'normal' } + .map { meta, f -> [meta.id, f] } + .groupTuple() + .set { report_qc_normal_ch } + + report_id_meta + .join(report_vep_ch, remainder: true) + .join(report_sv_vep_ch, remainder: true) + .join(report_severus_ch, remainder: true) + .join(report_somatic_ch, remainder: true) + .join(report_ascat_ch, remainder: true) + .join(report_qc_tumor_ch, remainder: true) + .join(report_qc_normal_ch, remainder: true) + .join(report_wakhan_ch, remainder: true) + .filter { _id, meta, _vep, _sv_vep, _severus, _somatic, _ascat, _qc_t, _qc_n, _wakhan -> meta != null } + .map { _id, meta, vep, sv_vep_vcf, severus, somatic, ascat, qc_t, qc_n, wakhan -> + return [ + meta, + vep ?: [], + sv_vep_vcf ?: [], + severus ?: [], + somatic ?: [], + ascat ?: [], + qc_t ?: [], + qc_n ?: [], + wakhan ?: [] + ] + } + .set { report_input_ch } + // report_input_ch: [meta, vep_somatic, sv_vep, severus_vcf, somatic_vcf, ascat_files, qc_tumor_files, qc_normal_files, wakhan_files] + + // Only panel files need staging, so they are bound into the container; builtin names + // reach the tool through ext.args alone -- see conf/modules.config + def report_gene_panel_files = reportGenePanelTokens(params.report_gene_panel) + .findAll { tok -> reportGenePanelIsFile(tok) } + .collect { tok -> file(tok, checkIfExists: true) } + + LRSOMATICREPORT ( + report_input_ch, + file(params.report_src, checkIfExists: true), + report_gene_panel_files + ) } //