Skip to content

Commit

Permalink
added limits
Browse files Browse the repository at this point in the history
  • Loading branch information
HDembinski committed Sep 14, 2024
1 parent b02dcd2 commit 66c2515
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 77 deletions.
73 changes: 57 additions & 16 deletions src/iminuit/ipywidget.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ def make_widget(
# we frequently use variables which are defined
# near the end of the function.
original_values = minuit.values[:]
original_limits = minuit.limits[:]

def plot_with_frame(from_fit, report_success):
trans = plt.gca().transAxes
Expand Down Expand Up @@ -136,62 +137,95 @@ def on_update_button_clicked(change):
def on_reset_button_clicked(change):
minuit.reset()
minuit.values = original_values
minuit.limits = original_limits
for i, x in enumerate(parameters):
x.reset(minuit.values[i])
x.reset(minuit.values[i], minuit.limits[i])
OnParameterChange()()

class Parameter(widgets.HBox):
def __init__(self, minuit, par):
self.minuit = minuit
self.par = par
val = minuit.values[par]
step = _guess_initial_step(val)
vmin, vmax = minuit.limits[par]
vmin = _make_finite(vmin)
vmax = _make_finite(vmax)
# safety margin to avoid overflow warnings
vmin = vmin + 1e-300 if np.isfinite(vmin) else val - 100 * step
vmax = vmax - 1e-300 if np.isfinite(vmax) else val + 100 * step
vmin2 = vmin + 1e-300 if np.isfinite(vmin) else val - 100 * step
vmax2 = vmax - 1e-300 if np.isfinite(vmax) else val + 100 * step

self.slider = widgets.FloatSlider(
val,
tmin = widgets.BoundedFloatText(
vmin,
min=vmin,
max=vmax2,
step=1e-1 * (vmax2 - vmin2),
layout=widgets.Layout(width="4.1em"),
)

tmax = widgets.BoundedFloatText(
vmax,
min=vmin2,
max=vmax,
step=1e-1 * (vmax2 - vmin2),
layout=widgets.Layout(width="4.1em"),
)

self.slider = widgets.FloatSlider(
val,
min=vmin2,
max=vmax2,
step=step,
description=par,
continuous_update=True,
readout_format=".4g",
layout=widgets.Layout(min_width="70%"),
layout=widgets.Layout(min_width="50%"),
)
self.slider.observe(OnParameterChange(), "value")

def on_min_change(change):
self.slider.min = change["new"]
tmax.min = change["new"]
lim = minuit.limits[par]
minuit.limits[par] = (self.slider.min, lim[1])

def on_max_change(change):
self.slider.max = change["new"]
tmin.max = change["new"]
lim = minuit.limits[par]
minuit.limits[par] = (lim[0], self.slider.max)

tmin.observe(on_min_change, "value")
tmax.observe(on_max_change, "value")

self.fix = widgets.ToggleButton(
minuit.fixed[par],
description="Fix",
layout=widgets.Layout(width="3.1em"),
)

self.fit = widgets.ToggleButton(
False, description="Fit", layout=widgets.Layout(width="3.5em")
)

def on_fix_toggled(change):
minuit.fixed[par] = change["new"]
if change["new"]:
self.fit.value = False

self.fix.observe(on_fix_toggled, "value")

self.fit = widgets.ToggleButton(
False, description="Fit", layout=widgets.Layout(width="3.5em")
)

def on_fit_toggled(change):
self.slider.disabled = change["new"]
if change["new"]:
self.fix.value = False
OnParameterChange()()

self.fix.observe(on_fix_toggled, "value")
self.fit.observe(on_fit_toggled, "value")
super().__init__([self.slider, self.fix, self.fit])
super().__init__([tmin, self.slider, tmax, self.fix, self.fit])

def reset(self, value):
def reset(self, value, limits=None):
self.slider.unobserve_all("value")
self.slider.value = value
if limits:
self.slider.min, self.slider.max = limits
# Installing the observer actually triggers a notification,
# we skip it. See notes in OnParameterChange.
self.slider.observe(OnParameterChange(1), "value")
Expand Down Expand Up @@ -220,3 +254,10 @@ def reset(self, value):
out = widgets.Output()
OnParameterChange()()
return widgets.HBox([out, ui])


def _make_finite(x: float) -> float:
sign = -1 if x < 0 else 1
if abs(x) == np.inf:
return sign * np.finfo(float).max
return x
61 changes: 0 additions & 61 deletions test.ipynb

This file was deleted.

0 comments on commit 66c2515

Please sign in to comment.