varvamp 1.2.0__tar.gz → 1.2.2__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 (27) hide show
  1. {varvamp-1.2.0 → varvamp-1.2.2}/PKG-INFO +14 -7
  2. {varvamp-1.2.0 → varvamp-1.2.2}/README.md +3 -5
  3. {varvamp-1.2.0 → varvamp-1.2.2}/varvamp/__init__.py +1 -1
  4. {varvamp-1.2.0 → varvamp-1.2.2}/varvamp/command.py +24 -15
  5. {varvamp-1.2.0 → varvamp-1.2.2}/varvamp/scripts/logging.py +13 -4
  6. {varvamp-1.2.0 → varvamp-1.2.2}/varvamp/scripts/reporting.py +56 -58
  7. {varvamp-1.2.0 → varvamp-1.2.2}/varvamp/scripts/scheme.py +2 -2
  8. {varvamp-1.2.0 → varvamp-1.2.2}/varvamp.egg-info/PKG-INFO +14 -7
  9. {varvamp-1.2.0 → varvamp-1.2.2}/setup.cfg +0 -0
  10. {varvamp-1.2.0 → varvamp-1.2.2}/setup.py +0 -0
  11. {varvamp-1.2.0 → varvamp-1.2.2}/varvamp/__main__.py +0 -0
  12. {varvamp-1.2.0 → varvamp-1.2.2}/varvamp/scripts/__init__.py +0 -0
  13. {varvamp-1.2.0 → varvamp-1.2.2}/varvamp/scripts/alignment.py +0 -0
  14. {varvamp-1.2.0 → varvamp-1.2.2}/varvamp/scripts/blast.py +0 -0
  15. {varvamp-1.2.0 → varvamp-1.2.2}/varvamp/scripts/consensus.py +0 -0
  16. {varvamp-1.2.0 → varvamp-1.2.2}/varvamp/scripts/default_config.py +0 -0
  17. {varvamp-1.2.0 → varvamp-1.2.2}/varvamp/scripts/get_config.py +0 -0
  18. {varvamp-1.2.0 → varvamp-1.2.2}/varvamp/scripts/param_estimation.py +0 -0
  19. {varvamp-1.2.0 → varvamp-1.2.2}/varvamp/scripts/primers.py +0 -0
  20. {varvamp-1.2.0 → varvamp-1.2.2}/varvamp/scripts/qpcr.py +0 -0
  21. {varvamp-1.2.0 → varvamp-1.2.2}/varvamp/scripts/regions.py +0 -0
  22. {varvamp-1.2.0 → varvamp-1.2.2}/varvamp.egg-info/SOURCES.txt +0 -0
  23. {varvamp-1.2.0 → varvamp-1.2.2}/varvamp.egg-info/dependency_links.txt +0 -0
  24. {varvamp-1.2.0 → varvamp-1.2.2}/varvamp.egg-info/entry_points.txt +0 -0
  25. {varvamp-1.2.0 → varvamp-1.2.2}/varvamp.egg-info/not-zip-safe +0 -0
  26. {varvamp-1.2.0 → varvamp-1.2.2}/varvamp.egg-info/requires.txt +0 -0
  27. {varvamp-1.2.0 → varvamp-1.2.2}/varvamp.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.2
2
2
  Name: varvamp
3
- Version: 1.2.0
3
+ Version: 1.2.2
4
4
  Summary: Variable VirusAMPlicons (varVAMP) is a tool to design primers for highly diverse viruses
5
5
  Home-page: https://github.com/jonas-fuchs/varVAMP
6
6
  Author: Dr. Jonas Fuchs
@@ -15,6 +15,15 @@ Requires-Dist: primer3-py>=1.1.0
15
15
  Requires-Dist: pandas>=1.4.4
16
16
  Requires-Dist: numpy>=1.23.3
17
17
  Requires-Dist: seqfold>=0.7.15
18
+ Dynamic: author
19
+ Dynamic: author-email
20
+ Dynamic: classifier
21
+ Dynamic: description
22
+ Dynamic: description-content-type
23
+ Dynamic: home-page
24
+ Dynamic: requires-dist
25
+ Dynamic: requires-python
26
+ Dynamic: summary
18
27
 
19
28
 
20
29
  **var**iable **V**irus**AMP**licons (varVAMP) is a tool to design primers for highly diverse viruses. The input is an alignment of your viral (full-genome) sequences.
@@ -61,15 +70,13 @@ For a lot of virus genera it is difficult to design pan-specific primers. varVAM
61
70
 
62
71
  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).
63
72
 
64
- 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!
73
+ 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.
65
74
 
66
- # Citing varVAMP (coming soon)
67
-
68
- Please cite with the respective DOI of the version you used:
75
+ # Citing varVAMP
69
76
 
70
77
  **varVAMP: automated pan-specific primer design for tiled full genome sequencing and qPCR of highly diverse viral pathogens.**
71
78
 
72
- (paper currently under preparation)
79
+ [biorxiv preprint](https://doi.org/10.1101/2024.05.08.593102)
73
80
 
74
81
  ---
75
82
 
@@ -43,15 +43,13 @@ For a lot of virus genera it is difficult to design pan-specific primers. varVAM
43
43
 
44
44
  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).
45
45
 
46
- 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!
46
+ 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.
47
47
 
48
- # Citing varVAMP (coming soon)
49
-
50
- Please cite with the respective DOI of the version you used:
48
+ # Citing varVAMP
51
49
 
52
50
  **varVAMP: automated pan-specific primer design for tiled full genome sequencing and qPCR of highly diverse viral pathogens.**
53
51
 
54
- (paper currently under preparation)
52
+ [biorxiv preprint](https://doi.org/10.1101/2024.05.08.593102)
55
53
 
56
54
  ---
57
55
 
@@ -1,3 +1,3 @@
1
1
  """Tool to design amplicons for highly variable virusgenomes"""
2
2
  _program = "varvamp"
3
- __version__ = "1.2.0"
3
+ __version__ = "1.2.2"
@@ -89,6 +89,13 @@ def get_args(sysargs):
89
89
  type=int,
90
90
  default=1
91
91
  )
92
+ par.add_argument(
93
+ "--name",
94
+ help="name of the scheme",
95
+ metavar="varVAMP",
96
+ type=str,
97
+ default="varVAMP"
98
+ )
92
99
  for par in (SINGLE_parser, TILED_parser):
93
100
  par.add_argument(
94
101
  "-ol",
@@ -112,7 +119,7 @@ def get_args(sysargs):
112
119
  type=int,
113
120
  metavar="100",
114
121
  default=100,
115
- help="min overlap of the amplicons"
122
+ help="min overlap of the amplicon inserts"
116
123
  )
117
124
  SINGLE_parser.add_argument(
118
125
  "-n",
@@ -261,10 +268,10 @@ def shared_workflow(args, log_file):
261
268
  ambiguous_consensus,
262
269
  alignment_cleaned
263
270
  )
264
- for type, primer_candidates in [("+", left_primer_candidates), ("-", right_primer_candidates)]:
271
+ for primer_type, primer_candidates in [("+", left_primer_candidates), ("-", right_primer_candidates)]:
265
272
  if not primer_candidates:
266
273
  logging.raise_error(
267
- f"no {type} primers found.\n",
274
+ f"no {primer_type} primers found.\n",
268
275
  log_file,
269
276
  exit=True
270
277
  )
@@ -330,7 +337,7 @@ def single_and_tiled_shared_workflow(args, left_primer_candidates, right_primer_
330
337
  return all_primers, amplicons
331
338
 
332
339
 
333
- def single_workflow(args, amplicons, all_primers, log_file):
340
+ def single_workflow(args, amplicons, log_file):
334
341
  """
335
342
  workflow part specific for single mode
336
343
  """
@@ -477,13 +484,13 @@ def qpcr_workflow(args, data_dir, alignment_cleaned, ambiguous_consensus, majori
477
484
  return probe_regions, final_schemes
478
485
 
479
486
 
480
- def main(sysargs=sys.argv[1:]):
487
+ def main():
481
488
  """
482
489
  main varvamp workflow
483
490
  """
484
491
 
485
492
  # start varVAMP
486
- args = get_args(sysargs)
493
+ args = get_args(sys.argv[1:])
487
494
  if not args.verbose:
488
495
  sys.stdout = open(os.devnull, 'w')
489
496
  start_time = datetime.datetime.now()
@@ -496,10 +503,10 @@ def main(sysargs=sys.argv[1:]):
496
503
  alignment_cleaned, majority_consensus, ambiguous_consensus, primer_regions, left_primer_candidates, right_primer_candidates = shared_workflow(args, log_file)
497
504
 
498
505
  # write files that are shared in all modes
499
- reporting.write_regions_to_bed(primer_regions, data_dir)
506
+ reporting.write_regions_to_bed(primer_regions, args.name, data_dir)
500
507
  reporting.write_alignment(data_dir, alignment_cleaned)
501
- reporting.write_fasta(data_dir, "majority_consensus", majority_consensus)
502
- reporting.write_fasta(results_dir, "ambiguous_consensus", ambiguous_consensus)
508
+ reporting.write_fasta(data_dir, f"majority_consensus", f"{args.name}_majority_consensus",majority_consensus)
509
+ reporting.write_fasta(results_dir, f"ambiguous_consensus", f"{args.name}_ambiguous_consensus", ambiguous_consensus)
503
510
 
504
511
  # Functions called from here on return lists of amplicons that are refined step-wise into final schemes.
505
512
  # These lists that are passed between functions and later used for reporting consist of dictionary elemnts,
@@ -526,7 +533,6 @@ def main(sysargs=sys.argv[1:]):
526
533
  amplicon_scheme = single_workflow(
527
534
  args,
528
535
  amplicons,
529
- all_primers,
530
536
  log_file
531
537
  )
532
538
  elif args.mode == "tiled":
@@ -549,11 +555,12 @@ def main(sysargs=sys.argv[1:]):
549
555
  else:
550
556
  # make sure amplicons with no off-target products and with low penalties get the lowest numbers
551
557
  amplicon_scheme.sort(key=lambda x: (x.get("off_targets", False), x["penalty"]))
552
- reporting.write_all_primers(data_dir, all_primers)
558
+ reporting.write_all_primers(data_dir, args.name, all_primers)
553
559
  reporting.write_scheme_to_files(
554
560
  results_dir,
555
561
  amplicon_scheme,
556
562
  ambiguous_consensus,
563
+ args.name,
557
564
  args.mode,
558
565
  log_file
559
566
  )
@@ -561,10 +568,11 @@ def main(sysargs=sys.argv[1:]):
561
568
  results_dir,
562
569
  alignment_cleaned,
563
570
  primer_regions,
571
+ args.name,
564
572
  all_primers=all_primers,
565
573
  amplicon_scheme=amplicon_scheme,
566
574
  )
567
- reporting.per_base_mismatch_plot(results_dir, amplicon_scheme, args.threshold)
575
+ reporting.per_base_mismatch_plot(results_dir, amplicon_scheme, args.threshold, args.name)
568
576
 
569
577
  # QPCR mode
570
578
  if args.mode == "qpcr":
@@ -583,16 +591,17 @@ def main(sysargs=sys.argv[1:]):
583
591
 
584
592
  # make sure amplicons with no off-target products and with low penalties get the lowest numbers
585
593
  final_schemes.sort(key=lambda x: (x.get("off_targets", False), x["penalty"]))
586
- reporting.write_regions_to_bed(probe_regions, data_dir, "probe")
587
- reporting.write_qpcr_to_files(results_dir, final_schemes, ambiguous_consensus, log_file)
594
+ reporting.write_regions_to_bed(probe_regions, args.name, data_dir, "probe")
595
+ reporting.write_qpcr_to_files(results_dir, final_schemes, ambiguous_consensus, args.name, log_file)
588
596
  reporting.varvamp_plot(
589
597
  results_dir,
590
598
  alignment_cleaned,
591
599
  primer_regions,
600
+ args.name,
592
601
  probe_regions=probe_regions,
593
602
  amplicon_scheme=final_schemes
594
603
  )
595
- reporting.per_base_mismatch_plot(results_dir, final_schemes, args.threshold, mode="QPCR")
604
+ reporting.per_base_mismatch_plot(results_dir, final_schemes, args.threshold, args.name, mode="QPCR")
596
605
 
597
606
  # varVAMP finished
598
607
  logging.varvamp_progress(log_file, progress=1, start_time=start_time)
@@ -15,12 +15,12 @@ from varvamp.scripts import config
15
15
  from varvamp import __version__
16
16
 
17
17
 
18
- def create_dir_structure(dir):
18
+ def create_dir_structure(dir_path):
19
19
  """
20
20
  create output folders and log file
21
21
  """
22
22
  cwd = os.getcwd()
23
- results_dir = os.path.join(cwd, dir)
23
+ results_dir = os.path.join(cwd, dir_path)
24
24
  data_dir = os.path.join(results_dir, "data/")
25
25
  # create folders
26
26
  if not os.path.exists(results_dir):
@@ -147,7 +147,7 @@ def raise_arg_errors(args, log_file):
147
147
  log_file,
148
148
  exit=True
149
149
  )
150
- if args.overlap < 50:
150
+ if args.overlap < 10:
151
151
  raise_error(
152
152
  "small overlaps might hinder downstream analyses. Consider increasing.",
153
153
  log_file
@@ -567,7 +567,7 @@ def goodbye_message():
567
567
  "Thank you. Come again.",
568
568
  ">Placeholder for your advertisement<",
569
569
  "Make primers great again!",
570
- "Ciao cacao!"
570
+ "Ciao cacao!",
571
571
  "And now lets pray to the PCR gods.",
572
572
  "**bibobibobop** task finished",
573
573
  "Thank you for traveling with varVAMP.",
@@ -581,5 +581,14 @@ def goodbye_message():
581
581
  "Barba non facit philosophum.",
582
582
  "Task failed successfully.",
583
583
  "Never gonna give you up, never gonna let you down.",
584
+ "Have you tried turning it off and on again?",
585
+ "Look, I am your primer scheme.",
586
+ "Quod erat demonstrandum.",
587
+ "Miau?",
588
+ "This is an automated message informing you that you are awsome.",
589
+ "Why was the negative-sense virus angry at the positive-sense virus?\nBecause he was left stranded!",
590
+ "If you see this message twice, you are an experienced user.",
591
+ "No one expects the spanish inquisition!",
592
+ "Primer design you must."
584
593
  ]
585
594
  print(f"\n{random.choice(messages)}")
@@ -19,11 +19,11 @@ from varvamp.scripts import config
19
19
  from varvamp.scripts import logging
20
20
 
21
21
 
22
- def write_fasta(path, seq_id, seq):
22
+ def write_fasta(path, file_name, seq_id, seq):
23
23
  """
24
24
  write fasta files
25
25
  """
26
- name = f"{seq_id}.fasta"
26
+ name = f"{file_name}.fasta"
27
27
  out = os.path.join(path, name)
28
28
  with open(out, 'w') as o:
29
29
  print(f">{seq_id}\n{seq}", file=o)
@@ -40,7 +40,7 @@ def write_alignment(path, alignment):
40
40
  print(f">{seq[0]}\n{seq[1]}", file=o)
41
41
 
42
42
 
43
- def write_regions_to_bed(primer_regions, path, mode=None):
43
+ def write_regions_to_bed(primer_regions, scheme_name, path, mode=None):
44
44
  """
45
45
  write primer regions as bed file
46
46
  """
@@ -53,7 +53,7 @@ def write_regions_to_bed(primer_regions, path, mode=None):
53
53
  with open(outfile, 'w') as o:
54
54
  for counter, region in enumerate(primer_regions):
55
55
  print(
56
- "ambiguous_consensus",
56
+ f"{scheme_name}_ambiguous_consensus",
57
57
  region[0],
58
58
  region[1],
59
59
  "REGION_"+str(counter),
@@ -62,24 +62,28 @@ def write_regions_to_bed(primer_regions, path, mode=None):
62
62
  )
63
63
 
64
64
 
65
- def write_primers_to_bed(outfile, primer_name, primer_properties, direction):
65
+ def write_primers_to_bed(outfile, scheme_name, primer_name, primer_properties, numeric_value, direction, sequence=None):
66
66
  """
67
67
  write primers as bed file
68
68
  """
69
69
  with open(outfile, 'a') as o:
70
- print(
71
- "ambiguous_consensus",
70
+ # write header for primer bed
71
+ data = [f"{scheme_name}_ambiguous_consensus",
72
72
  primer_properties[1], # start
73
73
  primer_properties[2], # stop
74
74
  primer_name,
75
- round(primer_properties[3], 1), # penalty
76
- direction,
75
+ numeric_value, # can be pool or score
76
+ direction]
77
+ if sequence is not None:
78
+ data.append(sequence)
79
+ print(
80
+ *data,
77
81
  sep="\t",
78
82
  file=o
79
83
  )
80
84
 
81
85
 
82
- def write_all_primers(path, all_primers):
86
+ def write_all_primers(path, scheme_name, all_primers):
83
87
  """
84
88
  write all primers that varVAMP designed as bed file
85
89
  """
@@ -87,7 +91,7 @@ def write_all_primers(path, all_primers):
87
91
 
88
92
  for direction in all_primers:
89
93
  for primer in all_primers[direction]:
90
- write_primers_to_bed(outfile, primer, all_primers[direction][primer], direction)
94
+ write_primers_to_bed(outfile, scheme_name, primer, all_primers[direction][primer], round(all_primers[direction][primer][3], 2), direction)
91
95
 
92
96
 
93
97
  def get_permutations(seq):
@@ -120,7 +124,7 @@ def calc_mean_stats(permutations):
120
124
  return round(gc/len(permutations), 1), round(temp/len(permutations), 1)
121
125
 
122
126
 
123
- def write_qpcr_to_files(path, final_schemes, ambiguous_consensus, log_file):
127
+ def write_qpcr_to_files(path, final_schemes, ambiguous_consensus, scheme_name, log_file):
124
128
  """
125
129
  write all relevant bed files and tsv file for the qPCR design
126
130
  """
@@ -141,10 +145,10 @@ def write_qpcr_to_files(path, final_schemes, ambiguous_consensus, log_file):
141
145
  file=tsv
142
146
  )
143
147
  for n, amp in enumerate(final_schemes):
144
- amp_name = f"QPCR_SCHEME_{n}"
148
+ amp_name = f"{scheme_name}_{n}"
145
149
  # write bed amplicon file
146
150
  print(
147
- "ambiguous_consensus",
151
+ f"{scheme_name}_ambiguous_consensus",
148
152
  amp["LEFT"][1],
149
153
  amp["RIGHT"][2],
150
154
  amp_name,
@@ -188,6 +192,7 @@ def write_qpcr_to_files(path, final_schemes, ambiguous_consensus, log_file):
188
192
 
189
193
  permutations = get_permutations(seq)
190
194
  gc, temp = calc_mean_stats(permutations)
195
+ primer_name = f"{amp_name}_{oligo_type}"
191
196
 
192
197
  print(
193
198
  amp_name,
@@ -208,15 +213,18 @@ def write_qpcr_to_files(path, final_schemes, ambiguous_consensus, log_file):
208
213
  # write primer bed file
209
214
  write_primers_to_bed(
210
215
  primer_bed_file,
211
- f"{amp_name}_{oligo_type}",
216
+ scheme_name,
217
+ primer_name,
212
218
  amp[oligo_type],
213
- direction
219
+ round(amp[oligo_type][3], 2),
220
+ direction,
221
+ seq.upper()
214
222
  )
215
223
  # write fasta
216
- print(f">{amp_name}_{oligo_type}\n{seq.upper()}", file=fasta)
224
+ print(f">{primer_name}\n{seq.upper()}", file=fasta)
217
225
 
218
226
 
219
- def write_scheme_to_files(path, amplicon_scheme, ambiguous_consensus, mode, log_file):
227
+ def write_scheme_to_files(path, amplicon_scheme, ambiguous_consensus, scheme_name, mode, log_file):
220
228
  """
221
229
  write all relevant bed files and a tsv file with all primer stats
222
230
  """
@@ -229,7 +237,7 @@ def write_scheme_to_files(path, amplicon_scheme, ambiguous_consensus, mode, log_
229
237
  with open(tsv_file, "w") as tsv, open(amplicon_bed_file, "w") as bed, open(tabular_file, "w") as tabular:
230
238
  # write header for primer tsv
231
239
  print(
232
- "amlicon_name\tamplicon_length\tprimer_name\talternate_primer_name\tpool\tstart\tstop\tseq\tsize\tgc_best\ttemp_best\tmean_gc\tmean_temp\tpenalty\toff_target_amplicons",
240
+ "amlicon_name\tamplicon_length\tprimer_name\tprimer_name_all_primers\tpool\tstart\tstop\tseq\tsize\tgc_best\ttemp_best\tmean_gc\tmean_temp\tpenalty\toff_target_amplicons",
233
241
  file=tsv
234
242
  )
235
243
  amplicon_bed_records = []
@@ -240,12 +248,12 @@ def write_scheme_to_files(path, amplicon_scheme, ambiguous_consensus, mode, log_
240
248
  if mode == "single":
241
249
  primer_fasta_file = os.path.join(path, "primers.fasta")
242
250
  else:
243
- primer_fasta_file = os.path.join(path, f"primers_pool_{pool}.fasta")
251
+ primer_fasta_file = os.path.join(path, f"primers_pool_{pool+1}.fasta")
244
252
  with open(primer_fasta_file, "w") as primer_fasta:
245
253
  for counter, amp in enumerate(amplicon_scheme[pool::len(pools)]):
246
254
  # give a new amplicon name
247
255
  amplicon_index = counter*len(pools) + pool
248
- new_name = f"AMPLICON_{amplicon_index}"
256
+ amp_name = f"{scheme_name}_{amplicon_index}"
249
257
  # get left and right primers and their names
250
258
  amp_length = amp["RIGHT"][2] - amp["LEFT"][1]
251
259
  if "off_targets" in amp:
@@ -258,14 +266,14 @@ def write_scheme_to_files(path, amplicon_scheme, ambiguous_consensus, mode, log_
258
266
  amplicon_has_off_target = "n.d."
259
267
  # write amplicon bed
260
268
  if mode == "tiled":
261
- bed_score = pool
269
+ bed_score = pool+1
262
270
  elif mode == "single":
263
271
  bed_score = round(amp["LEFT"][3] + amp["RIGHT"][3], 1)
264
272
  amplicon_bed_records.append(
265
273
  (
266
274
  amp["LEFT"][1],
267
275
  amp["RIGHT"][2],
268
- new_name,
276
+ amp_name,
269
277
  bed_score
270
278
  )
271
279
  )
@@ -273,7 +281,7 @@ def write_scheme_to_files(path, amplicon_scheme, ambiguous_consensus, mode, log_
273
281
  (
274
282
  # will need amplicon_index for sorting
275
283
  amplicon_index,
276
- (f"{new_name}_LEFT", f"{new_name}_RIGHT")
284
+ (f"{amp_name}_LEFT", f"{amp_name}_RIGHT")
277
285
  )
278
286
  )
279
287
  # write primer tsv and primer bed
@@ -281,9 +289,9 @@ def write_scheme_to_files(path, amplicon_scheme, ambiguous_consensus, mode, log_
281
289
  seq = ambiguous_consensus[primer[1]:primer[2]]
282
290
  if direction == "-":
283
291
  seq = primers.rev_complement(seq)
284
- primer_name = f"{new_name}_RIGHT"
292
+ primer_name = f"{amp_name}_RIGHT"
285
293
  else:
286
- primer_name = f"{new_name}_LEFT"
294
+ primer_name = f"{amp_name}_LEFT"
287
295
  # write primers to fasta pool file
288
296
  print(f">{primer_name}\n{seq.upper()}", file=primer_fasta)
289
297
  # calc primer parameters for all permutations
@@ -291,11 +299,11 @@ def write_scheme_to_files(path, amplicon_scheme, ambiguous_consensus, mode, log_
291
299
  gc, temp = calc_mean_stats(permutations)
292
300
  # write tsv file
293
301
  print(
294
- new_name,
302
+ amp_name,
295
303
  amp_length,
296
304
  primer_name,
297
305
  primer[-1],
298
- pool,
306
+ pool+1,
299
307
  primer[1] + 1,
300
308
  primer[2],
301
309
  seq.upper(),
@@ -313,13 +321,13 @@ def write_scheme_to_files(path, amplicon_scheme, ambiguous_consensus, mode, log_
313
321
  (
314
322
  # will need amplicon_index for sorting
315
323
  amplicon_index,
316
- (primer_name, primer, direction)
324
+ (primer_name, primer, pool+1, direction, seq.upper())
317
325
  )
318
326
  )
319
327
  # write amplicon bed with amplicons sorted by start position
320
328
  for record in sorted(amplicon_bed_records, key=lambda x: x[0]):
321
329
  print(
322
- "ambiguous_consensus",
330
+ f"{scheme_name}_ambiguous_consensus",
323
331
  *record,
324
332
  ".",
325
333
  sep="\t",
@@ -336,6 +344,7 @@ def write_scheme_to_files(path, amplicon_scheme, ambiguous_consensus, mode, log_
336
344
  for record in sorted(primer_bed_records):
337
345
  write_primers_to_bed(
338
346
  primer_bed_file,
347
+ scheme_name,
339
348
  *record[1]
340
349
  )
341
350
 
@@ -352,7 +361,7 @@ def write_dimers(path, primer_dimers):
352
361
  )
353
362
  for pool, primer1, primer2 in primer_dimers:
354
363
  print(
355
- pool,
364
+ pool+1,
356
365
  primer1[1],
357
366
  primer2[1],
358
367
  round(primers.calc_dimer(primer1[2][0], primer2[2][0]).tm, 1),
@@ -405,7 +414,7 @@ def alignment_entropy(alignment_cleaned):
405
414
  return entropy_df
406
415
 
407
416
 
408
- def entropy_subplot(ax, alignment_cleaned):
417
+ def entropy_subplot(ax, alignment_cleaned, scheme_name):
409
418
  """
410
419
  creates the entropy subplot
411
420
  """
@@ -417,7 +426,7 @@ def entropy_subplot(ax, alignment_cleaned):
417
426
  ax[0].set_ylim((0, 1))
418
427
  ax[0].set_xlim(0, max(entropy_df["position"]))
419
428
  ax[0].set_ylabel("normalized Shannon's entropy")
420
- ax[0].set_title("final amplicon design")
429
+ ax[0].set_title(f"{scheme_name} amplicon design")
421
430
  ax[0].spines['top'].set_visible(False)
422
431
  ax[0].spines['right'].set_visible(False)
423
432
 
@@ -501,7 +510,7 @@ def qpcr_subplot(ax, amplicon_scheme):
501
510
  ax[1].hlines(0.75, probe[1], probe[2], linewidth=5, color="darkgrey", label="probe")
502
511
 
503
512
 
504
- def varvamp_plot(path, alignment_cleaned, primer_regions, all_primers=None, amplicon_scheme=None, probe_regions=None):
513
+ def varvamp_plot(path, alignment_cleaned, primer_regions, scheme_name, all_primers=None, amplicon_scheme=None, probe_regions=None):
505
514
  """
506
515
  creates overview plot for the amplicon design
507
516
  and per base coverage plots
@@ -514,7 +523,7 @@ def varvamp_plot(path, alignment_cleaned, primer_regions, all_primers=None, ampl
514
523
  fig, ax = plt.subplots(2, 1, figsize=[22, 6], squeeze=True, sharex=True, gridspec_kw={'height_ratios': [4, 1]})
515
524
  fig.subplots_adjust(hspace=0)
516
525
  # entropy plot
517
- entropy_subplot(ax, alignment_cleaned)
526
+ entropy_subplot(ax, alignment_cleaned, scheme_name)
518
527
  # primer regions plot
519
528
  region_subplot(ax, primer_regions)
520
529
  # probe region plot for probes
@@ -540,43 +549,32 @@ def varvamp_plot(path, alignment_cleaned, primer_regions, all_primers=None, ampl
540
549
  plt.close()
541
550
 
542
551
 
543
- def get_SINGLE_TILED_primers_for_plot(amplicon_scheme):
552
+ def get_primers_for_plot(amplicon_scheme, scheme_name, mode):
544
553
  """
545
554
  get the primers for per base pair plot (single, tiled)
546
555
  """
547
556
  amplicon_primers = []
548
557
 
549
- for counter, amp in enumerate(amplicon_scheme):
550
- for type in ["LEFT", "RIGHT"]:
551
- primer_name = f"AMPLICON_{counter}_{type}"
552
- amplicon_primers.append((primer_name, amp[type]))
553
-
554
- return amplicon_primers
555
-
556
-
557
- def get_QPCR_primers_for_plot(amplicon_schemes):
558
- """
559
- get the primers for per base pair plot (qpcr)
560
- """
561
- amplicon_primers = []
558
+ if mode == "SINGLE/TILED":
559
+ oligo_types = ["LEFT", "RIGHT"]
560
+ else:
561
+ oligo_types = ["PROBE", "LEFT", "RIGHT"]
562
562
 
563
- for counter, amp in enumerate(amplicon_schemes):
564
- for type in ["PROBE", "LEFT", "RIGHT"]:
565
- primer_name = f"QPCR_SCHEME_{counter}_{type}"
566
- amplicon_primers.append((primer_name, amp[type]))
563
+ for counter, amp in enumerate(amplicon_scheme):
564
+ for oligo_type in oligo_types:
565
+ primer_name = f"{scheme_name}_{counter}_{oligo_type}"
566
+ amplicon_primers.append((primer_name, amp[oligo_type]))
567
567
 
568
568
  return amplicon_primers
569
569
 
570
570
 
571
- def per_base_mismatch_plot(path, amplicon_scheme, threshold, mode="SINGLE/TILED"):
571
+ def per_base_mismatch_plot(path, amplicon_scheme, threshold, scheme_name, mode="SINGLE/TILED"):
572
572
  """
573
573
  per base pair mismatch multiplot
574
574
  """
575
575
  out = os.path.join(path, "per_base_mismatches.pdf")
576
- if mode == "SINGLE/TILED":
577
- amplicon_primers = get_SINGLE_TILED_primers_for_plot(amplicon_scheme)
578
- elif mode == "QPCR":
579
- amplicon_primers = get_QPCR_primers_for_plot(amplicon_scheme)
576
+
577
+ amplicon_primers = get_primers_for_plot(amplicon_scheme, scheme_name, mode)
580
578
  # ini multi pdf
581
579
  with PdfPages(out) as pdf:
582
580
  # always print 4 primers to one page
@@ -102,14 +102,14 @@ def create_amplicon_graph(amplicons, min_overlap):
102
102
 
103
103
  # add the maximum len of a primer to ensure that possible amplicon starts
104
104
  # before the min overlap
105
- min_overlap = min_overlap + config.PRIMER_SIZES[2]
105
+ min_overlap = min_overlap + config.PRIMER_SIZES[1]
106
106
 
107
107
  for current_amplicon in amplicons:
108
108
  # remember all vertices
109
109
  amplicon_id = current_amplicon["id"]
110
110
  nodes.append(amplicon_id)
111
111
  start = current_amplicon["LEFT"][1] + current_amplicon["length"]/2
112
- stop = current_amplicon["RIGHT"][2] - min_overlap
112
+ stop = current_amplicon["RIGHT"][1] - min_overlap
113
113
  for next_amplicon in amplicons:
114
114
  # check if the next amplicon lies within the start/stop range of
115
115
  # the current amplicon and if its non-overlapping part is large
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.2
2
2
  Name: varvamp
3
- Version: 1.2.0
3
+ Version: 1.2.2
4
4
  Summary: Variable VirusAMPlicons (varVAMP) is a tool to design primers for highly diverse viruses
5
5
  Home-page: https://github.com/jonas-fuchs/varVAMP
6
6
  Author: Dr. Jonas Fuchs
@@ -15,6 +15,15 @@ Requires-Dist: primer3-py>=1.1.0
15
15
  Requires-Dist: pandas>=1.4.4
16
16
  Requires-Dist: numpy>=1.23.3
17
17
  Requires-Dist: seqfold>=0.7.15
18
+ Dynamic: author
19
+ Dynamic: author-email
20
+ Dynamic: classifier
21
+ Dynamic: description
22
+ Dynamic: description-content-type
23
+ Dynamic: home-page
24
+ Dynamic: requires-dist
25
+ Dynamic: requires-python
26
+ Dynamic: summary
18
27
 
19
28
 
20
29
  **var**iable **V**irus**AMP**licons (varVAMP) is a tool to design primers for highly diverse viruses. The input is an alignment of your viral (full-genome) sequences.
@@ -61,15 +70,13 @@ For a lot of virus genera it is difficult to design pan-specific primers. varVAM
61
70
 
62
71
  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).
63
72
 
64
- 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!
73
+ 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.
65
74
 
66
- # Citing varVAMP (coming soon)
67
-
68
- Please cite with the respective DOI of the version you used:
75
+ # Citing varVAMP
69
76
 
70
77
  **varVAMP: automated pan-specific primer design for tiled full genome sequencing and qPCR of highly diverse viral pathogens.**
71
78
 
72
- (paper currently under preparation)
79
+ [biorxiv preprint](https://doi.org/10.1101/2024.05.08.593102)
73
80
 
74
81
  ---
75
82
 
File without changes
File without changes
File without changes
File without changes