Feature/history panel#339
Open
ThomasMalletCodra wants to merge 65 commits into
Open
Conversation
Assisted-by: Claude Opus 4.7
Migrated from history panel legacy branch
…get and HTML rendering
…el and related components
…ages and replay actions
(cherry picked from commit 6807861)
…s and add new history panel entries
Split the history feature into dedicated modules, refresh the GUI wiring and widgets, and update the related tests and translations.
# Conflicts: # datalab/locale/fr/LC_MESSAGES/datalab.po # doc/locale/fr/LC_MESSAGES/release_notes/release_1.03.po # doc/release_notes/release_1.03.md
Follow-up to a review noting that ruff/pylint had not been run on the History panel refactor after it was split into submodules. Cross-module access to underscore-prefixed members triggered W0212, plus a batch of other lint warnings that were addressed without disabling any checks.
Creation actions (new signal/image) were recorded in the history but, unlike process actions, could not be edited, recomputed or reverted. Editing a creation left downstream steps inconsistent. This makes creations first-class history actions: their parameters can be re-edited, the result is recomputed in place (keeping the UUID and downstream references), and the chain cascades correctly. * [NEW] : Allow editing creation (new_object) parameters via dialog and recompute in place, preserving the output UUID so downstream actions stay linked * [NEW] : Resolve target panel for UI creation actions so they replay and cascade like compute actions * [CHG] : add_ui_entry now returns the created HistoryAction, enabling creation output_uuids to be registered for downstream resolution * [CHG] : Restore/undo without saving now covers creation actions for both single action and full session * [FIX] : Snapshot creation parameters on edit for proper export/import and revert
…ompute Edit-mode replay opened parameter dialogs per selected action, each editing its own downstream chain. Overlapping chains caused repeated prompts and inconsistent state. Recompute also stopped at the edited action instead of cascading to the full downstream. * [FIX] : Process selected actions once via edit_mode_replay_actions, with deduplication, session-order sorting and a re-entrance guard, instead of calling edit_mode_replay per action * [FIX] : Replay only the selected actions; on param change, recompute in place then cascade fully downstream from the most upstream edited action * [CHG] : Cancel restores parameter snapshots for already-edited actions
…actions (C2/C3) Interactive fit dialogs now record a UI history action targeting the signal processor's new recompute_fit method, which reconstructs the fitted curve headlessly via fitdialog.evaluate_fit at replay time (no dialog reopened). - action.py: resolve signalprocessor/imageprocessor targets; translate the recorded source_uuid through uuid_remap on session replay. - historysession_ops.py: scope captured state and panel_str to processor targets. - processor/signal.py: thread fit_type/fit_x0 through the fit path, record one action per source object, add deterministic recompute_fit. - Covered types: polynomial, linear, gaussian, lorentzian, voigt, multigaussian, multilorentzian. Other interactive fits remain interactive-only (graceful). - Add integration test test_history_interactive_fit_replay.
…ior (P3a) Safety net before architecture slimming: assert bounded recompute call count (no replay loop), output identity (UUID + __number) preservation, source immutability, and document current metadata-clearing semantics on cascade.
…e (P3b) Introduce ObjectProp.apply_recomputed_object_in_place as the single source of truth for applying a recomputed object onto an existing one in place. Both the interactive Apply callback (edit mode) and the History cascade (recompute_1_to_1_in_place) now route through it, removing duplicated logic and unifying metadata semantics on the pre-history behavior (preserve the object's metadata instead of clearing it). Update the P3a characterization test to reflect the intentional metadata-preservation change.
…or (P3c) Add an explicit optional 'param' argument to ObjectProp.apply_processing_parameters. When provided it takes precedence over the Processing-tab editor state, turning the interactive Apply path into a reusable, editor-independent pre-history entry point (structural keystone to reduce future per-method history-compatibility work). Backward compatible: param=None keeps the current editor/stored-params fallback. Add a characterization test proving editor-independence via a decoy editor value.
… batch (P3c-B2) Pass each object's stored param explicitly to apply_processing_parameters instead of selecting the object to populate the Processing-tab editor. Removes the per-object set_current_object workaround (no more highlighting each object during batch recompute), made possible by the editor decoupling from P3c.
Recording no longer always appends to the last session. Each action now routes to the active recording session of its panel (signal/image), auto-creating a dedicated session per panel on first use, so signal and image pipelines stay in separate sessions. Selecting a session (or one of its actions) while recording makes it the active session for its panel, letting the user resume recording into any session. The history tree adds each action under the correct session item (add_action_to_tree gains an optional session_index, backward compatible). Add a feature test locking the routing and resume-into-selected behavior.
Make each panel's active recording session visually obvious in the History tree: its top-level item is shown in bold with a palette-derived tint and a tooltip naming the panel. The highlight is keyed by session number so it survives any tree repopulate (delete/replay/HDF5 reload), and it follows active-session changes (selection, auto-create, panel switch). On a Signal/ Image tab switch, the current panel's active session is scrolled into view and the highlight is refreshed, without forcing tree selection (avoids the selection/sync recursion). Add a feature test locking the highlight behavior.
Add the French translation for the new 'Active recording session ({panel}).'
string introduced by the per-panel history highlight (A2) and finalize three
related history-session strings that were still fuzzy (new-session prompts and
'New history session'). Catalog now 100% translated.
Signal and Image objects store their UUID in metadata["__uuid"] rather than as an attribute, so get_uuid() was generating a throwaway uuid4 on every call, making object identity unstable across the history panel. On top of this, a compute action that produced no output (failure or complete no-op) was still recorded as a successful action in the history tree. * [FIX] : Materialize object identity deterministically in get_uuid() by reusing set_uuid() on first access, instead of generating a transient uuid4 each time * [FIX] : Replace the faulty direct o.uuid access with get_uuid(o) in the AI assistant builtin tools, since data objects have no .uuid attribute * [FIX] : Drop object-producing compute actions (1_to_1, 1_to_n, n_to_1, 2_to_1) from the history when they yield no output, while keeping UI actions (load, duplicate, interactive fit) and 1_to_0 analysis * [NEW] : Add test_history_capture_outputs_drops_failed_compute covering the dropped failed compute plus retained UI action and 1_to_0 analysis
Introduce a new history panel that records the operations applied to each signal and image, enabling users to review and deterministically replay the processing steps that produced a given object. The work consolidates object identity, per-panel session management, and a redesigned recompute pipeline so that recorded histories stay consistent and reproducible across panels. * [NEW] : Record processing operations per object into a dedicated history panel, with deterministic replay of the recorded action sequence * [NEW] : Manage recording sessions per panel, routing each operation to the correct panel's active session and highlighting the active session * [NEW] : Offer to start a new session when creating or loading an object * [NEW] : Add a headless deterministic fit evaluator and record interactive curve fits as replayable actions * [CHG] : Disable history auto-recording by default * [CHG] : Persist action UUIDs and register produced outputs so replay can reliably reference the objects it creates * [CHG] : Redesign cascade recompute around a 1-to-1 in-place reprocess of a single primitive, decouple parameter application from the editor, and drop the selection side-effect in batch reprocessing * [CHG] : Lock cascade-recompute behavior with characterization tests * [FIX] : Stabilize object identity using deterministic UUIDs and scope workspace-state compatibility per panel, removing false cross-panel incompatibility warnings * [FIX] : Do not record a compute operation that failed * [CHG] : Add French translations for the history panel strings
Temporarily set aside two features not part of the current scope, without removing their implementation, and allow parameter editing when replaying a whole session in edit mode. * [CHG] : Hide the "Generate macro" action from the toolbar and context menu while keeping its implementation for a later re-enable * [CHG] : Hide the "Restore parameters" action from the toolbar and context menu while keeping the restore logic intact * [CHG] : Clicking a session in edit mode now replays it with parameter dialogs instead of a view-only replay, so session parameters stay editable
First two lots of the History-panel "workflow" refactor. Sessions remain the persistence unit and top-level tree items; processing chains are a derived, read-only view grouping actions by UUID parenthood. * [NEW] : Add pure, non-mutating read-model (chainmodel.py) with ProcessingChain dataclass, action_input_uuids, build_session_chains and build_processing_chains; deterministic grouping rooted at creation or external-root actions, dropping no action * [CHG] : Render the history tree in 3 levels (Session -> Chain -> Action) with new item-kind roles and _build_session_children; update populate_tree, add_action_to_tree, update_compatibility_states, get_selected_actions and get_selected_actions_or_sessions * [CHG] : Make select_action_in_tree and current_session depth-agnostic by walking to the top-level ancestor for the 3-level tree * [CHG] : Target the last action leaf of the session for post-delete auto-selection * [NEW] : Add test_history_chain_model_grouping and make the _get_tree_item_for helper depth-agnostic No persistence-format change. All history tests pass (21 passed), ruff clean.
This delivers two lots of the History-panel workflow refactor, both scoped to DataLab with no change to the persistence format. Deleting an intermediate history action previously truncated the whole session, discarding every downstream step. It now splices the action out of its processing chain and preserves the work that followed. When the deleted action had downstream steps, its now-orphaned output object is deep-copied into a new "Chain copy" group as a parentless creation root, and every downstream action consuming that output is rewired onto the copy, so the derived chain view renders those steps as a new independent chain. The persistent "Edit mode" toggle was error-prone as a long-lived session state. It is now hidden from the toolbar and context menu (code and API kept) in favor of two explicit launch modes, making replay intent clear at the moment the user triggers it. * [CHG] : Deleting an intermediate action now splits its processing chain instead of truncating the session; downstream steps are preserved on a deep-copied autonomous output and rendered as a new independent chain * [NEW] : Opt-in confirmation (skipped when unattended) to also remove the orphaned output object(s) from the workspace after a chain split * [CHG] : Hide the persistent "Edit mode" toggle from the toolbar and context menu, replaced by explicit "Replay" (silent) and "Step-by-step" launch modes; double-click behavior unchanged * [NEW] : "Step-by-step" replay action driving parameter dialogs and committing edits immediately, with no persistent edit session (replay_step_by_step) * [NEW] : French translations for the 6 new UI strings; resolved 2 fuzzy entries, including a stale "Processing chain — %d step(s)" that broke .mo compilation New tests: test_history_delete_splits_chain, test_history_step_by_step_launch. Full history suite: 23 passed, ruff clean.
The object-properties "Analysis parameters" section was read-only, so a user who wanted to re-run a 1-to-0 analysis (2D peak detection, FWHM, segments) with different settings had to restart the whole operation from scratch. This lot adds an editable "Analysis" tab that mirrors the existing editable Processing tab, letting the user adjust the stored parameters and re-run the analysis in place without polluting the history chain. * [NEW] : Add editable "Analysis" scroll tab to ObjectProp via setup_analysis_tab() and apply_analysis_parameters(); parameters are read from the object's ANALYSIS_PARAMETERS_OPTION metadata through extract_analysis_parameters (guards against None, non-1-to-0 and list params) * [NEW] : Re-run through processor.recompute_1_to_0() under the history replaying() guard so no synthetic history entry is created and the chain is left untouched * [NEW] : Add find_analysis_action() in history/chain.py (delegated from history/panel.py) to locate the matching 1-to-0 compute action by input UUID and function name, scanning most-recent-first for consistency with find_action_for_output * [CHG] : Extend update_properties_from with dynamic teardown/rebuild of the analysis tab; force_tab == "analysis" now prefers the editable tab and falls back to the unchanged read-only HTML view * [CHG] : On re-run, keep the located action consistent by refreshing snapshot_kwargs() and kwargs["param"] and updating the tree (no cascade, analysis is a leaf) * [CHG] : Force create_rois to False before recompute to avoid re-creating non-deletable ROIs when editing parameters Validation: new test_analysis_parameters_edit_image (peak-image threshold edit, recompute effect + ROI guard) plus analysis-recompute, result-deletion and full history suites all pass; ruff clean on all changed files; fr translations 100% translated and compiling.
- Introduce derived processing-chain view in the History panel - Split chains on delete and add step-by-step replay - Add editable analysis parameters tab for in-place re-run - Narrow history panel scope for the current deliverable
update_compatibility_states iterated every action item and resolved its uuid via get_action_from_uuid, which raises when the action is no longer in the model. During reconnect_chain_after_removal the recompute cascade emits SIG_OBJECT_MODIFIED (firing refresh_compatibility_items) before the final repopulate, so the tree transiently references a just-removed action and the Qt slot crashed with 'Action not found'. Build a uuid->action map once and skip unresolved items instead of raising; harden get_selected_actions[_or_ sessions] the same way. Add a regression test.
History duplication used to clone whole sessions and remap them at the session level, which left duplicated entries still pointing at the original objects' UUIDs. The feature is reworked around processing chains: selecting a session duplicates all its chains, selecting an action duplicates the single chain that contains it. Every cloned object receives a fresh UUID and all action references are remapped to the clones, so the result is an independent, editable and replayable session. Operation-rooted chains consume an object created outside the chain, so they cannot be replayed on their own. A synthetic "Initial state" creation head is prepended per distinct source object to materialize a clone snapshot, making such chains self-contained. * [CHG] : Resolve selection to processing chains via build_session_chains instead of normalising actions to their parent session * [FIX] : Assign a fresh UUID to every cloned object and remap all action references, fixing duplicated entries still referencing original UUIDs * [NEW] : Handle Cas A (creation-rooted chain) by duplicating the root new_object action as-is so it stays replayable * [NEW] : Handle Cas B (operation-rooted chain) by prepending a synthetic KIND_UI new_object head (empty kwargs/state, output_uuids=[clone]) recognised as a chain root by build_session_chains * [TEST] : Update test_history_duplication (scenarios 1-3) and add test_history_duplication_cas_a_creation_root and test_history_duplication_cas_b_synthetic_head (26 passed) * [NEW] : Add French translation "Initial state" -> "Etat initial"
A history session now represents exactly one linear processing chain. The previous read-model split a session into several chains at each creation action, which detached downstream processing when duplicating a session. Session boundaries are already decided at recording time (the "start a new history session?" prompt shown on object creation), so no per-creation splitting is performed at display time anymore. * [CHG] : build_session_chains() now returns a single ProcessingChain per session (root = first action, all actions kept in order) * [FIX] : copy_with_uuid_remap() resolves an effective panel string from the action target so new_object output UUIDs are remapped on duplication * [CHG] : Remove dead HistoryAction.regenerate_uuid no-op
Clean-up pass on the history panel: remove symbols that had no caller left in production nor in the test suite. This reduces the maintenance surface without changing any behaviour. * [CHG] : Remove unused add_to_history decorator and its _resolve_self_target helper (never applied anywhere), drop the add_to_history re-export * [CHG] : Remove unused add_entry entry-point and its panel delegation * [CHG] : Remove dead chain helper collect_downstream_uuids * [CHG] : Remove unused HistoryTree.get_selected_actions * [CHG] : Remove dead replay helpers edit_mode_replay (singular), view_only_session_replay and show_readonly_param_dialog * [CHG] : Remove ~14 dead HistoryPanel delegation methods that duplicated live module-level functions with no caller
The "Generate macro" action of the history panel was permanently hidden (setVisible(False), "out of current scope"). Remove it entirely together with its unreachable implementation to reduce the maintenance surface. * [CHG] : Remove the generate_macro_action and its HistoryPanel.generate_macro delegation from the history panel * [CHG] : Remove the historytools_ops.generate_macro implementation * [CHG] : Remove HistoryAction.to_macro_code (only consumed by generate_macro)
The "Restore parameters" toolbar/context action was permanently hidden (setVisible(False), "out of current scope"). Remove the dead UI entry point and its unused panel delegation. The underlying replay_restore_actions() branch is kept as it is still exercised elsewhere. * [CHG] : Remove the _restore_selection_action and all its references in create_menu_actions and update_actions_state * [CHG] : Remove the dead HistoryPanel.restore_action_params delegation
The "Edit mode" toggle action was permanently hidden (setVisible(False), superseded by the Replay / Step-by-step launch modes). Remove the dead UI entry point and its _edit_action attribute. The edit-mode mechanism itself is kept intact as it is still used by the recompute pipeline (is_edit_mode), the step-by-step replay and the test suite. * [CHG] : Remove the edit_action button, its _edit_action attribute and the now-useless action re-sync branch in toggle_edit_mode
Reflect the removal of the disabled "Generate macro", "Restore parameters" and "Edit mode" toolbar actions, and document the "New session" and "Step-by-step" actions that were missing. * [CHG] : Update historypanel.rst toolbar list to match the actual actions * [CHG] : Drop obsolete UI translation entries (Generate macro, Restore parameters, Edit mode and related strings) * [CHG] : Update the French documentation catalog for the history panel
Rename module-level functions, methods and the cross-module panel attributes so they no longer use the single leading-underscore "private" formalism, in line with the project coding conventions. This clears the protected-access (W0212) warnings raised on cross-module usage without introducing any lint suppression. Property backing fields and purely-internal attributes stay private. * [CHG] : Rename private history helper functions to public names * [CHG] : Rename private HistoryAction, WorkspaceState, HistoryPanel and HistoryTree methods to public names * [CHG] : Expose the cross-module panel flags (edit_replay_in_progress, suppress_session_prompt, session_input_pending) as public attributes
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.