From 3eef1622bf7391c37bc09693ae6013299ff25dc1 Mon Sep 17 00:00:00 2001 From: Ivan Usov Date: Wed, 13 May 2026 15:15:04 +0200 Subject: [PATCH] Add in-memory hdf append functionality Fix #71 --- pyzebra/app/panel_hdf_viewer.py | 87 +++++++++++++++++++-------------- 1 file changed, 49 insertions(+), 38 deletions(-) diff --git a/pyzebra/app/panel_hdf_viewer.py b/pyzebra/app/panel_hdf_viewer.py index f7226c9..97ed303 100644 --- a/pyzebra/app/panel_hdf_viewer.py +++ b/pyzebra/app/panel_hdf_viewer.py @@ -49,6 +49,7 @@ IMAGE_PLOT_H = int(IMAGE_H * 2.4) + 27 def create(): doc = curdoc() log = doc.logger + uploaded_files = {} dataset = [] ub_matrix_global = None @@ -81,15 +82,18 @@ def create(): ub_matrix.on_change("value", ub_matrix_callback) def file_select_update(): - proposal_path = proposal_textinput.name - if proposal_path: - 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 - else: - file_select.options = [] + if data_source.value == "proposal number": + proposal_path = proposal_textinput.name + if proposal_path: + 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 + else: + file_select.options = [] + else: # data_source.value == "uploaded files" + file_select.options = list(uploaded_files.keys()) doc.add_periodic_callback(file_select_update, 5000) @@ -99,47 +103,43 @@ def create(): proposal_textinput = doc.proposal_textinput proposal_textinput.on_change("name", proposal_textinput_callback) - def upload_hdf_button_callback(_attr, _old, new): - nonlocal dataset - try: - scan = pyzebra.read_detector_data(io.BytesIO(base64.b64decode(new)), ub_matrix_global) - except Exception as e: - log.exception(e) - return + def data_source_callback(_attr, _old, _new): + file_select_update() - dataset = [scan] - last_im_index = scan["counts"].shape[0] - 1 + data_source = Select( + title="Data Source:", + value="proposal number", + options=["proposal number", "uploaded files"], + width=210, + ) + data_source.on_change("value", data_source_callback) - index_spinner.value = 0 - index_spinner.high = last_im_index - if last_im_index == 0: - index_slider.disabled = True - else: - index_slider.disabled = False - index_slider.end = last_im_index - - zebra_mode = scan["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"]) - - _init_datatable() + def upload_hdf_button_callback(_attr, _old, _new): + nonlocal uploaded_files + for f_name, f_val in zip(upload_hdf_button.filename, upload_hdf_button.value): + uploaded_files[f_name] = io.BytesIO(base64.b64decode(f_val)) upload_hdf_div = Div(text="Upload .hdf file:", margin=(5, 5, 0, 5)) - upload_hdf_button = FileInput(accept=".hdf", width=200) - upload_hdf_button.on_change("value", upload_hdf_button_callback) + upload_hdf_button = FileInput(accept=".hdf", multiple=True, width=200) + upload_hdf_button.on_change("filename", upload_hdf_button_callback) def file_open_button_callback(): nonlocal dataset new_data = [] for f_path in file_select.value: + if data_source.value == "uploaded files": + f_name = f_path + f_path = uploaded_files[f_path] + try: - file_data = [pyzebra.read_detector_data(f_path, ub_matrix_global)] + file_data = [pyzebra.read_detector_data(f_path, ub_matrix=ub_matrix_global)] except Exception as e: log.exception(e) continue + if data_source.value == "uploaded files": + file_data[0]["original_filename"] = os.path.join("/uploaded_files", f_name) + pyzebra.normalize_dataset(file_data, monitor_spinner.value) if not new_data: # first file @@ -157,12 +157,19 @@ def create(): def file_append_button_callback(): file_data = [] for f_path in file_select.value: + if data_source.value == "uploaded files": + f_name = f_path + f_path = uploaded_files[f_path] + try: - file_data = [pyzebra.read_detector_data(f_path, ub_matrix_global)] + file_data = [pyzebra.read_detector_data(f_path, ub_matrix=ub_matrix_global)] except Exception as e: log.exception(e) continue + if data_source.value == "uploaded files": + file_data[0]["original_filename"] = os.path.join("/uploaded_files", f_name) + pyzebra.normalize_dataset(file_data, monitor_spinner.value) pyzebra.merge_datasets(dataset, file_data, log=log) @@ -885,7 +892,11 @@ def create(): ) import_layout = column( - upload_hdf_div, upload_hdf_button, file_select, row(file_open_button, file_append_button) + data_source, + upload_hdf_div, + upload_hdf_button, + file_select, + row(file_open_button, file_append_button), ) layout_image = column(grid([[proj_v, None], [plot, proj_h]]))