5 Commits
0.7.12 ... main

Author SHA1 Message Date
b60208dd2d Clean conda cache
All checks were successful
pyzebra CI/CD pipeline / test-env (push) Successful in 2m5s
pyzebra CI/CD pipeline / prod-env (push) Has been skipped
pyzebra CI/CD pipeline / cleanup (push) Successful in 2s
2026-02-24 11:01:10 +01:00
56f6268364 Fix cicd workflow output
All checks were successful
pyzebra CI/CD pipeline / test-env (push) Successful in 2m14s
pyzebra CI/CD pipeline / prod-env (push) Has been skipped
pyzebra CI/CD pipeline / cleanup (push) Successful in 1s
2026-02-24 09:55:29 +01:00
e6e97be58a Migrate to python/3.10 and bokeh/3.8
All checks were successful
pyzebra CI/CD pipeline / test-env (push) Successful in 2m20s
pyzebra CI/CD pipeline / prod-env (push) Has been skipped
pyzebra CI/CD pipeline / cleanup (push) Successful in 1s
* use TabPanel instead of Panel
* use scatter(marker=...) instead of specific marker function
* replace gridplot with grid
2026-02-23 15:50:52 +01:00
36cb92f6d5 Avoid reconnection feature in bokeh/3.8+ 2026-02-23 15:50:45 +01:00
5dcf51b939 Use requires-python from pyproject.toml in conda-recipe
All checks were successful
pyzebra CI/CD pipeline / test-env (push) Successful in 2m1s
pyzebra CI/CD pipeline / prod-env (push) Has been skipped
pyzebra CI/CD pipeline / cleanup (push) Successful in 1s
2026-02-09 13:23:26 +01:00
14 changed files with 127 additions and 105 deletions

View File

@@ -20,8 +20,8 @@ jobs:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v4 uses: actions/checkout@v4
- run: $CONDA/bin/conda build --no-anaconda-upload --output-folder $BUILD_DIR ./conda-recipe - run: $CONDA/bin/conda build --no-anaconda-upload --output-folder $BUILD_DIR ./conda-recipe
- run: $CONDA/bin/conda remove --name test --all --keep-env -y - run: $CONDA/bin/conda remove --yes --quiet --name test --all --keep-env
- run: $CONDA/bin/conda install --name test --channel $BUILD_DIR python=3.8 pyzebra -y - run: $CONDA/bin/conda install --yes --quiet --name test --channel $BUILD_DIR python=3.10 pyzebra
- run: sudo systemctl restart pyzebra-test.service - run: sudo systemctl restart pyzebra-test.service
prod-env: prod-env:
@@ -33,8 +33,8 @@ jobs:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v4 uses: actions/checkout@v4
- run: $CONDA/bin/conda build --token ${{ secrets.ANACONDA_TOKEN }} --output-folder $BUILD_DIR ./conda-recipe - run: $CONDA/bin/conda build --token ${{ secrets.ANACONDA_TOKEN }} --output-folder $BUILD_DIR ./conda-recipe
- run: $CONDA/bin/conda remove --name prod --all --keep-env -y - run: $CONDA/bin/conda remove --yes --quiet --name prod --all --keep-env
- run: $CONDA/bin/conda install --name prod --channel $BUILD_DIR python=3.8 pyzebra -y - run: $CONDA/bin/conda install --yes --quiet --name prod --channel $BUILD_DIR python=3.10 pyzebra
- run: sudo systemctl restart pyzebra-prod.service - run: sudo systemctl restart pyzebra-prod.service
cleanup: cleanup:
@@ -42,4 +42,5 @@ jobs:
needs: [test-env, prod-env] needs: [test-env, prod-env]
if: always() if: always()
steps: steps:
- run: $CONDA/bin/conda build purge-all - run: $CONDA/bin/conda build purge-all
- run: $CONDA/bin/conda clean --yes --all

View File

@@ -17,15 +17,14 @@ build:
requirements: requirements:
host: host:
- python >=3.8 - python {{ pyproject['project']['requires-python'] }}
- hatchling - hatchling
run: run:
- python >=3.8 - python {{ pyproject['project']['requires-python'] }}
{% for dep in pyproject['project']['dependencies'] %} {% for dep in pyproject['project']['dependencies'] %}
- {{ dep }} - {{ dep }}
{% endfor %} {% endfor %}
about: about:
home: {{ pyproject['project']['urls']['Homepage'] }} home: {{ pyproject['project']['urls']['Homepage'] }}
summary: {{ pyproject['project']['description'] }} summary: {{ pyproject['project']['description'] }}

View File

@@ -5,12 +5,12 @@ build-backend = "hatchling.build"
[project] [project]
name = "pyzebra" name = "pyzebra"
dynamic = ["version"] # version will be read from __init__.py dynamic = ["version"] # version will be read from __init__.py
requires-python = ">=3.8" requires-python = ">=3.10"
dependencies = [ dependencies = [
"numpy", "numpy",
"scipy", "scipy",
"h5py", "h5py",
"bokeh ~=2.4", "bokeh ~=3.8",
"numba", "numba",
"lmfit >=1.0.2", "lmfit >=1.0.2",
] ]

View File

@@ -3,8 +3,8 @@ import logging
from io import StringIO from io import StringIO
from bokeh.io import curdoc from bokeh.io import curdoc
from bokeh.layouts import column, row from bokeh.layouts import column
from bokeh.models import Button, Panel, Tabs, TextAreaInput, TextInput from bokeh.models import Button, TabPanel, Tabs, TextAreaInput, TextInput
import pyzebra import pyzebra
from pyzebra.app import ( from pyzebra.app import (
@@ -20,6 +20,8 @@ from pyzebra.app import (
) )
doc = curdoc() doc = curdoc()
doc.config.reconnect_session = False
doc.config.notify_connection_status = False
doc.title = "pyzebra" doc.title = "pyzebra"
parser = argparse.ArgumentParser() parser = argparse.ArgumentParser()
@@ -53,14 +55,14 @@ logger.setLevel(logging.INFO)
logger.addHandler(handler) logger.addHandler(handler)
doc.logger = logger doc.logger = logger
log_textareainput = TextAreaInput(title="Logging output:") log_textareainput = TextAreaInput(title="Logging output:", sizing_mode="stretch_both")
def proposal_textinput_callback(_attr, _old, _new): def proposal_textinput_callback(_attr, _old, _new):
apply_button.disabled = False apply_button.disabled = False
proposal_textinput = TextInput(title="Proposal number:", name="") proposal_textinput = TextInput(title="Proposal number:", name="", sizing_mode="stretch_width")
proposal_textinput.on_change("value_input", proposal_textinput_callback) proposal_textinput.on_change("value_input", proposal_textinput_callback)
doc.proposal_textinput = proposal_textinput doc.proposal_textinput = proposal_textinput
@@ -80,7 +82,7 @@ def apply_button_callback():
proposal_textinput.name = proposal_path proposal_textinput.name = proposal_path
apply_button = Button(label="Apply", button_type="primary") apply_button = Button(label="Apply", button_type="primary", width=300)
apply_button.on_click(apply_button_callback) apply_button.on_click(apply_button_callback)
# Final layout # Final layout
@@ -88,7 +90,7 @@ doc.add_root(
column( column(
Tabs( Tabs(
tabs=[ tabs=[
Panel(child=column(proposal_textinput, apply_button), title="user config"), TabPanel(child=column(proposal_textinput, apply_button), title="user config"),
panel_hdf_viewer.create(), panel_hdf_viewer.create(),
panel_hdf_anatric.create(), panel_hdf_anatric.create(),
panel_ccl_prepare.create(), panel_ccl_prepare.create(),
@@ -100,7 +102,8 @@ doc.add_root(
panel_spind.create(), panel_spind.create(),
] ]
), ),
row(log_textareainput, sizing_mode="scale_both"), log_textareainput,
sizing_mode="stretch_height",
) )
) )

View File

@@ -15,13 +15,13 @@ from bokeh.models import (
Div, Div,
FileInput, FileInput,
MultiSelect, MultiSelect,
Panel,
RadioGroup, RadioGroup,
Select, Select,
Spacer, Spacer,
Span, Span,
Spinner, Spinner,
TableColumn, TableColumn,
TabPanel,
TextAreaInput, TextAreaInput,
Whisker, Whisker,
) )
@@ -250,7 +250,8 @@ def create():
) )
scatter1_source = ColumnDataSource(dict(x=[0], y=[0], y_upper=[0], y_lower=[0])) scatter1_source = ColumnDataSource(dict(x=[0], y=[0], y_upper=[0], y_lower=[0]))
plot.circle( plot.scatter(
marker="circle",
source=scatter1_source, source=scatter1_source,
line_color="steelblue", line_color="steelblue",
fill_color="steelblue", fill_color="steelblue",
@@ -259,7 +260,8 @@ def create():
plot.add_layout(Whisker(source=scatter1_source, base="x", upper="y_upper", lower="y_lower")) plot.add_layout(Whisker(source=scatter1_source, base="x", upper="y_upper", lower="y_lower"))
scatter2_source = ColumnDataSource(dict(x=[0], y=[0], y_upper=[0], y_lower=[0])) scatter2_source = ColumnDataSource(dict(x=[0], y=[0], y_upper=[0], y_lower=[0]))
plot.circle( plot.scatter(
marker="circle",
source=scatter2_source, source=scatter2_source,
line_color="firebrick", line_color="firebrick",
fill_color="firebrick", fill_color="firebrick",
@@ -535,4 +537,4 @@ def create():
row(fitpeak_controls, app_fitctrl.result_textarea), row(fitpeak_controls, app_fitctrl.result_textarea),
) )
return Panel(child=tab_layout, title="ccl compare") return TabPanel(child=tab_layout, title="ccl compare")

View File

@@ -11,11 +11,11 @@ from bokeh.models import (
ColumnDataSource, ColumnDataSource,
DataTable, DataTable,
Div, Div,
Panel,
Select, Select,
Spacer, Spacer,
Span, Span,
TableColumn, TableColumn,
TabPanel,
TextAreaInput, TextAreaInput,
Whisker, Whisker,
) )
@@ -121,8 +121,12 @@ def create():
) )
scatter_source = ColumnDataSource(dict(x=[0], y=[0], y_upper=[0], y_lower=[0])) scatter_source = ColumnDataSource(dict(x=[0], y=[0], y_upper=[0], y_lower=[0]))
plot.circle( plot.scatter(
source=scatter_source, line_color="steelblue", fill_color="steelblue", legend_label="data" marker="circle",
source=scatter_source,
line_color="steelblue",
fill_color="steelblue",
legend_label="data",
) )
plot.add_layout(Whisker(source=scatter_source, base="x", upper="y_upper", lower="y_lower")) plot.add_layout(Whisker(source=scatter_source, base="x", upper="y_upper", lower="y_lower"))
@@ -364,4 +368,4 @@ def create():
row(fitpeak_controls, app_fitctrl.result_textarea), row(fitpeak_controls, app_fitctrl.result_textarea),
) )
return Panel(child=tab_layout, title="ccl integrate") return TabPanel(child=tab_layout, title="ccl integrate")

View File

@@ -20,11 +20,11 @@ from bokeh.models import (
MultiSelect, MultiSelect,
NormalHead, NormalHead,
NumericInput, NumericInput,
Panel,
RadioGroup, RadioGroup,
Select, Select,
Spacer, Spacer,
Spinner, Spinner,
TabPanel,
TextAreaInput, TextAreaInput,
TextInput, TextInput,
) )
@@ -89,7 +89,7 @@ def create():
ang_lims = pyzebra.read_geom_file(fileobj) ang_lims = pyzebra.read_geom_file(fileobj)
_update_ang_lims(ang_lims) _update_ang_lims(ang_lims)
open_geom_div = Div(text="Open GEOM:") open_geom_div = Div(text="Open GEOM:", margin=(12, 5, 5, 5))
open_geom = FileInput(accept=".geom", width=200) open_geom = FileInput(accept=".geom", width=200)
open_geom.on_change("value", open_geom_callback) open_geom.on_change("value", open_geom_callback)
@@ -99,7 +99,7 @@ def create():
params = pyzebra.read_cfl_file(fileobj) params = pyzebra.read_cfl_file(fileobj)
_update_params(params) _update_params(params)
open_cfl_div = Div(text="Open CFL:") open_cfl_div = Div(text="Open CFL:", margin=(12, 5, 5, 5))
open_cfl = FileInput(accept=".cfl", width=200) open_cfl = FileInput(accept=".cfl", width=200)
open_cfl.on_change("value", open_cfl_callback) open_cfl.on_change("value", open_cfl_callback)
@@ -109,7 +109,7 @@ def create():
cif_data = pyzebra.read_cif_file(fileobj) cif_data = pyzebra.read_cif_file(fileobj)
_update_params(cif_data) _update_params(cif_data)
open_cif_div = Div(text="Open CIF:") open_cif_div = Div(text="Open CIF:", margin=(12, 5, 5, 5))
open_cif = FileInput(accept=".cif", width=200) open_cif = FileInput(accept=".cif", width=200)
open_cif.on_change("value", open_cif_callback) open_cif.on_change("value", open_cif_callback)
@@ -145,7 +145,7 @@ def create():
ub_matrix_calc = Button(label="UB matrix:", button_type="primary", width=100) ub_matrix_calc = Button(label="UB matrix:", button_type="primary", width=100)
ub_matrix_calc.on_click(ub_matrix_calc_callback) ub_matrix_calc.on_click(ub_matrix_calc_callback)
ub_matrix = TextInput(title="\u200B", width=600) ub_matrix = TextInput(title="\u200b", width=600)
ranges_div = Div(text="Ranges:", margin=(5, 5, 0, 5)) ranges_div = Div(text="Ranges:", margin=(5, 5, 0, 5))
ranges_hkl = TextInput(title="HKL", value="-25 25 -25 25 -25 25", width=250) ranges_hkl = TextInput(title="HKL", value="-25 25 -25 25 -25 25", width=250)
@@ -153,7 +153,7 @@ def create():
magstruct_div = Div(text="Magnetic structure:", margin=(5, 5, 0, 5)) magstruct_div = Div(text="Magnetic structure:", margin=(5, 5, 0, 5))
magstruct_lattice = TextInput(title="lattice", width=100) magstruct_lattice = TextInput(title="lattice", width=100)
magstruct_kvec = TextAreaInput(title="k vector", width=150) magstruct_kvec = TextAreaInput(title="k vector", rows=3, width=150)
def sorting0_callback(_attr, _old, new): def sorting0_callback(_attr, _old, new):
sorting_0_dt.value = ANG_CHUNK_DEFAULTS[new] sorting_0_dt.value = ANG_CHUNK_DEFAULTS[new]
@@ -321,7 +321,7 @@ def create():
plot_list.on_click(plot_list_callback) plot_list.on_click(plot_list_callback)
# Plot # Plot
upload_data_div = Div(text="Open hkl/mhkl data:") upload_data_div = Div(text="Open hkl/mhkl data:", margin=(12, 5, 5, 5))
upload_data = FileInput(accept=".hkl,.mhkl", multiple=True, width=200) upload_data = FileInput(accept=".hkl,.mhkl", multiple=True, width=200)
min_grid_x = -10 min_grid_x = -10
@@ -667,7 +667,7 @@ def create():
) )
k_vectors = TextAreaInput( k_vectors = TextAreaInput(
title="k vectors:", value="0.0 0.0 0.0\n0.5 0.0 0.0\n0.5 0.5 0.0", width=150 title="k vectors:", value="0.0 0.0 0.0\n0.5 0.0 0.0\n0.5 0.5 0.0", rows=3, width=150
) )
tol_k_ni = NumericInput(title="k tolerance:", value=0.01, mode="float", width=100) tol_k_ni = NumericInput(title="k tolerance:", value=0.01, mode="float", width=100)
@@ -721,4 +721,4 @@ def create():
tab_layout = row(column1_layout, column2_layout) tab_layout = row(column1_layout, column2_layout)
return Panel(child=tab_layout, title="ccl prepare") return TabPanel(child=tab_layout, title="ccl prepare")

View File

@@ -10,9 +10,9 @@ from bokeh.models import (
Button, Button,
Div, Div,
FileInput, FileInput,
Panel,
Select, Select,
Spacer, Spacer,
TabPanel,
Tabs, Tabs,
TextAreaInput, TextAreaInput,
TextInput, TextInput,
@@ -82,7 +82,7 @@ def create():
with io.BytesIO(base64.b64decode(new)) as file: with io.BytesIO(base64.b64decode(new)) as file:
_load_config_file(file) _load_config_file(file)
upload_div = Div(text="Open .xml config:") upload_div = Div(text="Open .xml config:", margin=(12, 5, 5, 5))
upload_button = FileInput(accept=".xml", width=200) upload_button = FileInput(accept=".xml", width=200)
upload_button.on_change("value", upload_button_callback) upload_button.on_change("value", upload_button_callback)
@@ -91,7 +91,9 @@ def create():
def logfile_textinput_callback(_attr, _old, new): def logfile_textinput_callback(_attr, _old, new):
config.logfile = new config.logfile = new
logfile_textinput = TextInput(title="Logfile:", value="logfile.log") logfile_textinput = TextInput(
title="Logfile:", value="logfile.log", sizing_mode="stretch_width"
)
logfile_textinput.on_change("value", logfile_textinput_callback) logfile_textinput.on_change("value", logfile_textinput_callback)
def logfile_verbosity_callback(_attr, _old, new): def logfile_verbosity_callback(_attr, _old, new):
@@ -104,7 +106,7 @@ def create():
def filelist_type_callback(_attr, _old, new): def filelist_type_callback(_attr, _old, new):
config.filelist_type = new config.filelist_type = new
filelist_type = Select(title="File List:", options=["TRICS", "SINQ"], width=100) filelist_type = Select(title="File List:", options=["TRICS", "SINQ"], value="TRICS", width=100)
filelist_type.on_change("value", filelist_type_callback) filelist_type.on_change("value", filelist_type_callback)
def filelist_format_textinput_callback(_attr, _old, new): def filelist_format_textinput_callback(_attr, _old, new):
@@ -116,7 +118,7 @@ def create():
def filelist_datapath_textinput_callback(_attr, _old, new): def filelist_datapath_textinput_callback(_attr, _old, new):
config.filelist_datapath = new config.filelist_datapath = new
filelist_datapath_textinput = TextInput(title="datapath:") filelist_datapath_textinput = TextInput(title="datapath:", sizing_mode="stretch_width")
filelist_datapath_textinput.on_change("value", filelist_datapath_textinput_callback) filelist_datapath_textinput.on_change("value", filelist_datapath_textinput_callback)
def filelist_ranges_textareainput_callback(_attr, _old, new): def filelist_ranges_textareainput_callback(_attr, _old, new):
@@ -125,7 +127,9 @@ def create():
ranges.append(re.findall(r"\b\d+\b", line)) ranges.append(re.findall(r"\b\d+\b", line))
config.filelist_ranges = ranges config.filelist_ranges = ranges
filelist_ranges_textareainput = TextAreaInput(title="ranges:", rows=1) filelist_ranges_textareainput = TextAreaInput(
title="ranges:", rows=1, sizing_mode="stretch_width"
)
filelist_ranges_textareainput.on_change("value", filelist_ranges_textareainput_callback) filelist_ranges_textareainput.on_change("value", filelist_ranges_textareainput_callback)
# ---- crystal # ---- crystal
@@ -144,7 +148,7 @@ def create():
def ub_textareainput_callback(_attr, _old, new): def ub_textareainput_callback(_attr, _old, new):
config.crystal_UB = new config.crystal_UB = new
ub_textareainput = TextAreaInput(title="UB matrix:", height=100) ub_textareainput = TextAreaInput(title="UB matrix:", height=100, sizing_mode="stretch_width")
ub_textareainput.on_change("value", ub_textareainput_callback) ub_textareainput.on_change("value", ub_textareainput_callback)
def zeroOM_textinput_callback(_attr, _old, new): def zeroOM_textinput_callback(_attr, _old, new):
@@ -170,7 +174,10 @@ def create():
config.dataFactory_implementation = new config.dataFactory_implementation = new
dataFactory_implementation_select = Select( dataFactory_implementation_select = Select(
title="DataFactory implement.:", options=DATA_FACTORY_IMPLEMENTATION, width=145 title="DataFactory implement.:",
options=DATA_FACTORY_IMPLEMENTATION,
value=DATA_FACTORY_IMPLEMENTATION[0],
width=145,
) )
dataFactory_implementation_select.on_change("value", dataFactory_implementation_select_callback) dataFactory_implementation_select.on_change("value", dataFactory_implementation_select_callback)
@@ -201,7 +208,10 @@ def create():
config.reflectionPrinter_format = new config.reflectionPrinter_format = new
reflectionPrinter_format_select = Select( reflectionPrinter_format_select = Select(
title="ReflectionPrinter format:", options=REFLECTION_PRINTER_FORMATS, width=145 title="ReflectionPrinter format:",
options=REFLECTION_PRINTER_FORMATS,
value=REFLECTION_PRINTER_FORMATS[0],
width=145,
) )
reflectionPrinter_format_select.on_change("value", reflectionPrinter_format_select_callback) reflectionPrinter_format_select.on_change("value", reflectionPrinter_format_select_callback)
@@ -325,14 +335,14 @@ def create():
algorithm_params = Tabs( algorithm_params = Tabs(
tabs=[ tabs=[
Panel( TabPanel(
child=column( child=column(
row(threshold_textinput, shell_textinput, steepness_textinput), row(threshold_textinput, shell_textinput, steepness_textinput),
row(duplicateDistance_textinput, maxequal_textinput, aps_window_textinput), row(duplicateDistance_textinput, maxequal_textinput, aps_window_textinput),
), ),
title="Peak Search", title="Peak Search",
), ),
Panel( TabPanel(
child=column( child=column(
row(adm_window_textinput, border_textinput, minWindow_textinput), row(adm_window_textinput, border_textinput, minWindow_textinput),
row(reflectionFile_textinput, targetMonitor_textinput, smoothSize_textinput), row(reflectionFile_textinput, targetMonitor_textinput, smoothSize_textinput),
@@ -360,7 +370,7 @@ def create():
with open(os.path.join(temp_dir, config.reflectionPrinter_file)) as f_res: with open(os.path.join(temp_dir, config.reflectionPrinter_file)) as f_res:
output_res.value = f_res.read() output_res.value = f_res.read()
process_button = Button(label="Process", button_type="primary") process_button = Button(label="Process", button_type="primary", width=300)
process_button.on_click(process_button_callback) process_button.on_click(process_button_callback)
output_log = TextAreaInput(title="Logfile output:", height=320, width=465, disabled=True) output_log = TextAreaInput(title="Logfile output:", height=320, width=465, disabled=True)
@@ -368,8 +378,8 @@ def create():
output_config = TextAreaInput(title="Current config:", height=320, width=465, disabled=True) output_config = TextAreaInput(title="Current config:", height=320, width=465, disabled=True)
general_params_layout = column( general_params_layout = column(
row(column(Spacer(height=2), upload_div), upload_button), row(upload_div, upload_button),
row(logfile_textinput, logfile_verbosity), row(logfile_textinput, logfile_verbosity, sizing_mode="stretch_width"),
row(filelist_type, filelist_format_textinput), row(filelist_type, filelist_format_textinput),
filelist_datapath_textinput, filelist_datapath_textinput,
filelist_ranges_textareainput, filelist_ranges_textareainput,
@@ -387,7 +397,7 @@ def create():
tab_layout = row( tab_layout = row(
general_params_layout, general_params_layout,
column(output_config, algorithm_params, row(process_button)), column(output_config, algorithm_params, process_button),
column(output_log, output_res), column(output_log, output_res),
) )
@@ -396,4 +406,4 @@ def create():
doc.add_periodic_callback(update_config, 1000) doc.add_periodic_callback(update_config, 1000)
return Panel(child=tab_layout, title="hdf anatric") return TabPanel(child=tab_layout, title="hdf anatric")

View File

@@ -4,8 +4,9 @@ import os
import numpy as np import numpy as np
from bokeh.io import curdoc from bokeh.io import curdoc
from bokeh.layouts import column, gridplot, row from bokeh.layouts import column, grid, row
from bokeh.models import ( from bokeh.models import (
BoxZoomTool,
Button, Button,
CellEditor, CellEditor,
CheckboxGroup, CheckboxGroup,
@@ -17,12 +18,15 @@ from bokeh.models import (
MultiSelect, MultiSelect,
NumberEditor, NumberEditor,
NumberFormatter, NumberFormatter,
Panel, PanTool,
Range1d, Range1d,
ResetTool,
Select, Select,
Spinner, Spinner,
TableColumn, TableColumn,
TabPanel,
Tabs, Tabs,
WheelZoomTool,
) )
from bokeh.plotting import figure from bokeh.plotting import figure
@@ -293,6 +297,7 @@ def create():
frame_range = Range1d(0, 1, bounds=(0, 1)) frame_range = Range1d(0, 1, bounds=(0, 1))
scanning_motor_range = Range1d(0, 1, bounds=(0, 1)) scanning_motor_range = Range1d(0, 1, bounds=(0, 1))
color_mapper_proj = LinearColorMapper() color_mapper_proj = LinearColorMapper()
shared_tools = [PanTool(), BoxZoomTool(), WheelZoomTool(maintain_focus=False), ResetTool()]
det_x_range = Range1d(0, IMAGE_W, bounds=(0, IMAGE_W)) det_x_range = Range1d(0, IMAGE_W, bounds=(0, IMAGE_W))
proj_x_plot = figure( proj_x_plot = figure(
@@ -304,12 +309,11 @@ def create():
extra_y_ranges={"scanning_motor": scanning_motor_range}, extra_y_ranges={"scanning_motor": scanning_motor_range},
height=540, height=540,
width=IMAGE_PLOT_W - 3, width=IMAGE_PLOT_W - 3,
tools="pan,box_zoom,wheel_zoom,reset", tools=shared_tools,
active_scroll="wheel_zoom", toolbar_location=None,
) )
proj_x_plot.yaxis.major_label_orientation = "vertical" proj_x_plot.yaxis.major_label_orientation = "vertical"
proj_x_plot.toolbar.tools[2].maintain_focus = False
proj_x_image_source = ColumnDataSource( proj_x_image_source = ColumnDataSource(
dict(image=[np.zeros((1, 1), dtype="float32")], x=[0], y=[0], dw=[IMAGE_W], dh=[1]) dict(image=[np.zeros((1, 1), dtype="float32")], x=[0], y=[0], dw=[IMAGE_W], dh=[1])
@@ -328,13 +332,13 @@ def create():
extra_y_ranges={"scanning_motor": scanning_motor_range}, extra_y_ranges={"scanning_motor": scanning_motor_range},
height=540, height=540,
width=IMAGE_PLOT_H + 22, width=IMAGE_PLOT_H + 22,
tools="pan,box_zoom,wheel_zoom,reset", tools=shared_tools,
active_scroll="wheel_zoom", active_scroll=shared_tools[2],
) )
proj_y_plot.yaxis.y_range_name = "scanning_motor" proj_y_plot.yaxis.y_range_name = "scanning_motor"
proj_y_plot.yaxis.major_label_orientation = "vertical" proj_y_plot.yaxis.major_label_orientation = "vertical"
proj_y_plot.toolbar.tools[2].maintain_focus = False proj_y_plot.toolbar.logo = None
proj_y_image_source = ColumnDataSource( proj_y_image_source = ColumnDataSource(
dict(image=[np.zeros((1, 1), dtype="float32")], x=[0], y=[0], dw=[IMAGE_H], dh=[1]) dict(image=[np.zeros((1, 1), dtype="float32")], x=[0], y=[0], dw=[IMAGE_H], dh=[1])
@@ -418,7 +422,7 @@ def create():
) )
param_scatter_source = ColumnDataSource(dict(x=[], y=[])) param_scatter_source = ColumnDataSource(dict(x=[], y=[]))
param_plot.circle(source=param_scatter_source) param_plot.scatter(marker="circle", source=param_scatter_source)
param_plot.toolbar.logo = None param_plot.toolbar.logo = None
@@ -487,18 +491,13 @@ def create():
proc_all_button, proc_all_button,
) )
layout_proj = column( layout_proj = column(grid([[proj_x_plot, proj_y_plot]]), layout_controls)
gridplot(
[[proj_x_plot, proj_y_plot]], toolbar_options={"logo": None}, toolbar_location="right"
),
layout_controls,
)
# Plot tabs # Plot tabs
plots = Tabs( plots = Tabs(
tabs=[ tabs=[
Panel(child=layout_proj, title="single scan"), TabPanel(child=layout_proj, title="single scan"),
Panel(child=column(param_plot, row(fit_param_select)), title="parameter plot"), TabPanel(child=column(param_plot, row(fit_param_select)), title="parameter plot"),
] ]
) )
@@ -515,4 +514,4 @@ def create():
tab_layout = column(row(import_layout, scan_layout, plots)) tab_layout = column(row(import_layout, scan_layout, plots))
return Panel(child=tab_layout, title="hdf param study") return TabPanel(child=tab_layout, title="hdf param study")

View File

@@ -5,9 +5,10 @@ import os
import numpy as np import numpy as np
from bokeh.events import MouseEnter from bokeh.events import MouseEnter
from bokeh.io import curdoc from bokeh.io import curdoc
from bokeh.layouts import column, gridplot, row from bokeh.layouts import column, grid, row
from bokeh.models import ( from bokeh.models import (
BoxEditTool, BoxEditTool,
BoxZoomTool,
Button, Button,
CellEditor, CellEditor,
CheckboxGroup, CheckboxGroup,
@@ -21,15 +22,18 @@ from bokeh.models import (
LogColorMapper, LogColorMapper,
MultiSelect, MultiSelect,
NumberFormatter, NumberFormatter,
Panel, PanTool,
RadioGroup, RadioGroup,
Range1d, Range1d,
ResetTool,
Select, Select,
Slider, Slider,
Spacer, Spacer,
Spinner, Spinner,
TableColumn, TableColumn,
TabPanel,
Tabs, Tabs,
WheelZoomTool,
) )
from bokeh.plotting import figure from bokeh.plotting import figure
@@ -579,6 +583,7 @@ def create():
scanning_motor_range = Range1d(0, 1, bounds=(0, 1)) scanning_motor_range = Range1d(0, 1, bounds=(0, 1))
lin_color_mapper_proj = LinearColorMapper(low=0, high=1) lin_color_mapper_proj = LinearColorMapper(low=0, high=1)
log_color_mapper_proj = LogColorMapper(low=0, high=1) log_color_mapper_proj = LogColorMapper(low=0, high=1)
shared_tools = [PanTool(), BoxZoomTool(), WheelZoomTool(maintain_focus=False), ResetTool()]
det_x_range = Range1d(0, IMAGE_W, bounds=(0, IMAGE_W)) det_x_range = Range1d(0, IMAGE_W, bounds=(0, IMAGE_W))
gamma_range = Range1d(0, 1, bounds=(0, 1)) gamma_range = Range1d(0, 1, bounds=(0, 1))
@@ -592,12 +597,11 @@ def create():
extra_y_ranges={"scanning_motor": scanning_motor_range}, extra_y_ranges={"scanning_motor": scanning_motor_range},
height=540, height=540,
width=IMAGE_PLOT_W - 3, width=IMAGE_PLOT_W - 3,
tools="pan,box_zoom,wheel_zoom,reset", tools=shared_tools,
active_scroll="wheel_zoom", toolbar_location=None,
) )
proj_x_plot.yaxis.major_label_orientation = "vertical" proj_x_plot.yaxis.major_label_orientation = "vertical"
proj_x_plot.toolbar.tools[2].maintain_focus = False
proj_x_plot.add_layout(LinearAxis(x_range_name="gamma", axis_label="Gamma, deg"), place="above") proj_x_plot.add_layout(LinearAxis(x_range_name="gamma", axis_label="Gamma, deg"), place="above")
@@ -620,13 +624,13 @@ def create():
extra_y_ranges={"scanning_motor": scanning_motor_range}, extra_y_ranges={"scanning_motor": scanning_motor_range},
height=540, height=540,
width=IMAGE_PLOT_H + 22, width=IMAGE_PLOT_H + 22,
tools="pan,box_zoom,wheel_zoom,reset", tools=shared_tools,
active_scroll="wheel_zoom", active_scroll=shared_tools[2],
) )
proj_y_plot.yaxis.y_range_name = "scanning_motor" proj_y_plot.yaxis.y_range_name = "scanning_motor"
proj_y_plot.yaxis.major_label_orientation = "vertical" proj_y_plot.yaxis.major_label_orientation = "vertical"
proj_y_plot.toolbar.tools[2].maintain_focus = False proj_y_plot.toolbar.logo = None
proj_y_plot.add_layout(LinearAxis(x_range_name="nu", axis_label="Nu, deg"), place="above") proj_y_plot.add_layout(LinearAxis(x_range_name="nu", axis_label="Nu, deg"), place="above")
@@ -890,8 +894,8 @@ def create():
# Final layout # Final layout
peak_tables = Tabs( peak_tables = Tabs(
tabs=[ tabs=[
Panel(child=events_table, title="Actual peak center"), TabPanel(child=events_table, title="Actual peak center"),
Panel(child=detcenter_table, title="Peak in the detector center"), TabPanel(child=detcenter_table, title="Peak in the detector center"),
] ]
) )
@@ -905,7 +909,7 @@ def create():
row(file_open_button, file_append_button), row(file_open_button, file_append_button),
) )
layout_image = column(gridplot([[proj_v, None], [plot, proj_h]], merge_tools=False)) layout_image = column(grid([[proj_v, None], [plot, proj_h]]))
colormap_layout = column( colormap_layout = column(
row(colormap_select, column(Spacer(height=15), colormap_scale_rg)), row(colormap_select, column(Spacer(height=15), colormap_scale_rg)),
main_auto_checkbox, main_auto_checkbox,
@@ -919,11 +923,7 @@ def create():
row(column(add_event_button, remove_event_button), peak_tables), row(column(add_event_button, remove_event_button), peak_tables),
) )
layout_proj = column( layout_proj = grid([[proj_x_plot, proj_y_plot]])
gridplot(
[[proj_x_plot, proj_y_plot]], toolbar_options={"logo": None}, toolbar_location="right"
)
)
scan_layout = column( scan_layout = column(
scan_table, scan_table,
@@ -937,7 +937,7 @@ def create():
column(roi_avg_plot, layout_image), column(roi_avg_plot, layout_image),
) )
return Panel(child=tab_layout, title="hdf viewer") return TabPanel(child=tab_layout, title="hdf viewer")
def calculate_hkl(scan, index): def calculate_hkl(scan, index):

View File

@@ -15,12 +15,12 @@ from bokeh.models import (
HoverTool, HoverTool,
LinearColorMapper, LinearColorMapper,
NumberEditor, NumberEditor,
Panel,
Range1d, Range1d,
Select, Select,
Spacer, Spacer,
Span, Span,
TableColumn, TableColumn,
TabPanel,
Tabs, Tabs,
TextAreaInput, TextAreaInput,
Whisker, Whisker,
@@ -218,8 +218,12 @@ def create():
) )
scatter_source = ColumnDataSource(dict(x=[0], y=[0], y_upper=[0], y_lower=[0])) scatter_source = ColumnDataSource(dict(x=[0], y=[0], y_upper=[0], y_lower=[0]))
plot.circle( plot.scatter(
source=scatter_source, line_color="steelblue", fill_color="steelblue", legend_label="data" marker="circle",
source=scatter_source,
line_color="steelblue",
fill_color="steelblue",
legend_label="data",
) )
plot.add_layout(Whisker(source=scatter_source, base="x", upper="y_upper", lower="y_lower")) plot.add_layout(Whisker(source=scatter_source, base="x", upper="y_upper", lower="y_lower"))
@@ -274,7 +278,7 @@ def create():
ov_param_plot.image(source=ov_param_image_source, color_mapper=color_mapper) ov_param_plot.image(source=ov_param_image_source, color_mapper=color_mapper)
ov_param_scatter_source = ColumnDataSource(dict(x=[], y=[])) ov_param_scatter_source = ColumnDataSource(dict(x=[], y=[]))
ov_param_plot.dot(source=ov_param_scatter_source, size=15, color="black") ov_param_plot.scatter(marker="dot", source=ov_param_scatter_source, size=15, color="black")
ov_param_plot.toolbar.logo = None ov_param_plot.toolbar.logo = None
@@ -288,7 +292,7 @@ def create():
) )
param_scatter_source = ColumnDataSource(dict(x=[], y=[], y_upper=[], y_lower=[])) param_scatter_source = ColumnDataSource(dict(x=[], y=[], y_upper=[], y_lower=[]))
param_plot.circle(source=param_scatter_source) param_plot.scatter(marker="circle", source=param_scatter_source)
param_plot.add_layout( param_plot.add_layout(
Whisker(source=param_scatter_source, base="x", upper="y_upper", lower="y_lower") Whisker(source=param_scatter_source, base="x", upper="y_upper", lower="y_lower")
) )
@@ -304,10 +308,10 @@ def create():
# Plot tabs # Plot tabs
plots = Tabs( plots = Tabs(
tabs=[ tabs=[
Panel(child=plot, title="single scan"), TabPanel(child=plot, title="single scan"),
Panel(child=ov_plot, title="overview"), TabPanel(child=ov_plot, title="overview"),
Panel(child=ov_param_plot, title="overview map"), TabPanel(child=ov_param_plot, title="overview map"),
Panel(child=column(param_plot, row(fit_param_select)), title="parameter plot"), TabPanel(child=column(param_plot, row(fit_param_select)), title="parameter plot"),
] ]
) )
@@ -515,4 +519,4 @@ def create():
row(fitpeak_controls, app_fitctrl.result_textarea), row(fitpeak_controls, app_fitctrl.result_textarea),
) )
return Panel(child=tab_layout, title="param study") return TabPanel(child=tab_layout, title="param study")

View File

@@ -16,11 +16,11 @@ from bokeh.models import (
LinearColorMapper, LinearColorMapper,
LogColorMapper, LogColorMapper,
NumericInput, NumericInput,
Panel,
RadioGroup, RadioGroup,
Select, Select,
Spacer, Spacer,
Spinner, Spinner,
TabPanel,
TextInput, TextInput,
) )
from bokeh.plotting import figure from bokeh.plotting import figure
@@ -35,10 +35,10 @@ def create():
doc = curdoc() doc = curdoc()
log = doc.logger log = doc.logger
_update_slice = None _update_slice = None
measured_data_div = Div(text="Measured <b>HDF</b> data:") measured_data_div = Div(text="Measured <b>HDF</b> data:", margin=(12, 5, 5, 5))
measured_data = FileInput(accept=".hdf", multiple=True, width=200) measured_data = FileInput(accept=".hdf", multiple=True, width=200)
upload_hkl_div = Div(text="Open hkl/mhkl data:") upload_hkl_div = Div(text="Open hkl/mhkl data:", margin=(12, 5, 5, 5))
upload_hkl_fi = FileInput(accept=".hkl,.mhkl", multiple=True, width=200) upload_hkl_fi = FileInput(accept=".hkl,.mhkl", multiple=True, width=200)
def _prepare_plotting(): def _prepare_plotting():
@@ -439,4 +439,4 @@ def create():
tab_layout = row(column1_layout, Spacer(width=50), column2_layout) tab_layout = row(column1_layout, Spacer(width=50), column2_layout)
return Panel(child=tab_layout, title="plot data") return TabPanel(child=tab_layout, title="plot data")

View File

@@ -9,9 +9,9 @@ from bokeh.models import (
Button, Button,
ColumnDataSource, ColumnDataSource,
DataTable, DataTable,
Panel,
Spinner, Spinner,
TableColumn, TableColumn,
TabPanel,
TextAreaInput, TextAreaInput,
TextInput, TextInput,
) )
@@ -156,7 +156,7 @@ def create():
results_table_source.data.update(spind_res) results_table_source.data.update(spind_res)
process_button = Button(label="Process", button_type="primary") process_button = Button(label="Process", button_type="primary", width=300)
process_button.on_click(process_button_callback) process_button.on_click(process_button_callback)
if doc.spind_path is None: if doc.spind_path is None:
@@ -220,4 +220,4 @@ def create():
doc.add_periodic_callback(update_npeaks_spinner, 1000) doc.add_periodic_callback(update_npeaks_spinner, 1000)
return Panel(child=tab_layout, title="spind") return TabPanel(child=tab_layout, title="spind")

View File

@@ -35,10 +35,10 @@ class PlotHKL:
log = doc.logger log = doc.logger
_update_slice = None _update_slice = None
measured_data_div = Div(text="Measured <b>CCL</b> data:") measured_data_div = Div(text="Measured <b>CCL</b> data:", margin=(12, 5, 5, 5))
measured_data = FileInput(accept=".ccl", multiple=True, width=200) measured_data = FileInput(accept=".ccl", multiple=True, width=200)
upload_hkl_div = Div(text="Open hkl/mhkl data:") upload_hkl_div = Div(text="Open hkl/mhkl data:", margin=(12, 5, 5, 5))
upload_hkl_fi = FileInput(accept=".hkl,.mhkl", multiple=True, width=200) upload_hkl_fi = FileInput(accept=".hkl,.mhkl", multiple=True, width=200)
min_grid_x = -10 min_grid_x = -10
@@ -515,7 +515,7 @@ class PlotHKL:
) )
k_vectors = TextAreaInput( k_vectors = TextAreaInput(
title="k vectors:", value="0.0 0.0 0.0\n0.5 0.0 0.0\n0.5 0.5 0.0", width=150 title="k vectors:", value="0.0 0.0 0.0\n0.5 0.0 0.0\n0.5 0.5 0.0", rows=3, width=150
) )
res_mult_ni = NumericInput(title="Resolution mult:", value=10, mode="int", width=100) res_mult_ni = NumericInput(title="Resolution mult:", value=10, mode="int", width=100)
tol_k_ni = NumericInput(title="k tolerance:", value=0.01, mode="float", width=100) tol_k_ni = NumericInput(title="k tolerance:", value=0.01, mode="float", width=100)