Custom composable apps¶
You can make a simple customised app using the user_function
app. This is a wrapper class that takes a reference to your function and the input, output and data types. The resulting app can then become part of a composed function.
Defining a user_function
requires you consider four things.
func
A function you have written. This is required.
input_types
A type, or collection of type that your function can handle. This setting dictates what other apps have an output that is a compatable input for your function.
output_types
A type, or collection of type that your function produces. This setting dictates what other apps can have yours as input.
data_types
The data class names, as strings, that your function can handle. Not required, but useful.
A simple example¶
We make a very simple function first4
, that returns the first 4 elements of an alignment.
>>> def first4(val):
... return val[:4]
Now we define a user_function
instance that takes and returns an ALIGNED_TYPE
.
>>> from cogent3.app.composable import user_function, ALIGNED_TYPE
>>> just4 = user_function(first4, input_types=ALIGNED_TYPE, output_types=ALIGNED_TYPE, data_types="Alignment")
The repr()
of your user_function
instance indicates the wrapped function and the module it’s in.
>>> just4
user_function(name='first4', module='__main__')
You use it like all composable apps which we demonstrate using a small sample alignment.
>>> from cogent3 import make_aligned_seqs
>>> aln = make_aligned_seqs(data=dict(a="GCAAGCGTTTAT", b="GCTTTTGTCAAT"), array_align=False)
>>> result = just4(aln)
>>> result
2 x 4 text alignment: a[GCAA], b[GCTT]
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 SERIALISABLE_TYPE
indicates the data has the ability to be converted to json
.
>>> from cogent3.app.composable import user_function, ALIGNED_TYPE, SEQUENCE_TYPE, SERIALISABLE_TYPE
>>> def renamer(aln):
... """upper case names"""
... return aln.rename_seqs(lambda x: x.upper())
>>> rename_seqs = user_function(renamer,
... input_types=(ALIGNED_TYPE, SEQUENCE_TYPE),
... output_types=SERIALISABLE_TYPE,
... data_types=("SequenceCollection", "Alignment", "ArrayAlignment"))
>>> result = rename_seqs(aln)
>>> result.names
['A', 'B']
A user function for with a different output type¶
In this example, we make an function that returns DistanceMatrix
of an alignment.
>>> from cogent3.app.composable import user_function, ALIGNED_TYPE, PAIRWISE_DISTANCE_TYPE
>>> def _get_dist(aln):
... return aln.distance_matrix(calc="hamming", show_progress=False)
>>> get_dist = user_function(_get_dist, input_types=ALIGNED_TYPE,
... output_types=PAIRWISE_DISTANCE_TYPE,
... data_types=("Alignment", "ArrayAlignment"))
>>> result = get_dist(aln)
>>> result
=====================
a b
---------------------
a 0.0000 6.0000
b 6.0000 0.0000
---------------------