Source code for dnachisel.builtin_specifications.AvoidPattern

"""Implement AvoidPattern"""

from ..SequencePattern import SequencePattern
from ..Location import Location
from ..Specification.Specification import Specification
from ..Specification.SpecEvaluation import SpecEvaluation


[docs]class AvoidPattern(Specification): """Enforce that the given pattern is absent in the sequence. Shorthand for annotations: "no". Parameters ---------- pattern A SequencePattern or DnaNotationPattern location Location of the DNA segment on which to enforce the pattern e.g. ``Location(10, 45, 1)``. For patterns which are not palindromic, the strand matters! Use +1 for eliminating the pattern on the +1 strand only, -1 for eliminating the pattern on the -1 strand, and 0 for eliminating the pattern on both strands. Default ``None`` enforces on the whole sequence. strand Alternative way to set the strand, meant to be used in two cases only: (1) in a Genbank annotation by setting ``strand=both`` to indicate that the pattern should be avoided on both strands (otherwise, only the feature's strand will be considered). (2) if you want to create a specification without preset location, but with a set strand: ``AvoidPattern('BsmBI_site', strand=1)``. The default 'from_location' uses the strand specified in ``location``, or if that is ``None``, it sets both strands. """ best_possible_score = 0 priority = 1 shorthand_name = "no" # will appear as, for instance, @no(BsmBI_site) def __init__(self, pattern=None, location=None, strand="from_location", boost=1.0): """Initialize.""" if isinstance(pattern, str): pattern = SequencePattern.from_string(pattern) self.pattern = pattern self.location = Location.from_data(location) if strand == "from_location": if self.location is None: self.strand = 0 else: self.strand = self.location.strand elif strand == "both": self.strand = 0 elif strand in [-1, 0, 1]: self.strand = strand else: raise ValueError("unknown strand: %s" % strand) self.boost = boost def evaluate(self, problem): """Return score=-number_of_occurences. And patterns locations.""" locations = self.pattern.find_matches(problem.sequence, self.location) score = -len(locations) if score == 0: message = "Passed. Pattern not found !" else: message = "Failed. Pattern found at positions %s" % locations return SpecEvaluation( self, problem, score, locations=locations, message=message ) def short_label(self): if self.pattern.name is not None: return "No %s" % self.pattern.name else: return "No %s" % self.pattern def breach_label(self): if self.pattern.name is not None: return str(self.pattern.name) else: return str(self.pattern) def initialized_on_problem(self, problem, role="constraint"): copy_of_constraint = self._copy_with_full_span_if_no_location(problem) copy_of_constraint.location.strand = self.strand return copy_of_constraint def localized(self, location, problem=None, with_righthand=True): """Localize the pattern to the given location. Taking into account the specification's own location, and the size of the pattern.""" if self.location.overlap_region(location) is None: return None if self.pattern.size is None: return self extended_location = location.extended( self.pattern.size - 1, right=with_righthand ) new_location = self.location.overlap_region(extended_location) return self.copy_with_changes(location=new_location) def label_parameters(self): return [("pattern", str(self.pattern))]