Releases: PlotPyStack/PlotPy
Releases · PlotPyStack/PlotPy
v2.10.0
PlotPy Version 2.10.0
✨ New features:
- Per-axis autoscale strategy: Added configurable autoscale behavior for each axis via the axis parameters dialog. Three strategies are available: Auto (default — compute bounds from items), Fixed range (apply user-defined Min/Max values) and Disabled (leave the axis untouched on autoscale). New API:
BasePlot.set_axis_autoscale_strategy()/BasePlot.get_axis_autoscale_strategy()(closes Issue #63, partial) - Symbol border width: Added an
edgewidthparameter toSymbolParamfor customizable marker border thickness — previously the border was always 1 pixel wide
🛠️ Bug fixes:
- Rectangular snapshot tool — Fixed the "Original size" computation (closes Issue #57):
- The preview no longer displays negative dimensions when the X or Y axis is
reversed - The "Original size" is now computed from pixel coordinates instead of axis
units, so it is correct forXYImageItem(and any item with non-uniform
axis scaling) regardless of axis orientation - The
ValueErrorraised by the resize dialog when the selection produced
negative dimensions on a reversed axis is gone - Selecting a region larger than the plotted image now reports the same
native pixel resolution for bothImageItemandXYImageItem
(previouslyXYImageItemreportedshape - 1whileImageItem
reported the full oversized resolution): exporting at "Original size"
now consistently preserves the source pixel density and avoids
upsampling, regardless of the item type
- The preview no longer displays negative dimensions when the X or Y axis is
- Snapshot tool cursor — Fixed the mouse cursor remaining stuck as a cross (
+) outside the plot canvas (axes, toolbar) after using the snapshot tool. The modal dialogs are now opened after Qt has released the implicit pointer grab, so the cursor is correctly restored (closes Issue #58) - Z-axis log tool — Fixed the
ZAxisLogToolbeing always disabled for non-ImageItemimage types (XYImageItem,MaskedImageItem,MaskedXYImageItem,TrImageItem,RGBImageItem). The Z-axis log API (get_zaxis_log_state/set_zaxis_log_state) was moved fromImageItemup toBaseImageItemso all image item types support it. This notably fixes the tool being permanently greyed out in DataLab's image panel (closes Issue #59) - Z-axis log data update — Fixed image data not being recomputed when calling
set_data()while Z-axis log scale is active — the log-transformed data is now refreshed and the LUT range preserved in log mode YRangeCursorTool— Fixed incorrect inequality display and negative ∆y when the Y-range cursors are inverted (dragging the top cursor below the bottom one). Values are now sorted and ∆y is always positive (closes Issue #55)CurveStatsTool— Replacedmin/max/mean/std/sumwith their NaN-safe equivalents (nanmin,nanmax,nanmean,nanstd,nansum) so that signal statistics are computed correctly when the data contains NaN values
⚙️ Dependencies:
- Bumped minimum PythonQwt version from 0.15 to 0.16 to benefit from the Qt6 performance optimizations (closes Issue #22 — see PythonQwt#93 for the full optimization log)
v2.9.0
PlotPy Version 2.9.0
💥 New features:
- Added
QuiverItemfor displaying 2D vector fields (quiver plots), similar to
Matplotlib'squiver. This closes
Issue #54:- New
QuiverItemplot item class supporting X, Y, U, V arrays (1D or 2D) - Auto-meshgrid expansion when X, Y are 1D and U, V are 2D
- Configurable arrow scale, head size, and color
- New
make.quiver()builder method for easy item creation - New
quiver()function in the interactive plotting interface (plotpy.pyplot) - Integrated with plot autoscale (initial zoom and middle-click reset)
- Item icon displayed in the item list widget
- New
- Added "Invert colormap" checkbox directly in the Colormap Manager dialog. This
closes Issue #53:- Reflects the current inversion state when the dialog is opened
- Allows toggling inversion from the colormap selection widget
- Updates the colormap preview in real-time when toggled
- Inversion is treated as a display parameter, independent of the colormap
definition (toggling does not mark the colormap as having unsaved changes)
🛠️ Bug fixes:
- Fixed marker style parameters being overwritten when updating selected markers:
MarkerParam.update_paramnow correctly reads back the selected or unselected
visual state into the matching parameter set, instead of overwriting the base
(normal) style with the selected style- This preserves distinct normal and selected appearance for markers
- Fixed error-bar curve cursor snapping: clicking near an error-bar bound on an
ErrorBarCurveItemnow correctly returns the closest bar end coordinate.
Previously a typo (abs(y - y)/abs(x - x)instead ofabs(y - yi)/
abs(x - xi)) made the snap-to-bound branches dead code, so the closest
coordinate was always the central curve point regardless of cursor position - Fixed image export via
Figure.print_(plotpy.pyplot) leaking the underlying
QPainter: the painter is now always released, even when an axis fails to
render. This avoids "QPainter::begin: A paint device can only be painted by
one painter at a time" warnings, GDI/GL resource leaks, and truncated output
files on subsequent paints - Fixed
vector_projectionraising a division-by-zero warning and returning NaN
coordinates when the two reference points A and B coincided. The function now
detects the degenerate zero-length AB vector and returns point B - Fixed
scale_data_to_dtype(plotpy.io) producing NaN values when the input
array was constant (dmax == dmin). The function now returns a finite
constant array set to the target dtype's minimum value instead of dividing by
zero - Fixed
get_nan_min/get_nan_max(plotpy.mathutils.arrayfuncs) raising
ValueErroron empty arrays and emittingRuntimeWarningon all-NaN inputs.
Both helpers now return NaN for empty or fully-NaN arrays without warnings
🔧 Other changes:
- CI: gate PyPI deployment on test suite passing
- Development environment: improved
scripts/run_with_env.pyto support multiple
Python environment contexts (WinPython, venv, etc.) with legacy support for the
WINPYDIRBASEenvironment variable
v2.8.4
PlotPy Version 2.8.4 (2026-02-14)
💥 New features:
- Added official support for Python 3.14
🛠️ Bug fixes:
- Fixed PySide6 compatibility issues causing segfaults in the test suite:
- Use
objectinstead of C++ type strings (e.g.,"QMouseEvent","QEvent","QPointF") inSignaldeclarations — PySide6 segfaults with C++ type name strings - Check QObject validity via
is_qobject_valid()before accessing widgets in__del__,closeEvent, and panel close operations — PySide6 segfaults on deleted C++ objects instead of raisingRuntimeError - Restructure
BaseSyncPlot.__init__to defer widget operations until after Qt__init__completes — PySide6 requires__init__to have fully completed before the widget can be used as a parent - Replace deprecated
exec_()calls withexec()
- Use
- Fixed
test_multiline_toolfailing with PyQt6 due to smaller canvas size:- The spiral test data started at
t=0, placing the first two points so close together that they mapped to the same pixel on PyQt6's smaller default canvas - Start the spiral at
t=2πto ensure sufficient pixel spacing between consecutive points
- The spiral test data started at
- Fixed pytest running all tests when selecting a single test from VS Code:
- Move
plotpyfromaddoptstotestpathsin[tool.pytest.ini_options]
- Move
🔧 Other changes:
- Add missing
setuptoolstorequirements.txt(dev) - Update GitHub Actions to use latest artifact upload and download versions
- Update
cibuildwheelversion to v3.3.1 for improved wheel building - Add
.venv*to.gitignoreto exclude virtual environment files
v2.8.3
PlotPy Version 2.8.3
💥 New features:
AnnotatedSegmentnew angle display:- Added angle display in annotation label, showing the segment's angle relative to the horizontal direction (0° to 180°)
- This implements the equivalent feature submitted in Pull Request #51 by user @deuterium33
🛠️ Bug fixes:
- Fixed
IndexErrorwhen displaying images with a single row or column (e.g., SIF files with shape(1, N)):- The
to_bins()function now handles single-element coordinate arrays by assuming a bin width of 1.0 centered on the point - Previously, loading such images in DataLab caused an
IndexError: index 1 is out of bounds for axis 0 with size 1
- The
- Fixed circle/ellipse shape drawing with non-uniform aspect ratios:
- Axes were not perpendicular and did not connect to the ellipse edge when plot aspect ratio differed from 1.0
- Now uses parametric ellipse drawing that correctly handles non-perpendicular axes in pixel space
- The ellipse properly passes through all four handle points regardless of aspect ratio or rotation
- Fixed angle display range for
AnnotatedObliqueRectangleandAnnotatedEllipse:- Angle is now displayed in the 0° to 180° range instead of -90° to 90° (the original implementation was also displaying 0° at vertical orientation -additionally to horizontal orientation- which was counter-intuitive)
- This provides a more intuitive and consistent angle representation
v2.8.2
Version 2.8.2
🛠️ Bug fixes:
- Fixed
RuntimeWarningwhen changing masked image data type from float to integer:MaskedImageItem.update_mask()now handles NaN and Nonefilling_valuegracefully- When converting to integer dtypes, NaN/None values are replaced with 0 instead of triggering numpy cast warnings
- When converting to float dtypes, NaN is preserved as the fill value
- Added comprehensive tests to validate dtype conversion scenarios
Version 2.8.1
🛠️ Bug fixes:
- Issue #50 - Fixed ImageStatsTool displaying "No available data" for
XYImageItemandMaskedXYImageItem:- Added
IExportROIImageItemTypetoXYImageItem.types()so thatget_items_in_rectangle()can properly identify XY image items - Updated
__implements__tuples for consistency acrossXYImageItem,MaskedXYImageItem, andMaskedImageItem - The tool now correctly displays statistics for images with non-uniform coordinates
- Added
- Fixed snapshot tool failing with
SystemErroronXYImageItemandMaskedXYImageItem:- Fixed
assemble_imageitemspassing list instead of tuple to C extension function_scale_rect - Added missing
export_roimethod toXYImageItemto properly handle non-uniform coordinate transformations - Snapshots of XY images now render correctly instead of producing black images
- Fixed
Version 2.8.0
💥 New features / Enhancements:
- Curve fitting: added support for locked parameters:
- New
lockedparameter inFitParamclass to lock parameter values during automatic optimization - New
lockedfield inFitParamDataSetto configure parameter locking via the settings dialog - When locked, parameters retain their manually-adjusted values during auto-fit
- Visual indicators: locked parameters show a 🔒 emoji and are grayed out with disabled controls
- All optimization algorithms (simplex, Powell, BFGS, L-BFGS-B, conjugate gradient, least squares) fully support locked parameters
- Enables partial optimization workflows: fix well-determined parameters, optimize uncertain ones
- Improves fit convergence by reducing problem dimensionality
- New
- Configurable autoscale margin:
- Added
autoscale_margin_percentparameter toBasePlotOptionsfor intuitive percentage-based margin control - Users can now specify autoscale margins as percentages (e.g.,
0.2for 0.2%,5.0for 5%) - Replaces the previous decimal-based approach with more user-friendly percentage values
- Default remains 0.2% (equivalent to previous 0.002) for backward compatibility
- Includes validation to prevent unreasonable values (0-50% range)
- Added
- Image statistics tool improvements:
- Enhanced
get_statsfunction to display delta (Δ) values for coordinate ranges - Now shows Δx, Δy, and Δz values alongside the min/max ranges for better analysis
- Enhanced
- Added optional "Axes" tab control in Parameters dialog:
- New
show_axes_taboption inBasePlotOptionsandPlotOptions(default:True) - When set to
False, the "Axes" tab is hidden from item parameter dialogs - This allows applications to provide their own axes management while using PlotPy
- Can be configured during plot creation or changed at runtime using
plot.set_show_axes_tab(False)
- New
- Issue #45 - Add support for new curve Y-range cursor tool
YRangeCursorTool:- This tool is similar to the existing
CurveStatsTool, but it simply shows the Y-range values (min, max and interval). - It can be added to the plot widget using
plot_widget.manager.add_tool(YRangeCursorTool)
- This tool is similar to the existing
- Update color configurations defaults for improved visibility
- Item list:
- Added a new "Rename" context menu entry to rename the selected item
- This entry is only available for editable items
- X and Y range selection items:
- Added support for item title in parameters data set (
RangeShapeParam) - This concerns the
XRangeSelectionandYRangeSelectionitems
- Added support for item title in parameters data set (
- New annotated X and Y range selection items:
- Added
AnnotatedXRangeandAnnotatedYRangeitems - These items provide X and Y range selection with an annotation label
- They can be created using
make.annotated_xrangeandmake.annotated_yrangefunctions
- Added
- New
SyncPlotDialogclass:- This class provides a dialog for displaying synchronized plots.
- This is a complementary class to
SyncPlotWindow, providing a modal dialog interface for synchronized plotting.
- Native datetime axis support:
- Added
BasePlot.set_axis_datetime()method to easily configure an axis for datetime display - Added
BasePlot.set_axis_limits_from_datetime()method to set axis limits using datetime objects directly - Supports customizable datetime format strings using Python's
strftimeformat codes - Configurable label rotation and spacing for optimal display
- Example:
plot.set_axis_datetime("bottom", format="%H:%M:%S")for time-only display - Example:
plot.set_axis_limits_from_datetime("bottom", dt1, dt2)to zoom to a specific time range - Added
"datetime"as a valid scale type (alongside"lin"and"log") for axis configuration - Added datetime coordinate formatting support throughout PlotPy:
- Cursor tools (
VCursorTool,HCursorTool,XCursorTool) now display datetime-formatted X/Y coordinates CurveStatsToolnow displays datetime-formatted X coordinates for statistical computations- Marker labels automatically format coordinates as datetime when axis uses datetime scale
- Coordinate display in the plot canvas now shows datetime format when appropriate
- Refactored
ObjectInfobase class to provide shared datetime formatting methods for code reuse
- Cursor tools (
- Added
🧹 API cleanup: removed deprecated update methods (use update_item instead)
- Removed
AnnotationParam.update_annotationmethod - Removed
AxesShapeParam.update_axesmethod - Removed
AxesParam.update_axesmethod - Removed
ImageAxesParam.update_axesmethod - Removed
LabelParam.update_labelmethod - Removed
MarkerParam.update_markermethod - Removed
RangeShapeParam.update_rangemethod - Removed
ShapeParam.update_shapemethod
🛠️ Bug fixes:
- Fixed
RuntimeErrorinSyncPlotWindowandSyncPlotDialogwhen closing widgets quickly:- Fixed "wrapped C/C++ object of type QwtScaleWidget has been deleted" error that occurred when widgets were closed before the deferred plot rescaling operation could complete
- Replaced
QTimer.singleShot()with controllableQTimerinstances that can be stopped on widget close - Added
handle_show_event()andhandle_close_event()methods toBaseSyncPlotfor proper timer lifecycle management - Refactored
showEvent()andcloseEvent()in bothSyncPlotWindowandSyncPlotDialogto eliminate code duplication - Added early exit check in
rescale_plots()to prevent execution if the timer has been stopped - This fix ensures clean widget shutdown and prevents Qt from attempting to access deleted C++ objects
- Cross-section panels: Fixed autoscaling logic in
BaseCrossSectionPlot- Streamlined handling of
autoscale_modeandlockscalesoptions for consistent scaling behavior across all code paths - The
update_plot()method now delegates all scaling logic toplot_axis_changed()to avoid code duplication and ensure consistency - Fixed issue where Y cross-section plots for rectangular images with non-uniform axes (e.g., Y = f(X)) were not properly scaled on initial display
- The lockscales mode now correctly syncs the cross-section axis (CS_AXIS) to the image plot while autoscaling the intensity axis (Z_AXIS)
- Streamlined handling of
- Issue #49 - Fixed multiple coordinate handling bugs in
XYImageItem:- Root cause:
XYImageIteminternally stores bin edges (length n+1) but several methods were incorrectly treating them as pixel centers (length n) - Fixed
get_x_values()andget_y_values()to correctly compute and return pixel centers from stored bin edges:(edge[i] + edge[i+1]) / 2 - Fixed
get_pixel_coordinates()to correctly convert plot coordinates to pixel indices usingsearchsorted()with proper edge-to-index adjustment - Fixed
get_plot_coordinates()to return pixel center coordinates instead of bin edge coordinates - Fixed
get_closest_coordinates()to return pixel center coordinates instead of bin edge coordinates - Added comprehensive docstring documentation explaining that
XYImageItem.xandXYImageItem.ystore bin edges, not pixel centers - Removed redundant pixel centering code in
CrossSectionItem.update_curve_data()that was working around these bugs - This fixes the reported issue where using cross-section tools progressively translated image data to the bottom-right corner
- All coordinate-related methods now properly handle the bin edge vs pixel center distinction throughout the
XYImageItemAPI
- Root cause:
- Fixed index bounds calculation for image slicing compatibility:
- Corrected the calculation of maximum indices in
get_plot_coordinatesto ensure proper bounds when using NumPy array slicing - Previously, the maximum indices were off by one, which could cause issues when extracting image data using the returned coordinates
- Now returns indices that correctly align with Python/NumPy slicing conventions (e.g.,
[i1:i2+1, j1:j2+1]) - This fixes an historic bug that could lead to off-by-one errors when users extracted image data using the coordinates provided by this function
- Corrected the calculation of maximum indices in
- Fixed plot update after inserting a point using the
EditPointToolon non-Windows platforms - Issue #46 - Contrast adjustment with 'Eliminate outliers' failed for float images with high dynamic range
- Issue #29 - SelectTool: Selectin...
v2.8.1
Version 2.8.1
🛠️ Bug fixes:
- Issue #50 - Fixed ImageStatsTool displaying "No available data" for
XYImageItemandMaskedXYImageItem:- Added
IExportROIImageItemTypetoXYImageItem.types()so thatget_items_in_rectangle()can properly identify XY image items - Updated
__implements__tuples for consistency acrossXYImageItem,MaskedXYImageItem, andMaskedImageItem - The tool now correctly displays statistics for images with non-uniform coordinates
- Added
- Fixed snapshot tool failing with
SystemErroronXYImageItemandMaskedXYImageItem:- Fixed
assemble_imageitemspassing list instead of tuple to C extension function_scale_rect - Added missing
export_roimethod toXYImageItemto properly handle non-uniform coordinate transformations - Snapshots of XY images now render correctly instead of producing black images
- Fixed
Version 2.8.0
💥 New features / Enhancements:
- Curve fitting: added support for locked parameters:
- New
lockedparameter inFitParamclass to lock parameter values during automatic optimization - New
lockedfield inFitParamDataSetto configure parameter locking via the settings dialog - When locked, parameters retain their manually-adjusted values during auto-fit
- Visual indicators: locked parameters show a 🔒 emoji and are grayed out with disabled controls
- All optimization algorithms (simplex, Powell, BFGS, L-BFGS-B, conjugate gradient, least squares) fully support locked parameters
- Enables partial optimization workflows: fix well-determined parameters, optimize uncertain ones
- Improves fit convergence by reducing problem dimensionality
- New
- Configurable autoscale margin:
- Added
autoscale_margin_percentparameter toBasePlotOptionsfor intuitive percentage-based margin control - Users can now specify autoscale margins as percentages (e.g.,
0.2for 0.2%,5.0for 5%) - Replaces the previous decimal-based approach with more user-friendly percentage values
- Default remains 0.2% (equivalent to previous 0.002) for backward compatibility
- Includes validation to prevent unreasonable values (0-50% range)
- Added
- Image statistics tool improvements:
- Enhanced
get_statsfunction to display delta (Δ) values for coordinate ranges - Now shows Δx, Δy, and Δz values alongside the min/max ranges for better analysis
- Enhanced
- Added optional "Axes" tab control in Parameters dialog:
- New
show_axes_taboption inBasePlotOptionsandPlotOptions(default:True) - When set to
False, the "Axes" tab is hidden from item parameter dialogs - This allows applications to provide their own axes management while using PlotPy
- Can be configured during plot creation or changed at runtime using
plot.set_show_axes_tab(False)
- New
- Issue #45 - Add support for new curve Y-range cursor tool
YRangeCursorTool:- This tool is similar to the existing
CurveStatsTool, but it simply shows the Y-range values (min, max and interval). - It can be added to the plot widget using
plot_widget.manager.add_tool(YRangeCursorTool)
- This tool is similar to the existing
- Update color configurations defaults for improved visibility
- Item list:
- Added a new "Rename" context menu entry to rename the selected item
- This entry is only available for editable items
- X and Y range selection items:
- Added support for item title in parameters data set (
RangeShapeParam) - This concerns the
XRangeSelectionandYRangeSelectionitems
- Added support for item title in parameters data set (
- New annotated X and Y range selection items:
- Added
AnnotatedXRangeandAnnotatedYRangeitems - These items provide X and Y range selection with an annotation label
- They can be created using
make.annotated_xrangeandmake.annotated_yrangefunctions
- Added
- New
SyncPlotDialogclass:- This class provides a dialog for displaying synchronized plots.
- This is a complementary class to
SyncPlotWindow, providing a modal dialog interface for synchronized plotting.
- Native datetime axis support:
- Added
BasePlot.set_axis_datetime()method to easily configure an axis for datetime display - Added
BasePlot.set_axis_limits_from_datetime()method to set axis limits using datetime objects directly - Supports customizable datetime format strings using Python's
strftimeformat codes - Configurable label rotation and spacing for optimal display
- Example:
plot.set_axis_datetime("bottom", format="%H:%M:%S")for time-only display - Example:
plot.set_axis_limits_from_datetime("bottom", dt1, dt2)to zoom to a specific time range - Added
"datetime"as a valid scale type (alongside"lin"and"log") for axis configuration - Added datetime coordinate formatting support throughout PlotPy:
- Cursor tools (
VCursorTool,HCursorTool,XCursorTool) now display datetime-formatted X/Y coordinates CurveStatsToolnow displays datetime-formatted X coordinates for statistical computations- Marker labels automatically format coordinates as datetime when axis uses datetime scale
- Coordinate display in the plot canvas now shows datetime format when appropriate
- Refactored
ObjectInfobase class to provide shared datetime formatting methods for code reuse
- Cursor tools (
- Added
🧹 API cleanup: removed deprecated update methods (use update_item instead)
- Removed
AnnotationParam.update_annotationmethod - Removed
AxesShapeParam.update_axesmethod - Removed
AxesParam.update_axesmethod - Removed
ImageAxesParam.update_axesmethod - Removed
LabelParam.update_labelmethod - Removed
MarkerParam.update_markermethod - Removed
RangeShapeParam.update_rangemethod - Removed
ShapeParam.update_shapemethod
🛠️ Bug fixes:
- Fixed
RuntimeErrorinSyncPlotWindowandSyncPlotDialogwhen closing widgets quickly:- Fixed "wrapped C/C++ object of type QwtScaleWidget has been deleted" error that occurred when widgets were closed before the deferred plot rescaling operation could complete
- Replaced
QTimer.singleShot()with controllableQTimerinstances that can be stopped on widget close - Added
handle_show_event()andhandle_close_event()methods toBaseSyncPlotfor proper timer lifecycle management - Refactored
showEvent()andcloseEvent()in bothSyncPlotWindowandSyncPlotDialogto eliminate code duplication - Added early exit check in
rescale_plots()to prevent execution if the timer has been stopped - This fix ensures clean widget shutdown and prevents Qt from attempting to access deleted C++ objects
- Cross-section panels: Fixed autoscaling logic in
BaseCrossSectionPlot- Streamlined handling of
autoscale_modeandlockscalesoptions for consistent scaling behavior across all code paths - The
update_plot()method now delegates all scaling logic toplot_axis_changed()to avoid code duplication and ensure consistency - Fixed issue where Y cross-section plots for rectangular images with non-uniform axes (e.g., Y = f(X)) were not properly scaled on initial display
- The lockscales mode now correctly syncs the cross-section axis (CS_AXIS) to the image plot while autoscaling the intensity axis (Z_AXIS)
- Streamlined handling of
- Issue #49 - Fixed multiple coordinate handling bugs in
XYImageItem:- Root cause:
XYImageIteminternally stores bin edges (length n+1) but several methods were incorrectly treating them as pixel centers (length n) - Fixed
get_x_values()andget_y_values()to correctly compute and return pixel centers from stored bin edges:(edge[i] + edge[i+1]) / 2 - Fixed
get_pixel_coordinates()to correctly convert plot coordinates to pixel indices usingsearchsorted()with proper edge-to-index adjustment - Fixed
get_plot_coordinates()to return pixel center coordinates instead of bin edge coordinates - Fixed
get_closest_coordinates()to return pixel center coordinates instead of bin edge coordinates - Added comprehensive docstring documentation explaining that
XYImageItem.xandXYImageItem.ystore bin edges, not pixel centers - Removed redundant pixel centering code in
CrossSectionItem.update_curve_data()that was working around these bugs - This fixes the reported issue where using cross-section tools progressively translated image data to the bottom-right corner
- All coordinate-related methods now properly handle the bin edge vs pixel center distinction throughout the
XYImageItemAPI
- Root cause:
- Fixed index bounds calculation for image slicing compatibility:
- Corrected the calculation of maximum indices in
get_plot_coordinatesto ensure proper bounds when using NumPy array slicing - Previously, the maximum indices were off by one, which could cause issues when extracting image data using the returned coordinates
- Now returns indices that correctly align with Python/NumPy slicing conventions (e.g.,
[i1:i2+1, j1:j2+1]) - This fixes an historic bug that could lead to off-by-one errors when users extracted image data using the coordinates provided by this function
- Corrected the calculation of maximum indices in
- Fixed plot update after inserting a point using the
EditPointToolon non-Windows platforms - Issue #46 - Contrast adjustment with 'Eliminate outliers' failed for float images with high dynamic range
- Issue #29 - SelectTool: Selecting Another Shape Without Unselection
- Fixed direct selection between different shapes without requiring intermediate click on empty space
- Users can now click directly from one shape to another for immediate selection
- Maintains all existing functionality including multi-selection (Ctrl+click), moving, and resizing
- Fixed
ErrorBarCurveItemhandling of all-NaN data:- Fixed
ValueError: zero-size array to reduction operation minimum which has no identityw...
- Fixed
v2.8.0
Immutable
release. Only release title and notes can be modified.
💥 New features / Enhancements:
- Curve fitting: added support for locked parameters:
- New
lockedparameter inFitParamclass to lock parameter values during automatic optimization - New
lockedfield inFitParamDataSetto configure parameter locking via the settings dialog - When locked, parameters retain their manually-adjusted values during auto-fit
- Visual indicators: locked parameters show a 🔒 emoji and are grayed out with disabled controls
- All optimization algorithms (simplex, Powell, BFGS, L-BFGS-B, conjugate gradient, least squares) fully support locked parameters
- Enables partial optimization workflows: fix well-determined parameters, optimize uncertain ones
- Improves fit convergence by reducing problem dimensionality
- New
- Configurable autoscale margin:
- Added
autoscale_margin_percentparameter toBasePlotOptionsfor intuitive percentage-based margin control - Users can now specify autoscale margins as percentages (e.g.,
0.2for 0.2%,5.0for 5%) - Replaces the previous decimal-based approach with more user-friendly percentage values
- Default remains 0.2% (equivalent to previous 0.002) for backward compatibility
- Includes validation to prevent unreasonable values (0-50% range)
- Added
- Image statistics tool improvements:
- Enhanced
get_statsfunction to display delta (Δ) values for coordinate ranges - Now shows Δx, Δy, and Δz values alongside the min/max ranges for better analysis
- Enhanced
- Added optional "Axes" tab control in Parameters dialog:
- New
show_axes_taboption inBasePlotOptionsandPlotOptions(default:True) - When set to
False, the "Axes" tab is hidden from item parameter dialogs - This allows applications to provide their own axes management while using PlotPy
- Can be configured during plot creation or changed at runtime using
plot.set_show_axes_tab(False)
- New
- Issue #45 - Add support for new curve Y-range cursor tool
YRangeCursorTool:- This tool is similar to the existing
CurveStatsTool, but it simply shows the Y-range values (min, max and interval). - It can be added to the plot widget using
plot_widget.manager.add_tool(YRangeCursorTool)
- This tool is similar to the existing
- Update color configurations defaults for improved visibility
- Item list:
- Added a new "Rename" context menu entry to rename the selected item
- This entry is only available for editable items
- X and Y range selection items:
- Added support for item title in parameters data set (
RangeShapeParam) - This concerns the
XRangeSelectionandYRangeSelectionitems
- Added support for item title in parameters data set (
- New annotated X and Y range selection items:
- Added
AnnotatedXRangeandAnnotatedYRangeitems - These items provide X and Y range selection with an annotation label
- They can be created using
make.annotated_xrangeandmake.annotated_yrangefunctions
- Added
- New
SyncPlotDialogclass:- This class provides a dialog for displaying synchronized plots.
- This is a complementary class to
SyncPlotWindow, providing a modal dialog interface for synchronized plotting.
- Native datetime axis support:
- Added
BasePlot.set_axis_datetime()method to easily configure an axis for datetime display - Added
BasePlot.set_axis_limits_from_datetime()method to set axis limits using datetime objects directly - Supports customizable datetime format strings using Python's
strftimeformat codes - Configurable label rotation and spacing for optimal display
- Example:
plot.set_axis_datetime("bottom", format="%H:%M:%S")for time-only display - Example:
plot.set_axis_limits_from_datetime("bottom", dt1, dt2)to zoom to a specific time range - Added
"datetime"as a valid scale type (alongside"lin"and"log") for axis configuration - Added datetime coordinate formatting support throughout PlotPy:
- Cursor tools (
VCursorTool,HCursorTool,XCursorTool) now display datetime-formatted X/Y coordinates CurveStatsToolnow displays datetime-formatted X coordinates for statistical computations- Marker labels automatically format coordinates as datetime when axis uses datetime scale
- Coordinate display in the plot canvas now shows datetime format when appropriate
- Refactored
ObjectInfobase class to provide shared datetime formatting methods for code reuse
- Cursor tools (
- Added
🧹 API cleanup: removed deprecated update methods (use update_item instead)
- Removed
AnnotationParam.update_annotationmethod - Removed
AxesShapeParam.update_axesmethod - Removed
AxesParam.update_axesmethod - Removed
ImageAxesParam.update_axesmethod - Removed
LabelParam.update_labelmethod - Removed
MarkerParam.update_markermethod - Removed
RangeShapeParam.update_rangemethod - Removed
ShapeParam.update_shapemethod
🛠️ Bug fixes:
- Fixed
RuntimeErrorinSyncPlotWindowandSyncPlotDialogwhen closing widgets quickly:- Fixed "wrapped C/C++ object of type QwtScaleWidget has been deleted" error that occurred when widgets were closed before the deferred plot rescaling operation could complete
- Replaced
QTimer.singleShot()with controllableQTimerinstances that can be stopped on widget close - Added
handle_show_event()andhandle_close_event()methods toBaseSyncPlotfor proper timer lifecycle management - Refactored
showEvent()andcloseEvent()in bothSyncPlotWindowandSyncPlotDialogto eliminate code duplication - Added early exit check in
rescale_plots()to prevent execution if the timer has been stopped - This fix ensures clean widget shutdown and prevents Qt from attempting to access deleted C++ objects
- Cross-section panels: Fixed autoscaling logic in
BaseCrossSectionPlot- Streamlined handling of
autoscale_modeandlockscalesoptions for consistent scaling behavior across all code paths - The
update_plot()method now delegates all scaling logic toplot_axis_changed()to avoid code duplication and ensure consistency - Fixed issue where Y cross-section plots for rectangular images with non-uniform axes (e.g., Y = f(X)) were not properly scaled on initial display
- The lockscales mode now correctly syncs the cross-section axis (CS_AXIS) to the image plot while autoscaling the intensity axis (Z_AXIS)
- Streamlined handling of
- Issue #49 - Fixed multiple coordinate handling bugs in
XYImageItem:- Root cause:
XYImageIteminternally stores bin edges (length n+1) but several methods were incorrectly treating them as pixel centers (length n) - Fixed
get_x_values()andget_y_values()to correctly compute and return pixel centers from stored bin edges:(edge[i] + edge[i+1]) / 2 - Fixed
get_pixel_coordinates()to correctly convert plot coordinates to pixel indices usingsearchsorted()with proper edge-to-index adjustment - Fixed
get_plot_coordinates()to return pixel center coordinates instead of bin edge coordinates - Fixed
get_closest_coordinates()to return pixel center coordinates instead of bin edge coordinates - Added comprehensive docstring documentation explaining that
XYImageItem.xandXYImageItem.ystore bin edges, not pixel centers - Removed redundant pixel centering code in
CrossSectionItem.update_curve_data()that was working around these bugs - This fixes the reported issue where using cross-section tools progressively translated image data to the bottom-right corner
- All coordinate-related methods now properly handle the bin edge vs pixel center distinction throughout the
XYImageItemAPI
- Root cause:
- Fixed index bounds calculation for image slicing compatibility:
- Corrected the calculation of maximum indices in
get_plot_coordinatesto ensure proper bounds when using NumPy array slicing - Previously, the maximum indices were off by one, which could cause issues when extracting image data using the returned coordinates
- Now returns indices that correctly align with Python/NumPy slicing conventions (e.g.,
[i1:i2+1, j1:j2+1]) - This fixes an historic bug that could lead to off-by-one errors when users extracted image data using the coordinates provided by this function
- Corrected the calculation of maximum indices in
- Fixed plot update after inserting a point using the
EditPointToolon non-Windows platforms - Issue #46 - Contrast adjustment with 'Eliminate outliers' failed for float images with high dynamic range
- Issue #29 - SelectTool: Selecting Another Shape Without Unselection
- Fixed direct selection between different shapes without requiring intermediate click on empty space
- Users can now click directly from one shape to another for immediate selection
- Maintains all existing functionality including multi-selection (Ctrl+click), moving, and resizing
- Fixed
ErrorBarCurveItemhandling of all-NaN data:- Fixed
ValueError: zero-size array to reduction operation minimum which has no identitywhen error bar curves contain only NaN values - Added proper checks in
boundingRect()anddraw()methods to handle empty arrays gracefully - Error bar curves with all-NaN data now fall back to parent class behavior instead of crashing
- Fixed
- Item list: refresh tree when item parameters are changed:
- Added
SIG_ITEM_PARAMETERS_CHANGEDsignal toBasePlotclass - This signal is emitted when the parameters of an item are changed using the parameters dialog, or a specific tool (e.g. the colormap selection tool, or the lock/unlock tool for image items)
- The signal is emitted with the item as argument
- The
ItemListWidgetnow listens to this signal and refreshes the item list accordingly
- Added
- Edit tools (Edit data, center image position):
- Exclude read-only items from the list of editable items
- It is no longer possible to use those tools on read-only items
- Marker items (markers, cursors):
- Setting item movable s...
v2.7.5
Version 2.7.5
🛠️ Bug fixes:
- Issue #44 - Incorrect calculation method for "∑(y)" in
CurveStatsTool: replacedspt.trapezoidwithnp.sum, which is more consistent with the summation operation - Fix
update_statusmethod in all cross-section tools (intensity profile tools):- Use
get_itemsinstead ofget_selected_itemsto retrieve the image items - This allows the tools to work properly when no image item is selected, but there are image items in the plot
- This closes Issue #47 - Intensity profile tools do not work when no image item is selected
- Use
Other changes:
- Updated
guidatadependency to V3.10.0 - Using new
guidatatranslation utility based onbabel
v2.7.4
v2.7.3
In this release, test coverage is 80%.
🛠️ Bug fixes:
- Issue #40 - Z-axis logarithmic scale (
ZAxisLogTooltool) is not compatible with anti-aliasing interpolation - Fix intersection check for destination rectangle in
XYImageFilterItem - Issue #36 - Image items are not properly scaling along Y-axis with logarithmic scale:
- Actually, image items do not support non-linear scales (this is an historical limitation)
- This is not documented at all, so we've added an explicit warning: a red colored message is displayed at the center of the image frame when any non-linear scale is applied to either X or Y axis
- When dealing with non-linear scales, PlotPy provides an alternative solution: the user may rely on
XYImageItem(e.g. by usingmake.xyimage) as this item supports arbitrary X and Y pixel coordinates
- Issue #34 -
ValueErrorwhen trying to plot 2D histogram items withPyQt6
Other changes:
- Replace deprecated icon files with new SVG icons for selection tools