Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Changed bed file structure to ARTICv3 #42

Merged
merged 11 commits into from
Sep 6, 2024
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