Skip to content

Fixing plot mode when chunk prompt triggers#40

Merged
WillJRoper merged 22 commits into
mainfrom
fixing-plot-mode
Nov 11, 2025
Merged

Fixing plot mode when chunk prompt triggers#40
WillJRoper merged 22 commits into
mainfrom
fixing-plot-mode

Conversation

@WillJRoper

Copy link
Copy Markdown
Owner

There was a bug where the prompt for accepting a chunk caused issues with subsequent plotting interactions. The y key binding was intercepted and caused the old plot to be shown.

WillJRoper and others added 10 commits November 11, 2025 21:34
Previously, chunking prompts occurred during data selection (when
pressing Enter in histogram mode), which broke the data selection
workflow. This change moves the prompts to when the user actually
triggers plotting or saving (p/P for scatter plots, h/H for histograms).

Changes:
- Added chunk_preference attribute to ScatterPlotter and
  HistogramPlotter classes to store user preference
- Created prompt_for_chunking_preference() helper function in
  dataset_prompts.py that prompts once and remembers the preference
- Updated plot_scatter, save_scatter, plot_hist, and save_hist to
  prompt for chunking preference before performing operations
- Modified ScatterPlotter._plot() and HistogramPlotter.compute_hist()
  to use the stored chunk_preference instead of auto-detecting
- Removed prompt_for_dataset_operation() calls from data selection
  flow in hist_bindings.py

The chunking preference is reset when the plotter is reset, so users
are re-prompted when starting a new plot.
After chunking prompts completed, the 'y' key from the prompt_yn
dialog could interfere with the 'y' key for selecting y-axis in
plotting mode. This was caused by the operation_callback being
executed synchronously before the prompt cleanup fully completed.

The fix defers the operation_callback execution using
get_app().loop.call_soon(), which schedules it for the next event
loop iteration. This ensures the prompt's temporary key bindings
are fully cleaned up before the plotting operation begins.
The previous approach of caching the chunking preference in
chunk_preference attribute was causing key binding conflicts. When the
prompt_yn dialog added temporary 'y' and 'n' bindings, these weren't
being properly cleaned up before the matplotlib plot window blocked,
leading to the 'y' key interfering with y-axis selection in plot mode.

This commit removes all chunking preference caching:
- Removed chunk_preference attribute from ScatterPlotter and
  HistogramPlotter
- Changed prompt_for_chunking_preference() to accept operation_callback
  with use_chunks parameter instead of caching in plotter
- Updated plot_and_show(), plot_and_save(), and compute_hist() to
  accept use_chunks parameter
- Updated _plot() methods to use use_chunks parameter directly instead
  of reading from self.chunk_preference

Now users are prompted fresh each time they plot/save, and the
use_chunks decision is passed directly through the call stack rather
than being stored. This eliminates the keybinding cleanup issues.
The root cause was that prompt_yn() added temporary 'y' and 'n'
bindings without any filter condition. Even after cleanup attempted
to remove them, the bindings could persist (cleanup failures are
silently caught). These unfiltered bindings would take precedence
over the filtered plot mode bindings.

Solution: Add a _flag_in_prompt flag that tracks whether we're
currently in a prompt_yn dialog. The temporary prompt bindings now
include a filter checking this flag:
  filter=Condition(lambda: self._flag_in_prompt)

When cleanup() is called, it sets _flag_in_prompt = False FIRST,
before executing callbacks. This ensures that even if binding
removal fails, the prompt bindings are immediately disabled and
won't interfere with normal mode bindings.
The plot_scatter function was immediately calling plot_and_show()
without first checking if both x and y axes were selected. This
could cause errors when pressing 'p' without selecting datasets.

This commit adds the same validation that save_scatter already has:
- Check if both x and y are in plot_params
- Return early with helpful message if not
- Only proceed to chunking prompt if both are selected

This matches the pattern used in save_scatter and prevents
premature plotting attempts.
@WillJRoper WillJRoper added bug Something isn't working Plotting Anything related plotting labels Nov 11, 2025
claude and others added 6 commits November 11, 2025 22:53
Updates test files to reflect the new chunking preference system:

1. test_hist_bindings.py:
   - Replace references to prompt_for_dataset_operation with
     prompt_for_chunking_preference
   - Update mock signature to accept nodes (list) instead of node
   - Remove incorrect patch from test_select_data (no longer prompts)

2. test_plot_bindings.py:
   - Add patches for prompt_for_chunking_preference to plot/save tests
   - Update assertions to expect use_chunks parameter in method calls
   - Fix mock setup to call callbacks with use_chunks parameter

3. test_plotting.py:
   - Add use_chunks=False parameter to all plot_and_show() calls
   - Add use_chunks=False parameter to all _plot() calls
   - Fix test_plot_chunked_data to expect correct behavior (1 call not 5)
   - Add mini_buffer_content mock to test_full_histogram_workflow
   - Update compute_hist calls to include use_chunks parameter

All tests now align with the new chunking preference workflow where:
- Users are prompted at plot/save time (not during selection)
- The use_chunks parameter is passed through the call stack
- prompt_for_chunking_preference takes a list of nodes to check
Adds 7 new test cases to cover the prompt_for_chunking_preference function:

1. test_prompt_for_chunking_preference_always_chunk:
   - Tests behavior when always_chunk config is enabled
   - Verifies callback is called with use_chunks=True immediately
   - Confirms no prompts are shown

2. test_prompt_for_chunking_preference_no_chunked_nodes:
   - Tests with non-chunked nodes
   - Verifies callback is called with use_chunks=False immediately
   - Confirms no prompts are shown

3. test_prompt_for_chunking_preference_with_chunked_nodes:
   - Tests that prompt is shown for chunked data
   - Verifies prompt message contains chunk count information
   - Mocks HDF5 file access to get chunk details

4. test_prompt_for_chunking_preference_user_says_yes:
   - Tests user choosing to use chunks (press 'y')
   - Verifies callback receives use_chunks=True
   - Confirms proper cleanup (default_focus, return_to_normal_mode)

5. test_prompt_for_chunking_preference_user_says_no:
   - Tests user choosing to load all data (press 'n')
   - Verifies callback receives use_chunks=False
   - Confirms proper cleanup

6. test_prompt_for_chunking_preference_multiple_nodes:
   - Tests with multiple chunked nodes
   - Verifies combined memory footprint calculation
   - Checks that all chunk counts are included in prompt

These tests ensure complete coverage of the new chunking preference
system used in plot and histogram workflows.
This commit addresses 8 failing tests with the following fixes:

1. test_dataset_prompts.py (3 tests fixed):
   - test_prompt_for_chunking_preference_user_says_yes:
     Removed incorrect assertion for return_to_normal_mode (function
     only calls default_focus, not return_to_normal_mode)

   - test_prompt_for_chunking_preference_user_says_no:
     Fixed flow to follow two-prompt pattern (first asks about chunks,
     second asks about loading all if user says no to chunks)

   - test_prompt_for_chunking_preference_multiple_nodes:
     Fixed expected values to match actual calculation:
     - Total size: 0.02 GB (not 0.29 GB)
     - Total chunks: 200 (100 from each node)
     - Calculation uses dataset.size * dataset.dtype.itemsize

2. test_hist_bindings.py (4 tests fixed):
   - test_plot_hist_with_empty_params & test_save_hist_with_empty_params:
     Added side_effect to set_data_key mock to actually update
     plot_params["data"], allowing code to pass the "data" check
     and reach the prompt/compute logic

   - test_plot_hist_with_existing_params & test_save_hist:
     Added WaitIndicator mock patch to prevent H5Forest singleton
     instantiation errors
     Added prompt_for_chunking_preference mock patch
     Created proper mock node for plot_params

3. test_plotting.py (1 test fixed):
   - test_plot_chunked_data:
     Corrected assertion - scatter should be called 5 times (once
     per chunk index from np.ndindex((5,))), not 1 time

   - test_full_histogram_workflow:
     Changed get_app patch to H5Forest class patch to avoid
     singleton instantiation issues

All tests now properly mock dependencies and reflect actual code behavior.
Run 'ruff format' to fix formatting issues:
- tests/unit/test_dataset_prompts.py
- tests/unit/test_hist_bindings.py

All linting checks now pass.
@codecov

codecov Bot commented Nov 11, 2025

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 99.57%. Comparing base (a593e2d) to head (48e793d).
⚠️ Report is 23 commits behind head on main.

Additional details and impacted files
@@             Coverage Diff             @@
##              main      #40      +/-   ##
===========================================
- Coverage   100.00%   99.57%   -0.43%     
===========================================
  Files           21       21              
  Lines         2285     2350      +65     
===========================================
+ Hits          2285     2340      +55     
- Misses           0       10      +10     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

claude and others added 6 commits November 11, 2025 23:22
This commit adds 11 new test cases to achieve 100% coverage:

1. test_dataset_prompts.py (2 new tests):
   - test_prompt_for_chunking_preference_user_aborts:
     Tests the abort path when user says no twice (no to chunks,
     then no to load all). Verifies operation callback is NOT called
     and abort message is printed.

   - test_prompt_for_chunking_preference_file_access_error:
     Tests exception handling when h5py.File access fails. Verifies
     fallback to node.nbytes estimate and prompts without chunk count
     (total_chunks = "unknown" path).

2. test_plot_bindings.py (6 new tests):
   - test_plot_scatter_missing_x_axis:
     Tests error handling when only y-axis is selected

   - test_plot_scatter_missing_y_axis:
     Tests error handling when only x-axis is selected

   - test_plot_scatter_missing_both_axes:
     Tests error handling when neither axis is selected

   - test_save_scatter_missing_x_axis:
     Tests save error handling when only y-axis is selected

   - test_save_scatter_missing_y_axis:
     Tests save error handling when only x-axis is selected

   - test_plot_scatter_calls_default_focus:
     Tests that default_focus() is called after plotting completes

3. test_hist_bindings.py (2 new tests):
   - test_plot_hist_missing_data:
     Tests error handling when no dataset is selected for plotting

   - test_save_hist_missing_data:
     Tests error handling when no dataset is selected for saving

All new tests cover previously untested code paths:
- Exception handlers
- Error validation branches
- Cleanup/focus management calls
- Abort/cancellation flows

This brings test coverage back to 100% for the chunking preference feature.
The tests were incorrectly setting plot_params to empty {}, which
triggered the 'if len(plot_params) == 0' block that tries to get
the current node. This caused the tests to fail with 'is not a Dataset'
error instead of the expected 'Please select a dataset first' error.

Fix: Set plot_params to {'other_key': 'value'} instead of {}.
This skips the empty check but still fails the 'data' not in plot_params
check, correctly testing the validation path we intended to cover.

The code flow is:
1. if len(plot_params) == 0: get node, check if group, set data key
2. if 'data' not in plot_params: print error and return

To test #2, plot_params must be non-empty but lack 'data' key.
Adds test_prompt_for_chunking_preference_chunks_none to cover
the code path where dataset.chunks is None (contiguous layout).

When chunks is None, the 'if dataset.chunks:' check fails and
total_chunks remains 0. This causes the prompt message builder
to use the else branch (lines 105-108) which doesn't include
chunk count in the message.

This test ensures complete coverage of the chunk counting logic
in prompt_for_chunking_preference.
@WillJRoper
WillJRoper merged commit 17b7d79 into main Nov 11, 2025
8 of 9 checks passed
@WillJRoper
WillJRoper deleted the fixing-plot-mode branch November 11, 2025 23:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working Plotting Anything related plotting

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants