1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102
|
Turn your functions into composable apps
========================================
Just use the ``define_app`` decorator! This generates a wrapper class that has a reference to your function and can then become part of a composed function.
You need two things:
1. your function
2. Type hints on the function's first argument and the function return type.
.. note:: At present, your function can have only one required argument.
Supported cogent3 types
-----------------------
If your function takes or returns ``cogent3`` types, you can use the existing type hints. To see what these are, use the ``defined_types()`` function.
.. jupyter-execute::
from cogent3.app.typing import defined_types
defined_types()
.. note:: You don't have to use cogent3 types, you can also use standard python types.
A simple example
----------------
Let's make an app that returns the elements of an alignment up to a specified index, with the index being a keyword argument. We now define a decorated function ``up_to`` and import the type hints and the decorator.
.. jupyter-execute::
from cogent3.app.composable import define_app
from cogent3.app.typing import AlignedSeqsType
@define_app
def up_to(val: AlignedSeqsType, index=2) -> AlignedSeqsType:
return val[:index]
We create an app instance for a specific value of ``index``
.. jupyter-execute::
first4 = up_to(index=4)
first4
The ``repr()`` of the instance indicates the wrapped function and the module it's in.
You use ``first4()`` like all composable apps, e.g.
.. jupyter-execute::
from cogent3 import make_aligned_seqs
aln = make_aligned_seqs(
data=dict(a="GCAAGCGTTTAT", b="GCTTTTGTCAAT"), array_align=False, moltype="dna"
)
result = first4(aln)
result
Renaming sequences
------------------
This time we wrap a method call on a ``SequenceCollection`` (and the alignment sub-classes) for renaming sequences. We also illustrate here that to support both aligned and unaligned data types as input/output, we have to include these in the construction of the custom function.
.. note:: The ``SerialisableType`` indicates the data has the ability to be converted to ``json``.
.. jupyter-execute::
from typing import Union
from cogent3.app.composable import define_app
from cogent3.app.typing import SeqsCollectionType, SerialisableType
T = Union[SeqsCollectionType, SerialisableType]
@define_app
def rename_seqs(seqs: SeqsCollectionType) -> T:
"""upper case names"""
return seqs.rename_seqs(lambda x: x.upper())
renamer = rename_seqs()
result = renamer(aln)
result
A user app with a different output type
---------------------------------------
In this example, we make a function that returns a ``DistanceMatrix`` from an alignment.
.. jupyter-execute::
from cogent3.app.composable import define_app
from cogent3.app.typing import AlignedSeqsType, PairwiseDistanceType
@define_app
def get_dists(aln: AlignedSeqsType, calc="hamming") -> PairwiseDistanceType:
return aln.distance_matrix(calc=calc, show_progress=False)
percent_dist = get_dists(calc="pdist")
result = percent_dist(aln)
result
|