Writing your own apps#

The app infrastructure is provided by the scinexus package. See the scinexus documentation for full details on define_app, app types, handling NotCompleted, and citations.

Below are cogent3-specific examples showing how to write apps that work with cogent3 data types.

Available cogent3 types#

You can use existing type hints if your function takes or returns cogent3 types.

from cogent3.app.typing import defined_types

defined_types()
To use a type hint, from cogent3.app import typing
An app which uses one of these hints is compatible with the indicated types.
type hintincludes
UnionTypeUnionType
AlignedSeqsTypeAlignment
UnalignedSeqsTypeSequenceCollection
SeqsCollectionTypeAlignment, SequenceCollection
SeqTypeByteSequence, DnaSequence, ProteinSequence, ProteinWithStopSequence, RnaSequence, Sequence
PairwiseDistanceTypeDistanceMatrix
TabularTypeDictArray, DistanceMatrix, Table
TreeTypePhyloNode
BootstrapResultTypebootstrap_result
HypothesisResultTypehypothesis_result
ModelCollectionResultTypemodel_collection_result
ModelResultTypemodel_result
TabularResultTypetabular_result
GenericResultTypegeneric_result
ResultTypebootstrap_result, generic_result, hypothesis_result, model_result, tabular_result
SerialisableTypeSerialisableType
IdentifierTypeDataMemberABC, Path, str

Note

You don’t have to use cogent3 types. You can also use standard Python types.

Defining a cogent3 app from a function#

We write a function that takes a cogent3 alignment and returns the first n positions.

from scinexus.composable import define_app
from cogent3.app.typing import AlignedSeqsType

@define_app
def n_positions(val: AlignedSeqsType, n=2) -> AlignedSeqsType:
    return val[:n]

The critical elements are:

  1. The define_app decorator is used.

  2. Type hints are specified for the function’s first argument and its return type.

Using the custom app

We create an app instance for a specific value of n.

first4 = n_positions(n=4)
first4
n_positions(n=4)

The instance’s repr() indicates the wrapped function and the argument values. You use first4() like all composable apps, e.g.

from cogent3 import make_aligned_seqs

aln = make_aligned_seqs(
    dict(a="GCAAGCGTTTAT", b="GCTTTTGTCAAT"), moltype="dna"
)
result = first4(aln)
result
0
aGCAA
b..TT

2 x 4 dna alignment

Defining a cogent3 app from a class#

from scinexus.composable import define_app
from cogent3.app.typing import AlignedSeqsType

@define_app
class n_positions:
    def __init__(self, n=2):
        self.n = n

    def main(self, val: AlignedSeqsType) -> AlignedSeqsType:
        return val[:self.n]

The critical elements are:

  1. The define_app decorator is used.

  2. The class has a main() method.

  3. Type hints are specified for the main() method’s first argument and its return type.

Using the custom app

This is identical to what we did above.

first4 = n_positions(n=4)

# we use the alignment defined above

result = first4(aln)
result
0
aGCAA
b..TT

2 x 4 dna alignment

App naming conventions#

Use words in lower case separated by underscores (e.g. lower_case) to name your apps. Apps are callable, just like functions, and the PEP8 guidelines specify this naming style.

If you will make your app available on the Python package index, we recommend prefixing each app with your package name. For example, the piqtree2 library distributes apps with names such as piqtree_phylo.

See scinexus documentation for how to add a citation to your app.

How to get the citations for the apps you use#

Correctly attributing the authors of algorithms and software is a requirement of good scientific practice. The .citations property on an app instance returns its citations as a tuple.

app = some_app()
app.citations
(Software(
     author=['Doe, J', 'Smith, A'],
     title='My Sequence Filter',
     year=2025,
     version='0.1.0',
     url='https://example.com/my-filter',
 ),)

You can get the BibTeX string directly via the .bib property.

print(app.bib)
@software{Doe.2025,
  author    = {Doe, J and Smith, A},
  title     = {My Sequence Filter},
  year      = {2025},
  version   = {0.1.0},
  url       = {https://example.com/my-filter},
}
Citations in a composed pipeline

When apps are composed into a pipeline, .citations collects unique citations from all apps in the chain.

from cogent3 import get_app

loader = get_app("load_aligned", moltype="dna", format_name="fasta")
pipeline = loader + some_app()
pipeline.citations
(Software(
     author=['Doe, J', 'Smith, A'],
     title='My Sequence Filter',
     year=2025,
     version='0.1.0',
     url='https://example.com/my-filter',
 ),
 Software(
     key='cogent3',
     author=['Huttley, Gavin', 'Caley, Katherine', 'Fotovat, Nabi', 'Ma, Stephen Ka-Wah', 'Koh, Moses', 'Morris, Richard', 'McArthur, Robert', 'McDonald, Daniel', 'Jaya, Fred', 'Maxwell, Peter', 'Martini, James', 'La, Thomas', 'Lang, Yapeng'],
     title='{cogent3}: making sense of sequence',
     year=2025,
     doi='10.5281/zenodo.16519079',
     url='https://cogent3.org',
 ))

The .bib property gives the combined BibTeX for the whole pipeline.

print(pipeline.bib)
@software{Doe.2025,
  author    = {Doe, J and Smith, A},
  title     = {My Sequence Filter},
  year      = {2025},
  version   = {0.1.0},
  url       = {https://example.com/my-filter},
}

@software{cogent3,
  author    = {Huttley, Gavin and Caley, Katherine and Fotovat, Nabi and Ma, Stephen Ka-Wah and Koh, Moses and Morris, Richard and McArthur, Robert and McDonald, Daniel and Jaya, Fred and Maxwell, Peter and Martini, James and La, Thomas and Lang, Yapeng},
  title     = {{cogent3}: making sense of sequence},
  year      = {2025},
  doi       = {10.5281/zenodo.16519079},
  url       = {https://cogent3.org},
}

Note

When a composed pipeline is run via apply_to(), citations are automatically saved in the output data store. See data store citations for how to inspect and export them.