mirror of
https://github.com/biopython/biopython.git
synced 2025-10-20 21:53:47 +08:00
631 lines
25 KiB
Python
631 lines
25 KiB
Python
# This code is part of the Biopython distribution and governed by its
|
|
# license. Please see the LICENSE file that should have been included
|
|
# as part of this package.
|
|
#
|
|
|
|
"""Testing code for Restriction enzyme classes of Biopython."""
|
|
|
|
import unittest
|
|
|
|
from Bio import BiopythonWarning
|
|
from Bio.Restriction import AanI
|
|
from Bio.Restriction import Acc65I
|
|
from Bio.Restriction import AllEnzymes
|
|
from Bio.Restriction import Analysis
|
|
from Bio.Restriction import Asp718I
|
|
from Bio.Restriction import BamHI
|
|
from Bio.Restriction import BsmBI
|
|
from Bio.Restriction import CommOnly
|
|
from Bio.Restriction import EarI
|
|
from Bio.Restriction import EcoRI
|
|
from Bio.Restriction import EcoRV
|
|
from Bio.Restriction import FormattedSeq
|
|
from Bio.Restriction import KpnI
|
|
from Bio.Restriction import McrI
|
|
from Bio.Restriction import MluCI
|
|
from Bio.Restriction import NdeI
|
|
from Bio.Restriction import NonComm
|
|
from Bio.Restriction import Restriction
|
|
from Bio.Restriction import RestrictionBatch
|
|
from Bio.Restriction import SmaI
|
|
from Bio.Restriction import SnaI
|
|
from Bio.Restriction import SphI
|
|
from Bio.Restriction import BsaI
|
|
from Bio.Restriction import BsaXI
|
|
from Bio.Restriction import BspCNI
|
|
from Bio.Seq import MutableSeq
|
|
from Bio.Seq import Seq
|
|
|
|
|
|
class SequenceTesting(unittest.TestCase):
|
|
"""Tests for dealing with input."""
|
|
|
|
def test_sequence_object(self):
|
|
"""Test if sequence must be a Seq or MutableSeq object."""
|
|
with self.assertRaises(TypeError):
|
|
seq = FormattedSeq("GATC")
|
|
seq = FormattedSeq(Seq("TAGC"))
|
|
seq = FormattedSeq(MutableSeq("AGTC"))
|
|
seq = FormattedSeq(seq)
|
|
with self.assertRaises(TypeError):
|
|
EcoRI.search("GATC")
|
|
EcoRI.search(Seq("ATGC"))
|
|
EcoRI.search(MutableSeq("TCAG"))
|
|
|
|
def test_non_allowed_characters(self):
|
|
"""Test if non-allowed characters raise a TypeError."""
|
|
# Any letter is accepted, even if it's not a nucleotide
|
|
FormattedSeq(Seq("ABCDEFGHIJKLMNOPQRSTUVWXYZ"))
|
|
# Other characters are not accepted
|
|
with self.assertRaises(TypeError):
|
|
FormattedSeq(Seq("GATCZE-"))
|
|
|
|
def test_formatted_seq(self):
|
|
"""Test several methods of FormattedSeq."""
|
|
self.assertEqual(
|
|
str(FormattedSeq(Seq("GATC"))), "FormattedSeq(Seq('GATC'), linear=True)"
|
|
)
|
|
self.assertNotEqual(FormattedSeq(Seq("GATC")), FormattedSeq(Seq("TAGC")))
|
|
self.assertNotEqual(FormattedSeq(Seq("TAGC")), Seq("TAGC"))
|
|
self.assertEqual(FormattedSeq(Seq("ATGC")), FormattedSeq(Seq("ATGC")))
|
|
linear_seq = FormattedSeq(Seq("T"))
|
|
self.assertTrue(linear_seq.is_linear())
|
|
linear_seq.circularise()
|
|
self.assertFalse(linear_seq.is_linear())
|
|
linear_seq.linearise()
|
|
circular_seq = linear_seq.to_circular()
|
|
self.assertFalse(circular_seq.is_linear())
|
|
linear_seq = circular_seq.to_linear()
|
|
self.assertTrue(linear_seq.is_linear())
|
|
|
|
|
|
class SimpleEnzyme(unittest.TestCase):
|
|
"""Tests for dealing with basic enzymes using the Restriction package."""
|
|
|
|
def test_init(self):
|
|
"""Check for error during __init__."""
|
|
with self.assertRaises(ValueError) as ve:
|
|
Restriction.OneCut("bla-me", (Restriction.RestrictionType,), {})
|
|
self.assertIn("hyphen", str(ve.exception))
|
|
|
|
def setUp(self):
|
|
"""Set up some sequences for later use."""
|
|
base_seq = Seq("AAAA")
|
|
self.ecosite_seq = base_seq + Seq(EcoRI.site) + base_seq
|
|
self.smasite_seq = base_seq + Seq(SmaI.site) + base_seq
|
|
self.kpnsite_seq = base_seq + Seq(KpnI.site) + base_seq
|
|
|
|
def test_eco_cutting(self):
|
|
"""Test basic cutting with EcoRI (5'overhang)."""
|
|
self.assertEqual(EcoRI.site, "GAATTC")
|
|
self.assertTrue(EcoRI.cut_once())
|
|
self.assertFalse(EcoRI.is_blunt())
|
|
self.assertTrue(EcoRI.is_5overhang())
|
|
self.assertFalse(EcoRI.is_3overhang())
|
|
self.assertEqual(EcoRI.overhang(), "5' overhang")
|
|
self.assertTrue(EcoRI.is_defined())
|
|
self.assertFalse(EcoRI.is_ambiguous())
|
|
self.assertFalse(EcoRI.is_unknown())
|
|
self.assertTrue(EcoRI.is_palindromic())
|
|
self.assertTrue(EcoRI.is_comm())
|
|
self.assertIn("Thermo Fisher Scientific", EcoRI.supplier_list())
|
|
self.assertEqual(EcoRI.elucidate(), "G^AATT_C")
|
|
self.assertEqual(EcoRI.search(self.ecosite_seq), [6])
|
|
self.assertEqual(EcoRI.characteristic(), (1, -1, None, None, "GAATTC"))
|
|
|
|
parts = EcoRI.catalyse(self.ecosite_seq)
|
|
self.assertEqual(len(parts), 2)
|
|
self.assertEqual(str(parts[1]), "AATTCAAAA")
|
|
parts = EcoRI.catalyze(self.ecosite_seq)
|
|
self.assertEqual(len(parts), 2)
|
|
|
|
def test_kpn_cutting(self):
|
|
"""Test basic cutting with KpnI (3'overhang)."""
|
|
self.assertTrue(KpnI.is_3overhang())
|
|
self.assertFalse(KpnI.is_5overhang())
|
|
self.assertFalse(KpnI.is_blunt())
|
|
self.assertEqual(KpnI.overhang(), "3' overhang")
|
|
parts = KpnI.catalyse(self.kpnsite_seq)
|
|
self.assertEqual(len(parts), 2)
|
|
self.assertEqual(
|
|
KpnI.catalyse(self.kpnsite_seq), KpnI.catalyze(self.kpnsite_seq)
|
|
)
|
|
|
|
def test_sma_cutting(self):
|
|
"""Test basic cutting with SmaI (blunt cutter)."""
|
|
self.assertTrue(SmaI.is_blunt())
|
|
self.assertFalse(SmaI.is_3overhang())
|
|
self.assertFalse(SmaI.is_5overhang())
|
|
self.assertEqual(SmaI.overhang(), "blunt")
|
|
parts = SmaI.catalyse(self.smasite_seq)
|
|
self.assertEqual(len(parts), 2)
|
|
self.assertEqual(str(parts[1]), "GGGAAAA")
|
|
parts = SmaI.catalyze(self.smasite_seq)
|
|
self.assertEqual(len(parts), 2)
|
|
|
|
def test_ear_cutting(self):
|
|
"""Test basic cutting with EarI (ambiguous overhang)."""
|
|
self.assertFalse(EarI.is_palindromic())
|
|
self.assertFalse(EarI.is_defined())
|
|
self.assertTrue(EarI.is_ambiguous())
|
|
self.assertFalse(EarI.is_unknown())
|
|
self.assertEqual(EarI.elucidate(), "CTCTTCN^NNN_N")
|
|
|
|
def test_sna_cutting(self):
|
|
"""Test basic cutting with SnaI (unknown)."""
|
|
self.assertEqual(SnaI.elucidate(), "? GTATAC ?")
|
|
self.assertFalse(SnaI.is_defined())
|
|
self.assertFalse(SnaI.is_ambiguous())
|
|
self.assertTrue(SnaI.is_unknown())
|
|
self.assertFalse(SnaI.is_comm())
|
|
self.assertIsNone(SnaI.suppliers())
|
|
self.assertEqual(SnaI.supplier_list(), [])
|
|
with self.assertRaises(TypeError):
|
|
SnaI.buffers("no company")
|
|
|
|
def test_circular_sequences(self):
|
|
"""Deal with cutting circular sequences."""
|
|
parts = EcoRI.catalyse(self.ecosite_seq, linear=False)
|
|
self.assertEqual(len(parts), 1)
|
|
locations = EcoRI.search(parts[0], linear=False)
|
|
self.assertEqual(locations, [1])
|
|
|
|
parts = KpnI.catalyse(self.kpnsite_seq, linear=False)
|
|
self.assertEqual(len(parts), 1)
|
|
locations = KpnI.search(parts[0], linear=False)
|
|
self.assertEqual(locations, [1])
|
|
|
|
parts = SmaI.catalyse(self.smasite_seq, linear=False)
|
|
self.assertEqual(len(parts), 1)
|
|
locations = SmaI.search(parts[0], linear=False)
|
|
self.assertEqual(locations, [1])
|
|
|
|
self.assertEqual(
|
|
EarI.search(FormattedSeq(Seq("CTCTTCAAAAA")), linear=False), [8]
|
|
)
|
|
self.assertEqual(
|
|
SnaI.search(FormattedSeq(Seq("GTATACAAAAA")), linear=False), [1]
|
|
)
|
|
|
|
def test_shortcuts(self):
|
|
"""Check if '/' and '//' work as '.search' and '.catalyse'."""
|
|
self.assertEqual(EcoRI / self.ecosite_seq, [6])
|
|
self.assertEqual(self.ecosite_seq / EcoRI, [6])
|
|
self.assertEqual(len(EcoRI // self.ecosite_seq), 2)
|
|
self.assertEqual(len(self.ecosite_seq // EcoRI), 2)
|
|
|
|
def test_cutting_border_positions(self):
|
|
"""Check if cutting after first and penultimate position works."""
|
|
# Use EarI, cuts as follows: CTCTTCN^NNN_N
|
|
# Only when the cut produces double stranded DNA on both outputs
|
|
# it is returned.
|
|
seq = Seq("CTCTTCA")
|
|
self.assertEqual(EarI.search(seq), [])
|
|
seq += "AAA"
|
|
self.assertEqual(EarI.search(seq), [])
|
|
seq += "A"
|
|
self.assertEqual(EarI.search(seq), [8])
|
|
# Recognition site on reverse-complement strand
|
|
seq = Seq("AAAAGAAGAG")
|
|
self.assertEqual(EarI.search(seq), [])
|
|
seq = "A" + seq
|
|
self.assertEqual(EarI.search(seq), [2])
|
|
|
|
# Examples from https://github.com/biopython/biopython/issues/4604
|
|
self.assertEqual(BsaI.search(Seq("GGTCTCATAAAA")), [8])
|
|
self.assertEqual(BsaI.search(Seq("GGTCTCATAAA")), [])
|
|
self.assertEqual(BsaI.search(Seq("GGTCTCGT")), [])
|
|
self.assertEqual(BsaI.search(Seq("GGTCTCGT").reverse_complement()), [])
|
|
|
|
self.assertEqual(BsaXI.search(Seq("AAATAAAAAAAAAACAAAAACTCC")), [5])
|
|
self.assertEqual(BsaXI.search(Seq("AATAAAAAAAAAACAAAAACTCC")), [])
|
|
|
|
self.assertEqual(BspCNI.search(Seq("CTCAGAAAAAAAAAT")), [15])
|
|
self.assertEqual(BspCNI.search(Seq("CTCAGAAAAAAAAA")), [])
|
|
|
|
def test_recognition_site_on_both_strands(self):
|
|
"""Check if recognition sites on both strands are properly handled."""
|
|
seq = Seq("CTCTTCGAAGAG")
|
|
self.assertEqual(EarI.search(seq), [3, 8])
|
|
|
|
def test_overlapping_cut_sites(self):
|
|
"""Check if overlapping recognition sites are properly handled."""
|
|
seq = Seq("CATGCACGCATGCATGCACGC")
|
|
self.assertEqual(SphI.search(seq), [13, 17])
|
|
|
|
|
|
class EnzymeComparison(unittest.TestCase):
|
|
"""Tests for comparing various enzymes."""
|
|
|
|
def test_basic_isochizomers(self):
|
|
"""Test to be sure isochizomer and neoschizomers are as expected."""
|
|
self.assertEqual(Acc65I.isoschizomers(), [Asp718I, KpnI])
|
|
self.assertEqual(Acc65I.elucidate(), "G^GTAC_C")
|
|
self.assertEqual(Asp718I.elucidate(), "G^GTAC_C")
|
|
self.assertEqual(KpnI.elucidate(), "G_GTAC^C")
|
|
self.assertTrue(Acc65I.is_isoschizomer(KpnI))
|
|
self.assertFalse(Acc65I.is_equischizomer(KpnI))
|
|
self.assertTrue(Acc65I.is_neoschizomer(KpnI))
|
|
self.assertIn(Acc65I, Asp718I.equischizomers())
|
|
self.assertIn(KpnI, Asp718I.neoschizomers())
|
|
self.assertIn(KpnI, Acc65I.isoschizomers())
|
|
|
|
def test_comparisons(self):
|
|
"""Test comparison operators between different enzymes."""
|
|
# Comparison of iso- and neoschizomers
|
|
self.assertEqual(Acc65I, Acc65I)
|
|
self.assertNotEqual(Acc65I, KpnI)
|
|
self.assertFalse(Acc65I == Asp718I) # noqa: A500
|
|
# self.assertNotEqual(Acc65I, Asp718I) it doesn't work as expected
|
|
self.assertFalse(Acc65I != Asp718I) # noqa: A500
|
|
self.assertNotEqual(Acc65I, EcoRI)
|
|
self.assertTrue(Acc65I >> KpnI)
|
|
self.assertFalse(Acc65I >> Asp718I)
|
|
|
|
# Compare length of recognition sites
|
|
self.assertFalse(EcoRI >= EcoRV)
|
|
self.assertGreaterEqual(EcoRV, EcoRI)
|
|
with self.assertRaises(NotImplementedError):
|
|
EcoRV >= 3
|
|
self.assertFalse(EcoRI > EcoRV)
|
|
self.assertGreater(EcoRV, EcoRI)
|
|
with self.assertRaises(NotImplementedError):
|
|
EcoRV > 3
|
|
self.assertLessEqual(EcoRI, EcoRV)
|
|
self.assertFalse(EcoRV <= EcoRI)
|
|
with self.assertRaises(NotImplementedError):
|
|
EcoRV <= 3
|
|
self.assertLess(EcoRI, EcoRV)
|
|
self.assertFalse(EcoRV < EcoRI)
|
|
with self.assertRaises(NotImplementedError):
|
|
EcoRV < 3
|
|
|
|
# Compare compatible overhangs
|
|
self.assertTrue(Acc65I % Asp718I)
|
|
self.assertTrue(Acc65I % Acc65I)
|
|
self.assertFalse(Acc65I % KpnI)
|
|
with self.assertRaises(TypeError):
|
|
Acc65I % "KpnI"
|
|
self.assertTrue(SmaI % EcoRV)
|
|
self.assertTrue(EarI % EarI)
|
|
self.assertIn(EcoRV, SmaI.compatible_end())
|
|
self.assertIn(Acc65I, Asp718I.compatible_end())
|
|
|
|
|
|
class RestrictionBatchPrintTest(unittest.TestCase):
|
|
"""Tests Restriction.Analysis printing functionality."""
|
|
|
|
def createAnalysis(self, seq_str, batch_ary):
|
|
"""Restriction.Analysis creation helper method."""
|
|
rb = Restriction.RestrictionBatch(batch_ary)
|
|
seq = Seq(seq_str)
|
|
return Restriction.Analysis(rb, seq)
|
|
|
|
def assertAnalysisFormat(self, analysis, expected):
|
|
"""Test make_format.
|
|
|
|
Test that the Restriction.Analysis make_format(print_that) matches
|
|
some string.
|
|
"""
|
|
dct = analysis.mapping
|
|
ls, nc = [], []
|
|
for k, v in dct.items():
|
|
if v:
|
|
ls.append((k, v))
|
|
else:
|
|
nc.append(k)
|
|
result = analysis.make_format(ls, "", [], "")
|
|
self.assertEqual(result.replace(" ", ""), expected.replace(" ", ""))
|
|
|
|
def test_make_format_map1(self):
|
|
"""Test that print_as('map'); print_that() correctly wraps round.
|
|
|
|
1. With no marker.
|
|
"""
|
|
analysis = self.createAnalysis(
|
|
"CCAGTCTATAATTCG"
|
|
+ Restriction.BamHI.site
|
|
+ "GCGGCATCATACTCGAATATCGCGTGATGATACGTAGTAATTACGCATG",
|
|
["BamHI"],
|
|
)
|
|
analysis.print_as("map")
|
|
expected = [
|
|
" 17 BamHI",
|
|
" | ",
|
|
"CCAGTCTATAATTCGGGATCCGCGGCATCATACTCGAATATCGCGTGATGATACGTAGTA",
|
|
"||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||",
|
|
"GGTCAGATATTAAGCCCTAGGCGCCGTAGTATGAGCTTATAGCGCACTACTATGCATCAT",
|
|
"1 60",
|
|
"",
|
|
"ATTACGCATG",
|
|
"||||||||||",
|
|
"TAATGCGTAC",
|
|
"61 70",
|
|
"",
|
|
"",
|
|
]
|
|
self.assertAnalysisFormat(analysis, "\n".join(expected))
|
|
|
|
def test_make_format_map2(self):
|
|
"""Test that print_as('map'); print_that() correctly wraps round.
|
|
|
|
2. With marker.
|
|
"""
|
|
analysis = self.createAnalysis(
|
|
"CCAGTCTATAATTCG"
|
|
+ Restriction.BamHI.site
|
|
+ "GCGGCATCATACTCGA"
|
|
+ Restriction.BamHI.site
|
|
+ "ATATCGCGTGATGATA"
|
|
+ Restriction.NdeI.site
|
|
+ "CGTAGTAATTACGCATG",
|
|
["NdeI", "EcoRI", "BamHI", "BsmBI"],
|
|
)
|
|
analysis.print_as("map")
|
|
expected = [
|
|
" 17 BamHI",
|
|
" | ",
|
|
" | 39 BamHI",
|
|
" | | ",
|
|
"CCAGTCTATAATTCGGGATCCGCGGCATCATACTCGAGGATCCATATCGCGTGATGATAC",
|
|
"||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||",
|
|
"GGTCAGATATTAAGCCCTAGGCGCCGTAGTATGAGCTCCTAGGTATAGCGCACTACTATG",
|
|
"1 60",
|
|
"",
|
|
" 62 NdeI",
|
|
" | ",
|
|
"ATATGCGTAGTAATTACGCATG",
|
|
"||||||||||||||||||||||",
|
|
"TATACGCATCATTAATGCGTAC",
|
|
"61 82",
|
|
"",
|
|
"",
|
|
]
|
|
self.assertAnalysisFormat(analysis, "\n".join(expected))
|
|
|
|
def test_make_format_map3(self):
|
|
"""Test that print_as('map'); print_that() correctly wraps round.
|
|
|
|
3. With marker restricted.
|
|
"""
|
|
analysis = self.createAnalysis(
|
|
"CCAGTCTATAATTCG"
|
|
+ Restriction.BamHI.site
|
|
+ "GCGGCATCATACTCGA"
|
|
+ Restriction.BamHI.site
|
|
+ "ATATCGCGTGATGATA"
|
|
+ Restriction.EcoRV.site
|
|
+ "CGTAGTAATTACGCATG",
|
|
["NdeI", "EcoRI", "BamHI", "BsmBI"],
|
|
)
|
|
analysis.print_as("map")
|
|
expected = [
|
|
" 17 BamHI",
|
|
" | ",
|
|
" | 39 BamHI",
|
|
" | | ",
|
|
"CCAGTCTATAATTCGGGATCCGCGGCATCATACTCGAGGATCCATATCGCGTGATGATAG",
|
|
"||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||",
|
|
"GGTCAGATATTAAGCCCTAGGCGCCGTAGTATGAGCTCCTAGGTATAGCGCACTACTATC",
|
|
"1 60",
|
|
"",
|
|
"ATATCCGTAGTAATTACGCATG",
|
|
"||||||||||||||||||||||",
|
|
"TATAGGCATCATTAATGCGTAC",
|
|
"61 82",
|
|
"",
|
|
"",
|
|
]
|
|
self.assertAnalysisFormat(analysis, "\n".join(expected))
|
|
|
|
def test_change(self):
|
|
"""Test that change() changes something."""
|
|
seq = Seq(
|
|
"CCAGTCTATAATTCG"
|
|
+ BamHI.site
|
|
+ "GCGGCATCATACTCGA"
|
|
+ BamHI.site
|
|
+ "ATATCGCGTGATGATA"
|
|
+ EcoRV.site
|
|
+ "CGTAGTAATTACGCATG"
|
|
)
|
|
batch = NdeI + EcoRI + BamHI + BsmBI
|
|
analysis = Analysis(batch, seq)
|
|
self.assertEqual(analysis.full()[BamHI], [17, 39])
|
|
batch = NdeI + EcoRI + BsmBI
|
|
seq += NdeI.site
|
|
analysis.change(sequence=seq)
|
|
analysis.change(rb=batch)
|
|
self.assertEqual(len(analysis.full()), 3)
|
|
self.assertEqual(analysis.full()[NdeI], [85])
|
|
with self.assertRaises(AttributeError):
|
|
analysis.change(**{"NameWidth": 3, "KonsoleWidth": 40}) # Console
|
|
|
|
|
|
class RestrictionBatches(unittest.TestCase):
|
|
"""Tests for dealing with batches of restriction enzymes."""
|
|
|
|
def test_creating_batch(self):
|
|
"""Creating and modifying a restriction batch."""
|
|
batch = RestrictionBatch()
|
|
self.assertEqual(batch.suppl_codes()["N"], "New England Biolabs")
|
|
self.assertTrue(batch.is_restriction(EcoRI))
|
|
batch = RestrictionBatch([EcoRI])
|
|
batch.add(KpnI)
|
|
batch += EcoRV
|
|
self.assertEqual(len(batch), 3)
|
|
self.assertEqual(batch.elements(), ["EcoRI", "EcoRV", "KpnI"])
|
|
# Problem with Python 3, as sequence of list may be different:
|
|
# self.assertEqual(batch.as_string(), ['EcoRI', 'KpnI', 'EcoRV'])
|
|
self.assertIn("EcoRI", batch.as_string())
|
|
|
|
# The usual way to test batch membership
|
|
self.assertIn(EcoRV, batch)
|
|
self.assertIn(EcoRI, batch)
|
|
self.assertIn(KpnI, batch)
|
|
self.assertNotIn(SmaI, batch)
|
|
# Syntax sugar for the above
|
|
self.assertIn("EcoRV", batch)
|
|
self.assertNotIn("SmaI", batch)
|
|
|
|
batch.get(EcoRV)
|
|
self.assertRaises(ValueError, batch.get, SmaI)
|
|
batch.get(SmaI, add=True)
|
|
self.assertEqual(len(batch), 4)
|
|
batch.remove(SmaI)
|
|
batch.remove(EcoRV)
|
|
self.assertEqual(len(batch), 2)
|
|
|
|
self.assertNotIn(EcoRV, batch)
|
|
self.assertNotIn("EcoRV", batch)
|
|
|
|
# Creating a batch by addition of restriction enzymes
|
|
new_batch = EcoRI + KpnI
|
|
self.assertEqual(batch, new_batch)
|
|
# or by addition of a batch with an enzyme
|
|
another_new_batch = new_batch + EcoRV
|
|
new_batch += EcoRV
|
|
self.assertEqual(another_new_batch, new_batch)
|
|
self.assertRaises(TypeError, EcoRI.__add__, 1)
|
|
|
|
# Create a batch with suppliers and other supplier related methods
|
|
# These tests may be 'update sensitive' since company names and
|
|
# products may change often...
|
|
batch = RestrictionBatch((), ("S")) # Sigma
|
|
self.assertEqual(batch.current_suppliers(), ["Sigma Chemical Corporation"])
|
|
self.assertIn(EcoRI, batch)
|
|
self.assertNotIn(AanI, batch)
|
|
batch.add_supplier("B") # Thermo Fisher Scientific
|
|
self.assertIn(AanI, batch)
|
|
|
|
def test_batch_analysis(self):
|
|
"""Sequence analysis with a restriction batch."""
|
|
seq = Seq("AAAA" + EcoRV.site + "AAAA" + EcoRI.site + "AAAA")
|
|
batch = RestrictionBatch([EcoRV, EcoRI])
|
|
|
|
hits = batch.search(seq)
|
|
self.assertEqual(hits[EcoRV], [8])
|
|
self.assertEqual(hits[EcoRI], [16])
|
|
|
|
def test_premade_batches(self):
|
|
"""Test content of premade batches CommOnly, NoComm, AllEnzymes."""
|
|
self.assertEqual(len(AllEnzymes), (len(CommOnly) + len(NonComm)))
|
|
self.assertTrue(len(AllEnzymes) > len(CommOnly) > len(NonComm))
|
|
|
|
def test_search_premade_batches(self):
|
|
"""Test search with pre-made batches CommOnly, NoComm, AllEnzymes."""
|
|
seq = Seq("ACCCGAATTCAAAACTGACTGATCGATCGTCGACTG")
|
|
search = AllEnzymes.search(seq)
|
|
self.assertEqual(search[MluCI], [6])
|
|
# Check if '/' operator works as 'search':
|
|
search = CommOnly / seq
|
|
self.assertEqual(search[MluCI], [6])
|
|
# Also in reverse order:
|
|
search = seq / NonComm
|
|
self.assertEqual(search[McrI], [28])
|
|
|
|
def test_analysis_restrictions(self):
|
|
"""Test Fancier restriction analysis."""
|
|
new_seq = Seq("TTCAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAA")
|
|
rb = RestrictionBatch([EcoRI, KpnI, EcoRV])
|
|
ana = Analysis(rb, new_seq, linear=False)
|
|
# Output only the result for enzymes which cut blunt:
|
|
self.assertEqual(ana.blunt(), {EcoRV: []})
|
|
self.assertEqual(ana.full(), {KpnI: [], EcoRV: [], EcoRI: [33]})
|
|
# Output only the result for enzymes which have a site:
|
|
self.assertEqual(ana.with_sites(), {EcoRI: [33]})
|
|
# Output only the enzymes which have no site:
|
|
self.assertEqual(ana.without_site(), {KpnI: [], EcoRV: []})
|
|
self.assertEqual(ana.with_site_size([32]), {})
|
|
# Output only enzymes which produce 5' overhangs
|
|
self.assertEqual(ana.overhang5(), {EcoRI: [33]})
|
|
# Output only enzymes which produce 3' overhangs
|
|
self.assertEqual(ana.overhang3(), {KpnI: []})
|
|
# Output only enzymes which produce defined ends
|
|
self.assertEqual(ana.defined(), {KpnI: [], EcoRV: [], EcoRI: [33]})
|
|
# Output only enzymes hich cut N times
|
|
self.assertEqual(ana.with_N_sites(2), {})
|
|
# The enzymes which cut between position x and y:
|
|
with self.assertRaises(TypeError):
|
|
ana.only_between("t", 20)
|
|
with self.assertRaises(TypeError):
|
|
ana.only_between(1, "t")
|
|
self.assertEqual(ana.only_between(1, 20), {})
|
|
self.assertEqual(ana.only_between(20, 34), {EcoRI: [33]})
|
|
# Mix start/end order:
|
|
self.assertEqual(ana.only_between(34, 20), {EcoRI: [33]})
|
|
self.assertEqual(ana.only_outside(20, 34), {})
|
|
with self.assertWarns(BiopythonWarning):
|
|
ana.with_name(["fake"])
|
|
self.assertEqual(ana.with_name([EcoRI]), {EcoRI: [33]})
|
|
self.assertEqual((ana._boundaries(1, 20)[:2]), (1, 20))
|
|
# Reverse order:
|
|
self.assertEqual((ana._boundaries(20, 1)[:2]), (1, 20))
|
|
# Fix negative start:
|
|
self.assertEqual((ana._boundaries(-1, 20)[:2]), (20, 33))
|
|
# Fix negative end:
|
|
self.assertEqual((ana._boundaries(1, -1)[:2]), (1, 33))
|
|
# Sites in- and outside of boundaries
|
|
new_seq = Seq("GAATTCAAAAAAGAATTC")
|
|
rb = RestrictionBatch([EcoRI])
|
|
ana = Analysis(rb, new_seq)
|
|
# Cut at least inside
|
|
self.assertEqual(ana.between(1, 7), {EcoRI: [2, 14]})
|
|
# Cut at least inside and report only inside site
|
|
self.assertEqual(ana.show_only_between(1, 7), {EcoRI: [2]})
|
|
# Cut at least outside
|
|
self.assertEqual(ana.outside(1, 7), {EcoRI: [2, 14]})
|
|
# Don't cut within
|
|
self.assertEqual(ana.do_not_cut(7, 12), {EcoRI: [2, 14]})
|
|
|
|
|
|
class TestPrintOutputs(unittest.TestCase):
|
|
"""Class to test various print outputs."""
|
|
|
|
import sys
|
|
from io import StringIO
|
|
|
|
def test_supplier(self):
|
|
"""Test output of supplier list for different enzyme types."""
|
|
out = self.StringIO()
|
|
self.sys.stdout = out
|
|
EcoRI.suppliers()
|
|
self.assertIn("Thermo Fisher Scientific", out.getvalue())
|
|
self.assertIsNone(SnaI.suppliers())
|
|
EcoRI.all_suppliers() # Independent of enzyme, list of all suppliers
|
|
self.assertIn("Agilent Technologies", out.getvalue())
|
|
batch = EcoRI + SnaI
|
|
batch.show_codes()
|
|
self.assertIn("N = New England Biolabs", out.getvalue())
|
|
self.sys.stdout = self.sys.__stdout__
|
|
|
|
def test_print_that(self):
|
|
"""Test print_that function."""
|
|
out = self.StringIO()
|
|
self.sys.stdout = out
|
|
my_batch = EcoRI + SmaI + KpnI
|
|
my_seq = Seq("GAATTCCCGGGATATA") # EcoRI and SmaI sites
|
|
analysis = Analysis(my_batch, my_seq)
|
|
analysis.print_that(None, title="My sequence\n\n", s1="Non Cutters\n\n")
|
|
self.assertIn("My sequence", out.getvalue())
|
|
self.assertIn("Non Cutters", out.getvalue())
|
|
self.assertIn("2.", out.getvalue())
|
|
self.sys.stdout = self.sys.__stdout__
|
|
|
|
def test_str_method(self):
|
|
"""Test __str__ and __repr__ outputs."""
|
|
batch = EcoRI + SmaI + KpnI
|
|
self.assertEqual(str(batch), "EcoRI+KpnI+SmaI")
|
|
batch += Asp718I
|
|
batch += SnaI
|
|
self.assertEqual(str(batch), "Asp718I+EcoRI...SmaI+SnaI")
|
|
self.assertEqual(
|
|
repr(batch),
|
|
"RestrictionBatch(['Asp718I', 'EcoRI', 'KpnI', 'SmaI', 'SnaI'])",
|
|
)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
runner = unittest.TextTestRunner(verbosity=2)
|
|
unittest.main(testRunner=runner)
|