TF is a generic engine to process text and annotations.
When working with specific corpora, we want to have more power at our fingertips.
We need extra power on top of the core TF engine.
The way we have chosen to do it is via apps. An app is a bunch of extra settings and / or functions and / or styles that feed the advance API.
The advanced API will do its best to generate sensible default settings from the corpus data, but a bit of nudging will usually improve the results of displaying structures of the corpus.
For a list of current corpora, see
Apps usually reside in a subdirectory
app of a repository that holds the corpus data.
Apps can be trivial, completely empty even.
Each TF app consists of a folder with these items, all optional:
A folder with styles, fonts and logos, to be used by web servers such as the
TF browser, see
display.css contains additional styles used for pretty displays.
These styles will be programmatically combined with other styles,
to deliver them to the TF browser on the one hand, and to Jupyter notebooks
on the other hand.
Settings to feed the advanced API for this app. See
Corpus dependent helpers for the advanced API.
If you organize bits of the functionality of a corpus app into modules
to be imported by
app.py, you can put them in this same directory.
import app-dependent modules
If you import these other modules by means of the Python import system using
import module or
from module import name then everything works fine until you
load two apps in the same program, that in turn load their other modules.
As long as different apps load modules with different names, there is no problem.
But if two apps both have a module with the same name, then the first of them
will be loaded, and both apps use the same code.
In order to prevent this, you can use the function
dynamically load these modules. They will be given an app-dependent internal
name, so the Python importer will not conflate them.
Here is how you load auxiliary modules in your
The example is taken from the
uruk app, which loads
See for example the app in the Uruk corpus.
The place to put the
loadModule() calls is in the
__init()__ method of the
TfApp object, before the call to
Here the name of the app and the path to the code directory of the
app are known.
The first argument for
loadModule() is the file name of the module,
loadModule() needs the app name and the path to the code,
but we pass it all
*args, received by
The result of loading the module is a code object, from which you can get all the names defined by the module and their semantics.
atf case, we use the
atfApi() function of the module to add
a bunch of functions defined in that module as methods to the
image case, we add the code object as an attribute to the
so that all its methods can retrieve all names defined by the
Most parts of the advanced API are implemented in the API modules of TF.
Most functions with the
app argument are meant to perform their duty
in two contexts:
- when called in a Jupyter notebook they deliver output meant
for a notebook output cell, using methods provided by the
- when called by the web app they deliver output meant for the TF browser website, generating raw HTML.
When we construct the rich, app-dependent API, we let it know whether it is constructed for the purposes of the Jupyter notebook, or for the purposes of the web app.
We set the attribute
_browse on the
app object to
if we use the
app in the web app context, otherwise in a programming context.
Most of the code in most functions is independent of
The main difference is how to deliver the result:
by a call to an
IPython display method, or by returning raw HTML.
Expand source code Browse git
""" .. include:: ../docs/about/apps.md """