Skip to content

Commit

Permalink
mod readme and moved imports of optional deps to the functions that u…
Browse files Browse the repository at this point in the history
…ses them.
  • Loading branch information
BjornFJohansson committed Nov 16, 2023
1 parent 47cd72f commit e3e7677
Show file tree
Hide file tree
Showing 6 changed files with 129 additions and 100 deletions.
108 changes: 65 additions & 43 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ Pydna provides simulation of:
- Gel electrophoresis of DNA with generation of gel images
- Homologous recombination
- Gibson assembly
- Golden gate assembly
- Golden gate assembly (in progress)


Virtually any sub-cloning experiment can be described in pydna, and its execution yield
Expand All @@ -38,12 +38,13 @@ Pydna has been designed with the goal of being understandable for biologists wit
Pydna can formalize planning and sharing of cloning strategies and is especially useful for complex or combinatorial
DNA molecule constructions.

To get started, I have compiled some [simple examples](https://github.com/MetabolicEngineeringGroupCBMA/pydna-examples#pydna-examples).
For more elaborate use, look at some assembly strategies of D-xylose metabolic pathways [MetabolicEngineeringGroupCBMA/ypk-xylose-pathways](https://github.com/MetabolicEngineeringGroupCBMA/ypk-xylose-pathways#pereira-et-al-2016).

Start by looking at the [cookbook](https://github.com/BjornFJohansson/pydna/blob/master/docs/cookbook/cookbook.ipynb).

Some simple examples can be found [here](https://github.com/MetabolicEngineeringGroupCBMA/pydna-examples#pydna-examples).

For more elaborate use, look at some assembly strategies of D-xylose metabolic pathways [MetabolicEngineeringGroupCBMA/ypk-xylose-pathways](https://github.com/MetabolicEngineeringGroupCBMA/ypk-xylose-pathways#pereira-et-al-2016).

See below for documentation.

![----]( http://bit.ly/coloredline)

Expand Down Expand Up @@ -80,11 +81,7 @@ DNA sequences are downloaded from Genbank by accession numbers that are guarante
lin_vector = vector.linearize(EcoRV)
rec_vec = ( lin_vector + pcr_prod ).looped()

Pydna can automate the simulation of [sub cloning](http://en.wikipedia.org/wiki/Subcloning) experiments using
python. This is helpful to generate examples for teaching purposes.

Read the documentation (below) or the [cookbook](https://github.com/BjornFJohansson/pydna/blob/master/docs/cookbook/cookbook.ipynb) with example files
for further information.
Another use case for pydna in the automatic generation of [sub cloning](http://en.wikipedia.org/wiki/Subcloning) examples for teaching purposes. These examples

Feedback & suggestions are very welcome! Please post a message in the [google group](https://groups.google.com/d/forum/pydna) for pydna if you need help or have problems, questions or comments :sos:.

Expand Down Expand Up @@ -126,11 +123,10 @@ When using pydna.

![----]( http://bit.ly/coloredline)

## Documentation
## Documentation :page_with_curl:

Documentation is built using [Sphinx](http://www.sphinx-doc.org/) from [docstrings](https://www.python.org/dev/peps/pep-0257/)
in the code and displayed at readthedocs [![Documentation Status](https://readthedocs.org/projects/pydna/badge/?version=latest)](http://pydna.readthedocs.io/?badge=latest)

in the code and displayed at readthedocs [![Documentation Status](https://readthedocs.org/projects/pydna/badge/?version=latest)](http://pydna.readthedocs.io/?badge=latest).
The [numpy](www.numpy.org) [docstring format](https://github.com/numpy/numpy/blob/release/doc/HOWTO_DOCUMENT.rst.txt) is used.

![----]( http://bit.ly/coloredline)
Expand All @@ -150,7 +146,7 @@ or use the --pre switch to get the latest version of pydna.

for optional functionality do:

pip install pydna[gel,download,express,gui]
pip install pydna[clipboard,download,express,gel]

Remove options inside the square brackets as required, but be sure not to leave spaces as pip will not recognize the options. See below under "Optional dependencies".

Expand Down Expand Up @@ -178,32 +174,65 @@ I am happy to collaborate on new features or bugfixes.
The list below is the minimal requirements for installing pydna.
Biopython and pydivsufsort has c-extensions, but the other modules are pure python.

- [Python 3.8, 3.9, 3.10 or 3.11](http://www.python.org)
- [Python 3.8, 3.9, 3.10, 3.11 or 3.12](http://www.python.org)
- [appdirs](https://pypi.python.org/pypi/appdirs)
- [biopython](http://pypi.python.org/pypi/biopython)
- [networkx](http://pypi.python.org/pypi/networkx)
- [prettytable](https://pypi.python.org/pypi/PrettyTable)
- [pydivsufsort](https://pypi.python.org/pypi/pydivsufsort)
- [pyfiglet](https://pypi.python.org/pypi/pyfiglet)

The above modules are installed as well as pyperclip and pyfiglet.
Pydna is importable even without these two modules.
Pydna is importable even without pyfiglet.

## Optional dependencies

If the modules listed below in the first column are installed, they will provide the functionality listed in the second column.
These can be installed `pip install pydna[clipboard,gel,download,express]`
where `[clipboard,gel,download,express]` is the list of options available. Any
combination of the words inside the square brackets are allowed, but no white space.


### `clipboard`

Enables the `pydna.dseqrecord.Dseqrecord.copy_gb_to_clipboard()` and `pydna.dseqrecord.Dseqrecord.copy_fasta_to_clipboard()`

These methods will put a copy the sequence on the clipboard in either Genbank (gb) or fasta format.


| Dependency | Function in pydna |
| --------------------------------------------------- | ------------------------------------------------------ |
| [pyperclip](https://pypi.python.org/pypi/pyperclip) | copy sequence to clipboard |

### download

Pyparsing enables the `pydna.genbankfixer.gbtext_clean()` function that can automatically
correct malformed sequence files in Genbank format. These are often found online, so this option also installs requests to enable the `pydna.genbankfixer.download.download_text()` function which can be used to get cleaned up text from a URL.


| Dependency | Function in pydna |
| --------------------------------------------------- | ------------------------------------------------------ |
| [scipy](https://www.scipy.org) | gel simulation with pydna.gel |
| [matplotlib](http://matplotlib.org) ||
| [pillow](https://github.com/python-pillow/Pillow) ||
| [numpy](http://www.numpy.org) | " |
| [pyparsing](https://pypi.python.org/pypi/pyparsing) | fix corrupt Genbank files with pydna.genbankfixer |
| [requests](https://pypi.org/project/requests) | download sequences with pydna.download |

### express

This option enables the `pydna.utils.cai()` function and the `cai()` method
available from subclasses of `pydna.seqrecord.SeqRecord`, such as
`pydna.dseqrecord.Dseqrecord`.

| [cai2](https://pypi.python.org/pypi/cai2) | codon adaptation index calculations in several modules |
| [pyqt5](https://pypi.python.org/pypi/pyqt5) | future plan for gui |
| [pyperclip](https://pypi.python.org/pypi/pyperclip) | copy sequence to clipboard |
| [pyfiglet](https://pypi.python.org/pypi/pyfiglet) | print nice logotype (pydna.logo() |

### gel

Scipy, matplotlib and pillow (PIL) enable the generation of gel images. Numpy is also
needed, but usually installed as a dependency of biopython.


| Dependency | Function in pydna |
| --------------------------------------------------- | ------------------------------------------------------ |
| [scipy](https://www.scipy.org) | gel simulation with pydna.gel |
| [matplotlib](http://matplotlib.org) ||
| [pillow](https://github.com/python-pillow/Pillow) ||


## Requirements for running tests, coverage and profiling

Expand All @@ -217,28 +246,30 @@ If the modules listed below in the first column are installed, they will provide

for instance by `pip install pytest pytest-cov pytest-doctestplus pytest-profiling coverage nbval requests-mock`

Running the antire test suite also require:
Running the entire test suite also require:

- scipy
- matplotlib
- pillow
- pyparsing
- requests
- cai2
- pyqt5

That can be installed by `pip install pydna[gel,gui,download,express]`
That can be installed by `pip install pydna[clipboard,gel,download,express]`

or by `pip install scipy matplotlib pillow pyparsing requests cai2 pyqt5`
or by `pip install pyparsing requests cai2 scipy matplotlib pillow`


![----]( http://bit.ly/coloredline)

## Contributing

Please direct pull requests towards the `develop` branch.


### Local development

1. Use [Poetry](https://pypi.org/project/poetry) to install depencies and activate virtual environment.
1. Use [Poetry](https://pypi.org/project/poetry) to install dependencies and activate virtual environment.

```bash
# If you want the virtual environment to be created in this folder
Expand Down Expand Up @@ -268,26 +299,19 @@ sphinx-autobuild --watch src/ docs docs/_build/html

```
## Releases
## Automatic testing & Release process
See the [releases](https://github.com/BjornFJohansson/pydna/releases) for changes and releases.
![----]( http://bit.ly/coloredline)
## Automatic testing & Release process
There are two github actions for this package:
- `pydna_test_and_coverage_workflow.yml`
- `pydna_pypi_build_workflow.yml`
- `.github/workflows/pydna_test_and_coverage_workflow.yml`
- `.github/workflows/pydna_pypi_build_workflow.yml`
The `pydna_test_and_coverage_workflow.yml` is triggered on all pushed commits for all branches.
This workflow run tests, doctests and a series of Jupyter notebooks using pytest on Linux, Windows and macOS and all
The test_and_coverage workflow is triggered on all pushed commits for all branches except the `master` branch. This workflow run tests, doctests and a series of Jupyter notebooks using pytest on Linux, Windows and macOS with all
supported python versions.
The other workflow builds a PyPI packages using poetry on
These are triggered by publishing a github release manually from the github interface.
The build workflow builds a PyPI packages using poetry. This workflow is triggered by publishing a Github release manually from the Github web interface.
![----]( http://bit.ly/coloredline)
Expand Down Expand Up @@ -322,8 +346,6 @@ These are triggered by publishing a github release manually from the github inte
Pydna was made public in 2012 on [Google code](https://code.google.com/archive/p/pydna).
:microbe:
:portugal:
48 changes: 24 additions & 24 deletions src/pydna/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -230,30 +230,30 @@
_Path(_os.environ["pydna_data_dir"]).mkdir(parents=True, exist_ok=True)

# find out if optional dependecies for gel module are in place


def _missing_modules_for_gel():
import importlib
from importlib import util

_missing = []
for _optm in ["scipy", "PIL", "numpy", "pyparsing", "requests"]:
_missing.extend([_optm] if not util.find_spec(_optm) else [])
del importlib
del util
return _missing


_missing = _missing_modules_for_gel()

if _missing:
_logger.warning(
"gel simulation will NOT be available." " Missing modules: %s",
", ".join(_missing),
)
else:
_logger.info("gel simulation is available," " optional dependencies were found.")

#
#
# def _missing_modules_for_gel():
# import importlib
# from importlib import util
#
# _missing = []
# for _optm in ["scipy", "PIL", "numpy", "pyparsing", "requests"]:
# _missing.extend([_optm] if not util.find_spec(_optm) else [])
# del importlib
# del util
# return _missing
#
#
# _missing = _missing_modules_for_gel()
#
# if _missing:
# _logger.warning(
# "gel simulation will NOT be available." " Missing modules: %s",
# ", ".join(_missing),
# )
# else:
# _logger.info("gel simulation is available," " optional dependencies were found.")
#

_logger.info("__version__ = %s", __version__)

Expand Down
9 changes: 6 additions & 3 deletions src/pydna/download.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
# This code is part of the Python-dna distribution and governed by its
# license. Please see the LICENSE.txt file that should have been included
# as part of this package.
"""Provides a function for downloading online text files"""
"""Provides a function for downloading online text files."""

import textwrap as _textwrap
import requests as _requests

import os as _os
from pydna._pretty import pretty_str as _pretty_str
from pydna.utils import memorize as _memorize
Expand All @@ -18,9 +18,12 @@

@_memorize("pydna.download.download_text")
def download_text(url):
"""docstring."""
import requests

_module_logger.info("#### DOWNLOAD TEXT ####")
_module_logger.info("url = %s", url)
req = _requests.get(url)
req = requests.get(url)
_module_logger.info("url = %s", str(req))
result = _textwrap.dedent(req.text).strip()
result = result.replace("\r\n", "\n").replace("\r", "\n")
Expand Down
24 changes: 13 additions & 11 deletions src/pydna/gel.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,15 @@

"""docstring."""

from PIL import Image as _Image
from PIL import ImageDraw as _ImageDraw
import numpy as _np
import math as _math
from scipy.interpolate import CubicSpline as _CubicSpline
from pydna.ladders import GeneRuler_1kb_plus as _mwstd


def interpolator(mwstd):
"""docstring."""
interpolator = _CubicSpline(
from scipy.interpolate import CubicSpline

interpolator = CubicSpline(
[len(fr) for fr in mwstd[::-1]],
[fr.rf for fr in mwstd[::-1]],
bc_type="natural",
Expand All @@ -30,16 +28,20 @@ def interpolator(mwstd):


def gel(samples=None, gel_length=600, margin=50, interpolator=interpolator(mwstd=_mwstd)):
import numpy as np
from PIL import Image as Image
from PIL import ImageDraw as ImageDraw

"""docstring."""
max_intensity = 256
lane_width = 50
lanesep = 10
start = 10
samples = samples or [interpolator.mwstd]
width = int(60 + (lane_width + lanesep) * len(samples))
lanes = _np.zeros((len(samples), gel_length), dtype=int)
image = _Image.new("RGB", (width, gel_length), "#ddd")
draw = _ImageDraw.Draw(image)
lanes = np.zeros((len(samples), gel_length), dtype=int)
image = Image.new("RGB", (width, gel_length), "#ddd")
draw = ImageDraw.Draw(image)
draw.rectangle((0, 0, (width, gel_length)), fill=(0, 0, 0))
scale = (gel_length - margin) / interpolator(min(interpolator.x))

Expand Down Expand Up @@ -72,10 +74,10 @@ def gel(samples=None, gel_length=600, margin=50, interpolator=interpolator(mwstd
pass

for i, lane in enumerate(lanes):
max_intensity = _np.amax(lanes[i])
max_intensity = np.amax(lanes[i])
if max_intensity > 256:
lanes[i] = _np.multiply(lanes[i], 256)
lanes[i] = _np.divide(lanes[i], max_intensity)
lanes[i] = np.multiply(lanes[i], 256)
lanes[i] = np.divide(lanes[i], max_intensity)

for i, lane in enumerate(lanes):
x1 = 50 + i * (lane_width + lanesep)
Expand Down
Loading

0 comments on commit e3e7677

Please sign in to comment.