Skip to content

Commit e44a1e8

Browse files
committed
feat(#115): Add PINTS visualizer module
1 parent 06f479c commit e44a1e8

File tree

18 files changed

+370
-51
lines changed

18 files changed

+370
-51
lines changed

conf/test.config

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,4 +50,8 @@ process {
5050
withName: PINTS_CALLER {
5151
ext.args = { "--disable-small" }
5252
}
53+
54+
withName: PINTS_VISUALIZER {
55+
errorStrategy = 'ignore'
56+
}
5357
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
channels:
2+
- conda-forge
3+
- bioconda
4+
dependencies:
5+
- pybedtools
6+
- bedtools
7+
- htslib
8+
- python=3.12.6
9+
- pip
10+
- pybigwig
11+
- numpy
12+
- pip: # FIXME https://github.com/nf-core/modules/issues/5814
13+
# NOTE PINTS isn't adding conda builds and is a few versions behind.
14+
# renovate: datasource=pypi depName=pypints
15+
- pypints==1.1.15
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
process PINTS_VISUALIZER {
2+
tag "$meta.id"
3+
label 'process_medium'
4+
5+
conda "${moduleDir}/environment.yml"
6+
// NOTE Stopped publishing at 1.1.9 https://quay.io/repository/biocontainers/pypints?tab=tags
7+
container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ?
8+
'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/f1/f1a9e30012e1b41baf9acd1ff94e01161138d8aa17f4e97aa32f2dc4effafcd1/data' :
9+
'community.wave.seqera.io/library/pybedtools_bedtools_htslib_pip_pypints:39699b96998ec5f6' }"
10+
11+
input:
12+
tuple val(meta), path(bam)
13+
val(assay_type)
14+
// val(norm_factor)
15+
// val(rpm_normalize)
16+
// val(reverse_complement)
17+
18+
output:
19+
tuple val(meta), path("*_pl.bw"), emit: plus_bw
20+
tuple val(meta), path("*_mn.bw"), emit: minus_bw
21+
path "versions.yml", emit: versions
22+
23+
when:
24+
task.ext.when == null || task.ext.when
25+
26+
script:
27+
def args = task.ext.args ?: ''
28+
def prefix = task.ext.prefix ?: "${meta.id}"
29+
// def chr_arg = chr_name ? "--chrom ${chr_name}" : ''
30+
// def norm_arg = norm_factor != null ? "--norm-fact ${norm_factor}" : ''
31+
// def rpm_arg = rpm_normalize ? "--rpm" : ''
32+
// def rc_arg = reverse_complement ? "--reverse-complement" : ''
33+
34+
"""
35+
pints_visualizer \\
36+
--bam ${bam} \\
37+
--exp-type ${assay_type} \\
38+
--output-prefix ${prefix} \\
39+
${args}
40+
41+
cat <<-END_VERSIONS > versions.yml
42+
"${task.process}":
43+
python: \$(python --version | sed 's/Python //g')
44+
pints: \$(pints_visualizer --version)
45+
END_VERSIONS
46+
"""
47+
48+
stub:
49+
def prefix = task.ext.prefix ?: "${meta.id}"
50+
"""
51+
touch ${prefix}_${chr_name}_plus.bigwig
52+
touch ${prefix}_${chr_name}_minus.bigwig
53+
54+
cat <<-END_VERSIONS > versions.yml
55+
"${task.process}":
56+
python: \$(python --version | sed 's/Python //g')
57+
pints: \$(pints_visualizer --version)
58+
END_VERSIONS
59+
"""
60+
}
61+
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
name: "pints_visualizer"
2+
description: Visualization script for creating strand-specific bigWig files from nascent RNA-seq data
3+
keywords:
4+
- bigWig
5+
- visualization
6+
- CoPRO
7+
- GRO-cap
8+
- PRO-cap
9+
- CAGE
10+
- NETCAGE
11+
- RAMPAGE
12+
- csRNA-seq
13+
- STRIPE-seq
14+
- PRO-seq
15+
- GRO-seq
16+
tools:
17+
- "pints":
18+
description: "Peak Identifier for Nascent Transcripts Starts (PINTS)"
19+
homepage: "https://pints.yulab.org/"
20+
documentation: "https://github.com/hyulab/PINTS/blob/main/README.md"
21+
tool_dev_url: "https://github.com/hyulab/PINTS"
22+
doi: "10.1038/s41587-022-01211-7"
23+
licence: ["GPL v3"]
24+
identifier: biotools:pyPINTS
25+
input:
26+
- - meta:
27+
type: map
28+
description: |
29+
Groovy Map containing sample information
30+
e.g. [ id:'test', single_end:false ]
31+
- bam:
32+
type: file
33+
description: BAM file to generate bigWig files from
34+
pattern: "*.{bam}"
35+
- chr_name:
36+
type: string
37+
description: Optional chromosome name prefix to filter
38+
- assay_type:
39+
type: string
40+
description: Type of experiment (CoPRO/GROcap/GROseq/PROcap/PROseq)
41+
- norm_factor:
42+
type: float
43+
description: Normalization factor for signal
44+
- rpm_normalize:
45+
type: boolean
46+
description: Whether to apply RPM normalization
47+
- reverse_complement:
48+
type: boolean
49+
description: Whether the reads represent the reverse complement of nascent RNAs
50+
output:
51+
- meta:
52+
type: map
53+
description: |
54+
Groovy Map containing sample information
55+
e.g. [ id:'test', single_end:false ]
56+
- bigwigs:
57+
type: file
58+
description: Two strand-specific bigWig files (forward and reverse)
59+
pattern: "*_{pl,mn}.bw"
60+
- versions:
61+
type: file
62+
description: File containing software versions
63+
pattern: "versions.yml"
64+
authors:
65+
- "@hyulab"
66+
- "@edmiller01"
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
nextflow_process {
2+
3+
name "Test Process PINTS_VISUALIZER"
4+
script "../main.nf"
5+
process "PINTS_VISUALIZER"
6+
tag "modules"
7+
tag "modules_local"
8+
tag "pints"
9+
tag "pints/visualizer"
10+
11+
test("Should run PINTS_VISUALIZER with PROseq data and produce strand-specific bigwigs") {
12+
when {
13+
process {
14+
"""
15+
input[0] = Channel.of([
16+
[ id:'test_sample', single_end:false ],
17+
file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/bam/test.paired_end.sorted.bam', checkIfExists: true),
18+
'chr1'
19+
])
20+
input[1] = 'PROseq'
21+
"""
22+
}
23+
}
24+
25+
then {
26+
assertAll(
27+
{ assert process.success },
28+
{ assert process.out.plus_bw.size() == 1 },
29+
{ assert process.out.minus_bw.size() == 1 },
30+
{ assert snapshot(
31+
process.out.plus_bw.get(0)[1],
32+
process.out.minus_bw.get(0)[1]
33+
).match()
34+
},
35+
{ assert snapshot(path(process.out.versions[0]).yaml).match("flipped_versions") }
36+
)
37+
}
38+
}
39+
40+
test("Should run PINTS_VISUALIZER with GROseq data without reverse complement") {
41+
when {
42+
process {
43+
"""
44+
input[0] = Channel.of([
45+
[ id:'test_gro', single_end:false ],
46+
file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/bam/test.paired_end.sorted.bam', checkIfExists: true),
47+
'chr1'
48+
])
49+
input[1] = 'GROseq'
50+
"""
51+
}
52+
}
53+
54+
then {
55+
assertAll(
56+
{ assert process.success },
57+
{ assert process.out.plus_bw.size() == 1 },
58+
{ assert process.out.minus_bw.size() == 1 },
59+
{ assert snapshot(
60+
process.out.plus_bw.get(0)[1],
61+
process.out.minus_bw.get(0)[1]
62+
).match()
63+
},
64+
{ assert snapshot(path(process.out.versions[0]).yaml).match("versions") }
65+
)
66+
}
67+
}
68+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
{
2+
"versions": {
3+
"content": [
4+
{
5+
"PINTS_VISUALIZER": {
6+
"python": "3.12.6",
7+
"pints": "1.1.13"
8+
}
9+
}
10+
],
11+
"meta": {
12+
"nf-test": "0.9.2",
13+
"nextflow": "24.10.3"
14+
},
15+
"timestamp": "2025-05-08T18:07:16.978238"
16+
},
17+
"flipped_versions": {
18+
"content": [
19+
{
20+
"PINTS_VISUALIZER": {
21+
"python": "3.12.6",
22+
"pints": "1.1.13"
23+
}
24+
}
25+
],
26+
"meta": {
27+
"nf-test": "0.9.2",
28+
"nextflow": "24.10.3"
29+
},
30+
"timestamp": "2025-05-08T18:07:07.331434"
31+
},
32+
"Should run PINTS_VISUALIZER with PROseq data and produce strand-specific bigwigs": {
33+
"content": [
34+
"test_sample_pl.bw:md5,6fd3346be91cc84750f839b050c6bc5b",
35+
"test_sample_mn.bw:md5,9eecf5936bdf1c0c44ec123636a305f5"
36+
],
37+
"meta": {
38+
"nf-test": "0.9.2",
39+
"nextflow": "24.10.3"
40+
},
41+
"timestamp": "2025-05-04T18:24:13.206646"
42+
},
43+
"Should run PINTS_VISUALIZER with GROseq data without reverse complement": {
44+
"content": [
45+
"test_gro_pl.bw:md5,e399e77f224d993e789bf8f7c4b826e1",
46+
"test_gro_mn.bw:md5,21c7ef549d8cb39788e13080dc573848"
47+
],
48+
"meta": {
49+
"nf-test": "0.9.2",
50+
"nextflow": "24.10.3"
51+
},
52+
"timestamp": "2025-05-04T18:24:22.747334"
53+
}
54+
}

subworkflows/local/coverage_graphs/main.nf

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
include { DEEPTOOLS_BAMCOVERAGE as DEEPTOOLS_BAMCOVERAGE_PLUS } from '../../../modules/nf-core/deeptools/bamcoverage/main'
66
include { DEEPTOOLS_BAMCOVERAGE as DEEPTOOLS_BAMCOVERAGE_MINUS } from '../../../modules/nf-core/deeptools/bamcoverage/main'
77
include { FLIP_STRAND } from '../../../modules/flip_strand'
8+
include { PINTS_VISUALIZER } from '../../../modules/local/pints/visualizer'
89

910
workflow COVERAGE_GRAPHS {
1011
take:
@@ -33,18 +34,25 @@ workflow COVERAGE_GRAPHS {
3334
)
3435
ch_versions = ch_versions.mix(DEEPTOOLS_BAMCOVERAGE_MINUS.out.versions.first())
3536

36-
37-
ch_plus_minus = DEEPTOOLS_BAMCOVERAGE_PLUS.out.bigwig.join(DEEPTOOLS_BAMCOVERAGE_MINUS.out.bigwig)
37+
ch_deeptools_plus_minus = DEEPTOOLS_BAMCOVERAGE_PLUS.out.bigwig.join(DEEPTOOLS_BAMCOVERAGE_MINUS.out.bigwig)
3838

3939
if (params.assay_type in ["PROseq", "PROcap", "CoPRO"]) {
4040
FLIP_STRAND(
41-
ch_plus_minus,
41+
ch_deeptools_plus_minus
4242
)
4343
ch_versions = ch_versions.mix(FLIP_STRAND.out.versions.first())
44-
ch_plus_minus = FLIP_STRAND.out.flipped_bigwig
44+
ch_deeptools_plus_minus = FLIP_STRAND.out.flipped_bigwig
4545
}
4646

47+
PINTS_VISUALIZER(
48+
bam_bai,
49+
params.assay_type,
50+
)
51+
ch_versions = ch_versions.mix(PINTS_VISUALIZER.out.versions.first())
52+
ch_pints_plus_minus = PINTS_VISUALIZER.out.plus_bw.join(PINTS_VISUALIZER.out.minus_bw)
53+
4754
emit:
48-
plus_minus = ch_plus_minus
49-
versions = ch_versions
55+
deeptools_plus_minus = ch_deeptools_plus_minus
56+
pints_plus_minus = ch_pints_plus_minus
57+
versions = ch_versions
5058
}

workflows/tests/aligner/bowtie2.nf.test.snap

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"Should run with defaults": {
33
"content": [
4-
68,
4+
71,
55
{
66
"BBMAP_PILEUP": {
77
"bbmap": 39.01,
@@ -44,6 +44,10 @@
4444
"homer": 4.11,
4545
"samtools": 1.21
4646
},
47+
"PINTS_VISUALIZER": {
48+
"python": "3.12.6",
49+
"pints": "1.1.13"
50+
},
4751
"PRESEQ_CCURVE": {
4852
"preseq": "3.1.1"
4953
},
@@ -296,8 +300,8 @@
296300
],
297301
"meta": {
298302
"nf-test": "0.9.2",
299-
"nextflow": "24.10.3"
303+
"nextflow": "25.03.1"
300304
},
301-
"timestamp": "2025-05-11T12:24:05.753243"
305+
"timestamp": "2025-05-20T21:52:41.120419"
302306
}
303307
}

0 commit comments

Comments
 (0)