Skip to content

Feature/history panel#339

Open
ThomasMalletCodra wants to merge 65 commits into
developfrom
feature/history-panel
Open

Feature/history panel#339
ThomasMalletCodra wants to merge 65 commits into
developfrom
feature/history-panel

Conversation

@ThomasMalletCodra

Copy link
Copy Markdown
Contributor

No description provided.

PierreRaybaut and others added 30 commits May 15, 2026 06:42
Assisted-by: Claude Opus 4.7
Migrated from history panel legacy branch
After eba8385, plot_results creates a "Results" group in the signal
panel, breaking panel-wide index lookups. Use group-local lookups so
the test is robust against extra groups.

(cherry picked from commit 5e08f9c)
(cherry picked from commit b2c4965)
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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants