Skip to content

Commit d1635d4

Browse files
authored
Merge pull request #676 from SasView/fix-plotly-plotting
Update examples and plotters for bumps webview
2 parents e3ec644 + 158c97e commit d1635d4

11 files changed

Lines changed: 789 additions & 346 deletions

example/fit.py renamed to example/fit2d.py

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#!/usr/bin/env python
22

33
import sys
4+
from pathlib import Path
45

56
from bumps.names import FitProblem
67

@@ -9,11 +10,12 @@
910
from sasmodels.data import load_data, set_beam_stop, set_top
1011

1112
""" IMPORT THE DATA USED """
12-
radial_data = load_data('DEC07267.DAT')
13+
path = Path(__file__).resolve().parent
14+
radial_data = load_data(str(path / 'DEC07267.DAT'))
1315
set_beam_stop(radial_data, 0.00669, outer=0.025)
1416
set_top(radial_data, -.0185)
1517

16-
tan_data = load_data('DEC07266.DAT')
18+
tan_data = load_data(str(path / 'DEC07266.DAT'))
1719
set_beam_stop(tan_data, 0.00669, outer=0.025)
1820
set_top(tan_data, -.0185)
1921
#sas.set_half(tan_data, 'right')
@@ -188,7 +190,15 @@
188190
else:
189191
problem = FitProblem(M)
190192

193+
M.problem = problem
194+
191195
if __name__ == "__main__":
192196
import matplotlib.pyplot as plt
193-
problem.plot()
197+
198+
problem.summarize()
199+
# Plot using plotly
200+
fig = M._plot(backend="plotly")
201+
fig.show(renderer='browser')
202+
# Plot using matplotlib
203+
M._plot(backend="matplotlib")
194204
plt.show()

example/multiscatfit.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@
2828

2929
from bumps.names import FitProblem
3030

31+
from sasdata import data_path
32+
3133
from sasmodels.bumps_model import Experiment, Model
3234
from sasmodels.core import load_model
3335
from sasmodels.data import load_data
@@ -36,7 +38,7 @@
3638
## Load the data
3739
#data = load_data('DEC07267.DAT')
3840
#set_beam_stop(data, 0.003, outer=0.025)
39-
data = load_data('latex_smeared.xml', index=0)
41+
data = load_data(str(data_path / '1d_data' / 'latex_smeared.xml'), index=0)
4042

4143
## Define the model
4244
kernel = load_model("ellipsoid")
@@ -78,5 +80,5 @@
7880
if __name__ == "__main__":
7981
#M.theory()
8082
M.plot()
81-
import pylab
82-
pylab.show()
83+
import matplotlib.pyplot as plt
84+
plt.show()

example/oriented_usans.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
import numpy as np
22
from bumps.names import FitProblem
33

4+
from sasdata import data_path
5+
46
from sasmodels.bumps_model import Experiment, Model
57
from sasmodels.core import load_model
68
from sasmodels.data import load_data
79

810
# Spherical particle data, not ellipsoids
9-
sans, usans = load_data('latex_smeared.xml', index='all')
11+
sans, usans = load_data(str(data_path / '1d_data' / 'latex_smeared.xml'), index='all')
1012
usans.qmin, usans.qmax = np.min(usans.x), np.max(usans.x)
1113
usans.mask = (usans.x < 0.0)
1214
usans.oriented = True

example/sesans_sphere_2micron.py

Lines changed: 37 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,54 @@
11
"""
22
This is a data file used to load in sesans data and fit it using the bumps engine
3+
4+
Usage:
5+
6+
bumps sesans_sphere_2micron.py
37
"""
4-
import sesansfit
5-
from bumps.names import Parameter
8+
from bumps.names import FitProblem, Parameter
69

7-
# Enter the model name to use
8-
model_name = "sphere"
10+
from sasdata import data_path
911

10-
# DO NOT MODIFY THIS LINE
11-
model = sesansfit.get_bumps_model(model_name)
12+
from sasmodels.bumps_model import Experiment, Model
13+
from sasmodels.core import load_model
14+
from sasmodels.data import load_data
1215

13-
# Enter any custom parameters
14-
# name = Parameter(initial_value, name='name')
15-
phi = Parameter(0.0855, name='phi')
16-
# Add the parameters to this list that should be displayed in the fitting window
17-
custom_params = {"phi" : phi}
16+
# Enter the model name and the datafile path
17+
model_name = "sphere"
18+
data_file = data_path / "sesans_data" / "sphere2micron.ses"
1819

19-
# SESANS data file name
20-
sesans_file = "spheres2micron.ses"
20+
# Custom parameters for use in expressions
21+
# name = Parameter(initial_value, name='name')
22+
phi = Parameter(0.0855, name='phi') # scale = phi*(1-phi)
2123

22-
# Initial parameter values (if other than defaults)
23-
# "model_parameter_name" : value
24-
initial_vals = {
24+
# Initial parameter values and expressions (if other than defaults)
25+
# "model_parameter_name" : value or expression
26+
pars = {
27+
"scale": phi*(1-phi),
2528
"sld" : 1.41,
2629
"radius" : 10000,
2730
"sld_solvent" : 2.70,
2831
}
2932

30-
# Ranges for parameters if other than default
31-
# "model_parameter_name" : [min, max]
32-
param_range = {
33-
"phi" : [0.001, 0.5],
34-
"radius" : [100, 100000]
35-
}
33+
# DO NOT MODIFY THIS LINE
34+
model = Model(load_model(model_name), **pars)
3635

37-
# Constraints
36+
# Bounds constraints
3837
# model.param_name = f(other params)
39-
# EXAMPLE: model.scale = model.radius*model.radius*(1 - phi) - where radius
40-
# and scale are model functions and phi is a custom parameter
41-
model.scale = phi*(1-phi)
38+
model.radius.range(100, 100000)
39+
phi.range(0.001, 0.5)
40+
4241

4342
# Send to the fitting engine
44-
# DO NOT MODIFY THIS LINE
45-
problem = sesansfit.sesans_fit(sesans_file, model, initial_vals, custom_params, param_range)
43+
# DO NOT MODIFY THESE LINES
44+
data = load_data(str(data_file))
45+
M = Experiment(data=data, model=model)
46+
problem = FitProblem([M])
47+
48+
if __name__ == "__main__":
49+
import matplotlib.pyplot as plt
50+
51+
print(f"==== {model_name} model for {data_file.name} has χ² = {problem.chisq_str()} ====")
52+
print(problem.summarize())
53+
problem.plot()
54+
plt.show()

example/sesansfit_CodeCampIII.py

Lines changed: 15 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,23 @@
1-
import numpy as np
1+
from pathlib import Path
2+
23
from bumps.names import FitProblem, Parameter
34

45
from sasmodels import bumps_model, core
6+
from sasmodels.data import load_data
57

6-
if True: # fix when data loader exists
7-
# from sas.dataloader.readers\
8-
from sas.dataloader.loader import Loader
9-
loader = Loader()
10-
filename = 'sphere.ses'
11-
data = loader.load(filename)
12-
if data is None:
13-
raise OSError("Could not load file %r"%(filename,))
14-
data.x /= 10
15-
# print data
16-
# data = load_sesans('mydatfile.pz')
17-
# sans_data = load_sans('mysansfile.xml')
18-
19-
else:
20-
SElength = np.linspace(0, 2400, 61) # [A]
21-
data = np.ones_like(SElength)
22-
err_data = np.ones_like(SElength)*0.03
23-
24-
class Sample:
25-
zacceptance = 0.1 # [A^-1]
26-
thickness = 0.2 # [cm]
27-
28-
class SESANSData1D:
29-
#q_zmax = 0.23 # [A^-1]
30-
lam = 0.2 # [nm]
31-
x = SElength
32-
y = data
33-
dy = err_data
34-
sample = Sample()
35-
data = SESANSData1D()
8+
path = Path(__file__).resolve().parent
9+
data = load_data(str(path / 'sphere.ses'))
3610

3711
radius = 1000
3812
data.Rmax = 3*radius # [A]
3913

4014
## Sphere parameters
4115

42-
kernel = core.load_model("sphere", dtype='single')
16+
kernel = core.load_model("sphere")
4317
phi = Parameter(0.1, name="phi")
44-
model = bumps_model.Model(kernel,
45-
scale=phi*(1-phi), sld=7.0, solvent_sld=1.0, radius=radius,
18+
model = bumps_model.Model(
19+
kernel,
20+
scale=phi*(1-phi), sld=7.0, sld_solvent=1.0, radius=radius,
4621
)
4722
phi.range(0.001,0.5)
4823
#model.radius.pmp(40)
@@ -74,3 +49,9 @@ class SESANSData1D:
7449
else:
7550
M_sesans = bumps_model.Experiment(data=data, model=model)
7651
problem = FitProblem(M_sesans)
52+
53+
54+
if __name__ == "__main__":
55+
import matplotlib.pyplot as plt
56+
problem.plot()
57+
plt.show()

example/simul_fit.py

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
1-
import numpy as np
21
from bumps.names import FitProblem, FreeVariables
32

3+
from sasdata import data_path
4+
45
from sasmodels.bumps_model import Experiment, Model
56
from sasmodels.core import load_model
67
from sasmodels.data import load_data
78

89
# latex data, same sample usans and sans
910
# particles radius ~2300, uniform dispersity
10-
datasets = load_data('latex_smeared.xml', index='all')
11+
datasets = load_data(str(data_path / '1d_data' / 'latex_smeared.xml'), index='all')
1112
#[print(data) for data in datasets]
1213

1314
# A single sphere model to share between the datasets. We will use
@@ -20,14 +21,14 @@
2021
model = Model(kernel, **pars)
2122

2223
# radius and polydispersity (if any) are shared
23-
model.radius.range(0, np.inf)
24+
model.radius.range(0, 3000.)
2425
#model.radius_pd.range(0, 1)
2526

2627
# Contrast and dilution are the same for both measurements, but are not
2728
# separable with a single measurement (i.e., I(q) ~ F(q) contrast^2 Vf),
2829
# so fit one of scale, sld or solvent sld. With absolute scaling from
2930
# data reduction, can use the same parameter for both datasets.
30-
model.scale.range(0, np.inf)
31+
model.scale.range(0, 1.0)
3132
#model.sld.range(-inf, inf)
3233
#model.sld_solvent.range(-inf, inf)
3334

@@ -37,7 +38,7 @@
3738
names=[data.run[0] for data in datasets],
3839
background=model.background,
3940
)
40-
free.background.range(-np.inf, np.inf)
41+
free.background.range(-1, 1)
4142

4243
# Note: can access the parameters for the individual models using
4344
# free.background[0] and free.background[1], setting constraints or
@@ -61,3 +62,8 @@
6162
M = [Experiment(data=data, model=model, name=data.run[0]) for data in datasets]
6263

6364
problem = FitProblem(M, freevars=free)
65+
66+
if __name__ == "__main__":
67+
import matplotlib.pyplot as plt
68+
problem.plot()
69+
plt.show()

sasmodels/bumps_model.py

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,7 @@ def parameters(self):
240240
"""
241241
Return a dictionary of parameters
242242
"""
243+
# TODO: tie the background and scale to the data rather than the model
243244
pars = self.model.parameters()
244245
if self.extra_pars is not None:
245246
pars.update(self.extra_pars)
@@ -264,7 +265,9 @@ def residuals(self):
264265
"""
265266
Return theory minus data normalized by uncertainty.
266267
"""
267-
#if np.any(self.err ==0): print("zeros in err")
268+
# if np.any(self.err ==0): print("zeros in err")
269+
# from bumps.fitproblem import fitness_show_parameters
270+
# if any(np.isnan(self.theory())): (print("nan in theory for:"),fitness_show_parameters(self))
268271
return (self.theory() - self.Iq) / self.dIq
269272

270273
def nllf(self):
@@ -281,15 +284,24 @@ def nllf(self):
281284
#def __call__(self):
282285
# return 2 * self.nllf() / self.dof
283286

284-
def plot(self, view=None):
287+
def _plot(self, view=None, backend='matplotlib'):
285288
# type: (str) -> None
286289
"""
287290
Plot the data and residuals.
288291
"""
289292
data, theory, resid = self._data, self.theory(), self.residuals()
290293
# TODO: hack to display oriented usans 2-D pattern
291-
Iq_calc = self.Iq_calc if isinstance(self.Iq_calc, tuple) else None
292-
plot_theory(data, theory, resid, view, Iq_calc=Iq_calc)
294+
#Iq_calc = self.Iq_calc if isinstance(self.Iq_calc, tuple) else None
295+
label = f"I(q) {self.model.sasmodel.info.name}"
296+
Iq_calc = self.Iq_calc
297+
fig = plot_theory(data, theory, resid, view, Iq_calc=Iq_calc, label=label, backend=backend)
298+
return fig
299+
300+
def plot(self, view=None):
301+
return self._plot(view=view, backend='matplotlib')
302+
303+
def plotly(self, view=None):
304+
return self._plot(view=view, backend='plotly')
293305

294306
def simulate_data(self, noise=None):
295307
# type: (float) -> None

0 commit comments

Comments
 (0)