///|
/// A cleavage model with offsets measured on the displayed recognition strand.
pub struct Enzyme {
name : String
motif : String
top_offset : Int
bottom_offset : Int
} derive(Eq, Debug, ToJson)
///|
/// Names are report identifiers, not claims about a curated enzyme catalogue.
pub fn Enzyme::new(
name : String,
motif : String,
top_offset : Int,
bottom_offset : Int,
) -> Enzyme raise RestrictError {
if name.length() == 0 || name.length() > 64 {
raise InvalidInput("ENZYME_NAME")
}
for c in name.iter() {
if !((c >= 'A' && c <= 'Z') ||
(c >= 'a' && c <= 'z') ||
(c >= '0' && c <= '9') ||
c == '_' ||
c == '-') {
raise InvalidInput("ENZYME_NAME")
}
}
if motif.length() == 0 || motif.length() > 64 {
raise InvalidInput("MOTIF_LENGTH")
}
let dna = Dna::new(motif)
if top_offset < -64 ||
top_offset > 128 ||
bottom_offset < -64 ||
bottom_offset > 128 {
raise InvalidInput("CUT_OFFSET")
}
{ name, motif: dna.sequence(), top_offset, bottom_offset }
}
///|
pub fn Enzyme::name(self : Enzyme) -> String {
self.name
}
///|
pub fn Enzyme::motif(self : Enzyme) -> String {
self.motif
}
///|
pub fn Enzyme::offsets(self : Enzyme) -> (Int, Int) {
(self.top_offset, self.bottom_offset)
}
///|
/// IUPAC reverse complement is delegated to upstream base semantics.
pub fn reverse_complement(dna : Dna) -> Dna {
let chars = dna.bases.to_array()
let out = StringBuilder::new()
for i = chars.length() - 1; i >= 0; i = i - 1 {
out.write_char(@base.IupacBase::from_char(chars[i]).complement().to_char())
}
{ bases: out.to_string(), topology: dna.topology }
}