Extract fit controls
This commit is contained in:
parent
0b340d0bb9
commit
200e5d0a13
@ -0,0 +1 @@
|
|||||||
|
from pyzebra.app.fit_controls import FitControls
|
169
pyzebra/app/fit_controls.py
Normal file
169
pyzebra/app/fit_controls.py
Normal file
@ -0,0 +1,169 @@
|
|||||||
|
import types
|
||||||
|
|
||||||
|
from bokeh.models import (
|
||||||
|
Button,
|
||||||
|
CellEditor,
|
||||||
|
CheckboxEditor,
|
||||||
|
CheckboxGroup,
|
||||||
|
ColumnDataSource,
|
||||||
|
DataTable,
|
||||||
|
Dropdown,
|
||||||
|
MultiSelect,
|
||||||
|
NumberEditor,
|
||||||
|
RadioGroup,
|
||||||
|
Spinner,
|
||||||
|
TableColumn,
|
||||||
|
TextAreaInput,
|
||||||
|
)
|
||||||
|
|
||||||
|
import pyzebra
|
||||||
|
|
||||||
|
|
||||||
|
def _params_factory(function):
|
||||||
|
if function == "linear":
|
||||||
|
param_names = ["slope", "intercept"]
|
||||||
|
elif function == "gaussian":
|
||||||
|
param_names = ["amplitude", "center", "sigma"]
|
||||||
|
elif function == "voigt":
|
||||||
|
param_names = ["amplitude", "center", "sigma", "gamma"]
|
||||||
|
elif function == "pvoigt":
|
||||||
|
param_names = ["amplitude", "center", "sigma", "fraction"]
|
||||||
|
elif function == "pseudovoigt1":
|
||||||
|
param_names = ["amplitude", "center", "g_sigma", "l_sigma", "fraction"]
|
||||||
|
else:
|
||||||
|
raise ValueError("Unknown fit function")
|
||||||
|
|
||||||
|
n = len(param_names)
|
||||||
|
params = dict(
|
||||||
|
param=param_names, value=[None] * n, vary=[True] * n, min=[None] * n, max=[None] * n
|
||||||
|
)
|
||||||
|
|
||||||
|
if function == "linear":
|
||||||
|
params["value"] = [0, 1]
|
||||||
|
params["vary"] = [False, True]
|
||||||
|
params["min"] = [None, 0]
|
||||||
|
|
||||||
|
elif function == "gaussian":
|
||||||
|
params["min"] = [0, None, None]
|
||||||
|
|
||||||
|
return params
|
||||||
|
|
||||||
|
|
||||||
|
class FitControls:
|
||||||
|
def __init__(self):
|
||||||
|
self.params = {}
|
||||||
|
|
||||||
|
def add_function_button_callback(click):
|
||||||
|
# bokeh requires (str, str) for MultiSelect options
|
||||||
|
new_tag = f"{click.item}-{function_select.tags[0]}"
|
||||||
|
function_select.options.append((new_tag, click.item))
|
||||||
|
self.params[new_tag] = _params_factory(click.item)
|
||||||
|
function_select.tags[0] += 1
|
||||||
|
|
||||||
|
add_function_button = Dropdown(
|
||||||
|
label="Add fit function",
|
||||||
|
menu=[
|
||||||
|
("Linear", "linear"),
|
||||||
|
("Gaussian", "gaussian"),
|
||||||
|
("Voigt", "voigt"),
|
||||||
|
("Pseudo Voigt", "pvoigt"),
|
||||||
|
# ("Pseudo Voigt1", "pseudovoigt1"),
|
||||||
|
],
|
||||||
|
width=145,
|
||||||
|
)
|
||||||
|
add_function_button.on_click(add_function_button_callback)
|
||||||
|
self.add_function_button = add_function_button
|
||||||
|
|
||||||
|
def function_list_callback(_attr, old, new):
|
||||||
|
# Avoid selection of multiple indicies (via Shift+Click or Ctrl+Click)
|
||||||
|
if len(new) > 1:
|
||||||
|
# drop selection to the previous one
|
||||||
|
function_select.value = old
|
||||||
|
return
|
||||||
|
|
||||||
|
if len(old) > 1:
|
||||||
|
# skip unnecessary update caused by selection drop
|
||||||
|
return
|
||||||
|
|
||||||
|
if new:
|
||||||
|
params_table_source.data.update(self.params[new[0]])
|
||||||
|
else:
|
||||||
|
params_table_source.data.update(dict(param=[], value=[], vary=[], min=[], max=[]))
|
||||||
|
|
||||||
|
function_select = MultiSelect(options=[], height=120, width=145)
|
||||||
|
function_select.tags = [0]
|
||||||
|
function_select.on_change("value", function_list_callback)
|
||||||
|
self.function_select = function_select
|
||||||
|
|
||||||
|
def remove_function_button_callback():
|
||||||
|
if function_select.value:
|
||||||
|
sel_tag = function_select.value[0]
|
||||||
|
del self.params[sel_tag]
|
||||||
|
for elem in function_select.options:
|
||||||
|
if elem[0] == sel_tag:
|
||||||
|
function_select.options.remove(elem)
|
||||||
|
break
|
||||||
|
|
||||||
|
function_select.value = []
|
||||||
|
|
||||||
|
remove_function_button = Button(label="Remove fit function", width=145)
|
||||||
|
remove_function_button.on_click(remove_function_button_callback)
|
||||||
|
self.remove_function_button = remove_function_button
|
||||||
|
|
||||||
|
params_table_source = ColumnDataSource(dict(param=[], value=[], vary=[], min=[], max=[]))
|
||||||
|
self.params_table = DataTable(
|
||||||
|
source=params_table_source,
|
||||||
|
columns=[
|
||||||
|
TableColumn(field="param", title="Parameter", editor=CellEditor()),
|
||||||
|
TableColumn(field="value", title="Value", editor=NumberEditor()),
|
||||||
|
TableColumn(field="vary", title="Vary", editor=CheckboxEditor()),
|
||||||
|
TableColumn(field="min", title="Min", editor=NumberEditor()),
|
||||||
|
TableColumn(field="max", title="Max", editor=NumberEditor()),
|
||||||
|
],
|
||||||
|
height=200,
|
||||||
|
width=350,
|
||||||
|
index_position=None,
|
||||||
|
editable=True,
|
||||||
|
auto_edit=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
# start with `background` and `gauss` fit functions added
|
||||||
|
add_function_button_callback(types.SimpleNamespace(item="linear"))
|
||||||
|
add_function_button_callback(types.SimpleNamespace(item="gaussian"))
|
||||||
|
function_select.value = ["gaussian-1"] # put selection on gauss
|
||||||
|
|
||||||
|
self.from_spinner = Spinner(title="Fit from:", width=145)
|
||||||
|
self.to_spinner = Spinner(title="to:", width=145)
|
||||||
|
|
||||||
|
self.area_method_radiogroup = RadioGroup(labels=["Function", "Area"], active=0, width=145)
|
||||||
|
|
||||||
|
self.lorentz_checkbox = CheckboxGroup(
|
||||||
|
labels=["Lorentz Correction"], width=145, margin=(13, 5, 5, 5)
|
||||||
|
)
|
||||||
|
|
||||||
|
self.result_textarea = TextAreaInput(title="Fit results:", width=750, height=200)
|
||||||
|
|
||||||
|
def _process_scan(self, scan):
|
||||||
|
pyzebra.fit_scan(
|
||||||
|
scan, self.params, fit_from=self.from_spinner.value, fit_to=self.to_spinner.value
|
||||||
|
)
|
||||||
|
pyzebra.get_area(
|
||||||
|
scan,
|
||||||
|
area_method=pyzebra.AREA_METHODS[self.area_method_radiogroup.active],
|
||||||
|
lorentz=self.lorentz_checkbox.active,
|
||||||
|
)
|
||||||
|
|
||||||
|
def fit_scan(self, scan):
|
||||||
|
self._process_scan(scan)
|
||||||
|
|
||||||
|
def fit_dataset(self, dataset):
|
||||||
|
for scan in dataset:
|
||||||
|
if scan["export"]:
|
||||||
|
self._process_scan(scan)
|
||||||
|
|
||||||
|
def update_result_textarea(self, scan):
|
||||||
|
fit = scan.get("fit")
|
||||||
|
if fit is None:
|
||||||
|
self.result_textarea.value = ""
|
||||||
|
else:
|
||||||
|
self.result_textarea.value = fit.fit_report()
|
@ -2,7 +2,6 @@ import base64
|
|||||||
import io
|
import io
|
||||||
import os
|
import os
|
||||||
import tempfile
|
import tempfile
|
||||||
import types
|
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from bokeh.io import curdoc
|
from bokeh.io import curdoc
|
||||||
@ -11,15 +10,12 @@ from bokeh.models import (
|
|||||||
Button,
|
Button,
|
||||||
CellEditor,
|
CellEditor,
|
||||||
CheckboxEditor,
|
CheckboxEditor,
|
||||||
CheckboxGroup,
|
|
||||||
ColumnDataSource,
|
ColumnDataSource,
|
||||||
CustomJS,
|
CustomJS,
|
||||||
DataTable,
|
DataTable,
|
||||||
Div,
|
Div,
|
||||||
Dropdown,
|
|
||||||
FileInput,
|
FileInput,
|
||||||
MultiSelect,
|
MultiSelect,
|
||||||
NumberEditor,
|
|
||||||
Panel,
|
Panel,
|
||||||
RadioGroup,
|
RadioGroup,
|
||||||
Select,
|
Select,
|
||||||
@ -33,7 +29,7 @@ from bokeh.models import (
|
|||||||
from bokeh.plotting import figure
|
from bokeh.plotting import figure
|
||||||
|
|
||||||
import pyzebra
|
import pyzebra
|
||||||
from pyzebra import AREA_METHODS, EXPORT_TARGETS
|
from pyzebra import EXPORT_TARGETS, app
|
||||||
|
|
||||||
javaScript = """
|
javaScript = """
|
||||||
let j = 0;
|
let j = 0;
|
||||||
@ -61,7 +57,6 @@ def create():
|
|||||||
doc = curdoc()
|
doc = curdoc()
|
||||||
dataset1 = []
|
dataset1 = []
|
||||||
dataset2 = []
|
dataset2 = []
|
||||||
fit_params = {}
|
|
||||||
js_data = ColumnDataSource(data=dict(content=["", ""], fname=["", ""], ext=["", ""]))
|
js_data = ColumnDataSource(data=dict(content=["", ""], fname=["", ""], ext=["", ""]))
|
||||||
|
|
||||||
def file_select_update_for_proposal():
|
def file_select_update_for_proposal():
|
||||||
@ -244,7 +239,7 @@ def create():
|
|||||||
xs_peak = []
|
xs_peak = []
|
||||||
ys_peak = []
|
ys_peak = []
|
||||||
comps = fit.eval_components(x=x_fit)
|
comps = fit.eval_components(x=x_fit)
|
||||||
for i, model in enumerate(fit_params):
|
for i, model in enumerate(app_fitctrl.params):
|
||||||
if "linear" in model:
|
if "linear" in model:
|
||||||
x_bkg = x_fit
|
x_bkg = x_fit
|
||||||
y_bkg = comps[f"f{i}_"]
|
y_bkg = comps[f"f{i}_"]
|
||||||
@ -264,7 +259,7 @@ def create():
|
|||||||
bkg_source.data.update(x=[], y=[])
|
bkg_source.data.update(x=[], y=[])
|
||||||
peak_source.data.update(xs=[], ys=[])
|
peak_source.data.update(xs=[], ys=[])
|
||||||
|
|
||||||
fit_output_textinput.value = fit_output
|
app_fitctrl.result_textarea.value = fit_output
|
||||||
|
|
||||||
# Main plot
|
# Main plot
|
||||||
plot = figure(
|
plot = figure(
|
||||||
@ -425,136 +420,21 @@ def create():
|
|||||||
restore_button = Button(label="Restore scan", width=145)
|
restore_button = Button(label="Restore scan", width=145)
|
||||||
restore_button.on_click(restore_button_callback)
|
restore_button.on_click(restore_button_callback)
|
||||||
|
|
||||||
|
app_fitctrl = app.FitControls()
|
||||||
|
|
||||||
def fit_from_spinner_callback(_attr, _old, new):
|
def fit_from_spinner_callback(_attr, _old, new):
|
||||||
fit_from_span.location = new
|
fit_from_span.location = new
|
||||||
|
|
||||||
fit_from_spinner = Spinner(title="Fit from:", width=145)
|
app_fitctrl.from_spinner.on_change("value", fit_from_spinner_callback)
|
||||||
fit_from_spinner.on_change("value", fit_from_spinner_callback)
|
|
||||||
|
|
||||||
def fit_to_spinner_callback(_attr, _old, new):
|
def fit_to_spinner_callback(_attr, _old, new):
|
||||||
fit_to_span.location = new
|
fit_to_span.location = new
|
||||||
|
|
||||||
fit_to_spinner = Spinner(title="to:", width=145)
|
app_fitctrl.to_spinner.on_change("value", fit_to_spinner_callback)
|
||||||
fit_to_spinner.on_change("value", fit_to_spinner_callback)
|
|
||||||
|
|
||||||
def fitparams_add_dropdown_callback(click):
|
|
||||||
# bokeh requires (str, str) for MultiSelect options
|
|
||||||
new_tag = f"{click.item}-{fitparams_select.tags[0]}"
|
|
||||||
fitparams_select.options.append((new_tag, click.item))
|
|
||||||
fit_params[new_tag] = fitparams_factory(click.item)
|
|
||||||
fitparams_select.tags[0] += 1
|
|
||||||
|
|
||||||
fitparams_add_dropdown = Dropdown(
|
|
||||||
label="Add fit function",
|
|
||||||
menu=[
|
|
||||||
("Linear", "linear"),
|
|
||||||
("Gaussian", "gaussian"),
|
|
||||||
("Voigt", "voigt"),
|
|
||||||
("Pseudo Voigt", "pvoigt"),
|
|
||||||
# ("Pseudo Voigt1", "pseudovoigt1"),
|
|
||||||
],
|
|
||||||
width=145,
|
|
||||||
)
|
|
||||||
fitparams_add_dropdown.on_click(fitparams_add_dropdown_callback)
|
|
||||||
|
|
||||||
def fitparams_select_callback(_attr, old, new):
|
|
||||||
# Avoid selection of multiple indicies (via Shift+Click or Ctrl+Click)
|
|
||||||
if len(new) > 1:
|
|
||||||
# drop selection to the previous one
|
|
||||||
fitparams_select.value = old
|
|
||||||
return
|
|
||||||
|
|
||||||
if len(old) > 1:
|
|
||||||
# skip unnecessary update caused by selection drop
|
|
||||||
return
|
|
||||||
|
|
||||||
if new:
|
|
||||||
fitparams_table_source.data.update(fit_params[new[0]])
|
|
||||||
else:
|
|
||||||
fitparams_table_source.data.update(dict(param=[], value=[], vary=[], min=[], max=[]))
|
|
||||||
|
|
||||||
fitparams_select = MultiSelect(options=[], height=120, width=145)
|
|
||||||
fitparams_select.tags = [0]
|
|
||||||
fitparams_select.on_change("value", fitparams_select_callback)
|
|
||||||
|
|
||||||
def fitparams_remove_button_callback():
|
|
||||||
if fitparams_select.value:
|
|
||||||
sel_tag = fitparams_select.value[0]
|
|
||||||
del fit_params[sel_tag]
|
|
||||||
for elem in fitparams_select.options:
|
|
||||||
if elem[0] == sel_tag:
|
|
||||||
fitparams_select.options.remove(elem)
|
|
||||||
break
|
|
||||||
|
|
||||||
fitparams_select.value = []
|
|
||||||
|
|
||||||
fitparams_remove_button = Button(label="Remove fit function", width=145)
|
|
||||||
fitparams_remove_button.on_click(fitparams_remove_button_callback)
|
|
||||||
|
|
||||||
def fitparams_factory(function):
|
|
||||||
if function == "linear":
|
|
||||||
params = ["slope", "intercept"]
|
|
||||||
elif function == "gaussian":
|
|
||||||
params = ["amplitude", "center", "sigma"]
|
|
||||||
elif function == "voigt":
|
|
||||||
params = ["amplitude", "center", "sigma", "gamma"]
|
|
||||||
elif function == "pvoigt":
|
|
||||||
params = ["amplitude", "center", "sigma", "fraction"]
|
|
||||||
elif function == "pseudovoigt1":
|
|
||||||
params = ["amplitude", "center", "g_sigma", "l_sigma", "fraction"]
|
|
||||||
else:
|
|
||||||
raise ValueError("Unknown fit function")
|
|
||||||
|
|
||||||
n = len(params)
|
|
||||||
fitparams = dict(
|
|
||||||
param=params, value=[None] * n, vary=[True] * n, min=[None] * n, max=[None] * n
|
|
||||||
)
|
|
||||||
|
|
||||||
if function == "linear":
|
|
||||||
fitparams["value"] = [0, 1]
|
|
||||||
fitparams["vary"] = [False, True]
|
|
||||||
fitparams["min"] = [None, 0]
|
|
||||||
|
|
||||||
elif function == "gaussian":
|
|
||||||
fitparams["min"] = [0, None, None]
|
|
||||||
|
|
||||||
return fitparams
|
|
||||||
|
|
||||||
fitparams_table_source = ColumnDataSource(dict(param=[], value=[], vary=[], min=[], max=[]))
|
|
||||||
fitparams_table = DataTable(
|
|
||||||
source=fitparams_table_source,
|
|
||||||
columns=[
|
|
||||||
TableColumn(field="param", title="Parameter", editor=CellEditor()),
|
|
||||||
TableColumn(field="value", title="Value", editor=NumberEditor()),
|
|
||||||
TableColumn(field="vary", title="Vary", editor=CheckboxEditor()),
|
|
||||||
TableColumn(field="min", title="Min", editor=NumberEditor()),
|
|
||||||
TableColumn(field="max", title="Max", editor=NumberEditor()),
|
|
||||||
],
|
|
||||||
height=200,
|
|
||||||
width=350,
|
|
||||||
index_position=None,
|
|
||||||
editable=True,
|
|
||||||
auto_edit=True,
|
|
||||||
)
|
|
||||||
|
|
||||||
# start with `background` and `gauss` fit functions added
|
|
||||||
fitparams_add_dropdown_callback(types.SimpleNamespace(item="linear"))
|
|
||||||
fitparams_add_dropdown_callback(types.SimpleNamespace(item="gaussian"))
|
|
||||||
fitparams_select.value = ["gaussian-1"] # add selection to gauss
|
|
||||||
|
|
||||||
fit_output_textinput = TextAreaInput(title="Fit results:", width=750, height=200)
|
|
||||||
|
|
||||||
def proc_all_button_callback():
|
def proc_all_button_callback():
|
||||||
for scan in [*dataset1, *dataset2]:
|
app_fitctrl.fit_dataset(dataset1)
|
||||||
if scan["export"]:
|
app_fitctrl.fit_dataset(dataset2)
|
||||||
pyzebra.fit_scan(
|
|
||||||
scan, fit_params, fit_from=fit_from_spinner.value, fit_to=fit_to_spinner.value
|
|
||||||
)
|
|
||||||
pyzebra.get_area(
|
|
||||||
scan,
|
|
||||||
area_method=AREA_METHODS[area_method_radiobutton.active],
|
|
||||||
lorentz=lorentz_checkbox.active,
|
|
||||||
)
|
|
||||||
|
|
||||||
_update_plot()
|
_update_plot()
|
||||||
_update_table()
|
_update_table()
|
||||||
@ -563,15 +443,9 @@ def create():
|
|||||||
proc_all_button.on_click(proc_all_button_callback)
|
proc_all_button.on_click(proc_all_button_callback)
|
||||||
|
|
||||||
def proc_button_callback():
|
def proc_button_callback():
|
||||||
for scan in _get_selected_scan():
|
scan1, scan2 = _get_selected_scan()
|
||||||
pyzebra.fit_scan(
|
app_fitctrl.fit_scan(scan1)
|
||||||
scan, fit_params, fit_from=fit_from_spinner.value, fit_to=fit_to_spinner.value
|
app_fitctrl.fit_scan(scan2)
|
||||||
)
|
|
||||||
pyzebra.get_area(
|
|
||||||
scan,
|
|
||||||
area_method=AREA_METHODS[area_method_radiobutton.active],
|
|
||||||
lorentz=lorentz_checkbox.active,
|
|
||||||
)
|
|
||||||
|
|
||||||
_update_plot()
|
_update_plot()
|
||||||
_update_table()
|
_update_table()
|
||||||
@ -579,16 +453,11 @@ def create():
|
|||||||
proc_button = Button(label="Process Current", width=145)
|
proc_button = Button(label="Process Current", width=145)
|
||||||
proc_button.on_click(proc_button_callback)
|
proc_button.on_click(proc_button_callback)
|
||||||
|
|
||||||
area_method_div = Div(text="Intensity:", margin=(5, 5, 0, 5))
|
|
||||||
area_method_radiobutton = RadioGroup(labels=["Function", "Area"], active=0, width=145)
|
|
||||||
|
|
||||||
intensity_diff_div = Div(text="Intensity difference:", margin=(5, 5, 0, 5))
|
intensity_diff_div = Div(text="Intensity difference:", margin=(5, 5, 0, 5))
|
||||||
intensity_diff_radiobutton = RadioGroup(
|
intensity_diff_radiobutton = RadioGroup(
|
||||||
labels=["file1 - file2", "file2 - file1"], active=0, width=145
|
labels=["file1 - file2", "file2 - file1"], active=0, width=145
|
||||||
)
|
)
|
||||||
|
|
||||||
lorentz_checkbox = CheckboxGroup(labels=["Lorentz Correction"], width=145, margin=(13, 5, 5, 5))
|
|
||||||
|
|
||||||
export_preview_textinput = TextAreaInput(title="Export file(s) preview:", width=500, height=400)
|
export_preview_textinput = TextAreaInput(title="Export file(s) preview:", width=500, height=400)
|
||||||
|
|
||||||
def _update_preview():
|
def _update_preview():
|
||||||
@ -648,19 +517,24 @@ def create():
|
|||||||
save_button = Button(label="Download File(s)", button_type="success", width=200)
|
save_button = Button(label="Download File(s)", button_type="success", width=200)
|
||||||
save_button.js_on_click(CustomJS(args={"js_data": js_data}, code=javaScript))
|
save_button.js_on_click(CustomJS(args={"js_data": js_data}, code=javaScript))
|
||||||
|
|
||||||
|
area_method_div = Div(text="Intensity:", margin=(5, 5, 0, 5))
|
||||||
fitpeak_controls = row(
|
fitpeak_controls = row(
|
||||||
column(fitparams_add_dropdown, fitparams_select, fitparams_remove_button),
|
column(
|
||||||
fitparams_table,
|
app_fitctrl.add_function_button,
|
||||||
|
app_fitctrl.function_select,
|
||||||
|
app_fitctrl.remove_function_button,
|
||||||
|
),
|
||||||
|
app_fitctrl.params_table,
|
||||||
Spacer(width=20),
|
Spacer(width=20),
|
||||||
column(
|
column(
|
||||||
fit_from_spinner,
|
app_fitctrl.from_spinner,
|
||||||
lorentz_checkbox,
|
app_fitctrl.lorentz_checkbox,
|
||||||
area_method_div,
|
area_method_div,
|
||||||
area_method_radiobutton,
|
app_fitctrl.area_method_radiogroup,
|
||||||
intensity_diff_div,
|
intensity_diff_div,
|
||||||
intensity_diff_radiobutton,
|
intensity_diff_radiobutton,
|
||||||
),
|
),
|
||||||
column(fit_to_spinner, proc_button, proc_all_button),
|
column(app_fitctrl.to_spinner, proc_button, proc_all_button),
|
||||||
)
|
)
|
||||||
|
|
||||||
scan_layout = column(
|
scan_layout = column(
|
||||||
@ -680,7 +554,7 @@ def create():
|
|||||||
|
|
||||||
tab_layout = column(
|
tab_layout = column(
|
||||||
row(import_layout, scan_layout, plot, Spacer(width=30), export_layout),
|
row(import_layout, scan_layout, plot, Spacer(width=30), export_layout),
|
||||||
row(fitpeak_controls, fit_output_textinput),
|
row(fitpeak_controls, app_fitctrl.result_textarea),
|
||||||
)
|
)
|
||||||
|
|
||||||
return Panel(child=tab_layout, title="ccl compare")
|
return Panel(child=tab_layout, title="ccl compare")
|
||||||
|
@ -2,7 +2,6 @@ import base64
|
|||||||
import io
|
import io
|
||||||
import os
|
import os
|
||||||
import tempfile
|
import tempfile
|
||||||
import types
|
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from bokeh.io import curdoc
|
from bokeh.io import curdoc
|
||||||
@ -11,17 +10,13 @@ from bokeh.models import (
|
|||||||
Button,
|
Button,
|
||||||
CellEditor,
|
CellEditor,
|
||||||
CheckboxEditor,
|
CheckboxEditor,
|
||||||
CheckboxGroup,
|
|
||||||
ColumnDataSource,
|
ColumnDataSource,
|
||||||
CustomJS,
|
CustomJS,
|
||||||
DataTable,
|
DataTable,
|
||||||
Div,
|
Div,
|
||||||
Dropdown,
|
|
||||||
FileInput,
|
FileInput,
|
||||||
MultiSelect,
|
MultiSelect,
|
||||||
NumberEditor,
|
|
||||||
Panel,
|
Panel,
|
||||||
RadioGroup,
|
|
||||||
Select,
|
Select,
|
||||||
Spacer,
|
Spacer,
|
||||||
Span,
|
Span,
|
||||||
@ -33,7 +28,7 @@ from bokeh.models import (
|
|||||||
from bokeh.plotting import figure
|
from bokeh.plotting import figure
|
||||||
|
|
||||||
import pyzebra
|
import pyzebra
|
||||||
from pyzebra import AREA_METHODS, EXPORT_TARGETS
|
from pyzebra import EXPORT_TARGETS, app
|
||||||
|
|
||||||
javaScript = """
|
javaScript = """
|
||||||
let j = 0;
|
let j = 0;
|
||||||
@ -60,7 +55,6 @@ for (let i = 0; i < js_data.data['fname'].length; i++) {
|
|||||||
def create():
|
def create():
|
||||||
doc = curdoc()
|
doc = curdoc()
|
||||||
dataset = []
|
dataset = []
|
||||||
fit_params = {}
|
|
||||||
js_data = ColumnDataSource(data=dict(content=["", ""], fname=["", ""], ext=["", ""]))
|
js_data = ColumnDataSource(data=dict(content=["", ""], fname=["", ""], ext=["", ""]))
|
||||||
|
|
||||||
def file_select_update_for_proposal():
|
def file_select_update_for_proposal():
|
||||||
@ -259,7 +253,7 @@ def create():
|
|||||||
xs_peak = []
|
xs_peak = []
|
||||||
ys_peak = []
|
ys_peak = []
|
||||||
comps = fit.eval_components(x=x_fit)
|
comps = fit.eval_components(x=x_fit)
|
||||||
for i, model in enumerate(fit_params):
|
for i, model in enumerate(app_fitctrl.params):
|
||||||
if "linear" in model:
|
if "linear" in model:
|
||||||
x_bkg = x_fit
|
x_bkg = x_fit
|
||||||
y_bkg = comps[f"f{i}_"]
|
y_bkg = comps[f"f{i}_"]
|
||||||
@ -271,13 +265,12 @@ def create():
|
|||||||
bkg_source.data.update(x=x_bkg, y=y_bkg)
|
bkg_source.data.update(x=x_bkg, y=y_bkg)
|
||||||
peak_source.data.update(xs=xs_peak, ys=ys_peak)
|
peak_source.data.update(xs=xs_peak, ys=ys_peak)
|
||||||
|
|
||||||
fit_output_textinput.value = fit.fit_report()
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
fit_source.data.update(x=[], y=[])
|
fit_source.data.update(x=[], y=[])
|
||||||
bkg_source.data.update(x=[], y=[])
|
bkg_source.data.update(x=[], y=[])
|
||||||
peak_source.data.update(xs=[], ys=[])
|
peak_source.data.update(xs=[], ys=[])
|
||||||
fit_output_textinput.value = ""
|
|
||||||
|
app_fitctrl.update_result_textarea(scan)
|
||||||
|
|
||||||
# Main plot
|
# Main plot
|
||||||
plot = figure(
|
plot = figure(
|
||||||
@ -403,136 +396,20 @@ def create():
|
|||||||
restore_button = Button(label="Restore scan", width=145)
|
restore_button = Button(label="Restore scan", width=145)
|
||||||
restore_button.on_click(restore_button_callback)
|
restore_button.on_click(restore_button_callback)
|
||||||
|
|
||||||
|
app_fitctrl = app.FitControls()
|
||||||
|
|
||||||
def fit_from_spinner_callback(_attr, _old, new):
|
def fit_from_spinner_callback(_attr, _old, new):
|
||||||
fit_from_span.location = new
|
fit_from_span.location = new
|
||||||
|
|
||||||
fit_from_spinner = Spinner(title="Fit from:", width=145)
|
app_fitctrl.from_spinner.on_change("value", fit_from_spinner_callback)
|
||||||
fit_from_spinner.on_change("value", fit_from_spinner_callback)
|
|
||||||
|
|
||||||
def fit_to_spinner_callback(_attr, _old, new):
|
def fit_to_spinner_callback(_attr, _old, new):
|
||||||
fit_to_span.location = new
|
fit_to_span.location = new
|
||||||
|
|
||||||
fit_to_spinner = Spinner(title="to:", width=145)
|
app_fitctrl.to_spinner.on_change("value", fit_to_spinner_callback)
|
||||||
fit_to_spinner.on_change("value", fit_to_spinner_callback)
|
|
||||||
|
|
||||||
def fitparams_add_dropdown_callback(click):
|
|
||||||
# bokeh requires (str, str) for MultiSelect options
|
|
||||||
new_tag = f"{click.item}-{fitparams_select.tags[0]}"
|
|
||||||
fitparams_select.options.append((new_tag, click.item))
|
|
||||||
fit_params[new_tag] = fitparams_factory(click.item)
|
|
||||||
fitparams_select.tags[0] += 1
|
|
||||||
|
|
||||||
fitparams_add_dropdown = Dropdown(
|
|
||||||
label="Add fit function",
|
|
||||||
menu=[
|
|
||||||
("Linear", "linear"),
|
|
||||||
("Gaussian", "gaussian"),
|
|
||||||
("Voigt", "voigt"),
|
|
||||||
("Pseudo Voigt", "pvoigt"),
|
|
||||||
# ("Pseudo Voigt1", "pseudovoigt1"),
|
|
||||||
],
|
|
||||||
width=145,
|
|
||||||
)
|
|
||||||
fitparams_add_dropdown.on_click(fitparams_add_dropdown_callback)
|
|
||||||
|
|
||||||
def fitparams_select_callback(_attr, old, new):
|
|
||||||
# Avoid selection of multiple indicies (via Shift+Click or Ctrl+Click)
|
|
||||||
if len(new) > 1:
|
|
||||||
# drop selection to the previous one
|
|
||||||
fitparams_select.value = old
|
|
||||||
return
|
|
||||||
|
|
||||||
if len(old) > 1:
|
|
||||||
# skip unnecessary update caused by selection drop
|
|
||||||
return
|
|
||||||
|
|
||||||
if new:
|
|
||||||
fitparams_table_source.data.update(fit_params[new[0]])
|
|
||||||
else:
|
|
||||||
fitparams_table_source.data.update(dict(param=[], value=[], vary=[], min=[], max=[]))
|
|
||||||
|
|
||||||
fitparams_select = MultiSelect(options=[], height=120, width=145)
|
|
||||||
fitparams_select.tags = [0]
|
|
||||||
fitparams_select.on_change("value", fitparams_select_callback)
|
|
||||||
|
|
||||||
def fitparams_remove_button_callback():
|
|
||||||
if fitparams_select.value:
|
|
||||||
sel_tag = fitparams_select.value[0]
|
|
||||||
del fit_params[sel_tag]
|
|
||||||
for elem in fitparams_select.options:
|
|
||||||
if elem[0] == sel_tag:
|
|
||||||
fitparams_select.options.remove(elem)
|
|
||||||
break
|
|
||||||
|
|
||||||
fitparams_select.value = []
|
|
||||||
|
|
||||||
fitparams_remove_button = Button(label="Remove fit function", width=145)
|
|
||||||
fitparams_remove_button.on_click(fitparams_remove_button_callback)
|
|
||||||
|
|
||||||
def fitparams_factory(function):
|
|
||||||
if function == "linear":
|
|
||||||
params = ["slope", "intercept"]
|
|
||||||
elif function == "gaussian":
|
|
||||||
params = ["amplitude", "center", "sigma"]
|
|
||||||
elif function == "voigt":
|
|
||||||
params = ["amplitude", "center", "sigma", "gamma"]
|
|
||||||
elif function == "pvoigt":
|
|
||||||
params = ["amplitude", "center", "sigma", "fraction"]
|
|
||||||
elif function == "pseudovoigt1":
|
|
||||||
params = ["amplitude", "center", "g_sigma", "l_sigma", "fraction"]
|
|
||||||
else:
|
|
||||||
raise ValueError("Unknown fit function")
|
|
||||||
|
|
||||||
n = len(params)
|
|
||||||
fitparams = dict(
|
|
||||||
param=params, value=[None] * n, vary=[True] * n, min=[None] * n, max=[None] * n
|
|
||||||
)
|
|
||||||
|
|
||||||
if function == "linear":
|
|
||||||
fitparams["value"] = [0, 1]
|
|
||||||
fitparams["vary"] = [False, True]
|
|
||||||
fitparams["min"] = [None, 0]
|
|
||||||
|
|
||||||
elif function == "gaussian":
|
|
||||||
fitparams["min"] = [0, None, None]
|
|
||||||
|
|
||||||
return fitparams
|
|
||||||
|
|
||||||
fitparams_table_source = ColumnDataSource(dict(param=[], value=[], vary=[], min=[], max=[]))
|
|
||||||
fitparams_table = DataTable(
|
|
||||||
source=fitparams_table_source,
|
|
||||||
columns=[
|
|
||||||
TableColumn(field="param", title="Parameter", editor=CellEditor()),
|
|
||||||
TableColumn(field="value", title="Value", editor=NumberEditor()),
|
|
||||||
TableColumn(field="vary", title="Vary", editor=CheckboxEditor()),
|
|
||||||
TableColumn(field="min", title="Min", editor=NumberEditor()),
|
|
||||||
TableColumn(field="max", title="Max", editor=NumberEditor()),
|
|
||||||
],
|
|
||||||
height=200,
|
|
||||||
width=350,
|
|
||||||
index_position=None,
|
|
||||||
editable=True,
|
|
||||||
auto_edit=True,
|
|
||||||
)
|
|
||||||
|
|
||||||
# start with `background` and `gauss` fit functions added
|
|
||||||
fitparams_add_dropdown_callback(types.SimpleNamespace(item="linear"))
|
|
||||||
fitparams_add_dropdown_callback(types.SimpleNamespace(item="gaussian"))
|
|
||||||
fitparams_select.value = ["gaussian-1"] # add selection to gauss
|
|
||||||
|
|
||||||
fit_output_textinput = TextAreaInput(title="Fit results:", width=750, height=200)
|
|
||||||
|
|
||||||
def proc_all_button_callback():
|
def proc_all_button_callback():
|
||||||
for scan in dataset:
|
app_fitctrl.fit_dataset(dataset)
|
||||||
if scan["export"]:
|
|
||||||
pyzebra.fit_scan(
|
|
||||||
scan, fit_params, fit_from=fit_from_spinner.value, fit_to=fit_to_spinner.value
|
|
||||||
)
|
|
||||||
pyzebra.get_area(
|
|
||||||
scan,
|
|
||||||
area_method=AREA_METHODS[area_method_radiobutton.active],
|
|
||||||
lorentz=lorentz_checkbox.active,
|
|
||||||
)
|
|
||||||
|
|
||||||
_update_plot()
|
_update_plot()
|
||||||
_update_table()
|
_update_table()
|
||||||
@ -541,15 +418,7 @@ def create():
|
|||||||
proc_all_button.on_click(proc_all_button_callback)
|
proc_all_button.on_click(proc_all_button_callback)
|
||||||
|
|
||||||
def proc_button_callback():
|
def proc_button_callback():
|
||||||
scan = _get_selected_scan()
|
app_fitctrl.fit_scan(_get_selected_scan())
|
||||||
pyzebra.fit_scan(
|
|
||||||
scan, fit_params, fit_from=fit_from_spinner.value, fit_to=fit_to_spinner.value
|
|
||||||
)
|
|
||||||
pyzebra.get_area(
|
|
||||||
scan,
|
|
||||||
area_method=AREA_METHODS[area_method_radiobutton.active],
|
|
||||||
lorentz=lorentz_checkbox.active,
|
|
||||||
)
|
|
||||||
|
|
||||||
_update_plot()
|
_update_plot()
|
||||||
_update_table()
|
_update_table()
|
||||||
@ -557,11 +426,6 @@ def create():
|
|||||||
proc_button = Button(label="Process Current", width=145)
|
proc_button = Button(label="Process Current", width=145)
|
||||||
proc_button.on_click(proc_button_callback)
|
proc_button.on_click(proc_button_callback)
|
||||||
|
|
||||||
area_method_div = Div(text="Intensity:", margin=(5, 5, 0, 5))
|
|
||||||
area_method_radiobutton = RadioGroup(labels=["Function", "Area"], active=0, width=145)
|
|
||||||
|
|
||||||
lorentz_checkbox = CheckboxGroup(labels=["Lorentz Correction"], width=145, margin=(13, 5, 5, 5))
|
|
||||||
|
|
||||||
export_preview_textinput = TextAreaInput(title="Export file(s) preview:", width=500, height=400)
|
export_preview_textinput = TextAreaInput(title="Export file(s) preview:", width=500, height=400)
|
||||||
|
|
||||||
def _update_preview():
|
def _update_preview():
|
||||||
@ -615,12 +479,22 @@ def create():
|
|||||||
save_button = Button(label="Download File(s)", button_type="success", width=200)
|
save_button = Button(label="Download File(s)", button_type="success", width=200)
|
||||||
save_button.js_on_click(CustomJS(args={"js_data": js_data}, code=javaScript))
|
save_button.js_on_click(CustomJS(args={"js_data": js_data}, code=javaScript))
|
||||||
|
|
||||||
|
area_method_div = Div(text="Intensity:", margin=(5, 5, 0, 5))
|
||||||
fitpeak_controls = row(
|
fitpeak_controls = row(
|
||||||
column(fitparams_add_dropdown, fitparams_select, fitparams_remove_button),
|
column(
|
||||||
fitparams_table,
|
app_fitctrl.add_function_button,
|
||||||
|
app_fitctrl.function_select,
|
||||||
|
app_fitctrl.remove_function_button,
|
||||||
|
),
|
||||||
|
app_fitctrl.params_table,
|
||||||
Spacer(width=20),
|
Spacer(width=20),
|
||||||
column(fit_from_spinner, lorentz_checkbox, area_method_div, area_method_radiobutton),
|
column(
|
||||||
column(fit_to_spinner, proc_button, proc_all_button),
|
app_fitctrl.from_spinner,
|
||||||
|
app_fitctrl.lorentz_checkbox,
|
||||||
|
area_method_div,
|
||||||
|
app_fitctrl.area_method_radiogroup,
|
||||||
|
),
|
||||||
|
column(app_fitctrl.to_spinner, proc_button, proc_all_button),
|
||||||
)
|
)
|
||||||
|
|
||||||
scan_layout = column(
|
scan_layout = column(
|
||||||
@ -647,7 +521,7 @@ def create():
|
|||||||
|
|
||||||
tab_layout = column(
|
tab_layout = column(
|
||||||
row(import_layout, scan_layout, plot, Spacer(width=30), export_layout),
|
row(import_layout, scan_layout, plot, Spacer(width=30), export_layout),
|
||||||
row(fitpeak_controls, fit_output_textinput),
|
row(fitpeak_controls, app_fitctrl.result_textarea),
|
||||||
)
|
)
|
||||||
|
|
||||||
return Panel(child=tab_layout, title="ccl integrate")
|
return Panel(child=tab_layout, title="ccl integrate")
|
||||||
|
@ -3,7 +3,6 @@ import io
|
|||||||
import itertools
|
import itertools
|
||||||
import os
|
import os
|
||||||
import tempfile
|
import tempfile
|
||||||
import types
|
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from bokeh.io import curdoc
|
from bokeh.io import curdoc
|
||||||
@ -12,19 +11,16 @@ from bokeh.models import (
|
|||||||
Button,
|
Button,
|
||||||
CellEditor,
|
CellEditor,
|
||||||
CheckboxEditor,
|
CheckboxEditor,
|
||||||
CheckboxGroup,
|
|
||||||
ColumnDataSource,
|
ColumnDataSource,
|
||||||
CustomJS,
|
CustomJS,
|
||||||
DataTable,
|
DataTable,
|
||||||
Div,
|
Div,
|
||||||
Dropdown,
|
|
||||||
FileInput,
|
FileInput,
|
||||||
HoverTool,
|
HoverTool,
|
||||||
LinearColorMapper,
|
LinearColorMapper,
|
||||||
MultiSelect,
|
MultiSelect,
|
||||||
NumberEditor,
|
NumberEditor,
|
||||||
Panel,
|
Panel,
|
||||||
RadioGroup,
|
|
||||||
Range1d,
|
Range1d,
|
||||||
Select,
|
Select,
|
||||||
Spacer,
|
Spacer,
|
||||||
@ -40,7 +36,7 @@ from bokeh.plotting import figure
|
|||||||
from scipy import interpolate
|
from scipy import interpolate
|
||||||
|
|
||||||
import pyzebra
|
import pyzebra
|
||||||
from pyzebra import AREA_METHODS
|
from pyzebra import app
|
||||||
|
|
||||||
javaScript = """
|
javaScript = """
|
||||||
let j = 0;
|
let j = 0;
|
||||||
@ -72,7 +68,6 @@ def color_palette(n_colors):
|
|||||||
def create():
|
def create():
|
||||||
doc = curdoc()
|
doc = curdoc()
|
||||||
dataset = []
|
dataset = []
|
||||||
fit_params = {}
|
|
||||||
js_data = ColumnDataSource(data=dict(content=[""], fname=[""], ext=[""]))
|
js_data = ColumnDataSource(data=dict(content=[""], fname=[""], ext=[""]))
|
||||||
|
|
||||||
def file_select_update_for_proposal():
|
def file_select_update_for_proposal():
|
||||||
@ -281,7 +276,7 @@ def create():
|
|||||||
xs_peak = []
|
xs_peak = []
|
||||||
ys_peak = []
|
ys_peak = []
|
||||||
comps = fit.eval_components(x=x_fit)
|
comps = fit.eval_components(x=x_fit)
|
||||||
for i, model in enumerate(fit_params):
|
for i, model in enumerate(app_fitctrl.params):
|
||||||
if "linear" in model:
|
if "linear" in model:
|
||||||
x_bkg = x_fit
|
x_bkg = x_fit
|
||||||
y_bkg = comps[f"f{i}_"]
|
y_bkg = comps[f"f{i}_"]
|
||||||
@ -293,13 +288,12 @@ def create():
|
|||||||
bkg_source.data.update(x=x_bkg, y=y_bkg)
|
bkg_source.data.update(x=x_bkg, y=y_bkg)
|
||||||
peak_source.data.update(xs=xs_peak, ys=ys_peak)
|
peak_source.data.update(xs=xs_peak, ys=ys_peak)
|
||||||
|
|
||||||
fit_output_textinput.value = fit.fit_report()
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
fit_source.data.update(x=[], y=[])
|
fit_source.data.update(x=[], y=[])
|
||||||
bkg_source.data.update(x=[], y=[])
|
bkg_source.data.update(x=[], y=[])
|
||||||
peak_source.data.update(xs=[], ys=[])
|
peak_source.data.update(xs=[], ys=[])
|
||||||
fit_output_textinput.value = ""
|
|
||||||
|
app_fitctrl.update_result_textarea(scan)
|
||||||
|
|
||||||
def _update_overview():
|
def _update_overview():
|
||||||
xs = []
|
xs = []
|
||||||
@ -562,136 +556,20 @@ def create():
|
|||||||
)
|
)
|
||||||
param_select.on_change("value", param_select_callback)
|
param_select.on_change("value", param_select_callback)
|
||||||
|
|
||||||
|
app_fitctrl = app.FitControls()
|
||||||
|
|
||||||
def fit_from_spinner_callback(_attr, _old, new):
|
def fit_from_spinner_callback(_attr, _old, new):
|
||||||
fit_from_span.location = new
|
fit_from_span.location = new
|
||||||
|
|
||||||
fit_from_spinner = Spinner(title="Fit from:", width=145)
|
app_fitctrl.from_spinner.on_change("value", fit_from_spinner_callback)
|
||||||
fit_from_spinner.on_change("value", fit_from_spinner_callback)
|
|
||||||
|
|
||||||
def fit_to_spinner_callback(_attr, _old, new):
|
def fit_to_spinner_callback(_attr, _old, new):
|
||||||
fit_to_span.location = new
|
fit_to_span.location = new
|
||||||
|
|
||||||
fit_to_spinner = Spinner(title="to:", width=145)
|
app_fitctrl.to_spinner.on_change("value", fit_to_spinner_callback)
|
||||||
fit_to_spinner.on_change("value", fit_to_spinner_callback)
|
|
||||||
|
|
||||||
def fitparams_add_dropdown_callback(click):
|
|
||||||
# bokeh requires (str, str) for MultiSelect options
|
|
||||||
new_tag = f"{click.item}-{fitparams_select.tags[0]}"
|
|
||||||
fitparams_select.options.append((new_tag, click.item))
|
|
||||||
fit_params[new_tag] = fitparams_factory(click.item)
|
|
||||||
fitparams_select.tags[0] += 1
|
|
||||||
|
|
||||||
fitparams_add_dropdown = Dropdown(
|
|
||||||
label="Add fit function",
|
|
||||||
menu=[
|
|
||||||
("Linear", "linear"),
|
|
||||||
("Gaussian", "gaussian"),
|
|
||||||
("Voigt", "voigt"),
|
|
||||||
("Pseudo Voigt", "pvoigt"),
|
|
||||||
# ("Pseudo Voigt1", "pseudovoigt1"),
|
|
||||||
],
|
|
||||||
width=145,
|
|
||||||
)
|
|
||||||
fitparams_add_dropdown.on_click(fitparams_add_dropdown_callback)
|
|
||||||
|
|
||||||
def fitparams_select_callback(_attr, old, new):
|
|
||||||
# Avoid selection of multiple indicies (via Shift+Click or Ctrl+Click)
|
|
||||||
if len(new) > 1:
|
|
||||||
# drop selection to the previous one
|
|
||||||
fitparams_select.value = old
|
|
||||||
return
|
|
||||||
|
|
||||||
if len(old) > 1:
|
|
||||||
# skip unnecessary update caused by selection drop
|
|
||||||
return
|
|
||||||
|
|
||||||
if new:
|
|
||||||
fitparams_table_source.data.update(fit_params[new[0]])
|
|
||||||
else:
|
|
||||||
fitparams_table_source.data.update(dict(param=[], value=[], vary=[], min=[], max=[]))
|
|
||||||
|
|
||||||
fitparams_select = MultiSelect(options=[], height=120, width=145)
|
|
||||||
fitparams_select.tags = [0]
|
|
||||||
fitparams_select.on_change("value", fitparams_select_callback)
|
|
||||||
|
|
||||||
def fitparams_remove_button_callback():
|
|
||||||
if fitparams_select.value:
|
|
||||||
sel_tag = fitparams_select.value[0]
|
|
||||||
del fit_params[sel_tag]
|
|
||||||
for elem in fitparams_select.options:
|
|
||||||
if elem[0] == sel_tag:
|
|
||||||
fitparams_select.options.remove(elem)
|
|
||||||
break
|
|
||||||
|
|
||||||
fitparams_select.value = []
|
|
||||||
|
|
||||||
fitparams_remove_button = Button(label="Remove fit function", width=145)
|
|
||||||
fitparams_remove_button.on_click(fitparams_remove_button_callback)
|
|
||||||
|
|
||||||
def fitparams_factory(function):
|
|
||||||
if function == "linear":
|
|
||||||
params = ["slope", "intercept"]
|
|
||||||
elif function == "gaussian":
|
|
||||||
params = ["amplitude", "center", "sigma"]
|
|
||||||
elif function == "voigt":
|
|
||||||
params = ["amplitude", "center", "sigma", "gamma"]
|
|
||||||
elif function == "pvoigt":
|
|
||||||
params = ["amplitude", "center", "sigma", "fraction"]
|
|
||||||
elif function == "pseudovoigt1":
|
|
||||||
params = ["amplitude", "center", "g_sigma", "l_sigma", "fraction"]
|
|
||||||
else:
|
|
||||||
raise ValueError("Unknown fit function")
|
|
||||||
|
|
||||||
n = len(params)
|
|
||||||
fitparams = dict(
|
|
||||||
param=params, value=[None] * n, vary=[True] * n, min=[None] * n, max=[None] * n
|
|
||||||
)
|
|
||||||
|
|
||||||
if function == "linear":
|
|
||||||
fitparams["value"] = [0, 1]
|
|
||||||
fitparams["vary"] = [False, True]
|
|
||||||
fitparams["min"] = [None, 0]
|
|
||||||
|
|
||||||
elif function == "gaussian":
|
|
||||||
fitparams["min"] = [0, None, None]
|
|
||||||
|
|
||||||
return fitparams
|
|
||||||
|
|
||||||
fitparams_table_source = ColumnDataSource(dict(param=[], value=[], vary=[], min=[], max=[]))
|
|
||||||
fitparams_table = DataTable(
|
|
||||||
source=fitparams_table_source,
|
|
||||||
columns=[
|
|
||||||
TableColumn(field="param", title="Parameter", editor=CellEditor()),
|
|
||||||
TableColumn(field="value", title="Value", editor=NumberEditor()),
|
|
||||||
TableColumn(field="vary", title="Vary", editor=CheckboxEditor()),
|
|
||||||
TableColumn(field="min", title="Min", editor=NumberEditor()),
|
|
||||||
TableColumn(field="max", title="Max", editor=NumberEditor()),
|
|
||||||
],
|
|
||||||
height=200,
|
|
||||||
width=350,
|
|
||||||
index_position=None,
|
|
||||||
editable=True,
|
|
||||||
auto_edit=True,
|
|
||||||
)
|
|
||||||
|
|
||||||
# start with `background` and `gauss` fit functions added
|
|
||||||
fitparams_add_dropdown_callback(types.SimpleNamespace(item="linear"))
|
|
||||||
fitparams_add_dropdown_callback(types.SimpleNamespace(item="gaussian"))
|
|
||||||
fitparams_select.value = ["gaussian-1"] # add selection to gauss
|
|
||||||
|
|
||||||
fit_output_textinput = TextAreaInput(title="Fit results:", width=750, height=200)
|
|
||||||
|
|
||||||
def proc_all_button_callback():
|
def proc_all_button_callback():
|
||||||
for scan in dataset:
|
app_fitctrl.fit_dataset(dataset)
|
||||||
if scan["export"]:
|
|
||||||
pyzebra.fit_scan(
|
|
||||||
scan, fit_params, fit_from=fit_from_spinner.value, fit_to=fit_to_spinner.value
|
|
||||||
)
|
|
||||||
pyzebra.get_area(
|
|
||||||
scan,
|
|
||||||
area_method=AREA_METHODS[area_method_radiobutton.active],
|
|
||||||
lorentz=lorentz_checkbox.active,
|
|
||||||
)
|
|
||||||
|
|
||||||
_update_single_scan_plot()
|
_update_single_scan_plot()
|
||||||
_update_overview()
|
_update_overview()
|
||||||
@ -708,15 +586,7 @@ def create():
|
|||||||
proc_all_button.on_click(proc_all_button_callback)
|
proc_all_button.on_click(proc_all_button_callback)
|
||||||
|
|
||||||
def proc_button_callback():
|
def proc_button_callback():
|
||||||
scan = _get_selected_scan()
|
app_fitctrl.fit_scan(_get_selected_scan())
|
||||||
pyzebra.fit_scan(
|
|
||||||
scan, fit_params, fit_from=fit_from_spinner.value, fit_to=fit_to_spinner.value
|
|
||||||
)
|
|
||||||
pyzebra.get_area(
|
|
||||||
scan,
|
|
||||||
area_method=AREA_METHODS[area_method_radiobutton.active],
|
|
||||||
lorentz=lorentz_checkbox.active,
|
|
||||||
)
|
|
||||||
|
|
||||||
_update_single_scan_plot()
|
_update_single_scan_plot()
|
||||||
_update_overview()
|
_update_overview()
|
||||||
@ -732,11 +602,6 @@ def create():
|
|||||||
proc_button = Button(label="Process Current", width=145)
|
proc_button = Button(label="Process Current", width=145)
|
||||||
proc_button.on_click(proc_button_callback)
|
proc_button.on_click(proc_button_callback)
|
||||||
|
|
||||||
area_method_div = Div(text="Intensity:", margin=(5, 5, 0, 5))
|
|
||||||
area_method_radiobutton = RadioGroup(labels=["Function", "Area"], active=0, width=145)
|
|
||||||
|
|
||||||
lorentz_checkbox = CheckboxGroup(labels=["Lorentz Correction"], width=145, margin=(13, 5, 5, 5))
|
|
||||||
|
|
||||||
export_preview_textinput = TextAreaInput(title="Export file preview:", width=450, height=400)
|
export_preview_textinput = TextAreaInput(title="Export file preview:", width=450, height=400)
|
||||||
|
|
||||||
def _update_preview():
|
def _update_preview():
|
||||||
@ -769,12 +634,22 @@ def create():
|
|||||||
save_button = Button(label="Download File", button_type="success", width=220)
|
save_button = Button(label="Download File", button_type="success", width=220)
|
||||||
save_button.js_on_click(CustomJS(args={"js_data": js_data}, code=javaScript))
|
save_button.js_on_click(CustomJS(args={"js_data": js_data}, code=javaScript))
|
||||||
|
|
||||||
|
area_method_div = Div(text="Intensity:", margin=(5, 5, 0, 5))
|
||||||
fitpeak_controls = row(
|
fitpeak_controls = row(
|
||||||
column(fitparams_add_dropdown, fitparams_select, fitparams_remove_button),
|
column(
|
||||||
fitparams_table,
|
app_fitctrl.add_function_button,
|
||||||
|
app_fitctrl.function_select,
|
||||||
|
app_fitctrl.remove_function_button,
|
||||||
|
),
|
||||||
|
app_fitctrl.params_table,
|
||||||
Spacer(width=20),
|
Spacer(width=20),
|
||||||
column(fit_from_spinner, lorentz_checkbox, area_method_div, area_method_radiobutton),
|
column(
|
||||||
column(fit_to_spinner, proc_button, proc_all_button),
|
app_fitctrl.from_spinner,
|
||||||
|
app_fitctrl.lorentz_checkbox,
|
||||||
|
area_method_div,
|
||||||
|
app_fitctrl.area_method_radiogroup,
|
||||||
|
),
|
||||||
|
column(app_fitctrl.to_spinner, proc_button, proc_all_button),
|
||||||
)
|
)
|
||||||
|
|
||||||
scan_layout = column(
|
scan_layout = column(
|
||||||
@ -796,7 +671,7 @@ def create():
|
|||||||
|
|
||||||
tab_layout = column(
|
tab_layout = column(
|
||||||
row(import_layout, scan_layout, plots, Spacer(width=30), export_layout),
|
row(import_layout, scan_layout, plots, Spacer(width=30), export_layout),
|
||||||
row(fitpeak_controls, fit_output_textinput),
|
row(fitpeak_controls, app_fitctrl.result_textarea),
|
||||||
)
|
)
|
||||||
|
|
||||||
return Panel(child=tab_layout, title="param study")
|
return Panel(child=tab_layout, title="param study")
|
||||||
|
Loading…
x
Reference in New Issue
Block a user