cubevis 1.0.19__tar.gz → 1.0.28__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {cubevis-1.0.19 → cubevis-1.0.28}/PKG-INFO +1 -1
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/__js__/bokeh-3.8/cubevisjs.min.js +3 -3
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/bokeh/__init__.py +1 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/bokeh/models/_bokeh_app_context.py +48 -1
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/bokeh/models/_showable.py +92 -60
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/bokeh/state/_initialize.py +7 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/private/apps/_createmask.py +3 -9
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/private/apps/_createregion.py +3 -9
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/private/apps/_interactiveclean.mustache +2 -1
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/private/apps/_interactiveclean.py +2 -1
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/private/apps/_interactivecleannotebook.mustache +24 -1
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/private/apps/_interactivecleannotebook.py +24 -1
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/toolbox/__init__.py +0 -1
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/toolbox/_cube.py +17 -11
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/toolbox/_interactive_clean_ui.mustache +22 -7
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/toolbox/_interactive_clean_ui.py +22 -7
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/utils/__init__.py +2 -1
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/utils/_jupyter.py +35 -12
- cubevis-1.0.28/cubevis/utils/_mutual_exclusion.py +117 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/pyproject.toml +1 -1
- {cubevis-1.0.19 → cubevis-1.0.28}/LICENSE +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/README.rst +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/LICENSE.rst +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/__icons__/20px/fast-backward.svg +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/__icons__/20px/fast-forward.svg +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/__icons__/20px/step-backward.svg +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/__icons__/20px/step-forward.svg +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/__icons__/add-chan.png +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/__icons__/add-chan.svg +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/__icons__/add-cube.png +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/__icons__/add-cube.svg +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/__icons__/drag.png +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/__icons__/drag.svg +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/__icons__/mask-selected.png +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/__icons__/mask.png +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/__icons__/mask.svg +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/__icons__/new-layer-sm-selected.png +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/__icons__/new-layer-sm-selected.svg +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/__icons__/new-layer-sm.png +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/__icons__/new-layer-sm.svg +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/__icons__/reset.png +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/__icons__/reset.svg +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/__icons__/sub-chan.png +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/__icons__/sub-chan.svg +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/__icons__/sub-cube.png +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/__icons__/sub-cube.svg +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/__icons__/trash.png +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/__icons__/trash.svg +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/__icons__/trash_full.png +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/__icons__/trash_full.svg +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/__icons__/trash_full_raw.png +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/__icons__/zoom-to-fit.png +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/__icons__/zoom-to-fit.svg +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/__init__.py +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/__js__/bokeh-3.6/cubevisjs.min.js +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/__js__/bokeh-3.7/cubevisjs.min.js +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/__js__/casalib.min.js +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/bokeh/annotations/__init__.py +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/bokeh/annotations/_ev_poly_annotation.py +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/bokeh/components/__init__.py +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/bokeh/format/__init__.py +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/bokeh/format/_time_ticks.py +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/bokeh/format/_wcs_ticks.py +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/bokeh/models/__init__.py +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/bokeh/models/_edit_span.py +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/bokeh/models/_ev_text_input.py +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/bokeh/models/_shared_dict.py +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/bokeh/models/_tip.py +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/bokeh/models/_tip_button.py +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/bokeh/sources/__init__.py +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/bokeh/sources/_data_pipe.py +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/bokeh/sources/_image_data_source.py +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/bokeh/sources/_image_pipe.py +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/bokeh/sources/_spectra_data_source.py +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/bokeh/sources/_updatable_data_source.py +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/bokeh/state/__init__.py +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/bokeh/state/_current.py +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/bokeh/state/_javascript.py +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/bokeh/state/_palette.py +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/bokeh/state/_session.py +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/bokeh/state/js/bokeh-2.4.1.min.js +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/bokeh/state/js/bokeh-gl-2.4.1.min.js +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/bokeh/state/js/bokeh-tables-2.4.1.min.js +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/bokeh/state/js/bokeh-widgets-2.4.1.min.js +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/bokeh/state/js/casaguijs-v0.0.4.0-b2.4.min.js +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/bokeh/state/js/casaguijs-v0.0.5.0-b2.4.min.js +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/bokeh/state/js/casaguijs-v0.0.6.0-b2.4.min.js +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/bokeh/state/js/casalib-v0.0.1.min.js +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/bokeh/tools/__init__.py +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/bokeh/tools/_cbreset_tool.py +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/bokeh/tools/_drag_tool.py +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/bokeh/utils/__init__.py +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/bokeh/utils/_axes_labels.py +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/bokeh/utils/_svg_icon.py +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/data/__init__.py +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/data/casaimage/__init__.py +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/exe/__init__.py +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/exe/_context.py +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/exe/_mode.py +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/exe/_setting.py +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/exe/_task.py +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/private/_gclean.py +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/private/apps/__init__.py +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/private/apps/_plotants.py +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/private/apps/_plotbandpass.py +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/private/casashell/createmask.py +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/private/casashell/iclean.py +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/private/casatasks/__init__.py +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/private/casatasks/createmask.py +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/private/casatasks/createregion.py +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/private/casatasks/iclean.py +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/private/casatasks/iclean_notebook.py +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/readme.rst +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/remote/__init__.py +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/remote/_gclean.py +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/remote/_local.py +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/remote/_remote_kernel.py +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/toolbox/_app_context.py +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/toolbox/_interactiveclean_wrappers.py +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/toolbox/_region_list.py +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/utils/_ResourceManager.py +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/utils/_browser.py +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/utils/_contextmgrchain.py +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/utils/_conversion.py +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/utils/_copydoc.py +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/utils/_docenum.py +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/utils/_git.py +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/utils/_import_protected_module.py +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/utils/_logging.py +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/utils/_pkgs.py +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/utils/_regions.py +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/utils/_static.py +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/cubevis/utils/_tiles.py +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/tests/manual/alma-many-chan/alma-many-chan.py +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/tests/manual/basic-websockets-demo/client.html +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/tests/manual/basic-websockets-demo/client.py +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/tests/manual/basic-websockets-demo/server.py +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/tests/manual/createmask-demo/run-createmask.py +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/tests/manual/createregion-demo/run-createregion.py +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/tests/manual/cubemask-demo/image-slider-spectra-done-stats.py +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/tests/manual/cubemask-demo/image-slider-spectra-done.py +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/tests/manual/cubemask-demo/image-slider-spectra.py +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/tests/manual/cubemask-demo/image-slider.py +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/tests/manual/cubemask-demo/image.py +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/tests/manual/iclean-demo/iclean-demo.ipynb +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/tests/manual/iclean-demo/m100_interactive.py +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/tests/manual/iclean-demo/mask0-iclean.py +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/tests/manual/iclean-demo/run-gclean.py +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/tests/manual/iclean-demo/run-iclean-obj.py +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/tests/manual/iclean-demo/run-iclean.py +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/tests/manual/iclean-demo/vla-sim-jet-iclean.py +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/tests/manual/iclean-first-look/run-fl-cont.py +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/tests/manual/iclean-first-look/run-fl-line.py +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/tests/manual/iclean-outlier/run-iclean.py +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/tests/manual/iclean-outlier/test_outlier.txt +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/tests/manual/iclean-remote/iclean_remote_webserver.py +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/tests/manual/large-cube/run-largecube.py +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/tests/manual/svg-test.py +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/tests/manual/updatable-data-source/direct-plot.py +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/tests/manual/updatable-data-source/simple-update.py +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/tests/manual/updatable-data-source/updated-plot.py +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/tests/manual/uranus-demo/uranus-iclean.py +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/tests/manual/websocket-reconnect/client.html +0 -0
- {cubevis-1.0.19 → cubevis-1.0.28}/tests/manual/websocket-reconnect/server.py +0 -0
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
}
|
|
43
43
|
})
|
|
44
44
|
({
|
|
45
|
-
"07c9fde72b": function _(e,a,
|
|
45
|
+
"07c9fde72b": function _(e,t,a,o,c){o();const i=e("tslib"),n=e("f8eca7a5dd");c("DataPipe",n.DataPipe);c("activeDataPipes",e("5179d11e71").activeDataPipes);const p=e("2889e0dd45");c("ImagePipe",p.ImagePipe);const s=e("de65005924");c("ImageDataSource",s.ImageDataSource);const r=e("02e3c3e46c");c("SpectraDataSource",r.SpectraDataSource);const d=e("64b16deff9");c("UpdatableDataSource",d.UpdatableDataSource);const S=e("b6ae454f0d");c("WcsTicks",S.WcsTicks);const l=e("cb7d28d6b3");c("DragTool",l.DragTool);const D=e("9d3c34ff8e");c("CBResetTool",D.CBResetTool);const T=e("e3901fa9f2");c("serialize",T.serialize),c("deserialize",T.deserialize);const b=e("9f961622ce");c("TipButton",b.TipButton);const u=e("ca4c845905");c("Tip",u.Tip);const f=e("92e97078e3");c("Showable",f.Showable);const P=e("467d2716b0");c("BokehAppContext",P.BokehAppContext);const g=e("50a1e32f01");c("SharedDict",g.SharedDict);const h=e("b55081402e");c("EditSpan",h.EditSpan);const B=e("9144bfc7a5");c("EvTextInput",B.EvTextInput);const E=e("74e0abef8a");c("EvPolyAnnotation",E.EvPolyAnnotation);const I=i.__importStar(e("484bb85d20"));a.find=I;(0,e("@bokehjs/base").register_models)({DataPipe:n.DataPipe,ImagePipe:p.ImagePipe,ImageDataSource:s.ImageDataSource,SpectraDataSource:r.SpectraDataSource,UpdatableDataSource:d.UpdatableDataSource,WcsTicks:S.WcsTicks,DragTool:l.DragTool,CBResetTool:D.CBResetTool,Tip:u.Tip,TipButton:b.TipButton,SharedDict:g.SharedDict,Showable:f.Showable,BokehAppContext:P.BokehAppContext,EditSpan:h.EditSpan,EvTextInput:B.EvTextInput,EvPolyAnnotation:E.EvPolyAnnotation})},
|
|
46
46
|
"f8eca7a5dd": function _(e,s,t,i,n){var o;i();const a=e("@bokehjs/models/sources/data_source"),c=e("e3901fa9f2"),r=e("@bokehjs/core/util/callbacks"),l=e("5179d11e71");class d extends a.DataSource{constructor(e){super(e),this.send_queue={},this.connection_queue=[],this.pending={},this.incoming_callbacks={},this.session_id=casalib.object_id(this)}checkSessionConflict(){try{if("undefined"==typeof Storage)return console.warn("localStorage not available, skipping session conflict detection"),!0;const e=localStorage.getItem(this.session_storage_key);if(e){const s=JSON.parse(e);if(s.sessionId!==this.session_id&&Date.now()-s.timestamp<12e4){if(this.conflict_check){const e=`CubeVis DataPipe (${this.instance_key}) is already running in another browser window or tab.\n\nPlease close other instances and refresh this page, or\nclose this window to continue using the other instance.`;return alert(e),window.opener||1===window.history.length?window.close():window.location.href="about:blank",!1}console.group(`DataPipe ${this.instance_key} conflict detected in Jupyter context`),console.log("Current session ID:",this.session_id),console.log("Existing session ID:",s.sessionId),console.log("Existing timestamp:",new Date(s.timestamp).toISOString()),console.log("Age of existing session (ms):",Date.now()-s.timestamp),console.log("Address:",this.address),console.log("Instance key:",this.instance_key),console.log("Storage key:",this.session_storage_key),console.log("Existing data:",s),console.log("All localStorage keys:",Object.keys(localStorage).filter((e=>e.startsWith("cubevis_datapipe_")))),console.groupEnd()}}return this.updateSessionHeartbeat(),!0}catch(e){return console.warn("Session conflict detection failed:",e),!0}}updateSessionHeartbeat(){try{"undefined"!=typeof Storage&&localStorage.setItem(this.session_storage_key,JSON.stringify({sessionId:this.session_id,timestamp:Date.now(),instanceKey:this.instance_key}))}catch(e){console.warn("Session heartbeat update failed:",e)}}startHeartbeat(){this.heartbeat_interval=window.setInterval((()=>{this.updateSessionHeartbeat()}),3e4)}stopHeartbeat(){this.heartbeat_interval&&(clearInterval(this.heartbeat_interval),this.heartbeat_interval=void 0)}cleanupSession(){try{if("undefined"!=typeof Storage){const e=localStorage.getItem(this.session_storage_key);if(e){JSON.parse(e).sessionId===this.session_id&&localStorage.removeItem(this.session_storage_key)}}}catch(e){console.warn("Session cleanup failed:",e)}this.stopHeartbeat()}handleSessionConflictMessage(e){console.error("Session conflict detected by server:",e);let s="Session conflict detected by server.";"session_conflict"===e.type?s=e.error||s:"session_corruption"===e.type&&(s=`Session corruption detected.\nExpected: ${e.expected}\nReceived: ${e.received}`),alert(s+"\n\nThis window will be closed to prevent data corruption."),this.cleanupSession();const t=new CustomEvent("cubevis_session_conflict",{detail:{message:e,sessionId:this.session_id}});window.dispatchEvent(t),setTimeout((()=>{window.opener||1===window.history.length?window.close():window.location.href="about:blank"}),2e3)}generateInstanceKey(){const e=`${this.address[0]}_${this.address[1]}`;return`${this.instance_id}_${e}`}initialize(){if(super.initialize(),l.activeDataPipes.register(this),this.instance_key=this.generateInstanceKey(),this.session_storage_key=`cubevis_datapipe_${this.instance_key}`,!this.checkSessionConflict())return;let e=`ws://${this.address[0]}:${this.address[1]}`;console.log("datapipe url:",e);var s=void 0;document.shutdown_in_progress_=!1;var t=()=>{void 0!==this.websocket&&this.websocket.close(),this.websocket=new WebSocket(e),this.websocket.binaryType="arraybuffer",this.websocket.addEventListener("error",(e=>{console.log("error encountered:",e)})),this.websocket.onmessage=e=>{if("string"==typeof e.data||e.data instanceof String){let s=(0,c.deserialize)(e.data);if("id"in s&&"direction"in s&&"message"in s){let{id:e,message:t,direction:i}=s;if("error"===i&&("session_conflict"===e||e===this.session_id)&&t&&("session_conflict"===t.type||"session_corruption"===t.type||"close_duplicate"===t.action))return void this.handleSessionConflictMessage(t);if(void 0===t&&console.log("Error, event failure",s),"j2p"==i)if(e in this.pending){let{cb:i}=this.pending[e];if(delete this.pending[e],e in this.send_queue&&this.send_queue[e].length>0){let{cb:s,msg:t}=this.send_queue[e].shift();this.pending[e]={cb:s},this.websocket.send((0,c.serialize)(t))}void 0===t?console.log("DROPPING ERROR FOR NOW (maybe need error callbacks)",s):i(t)}else console.log("message received but could not find id");else if(e in this.incoming_callbacks){let s=this.incoming_callbacks[e](t);this.websocket.send((0,c.serialize)({id:e,direction:i,message:s,session:this.session_id}))}}else console.log(`datapipe received message without one of 'id', 'message' or 'direction': ${s}`)}else console.log("datapipe received binary data",e.data.byteLength,"bytes")},this.websocket.onopen=()=>{for(s?0==s.connected&&console.log(`connection reestablished at ${new Date}`):(this.websocket.send((0,c.serialize)({id:"initialize",direction:"j2p",session:this.session_id})),this.startHeartbeat()),s=new casalib.ReconnectState;this.connection_queue.length>0;){let e=this.connection_queue.shift();this.send.apply(e[0],e[1])}},this.websocket.onclose=()=>{if(s&&1==s.connected&&(console.log(`connection lost at ${new Date}`),s.connected=!1,!document.shutdown_in_progress_)){console.log(`connection lost at ${new Date}`);var e=s;function i(n){0==s.connected&&(console.log(`${n+1}\treconnection attempt ${new Date}`),t(),e.backoff(),e.retries>0?setTimeout(i,e.timeout,n+1):0==s.connected&&console.log(`aborting reconnection after ${n} attempts ${new Date}`))}i(0)}}};window.addEventListener("beforeunload",(()=>{this.cleanupSession()})),document.addEventListener("visibilitychange",(()=>{"hidden"===document.visibilityState?this.stopHeartbeat():"visible"===document.visibilityState&&(this.updateSessionHeartbeat(),this.startHeartbeat())})),t();(()=>{null!=this.init_script&&(0,r.execute)(this.init_script,this)})()}destroy(){l.activeDataPipes.unregister(this),super.destroy()}register(e,s){this.incoming_callbacks[e]=s}send(e,s,t,i=!1){let n={id:e,message:s,direction:"j2p",session:this.session_id};if(!this.websocket||e in this.pending)if(e in this.send_queue)if("boolean"==typeof i&&i&&this.send_queue[e].length>0)this.send_queue[e][0].msg=n,this.send_queue[e][0].cb=t;else if("function"==typeof i&&this.send_queue[e].length>0){let o=!1;for(const a of this.send_queue[e])i(a.msg.message)&&(a.msg=n,a.cb=t,o=!0);o||this.send_queue[e].push({cb:t,msg:n})}else this.send_queue[e].push({cb:t,msg:n});else this.send_queue[e]=[{cb:t,msg:n}];else if(this.websocket.readyState===WebSocket.CONNECTING)this.connection_queue.push([this,[e,s,t]]);else if(e in this.send_queue&&this.send_queue[e].length>0){this.send_queue[e].push({cb:t,msg:n});{let{cb:r,msg:l}=this.send_queue[e].shift();if(this.pending[e]={cb:r},this.websocket.readyState===WebSocket.OPEN)this.websocket.send((0,c.serialize)(l));else{let d=20,h=this;function u(){h.websocket.readyState===WebSocket.OPEN?h.websocket.send((0,c.serialize)(l)):(d-=1,d>0&&setTimeout(u,3e3))}setTimeout(u,3e3)}}}else if(this.websocket.readyState===WebSocket.OPEN)this.pending[e]={cb:t},this.websocket.send((0,c.serialize)(n));else{let g=20,b=this;function _(){b.websocket.readyState===WebSocket.OPEN?(b.pending[e]={cb:t},b.websocket.send((0,c.serialize)(n))):(g-=1,g>0&&setTimeout(_,3e3))}setTimeout(_,3e3)}}}t.DataPipe=d,o=d,d.__name__="DataPipe",d.__module__="cubevis.bokeh.sources._data_pipe",o.define((({Any:e,Tuple:s,String:t,Number:i,Bool:n})=>({init_script:[e,null],address:[s(t,i)],instance_id:[t],conflict_check:[n,!0]})))},
|
|
47
47
|
"e3901fa9f2": function _(e,r,s,i,o){i();const l=e("@bokehjs/base"),a=e("@bokehjs/core/resolvers"),t=e("@bokehjs/core/serialization/deserializer"),n=e("@bokehjs/core/serialization/serializer"),{deserialize:c}=new class{constructor(){this.resolver=new a.ModelResolver(l.default_resolver),this.deserializer=new t.Deserializer(this.resolver),this.deserialize=e=>{try{return this.deserializer.decode(JSON.parse(e))}catch(r){return console.group("deserialize error"),console.log(e),console.log(r),console.groupEnd(),{}}}}};s.deserialize=c;const{serialize:z}=new class{constructor(){this.serializer=new n.Serializer,this.serialize=e=>JSON.stringify(this.serializer.encode(e))}};s.serialize=z},
|
|
48
48
|
"5179d11e71": function _(a,e,n,c,t){c();const i=a("30b45c52a1");n.activeDataPipes=new i.ModelManager},
|
|
@@ -58,10 +58,10 @@
|
|
|
58
58
|
"9d3c34ff8e": function _(e,o,l,s,t){var c;s();const _=e("@bokehjs/models/tools/actions/reset_tool"),i=e("@bokehjs/styles/icons.css"),a=e("@bokehjs/core/util/callbacks");class n extends _.ResetToolView{doit(){const{precallback:e,postcallback:o}=this.model;null!=e&&(0,a.execute)(e,this.model),this.plot_view.reset(),null!=o&&(0,a.execute)(o,this.model)}}l.CBResetToolView=n,n.__name__="CBResetToolView";class r extends _.ResetTool{constructor(e){super(e),this.tool_name="CBReset",this.tool_icon=i.tool_icon_reset}}l.CBResetTool=r,c=r,r.__name__="CBResetTool",r.__module__="cubevis.bokeh.tools._cbreset_tool",c.prototype.default_view=n,c.define((({Any:e,Nullable:o})=>({precallback:[o(e),null],postcallback:[o(e),null]}))),c.register_alias("cbreset",(()=>new c))},
|
|
59
59
|
"9f961622ce": function _(e,t,i,o,s){var n;o();const l=e("@bokehjs/models/widgets/abstract_button"),c=e("@bokehjs/models/ui/tooltip"),d=e("@bokehjs/models/ui/icons/builtin_icon"),u=e("@bokehjs/core/build_views"),h=e("@bokehjs/core/bokeh_events"),r=e("@bokehjs/core/util/object");class a extends l.AbstractButtonView{constructor(){super(...arguments),this.isMouseInside=!1}click(){this.model.trigger_event(new h.ButtonClick),super.click()}*children(){yield*super.children(),yield this.tooltip}Show(){this.tooltip.model.setv({visible:!0,closable:!1})}unShow(){this.tooltip.model.setv({visible:!1,closable:!1})}async lazy_initialize(){const{hover_wait:e}=this.model;this.debouncedShow=casalib.debounce((()=>{this.isMouseInside&&this.Show()}),1e3*e),await super.lazy_initialize();const{tooltip:t}=this.model;this.tooltip=await(0,u.build_view)(t,{parent:this})}remove(){this.tooltip.remove(),super.remove()}render(){super.render(),this.el.addEventListener("mouseenter",(()=>{this.isMouseInside=!0,this.debouncedShow()})),this.el.addEventListener("mouseleave",(()=>{this.isMouseInside=!1,this.debouncedShow.cancel(),this.unShow()})),document.addEventListener("mousedown",(e=>{if(void 0===(0,r.dict)(this.model.js_event_callbacks).get(h.ButtonClick.prototype.event_name)){if(e.composedPath().includes(this.tooltip.el))return;this.debouncedShow.cancel(),this.unShow()}else this.isMouseInside=!1,this.debouncedShow.cancel(),this.unShow()})),window.addEventListener("blur",(()=>{this.debouncedShow.cancel(),this.unShow()}))}}i.TipButtonView=a,a.__name__="TipButtonView";class b extends l.AbstractButton{constructor(e){super(e)}on_click(e){this.on_event(h.ButtonClick,e)}}i.TipButton=b,n=b,b.__name__="TipButton",b.__module__="cubevis.bokeh.models._tip_button",n.prototype.default_view=a,n.define((({Ref:e,Number:t})=>({tooltip:[e(c.Tooltip)],hover_wait:[t,1.5]}))),n.override({label:"",icon:new d.BuiltinIcon({icon_name:"help",size:18}),button_type:"default"})},
|
|
60
60
|
"ca4c845905": function _(e,i,s,t,o){var l;t();const d=e("@bokehjs/models/layouts/layout_dom"),n=e("@bokehjs/models/ui/ui_element"),h=e("@bokehjs/models/ui/tooltip"),r=e("@bokehjs/core/dom"),a=e("@bokehjs/core/build_views");class c extends d.LayoutDOMView{constructor(){super(...arguments),this.isMouseInside=!1}stylesheets(){return[...super.stylesheets(),"*, *:before, *:after { box-sizing: border-box; } fieldset { border: 0px; margin: 0px; padding: 0px; }"]}Show(){this.tooltip.model.setv({visible:!0,closable:!1})}unShow(){this.tooltip.model.setv({visible:!1,closable:!1})}async lazy_initialize(){const{hover_wait:e}=this.model;this.debouncedShow=casalib.debounce((()=>{this.isMouseInside&&this.Show()}),1e3*e),await super.lazy_initialize(),await this.build_child_views();const{tooltip:i}=this.model;this.tooltip=await(0,a.build_view)(i,{parent:this})}remove(){this.tooltip.remove(),super.remove()}connect_signals(){super.connect_signals();const{child:e}=this.model.properties;this.on_change(e,(()=>this.update_children())),this.el.addEventListener("mouseenter",(e=>{this.mouseenter.emit(e)})),this.el.addEventListener("mouseleave",(e=>{this.mouseleave.emit(e)}))}*children(){yield*super.children(),yield this.tooltip}get child_models(){return[this.model.child]}render(){super.render(),this.el.addEventListener("mouseenter",(()=>{this.isMouseInside=!0,this.debouncedShow()})),this.el.addEventListener("mouseleave",(()=>{this.isMouseInside=!1,this.debouncedShow.cancel(),this.unShow()})),window.addEventListener("blur",(()=>{this.debouncedShow.cancel(),this.unShow()})),this.el.addEventListener("click",(()=>{this.debouncedShow.cancel(),this.unShow()}));const e=this.child_views.map((e=>e.el));this.fieldset_el=(0,r.fieldset)({},...e),this.shadow_el.appendChild(this.fieldset_el)}_update_children(){const e=this.child_views.map((e=>e.el));this.fieldset_el.append(...e)}}s.TipView=c,c.__name__="TipView";class u extends d.LayoutDOM{constructor(e){super(e)}}s.Tip=u,l=u,u.__name__="Tip",u.__module__="cubevis.bokeh.models._tip",l.prototype.default_view=c,l.define((({Ref:e,Number:i})=>({child:[e(n.UIElement)],tooltip:[e(h.Tooltip)],hover_wait:[i,1.5]})))},
|
|
61
|
-
"
|
|
61
|
+
"92e97078e3": function _(e,t,o,l,s){var i;l();const a=e("@bokehjs/models/layouts/layout_dom"),n=e("@bokehjs/models/ui/ui_element");class r extends a.LayoutDOMView{constructor(){super(...arguments),this._overlay_el=null}get child_models(){return null!=this.model.ui?[this.model.ui]:[]}initialize(){super.initialize(),this.el.setAttribute("data-lm-suppress-shortcuts","true")}async lazy_initialize(){await super.lazy_initialize()}connect_signals(){super.connect_signals(),this.connect(this.model.properties.disabled.change,(()=>{this._update_disabled_state()})),this.connect(this.model.properties.disabled_message.change,(()=>{this.model.disabled&&null!=this._overlay_el&&this._update_overlay_message()}))}_update_layout(){super._update_layout()}render(){super.render(),console.log("Showable render() - disabled:",this.model.disabled,"shadow_el:",null!=this.shadow_el);try{console.log("Colab environment check:"),console.log("window.location:",window.location),console.log("window.google:",window.google),console.log("Parent frame:",window.parent!==window),window.parent!==window&&(console.log("Running in iframe"),console.log("Parent location:",document.referrer))}catch(e){console.warn("An error occurred during Colab diagnostics")}console.log("Past Colab diagnostics..."),0===this.child_views.length&&null==this.model.ui&&(this.el.innerHTML='<div style="color: gray; padding: 10px; border: 1px dashed gray;">\n Showable: No UI element set\n </div>'),this._update_disabled_state()}after_layout(){super.after_layout(),console.log("Showable after_layout() - disabled:",this.model.disabled,"shadow_el:",null!=this.shadow_el),this.model.disabled&&this._update_disabled_state()}_intrinsic_display(){return super._intrinsic_display()}_update_disabled_state(){console.log("_update_disabled_state called, disabled:",this.model.disabled),this.model.disabled?(this._show_disabled_overlay(),this.el.style.filter="grayscale(50%)"):(this._hide_disabled_overlay(),this.el.style.filter="")}_disable_interactive_elements(){this.el.querySelectorAll(".bk-toolbar, .bk-toolbar-button").forEach((e=>{e.style.pointerEvents="none",e.style.opacity="0.5"}));this.el.querySelectorAll("canvas").forEach((e=>{e.style.pointerEvents="none"}));this.el.querySelectorAll("button, .bk-btn").forEach((e=>{e.disabled=!0}))}_enable_interactive_elements(){const e=this.shadow_el;if(!e)return;e.querySelectorAll(".bk-toolbar, .bk-toolbar-button").forEach((e=>{e.style.pointerEvents="",e.style.opacity=""}));e.querySelectorAll("canvas").forEach((e=>{e.style.pointerEvents=""}));e.querySelectorAll("button, .bk-btn").forEach((e=>{e.disabled=!1})),console.log("Interactive elements re-enabled")}_show_disabled_overlay(){if(console.log("_show_disabled_overlay called, _overlay_el exists:",null!=this._overlay_el),console.log("disabled_message:",this.model.disabled_message),null==this._overlay_el){console.log("Creating new overlay element");const e=this.shadow_el;if(console.log("Shadow root:",e),!e)return void console.error("No shadow root found!");const t=document.createElement("div");t.className="showable-disabled-message",t.style.cssText="\n background: white;\n padding: 30px 40px;\n border-radius: 10px;\n box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);\n text-align: center;\n border: 2px solid #4CAF50;\n max-width: 90%;\n word-wrap: break-word;\n pointer-events: auto;\n cursor: default;\n ",t.innerHTML=`\n <div style="font-size: 24px; font-weight: bold; color: #4CAF50; margin-bottom: 10px;">\n ${this.model.disabled_message}\n </div>\n `,console.log("Message box created"),this._overlay_el=document.createElement("div"),this._overlay_el.appendChild(t),this._overlay_el.style.setProperty("position","absolute","important"),this._overlay_el.style.setProperty("top","0","important"),this._overlay_el.style.setProperty("left","0","important"),this._overlay_el.style.setProperty("right","0","important"),this._overlay_el.style.setProperty("bottom","0","important"),this._overlay_el.style.setProperty("width","100%","important"),this._overlay_el.style.setProperty("height","100%","important"),this._overlay_el.style.setProperty("background-color","rgba(220, 220, 220, 0.85)","important"),this._overlay_el.style.setProperty("display","flex","important"),this._overlay_el.style.setProperty("justify-content","center","important"),this._overlay_el.style.setProperty("align-items","center","important"),this._overlay_el.style.setProperty("z-index","2147483647","important"),this._overlay_el.style.setProperty("pointer-events","auto","important"),this._overlay_el.style.setProperty("cursor","not-allowed","important"),console.log("Overlay element styles set");const o=e.firstElementChild;o&&(o.style.position="relative",console.log("Set content container to relative positioning")),e.appendChild(this._overlay_el),console.log("Overlay appended to shadow root"),setTimeout((()=>{const e=this._overlay_el.getBoundingClientRect(),o=t.getBoundingClientRect();console.log("Overlay bounding rect:",{width:e.width,height:e.height,top:e.top,left:e.left}),console.log("Message box bounding rect:",{width:o.width,height:o.height})}),100),this._disable_interactive_elements();["mousedown","mouseup","click","dblclick","contextmenu","touchstart","touchmove","touchend","keydown","keyup","keypress","pointerdown","pointerup","pointermove","dragstart","drag","dragend"].forEach((e=>{this._overlay_el.addEventListener(e,(e=>{if(e.target!==t&&!t.contains(e.target))return e.stopPropagation(),e.preventDefault(),e.stopImmediatePropagation(),!1}),{capture:!0,passive:!1})})),this._overlay_el.addEventListener("wheel",(t=>{let o=e.host.parentElement;for(;o;){const e=window.getComputedStyle(o).overflow,t=window.getComputedStyle(o).overflowY;if("auto"===e||"scroll"===e||"auto"===t||"scroll"===t)break;o=o.parentElement}o&&(o.scrollTop+=t.deltaY,o.scrollLeft+=t.deltaX),t.stopPropagation(),t.preventDefault()}),{capture:!0,passive:!1})}else console.log("Overlay already exists, showing it"),this._overlay_el.style.display="flex";console.log("_show_disabled_overlay complete")}_update_overlay_message(){if(null!=this._overlay_el){const e=this._overlay_el.querySelector(".showable-disabled-message");e&&(e.innerHTML=`\n <div style="font-size: 24px; font-weight: bold; color: #4CAF50; margin-bottom: 10px;">\n ${this.model.disabled_message}\n </div>\n <div style="font-size: 14px; color: #666;">\n You can now close this GUI or continue working in your notebook\n </div>\n `)}}_hide_disabled_overlay(){null!=this._overlay_el&&(this._overlay_el.style.display="none",this._enable_interactive_elements())}remove(){null!=this._overlay_el&&(this._overlay_el.remove(),this._overlay_el=null),super.remove()}}o.ShowableView=r,r.__name__="ShowableView";class d extends a.LayoutDOM{constructor(e){super(e)}}o.Showable=d,i=d,d.__name__="Showable",d.__module__="cubevis.bokeh.models._showable",i.prototype.default_view=r,i.define((({Ref:e,String:t})=>({ui:[e(n.UIElement)],disabled_message:[t,"Interaction Complete \u2713"]})))},
|
|
62
62
|
"467d2716b0": function _(e,i,s,t,o){var n;t();const p=e("@bokehjs/models/layouts/layout_dom"),a=e("@bokehjs/models/ui/ui_element");class l extends p.LayoutDOMView{get child_models(){return null!=this.model.ui?[this.model.ui]:[]}initialize(){super.initialize(),this.el&&(this.el.style.padding="0",this.el.style.margin="0",this.el.style.border="none",this.el.style.background="transparent",this.el.style.display="contents"),this.connect(this.model.properties.app_state.change,(()=>{const e=window.cubevisAppSession;(null==e?void 0:e.applications[this.model.app_id])&&(e.applications[this.model.app_id].state=this.model.app_state)}))}}s.BokehAppContextView=l,l.__name__="BokehAppContextView";class d extends p.LayoutDOM{constructor(e){super(e)}initialize(){super.initialize(),window.cubevisAppSession||(window.cubevisAppSession={sessionId:this.session_id,applications:{}},console.log(`Initialized Bokeh session: ${this.session_id}`));const e=window.cubevisAppSession;e.applications[this.app_id]||(e.applications[this.app_id]={appId:this.app_id,state:this.app_state,createdAt:(new Date).toISOString()},console.log(`Registered application: ${this.app_id}`))}}s.BokehAppContext=d,n=d,d.__name__="BokehAppContext",d.__module__="cubevis.bokeh.models._bokeh_app_context",n.prototype.default_view=l,n.define((({Ref:e,Nullable:i,Dict:s,String:t,Unknown:o})=>({ui:[i(e(a.UIElement)),null],app_id:[t,""],session_id:[t,""],app_state:[s(o),{}]})))},
|
|
63
63
|
"50a1e32f01": function _(e,s,i,n,t){var a;n();const c=e("@bokehjs/core/view"),o=e("@bokehjs/model");class _ extends c.View{initialize(){super.initialize()}connect_signals(){super.connect_signals();const{values:e}=this.model.properties;this.on_change(e,(()=>this.values_changed()))}values_changed(){}}i.SharedDictView=_,_.__name__="SharedDictView";class d extends o.Model{constructor(e){super(e)}}i.SharedDict=d,a=d,d.__name__="SharedDict",d.__module__="cubevis.bokeh.models._shared_dict",a.prototype.default_view=_,a.define((({Dict:e,Unknown:s})=>({values:[e(s),{}]})))},
|
|
64
64
|
"b55081402e": function _(e,n,t,_,s){var a;_();const o=e("@bokehjs/models/annotations/span"),p=e("@bokehjs/core/bokeh_events");class r extends o.SpanView{on_pan_start(e){const n=super.on_pan_start(e);return this.model.trigger_event(new p.LODStart),n}on_pan(e){super.on_pan(e)}on_pan_end(e){super.on_pan_end(e),this.model.trigger_event(new p.LODEnd)}}t.EditSpanView=r,r.__name__="EditSpanView";class d extends o.Span{constructor(e){super(e)}}t.EditSpan=d,a=d,d.__name__="EditSpan",d.__module__="cubevis.bokeh.models._edit_span",a.prototype.default_view=r},
|
|
65
65
|
"9144bfc7a5": function _(e,t,s,n,r){var i;n();const l=e("@bokehjs/models/widgets/text_input"),o=e("@bokehjs/core/dom"),u=e("@bokehjs/core/bokeh_events");class _ extends l.TextInputView{stylesheets(){return[...super.stylesheets(),new o.InlineStyleSheet(".bk-input-prefix { padding: 0 var(--padding-vertical); }")]}connect_signals(){super.connect_signals(),this.el.addEventListener("mouseenter",(e=>{this.model.trigger_event(new u.MouseEnter(e.screenX,e.screenY,e.x,e.y,{shift:e.shiftKey,ctrl:e.ctrlKey,alt:e.altKey}))})),this.el.addEventListener("mouseleave",(e=>{this.model.trigger_event(new u.MouseLeave(e.screenX,e.screenY,e.x,e.y,{shift:e.shiftKey,ctrl:e.ctrlKey,alt:e.altKey}))}))}render(){super.render()}}s.EvTextInputView=_,_.__name__="EvTextInputView";class c extends l.TextInput{constructor(e){super(e)}}s.EvTextInput=c,i=c,c.__name__="EvTextInput",c.__module__="cubevis.bokeh.models._ev_text_input",i.prototype.default_view=_},
|
|
66
66
|
"74e0abef8a": function _(e,t,n,s,o){var i;s();const r=e("@bokehjs/models/annotations/poly_annotation"),a=e("@bokehjs/core/bokeh_events");class _ extends r.PolyAnnotationView{on_enter(e){const{x_scale:t,y_scale:n}=this.plot_view.frame,s=new a.MouseEnter(e.sx,e.sy,t.invert(e.sx),n.invert(e.sy),{shift:e.modifiers.shift,ctrl:e.modifiers.ctrl,alt:e.modifiers.alt}),o=super.on_enter(e);return this.model.trigger_event(s),o}on_leave(e){const{x_scale:t,y_scale:n}=this.plot_view.frame,s=new a.MouseLeave(e.sx,e.sy,t.invert(e.sx),n.invert(e.sy),{shift:e.modifiers.shift,ctrl:e.modifiers.ctrl,alt:e.modifiers.alt});super.on_leave(e),this.model.trigger_event(s)}on_pan_start(e){const{x_scale:t,y_scale:n}=this.plot_view.frame,s=new a.PanStart(e.sx,e.sy,t.invert(e.sx),n.invert(e.sy),{shift:e.modifiers.shift,ctrl:e.modifiers.ctrl,alt:e.modifiers.alt}),o=super.on_pan_start(e);return this.model.trigger_event(s),o}on_pan_end(e){const{x_scale:t,y_scale:n}=this.plot_view.frame,s=new a.PanEnd(e.sx,e.sy,t.invert(e.sx),n.invert(e.sy),{shift:e.modifiers.shift,ctrl:e.modifiers.ctrl,alt:e.modifiers.alt});super.on_pan_end(e),this.model.trigger_event(s)}on_pan(e){super.on_pan(e);const t=new a.RangesUpdate(e.sx,e.sx+e.dx,e.sy,e.sy+e.dy);this.model.trigger_event(t)}}n.EvPolyAnnotationView=_,_.__name__="EvPolyAnnotationView";class l extends r.PolyAnnotation{constructor(e){super(e)}}n.EvPolyAnnotation=l,i=l,l.__name__="EvPolyAnnotation",l.__module__="cubevis.bokeh.annotations._ev_poly_annotation",i.prototype.default_view=_},
|
|
67
|
-
}, "07c9fde72b", {"index":"07c9fde72b","src/bokeh/sources/data_pipe":"f8eca7a5dd","src/bokeh/util/conversions":"e3901fa9f2","src/bokeh/sources/active_data_pipes":"5179d11e71","src/bokeh/util/model_manager":"30b45c52a1","src/bokeh/sources/image_pipe":"2889e0dd45","src/bokeh/sources/image_data_source":"de65005924","src/bokeh/sources/spectra_data_source":"02e3c3e46c","src/bokeh/sources/updatable_data_source":"64b16deff9","src/bokeh/format/wcs_ticks":"b6ae454f0d","src/bokeh/tools/drag_tool":"cb7d28d6b3","src/bokeh/events":"8fc7a9e935","src/bokeh/util/find":"484bb85d20","src/bokeh/tools/cbreset_tool":"9d3c34ff8e","src/bokeh/models/tip_button":"9f961622ce","src/bokeh/models/tip":"ca4c845905","src/bokeh/models/showable":"
|
|
67
|
+
}, "07c9fde72b", {"index":"07c9fde72b","src/bokeh/sources/data_pipe":"f8eca7a5dd","src/bokeh/util/conversions":"e3901fa9f2","src/bokeh/sources/active_data_pipes":"5179d11e71","src/bokeh/util/model_manager":"30b45c52a1","src/bokeh/sources/image_pipe":"2889e0dd45","src/bokeh/sources/image_data_source":"de65005924","src/bokeh/sources/spectra_data_source":"02e3c3e46c","src/bokeh/sources/updatable_data_source":"64b16deff9","src/bokeh/format/wcs_ticks":"b6ae454f0d","src/bokeh/tools/drag_tool":"cb7d28d6b3","src/bokeh/events":"8fc7a9e935","src/bokeh/util/find":"484bb85d20","src/bokeh/tools/cbreset_tool":"9d3c34ff8e","src/bokeh/models/tip_button":"9f961622ce","src/bokeh/models/tip":"ca4c845905","src/bokeh/models/showable":"92e97078e3","src/bokeh/models/bokeh_app_context":"467d2716b0","src/bokeh/models/shared_dict":"50a1e32f01","src/bokeh/models/edit_span":"b55081402e","src/bokeh/models/ev_text_input":"9144bfc7a5","src/bokeh/annotations/ev_poly_annotation":"74e0abef8a"}, {});});
|
|
@@ -2,7 +2,13 @@ import logging
|
|
|
2
2
|
from bokeh.core.properties import String, Dict, Any, Nullable, Instance
|
|
3
3
|
from bokeh.models.layouts import LayoutDOM
|
|
4
4
|
from bokeh.models.ui import UIElement
|
|
5
|
+
from bokeh.resources import CDN
|
|
6
|
+
from tempfile import TemporaryDirectory
|
|
5
7
|
from uuid import uuid4
|
|
8
|
+
import unicodedata
|
|
9
|
+
import webbrowser
|
|
10
|
+
import os
|
|
11
|
+
import re
|
|
6
12
|
|
|
7
13
|
logger = logging.getLogger(__name__)
|
|
8
14
|
|
|
@@ -29,9 +35,34 @@ class BokehAppContext(LayoutDOM):
|
|
|
29
35
|
cls._session_id = str(uuid4())
|
|
30
36
|
return cls._session_id
|
|
31
37
|
|
|
32
|
-
def
|
|
38
|
+
def _slugify(self, value, allow_unicode=False):
|
|
39
|
+
"""
|
|
40
|
+
Taken from https://github.com/django/django/blob/master/django/utils/text.py
|
|
41
|
+
Convert to ASCII if 'allow_unicode' is False. Convert spaces or repeated
|
|
42
|
+
dashes to single dashes. Remove characters that aren't alphanumerics,
|
|
43
|
+
underscores, or hyphens. Convert to lowercase. Also strip leading and
|
|
44
|
+
trailing whitespace, dashes, and underscores.
|
|
45
|
+
https://stackoverflow.com/a/295466/2903943
|
|
46
|
+
"""
|
|
47
|
+
value = str(value)
|
|
48
|
+
if allow_unicode:
|
|
49
|
+
value = unicodedata.normalize('NFKC', value)
|
|
50
|
+
else:
|
|
51
|
+
value = unicodedata.normalize('NFKD', value).encode('ascii', 'ignore').decode('ascii')
|
|
52
|
+
value = re.sub(r'[^\w\s-]', '', value.lower())
|
|
53
|
+
return re.sub(r'[-\s]+', '-', value).strip('-_')
|
|
54
|
+
|
|
55
|
+
def __init__( self, ui=None, title=str(uuid4( )), prefix=None, **kwargs ):
|
|
33
56
|
logger.debug(f"\tBokehAppContext::__init__(ui={type(ui).__name__ if ui else None}, {kwargs}): {id(self)}")
|
|
34
57
|
|
|
58
|
+
if prefix is None:
|
|
59
|
+
## create a prefix from the title
|
|
60
|
+
prefix = self._slugify(title)[:10]
|
|
61
|
+
|
|
62
|
+
self.__title = title
|
|
63
|
+
self.__workdir = TemporaryDirectory(prefix=prefix)
|
|
64
|
+
self.__htmlpath = os.path.join( self.__workdir.name, f'''{self._slugify(self.__title)}.html''' )
|
|
65
|
+
|
|
35
66
|
if ui is not None and 'ui' in kwargs:
|
|
36
67
|
raise RuntimeError( "'ui' supplied as both a positional parameter and a keyword parameter" )
|
|
37
68
|
|
|
@@ -61,3 +92,19 @@ class BokehAppContext(LayoutDOM):
|
|
|
61
92
|
current_state = dict(self.app_state)
|
|
62
93
|
current_state.update(state_updates)
|
|
63
94
|
self.app_state = current_state
|
|
95
|
+
|
|
96
|
+
def show( self ):
|
|
97
|
+
"""Always show plot in a new browser tab without changing output settings.
|
|
98
|
+
Jupyter display is handled by the Showable class. However, at some
|
|
99
|
+
point this function might need to support more than just independent
|
|
100
|
+
browser tab display.
|
|
101
|
+
"""
|
|
102
|
+
logger.debug(f"\tBokehAppContext::show( ): {id(self)}")
|
|
103
|
+
|
|
104
|
+
from bokeh.plotting import save
|
|
105
|
+
|
|
106
|
+
# Save the plot
|
|
107
|
+
save( self, filename=self.__htmlpath, resources=CDN, title=self.__title)
|
|
108
|
+
|
|
109
|
+
# Open in browser
|
|
110
|
+
webbrowser.open('file://' + os.path.abspath(self.__htmlpath))
|
|
@@ -5,6 +5,7 @@ from bokeh.core.properties import Instance, String
|
|
|
5
5
|
|
|
6
6
|
from bokeh.io import curdoc
|
|
7
7
|
from .. import BokehInit
|
|
8
|
+
from ...utils import is_colab
|
|
8
9
|
|
|
9
10
|
logger = logging.getLogger(__name__)
|
|
10
11
|
|
|
@@ -48,39 +49,11 @@ class Showable(LayoutDOM,BokehInit):
|
|
|
48
49
|
# It might be a regular function or static method without explicit 'self'/'cls'
|
|
49
50
|
return None
|
|
50
51
|
|
|
51
|
-
# Detect Bokeh usage mode (i.e. self.__class__._usage_mode unset)
|
|
52
|
-
calling_mode = None
|
|
53
|
-
if self.__class__._usage_mode is None:
|
|
54
|
-
self.__class__._usage_mode = "bokeh"
|
|
55
|
-
calling_mode = "bokeh"
|
|
56
|
-
|
|
57
52
|
# Allow None (detaching from document) without any further checking
|
|
58
53
|
if doc is None:
|
|
59
54
|
self._document = None
|
|
60
55
|
return
|
|
61
56
|
|
|
62
|
-
if calling_mode is None:
|
|
63
|
-
import inspect
|
|
64
|
-
stack_frames = inspect.stack( )
|
|
65
|
-
try:
|
|
66
|
-
for frame in stack_frames[1:]:
|
|
67
|
-
if frame.function == '_repr_mimebundle_' or frame.function == 'show':
|
|
68
|
-
if get_caller_class_name(frame.frame) == self.__class__.__name__:
|
|
69
|
-
calling_mode = "custom"
|
|
70
|
-
break
|
|
71
|
-
finally:
|
|
72
|
-
# Essential to delete stack frames to avoid reference cycles
|
|
73
|
-
del stack_frames
|
|
74
|
-
|
|
75
|
-
if calling_mode != self.__class__._usage_mode:
|
|
76
|
-
### THIS CATCHES: using Bokeh show after Showable display methods
|
|
77
|
-
### using Showable.show after Bokeh show
|
|
78
|
-
raise RuntimeError(
|
|
79
|
-
f"\n{'='*70}\n" +
|
|
80
|
-
( (self._usage_error['custom'] % self.__class__.__name__) if calling_mode == 'custom' else
|
|
81
|
-
(self._usage_error['bokeh'] % 'bokeh.plotting.show') ) +
|
|
82
|
-
f"\n{'='*70}\n" )
|
|
83
|
-
|
|
84
57
|
from bokeh.io.state import curstate
|
|
85
58
|
state = curstate( )
|
|
86
59
|
|
|
@@ -118,12 +91,23 @@ class Showable(LayoutDOM,BokehInit):
|
|
|
118
91
|
self._start_backend()
|
|
119
92
|
self._backend_started = True
|
|
120
93
|
|
|
94
|
+
def to_serializable(self, *args, **kwargs):
|
|
95
|
+
if self._display_context:
|
|
96
|
+
self._display_context.on_to_serializable( )
|
|
97
|
+
|
|
98
|
+
# Call parent's to_serializable
|
|
99
|
+
return super().to_serializable(*args, **kwargs)
|
|
100
|
+
|
|
121
101
|
def __init__( self, ui_element=None, backend_func=None,
|
|
122
102
|
result_retrieval=None,
|
|
123
103
|
notebook_width=1200, notebook_height=800,
|
|
124
|
-
notebook_sizing='fixed',
|
|
104
|
+
notebook_sizing='fixed',
|
|
105
|
+
display_context=None,
|
|
106
|
+
**kwargs ):
|
|
125
107
|
logger.debug(f"\tShowable::__init__(ui_element={type(ui_element).__name__ if ui_element else None}, {kwargs}): {id(self)}")
|
|
126
108
|
|
|
109
|
+
self._display_context = display_context
|
|
110
|
+
|
|
127
111
|
# Set default sizing if not provided
|
|
128
112
|
sizing_params = {'sizing_mode', 'width', 'height'}
|
|
129
113
|
provided_sizing_params = set(kwargs.keys()) & sizing_params
|
|
@@ -147,18 +131,6 @@ class Showable(LayoutDOM,BokehInit):
|
|
|
147
131
|
'browser': { 'mode': self.sizing_mode, 'width': self.width, 'height': self.height }
|
|
148
132
|
}
|
|
149
133
|
|
|
150
|
-
# Error messages included in RuntimeErrors
|
|
151
|
-
self._usage_error = {
|
|
152
|
-
'custom': "❌ Cannot use %s display methods:\n\n" \
|
|
153
|
-
"Reason: bokeh.plotting.show() has already been used for display\n" \
|
|
154
|
-
" of this class. Mixing display methods within a single notebook\n" \
|
|
155
|
-
" corrupts Bokeh display within the notebook\n",
|
|
156
|
-
'bokeh': "❌ Cannot use %s display method:\n\n" \
|
|
157
|
-
"Reason: Showable display methods have already been used for display\n" \
|
|
158
|
-
" of this class. Mixing display methods within a single notebook\n" \
|
|
159
|
-
" corrupts Bokeh display within the notebook\n" }
|
|
160
|
-
|
|
161
|
-
|
|
162
134
|
# Set the function to be called upon display
|
|
163
135
|
if backend_func is not None:
|
|
164
136
|
self._backend_startup_callback = backend_func
|
|
@@ -301,15 +273,11 @@ class Showable(LayoutDOM,BokehInit):
|
|
|
301
273
|
Common logic for generating HTML in notebook environments.
|
|
302
274
|
Returns the HTML string to display, or None if not in a notebook.
|
|
303
275
|
"""
|
|
304
|
-
from bokeh.embed import components
|
|
276
|
+
from bokeh.embed import components, json_item
|
|
305
277
|
from bokeh.io.state import curstate
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
raise RuntimeError(
|
|
310
|
-
f"\n{'='*70}\n" +
|
|
311
|
-
(self._usage_error['custom'] % self.__class__.__name__) +
|
|
312
|
-
f"\n{'='*70}\n" )
|
|
278
|
+
from bokeh.resources import CDN
|
|
279
|
+
import sys
|
|
280
|
+
import json as json_lib
|
|
313
281
|
|
|
314
282
|
state = curstate()
|
|
315
283
|
|
|
@@ -319,29 +287,93 @@ class Showable(LayoutDOM,BokehInit):
|
|
|
319
287
|
if self.ui is None:
|
|
320
288
|
return '<div style="color: red; padding: 10px; border: 1px solid red;">Showable object with no UI set</div>'
|
|
321
289
|
|
|
290
|
+
if self._display_context:
|
|
291
|
+
self._display_context.on_show()
|
|
292
|
+
|
|
322
293
|
if self._notebook_rendering:
|
|
323
294
|
# Return a lightweight reference instead of re-rendering the full GUI
|
|
324
295
|
return f'''
|
|
325
296
|
<div style="padding: 10px; background: #f0f8f0; border-left: 4px solid #4CAF50; margin: 5px 0;">
|
|
326
|
-
<strong
|
|
297
|
+
<strong>→ iclean GUI active above</strong>
|
|
327
298
|
<small style="color: #666; display: block; margin-top: 5px;">
|
|
328
299
|
Showable ID: {self.id[-8:]} | Backend: Running
|
|
329
300
|
</small>
|
|
330
301
|
</div>
|
|
331
302
|
'''
|
|
332
303
|
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
304
|
+
if is_colab( ):
|
|
305
|
+
# Get all JS paths from the existing function
|
|
306
|
+
# This returns paths in the correct order:
|
|
307
|
+
# [casalib, bokeh-core, bokeh-widgets, bokeh-tables, cubevisjs]
|
|
308
|
+
from cubevis.bokeh import get_bokeh_js_paths
|
|
309
|
+
js_paths = get_bokeh_js_paths( )
|
|
310
|
+
|
|
311
|
+
# Build script tags for all libraries in order
|
|
312
|
+
all_scripts = '\n'.join([
|
|
313
|
+
f'<script type="text/javascript" src="{url}"></script>'
|
|
314
|
+
for url in js_paths
|
|
315
|
+
])
|
|
316
|
+
|
|
317
|
+
# Use json_item approach which is more reliable in iframes
|
|
318
|
+
item = json_item(self, target=f"bokeh-{self.id}")
|
|
319
|
+
item_json = json_lib.dumps(item)
|
|
320
|
+
|
|
321
|
+
# Build complete HTML with proper loading sequence
|
|
322
|
+
# get_bokeh_js_paths() already returns libs in the correct order:
|
|
323
|
+
# 1. casalib (third-party libs for CustomJS)
|
|
324
|
+
# 2. bokeh-core
|
|
325
|
+
# 3. bokeh-widgets
|
|
326
|
+
# 4. bokeh-tables
|
|
327
|
+
# 5. cubevisjs (custom Bokeh models)
|
|
328
|
+
html = f'''
|
|
329
|
+
{f'<link href="{CDN.css_files[0]}" rel="stylesheet" type="text/css">' if CDN.css_files else ""}
|
|
330
|
+
<div id="bokeh-{self.id}" class="bk-root"></div>
|
|
331
|
+
{all_scripts}
|
|
332
|
+
<script type="text/javascript">
|
|
333
|
+
(function() {{
|
|
334
|
+
var item = {item_json};
|
|
335
|
+
|
|
336
|
+
function embedWhenReady() {{
|
|
337
|
+
// Check if all required libraries are loaded
|
|
338
|
+
if (typeof Bokeh !== 'undefined' && Bokeh.embed) {{
|
|
339
|
+
var target = document.getElementById("bokeh-{self.id}");
|
|
340
|
+
if (target) {{
|
|
341
|
+
try {{
|
|
342
|
+
Bokeh.embed.embed_item(item);
|
|
343
|
+
console.log("Bokeh plot embedded successfully");
|
|
344
|
+
}} catch(e) {{
|
|
345
|
+
console.error("Error embedding Bokeh plot:", e);
|
|
346
|
+
}}
|
|
347
|
+
}} else {{
|
|
348
|
+
console.error("Target element not found");
|
|
349
|
+
setTimeout(embedWhenReady, 50);
|
|
350
|
+
}}
|
|
351
|
+
}} else {{
|
|
352
|
+
setTimeout(embedWhenReady, 50);
|
|
353
|
+
}}
|
|
354
|
+
}}
|
|
355
|
+
|
|
356
|
+
if (document.readyState === 'loading') {{
|
|
357
|
+
document.addEventListener('DOMContentLoaded', embedWhenReady);
|
|
358
|
+
}} else {{
|
|
359
|
+
embedWhenReady();
|
|
360
|
+
}}
|
|
361
|
+
}})();
|
|
362
|
+
</script>
|
|
363
|
+
'''
|
|
338
364
|
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
self._start_backend()
|
|
365
|
+
if start_backend:
|
|
366
|
+
self._start_backend()
|
|
342
367
|
|
|
343
|
-
|
|
344
|
-
|
|
368
|
+
self._notebook_rendering = html
|
|
369
|
+
return html
|
|
370
|
+
else:
|
|
371
|
+
# In Jupyter Lab/Classic, use components() as before
|
|
372
|
+
script, div = components(self)
|
|
373
|
+
if start_backend:
|
|
374
|
+
self._start_backend()
|
|
375
|
+
self._notebook_rendering = f'{script}\n{div}'
|
|
376
|
+
return self._notebook_rendering
|
|
345
377
|
|
|
346
378
|
def _repr_mimebundle_(self, include=None, exclude=None):
|
|
347
379
|
"""
|
|
@@ -321,6 +321,13 @@ def order_bokeh_js():
|
|
|
321
321
|
resources.Resources.js_files = property(js_files)
|
|
322
322
|
return
|
|
323
323
|
|
|
324
|
+
#def get_bokeh_js_paths( ):
|
|
325
|
+
# modes = ['cdn','inline','server','server-dev','relative','relative-dev','absolute','absolute-dev']
|
|
326
|
+
# return { 'new': { mode: resources.Resources(mode=mode).js_files for mode in modes },
|
|
327
|
+
# 'old': { mode: resources.Resources(mode=mode)._old_js_files for mode in modes } }
|
|
328
|
+
def get_bokeh_js_paths( ):
|
|
329
|
+
return resources.Resources(mode='cdn').js_files
|
|
330
|
+
|
|
324
331
|
def get_jupyter_state( ):
|
|
325
332
|
"""Get the package-level Jupyter state"""
|
|
326
333
|
return _JUPYTER_STATE
|
|
@@ -35,7 +35,7 @@ from contextlib import asynccontextmanager
|
|
|
35
35
|
from bokeh.layouts import row, column
|
|
36
36
|
from bokeh.plotting import show
|
|
37
37
|
from bokeh.models import Button, CustomJS, TabPanel, Tabs, Spacer, Div
|
|
38
|
-
from cubevis.toolbox import CubeMask
|
|
38
|
+
from cubevis.toolbox import CubeMask
|
|
39
39
|
from cubevis.bokeh.utils import svg_icon
|
|
40
40
|
from bokeh.io import reset_output as reset_bokeh_output
|
|
41
41
|
from bokeh.io import output_notebook
|
|
@@ -149,12 +149,6 @@ class CreateMask:
|
|
|
149
149
|
if False a mask path which does not exist results in an exception
|
|
150
150
|
'''
|
|
151
151
|
|
|
152
|
-
###
|
|
153
|
-
### Create application context (which includes a temporary directory).
|
|
154
|
-
### This sets the title of the plot.
|
|
155
|
-
###
|
|
156
|
-
self._app_state = AppContext( 'Create Mask' )
|
|
157
|
-
|
|
158
152
|
###
|
|
159
153
|
### widgets shared across image tabs (masking multiple images)
|
|
160
154
|
###
|
|
@@ -382,7 +376,7 @@ class CreateMask:
|
|
|
382
376
|
app_state={ ### while the state dictionary itself
|
|
383
377
|
'name': 'create mask', ### is used, these particular element
|
|
384
378
|
'initialized': True ### are not currently used for anything
|
|
385
|
-
} )
|
|
379
|
+
}, title='Create Mask' )
|
|
386
380
|
|
|
387
381
|
###
|
|
388
382
|
### Keep track of which image is currently active in appstate.image_name (which is
|
|
@@ -411,7 +405,7 @@ class CreateMask:
|
|
|
411
405
|
### output_file(self._imagename+'_webpage/index.html')
|
|
412
406
|
pass
|
|
413
407
|
|
|
414
|
-
|
|
408
|
+
self._fig['layout'].show( )
|
|
415
409
|
|
|
416
410
|
def _asyncio_loop( self ):
|
|
417
411
|
'''return the event loop which can be mixed in with an existing event loop
|
|
@@ -35,7 +35,7 @@ from contextlib import asynccontextmanager
|
|
|
35
35
|
from bokeh.layouts import row, column, grid
|
|
36
36
|
from bokeh.plotting import show
|
|
37
37
|
from bokeh.models import Button, CustomJS, TabPanel, Tabs, Spacer, Div, Dropdown
|
|
38
|
-
from cubevis.toolbox import CubeMask,
|
|
38
|
+
from cubevis.toolbox import CubeMask, RegionList
|
|
39
39
|
from cubevis.bokeh.utils import svg_icon
|
|
40
40
|
from bokeh.io import curdoc
|
|
41
41
|
from bokeh.io import reset_output as reset_bokeh_output
|
|
@@ -141,12 +141,6 @@ class CreateRegion:
|
|
|
141
141
|
path(s) to CASA image for which interactive regions will be drawn
|
|
142
142
|
'''
|
|
143
143
|
|
|
144
|
-
###
|
|
145
|
-
### Create application context (which includes a temporary directory).
|
|
146
|
-
### This sets the title of the plot.
|
|
147
|
-
###
|
|
148
|
-
self._app_state = AppContext( 'Create Region' )
|
|
149
|
-
|
|
150
144
|
###
|
|
151
145
|
### widgets shared across image tabs (masking multiple images)
|
|
152
146
|
###
|
|
@@ -435,7 +429,7 @@ class CreateRegion:
|
|
|
435
429
|
app_state={ ### while the state dictionary itself
|
|
436
430
|
'name': 'create region', ### is used, these particular element
|
|
437
431
|
'initialized': True ### are not currently used for anything
|
|
438
|
-
} )
|
|
432
|
+
}, title='Create Region' )
|
|
439
433
|
|
|
440
434
|
###
|
|
441
435
|
### Keep track of which image is currently active in appstate.image_name (which is
|
|
@@ -464,7 +458,7 @@ class CreateRegion:
|
|
|
464
458
|
### output_file(self._imagename+'_webpage/index.html')
|
|
465
459
|
pass
|
|
466
460
|
|
|
467
|
-
|
|
461
|
+
self._fig['layout'].show( )
|
|
468
462
|
|
|
469
463
|
def _asyncio_loop( self ):
|
|
470
464
|
'''return the event loop which can be mixed in with an existing event loop
|
|
@@ -87,7 +87,8 @@ class InteractiveClean:
|
|
|
87
87
|
interpolation='nearest', ... )( ) )
|
|
88
88
|
'''
|
|
89
89
|
self._id = uuid4( )
|
|
90
|
+
self._ui.exclusion_mgr.set_mode("tab")
|
|
90
91
|
context = exe.Context( exe.Mode.SYNC )
|
|
91
92
|
bokeh_ui, exec_task = self._ui( context, self._id )
|
|
92
|
-
show(
|
|
93
|
+
bokeh_ui.show( )
|
|
93
94
|
return context.execute( exec_task, self._id )
|
|
@@ -1849,7 +1849,8 @@ class InteractiveClean:
|
|
|
1849
1849
|
interpolation='nearest', ... )( ) )
|
|
1850
1850
|
'''
|
|
1851
1851
|
self._id = uuid4( )
|
|
1852
|
+
self._ui.exclusion_mgr.set_mode("tab")
|
|
1852
1853
|
context = exe.Context( exe.Mode.SYNC )
|
|
1853
1854
|
bokeh_ui, exec_task = self._ui( context, self._id )
|
|
1854
|
-
show(
|
|
1855
|
+
bokeh_ui.show( )
|
|
1855
1856
|
return context.execute( exec_task, self._id )
|
|
@@ -43,6 +43,22 @@ from cubevis.utils import find_pkg, load_pkg
|
|
|
43
43
|
from cubevis.toolbox import InteractiveCleanUI
|
|
44
44
|
from cubevis import exe
|
|
45
45
|
|
|
46
|
+
class DisplayContext:
|
|
47
|
+
def __init__(self, exclusion_manager):
|
|
48
|
+
self.exclusion_manager = exclusion_manager
|
|
49
|
+
self._custom_show_called = False
|
|
50
|
+
|
|
51
|
+
def on_show(self):
|
|
52
|
+
self._custom_show_called = True
|
|
53
|
+
self.exclusion_manager.set_mode('cell-custom-show')
|
|
54
|
+
|
|
55
|
+
def on_to_serializable(self):
|
|
56
|
+
# Only set mode if custom_show hasn't been called
|
|
57
|
+
if not self._custom_show_called:
|
|
58
|
+
self.exclusion_manager.set_mode('cell-bokeh-show')
|
|
59
|
+
# If custom_show was called, we're already in 'cell-custom-show' mode
|
|
60
|
+
# and don't need to do anything
|
|
61
|
+
|
|
46
62
|
class InteractiveCleanNotebook:
|
|
47
63
|
r'''InteractiveCleanNotebook(...) implements interactive clean using Bokeh
|
|
48
64
|
{{docstring}}
|
|
@@ -107,6 +123,13 @@ class InteractiveCleanNotebook:
|
|
|
107
123
|
def startup( ):
|
|
108
124
|
self._future = context.execute( exec_task, self._id )
|
|
109
125
|
|
|
126
|
+
display_ctx = DisplayContext(self._ui.exclusion_mgr)
|
|
110
127
|
### name is used in summary output of the Showable
|
|
111
|
-
showed = Showable(
|
|
128
|
+
showed = Showable(
|
|
129
|
+
bokeh_ui,
|
|
130
|
+
startup,
|
|
131
|
+
self.get_future,
|
|
132
|
+
name="iclean-jpy",
|
|
133
|
+
display_context=display_ctx
|
|
134
|
+
)
|
|
112
135
|
return showed
|
|
@@ -42,6 +42,22 @@ from cubevis.utils import find_pkg, load_pkg
|
|
|
42
42
|
from cubevis.toolbox import InteractiveCleanUI
|
|
43
43
|
from cubevis import exe
|
|
44
44
|
|
|
45
|
+
class DisplayContext:
|
|
46
|
+
def __init__(self, exclusion_manager):
|
|
47
|
+
self.exclusion_manager = exclusion_manager
|
|
48
|
+
self._custom_show_called = False
|
|
49
|
+
|
|
50
|
+
def on_show(self):
|
|
51
|
+
self._custom_show_called = True
|
|
52
|
+
self.exclusion_manager.set_mode('cell-custom-show')
|
|
53
|
+
|
|
54
|
+
def on_to_serializable(self):
|
|
55
|
+
# Only set mode if custom_show hasn't been called
|
|
56
|
+
if not self._custom_show_called:
|
|
57
|
+
self.exclusion_manager.set_mode('cell-bokeh-show')
|
|
58
|
+
# If custom_show was called, we're already in 'cell-custom-show' mode
|
|
59
|
+
# and don't need to do anything
|
|
60
|
+
|
|
45
61
|
class InteractiveCleanNotebook:
|
|
46
62
|
r'''InteractiveCleanNotebook(...) implements interactive clean using Bokeh
|
|
47
63
|
tclean ---- Radio Interferometric Image Reconstruction
|
|
@@ -1869,6 +1885,13 @@ class InteractiveCleanNotebook:
|
|
|
1869
1885
|
def startup( ):
|
|
1870
1886
|
self._future = context.execute( exec_task, self._id )
|
|
1871
1887
|
|
|
1888
|
+
display_ctx = DisplayContext(self._ui.exclusion_mgr)
|
|
1872
1889
|
### name is used in summary output of the Showable
|
|
1873
|
-
showed = Showable(
|
|
1890
|
+
showed = Showable(
|
|
1891
|
+
bokeh_ui,
|
|
1892
|
+
startup,
|
|
1893
|
+
self.get_future,
|
|
1894
|
+
name="iclean-jpy",
|
|
1895
|
+
display_context=display_ctx
|
|
1896
|
+
)
|
|
1874
1897
|
return showed
|