diff --git a/datalab/gui/applications.py b/datalab/gui/applications.py index 4ef227595..2f3bef5c7 100644 --- a/datalab/gui/applications.py +++ b/datalab/gui/applications.py @@ -40,6 +40,7 @@ "ApplicationsDialog", "RecipeCard", "get_application_plugins", + "get_declared_metadata_keys", "get_plugin_icon", "record_application_use", "set_application_hidden", @@ -312,6 +313,27 @@ def get_application_plugins() -> tuple[PluginBase, ...]: return tuple(sorted(plugins, key=lambda plugin: plugin.info.name.casefold())) +def get_declared_metadata_keys(object_type: str) -> list[tuple[str, str]]: + """Return the metadata keys expected by the methods of application plugins + + Args: + object_type: type of the objects carrying the metadata ("signal" or + "image") + + Returns: + ``(key, description)`` pairs, in declaration order, without duplicates + """ + keys: dict[str, str] = {} + for plugin in get_application_plugins(): + for recipe in plugin.get_recipes(): + for slot in recipe.inputs: + if slot.object_type.value != object_type: + continue + for requirement in slot.metadata: + keys.setdefault(requirement.key, requirement.description) + return list(keys.items()) + + def record_application_use(plugin_id: str) -> None: """Remember an application as the most recently used one diff --git a/datalab/gui/main.py b/datalab/gui/main.py index 3bb091fc8..ee05be3ed 100644 --- a/datalab/gui/main.py +++ b/datalab/gui/main.py @@ -995,6 +995,10 @@ def show_applications(self, plugin_id: str | None = None) -> None: panel.objview.SIG_SELECTION_CHANGED.connect( self.__applications_dialog.schedule_readiness_update ) + # Metadata edits change readiness without changing the selection + panel.SIG_OBJECT_MODIFIED.connect( + self.__applications_dialog.schedule_readiness_update + ) self.tabwidget.currentChanged.connect( self.__applications_dialog.schedule_readiness_update ) diff --git a/datalab/gui/panel/base.py b/datalab/gui/panel/base.py index 80a2ec2be..1e1ecb399 100644 --- a/datalab/gui/panel/base.py +++ b/datalab/gui/panel/base.py @@ -74,6 +74,7 @@ from datalab.config import APP_NAME, Conf, _ from datalab.env import execenv from datalab.gui import actionhandler, objectview +from datalab.gui.applications import get_declared_metadata_keys from datalab.gui.newobject import ( CREATION_PARAMETERS_OPTION, LEGACY_CREATION_PARAMETERS_OPTION, @@ -2493,9 +2494,17 @@ def get_known_metadata_keys(self, objs: Sequence[TypeObj]) -> list[tuple[str, st objs: selected objects Returns: - ``(key, description)`` pairs + ``(key, description)`` pairs: the keys found on the objects, then the + keys expected by the methods of application plugins """ - return collect_metadata_keys(objs) + keys = collect_metadata_keys(objs) + found = {key for key, _description in keys} + keys.extend( + (key, description) + for key, description in get_declared_metadata_keys(self.PANEL_STR_ID) + if key not in found + ) + return keys def add_metadata(self, param: AddMetadataParam | None = None) -> None: """Add metadata item to selected object(s) diff --git a/datalab/gui/recipe_inputs.py b/datalab/gui/recipe_inputs.py index 379d8c7cc..236854c38 100644 --- a/datalab/gui/recipe_inputs.py +++ b/datalab/gui/recipe_inputs.py @@ -144,6 +144,11 @@ def format_readiness( RecipeReadinessStatus.NO_INPUT: _("Select the input data in the workspace"), } reasons = [format_input_issue(issue, descriptor) for issue in readiness.issues] + if any( + issue.code is RecipeInputIssueCode.MISSING_METADATA + for issue in readiness.issues + ): + reasons.append(_("To set it, use Edit > Metadata > Add metadata...")) if readiness.status is not RecipeReadinessStatus.NO_INPUT: reasons.extend( format_diagnostic(diagnostic) for diagnostic in readiness.diagnostics diff --git a/datalab/locale/fr/LC_MESSAGES/datalab.po b/datalab/locale/fr/LC_MESSAGES/datalab.po index c00e51ba4..39427179b 100644 --- a/datalab/locale/fr/LC_MESSAGES/datalab.po +++ b/datalab/locale/fr/LC_MESSAGES/datalab.po @@ -4593,3 +4593,6 @@ msgstr "Multiplie les valeurs numériques, par ex. 0.001 pour convertir des ms e msgid "unchanged" msgstr "inchangé" + +msgid "To set it, use Edit > Metadata > Add metadata..." +msgstr "Pour la définir, utilisez Édition > Métadonnées > Ajouter des métadonnées..." diff --git a/datalab/tests/features/plugins/applications_dialog_test.py b/datalab/tests/features/plugins/applications_dialog_test.py index 38a25f6b4..964eefbce 100644 --- a/datalab/tests/features/plugins/applications_dialog_test.py +++ b/datalab/tests/features/plugins/applications_dialog_test.py @@ -6,6 +6,8 @@ from types import SimpleNamespace +import numpy as np +import sigima.objects from guidata.configtools import get_icon from qtpy import QtCore as QC from qtpy import QtGui as QG @@ -18,6 +20,7 @@ from datalab.gui.applications import ( ApplicationsDialog, get_application_plugins, + get_declared_metadata_keys, record_application_use, set_application_hidden, set_application_pinned, @@ -314,6 +317,7 @@ def test_application_page_shows_readiness_of_each_method() -> None: text = card.readiness_label.text() assert "cannot be analyzed" in text assert "Flat frames: metadata 'exposure_s' missing on 2" in text + assert "Edit > Metadata > Add metadata..." in text # The method item shows the readiness without being opened toolbox = dialog.application_pages[0].toolbox assert "cannot be analyzed" in toolbox.itemToolTip(0) @@ -515,6 +519,12 @@ def test_main_window_exposes_applications_catalog(monkeypatch) -> None: "exec", lambda dialog: executed.append(dialog), ) + updates: list[tuple] = [] + monkeypatch.setattr( + main.ApplicationsDialog, + "schedule_readiness_update", + lambda _dialog, *args: updates.append(args), + ) with datalab_test_app_context(console=False, exec_loop=False) as window: menu_actions = window.menuBar().actions() @@ -541,6 +551,40 @@ def test_main_window_exposes_applications_catalog(monkeypatch) -> None: assert window.findChildren(ApplicationsDialog) == [dialog] + # Editing objects (e.g. their metadata) re-assesses the methods + updates.clear() + window.imagepanel.SIG_OBJECT_MODIFIED.emit() + assert updates + + +def test_add_metadata_suggests_keys_declared_by_applications() -> None: + """Add metadata offers the keys expected by application methods""" + application = _plugin( + "org.example.camera", + "Camera Characterization", + frozenset({PluginCapability.APPLICATION}), + recipes=(RECIPE,), + ) + with datalab_test_app_context(console=False, exec_loop=False) as window: + # DataLab unregisters the plugins on close: restore the registry first + registry = PluginRegistry.get_plugins() + previous_plugins = list(registry) + registry[:] = [application] + try: + assert get_declared_metadata_keys("image") == [ + ("exposure_s", "Exposure time") + ] + assert get_declared_metadata_keys("signal") == [] + image = sigima.objects.create_image("Flat", np.zeros((2, 2))) + image.metadata["gain"] = 2 + assert window.imagepanel.get_known_metadata_keys([image]) == [ + ("gain", "e.g. 2"), + ("exposure_s", "Exposure time"), + ] + assert window.signalpanel.get_known_metadata_keys([]) == [] + finally: + registry[:] = previous_plugins + def test_application_commands_delegate_to_plugin_contracts(monkeypatch) -> None: """Each catalog command calls its plugin entry point and keeps the dialog.""" diff --git a/doc/features/common/overview.rst b/doc/features/common/overview.rst index ddf2d3393..756945634 100644 --- a/doc/features/common/overview.rst +++ b/doc/features/common/overview.rst @@ -47,7 +47,7 @@ A **Welcome** page is shown next to the signal and image views when DataLab star When application plugins are installed, an **Applications** section at the top of the page shows their tiles: clicking the main tile of an application opens its page in the **Applications** catalog, or starts the main action provided by the plugin. An application may provide other tiles, for example to open an example directly: they are shown next to its main tile when the section has room for them, and otherwise move to the menu of the main tile. This menu, opened from the "…" button of the main tile or by right-clicking it, also lets you pin the application to the top of the section or hide it from the welcome page. Pinned applications come first, then recently used ones, then the others by name. The section is limited to two rows of tiles by default (this number may be changed in the :ref:`settings`): when more applications are installed, the last tile gives the number of applications left out and opens the catalog. The "Browse all applications..." button also opens the catalog, where a search field filters applications by name or description, and where the "Show on welcome page" and "Pin to the welcome page" check boxes of each application change the same preferences (see :ref:`about_plugins`). -On the page of an application, the methods are listed one below the other, followed by the tools and datasets of the application, if any: clicking a title opens its section and closes the one previously open. The colored dot before each method tells whether the current selection can be analyzed, and its tooltip gives the reason. The open method presents the inputs it expects and this status in detail. "Run on selection..." starts the method, and asks you to assign the selected objects to its inputs only when needed. The examples designed for a method are listed below it: "Try with this example" opens the example and runs the method with suitable parameters. The vertical strip between the application list and the page hides the list, or shows it again: the window shrinks or grows accordingly, and DataLab remembers this choice. +On the page of an application, the methods are listed one below the other, followed by the tools and datasets of the application, if any: clicking a title opens its section and closes the one previously open. The colored dot before each method tells whether the current selection can be analyzed, and its tooltip gives the reason. The open method presents the inputs it expects and this status in detail. When metadata are missing, the status points to "Edit > Metadata > Add metadata...", and it is updated as soon as objects are modified. "Run on selection..." starts the method, and asks you to assign the selected objects to its inputs only when needed. The examples designed for a method are listed below it: "Try with this example" opens the example and runs the method with suitable parameters. The vertical strip between the application list and the page hides the list, or shows it again: the window shrinks or grows accordingly, and DataLab remembers this choice. The Welcome page is a regular dockable panel: as soon as a signal or an image is created or opened, the corresponding view is brought to the front, and the Welcome page remains available as a tab. It may be closed like any other panel, and reopened at any time from the "Welcome page" entry of the "?" (Help) menu or from the "View" menu; it is also reopened automatically when the current panel becomes empty. The "Show welcome page when the current panel is empty" check box, at the bottom of the page, controls this automatic display, including at startup (this option is also available in the :ref:`settings`). diff --git a/doc/features/image/menu_edit.rst b/doc/features/image/menu_edit.rst index 62b179cbc..995532da1 100644 --- a/doc/features/image/menu_edit.rst +++ b/doc/features/image/menu_edit.rst @@ -171,7 +171,7 @@ sample names, processing steps, or any other custom information. When you select "Add metadata..." from the Edit menu, a dialog appears where you can: - **Metadata key**: Enter the name of the metadata field to add (letters, digits, ``_``, ``.`` and ``-``, e.g. a plugin key such as ``plugin.org.example.my-plugin.gain``) -- **Known keys**: Pick a key already present on the selected images to copy it into the metadata key +- **Known keys**: Pick a key already present on the selected images, or a key expected by the methods of the installed application plugins, to copy it into the metadata key - **Value pattern**: Define a pattern for the metadata value using Python format strings - **Extraction pattern**: Optionally, extract the value from the formatted text with a Python regular expression: its first group, or the whole match if it has no group, becomes the value - **If no match**: Leave images without a match unchanged (default), or report an error diff --git a/doc/features/signal/menu_edit.rst b/doc/features/signal/menu_edit.rst index 3559e6ca5..b15b9bb1c 100644 --- a/doc/features/signal/menu_edit.rst +++ b/doc/features/signal/menu_edit.rst @@ -166,7 +166,7 @@ sample names, processing steps, or any other custom information. When you select "Add metadata..." from the Edit menu, a dialog appears where you can: - **Metadata key**: Enter the name of the metadata field to add (letters, digits, ``_``, ``.`` and ``-``, e.g. a plugin key such as ``plugin.org.example.my-plugin.gain``) -- **Known keys**: Pick a key already present on the selected signals to copy it into the metadata key +- **Known keys**: Pick a key already present on the selected signals, or a key expected by the methods of the installed application plugins, to copy it into the metadata key - **Value pattern**: Define a pattern for the metadata value using Python format strings - **Extraction pattern**: Optionally, extract the value from the formatted text with a Python regular expression: its first group, or the whole match if it has no group, becomes the value - **If no match**: Leave signals without a match unchanged (default), or report an error diff --git a/doc/locale/fr/LC_MESSAGES/features/common/overview.po b/doc/locale/fr/LC_MESSAGES/features/common/overview.po index 4db324674..fbe6128e6 100644 --- a/doc/locale/fr/LC_MESSAGES/features/common/overview.po +++ b/doc/locale/fr/LC_MESSAGES/features/common/overview.po @@ -51,8 +51,8 @@ msgstr "interroger l':ref:`ai_assistant`, suivre la visite guidée, lancer la d msgid "When application plugins are installed, an **Applications** section at the top of the page shows their tiles: clicking the main tile of an application opens its page in the **Applications** catalog, or starts the main action provided by the plugin. An application may provide other tiles, for example to open an example directly: they are shown next to its main tile when the section has room for them, and otherwise move to the menu of the main tile. This menu, opened from the \"…\" button of the main tile or by right-clicking it, also lets you pin the application to the top of the section or hide it from the welcome page. Pinned applications come first, then recently used ones, then the others by name. The section is limited to two rows of tiles by default (this number may be changed in the :ref:`settings`): when more applications are installed, the last tile gives the number of applications left out and opens the catalog. The \"Browse all applications...\" button also opens the catalog, where a search field filters applications by name or description, and where the \"Show on welcome page\" and \"Pin to the welcome page\" check boxes of each application change the same preferences (see :ref:`about_plugins`)." msgstr "Lorsque des plugins d'application sont installés, une section **Applications** en haut de la page affiche leurs tuiles : un clic sur la tuile principale d'une application ouvre sa page dans le catalogue **Applications**, ou lance l'action principale fournie par le plugin. Une application peut proposer d'autres tuiles, par exemple pour ouvrir directement un exemple : elles sont affichées à côté de sa tuile principale lorsque la section a la place nécessaire, et passent sinon dans le menu de la tuile principale. Ce menu, ouvert depuis le bouton « … » de la tuile principale ou par un clic droit sur celle-ci, permet aussi d'épingler l'application en tête de la section ou de la masquer de la page d'accueil. Les applications épinglées viennent en premier, puis celles utilisées récemment, puis les autres par ordre alphabétique. La section est limitée par défaut à deux lignes de tuiles (ce nombre peut être modifié dans les :ref:`settings`) : lorsque davantage d'applications sont installées, la dernière tuile indique le nombre d'applications non affichées et ouvre le catalogue. Le bouton « Parcourir toutes les applications... » ouvre également le catalogue, où un champ de recherche filtre les applications par nom ou par description, et où les cases à cocher « Afficher sur la page d'accueil » et « Épingler sur la page d'accueil » de chaque application modifient ces mêmes préférences (voir :ref:`about_plugins`)." -msgid "On the page of an application, the methods are listed one below the other, followed by the tools and datasets of the application, if any: clicking a title opens its section and closes the one previously open. The colored dot before each method tells whether the current selection can be analyzed, and its tooltip gives the reason. The open method presents the inputs it expects and this status in detail. \"Run on selection...\" starts the method, and asks you to assign the selected objects to its inputs only when needed. The examples designed for a method are listed below it: \"Try with this example\" opens the example and runs the method with suitable parameters. The vertical strip between the application list and the page hides the list, or shows it again: the window shrinks or grows accordingly, and DataLab remembers this choice." -msgstr "Sur la page d'une application, les méthodes sont listées les unes sous les autres, suivies le cas échéant des outils et des jeux de données de l'application : cliquer sur un titre ouvre sa section et referme celle qui était ouverte. La pastille de couleur placée devant chaque méthode indique si la sélection courante peut être analysée, et son infobulle en donne la raison. La méthode ouverte présente les entrées qu'elle attend et ce statut en détail. « Exécuter sur la sélection... » lance la méthode et ne vous demande d'affecter les objets sélectionnés à ses entrées qu'en cas de besoin. Les exemples conçus pour une méthode sont listés en dessous : « Essayer avec cet exemple » ouvre l'exemple et exécute la méthode avec des paramètres adaptés. La bande verticale située entre la liste des applications et la page masque la liste, ou l'affiche à nouveau : la fenêtre se réduit ou s'agrandit en conséquence, et DataLab mémorise ce choix." +msgid "On the page of an application, the methods are listed one below the other, followed by the tools and datasets of the application, if any: clicking a title opens its section and closes the one previously open. The colored dot before each method tells whether the current selection can be analyzed, and its tooltip gives the reason. The open method presents the inputs it expects and this status in detail. When metadata are missing, the status points to \"Edit > Metadata > Add metadata...\", and it is updated as soon as objects are modified. \"Run on selection...\" starts the method, and asks you to assign the selected objects to its inputs only when needed. The examples designed for a method are listed below it: \"Try with this example\" opens the example and runs the method with suitable parameters. The vertical strip between the application list and the page hides the list, or shows it again: the window shrinks or grows accordingly, and DataLab remembers this choice." +msgstr "Sur la page d'une application, les méthodes sont listées les unes sous les autres, suivies le cas échéant des outils et des jeux de données de l'application : cliquer sur un titre ouvre sa section et referme celle qui était ouverte. La pastille de couleur placée devant chaque méthode indique si la sélection courante peut être analysée, et son infobulle en donne la raison. La méthode ouverte présente les entrées qu'elle attend et ce statut en détail. Lorsque des métadonnées manquent, le statut renvoie vers « Édition > Métadonnées > Ajouter des métadonnées... », et il est mis à jour dès que des objets sont modifiés. « Exécuter sur la sélection... » lance la méthode et ne vous demande d'affecter les objets sélectionnés à ses entrées qu'en cas de besoin. Les exemples conçus pour une méthode sont listés en dessous : « Essayer avec cet exemple » ouvre l'exemple et exécute la méthode avec des paramètres adaptés. La bande verticale située entre la liste des applications et la page masque la liste, ou l'affiche à nouveau : la fenêtre se réduit ou s'agrandit en conséquence, et DataLab mémorise ce choix." msgid "The Welcome page is a regular dockable panel: as soon as a signal or an image is created or opened, the corresponding view is brought to the front, and the Welcome page remains available as a tab. It may be closed like any other panel, and reopened at any time from the \"Welcome page\" entry of the \"?\" (Help) menu or from the \"View\" menu; it is also reopened automatically when the current panel becomes empty. The \"Show welcome page when the current panel is empty\" check box, at the bottom of the page, controls this automatic display, including at startup (this option is also available in the :ref:`settings`)." msgstr "La page d'accueil est un panneau ancrable comme les autres : dès qu'un signal ou une image est créé ou ouvert, la vue correspondante passe au premier plan, et la page d'accueil reste disponible sous forme d'onglet. Elle peut être fermée comme n'importe quel autre panneau, et rouverte à tout moment depuis l'entrée « Page d'accueil » du menu « ? » (Aide) ou depuis le menu « Affichage » ; elle est aussi rouverte automatiquement lorsque le panneau courant devient vide. La case à cocher « Afficher la page d'accueil lorsque le panneau courant est vide », en bas de la page, détermine cet affichage automatique, y compris au démarrage (cette option est également disponible dans les :ref:`settings`)." diff --git a/doc/locale/fr/LC_MESSAGES/features/image/menu_edit.po b/doc/locale/fr/LC_MESSAGES/features/image/menu_edit.po index 2b05829c1..9cfe20a0c 100644 --- a/doc/locale/fr/LC_MESSAGES/features/image/menu_edit.po +++ b/doc/locale/fr/LC_MESSAGES/features/image/menu_edit.po @@ -143,8 +143,8 @@ msgstr "Lorsque vous sélectionnez \"Ajouter des métadonnées...\" dans le menu msgid "**Metadata key**: Enter the name of the metadata field to add (letters, digits, ``_``, ``.`` and ``-``, e.g. a plugin key such as ``plugin.org.example.my-plugin.gain``)" msgstr "**Clé de métadonnée** : Saisir le nom du champ de métadonnée à ajouter (lettres, chiffres, ``_``, ``.`` et ``-``, par exemple une clé de plugin telle que ``plugin.org.example.my-plugin.gain``)" -msgid "**Known keys**: Pick a key already present on the selected images to copy it into the metadata key" -msgstr "**Clés connues** : Choisir une clé déjà présente sur les images sélectionnées pour la copier dans la clé de métadonnée" +msgid "**Known keys**: Pick a key already present on the selected images, or a key expected by the methods of the installed application plugins, to copy it into the metadata key" +msgstr "**Clés connues** : Choisir une clé déjà présente sur les images sélectionnées, ou une clé attendue par les méthodes des plugins d'application installés, pour la copier dans la clé de métadonnée" msgid "**Value pattern**: Define a pattern for the metadata value using Python format strings" msgstr "**Modèle de valeur** : Définir un modèle pour la valeur des métadonnées en utilisant des chaînes de format Python" diff --git a/doc/locale/fr/LC_MESSAGES/features/signal/menu_edit.po b/doc/locale/fr/LC_MESSAGES/features/signal/menu_edit.po index dba3d52cd..dfa150d8b 100644 --- a/doc/locale/fr/LC_MESSAGES/features/signal/menu_edit.po +++ b/doc/locale/fr/LC_MESSAGES/features/signal/menu_edit.po @@ -140,8 +140,8 @@ msgstr "Lorsque vous sélectionnez \"Ajouter des métadonnées...\" dans le menu msgid "**Metadata key**: Enter the name of the metadata field to add (letters, digits, ``_``, ``.`` and ``-``, e.g. a plugin key such as ``plugin.org.example.my-plugin.gain``)" msgstr "**Clé de métadonnée** : Saisir le nom du champ de métadonnée à ajouter (lettres, chiffres, ``_``, ``.`` et ``-``, par exemple une clé de plugin telle que ``plugin.org.example.my-plugin.gain``)" -msgid "**Known keys**: Pick a key already present on the selected signals to copy it into the metadata key" -msgstr "**Clés connues** : Choisir une clé déjà présente sur les signaux sélectionnés pour la copier dans la clé de métadonnée" +msgid "**Known keys**: Pick a key already present on the selected signals, or a key expected by the methods of the installed application plugins, to copy it into the metadata key" +msgstr "**Clés connues** : Choisir une clé déjà présente sur les signaux sélectionnés, ou une clé attendue par les méthodes des plugins d'application installés, pour la copier dans la clé de métadonnée" msgid "**Value pattern**: Define a pattern for the metadata value using Python format strings" msgstr "**Modèle de valeur** : Définissez un modèle pour la valeur des métadonnées en utilisant des chaînes de format Python" diff --git a/doc/locale/fr/LC_MESSAGES/release_notes/release_1.04.po b/doc/locale/fr/LC_MESSAGES/release_notes/release_1.04.po index dda13ac48..4f43c7225 100644 --- a/doc/locale/fr/LC_MESSAGES/release_notes/release_1.04.po +++ b/doc/locale/fr/LC_MESSAGES/release_notes/release_1.04.po @@ -66,6 +66,9 @@ msgstr "Chaque application affiche sa description, son identité, sa version, se msgid "Each method shows the inputs it expects (object type and count, required metadata) and a live status telling whether the current selection can be analyzed, and why not" msgstr "Chaque méthode présente les entrées qu'elle attend (type et nombre d'objets, métadonnées requises) et un statut mis à jour indiquant si la sélection courante peut être analysée, et sinon pourquoi" +msgid "When required metadata are missing, the status points to **Edit > Metadata > Add metadata...**, whose **Known keys** list also offers the keys expected by application methods; the status is updated as soon as objects are modified" +msgstr "Lorsque des métadonnées requises manquent, le statut renvoie vers **Édition > Métadonnées > Ajouter des métadonnées...**, dont la liste **Clés connues** propose aussi les clés attendues par les méthodes des applications ; le statut est mis à jour dès que des objets sont modifiés" + msgid "**Run on selection...** starts a method directly when the selection is ready, and asks for the input assignment only when it is ambiguous or invalid; the assignment dialog checks the chosen objects before the run can continue" msgstr "**Exécuter sur la sélection...** lance directement une méthode lorsque la sélection convient, et ne demande l'affectation des entrées que si elle est ambiguë ou invalide ; la boîte de dialogue d'affectation vérifie les objets choisis avant de permettre l'exécution" diff --git a/doc/release_notes/release_1.04.md b/doc/release_notes/release_1.04.md index 76d68d732..ad1f25be2 100644 --- a/doc/release_notes/release_1.04.md +++ b/doc/release_notes/release_1.04.md @@ -26,6 +26,7 @@ * Added a top-level **Applications** entry that presents active scientific application plugins in a dedicated catalog * Each application displays its description, identity, version, methods, tools, and examples; processing-only plugins remain outside this focused view * Each method shows the inputs it expects (object type and count, required metadata) and a live status telling whether the current selection can be analyzed, and why not +* When required metadata are missing, the status points to **Edit > Metadata > Add metadata...**, whose **Known keys** list also offers the keys expected by application methods; the status is updated as soon as objects are modified * **Run on selection...** starts a method directly when the selection is ready, and asks for the input assignment only when it is ambiguous or invalid; the assignment dialog checks the chosen objects before the run can continue * Examples are listed under the methods they are designed for: **Try with this example** opens the example, prefills the method parameters, and runs the method once they are accepted. One example may serve several methods, and examples designed for no method are listed as datasets * Application plugins may also list tools, such as wizards or editors, in the catalog