def test_gfp(gfp, iter_random_primer): fwd_primers = list(iter_random_primer(25, gfp[:250], 16)) rev_primers = list(iter_random_primer(25, rc(gfp)[:250], 16)) primers = fwd_primers + rev_primers # from itertools import product # # for f, r in product(fwd_primers, rev_primers): # design = Design() # design.settings.left_sequence(f) # design.settings.right_sequence(r) # design.settings.task('check_primers') # design.settings.template(gfp) # design.run() region_ok = check_primers(gfp, primers) # print(region_ok[:1]) design = Design() design.settings.template(gfp) print(region_ok) design.settings.pair_region_list(region_ok[:10]) design.settings.product_size([50, 2000]) pairs, explain = design.run() print(explain) print(pairs)
def test_primer_design_overorigin(self): """Tests whether primers can be designed over an origin of a cyclic sequence.""" fixtures = join(abspath(dirname(__file__)), "fixtures") with open(join(fixtures, "template.txt")) as f: template = f.read().strip() region = Region(2020, 1616, len(template), cyclic=True) adjusted_template = region.get_slice(template) + region.invert()[0].get_slice( template ) rprimer = "CGCTGGAGAAAACCTTCGTATCGGCgcatgcacgcgtgtcgacatcg" assert ( rc("CGCTGGAGAAAACCTTCGTATCGGCgcatgcacgcgtgtcgacatcg".upper()) in adjusted_template.upper() ) fwd, rev = anneal(adjusted_template, [rprimer]) print(rev[0]["top_strand_slice"]) rprimer = "CGCTGGAGAAAACCTTCGTATCGGCgcatgcacgcgtgtcgacatcg" pairs, explain = _design_primers(template, region, None, rseq=rprimer) print(json.dumps(pairs, indent=1)) print(explain) assert pairs
def test_right_overhang_default_behavior(self, gfp): """Without setting overhangs, should raise run time error.""" design = Design() design.settings.template(gfp) rseq = "AAAAAA" + rc(gfp[200:220]) design.settings.right_sequence(rseq) with pytest.raises(Primer3PlusRunTimeError): design.run()
def test_right_overhang(self, gfp): design = Design() design.settings.template(gfp) rseq = "AGGCGGCTGA" + rc(gfp[200:225]) design.settings.right_sequence(rseq) design.settings.use_overhangs() pairs, explain = design.run_and_optimize(5) assert pairs
def test_long_right_primer_default_behavior(self, gfp): design = Design() design.settings.template(gfp) design.settings.right_sequence(rc(gfp[-50:])) design.PRIMER_MAX_TM.value = 75.0 design.PRIMER_MAX_SIZE = 35 design.PRIMER_PICK_ANYWAY = 1 with pytest.raises(Primer3PlusRunTimeError): design.run_and_optimize(10)
def test_both_overhangs(self, gfp): design = Design() design.settings.template(gfp) lseq = "TTTTTT" + gfp[10:30] rseq = rc(gfp[200:220] + "AAAAAAA") design.settings.left_sequence(lseq) design.settings.right_sequence(rseq) design.settings.use_overhangs() pairs, explain = design.run_and_optimize(5) assert pairs
def test_long_right_primer(self, gfp): design = Design() design.settings.template(gfp) design.settings.right_sequence(rc(gfp[-50:])) design.PRIMER_MAX_TM.value = 75.0 design.PRIMER_MAX_SIZE = 35 design.PRIMER_PICK_ANYWAY = 1 design.settings.long_ok() pairs, explain = design.run_and_optimize(10) print(explain) assert pairs
def thermo(self): settings = self._thermo_settings if self._thermo is None: if len(self.sequence) > 60: warning = "sequence length greater than 60. Thermo results are limited to 60bp." else: warning = "" self._thermo = { "hairpin": primer3.calcHairpin(self._safe_sequence, **settings), "homodimer": primer3.calcHomodimer(self._safe_sequence, **settings), "annealing": primer3.calcHeterodimer(self.anneal, rc(self.anneal), **settings), "sequence": primer3.calcHeterodimer(self._safe_sequence, rc(self._safe_sequence), **settings), "warning": warning, } return self._thermo
def test_long_right_primer_with_overhangs(self, gfp): """We expect no errors with setting long right primers. The settings should automatically readjust the product length to match and the 'SEQUENCE', 'OVERHANG', and 'location' and 'PRODUCT_SIZE' results should automatically be adjusted. """ design = Design() design.settings.template(gfp) design.settings.right_sequence(rc(gfp[-50:])) design.settings.product_size((len(gfp), len(gfp))) loverhang = "TTTTTTT" roverhang = "GGGAGAG" design.settings.left_overhang(loverhang) design.settings.right_overhang(roverhang) design.settings.long_ok() design.settings.use_overhangs() design.settings.pick_anyway() pairs, explain = design.run() pprint(pairs) assert pairs for pair in pairs.values(): assert pair["PAIR"]["PRODUCT_SIZE"] == len(gfp) assert pair["RIGHT"]["OVERHANG"] == roverhang assert pair["LEFT"]["OVERHANG"] == loverhang assert pair["RIGHT"]["SEQUENCE"] == rc(gfp[-50:]) lloc = pair["LEFT"]["location"] rloc = pair["RIGHT"]["location"] assert lloc[0] == 0 assert rloc[0] == len(gfp) - 1 assert rloc[1] == 50 assert pairs
def test_set_long_right_primers_with_included_and_size(self, gfp): design = Design() design.settings.template(gfp) right = rc(gfp[-100:-20]) design.settings.right_sequence(right) design.settings.included((len(gfp) - 50 - 300, 300)) design.settings.product_size((250, 250)) design.settings.long_ok() design.settings.use_overhangs() design.settings.pick_anyway() pairs, explain = design.run_and_optimize(15) print(pairs) assert pairs
def _design_primers( template: str, region: Region, lseq: Union[None, str], rseq: Union[None, str], left_overhang: Union[None, str] = None, right_overhang: Union[None, str] = None, ) -> Tuple[Dict[int, dict], Dict[str, Any]]: """Design primers flanking the specified. :class:`Region.<dasi.utils.Region>`. If the region is cyclic and spans the origin, this method will handle the appropriate manipulations to design primers around the origin and restore the locations of the resulting primer pairs. :param template: the template string to design primers :param region: region specified to design primers around. Regions are exclusive at their end points (`.b` parameter) :param lseq: optionally provided left sequence :param rseq: optionally provided right sequence :param left_overhang: optionally provided left overhang sequence of the primer :param right_overhang: optionally provided right overhang sequence of the primer :return: tuple of pairs and the 'explain' dictionary. """ design = primer3plus.new() design.logger = logger(design) design.settings.as_cloning_task() if region.direction == -1: region = region.flip() template = rc(template) if lseq and left_overhang: raise DasiSequenceDesignException if rseq and right_overhang: raise DasiSequenceDesignException if region.spans_origin(): adjusted_template = region.get_slice( template) + region.invert()[0].get_slice(template) design.settings.template(adjusted_template) design.settings.included((0, len(region))) index = list(region) + list(region.invert()[0]) else: design.settings.template(template) design.settings.included((region.a, len(region))) index = None if lseq: design.settings.left_sequence(lseq) if rseq: design.settings.right_sequence(rseq) if left_overhang is None: left_overhang = "" if right_overhang is None: right_overhang = "" design.settings.product_size((len(region), len(region))) design.settings.left_overhang(left_overhang) design.settings.right_overhang(right_overhang) design.PRIMER_PICK_ANYWAY = False design.PRIMER_MIN_ANNEAL_CHECK = Config.PRIMER3_MIN_ANNEAL_CHECK design.settings.use_overhangs() design.settings.long_ok() design.logger.set_level("INFO") # TODO: remove debugging code try: pairs, explain = design.run_and_optimize(Config.PRIMER3_N_RUNS, pick_anyway=True) except Exception as e: import json print(json.dumps(dict(design.params.items()), indent=2)) raise e if index is not None: for pair in pairs.values(): loc = pair["LEFT"]["location"] pair["LEFT"]["location"] = (index[loc[0]], loc[1]) loc = pair["RIGHT"]["location"] pair["RIGHT"]["location"] = (index[loc[0]], loc[1]) return pairs, explain