cubevis 0.5.24__tar.gz → 0.5.25__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.

Files changed (151) hide show
  1. {cubevis-0.5.24 → cubevis-0.5.25}/PKG-INFO +1 -1
  2. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/__js__/cubevisjs.min.js +3 -2
  3. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/bokeh/models/__init__.py +1 -0
  4. cubevis-0.5.25/cubevis/bokeh/models/_shared_dict.py +23 -0
  5. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/toolbox/_cube.py +57 -15
  6. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/toolbox/_interactive_clean_ui.mustache +26 -19
  7. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/toolbox/_interactive_clean_ui.py +26 -19
  8. {cubevis-0.5.24 → cubevis-0.5.25}/pyproject.toml +1 -1
  9. {cubevis-0.5.24 → cubevis-0.5.25}/LICENSE +0 -0
  10. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/LICENSE.rst +0 -0
  11. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/__icons__/20px/fast-backward.svg +0 -0
  12. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/__icons__/20px/fast-forward.svg +0 -0
  13. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/__icons__/20px/step-backward.svg +0 -0
  14. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/__icons__/20px/step-forward.svg +0 -0
  15. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/__icons__/add-chan.png +0 -0
  16. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/__icons__/add-chan.svg +0 -0
  17. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/__icons__/add-cube.png +0 -0
  18. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/__icons__/add-cube.svg +0 -0
  19. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/__icons__/drag.png +0 -0
  20. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/__icons__/drag.svg +0 -0
  21. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/__icons__/mask-selected.png +0 -0
  22. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/__icons__/mask.png +0 -0
  23. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/__icons__/mask.svg +0 -0
  24. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/__icons__/new-layer-sm-selected.png +0 -0
  25. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/__icons__/new-layer-sm-selected.svg +0 -0
  26. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/__icons__/new-layer-sm.png +0 -0
  27. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/__icons__/new-layer-sm.svg +0 -0
  28. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/__icons__/reset.png +0 -0
  29. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/__icons__/reset.svg +0 -0
  30. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/__icons__/sub-chan.png +0 -0
  31. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/__icons__/sub-chan.svg +0 -0
  32. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/__icons__/sub-cube.png +0 -0
  33. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/__icons__/sub-cube.svg +0 -0
  34. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/__icons__/zoom-to-fit.png +0 -0
  35. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/__icons__/zoom-to-fit.svg +0 -0
  36. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/__init__.py +0 -0
  37. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/__js__/bokeh-3.6.1.min.js +0 -0
  38. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/__js__/bokeh-tables-3.6.1.min.js +0 -0
  39. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/__js__/bokeh-widgets-3.6.1.min.js +0 -0
  40. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/__js__/casalib.min.js +0 -0
  41. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/bokeh/__init__.py +0 -0
  42. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/bokeh/annotations/__init__.py +0 -0
  43. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/bokeh/annotations/_ev_poly_annotation.py +0 -0
  44. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/bokeh/components/__init__.py +0 -0
  45. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/bokeh/format/__init__.py +0 -0
  46. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/bokeh/format/_time_ticks.py +0 -0
  47. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/bokeh/format/_wcs_ticks.py +0 -0
  48. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/bokeh/models/_edit_span.py +0 -0
  49. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/bokeh/models/_ev_text_input.py +0 -0
  50. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/bokeh/models/_tip.py +0 -0
  51. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/bokeh/models/_tip_button.py +0 -0
  52. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/bokeh/sources/__init__.py +0 -0
  53. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/bokeh/sources/_data_pipe.py +0 -0
  54. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/bokeh/sources/_image_data_source.py +0 -0
  55. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/bokeh/sources/_image_pipe.py +0 -0
  56. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/bokeh/sources/_spectra_data_source.py +0 -0
  57. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/bokeh/sources/_updatable_data_source.py +0 -0
  58. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/bokeh/state/__init__.py +0 -0
  59. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/bokeh/state/_initialize.py +0 -0
  60. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/bokeh/state/_javascript.py +0 -0
  61. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/bokeh/state/_palette.py +0 -0
  62. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/bokeh/state/_session.py +0 -0
  63. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/bokeh/state/js/bokeh-2.4.1.min.js +0 -0
  64. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/bokeh/state/js/bokeh-gl-2.4.1.min.js +0 -0
  65. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/bokeh/state/js/bokeh-tables-2.4.1.min.js +0 -0
  66. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/bokeh/state/js/bokeh-widgets-2.4.1.min.js +0 -0
  67. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/bokeh/state/js/casaguijs-v0.0.4.0-b2.4.min.js +0 -0
  68. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/bokeh/state/js/casaguijs-v0.0.5.0-b2.4.min.js +0 -0
  69. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/bokeh/state/js/casaguijs-v0.0.6.0-b2.4.min.js +0 -0
  70. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/bokeh/state/js/casalib-v0.0.1.min.js +0 -0
  71. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/bokeh/tools/__init__.py +0 -0
  72. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/bokeh/tools/_cbreset_tool.py +0 -0
  73. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/bokeh/tools/_drag_tool.py +0 -0
  74. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/bokeh/utils/__init__.py +0 -0
  75. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/bokeh/utils/_axes_labels.py +0 -0
  76. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/bokeh/utils/_svg_icon.py +0 -0
  77. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/data/__init__.py +0 -0
  78. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/data/casaimage/__init__.py +0 -0
  79. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/exe/__init__.py +0 -0
  80. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/exe/_context.py +0 -0
  81. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/exe/_mode.py +0 -0
  82. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/exe/_setting.py +0 -0
  83. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/exe/_task.py +0 -0
  84. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/private/_gclean.py +0 -0
  85. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/private/apps/__init__.py +0 -0
  86. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/private/apps/_createmask.py +0 -0
  87. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/private/apps/_createregion.py +0 -0
  88. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/private/apps/_interactiveclean.mustache +0 -0
  89. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/private/apps/_interactiveclean.py +0 -0
  90. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/private/apps/_plotants.py +0 -0
  91. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/private/apps/_plotbandpass.py +0 -0
  92. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/private/casashell/createmask.py +0 -0
  93. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/private/casashell/iclean.py +0 -0
  94. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/private/casatasks/__init__.py +0 -0
  95. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/private/casatasks/createmask.py +0 -0
  96. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/private/casatasks/createregion.py +0 -0
  97. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/private/casatasks/iclean.py +0 -0
  98. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/readme.rst +0 -0
  99. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/remote/__init__.py +0 -0
  100. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/remote/_gclean.py +0 -0
  101. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/remote/_local.py +0 -0
  102. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/remote/_remote_kernel.py +0 -0
  103. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/toolbox/__init__.py +0 -0
  104. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/toolbox/_app_context.py +0 -0
  105. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/toolbox/_interactiveclean_wrappers.py +0 -0
  106. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/toolbox/_region_list.py +0 -0
  107. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/utils/_ResourceManager.py +0 -0
  108. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/utils/__init__.py +0 -0
  109. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/utils/_browser.py +0 -0
  110. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/utils/_contextmgrchain.py +0 -0
  111. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/utils/_conversion.py +0 -0
  112. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/utils/_copydoc.py +0 -0
  113. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/utils/_docenum.py +0 -0
  114. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/utils/_import_protected_module.py +0 -0
  115. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/utils/_jupyter.py +0 -0
  116. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/utils/_logging.py +0 -0
  117. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/utils/_pkgs.py +0 -0
  118. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/utils/_regions.py +0 -0
  119. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/utils/_static.py +0 -0
  120. {cubevis-0.5.24 → cubevis-0.5.25}/cubevis/utils/_tiles.py +0 -0
  121. {cubevis-0.5.24 → cubevis-0.5.25}/readme.rst +0 -0
  122. {cubevis-0.5.24 → cubevis-0.5.25}/tests/manual/alma-many-chan/alma-many-chan.py +0 -0
  123. {cubevis-0.5.24 → cubevis-0.5.25}/tests/manual/basic-websockets-demo/client.html +0 -0
  124. {cubevis-0.5.24 → cubevis-0.5.25}/tests/manual/basic-websockets-demo/client.py +0 -0
  125. {cubevis-0.5.24 → cubevis-0.5.25}/tests/manual/basic-websockets-demo/server.py +0 -0
  126. {cubevis-0.5.24 → cubevis-0.5.25}/tests/manual/createmask-demo/run-createmask.py +0 -0
  127. {cubevis-0.5.24 → cubevis-0.5.25}/tests/manual/createregion-demo/run-createregion.py +0 -0
  128. {cubevis-0.5.24 → cubevis-0.5.25}/tests/manual/cubemask-demo/image-slider-spectra-done-stats.py +0 -0
  129. {cubevis-0.5.24 → cubevis-0.5.25}/tests/manual/cubemask-demo/image-slider-spectra-done.py +0 -0
  130. {cubevis-0.5.24 → cubevis-0.5.25}/tests/manual/cubemask-demo/image-slider-spectra.py +0 -0
  131. {cubevis-0.5.24 → cubevis-0.5.25}/tests/manual/cubemask-demo/image-slider.py +0 -0
  132. {cubevis-0.5.24 → cubevis-0.5.25}/tests/manual/cubemask-demo/image.py +0 -0
  133. {cubevis-0.5.24 → cubevis-0.5.25}/tests/manual/iclean-demo/m100_interactive.py +0 -0
  134. {cubevis-0.5.24 → cubevis-0.5.25}/tests/manual/iclean-demo/mask0-iclean.py +0 -0
  135. {cubevis-0.5.24 → cubevis-0.5.25}/tests/manual/iclean-demo/run-gclean.py +0 -0
  136. {cubevis-0.5.24 → cubevis-0.5.25}/tests/manual/iclean-demo/run-iclean-obj.py +0 -0
  137. {cubevis-0.5.24 → cubevis-0.5.25}/tests/manual/iclean-demo/run-iclean.py +0 -0
  138. {cubevis-0.5.24 → cubevis-0.5.25}/tests/manual/iclean-demo/vla-sim-jet-iclean.py +0 -0
  139. {cubevis-0.5.24 → cubevis-0.5.25}/tests/manual/iclean-first-look/run-fl-cont.py +0 -0
  140. {cubevis-0.5.24 → cubevis-0.5.25}/tests/manual/iclean-first-look/run-fl-line.py +0 -0
  141. {cubevis-0.5.24 → cubevis-0.5.25}/tests/manual/iclean-outlier/run-iclean.py +0 -0
  142. {cubevis-0.5.24 → cubevis-0.5.25}/tests/manual/iclean-outlier/test_outlier.txt +0 -0
  143. {cubevis-0.5.24 → cubevis-0.5.25}/tests/manual/iclean-remote/iclean_remote_webserver.py +0 -0
  144. {cubevis-0.5.24 → cubevis-0.5.25}/tests/manual/large-cube/run-largecube.py +0 -0
  145. {cubevis-0.5.24 → cubevis-0.5.25}/tests/manual/svg-test.py +0 -0
  146. {cubevis-0.5.24 → cubevis-0.5.25}/tests/manual/updatable-data-source/direct-plot.py +0 -0
  147. {cubevis-0.5.24 → cubevis-0.5.25}/tests/manual/updatable-data-source/simple-update.py +0 -0
  148. {cubevis-0.5.24 → cubevis-0.5.25}/tests/manual/updatable-data-source/updated-plot.py +0 -0
  149. {cubevis-0.5.24 → cubevis-0.5.25}/tests/manual/uranus-demo/uranus-iclean.py +0 -0
  150. {cubevis-0.5.24 → cubevis-0.5.25}/tests/manual/websocket-reconnect/client.html +0 -0
  151. {cubevis-0.5.24 → cubevis-0.5.25}/tests/manual/websocket-reconnect/server.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: cubevis
3
- Version: 0.5.24
3
+ Version: 0.5.25
4
4
  Summary: visualization toolkit and apps for casa
5
5
  License: LGPL
6
6
  Author-email: Darrell Schiebel <darrell@schiebel.us>,Pam Harris <pharris@nrao.edu>
@@ -42,7 +42,7 @@
42
42
  }
43
43
  })
44
44
  ({
45
- "de17b915c5": function _(a,t,e,o,c){o();const n=a("tslib"),i=a("b33e822163");c("DataPipe",i.DataPipe);const s=a("2889e0dd45");c("ImagePipe",s.ImagePipe);const p=a("de65005924");c("ImageDataSource",p.ImageDataSource);const r=a("02e3c3e46c");c("SpectraDataSource",r.SpectraDataSource);const T=a("64b16deff9");c("UpdatableDataSource",T.UpdatableDataSource);const l=a("b6ae454f0d");c("WcsTicks",l.WcsTicks);const u=a("cb7d28d6b3");c("DragTool",u.DragTool);const S=a("01959f25a3");c("CBResetTool",S.CBResetTool);const D=a("e3901fa9f2");c("serialize",D.serialize),c("deserialize",D.deserialize);const d=a("9f961622ce");c("TipButton",d.TipButton);const b=a("ca4c845905");c("Tip",b.Tip);const g=a("b55081402e");c("EditSpan",g.EditSpan);const E=a("9144bfc7a5");c("EvTextInput",E.EvTextInput);const I=a("74e0abef8a");c("EvPolyAnnotation",I.EvPolyAnnotation);const P=n.__importStar(a("15b954190c"));e.find=P;(0,a("@bokehjs/base").register_models)({DataPipe:i.DataPipe,ImagePipe:s.ImagePipe,ImageDataSource:p.ImageDataSource,SpectraDataSource:r.SpectraDataSource,UpdatableDataSource:T.UpdatableDataSource,WcsTicks:l.WcsTicks,DragTool:u.DragTool,CBResetTool:S.CBResetTool,Tip:b.Tip,TipButton:d.TipButton,EditSpan:g.EditSpan,EvTextInput:E.EvTextInput,EvPolyAnnotation:I.EvPolyAnnotation})},
45
+ "97397933dc": function _(a,t,e,o,c){o();const i=a("tslib"),n=a("b33e822163");c("DataPipe",n.DataPipe);const s=a("2889e0dd45");c("ImagePipe",s.ImagePipe);const p=a("de65005924");c("ImageDataSource",p.ImageDataSource);const r=a("02e3c3e46c");c("SpectraDataSource",r.SpectraDataSource);const S=a("64b16deff9");c("UpdatableDataSource",S.UpdatableDataSource);const D=a("b6ae454f0d");c("WcsTicks",D.WcsTicks);const T=a("cb7d28d6b3");c("DragTool",T.DragTool);const d=a("01959f25a3");c("CBResetTool",d.CBResetTool);const l=a("e3901fa9f2");c("serialize",l.serialize),c("deserialize",l.deserialize);const u=a("9f961622ce");c("TipButton",u.TipButton);const b=a("ca4c845905");c("Tip",b.Tip);const g=a("50a1e32f01");c("SharedDict",g.SharedDict);const f=a("b55081402e");c("EditSpan",f.EditSpan);const E=a("9144bfc7a5");c("EvTextInput",E.EvTextInput);const I=a("74e0abef8a");c("EvPolyAnnotation",I.EvPolyAnnotation);const P=i.__importStar(a("15b954190c"));e.find=P;(0,a("@bokehjs/base").register_models)({DataPipe:n.DataPipe,ImagePipe:s.ImagePipe,ImageDataSource:p.ImageDataSource,SpectraDataSource:r.SpectraDataSource,UpdatableDataSource:S.UpdatableDataSource,WcsTicks:D.WcsTicks,DragTool:T.DragTool,CBResetTool:d.CBResetTool,Tip:b.Tip,TipButton:u.TipButton,SharedDict:g.SharedDict,EditSpan:f.EditSpan,EvTextInput:E.EvTextInput,EvPolyAnnotation:I.EvPolyAnnotation})},
46
46
  "b33e822163": function _(e,s,t,i,n){var o;i();const c=e("@bokehjs/models/sources/data_source"),a=e("e3901fa9f2"),d=e("@bokehjs/core/util/callbacks");class l extends c.DataSource{constructor(e){super(e),this.send_queue={},this.connection_queue=[],this.pending={},this.incoming_callbacks={}}initialize(){super.initialize();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(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:casalib.object_id(this)}))}}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:casalib.object_id(this)})),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)}}};t();(()=>{null!=this.init_script&&(0,d.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:casalib.object_id(this)};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:d,msg:l}=this.send_queue[e].shift();if(this.pending[e]={cb:d},this.websocket.readyState===WebSocket.OPEN)this.websocket.send((0,a.serialize)(l));else{let u=20,h=this;function r(){h.websocket.readyState===WebSocket.OPEN?h.websocket.send((0,a.serialize)(l)):(u-=1,u>0&&setTimeout(r,3e3))}setTimeout(r,3e3)}}}else if(this.websocket.readyState===WebSocket.OPEN)this.pending[e]={cb:t},this.websocket.send((0,a.serialize)(n));else{let b=20,g=this;function _(){g.websocket.readyState===WebSocket.OPEN?(g.pending[e]={cb:t},g.websocket.send((0,a.serialize)(n))):(b-=1,b>0&&setTimeout(_,3e3))}setTimeout(_,3e3)}}}t.DataPipe=l,o=l,l.__name__="DataPipe",l.__module__="cubevis.bokeh.sources._data_pipe",o.define((({Any:e,Tuple:s,String:t,Number:i})=>({init_script:[e,null],address:[s(t,i)]})))},
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
  "2889e0dd45": function _(i,e,s,t,n){var a;t();const o=i("@bokehjs/models/sources/column_data_source"),d=i("b33e822163");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]})))},
@@ -56,7 +56,8 @@
56
56
  "01959f25a3": 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
+ "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),{}]})))},
59
60
  "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},
60
61
  "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=_},
61
62
  "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=_},
62
- }, "de17b915c5", {"index":"de17b915c5","src/bokeh/sources/data_pipe":"b33e822163","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":"949501ff1c","src/bokeh/util/find":"15b954190c","src/bokeh/tools/cbreset_tool":"01959f25a3","src/bokeh/models/tip_button":"9f961622ce","src/bokeh/models/tip":"ca4c845905","src/bokeh/models/edit_span":"b55081402e","src/bokeh/models/ev_text_input":"9144bfc7a5","src/bokeh/annotations/ev_poly_annotation":"74e0abef8a"}, {});});
63
+ }, "97397933dc", {"index":"97397933dc","src/bokeh/sources/data_pipe":"b33e822163","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":"949501ff1c","src/bokeh/util/find":"15b954190c","src/bokeh/tools/cbreset_tool":"01959f25a3","src/bokeh/models/tip_button":"9f961622ce","src/bokeh/models/tip":"ca4c845905","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,3 +2,4 @@ from ._tip_button import TipButton
2
2
  from ._tip import Tip
3
3
  from ._edit_span import EditSpan
4
4
  from ._ev_text_input import EvTextInput
5
+ from ._shared_dict import SharedDict
@@ -0,0 +1,23 @@
1
+ from bokeh.models import Model
2
+ from bokeh.models.layouts import LayoutDOM, UIElement
3
+ from bokeh.core.properties import Dict, Any, String, Required
4
+
5
+ class SharedDict(Model):
6
+ '''Display a tooltip for the child element
7
+ '''
8
+
9
+ def __init__(self, *args, **kwargs) -> None:
10
+ if len(args) != 1 and "values" not in kwargs:
11
+ raise ValueError("a 'values' argument must be supplied")
12
+ elif len(args) == 1 and "values" in kwargs:
13
+ raise ValueError("'values' supplied as both a positional argument and a keyword")
14
+ elif len(args) > 1:
15
+ raise ValueError("only one 'values' can be supplied as a positional argument")
16
+ elif len(args) > 0:
17
+ kwargs["values"] = args[0]
18
+
19
+ super().__init__(**kwargs)
20
+
21
+ values = Required(Dict(String, Any), help="""
22
+ Python dictionary to be shared among multiple JavaScript callbacks.
23
+ """)
@@ -55,7 +55,7 @@ from cubevis.bokeh.format import WcsTicks
55
55
  from cubevis.bokeh.models import EditSpan
56
56
  from ..data import casaimage
57
57
  from ..utils import pack_arrays, find_ws_address, set_attributes, resource_manager, polygon_indexes, is_interactive_jupyter, have_firefox
58
- from ..bokeh.models import EvTextInput
58
+ from ..bokeh.models import EvTextInput, SharedDict
59
59
  from ..bokeh.tools import CBResetTool
60
60
  from ..bokeh.state import available_palettes, find_palette, default_palette
61
61
  from ..bokeh.annotations import EvPolyAnnotation
@@ -188,6 +188,12 @@ class CubeMask:
188
188
  self._image_freeze_cb = [ ] # CustomJS to be invoked when the use freezes cursor tracking (by typing 'f')
189
189
  self._image_unfreeze_cb = [ ] # CustomJS to be invoked when cursor tracking is unfrozen
190
190
 
191
+ ###
192
+ ### This state object is provided as "this.disable_add_sub" when "init_script" is called.
193
+ ### By setting "disable_add_sub.values.disabled = True", the user can disable mask updates.
194
+ ###
195
+ self._mask_add_sub_disable = SharedDict( { 'disabled': False, 'message': None } )
196
+
191
197
  if self._mask_path:
192
198
  ###########################################################################################################################
193
199
  ### JavaScript init script to be run early in the startup. Piggybacked off of the ImagePipe initialization ###
@@ -1456,6 +1462,7 @@ class CubeMask:
1456
1462
  contour_ds=self._bitmask_contour_ds,
1457
1463
  status=self._status_div, statprec=7,
1458
1464
  selector=self._bitmask_color_selector,
1465
+ disable_add_sub = self._mask_add_sub_disable,
1459
1466
  user_init_script = self.init_script,
1460
1467
  freeze_cb = self._image_freeze_cb )
1461
1468
 
@@ -1465,7 +1472,8 @@ class CubeMask:
1465
1472
  ''' + self._js['mask-state-init'] +
1466
1473
  ( self._js['func-curmasks']( ) +
1467
1474
  self._js['key-state-funcs']
1468
- if self._mask_path is None else '' ) + self._js['setup-key-mgmt'] +
1475
+ if self._mask_path is None else '' ) +
1476
+ self._js['update-status'] + self._js['setup-key-mgmt'] +
1469
1477
  """// This function is called to collect the masks and/or stop
1470
1478
  // -->> collect_masks( ) is only defined if bitmask cube is NOT used
1471
1479
  document._cube_done = ( final_polys=null, cb=null ) => {
@@ -1511,6 +1519,8 @@ class CubeMask:
1511
1519
  stats_source.data = data
1512
1520
  }
1513
1521
  if ( stats_source ) source.update_statistics( stats_source.data ) /*** round pre-filled floats ***/
1522
+ /*** this is the hook that allows the user to disable mask changes ***/
1523
+ this.disable_add_sub = disable_add_sub
1514
1524
  if ( user_init_script ) { user_init_script.execute(this) }
1515
1525
  """ )
1516
1526
 
@@ -1619,12 +1629,6 @@ class CubeMask:
1619
1629
  {input_screen}.value_ = {input_screen}.value = center.toFixed(5)
1620
1630
  }}'''
1621
1631
 
1622
- update_status = '''function update_status( str ) {
1623
- const msg = `<b style='color:red;'>${str}</b>`
1624
- status.text = msg
1625
- setTimeout( ( ) => { if ( status.text == msg ) status.text = '' }, 5000 )
1626
- }'''
1627
-
1628
1632
  self._region_controls['tracking']['color-picker'].child.js_on_change( 'color',
1629
1633
  CustomJS( args=dict( tracker=self._region_controls['tracking']['pointer'] ),
1630
1634
  code='''tracker.line_color = cb_obj.color
@@ -1685,15 +1689,15 @@ class CubeMask:
1685
1689
  text=text, source=self._image_source,
1686
1690
  status=self._region_controls['coord']['status'],
1687
1691
  stokes=(index,s) ),
1688
- code=parse_ranges + update_status +
1692
+ code=parse_ranges + self._js['update-status'] +
1689
1693
  #self._js['func-curmasks']('isource') +
1690
1694
  '''if ( tracker._current_region ) {
1691
1695
  status.text=''
1692
1696
  const ranges = casalib.strparse_intranges(cb_obj.value,true)
1693
1697
  const minmax = casalib.minmax(ranges.flat(Infinity))
1694
1698
 
1695
- if ( minmax[0] < 0 ) nupdate_status('negative range')
1696
- else if ( minmax[1] >= source.num_chans[1] ) update_status('exceeds channel range')
1699
+ if ( minmax[0] < 0 ) update_status_error('negative range')
1700
+ else if ( minmax[1] >= source.num_chans[1] ) update_status_error('exceeds channel range')
1697
1701
  else {
1698
1702
  const chans_as_set = ranges.reduce(
1699
1703
  (set,v) => casalib.forexpr( v[0], v[1], (s,i) => s.add([stokes[0],i]), set),
@@ -1704,7 +1708,7 @@ class CubeMask:
1704
1708
  if (chan[0] == stokes[0]) acc.push(chan[1])
1705
1709
  return acc }, chans_as_set, [ ] ) )
1706
1710
  }
1707
- } else update_status('no region selected')''' ) )
1711
+ } else update_status_error('no region selected')''' ) )
1708
1712
 
1709
1713
  ###
1710
1714
  ### set _region_controls_newpoly so it can be passed along and eventuall called by
@@ -1832,8 +1836,10 @@ class CubeMask:
1832
1836
  mask_region_button=self._mask_add_sub['mask'],
1833
1837
  mask_region_ds=self._bitmask_contour_maskmod_ds,
1834
1838
  contour_ds=self._bitmask_contour_ds,
1839
+ disable_add_sub = self._mask_add_sub_disable,
1835
1840
  status=self._status_div ),
1836
- code=self._js_mode_code['bitmask-hotkey-setup-add-sub'] +
1841
+ code=self._js['update-status'] +
1842
+ self._js_mode_code['bitmask-hotkey-setup-add-sub'] +
1837
1843
  '''if ( cb_obj._mode == 'cube' ) mask_add_cube( )
1838
1844
  else mask_add_chan( )''' )
1839
1845
  self._mask_add_sub['sub'].callback = CustomJS( args=dict( annotations=self._annotations,
@@ -1845,8 +1851,10 @@ class CubeMask:
1845
1851
  mask_region_button=self._mask_add_sub['mask'],
1846
1852
  mask_region_ds=self._bitmask_contour_maskmod_ds,
1847
1853
  contour_ds=self._bitmask_contour_ds,
1854
+ disable_add_sub = self._mask_add_sub_disable,
1848
1855
  status=self._status_div ),
1849
- code=self._js_mode_code['bitmask-hotkey-setup-add-sub'] +
1856
+ code=self._js['update-status'] +
1857
+ self._js_mode_code['bitmask-hotkey-setup-add-sub'] +
1850
1858
  '''if ( cb_obj._mode == 'cube' ) mask_sub_cube( )
1851
1859
  else mask_sub_chan( )''' )
1852
1860
 
@@ -1858,8 +1866,10 @@ class CubeMask:
1858
1866
  mask_region_button=self._mask_add_sub['mask'],
1859
1867
  mask_region_icons=self._mask_icons_,
1860
1868
  source=self._image_source,
1869
+ disable_add_sub = self._mask_add_sub_disable,
1861
1870
  status=self._status_div ),
1862
- code=self._js_mode_code['bitmask-hotkey-setup-add-sub'] +
1871
+ code=self._js['update-status'] +
1872
+ self._js_mode_code['bitmask-hotkey-setup-add-sub'] +
1863
1873
  '''if ( mask_region_button.icon == mask_region_icons['on'] ) source._mask.clear( )
1864
1874
  else source.mask.set( region )''' )
1865
1875
 
@@ -2258,6 +2268,7 @@ class CubeMask:
2258
2268
  ###########################################################################################################################
2259
2269
  self._js_mode_code = {
2260
2270
  'bitmask-hotkey-setup-add-sub': '''
2271
+ const default_add_sub_disabled_text = 'mask ops currently disabled'
2261
2272
  function mask_mod_result( msg ) {
2262
2273
  if ( msg.result == 'success' ) {
2263
2274
  if ( 'update' in msg && 'clear_region' in msg.update && msg.update.clear_region ) {
@@ -2268,6 +2279,12 @@ class CubeMask:
2268
2279
  }
2269
2280
  }
2270
2281
  function mask_add_chan( ) {
2282
+ if ( disable_add_sub.values.disabled ) {
2283
+ update_status_error( disable_add_sub.values.message ?
2284
+ disable_add_sub.values.message :
2285
+ default_add_sub_disabled_text )
2286
+ return
2287
+ }
2271
2288
  const anno = source._mask.get( )
2272
2289
  if ( anno.xs.length > 0 && anno.ys.length > 0 ) {
2273
2290
  ctrl.send( ids['mask-mod'],
@@ -2287,6 +2304,12 @@ class CubeMask:
2287
2304
  } else if ( status ) status.text = '<p>no region found</p>'
2288
2305
  }
2289
2306
  function mask_sub_chan( ) {
2307
+ if ( disable_add_sub.values.disabled ) {
2308
+ update_status_error( disable_add_sub.values.message ?
2309
+ disable_add_sub.values.message :
2310
+ default_add_sub_disabled_text )
2311
+ return
2312
+ }
2290
2313
  if ( annotations[0].xs.length > 0 && annotations[0].ys.length > 0 ) {
2291
2314
  ctrl.send( ids['mask-mod'],
2292
2315
  { scope: 'chan',
@@ -2305,6 +2328,12 @@ class CubeMask:
2305
2328
  } else if ( status ) status.text = '<p>no region found</p>'
2306
2329
  }
2307
2330
  function mask_add_cube( ) {
2331
+ if ( disable_add_sub.values.disabled ) {
2332
+ update_status_error( disable_add_sub.values.message ?
2333
+ disable_add_sub.values.message :
2334
+ default_add_sub_disabled_text )
2335
+ return
2336
+ }
2308
2337
  if ( annotations[0].xs.length > 0 && annotations[0].ys.length > 0 ) {
2309
2338
  ctrl.send( ids['mask-mod'],
2310
2339
  { scope: 'cube',
@@ -2323,6 +2352,12 @@ class CubeMask:
2323
2352
  } else if ( status ) status.text = '<p>no region found</p>'
2324
2353
  }
2325
2354
  function mask_sub_cube( ) {
2355
+ if ( disable_add_sub.values.disabled ) {
2356
+ update_status_error( disable_add_sub.values.message ?
2357
+ disable_add_sub.values.message :
2358
+ default_add_sub_disabled_text )
2359
+ return
2360
+ }
2326
2361
  if ( annotations[0].xs.length > 0 && annotations[0].ys.length > 0 ) {
2327
2362
  ctrl.send( ids['mask-mod'],
2328
2363
  { scope: 'cube',
@@ -2829,6 +2864,13 @@ class CubeMask:
2829
2864
 
2830
2865
  self._js = { ### ImagePipe initialization code which manages the shift-key behavior which swiches between
2831
2866
  ### addition/subtraction to a single channel VS add/sub from all channels of the cube...
2867
+ 'update-status': '''function update_status_error( str ) {
2868
+ if ( status ) {
2869
+ const msg = `<b style='color:red;'>${str}</b>`
2870
+ status.text = msg
2871
+ setTimeout( ( ) => { if ( status.text === msg ) status.text = '' }, 5000 )
2872
+ }
2873
+ }''',
2832
2874
  'cube-init': '''add._mode = 'chan'
2833
2875
  sub._mode = 'chan'
2834
2876
  let foo = casalib.is_empty
@@ -279,6 +279,23 @@ class InteractiveCleanUI:
279
279
  imdetails['path']['residual'] = join( output_dir, self._clean['gclean_paths'][imid]['residualname'] )
280
280
  imdetails['path']['mask'] = join( output_dir, self._clean['gclean_paths'][imid]['maskname'] )
281
281
 
282
+ ###
283
+ ### There is one set of tclean controls for all images/outlier/etc. because
284
+ ### in the final version gclean will handle the iterations for all fields...
285
+ ###
286
+ cwidth = 64
287
+ cheight = 40
288
+ self._control['iteration'] = { }
289
+ self._control['iteration']['continue'] = TipButton( max_width=cwidth, max_height=cheight, name='continue',
290
+ icon=svg_icon(icon_name="iclean-continue", size=18),
291
+ tooltip=Tooltip( content=HTML( '''Stop after <b>one major cycle</b> or when any stopping criteria is met.''' ), position='left') )
292
+ self._control['iteration']['finish'] = TipButton( max_width=cwidth, max_height=cheight, name='finish',
293
+ icon=svg_icon(icon_name="iclean-finish", size=18),
294
+ tooltip=Tooltip( content=HTML( '''<b>Continue</b> until some stopping criteria is met.''' ), position='left') )
295
+ self._control['iteration']['stop'] = TipButton( button_type="danger", max_width=cwidth, max_height=cheight, name='stop',
296
+ icon=svg_icon(icon_name="iclean-stop", size=18),
297
+ tooltip=Tooltip( content=HTML( '''<p>Clicking a <font color="red">red</font> stop button will cause this tab to close and control will return to Python.<p>Clicking an <font color="orange">orange</font> stop button will cause <tt>tclean</tt> to stop after the current major cycle.''' ), position='left' ) )
298
+
282
299
  for idx, (imid, imdetails) in enumerate(self._clean_targets.items( )):
283
300
  imdetails['gui'] = { }
284
301
 
@@ -291,8 +308,13 @@ class InteractiveCleanUI:
291
308
  ###
292
309
  imdetails['gui']['cube'] = CubeMask( imdetails['path']['residual'], mask=imdetails['path']['mask'], abort=self._abort_handler,
293
310
  init_script=CustomJS( args=dict( initial_convergence_state=self._init_values["convergence_state"],
311
+ clean_ctrl=self._control['iteration'],
294
312
  name=imid ),
295
- code='''document._casa_convergence_data = initial_convergence_state''' )
313
+ code='''document._casa_convergence_data = initial_convergence_state
314
+ clean_ctrl.continue.disable_add_sub = this.disable_add_sub.values
315
+ clean_ctrl.finish.disable_add_sub = this.disable_add_sub.values
316
+ clean_ctrl.stop.disable_add_sub = this.disable_add_sub.values
317
+ this.disable_add_sub.values.message = "cannot modify mask during cleaning"''' )
296
318
  if idx == 0 else None )
297
319
 
298
320
  ###
@@ -588,24 +610,6 @@ class InteractiveCleanUI:
588
610
  #print("%s: %s" % ( btn, self._clean_ids[btn] ) )
589
611
  self._pipe['control'].register( self._clean_ids[btn], clean_handler )
590
612
 
591
-
592
- ###
593
- ### There is one set of tclean controls for all images/outlier/etc. because
594
- ### in the final version gclean will handle the iterations for all fields...
595
- ###
596
- cwidth = 64
597
- cheight = 40
598
- self._control['iteration'] = { }
599
- self._control['iteration']['continue'] = TipButton( max_width=cwidth, max_height=cheight, name='continue',
600
- icon=svg_icon(icon_name="iclean-continue", size=18),
601
- tooltip=Tooltip( content=HTML( '''Stop after <b>one major cycle</b> or when any stopping criteria is met.''' ), position='left') )
602
- self._control['iteration']['finish'] = TipButton( max_width=cwidth, max_height=cheight, name='finish',
603
- icon=svg_icon(icon_name="iclean-finish", size=18),
604
- tooltip=Tooltip( content=HTML( '''<b>Continue</b> until some stopping criteria is met.''' ), position='left') )
605
- self._control['iteration']['stop'] = TipButton( button_type="danger", max_width=cwidth, max_height=cheight, name='stop',
606
- icon=svg_icon(icon_name="iclean-stop", size=18),
607
- tooltip=Tooltip( content=HTML( '''<p>Clicking a <font color="red">red</font> stop button will cause this tab to close and control will return to Python.<p>Clicking an <font color="orange">orange</font> stop button will cause <tt>tclean</tt> to stop after the current major cycle.''' ), position='left' ) )
608
-
609
613
  ###
610
614
  ### The single SHARED help button will be supplied by the first CubeMask...
611
615
  ###
@@ -785,6 +789,7 @@ class InteractiveCleanUI:
785
789
  margin=(-1, 0, -10, 0), button_type='light',
786
790
  stylesheets=[ InlineStyleSheet( css='''.bk-btn { border: 0px solid #ccc; padding: 0 var(--padding-vertical) var(--padding-horizontal); margin-top: 3px; }''' ) ] )
787
791
 
792
+
788
793
  self._control['iteration']['cb'] = CustomJS( args=dict( images_state={ k: { 'status': v['gui']['stopcode'],
789
794
  'automask': v['gui']['params']['automask'],
790
795
  'iteration': v['gui']['params']['iteration'],
@@ -1453,6 +1458,7 @@ class InteractiveCleanUI:
1453
1458
  )
1454
1459
  }
1455
1460
  )
1461
+ clean_ctrl.continue.disable_add_sub.disabled = true
1456
1462
  clean_ctrl.continue.disabled = true
1457
1463
  clean_ctrl.finish.disabled = true
1458
1464
  clean_ctrl.stop.disabled = with_stop
@@ -1477,6 +1483,7 @@ class InteractiveCleanUI:
1477
1483
 
1478
1484
  clean_ctrl.stop.disabled = false
1479
1485
  if ( ! only_stop ) {
1486
+ clean_ctrl.continue.disable_add_sub.disabled = false
1480
1487
  clean_ctrl.continue.disabled = false
1481
1488
  clean_ctrl.finish.disabled = false
1482
1489
  }
@@ -278,6 +278,23 @@ class InteractiveCleanUI:
278
278
  imdetails['path']['residual'] = join( output_dir, self._clean['gclean_paths'][imid]['residualname'] )
279
279
  imdetails['path']['mask'] = join( output_dir, self._clean['gclean_paths'][imid]['maskname'] )
280
280
 
281
+ ###
282
+ ### There is one set of tclean controls for all images/outlier/etc. because
283
+ ### in the final version gclean will handle the iterations for all fields...
284
+ ###
285
+ cwidth = 64
286
+ cheight = 40
287
+ self._control['iteration'] = { }
288
+ self._control['iteration']['continue'] = TipButton( max_width=cwidth, max_height=cheight, name='continue',
289
+ icon=svg_icon(icon_name="iclean-continue", size=18),
290
+ tooltip=Tooltip( content=HTML( '''Stop after <b>one major cycle</b> or when any stopping criteria is met.''' ), position='left') )
291
+ self._control['iteration']['finish'] = TipButton( max_width=cwidth, max_height=cheight, name='finish',
292
+ icon=svg_icon(icon_name="iclean-finish", size=18),
293
+ tooltip=Tooltip( content=HTML( '''<b>Continue</b> until some stopping criteria is met.''' ), position='left') )
294
+ self._control['iteration']['stop'] = TipButton( button_type="danger", max_width=cwidth, max_height=cheight, name='stop',
295
+ icon=svg_icon(icon_name="iclean-stop", size=18),
296
+ tooltip=Tooltip( content=HTML( '''<p>Clicking a <font color="red">red</font> stop button will cause this tab to close and control will return to Python.<p>Clicking an <font color="orange">orange</font> stop button will cause <tt>tclean</tt> to stop after the current major cycle.''' ), position='left' ) )
297
+
281
298
  for idx, (imid, imdetails) in enumerate(self._clean_targets.items( )):
282
299
  imdetails['gui'] = { }
283
300
 
@@ -290,8 +307,13 @@ class InteractiveCleanUI:
290
307
  ###
291
308
  imdetails['gui']['cube'] = CubeMask( imdetails['path']['residual'], mask=imdetails['path']['mask'], abort=self._abort_handler,
292
309
  init_script=CustomJS( args=dict( initial_convergence_state=self._init_values["convergence_state"],
310
+ clean_ctrl=self._control['iteration'],
293
311
  name=imid ),
294
- code='''document._casa_convergence_data = initial_convergence_state''' )
312
+ code='''document._casa_convergence_data = initial_convergence_state
313
+ clean_ctrl.continue.disable_add_sub = this.disable_add_sub.values
314
+ clean_ctrl.finish.disable_add_sub = this.disable_add_sub.values
315
+ clean_ctrl.stop.disable_add_sub = this.disable_add_sub.values
316
+ this.disable_add_sub.values.message = "cannot modify mask during cleaning"''' )
295
317
  if idx == 0 else None )
296
318
 
297
319
  ###
@@ -587,24 +609,6 @@ class InteractiveCleanUI:
587
609
  #print("%s: %s" % ( btn, self._clean_ids[btn] ) )
588
610
  self._pipe['control'].register( self._clean_ids[btn], clean_handler )
589
611
 
590
-
591
- ###
592
- ### There is one set of tclean controls for all images/outlier/etc. because
593
- ### in the final version gclean will handle the iterations for all fields...
594
- ###
595
- cwidth = 64
596
- cheight = 40
597
- self._control['iteration'] = { }
598
- self._control['iteration']['continue'] = TipButton( max_width=cwidth, max_height=cheight, name='continue',
599
- icon=svg_icon(icon_name="iclean-continue", size=18),
600
- tooltip=Tooltip( content=HTML( '''Stop after <b>one major cycle</b> or when any stopping criteria is met.''' ), position='left') )
601
- self._control['iteration']['finish'] = TipButton( max_width=cwidth, max_height=cheight, name='finish',
602
- icon=svg_icon(icon_name="iclean-finish", size=18),
603
- tooltip=Tooltip( content=HTML( '''<b>Continue</b> until some stopping criteria is met.''' ), position='left') )
604
- self._control['iteration']['stop'] = TipButton( button_type="danger", max_width=cwidth, max_height=cheight, name='stop',
605
- icon=svg_icon(icon_name="iclean-stop", size=18),
606
- tooltip=Tooltip( content=HTML( '''<p>Clicking a <font color="red">red</font> stop button will cause this tab to close and control will return to Python.<p>Clicking an <font color="orange">orange</font> stop button will cause <tt>tclean</tt> to stop after the current major cycle.''' ), position='left' ) )
607
-
608
612
  ###
609
613
  ### The single SHARED help button will be supplied by the first CubeMask...
610
614
  ###
@@ -784,6 +788,7 @@ class InteractiveCleanUI:
784
788
  margin=(-1, 0, -10, 0), button_type='light',
785
789
  stylesheets=[ InlineStyleSheet( css='''.bk-btn { border: 0px solid #ccc; padding: 0 var(--padding-vertical) var(--padding-horizontal); margin-top: 3px; }''' ) ] )
786
790
 
791
+
787
792
  self._control['iteration']['cb'] = CustomJS( args=dict( images_state={ k: { 'status': v['gui']['stopcode'],
788
793
  'automask': v['gui']['params']['automask'],
789
794
  'iteration': v['gui']['params']['iteration'],
@@ -1452,6 +1457,7 @@ class InteractiveCleanUI:
1452
1457
  )
1453
1458
  }
1454
1459
  )
1460
+ clean_ctrl.continue.disable_add_sub.disabled = true
1455
1461
  clean_ctrl.continue.disabled = true
1456
1462
  clean_ctrl.finish.disabled = true
1457
1463
  clean_ctrl.stop.disabled = with_stop
@@ -1476,6 +1482,7 @@ class InteractiveCleanUI:
1476
1482
 
1477
1483
  clean_ctrl.stop.disabled = false
1478
1484
  if ( ! only_stop ) {
1485
+ clean_ctrl.continue.disable_add_sub.disabled = false
1479
1486
  clean_ctrl.continue.disabled = false
1480
1487
  clean_ctrl.finish.disabled = false
1481
1488
  }
@@ -16,7 +16,7 @@ dependencies = [
16
16
  ]
17
17
  requires-python = ">=3.10"
18
18
  readme = "readme.rst"
19
- version = "0.5.24"
19
+ version = "0.5.25"
20
20
 
21
21
  [project.license]
22
22
  text = "LGPL"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes