Enable Fit/Int area selector
This commit is contained in:
parent
09d22e7674
commit
0b6a58e160
@ -43,7 +43,7 @@ from bokeh.models import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
import pyzebra
|
import pyzebra
|
||||||
from pyzebra.ccl_io import AREA_METHODS
|
from pyzebra.ccl_process import AREA_METHODS
|
||||||
|
|
||||||
|
|
||||||
javaScript = """
|
javaScript = """
|
||||||
@ -467,6 +467,11 @@ def create():
|
|||||||
pyzebra.fit_scan(
|
pyzebra.fit_scan(
|
||||||
scan, fit_params, fit_from=fit_from_spinner.value, fit_to=fit_to_spinner.value
|
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(_get_selected_scan())
|
_update_plot(_get_selected_scan())
|
||||||
_update_table()
|
_update_table()
|
||||||
@ -479,6 +484,11 @@ def create():
|
|||||||
pyzebra.fit_scan(
|
pyzebra.fit_scan(
|
||||||
scan, fit_params, fit_from=fit_from_spinner.value, fit_to=fit_to_spinner.value
|
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(scan)
|
_update_plot(scan)
|
||||||
_update_table()
|
_update_table()
|
||||||
@ -486,19 +496,9 @@ def create():
|
|||||||
fit_button = Button(label="Fit Current", width=145)
|
fit_button = Button(label="Fit Current", width=145)
|
||||||
fit_button.on_click(fit_button_callback)
|
fit_button.on_click(fit_button_callback)
|
||||||
|
|
||||||
def area_method_radiobutton_callback(_handler):
|
area_method_radiobutton = RadioButtonGroup(labels=["Fit area", "Int area"], active=0, width=145)
|
||||||
_update_preview()
|
|
||||||
|
|
||||||
area_method_radiobutton = RadioButtonGroup(
|
|
||||||
labels=["Fit area", "Int area"], active=0, width=145, disabled=True
|
|
||||||
)
|
|
||||||
area_method_radiobutton.on_click(area_method_radiobutton_callback)
|
|
||||||
|
|
||||||
def lorentz_checkbox_callback(_handler):
|
|
||||||
_update_preview()
|
|
||||||
|
|
||||||
lorentz_checkbox = CheckboxGroup(labels=["Lorentz Correction"], width=145, margin=[13, 5, 5, 5])
|
lorentz_checkbox = CheckboxGroup(labels=["Lorentz Correction"], width=145, margin=[13, 5, 5, 5])
|
||||||
lorentz_checkbox.on_click(lorentz_checkbox_callback)
|
|
||||||
|
|
||||||
export_preview_textinput = TextAreaInput(title="Export file preview:", width=500, height=400)
|
export_preview_textinput = TextAreaInput(title="Export file preview:", width=500, height=400)
|
||||||
|
|
||||||
@ -511,11 +511,7 @@ def create():
|
|||||||
export_data.append(s)
|
export_data.append(s)
|
||||||
|
|
||||||
pyzebra.export_1D(
|
pyzebra.export_1D(
|
||||||
export_data,
|
export_data, temp_file, hkl_precision=int(hkl_precision_select.value),
|
||||||
temp_file,
|
|
||||||
area_method=AREA_METHODS[int(area_method_radiobutton.active)],
|
|
||||||
lorentz=bool(lorentz_checkbox.active),
|
|
||||||
hkl_precision=int(hkl_precision_select.value),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
exported_content = ""
|
exported_content = ""
|
||||||
|
@ -48,7 +48,7 @@ from bokeh.palettes import Category10, Turbo256
|
|||||||
from bokeh.transform import linear_cmap
|
from bokeh.transform import linear_cmap
|
||||||
|
|
||||||
import pyzebra
|
import pyzebra
|
||||||
from pyzebra.ccl_io import AREA_METHODS
|
from pyzebra.ccl_process import AREA_METHODS
|
||||||
|
|
||||||
javaScript = """
|
javaScript = """
|
||||||
for (let i = 0; i < js_data.data['fname'].length; i++) {
|
for (let i = 0; i < js_data.data['fname'].length; i++) {
|
||||||
@ -557,6 +557,11 @@ def create():
|
|||||||
pyzebra.fit_scan(
|
pyzebra.fit_scan(
|
||||||
scan, fit_params, fit_from=fit_from_spinner.value, fit_to=fit_to_spinner.value
|
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()
|
||||||
@ -569,6 +574,11 @@ def create():
|
|||||||
pyzebra.fit_scan(
|
pyzebra.fit_scan(
|
||||||
scan, fit_params, fit_from=fit_from_spinner.value, fit_to=fit_to_spinner.value
|
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()
|
||||||
@ -576,19 +586,9 @@ def create():
|
|||||||
fit_button = Button(label="Fit Current", width=145)
|
fit_button = Button(label="Fit Current", width=145)
|
||||||
fit_button.on_click(fit_button_callback)
|
fit_button.on_click(fit_button_callback)
|
||||||
|
|
||||||
def area_method_radiobutton_callback(_handler):
|
area_method_radiobutton = RadioButtonGroup(labels=["Fit area", "Int area"], active=0, width=145)
|
||||||
_update_preview()
|
|
||||||
|
|
||||||
area_method_radiobutton = RadioButtonGroup(
|
|
||||||
labels=["Fit area", "Int area"], active=0, width=145, disabled=True
|
|
||||||
)
|
|
||||||
area_method_radiobutton.on_click(area_method_radiobutton_callback)
|
|
||||||
|
|
||||||
def lorentz_checkbox_callback(_handler):
|
|
||||||
_update_preview()
|
|
||||||
|
|
||||||
lorentz_checkbox = CheckboxGroup(labels=["Lorentz Correction"], width=145, margin=[13, 5, 5, 5])
|
lorentz_checkbox = CheckboxGroup(labels=["Lorentz Correction"], width=145, margin=[13, 5, 5, 5])
|
||||||
lorentz_checkbox.on_click(lorentz_checkbox_callback)
|
|
||||||
|
|
||||||
export_preview_textinput = TextAreaInput(title="Export file preview:", width=450, height=400)
|
export_preview_textinput = TextAreaInput(title="Export file preview:", width=450, height=400)
|
||||||
|
|
||||||
@ -600,12 +600,7 @@ def create():
|
|||||||
if export:
|
if export:
|
||||||
export_data.append(s)
|
export_data.append(s)
|
||||||
|
|
||||||
pyzebra.export_1D(
|
pyzebra.export_1D(export_data, temp_file)
|
||||||
export_data,
|
|
||||||
temp_file,
|
|
||||||
area_method=AREA_METHODS[int(area_method_radiobutton.active)],
|
|
||||||
lorentz=bool(lorentz_checkbox.active),
|
|
||||||
)
|
|
||||||
|
|
||||||
exported_content = ""
|
exported_content = ""
|
||||||
file_content = []
|
file_content = []
|
||||||
|
@ -3,7 +3,6 @@ import re
|
|||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from scipy.integrate import simpson, trapezoid
|
|
||||||
|
|
||||||
META_VARS_STR = (
|
META_VARS_STR = (
|
||||||
"instrument",
|
"instrument",
|
||||||
@ -77,8 +76,6 @@ CCL_SECOND_LINE = (
|
|||||||
("scan_motor", str),
|
("scan_motor", str),
|
||||||
)
|
)
|
||||||
|
|
||||||
AREA_METHODS = ("fit_area", "int_area")
|
|
||||||
|
|
||||||
|
|
||||||
def load_1D(filepath):
|
def load_1D(filepath):
|
||||||
"""
|
"""
|
||||||
@ -244,7 +241,7 @@ def parse_1D(fileobj, data_type):
|
|||||||
return scan
|
return scan
|
||||||
|
|
||||||
|
|
||||||
def export_1D(data, path, area_method=AREA_METHODS[0], lorentz=False, hkl_precision=2):
|
def export_1D(data, path, hkl_precision=2):
|
||||||
"""Exports data in the .comm/.incomm format
|
"""Exports data in the .comm/.incomm format
|
||||||
|
|
||||||
Scans with integer/real hkl values are saved in .comm/.incomm files correspondingly. If no scans
|
Scans with integer/real hkl values are saved in .comm/.incomm files correspondingly. If no scans
|
||||||
@ -266,38 +263,7 @@ def export_1D(data, path, area_method=AREA_METHODS[0], lorentz=False, hkl_precis
|
|||||||
else:
|
else:
|
||||||
hkl_str = f"{h:8.{hkl_precision}f}{k:8.{hkl_precision}f}{l:8.{hkl_precision}f}"
|
hkl_str = f"{h:8.{hkl_precision}f}{k:8.{hkl_precision}f}{l:8.{hkl_precision}f}"
|
||||||
|
|
||||||
for name, param in scan["fit"].params.items():
|
area_n, area_s = scan["area"]
|
||||||
if "amplitude" in name:
|
|
||||||
if param.stderr is None:
|
|
||||||
area_n = np.nan
|
|
||||||
area_s = np.nan
|
|
||||||
else:
|
|
||||||
area_n = param.value
|
|
||||||
area_s = param.stderr
|
|
||||||
# TODO: take into account multiple peaks
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
# no peak functions in a fit model
|
|
||||||
# assume this is a background fit, so do numeric integration
|
|
||||||
y_val = scan["Counts"]
|
|
||||||
x_val = scan[scan["scan_motor"]]
|
|
||||||
y_bkg = scan["fit"].eval(x=x_val)
|
|
||||||
area_n = simpson(y_val, x=x_val) - trapezoid(y_bkg, x=x_val)
|
|
||||||
area_s = np.sqrt(area_n)
|
|
||||||
|
|
||||||
# apply lorentz correction to area
|
|
||||||
if lorentz:
|
|
||||||
if zebra_mode == "bi":
|
|
||||||
twotheta = np.deg2rad(scan["twotheta"])
|
|
||||||
corr_factor = np.sin(twotheta)
|
|
||||||
else: # zebra_mode == "nb":
|
|
||||||
gamma = np.deg2rad(scan["gamma"])
|
|
||||||
nu = np.deg2rad(scan["nu"])
|
|
||||||
corr_factor = np.sin(gamma) * np.cos(nu)
|
|
||||||
|
|
||||||
area_n = np.abs(area_n * corr_factor)
|
|
||||||
area_s = np.abs(area_s * corr_factor)
|
|
||||||
|
|
||||||
area_str = f"{area_n:10.2f}{area_s:10.2f}"
|
area_str = f"{area_n:10.2f}{area_s:10.2f}"
|
||||||
|
|
||||||
ang_str = ""
|
ang_str = ""
|
||||||
|
@ -3,6 +3,7 @@ import os
|
|||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from lmfit.models import GaussianModel, LinearModel, PseudoVoigtModel, VoigtModel
|
from lmfit.models import GaussianModel, LinearModel, PseudoVoigtModel, VoigtModel
|
||||||
|
from scipy.integrate import simpson, trapezoid
|
||||||
|
|
||||||
from .ccl_io import CCL_ANGLES
|
from .ccl_io import CCL_ANGLES
|
||||||
|
|
||||||
@ -22,6 +23,8 @@ MAX_RANGE_GAP = {
|
|||||||
"omega": 0.5,
|
"omega": 0.5,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AREA_METHODS = ("fit_area", "int_area")
|
||||||
|
|
||||||
|
|
||||||
def normalize_dataset(dataset, monitor=100_000):
|
def normalize_dataset(dataset, monitor=100_000):
|
||||||
for scan in dataset:
|
for scan in dataset:
|
||||||
@ -148,3 +151,45 @@ def fit_scan(scan, model_dict, fit_from=None, fit_to=None):
|
|||||||
|
|
||||||
weights = [1 / np.sqrt(val) if val != 0 else 1 for val in y_fit]
|
weights = [1 / np.sqrt(val) if val != 0 else 1 for val in y_fit]
|
||||||
scan["fit"] = model.fit(y_fit, x=x_fit, weights=weights)
|
scan["fit"] = model.fit(y_fit, x=x_fit, weights=weights)
|
||||||
|
|
||||||
|
|
||||||
|
def get_area(scan, area_method, lorentz):
|
||||||
|
if area_method not in AREA_METHODS:
|
||||||
|
raise ValueError(f"Unknown area method: {area_method}.")
|
||||||
|
|
||||||
|
if area_method == "fit_area":
|
||||||
|
for name, param in scan["fit"].params.items():
|
||||||
|
if "amplitude" in name:
|
||||||
|
if param.stderr is None:
|
||||||
|
area_n = np.nan
|
||||||
|
area_s = np.nan
|
||||||
|
else:
|
||||||
|
area_n = param.value
|
||||||
|
area_s = param.stderr
|
||||||
|
# TODO: take into account multiple peaks
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
area_n = np.nan
|
||||||
|
area_s = np.nan
|
||||||
|
|
||||||
|
else: # area_method == "int_area"
|
||||||
|
y_val = scan["Counts"]
|
||||||
|
x_val = scan[scan["scan_motor"]]
|
||||||
|
y_bkg = scan["fit"].eval_components(x=x_val)["f0_"]
|
||||||
|
area_n = simpson(y_val, x=x_val) - trapezoid(y_bkg, x=x_val)
|
||||||
|
area_s = np.sqrt(area_n)
|
||||||
|
|
||||||
|
if lorentz:
|
||||||
|
# lorentz correction to area
|
||||||
|
if scan["zebra_mode"] == "bi":
|
||||||
|
twotheta = np.deg2rad(scan["twotheta"])
|
||||||
|
corr_factor = np.sin(twotheta)
|
||||||
|
else: # zebra_mode == "nb":
|
||||||
|
gamma = np.deg2rad(scan["gamma"])
|
||||||
|
nu = np.deg2rad(scan["nu"])
|
||||||
|
corr_factor = np.sin(gamma) * np.cos(nu)
|
||||||
|
|
||||||
|
area_n = np.abs(area_n * corr_factor)
|
||||||
|
area_s = np.abs(area_s * corr_factor)
|
||||||
|
|
||||||
|
scan["area"] = (area_n, area_s)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user