3D, views, recent files, background, axis limits, copy and paste shortcuts, fixes#4
Merged
Conversation
Adds a third variable (Z) to the selection panel with colour scale, enabling coloured 2-D scatter plots and a full 3-D view. Polishes the Z/colour UI and 3-D mouse interaction, and fixes Ctrl+rotate using button_pressed reset.
…vview files Introduces the Views feature: named views (column selection + plot settings) can be saved and restored at any time. Views can be exported to portable .pdvview JSON files with relative data-file paths, and re-imported via drag-and-drop or the Views menu. Missing tables/columns on restore produce warnings rather than crashes. Extends to cover: Z/color column selection, 3D view state (log-z, flip-z, cb3D), pipeline actions (Filter/Resample/Bin/Mask), all sub-panel settings and loader options. Adds "Apply view to current table" which resolves saved column names on whichever table is selected. Fixes crashes, list-deselect TypeError, compare-with-1-series, multi-y column drop, formula restore, and drag-drop/Ctrl+drag parity. https://claude.ai/code/session_01RK7XoUAyBGq81RqNdX7htm
…olorbar Replaces CTRL-rotate with a dedicated Rotate toggle button in the toolbar. Adds orthographic plane-reset, Home button, and 3D left-click pan mode matching 2D behaviour. Adds x/y/z axis constraint support. Includes 6 UI improvements: view menu submenus, surf/scatter choice, single shared colorbar per axis, plane reset, and Scatter as default 3D type. Improves control- panel layout and error robustness throughout. https://claude.ai/code/session_01RK7XoUAyBGq81RqNdX7htm
…ombo Cancels debounce timer in empty(), guards against np.array column indices (TypeError fix). Adds Scatter/Scatter+Line choices to the curve-type combo when a Z column is selected but 3-D view is off.
…ries) The Recent Files submenu now tracks: opened data files, imported .pdvview files, exported view files, and exported tables — all in a single list, newest first, capped at 30. Clicking a .pdvview entry calls load_view_file(); all others call load_files(). https://claude.ai/code/session_01RK7XoUAyBGq81RqNdX7htm
Each panel now stores its own absolute pixel width. Window resize only affects the last panel (absorbs slack); other panels keep their width. Dragging a sash updates only the panel to its left via GetSashIdx(). Mode switches (1/2/3 columns) restore saved widths instead of resetting to equal. Widths are persisted in view save/restore via stable panel names. https://claude.ai/code/session_01RK7XoUAyBGq81RqNdX7htm
Covers when to use the tool, installation, all supported file formats, GUI layout, selection/plot/pipeline/view features, export options, keyboard shortcuts, and common-task quick reference. https://claude.ai/code/session_01RK7XoUAyBGq81RqNdX7htm
Previously the last panel was never stored in _panelWidths so dragging the sash to its left had no persistent effect — the panel snapped back to "remainder" on the next resize. Changes: - _savePanelWidths now records ALL panels including the last - _restorePanelWidths scales all panels proportionally when the window is resized (instead of letting only the last panel absorb slack) - onSashChange also saves the last panel's width after every drag Result: every panel has a stored width; resizing the window maintains proportions; no panel is treated as a passive remainder. https://claude.ai/code/session_01RK7XoUAyBGq81RqNdX7htm
- Set vSplitter sash gravity to 0 so the left selection panel keeps its width when the window is resized - Stop MultiSplit from scaling sub-panels proportionally on EVT_SIZE - Remove automatic sash repositioning from the resize/idle handler; layout updates still happen when switching column modes https://claude.ai/code/session_01TEDdcedUgmSE1yVF33MFYE
- Fix pipeline save/delete and table repr typos (GUIPipelinePanel, pipeline, Tables) - Fix saveOptions typo'd parameter name (Tables) - Persist loader options (dayfirst, naming) on shutdown (appdata) - Drop DC bin when converting FFT to Period (plotdata) - Fix mask plugin IndexError on empty dataframes by using dtype-based timestamp detection instead of df.iloc[0,i]; surface the underlying exception in applyMaskString for better debugging (data_mask, Tables) https://claude.ai/code/session_01RusnXtXqo9DDz4dX2rUhXB
- Fix selection-panel width blowing out with long column names by subclassing ListBox/ComboBox to clamp DoGetBestSize (GUISelectionPanel) - Restore MultiSplit onParentChangeSize to call _restorePanelWidths and Skip the event so base class handles resize (GUIMultiSplit) - Set MinimumPaneSize and SashGravity before SplitVertically so the initial sash position is not silently overridden (GUIFields1D) - Enable SP_LIVE_UPDATE on both outer vSplitter and tSplitter to eliminate the XOR tracker line on click-and-hold (GUIFields1D) - Don't clear the filter search box text on Ctrl+C (GUISelectionPanel) https://claude.ai/code/session_01RusnXtXqo9DDz4dX2rUhXB
Axis limits: - Add xmin/xmax/ymin/ymax text fields to EstheticsPanel - Add zmin/zmax fields for 2D+Z and 3D modes - Flatten EstheticsPanel to a single WrapSizer; hide optional panels reliably on first open via plotsizer.Hide() Background image: - Add BG toolbar button with Load/Paste/Clear menu - Two modes: 'Fixed' (default, fills plot area via imshow + xlim/ylim-changed callbacks) and 'Moving with axes' (glued to data coords captured on switch) - IMAGE_EXTS constant shared with main.py for recent-files routing Z-axis / color-scale: - Use z-axis limit fields for color scale in 2D+Z scatter mode - Fix color-scale / z-limit sync when AutoScale toggles - Exclude datetime Z columns from color-scale path - Preserve 3D camera state across redraws; enable logZ; dedupe colorbars https://claude.ai/code/session_01RusnXtXqo9DDz4dX2rUhXB
Ctrl+V (paste): accepts file paths (data, .pdvview, images) or raw bitmaps from the clipboard. File paths are routed through a shared _routeFilenames helper (also used by drag-and-drop). Shift+Ctrl+V adds to existing tables instead of replacing. All pasted files appear in the Recent Files menu. Ctrl+C (copy): dispatches based on last-focused pane: - Columns list → TSV of selected X/Y/Z columns across tables - Tables list → TSV of all columns for selected tables - Plot canvas → PNG bitmap of the current figure - Stats panel → reuses existing CopyToClipBoard method Implementation uses EVT_CHAR_HOOK (not AcceleratorTable) so native Ctrl+C/V in TextCtrl/SearchCtrl/ComboBox is preserved. Visible File menu entries added for discoverability. Status bar feedback on every successful paste/copy. Removes the auto-copy-on-select binding in GUIInfoPanel that silently overwrote the clipboard on every stats row click. https://claude.ai/code/session_01RusnXtXqo9DDz4dX2rUhXB
…tation PR #2 (now in dev) contained an earlier, simpler Z/color and 3D implementation. PR #4's 13 commits are the polished, final version that supersedes PR #2 entirely. Conflicts resolved in 3 files (13 conflict blocks total) by keeping HEAD: - GUIPlotPanel.py: _patch_3d_ctrl_rotate (3-layer toolbar-aware approach), ColorCtrlPanel (btFree + cbPlot3D + camera state), plotSignals (shared z_norm, logZ/flipZ, single colorbar per axis), _store/_restore_limits (3D camera + zlim preservation). - GUISelectionPanel.py: _ClampedComboBox for comboZ, zSel parameter handling. - plotdata.py: auto-merged cleanly (no manual resolution needed). https://claude.ai/code/session_01TRfZkFW9YczDyobkh3cndo
…s, 3D controls - Append 3D navigation note (Rotate, plane views, Home) to Z/color bullet - Add 5 new Workflow bullets: BG image, manual axis limits, Ctrl+V paste, context-aware Ctrl+C copy, Recent Files - Add 4 bullets to Features list covering same new capabilities - Remove duplicate Z/color and 3D view entries from Plot options section https://claude.ai/code/session_01TRfZkFW9YczDyobkh3cndo
W2 — GUIPlotPanel.py: add missing '1.75' to LWChoices in restoreViewData;
restoring a view saved with LineWidth=1.75 previously raised ValueError.
W3 — GUIPlotPanel.py: captureViewData now reads plot3D_type from the live
cbCurveType widget (not the always-hidden cbPlot3D), so 3D type is
correctly captured when saving a view in 3D mode.
W1 — main.py: remove dead onRestoreViewFromCombo method; it referenced a
comboViews widget that was never created (views are restored via menu
lambdas calling onRestoreView directly).
M1 — GUISelectionPanel.py: fix off-by-one iFilt<=len → iFilt<len in
setGUIColumns; passing len(columnsY) to SetSelection is out-of-bounds.
M2 — main.py: remove dead self.restore_formulas (real mechanism uses
formulas_backup).
M3 — GUIToolBox.py: remove unreachable docstring after return in GetKeyString.
M4 — GUIToolBox.py: remove debug print('MPL VERSION:') that fired on every
toolbar instantiation.
tests: add TestPlotPanelViewData (9 headless tests) covering W2 LWChoices
consistency, W3 curveType-over-plot3D_type restore path, axis limits dict
structure, and axis limits JSON round-trip. Total: 52 → 61 tests.
https://claude.ai/code/session_01TRfZkFW9YczDyobkh3cndo
Two bugs fixed:
1. _toggle_rotate (GUIToolBox.py): when the Rotate toggle was turned OFF
it activated zoom mode, so left-drag box-zoomed rather than panned.
Now it activates pan mode instead, making the tooltip text ("When off:
left-drag pans, right-drag zooms") accurate.
2. _patch_3d_ctrl_rotate (GUIPlotPanel.py): the pan implementation set
ax.button_pressed=2 hoping Axes3D would pan, but button 2 triggers
zoom in modern matplotlib. Replaced with a proper manual pan: on
left-press in pan mode the start position and axis limits are stored;
on each mouse-move the screen delta is projected onto the camera's
screen-right / screen-up vectors (derived from ax.azim / ax.elev)
and applied as a shift to xlim3d / ylim3d / zlim3d. x/y/z key
constraints are preserved. A button-release handler clears the pan
state. A fallback motion handler is added for old matplotlib builds
where _on_move is not found in canvas callbacks.
https://claude.ai/code/session_01GNbfFRd1uPxiEHSHYZkE6t
When two files with the same basename were loaded from different directories (e.g. /dir1/data.csv and /dir2/data.csv), _tab_shortname returned 'data' for both. captureViewState keyed tabSelectionsFull by shortname so the second table's entry silently overwrote the first, causing wrong y-axis and z-axis selections after view restore. Add _unique_tab_keys(tab_list) which uses the portable shortname when it is unique across all loaded tables, and falls back to the full tab.name when two or more tables share the same shortname. Use this helper consistently for tabSelectedNames, tabSelectionsFull, and formulas_state in captureViewState. The restore path (_find_tab_by_key, t.name fallback in table-selection rebuild) already handles full-name keys correctly, so no restore-side changes are needed. https://claude.ai/code/session_01JQiNFHSjaNDv2VpPE2DzLV
- Right-drag in 3D pan or rotate mode now zooms (exponential scale about axis centre, matching matplotlib 2D convention) instead of doing nothing - Pan and Rotate buttons are now fully mutually exclusive: activating one forces the other off, with defensive ToggleTool calls to keep visuals in sync - Rotate-off no longer auto-activates pan; returns to default zoom mode - Tooltips updated: Pan shows When-on/When-off sections; Rotate shows "Rotation for 3D: left rotates, right zooms" https://claude.ai/code/session_01GNbfFRd1uPxiEHSHYZkE6t
Panel (sash) widths are a UI/workspace preference and should not be coupled to named views. Restoring a view was overriding the user's current panel layout, which is unexpected. Remove the sashWidths capture block from captureViewState and the corresponding restore block from restoreViewState. Old view files that already contain a sashWidths key are unaffected — the key is simply never read. https://claude.ai/code/session_01JQiNFHSjaNDv2VpPE2DzLV
fix 3d panning
fix view restore duplicates
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.
Summary
This PR adds a full 3D view, a Z/color variable selector, named Views with portable
.pdvviewfiles, a unified Recent Files menu, background images behind plots, manual axis/z limits, and standard Ctrl+C / Ctrl+V shortcuts. It also bundles GUI layout fixes, miscellaneous bug fixes, expanded documentation, and a post-review fix pass.Base:
dev← Head:claude/add-axis-limits-fHfBp— 16 files changed, +3,933 / −284 (22 commits).Features
3D view & Z/color variable
Named Views (
.pdvview).pdvviewJSON files with relative data-file paths, importable via drag-and-drop or the Views menu.Recent Files
.pdvviewfiles, exported view files, exported tables, and pasted files.Background image
Manual axis & z limits
xmin/xmax/ymin/ymaxtext fields added to the Esthetics panel.zmin/zmaxfields appear in 2D+Z and 3D modes.Copy & paste shortcuts
.pdvview, images) or raw bitmaps from the clipboard. Shift+Ctrl+V appends to existing tables instead of replacing.EVT_CHAR_HOOKso native Ctrl+C/V inTextCtrl/SearchCtrl/ComboBoxkeep working.GUI layout fixes
ListBox/ComboBoxsubclassed to clampDoGetBestSize.SP_LIVE_UPDATEenabled on both splitters — no more XOR tracker line on click-and-hold.Miscellaneous bug fixes
__repr__typos.saveOptionstypo'd parameter name.dayfirst, naming) now persisted on shutdown.IndexErroron empty dataframes — switched to dtype-based timestamp detection.TypeErroragainstnp.arraycolumn indices.Post-review fixes (pre-merge)
main.py— removed deadonRestoreViewFromCombomethod (referenced a non-existentcomboViewswidget).GUIPlotPanel—'1.75'was missing fromLWChoicesinrestoreViewData; restoring a view saved with LineWidth=1.75 previously raisedValueErrorsilently.GUIPlotPanel—captureViewDatanow readsplot3D_typefrom the livecbCurveTypewidget (not the always-hiddencbPlot3D), so 3D type is correctly saved.GUISelectionPanel— off-by-oneiFilt<=len→iFilt<leninsetGUIColumns; passinglen(columnsY)toSetSelectionis out-of-bounds.main.py— removed deadself.restore_formulas(real mechanism usesformulas_backup).GUIToolBox— removed unreachable docstring afterreturninGetKeyString.GUIToolBox— removed debugprint('MPL VERSION:')that fired on every toolbar instantiation.TestPlotPanelViewData: LWChoices consistency, curveType save/restore, axis-limits dict structure, JSON round-trip).3D interaction fixes (post-review)
ax.azim/ax.elev), instead of incorrectly settingbutton_pressed=2which triggered zoom in modern matplotlib.ToggleToolcalls to keep visuals in sync); toggling Rotate off returns to zoom mode rather than auto-activating pan.View save/restore fixes (post-review)
/dir1/data.csvand/dir2/data.csv),captureViewStatenow uses a unique key (fulltab.name) instead of the short name, preventing the second table's selection from silently overwriting the first.captureViewState/ restored inrestoreViewState; old.pdvviewfiles that already contain asashWidthskey are unaffected (key is ignored on load).