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 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 state now also sets the resizable state:
- The PlotPy event system won't prevent the user from moving the item by dragging the handles if the item is just not movable: it has to be not resizable, which is not intuitive.
- This is now fixed
- Setting item movable state now also sets the resizable state:
- Range selection items (
XRangeSelection,YRangeSelection):- Handles are now displayed only when the item is resizable
- If the item is set as not resizable (using the
set_resizablemethod), the handles will be hidden
- Fixed cursor label formatting error with percentage symbols:
- Fixed
ValueError: unsupported format character '=' (0x3d)when cursor labels contain percentage signs followed by format specifiers (e.g., "Crossing at 20.0% = %g") - The issue occurred because old-style string formatting (
label % value) treated the%in percentage displays as format specifiers - Added robust fallback mechanism that tests label format once during cursor creation and uses regex-based replacement when needed
- Performance optimized: format validation is done once at cursor creation time, not on every callback execution
- Affects
vcursor,hcursor, andxcursormethods inCurveMarkerBuilder
- Fixed
Other changes:
- API breakage: renamed annotations
AnnotatedShape.get_infosmethod toget_info - Updated dependencies following the latest security advisories (NumPy >= 1.22)
- Added
pre-commithook to runruff(bothruff checkandruff format) on commit - Added missing
buildoptional dependency to development dependencies inpyproject.toml - Visual Studio Code tasks:
- Major overhaul (cleanup and simplification)
- Removal of no longer used batch files