Architecture ============ This page is for whoever maintains cellmap-flow. It says what each module is for, how the main requests travel through them, where state is kept, and the conventions a change has to keep. It describes the package as the 0.3.0 cleanup (PR #103) leaves it. Each module's docstring says more about it, and ``CHANGELOG.md`` at the repository root says what changed and why. Paths below are relative to ``cellmap_flow/``. .. contents:: On this page :local: :depth: 1 Module map ---------- Reading data and running a model ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. list-table:: :header-rows: 1 :widths: 28 72 * - Module - What it is for * - ``io/`` - Reading datasets. It imports nothing from the rest of the package (no ``globals``, Flask, neuroglancer or torch). Import the submodule you need: - ``paths``: where a container ends, and which format a path is; - ``metadata``: ``read_array_meta``, one ``ArrayMeta`` for zarr v2 and v3, N5 and precomputed; ``list_levels`` for a pyramid; - ``multiscale``: the pyramid level for a voxel size, and ``closest_raw_scale``; - ``geometry``: ``Grid`` and ``Box``, world nanometres to voxels and back; ``list_populated_chunks``; - ``source``: ``open_array`` and ``read_padded``, tensorstore reads that pad what lies outside the array; - ``ome``: OME-NGFF translation to corner and back, and the ``multiscales`` attributes writers use. * - ``image_data_interface.py`` - ``ImageDataInterface``: a dataset read in world coordinates through the input chain. It picks the level, keeps the grid and the array, and pads reads. Model scripts use it, so its path is public. * - ``norm/`` - ``input_normalize``: the input normalizers (``InputNormalizer`` subclasses) and ``SerializableInterface``. ``safe_expression``: the whitelist that Lambda normalizer and postprocessor expressions are checked against. * - ``post/`` - ``postprocessors``: the postprocessors (``PostProcessor`` subclasses). * - ``pipeline_spec.py`` - ``PipelineSpec``: the normalization and postprocessing chain as data, with a reader for every form it travels in (layer URL blob, YAML ``json_data``, finetune manifest, pipeline-builder nodes), its ``digest()`` and ``build()``. Also ``chain_output_dtype``, ``chain_num_channels`` and ``chain_is_segmentation``. * - ``process_chain.py`` - ``process_chain()``: the process's chain, its live steps and their configured ``spec``, changed only by ``set()``. See `Where state lives`_. * - ``inference/runner.py`` - ``ModelRunner``: a model on its device, the warmup forward (which checks the declared shapes, probes the output range and decides on fp16), and ``predict`` of an output region as ``(C, *spatial)``, with no postprocessing and no process-wide state. ``DeviceSlots``: how many chunks may use the device at once, in arrival order. * - ``inferencer.py`` - ``Inferencer``: a ``ModelRunner`` that also applies a chain (``process_chunk``). ``predict`` and ``apply_postprocess`` stay importable here for model scripts. Models ~~~~~~ .. list-table:: :header-rows: 1 :widths: 28 72 * - Module - What it is for * - ``models/configs/`` - One module per model type. ``base`` has ``ModelConfig`` (its ``config``, ``geometry``, ``to_dict()`` and ``command``) and ``Config``; then ``script``, ``dacapo``, ``fly``, ``bio``, ``cellmap``, ``finetune`` and ``huggingface``. * - ``models/models_config.py`` - The classes' public import path, which the docs and plugins use, and ``Config``. * - ``models/registry.py`` - The model types (every ``ModelConfig`` subclass, a plugin's included) and how a config is built from a YAML entry, command-line strings or the dashboard's form: ``model_types``, ``build_model(s)``, ``coerce_cli_args``, ``coerce_form_params``, ``click_options``, ``instantiate_model_config``, ``describe_types``. * - ``models/geometry.py`` - ``ModelGeometry``: a model's shapes and voxel sizes, read once from its config, with the context and block shape derived. * - ``models/geometry_cache.py`` - A model's geometry without building the model: from a running server's ``model_info``, else a cache file, else a build. * - ``models/hf_catalog.py`` - The cellmap models on the Hugging Face Hub, for the Models tab. * - ``models/model_merger.py`` - Merging several models' outputs in a blockwise run (``model_mode``). * - ``models/models.yaml`` - The Models tab's catalog. * - ``models/model_registry.py`` - A deprecated alias; see `Deprecated in 0.3.0`_. Serving and jobs ~~~~~~~~~~~~~~~~ .. list-table:: :header-rows: 1 :widths: 28 72 * - Module - What it is for * - ``server.py`` - ``CellMapFlowServer``, the inference server: one model's output served as a zarr, plus ``/__control__/model_info`` and ``/__control__/restart``. It prints its address and writes the ready file. * - ``serving/launch.py`` - The one place a server's command line is built (``server_argv``, ``server_argv_for``, ``server_command``). * - ``serving/protocol.py`` - What a layer URL carries to a server: ``ARGS_KEY``, ``encode_to_str``, ``decode_to_json``, ``split_dataset_url``; and ``IP_PATTERN``, the markers a server prints its address between. * - ``serving/virtual_zarr.py`` - The served zarr's metadata and chunk-key arithmetic, with no Flask. * - ``serving/client.py`` - ``fetch_model_info``: ask a running server about its model. * - ``serving/probe.py`` - What a model's output range says about the postprocessing it needs. * - ``serving/restart_token.py`` - The secret a finetune job's server takes a restart with. * - ``jobs/`` - Running jobs on LSF or on this machine, without importing ``globals``, Flask or torch at module level: - ``spec``: ``JobSpec``, ``Job``, ``JobStatus``, ``JobStartError``; - ``lsf``: ``bsub_argv`` (the one place a bsub line is built), ``submit``, ``LSFJob``, ``statuses`` (one bjobs call for many jobs); - ``local``: ``LocalJob``, for when there is no LSF; - ``queues``: which GPU queues are usable, and the order to try them; - ``site``: ``SiteProfile``, the cluster's numbers (queues, cores, walltime, timeouts); only ``JANELIA`` exists; - ``settings``: ``launcher_settings()``, the settings saved in ``~/.cellmap_flow/server_config.yaml`` (queue, charge group, walltime, ...), with their defaults; - ``ready``: the file a server writes once it knows its address; - ``launch``: ``start_hosts`` (the policy over the others), ``submit_bsub_job``, ``started_jobs``, ``install_cleanup_handlers``, ``SERVER_COMMAND`` and ``SERVER_LOG_DIR``. The viewer and the dashboard ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. list-table:: :header-rows: 1 :widths: 28 72 * - Module - What it is for * - ``viewer/`` - The neuroglancer viewer. It never imports or starts the dashboard; callers pass what a layer needs. (The raw layer is read through ``ImageDataInterface``, and so through the process's input chain, ``process_chain()``.) - ``bootstrap``: ``new_viewer()``; - ``layers``: ``prediction_layer``, ``prediction_source``, ``prediction_shader_for``, ``prediction_voxel_override`` and ``raw_layer``, which every path that shows a layer builds it with; - ``raw``: ``get_raw_layer`` (a pyramid as one ``ScalePyramid``), and the shaders. * - ``dashboard/app.py`` - The Flask app: its blueprints, the log panel's handler, and ``create_and_run_app``. * - ``dashboard/state.py`` - ``Session`` and ``get_session()``; see `Where state lives`_. * - ``dashboard/requests.py`` - The typed bodies of the POST routes (pydantic), and ``parse``, which answers a bad body with a 400 ``{"success": false, "error"}`` before anything changes. * - ``dashboard/progress.py`` - How far a long request has got (a YAML crop import, a resume), under the ``load_id`` the page polls with. * - ``dashboard/finetune_layers.py`` - The job manager's listener: a finetuned model's viewer layer, and its ``FinetuneModelConfig`` among the session's models. * - ``dashboard/finetune_utils.py`` - Hands the session's MinIO state and volume records to ``finetune.session``'s MinIO and sync functions. * - ``dashboard/services/`` - ``launch``: start the Models tab's picks and show them. ``startup``: ``generate_neuroglancer_url``, the CLIs' last step (the viewer with their models, then the dashboard). * - ``dashboard/routes/`` - One blueprint per area: - ``index_page``: ``/`` and ``/api/set-data``; - ``pipeline``: ``PUT /api/pipeline``, its two deprecated aliases, ``/api/blockwise-config``, ``/update/equivalences``; - ``pipeline_builder_page``: ``/pipeline-builder``; - ``models``: the model form, the catalog and Hugging Face picks, the saved settings, GPU queues, job logs, ``/api/export-config``; - ``model_advice``, ``blockwise``, ``bbx_generator`` (the box tool), ``logging_routes`` (the log stream), ``review_routes``; - ``finetune/``: ``training``, ``annotation_core``, ``annotation_sessions``, ``yaml_crops``, ``overlay``, ``good_regions``, ``instance_correction`` and ``layers``, all on the blueprint in ``finetune/blueprint.py``, with shared helpers in ``finetune/common.py``. * - ``dashboard/templates/``, ``dashboard/static/`` - The two pages; below. The pages are ES modules served as they are, with no bundler: .. code-block:: text dashboard/templates/ index.html the dashboard page; includes _dashboard.html and the _input_tab, _output_tab, _models_tab, _finetune_tab and _review_tab partials pipeline_builder_v2.html the pipeline builder bbox_json_template.html dashboard/static/css/ tokens.css (the palette), dark.css, pipeline_builder.css dashboard/static/js/ lib/ api, dom, page-data, poll, sortable, sse: know no page shared/ gpu-queues, op-chain, server-config: used by both pages dashboard/ main.js (the page's entry), connect, models-tab, model-advice; finetune/ and review/, each an index.js that wires one module per part of its tab pipeline-builder/ main.js (the entry), state, canvas, nodes, palette, io, blockwise, bbx, dialogs, log-panel, messages, model-config-modal, output-channels vendor/js-yaml.js A template hands its scripts data as JSON, in ``