cubevis 1.0.10__tar.gz → 1.0.14__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.
Potentially problematic release.
This version of cubevis might be problematic. Click here for more details.
- {cubevis-1.0.10 → cubevis-1.0.14}/PKG-INFO +1 -1
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/__js__/bokeh-3.8/cubevisjs.min.js +9 -8
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/bokeh/models/__init__.py +1 -0
- cubevis-1.0.14/cubevis/bokeh/models/_bokeh_app_context.py +63 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/bokeh/sources/_data_pipe.py +5 -4
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/toolbox/_interactive_clean_ui.mustache +15 -10
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/toolbox/_interactive_clean_ui.py +15 -10
- {cubevis-1.0.10 → cubevis-1.0.14}/pyproject.toml +2 -2
- cubevis-1.0.14/tests/manual/iclean-demo/iclean-demo.ipynb +246 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/LICENSE +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/README.rst +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/LICENSE.rst +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/__icons__/20px/fast-backward.svg +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/__icons__/20px/fast-forward.svg +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/__icons__/20px/step-backward.svg +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/__icons__/20px/step-forward.svg +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/__icons__/add-chan.png +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/__icons__/add-chan.svg +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/__icons__/add-cube.png +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/__icons__/add-cube.svg +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/__icons__/drag.png +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/__icons__/drag.svg +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/__icons__/mask-selected.png +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/__icons__/mask.png +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/__icons__/mask.svg +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/__icons__/new-layer-sm-selected.png +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/__icons__/new-layer-sm-selected.svg +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/__icons__/new-layer-sm.png +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/__icons__/new-layer-sm.svg +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/__icons__/reset.png +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/__icons__/reset.svg +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/__icons__/sub-chan.png +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/__icons__/sub-chan.svg +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/__icons__/sub-cube.png +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/__icons__/sub-cube.svg +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/__icons__/trash.png +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/__icons__/trash.svg +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/__icons__/trash_full.png +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/__icons__/trash_full.svg +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/__icons__/trash_full_raw.png +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/__icons__/zoom-to-fit.png +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/__icons__/zoom-to-fit.svg +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/__init__.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/__js__/bokeh-3.6/cubevisjs.min.js +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/__js__/bokeh-3.7/cubevisjs.min.js +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/__js__/casalib.min.js +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/bokeh/__init__.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/bokeh/annotations/__init__.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/bokeh/annotations/_ev_poly_annotation.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/bokeh/components/__init__.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/bokeh/format/__init__.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/bokeh/format/_time_ticks.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/bokeh/format/_wcs_ticks.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/bokeh/models/_edit_span.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/bokeh/models/_ev_text_input.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/bokeh/models/_shared_dict.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/bokeh/models/_showable.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/bokeh/models/_tip.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/bokeh/models/_tip_button.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/bokeh/sources/__init__.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/bokeh/sources/_image_data_source.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/bokeh/sources/_image_pipe.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/bokeh/sources/_spectra_data_source.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/bokeh/sources/_updatable_data_source.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/bokeh/state/__init__.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/bokeh/state/_current.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/bokeh/state/_initialize.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/bokeh/state/_javascript.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/bokeh/state/_palette.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/bokeh/state/_session.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/bokeh/state/js/bokeh-2.4.1.min.js +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/bokeh/state/js/bokeh-gl-2.4.1.min.js +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/bokeh/state/js/bokeh-tables-2.4.1.min.js +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/bokeh/state/js/bokeh-widgets-2.4.1.min.js +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/bokeh/state/js/casaguijs-v0.0.4.0-b2.4.min.js +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/bokeh/state/js/casaguijs-v0.0.5.0-b2.4.min.js +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/bokeh/state/js/casaguijs-v0.0.6.0-b2.4.min.js +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/bokeh/state/js/casalib-v0.0.1.min.js +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/bokeh/tools/__init__.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/bokeh/tools/_cbreset_tool.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/bokeh/tools/_drag_tool.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/bokeh/utils/__init__.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/bokeh/utils/_axes_labels.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/bokeh/utils/_svg_icon.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/data/__init__.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/data/casaimage/__init__.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/exe/__init__.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/exe/_context.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/exe/_mode.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/exe/_setting.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/exe/_task.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/private/_gclean.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/private/apps/__init__.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/private/apps/_createmask.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/private/apps/_createregion.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/private/apps/_interactiveclean.mustache +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/private/apps/_interactiveclean.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/private/apps/_interactivecleannotebook.mustache +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/private/apps/_interactivecleannotebook.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/private/apps/_plotants.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/private/apps/_plotbandpass.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/private/casashell/createmask.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/private/casashell/iclean.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/private/casatasks/__init__.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/private/casatasks/createmask.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/private/casatasks/createregion.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/private/casatasks/iclean.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/private/casatasks/iclean_notebook.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/readme.rst +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/remote/__init__.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/remote/_gclean.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/remote/_local.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/remote/_remote_kernel.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/toolbox/__init__.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/toolbox/_app_context.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/toolbox/_cube.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/toolbox/_interactiveclean_wrappers.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/toolbox/_region_list.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/utils/_ResourceManager.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/utils/__init__.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/utils/_browser.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/utils/_contextmgrchain.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/utils/_conversion.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/utils/_copydoc.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/utils/_docenum.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/utils/_git.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/utils/_import_protected_module.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/utils/_jupyter.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/utils/_logging.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/utils/_pkgs.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/utils/_regions.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/utils/_static.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/cubevis/utils/_tiles.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/tests/manual/alma-many-chan/alma-many-chan.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/tests/manual/basic-websockets-demo/client.html +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/tests/manual/basic-websockets-demo/client.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/tests/manual/basic-websockets-demo/server.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/tests/manual/createmask-demo/run-createmask.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/tests/manual/createregion-demo/run-createregion.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/tests/manual/cubemask-demo/image-slider-spectra-done-stats.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/tests/manual/cubemask-demo/image-slider-spectra-done.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/tests/manual/cubemask-demo/image-slider-spectra.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/tests/manual/cubemask-demo/image-slider.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/tests/manual/cubemask-demo/image.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/tests/manual/iclean-demo/m100_interactive.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/tests/manual/iclean-demo/mask0-iclean.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/tests/manual/iclean-demo/run-gclean.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/tests/manual/iclean-demo/run-iclean-obj.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/tests/manual/iclean-demo/run-iclean.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/tests/manual/iclean-demo/vla-sim-jet-iclean.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/tests/manual/iclean-first-look/run-fl-cont.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/tests/manual/iclean-first-look/run-fl-line.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/tests/manual/iclean-outlier/run-iclean.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/tests/manual/iclean-outlier/test_outlier.txt +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/tests/manual/iclean-remote/iclean_remote_webserver.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/tests/manual/large-cube/run-largecube.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/tests/manual/svg-test.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/tests/manual/updatable-data-source/direct-plot.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/tests/manual/updatable-data-source/simple-update.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/tests/manual/updatable-data-source/updated-plot.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/tests/manual/uranus-demo/uranus-iclean.py +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/tests/manual/websocket-reconnect/client.html +0 -0
- {cubevis-1.0.10 → cubevis-1.0.14}/tests/manual/websocket-reconnect/server.py +0 -0
|
@@ -42,23 +42,24 @@
|
|
|
42
42
|
}
|
|
43
43
|
})
|
|
44
44
|
({
|
|
45
|
-
"
|
|
46
|
-
"
|
|
45
|
+
"e2864cf297": function _(e,t,a,o,c){o();const n=e("tslib"),i=e("87aeec7876");c("DataPipe",i.DataPipe);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 S=e("64b16deff9");c("UpdatableDataSource",S.UpdatableDataSource);const d=e("b6ae454f0d");c("WcsTicks",d.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 u=e("9f961622ce");c("TipButton",u.TipButton);const b=e("ca4c845905");c("Tip",b.Tip);const f=e("5e5f767c53");c("Showable",f.Showable);const g=e("467d2716b0");c("BokehAppContext",g.BokehAppContext);const h=e("50a1e32f01");c("SharedDict",h.SharedDict);const B=e("b55081402e");c("EditSpan",B.EditSpan);const E=e("9144bfc7a5");c("EvTextInput",E.EvTextInput);const I=e("74e0abef8a");c("EvPolyAnnotation",I.EvPolyAnnotation);const P=n.__importStar(e("3684bcd721"));a.find=P;(0,e("@bokehjs/base").register_models)({DataPipe:i.DataPipe,ImagePipe:p.ImagePipe,ImageDataSource:s.ImageDataSource,SpectraDataSource:r.SpectraDataSource,UpdatableDataSource:S.UpdatableDataSource,WcsTicks:d.WcsTicks,DragTool:l.DragTool,CBResetTool:D.CBResetTool,Tip:b.Tip,TipButton:u.TipButton,SharedDict:h.SharedDict,Showable:f.Showable,BokehAppContext:g.BokehAppContext,EditSpan:B.EditSpan,EvTextInput:E.EvTextInput,EvPolyAnnotation:I.EvPolyAnnotation})},
|
|
46
|
+
"87aeec7876": function _(e,s,t,i,n){var o;i();const c=e("@bokehjs/models/sources/data_source"),a=e("e3901fa9f2"),l=e("@bokehjs/core/util/callbacks");class r extends c.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(),console.log("**** TypeScript initialize ****"),console.log("conflict_check value:",this.conflict_check),console.log("conflict_check type:",typeof this.conflict_check),console.log("All properties:",this.properties),console.log("*******************************"),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,a.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,a.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,a.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,a.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,l.execute)(this.init_script,this)})()}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 c of this.send_queue[e])i(c.msg.message)&&(c.msg=n,c.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:l,msg:r}=this.send_queue[e].shift();if(this.pending[e]={cb:l},this.websocket.readyState===WebSocket.OPEN)this.websocket.send((0,a.serialize)(r));else{let d=20,h=this;function u(){h.websocket.readyState===WebSocket.OPEN?h.websocket.send((0,a.serialize)(r)):(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,a.serialize)(n));else{let g=20,_=this;function b(){_.websocket.readyState===WebSocket.OPEN?(_.pending[e]={cb:t},_.websocket.send((0,a.serialize)(n))):(g-=1,g>0&&setTimeout(b,3e3))}setTimeout(b,3e3)}}}t.DataPipe=r,o=r,r.__name__="DataPipe",r.__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
|
-
"2889e0dd45": function _(i,e,s,t,n){var a;t();const o=i("@bokehjs/models/sources/column_data_source"),d=i("
|
|
48
|
+
"2889e0dd45": function _(i,e,s,t,n){var a;t();const o=i("@bokehjs/models/sources/column_data_source"),d=i("87aeec7876");class r extends d.DataPipe{constructor(i){super(i),this.position={},this._wcs=null}initialize(){super.initialize(),this.fits_header_json&&(this._wcs=new casalib.coordtxl.WCSTransform(new casalib.coordtxl.MapKeywordProvider(JSON.parse(this.fits_header_json))))}channel(i,e,s){this.position[s]={index:i};let t={action:"channel",index:i,id:s};super.send(this.dataid,t,(i=>{null!=this._histogram_source&&"hist"in i&&"top"in i.hist&&"bottom"in i.hist&&"left"in i.hist&&"right"in i.hist&&(this._histogram_source.data=i.hist),e(i)}))}spectrum(i,e,s,t=!1){let n={action:"spectrum",index:i,id:s};super.send(this.dataid,n,e,t)}adjust_colormap(i,e,s,t,n=!1){const a={action:"adjust-colormap",bounds:i,transfer:e,id:t};super.send(this.dataid,a,s,n)}refresh(i,e,s=[0,0]){let{index:t}=e in this.position?this.position[e]:{index:s};if(2===t.length){let s={action:"channel",index:t,id:e};super.send(this.dataid,s,i)}else if(3===t.length){let s={action:"spectrum",index:t,id:e};super.send(this.dataid,s,i)}}wcs(){return this._wcs}}s.ImagePipe=r,a=r,r.__name__="ImagePipe",r.__module__="cubevis.bokeh.sources._image_pipe",a.define((({Number:i,Nullable:e,String:s,Tuple:t,Ref:n})=>({dataid:[s],shape:[t(i,i,i,i)],fits_header_json:[e(s),null],_histogram_source:[e(n(o.ColumnDataSource)),null]})))},
|
|
49
49
|
"de65005924": function _(s,a,t,c,i){var o;c();const e=s("@bokehjs/models/sources/column_data_source"),n=s("@bokehjs/core/util/string"),u=s("2889e0dd45"),h=s("@bokehjs/core/util/callbacks");class r extends e.ColumnDataSource{constructor(s){super(s),this.imid=(0,n.uuid4)()}_mask_contour(s){const a=casalib.d3.contours().size(this.image_source.shape.slice(0,2)).thresholds([1])(s[0])[0].coordinates.map((s=>s.map((s=>s.reduce(((s,a)=>(s[0].push(a[0]),s[1].push(a[1]),s)),[[],[]])))));return{xs:[a.map((s=>s.map((s=>s[0]))))],ys:[a.map((s=>s.map((s=>s[1]))))]}}initialize(){if(super.initialize(),null!=this._mask_contour_source&&"msk"in this.data&&this.data.msk.length>0&&this.data.msk[0].length>0){const s=this.data.msk;this._mask_contour_source.data=this._mask_contour(s)}void 0===this.last_chan&&(this.last_chan=[this.cur_chan[0].valueOf(),this.cur_chan[1].valueOf()]);(()=>{null!=this.init_script&&(0,h.execute)(this.init_script,this)})()}channel(s,a=0,t){this.image_source.channel([a,s],(c=>{void 0!==c&&void 0!==c.chan||console.log("ImageDataSource ERROR ENCOUNTERED <1>",c),this.last_chan=[this.cur_chan[0].valueOf(),this.cur_chan[1].valueOf()],this.cur_chan=[a,s],null!=this._mask_contour_source&&"chan"in c&&"msk"in c.chan&&(c.msk_contour=this._mask_contour(c.chan.msk),this._mask_contour_source.data=c.msk_contour),t&&t(c),this.data=c.chan}),this.imid)}adjust_colormap(s,a,t){this.image_source.adjust_colormap(s,a,t,this.imid,!0)}signal_change(){this.change.emit()}refresh(s){this.image_source.refresh((a=>{void 0!==a&&void 0!==a.chan||console.log("ImageDataSource ERROR ENCOUNTERED <2>",a),null!=this._mask_contour_source&&"chan"in a&&"msk"in a.chan&&(a.msk_contour=this._mask_contour(a.chan.msk),this._mask_contour_source.data=a.msk_contour),s&&s(a),this.data=a.chan}),this.imid,[0,0])}wcs(){return this.image_source.wcs()}}t.ImageDataSource=r,o=r,r.__name__="ImageDataSource",r.__module__="cubevis.bokeh.sources._image_data_source",o.define((({Tuple:s,Number:a,Ref:t,Nullable:c,Any:i})=>({init_script:[i,null],image_source:[t(u.ImagePipe)],_mask_contour_source:[c(t(e.ColumnDataSource)),null],num_chans:[s(a,a)],cur_chan:[s(a,a)]})))},
|
|
50
50
|
"02e3c3e46c": function _(e,s,i,t,r){var a;t();const c=e("@bokehjs/models/sources/column_data_source"),u=e("@bokehjs/core/util/string"),o=e("2889e0dd45");class _ extends c.ColumnDataSource{constructor(e){super(e),this.imid=(0,u.uuid4)()}initialize(){super.initialize()}spectra(e,s,i=0,t=!1){this.image_source.spectrum([e,s,i],(e=>this.data=e.spectrum),this.imid,t)}refresh(){this.image_source.refresh((e=>this.data=e.spectrum),this.imid,[0,0,0])}}i.SpectraDataSource=_,a=_,_.__name__="SpectraDataSource",_.__module__="cubevis.bokeh.sources._spectra_data_source",a.define((({Ref:e})=>({image_source:[e(o.ImagePipe)]})))},
|
|
51
|
-
"64b16deff9": function _(e,s,i,t,a){var n;t();const u=e("@bokehjs/models/sources/column_data_source"),l=e("
|
|
51
|
+
"64b16deff9": function _(e,s,i,t,a){var n;t();const u=e("@bokehjs/models/sources/column_data_source"),l=e("87aeec7876"),o=e("@bokehjs/core/util/callbacks");class c extends u.ColumnDataSource{constructor(e){super(e)}send(e,s){this.pipe.send(this.session_id.valueOf(),{action:"callback",message:e},(e=>{s("result"in e?e.result:{error:`expected to find a "result" in "${e}"`,msg:e})}))}initialize(){super.initialize();(()=>{null!=this.js_init&&(0,o.execute)(this.js_init,this)})()}}i.UpdatableDataSource=c,n=c,c.__name__="UpdatableDataSource",c.__module__="cubevis.bokeh.sources._updatable_data_source",n.define((({Ref:e,Any:s,String:i})=>({js_init:[s,null],js_update:[s,null],pipe:[e(l.DataPipe)],session_id:[i]})))},
|
|
52
52
|
"b6ae454f0d": function _(s,i,o,t,e){var r;t();const a=s("@bokehjs/models/formatters/tick_formatter"),c=s("de65005924");class l extends a.TickFormatter{constructor(s){super(s),this._axis=null,this._coord="world"}initialize(){super.initialize(),"x"==this.axis||"X"==this.axis||"y"==this.axis||"Y"==this.axis?this._axis="x"==this.axis||"X"==this.axis?"x":"y":console.log("ERROR: WcsTicks formatter created with invalid axis:",this.axis)}doFormat(s){const i=[];if(this._axis&&this.image_source.wcs()&&"world"==this._coord)for(let o=0,t=s.length;o<t;o++)if("x"==this._axis){const t=new casalib.coordtxl.Point2D(Number(s[o]),0);this.image_source.wcs().imageToWorldCoords(t,!1),i.push(new casalib.coordtxl.WorldCoords(t.getX(),t.getY()).format(2e3)[0])}else{const t=new casalib.coordtxl.Point2D(0,Number(s[o]));this.image_source.wcs().imageToWorldCoords(t,!1),i.push(new casalib.coordtxl.WorldCoords(t.getX(),t.getY()).format(2e3)[1])}else for(let o=0,t=s.length;o<t;o++)i.push(""+s[o]);return i}coordinates(s){return s!=this._coord&&("world"!=s&&"pixel"!=s||(this._coord=s)),this._coord}}o.WcsTicks=l,r=l,l.__name__="WcsTicks",l.__module__="cubevis.bokeh.format._wcs_ticks",r.define((({Ref:s,String:i})=>({axis:[i],image_source:[s(c.ImageDataSource)]})))},
|
|
53
|
-
"cb7d28d6b3": function _(i,e,t,o,s){var d;o();const l=i("@bokehjs/models/tools/gestures/gesture_tool"),r=i("
|
|
54
|
-
"
|
|
55
|
-
"
|
|
53
|
+
"cb7d28d6b3": function _(i,e,t,o,s){var d;o();const l=i("@bokehjs/models/tools/gestures/gesture_tool"),r=i("8fc7a9e935"),_=i("3684bcd721"),m=i("@bokehjs/core/util/callbacks");class a extends l.GestureToolView{_pan_start(i){var e;null===(e=this.model.document)||void 0===e||e.interactive_start(this.plot_view.model);const t=(0,_.px_from_sx)(this.plot_view,i.sx),o=(0,_.py_from_sy)(this.plot_view,i.sy),s=(0,_.dx_from_px)(this.plot_view,t),d=(0,_.dy_from_py)(this.plot_view,o),{start:l}=this.model;l?(0,m.execute)(l,this.model,{sx:t,sy:o,x:s,y:d,delta_x:i.dx,delta_y:-i.dy,shift:"modifiers"in i?i.modifiers.shift:void 0,ctrl:"modifiers"in i?i.modifiers.ctrl:void 0,alt:"modifiers"in i?i.modifiers.alt:void 0}):this.model.trigger_event(new r.DragStart(t,o,s,d,i.dx,-i.dy,i.modifiers))}_pan(i){var e;null===(e=this.model.document)||void 0===e||e.interactive_start(this.plot_view.model);const t=(0,_.px_from_sx)(this.plot_view,i.sx),o=(0,_.py_from_sy)(this.plot_view,i.sy),s=(0,_.dx_from_px)(this.plot_view,t),d=(0,_.dy_from_py)(this.plot_view,o),{move:l}=this.model;l?(0,m.execute)(l,this.model,{sx:t,sy:o,x:s,y:d,delta_x:i.dx,delta_y:-i.dy,shift:"modifiers"in i?i.modifiers.shift:void 0,ctrl:"modifiers"in i?i.modifiers.ctrl:void 0,alt:"modifiers"in i?i.modifiers.alt:void 0}):this.model.trigger_event(new r.Drag(t,o,s,d,i.dx,-i.dy,i.modifiers))}_pan_end(i){const e=(0,_.px_from_sx)(this.plot_view,i.sx),t=(0,_.py_from_sy)(this.plot_view,i.sy),o=(0,_.dx_from_px)(this.plot_view,e),s=(0,_.dy_from_py)(this.plot_view,t),{end:d}=this.model;d?(0,m.execute)(d,this.model,{sx:e,sy:t,x:o,y:s,delta_x:i.dx,delta_y:-i.dy,shift:"modifiers"in i?i.modifiers.shift:void 0,ctrl:"modifiers"in i?i.modifiers.ctrl:void 0,alt:"modifiers"in i?i.modifiers.alt:void 0}):this.model.trigger_event(new r.DragEnd(e,t,o,s,i.dx,-i.dy,i.modifiers))}}t.DragToolView=a,a.__name__="DragToolView";class n extends l.GestureTool{constructor(i){super(i),this.tool_name="Drag",this.event_type="pan",this.default_order=10}}t.DragTool=n,d=n,n.__name__="DragTool",n.__module__="cubevis.bokeh.tools._drag_tool",d.prototype.default_view=a,d.define((({Any:i,Nullable:e})=>({start:[e(i),null],move:[e(i),null],end:[e(i),null]})))},
|
|
54
|
+
"8fc7a9e935": function _(e,t,a,s,_){s();const n=e("@bokehjs/core/bokeh_events");class r extends n.Pan{}a.Drag=r,r.__name__="Drag";class l extends n.PanStart{constructor(e,t,a,s,_,n,r){super(e,t,a,s,r),this.delta_x=_,this.delta_y=n}get event_values(){const{delta_x:e,delta_y:t}=this;return{...super.event_values,delta_x:e,delta_y:t}}}a.DragStart=l,l.__name__="DragStart";class d extends n.PanEnd{constructor(e,t,a,s,_,n,r){super(e,t,a,s,r),this.delta_x=_,this.delta_y=n}get event_values(){const{delta_x:e,delta_y:t}=this;return{...super.event_values,delta_x:e,delta_y:t}}}a.DragEnd=d,d.__name__="DragEnd"},
|
|
55
|
+
"3684bcd721": function _(n,o,e,t,r){t(),e.view=function(n){function o(e){if(e.model===n)return e;for(const n of e.children()){const e=o(n);if(e)return e}return null}const e=n.document;if(!e)return null;const t=e.views_manager;if(!t)return null;const r=t.roots;for(const n of r){const e=o(n);if(e)return e}return null},e.span_coords=function(n){function o(n,o,e,t,r){if(null!=n)switch(o){case"canvas":return r.compute(n);case"screen":return t.compute(n);case"data":return e.compute(n)}return NaN}const{frame:e,canvas:t}=n.plot_view,{x_scale:r,y_scale:i}=n.coordinates;let c,u,s,f,_=n.model.dimension;"width"==n.model.dimension?(s=o(n.model.location,n.model.location_units,i,e.bbox.yview,t.bbox.y_screen),u=e.bbox.left,f=e.bbox.width,c=n.model.line_width):(s=e.bbox.top,u=o(n.model.location,n.model.location_units,r,e.bbox.xview,t.bbox.y_screen),f=n.model.line_width,c=e.bbox.height);return{stop:s,sleft:u,width:f,height:c,orientation:_}},e.px_from_sx=function(n,o){return n.frame.bbox.x_view.invert(o)},e.py_from_sy=function(n,o){return n.frame.bbox.y_view.invert(o)},e.dx_from_px=function(n,o){const e=n.frame.bbox.x_view.compute(o);return n.frame.x_scale.invert(e)},e.dy_from_py=function(n,o){const e=n.frame.bbox.y_view.compute(o);return n.frame.y_scale.invert(e)},e.sx_from_dx=function(n,o){return n.frame.x_scale.compute(o)},e.sy_from_dy=function(n,o){return n.frame.y_scale.compute(o)},e.v_px_from_sx=function(n,o){return n.frame.bbox.x_view.v_invert(o)},e.v_py_from_sy=function(n,o){return n.frame.bbox.y_view.v_invert(o)},e.v_dx_from_px=function(n,o){const e=n.frame.bbox.x_view.v_compute(o);return n.frame.x_scale.v_invert(e)},e.v_dy_from_py=function(n,o){const e=n.frame.bbox.y_view.v_compute(o);return n.frame.y_scale.v_invert(e)},e.v_sx_from_dx=function(n,o){return n.frame.x_scale.v_compute(o)},e.v_sy_from_dy=function(n,o){return n.frame.y_scale.v_compute(o)},e.context=u,e.appState=function(n){var o,e;const t=u(n);if(t){return null!==(e=(null===(o=null===window||void 0===window?void 0:window.cubevisAppSession)||void 0===o?void 0:o.applications)[t.app_id])&&void 0!==e?e:void 0}return};const i=n("@bokehjs/model");function c(n,o,e=new Set){if(e.has(n))return;if(e.add(n),o(n))return n;const t=["children","items","panes","tabs","child","ui"];for(const r of t){const t=n[r];if(t){const n=Array.isArray(t)?t:[t];for(const t of n)if(t instanceof i.Model&&!e.has(t)){const n=c(t,o,e);if(n)return n}}}}function u(n){var o;const e=null===(o=null==n?void 0:n.document)||void 0===o?void 0:o.all_roots;if(e){const o=e.flatMap((n=>{const o=n;return o&&"cubevis.bokeh.models._bokeh_app_context.BokehAppContext"===o.type?[o]:[]}));return o.find((o=>Boolean(c(o,(o=>o.id===n.id)))))}}},
|
|
56
56
|
"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))},
|
|
57
57
|
"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"})},
|
|
58
58
|
"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]})))},
|
|
59
59
|
"5e5f767c53": function _(e,i,t,s,l){var a;s();const o=e("@bokehjs/models/layouts/layout_dom"),n=e("@bokehjs/models/ui/ui_element");class u extends o.LayoutDOMView{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()}_update_layout(){super._update_layout()}render(){super.render(),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>')}after_layout(){super.after_layout()}_intrinsic_display(){return super._intrinsic_display()}remove(){super.remove()}}t.ShowableView=u,u.__name__="ShowableView";class r extends o.LayoutDOM{constructor(e){super(e)}}t.Showable=r,a=r,r.__name__="Showable",r.__module__="cubevis.bokeh.models._showable",a.prototype.default_view=u,a.define((({Ref:e})=>({ui:[e(n.UIElement)]})))},
|
|
60
|
+
"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),{}]})))},
|
|
60
61
|
"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),{}]})))},
|
|
61
62
|
"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},
|
|
62
63
|
"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=_},
|
|
63
64
|
"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=_},
|
|
64
|
-
}, "
|
|
65
|
+
}, "e2864cf297", {"index":"e2864cf297","src/bokeh/sources/data_pipe":"87aeec7876","src/bokeh/util/conversions":"e3901fa9f2","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":"3684bcd721","src/bokeh/tools/cbreset_tool":"9d3c34ff8e","src/bokeh/models/tip_button":"9f961622ce","src/bokeh/models/tip":"ca4c845905","src/bokeh/models/showable":"5e5f767c53","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"}, {});});
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from bokeh.core.properties import String, Dict, Any, Nullable, Instance
|
|
3
|
+
from bokeh.models.layouts import LayoutDOM
|
|
4
|
+
from bokeh.models.ui import UIElement
|
|
5
|
+
from uuid import uuid4
|
|
6
|
+
|
|
7
|
+
logger = logging.getLogger(__name__)
|
|
8
|
+
|
|
9
|
+
class BokehAppContext(LayoutDOM):
|
|
10
|
+
"""
|
|
11
|
+
Custom Bokeh model that bridges Python AppContext with JavaScript.
|
|
12
|
+
Initializes session-level data structure and app-specific state.
|
|
13
|
+
"""
|
|
14
|
+
ui = Nullable(Instance(UIElement), help="""
|
|
15
|
+
A UI element, which can be plots, layouts, widgets, or any other UIElement.
|
|
16
|
+
""")
|
|
17
|
+
|
|
18
|
+
app_id = String(default="")
|
|
19
|
+
session_id = String(default="")
|
|
20
|
+
app_state = Dict(String, Any, default={})
|
|
21
|
+
|
|
22
|
+
# Class-level session ID shared across all apps in the same Python session
|
|
23
|
+
_session_id = None
|
|
24
|
+
|
|
25
|
+
@classmethod
|
|
26
|
+
def get_session_id(cls):
|
|
27
|
+
"""Get or create a session ID for this Python session"""
|
|
28
|
+
if cls._session_id is None:
|
|
29
|
+
cls._session_id = str(uuid4())
|
|
30
|
+
return cls._session_id
|
|
31
|
+
|
|
32
|
+
def __init__( self, ui=None, **kwargs ):
|
|
33
|
+
logger.debug(f"\tBokehAppContext::__init__(ui={type(ui).__name__ if ui else None}, {kwargs}): {id(self)}")
|
|
34
|
+
|
|
35
|
+
if ui is not None and 'ui' in kwargs:
|
|
36
|
+
raise RuntimeError( "'ui' supplied as both a positional parameter and a keyword parameter" )
|
|
37
|
+
|
|
38
|
+
kwargs['session_id'] = self.get_session_id( )
|
|
39
|
+
|
|
40
|
+
if 'ui' not in kwargs:
|
|
41
|
+
kwargs['ui'] = ui
|
|
42
|
+
if 'app_id' not in kwargs:
|
|
43
|
+
kwargs['app_id'] = str(uuid4())
|
|
44
|
+
|
|
45
|
+
super().__init__(**kwargs)
|
|
46
|
+
|
|
47
|
+
def _sphinx_height_hint(self):
|
|
48
|
+
"""Delegate height hint to the wrapped UI element"""
|
|
49
|
+
logger.debug(f"\tShowable::_sphinx_height_hint(): {id(self)}")
|
|
50
|
+
if self.ui and hasattr(self.ui, '_sphinx_height_hint'):
|
|
51
|
+
return self.ui._sphinx_height_hint()
|
|
52
|
+
return None
|
|
53
|
+
|
|
54
|
+
def update_app_state(self, state_updates):
|
|
55
|
+
"""
|
|
56
|
+
Update the application state (will be in the generated HTML/JS)
|
|
57
|
+
|
|
58
|
+
Args:
|
|
59
|
+
state_updates: dict of state key-value pairs to update
|
|
60
|
+
"""
|
|
61
|
+
current_state = dict(self.app_state)
|
|
62
|
+
current_state.update(state_updates)
|
|
63
|
+
self.app_state = current_state
|
|
@@ -36,6 +36,7 @@ import asyncio
|
|
|
36
36
|
import traceback
|
|
37
37
|
import time
|
|
38
38
|
import json
|
|
39
|
+
from uuid import uuid4
|
|
39
40
|
|
|
40
41
|
from bokeh.models.sources import DataSource
|
|
41
42
|
from bokeh.util.compiler import TypeScript
|
|
@@ -72,6 +73,8 @@ class DataPipe(DataSource,BokehInit):
|
|
|
72
73
|
|
|
73
74
|
address = Tuple( String, Int, help="two integer sequence representing the address and port to use for the websocket" )
|
|
74
75
|
|
|
76
|
+
instance_id = String( help="Unique ID for each DataPipe object" )
|
|
77
|
+
|
|
75
78
|
conflict_check = Bool( default=True, help="Perform check to avoid reuse of URL for GUI. Not needed in the Jupyter context" )
|
|
76
79
|
|
|
77
80
|
# Class-level session tracking to prevent multiple connections
|
|
@@ -87,13 +90,11 @@ class DataPipe(DataSource,BokehInit):
|
|
|
87
90
|
|
|
88
91
|
if 'conflict_check' not in kwargs:
|
|
89
92
|
kwargs['conflict_check'] = not is_interactive_jupyter( )
|
|
93
|
+
if 'instance_id' not in kwargs:
|
|
94
|
+
kwargs['instance_id'] = str(uuid4( ))
|
|
90
95
|
|
|
91
96
|
super( ).__init__( *args, **kwargs )
|
|
92
97
|
|
|
93
|
-
print('************************************************************************************************************************')
|
|
94
|
-
print(f"*conflict check: {self.conflict_check}")
|
|
95
|
-
print('************************************************************************************************************************')
|
|
96
|
-
|
|
97
98
|
self.__send_queue = { }
|
|
98
99
|
self.__pending = { }
|
|
99
100
|
self.__incoming_callbacks = { }
|
|
@@ -49,7 +49,8 @@ from bokeh.io import reset_output as reset_bokeh_output, output_notebook
|
|
|
49
49
|
from bokeh.models.dom import HTML
|
|
50
50
|
|
|
51
51
|
from bokeh.models.ui.tooltips import Tooltip
|
|
52
|
-
from cubevis.bokeh.models import TipButton, Tip, EvTextInput
|
|
52
|
+
from cubevis.bokeh.models import TipButton, Tip, EvTextInput, BokehAppContext
|
|
53
|
+
|
|
53
54
|
from cubevis.utils import resource_manager, reset_resource_manager, is_interactive_jupyter, find_pkg, load_pkg
|
|
54
55
|
from cubevis.utils import ContextMgrChain as CMC
|
|
55
56
|
|
|
@@ -932,15 +933,19 @@ class InteractiveCleanUI:
|
|
|
932
933
|
|
|
933
934
|
image_tabs = Tabs( tabs=tab_panels, tabs_location='below', height_policy='max', width_policy='max' )
|
|
934
935
|
|
|
935
|
-
self._fig['layout'] =
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
936
|
+
self._fig['layout'] = BokehAppContext(
|
|
937
|
+
column( row( help_button,
|
|
938
|
+
self._log_button,
|
|
939
|
+
Spacer( height=self._control['iteration']['stop'].height, sizing_mode="scale_width" ),
|
|
940
|
+
Div( text="<div><b>status:</b></div>" ),
|
|
941
|
+
status_line,
|
|
942
|
+
self._control['iteration']['stop'], self._control['iteration']['continue'], self._control['iteration']['finish'], sizing_mode="scale_width" ),
|
|
943
|
+
row( image_tabs, height_policy='max', width_policy='max' ),
|
|
944
|
+
height_policy='max', width_policy='max' ),
|
|
945
|
+
app_state={
|
|
946
|
+
'name': 'interactive clean',
|
|
947
|
+
'initialized': True
|
|
948
|
+
} )
|
|
944
949
|
|
|
945
950
|
###
|
|
946
951
|
### Keep track of which image is currently active in document._casa_image_name (which is
|
|
@@ -48,7 +48,8 @@ from bokeh.io import reset_output as reset_bokeh_output, output_notebook
|
|
|
48
48
|
from bokeh.models.dom import HTML
|
|
49
49
|
|
|
50
50
|
from bokeh.models.ui.tooltips import Tooltip
|
|
51
|
-
from cubevis.bokeh.models import TipButton, Tip, EvTextInput
|
|
51
|
+
from cubevis.bokeh.models import TipButton, Tip, EvTextInput, BokehAppContext
|
|
52
|
+
|
|
52
53
|
from cubevis.utils import resource_manager, reset_resource_manager, is_interactive_jupyter, find_pkg, load_pkg
|
|
53
54
|
from cubevis.utils import ContextMgrChain as CMC
|
|
54
55
|
|
|
@@ -931,15 +932,19 @@ class InteractiveCleanUI:
|
|
|
931
932
|
|
|
932
933
|
image_tabs = Tabs( tabs=tab_panels, tabs_location='below', height_policy='max', width_policy='max' )
|
|
933
934
|
|
|
934
|
-
self._fig['layout'] =
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
935
|
+
self._fig['layout'] = BokehAppContext(
|
|
936
|
+
column( row( help_button,
|
|
937
|
+
self._log_button,
|
|
938
|
+
Spacer( height=self._control['iteration']['stop'].height, sizing_mode="scale_width" ),
|
|
939
|
+
Div( text="<div><b>status:</b></div>" ),
|
|
940
|
+
status_line,
|
|
941
|
+
self._control['iteration']['stop'], self._control['iteration']['continue'], self._control['iteration']['finish'], sizing_mode="scale_width" ),
|
|
942
|
+
row( image_tabs, height_policy='max', width_policy='max' ),
|
|
943
|
+
height_policy='max', width_policy='max' ),
|
|
944
|
+
app_state={
|
|
945
|
+
'name': 'interactive clean',
|
|
946
|
+
'initialized': True
|
|
947
|
+
} )
|
|
943
948
|
|
|
944
949
|
###
|
|
945
950
|
### Keep track of which image is currently active in document._casa_image_name (which is
|
|
@@ -7,7 +7,7 @@ authors = [
|
|
|
7
7
|
{ name = "Pam Harris", email = "pharris@nrao.edu" },
|
|
8
8
|
]
|
|
9
9
|
dependencies = [
|
|
10
|
-
"bokeh
|
|
10
|
+
"bokeh>=3.8, <3.9",
|
|
11
11
|
"astropy>=5.1",
|
|
12
12
|
"regions>=0.8",
|
|
13
13
|
"websockets>=10.3",
|
|
@@ -16,7 +16,7 @@ dependencies = [
|
|
|
16
16
|
]
|
|
17
17
|
requires-python = ">=3.11"
|
|
18
18
|
readme = "README.rst"
|
|
19
|
-
version = "1.0.
|
|
19
|
+
version = "1.0.14"
|
|
20
20
|
|
|
21
21
|
[project.license]
|
|
22
22
|
text = "LGPL"
|
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
{
|
|
2
|
+
"cells": [
|
|
3
|
+
{
|
|
4
|
+
"cell_type": "markdown",
|
|
5
|
+
"id": "170380fc-ed7d-424a-a474-134100bd3532",
|
|
6
|
+
"metadata": {},
|
|
7
|
+
"source": [
|
|
8
|
+
"# Interactive Clean\n",
|
|
9
|
+
"The CASA interactive clean application is available for use in Jupyter notebooks. The primary difference between usage in Jupyter and usage directly from a Python command line interface (CLI) is that the `iclean.notebook` function is used within a notebook instead of the `iclean` function that is used from the Python CLI.\n",
|
|
10
|
+
"\n",
|
|
11
|
+
"## Current status\n",
|
|
12
|
+
"\n",
|
|
13
|
+
"Currently the interactive clean app works well when a **single** instance is run within a notebook **and** the Jupyter kernel is running on the same host as the browser displaying the notebook. Things begin to go wrong when the *red stop sign* is pressed. Doing this is necessary because this is how the `iclean` return dictionary is returned. The `get_result` function blocks until the *red stop sign* is clicked and confirmed. At this point, the `iclean` return dictionary is returned as the result of `get_result`. Another function called `get_future` is available which does not block but instead retrieved the future where the `iclean` return dictionary will eventually appear.\n",
|
|
14
|
+
"\n",
|
|
15
|
+
"Supporting, multiple `iclean` instances within a single worksheet is the goal, but currently only one instance should be used, *unless you are willing to risk corruption of your Jupyter session*. All of the GUI display cells in this notebook are beleved to work when a **single** one is executed within a given notebook instance.\n",
|
|
16
|
+
"\n",
|
|
17
|
+
"## Setup\n",
|
|
18
|
+
"This first cell simply retrieves the data that is required."
|
|
19
|
+
]
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"cell_type": "code",
|
|
23
|
+
"execution_count": null,
|
|
24
|
+
"id": "738dd1a5-2fa5-4824-a2d5-d3b0db850a8a",
|
|
25
|
+
"metadata": {},
|
|
26
|
+
"outputs": [],
|
|
27
|
+
"source": [
|
|
28
|
+
"import os\n",
|
|
29
|
+
"import ssl\n",
|
|
30
|
+
"import certifi\n",
|
|
31
|
+
"import urllib\n",
|
|
32
|
+
"import tarfile\n",
|
|
33
|
+
"ms_path = 'refim_point_withline.ms'\n",
|
|
34
|
+
"ms_url = \"https://casa.nrao.edu/download/devel/casavis/data/refim_point_withline-ms.tar.gz\"\n",
|
|
35
|
+
"if not os.path.isdir(ms_path):\n",
|
|
36
|
+
" try:\n",
|
|
37
|
+
" context = ssl.create_default_context(cafile=certifi.where())\n",
|
|
38
|
+
" tstream = urllib.request.urlopen(ms_url, context=context, timeout=400)\n",
|
|
39
|
+
" tar = tarfile.open(fileobj=tstream, mode=\"r:gz\")\n",
|
|
40
|
+
" tar.extractall( )\n",
|
|
41
|
+
" except urllib.error.URLError:\n",
|
|
42
|
+
" print(\"Failed to open connection to \"+ms_url)"
|
|
43
|
+
]
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
"cell_type": "markdown",
|
|
47
|
+
"id": "68fdc83b-17d1-4d8e-a12e-2c420cb13a35",
|
|
48
|
+
"metadata": {},
|
|
49
|
+
"source": [
|
|
50
|
+
"## Import\n",
|
|
51
|
+
"The first step is to import the `iclean` function:"
|
|
52
|
+
]
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
"cell_type": "code",
|
|
56
|
+
"execution_count": null,
|
|
57
|
+
"id": "aac06f5e-27cf-4465-983c-967f6dca2a66",
|
|
58
|
+
"metadata": {},
|
|
59
|
+
"outputs": [],
|
|
60
|
+
"source": [
|
|
61
|
+
"from cubevis import iclean"
|
|
62
|
+
]
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
"cell_type": "markdown",
|
|
66
|
+
"id": "5b93ca76-abe4-42e2-940b-e312bb3e9203",
|
|
67
|
+
"metadata": {},
|
|
68
|
+
"source": [
|
|
69
|
+
"## Cleanup\n",
|
|
70
|
+
"`iclean` operates on state contained within files in the current directory, so it is always a good idea to make sure that you are starting with a clean slate. This command removes the state files that accumulate from running this example."
|
|
71
|
+
]
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
"cell_type": "code",
|
|
75
|
+
"execution_count": null,
|
|
76
|
+
"id": "c2998492-96d3-46a1-b830-c2fa50d1a8f3",
|
|
77
|
+
"metadata": {},
|
|
78
|
+
"outputs": [],
|
|
79
|
+
"source": [
|
|
80
|
+
"!rm -rf test.*"
|
|
81
|
+
]
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
"cell_type": "markdown",
|
|
85
|
+
"id": "4505c0a4-b73b-43a6-a265-29bf4157d544",
|
|
86
|
+
"metadata": {},
|
|
87
|
+
"source": [
|
|
88
|
+
"## Create the Application Object\n",
|
|
89
|
+
"This cell creates the interactive clean application object. This object is used to display the GUI and to retreive the `iclean` return dictionary from the GUI once the user has completed cleaning."
|
|
90
|
+
]
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
"cell_type": "code",
|
|
94
|
+
"execution_count": null,
|
|
95
|
+
"id": "415cf4e6-4e29-4b86-8d35-7d38485b22f4",
|
|
96
|
+
"metadata": {},
|
|
97
|
+
"outputs": [],
|
|
98
|
+
"source": [
|
|
99
|
+
"ic = iclean.notebook( vis=ms_path, imagename='test',\n",
|
|
100
|
+
" imsize=512, niter=50,\n",
|
|
101
|
+
" cycleniter=10,\n",
|
|
102
|
+
" cell='12.0arcsec',\n",
|
|
103
|
+
" specmode='cube', interpolation='nearest',\n",
|
|
104
|
+
" nchan=5, start='1.0GHz', width='0.2GHz', pblimit=-1e-05,\n",
|
|
105
|
+
" deconvolver='hogbom', threshold='0.001Jy', cyclefactor=3, scales=[0,3,10] )"
|
|
106
|
+
]
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
"cell_type": "markdown",
|
|
110
|
+
"id": "e73d12a1-327d-483c-9835-d6fccb5a04ad",
|
|
111
|
+
"metadata": {},
|
|
112
|
+
"source": [
|
|
113
|
+
"## Display the GUI\n",
|
|
114
|
+
"Once the application object has been created, the GUI can be displayed:"
|
|
115
|
+
]
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
"cell_type": "code",
|
|
119
|
+
"execution_count": null,
|
|
120
|
+
"id": "0a465972-26e9-44ca-8bc1-9f2e3c789c3a",
|
|
121
|
+
"metadata": {},
|
|
122
|
+
"outputs": [],
|
|
123
|
+
"source": [
|
|
124
|
+
"ic.show( )"
|
|
125
|
+
]
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
"cell_type": "markdown",
|
|
129
|
+
"id": "0fca3f96-f725-4155-a2de-b197fe7c196f",
|
|
130
|
+
"metadata": {},
|
|
131
|
+
"source": [
|
|
132
|
+
"## Retrieve the result\n",
|
|
133
|
+
"Once the user has completed cleaning, clicked the stop sign and approved the exiting the application, the result can be retrieved:"
|
|
134
|
+
]
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
"cell_type": "code",
|
|
138
|
+
"execution_count": null,
|
|
139
|
+
"id": "8c555250-7425-43e2-83f7-0ba2d0a6ff21",
|
|
140
|
+
"metadata": {},
|
|
141
|
+
"outputs": [],
|
|
142
|
+
"source": [
|
|
143
|
+
"ic.get_result( )"
|
|
144
|
+
]
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
"cell_type": "markdown",
|
|
148
|
+
"id": "a9f3aba7-7c19-4876-84a4-14a14e89e87e",
|
|
149
|
+
"metadata": {},
|
|
150
|
+
"source": [
|
|
151
|
+
"## Alternate ways to display the GUI\n",
|
|
152
|
+
"While this is the most obvious way to create and use the interactive clean within a Jupyter notebook, there are also some subtle variations.\n",
|
|
153
|
+
"\n",
|
|
154
|
+
"### Display as a result of cell evaulation\n",
|
|
155
|
+
"The last evaluated statement in a notebook cell is displayed and displaying the `iclean` application object results in the GUI being displayed."
|
|
156
|
+
]
|
|
157
|
+
},
|
|
158
|
+
{
|
|
159
|
+
"cell_type": "code",
|
|
160
|
+
"execution_count": null,
|
|
161
|
+
"id": "537b51db-0d57-43e4-96b3-45e65fa6d1ff",
|
|
162
|
+
"metadata": {},
|
|
163
|
+
"outputs": [],
|
|
164
|
+
"source": [
|
|
165
|
+
"!rm -rf test.*\n",
|
|
166
|
+
"iclean.notebook( vis=ms_path, imagename='test',\n",
|
|
167
|
+
" imsize=512, niter=50,\n",
|
|
168
|
+
" cycleniter=10,\n",
|
|
169
|
+
" cell='12.0arcsec',\n",
|
|
170
|
+
" specmode='cube', interpolation='nearest',\n",
|
|
171
|
+
" nchan=5, start='1.0GHz', width='0.2GHz', pblimit=-1e-05,\n",
|
|
172
|
+
" deconvolver='hogbom', threshold='0.001Jy', cyclefactor=3, scales=[0,3,10] )"
|
|
173
|
+
]
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
"cell_type": "markdown",
|
|
177
|
+
"id": "94ec4e93-0156-4791-938d-72358bc303c4",
|
|
178
|
+
"metadata": {},
|
|
179
|
+
"source": [
|
|
180
|
+
"### Retrieving the result\n",
|
|
181
|
+
"Even though we did not retain the application object, the value of the **last** cell evaluation is available as `_`. So using this, we can retrieve the return dictionary:"
|
|
182
|
+
]
|
|
183
|
+
},
|
|
184
|
+
{
|
|
185
|
+
"cell_type": "code",
|
|
186
|
+
"execution_count": null,
|
|
187
|
+
"id": "10755706-58fc-40eb-81e0-a45c0b77d4e0",
|
|
188
|
+
"metadata": {},
|
|
189
|
+
"outputs": [],
|
|
190
|
+
"source": [
|
|
191
|
+
"_.get_result( )"
|
|
192
|
+
]
|
|
193
|
+
},
|
|
194
|
+
{
|
|
195
|
+
"cell_type": "markdown",
|
|
196
|
+
"id": "ac33d8bf-3a21-4c84-b940-e94afdf98fc0",
|
|
197
|
+
"metadata": {},
|
|
198
|
+
"source": [
|
|
199
|
+
"### Using Bokeh's show function\n",
|
|
200
|
+
"One last slight variation is to use [Bokeh's](https://bokeh.org/) `show` function to display the application object:"
|
|
201
|
+
]
|
|
202
|
+
},
|
|
203
|
+
{
|
|
204
|
+
"cell_type": "code",
|
|
205
|
+
"execution_count": null,
|
|
206
|
+
"id": "437e425d-96a1-4007-a131-cf6d1d3b4379",
|
|
207
|
+
"metadata": {},
|
|
208
|
+
"outputs": [],
|
|
209
|
+
"source": [
|
|
210
|
+
"!rm -rf test.*\n",
|
|
211
|
+
"from bokeh.io import output_notebook\n",
|
|
212
|
+
"from bokeh.plotting import show\n",
|
|
213
|
+
"output_notebook( )\n",
|
|
214
|
+
"ic = iclean.notebook( vis=ms_path, imagename='test',\n",
|
|
215
|
+
" imsize=512, niter=50,\n",
|
|
216
|
+
" cycleniter=10,\n",
|
|
217
|
+
" cell='12.0arcsec',\n",
|
|
218
|
+
" specmode='cube', interpolation='nearest',\n",
|
|
219
|
+
" nchan=5, start='1.0GHz', width='0.2GHz', pblimit=-1e-05,\n",
|
|
220
|
+
" deconvolver='hogbom', threshold='0.001Jy', cyclefactor=3, scales=[0,3,10] )\n",
|
|
221
|
+
"show(ic)"
|
|
222
|
+
]
|
|
223
|
+
}
|
|
224
|
+
],
|
|
225
|
+
"metadata": {
|
|
226
|
+
"kernelspec": {
|
|
227
|
+
"display_name": "Python 3 (ipykernel)",
|
|
228
|
+
"language": "python",
|
|
229
|
+
"name": "python3"
|
|
230
|
+
},
|
|
231
|
+
"language_info": {
|
|
232
|
+
"codemirror_mode": {
|
|
233
|
+
"name": "ipython",
|
|
234
|
+
"version": 3
|
|
235
|
+
},
|
|
236
|
+
"file_extension": ".py",
|
|
237
|
+
"mimetype": "text/x-python",
|
|
238
|
+
"name": "python",
|
|
239
|
+
"nbconvert_exporter": "python",
|
|
240
|
+
"pygments_lexer": "ipython3",
|
|
241
|
+
"version": "3.11.13"
|
|
242
|
+
}
|
|
243
|
+
},
|
|
244
|
+
"nbformat": 4,
|
|
245
|
+
"nbformat_minor": 5
|
|
246
|
+
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|