Skip to content

Commit

Permalink
Changed bed file structure to ARTICv3 (#42)
Browse files Browse the repository at this point in the history
* changed requirements txt to inhibit incomp

* added --name option and now bed primer files are reported in ARTIC v3 style

* updated docs

* changed pool indexing to +1

* comma fix

* small changes in main

* changed type var shadowing

* removed not needed variable

* further code cleanup

* small fixes in goodbye message

* fixed BLAST reporting error due to not defined variable
  • Loading branch information
jonas-fuchs authored Sep 6, 2024
1 parent 0c9cf54 commit ac4b1ed
Show file tree
Hide file tree
Showing 8 changed files with 106 additions and 84 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ For a lot of virus genera it is difficult to design pan-specific primers. varVAM

We, in collaboration with specialists for the respective viruses, have already designed and wet-lab evaluated primer schemes for various viral pathogens. All the input data and varVAMP outputs are freely available [here](https://github.com/jonas-fuchs/ViralPrimerSchemes).

If you design primers for a particular pathogen, we will be happy to include them in this repo and make it freely available. Just contribute via an issue or pull request!
Moreover, varVAMP primers are now available at [primerschemes](https://labs.primalscheme.com/). varVAMP now reports primer bed files in ARTICv3 format. Feel free to contribute newly designed schemes via this [Github repository of the QuickLab](https://github.com/quick-lab/primerschemes). Use [primal-page](https://github.com/ChrisgKent/primal-page) developed by [Chris Kent](https://github.com/ChrisgKent) to generate data for compatible pull-requests.

# Citing varVAMP

Expand Down
3 changes: 2 additions & 1 deletion docs/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ pip install setuptools varvamp
### CONDA:

```shell
conda install -c bioconda varvamp
conda create -n varvamp varvamp
conda activate varvamp
```

### DOCKER:
Expand Down
3 changes: 3 additions & 0 deletions docs/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ optional arguments:
-a , --n-ambig max number of ambiguous characters in a primer
-db None, --database None location of the BLAST db
-th 1, --threads 1 number of threads
--name varVAMP name of the scheme
-ol 1000, --opt-length 1000 optimal length of the amplicons
-ml 1500, --max-length 1500 max length of the amplicons
-n inf, --report-n inf report the top n best hits
Expand All @@ -58,6 +59,7 @@ optional arguments:
-a , --n-ambig max number of ambiguous characters in a primer
-db None, --database None location of the BLAST db
-th 1, --threads 1 number of threads
--name varVAMP name of the scheme
-ol 1000, --opt-length 1000 optimal length of the amplicons
-ml 1500, --max-length 1500 max length of the amplicons
-o 100, --overlap 100 min overlap of the amplicons
Expand All @@ -73,6 +75,7 @@ optional arguments:
-a , --n-ambig max number of ambiguous characters in a primer
-db None, --database None location of the BLAST db
-th 1, --threads 1 number of threads
--name varVAMP name of the scheme
-pa , --pn-ambig max number of ambiguous characters in a probe
-n 50, --test-n 50 test the top n qPCR amplicons for secondary structures at the minimal primer temperature
-d -3, --deltaG -3 minimum free energy (kcal/mol/K) cutoff at the lowest primer melting temp
Expand Down
12 changes: 6 additions & 6 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
biopython>=1.79
matplotlib>=3.5.1
primer3-py>=1.1.0
pandas>=1.4.4
numpy>=1.23.3
seqfold>=0.7.15
biopython~=1.79
matplotlib~=3.5.1
primer3-py~=1.1.0
pandas~=1.4.4
numpy~=1.23.3
seqfold~=0.7.15
2 changes: 1 addition & 1 deletion varvamp/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
"""Tool to design amplicons for highly variable virusgenomes"""
_program = "varvamp"
__version__ = "1.2.0"
__version__ = "1.2.1"
37 changes: 23 additions & 14 deletions varvamp/command.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,13 @@ def get_args(sysargs):
type=int,
default=1
)
par.add_argument(
"--name",
help="name of the scheme",
metavar="varVAMP",
type=str,
default="varVAMP"
)
for par in (SINGLE_parser, TILED_parser):
par.add_argument(
"-ol",
Expand Down Expand Up @@ -261,10 +268,10 @@ def shared_workflow(args, log_file):
ambiguous_consensus,
alignment_cleaned
)
for type, primer_candidates in [("+", left_primer_candidates), ("-", right_primer_candidates)]:
for primer_type, primer_candidates in [("+", left_primer_candidates), ("-", right_primer_candidates)]:
if not primer_candidates:
logging.raise_error(
f"no {type} primers found.\n",
f"no {primer_type} primers found.\n",
log_file,
exit=True
)
Expand Down Expand Up @@ -330,7 +337,7 @@ def single_and_tiled_shared_workflow(args, left_primer_candidates, right_primer_
return all_primers, amplicons


def single_workflow(args, amplicons, all_primers, log_file):
def single_workflow(args, amplicons, log_file):
"""
workflow part specific for single mode
"""
Expand Down Expand Up @@ -477,13 +484,13 @@ def qpcr_workflow(args, data_dir, alignment_cleaned, ambiguous_consensus, majori
return probe_regions, final_schemes


def main(sysargs=sys.argv[1:]):
def main():
"""
main varvamp workflow
"""

# start varVAMP
args = get_args(sysargs)
args = get_args(sys.argv[1:])
if not args.verbose:
sys.stdout = open(os.devnull, 'w')
start_time = datetime.datetime.now()
Expand All @@ -496,10 +503,10 @@ def main(sysargs=sys.argv[1:]):
alignment_cleaned, majority_consensus, ambiguous_consensus, primer_regions, left_primer_candidates, right_primer_candidates = shared_workflow(args, log_file)

# write files that are shared in all modes
reporting.write_regions_to_bed(primer_regions, data_dir)
reporting.write_regions_to_bed(primer_regions, args.name, data_dir)
reporting.write_alignment(data_dir, alignment_cleaned)
reporting.write_fasta(data_dir, "majority_consensus", majority_consensus)
reporting.write_fasta(results_dir, "ambiguous_consensus", ambiguous_consensus)
reporting.write_fasta(data_dir, f"majority_consensus", f"{args.name}_consensus",majority_consensus)
reporting.write_fasta(results_dir, f"ambiguous_consensus", f"{args.name}_consensus", ambiguous_consensus)

# Functions called from here on return lists of amplicons that are refined step-wise into final schemes.
# These lists that are passed between functions and later used for reporting consist of dictionary elemnts,
Expand All @@ -526,7 +533,6 @@ def main(sysargs=sys.argv[1:]):
amplicon_scheme = single_workflow(
args,
amplicons,
all_primers,
log_file
)
elif args.mode == "tiled":
Expand All @@ -549,22 +555,24 @@ def main(sysargs=sys.argv[1:]):
else:
# make sure amplicons with no off-target products and with low penalties get the lowest numbers
amplicon_scheme.sort(key=lambda x: (x.get("off_targets", False), x["penalty"]))
reporting.write_all_primers(data_dir, all_primers)
reporting.write_all_primers(data_dir, args.name, all_primers)
reporting.write_scheme_to_files(
results_dir,
amplicon_scheme,
ambiguous_consensus,
args.name,
args.mode,
log_file
)
reporting.varvamp_plot(
results_dir,
alignment_cleaned,
primer_regions,
args.name,
all_primers=all_primers,
amplicon_scheme=amplicon_scheme,
)
reporting.per_base_mismatch_plot(results_dir, amplicon_scheme, args.threshold)
reporting.per_base_mismatch_plot(results_dir, amplicon_scheme, args.threshold, args.name)

# QPCR mode
if args.mode == "qpcr":
Expand All @@ -583,16 +591,17 @@ def main(sysargs=sys.argv[1:]):

# make sure amplicons with no off-target products and with low penalties get the lowest numbers
final_schemes.sort(key=lambda x: (x.get("off_targets", False), x["penalty"]))
reporting.write_regions_to_bed(probe_regions, data_dir, "probe")
reporting.write_qpcr_to_files(results_dir, final_schemes, ambiguous_consensus, log_file)
reporting.write_regions_to_bed(probe_regions, args.name, data_dir, "probe")
reporting.write_qpcr_to_files(results_dir, final_schemes, ambiguous_consensus, args.name, log_file)
reporting.varvamp_plot(
results_dir,
alignment_cleaned,
primer_regions,
args.name,
probe_regions=probe_regions,
amplicon_scheme=final_schemes
)
reporting.per_base_mismatch_plot(results_dir, final_schemes, args.threshold, mode="QPCR")
reporting.per_base_mismatch_plot(results_dir, final_schemes, args.threshold, args.name, mode="QPCR")

# varVAMP finished
logging.varvamp_progress(log_file, progress=1, start_time=start_time)
Expand Down
15 changes: 12 additions & 3 deletions varvamp/scripts/logging.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@
from varvamp import __version__


def create_dir_structure(dir):
def create_dir_structure(dir_path):
"""
create output folders and log file
"""
cwd = os.getcwd()
results_dir = os.path.join(cwd, dir)
results_dir = os.path.join(cwd, dir_path)
data_dir = os.path.join(results_dir, "data/")
# create folders
if not os.path.exists(results_dir):
Expand Down Expand Up @@ -567,7 +567,7 @@ def goodbye_message():
"Thank you. Come again.",
">Placeholder for your advertisement<",
"Make primers great again!",
"Ciao cacao!"
"Ciao cacao!",
"And now lets pray to the PCR gods.",
"**bibobibobop** task finished",
"Thank you for traveling with varVAMP.",
Expand All @@ -581,5 +581,14 @@ def goodbye_message():
"Barba non facit philosophum.",
"Task failed successfully.",
"Never gonna give you up, never gonna let you down.",
"Have you tried turning it off and on again?",
"Look, I am your primer scheme.",
"Quod erat demonstrandum.",
"Miau?",
"This is an automated message informing you that you are awsome.",
"Why was the negative-sense virus angry at the positive-sense virus?\nBecause he was left stranded!",
"If you see this message twice, you are an experienced user.",
"No one expects the spanish inquisition!",
"Primer design you must."
]
print(f"\n{random.choice(messages)}")
Loading

0 comments on commit ac4b1ed

Please sign in to comment.