{"id":16849265,"url":"https://github.com/mbhall88/rasusa","last_synced_at":"2026-02-19T03:00:43.900Z","repository":{"id":36174406,"uuid":"211095413","full_name":"mbhall88/rasusa","owner":"mbhall88","description":"Randomly subsample sequencing reads or alignments","archived":false,"fork":false,"pushed_at":"2026-02-09T09:22:01.000Z","size":14086,"stargazers_count":254,"open_issues_count":8,"forks_count":20,"subscribers_count":3,"default_branch":"main","last_synced_at":"2026-02-10T20:05:38.010Z","etag":null,"topics":["alignment","bam","bioinformatics","coverage","downsample","fasta","fastq","genome-analysis","random","rust","subsampling"],"latest_commit_sha":null,"homepage":"https://doi.org/10.21105/joss.03941","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mbhall88.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2019-09-26T13:25:47.000Z","updated_at":"2026-02-06T15:47:27.000Z","dependencies_parsed_at":"2023-01-16T23:45:46.044Z","dependency_job_id":"eb7f5ffe-220d-4f17-bd96-067385a1d352","html_url":"https://github.com/mbhall88/rasusa","commit_stats":{"total_commits":237,"total_committers":6,"mean_commits":39.5,"dds":"0.21518987341772156","last_synced_commit":"ae44cabded6fb83fbb75e6c90dc7e4f1a098d00e"},"previous_names":[],"tags_count":21,"template":false,"template_full_name":null,"purl":"pkg:github/mbhall88/rasusa","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mbhall88%2Frasusa","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mbhall88%2Frasusa/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mbhall88%2Frasusa/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mbhall88%2Frasusa/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mbhall88","download_url":"https://codeload.github.com/mbhall88/rasusa/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mbhall88%2Frasusa/sbom","scorecard":{"id":630944,"data":{"date":"2025-08-11","repo":{"name":"github.com/mbhall88/rasusa","commit":"42d1ad030db5162fdac297bdfd0cea5cc41c2200"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3.3,"checks":[{"name":"Code-Review","score":0,"reason":"Found 2/26 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Maintained","score":4,"reason":"3 commit(s) and 2 issue activity found in the last 90 days -- score normalized to 4","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: topLevel 'contents' permission set to 'write': .github/workflows/release-please.yaml:7","Warn: no topLevel permission defined: .github/workflows/release.yaml:1","Warn: no topLevel permission defined: .github/workflows/rust-ci.yaml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":0,"reason":"Project has not signed or included provenance with any releases.","details":["Warn: release artifact 2.1.1 not signed: https://api.github.com/repos/mbhall88/rasusa/releases/235075483","Warn: release artifact 2.1.0 not signed: https://api.github.com/repos/mbhall88/rasusa/releases/170809227","Warn: release artifact 2.0.0 not signed: https://api.github.com/repos/mbhall88/rasusa/releases/154219125","Warn: release artifact 1.0.0 not signed: https://api.github.com/repos/mbhall88/rasusa/releases/153170082","Warn: release artifact 0.8.0 not signed: https://api.github.com/repos/mbhall88/rasusa/releases/135625471","Warn: release artifact 2.1.1 does not have provenance: https://api.github.com/repos/mbhall88/rasusa/releases/235075483","Warn: release artifact 2.1.0 does not have provenance: https://api.github.com/repos/mbhall88/rasusa/releases/170809227","Warn: release artifact 2.0.0 does not have provenance: https://api.github.com/repos/mbhall88/rasusa/releases/154219125","Warn: release artifact 1.0.0 does not have provenance: https://api.github.com/repos/mbhall88/rasusa/releases/153170082","Warn: release artifact 0.8.0 does not have provenance: https://api.github.com/repos/mbhall88/rasusa/releases/135625471"],"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'main'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: third-party GitHubAction not pinned by hash: .github/workflows/release-please.yaml:16: update your workflow using https://app.stepsecurity.io/secureworkflow/mbhall88/rasusa/release-please.yaml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/release.yaml:18: update your workflow using https://app.stepsecurity.io/secureworkflow/mbhall88/rasusa/release.yaml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/release.yaml:21: update your workflow using https://app.stepsecurity.io/secureworkflow/mbhall88/rasusa/release.yaml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/release.yaml:44: update your workflow using https://app.stepsecurity.io/secureworkflow/mbhall88/rasusa/release.yaml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/release.yaml:55: update your workflow using https://app.stepsecurity.io/secureworkflow/mbhall88/rasusa/release.yaml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/release.yaml:70: update your workflow using https://app.stepsecurity.io/secureworkflow/mbhall88/rasusa/release.yaml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/release.yaml:125: update your workflow using https://app.stepsecurity.io/secureworkflow/mbhall88/rasusa/release.yaml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/release.yaml:138: update your workflow using https://app.stepsecurity.io/secureworkflow/mbhall88/rasusa/release.yaml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/rust-ci.yaml:112: update your workflow using https://app.stepsecurity.io/secureworkflow/mbhall88/rasusa/rust-ci.yaml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/rust-ci.yaml:115: update your workflow using https://app.stepsecurity.io/secureworkflow/mbhall88/rasusa/rust-ci.yaml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/rust-ci.yaml:120: update your workflow using https://app.stepsecurity.io/secureworkflow/mbhall88/rasusa/rust-ci.yaml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/rust-ci.yaml:134: update your workflow using https://app.stepsecurity.io/secureworkflow/mbhall88/rasusa/rust-ci.yaml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/rust-ci.yaml:137: update your workflow using https://app.stepsecurity.io/secureworkflow/mbhall88/rasusa/rust-ci.yaml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/rust-ci.yaml:142: update your workflow using https://app.stepsecurity.io/secureworkflow/mbhall88/rasusa/rust-ci.yaml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/rust-ci.yaml:155: update your workflow using https://app.stepsecurity.io/secureworkflow/mbhall88/rasusa/rust-ci.yaml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/rust-ci.yaml:158: update your workflow using https://app.stepsecurity.io/secureworkflow/mbhall88/rasusa/rust-ci.yaml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/rust-ci.yaml:162: update your workflow using https://app.stepsecurity.io/secureworkflow/mbhall88/rasusa/rust-ci.yaml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/rust-ci.yaml:170: update your workflow using https://app.stepsecurity.io/secureworkflow/mbhall88/rasusa/rust-ci.yaml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/rust-ci.yaml:178: update your workflow using https://app.stepsecurity.io/secureworkflow/mbhall88/rasusa/rust-ci.yaml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/rust-ci.yaml:15: update your workflow using https://app.stepsecurity.io/secureworkflow/mbhall88/rasusa/rust-ci.yaml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/rust-ci.yaml:22: update your workflow using https://app.stepsecurity.io/secureworkflow/mbhall88/rasusa/rust-ci.yaml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/rust-ci.yaml:35: update your workflow using https://app.stepsecurity.io/secureworkflow/mbhall88/rasusa/rust-ci.yaml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/rust-ci.yaml:38: update your workflow using https://app.stepsecurity.io/secureworkflow/mbhall88/rasusa/rust-ci.yaml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/rust-ci.yaml:42: update your workflow using https://app.stepsecurity.io/secureworkflow/mbhall88/rasusa/rust-ci.yaml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/rust-ci.yaml:63: update your workflow using https://app.stepsecurity.io/secureworkflow/mbhall88/rasusa/rust-ci.yaml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/rust-ci.yaml:66: update your workflow using https://app.stepsecurity.io/secureworkflow/mbhall88/rasusa/rust-ci.yaml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/rust-ci.yaml:70: update your workflow using https://app.stepsecurity.io/secureworkflow/mbhall88/rasusa/rust-ci.yaml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/rust-ci.yaml:72: update your workflow using https://app.stepsecurity.io/secureworkflow/mbhall88/rasusa/rust-ci.yaml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/rust-ci.yaml:92: update your workflow using https://app.stepsecurity.io/secureworkflow/mbhall88/rasusa/rust-ci.yaml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/rust-ci.yaml:95: update your workflow using https://app.stepsecurity.io/secureworkflow/mbhall88/rasusa/rust-ci.yaml/main?enable=pin","Warn: containerImage not pinned by hash: Dockerfile:1","Warn: containerImage not pinned by hash: Dockerfile:16: pin your Docker image by updating bash:5.1 to bash:5.1@sha256:6ea8de000c2c0213caad31ebb86493bd628cd28b2ffffb961425be2c56d345e2","Info:   0 out of  13 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of  17 third-party GitHubAction dependencies pinned","Info:   0 out of   2 containerImage dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 13 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Vulnerabilities","score":8,"reason":"2 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: RUSTSEC-2024-0421 / GHSA-h97m-ww89-6jmq","Warn: Project is vulnerable to: RUSTSEC-2023-0081"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-21T07:53:38.309Z","repository_id":36174406,"created_at":"2025-08-21T07:53:38.310Z","updated_at":"2025-08-21T07:53:38.310Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29601499,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-19T02:50:40.506Z","status":"ssl_error","status_checked_at":"2026-02-19T02:50:26.316Z","response_time":117,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["alignment","bam","bioinformatics","coverage","downsample","fasta","fastq","genome-analysis","random","rust","subsampling"],"created_at":"2024-10-13T13:14:45.691Z","updated_at":"2026-02-19T03:00:43.888Z","avatar_url":"https://github.com/mbhall88.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"![rasusa](img/logo.png)\n\n[![Build Status](https://github.com/mbhall88/rasusa/actions/workflows/rust-ci.yaml/badge.svg?branch=main)](https://github.com/mbhall88/rasusa/actions/workflows/rust-ci.yaml)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n[![github release version](https://img.shields.io/github/v/release/mbhall88/rasusa)](https://github.com/mbhall88/rasusa/releases)\n[![DOI](https://joss.theoj.org/papers/10.21105/joss.03941/status.svg)](https://doi.org/10.21105/joss.03941)\n\n**Ra**ndomly **su**b**sa**mple sequencing reads or alignments.\n\n\u003e Hall, M. B., (2022). Rasusa: Randomly subsample sequencing reads to a specified coverage. Journal of Open Source\n\u003e Software, 7(69), 3941, https://doi.org/10.21105/joss.03941\n\n[TOC]: #\n\n## Table of Contents\n\n- [Table of Contents](#table-of-contents)\n- [Install](#install)\n- [Usage](#usage)\n- [Benchmark](#benchmark)\n- [Contributing](#contributing)\n- [Citing](#citing)\n\n## Install\n\n![GitHub Downloads (all assets, all releases)](https://img.shields.io/github/downloads/mbhall88/rasusa/total)\n\n### Precompiled binary\n\n```shell\ncurl -sSL rasusa.mbh.sh | sh\n# or with wget\nwget -nv -O - rasusa.mbh.sh | sh\n```\n\nYou can also pass options to the script like so\n\n```\n$ curl -sSL rasusa.mbh.sh | sh -s -- --help\ninstall.sh [option]\n\nFetch and install the latest version of rasusa, if rasusa is already\ninstalled it will be updated to the latest version.\n\nOptions\n        -V, --verbose\n                Enable verbose output for the installer\n\n        -f, -y, --force, --yes\n                Skip the confirmation prompt during installation\n\n        -p, --platform\n                Override the platform identified by the installer [default: apple-darwin]\n\n        -b, --bin-dir\n                Override the bin installation directory [default: /usr/local/bin]\n\n        -a, --arch\n                Override the architecture identified by the installer [default: x86_64]\n\n        -B, --base-url\n                Override the base URL used for downloading releases [default: https://github.com/mbhall88/rasusa/releases]\n\n        -h, --help\n                Display this help message\n```\n\n### `cargo`\n\n[![Crates.io](https://img.shields.io/crates/v/rasusa.svg)](https://crates.io/crates/rasusa)\n![Crates.io Total Downloads](https://img.shields.io/crates/d/rasusa)\n\nPrerequisite: [`rust` toolchain][rust] (min. v1.74.1)\n\n```sh\ncargo install rasusa\n```\n\n### `conda`\n\n[![Conda (channel only)](https://img.shields.io/conda/vn/bioconda/rasusa)](https://anaconda.org/bioconda/rasusa)\n[![bioconda version](https://anaconda.org/bioconda/rasusa/badges/platforms.svg)](https://anaconda.org/bioconda/rasusa)\n![Conda](https://img.shields.io/conda/dn/bioconda/rasusa)\n\nPrerequisite: [`conda`][conda] (and bioconda channel [correctly set up][channels])\n\n```sh\nconda install rasusa\n```\n\n### Container\n\nDocker images are hosted on [GitHub Container Registry][ghcr].\n\n#### `apptainer`\n\nPrerequisite: [`apptainer`][apptainer]\n\n```sh\nURI=\"docker://ghcr.io/mbhall88/rasusa\"\napptainer exec \"$URI\" rasusa --help\n```\n\nThe above will use the latest version. If you want to specify a version then use a\n[tag][ghcr] (or commit) like so.\n\n```sh\nVERSION=\"2.2.2\"\nURI=\"docker://ghcr.io/mbhall88/rasusa:${VERSION}\"\n```\n\n#### `docker`\n\nPrerequisite: [`docker`][docker]\n\n```sh\ndocker pull ghcr.io/mbhall88/rasusa\ndocker run ghcr.io/mbhall88/rasusa --help\n```\n\nYou can find all the available tags on the [container registry][ghcr]. Note: versions\nprior to 0.4.0 were housed on [Docker Hub](https://hub.docker.com/r/mbhall88/rasusa).\nAnd versions from 0.4.0 to 2.2.0 were on [quay.io][quay.io].\n\n### `homebrew`\n\n![Homebrew](https://img.shields.io/homebrew/v/rasusa)\n![Homebrew Downloads](https://img.shields.io/homebrew/installs/dy/rasusa)\n\nPrerequisite: [`homebrew`][homebrew]\n\n```sh\nbrew install rasusa\n```\n\n### Build locally\n\nPrerequisite: [`rust` toolchain][rust]\n\n```sh\ngit clone https://github.com/mbhall88/rasusa.git\ncd rasusa\ncargo build --release\ntarget/release/rasusa --help\n# if you want to check everything is working ok\ncargo test --all\n```\n\n## Usage\n\n### Basic usage - reads\n\nSubsample fastq reads\n\n```\nrasusa reads --coverage 30 --genome-size 4.6mb in.fq\n```\n\nThe above command will output the subsampled file to `stdout`.\n\nOr, if you have paired Illumina\n\n```\nrasusa reads --coverage 30 --genome-size 4g -o out.r1.fq -o out.r2.fq r1.fq r2.fq\n```\n\nFor more details on the above options, and additional options, see below.\n\n### Basic usage - alignments\n\nSubsample alignments\n\n```\nrasusa aln --coverage 30 in.bam | samtools sort -o out.bam\n```\n\nthis will subsample each position in the alignment to 30x coverage.\n\n### Required parameters\n\n`rasusa` has three required options for the `reads` command, and two required options for the `aln` command.\n\n#### Input\n\nThis positional argument specifies the file(s) containing the reads or alignments you would like to subsample. The\nfile(s) must be valid fasta or fastq format for the `reads` command and can be compressed (with a tool such as\n`gzip`). For the `aln` command, the file must be a valid coordinate-sorted SAM/BAM/CRAM file. \nIf two files are passed to `reads`, `rasusa` will assume they are paired-end reads.\n\n\u003e Bash wizard tip 🧙: Let globs do the work for you `r*.fq`\n\n#### Coverage\n\n##### `-c`, `--coverage`\n\n\u003e Not required if [`--bases`](#target-number-of-bases) is present for `reads`\n\nThis option is used to determine the minimum coverage to subsample the reads to. For the `reads` command, it can\nbe specified as an integer (100), a decimal/float (100.7), or either of the previous\nsuffixed with an 'x' (100x). For the `aln` command, it is an integer only.\n\nDue to the method for determining how many bases are required to achieve the\ndesired coverage in the `reads` command, the actual coverage, in the end, could be slightly higher than\nrequested. For example, if the last included read is very long. The log messages should\ninform you of the actual coverage in the end.\n\nFor the `aln` command, the coverage is the maximum number of reads that should be present at each position in the\nalignment. If a position has fewer than the requested number of reads, all reads at that position will be included.\n\n\u003e [!NOTE]\n\u003e **For paired-end data:**\n\u003e To ensure 100% pair retention (i.e., no orphan reads) during subsampling, the `aln` command uses a two-pass strategy.\n\u003e It first subsamples the first segment (Read 1) at half the target coverage (`coverage / 2`) and then recovers\n\u003e the corresponding mates (Read 2).\n\u003e \n\u003e Because this approach is constrained by pairing rather than per-position depth alone, the resulting coverage\n\u003e is not guaranteed to be perfectly uniform across all positions. Instead, some fluctuations around the requested\n\u003e depth should be expected.\n\u003e \n\u003e If the requested coverage is a strict *minimum* requirement, we recommend setting `--coverage` slightly higher to account\n\u003e for these fluctuations.\n\u003e See the discussion in [this PR](https://github.com/mbhall88/rasusa/pull/118) for additional details.\n\n#### Genome size\n\n##### `-g`, `--genome-size`\n\n\u003e Not valid for `aln`\n\n\u003e Not required if [`--bases`](#target-number-of-bases) is present for `reads`\n\nThe genome size of the input is also required. It is used to determine how many bases\nare necessary to achieve the desired coverage. This can, of course, be as precise or\nrough as you like.  \nGenome size can be passed in many ways. As a plain old integer (1600), or with a metric\nsuffix (1.6kb). All metric suffixes can have an optional 'b' suffix and be lower, upper,\nor mixed case. So 'Kb', 'kb' and 'k' would all be inferred as 'kilo'. Valid metric\nsuffixes include:\n\n- Base (b) - multiplies by 1\n- Kilo (k) - multiplies by 1,000\n- Mega (m) - multiplies by 1,000,000\n- Giga (g) - multiplies by 1,000,000,000\n- Tera (t) - multiplies by 1,000,000,000,000\n\nAlternatively, a [FASTA/Q index file][faidx] can be given and the genome size will be\nset to the sum of all reference sequences in it.\n\n\u003e [!TIP]\n\u003e If you want to use `rasusa` in a scenario where you don't know what the genome size is, \n\u003e such as in an automated pipeline that can take in any kind of organism, you could estimate \n\u003e the genome size with something like [`lrge`](https://github.com/mbhall88/lrge) (#shamelessplug).\n\u003e \n\u003e ```\n\u003e $ gsize=$(lrge reads.fq)\n\u003e $ rasusa reads -g $gsize -c 10 reads.fq\n\u003e ```\n\u003e `lrge` is designed for long reads. If you want to estimate the genome size from short \n\u003e reads, you could use something like [Mash](https://github.com/marbl/Mash) or \n\u003e [GenomeScope2](https://github.com/tbenavi1/genomescope2.0). See [the `lrge` docs](https://github.com/mbhall88/lrge?tab=readme-ov-file#alternatives) \n\u003e for examples of how Mash/GenomeScope2 can be used for this task.\n\n[faidx]: https://www.htslib.org/doc/faidx.html\n\n### Optional parameters\n\n#### Output\n\n##### `-o`, `--output`\n\n**`reads`**\n\n\u003e [!IMPORTANT]\n\u003e This parameter is required if passing paired Illumina data to `reads`.\n\nBy default, `rasusa` will output the subsampled file to `stdout` (if one file is given).\nIf you would prefer to specify an output file path, then use this option.\n\nOutput for Illumina paired files must be specified using `--output` twice - `-o out.r1.fq -o out.r2.fq`\n\nThe ordering of the output files is assumed to be the same as the input.  \n\u003e [!NOTE]\n\u003e The output will always be in the same format as the input. You cannot pass FASTQ\n\u003e as input and ask for fasta as output.\n\n`rasusa reads` will also attempt to automatically infer whether compression of the output\nfile(s) is required. It does this by detecting any of the supported extensions:\n\n- `.gz`: will compress the output with [`gzip`][gzip]\n- `.bz` or `.bz2`: will compress the output with [`bzip2`][bzip]\n- `.lzma`: will compress the output with the [`xz`][xz] LZMA algorithm\n\n**`aln`**\n\nFor the `aln` command, the output file format will be the same as the input if writing to stdout, otherwise it will be\ninferred from the file extension. \n\n\u003e [!NOTE]\n\u003e The output alignment will most likely **not be sorted**. You can use `samtools sort` to sort the output. e.g.,\n\u003e \n\u003e ```\n\u003e rasusa aln -c 5 in.bam | samtools sort -o out.bam\n\u003e ```\n\n[gzip]: http://www.gzip.org/\n\n[bzip]: https://sourceware.org/bzip2/\n\n[xz]: https://tukaani.org/xz/\n\n#### Output compression/format\n\n##### `-O`, `--output-type`\n\n**`reads`**\n\nUse this option to manually set the compression algoritm to use for the output file(s).\nIt will override any format automatically detected from the output path.\n\nValid options are:\n\n- `g`: [`gzip`][gzip]\n- `b`: [`bzip2`][bzip]\n- `l` or `x`: [`xz`][xz] LZMA algorithm\n- `z`: [`zstd`][zstd]\n- `u`: no compression\n\n**`aln`**\n\nUse this option to manually set the output file format. By default, the same format as the input will be used, or the\nformat will be guessed from the `--output` path extension if given. Valid options are:\n\n- `b` or `bam`: BAM\n- `c` or `cram`: CRAM\n- `s` or `sam`: SAM\n\nAll values to this option are case insensitive.\n\n#### Compresion level\n\n##### `-l`, `--compress-level`\n\n\u003e `reads` only\n\nCompression level to use if compressing the output. By default this is set to the default for the compression type being\noutput.\n\n#### Target number of bases\n\n##### `-b`, `--bases`\n\n\u003e `reads` only\n\nExplicitly set the number of bases required in the subsample. This option takes the\nnumber in the same format as [genome size](#genome-size).\n\n\u003e [!NOTE]\n\u003e If this option is given, genome size and coverage are not required.\n\n#### Number of reads\n\n##### `-n`, `--num`\n\n\u003e `reads` only\n\nExplicitly set the number of reads in the subsample. This option takes the number in\nthe same format as [genome size](#genome-size).\n\nWhen providing paired reads as input, this option will sample this many total read\npairs. For example, when passing `-n 20 r1.fq r2.fq`, the two output files will have\n20 reads each, and the read ids will be the same in both.\n\n*Note: if this option is given, genome size and coverage are not required.*\n\n#### Fraction of reads\n\n##### `-f`, `--frac`\n\n\u003e `reads` only\n\nExplicitly set the fraction of total reads in the subsample. The value given to this\noption can be a float or a percentage - i.e., `-f 0.5` and `-f 50` will both take half\nof the reads.\n\n\u003e [!NOTE]\n\u003e If this option is given, genome size and coverage are not required.\n\n#### Random seed\n\n##### `-s`, `--seed`\n\nThis option allows you to specify the [random seed][seed] used by the random subsampler. By explicitly setting this \nparameter, you make the subsample for the input reproducible. You only need to pass this parameter if you are likely \nto want to subsample the same input file again in the future and want the same subset of reads. However, if you forget \nto use this option, the seed generated by the system will be printed to the log output, allowing you to use it in the\nfuture.\n\n#### Strictly adhere to requested coverage\n\n##### `-e`, `--strict`\n\n\u003e `reads` only\n\nIf the requested coverage, total bases, number of reads, or fraction of reads cannot be met, an error will be thrown.\nBy default, a warning is displayed, and the maximum possible coverage, total bases, number of reads, or fraction of reads is used.\n\n#### Subsampling strategy\n\n##### `--strategy`\n\n\u003e `aln` only\n\nBy default, `rasusa aln` uses the `stream` strategy, which implements a fast sweep-line algorithm with random priority.\nIt processes a coordinate-sorted alignment file in a single pass (two passes if using paired-end data) while maintaining an active set of reads in a heap,\nensuring that no position exceeds the target depth **N**.\n\n\nThis strategy provides the option `--swap-distance` (default: 5 bp), which limits the allowed distance when swapping\nbetween reads encountered in the current scan and reads already in the heap.\n\nAlternatively, users can select the `fetch` strategy. This approach repeatedly fetches overlapping reads,\nshuffles them, and samples to the target depth **N**.\n\nThe fetch strategy provides additional controls:\n\n- `--batch-size` (default: 10 kb): size of genomic window cached in memory\n- `--step-size` (default: 100 bp): step size used when scanning along the chromosome to find overlapping reads\n\nIn most cases, the default `stream` strategy is recommended due to its speed and low memory usage.\nSee [this PR](https://github.com/mbhall88/rasusa/pull/118) for a discussion of performance and behavior differences between these two strategies.\n\n#### Verbosity\n\n##### `-v`\n\n\u003e `reads` only\n\nAdding this optional flag will make the logging more verbose. By default, logging will\nproduce messages considered \"info\" or above (see [here][log-lvl] for more details). If\nverbosity is switched on, you will additionally get \"debug\" level logging messages.\n\n### Full usage\n\n```text\n$ rasusa --help\nRandomly subsample reads or alignments\n\nUsage: rasusa [OPTIONS] \u003cCOMMAND\u003e\n\nCommands:\n  reads  Randomly subsample reads\n  aln    Randomly subsample alignments to a specified depth of coverage\n  cite   Get a bibtex formatted citation for this package\n  help   Print this message or the help of the given subcommand(s)\n\nOptions:\n  -v             Switch on verbosity\n  -h, --help     Print help\n  -V, --version  Print version\n```\n\n#### `reads` command\n\n```text\n$ rasusa reads --help\nRandomly subsample reads\n\nUsage: rasusa reads [OPTIONS] \u003cFILE(S)\u003e...\n\nArguments:\n  \u003cFILE(S)\u003e...\n          The fast{a,q} file(s) to subsample.\n\n          For paired Illumina, the order matters. i.e., R1 then R2.\n\nOptions:\n  -o, --output \u003cOUTPUT\u003e\n          Output filepath(s); stdout if not present.\n\n          For paired Illumina pass this flag twice `-o o1.fq -o o2.fq`\n\n          NOTE: The order of the pairs is assumed to be the same as the input - e.g., R1 then R2. This option is required for paired input.\n\n  -g, --genome-size \u003csize|faidx\u003e\n          Genome size to calculate coverage with respect to. e.g., 4.3kb, 7Tb, 9000, 4.1MB\n\n          Alternatively, a FASTA/Q index file can be provided and the genome size will be set to the sum of all reference sequences.\n\n          If --bases is not provided, this option and --coverage are required\n\n  -c, --coverage \u003cFLOAT\u003e\n          The desired depth of coverage to subsample the reads to\n\n          If --bases is not provided, this option and --genome-size are required\n\n  -b, --bases \u003cbases\u003e\n          Explicitly set the number of bases required e.g., 4.3kb, 7Tb, 9000, 4.1MB\n\n          If this option is given, --coverage and --genome-size are ignored\n\n  -n, --num \u003cINT\u003e\n          Subsample to a specific number of reads\n\n          If paired-end reads are passed, this is the number of (matched) reads from EACH file. This option accepts the same format as genome size - e.g., 1k will take 1000 reads\n\n  -f, --frac \u003cFLOAT\u003e\n          Subsample to a fraction of the reads - e.g., 0.5 samples half the reads\n\n          Values \u003e1 and \u003c=100 will be automatically converted - e.g., 25 =\u003e 0.25\n\n  -e, --strict\n          Exit with an error if the requested coverage/bases/reads is not possible\n\n  -s, --seed \u003cINT\u003e\n          Random seed to use\n\n  -v\n          Switch on verbosity\n\n  -O, --output-type \u003cu|b|g|l|x|z\u003e\n          u: uncompressed; b: Bzip2; g: Gzip; l: Lzma; x: Xz (Lzma); z: Zstd\n\n          Rasusa will attempt to infer the output compression format automatically from the filename extension. This option is used to override that. If writing to stdout, the default is uncompressed\n\n  -l, --compress-level \u003c1-21\u003e\n          Compression level to use if compressing output. Uses the default level for the format if not specified\n\n  -h, --help\n          Print help (see a summary with '-h')\n\n  -V, --version\n          Print version\n```\n\n#### `aln` command\n\n```text\n$ rasusa aln --help\nRandomly subsample alignments to a specified depth of coverage\n\nUsage: rasusa aln [OPTIONS] --coverage \u003cINT\u003e \u003cFILE\u003e\n\nArguments:\n  \u003cFILE\u003e\n          Path to the input alignment file (SAM/BAM/CRAM) to subsample\n\n          Note: An index (.bai) is required when using '--strategy fetch'.\n\nOptions:\n  -o, --output \u003cFILE\u003e\n          Path to the output subsampled alignment file. Defaults to stdout (same format as input)\n\n          The output is not guaranteed to be sorted. We recommend piping the output to `samtools sort`\n\n  -O, --output-type \u003cFMT\u003e\n          Output format. Rasusa will attempt to infer the format from the output file extension if not provided\n\n  -c, --coverage \u003cINT\u003e\n          The desired depth of coverage to subsample the alignment to\n\n  -s, --seed \u003cINT\u003e\n          Random seed to use\n\n      --strategy \u003cSTRATEGY\u003e\n          Subsampling strategy\n\n          Possible values:\n          - stream: A linear scan approach using sweep line algorithm with random priority. Requires sorted alignment input\n          - fetch:  A fetching approach to randomly subsample reads given read overlap position. Requires indexed input (.bai)\n\n          [default: stream]\n\n      --swap-distance \u003cINT\u003e\n          [Stream] A maximum distance (bp) allowed between start position of new read and the worst read in the heap to consider them to be 'swappable'.\n\n          Larger values allow swapping reads over greater distances, but may cause local undersampling. A value of `0` means only allows swap between reads that have the same start position.\n\n          [default: 5]\n\n      --step-size \u003cINT\u003e\n          [Fetch] When a region has less than the desired coverage, the step size to move along the chromosome to find more reads.\n\n          The lowest of the step and the minimum end coordinate of the reads in the region will be used. This parameter can have a significant impact on the runtime of the subsampling process.\n\n          [default: 100]\n\n      --batch-size \u003cINT\u003e\n          [Fetch] The size of the genomic window (bp) to cache into memory at once.\n\n          Larger values reduce disk seeking, but at the cost of high memory usage. The minimum value is 1,000 bp to avoid small region queries.\n\n          [default: 10000]\n\n  -h, --help\n          Print help (see a summary with '-h')\n\n  -V, --version\n          Print version\n```\n\n## Benchmark\n\n\u003e “Time flies like an arrow; fruit flies like a banana.”  \n\u003e ― Anthony G. Oettinger\n\nThe real question is: will `rasusa` just needlessly eat away at your precious time on\nearth?\n\nTo do this benchmark, I am going to use [hyperfine][hyperfine].\n\nThe data I used comes from\n\n\u003e [Bainomugisa, Arnold, et al. \"A complete high-quality MinION nanopore assembly of an\n\u003e extensively drug-resistant Mycobacterium tuberculosis Beijing lineage strain\n\u003e identifies novel variation in repetitive PE/PPE gene regions.\" Microbial genomics 4.7\n\u003e (2018).][1]\n\n\u003e [!NOTE]\n\u003e These benchmarks are for `reads` only as there is no other tool that replicates the functionality of `aln`.\n\n### Single long read input\n\nDownload and rename the fastq\n\n```shell\nURL=\"ftp://ftp.sra.ebi.ac.uk/vol1/fastq/SRR649/008/SRR6490088/SRR6490088_1.fastq.gz\"\nwget \"$URL\" -O - | gzip -d -c \u003e tb.fq\n```\n\nThe file size is 2.9G, and it has 379,547 reads.  \nWe benchmark against `filtlong` using the same strategy outlined in\n[Motivation](#motivation).\n\n```shell\nTB_GENOME_SIZE=4411532\nCOVG=50\nTARGET_BASES=$(( TB_GENOME_SIZE * COVG ))\nFILTLONG_CMD=\"filtlong --target_bases $TARGET_BASES tb.fq\"\nRASUSA_CMD=\"rasusa reads tb.fq -c $COVG -g $TB_GENOME_SIZE -s 1\"\nhyperfine --warmup 3 --runs 10 --export-markdown results-single.md \\\n     \"$FILTLONG_CMD\" \"$RASUSA_CMD\" \n```\n\n#### Results\n\n| Command                                      |       Mean [s] | Min [s] | Max [s] |     Relative |\n|:---------------------------------------------|---------------:|--------:|--------:|-------------:|\n| `filtlong --target_bases 220576600 tb.fq`    | 21.685 ± 0.055 |  21.622 |  21.787 | 21.77 ± 0.29 |\n| `rasusa reads tb.fq -c 50 -g 4411532 -s 1` | 0.996 ±  0.013 |   0.983 |   1.023 |         1.00 |\n\n**Summary**: `rasusa` ran 21.77 ± 0.29 times faster than `filtlong`.\n\n### Paired-end input\n\nDownload and then deinterleave the fastq with [`pyfastaq`][pyfastaq]\n\n```shell\nURL=\"ftp://ftp.sra.ebi.ac.uk/vol1/fastq/SRR648/008/SRR6488968/SRR6488968.fastq.gz\"\nwget \"$URL\" -O - | gzip -d -c - | fastaq deinterleave - r1.fq r2.fq\n```\n\nEach file's size is 179M and has 283,590 reads.  \nFor this benchmark, we will use [`seqtk`][seqtk]. We will also test `seqtk`'s 2-pass\nmode as this is analogous to `rasusa reads`.\n\n```shell\nNUM_READS=140000\nSEQTK_CMD_1=\"seqtk sample -s 1 r1.fq $NUM_READS \u003e /tmp/r1.fq; seqtk sample -s 1 r2.fq $NUM_READS \u003e /tmp/r2.fq;\"\nSEQTK_CMD_2=\"seqtk sample -2 -s 1 r1.fq $NUM_READS \u003e /tmp/r1.fq; seqtk sample -2 -s 1 r2.fq $NUM_READS \u003e /tmp/r2.fq;\"\nRASUSA_CMD=\"rasusa reads r1.fq r2.fq -n $NUM_READS -s 1 -o /tmp/r1.fq -o /tmp/r2.fq\"\nhyperfine --warmup 10 --runs 100 --export-markdown results-paired.md \\\n     \"$SEQTK_CMD_1\" \"$SEQTK_CMD_2\" \"$RASUSA_CMD\"\n```\n\n#### Results\n\n| Command                                                                                           |     Mean [ms] | Min [ms] | Max [ms] |    Relative |\n|:--------------------------------------------------------------------------------------------------|--------------:|---------:|---------:|------------:|\n| `seqtk sample -s 1 r1.fq 140000 \u003e /tmp/r1.fq; seqtk sample -s 1 r2.fq 140000 \u003e /tmp/r2.fq;`       |  907.7 ± 23.6 |    875.4 |    997.8 | 1.84 ± 0.62 |\n| `seqtk sample -2 -s 1 r1.fq 140000 \u003e /tmp/r1.fq; seqtk sample -2 -s 1 r2.fq 140000 \u003e /tmp/r2.fq;` |  870.8 ± 54.9 |    818.2 |   1219.8 | 1.77 ± 0.61 |\n| `rasusa reads r1.fq r2.fq -n 140000 -s 1 -o /tmp/r1.fq -o /tmp/r2.fq`                           | 492.2 ± 165.4 |    327.4 |    887.4 |        1.00 |\n\n**Summary**: `rasusa reads` ran 1.84 times faster than `seqtk` (1-pass) and 1.77 times faster\nthan `seqtk` (2-pass)\n\nSo, `rasusa reads` is faster than `seqtk` but doesn't require a fixed number of reads -\nallowing you to avoid doing maths to determine how many reads you need to downsample to\na specific coverage. 🤓\n\n## Contributing\n\nIf you would like to help improve `rasusa` you are very welcome!\n\nFor changes to be accepted, they must pass the CI and coverage checks. These include:\n\n- Code is formatted with `rustfmt`. This can be done by running `cargo fmt` in the\n  project directory.\n- There are no compiler errors/warnings. You can check this by running `cargo clippy\n  --all-features --all-targets -- -D warnings`\n- Code coverage has not reduced. If you want to check coverage before pushing changes, I\n  use [`tarpaulin`][tarpaulin].\n\n## Citing\n\nIf you use `rasusa` in your research, it would be appreciated if you could cite it.\n\n[![DOI](https://joss.theoj.org/papers/10.21105/joss.03941/status.svg)](https://doi.org/10.21105/joss.03941)\n\n\u003e Hall, M. B., (2022). Rasusa: Randomly subsample sequencing reads to a specified coverage. Journal of Open Source\n\u003e Software, 7(69), 3941, https://doi.org/10.21105/joss.03941\n\n### Bibtex\n\nYou can get the following citation by running `rasusa cite`\n\n```Bibtex\n@article{Hall2022,\n  doi = {10.21105/joss.03941},\n  url = {https://doi.org/10.21105/joss.03941},\n  year = {2022},\n  publisher = {The Open Journal},\n  volume = {7},\n  number = {69},\n  pages = {3941},\n  author = {Michael B. Hall},\n  title = {Rasusa: Randomly subsample sequencing reads to a specified coverage},\n  journal = {Journal of Open Source Software}\n}\n\n```\n\n[1]: https://doi.org/10.1099/mgen.0.000188\n\n[brew-tap]: https://github.com/brewsci/homebrew-bio\n\n[channels]: https://bioconda.github.io/user/install.html#set-up-channels\n\n[conda]: https://docs.conda.io/projects/conda/en/latest/user-guide/install/\n\n[docker]: https://docs.docker.com/v17.12/install/\n\n[dockerhub]: https://hub.docker.com/r/mbhall88/rasusa\n\n[dpryan79]: https://github.com/dpryan79\n\n[filtlong]: https://github.com/rrwick/Filtlong\n\n[homebrew]: https://docs.brew.sh/Installation\n\n[hyperfine]: https://github.com/sharkdp/hyperfine\n\n[tarpaulin]: https://github.com/xd009642/tarpaulin\n\n[log-lvl]: https://docs.rs/log/0.4.6/log/enum.Level.html#variants\n\n[mgen-ref]: https://doi.org/10.1099/mgen.0.000294\n\n[pr-help]: https://github.com/bioconda/bioconda-recipes/pull/18690\n\n[pyfastaq]: https://github.com/sanger-pathogens/Fastaq\n\n[quay.io]: https://quay.io/repository/mbhall88/rasusa\n\n[rust]: https://www.rust-lang.org/tools/install\n\n[score]: https://github.com/rrwick/Filtlong#read-scoring\n\n[seed]: https://en.wikipedia.org/wiki/Random_seed\n\n[seqtk]: https://github.com/lh3/seqtk\n\n[apptainer]: https://github.com/apptainer/apptainer\n\n[snakemake]: https://snakemake.readthedocs.io/en/stable/\n\n[triples]: https://clang.llvm.org/docs/CrossCompilation.html#target-triple\n\n[wrapper]: https://snakemake-wrappers.readthedocs.io/en/stable/wrappers/rasusa.html\n\n[zstd]: https://github.com/facebook/zstd\n\n[ghcr]: https://github.com/mbhall88/rasusa/pkgs/container/rasusa\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmbhall88%2Frasusa","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmbhall88%2Frasusa","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmbhall88%2Frasusa/lists"}