rolypoly-tk 0.7.2__tar.gz → 0.7.4__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. {rolypoly_tk-0.7.2 → rolypoly_tk-0.7.4}/PKG-INFO +32 -26
  2. {rolypoly_tk-0.7.2 → rolypoly_tk-0.7.4}/README.md +29 -23
  3. {rolypoly_tk-0.7.2 → rolypoly_tk-0.7.4}/pyproject.toml +14 -2
  4. {rolypoly_tk-0.7.2 → rolypoly_tk-0.7.4}/rolypoly/__init__.py +1 -1
  5. {rolypoly_tk-0.7.2 → rolypoly_tk-0.7.4}/rolypoly/commands/annotation/annotate.py +9 -1
  6. {rolypoly_tk-0.7.2 → rolypoly_tk-0.7.4}/rolypoly/commands/annotation/annotate_RNA.py +9 -4
  7. {rolypoly_tk-0.7.2 → rolypoly_tk-0.7.4}/rolypoly/commands/assembly/assemble.py +10 -1
  8. {rolypoly_tk-0.7.2 → rolypoly_tk-0.7.4}/rolypoly/commands/assembly/filter_contigs.py +7 -1
  9. {rolypoly_tk-0.7.2 → rolypoly_tk-0.7.4}/rolypoly/commands/bining/binit.py +6 -1
  10. {rolypoly_tk-0.7.2 → rolypoly_tk-0.7.4}/rolypoly/commands/bining/correlate.py +8 -1
  11. {rolypoly_tk-0.7.2 → rolypoly_tk-0.7.4}/rolypoly/commands/identify_virus/search_viruses.py +7 -1
  12. {rolypoly_tk-0.7.2 → rolypoly_tk-0.7.4}/rolypoly/commands/misc/fastx_stats.py +4 -2
  13. {rolypoly_tk-0.7.2 → rolypoly_tk-0.7.4}/rolypoly/commands/reads/filter_reads.py +8 -2
  14. {rolypoly_tk-0.7.2 → rolypoly_tk-0.7.4}/rolypoly/commands/reads/shrink_reads.py +7 -5
  15. {rolypoly_tk-0.7.2 → rolypoly_tk-0.7.4}/rolypoly/rolypoly.py +4 -3
  16. rolypoly_tk-0.7.2/rolypoly/commands/host/classify.py +0 -47
  17. rolypoly_tk-0.7.2/rolypoly/commands/misc/quick_taxonomy.py +0 -372
  18. rolypoly_tk-0.7.2/rolypoly/utils/logging/__init__.py +0 -0
  19. {rolypoly_tk-0.7.2 → rolypoly_tk-0.7.4}/.gitignore +0 -0
  20. {rolypoly_tk-0.7.2 → rolypoly_tk-0.7.4}/LICENSE +0 -0
  21. {rolypoly_tk-0.7.2 → rolypoly_tk-0.7.4}/rolypoly/commands/__init__.py +0 -0
  22. {rolypoly_tk-0.7.2 → rolypoly_tk-0.7.4}/rolypoly/commands/annotation/__init__.py +0 -0
  23. {rolypoly_tk-0.7.2 → rolypoly_tk-0.7.4}/rolypoly/commands/annotation/annotate_prot.py +0 -0
  24. {rolypoly_tk-0.7.2 → rolypoly_tk-0.7.4}/rolypoly/commands/annotation/resolve_hits.py +0 -0
  25. {rolypoly_tk-0.7.2 → rolypoly_tk-0.7.4}/rolypoly/commands/assembly/__init__.py +0 -0
  26. {rolypoly_tk-0.7.2 → rolypoly_tk-0.7.4}/rolypoly/commands/assembly/co_assembly.py +0 -0
  27. {rolypoly_tk-0.7.2 → rolypoly_tk-0.7.4}/rolypoly/commands/assembly/extend.py +0 -0
  28. {rolypoly_tk-0.7.2 → rolypoly_tk-0.7.4}/rolypoly/commands/assembly/refinement.py +0 -0
  29. {rolypoly_tk-0.7.2 → rolypoly_tk-0.7.4}/rolypoly/commands/bining/__init__.py +0 -0
  30. {rolypoly_tk-0.7.2 → rolypoly_tk-0.7.4}/rolypoly/commands/bining/cluster.py +0 -0
  31. {rolypoly_tk-0.7.2 → rolypoly_tk-0.7.4}/rolypoly/commands/bining/termini.py +0 -0
  32. {rolypoly_tk-0.7.2/rolypoly/commands/host → rolypoly_tk-0.7.4/rolypoly/commands/identify_virus}/__init__.py +0 -0
  33. {rolypoly_tk-0.7.2 → rolypoly_tk-0.7.4}/rolypoly/commands/identify_virus/marker_search.py +0 -0
  34. {rolypoly_tk-0.7.2 → rolypoly_tk-0.7.4}/rolypoly/commands/identify_virus/rdrp_motif_search.py +0 -0
  35. {rolypoly_tk-0.7.2/rolypoly/commands/identify_virus → rolypoly_tk-0.7.4/rolypoly/commands/misc}/__init__.py +0 -0
  36. {rolypoly_tk-0.7.2 → rolypoly_tk-0.7.4}/rolypoly/commands/misc/add_command.py +0 -0
  37. {rolypoly_tk-0.7.2 → rolypoly_tk-0.7.4}/rolypoly/commands/misc/build_data.py +0 -0
  38. {rolypoly_tk-0.7.2 → rolypoly_tk-0.7.4}/rolypoly/commands/misc/end_2_end.py +0 -0
  39. {rolypoly_tk-0.7.2 → rolypoly_tk-0.7.4}/rolypoly/commands/misc/fastx_calc.py +0 -0
  40. {rolypoly_tk-0.7.2 → rolypoly_tk-0.7.4}/rolypoly/commands/misc/fetch_sra_fastq.py +0 -0
  41. {rolypoly_tk-0.7.2 → rolypoly_tk-0.7.4}/rolypoly/commands/misc/get_external_data.py +0 -0
  42. {rolypoly_tk-0.7.2 → rolypoly_tk-0.7.4}/rolypoly/commands/misc/rename_seqs.py +0 -0
  43. {rolypoly_tk-0.7.2 → rolypoly_tk-0.7.4}/rolypoly/commands/reads/__init__.py +0 -0
  44. {rolypoly_tk-0.7.2 → rolypoly_tk-0.7.4}/rolypoly/commands/reads/mask_dna.py +0 -0
  45. {rolypoly_tk-0.7.2/rolypoly/commands/misc → rolypoly_tk-0.7.4/rolypoly/commands/virotype}/__init__.py +0 -0
  46. {rolypoly_tk-0.7.2 → rolypoly_tk-0.7.4}/rolypoly/commands/virotype/draw_rdrp_msa.py +0 -0
  47. {rolypoly_tk-0.7.2 → rolypoly_tk-0.7.4}/rolypoly/commands/virotype/predict_characteristics.py +0 -0
  48. {rolypoly_tk-0.7.2 → rolypoly_tk-0.7.4}/rolypoly/commands/virotype/summarize.py +0 -0
  49. {rolypoly_tk-0.7.2 → rolypoly_tk-0.7.4}/rolypoly/commands/virotype/visualize.py +0 -0
  50. {rolypoly_tk-0.7.2 → rolypoly_tk-0.7.4}/rolypoly/rpconfig.json +0 -0
  51. {rolypoly_tk-0.7.2 → rolypoly_tk-0.7.4}/rolypoly/utils/__init__.py +0 -0
  52. {rolypoly_tk-0.7.2/rolypoly/commands/virotype → rolypoly_tk-0.7.4/rolypoly/utils/benchmarking}/__init__.py +0 -0
  53. {rolypoly_tk-0.7.2 → rolypoly_tk-0.7.4}/rolypoly/utils/benchmarking/get_data.py +0 -0
  54. {rolypoly_tk-0.7.2 → rolypoly_tk-0.7.4}/rolypoly/utils/bio/__init__.py +0 -0
  55. {rolypoly_tk-0.7.2 → rolypoly_tk-0.7.4}/rolypoly/utils/bio/alignments.py +0 -0
  56. {rolypoly_tk-0.7.2 → rolypoly_tk-0.7.4}/rolypoly/utils/bio/clustering.py +0 -0
  57. {rolypoly_tk-0.7.2 → rolypoly_tk-0.7.4}/rolypoly/utils/bio/dotplot.py +0 -0
  58. {rolypoly_tk-0.7.2 → rolypoly_tk-0.7.4}/rolypoly/utils/bio/genome_fetch.py +0 -0
  59. {rolypoly_tk-0.7.2 → rolypoly_tk-0.7.4}/rolypoly/utils/bio/interval_ops.py +0 -0
  60. {rolypoly_tk-0.7.2 → rolypoly_tk-0.7.4}/rolypoly/utils/bio/library_detection.py +0 -0
  61. {rolypoly_tk-0.7.2 → rolypoly_tk-0.7.4}/rolypoly/utils/bio/polars_fastx.py +0 -0
  62. {rolypoly_tk-0.7.2 → rolypoly_tk-0.7.4}/rolypoly/utils/bio/sequences.py +0 -0
  63. {rolypoly_tk-0.7.2 → rolypoly_tk-0.7.4}/rolypoly/utils/bio/translation.py +0 -0
  64. {rolypoly_tk-0.7.2 → rolypoly_tk-0.7.4}/rolypoly/utils/bio/trees.py +0 -0
  65. {rolypoly_tk-0.7.2 → rolypoly_tk-0.7.4}/rolypoly/utils/lazy_group.py +0 -0
  66. {rolypoly_tk-0.7.2/rolypoly/utils/benchmarking → rolypoly_tk-0.7.4/rolypoly/utils/logging}/__init__.py +0 -0
  67. {rolypoly_tk-0.7.2 → rolypoly_tk-0.7.4}/rolypoly/utils/logging/all_used_tools_dbs_citations.json +0 -0
  68. {rolypoly_tk-0.7.2 → rolypoly_tk-0.7.4}/rolypoly/utils/logging/citation_reminder.py +0 -0
  69. {rolypoly_tk-0.7.2 → rolypoly_tk-0.7.4}/rolypoly/utils/logging/config.py +0 -0
  70. {rolypoly_tk-0.7.2 → rolypoly_tk-0.7.4}/rolypoly/utils/logging/loggit.py +0 -0
  71. {rolypoly_tk-0.7.2 → rolypoly_tk-0.7.4}/rolypoly/utils/logging/output_tracker.py +0 -0
  72. {rolypoly_tk-0.7.2 → rolypoly_tk-0.7.4}/rolypoly/utils/various.py +0 -0
@@ -1,9 +1,9 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: rolypoly_tk
3
- Version: 0.7.2
3
+ Version: 0.7.4
4
4
  Summary: RNA virus analysis toolkit
5
5
  Project-URL: Source, https://github.com/UriNeri/rolypoly
6
- Project-URL: Documentation, https://pages.jgi.doe.gov/rolypoly/docs/
6
+ Project-URL: Documentation, https://urineri.github.io/rolypoly/
7
7
  Project-URL: pypi, https://pypi.org/project/rolypoly-tk/
8
8
  Author: Lander De Coninck
9
9
  Author-email: Uri Neri <uneri@lbl.gov>, Dimitris Karapliafis <dimitris.karapliafis@atwur.nl>, Brian Bushnell <bbushnell@lbl.gov>, Frederik Schulz <fschulz@lbl.gov>, Antonio Camargo <antoniop.camargo@lbl.gov>, Andrei Stecca Steindorff <andreiss@jgi.doe.gov>, Clement Coclet <cclement@jgi.doe.gov>, David Parker <dparker@carnegiescience.edu>, Simon Roux <sroux@lbl.gov>
@@ -682,7 +682,7 @@ License: GNU GENERAL PUBLIC LICENSE
682
682
  Public License instead of this License. But first, please read
683
683
  <https://www.gnu.org/licenses/why-not-lgpl.html>.
684
684
  License-File: LICENSE
685
- Requires-Python: >=3.10
685
+ Requires-Python: <3.14,>=3.10
686
686
  Requires-Dist: bbmapy<0.0.58,>=0.0.56
687
687
  Requires-Dist: genomicranges<0.8,>=0.7.3
688
688
  Requires-Dist: intervaltree<4,>=3.1.0
@@ -708,16 +708,18 @@ Requires-Dist: viennarna<3,>=2.7.0
708
708
  Requires-Dist: xxhash<4,>=3.6.0
709
709
  Description-Content-Type: text/markdown
710
710
 
711
- ![RolyPoly Logo](https://code.jgi.doe.gov/rolypoly/docs/-/raw/main/docs/rolypoly_logo.png?ref_type=heads)
711
+ ![RolyPoly Logo](https://raw.githubusercontent.com/UriNeri/rolypoly/main/docs/rolypoly_logo.png)
712
712
 
713
713
  # RolyPoly
714
714
 
715
+ [![PyPI version](https://img.shields.io/pypi/v/rolypoly-tk.svg?cacheSeconds=300)](https://pypi.org/project/rolypoly-tk/) [![Python versions](https://img.shields.io/pypi/pyversions/rolypoly-tk.svg?cacheSeconds=300)](https://pypi.org/project/rolypoly-tk/) [![PyPI Downloads](https://static.pepy.tech/personalized-badge/rolypoly-tk?period=monthly&units=INTERNATIONAL_SYSTEM&left_color=BLACK&right_color=GREEN&left_text=Downloads+%28month%29)](https://pepy.tech/projects/rolypoly-tk) [![License](https://img.shields.io/github/license/UriNeri/rolypoly.svg)](LICENSE) [![Docs](https://img.shields.io/badge/docs-urineri.github.io%2Frolypoly-blue)](https://urineri.github.io/rolypoly/)
716
+
715
717
  RolyPoly is an RNA virus analysis toolkit, meant to be a "swiss-army knife" for RNA virus discovery and characterization by including a variety of commands, wrappers, parsers, automations, and some "quality of life" features for any many of a virus investigation process (from raw read processing to genome annotation). While it includes an "end-2-end" command that employs an entire pipeline, the main goals of rolypoly are:
716
718
  - Help non-computational researchers take a deep dive into their data without compromising on using tools that are non-techie friendly.
717
719
  - Help (software) developers of virus analysis pipeline "plug" holes missing from their framework, by using specific RolyPoly commands to add features to their existing code base.
718
720
 
719
721
  ## Note - Rolypoly is still under development (contributions welcome!)
720
- RolyPoly is an open, still in progress project - I aim to summarise the main functionality into a manuscript ~early 2026. Pull requests and contributions are welcome and will be considered (see [CONTRIBUTING.md](CONTRIBUTING.md)).
722
+ RolyPoly is an open, still in progress project - I aim to summarise the main functionality into a manuscript ~mid 2026. Pull requests and contributions are welcome and will be considered (see [CONTRIBUTING.md](CONTRIBUTING.md)).
721
723
  This also means that there are bugs, verbose logging even for non debug mode, and some place holders and TODOs here and there.
722
724
 
723
725
  ## Installation
@@ -726,23 +728,27 @@ This also means that there are bugs, verbose logging even for non debug mode, an
726
728
  **Recommended for most users** who want a "just works" solution and primarily intend to use rolypoly as a CLI tool in an independent environment.
727
729
 
728
730
  We hope to have rolypoly available from bioconda in the near future.
729
- In the meantime, it can be installed with the [`quick_setup.sh`](https://code.jgi.doe.gov/rolypoly/rolypoly/-/raw/main/src/setup/quick_setup.sh) script, which will also fetch the pre-generated data rolypoly requires.
731
+ In the meantime, it can be installed with the [`quick_setup.sh`](https://raw.githubusercontent.com/UriNeri/rolypoly/main/src/setup/quick_setup.sh) script, which is Conda/Mamba-based (uses `mamba` or `micromamba`) and also fetches the pre-generated data rolypoly requires.
730
732
 
731
733
  ```bash
732
- curl -O https://code.jgi.doe.gov/rolypoly/rolypoly/-/raw/main/src/setup/quick_setup.sh && \
734
+ curl -O https://raw.githubusercontent.com/UriNeri/rolypoly/main/src/setup/quick_setup.sh && \
733
735
  bash quick_setup.sh
734
736
  ```
735
737
 
736
738
  #### Quick Setup - Additional Options
737
- You can specify custom paths for the code, databases, and conda environment location:
739
+ You can specify custom paths for the code, databases, and Conda/Mamba environment location (this is also how you "name" the environment by choosing its path):
738
740
  ```bash
739
741
  bash quick_setup.sh /path/to/conda/env /path/to/install/rolypoly_code /path/to/store/databases /path/to/logfile
740
742
  ```
743
+ Example with an explicit environment path:
744
+ ```bash
745
+ bash quick_setup.sh "$HOME/mamba_envs/rolypoly"
746
+ ```
741
747
  By default if no positional arguments are supplied, rolypoly is installed into the session current folder (path the quick_setup.sh is called from):
742
748
  - database in `./rolypoly/data/`
743
749
  - code in `./rolypoly/code/ `
744
750
  - conda environment in `./rolypoly/env/`
745
- - log file in `./RolyPoly_quick_setup.log`
751
+ - log file in `./rolypoly/RolyPoly_quick_setup.log`
746
752
 
747
753
 
748
754
 
@@ -754,7 +760,7 @@ By default if no positional arguments are supplied, rolypoly is installed into t
754
760
  curl -fsSL https://pixi.sh/install.sh | bash
755
761
 
756
762
  # Clone the repository
757
- git clone https://code.jgi.doe.gov/rolypoly/rolypoly.git
763
+ git clone https://github.com/UriNeri/rolypoly.git
758
764
  cd rolypoly
759
765
 
760
766
  # Install for specific functionality (examples):
@@ -794,11 +800,11 @@ Legend:
794
800
 
795
801
  #### Raw-Reads
796
802
  - ✅ [`filter-reads`](https://urineri.github.io/rolypoly/commands/read_processing) — Host/rRNA/adapters/artifact filtering and QC (bbmap, falco, etc.)
797
- - ✅ [`shrink-reads`](https://urineri.github.io/rolypoly/commands/shrink_reads) — Downsample or subsample reads. Useful for testing or normalizing coverage across samples.
798
- - ✅ [`mask-dna`](https://urineri.github.io/rolypoly/commands/mask_dna) — Mask DNA regions in RNA-seq reads (bbmap, seqkit). Useful for avoiding mis-filtering of RNA virus reads in because of potential matches to EVEs.
803
+ - ✅ [`shrink-reads`](https://urineri.github.io/rolypoly/commands/read_processing) — Downsample or subsample reads. Useful for testing or normalizing coverage across samples.
804
+ - ✅ [`mask-dna`](https://urineri.github.io/rolypoly/commands/read_processing) — Mask DNA regions in RNA-seq reads (bbmap, seqkit). Useful for avoiding mis-filtering of RNA virus reads in because of potential matches to EVEs.
799
805
 
800
806
  #### Annotation
801
- - ✅ [`annotate`](https://urineri.github.io/rolypoly/commands/annotate) — Genome feature annotation (wraps the rna and prot commands)
807
+ - ✅ [`annotate`](https://urineri.github.io/rolypoly/commands/annotate_rna/#annotate-rna) — Genome feature annotation (wraps the rna and prot commands)
802
808
  - ✅ [`annotate-rna`](https://urineri.github.io/rolypoly/commands/annotate_rna) — RNA secondary structure labelling and ribozyme detection (Infernal, ViennaRNA/linearfold, cmsearch on Rfam...)
803
809
  - 🧪 [`annotate-prot`](https://urineri.github.io/rolypoly/commands/annotate_prot) — Gene calling and Protein domain annotation and functional prediction (HMMER, Pfam, custom).
804
810
 
@@ -809,22 +815,22 @@ Legend:
809
815
  #### RNA Virus Identification
810
816
  - ✅ [`marker-search`](https://urineri.github.io/rolypoly/commands/marker_search) — Search for viral markers (mainly RdRps, genomad VVs, or user-provided), using profile-based methods (HMMER / MMseqs2).
811
817
  - ✅ [`virus-mapping`](https://urineri.github.io/rolypoly/commands/search_viruses) — Map and identify viruses using nucleic acid search (MMseqs2).
812
- - ✅ `rdrp-motif-search` — Search RdRp motifs (A/B/C/D) in nucleotide or amino acid sequences.
818
+ - ✅ [`rdrp-motif-search`](https://urineri.github.io/rolypoly/commands/rdrp_motif_search) — Search RdRp motifs (A/B/C/D) in nucleotide or amino acid sequences.
813
819
 
814
820
  #### Bining / Clustering
815
- - 🧪 `cluster` — Average Nucleic identity (ANI) based contig gropuing. Supports several common backends and methods.
816
- - 🧪 `extend` — Extend sequences by pile-up/assembly. Useful for combining assemblies of with low abundance viruses, or those with high microdiversity, at the cost of worse strain/sub-species resolution (i.e. can condense to a consenus).
817
- - 🧪 `termini` — Shared termini grouping and motif reporting. Writes assignments + groups tables (TSV/CSV/Parquet/JSONL) and motif FASTA by default.
818
- - 🧪 `correlate` — group contigs based on co-occurence, co-abundance, minimal correlation (Spearman's) of these, or both.
819
- - 🤔 `binit` — Combines the above commands with sample information and genome attributes (e.g. require a shared termini AND protein complementarity, like CP + RdRp). See [notebooks/Exprimental/partiti_usecase/partiti_segment_workflow_experimental.ipynb](notebooks/Exprimental/partiti_usecase/partiti_segment_workflow_experimental.ipynb) for candidate workflow.
821
+ - 🧪 [`cluster`](https://urineri.github.io/rolypoly/commands/cluster) — Average Nucleic identity (ANI) based contig grouping. Supports several common backends and methods.
822
+ - 🧪 [`extend`](https://urineri.github.io/rolypoly/commands/extend) — Extend sequences by pile-up/assembly. Useful for combining assemblies of with low abundance viruses, or those with high microdiversity, at the cost of worse strain/sub-species resolution (i.e. can condense to a consensus).
823
+ - 🧪 [`termini`](https://urineri.github.io/rolypoly/commands/binning_termini) — Shared termini grouping and motif reporting. Writes assignments + groups tables (TSV/CSV/Parquet/JSONL) and motif FASTA by default.
824
+ - 🧪 [`correlate`](https://urineri.github.io/rolypoly/commands/binning_correlate) — Group contigs based on co-occurrence, co-abundance, minimal correlation (Spearman's) of these, or both.
825
+ - 🤔 [`binit`](https://urineri.github.io/rolypoly/commands/binit) — Combines the above commands with sample information and genome attributes (e.g. require a shared termini AND protein complementarity, like CP + RdRp). See [notebooks/Exprimental/partiti_usecase/partiti_segment_workflow_experimental.ipynb](notebooks/Exprimental/partiti_usecase/partiti_segment_workflow_experimental.ipynb) for candidate workflow.
820
826
 
821
827
  #### Miscellaneous
822
- - ✅ `roll` — Run an end-to-end pipeline (before v0.7.1, named `end2end`).
823
- - ✅ `fetch-sra` — Download SRA fastq files (from ENA)
824
- - ✅ `fastx-calc` — Calculate per-sequence metrics (length, GC content, hash, ...)
825
- - ✅ `fastx-stats` — Calculate (-->aggregate) statistics for sequences (min, max, mean, median, ...) (input is file/s)
826
- - ✅ `rename-seqs` — Rename sequences (add a prefix, suffix, hash, running number, etc.)
827
- - 🚧 `quick-taxonomy` — Quick taxonomy assignment. Candidate workflows are [github.com/UriNeri/ictv-mmseqs2-protein-database](https://github.com/UriNeri/ictv-mmseqs2-protein-database) and [github.com/apcamargo/ictv-mmseqs2-protein-database](https://github.com/apcamargo/ictv-mmseqs2-protein-database)
828
+ - ✅ [`roll`](https://urineri.github.io/rolypoly/commands/end_to_end) — Run an end-to-end pipeline (before v0.7.1, named `end2end`).
829
+ - ✅ [`fetch-sra`](https://urineri.github.io/rolypoly/commands/misc) — Download SRA fastq files (from ENA)
830
+ - ✅ [`fastx-calc`](https://urineri.github.io/rolypoly/commands/misc) — Calculate per-sequence metrics (length, GC content, hash, ...)
831
+ - ✅ [`fastx-stats`](https://urineri.github.io/rolypoly/commands/misc) — Calculate (-->aggregate) statistics for sequences (min, max, mean, median, ...) (input is file/s)
832
+ - ✅ [`rename-seqs`](https://urineri.github.io/rolypoly/commands/misc) — Rename sequences (add a prefix, suffix, hash, running number, etc.)
833
+ - 🚧 [`quick-taxonomy`](https://urineri.github.io/rolypoly/commands/misc) — Quick taxonomy assignment. Candidate workflows are [github.com/UriNeri/ictv-mmseqs2-protein-database](https://github.com/UriNeri/ictv-mmseqs2-protein-database) and [github.com/apcamargo/ictv-mmseqs2-protein-database](https://github.com/apcamargo/ictv-mmseqs2-protein-database)
828
834
  - 🤔 support for [genotate](https://github.com/deprekate/genotate) for gene prediction.
829
835
  - 🤔 Genome refinement / strain de-entalgement / variant calling?
830
836
  - 🤔 Virus feature prediction (+/-ssRNA/dsRNA, circular/linear, mono/poly-segmented, capsid type, etc.)
@@ -835,7 +841,7 @@ If you have suggestions for additional commands or features, or want to implemen
835
841
 
836
842
  ## Dependencies
837
843
 
838
- **📦 Modular Installation Available**: RolyPoly supports both quick setup (one environment with all dependecies for all commands) and modular installation (command-specific environments). The modular approach is particularly useful for software developers who want to integrate specific rolypoly features with minimal dependency conflicts. See the [installation documentation](./docs/docs/mkdocs_docs/installation.md) for details.
844
+ **📦 Modular Installation Available**: RolyPoly supports both quick setup (one environment with all dependecies for all commands) and modular installation (command-specific environments). The modular approach is particularly useful for software developers who want to integrate specific rolypoly features with minimal dependency conflicts. See the [installation documentation](https://urineri.github.io/rolypoly/installation/) for details.
839
845
 
840
846
  Not all 3rd party software is used by all the different commands. RolyPoly includes a "citation reminder" that will try to list all the external software used by a command. The "reminded citations" are pretty printed to console (stdout) and to a logfile. To shut off the terminal citation reminder printing, set `ROLYPOLY_REMIND_CITATIONS` to false in your `rpconfig.json` file.
841
847
 
@@ -1,13 +1,15 @@
1
- ![RolyPoly Logo](https://code.jgi.doe.gov/rolypoly/docs/-/raw/main/docs/rolypoly_logo.png?ref_type=heads)
1
+ ![RolyPoly Logo](https://raw.githubusercontent.com/UriNeri/rolypoly/main/docs/rolypoly_logo.png)
2
2
 
3
3
  # RolyPoly
4
4
 
5
+ [![PyPI version](https://img.shields.io/pypi/v/rolypoly-tk.svg?cacheSeconds=300)](https://pypi.org/project/rolypoly-tk/) [![Python versions](https://img.shields.io/pypi/pyversions/rolypoly-tk.svg?cacheSeconds=300)](https://pypi.org/project/rolypoly-tk/) [![PyPI Downloads](https://static.pepy.tech/personalized-badge/rolypoly-tk?period=monthly&units=INTERNATIONAL_SYSTEM&left_color=BLACK&right_color=GREEN&left_text=Downloads+%28month%29)](https://pepy.tech/projects/rolypoly-tk) [![License](https://img.shields.io/github/license/UriNeri/rolypoly.svg)](LICENSE) [![Docs](https://img.shields.io/badge/docs-urineri.github.io%2Frolypoly-blue)](https://urineri.github.io/rolypoly/)
6
+
5
7
  RolyPoly is an RNA virus analysis toolkit, meant to be a "swiss-army knife" for RNA virus discovery and characterization by including a variety of commands, wrappers, parsers, automations, and some "quality of life" features for any many of a virus investigation process (from raw read processing to genome annotation). While it includes an "end-2-end" command that employs an entire pipeline, the main goals of rolypoly are:
6
8
  - Help non-computational researchers take a deep dive into their data without compromising on using tools that are non-techie friendly.
7
9
  - Help (software) developers of virus analysis pipeline "plug" holes missing from their framework, by using specific RolyPoly commands to add features to their existing code base.
8
10
 
9
11
  ## Note - Rolypoly is still under development (contributions welcome!)
10
- RolyPoly is an open, still in progress project - I aim to summarise the main functionality into a manuscript ~early 2026. Pull requests and contributions are welcome and will be considered (see [CONTRIBUTING.md](CONTRIBUTING.md)).
12
+ RolyPoly is an open, still in progress project - I aim to summarise the main functionality into a manuscript ~mid 2026. Pull requests and contributions are welcome and will be considered (see [CONTRIBUTING.md](CONTRIBUTING.md)).
11
13
  This also means that there are bugs, verbose logging even for non debug mode, and some place holders and TODOs here and there.
12
14
 
13
15
  ## Installation
@@ -16,23 +18,27 @@ This also means that there are bugs, verbose logging even for non debug mode, an
16
18
  **Recommended for most users** who want a "just works" solution and primarily intend to use rolypoly as a CLI tool in an independent environment.
17
19
 
18
20
  We hope to have rolypoly available from bioconda in the near future.
19
- In the meantime, it can be installed with the [`quick_setup.sh`](https://code.jgi.doe.gov/rolypoly/rolypoly/-/raw/main/src/setup/quick_setup.sh) script, which will also fetch the pre-generated data rolypoly requires.
21
+ In the meantime, it can be installed with the [`quick_setup.sh`](https://raw.githubusercontent.com/UriNeri/rolypoly/main/src/setup/quick_setup.sh) script, which is Conda/Mamba-based (uses `mamba` or `micromamba`) and also fetches the pre-generated data rolypoly requires.
20
22
 
21
23
  ```bash
22
- curl -O https://code.jgi.doe.gov/rolypoly/rolypoly/-/raw/main/src/setup/quick_setup.sh && \
24
+ curl -O https://raw.githubusercontent.com/UriNeri/rolypoly/main/src/setup/quick_setup.sh && \
23
25
  bash quick_setup.sh
24
26
  ```
25
27
 
26
28
  #### Quick Setup - Additional Options
27
- You can specify custom paths for the code, databases, and conda environment location:
29
+ You can specify custom paths for the code, databases, and Conda/Mamba environment location (this is also how you "name" the environment by choosing its path):
28
30
  ```bash
29
31
  bash quick_setup.sh /path/to/conda/env /path/to/install/rolypoly_code /path/to/store/databases /path/to/logfile
30
32
  ```
33
+ Example with an explicit environment path:
34
+ ```bash
35
+ bash quick_setup.sh "$HOME/mamba_envs/rolypoly"
36
+ ```
31
37
  By default if no positional arguments are supplied, rolypoly is installed into the session current folder (path the quick_setup.sh is called from):
32
38
  - database in `./rolypoly/data/`
33
39
  - code in `./rolypoly/code/ `
34
40
  - conda environment in `./rolypoly/env/`
35
- - log file in `./RolyPoly_quick_setup.log`
41
+ - log file in `./rolypoly/RolyPoly_quick_setup.log`
36
42
 
37
43
 
38
44
 
@@ -44,7 +50,7 @@ By default if no positional arguments are supplied, rolypoly is installed into t
44
50
  curl -fsSL https://pixi.sh/install.sh | bash
45
51
 
46
52
  # Clone the repository
47
- git clone https://code.jgi.doe.gov/rolypoly/rolypoly.git
53
+ git clone https://github.com/UriNeri/rolypoly.git
48
54
  cd rolypoly
49
55
 
50
56
  # Install for specific functionality (examples):
@@ -84,11 +90,11 @@ Legend:
84
90
 
85
91
  #### Raw-Reads
86
92
  - ✅ [`filter-reads`](https://urineri.github.io/rolypoly/commands/read_processing) — Host/rRNA/adapters/artifact filtering and QC (bbmap, falco, etc.)
87
- - ✅ [`shrink-reads`](https://urineri.github.io/rolypoly/commands/shrink_reads) — Downsample or subsample reads. Useful for testing or normalizing coverage across samples.
88
- - ✅ [`mask-dna`](https://urineri.github.io/rolypoly/commands/mask_dna) — Mask DNA regions in RNA-seq reads (bbmap, seqkit). Useful for avoiding mis-filtering of RNA virus reads in because of potential matches to EVEs.
93
+ - ✅ [`shrink-reads`](https://urineri.github.io/rolypoly/commands/read_processing) — Downsample or subsample reads. Useful for testing or normalizing coverage across samples.
94
+ - ✅ [`mask-dna`](https://urineri.github.io/rolypoly/commands/read_processing) — Mask DNA regions in RNA-seq reads (bbmap, seqkit). Useful for avoiding mis-filtering of RNA virus reads in because of potential matches to EVEs.
89
95
 
90
96
  #### Annotation
91
- - ✅ [`annotate`](https://urineri.github.io/rolypoly/commands/annotate) — Genome feature annotation (wraps the rna and prot commands)
97
+ - ✅ [`annotate`](https://urineri.github.io/rolypoly/commands/annotate_rna/#annotate-rna) — Genome feature annotation (wraps the rna and prot commands)
92
98
  - ✅ [`annotate-rna`](https://urineri.github.io/rolypoly/commands/annotate_rna) — RNA secondary structure labelling and ribozyme detection (Infernal, ViennaRNA/linearfold, cmsearch on Rfam...)
93
99
  - 🧪 [`annotate-prot`](https://urineri.github.io/rolypoly/commands/annotate_prot) — Gene calling and Protein domain annotation and functional prediction (HMMER, Pfam, custom).
94
100
 
@@ -99,22 +105,22 @@ Legend:
99
105
  #### RNA Virus Identification
100
106
  - ✅ [`marker-search`](https://urineri.github.io/rolypoly/commands/marker_search) — Search for viral markers (mainly RdRps, genomad VVs, or user-provided), using profile-based methods (HMMER / MMseqs2).
101
107
  - ✅ [`virus-mapping`](https://urineri.github.io/rolypoly/commands/search_viruses) — Map and identify viruses using nucleic acid search (MMseqs2).
102
- - ✅ `rdrp-motif-search` — Search RdRp motifs (A/B/C/D) in nucleotide or amino acid sequences.
108
+ - ✅ [`rdrp-motif-search`](https://urineri.github.io/rolypoly/commands/rdrp_motif_search) — Search RdRp motifs (A/B/C/D) in nucleotide or amino acid sequences.
103
109
 
104
110
  #### Bining / Clustering
105
- - 🧪 `cluster` — Average Nucleic identity (ANI) based contig gropuing. Supports several common backends and methods.
106
- - 🧪 `extend` — Extend sequences by pile-up/assembly. Useful for combining assemblies of with low abundance viruses, or those with high microdiversity, at the cost of worse strain/sub-species resolution (i.e. can condense to a consenus).
107
- - 🧪 `termini` — Shared termini grouping and motif reporting. Writes assignments + groups tables (TSV/CSV/Parquet/JSONL) and motif FASTA by default.
108
- - 🧪 `correlate` — group contigs based on co-occurence, co-abundance, minimal correlation (Spearman's) of these, or both.
109
- - 🤔 `binit` — Combines the above commands with sample information and genome attributes (e.g. require a shared termini AND protein complementarity, like CP + RdRp). See [notebooks/Exprimental/partiti_usecase/partiti_segment_workflow_experimental.ipynb](notebooks/Exprimental/partiti_usecase/partiti_segment_workflow_experimental.ipynb) for candidate workflow.
111
+ - 🧪 [`cluster`](https://urineri.github.io/rolypoly/commands/cluster) — Average Nucleic identity (ANI) based contig grouping. Supports several common backends and methods.
112
+ - 🧪 [`extend`](https://urineri.github.io/rolypoly/commands/extend) — Extend sequences by pile-up/assembly. Useful for combining assemblies of with low abundance viruses, or those with high microdiversity, at the cost of worse strain/sub-species resolution (i.e. can condense to a consensus).
113
+ - 🧪 [`termini`](https://urineri.github.io/rolypoly/commands/binning_termini) — Shared termini grouping and motif reporting. Writes assignments + groups tables (TSV/CSV/Parquet/JSONL) and motif FASTA by default.
114
+ - 🧪 [`correlate`](https://urineri.github.io/rolypoly/commands/binning_correlate) — Group contigs based on co-occurrence, co-abundance, minimal correlation (Spearman's) of these, or both.
115
+ - 🤔 [`binit`](https://urineri.github.io/rolypoly/commands/binit) — Combines the above commands with sample information and genome attributes (e.g. require a shared termini AND protein complementarity, like CP + RdRp). See [notebooks/Exprimental/partiti_usecase/partiti_segment_workflow_experimental.ipynb](notebooks/Exprimental/partiti_usecase/partiti_segment_workflow_experimental.ipynb) for candidate workflow.
110
116
 
111
117
  #### Miscellaneous
112
- - ✅ `roll` — Run an end-to-end pipeline (before v0.7.1, named `end2end`).
113
- - ✅ `fetch-sra` — Download SRA fastq files (from ENA)
114
- - ✅ `fastx-calc` — Calculate per-sequence metrics (length, GC content, hash, ...)
115
- - ✅ `fastx-stats` — Calculate (-->aggregate) statistics for sequences (min, max, mean, median, ...) (input is file/s)
116
- - ✅ `rename-seqs` — Rename sequences (add a prefix, suffix, hash, running number, etc.)
117
- - 🚧 `quick-taxonomy` — Quick taxonomy assignment. Candidate workflows are [github.com/UriNeri/ictv-mmseqs2-protein-database](https://github.com/UriNeri/ictv-mmseqs2-protein-database) and [github.com/apcamargo/ictv-mmseqs2-protein-database](https://github.com/apcamargo/ictv-mmseqs2-protein-database)
118
+ - ✅ [`roll`](https://urineri.github.io/rolypoly/commands/end_to_end) — Run an end-to-end pipeline (before v0.7.1, named `end2end`).
119
+ - ✅ [`fetch-sra`](https://urineri.github.io/rolypoly/commands/misc) — Download SRA fastq files (from ENA)
120
+ - ✅ [`fastx-calc`](https://urineri.github.io/rolypoly/commands/misc) — Calculate per-sequence metrics (length, GC content, hash, ...)
121
+ - ✅ [`fastx-stats`](https://urineri.github.io/rolypoly/commands/misc) — Calculate (-->aggregate) statistics for sequences (min, max, mean, median, ...) (input is file/s)
122
+ - ✅ [`rename-seqs`](https://urineri.github.io/rolypoly/commands/misc) — Rename sequences (add a prefix, suffix, hash, running number, etc.)
123
+ - 🚧 [`quick-taxonomy`](https://urineri.github.io/rolypoly/commands/misc) — Quick taxonomy assignment. Candidate workflows are [github.com/UriNeri/ictv-mmseqs2-protein-database](https://github.com/UriNeri/ictv-mmseqs2-protein-database) and [github.com/apcamargo/ictv-mmseqs2-protein-database](https://github.com/apcamargo/ictv-mmseqs2-protein-database)
118
124
  - 🤔 support for [genotate](https://github.com/deprekate/genotate) for gene prediction.
119
125
  - 🤔 Genome refinement / strain de-entalgement / variant calling?
120
126
  - 🤔 Virus feature prediction (+/-ssRNA/dsRNA, circular/linear, mono/poly-segmented, capsid type, etc.)
@@ -125,7 +131,7 @@ If you have suggestions for additional commands or features, or want to implemen
125
131
 
126
132
  ## Dependencies
127
133
 
128
- **📦 Modular Installation Available**: RolyPoly supports both quick setup (one environment with all dependecies for all commands) and modular installation (command-specific environments). The modular approach is particularly useful for software developers who want to integrate specific rolypoly features with minimal dependency conflicts. See the [installation documentation](./docs/docs/mkdocs_docs/installation.md) for details.
134
+ **📦 Modular Installation Available**: RolyPoly supports both quick setup (one environment with all dependecies for all commands) and modular installation (command-specific environments). The modular approach is particularly useful for software developers who want to integrate specific rolypoly features with minimal dependency conflicts. See the [installation documentation](https://urineri.github.io/rolypoly/installation/) for details.
129
135
 
130
136
  Not all 3rd party software is used by all the different commands. RolyPoly includes a "citation reminder" that will try to list all the external software used by a command. The "reminded citations" are pretty printed to console (stdout) and to a logfile. To shut off the terminal citation reminder printing, set `ROLYPOLY_REMIND_CITATIONS` to false in your `rpconfig.json` file.
131
137
 
@@ -16,7 +16,7 @@ authors = [
16
16
 
17
17
  description = "RNA virus analysis toolkit"
18
18
  readme = "README.md"
19
- requires-python = ">=3.10"
19
+ requires-python = ">=3.10,<3.14"
20
20
  license = { file = "LICENSE" }
21
21
  # License-File = "license"
22
22
  dependencies = [
@@ -47,7 +47,7 @@ dependencies = [
47
47
 
48
48
  [project.urls]
49
49
  Source = "https://github.com/UriNeri/rolypoly"
50
- Documentation = "https://pages.jgi.doe.gov/rolypoly/docs/"
50
+ Documentation = "https://urineri.github.io/rolypoly/"
51
51
  pypi = "https://pypi.org/project/rolypoly-tk/"
52
52
 
53
53
  [project.scripts]
@@ -160,6 +160,13 @@ aria2 = ">=1.37.0,<2"
160
160
  [tool.pixi.feature.dev.pypi-dependencies]
161
161
  lets-plot = ">=4.8.2,<5"
162
162
 
163
+ [tool.pixi.feature.docs.pypi-dependencies]
164
+ mkdocs = "*"
165
+ mkdocs-material = "*"
166
+ mkdocs-mermaid2-plugin = "*"
167
+ mkdocstrings = "*"
168
+ mkdocstrings-python = "*"
169
+
163
170
  [tool.pixi.feature.py310.dependencies]
164
171
  python = "~=3.10.0"
165
172
 
@@ -193,6 +200,7 @@ dev = { features = [
193
200
  "format",
194
201
  "publish",
195
202
  "dev",
203
+ "docs",
196
204
  ] }
197
205
 
198
206
  # Specific command group environments for targeted installations
@@ -234,6 +242,10 @@ test-import = "python -c 'import rolypoly; print(rolypoly.__version__)'"
234
242
  test-cli = "pytest -q src/tests/test_cli_contracts.py"
235
243
  bump-commit-publish = "bash src/setup/bump_commit_publish.sh"
236
244
 
245
+ [tool.pixi.feature.docs.tasks]
246
+ docs-serve = "mkdocs serve -f docs/mkdocs.yml"
247
+ docs-build = "mkdocs build -f docs/mkdocs.yml"
248
+
237
249
  [tool.ruff]
238
250
  exclude = [
239
251
  ".bzr",
@@ -1,4 +1,4 @@
1
1
  """rolypoly: RNA virus analysis toolkit"""
2
2
 
3
- __version__ = "0.7.2"
3
+ __version__ = "0.7.4"
4
4
  __name__ = "rolypoly-tk"
@@ -177,7 +177,15 @@ def annotate(
177
177
  log_level,
178
178
  search_tool,
179
179
  ):
180
- """Functionally and structurally annotate RNA viral sequence(s) (Wrapper for annotate_prot, annotate_RNA)"""
180
+ """Run combined RNA + protein annotation on nucleotide viral sequences.
181
+
182
+ This command orchestrates `annotate-rna` and `annotate-prot` into a single
183
+ workflow and writes results into `rna_annotation/` and
184
+ `protein_annotation/` subdirectories under the selected output path.
185
+
186
+ Use `--skip-steps` to disable specific stages and `--override-parameters`
187
+ to forward JSON overrides to sub-tools.
188
+ """
181
189
  import json
182
190
 
183
191
  from rolypoly.utils.logging.loggit import log_start_info
@@ -228,10 +228,15 @@ def annotate_RNA(
228
228
  resolve_mode,
229
229
  min_overlap_positions,
230
230
  ):
231
- """Predict viral sequence RNA secondary structure, search for ribozymes, IRES, tRNAs, and other RNA structural elements.
232
- By default, the following steps are run in the following order: predict_secondary_structure (LinearFold), search_ribozymes (Rfam via cmscan), predict_trnas (tRNAscan-SE).
233
- Additional steps (detect_ires, search_rna_motifs, search_rna_elements) are currently disabled as they are under development.
234
- Use --skip-steps to skip specific steps."""
231
+ """Annotate RNA structural features and motifs on viral nucleotide inputs.
232
+
233
+ The default pipeline runs secondary-structure prediction, ribozyme/CM
234
+ search, and tRNA detection, while optional modules can add IRES and motif
235
+ analyses depending on selected tools and skip settings.
236
+
237
+ Use `--skip-steps` to disable modules and `--override-parameters` to pass
238
+ tool-specific tuning values for individual stages.
239
+ """
235
240
  import json
236
241
 
237
242
  config = RNAAnnotationConfig(
@@ -530,7 +530,16 @@ def assembly(
530
530
  overwrite,
531
531
  log_level,
532
532
  ):
533
- """Assembly wrapper - takes in reads, assembles them using one or more assemblers, then performs post-assembly processing."""
533
+ """Assemble reads/contigs with one or more backends and optional post-processing.
534
+
535
+ Inputs can be provided explicitly (`--paired-end`, `--single-end`,
536
+ `--merged`, `--long-read`, `--raw-fasta`) and/or discovered from
537
+ `--input-dir`.
538
+
539
+ Selected assembler outputs are normalized and optionally post-processed
540
+ (for example `rmdup` or `linclust`) before writing final contigs and run
541
+ metadata to the output directory.
542
+ """
534
543
  import shutil
535
544
 
536
545
  import polars as pl
@@ -167,7 +167,13 @@ def filter_contigs(
167
167
  log_level,
168
168
  ):
169
169
  """
170
- Filter contigs based on user-supplied host sequences. Wrapper for both nucleotide and amino acid filtering.
170
+ Filter contigs against user-supplied host/contamination references.
171
+
172
+ Depending on `--mode`, the command applies nucleotide filtering, protein
173
+ filtering, or both, using two-stage rule sets (`filter1_*` and
174
+ `filter2_*`) to retain likely non-host contigs.
175
+
176
+ Host references can be masked first (default) unless `--dont-mask` is set.
171
177
  """
172
178
  from rolypoly.utils.logging.citation_reminder import remind_citations
173
179
  from rolypoly.utils.logging.loggit import log_start_info
@@ -432,7 +432,12 @@ def binit(
432
432
  log_file: Path | None,
433
433
  log_level: str,
434
434
  ) -> None:
435
- """Run a first integrated segment-binning workflow over RdRp and CP contigs."""
435
+ """Run an integrated segment-binning workflow over RdRp and CP contigs.
436
+
437
+ The workflow chains cluster, correlate, extend, and termini steps, then
438
+ joins their outputs to report candidate segment pairs with supporting
439
+ evidence from abundance/correlation and termini/motif consistency.
440
+ """
436
441
  logger = setup_logging(log_file, log_level)
437
442
  log_start_info(logger, locals())
438
443
 
@@ -296,7 +296,14 @@ def correlate(
296
296
  log_file,
297
297
  log_level,
298
298
  ):
299
- """Correlate and cluster contigs by cross-sample co-occurrence patterns."""
299
+ """Group contigs by cross-sample association patterns.
300
+
301
+ Supports correlation-based edges, co-occurrence-based edges, or both,
302
+ with prevalence and shared-sample thresholds to reduce spurious links.
303
+
304
+ Writes pairwise edge tables and connected-component style groups using the
305
+ selected output prefix.
306
+ """
300
307
  logger = setup_logging(log_file, log_level)
301
308
  log_start_info(logger, locals())
302
309
 
@@ -48,7 +48,13 @@ tools = []
48
48
  def virus_mapping(
49
49
  threads, memory, output, keep_tmp, db, db_path, log_file, log_level, input
50
50
  ):
51
- """MMseqs2 Virus mapping/search wrapper - takes in reads/contigs (i.e. nucs), and search them against precompiled virus databases OR user-supplied databases."""
51
+ """Search nucleotide reads/contigs against virus reference databases.
52
+
53
+ Input can be FASTA/FASTQ or an existing MMseqs2 database. The command
54
+ converts sequence inputs to MMseqs2 format as needed and runs searches
55
+ against built-in viral databases (`RVMT`, `NCBI_Ribovirus`, or `all`) or a
56
+ user-supplied target via `--db other --db-path`.
57
+ """
52
58
  import shutil
53
59
  import subprocess
54
60
 
@@ -82,8 +82,10 @@ def fastx_stats(
82
82
  """
83
83
  Calculate aggregate statistics for sequences (min, max, mean, median, etc.).
84
84
 
85
- This command computes summary statistics across all sequences in a FASTA/FASTQ file.
86
- For per-sequence calculations, use the 'fastx-calc' command instead.
85
+ This command computes dataset-level summaries across sequences in one or
86
+ more FASTA/FASTQ inputs, including count, length, and composition fields.
87
+
88
+ For per-sequence annotations instead of aggregates, use `fastx-calc`.
87
89
  """
88
90
  from rolypoly.utils.bio.polars_fastx import (
89
91
  compute_aggregate_stats,
@@ -463,8 +463,14 @@ def filter_reads(
463
463
  temp_dir,
464
464
  ):
465
465
  """
466
- Process RNA-seq (transcriptome, RNA virome, metatranscriptomes) Illumina raw reads.
467
- Removes host reads, synthetic artifacts, and unknown DNA, corrects sequencing errors, trims adapters and low quality reads.
466
+ Process RNA-seq Illumina reads through the read-cleaning pipeline.
467
+
468
+ The workflow combines host/contaminant removal, optional fetched-reference
469
+ filtering, adapter/quality trimming, and optional error correction based on
470
+ configured steps and speed presets.
471
+
472
+ Input can be a single file, paired files, or a directory of FASTQ files.
473
+ Use `--skip-steps` and `--override-parameters` to tailor the workflow.
468
474
  """
469
475
  from rolypoly.utils.logging.citation_reminder import remind_citations
470
476
  from rolypoly.utils.logging.loggit import log_start_info
@@ -65,11 +65,13 @@ def shrink_reads(
65
65
  log_level,
66
66
  ):
67
67
  """
68
- Subsets data from an input FASTQ file(s) based on the provided options.
69
- Supports random sampling (when sample_size < 1) and fixed number read sampling
70
- (i.e. first n reads)
71
- NOTE: UNLESS --keep-matching-pairs is used, the output may not be very useful in practice.
72
- TODO: no real threading support yet, maybe will have it if multiple input files are used (one per thread)
68
+ Subset FASTQ reads by count or fraction for lightweight test datasets.
69
+
70
+ Supports deterministic head-style subsampling (`first_n`) and random
71
+ sampling (`random`) for single-end, interleaved, and paired-end layouts.
72
+
73
+ This command is intended for quick dry runs and resource-reduced tests,
74
+ not as a full read-normalization strategy.
73
75
  """
74
76
  # Initialise logger
75
77
  logger = setup_logging(log_file=log_file, log_level=log_level)
@@ -109,7 +109,6 @@ CONTEXT_SETTINGS = dict(
109
109
  "fastx-stats": "rolypoly.commands.misc.fastx_stats.fastx_stats",
110
110
  "fastx-calc": "rolypoly.commands.misc.fastx_calc.fastx_calc",
111
111
  "rename-seqs": "rolypoly.commands.misc.rename_seqs.rename_seqs",
112
- "quick-taxonomy": "rolypoly.commands.misc.quick_taxonomy.quick_taxonomy",
113
112
  "help": "rolypoly.rolypoly.rolypoly",
114
113
  },
115
114
  },
@@ -126,7 +125,6 @@ CONTEXT_SETTINGS = dict(
126
125
  # "name": "Characterisation",
127
126
  # "commands": {
128
127
  # "characterise": "hidden:rolypoly.commands.virotype.predict_characteristics.predict_characteristics",
129
- # "predict-host": "hidden:rolypoly.commands.host.classify.predict_host_range",
130
128
  # # Commenting out unimplemented/broken commands
131
129
  # # "summarize": "rolypoly.commands.virotype.summarize.summarize"
132
130
  # },
@@ -156,7 +154,10 @@ def rolypoly():
156
154
  )
157
155
  def version(log_level):
158
156
  """
159
- Print code version (commit or semvar) and data (date) information.
157
+ Print RolyPoly code and data version details.
158
+
159
+ This is a command-form wrapper around top-level `--version` output, useful
160
+ in scripted workflows that call `rolypoly version` explicitly.
160
161
  """
161
162
  setup_logging(None, log_level)
162
163
  # click wrapper for version/data information, so it could be called vai rolypoly version (on top of rolypoly --version)
@@ -1,47 +0,0 @@
1
- """
2
- This is a place holder script.
3
- """
4
-
5
- import os
6
-
7
- import rich_click as click
8
-
9
- # from rich.console import Console
10
-
11
- # console = Console()
12
-
13
-
14
- @click.command()
15
- @click.option(
16
- "-i",
17
- "--input",
18
- required=True,
19
- help="Input directory containing rolypoly's virus identification and annotation results",
20
- )
21
- @click.option(
22
- "-o",
23
- "--output",
24
- default=lambda: f"{os.getcwd()}_predict_host_range.tsv",
25
- help="output path",
26
- )
27
- @click.option("-t", "--threads", default=1, help="Number of threads")
28
- @click.option(
29
- "-g",
30
- "--log-file",
31
- default=lambda: f"{os.getcwd()}/predict_host_range_logfile.txt",
32
- help="Path to log file",
33
- )
34
- @click.option(
35
- "-ll", "--log-level", hidden=True, default="INFO", help="Log level"
36
- )
37
- def predict_host_range(input, output, threads, log_file, log_level):
38
- """WIP WIP WIP Predict a viral seq host range - caution! this is not definitive"""
39
- from rolypoly.utils.logging.loggit import setup_logging
40
-
41
- logger = setup_logging(log_file, log_level)
42
- logger.info("Starting to predict ")
43
- logger.info("Sorry! command not yet implemented!")
44
-
45
-
46
- if __name__ == "main":
47
- predict_host_range()
@@ -1,372 +0,0 @@
1
- """
2
- this script is a place holder
3
- """
4
-
5
- from pathlib import Path
6
-
7
- import rich_click as click
8
- from rich.console import Console
9
-
10
- from rolypoly.utils.logging.citation_reminder import remind_citations
11
-
12
- console = Console()
13
-
14
-
15
- def parse_marker_results(marker_file):
16
- """Parse marker search results file.
17
-
18
- Args:
19
- marker_file (str): Path to marker search results
20
-
21
- Returns:
22
- pl.DataFrame: DataFrame with marker results
23
- """
24
- import json
25
-
26
- import polars as pl
27
-
28
- if marker_file.endswith(".tsv"):
29
- return pl.read_csv(marker_file, separator="\t")
30
- elif marker_file.endswith(".json"):
31
- with open(marker_file) as f:
32
- data = json.load(f)
33
- return pl.DataFrame(data)
34
- else:
35
- raise ValueError(f"Unsupported file format for {marker_file}")
36
-
37
-
38
- def run_genomad_hmm_search(input_fasta, output_dir, threads, logger):
39
- """Run genomad RNA viral HMM search.
40
-
41
- Args:
42
- input_fasta (str): Path to input fasta file
43
- output_dir (Path): Output directory
44
- threads (int): Number of threads to use
45
- logger (Logger): Logger object
46
-
47
- Returns:
48
- pl.DataFrame: DataFrame with HMM search results
49
- """
50
- import os
51
-
52
- import polars as pl
53
-
54
- from rolypoly.utils.bio.alignments import search_hmmdb
55
-
56
- hmm_db = (
57
- Path(os.environ["ROLYPOLY_DATA"])
58
- / "hmmdbs"
59
- / "genomad_rna_viral_markers.hmm"
60
- )
61
- output_file = output_dir / "genomad_hmm_results.txt"
62
-
63
- # Use existing HMM search functionality
64
- try:
65
- search_hmmdb(
66
- amino_file=input_fasta,
67
- db_path=str(hmm_db),
68
- output=str(output_file),
69
- threads=threads,
70
- logger=logger,
71
- output_format="tblout",
72
- )
73
-
74
- # Parse results
75
- results = []
76
- with open(output_file) as f:
77
- for line in f:
78
- if line.startswith("#"):
79
- continue
80
- parts = line.split()
81
- if len(parts) >= 5:
82
- results.append(
83
- {
84
- "query": parts[0],
85
- "target": parts[2],
86
- "evalue": float(parts[4]),
87
- "score": float(parts[5]),
88
- }
89
- )
90
-
91
- return pl.DataFrame(results)
92
- except Exception as e:
93
- logger.error(f"HMM search failed: {e}")
94
- return pl.DataFrame()
95
-
96
-
97
- def assign_taxonomy(sequence_id, markers, hmm_results, min_score=50):
98
- """Assign taxonomy based on marker and HMM results.
99
-
100
- Args:
101
- sequence_id (str): Sequence identifier
102
- markers (pl.DataFrame): Marker search results
103
- hmm_results (pl.DataFrame): HMM search results
104
- min_score (float): Minimum score threshold
105
-
106
- Returns:
107
- dict: Taxonomy assignment
108
- """
109
- import polars as pl
110
-
111
- # Filter results by score
112
- seq_markers = markers.filter(pl.col("query") == sequence_id)
113
- seq_hmms = hmm_results.filter(
114
- (pl.col("query") == sequence_id) & (pl.col("score") >= min_score)
115
- )
116
-
117
- # Initialize taxonomy assignment
118
- tax = {
119
- "sequence_id": sequence_id,
120
- "confidence": 0.0,
121
- "taxonomy": "Unknown",
122
- "evidence": [],
123
- }
124
-
125
- # Look for RdRP markers first (highest confidence)
126
- rdrp_markers = seq_markers.filter(
127
- pl.col("target").str.contains("RdRP|RdRp|rdrp")
128
- )
129
- if not rdrp_markers.is_empty():
130
- best_hit = rdrp_markers.sort("score", descending=True).row(0)
131
- tax["taxonomy"] = (
132
- best_hit["taxonomy"] if "taxonomy" in best_hit else "RNA virus"
133
- )
134
- tax["confidence"] = min(1.0, best_hit["score"] / 100)
135
- tax["evidence"].append(f"RdRP marker: {best_hit['target']}")
136
-
137
- # Check genomad HMM results
138
- if not seq_hmms.is_empty():
139
- hmm_hits = seq_hmms.sort("score", descending=True)
140
- for hit in hmm_hits.iter_rows():
141
- tax["evidence"].append(f"RNA viral marker: {hit['target']}")
142
- if (
143
- tax["confidence"] < 0.8
144
- ): # Only update if current confidence is low
145
- tax["confidence"] = min(0.8, hit["score"] / 100)
146
-
147
- # Check other viral markers
148
- other_markers = seq_markers.filter(
149
- ~pl.col("target").str.contains("RdRP|RdRp|rdrp")
150
- )
151
- if not other_markers.is_empty():
152
- for hit in other_markers.iter_rows():
153
- tax["evidence"].append(f"Other marker: {hit['target']}")
154
- if (
155
- tax["confidence"] < 0.6
156
- ): # Only update if current confidence is low
157
- tax["confidence"] = min(0.6, hit["score"] / 100)
158
-
159
- return tax
160
-
161
-
162
- def summarize_taxonomy(assignments):
163
- """Generate taxonomy summary statistics.
164
-
165
- Args:
166
- assignments (list): List of taxonomy assignments
167
-
168
- Returns:
169
- dict: Summary statistics
170
- """
171
- from collections import defaultdict
172
-
173
- total = len(assignments)
174
- assigned = sum(1 for a in assignments if a["taxonomy"] != "Unknown")
175
-
176
- # Count taxonomy levels
177
- tax_counts = defaultdict(int)
178
- confidence_sum = 0
179
-
180
- for assign in assignments:
181
- if assign["taxonomy"] != "Unknown":
182
- tax_counts[assign["taxonomy"]] += 1
183
- confidence_sum += assign["confidence"]
184
-
185
- return {
186
- "total_sequences": total,
187
- "assigned_sequences": assigned,
188
- "percent_assigned": (assigned / total * 100) if total > 0 else 0,
189
- "mean_confidence": confidence_sum / assigned if assigned > 0 else 0,
190
- "taxonomy_distribution": dict(tax_counts),
191
- }
192
-
193
-
194
- @click.command()
195
- @click.option("-i", "--input", required=True, help="Input file or directory")
196
- @click.option("-o", "--output", default="output", help="Output directory")
197
- @click.option("-t", "--threads", default=1, help="Number of threads")
198
- @click.option("--log-file", default="command.log", help="Path to log file")
199
- @click.option(
200
- "-ll", "--log-level", hidden=True, default="INFO", help="Log level"
201
- )
202
- @click.option("--marker_results", default=None, type=str, help="marker_results")
203
- @click.option(
204
- "--format",
205
- default="text",
206
- type=click.Choice(["text", "json", "tsv"]),
207
- help="format",
208
- )
209
- @click.option("--min_score", default=50.0, type=float, help="min_score")
210
- @click.option("--summarize", default=True, type=bool, help="summarize")
211
- def quick_taxonomy(
212
- input,
213
- output,
214
- threads,
215
- log_file,
216
- log_level,
217
- marker_results,
218
- format,
219
- min_score,
220
- summarize,
221
- ):
222
- """
223
- Rapid taxonomy assignment for viral sequences using marker search results and genomad RNA viral HMMs
224
- """
225
- import json
226
-
227
- import polars as pl
228
- from needletail import parse_fastx_file
229
- from rich.table import Table
230
-
231
- from rolypoly.utils.logging.loggit import log_start_info, setup_logging
232
-
233
- logger = setup_logging(log_file, log_level)
234
- log_start_info(logger, locals())
235
-
236
- # Create output directory
237
- output_path = Path(output)
238
- output_path.mkdir(parents=True, exist_ok=True)
239
-
240
- sequences = []
241
- for record in parse_fastx_file(input):
242
- sequences.append({"id": record.id, "seq": record.seq}) # type: ignore
243
-
244
- if not sequences:
245
- logger.error(f"No sequences found in {input}")
246
- return
247
-
248
- # Parse marker results if provided
249
- markers_df = None
250
- if marker_results:
251
- try:
252
- markers_df = parse_marker_results(marker_results)
253
- except Exception as e:
254
- logger.warning(f"Error parsing marker results: {e}")
255
-
256
- # Run genomad HMM search
257
- logger.info("Running genomad RNA viral HMM search...")
258
- hmm_results = run_genomad_hmm_search(input, output_path, threads, logger)
259
-
260
- # Assign taxonomy
261
- logger.info("Assigning taxonomy...")
262
- assignments = []
263
- for seq in sequences:
264
- tax = assign_taxonomy(
265
- seq["id"],
266
- markers_df if markers_df is not None else pl.DataFrame(),
267
- hmm_results,
268
- min_score,
269
- )
270
- assignments.append(tax)
271
-
272
- # Generate summary if requested
273
- if summarize:
274
- summary = summarize_taxonomy(assignments)
275
-
276
- # Output results based on format
277
- if format == "json":
278
- results = {
279
- "assignments": assignments,
280
- "summary": summary if summarize else None,
281
- }
282
- with open(output_path / "taxonomy_assignments.json", "w") as f:
283
- json.dump(results, f, indent=2)
284
-
285
- elif format == "tsv":
286
- # Flatten assignments for TSV
287
- flat_assignments = []
288
- for assign in assignments:
289
- flat_assign = {
290
- "sequence_id": assign["sequence_id"],
291
- "taxonomy": assign["taxonomy"],
292
- "confidence": assign["confidence"],
293
- "evidence": ";".join(assign["evidence"]),
294
- }
295
- flat_assignments.append(flat_assign)
296
-
297
- pl.DataFrame(flat_assignments).write_csv(
298
- output_path / "taxonomy_assignments.tsv", separator="\t"
299
- )
300
-
301
- if summarize:
302
- with open(output_path / "taxonomy_summary.tsv", "w") as f:
303
- for k, v in summary.items():
304
- if k != "taxonomy_distribution":
305
- f.write(f"{k}\t{v}\n")
306
- f.write("\nTaxonomy distribution:\n")
307
- for tax, count in summary["taxonomy_distribution"].items():
308
- f.write(f"{tax}\t{count}\n")
309
-
310
- else: # text format
311
- # Create assignments table
312
- assign_table = Table(title="Taxonomy Assignments")
313
- assign_table.add_column("Sequence ID")
314
- assign_table.add_column("Taxonomy")
315
- assign_table.add_column("Confidence")
316
- assign_table.add_column("Evidence")
317
-
318
- for assign in assignments:
319
- assign_table.add_row(
320
- assign["sequence_id"],
321
- assign["taxonomy"],
322
- f"{assign['confidence']:.2f}",
323
- "\n".join(assign["evidence"]),
324
- )
325
-
326
- console.print(assign_table)
327
-
328
- if summarize:
329
- # Create summary table
330
- summary_table = Table(title="Taxonomy Summary")
331
- summary_table.add_column("Metric")
332
- summary_table.add_column("Value")
333
-
334
- for k, v in summary.items():
335
- if k != "taxonomy_distribution":
336
- summary_table.add_row(
337
- k, f"{v:.1f}" if isinstance(v, float) else str(v)
338
- )
339
-
340
- console.print(summary_table)
341
-
342
- # Create taxonomy distribution table
343
- dist_table = Table(title="Taxonomy Distribution")
344
- dist_table.add_column("Taxonomy")
345
- dist_table.add_column("Count")
346
- dist_table.add_column("Percentage")
347
-
348
- total = sum(summary["taxonomy_distribution"].values())
349
- for tax, count in summary["taxonomy_distribution"].items():
350
- dist_table.add_row(
351
- tax, str(count), f"{count / total * 100:.1f}%"
352
- )
353
-
354
- console.print(dist_table)
355
-
356
- # Save to file
357
- with open(output_path / "taxonomy_assignments.txt", "w") as f:
358
- file_console = Console(file=f)
359
- file_console.print(assign_table)
360
- if summarize:
361
- file_console.print("\n")
362
- file_console.print(summary_table)
363
- file_console.print("\n")
364
- file_console.print(dist_table)
365
-
366
- logger.info("quick-taxonomy completed successfully!")
367
- tools = ["HMMER", "geNomad"]
368
- remind_citations(tools)
369
-
370
-
371
- if __name__ == "__main__":
372
- quick_taxonomy()
File without changes
File without changes
File without changes