diff --git a/pyzebra/app/__init__.py b/pyzebra/app/__init__.py index 4e2415e..4b0ee24 100644 --- a/pyzebra/app/__init__.py +++ b/pyzebra/app/__init__.py @@ -1 +1,2 @@ +from pyzebra.app.download_files import DownloadFiles from pyzebra.app.fit_controls import FitControls diff --git a/pyzebra/app/download_files.py b/pyzebra/app/download_files.py new file mode 100644 index 0000000..e99febb --- /dev/null +++ b/pyzebra/app/download_files.py @@ -0,0 +1,44 @@ +from bokeh.models import Button, ColumnDataSource, CustomJS + +js_code = """ +let j = 0; +for (let i = 0; i < source.data['name'].length; i++) { + if (source.data['content'][i] === "") continue; + + setTimeout(function() { + const blob = new Blob([source.data['content'][i]], {type: 'text/plain'}) + const link = document.createElement('a'); + document.body.appendChild(link); + const url = window.URL.createObjectURL(blob); + link.href = url; + link.download = source.data['name'][i] + source.data['ext'][i]; + link.click(); + window.URL.revokeObjectURL(url); + document.body.removeChild(link); + }, 100 * j) + + j++; +} +""" + + +class DownloadFiles: + def __init__(self, n_files): + source = ColumnDataSource( + data=dict(content=[""] * n_files, name=[""] * n_files, ext=[""] * n_files) + ) + self._source = source + + label = "Download File" if n_files == 1 else "Download Files" + button = Button(label=label, button_type="success", width=200) + button.js_on_click(CustomJS(args={"source": source}, code=js_code)) + self.button = button + + def set_contents(self, contents): + self._source.data.update(content=contents) + + def set_names(self, names): + self._source.data.update(name=names) + + def set_extensions(self, extensions): + self._source.data.update(ext=extensions) diff --git a/pyzebra/app/panel_ccl_compare.py b/pyzebra/app/panel_ccl_compare.py index 2f073bf..caab01f 100644 --- a/pyzebra/app/panel_ccl_compare.py +++ b/pyzebra/app/panel_ccl_compare.py @@ -11,7 +11,6 @@ from bokeh.models import ( CellEditor, CheckboxEditor, ColumnDataSource, - CustomJS, DataTable, Div, FileInput, @@ -31,33 +30,12 @@ from bokeh.plotting import figure import pyzebra from pyzebra import EXPORT_TARGETS, app -javaScript = """ -let j = 0; -for (let i = 0; i < js_data.data['fname'].length; i++) { - if (js_data.data['content'][i] === "") continue; - - setTimeout(function() { - const blob = new Blob([js_data.data['content'][i]], {type: 'text/plain'}) - const link = document.createElement('a'); - document.body.appendChild(link); - const url = window.URL.createObjectURL(blob); - link.href = url; - link.download = js_data.data['fname'][i] + js_data.data['ext'][i]; - link.click(); - window.URL.revokeObjectURL(url); - document.body.removeChild(link); - }, 100 * j) - - j++; -} -""" - def create(): doc = curdoc() dataset1 = [] dataset2 = [] - js_data = ColumnDataSource(data=dict(content=["", ""], fname=["", ""], ext=["", ""])) + app_dlfiles = app.DownloadFiles(n_files=2) def file_select_update_for_proposal(): proposal_path = proposal_textinput.name @@ -135,7 +113,7 @@ def create(): pyzebra.merge_duplicates(file_data) if ind == 0: - js_data.data.update(fname=[base, base]) + app_dlfiles.set_names([base, base]) new_data1 = file_data else: # ind = 1 new_data2 = file_data @@ -173,7 +151,7 @@ def create(): pyzebra.merge_duplicates(file_data) if ind == 0: - js_data.data.update(fname=[base, base]) + app_dlfiles.set_names([base, base]) new_data1 = file_data else: # ind = 1 new_data2 = file_data @@ -493,18 +471,18 @@ def create(): content = "" file_content.append(content) - js_data.data.update(content=file_content) + app_dlfiles.set_contents(file_content) export_preview_textinput.value = exported_content def export_target_select_callback(_attr, _old, new): - js_data.data.update(ext=EXPORT_TARGETS[new]) + app_dlfiles.set_extensions(EXPORT_TARGETS[new]) _update_preview() export_target_select = Select( title="Export target:", options=list(EXPORT_TARGETS.keys()), value="fullprof", width=80 ) export_target_select.on_change("value", export_target_select_callback) - js_data.data.update(ext=EXPORT_TARGETS[export_target_select.value]) + app_dlfiles.set_extensions(EXPORT_TARGETS[export_target_select.value]) def hkl_precision_select_callback(_attr, _old, _new): _update_preview() @@ -514,9 +492,6 @@ def create(): ) hkl_precision_select.on_change("value", hkl_precision_select_callback) - save_button = Button(label="Download File(s)", button_type="success", width=200) - save_button.js_on_click(CustomJS(args={"js_data": js_data}, code=javaScript)) - area_method_div = Div(text="Intensity:", margin=(5, 5, 0, 5)) fitpeak_controls = row( column( @@ -548,7 +523,9 @@ def create(): export_layout = column( export_preview_textinput, row( - export_target_select, hkl_precision_select, column(Spacer(height=19), row(save_button)) + export_target_select, + hkl_precision_select, + column(Spacer(height=19), row(app_dlfiles.button)), ), ) diff --git a/pyzebra/app/panel_ccl_integrate.py b/pyzebra/app/panel_ccl_integrate.py index 992b3bd..08a5e65 100644 --- a/pyzebra/app/panel_ccl_integrate.py +++ b/pyzebra/app/panel_ccl_integrate.py @@ -11,7 +11,6 @@ from bokeh.models import ( CellEditor, CheckboxEditor, ColumnDataSource, - CustomJS, DataTable, Div, FileInput, @@ -30,32 +29,11 @@ from bokeh.plotting import figure import pyzebra from pyzebra import EXPORT_TARGETS, app -javaScript = """ -let j = 0; -for (let i = 0; i < js_data.data['fname'].length; i++) { - if (js_data.data['content'][i] === "") continue; - - setTimeout(function() { - const blob = new Blob([js_data.data['content'][i]], {type: 'text/plain'}) - const link = document.createElement('a'); - document.body.appendChild(link); - const url = window.URL.createObjectURL(blob); - link.href = url; - link.download = js_data.data['fname'][i] + js_data.data['ext'][i]; - link.click(); - window.URL.revokeObjectURL(url); - document.body.removeChild(link); - }, 100 * j) - - j++; -} -""" - def create(): doc = curdoc() dataset = [] - js_data = ColumnDataSource(data=dict(content=["", ""], fname=["", ""], ext=["", ""])) + app_dlfiles = app.DownloadFiles(n_files=2) def file_select_update_for_proposal(): proposal_path = proposal_textinput.name @@ -131,7 +109,7 @@ def create(): if not new_data: # first file new_data = file_data pyzebra.merge_duplicates(new_data) - js_data.data.update(fname=[base, base]) + app_dlfiles.set_names([base, base]) else: pyzebra.merge_datasets(new_data, file_data) @@ -181,7 +159,7 @@ def create(): if not new_data: # first file new_data = file_data pyzebra.merge_duplicates(new_data) - js_data.data.update(fname=[base, base]) + app_dlfiles.set_names([base, base]) else: pyzebra.merge_datasets(new_data, file_data) @@ -455,18 +433,18 @@ def create(): content = "" file_content.append(content) - js_data.data.update(content=file_content) + app_dlfiles.set_contents(file_content) export_preview_textinput.value = exported_content def export_target_select_callback(_attr, _old, new): - js_data.data.update(ext=EXPORT_TARGETS[new]) + app_dlfiles.set_extensions(EXPORT_TARGETS[new]) _update_preview() export_target_select = Select( title="Export target:", options=list(EXPORT_TARGETS.keys()), value="fullprof", width=80 ) export_target_select.on_change("value", export_target_select_callback) - js_data.data.update(ext=EXPORT_TARGETS[export_target_select.value]) + app_dlfiles.set_extensions(EXPORT_TARGETS[export_target_select.value]) def hkl_precision_select_callback(_attr, _old, _new): _update_preview() @@ -476,9 +454,6 @@ def create(): ) hkl_precision_select.on_change("value", hkl_precision_select_callback) - save_button = Button(label="Download File(s)", button_type="success", width=200) - save_button.js_on_click(CustomJS(args={"js_data": js_data}, code=javaScript)) - area_method_div = Div(text="Intensity:", margin=(5, 5, 0, 5)) fitpeak_controls = row( column( @@ -515,7 +490,9 @@ def create(): export_layout = column( export_preview_textinput, row( - export_target_select, hkl_precision_select, column(Spacer(height=19), row(save_button)) + export_target_select, + hkl_precision_select, + column(Spacer(height=19), row(app_dlfiles.button)), ), ) diff --git a/pyzebra/app/panel_ccl_prepare.py b/pyzebra/app/panel_ccl_prepare.py index c8ad0c6..02de9bc 100644 --- a/pyzebra/app/panel_ccl_prepare.py +++ b/pyzebra/app/panel_ccl_prepare.py @@ -11,7 +11,6 @@ from bokeh.models import ( Button, CheckboxGroup, ColumnDataSource, - CustomJS, Div, FileInput, Legend, @@ -32,27 +31,7 @@ from bokeh.palettes import Dark2 from bokeh.plotting import figure import pyzebra - -javaScript = """ -let j = 0; -for (let i = 0; i < js_data.data['fname'].length; i++) { - if (js_data.data['content'][i] === "") continue; - - setTimeout(function() { - const blob = new Blob([js_data.data['content'][i]], {type: 'text/plain'}) - const link = document.createElement('a'); - document.body.appendChild(link); - const url = window.URL.createObjectURL(blob); - link.href = url; - link.download = js_data.data['fname'][i]; - link.click(); - window.URL.revokeObjectURL(url); - document.body.removeChild(link); - }, 100 * j) - - j++; -} -""" +from pyzebra import app ANG_CHUNK_DEFAULTS = {"2theta": 30, "gamma": 30, "omega": 30, "chi": 35, "phi": 35, "nu": 10} SORT_OPT_BI = ["2theta", "chi", "phi", "omega"] @@ -64,7 +43,7 @@ def create(): cif_data = {} params = {} res_files = {} - js_data = ColumnDataSource(data=dict(content=[""], fname=[""])) + app_dlfiles = app.DownloadFiles(n_files=1) anglim_div = Div(text="Angular min/max limits:", margin=(5, 5, 0, 5)) sttgamma_ti = TextInput(title="stt/gamma", width=100) @@ -315,14 +294,13 @@ def create(): sel_file = new[0] file_text = res_files[sel_file] preview_lists.value = file_text - js_data.data.update(content=[file_text], fname=[sel_file]) + app_dlfiles.set_contents([file_text]) + app_dlfiles.set_names([sel_file]) created_lists = MultiSelect(title="Created lists:", width=200, height=150) created_lists.on_change("value", created_lists_callback) preview_lists = TextAreaInput(title="Preview selected list:", width=600, height=150) - download_file = Button(label="Download file", button_type="success", width=200) - download_file.js_on_click(CustomJS(args={"js_data": js_data}, code=javaScript)) plot_list = Button(label="Plot selected list", button_type="primary", width=200, disabled=True) measured_data_div = Div(text="Measured data:") @@ -709,7 +687,7 @@ def create(): row(ranges_layout, Spacer(width=50), magstruct_layout), row(sorting_layout, Spacer(width=30), column(Spacer(height=18), go_button)), row(created_lists, preview_lists), - row(download_file, plot_list), + row(app_dlfiles.button, plot_list), ) hkl_layout = column( diff --git a/pyzebra/app/panel_param_study.py b/pyzebra/app/panel_param_study.py index 7b249e7..4b73550 100644 --- a/pyzebra/app/panel_param_study.py +++ b/pyzebra/app/panel_param_study.py @@ -12,7 +12,6 @@ from bokeh.models import ( CellEditor, CheckboxEditor, ColumnDataSource, - CustomJS, DataTable, Div, FileInput, @@ -38,27 +37,6 @@ from scipy import interpolate import pyzebra from pyzebra import app -javaScript = """ -let j = 0; -for (let i = 0; i < js_data.data['fname'].length; i++) { - if (js_data.data['content'][i] === "") continue; - - setTimeout(function() { - const blob = new Blob([js_data.data['content'][i]], {type: 'text/plain'}) - const link = document.createElement('a'); - document.body.appendChild(link); - const url = window.URL.createObjectURL(blob); - link.href = url; - link.download = js_data.data['fname'][i] + js_data.data['ext'][i]; - link.click(); - window.URL.revokeObjectURL(url); - document.body.removeChild(link); - }, 100 * j) - - j++; -} -""" - def color_palette(n_colors): palette = itertools.cycle(Category10[10]) @@ -68,7 +46,7 @@ def color_palette(n_colors): def create(): doc = curdoc() dataset = [] - js_data = ColumnDataSource(data=dict(content=[""], fname=[""], ext=[""])) + app_dlfiles = app.DownloadFiles(n_files=1) def file_select_update_for_proposal(): proposal_path = proposal_textinput.name @@ -138,7 +116,7 @@ def create(): if not new_data: # first file new_data = file_data pyzebra.merge_duplicates(new_data) - js_data.data.update(fname=[base]) + app_dlfiles.set_names([base]) else: pyzebra.merge_datasets(new_data, file_data) @@ -188,7 +166,7 @@ def create(): if not new_data: # first file new_data = file_data pyzebra.merge_duplicates(new_data) - js_data.data.update(fname=[base]) + app_dlfiles.set_names([base]) else: pyzebra.merge_datasets(new_data, file_data) @@ -628,12 +606,9 @@ def create(): content = "" file_content.append(content) - js_data.data.update(content=file_content) + app_dlfiles.set_contents(file_content) export_preview_textinput.value = exported_content - save_button = Button(label="Download File", button_type="success", width=220) - save_button.js_on_click(CustomJS(args={"js_data": js_data}, code=javaScript)) - area_method_div = Div(text="Intensity:", margin=(5, 5, 0, 5)) fitpeak_controls = row( column( @@ -667,7 +642,7 @@ def create(): append_upload_button, ) - export_layout = column(export_preview_textinput, row(save_button)) + export_layout = column(export_preview_textinput, row(app_dlfiles.button)) tab_layout = column( row(import_layout, scan_layout, plots, Spacer(width=30), export_layout),