def get_save_layout_button(enable_button, from_main): from astronomicAL.utils import save_config if ("save_button" not in settings.keys()) or from_main: settings["save_button"] = pn.widgets.Button( name="Save Current Configuration", disabled=not (enable_button) ) layout_dict = {} text_area_input = TextAreaInput(value="") text_area_input.on_change( "value", partial( save_config.save_config_file_cb, trigger_text=text_area_input, autosave=False, ), ) settings["save_button"].jscallback( clicks=save_config.save_layout_js_cb, args=dict(text_area_input=text_area_input), ) settings["save_button"].on_click(_save_layout_button_cb) return settings["save_button"] if not from_main: settings["save_button"].disabled = not (enable_button) return settings["save_button"]
def modify_doc(doc): source = ColumnDataSource(dict(x=[1, 2], y=[1, 1], val=["a", "b"])) plot = Plot(plot_height=400, plot_width=400, x_range=Range1d(0, 1), y_range=Range1d(0, 1), min_border=0) plot.add_glyph(source, Circle(x='x', y='y', size=20)) code = RECORD("data", "s.data") plot.add_tools(CustomAction(callback=CustomJS(args=dict(s=source), code=code))) text_input = TextAreaInput(cols=20, css_classes=["foo"]) def cb(attr, old, new): foo.append((old, new)) source.data['val'] = [old, new] text_input.on_change('value', cb) doc.add_root(column(text_input, plot))
def create_text(cont): """ Create a box to enter text for each tab. Args: cont (str): Continent name. Returns: text_input (:obj:`TextAreaInput`): Text input box. """ text_input = TextAreaInput( value="", rows=6, title="Manually enter line-separated countries, hit tab when finished") text_input.on_change("value", text_update) return text_input
def create(): doc = curdoc() det_data = {} cami_meta = {} def proposal_textinput_callback(_attr, _old, new): nonlocal cami_meta proposal = new.strip() for zebra_proposals_path in pyzebra.ZEBRA_PROPOSALS_PATHS: proposal_path = os.path.join(zebra_proposals_path, proposal) if os.path.isdir(proposal_path): # found it break else: raise ValueError(f"Can not find data for proposal '{proposal}'.") file_list = [] for file in os.listdir(proposal_path): if file.endswith(".hdf"): file_list.append((os.path.join(proposal_path, file), file)) file_select.options = file_list cami_meta = {} proposal_textinput = TextInput(title="Proposal number:", width=210) proposal_textinput.on_change("value", proposal_textinput_callback) def upload_button_callback(_attr, _old, new): nonlocal cami_meta with io.StringIO(base64.b64decode(new).decode()) as file: cami_meta = pyzebra.parse_h5meta(file) file_list = cami_meta["filelist"] file_select.options = [(entry, os.path.basename(entry)) for entry in file_list] upload_div = Div(text="or upload .cami file:", margin=(5, 5, 0, 5)) upload_button = FileInput(accept=".cami", width=200) upload_button.on_change("value", upload_button_callback) def update_image(index=None): if index is None: index = index_spinner.value current_image = det_data["data"][index] proj_v_line_source.data.update(x=np.arange(0, IMAGE_W) + 0.5, y=np.mean(current_image, axis=0)) proj_h_line_source.data.update(x=np.mean(current_image, axis=1), y=np.arange(0, IMAGE_H) + 0.5) image_source.data.update( h=[np.zeros((1, 1))], k=[np.zeros((1, 1))], l=[np.zeros((1, 1))], ) image_source.data.update(image=[current_image]) if main_auto_checkbox.active: im_min = np.min(current_image) im_max = np.max(current_image) display_min_spinner.value = im_min display_max_spinner.value = im_max image_glyph.color_mapper.low = im_min image_glyph.color_mapper.high = im_max if "mf" in det_data: metadata_table_source.data.update(mf=[det_data["mf"][index]]) else: metadata_table_source.data.update(mf=[None]) if "temp" in det_data: metadata_table_source.data.update(temp=[det_data["temp"][index]]) else: metadata_table_source.data.update(temp=[None]) gamma, nu = calculate_pol(det_data, index) omega = np.ones((IMAGE_H, IMAGE_W)) * det_data["omega"][index] image_source.data.update(gamma=[gamma], nu=[nu], omega=[omega]) def update_overview_plot(): h5_data = det_data["data"] n_im, n_y, n_x = h5_data.shape overview_x = np.mean(h5_data, axis=1) overview_y = np.mean(h5_data, axis=2) overview_plot_x_image_source.data.update(image=[overview_x], dw=[n_x], dh=[n_im]) overview_plot_y_image_source.data.update(image=[overview_y], dw=[n_y], dh=[n_im]) if proj_auto_checkbox.active: im_min = min(np.min(overview_x), np.min(overview_y)) im_max = max(np.max(overview_x), np.max(overview_y)) proj_display_min_spinner.value = im_min proj_display_max_spinner.value = im_max overview_plot_x_image_glyph.color_mapper.low = im_min overview_plot_y_image_glyph.color_mapper.low = im_min overview_plot_x_image_glyph.color_mapper.high = im_max overview_plot_y_image_glyph.color_mapper.high = im_max frame_range.start = 0 frame_range.end = n_im frame_range.reset_start = 0 frame_range.reset_end = n_im frame_range.bounds = (0, n_im) scan_motor = det_data["scan_motor"] overview_plot_y.axis[1].axis_label = f"Scanning motor, {scan_motor}" var = det_data[scan_motor] var_start = var[0] var_end = var[-1] + (var[-1] - var[0]) / (n_im - 1) scanning_motor_range.start = var_start scanning_motor_range.end = var_end scanning_motor_range.reset_start = var_start scanning_motor_range.reset_end = var_end # handle both, ascending and descending sequences scanning_motor_range.bounds = (min(var_start, var_end), max(var_start, var_end)) def file_select_callback(_attr, old, new): nonlocal det_data if not new: # skip empty selections return # Avoid selection of multiple indicies (via Shift+Click or Ctrl+Click) if len(new) > 1: # drop selection to the previous one file_select.value = old return if len(old) > 1: # skip unnecessary update caused by selection drop return det_data = pyzebra.read_detector_data(new[0]) if cami_meta and "crystal" in cami_meta: det_data["ub"] = cami_meta["crystal"]["UB"] index_spinner.value = 0 index_spinner.high = det_data["data"].shape[0] - 1 index_slider.end = det_data["data"].shape[0] - 1 zebra_mode = det_data["zebra_mode"] if zebra_mode == "nb": metadata_table_source.data.update(geom=["normal beam"]) else: # zebra_mode == "bi" metadata_table_source.data.update(geom=["bisecting"]) update_image(0) update_overview_plot() file_select = MultiSelect(title="Available .hdf files:", width=210, height=250) file_select.on_change("value", file_select_callback) def index_callback(_attr, _old, new): update_image(new) index_slider = Slider(value=0, start=0, end=1, show_value=False, width=400) index_spinner = Spinner(title="Image index:", value=0, low=0, width=100) index_spinner.on_change("value", index_callback) index_slider.js_link("value_throttled", index_spinner, "value") index_spinner.js_link("value", index_slider, "value") plot = Plot( x_range=Range1d(0, IMAGE_W, bounds=(0, IMAGE_W)), y_range=Range1d(0, IMAGE_H, bounds=(0, IMAGE_H)), plot_height=IMAGE_PLOT_H, plot_width=IMAGE_PLOT_W, toolbar_location="left", ) # ---- tools plot.toolbar.logo = None # ---- axes plot.add_layout(LinearAxis(), place="above") plot.add_layout(LinearAxis(major_label_orientation="vertical"), place="right") # ---- grid lines plot.add_layout(Grid(dimension=0, ticker=BasicTicker())) plot.add_layout(Grid(dimension=1, ticker=BasicTicker())) # ---- rgba image glyph image_source = ColumnDataSource( dict( image=[np.zeros((IMAGE_H, IMAGE_W), dtype="float32")], h=[np.zeros((1, 1))], k=[np.zeros((1, 1))], l=[np.zeros((1, 1))], gamma=[np.zeros((1, 1))], nu=[np.zeros((1, 1))], omega=[np.zeros((1, 1))], x=[0], y=[0], dw=[IMAGE_W], dh=[IMAGE_H], )) h_glyph = Image(image="h", x="x", y="y", dw="dw", dh="dh", global_alpha=0) k_glyph = Image(image="k", x="x", y="y", dw="dw", dh="dh", global_alpha=0) l_glyph = Image(image="l", x="x", y="y", dw="dw", dh="dh", global_alpha=0) gamma_glyph = Image(image="gamma", x="x", y="y", dw="dw", dh="dh", global_alpha=0) nu_glyph = Image(image="nu", x="x", y="y", dw="dw", dh="dh", global_alpha=0) omega_glyph = Image(image="omega", x="x", y="y", dw="dw", dh="dh", global_alpha=0) plot.add_glyph(image_source, h_glyph) plot.add_glyph(image_source, k_glyph) plot.add_glyph(image_source, l_glyph) plot.add_glyph(image_source, gamma_glyph) plot.add_glyph(image_source, nu_glyph) plot.add_glyph(image_source, omega_glyph) image_glyph = Image(image="image", x="x", y="y", dw="dw", dh="dh") plot.add_glyph(image_source, image_glyph, name="image_glyph") # ---- projections proj_v = Plot( x_range=plot.x_range, y_range=DataRange1d(), plot_height=150, plot_width=IMAGE_PLOT_W, toolbar_location=None, ) proj_v.add_layout(LinearAxis(major_label_orientation="vertical"), place="right") proj_v.add_layout(LinearAxis(major_label_text_font_size="0pt"), place="below") proj_v.add_layout(Grid(dimension=0, ticker=BasicTicker())) proj_v.add_layout(Grid(dimension=1, ticker=BasicTicker())) proj_v_line_source = ColumnDataSource(dict(x=[], y=[])) proj_v.add_glyph(proj_v_line_source, Line(x="x", y="y", line_color="steelblue")) proj_h = Plot( x_range=DataRange1d(), y_range=plot.y_range, plot_height=IMAGE_PLOT_H, plot_width=150, toolbar_location=None, ) proj_h.add_layout(LinearAxis(), place="above") proj_h.add_layout(LinearAxis(major_label_text_font_size="0pt"), place="left") proj_h.add_layout(Grid(dimension=0, ticker=BasicTicker())) proj_h.add_layout(Grid(dimension=1, ticker=BasicTicker())) proj_h_line_source = ColumnDataSource(dict(x=[], y=[])) proj_h.add_glyph(proj_h_line_source, Line(x="x", y="y", line_color="steelblue")) # add tools hovertool = HoverTool(tooltips=[ ("intensity", "@image"), ("gamma", "@gamma"), ("nu", "@nu"), ("omega", "@omega"), ("h", "@h"), ("k", "@k"), ("l", "@l"), ]) box_edit_source = ColumnDataSource(dict(x=[], y=[], width=[], height=[])) box_edit_glyph = Rect(x="x", y="y", width="width", height="height", fill_alpha=0, line_color="red") box_edit_renderer = plot.add_glyph(box_edit_source, box_edit_glyph) boxedittool = BoxEditTool(renderers=[box_edit_renderer], num_objects=1) def box_edit_callback(_attr, _old, new): if new["x"]: h5_data = det_data["data"] x_val = np.arange(h5_data.shape[0]) left = int(np.floor(new["x"][0])) right = int(np.ceil(new["x"][0] + new["width"][0])) bottom = int(np.floor(new["y"][0])) top = int(np.ceil(new["y"][0] + new["height"][0])) y_val = np.sum(h5_data[:, bottom:top, left:right], axis=(1, 2)) else: x_val = [] y_val = [] roi_avg_plot_line_source.data.update(x=x_val, y=y_val) box_edit_source.on_change("data", box_edit_callback) wheelzoomtool = WheelZoomTool(maintain_focus=False) plot.add_tools( PanTool(), BoxZoomTool(), wheelzoomtool, ResetTool(), hovertool, boxedittool, ) plot.toolbar.active_scroll = wheelzoomtool # shared frame ranges frame_range = Range1d(0, 1, bounds=(0, 1)) scanning_motor_range = Range1d(0, 1, bounds=(0, 1)) det_x_range = Range1d(0, IMAGE_W, bounds=(0, IMAGE_W)) overview_plot_x = Plot( title=Title(text="Projections on X-axis"), x_range=det_x_range, y_range=frame_range, extra_y_ranges={"scanning_motor": scanning_motor_range}, plot_height=400, plot_width=IMAGE_PLOT_W - 3, ) # ---- tools wheelzoomtool = WheelZoomTool(maintain_focus=False) overview_plot_x.toolbar.logo = None overview_plot_x.add_tools( PanTool(), BoxZoomTool(), wheelzoomtool, ResetTool(), ) overview_plot_x.toolbar.active_scroll = wheelzoomtool # ---- axes overview_plot_x.add_layout(LinearAxis(axis_label="Coordinate X, pix"), place="below") overview_plot_x.add_layout(LinearAxis(axis_label="Frame", major_label_orientation="vertical"), place="left") # ---- grid lines overview_plot_x.add_layout(Grid(dimension=0, ticker=BasicTicker())) overview_plot_x.add_layout(Grid(dimension=1, ticker=BasicTicker())) # ---- rgba image glyph overview_plot_x_image_source = ColumnDataSource( dict(image=[np.zeros((1, 1), dtype="float32")], x=[0], y=[0], dw=[IMAGE_W], dh=[1])) overview_plot_x_image_glyph = Image(image="image", x="x", y="y", dw="dw", dh="dh") overview_plot_x.add_glyph(overview_plot_x_image_source, overview_plot_x_image_glyph, name="image_glyph") det_y_range = Range1d(0, IMAGE_H, bounds=(0, IMAGE_H)) overview_plot_y = Plot( title=Title(text="Projections on Y-axis"), x_range=det_y_range, y_range=frame_range, extra_y_ranges={"scanning_motor": scanning_motor_range}, plot_height=400, plot_width=IMAGE_PLOT_H + 22, ) # ---- tools wheelzoomtool = WheelZoomTool(maintain_focus=False) overview_plot_y.toolbar.logo = None overview_plot_y.add_tools( PanTool(), BoxZoomTool(), wheelzoomtool, ResetTool(), ) overview_plot_y.toolbar.active_scroll = wheelzoomtool # ---- axes overview_plot_y.add_layout(LinearAxis(axis_label="Coordinate Y, pix"), place="below") overview_plot_y.add_layout( LinearAxis( y_range_name="scanning_motor", axis_label="Scanning motor", major_label_orientation="vertical", ), place="right", ) # ---- grid lines overview_plot_y.add_layout(Grid(dimension=0, ticker=BasicTicker())) overview_plot_y.add_layout(Grid(dimension=1, ticker=BasicTicker())) # ---- rgba image glyph overview_plot_y_image_source = ColumnDataSource( dict(image=[np.zeros((1, 1), dtype="float32")], x=[0], y=[0], dw=[IMAGE_H], dh=[1])) overview_plot_y_image_glyph = Image(image="image", x="x", y="y", dw="dw", dh="dh") overview_plot_y.add_glyph(overview_plot_y_image_source, overview_plot_y_image_glyph, name="image_glyph") roi_avg_plot = Plot( x_range=DataRange1d(), y_range=DataRange1d(), plot_height=150, plot_width=IMAGE_PLOT_W, toolbar_location="left", ) # ---- tools roi_avg_plot.toolbar.logo = None # ---- axes roi_avg_plot.add_layout(LinearAxis(), place="below") roi_avg_plot.add_layout(LinearAxis(major_label_orientation="vertical"), place="left") # ---- grid lines roi_avg_plot.add_layout(Grid(dimension=0, ticker=BasicTicker())) roi_avg_plot.add_layout(Grid(dimension=1, ticker=BasicTicker())) roi_avg_plot_line_source = ColumnDataSource(dict(x=[], y=[])) roi_avg_plot.add_glyph(roi_avg_plot_line_source, Line(x="x", y="y", line_color="steelblue")) cmap_dict = { "gray": Greys256, "gray_reversed": Greys256[::-1], "plasma": Plasma256, "cividis": Cividis256, } def colormap_callback(_attr, _old, new): image_glyph.color_mapper = LinearColorMapper(palette=cmap_dict[new]) overview_plot_x_image_glyph.color_mapper = LinearColorMapper( palette=cmap_dict[new]) overview_plot_y_image_glyph.color_mapper = LinearColorMapper( palette=cmap_dict[new]) colormap = Select(title="Colormap:", options=list(cmap_dict.keys()), width=210) colormap.on_change("value", colormap_callback) colormap.value = "plasma" STEP = 1 def main_auto_checkbox_callback(state): if state: display_min_spinner.disabled = True display_max_spinner.disabled = True else: display_min_spinner.disabled = False display_max_spinner.disabled = False update_image() main_auto_checkbox = CheckboxGroup(labels=["Main Auto Range"], active=[0], width=145, margin=[10, 5, 0, 5]) main_auto_checkbox.on_click(main_auto_checkbox_callback) def display_max_spinner_callback(_attr, _old_value, new_value): display_min_spinner.high = new_value - STEP image_glyph.color_mapper.high = new_value display_max_spinner = Spinner( low=0 + STEP, value=1, step=STEP, disabled=bool(main_auto_checkbox.active), width=100, height=31, ) display_max_spinner.on_change("value", display_max_spinner_callback) def display_min_spinner_callback(_attr, _old_value, new_value): display_max_spinner.low = new_value + STEP image_glyph.color_mapper.low = new_value display_min_spinner = Spinner( low=0, high=1 - STEP, value=0, step=STEP, disabled=bool(main_auto_checkbox.active), width=100, height=31, ) display_min_spinner.on_change("value", display_min_spinner_callback) PROJ_STEP = 0.1 def proj_auto_checkbox_callback(state): if state: proj_display_min_spinner.disabled = True proj_display_max_spinner.disabled = True else: proj_display_min_spinner.disabled = False proj_display_max_spinner.disabled = False update_overview_plot() proj_auto_checkbox = CheckboxGroup(labels=["Projections Auto Range"], active=[0], width=145, margin=[10, 5, 0, 5]) proj_auto_checkbox.on_click(proj_auto_checkbox_callback) def proj_display_max_spinner_callback(_attr, _old_value, new_value): proj_display_min_spinner.high = new_value - PROJ_STEP overview_plot_x_image_glyph.color_mapper.high = new_value overview_plot_y_image_glyph.color_mapper.high = new_value proj_display_max_spinner = Spinner( low=0 + PROJ_STEP, value=1, step=PROJ_STEP, disabled=bool(proj_auto_checkbox.active), width=100, height=31, ) proj_display_max_spinner.on_change("value", proj_display_max_spinner_callback) def proj_display_min_spinner_callback(_attr, _old_value, new_value): proj_display_max_spinner.low = new_value + PROJ_STEP overview_plot_x_image_glyph.color_mapper.low = new_value overview_plot_y_image_glyph.color_mapper.low = new_value proj_display_min_spinner = Spinner( low=0, high=1 - PROJ_STEP, value=0, step=PROJ_STEP, disabled=bool(proj_auto_checkbox.active), width=100, height=31, ) proj_display_min_spinner.on_change("value", proj_display_min_spinner_callback) def hkl_button_callback(): index = index_spinner.value h, k, l = calculate_hkl(det_data, index) image_source.data.update(h=[h], k=[k], l=[l]) hkl_button = Button(label="Calculate hkl (slow)", width=210) hkl_button.on_click(hkl_button_callback) def events_list_callback(_attr, _old, new): doc.events_list_spind.value = new events_list = TextAreaInput(rows=7, width=830) events_list.on_change("value", events_list_callback) doc.events_list_hdf_viewer = events_list def add_event_button_callback(): diff_vec = [] p0 = [1.0, 0.0, 1.0] maxfev = 100000 wave = det_data["wave"] ddist = det_data["ddist"] gamma = det_data["gamma"][0] omega = det_data["omega"][0] nu = det_data["nu"][0] chi = det_data["chi"][0] phi = det_data["phi"][0] scan_motor = det_data["scan_motor"] var_angle = det_data[scan_motor] x0 = int(np.floor(det_x_range.start)) xN = int(np.ceil(det_x_range.end)) y0 = int(np.floor(det_y_range.start)) yN = int(np.ceil(det_y_range.end)) fr0 = int(np.floor(frame_range.start)) frN = int(np.ceil(frame_range.end)) data_roi = det_data["data"][fr0:frN, y0:yN, x0:xN] cnts = np.sum(data_roi, axis=(1, 2)) coeff, _ = curve_fit(gauss, range(len(cnts)), cnts, p0=p0, maxfev=maxfev) m = cnts.mean() sd = cnts.std() snr_cnts = np.where(sd == 0, 0, m / sd) frC = fr0 + coeff[1] var_F = var_angle[math.floor(frC)] var_C = var_angle[math.ceil(frC)] frStep = frC - math.floor(frC) var_step = var_C - var_F var_p = var_F + var_step * frStep if scan_motor == "gamma": gamma = var_p elif scan_motor == "omega": omega = var_p elif scan_motor == "nu": nu = var_p elif scan_motor == "chi": chi = var_p elif scan_motor == "phi": phi = var_p intensity = coeff[1] * abs( coeff[2] * var_step) * math.sqrt(2) * math.sqrt(np.pi) projX = np.sum(data_roi, axis=(0, 1)) coeff, _ = curve_fit(gauss, range(len(projX)), projX, p0=p0, maxfev=maxfev) x_pos = x0 + coeff[1] projY = np.sum(data_roi, axis=(0, 2)) coeff, _ = curve_fit(gauss, range(len(projY)), projY, p0=p0, maxfev=maxfev) y_pos = y0 + coeff[1] ga, nu = pyzebra.det2pol(ddist, gamma, nu, x_pos, y_pos) diff_vector = pyzebra.z1frmd(wave, ga, omega, chi, phi, nu) d_spacing = float(pyzebra.dandth(wave, diff_vector)[0]) diff_vector = diff_vector.flatten() * 1e10 dv1, dv2, dv3 = diff_vector diff_vec.append(diff_vector) if events_list.value and not events_list.value.endswith("\n"): events_list.value = events_list.value + "\n" events_list.value = ( events_list.value + f"{x_pos} {y_pos} {intensity} {snr_cnts} {dv1} {dv2} {dv3} {d_spacing}" ) add_event_button = Button(label="Add spind event") add_event_button.on_click(add_event_button_callback) metadata_table_source = ColumnDataSource( dict(geom=[""], temp=[None], mf=[None])) num_formatter = NumberFormatter(format="0.00", nan_format="") metadata_table = DataTable( source=metadata_table_source, columns=[ TableColumn(field="geom", title="Geometry", width=100), TableColumn(field="temp", title="Temperature", formatter=num_formatter, width=100), TableColumn(field="mf", title="Magnetic Field", formatter=num_formatter, width=100), ], width=300, height=50, autosize_mode="none", index_position=None, ) # Final layout import_layout = column(proposal_textinput, upload_div, upload_button, file_select) layout_image = column( gridplot([[proj_v, None], [plot, proj_h]], merge_tools=False)) colormap_layout = column( colormap, main_auto_checkbox, row(display_min_spinner, display_max_spinner), proj_auto_checkbox, row(proj_display_min_spinner, proj_display_max_spinner), ) layout_controls = column( row(metadata_table, index_spinner, column(Spacer(height=25), index_slider)), row(add_event_button, hkl_button), row(events_list), ) layout_overview = column( gridplot( [[overview_plot_x, overview_plot_y]], toolbar_options=dict(logo=None), merge_tools=True, toolbar_location="left", ), ) tab_layout = row( column(import_layout, colormap_layout), column(layout_overview, layout_controls), column(roi_avg_plot, layout_image), ) return Panel(child=tab_layout, title="hdf viewer")
def create(): config = pyzebra.AnatricConfig() def _load_config_file(file): config.load_from_file(file) logfile_textinput.value = config.logfile logfile_verbosity_select.value = config.logfile_verbosity filelist_type.value = config.filelist_type filelist_format_textinput.value = config.filelist_format filelist_datapath_textinput.value = config.filelist_datapath filelist_ranges_textareainput.value = "\n".join( map(str, config.filelist_ranges)) crystal_sample_textinput.value = config.crystal_sample lambda_textinput.value = config.crystal_lambda zeroOM_textinput.value = config.crystal_zeroOM zeroSTT_textinput.value = config.crystal_zeroSTT zeroCHI_textinput.value = config.crystal_zeroCHI ub_textareainput.value = config.crystal_UB dataFactory_implementation_select.value = config.dataFactory_implementation dataFactory_dist1_textinput.value = config.dataFactory_dist1 reflectionPrinter_format_select.value = config.reflectionPrinter_format set_active_widgets(config.algorithm) if config.algorithm == "adaptivemaxcog": threshold_textinput.value = config.threshold shell_textinput.value = config.shell steepness_textinput.value = config.steepness duplicateDistance_textinput.value = config.duplicateDistance maxequal_textinput.value = config.maxequal aps_window_textinput.value = str( tuple(map(int, config.aps_window.values()))) elif config.algorithm == "adaptivedynamic": adm_window_textinput.value = str( tuple(map(int, config.adm_window.values()))) border_textinput.value = str( tuple(map(int, config.border.values()))) minWindow_textinput.value = str( tuple(map(int, config.minWindow.values()))) reflectionFile_textinput.value = config.reflectionFile targetMonitor_textinput.value = config.targetMonitor smoothSize_textinput.value = config.smoothSize loop_textinput.value = config.loop minPeakCount_textinput.value = config.minPeakCount displacementCurve_textinput.value = "\n".join( map(str, config.displacementCurve)) else: raise ValueError("Unknown processing mode.") def set_active_widgets(implementation): if implementation == "adaptivemaxcog": mode_radio_button_group.active = 0 disable_adaptivemaxcog = False disable_adaptivedynamic = True elif implementation == "adaptivedynamic": mode_radio_button_group.active = 1 disable_adaptivemaxcog = True disable_adaptivedynamic = False else: raise ValueError( "Implementation can be either 'adaptivemaxcog' or 'adaptivedynamic'" ) threshold_textinput.disabled = disable_adaptivemaxcog shell_textinput.disabled = disable_adaptivemaxcog steepness_textinput.disabled = disable_adaptivemaxcog duplicateDistance_textinput.disabled = disable_adaptivemaxcog maxequal_textinput.disabled = disable_adaptivemaxcog aps_window_textinput.disabled = disable_adaptivemaxcog adm_window_textinput.disabled = disable_adaptivedynamic border_textinput.disabled = disable_adaptivedynamic minWindow_textinput.disabled = disable_adaptivedynamic reflectionFile_textinput.disabled = disable_adaptivedynamic targetMonitor_textinput.disabled = disable_adaptivedynamic smoothSize_textinput.disabled = disable_adaptivedynamic loop_textinput.disabled = disable_adaptivedynamic minPeakCount_textinput.disabled = disable_adaptivedynamic displacementCurve_textinput.disabled = disable_adaptivedynamic upload_div = Div(text="Open XML configuration file:") def upload_button_callback(_attr, _old, new): with io.BytesIO(base64.b64decode(new)) as file: _load_config_file(file) upload_button = FileInput(accept=".xml") upload_button.on_change("value", upload_button_callback) # General parameters # ---- logfile def logfile_textinput_callback(_attr, _old, new): config.logfile = new logfile_textinput = TextInput(title="Logfile:", value="logfile.log", width=520) logfile_textinput.on_change("value", logfile_textinput_callback) def logfile_verbosity_select_callback(_attr, _old, new): config.logfile_verbosity = new logfile_verbosity_select = Select(title="verbosity:", options=["0", "5", "10", "15", "30"], width=70) logfile_verbosity_select.on_change("value", logfile_verbosity_select_callback) # ---- FileList def filelist_type_callback(_attr, _old, new): config.filelist_type = new filelist_type = Select(title="File List:", options=["TRICS", "SINQ"], width=100) filelist_type.on_change("value", filelist_type_callback) def filelist_format_textinput_callback(_attr, _old, new): config.filelist_format = new filelist_format_textinput = TextInput(title="format:", width=490) filelist_format_textinput.on_change("value", filelist_format_textinput_callback) def filelist_datapath_textinput_callback(_attr, _old, new): config.filelist_datapath = new filelist_datapath_textinput = TextInput(title="datapath:") filelist_datapath_textinput.on_change( "value", filelist_datapath_textinput_callback) def filelist_ranges_textareainput_callback(_attr, _old, new): ranges = [] for line in new.splitlines(): ranges.append(re.findall(r"\b\d+\b", line)) config.filelist_ranges = ranges filelist_ranges_textareainput = TextAreaInput(title="ranges:", height=100) filelist_ranges_textareainput.on_change( "value", filelist_ranges_textareainput_callback) # ---- crystal def crystal_sample_textinput_callback(_attr, _old, new): config.crystal_sample = new crystal_sample_textinput = TextInput(title="Sample Name:") crystal_sample_textinput.on_change("value", crystal_sample_textinput_callback) def lambda_textinput_callback(_attr, _old, new): config.crystal_lambda = new lambda_textinput = TextInput(title="lambda:", width=140) lambda_textinput.on_change("value", lambda_textinput_callback) def ub_textareainput_callback(_attr, _old, new): config.crystal_UB = new ub_textareainput = TextAreaInput(title="UB matrix:", height=100) ub_textareainput.on_change("value", ub_textareainput_callback) def zeroOM_textinput_callback(_attr, _old, new): config.crystal_zeroOM = new zeroOM_textinput = TextInput(title="zeroOM:", width=140) zeroOM_textinput.on_change("value", zeroOM_textinput_callback) def zeroSTT_textinput_callback(_attr, _old, new): config.crystal_zeroSTT = new zeroSTT_textinput = TextInput(title="zeroSTT:", width=140) zeroSTT_textinput.on_change("value", zeroSTT_textinput_callback) def zeroCHI_textinput_callback(_attr, _old, new): config.crystal_zeroCHI = new zeroCHI_textinput = TextInput(title="zeroCHI:", width=140) zeroCHI_textinput.on_change("value", zeroCHI_textinput_callback) # ---- DataFactory def dataFactory_implementation_select_callback(_attr, _old, new): config.dataFactory_implementation = new dataFactory_implementation_select = Select( title="DataFactory implementation:", options=DATA_FACTORY_IMPLEMENTATION, width=300, ) dataFactory_implementation_select.on_change( "value", dataFactory_implementation_select_callback) def dataFactory_dist1_textinput_callback(_attr, _old, new): config.dataFactory_dist1 = new dataFactory_dist1_textinput = TextInput(title="dist1:", width=290) dataFactory_dist1_textinput.on_change( "value", dataFactory_dist1_textinput_callback) # ---- BackgroundProcessor # ---- DetectorEfficency # ---- ReflectionPrinter def reflectionPrinter_format_select_callback(_attr, _old, new): config.reflectionPrinter_format = new reflectionPrinter_format_select = Select( title="ReflectionPrinter format:", options=REFLECTION_PRINTER_FORMATS, width=300, ) reflectionPrinter_format_select.on_change( "value", reflectionPrinter_format_select_callback) # Adaptive Peak Detection (adaptivemaxcog) # ---- threshold def threshold_textinput_callback(_attr, _old, new): config.threshold = new threshold_textinput = TextInput(title="Threshold:") threshold_textinput.on_change("value", threshold_textinput_callback) # ---- shell def shell_textinput_callback(_attr, _old, new): config.shell = new shell_textinput = TextInput(title="Shell:") shell_textinput.on_change("value", shell_textinput_callback) # ---- steepness def steepness_textinput_callback(_attr, _old, new): config.steepness = new steepness_textinput = TextInput(title="Steepness:") steepness_textinput.on_change("value", steepness_textinput_callback) # ---- duplicateDistance def duplicateDistance_textinput_callback(_attr, _old, new): config.duplicateDistance = new duplicateDistance_textinput = TextInput(title="Duplicate Distance:") duplicateDistance_textinput.on_change( "value", duplicateDistance_textinput_callback) # ---- maxequal def maxequal_textinput_callback(_attr, _old, new): config.maxequal = new maxequal_textinput = TextInput(title="Max Equal:") maxequal_textinput.on_change("value", maxequal_textinput_callback) # ---- window def aps_window_textinput_callback(_attr, _old, new): config.aps_window = dict( zip(("x", "y", "z"), re.findall(r"\b\d+\b", new))) aps_window_textinput = TextInput(title="Window (x, y, z):") aps_window_textinput.on_change("value", aps_window_textinput_callback) # Adaptive Dynamic Mask Integration (adaptivedynamic) # ---- window def adm_window_textinput_callback(_attr, _old, new): config.adm_window = dict( zip(("x", "y", "z"), re.findall(r"\b\d+\b", new))) adm_window_textinput = TextInput(title="Window (x, y, z):") adm_window_textinput.on_change("value", adm_window_textinput_callback) # ---- border def border_textinput_callback(_attr, _old, new): config.border = dict(zip(("x", "y", "z"), re.findall(r"\b\d+\b", new))) border_textinput = TextInput(title="Border (x, y, z):") border_textinput.on_change("value", border_textinput_callback) # ---- minWindow def minWindow_textinput_callback(_attr, _old, new): config.minWindow = dict( zip(("x", "y", "z"), re.findall(r"\b\d+\b", new))) minWindow_textinput = TextInput(title="Min Window (x, y, z):") minWindow_textinput.on_change("value", minWindow_textinput_callback) # ---- reflectionFile def reflectionFile_textinput_callback(_attr, _old, new): config.reflectionFile = new reflectionFile_textinput = TextInput(title="Reflection File:") reflectionFile_textinput.on_change("value", reflectionFile_textinput_callback) # ---- targetMonitor def targetMonitor_textinput_callback(_attr, _old, new): config.targetMonitor = new targetMonitor_textinput = TextInput(title="Target Monitor:") targetMonitor_textinput.on_change("value", targetMonitor_textinput_callback) # ---- smoothSize def smoothSize_textinput_callback(_attr, _old, new): config.smoothSize = new smoothSize_textinput = TextInput(title="Smooth Size:") smoothSize_textinput.on_change("value", smoothSize_textinput_callback) # ---- loop def loop_textinput_callback(_attr, _old, new): config.loop = new loop_textinput = TextInput(title="Loop:") loop_textinput.on_change("value", loop_textinput_callback) # ---- minPeakCount def minPeakCount_textinput_callback(_attr, _old, new): config.minPeakCount = new minPeakCount_textinput = TextInput(title="Min Peak Count:") minPeakCount_textinput.on_change("value", minPeakCount_textinput_callback) # ---- displacementCurve def displacementCurve_textinput_callback(_attr, _old, new): maps = [] for line in new.splitlines(): maps.append(re.findall(r"\d+(?:\.\d+)?", line)) config.displacementCurve = maps displacementCurve_textinput = TextAreaInput( title="Displacement Curve (twotheta, x, y):", height=100) displacementCurve_textinput.on_change( "value", displacementCurve_textinput_callback) def mode_radio_button_group_callback(active): if active == 0: config.algorithm = "adaptivemaxcog" set_active_widgets("adaptivemaxcog") else: config.algorithm = "adaptivedynamic" set_active_widgets("adaptivedynamic") mode_radio_button_group = RadioButtonGroup( labels=["Adaptive Peak Detection", "Adaptive Dynamic Integration"], active=0) mode_radio_button_group.on_click(mode_radio_button_group_callback) set_active_widgets("adaptivemaxcog") def process_button_callback(): with tempfile.TemporaryDirectory() as temp_dir: temp_file = temp_dir + "/temp.xml" config.save_as(temp_file) pyzebra.anatric(temp_file) with open(config.logfile) as f_log: output_log.value = f_log.read() process_button = Button(label="Process", button_type="primary") process_button.on_click(process_button_callback) output_log = TextAreaInput(title="Logfile output:", height=700, disabled=True) output_config = TextAreaInput(title="Current config:", height=700, width=400, disabled=True) tab_layout = row( column( upload_div, upload_button, row(logfile_textinput, logfile_verbosity_select), row(filelist_type, filelist_format_textinput), filelist_datapath_textinput, filelist_ranges_textareainput, crystal_sample_textinput, row(lambda_textinput, zeroOM_textinput, zeroSTT_textinput, zeroCHI_textinput), ub_textareainput, row(dataFactory_implementation_select, dataFactory_dist1_textinput), reflectionPrinter_format_select, process_button, ), column( mode_radio_button_group, row( column( threshold_textinput, shell_textinput, steepness_textinput, duplicateDistance_textinput, maxequal_textinput, aps_window_textinput, ), column( adm_window_textinput, border_textinput, minWindow_textinput, reflectionFile_textinput, targetMonitor_textinput, smoothSize_textinput, loop_textinput, minPeakCount_textinput, displacementCurve_textinput, ), ), ), output_config, output_log, ) async def update_config(): config.save_as("debug.xml") with open("debug.xml") as f_config: output_config.value = f_config.read() curdoc().add_periodic_callback(update_config, 1000) return Panel(child=tab_layout, title="Anatric")
def create(): doc = curdoc() def events_list_callback(_attr, _old, new): doc.events_list_hdf_viewer.value = new events_list = TextAreaInput(title="Spind events:", rows=7, width=1500) events_list.on_change("value", events_list_callback) doc.events_list_spind = events_list lattice_const_textinput = TextInput( title="Lattice constants:", value="8.3211,8.3211,8.3211,90.00,90.00,90.00") max_res_spinner = Spinner(title="max-res:", value=2, step=0.01, width=145) seed_pool_size_spinner = Spinner(title="seed-pool-size:", value=5, step=0.01, width=145) seed_len_tol_spinner = Spinner(title="seed-len-tol:", value=0.02, step=0.01, width=145) seed_angle_tol_spinner = Spinner(title="seed-angle-tol:", value=1, step=0.01, width=145) eval_hkl_tol_spinner = Spinner(title="eval-hkl-tol:", value=0.15, step=0.01, width=145) diff_vec = [] ub_matrices = [] def process_button_callback(): # drop table selection to clear result fields results_table_source.selected.indices = [] nonlocal diff_vec with tempfile.TemporaryDirectory() as temp_dir: temp_peak_list_dir = os.path.join(temp_dir, "peak_list") os.mkdir(temp_peak_list_dir) temp_event_file = os.path.join(temp_peak_list_dir, "event-0.txt") temp_hkl_file = os.path.join(temp_dir, "hkl.h5") comp_proc = subprocess.run( [ "mpiexec", "-n", "2", "python", os.path.join(doc.spind_path, "gen_hkl_table.py"), lattice_const_textinput.value, "--max-res", str(max_res_spinner.value), "-o", temp_hkl_file, ], check=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True, ) print(" ".join(comp_proc.args)) print(comp_proc.stdout) # prepare an event file diff_vec = [] with open(temp_event_file, "w") as f: for event in events_list.value.splitlines(): diff_vec.append(np.array(event.split()[4:7], dtype=float)) f.write(event + "\n") print(f"Content of {temp_event_file}:") with open(temp_event_file) as f: print(f.read()) comp_proc = subprocess.run( [ "mpiexec", "-n", "2", "python", os.path.join(doc.spind_path, "SPIND.py"), temp_peak_list_dir, temp_hkl_file, "-o", temp_dir, "--seed-pool-size", str(seed_pool_size_spinner.value), "--seed-len-tol", str(seed_len_tol_spinner.value), "--seed-angle-tol", str(seed_angle_tol_spinner.value), "--eval-hkl-tol", str(eval_hkl_tol_spinner.value), ], check=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True, ) print(" ".join(comp_proc.args)) print(comp_proc.stdout) spind_out_file = os.path.join(temp_dir, "spind.txt") spind_res = dict( label=[], crystal_id=[], match_rate=[], matched_peaks=[], column_5=[], ub_matrix=[], ) try: with open(spind_out_file) as f_out: for line in f_out: c1, c2, c3, c4, c5, *c_rest = line.split() spind_res["label"].append(c1) spind_res["crystal_id"].append(c2) spind_res["match_rate"].append(c3) spind_res["matched_peaks"].append(c4) spind_res["column_5"].append(c5) # last digits are spind UB matrix vals = list(map(float, c_rest)) ub_matrix_spind = np.transpose( np.array(vals).reshape(3, 3)) ub_matrix = np.linalg.inv(ub_matrix_spind) ub_matrices.append(ub_matrix) spind_res["ub_matrix"].append( str(ub_matrix_spind * 1e-10)) print(f"Content of {spind_out_file}:") with open(spind_out_file) as f: print(f.read()) except FileNotFoundError: print("No results from spind") results_table_source.data.update(spind_res) process_button = Button(label="Process", button_type="primary") process_button.on_click(process_button_callback) if doc.spind_path is None: process_button.disabled = True ub_matrix_textareainput = TextAreaInput(title="UB matrix:", rows=7, width=400) hkl_textareainput = TextAreaInput(title="hkl values:", rows=7, width=400) def results_table_select_callback(_attr, old, new): if new: ind = new[0] ub_matrix = ub_matrices[ind] res = "" for vec in diff_vec: res += f"{ub_matrix @ vec}\n" ub_matrix_textareainput.value = str(ub_matrix * 1e10) hkl_textareainput.value = res else: ub_matrix_textareainput.value = "" hkl_textareainput.value = "" results_table_source = ColumnDataSource( dict(label=[], crystal_id=[], match_rate=[], matched_peaks=[], column_5=[], ub_matrix=[])) results_table = DataTable( source=results_table_source, columns=[ TableColumn(field="label", title="Label", width=50), TableColumn(field="crystal_id", title="Crystal ID", width=100), TableColumn(field="match_rate", title="Match Rate", width=100), TableColumn(field="matched_peaks", title="Matched Peaks", width=100), TableColumn(field="column_5", title="", width=100), TableColumn(field="ub_matrix", title="UB Matrix", width=700), ], height=300, width=1200, autosize_mode="none", index_position=None, ) results_table_source.selected.on_change("indices", results_table_select_callback) tab_layout = column( events_list, row( column( lattice_const_textinput, row(max_res_spinner, seed_pool_size_spinner), row(seed_len_tol_spinner, seed_angle_tol_spinner), row(eval_hkl_tol_spinner), process_button, ), column(results_table, row(ub_matrix_textareainput, hkl_textareainput)), ), ) return Panel(child=tab_layout, title="spind")
def create(): doc = curdoc() config = pyzebra.AnatricConfig() def _load_config_file(file): config.load_from_file(file) logfile_textinput.value = config.logfile logfile_verbosity.value = config.logfile_verbosity filelist_type.value = config.filelist_type filelist_format_textinput.value = config.filelist_format filelist_datapath_textinput.value = config.filelist_datapath filelist_ranges_textareainput.value = "\n".join( map(str, config.filelist_ranges)) crystal_sample_textinput.value = config.crystal_sample lambda_textinput.value = config.crystal_lambda zeroOM_textinput.value = config.crystal_zeroOM zeroSTT_textinput.value = config.crystal_zeroSTT zeroCHI_textinput.value = config.crystal_zeroCHI ub_textareainput.value = config.crystal_UB dataFactory_implementation_select.value = config.dataFactory_implementation if config.dataFactory_dist1 is not None: dataFactory_dist1_textinput.value = config.dataFactory_dist1 if config.dataFactory_dist2 is not None: dataFactory_dist2_textinput.value = config.dataFactory_dist2 if config.dataFactory_dist3 is not None: dataFactory_dist3_textinput.value = config.dataFactory_dist3 reflectionPrinter_format_select.value = config.reflectionPrinter_format if config.algorithm == "adaptivemaxcog": algorithm_params.active = 0 threshold_textinput.value = config.threshold shell_textinput.value = config.shell steepness_textinput.value = config.steepness duplicateDistance_textinput.value = config.duplicateDistance maxequal_textinput.value = config.maxequal aps_window_textinput.value = str( tuple(map(int, config.aps_window.values()))) elif config.algorithm == "adaptivedynamic": algorithm_params.active = 1 adm_window_textinput.value = str( tuple(map(int, config.adm_window.values()))) border_textinput.value = str( tuple(map(int, config.border.values()))) minWindow_textinput.value = str( tuple(map(int, config.minWindow.values()))) reflectionFile_textinput.value = config.reflectionFile targetMonitor_textinput.value = config.targetMonitor smoothSize_textinput.value = config.smoothSize loop_textinput.value = config.loop minPeakCount_textinput.value = config.minPeakCount displacementCurve_textinput.value = "\n".join( map(str, config.displacementCurve)) else: raise ValueError("Unknown processing mode.") def upload_button_callback(_attr, _old, new): with io.BytesIO(base64.b64decode(new)) as file: _load_config_file(file) upload_div = Div(text="Open .xml config:") upload_button = FileInput(accept=".xml", width=200) upload_button.on_change("value", upload_button_callback) # General parameters # ---- logfile def logfile_textinput_callback(_attr, _old, new): config.logfile = new logfile_textinput = TextInput(title="Logfile:", value="logfile.log") logfile_textinput.on_change("value", logfile_textinput_callback) def logfile_verbosity_callback(_attr, _old, new): config.logfile_verbosity = new logfile_verbosity = TextInput(title="verbosity:", width=70) logfile_verbosity.on_change("value", logfile_verbosity_callback) # ---- FileList def filelist_type_callback(_attr, _old, new): config.filelist_type = new filelist_type = Select(title="File List:", options=["TRICS", "SINQ"], width=100) filelist_type.on_change("value", filelist_type_callback) def filelist_format_textinput_callback(_attr, _old, new): config.filelist_format = new filelist_format_textinput = TextInput(title="format:", width=290) filelist_format_textinput.on_change("value", filelist_format_textinput_callback) def filelist_datapath_textinput_callback(_attr, _old, new): config.filelist_datapath = new filelist_datapath_textinput = TextInput(title="datapath:") filelist_datapath_textinput.on_change( "value", filelist_datapath_textinput_callback) def filelist_ranges_textareainput_callback(_attr, _old, new): ranges = [] for line in new.splitlines(): ranges.append(re.findall(r"\b\d+\b", line)) config.filelist_ranges = ranges filelist_ranges_textareainput = TextAreaInput(title="ranges:", rows=1) filelist_ranges_textareainput.on_change( "value", filelist_ranges_textareainput_callback) # ---- crystal def crystal_sample_textinput_callback(_attr, _old, new): config.crystal_sample = new crystal_sample_textinput = TextInput(title="Sample Name:", width=290) crystal_sample_textinput.on_change("value", crystal_sample_textinput_callback) def lambda_textinput_callback(_attr, _old, new): config.crystal_lambda = new lambda_textinput = TextInput(title="lambda:", width=100) lambda_textinput.on_change("value", lambda_textinput_callback) def ub_textareainput_callback(_attr, _old, new): config.crystal_UB = new ub_textareainput = TextAreaInput(title="UB matrix:", height=100) ub_textareainput.on_change("value", ub_textareainput_callback) def zeroOM_textinput_callback(_attr, _old, new): config.crystal_zeroOM = new zeroOM_textinput = TextInput(title="zeroOM:", width=100) zeroOM_textinput.on_change("value", zeroOM_textinput_callback) def zeroSTT_textinput_callback(_attr, _old, new): config.crystal_zeroSTT = new zeroSTT_textinput = TextInput(title="zeroSTT:", width=100) zeroSTT_textinput.on_change("value", zeroSTT_textinput_callback) def zeroCHI_textinput_callback(_attr, _old, new): config.crystal_zeroCHI = new zeroCHI_textinput = TextInput(title="zeroCHI:", width=100) zeroCHI_textinput.on_change("value", zeroCHI_textinput_callback) # ---- DataFactory def dataFactory_implementation_select_callback(_attr, _old, new): config.dataFactory_implementation = new dataFactory_implementation_select = Select( title="DataFactory implement.:", options=DATA_FACTORY_IMPLEMENTATION, width=145, ) dataFactory_implementation_select.on_change( "value", dataFactory_implementation_select_callback) def dataFactory_dist1_textinput_callback(_attr, _old, new): config.dataFactory_dist1 = new dataFactory_dist1_textinput = TextInput(title="dist1:", width=75) dataFactory_dist1_textinput.on_change( "value", dataFactory_dist1_textinput_callback) def dataFactory_dist2_textinput_callback(_attr, _old, new): config.dataFactory_dist2 = new dataFactory_dist2_textinput = TextInput(title="dist2:", width=75) dataFactory_dist2_textinput.on_change( "value", dataFactory_dist2_textinput_callback) def dataFactory_dist3_textinput_callback(_attr, _old, new): config.dataFactory_dist3 = new dataFactory_dist3_textinput = TextInput(title="dist3:", width=75) dataFactory_dist3_textinput.on_change( "value", dataFactory_dist3_textinput_callback) # ---- BackgroundProcessor # ---- DetectorEfficency # ---- ReflectionPrinter def reflectionPrinter_format_select_callback(_attr, _old, new): config.reflectionPrinter_format = new reflectionPrinter_format_select = Select( title="ReflectionPrinter format:", options=REFLECTION_PRINTER_FORMATS, width=145, ) reflectionPrinter_format_select.on_change( "value", reflectionPrinter_format_select_callback) # Adaptive Peak Detection (adaptivemaxcog) # ---- threshold def threshold_textinput_callback(_attr, _old, new): config.threshold = new threshold_textinput = TextInput(title="Threshold:", width=145) threshold_textinput.on_change("value", threshold_textinput_callback) # ---- shell def shell_textinput_callback(_attr, _old, new): config.shell = new shell_textinput = TextInput(title="Shell:", width=145) shell_textinput.on_change("value", shell_textinput_callback) # ---- steepness def steepness_textinput_callback(_attr, _old, new): config.steepness = new steepness_textinput = TextInput(title="Steepness:", width=145) steepness_textinput.on_change("value", steepness_textinput_callback) # ---- duplicateDistance def duplicateDistance_textinput_callback(_attr, _old, new): config.duplicateDistance = new duplicateDistance_textinput = TextInput(title="Duplicate Distance:", width=145) duplicateDistance_textinput.on_change( "value", duplicateDistance_textinput_callback) # ---- maxequal def maxequal_textinput_callback(_attr, _old, new): config.maxequal = new maxequal_textinput = TextInput(title="Max Equal:", width=145) maxequal_textinput.on_change("value", maxequal_textinput_callback) # ---- window def aps_window_textinput_callback(_attr, _old, new): config.aps_window = dict( zip(("x", "y", "z"), re.findall(r"\b\d+\b", new))) aps_window_textinput = TextInput(title="Window (x, y, z):", width=145) aps_window_textinput.on_change("value", aps_window_textinput_callback) # Adaptive Dynamic Mask Integration (adaptivedynamic) # ---- window def adm_window_textinput_callback(_attr, _old, new): config.adm_window = dict( zip(("x", "y", "z"), re.findall(r"\b\d+\b", new))) adm_window_textinput = TextInput(title="Window (x, y, z):", width=145) adm_window_textinput.on_change("value", adm_window_textinput_callback) # ---- border def border_textinput_callback(_attr, _old, new): config.border = dict(zip(("x", "y", "z"), re.findall(r"\b\d+\b", new))) border_textinput = TextInput(title="Border (x, y, z):", width=145) border_textinput.on_change("value", border_textinput_callback) # ---- minWindow def minWindow_textinput_callback(_attr, _old, new): config.minWindow = dict( zip(("x", "y", "z"), re.findall(r"\b\d+\b", new))) minWindow_textinput = TextInput(title="Min Window (x, y, z):", width=145) minWindow_textinput.on_change("value", minWindow_textinput_callback) # ---- reflectionFile def reflectionFile_textinput_callback(_attr, _old, new): config.reflectionFile = new reflectionFile_textinput = TextInput(title="Reflection File:", width=145) reflectionFile_textinput.on_change("value", reflectionFile_textinput_callback) # ---- targetMonitor def targetMonitor_textinput_callback(_attr, _old, new): config.targetMonitor = new targetMonitor_textinput = TextInput(title="Target Monitor:", width=145) targetMonitor_textinput.on_change("value", targetMonitor_textinput_callback) # ---- smoothSize def smoothSize_textinput_callback(_attr, _old, new): config.smoothSize = new smoothSize_textinput = TextInput(title="Smooth Size:", width=145) smoothSize_textinput.on_change("value", smoothSize_textinput_callback) # ---- loop def loop_textinput_callback(_attr, _old, new): config.loop = new loop_textinput = TextInput(title="Loop:", width=145) loop_textinput.on_change("value", loop_textinput_callback) # ---- minPeakCount def minPeakCount_textinput_callback(_attr, _old, new): config.minPeakCount = new minPeakCount_textinput = TextInput(title="Min Peak Count:", width=145) minPeakCount_textinput.on_change("value", minPeakCount_textinput_callback) # ---- displacementCurve def displacementCurve_textinput_callback(_attr, _old, new): maps = [] for line in new.splitlines(): maps.append(re.findall(r"\d+(?:\.\d+)?", line)) config.displacementCurve = maps displacementCurve_textinput = TextAreaInput( title="Displ. Curve (2θ, x, y):", width=145, height=100) displacementCurve_textinput.on_change( "value", displacementCurve_textinput_callback) def algorithm_tabs_callback(_attr, _old, new): if new == 0: config.algorithm = "adaptivemaxcog" else: config.algorithm = "adaptivedynamic" algorithm_params = Tabs(tabs=[ Panel( child=column( row(threshold_textinput, shell_textinput, steepness_textinput), row(duplicateDistance_textinput, maxequal_textinput, aps_window_textinput), ), title="Peak Search", ), Panel( child=column( row(adm_window_textinput, border_textinput, minWindow_textinput), row(reflectionFile_textinput, targetMonitor_textinput, smoothSize_textinput), row(loop_textinput, minPeakCount_textinput, displacementCurve_textinput), ), title="Dynamic Integration", ), ]) algorithm_params.on_change("active", algorithm_tabs_callback) def process_button_callback(): with tempfile.TemporaryDirectory() as temp_dir: temp_file = temp_dir + "/config.xml" config.save_as(temp_file) pyzebra.anatric(temp_file, anatric_path=doc.anatric_path, cwd=temp_dir) with open(os.path.join(temp_dir, config.logfile)) as f_log: output_log.value = f_log.read() with open(os.path.join(temp_dir, config.reflectionPrinter_file)) as f_res: output_res.value = f_res.read() process_button = Button(label="Process", button_type="primary") process_button.on_click(process_button_callback) output_log = TextAreaInput(title="Logfile output:", height=320, width=465, disabled=True) output_res = TextAreaInput(title="Result output:", height=320, width=465, disabled=True) output_config = TextAreaInput(title="Current config:", height=320, width=465, disabled=True) general_params_layout = column( row(column(Spacer(height=2), upload_div), upload_button), row(logfile_textinput, logfile_verbosity), row(filelist_type, filelist_format_textinput), filelist_datapath_textinput, filelist_ranges_textareainput, row(crystal_sample_textinput, lambda_textinput), ub_textareainput, row(zeroOM_textinput, zeroSTT_textinput, zeroCHI_textinput), row( dataFactory_implementation_select, dataFactory_dist1_textinput, dataFactory_dist2_textinput, dataFactory_dist3_textinput, ), row(reflectionPrinter_format_select), ) tab_layout = row( general_params_layout, column(output_config, algorithm_params, row(process_button)), column(output_log, output_res), ) async def update_config(): output_config.value = config.tostring() doc.add_periodic_callback(update_config, 1000) return Panel(child=tab_layout, title="hdf anatric")