-
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add cloning and fragmentation to python. Definitely should work to improve this over time, but this is good enough to get out there.
- Loading branch information
Showing
9 changed files
with
601 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
from typing import List, Optional | ||
from .cffi_bindings import ffi, lib | ||
|
||
class Part: | ||
def __init__(self, sequence: str, circular: bool): | ||
self.sequence = sequence | ||
self.circular = circular | ||
|
||
class Fragment: | ||
def __init__(self, sequence: str, forward_overhang: str, reverse_overhang: str): | ||
self.sequence = sequence | ||
self.forward_overhang = forward_overhang | ||
self.reverse_overhang = reverse_overhang | ||
|
||
def _create_c_string(python_string: str): | ||
return ffi.new("char[]", python_string.encode('utf-8')) | ||
|
||
def _create_c_part(part: Part): | ||
return {"sequence": _create_c_string(part.sequence), "circular": ffi.cast("int", int(part.circular))} | ||
|
||
def _create_c_fragment(fragment: Fragment): | ||
return { | ||
"sequence": _create_c_string(fragment.sequence), | ||
"forward_overhang": _create_c_string(fragment.forward_overhang), | ||
"reverse_overhang": _create_c_string(fragment.reverse_overhang) | ||
} | ||
|
||
def _fragment_from_c(c_fragment): | ||
return Fragment( | ||
ffi.string(c_fragment.sequence).decode('utf-8'), | ||
ffi.string(c_fragment.forward_overhang).decode('utf-8'), | ||
ffi.string(c_fragment.reverse_overhang).decode('utf-8') | ||
) | ||
|
||
def cut_with_enzyme_by_name(part: Part, directional: bool, name: str, methylated: bool) -> List[Fragment]: | ||
c_part = ffi.new("Part*", _create_c_part(part)) | ||
c_name = _create_c_string(name) | ||
c_directional = ffi.cast("int", int(directional)) | ||
c_methylated = ffi.cast("int", int(methylated)) | ||
|
||
result = lib.CutWithEnzymeByName(c_part[0], c_directional, c_name, c_methylated) | ||
if result.error != ffi.NULL: | ||
raise Exception(ffi.string(result.error).decode('utf-8')) | ||
|
||
fragments = [_fragment_from_c(result.fragments[i]) for i in range(result.size)] | ||
return fragments | ||
|
||
def ligate(fragments: List[Fragment], circular: bool) -> str: | ||
c_fragments = ffi.new("Fragment[]", [_create_c_fragment(f) for f in fragments]) | ||
c_fragment_count = ffi.cast("int", len(fragments)) | ||
c_circular = ffi.cast("int", int(circular)) | ||
|
||
result = lib.Ligate(c_fragments, c_fragment_count, c_circular) | ||
if result.error != ffi.NULL: | ||
raise Exception(ffi.string(result.error).decode('utf-8')) | ||
|
||
return ffi.string(result.ligation).decode('utf-8') | ||
|
||
def golden_gate(sequences: List[Part], cutting_enzyme_name: str, methylated: bool) -> str: | ||
c_parts = ffi.new("Part[]", [_create_c_part(part) for part in sequences]) | ||
c_sequence_count = ffi.cast("int", len(sequences)) | ||
c_cutting_enzyme_name = _create_c_string(cutting_enzyme_name) | ||
c_methylated = ffi.cast("int", int(methylated)) | ||
|
||
result = lib.GoldenGate(c_parts, c_sequence_count, c_cutting_enzyme_name, c_methylated) | ||
if result.error != ffi.NULL: | ||
raise Exception(ffi.string(result.error).decode('utf-8')) | ||
|
||
return ffi.string(result.ligation).decode('utf-8') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
from typing import List, Tuple | ||
from .cffi_bindings import ffi, lib | ||
|
||
class Assembly: | ||
def __init__(self, sequence: str, fragments: List[str], efficiency: float, sub_assemblies: List['Assembly']): | ||
self.sequence = sequence | ||
self.fragments = fragments | ||
self.efficiency = efficiency | ||
self.sub_assemblies = sub_assemblies | ||
|
||
def _create_c_string_array(python_strings: List[str]): | ||
c_strings = [ffi.new("char[]", s.encode('utf-8')) for s in python_strings] | ||
c_array = ffi.new("char *[]", c_strings) | ||
return c_array, c_strings # Return c_strings to keep them alive | ||
|
||
def _c_string_array_to_python(c_array, size): | ||
return [ffi.string(c_array[i]).decode('utf-8') for i in range(size)] | ||
|
||
def set_efficiency(overhangs: List[str]) -> float: | ||
c_overhangs, _ = _create_c_string_array(overhangs) | ||
return lib.SetEfficiency(c_overhangs, len(overhangs)) | ||
|
||
def next_overhangs(current_overhangs: List[str]) -> Tuple[List[str], List[float]]: | ||
c_overhangs, _ = _create_c_string_array(current_overhangs) | ||
result = lib.NextOverhangs(c_overhangs, len(current_overhangs)) | ||
|
||
if result.error != ffi.NULL: | ||
raise Exception(ffi.string(result.error).decode('utf-8')) | ||
|
||
overhangs = _c_string_array_to_python(result.overhangs, result.size) | ||
efficiencies = [result.efficiencies[i] for i in range(result.size)] | ||
return overhangs, efficiencies | ||
|
||
def next_overhang(current_overhangs: List[str]) -> str: | ||
c_overhangs, _ = _create_c_string_array(current_overhangs) | ||
result = lib.NextOverhang(c_overhangs, len(current_overhangs)) | ||
return ffi.string(result).decode('utf-8') | ||
|
||
def fragment(sequence: str, min_fragment_size: int, max_fragment_size: int, exclude_overhangs: List[str]) -> Tuple[List[str], float, str]: | ||
c_sequence = ffi.new("char[]", sequence.encode('utf-8')) | ||
c_exclude_overhangs, _ = _create_c_string_array(exclude_overhangs) | ||
|
||
result = lib.FragmentSequence(c_sequence, min_fragment_size, max_fragment_size, c_exclude_overhangs, len(exclude_overhangs)) | ||
|
||
if result.error != ffi.NULL: | ||
error = ffi.string(result.error).decode('utf-8') | ||
return [], 0.0, error | ||
|
||
fragments = _c_string_array_to_python(result.fragments, result.size) | ||
return fragments, result.efficiency, None | ||
|
||
def fragment_with_overhangs(sequence: str, min_fragment_size: int, max_fragment_size: int, | ||
exclude_overhangs: List[str], include_overhangs: List[str]) -> Tuple[List[str], float, str]: | ||
c_sequence = ffi.new("char[]", sequence.encode('utf-8')) | ||
c_exclude_overhangs, _ = _create_c_string_array(exclude_overhangs) | ||
c_include_overhangs, _ = _create_c_string_array(include_overhangs) | ||
|
||
result = lib.FragmentSequenceWithOverhangs(c_sequence, min_fragment_size, max_fragment_size, | ||
c_exclude_overhangs, len(exclude_overhangs), | ||
c_include_overhangs, len(include_overhangs)) | ||
|
||
if result.error != ffi.NULL: | ||
error = ffi.string(result.error).decode('utf-8') | ||
return [], 0.0, error | ||
|
||
fragments = _c_string_array_to_python(result.fragments, result.size) | ||
return fragments, result.efficiency, None | ||
|
||
def _assembly_from_c(c_assembly) -> Assembly: | ||
sequence = ffi.string(c_assembly.sequence).decode('utf-8') | ||
fragments = _c_string_array_to_python(c_assembly.fragments, c_assembly.fragmentCount) | ||
efficiency = c_assembly.efficiency | ||
sub_assemblies = [_assembly_from_c(c_assembly.subAssemblies[i]) for i in range(c_assembly.subAssemblyCount)] | ||
return Assembly(sequence, fragments, efficiency, sub_assemblies) | ||
|
||
def recursive_fragment(sequence: str, max_coding_size_oligo: int, assembly_pattern: List[int], | ||
exclude_overhangs: List[str], include_overhangs: List[str]) -> Assembly: | ||
c_sequence = ffi.new("char[]", sequence.encode('utf-8')) | ||
c_assembly_pattern = ffi.new("int[]", assembly_pattern) | ||
c_exclude_overhangs, _ = _create_c_string_array(exclude_overhangs) | ||
c_include_overhangs, _ = _create_c_string_array(include_overhangs) | ||
|
||
result = lib.RecursiveFragmentSequence(c_sequence, max_coding_size_oligo, c_assembly_pattern, len(assembly_pattern), | ||
c_exclude_overhangs, len(exclude_overhangs), | ||
c_include_overhangs, len(include_overhangs)) | ||
|
||
if result.error != ffi.NULL: | ||
raise Exception(ffi.string(result.error).decode('utf-8')) | ||
|
||
return _assembly_from_c(result.assembly) |
Oops, something went wrong.