Skip to content

Commit ff4356e

Browse files
committed
Add percentage-based autoscale margin configuration
Replace hardcoded autoscale margin with configurable `autoscale_margin_percent` parameter in BasePlotOptions. Users can now specify intuitive percentage values (0.2% default) instead of decimal fractions (0.002). Maintains full backward compatibility while improving user experience.
1 parent 6fde325 commit ff4356e

File tree

2 files changed

+47
-4
lines changed

2 files changed

+47
-4
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,12 @@
44

55
💥 New features / Enhancements:
66

7+
* Configurable autoscale margin:
8+
* Added `autoscale_margin_percent` parameter to `BasePlotOptions` for intuitive percentage-based margin control
9+
* Users can now specify autoscale margins as percentages (e.g., `0.2` for 0.2%, `5.0` for 5%)
10+
* Replaces the previous decimal-based approach with more user-friendly percentage values
11+
* Default remains 0.2% (equivalent to previous 0.002) for backward compatibility
12+
* Includes validation to prevent unreasonable values (0-50% range)
713
* Image statistics tool improvements:
814
* Enhanced `get_stats` function to display delta (Δ) values for coordinate ranges
915
* Now shows Δx, Δy, and Δz values alongside the min/max ranges for better analysis

plotpy/plot/base.py

Lines changed: 41 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,8 @@ class BasePlotOptions:
8888
axes_synchronised: If True, the axes are synchronised
8989
force_colorbar_enabled: If True, the colorbar is always enabled
9090
show_axes_tab: If True, the axes tab is shown in the parameters dialog
91+
autoscale_margin_percent: The percentage margin added when autoscaling
92+
(0.2% by default)
9193
"""
9294

9395
title: str | None = None
@@ -107,6 +109,7 @@ class BasePlotOptions:
107109
axes_synchronised: bool = False
108110
force_colorbar_enabled: bool = False
109111
show_axes_tab: bool = True
112+
autoscale_margin_percent: float = 0.2
110113

111114
def __post_init__(self) -> None:
112115
"""Check arguments"""
@@ -120,6 +123,11 @@ def __post_init__(self) -> None:
120123
# Check aspect ratio
121124
if self.aspect_ratio <= 0:
122125
raise ValueError("aspect_ratio must be strictly positive")
126+
# Check autoscale margin percentage
127+
if self.autoscale_margin_percent < 0:
128+
raise ValueError("autoscale_margin_percent must be non-negative")
129+
if self.autoscale_margin_percent > 50:
130+
raise ValueError("autoscale_margin_percent must be <= 50%")
123131
# Show a warning if force_colorbar_enabled is True and type is "curve"
124132
if self.force_colorbar_enabled and self.type == "curve":
125133
warnings.warn(
@@ -309,6 +317,7 @@ def __init__(
309317
self.options = options = options if options is not None else BasePlotOptions()
310318

311319
self.__autoscale_excluded_items: list[itf.IBasePlotItem] = []
320+
self.autoscale_margin_percent = options.autoscale_margin_percent
312321
self.lock_aspect_ratio = options.lock_aspect_ratio
313322
self.__autoLockAspectRatio = False
314323
if self.lock_aspect_ratio is None:
@@ -1105,6 +1114,32 @@ def set_scales(self, xscale: str, yscale: str) -> None:
11051114
self.set_axis_scale(ay, yscale)
11061115
self.replot()
11071116

1117+
def get_autoscale_margin_percent(self) -> float:
1118+
"""Get autoscale margin percentage
1119+
1120+
Returns:
1121+
float: the autoscale margin percentage
1122+
"""
1123+
return self.autoscale_margin_percent
1124+
1125+
def set_autoscale_margin_percent(self, margin_percent: float) -> None:
1126+
"""Set autoscale margin percentage
1127+
1128+
Args:
1129+
margin_percent (float): the autoscale margin percentage (0-50)
1130+
1131+
Raises:
1132+
ValueError: if margin_percent is not in valid range
1133+
"""
1134+
if margin_percent < 0:
1135+
raise ValueError("autoscale_margin_percent must be non-negative")
1136+
if margin_percent > 50:
1137+
raise ValueError("autoscale_margin_percent must be <= 50%")
1138+
1139+
self.autoscale_margin_percent = margin_percent
1140+
# Trigger an autoscale to apply the new margin immediately
1141+
self.do_autoscale(replot=True)
1142+
11081143
def enable_used_axes(self):
11091144
"""
11101145
Enable only used axes
@@ -2037,12 +2072,14 @@ def do_autoscale(self, replot: bool = True, axis_id: int | None = None) -> None:
20372072
vmax += 1
20382073
elif self.get_axis_scale(axis_id) == "lin":
20392074
dv = vmax - vmin
2040-
vmin -= 0.002 * dv
2041-
vmax += 0.002 * dv
2075+
margin = self.autoscale_margin_percent / 100.0
2076+
vmin -= margin * dv
2077+
vmax += margin * dv
20422078
elif vmin > 0 and vmax > 0: # log scale
20432079
dv = np.log10(vmax) - np.log10(vmin)
2044-
vmin = 10 ** (np.log10(vmin) - 0.002 * dv)
2045-
vmax = 10 ** (np.log10(vmax) + 0.002 * dv)
2080+
margin = self.autoscale_margin_percent / 100.0
2081+
vmin = 10 ** (np.log10(vmin) - margin * dv)
2082+
vmax = 10 ** (np.log10(vmax) + margin * dv)
20462083
self.set_axis_limits(axis_id, vmin, vmax)
20472084
self.setAutoReplot(auto)
20482085
self.updateAxes()

0 commit comments

Comments
 (0)