Composing apps
Compose multiple apps into a single pipeline using the + operator, see what happens when types don't match, and observe how NotCompleted propagates through a pipeline without raising exceptions.
Why compose?
Consider an app that performs a molecular evolutionary analysis (fit_model) and another that extracts statistics from the result (extract_stats). You could apply them sequentially:
fitted = fit_model(alignment)
stats = extract_stats(fitted)
Composability simplifies this into a single callable:
app = fit_model + extract_stats
stats = app(alignment)
You can have many more apps in a composed function than just two.
A worked example
We compose three apps: a loader, a processor, and a writer.
from cogent3 import get_app
from scinexus import open_data_store
out_dstore = open_data_store(path_to_dir, suffix="fa", mode="w")
loader = get_app("load_aligned", format_name="fasta", moltype="dna")
cpos3 = get_app("take_codon_positions", 3)
writer = get_app("write_seqs", out_dstore, format_name="fasta")
Using apps sequentially
data = loader("data/primate_brca1.fasta")
just3rd = cpos3(data)
m = writer(just3rd)
Composing into a single pipeline
process = loader + cpos3 + writer
m = process("data/primate_brca1.fasta")
The result is identical, but the composed form is more concise and enables batch processing via apply_to().
Composability rules
App type ordering
Loaders and writers are special cases. If included, a loader must always be first:
app = a_loader + a_generic
If included, a writer must always be last:
app = a_generic + a_writer
Changing the order for either will raise a TypeError.
Type compatibility
Apps define the type of input they accept and the type of output they produce. For two apps to be composed, the output type of the app on the left must overlap with the input type of the app on the right. If they don't match, a TypeError is raised.
NotCompleted propagation
If any step in a composed pipeline returns a NotCompleted, subsequent steps are skipped and the NotCompleted is returned as the final result.
Condition not satisfied
1 2 3 4 5 6 7 8 9 10 11 12 13 | |
- A successful load but a failed selection — the
NotCompletedfromselect_seqsis returned
Caught an exception
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | |
- An error during load —
select_seqsis never called.