Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 7 additions & 6 deletions .github/workflows/publish-docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,23 +13,24 @@ jobs:

runs-on: ubuntu-latest

strategy:
fail-fast: false

steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: "3.12"

- name: Session information
run: |
python --version

- name: Install Poetry
uses: snok/install-poetry@v1
with:
virtualenvs.prefer-active-python: true
run: |
python -m pip install --upgrade pip
pip install poetry==2.3.2

- name: 🔩 list Poetry settings
run: poetry config --list
Expand Down
4 changes: 3 additions & 1 deletion .github/workflows/pydna_test_and_coverage_workflow.yml
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,9 @@ jobs:
run: python -c "import sys; print(sys.version)"

- name: Install Poetry
uses: snok/[email protected]
run: |
python -m pip install --upgrade pip
pip install poetry==2.3.2

- name: 🔩 list Poetry settings
run: poetry config --list
Expand Down
92 changes: 89 additions & 3 deletions docs/notebooks/history.ipynb

Large diffs are not rendered by default.

2,632 changes: 1,589 additions & 1,043 deletions poetry.lock

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ scipy = [
]
seguid = ">=0.0.5"
regex = ">=2024.11.6,<2027.0.0"
opencloning-linkml = "^0.4.9"
opencloning-linkml = "^1"
[tool.poetry.extras]
clipboard = ["pyperclip"]
download = ["pyparsing", "requests"]
Expand Down
74 changes: 73 additions & 1 deletion src/pydna/assembly2.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
from pydna.gateway import gateway_overlap, find_gateway_sites
from pydna.cre_lox import cre_loxP_overlap
from pydna.alphabet import anneal_strands
from pydna.recombinase import Recombinase, RecombinaseCollection

from typing import TYPE_CHECKING, Callable, Literal
from pydna.opencloning_models import (
Expand All @@ -52,6 +53,7 @@
GatewaySource,
HomologousRecombinationSource,
CreLoxRecombinationSource,
RecombinaseSource,
PCRSource,
SourceInput,
CRISPRSource,
Expand Down Expand Up @@ -1968,11 +1970,15 @@ def __init__(self, frags: [Dseqrecord], limit=25, algorithm=common_sub_strings):
self.G.add_node(1, seq=frag)

matches = algorithm(frag, frag, limit)
# Remove matches where the whole sequence matches
matches = [match for match in matches if match[2] != len(frag)]

for match in matches:
self.add_edges_from_match(match, 1, 1, frag, frag)

# To avoid duplicated outputs
self.G.remove_edges_from([(-1, -1)])
while (-1, -1) in self.G.edges():
self.G.remove_edges_from([(-1, -1)])

# These two are constrained
self.use_fragment_order = True
Expand Down Expand Up @@ -2801,6 +2807,72 @@ def cre_lox_excision(genome: Dseqrecord) -> list[Dseqrecord]:
return _recast_sources(products, CreLoxRecombinationSource)


def recombinase_excision(
genome: Dseqrecord,
recombinase: Recombinase | RecombinaseCollection,
) -> list[Dseqrecord]:
"""Returns the products for recombinase-mediated excision.

Parameters
----------
genome : Dseqrecord
Target genome sequence containing two recombinase sites.
recombinase : Recombinase | RecombinaseCollection
Recombinase object.

Returns
-------
list[Dseqrecord]
List containing excised plasmid and remaining genome sequence.
"""
products = common_function_excision_products(genome, None, recombinase.overlap)
products = [recombinase.annotate(p) for p in products]
return _recast_sources(products, RecombinaseSource, recombinases=recombinase)


def recombinase_integration(
genome: Dseqrecord,
inserts: list[Dseqrecord],
recombinase: Recombinase | RecombinaseCollection,
) -> list[Dseqrecord]:
"""Returns the products resulting from recombinase-mediated integration.

Parameters
----------
genome : Dseqrecord
Target genome sequence.
inserts : list[Dseqrecord]
DNA fragment(s) to insert.
recombinase : Recombinase | RecombinaseCollection
Recombinase object.

Returns
-------
list[Dseqrecord]
List of integrated DNA molecules.

Examples
--------
>>> from pydna.dseqrecord import Dseqrecord
>>> from pydna.assembly2 import recombinase_integration, recombinase_excision
>>> from pydna.recombinase import Recombinase
>>> site1 = "ATGCCCTAAaaTT"
>>> site2 = "AAaaTTTTTTTCCCT"
>>> genome = Dseqrecord(f"cccccc{site1.upper()}aaaaa")
>>> insert = Dseqrecord(f"{site2.upper()}bbbbb", circular=True)
>>> recombinase = Recombinase(site1, site2)
>>> products = recombinase_integration(genome, [insert], recombinase)
>>> len(products) >= 1
True
"""
fragments = common_handle_insertion_fragments(genome, inserts)
products = common_function_integration_products(
fragments, None, recombinase.overlap
)
products = [recombinase.annotate(p) for p in products]
return _recast_sources(products, RecombinaseSource, recombinases=recombinase)


def crispr_integration(
genome: Dseqrecord,
inserts: list[Dseqrecord],
Expand Down
Loading