File: user_function.rst

package info (click to toggle)
python-cogent 2024.5.7a1%2Bdfsg-3
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 74,600 kB
  • sloc: python: 92,479; makefile: 117; sh: 16
file content (102 lines) | stat: -rw-r--r-- 3,233 bytes parent folder | download
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