Skip to content

Modality and Classification Schema

Flywheel uses a structured, vocabulary-controlled classification scheme for labeling file content. Each modality (for example, MR, CT, or PET) specifies the valid classification aspects and values for files acquired with that modality.

Unlike free-form metadata in info, classification values are constrained by the modality vocabulary defined on the site.

Warning

Starting in Flywheel 21.4.0, when a gear outputs a file with a classification value that does not match the defined classification schema, Flywheel logs a warning in the job log. In a future major version, invalid classification output will cause the job to fail. Ensure that your site's schema is updated to match users' data workflow needs and that gear output is adhering to this schema. See Upcoming Change: Gear Output Classification Validation for additional information.

What the classification schema is

The classification schema organizes file content along multiple dimensions called aspects. The available aspects and their allowed values depend on the file's modality.

For example, the MR modality defines the following aspects:

  • Intent — Structural, Functional, Localizer, etc.
  • Measurement — T1, T2, Diffusion, etc.
  • Features — 2D, 3D, Multi-Echo, etc.
  • Contrast - Contrast, No Contrast
  • Scan Orientation - Axial, Sagittal, Coronal, Oblique

A Custom aspect is always available for any file regardless of modality, and accepts arbitrary string values.

How classification differs from info metadata

Feature Classification Info
Structure Vocabulary-controlled aspect lists Free-form JSON dict
Validation Values validated against modality schema No validation
Filtering Supported via Finder queries Supported via Finder queries
Purpose Label file content type and intent Store arbitrary key-value data

Managing modality definitions

Modalities are site-wide objects that define which classification aspects and allowed values are available for a given imaging type. The SDK supports full create, read, update, and delete (CRUD) operations on modality definitions.

Modality fields

Field Type Description
id str Modality identifier (e.g., "MR", "CT")
classification dict[str, list[str]] Aspect names mapped to lists of allowed values
active bool Whether the modality is enabled on the site
description str Optional human-readable description

The classification dict maps each aspect name (e.g., "Measurement") to the list of vocabulary values allowed under that aspect.

Listing all modalities

List all modalities
modalities = fw.get_all_modalities()
for mod in modalities:
    print(mod.id, mod.active)

Inspecting the classification vocabulary

The classification vocabulary for each modality is stored in the modality object.

Inspect the MR classification vocabulary
mr = fw.get_modality("MR")
print(mr)

Adding a modality

Use ModalityInput to create a new modality. The id field becomes the modality identifier used in file classification:

Add a new modality
from flywheel.models.modality_input import ModalityInput

fw.add_modality(
    ModalityInput(
        id=modality_id,
        description="Test modality for docs",
        active=True,
        classification={
            "Anatomy": ["Chest", "Abdomen", "Extremity"],
            "View": ["AP", "Lateral", "PA"],
        },
    )
)

Replacing a modality

fw.replace_modality() does a full replacement of the classification vocabulary. Use ModalityModify to supply the updated fields. Unlike ModalityInput, ModalityModify does not take an id — the modality to update is identified by the first argument:

Replace a modality's classification vocabulary
from flywheel.models.modality_modify import ModalityModify

fw.replace_modality(
    modality_id,
    ModalityModify(
        description="Test modality (updated)",
        active=True,
        classification={
            "Anatomy": ["Chest", "Abdomen", "Extremity", "Spine"],
            "View": ["AP", "Lateral", "PA", "Oblique"],
        },
    ),
)

Note

replace_modality overwrites the entire classification dict. Any aspects or values not included in the new definition are removed.

Deleting a modality

Delete a modality
fw.delete_modality(modality_id)

Warning

Deleting a modality removes the classification vocabulary, but does not clear the modality and classification from files. Files already classified with the deleted modality retain their existing classification values and will raise validation errors on some file operations if the deleted modality is not cleared from the file metadata. See Metadata: File Classification for how to replace or remove classifications from files.

Upsert pattern

When syncing modality definitions from an external source, check whether each modality already exists before deciding to create or replace it:

Create or update a modality
from flywheel.models.modality_input import ModalityInput
from flywheel.models.modality_modify import ModalityModify

current_modalities = fw.get_all_modalities()
current_ids = [mod.id for mod in current_modalities]

if modality_id in current_ids:
    fw.replace_modality(
        modality_id,
        ModalityModify(
            classification=new_classification,
            active=True,
            description=new_description,
        ),
    )
else:
    fw.add_modality(
        ModalityInput(
            id=modality_id,
            classification=new_classification,
            active=True,
            description=new_description,
        )
    )