Source code for bandwitch.DigestionProblem.IdealDigestionsProblem
from .DigestionProblem import DigestionProblem
import numpy as np
[docs]class IdealDigestionsProblem(DigestionProblem):
"""Find ideal digestion(s) to validate constructs.
Other digestion problems subclass this problem and implement a computation
of coverages which depends on the problem.
Parameters
----------
sequences
An (ordered) dictionary of the form {sequence_name: sequence} where the
sequence is an ATGC string
enzymes
List of the names of the enzymes to consider, e.g. ``['EcoRI', 'XbaI']``.
ladder
A Ladder object representing the ladder used for migrations.
linear
True for linear sequences, false for circular sequences
max_enzymes_per_digestion
Maximal number of enzymes that can go in a single digestion.
Experimentally the best is 1, but you can try 2, or 3 in desperate
situations. Not sure if more enzymes will work.
relative_migration_error
Variance of the bands measured during the migration, given as a
proportion of the total migration span (difference between the migration
of the ladder's smallest and largest bands).
"""
def __init__(
self,
enzymes,
ladder,
sequences,
min_bands=3,
max_bands=7,
border_tolerance=0.1,
topology="default_to_linear",
max_enzymes_per_digestion=1,
relative_migration_precision=0.1,
):
"""Initialize."""
self.min_bands = min_bands
self.max_bands = max_bands
self.border_tolerance = border_tolerance
DigestionProblem.__init__(
self,
sequences=sequences,
enzymes=enzymes,
ladder=ladder,
topology=topology,
max_enzymes_per_digestion=max_enzymes_per_digestion,
relative_migration_precision=relative_migration_precision,
)
def _parameter_element_score(self, digestion, sequence):
"""Compute the sequence's ``.migration_score`` for each digestion."""
digestion = self.sequences_digestions[sequence][digestion]
if digestion["same_as"] in self.scores[sequence]:
return self.scores[sequence][digestion["same_as"]]
migration = digestion["migration"]
return self.migration_score(migration)
[docs] def migration_score(self, band_migrations):
"""Score the well-numbering and well-separation of all bands.
If some bands are too high or too low, or the number of bands is out
of bounds, return 0. Else, return the minimal distance between two
consecutive bands.
"""
if not self.min_bands <= len(band_migrations) <= self.max_bands:
return 0
t = self.border_tolerance
mini, maxi = (1 + t) * self.migration_min, (1 - t) * self.migration_max
if not (mini <= min(band_migrations) <= max(band_migrations) < maxi):
return 0
min_gap = np.diff(sorted(band_migrations)).min()
return 1.0 * min_gap / self.migration_span
def _compute_elements(self):
"""Return the list of digestions to serve as elements."""
return set(self.sequences.keys())