Standard AIKP development flow: Mondiran example

The Mondrian AIKP template is an example of a standard AIKP development workflow.
It is organized into a Python package with a clear separation between general template logic and satellite-specific logic (Sentinel-2 in this case).

Standard AIKP flow includes

  • task creation

  • setting of task specific parameters including filers used by internal Finder

  • fetching the data

  • creation of Stack with internal satellite specific Processor

  • creation of Tensors with Assembler object

  • optional: AIKP custom commands

  • for raster datasets: creation of COG

  • creation of metadata GeoJSON

  • upload (to DB) and publish (to webUI)

Code Structure and Components

Standard flow can (and usually is) in two levels

  • level 1 (mondiran/) = general implementation of the AIKP depending on the use case

    • init.py

    • config.py = Contains TASK_DEFAULTS (e.g. default directories for outputs, index_kind defaulting to “NDVI”, etc.) and RECIPE_DEFAULTS (base recipe metadata) used by the base template.

    • template.py = Defines the class TemplateMondrian (subclass of OCLI’s TaskTemplate) containing common AIKP logic not tied to a specific data source.
      This includes methods for task creation, validation, recipe generation, and CLI command mounting.
      For example, TemplateMondrian.create_task sets up a new task with default parameters and injects search filters via inject_finder_keys.
      The base template also provides a validate_task method that enforces required config values (e.g. ensuring paths exist and index_kind is one of the allowed values) and merges the template’s JSON schema for recipe validation.

    • cli.py = Implements any custom CLI commands for this template, using the Click library.
      Mondrian defines a custom visualize command that is mounted as task template visualize.
      The cli_task_mount method of the template class attaches this command so users can run it from the CLI.
      In Mondrian example, visualize function loads the NumPy output from the assembly step and converts it to a colored raster image (RGBA) for visualization. It uses utility classes (Recipe and Filenames) to locate the output files, applies color mapping and outputs an ENVI raster with four channels (R,G,B,Alpha).

    • recipe_schema.json = Defines the expected structure of a recipe JSON for Mondrian. The template uses this schema to validate any recipe created for the task, ensuring that required fields (like products with a valid index) are present. This helps maintain consistency and catches configuration errors early.

  • level 2 (/mondrian/s2/) = satellite specific implementation

    • init.py = Defines Template as a specialization of the base class for Sentinel-2 data.
      It inherits TemplateMondrian and overrides or extends defaults.
      The subclass merges its Sentinel-2 specific config (TASK_DEFAULTS and RECIPE_DEFAULTS) with the base defaults.
      For example, it sets 'sat_family_name': 's2' to indicate which data finder to use and adds NDMI/NDWI to the list of supported index products.
      The subclass may also override hooks like update_recipe to add metadata (e.g. adding “Index kind” to recipe tags).

    • config.py = Contains additional defaults specific to Sentinel-2. For instance, it sets the sat_family_name used by the data finder and defines naming patterns for outputs.
      It also extends the products list in the recipe defaults to include NDVI, NDMI and NDWI indices.

    • assemble_recipe.py = This module defines how to convert input data (Sentinel-2 Stack created using internal S2 Processor as a list of co-registered ENVI files ) into the final analysis result.
      It specifies:

      • input_list of required stack layers (band files) that will be used as inputs

      • assemble_kernel function that performs the computation on the input bands to produce expected result (spectral indices in this case). The function checks which product (index) is requested and applies the appropriate algorithm/formula and appends to the outputs with the appropriate name.

      • other settings like tnsr_fnames (filenames for output tensors), and tile overlap parameters for processing continuity
        The assembler module is loaded by the OCLI framework’s Assembler, which populates global variables (like the current recipe object, data directories, etc.) and then calls assemble_kernel during execution.

The 2 level structure (base template (TemplateMondrian) and a specialized subclass (Template for Sentinel-2)) allows for reuse of generic logic.
For example, if this demo example needs to be extended to perform the same workflow for Landsat-8 images, only Level-2 Landsat-8 directory needs to be added (with appropriate files inside).

Dependencies

The Mondrian template relies on the OCLI framework for much of its functionality.
OCLI provides the base classes (Task, TaskTemplate), the Finder for satellite data retrieval (+ Landsat-8, Sentinel-1), the stacking Processor for Sentinel-2 (+ Landsat-8, ASTER, WorldView-3, Sentinel-1, TSX/PAZ), and the Assembler that executes assemble_recipe.py.
The architecture is such that Mondrian’s code plugs into these framework components rather than reimplementing them, focusing on specifying what to do (e.g. which bands to use, how to compute the index, how to visualize) while OCLI handles how to do it (data fetching, task management, etc.).

This is a generic pattern for AIKP templates and can be adapted to other geospatial analyses with medium to minimal changes.

Limitations of the standard flow

Input to Stack Processor is “raw” satellite image. Output of Stack Processor is a directory of ENVI files (co-registered and re-sampled if necessary). Input to Assembler are selected ENVI files from the Stack. Output of Assembler is NumPy array (2D or multi-dimensional).

This ensures that whatever the input data it may be, it is always prepared as Analysis Ready Data internally for the Assembler (computation).

This means that standard flow includes:
(Finder) > (not AIKP specific) Processor for STACK creation (ENVI) > (AIKP specific) Assembler for TENSOR creation (NumPy array)

Finder and Stack Processor are not AIKP specific, but general tools inside the OCLI framework.

Regarding the Finder, it is possible to

  • (a) build your own Finder with appropriate API

  • (b) use one of already available Finders

  • (c) input your satellite data manually via rsync or drag-n-drop to the backend and point the master and master_path to them

Similar options are available for Stack Processor:

  • (a) build your own that would create co-registerd ENVI directory as input ARD

  • (b) use one of already available Processors (Sentinel-1, TerraSAR-X, PAZ (radar) and Sentinel-2, Landsat-8, ASTER, WorldView-3 (optical))

Configuration-Driven Behavior

Many aspects of the workflow are driven by config dictionaries and JSON recipes, rather than hard-coded values.
By defining TASK_DEFAULTS and RECIPE_DEFAULTS, the template cleanly separates static configuration (e.g., which indices are supported, what naming convention to use for outputs) from code.

This makes it easier to adapt the template: for a new use case, a developer can adjust these defaults (say, add a new index type or change output metadata) without altering the control flow.

The use of a JSON schema for recipes is a powerful addition – it enforces that any new recipe generated fits the expected format, catching errors if a required field isn’t set.
A new AIKP could provide its own schema to validate domain-specific fields in the recipe.

Framework Hooks

The template relies on OCLI’s class methods that are called at certain times).
For instance, create_task and update_recipe are called by the framework during task setup and recipe creation.
By implementing these hooks, the template injects its custom logic at the right moments.

The developer of a new template can follow the same pattern: implement create_task to initialize anything dynamic (and call inject_finder_keys if using the finder), implement validate_task to enforce any rules for new parameters, and so on.
The framework handles calling these methods, so AIKP developer doesn’t have to manage the sequencing – just provide the behavior.
This event-driven design (hooks for create, validate, upgrade, etc.) keeps the template code concise and focused.