diff --git a/pyzebra/app/panel_hdf_param_study.py b/pyzebra/app/panel_hdf_param_study.py index 3dc7f682571b07221a840295c39d5c22dd7d422a..94bb7b6127d39d4bb028b28459a272760b6a2e94 100644 --- a/pyzebra/app/panel_hdf_param_study.py +++ b/pyzebra/app/panel_hdf_param_study.py @@ -367,16 +367,16 @@ def create(): ) proj_auto_checkbox.on_click(proj_auto_checkbox_callback) - def proj_display_max_spinner_callback(_attr, _old_value, new_value): - color_mapper_proj.high = new_value + def proj_display_max_spinner_callback(_attr, _old, new): + color_mapper_proj.high = new proj_display_max_spinner = Spinner( value=1, disabled=bool(proj_auto_checkbox.active), mode="int", width=100 ) proj_display_max_spinner.on_change("value", proj_display_max_spinner_callback) - def proj_display_min_spinner_callback(_attr, _old_value, new_value): - color_mapper_proj.low = new_value + def proj_display_min_spinner_callback(_attr, _old, new): + color_mapper_proj.low = new proj_display_min_spinner = Spinner( value=0, disabled=bool(proj_auto_checkbox.active), mode="int", width=100 diff --git a/pyzebra/app/panel_hdf_viewer.py b/pyzebra/app/panel_hdf_viewer.py index 53283a4103a41f8c63602785fd38f52d062bb055..8b2b7d832f57f067e6d9fc1a14ba0244a080f437 100644 --- a/pyzebra/app/panel_hdf_viewer.py +++ b/pyzebra/app/panel_hdf_viewer.py @@ -18,9 +18,11 @@ from bokeh.models import ( HoverTool, LinearAxis, LinearColorMapper, + LogColorMapper, MultiSelect, NumberFormatter, Panel, + RadioGroup, Range1d, Select, Slider, @@ -483,8 +485,9 @@ def create(): ) ) - color_mapper = LinearColorMapper() - plot.image(source=image_source, color_mapper=color_mapper) + lin_color_mapper = LinearColorMapper(low=0, high=1) + log_color_mapper = LogColorMapper(low=0, high=1) + plot_image = plot.image(source=image_source, color_mapper=lin_color_mapper) plot.image(source=image_source, image="h", global_alpha=0) plot.image(source=image_source, image="k", global_alpha=0) plot.image(source=image_source, image="l", global_alpha=0) @@ -573,7 +576,8 @@ def create(): # shared frame ranges frame_range = Range1d(0, 1, bounds=(0, 1)) scanning_motor_range = Range1d(0, 1, bounds=(0, 1)) - color_mapper_proj = LinearColorMapper() + lin_color_mapper_proj = LinearColorMapper(low=0, high=1) + log_color_mapper_proj = LogColorMapper(low=0, high=1) det_x_range = Range1d(0, IMAGE_W, bounds=(0, IMAGE_W)) gamma_range = Range1d(0, 1, bounds=(0, 1)) @@ -600,7 +604,7 @@ def create(): dict(image=[np.zeros((1, 1), dtype="float32")], x=[0], y=[0], dw=[IMAGE_W], dh=[1]) ) - proj_x_plot.image(source=proj_x_image_source, color_mapper=color_mapper_proj) + proj_x_image = proj_x_plot.image(source=proj_x_image_source, color_mapper=lin_color_mapper_proj) det_y_range = Range1d(0, IMAGE_H, bounds=(0, IMAGE_H)) nu_range = Range1d(0, 1, bounds=(0, 1)) @@ -629,7 +633,7 @@ def create(): dict(image=[np.zeros((1, 1), dtype="float32")], x=[0], y=[0], dw=[IMAGE_H], dh=[1]) ) - proj_y_plot.image(source=proj_y_image_source, color_mapper=color_mapper_proj) + proj_y_image = proj_y_plot.image(source=proj_y_image_source, color_mapper=lin_color_mapper_proj) # ROI slice plot roi_avg_plot = figure(plot_height=150, plot_width=IMAGE_PLOT_W, tools="", toolbar_location=None) @@ -638,17 +642,41 @@ def create(): roi_avg_plot.line(source=roi_avg_plot_line_source, line_color="steelblue") def colormap_select_callback(_attr, _old, new): - color_mapper.palette = new - color_mapper_proj.palette = new + lin_color_mapper.palette = new + log_color_mapper.palette = new + lin_color_mapper_proj.palette = new + log_color_mapper_proj.palette = new colormap_select = Select( title="Colormap:", options=[("Greys256", "greys"), ("Plasma256", "plasma"), ("Cividis256", "cividis")], - width=210, + width=100, ) colormap_select.on_change("value", colormap_select_callback) colormap_select.value = "Plasma256" + def colormap_scale_rg_callback(selection): + if selection == 0: # Linear + plot_image.glyph.color_mapper = lin_color_mapper + proj_x_image.glyph.color_mapper = lin_color_mapper_proj + proj_y_image.glyph.color_mapper = lin_color_mapper_proj + + else: # Logarithmic + if ( + display_min_spinner.value > 0 + and display_max_spinner.value > 0 + and proj_display_min_spinner.value > 0 + and proj_display_max_spinner.value > 0 + ): + plot_image.glyph.color_mapper = log_color_mapper + proj_x_image.glyph.color_mapper = log_color_mapper_proj + proj_y_image.glyph.color_mapper = log_color_mapper_proj + else: + colormap_scale_rg.active = 0 + + colormap_scale_rg = RadioGroup(labels=["Linear", "Logarithmic"], active=0, width=100) + colormap_scale_rg.on_click(colormap_scale_rg_callback) + def main_auto_checkbox_callback(state): if state: display_min_spinner.disabled = True @@ -664,20 +692,21 @@ def create(): ) main_auto_checkbox.on_click(main_auto_checkbox_callback) - def display_max_spinner_callback(_attr, _old_value, new_value): - color_mapper.high = new_value + def display_max_spinner_callback(_attr, _old, new): + lin_color_mapper.high = new + log_color_mapper.high = new + # TODO: without this _update_image() log color mapper display is delayed + _update_image() - display_max_spinner = Spinner( - value=1, disabled=bool(main_auto_checkbox.active), mode="int", width=100 - ) + display_max_spinner = Spinner(value=1, disabled=bool(main_auto_checkbox.active), width=100) display_max_spinner.on_change("value", display_max_spinner_callback) - def display_min_spinner_callback(_attr, _old_value, new_value): - color_mapper.low = new_value + def display_min_spinner_callback(_attr, _old, new): + lin_color_mapper.low = new + log_color_mapper.low = new + _update_image() - display_min_spinner = Spinner( - value=0, disabled=bool(main_auto_checkbox.active), mode="int", width=100 - ) + display_min_spinner = Spinner(value=0, disabled=bool(main_auto_checkbox.active), width=100) display_min_spinner.on_change("value", display_min_spinner_callback) def proj_auto_checkbox_callback(state): @@ -695,20 +724,20 @@ def create(): ) proj_auto_checkbox.on_click(proj_auto_checkbox_callback) - def proj_display_max_spinner_callback(_attr, _old_value, new_value): - color_mapper_proj.high = new_value + def proj_display_max_spinner_callback(_attr, _old, new): + lin_color_mapper_proj.high = new + log_color_mapper_proj.high = new + _update_proj_plots() - proj_display_max_spinner = Spinner( - value=1, disabled=bool(proj_auto_checkbox.active), mode="int", width=100 - ) + proj_display_max_spinner = Spinner(value=1, disabled=bool(proj_auto_checkbox.active), width=100) proj_display_max_spinner.on_change("value", proj_display_max_spinner_callback) - def proj_display_min_spinner_callback(_attr, _old_value, new_value): - color_mapper_proj.low = new_value + def proj_display_min_spinner_callback(_attr, _old, new): + lin_color_mapper_proj.low = new + log_color_mapper_proj.low = new + _update_proj_plots() - proj_display_min_spinner = Spinner( - value=0, disabled=bool(proj_auto_checkbox.active), mode="int", width=100 - ) + proj_display_min_spinner = Spinner(value=0, disabled=bool(proj_auto_checkbox.active), width=100) proj_display_min_spinner.on_change("value", proj_display_min_spinner_callback) events_data = dict( @@ -881,7 +910,7 @@ def create(): layout_image = column(gridplot([[proj_v, None], [plot, proj_h]], merge_tools=False)) colormap_layout = column( - colormap_select, + row(colormap_select, column(Spacer(height=15), colormap_scale_rg)), main_auto_checkbox, row(display_min_spinner, display_max_spinner), proj_auto_checkbox, diff --git a/pyzebra/app/panel_plot_data.py b/pyzebra/app/panel_plot_data.py index fe0df2194890575261fbf1b9c5abc1ee9f798b09..f7c60f421f6bdee13ac7fec7a03a3d7c4145b732 100644 --- a/pyzebra/app/panel_plot_data.py +++ b/pyzebra/app/panel_plot_data.py @@ -13,8 +13,10 @@ from bokeh.models import ( Div, FileInput, LinearColorMapper, + LogColorMapper, NumericInput, Panel, + RadioGroup, Select, Spacer, Spinner, @@ -254,11 +256,15 @@ def create(): ) plot.toolbar.logo = None - color_mapper = LinearColorMapper(nan_color=(0, 0, 0, 0), low=0, high=1) + lin_color_mapper = LinearColorMapper(nan_color=(0, 0, 0, 0), low=0, high=1) + log_color_mapper = LogColorMapper(nan_color=(0, 0, 0, 0), low=0, high=1) image_source = ColumnDataSource(dict(image=[np.zeros((1, 1))], x=[0], y=[0], dw=[1], dh=[1])) - plot.image(source=image_source, color_mapper=color_mapper) + plot_image = plot.image(source=image_source, color_mapper=lin_color_mapper) - plot.add_layout(ColorBar(color_mapper=color_mapper, width=15), "right") + lin_color_bar = ColorBar(color_mapper=lin_color_mapper, width=15) + log_color_bar = ColorBar(color_mapper=log_color_mapper, width=15, visible=False) + plot.add_layout(lin_color_bar, "right") + plot.add_layout(log_color_bar, "right") scatter_source = ColumnDataSource(dict(x=[], y=[])) plot.scatter(source=scatter_source, size=4, fill_color="green", line_color="green") @@ -298,7 +304,8 @@ def create(): redef_ub_ti = TextInput(width=490, disabled=True) def colormap_select_callback(_attr, _old, new): - color_mapper.palette = new + lin_color_mapper.palette = new + log_color_mapper.palette = new colormap_select = Select( title="Colormap:", @@ -309,17 +316,36 @@ def create(): colormap_select.value = "Plasma256" def display_min_ni_callback(_attr, _old, new): - color_mapper.low = new + lin_color_mapper.low = new + log_color_mapper.low = new display_min_ni = NumericInput(title="Intensity min:", value=0, mode="float", width=70) display_min_ni.on_change("value", display_min_ni_callback) def display_max_ni_callback(_attr, _old, new): - color_mapper.high = new + lin_color_mapper.high = new + log_color_mapper.high = new display_max_ni = NumericInput(title="max:", value=1, mode="float", width=70) display_max_ni.on_change("value", display_max_ni_callback) + def colormap_scale_rg_callback(selection): + if selection == 0: # Linear + plot_image.glyph.color_mapper = lin_color_mapper + lin_color_bar.visible = True + log_color_bar.visible = False + + else: # Logarithmic + if display_min_ni.value > 0 and display_max_ni.value > 0: + plot_image.glyph.color_mapper = log_color_mapper + lin_color_bar.visible = False + log_color_bar.visible = True + else: + colormap_scale_rg.active = 0 + + colormap_scale_rg = RadioGroup(labels=["Linear", "Logarithmic"], active=0, width=100) + colormap_scale_rg.on_click(colormap_scale_rg_callback) + xrange_min_ni = NumericInput(title="x range min:", value=0, mode="float", width=70) xrange_max_ni = NumericInput(title="max:", value=1, mode="float", width=70) xrange_step_ni = NumericInput(title="x mesh:", value=0.01, mode="float", width=70) @@ -355,7 +381,7 @@ def create(): hkl_div, row(hkl_normal, hkl_cut, hkl_delta), row(hkl_in_plane_x, hkl_in_plane_y), - colormap_select, + row(colormap_select, column(Spacer(height=15), colormap_scale_rg)), row(display_min_ni, display_max_ni), row(column(Spacer(height=19), auto_range_cb)), row(xrange_min_ni, xrange_max_ni),