cubevis 0.5.23__tar.gz → 0.5.24__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-0.5.23 → cubevis-0.5.24}/PKG-INFO +1 -1
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/toolbox/_cube.py +1 -1
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/toolbox/_interactive_clean_ui.mustache +213 -72
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/toolbox/_interactive_clean_ui.py +213 -72
- {cubevis-0.5.23 → cubevis-0.5.24}/pyproject.toml +1 -1
- {cubevis-0.5.23 → cubevis-0.5.24}/LICENSE +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/LICENSE.rst +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/__icons__/20px/fast-backward.svg +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/__icons__/20px/fast-forward.svg +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/__icons__/20px/step-backward.svg +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/__icons__/20px/step-forward.svg +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/__icons__/add-chan.png +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/__icons__/add-chan.svg +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/__icons__/add-cube.png +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/__icons__/add-cube.svg +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/__icons__/drag.png +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/__icons__/drag.svg +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/__icons__/mask-selected.png +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/__icons__/mask.png +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/__icons__/mask.svg +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/__icons__/new-layer-sm-selected.png +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/__icons__/new-layer-sm-selected.svg +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/__icons__/new-layer-sm.png +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/__icons__/new-layer-sm.svg +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/__icons__/reset.png +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/__icons__/reset.svg +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/__icons__/sub-chan.png +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/__icons__/sub-chan.svg +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/__icons__/sub-cube.png +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/__icons__/sub-cube.svg +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/__icons__/zoom-to-fit.png +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/__icons__/zoom-to-fit.svg +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/__init__.py +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/__js__/bokeh-3.6.1.min.js +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/__js__/bokeh-tables-3.6.1.min.js +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/__js__/bokeh-widgets-3.6.1.min.js +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/__js__/casalib.min.js +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/__js__/cubevisjs.min.js +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/bokeh/__init__.py +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/bokeh/annotations/__init__.py +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/bokeh/annotations/_ev_poly_annotation.py +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/bokeh/components/__init__.py +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/bokeh/format/__init__.py +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/bokeh/format/_time_ticks.py +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/bokeh/format/_wcs_ticks.py +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/bokeh/models/__init__.py +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/bokeh/models/_edit_span.py +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/bokeh/models/_ev_text_input.py +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/bokeh/models/_tip.py +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/bokeh/models/_tip_button.py +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/bokeh/sources/__init__.py +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/bokeh/sources/_data_pipe.py +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/bokeh/sources/_image_data_source.py +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/bokeh/sources/_image_pipe.py +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/bokeh/sources/_spectra_data_source.py +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/bokeh/sources/_updatable_data_source.py +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/bokeh/state/__init__.py +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/bokeh/state/_initialize.py +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/bokeh/state/_javascript.py +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/bokeh/state/_palette.py +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/bokeh/state/_session.py +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/bokeh/state/js/bokeh-2.4.1.min.js +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/bokeh/state/js/bokeh-gl-2.4.1.min.js +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/bokeh/state/js/bokeh-tables-2.4.1.min.js +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/bokeh/state/js/bokeh-widgets-2.4.1.min.js +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/bokeh/state/js/casaguijs-v0.0.4.0-b2.4.min.js +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/bokeh/state/js/casaguijs-v0.0.5.0-b2.4.min.js +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/bokeh/state/js/casaguijs-v0.0.6.0-b2.4.min.js +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/bokeh/state/js/casalib-v0.0.1.min.js +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/bokeh/tools/__init__.py +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/bokeh/tools/_cbreset_tool.py +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/bokeh/tools/_drag_tool.py +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/bokeh/utils/__init__.py +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/bokeh/utils/_axes_labels.py +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/bokeh/utils/_svg_icon.py +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/data/__init__.py +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/data/casaimage/__init__.py +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/exe/__init__.py +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/exe/_context.py +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/exe/_mode.py +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/exe/_setting.py +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/exe/_task.py +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/private/_gclean.py +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/private/apps/__init__.py +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/private/apps/_createmask.py +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/private/apps/_createregion.py +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/private/apps/_interactiveclean.mustache +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/private/apps/_interactiveclean.py +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/private/apps/_plotants.py +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/private/apps/_plotbandpass.py +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/private/casashell/createmask.py +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/private/casashell/iclean.py +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/private/casatasks/__init__.py +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/private/casatasks/createmask.py +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/private/casatasks/createregion.py +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/private/casatasks/iclean.py +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/readme.rst +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/remote/__init__.py +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/remote/_gclean.py +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/remote/_local.py +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/remote/_remote_kernel.py +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/toolbox/__init__.py +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/toolbox/_app_context.py +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/toolbox/_interactiveclean_wrappers.py +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/toolbox/_region_list.py +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/utils/_ResourceManager.py +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/utils/__init__.py +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/utils/_browser.py +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/utils/_contextmgrchain.py +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/utils/_conversion.py +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/utils/_copydoc.py +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/utils/_docenum.py +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/utils/_import_protected_module.py +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/utils/_jupyter.py +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/utils/_logging.py +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/utils/_pkgs.py +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/utils/_regions.py +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/utils/_static.py +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/cubevis/utils/_tiles.py +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/readme.rst +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/tests/manual/alma-many-chan/alma-many-chan.py +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/tests/manual/basic-websockets-demo/client.html +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/tests/manual/basic-websockets-demo/client.py +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/tests/manual/basic-websockets-demo/server.py +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/tests/manual/createmask-demo/run-createmask.py +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/tests/manual/createregion-demo/run-createregion.py +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/tests/manual/cubemask-demo/image-slider-spectra-done-stats.py +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/tests/manual/cubemask-demo/image-slider-spectra-done.py +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/tests/manual/cubemask-demo/image-slider-spectra.py +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/tests/manual/cubemask-demo/image-slider.py +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/tests/manual/cubemask-demo/image.py +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/tests/manual/iclean-demo/m100_interactive.py +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/tests/manual/iclean-demo/mask0-iclean.py +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/tests/manual/iclean-demo/run-gclean.py +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/tests/manual/iclean-demo/run-iclean-obj.py +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/tests/manual/iclean-demo/run-iclean.py +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/tests/manual/iclean-demo/vla-sim-jet-iclean.py +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/tests/manual/iclean-first-look/run-fl-cont.py +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/tests/manual/iclean-first-look/run-fl-line.py +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/tests/manual/iclean-outlier/run-iclean.py +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/tests/manual/iclean-outlier/test_outlier.txt +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/tests/manual/iclean-remote/iclean_remote_webserver.py +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/tests/manual/large-cube/run-largecube.py +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/tests/manual/svg-test.py +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/tests/manual/updatable-data-source/direct-plot.py +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/tests/manual/updatable-data-source/simple-update.py +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/tests/manual/updatable-data-source/updated-plot.py +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/tests/manual/uranus-demo/uranus-iclean.py +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/tests/manual/websocket-reconnect/client.html +0 -0
- {cubevis-0.5.23 → cubevis-0.5.24}/tests/manual/websocket-reconnect/server.py +0 -0
|
@@ -2969,8 +2969,8 @@ class CubeMask:
|
|
|
2969
2969
|
( spec ) => {
|
|
2970
2970
|
if ( isource.masking_on( ) )
|
|
2971
2971
|
refresh_pixel_display( spec.index,
|
|
2972
|
+
spec.spectrum.pixel[spec.chan[1]],
|
|
2972
2973
|
'mask' in spec ? spec.mask[spec.chan[1]] : undefined,
|
|
2973
|
-
'mask' in spec && spec.mask[spec.chan[1]],
|
|
2974
2974
|
pix_wrld && pix_wrld.label == 'pixel' ? false : true )
|
|
2975
2975
|
} )
|
|
2976
2976
|
if ( go_to && ! go_to._has_focus ) {
|
|
@@ -45,12 +45,13 @@ import asyncio
|
|
|
45
45
|
import shutil
|
|
46
46
|
import websockets
|
|
47
47
|
from os.path import basename, abspath, exists, join
|
|
48
|
+
import numpy as np
|
|
48
49
|
from uuid import uuid4
|
|
49
50
|
from html import escape as html_escape
|
|
50
51
|
from contextlib import asynccontextmanager
|
|
51
52
|
from bokeh.models import Button, TextInput, Checkbox, Div, LinearAxis, CustomJS, Spacer, Span, HoverTool, DataRange1d, Step, InlineStyleSheet
|
|
52
53
|
from bokeh.events import ModelEvent, MouseEnter
|
|
53
|
-
from bokeh.models import TabPanel, Tabs
|
|
54
|
+
from bokeh.models import TabPanel, Tabs, Range1d
|
|
54
55
|
from bokeh.plotting import ColumnDataSource, figure, show
|
|
55
56
|
from bokeh.layouts import column, row, layout
|
|
56
57
|
from bokeh.io import reset_output as reset_bokeh_output, output_notebook
|
|
@@ -343,57 +344,159 @@ class InteractiveCleanUI:
|
|
|
343
344
|
</div>'''
|
|
344
345
|
|
|
345
346
|
hover = HoverTool( tooltips=TOOLTIPS )
|
|
346
|
-
imdetails['gui']['convergence'] = figure( sizing_mode=sizing_mode, y_axis_location="right",
|
|
347
|
-
tools=[ hover ], toolbar_location=None, **kw )
|
|
348
347
|
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
348
|
+
###
|
|
349
|
+
### Data source that will be used for updating the convergence plot
|
|
350
|
+
###
|
|
351
|
+
stokes = 0
|
|
352
|
+
convergence = imdetails['converge']['chan'][0][stokes]
|
|
353
|
+
imdetails['converge-data'] = { }
|
|
354
|
+
imdetails['converge-data']['flux'] = ColumnDataSource( data=dict( values=convergence['modelFlux'], iterations=convergence['iterations'],
|
|
355
|
+
cyclethreshold=convergence['cycleThresh'],
|
|
356
|
+
stopDesc=list( map( ImagingDict.get_summaryminor_stopdesc, convergence['stopCode'] ) ),
|
|
357
|
+
type=['flux'] * len(convergence['iterations']) ) )
|
|
358
|
+
imdetails['converge-data']['residual'] = ColumnDataSource( data=dict( values=convergence['peakRes'], iterations=convergence['iterations'],
|
|
359
|
+
cyclethreshold=convergence['cycleThresh'],
|
|
360
|
+
stopDesc=list( map( ImagingDict.get_summaryminor_stopdesc, convergence['stopCode'] ) ),
|
|
361
|
+
type=['residual'] * len(convergence['iterations'])) )
|
|
362
|
+
imdetails['converge-data']['cyclethreshold'] = ColumnDataSource( data=dict( values=convergence['cycleThresh'], iterations=convergence['iterations'] ) )
|
|
363
|
+
|
|
364
|
+
# Calculate explicit ranges for each dataset
|
|
365
|
+
flux_values = convergence['modelFlux']
|
|
366
|
+
residual_values = convergence['peakRes']
|
|
367
|
+
iterations = convergence['iterations']
|
|
368
|
+
cyclethresh_values = convergence['cycleThresh']
|
|
369
|
+
|
|
370
|
+
# Calculate ranges with padding
|
|
371
|
+
if len(flux_values) > 0:
|
|
372
|
+
flux_min, flux_max = np.min(flux_values), np.max(flux_values)
|
|
373
|
+
flux_padding = max((flux_max - flux_min) * 0.1, abs(flux_max * 0.05)) if flux_max != flux_min else abs(flux_max * 0.1)
|
|
374
|
+
else:
|
|
375
|
+
flux_min, flux_max, flux_padding = 0, 1, 0.1
|
|
372
376
|
|
|
377
|
+
if len(residual_values) > 0:
|
|
378
|
+
residual_min, residual_max = np.min(residual_values), np.max(residual_values)
|
|
379
|
+
residual_padding = max((residual_max - residual_min) * 0.1, abs(residual_max * 0.05)) if residual_max != residual_min else abs(residual_max * 0.1)
|
|
373
380
|
else:
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
381
|
+
residual_min, residual_max, residual_padding = 0, 1, 0.1
|
|
382
|
+
|
|
383
|
+
# Create Range1d objects
|
|
384
|
+
flux_range = Range1d(start=flux_min - flux_padding, end=flux_max + flux_padding)
|
|
385
|
+
residual_range = Range1d(start=residual_min - residual_padding, end=residual_max + residual_padding)
|
|
386
|
+
|
|
387
|
+
# Ensure ranges are valid (non-zero span)
|
|
388
|
+
if flux_range.end - flux_range.start < 1e-10:
|
|
389
|
+
center = flux_range.start
|
|
390
|
+
if abs(center) < 1e-10: # If center is essentially 0
|
|
391
|
+
flux_range.start = -0.1
|
|
392
|
+
flux_range.end = 1.0
|
|
393
|
+
else:
|
|
394
|
+
span = max(abs(center * 0.2), 0.1)
|
|
395
|
+
flux_range.start = center - span
|
|
396
|
+
flux_range.end = center + span
|
|
397
|
+
|
|
398
|
+
if residual_range.end - residual_range.start < 1e-10:
|
|
399
|
+
center = residual_range.start
|
|
400
|
+
span = max(abs(center * 0.2), 0.1)
|
|
401
|
+
residual_range.start = center - span
|
|
402
|
+
residual_range.end = center + span
|
|
403
|
+
|
|
404
|
+
# ORIENTATION CONFIGURATION - this eliminates the conditional branches
|
|
405
|
+
config = {
|
|
406
|
+
'vertical': {
|
|
407
|
+
'iteration_axis': 'y',
|
|
408
|
+
'data_axis': 'x',
|
|
409
|
+
'main_axis_label': 'Iteration (cycle threshold dotted red)',
|
|
410
|
+
'residual_axis_label': 'Peak Residual',
|
|
411
|
+
'flux_axis_label': 'Total Flux',
|
|
412
|
+
'residual_axis_pos': 'above',
|
|
413
|
+
'flux_axis_pos': 'above',
|
|
414
|
+
'extra_ranges_key': 'extra_x_ranges',
|
|
415
|
+
'glyph_coords': ('values', 'iterations'), # (x, y)
|
|
416
|
+
'range_name_param': 'x_range_name'
|
|
417
|
+
},
|
|
418
|
+
'horizontal': {
|
|
419
|
+
'iteration_axis': 'x',
|
|
420
|
+
'data_axis': 'y',
|
|
421
|
+
'main_axis_label': 'Iteration (cycle threshold dotted red)',
|
|
422
|
+
'residual_axis_label': 'Peak Residual',
|
|
423
|
+
'flux_axis_label': 'Total Flux',
|
|
424
|
+
'residual_axis_pos': 'right',
|
|
425
|
+
'flux_axis_pos': 'right',
|
|
426
|
+
'extra_ranges_key': 'extra_y_ranges',
|
|
427
|
+
'glyph_coords': ('iterations', 'values'), # (x, y)
|
|
428
|
+
'range_name_param': 'y_range_name'
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
cfg = config[orient]
|
|
433
|
+
|
|
434
|
+
# Create figure with no default axes; to control the axes they must
|
|
435
|
+
# be explicitly set to None
|
|
436
|
+
imdetails['gui']['convergence'] = figure( sizing_mode=sizing_mode,
|
|
437
|
+
x_axis_location=None, y_axis_location=None,
|
|
438
|
+
tools=[ hover ], toolbar_location=None, **kw )
|
|
439
|
+
|
|
440
|
+
# Set up extra ranges
|
|
441
|
+
setattr(imdetails['gui']['convergence'], cfg['extra_ranges_key'], {
|
|
442
|
+
'residual_range': residual_range,
|
|
443
|
+
'flux_range': flux_range
|
|
444
|
+
})
|
|
445
|
+
|
|
446
|
+
# Store references for JavaScript updates
|
|
447
|
+
imdetails['converge-ranges'] = {
|
|
448
|
+
'residual_range': residual_range,
|
|
449
|
+
'flux_range': flux_range
|
|
450
|
+
}
|
|
396
451
|
|
|
452
|
+
# Create main iteration axis
|
|
453
|
+
main_axis = LinearAxis(axis_label=cfg['main_axis_label'])
|
|
454
|
+
main_axis_pos = 'below' if cfg['iteration_axis'] == 'x' else 'left'
|
|
455
|
+
imdetails['gui']['convergence'].add_layout(main_axis, main_axis_pos)
|
|
456
|
+
|
|
457
|
+
# Create glyphs using configuration
|
|
458
|
+
x_coord, y_coord = cfg['glyph_coords']
|
|
459
|
+
range_param = {cfg['range_name_param']: 'residual_range'}
|
|
460
|
+
|
|
461
|
+
imdetails['gui']['convergence'].step( x_coord, y_coord, source=imdetails['converge-data']['cyclethreshold'],
|
|
462
|
+
line_color='red', line_dash='dotted', line_width=2, **range_param )
|
|
463
|
+
imdetails['gui']['convergence'].line( x_coord, y_coord, source=imdetails['converge-data']['residual'],
|
|
464
|
+
line_color=self._converge_color['residual'], **range_param )
|
|
465
|
+
imdetails['gui']['convergence'].scatter( x_coord, y_coord, source=imdetails['converge-data']['residual'],
|
|
466
|
+
color=self._converge_color['residual'], size=10, **range_param )
|
|
467
|
+
|
|
468
|
+
# Flux glyphs
|
|
469
|
+
range_param = {cfg['range_name_param']: 'flux_range'}
|
|
470
|
+
imdetails['gui']['convergence'].line( x_coord, y_coord, source=imdetails['converge-data']['flux'],
|
|
471
|
+
line_color=self._converge_color['flux'], **range_param )
|
|
472
|
+
imdetails['gui']['convergence'].scatter( x_coord, y_coord, source=imdetails['converge-data']['flux'],
|
|
473
|
+
color=self._converge_color['flux'], size=10, **range_param )
|
|
474
|
+
|
|
475
|
+
# Create and style residual axis
|
|
476
|
+
residual_axis_param = {cfg['range_name_param'].replace('_name', '_name'): 'residual_range'}
|
|
477
|
+
residual_axis = LinearAxis(axis_label=cfg['residual_axis_label'], **residual_axis_param)
|
|
478
|
+
residual_axis.axis_line_color = self._converge_color['residual']
|
|
479
|
+
residual_axis.major_label_text_color = self._converge_color['residual']
|
|
480
|
+
residual_axis.axis_label_text_color = self._converge_color['residual']
|
|
481
|
+
residual_axis.major_tick_line_color = self._converge_color['residual']
|
|
482
|
+
residual_axis.minor_tick_line_color = self._converge_color['residual']
|
|
483
|
+
imdetails['gui']['convergence'].add_layout(residual_axis, cfg['residual_axis_pos'])
|
|
484
|
+
|
|
485
|
+
# Create and style flux axis
|
|
486
|
+
flux_axis_param = {cfg['range_name_param'].replace('_name', '_name'): 'flux_range'}
|
|
487
|
+
flux_axis = LinearAxis(axis_label=cfg['flux_axis_label'], **flux_axis_param)
|
|
488
|
+
flux_axis.axis_line_color = self._converge_color['flux']
|
|
489
|
+
flux_axis.major_label_text_color = self._converge_color['flux']
|
|
490
|
+
flux_axis.axis_label_text_color = self._converge_color['flux']
|
|
491
|
+
flux_axis.major_tick_line_color = self._converge_color['flux']
|
|
492
|
+
flux_axis.minor_tick_line_color = self._converge_color['flux']
|
|
493
|
+
imdetails['gui']['convergence'].add_layout(flux_axis, cfg['flux_axis_pos'])
|
|
494
|
+
|
|
495
|
+
# Store axis references for JavaScript access
|
|
496
|
+
imdetails['converge-axes'] = {
|
|
497
|
+
'residual_axis': residual_axis,
|
|
498
|
+
'flux_axis': flux_axis
|
|
499
|
+
}
|
|
397
500
|
|
|
398
501
|
def _launch_gui( self ):
|
|
399
502
|
'''create and show GUI
|
|
@@ -534,23 +637,6 @@ class InteractiveCleanUI:
|
|
|
534
637
|
|
|
535
638
|
self._clean['converge']['pipe'].register( self._clean['converge']['id'], convergence_handler )
|
|
536
639
|
|
|
537
|
-
###
|
|
538
|
-
### Data source that will be used for updating the convergence plot
|
|
539
|
-
###
|
|
540
|
-
stokes = 0
|
|
541
|
-
convergence = imdetails['converge']['chan'][0][stokes]
|
|
542
|
-
imdetails['converge-data'] = { }
|
|
543
|
-
imdetails['converge-data']['flux'] = ColumnDataSource( data=dict( values=convergence['modelFlux'], iterations=convergence['iterations'],
|
|
544
|
-
cyclethreshold=convergence['cycleThresh'],
|
|
545
|
-
stopDesc=list( map( ImagingDict.get_summaryminor_stopdesc, convergence['stopCode'] ) ),
|
|
546
|
-
type=['flux'] * len(convergence['iterations']) ) )
|
|
547
|
-
imdetails['converge-data']['residual'] = ColumnDataSource( data=dict( values=convergence['peakRes'], iterations=convergence['iterations'],
|
|
548
|
-
cyclethreshold=convergence['cycleThresh'],
|
|
549
|
-
stopDesc=list( map( ImagingDict.get_summaryminor_stopdesc, convergence['stopCode'] ) ),
|
|
550
|
-
type=['residual'] * len(convergence['iterations'])) )
|
|
551
|
-
imdetails['converge-data']['cyclethreshold'] = ColumnDataSource( data=dict( values=convergence['cycleThresh'], iterations=convergence['iterations'] ) )
|
|
552
|
-
|
|
553
|
-
|
|
554
640
|
###
|
|
555
641
|
### help page for cube interactions
|
|
556
642
|
###
|
|
@@ -585,8 +671,12 @@ class InteractiveCleanUI:
|
|
|
585
671
|
imdetails['gui']['image']['src'] = imdetails['gui']['cube'].js_obj( )
|
|
586
672
|
imdetails['gui']['image']['fig'] = imdetails['gui']['cube'].image( grid=False, height_policy='max', width_policy='max',
|
|
587
673
|
channelcb=CustomJS( args=dict( img_state={ 'src': imdetails['gui']['image']['src'],
|
|
588
|
-
'flux': imdetails['converge-data']['flux'],
|
|
589
|
-
|
|
674
|
+
'flux': { 'source': imdetails['converge-data']['flux'],
|
|
675
|
+
'axis': imdetails['converge-axes']['flux_axis'],
|
|
676
|
+
'range': imdetails['converge-ranges']['flux_range'] },
|
|
677
|
+
'residual': { 'source': imdetails['converge-data']['residual'],
|
|
678
|
+
'axis': imdetails['converge-axes']['residual_axis'],
|
|
679
|
+
'range': imdetails['converge-ranges']['residual_range'] },
|
|
590
680
|
'cyclethreshold': imdetails['converge-data']['cyclethreshold'] },
|
|
591
681
|
imid=imid,
|
|
592
682
|
ctrl={ 'converge': self._clean['converge'] },
|
|
@@ -702,9 +792,13 @@ class InteractiveCleanUI:
|
|
|
702
792
|
'src': v['gui']['cube'].js_obj( ),
|
|
703
793
|
'spectrum': v['gui']['spectrum'],
|
|
704
794
|
'src': v['gui']['image']['src'],
|
|
705
|
-
'flux': v['converge-data']['flux'],
|
|
795
|
+
'flux': { 'source': v['converge-data']['flux'],
|
|
796
|
+
'axis': v['converge-axes']['flux_axis'],
|
|
797
|
+
'range': v['converge-ranges']['flux_range'] },
|
|
706
798
|
'cyclethreshold': v['converge-data']['cyclethreshold'],
|
|
707
|
-
'residual': v['converge-data']['residual'],
|
|
799
|
+
'residual': { 'source': v['converge-data']['residual'],
|
|
800
|
+
'axis': v['converge-axes']['residual_axis'],
|
|
801
|
+
'range': v['converge-ranges']['residual_range'] },
|
|
708
802
|
'navi': { 'slider': v['gui']['slider'],
|
|
709
803
|
'goto': v['gui']['goto'],
|
|
710
804
|
## it doesn't seem like pixel tracking must be disabled
|
|
@@ -1216,7 +1310,52 @@ class InteractiveCleanUI:
|
|
|
1216
1310
|
### -- The "Insert here ..." code seems to be called when when the stokes plane is changed --
|
|
1217
1311
|
### -- but there have been no tclean iterations yet... --
|
|
1218
1312
|
### --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---
|
|
1219
|
-
'update-converge': '''function
|
|
1313
|
+
'update-converge': '''function updateAxisRange(source, range_obj, axis_obj, axis_name) {
|
|
1314
|
+
const data = source.data;
|
|
1315
|
+
const values = data['values'];
|
|
1316
|
+
|
|
1317
|
+
if (values.length === 0) return;
|
|
1318
|
+
|
|
1319
|
+
// Calculate data bounds
|
|
1320
|
+
const min_val = Math.min(...values);
|
|
1321
|
+
const max_val = Math.max(...values);
|
|
1322
|
+
|
|
1323
|
+
// Add padding (10% of range, with minimum padding)
|
|
1324
|
+
const span = max_val - min_val;
|
|
1325
|
+
const padding = max_val != min_val ? Math.max(span * 0.1, Math.abs(max_val * 0.02)) : Math.abs(max_val * 0.1);
|
|
1326
|
+
|
|
1327
|
+
// Update range
|
|
1328
|
+
range_obj.start = min_val - padding;
|
|
1329
|
+
range_obj.end = max_val + padding;
|
|
1330
|
+
|
|
1331
|
+
// Ensure ranges are valid (non-zero span)
|
|
1332
|
+
if ( range_obj.end - range_obj.start < 1e-10 ) {
|
|
1333
|
+
const center = range_obj.start
|
|
1334
|
+
if ( Math.abs(center) < 1e-10 ) {
|
|
1335
|
+
// If center is essentially 0
|
|
1336
|
+
range_obj.start = -0.1
|
|
1337
|
+
range_obj.end = 1.0
|
|
1338
|
+
} else {
|
|
1339
|
+
const span = Math.max(Math.abs(center * 0.2), 0.1)
|
|
1340
|
+
range_obj.start = center - span
|
|
1341
|
+
range_obj.end = center + span
|
|
1342
|
+
}
|
|
1343
|
+
}
|
|
1344
|
+
|
|
1345
|
+
// Optional: Update tick density
|
|
1346
|
+
if (axis_obj && axis_obj.ticker) {
|
|
1347
|
+
const new_span = range_obj.end - range_obj.start;
|
|
1348
|
+
if (new_span < 10) {
|
|
1349
|
+
axis_obj.ticker.desired_num_ticks = 8;
|
|
1350
|
+
} else if (new_span < 100) {
|
|
1351
|
+
axis_obj.ticker.desired_num_ticks = 10;
|
|
1352
|
+
} else {
|
|
1353
|
+
axis_obj.ticker.desired_num_ticks = 6;
|
|
1354
|
+
}
|
|
1355
|
+
}
|
|
1356
|
+
}
|
|
1357
|
+
|
|
1358
|
+
function update_convergence_single( target, data ) {
|
|
1220
1359
|
const pos = target.src.cur_chan
|
|
1221
1360
|
const imdata = data.get(pos[1]).get(pos[0])
|
|
1222
1361
|
// chan----------------^^^^^^ ^^^^^^----stokes
|
|
@@ -1226,9 +1365,11 @@ class InteractiveCleanUI:
|
|
|
1226
1365
|
const modelFlux = imdata.modelFlux
|
|
1227
1366
|
const stopCode = imdata.stopCode
|
|
1228
1367
|
const stopDesc = imdata.stopCode.map( code => stopdescmap.has(code) ? stopdescmap.get(code): "" )
|
|
1229
|
-
target.residual.data = { iterations, cyclethreshold, stopDesc, values: peakRes, type: Array(iterations.length).fill('residual') }
|
|
1230
|
-
target.flux.data = { iterations, cyclethreshold, stopDesc, values: modelFlux, type: Array(iterations.length).fill('flux') }
|
|
1368
|
+
target.residual.source.data = { iterations, cyclethreshold, stopDesc, values: peakRes, type: Array(iterations.length).fill('residual') }
|
|
1369
|
+
target.flux.source.data = { iterations, cyclethreshold, stopDesc, values: modelFlux, type: Array(iterations.length).fill('flux') }
|
|
1231
1370
|
target.cyclethreshold.data = { iterations, values: cyclethreshold }
|
|
1371
|
+
updateAxisRange( target.flux.source, target.flux.range, target.flux.axis, 'Flux' )
|
|
1372
|
+
updateAxisRange( target.residual.source, target.residual.range, target.residual.axis, 'Residual' )
|
|
1232
1373
|
}
|
|
1233
1374
|
|
|
1234
1375
|
function update_convergence( recurse=false ) {
|