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:
your function
Type hints on the function first argument and the function return type.
Note
At present, your function can have only one required argument.
Supported cogent3 types#
If you function takes or returns cogent3 types, you can use the existing type hints. To see what these are, use the defined_types()
function.
from cogent3.app.typing import defined_types
defined_types()
type hint | includes |
---|---|
AlignedSeqsType | ArrayAlignment, Alignment |
UnalignedSeqsType | SequenceCollection |
SeqsCollectionType | ArrayAlignment, SequenceCollection, Alignment |
SeqType | Sequence, ProteinWithStopSequence, DnaSequence, RnaSequence, ByteSequence, ProteinSequence |
PairwiseDistanceType | DistanceMatrix |
TabularType | DictArray, DistanceMatrix, Table |
TreeType | TreeNode, PhyloNode |
SerialisableType | SerialisableType |
BootstrapResultType | bootstrap_result |
HypothesisResultType | hypothesis_result |
ModelCollectionResultType | model_collection_result |
ModelResultType | model_result |
TabularResultType | tabular_result |
GenericResultType | generic_result |
ResultType | tabular_result, bootstrap_result, generic_result, hypothesis_result, model_result |
IdentifierType | IdentifierType |
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.
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
first4 = up_to(index=4)
first4
up_to(index=4)
The repr()
of the instance indicates the wrapped function and the module it’s in.
You use first4()
like all composable apps, e.g.
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
0 | |
a | GCAA |
b | ..TT |
2 x 4 dna alignment
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
.
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
0 | |
A | GCAAGCGTTTAT |
B | ..TTTT..CA.. |
2 x 12 dna alignment
A user app with a different output type#
In this example, we make a function that returns a DistanceMatrix
from an alignment.
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
names | a | b |
---|---|---|
a | 0.0000 | 0.5000 |
b | 0.5000 | 0.0000 |