cubevis 0.5.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- cubevis/LICENSE.rst +500 -0
- cubevis/__icons__/20px/fast-backward.svg +13 -0
- cubevis/__icons__/20px/fast-forward.svg +13 -0
- cubevis/__icons__/20px/step-backward.svg +12 -0
- cubevis/__icons__/20px/step-forward.svg +12 -0
- cubevis/__icons__/add-chan.png +0 -0
- cubevis/__icons__/add-chan.svg +84 -0
- cubevis/__icons__/add-cube.png +0 -0
- cubevis/__icons__/add-cube.svg +186 -0
- cubevis/__icons__/drag.png +0 -0
- cubevis/__icons__/drag.svg +109 -0
- cubevis/__icons__/mask-selected.png +0 -0
- cubevis/__icons__/mask.png +0 -0
- cubevis/__icons__/mask.svg +1 -0
- cubevis/__icons__/new-layer-sm-selected.png +0 -0
- cubevis/__icons__/new-layer-sm-selected.svg +88 -0
- cubevis/__icons__/new-layer-sm.png +0 -0
- cubevis/__icons__/new-layer-sm.svg +15 -0
- cubevis/__icons__/reset.png +0 -0
- cubevis/__icons__/reset.svg +11 -0
- cubevis/__icons__/sub-chan.png +0 -0
- cubevis/__icons__/sub-chan.svg +71 -0
- cubevis/__icons__/sub-cube.png +0 -0
- cubevis/__icons__/sub-cube.svg +95 -0
- cubevis/__icons__/zoom-to-fit.png +0 -0
- cubevis/__icons__/zoom-to-fit.svg +21 -0
- cubevis/__init__.py +58 -0
- cubevis/__js__/bokeh-3.6.1.min.js +728 -0
- cubevis/__js__/bokeh-tables-3.6.1.min.js +119 -0
- cubevis/__js__/bokeh-widgets-3.6.1.min.js +141 -0
- cubevis/__js__/casalib.min.js +1 -0
- cubevis/__js__/cubevisjs.min.js +62 -0
- cubevis/__version__.py +1 -0
- cubevis/apps/__init__.py +44 -0
- cubevis/apps/_createmask.py +461 -0
- cubevis/apps/_createregion.py +513 -0
- cubevis/apps/_interactiveclean.py +3260 -0
- cubevis/apps/_interactiveclean_wrappers.py +130 -0
- cubevis/apps/_ms_raster.py +815 -0
- cubevis/apps/_plotants.py +286 -0
- cubevis/apps/_plotbandpass.py +7 -0
- cubevis/bokeh/__init__.py +29 -0
- cubevis/bokeh/annotations/__init__.py +1 -0
- cubevis/bokeh/annotations/_ev_poly_annotation.py +6 -0
- cubevis/bokeh/components/__init__.py +28 -0
- cubevis/bokeh/format/__init__.py +31 -0
- cubevis/bokeh/format/_time_ticks.py +44 -0
- cubevis/bokeh/format/_wcs_ticks.py +45 -0
- cubevis/bokeh/models/__init__.py +4 -0
- cubevis/bokeh/models/_edit_span.py +7 -0
- cubevis/bokeh/models/_ev_text_input.py +6 -0
- cubevis/bokeh/models/_tip.py +37 -0
- cubevis/bokeh/models/_tip_button.py +50 -0
- cubevis/bokeh/sources/__init__.py +35 -0
- cubevis/bokeh/sources/_data_pipe.py +258 -0
- cubevis/bokeh/sources/_image_data_source.py +83 -0
- cubevis/bokeh/sources/_image_pipe.py +581 -0
- cubevis/bokeh/sources/_spectra_data_source.py +55 -0
- cubevis/bokeh/sources/_updatable_data_source.py +189 -0
- cubevis/bokeh/state/__init__.py +34 -0
- cubevis/bokeh/state/_initialize.py +164 -0
- cubevis/bokeh/state/_javascript.py +53 -0
- cubevis/bokeh/state/_palette.py +58 -0
- cubevis/bokeh/state/_session.py +44 -0
- cubevis/bokeh/state/js/bokeh-2.4.1.min.js +596 -0
- cubevis/bokeh/state/js/bokeh-gl-2.4.1.min.js +74 -0
- cubevis/bokeh/state/js/bokeh-tables-2.4.1.min.js +132 -0
- cubevis/bokeh/state/js/bokeh-widgets-2.4.1.min.js +118 -0
- cubevis/bokeh/state/js/casaguijs-v0.0.4.0-b2.4.min.js +49 -0
- cubevis/bokeh/state/js/casaguijs-v0.0.5.0-b2.4.min.js +49 -0
- cubevis/bokeh/state/js/casaguijs-v0.0.6.0-b2.4.min.js +49 -0
- cubevis/bokeh/state/js/casalib-v0.0.1.min.js +1 -0
- cubevis/bokeh/tools/__init__.py +31 -0
- cubevis/bokeh/tools/_cbreset_tool.py +52 -0
- cubevis/bokeh/tools/_drag_tool.py +61 -0
- cubevis/bokeh/utils/__init__.py +35 -0
- cubevis/bokeh/utils/_axes_labels.py +94 -0
- cubevis/bokeh/utils/_svg_icon.py +136 -0
- cubevis/data/__init__.py +1 -0
- cubevis/data/casaimage/__init__.py +114 -0
- cubevis/data/measurement_set/__init__.py +7 -0
- cubevis/data/measurement_set/_ms_data.py +178 -0
- cubevis/data/measurement_set/processing_set/__init__.py +30 -0
- cubevis/data/measurement_set/processing_set/_ps_concat.py +98 -0
- cubevis/data/measurement_set/processing_set/_ps_coords.py +78 -0
- cubevis/data/measurement_set/processing_set/_ps_data.py +213 -0
- cubevis/data/measurement_set/processing_set/_ps_io.py +55 -0
- cubevis/data/measurement_set/processing_set/_ps_raster_data.py +154 -0
- cubevis/data/measurement_set/processing_set/_ps_select.py +91 -0
- cubevis/data/measurement_set/processing_set/_ps_stats.py +218 -0
- cubevis/data/measurement_set/processing_set/_xds_data.py +149 -0
- cubevis/plot/__init__.py +1 -0
- cubevis/plot/ms_plot/__init__.py +29 -0
- cubevis/plot/ms_plot/_ms_plot.py +242 -0
- cubevis/plot/ms_plot/_ms_plot_constants.py +22 -0
- cubevis/plot/ms_plot/_ms_plot_selectors.py +348 -0
- cubevis/plot/ms_plot/_raster_plot.py +292 -0
- cubevis/plot/ms_plot/_raster_plot_inputs.py +116 -0
- cubevis/plot/ms_plot/_xds_plot_axes.py +110 -0
- cubevis/private/__java__/xml-casa-assembly-1.86.jar +0 -0
- cubevis/private/_gclean.py +798 -0
- cubevis/private/casashell/createmask.py +332 -0
- cubevis/private/casashell/iclean.py +4432 -0
- cubevis/private/casatasks/__init__.py +140 -0
- cubevis/private/casatasks/createmask.py +86 -0
- cubevis/private/casatasks/createregion.py +83 -0
- cubevis/private/casatasks/iclean.py +1831 -0
- cubevis/readme.rst +16 -0
- cubevis/remote/__init__.py +10 -0
- cubevis/remote/_gclean.py +61 -0
- cubevis/remote/_local.py +287 -0
- cubevis/remote/_remote_kernel.py +80 -0
- cubevis/toolbox/__init__.py +32 -0
- cubevis/toolbox/_app_context.py +74 -0
- cubevis/toolbox/_cube.py +3457 -0
- cubevis/toolbox/_region_list.py +197 -0
- cubevis/utils/_ResourceManager.py +86 -0
- cubevis/utils/__init__.py +620 -0
- cubevis/utils/_contextmgrchain.py +84 -0
- cubevis/utils/_conversion.py +93 -0
- cubevis/utils/_copydoc.py +55 -0
- cubevis/utils/_docenum.py +25 -0
- cubevis/utils/_import_protected_module.py +35 -0
- cubevis/utils/_logging.py +85 -0
- cubevis/utils/_pkgs.py +77 -0
- cubevis/utils/_regions.py +40 -0
- cubevis/utils/_static.py +66 -0
- cubevis/utils/_tiles.py +167 -0
- cubevis-0.5.2.dist-info/METADATA +151 -0
- cubevis-0.5.2.dist-info/RECORD +132 -0
- cubevis-0.5.2.dist-info/WHEEL +4 -0
- cubevis-0.5.2.dist-info/licenses/LICENSE +504 -0
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
########################################################################
|
|
2
|
+
#
|
|
3
|
+
# Copyright (C) 2025
|
|
4
|
+
# Associated Universities, Inc. Washington DC, USA.
|
|
5
|
+
#
|
|
6
|
+
# This script is free software; you can redistribute it and/or modify it
|
|
7
|
+
# under the terms of the GNU Library General Public License as published by
|
|
8
|
+
# the Free Software Foundation; either version 2 of the License, or (at your
|
|
9
|
+
# option) any later version.
|
|
10
|
+
#
|
|
11
|
+
# This library is distributed in the hope that it will be useful, but WITHOUT
|
|
12
|
+
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
13
|
+
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
|
|
14
|
+
# License for more details.
|
|
15
|
+
#
|
|
16
|
+
# You should have received a copy of the GNU Library General Public License
|
|
17
|
+
# along with this library; if not, write to the Free Software Foundation,
|
|
18
|
+
# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
|
|
19
|
+
#
|
|
20
|
+
# Correspondence concerning AIPS++ should be adressed as follows:
|
|
21
|
+
# Internet email: casa-feedback@nrao.edu.
|
|
22
|
+
# Postal address: AIPS++ Project Office
|
|
23
|
+
# National Radio Astronomy Observatory
|
|
24
|
+
# 520 Edgemont Road
|
|
25
|
+
# Charlottesville, VA 22903-2475 USA
|
|
26
|
+
#
|
|
27
|
+
########################################################################
|
|
28
|
+
'''Specialization of the Bokeh ``DataSource`` which allows for update via WebSockets.'''
|
|
29
|
+
|
|
30
|
+
from uuid import uuid4
|
|
31
|
+
from sys import stderr
|
|
32
|
+
from contextlib import asynccontextmanager
|
|
33
|
+
from bokeh.plotting import ColumnDataSource
|
|
34
|
+
from bokeh.core.properties import Instance, String, Nullable
|
|
35
|
+
from bokeh.models.callbacks import Callback
|
|
36
|
+
from bokeh.models import CustomJS
|
|
37
|
+
import websockets
|
|
38
|
+
from ._data_pipe import DataPipe
|
|
39
|
+
from ..state import casalib_url, cubevisjs_url
|
|
40
|
+
from ...utils import find_ws_address
|
|
41
|
+
|
|
42
|
+
class UpdatableDataSource(ColumnDataSource):
|
|
43
|
+
"""Implementation of a `ColumnDataSource` customized to allow updates from Python via
|
|
44
|
+
WebSockets after the Bokeh GUI has been displayed. This class is derived from `ColumnDataSource`
|
|
45
|
+
and provides an `update` function that can be used to update the plotted data. While this
|
|
46
|
+
is useful when Bokeh is used directly in a Python session, the `stream` function provided
|
|
47
|
+
by `ColumnDataSource` should be used to update plots which are implemented using the Bokeh
|
|
48
|
+
server. This function can be used for plots which may displayed and managed directly from an
|
|
49
|
+
interactive Python session via `asyncio`. However, even in this case it may be more performant
|
|
50
|
+
to include all of the initial plot points when creating the data source. Future updates in
|
|
51
|
+
response to user interaction could be accomplished using this class.
|
|
52
|
+
|
|
53
|
+
This class allows the use to specify `js_init` code that is run in the browser when this
|
|
54
|
+
class is initialized there. The JavaScript implementation provides default code which is
|
|
55
|
+
run in the browser when the user calls the `update` function from Python. This code works
|
|
56
|
+
for single dimemsion data by simply appending the supplied updates to the end of the existing
|
|
57
|
+
plot data. If the user supplies an implementation for `js_update` then this code is used
|
|
58
|
+
in preference to the simple, default implementation. In the future the default update
|
|
59
|
+
implementation may be expanded to be more useful for 2D plots.
|
|
60
|
+
|
|
61
|
+
Attributes
|
|
62
|
+
----------
|
|
63
|
+
js_init: CustomJS
|
|
64
|
+
JavaScript code to be run when this DataSource is loaded
|
|
65
|
+
js_update: CustomJS
|
|
66
|
+
JavaScript code to be run to update the data
|
|
67
|
+
pipe: DataPipe
|
|
68
|
+
Optional attribute that allows the user to specify a reused DataPipe
|
|
69
|
+
data:
|
|
70
|
+
INHERITED contains the data provided by this DataSource
|
|
71
|
+
"""
|
|
72
|
+
|
|
73
|
+
js_init = Nullable(Instance(Callback), help="""
|
|
74
|
+
JavaScript to be run during initialization of an instance of this DataSource object.
|
|
75
|
+
""")
|
|
76
|
+
|
|
77
|
+
js_update = Nullable(Instance(Callback), help="""
|
|
78
|
+
JavaScript to be run to update during initialization of an instance of this DataSource object.
|
|
79
|
+
The default behavior is to append to the existing data.
|
|
80
|
+
""")
|
|
81
|
+
|
|
82
|
+
pipe = Instance(DataPipe, help="""
|
|
83
|
+
Optional attribute that allows for reusing a single DataPipe for multiple purposes
|
|
84
|
+
""" )
|
|
85
|
+
|
|
86
|
+
session_id = String( help="""
|
|
87
|
+
Internal id used for communcations.
|
|
88
|
+
""" )
|
|
89
|
+
|
|
90
|
+
__javascript__ = [ casalib_url( ), cubevisjs_url( ) ]
|
|
91
|
+
|
|
92
|
+
__created_pipe = False
|
|
93
|
+
__id = str(uuid4( ))
|
|
94
|
+
__user_init = None
|
|
95
|
+
|
|
96
|
+
def __init__( self, *args,
|
|
97
|
+
callback=None,
|
|
98
|
+
**kwargs ):
|
|
99
|
+
|
|
100
|
+
### websocket communication id
|
|
101
|
+
kwargs['session_id'] = self.__id
|
|
102
|
+
|
|
103
|
+
if 'pipe' not in kwargs:
|
|
104
|
+
kwargs['pipe'] = DataPipe( address=find_ws_address( ) ) #, abort=abort )
|
|
105
|
+
self.__created_pipe = True
|
|
106
|
+
if 'js_init' in kwargs:
|
|
107
|
+
self.__user_init = kwargs['js_init']
|
|
108
|
+
|
|
109
|
+
kwargs['js_init'] = CustomJS( args=dict( userinit=self.__user_init ),
|
|
110
|
+
code='''this._data_keys = casalib.reduce(
|
|
111
|
+
(acc,key,value) => {
|
|
112
|
+
if ( Array.isArray(value) ) acc.push( key )
|
|
113
|
+
return acc }, this.data, [ ] )
|
|
114
|
+
|
|
115
|
+
this.pipe.register( this.session_id,
|
|
116
|
+
( msg ) => {
|
|
117
|
+
// [...array1, ...array2]
|
|
118
|
+
if ( ! ('data' in msg) )
|
|
119
|
+
return { result: 'error', msg: 'expected to find "data" in message' }
|
|
120
|
+
for (const k of this._data_keys) {
|
|
121
|
+
if ( ! (k in msg.data) )
|
|
122
|
+
return { result: 'error', msg: `expected "${k}" field in update "data"` }
|
|
123
|
+
}
|
|
124
|
+
if ( this.js_update ) {
|
|
125
|
+
this.js_update.execute( this, { data: msg.data } ).then(
|
|
126
|
+
(data) => { this.data = data } )
|
|
127
|
+
} else {
|
|
128
|
+
const data_update = { }
|
|
129
|
+
for (const k of this._data_keys) {
|
|
130
|
+
const existing = this.data[k]
|
|
131
|
+
const addition = msg.data[k]
|
|
132
|
+
data_update[k] = [...existing, ...addition]
|
|
133
|
+
}
|
|
134
|
+
this.data = data_update
|
|
135
|
+
}
|
|
136
|
+
return { result: 'success',
|
|
137
|
+
msg: casalib.reduce(
|
|
138
|
+
(acc,key,value) => {
|
|
139
|
+
if ( ! ( key in this.data ) )
|
|
140
|
+
acc[key] = value
|
|
141
|
+
return acc
|
|
142
|
+
}, msg.data, { } ) }
|
|
143
|
+
} )
|
|
144
|
+
|
|
145
|
+
window.addEventListener(
|
|
146
|
+
'beforeunload',
|
|
147
|
+
(event) => {
|
|
148
|
+
function send_shutdown(id,pipe) {
|
|
149
|
+
return new Promise((resolve) =>
|
|
150
|
+
pipe.send( id, { action: 'stop' },
|
|
151
|
+
(msg) => { resolve(msg) } ) )
|
|
152
|
+
}
|
|
153
|
+
send_shutdown(this.session_id,this.pipe).then(
|
|
154
|
+
(result) => { console.log(`Shutdown Result: ${result}`) } )
|
|
155
|
+
} )
|
|
156
|
+
|
|
157
|
+
if ( userinit != null ) {
|
|
158
|
+
void userinit.execute( this )
|
|
159
|
+
}''' )
|
|
160
|
+
|
|
161
|
+
super( ).__init__( *args, **kwargs )
|
|
162
|
+
self.__callback = callback
|
|
163
|
+
self.__stop = None
|
|
164
|
+
|
|
165
|
+
async def manage_requests( msg, self=self ):
|
|
166
|
+
result = 'OK'
|
|
167
|
+
if self.__stop and 'action' in msg and msg['action'] == 'stop':
|
|
168
|
+
self.__stop( msg )
|
|
169
|
+
elif self.__callback and 'action' in msg and 'message' in msg and msg['action'] == 'callback':
|
|
170
|
+
result = await self.__callback( msg['message'] )
|
|
171
|
+
return { 'result': result }
|
|
172
|
+
|
|
173
|
+
self.pipe.register( self.__id, manage_requests )
|
|
174
|
+
|
|
175
|
+
async def update( self, data, callback=None ):
|
|
176
|
+
def default_callback( msg, self=self ):
|
|
177
|
+
if msg['result'] == 'error':
|
|
178
|
+
print( f'''UpdatableDataSource Error: {msg['msg']}''', file=stderr )
|
|
179
|
+
await self.pipe.send( self.__id, { 'action': 'append', 'data': data }, default_callback if callback is None else callback )
|
|
180
|
+
|
|
181
|
+
@asynccontextmanager
|
|
182
|
+
async def serve( self, stop_function ):
|
|
183
|
+
self.__stop = stop_function
|
|
184
|
+
if not self.__created_pipe:
|
|
185
|
+
raise RuntimeError( 'UpdatableDataSource.serve should only be called for when a "pipe" is NOT supplied as part of initialization' )
|
|
186
|
+
|
|
187
|
+
self._stop_serving_function = stop_function
|
|
188
|
+
async with websockets.serve( self.pipe.process_messages, self.pipe.address[0], self.pipe.address[1] ) as msgpipe:
|
|
189
|
+
yield { 'msgpipe': msgpipe }
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
########################################################################
|
|
2
|
+
#
|
|
3
|
+
# Copyright (C) 2022
|
|
4
|
+
# Associated Universities, Inc. Washington DC, USA.
|
|
5
|
+
#
|
|
6
|
+
# This script is free software; you can redistribute it and/or modify it
|
|
7
|
+
# under the terms of the GNU Library General Public License as published by
|
|
8
|
+
# the Free Software Foundation; either version 2 of the License, or (at your
|
|
9
|
+
# option) any later version.
|
|
10
|
+
#
|
|
11
|
+
# This library is distributed in the hope that it will be useful, but WITHOUT
|
|
12
|
+
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
13
|
+
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
|
|
14
|
+
# License for more details.
|
|
15
|
+
#
|
|
16
|
+
# You should have received a copy of the GNU Library General Public License
|
|
17
|
+
# along with this library; if not, write to the Free Software Foundation,
|
|
18
|
+
# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
|
|
19
|
+
#
|
|
20
|
+
# Correspondence concerning AIPS++ should be adressed as follows:
|
|
21
|
+
# Internet email: casa-feedback@nrao.edu.
|
|
22
|
+
# Postal address: AIPS++ Project Office
|
|
23
|
+
# National Radio Astronomy Observatory
|
|
24
|
+
# 520 Edgemont Road
|
|
25
|
+
# Charlottesville, VA 22903-2475 USA
|
|
26
|
+
#
|
|
27
|
+
########################################################################
|
|
28
|
+
'''Bokeh state management functions (both within the Bokeh distribution
|
|
29
|
+
and with the Bokeh extensions found in ``cubevis.bokeh``.'''
|
|
30
|
+
|
|
31
|
+
from ._initialize import initialize_bokeh
|
|
32
|
+
from ._session import setup_session as initialize_session
|
|
33
|
+
from ._palette import available_palettes, find_palette, default_palette
|
|
34
|
+
from ._javascript import casalib_url, cubevisjs_url
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
########################################################################
|
|
2
|
+
#
|
|
3
|
+
# Copyright (C) 2021,2022,2023
|
|
4
|
+
# Associated Universities, Inc. Washington DC, USA.
|
|
5
|
+
#
|
|
6
|
+
# This script is free software; you can redistribute it and/or modify it
|
|
7
|
+
# under the terms of the GNU Library General Public License as published by
|
|
8
|
+
# the Free Software Foundation; either version 2 of the License, or (at your
|
|
9
|
+
# option) any later version.
|
|
10
|
+
#
|
|
11
|
+
# This library is distributed in the hope that it will be useful, but WITHOUT
|
|
12
|
+
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
13
|
+
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
|
|
14
|
+
# License for more details.
|
|
15
|
+
#
|
|
16
|
+
# You should have received a copy of the GNU Library General Public License
|
|
17
|
+
# along with this library; if not, write to the Free Software Foundation,
|
|
18
|
+
# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
|
|
19
|
+
#
|
|
20
|
+
# Correspondence concerning AIPS++ should be adressed as follows:
|
|
21
|
+
# Internet email: casa-feedback@nrao.edu.
|
|
22
|
+
# Postal address: AIPS++ Project Office
|
|
23
|
+
# National Radio Astronomy Observatory
|
|
24
|
+
# 520 Edgemont Road
|
|
25
|
+
# Charlottesville, VA 22903-2475 USA
|
|
26
|
+
#
|
|
27
|
+
########################################################################
|
|
28
|
+
'''This contains functions to inject the ``cubevisjs`` library into the
|
|
29
|
+
generated HTML that is used to display the Bokeh plots that ``casagui``'s
|
|
30
|
+
applications produce'''
|
|
31
|
+
import os
|
|
32
|
+
import re
|
|
33
|
+
from os import path
|
|
34
|
+
from os.path import dirname, join, basename, abspath
|
|
35
|
+
from urllib.parse import urlparse
|
|
36
|
+
from bokeh import resources
|
|
37
|
+
from ...utils import path_to_url, static_vars, have_network
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
@static_vars( initialized=False,
|
|
41
|
+
do_local_subst=not have_network( ) )
|
|
42
|
+
def initialize_bokeh( bokehjs_subst=None ):
|
|
43
|
+
"""Initialize `bokeh` for use with the ``cubevisjs`` extensions.
|
|
44
|
+
|
|
45
|
+
The ``cubevisjs`` extensions for Bokeh are built into a stand-alone
|
|
46
|
+
external JavaScript file constructed for the specific version of
|
|
47
|
+
Bokeh that is being used. Previously the CASA minified JavaScript
|
|
48
|
+
libraries were loaded from the network. Now these libraries are
|
|
49
|
+
included in a ``__js__`` directory within the cubevis Python package.
|
|
50
|
+
If users need to debug JavaScript problems, non-minified versions
|
|
51
|
+
can be copied into the ``__js__`` directory to replace the existing
|
|
52
|
+
libraries. To debug within the bokehjs library, a URL or a path
|
|
53
|
+
can be supplied by the ``bokehjs_subst`` parameter and it will be
|
|
54
|
+
substituted for the standard Bokeh library.
|
|
55
|
+
|
|
56
|
+
Parameters
|
|
57
|
+
----------
|
|
58
|
+
bokehjs_subst: None or str or list of str
|
|
59
|
+
Bokeh dependent javascript library which is loaded after all
|
|
60
|
+
other Bokeh libraries have been loaded. This path could be a
|
|
61
|
+
local path, a URL or None. None is the default in which case
|
|
62
|
+
it loads the published library for the current version of
|
|
63
|
+
``cubevisjs`` and ``bokeh``
|
|
64
|
+
|
|
65
|
+
Example
|
|
66
|
+
-------
|
|
67
|
+
from cubevis.bokeh.state import initialize_bokeh
|
|
68
|
+
initialize_bokeh( bokehjs_subst="/tmp/bokeh-3.2.2.js" )
|
|
69
|
+
"""
|
|
70
|
+
|
|
71
|
+
if initialize_bokeh.initialized:
|
|
72
|
+
### only initialize once...
|
|
73
|
+
return
|
|
74
|
+
|
|
75
|
+
initialize_bokeh.initialized = True
|
|
76
|
+
resources.Resources._old_js_files = resources.Resources.js_files
|
|
77
|
+
def js_files( self ):
|
|
78
|
+
########################################################################
|
|
79
|
+
### Function that will replace the member function within Bokeh that ###
|
|
80
|
+
### returns the URLs for Bokeh initialization... ###
|
|
81
|
+
########################################################################
|
|
82
|
+
def expand_paths( replacement ):
|
|
83
|
+
### turn all paths into URLs
|
|
84
|
+
### turn a single string into a list with one string
|
|
85
|
+
if replacement is None:
|
|
86
|
+
return [ ]
|
|
87
|
+
if type(replacement) == str:
|
|
88
|
+
if path.isfile(replacement):
|
|
89
|
+
return [ f'''file://{abspath(replacement)}''' ]
|
|
90
|
+
elif replacement.startswith('http'):
|
|
91
|
+
return [ replacement ]
|
|
92
|
+
else:
|
|
93
|
+
raise RuntimeError( f'''debugging bokehjs substitution ('{replacement}') does not exist''' )
|
|
94
|
+
if type(replacement) == list:
|
|
95
|
+
result = [ ]
|
|
96
|
+
for u in replacement:
|
|
97
|
+
if path.isfile(u):
|
|
98
|
+
result.append( f'''file://{abspath(u)}''' )
|
|
99
|
+
elif u.startswith('http'):
|
|
100
|
+
result.append( u )
|
|
101
|
+
else:
|
|
102
|
+
raise RuntimeError( f'''debugging bokehjs substitution ('{u}') does not exist''' )
|
|
103
|
+
return result
|
|
104
|
+
return [ ]
|
|
105
|
+
def cubevisjs_predicate( s ):
|
|
106
|
+
### detect cubevisjs library URL
|
|
107
|
+
return basename(s).startswith('cubevisjs')
|
|
108
|
+
def replace_bokehjs( urls, replacement ):
|
|
109
|
+
### substitute replacement list for the bokehjs library URL
|
|
110
|
+
result = [ ]
|
|
111
|
+
for url in urls:
|
|
112
|
+
if re.match( r'.*/bokeh-\d+\.\d+\.\d+(?:\.min)?\.js$', url ):
|
|
113
|
+
result += replacement
|
|
114
|
+
else:
|
|
115
|
+
result.append(url)
|
|
116
|
+
return result
|
|
117
|
+
|
|
118
|
+
def include_all_bokehjs( urls ):
|
|
119
|
+
result = urls.copy( )
|
|
120
|
+
bokeh_path=None
|
|
121
|
+
has_bokeh_widgets=False
|
|
122
|
+
has_bokeh_tables=False
|
|
123
|
+
for url in urls:
|
|
124
|
+
if re.match( r'.*/bokeh-\d+\.\d+\.\d+(?:\.min)?\.js$', url ):
|
|
125
|
+
bokeh_path = url
|
|
126
|
+
if re.match( r'.*/bokeh-widgets-\d+\.\d+\.\d+(?:\.min)?\.js$', url ):
|
|
127
|
+
has_bokeh_widgets = True
|
|
128
|
+
if re.match( r'.*/bokeh-tables-\d+\.\d+\.\d+(?:\.min)?\.js$', url ):
|
|
129
|
+
has_bokeh_tables = True
|
|
130
|
+
|
|
131
|
+
if bokeh_path:
|
|
132
|
+
if not has_bokeh_widgets:
|
|
133
|
+
result.append( bokeh_path.replace('/bokeh-','/bokeh-widgets-') )
|
|
134
|
+
if not has_bokeh_tables:
|
|
135
|
+
result.append( bokeh_path.replace('/bokeh-','/bokeh-tables-') )
|
|
136
|
+
|
|
137
|
+
return result
|
|
138
|
+
|
|
139
|
+
user_bokehjs_replacement = expand_paths(bokehjs_subst)
|
|
140
|
+
sys_urls = include_all_bokehjs( resources.Resources._old_js_files.fget(self) )
|
|
141
|
+
if initialize_bokeh.do_local_subst:
|
|
142
|
+
local_urls = [ ]
|
|
143
|
+
for url in sys_urls:
|
|
144
|
+
pieces = urlparse(url)
|
|
145
|
+
if pieces.scheme != 'file':
|
|
146
|
+
lib = basename(pieces.path)
|
|
147
|
+
url = path_to_url(lib)
|
|
148
|
+
if lib != url:
|
|
149
|
+
local_urls.append(url)
|
|
150
|
+
else:
|
|
151
|
+
raise RuntimeError( '''Cannot confirm internet access and could not find local cached versions of Bokeh's libraries''' )
|
|
152
|
+
else:
|
|
153
|
+
local_urls.append(url)
|
|
154
|
+
sys_urls = local_urls
|
|
155
|
+
|
|
156
|
+
if len(user_bokehjs_replacement) == 0:
|
|
157
|
+
### move cubevisjs library after Bokeh libraries
|
|
158
|
+
return [x for x in sys_urls if not cubevisjs_predicate(x)] + [x for x in sys_urls if cubevisjs_predicate(x)]
|
|
159
|
+
else:
|
|
160
|
+
### replace bokehjs library with bokehjs_subst and move cubevisjs library after Bokeh libraries
|
|
161
|
+
return replace_bokehjs( [x for x in sys_urls if not cubevisjs_predicate(x)], user_bokehjs_replacement ) + [x for x in sys_urls if cubevisjs_predicate(x)]
|
|
162
|
+
|
|
163
|
+
resources.Resources.js_files = property(js_files)
|
|
164
|
+
return
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
########################################################################
|
|
2
|
+
#
|
|
3
|
+
# Copyright (C) 2023
|
|
4
|
+
# Associated Universities, Inc. Washington DC, USA.
|
|
5
|
+
#
|
|
6
|
+
# This script is free software; you can redistribute it and/or modify it
|
|
7
|
+
# under the terms of the GNU Library General Public License as published by
|
|
8
|
+
# the Free Software Foundation; either version 2 of the License, or (at your
|
|
9
|
+
# option) any later version.
|
|
10
|
+
#
|
|
11
|
+
# This library is distributed in the hope that it will be useful, but WITHOUT
|
|
12
|
+
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
13
|
+
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
|
|
14
|
+
# License for more details.
|
|
15
|
+
#
|
|
16
|
+
# You should have received a copy of the GNU Library General Public License
|
|
17
|
+
# along with this library; if not, write to the Free Software Foundation,
|
|
18
|
+
# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
|
|
19
|
+
#
|
|
20
|
+
# Correspondence concerning AIPS++ should be adressed as follows:
|
|
21
|
+
# Internet email: casa-feedback@nrao.edu.
|
|
22
|
+
# Postal address: AIPS++ Project Office
|
|
23
|
+
# National Radio Astronomy Observatory
|
|
24
|
+
# 520 Edgemont Road
|
|
25
|
+
# Charlottesville, VA 22903-2475 USA
|
|
26
|
+
#
|
|
27
|
+
########################################################################
|
|
28
|
+
'''This contains functions which return the URLs to the ``cubevis``
|
|
29
|
+
JavaScript libraries. The ``casalib`` library has Bokeh independent
|
|
30
|
+
functions while the `cubevisjs` library has the Bokeh extensions'''
|
|
31
|
+
from ...utils import static_vars
|
|
32
|
+
from ._initialize import initialize_bokeh
|
|
33
|
+
from os import path
|
|
34
|
+
|
|
35
|
+
@static_vars( library_path=None )
|
|
36
|
+
def casalib_url( ):
|
|
37
|
+
if casalib_url.library_path is None:
|
|
38
|
+
casalib_url.library_path = path.join(path.dirname(path.dirname(path.dirname(__file__))), '__js__', 'casalib.min.js')
|
|
39
|
+
if not path.isfile(casalib_url.library_path):
|
|
40
|
+
raise RuntimeError( f''''casalib' JavaScript library not found at '{casalib_url.library_path}\'''' )
|
|
41
|
+
if not initialize_bokeh.initialized:
|
|
42
|
+
initialize_bokeh( )
|
|
43
|
+
return f'''file://{casalib_url.library_path}'''
|
|
44
|
+
|
|
45
|
+
@static_vars( library_path=None )
|
|
46
|
+
def cubevisjs_url( ):
|
|
47
|
+
if cubevisjs_url.library_path is None:
|
|
48
|
+
cubevisjs_url.library_path = path.join(path.dirname(path.dirname(path.dirname(__file__))), '__js__', 'cubevisjs.min.js')
|
|
49
|
+
if not path.isfile(cubevisjs_url.library_path):
|
|
50
|
+
raise RuntimeError( f''''cubevisjs' JavaScript library not found at '{cubevisjs_url.library_path}\'''' )
|
|
51
|
+
if not initialize_bokeh.initialized:
|
|
52
|
+
initialize_bokeh( )
|
|
53
|
+
return f'''file://{cubevisjs_url.library_path}'''
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
########################################################################
|
|
2
|
+
#
|
|
3
|
+
# Copyright (C) 2022
|
|
4
|
+
# Associated Universities, Inc. Washington DC, USA.
|
|
5
|
+
#
|
|
6
|
+
# This script is free software; you can redistribute it and/or modify it
|
|
7
|
+
# under the terms of the GNU Library General Public License as published by
|
|
8
|
+
# the Free Software Foundation; either version 2 of the License, or (at your
|
|
9
|
+
# option) any later version.
|
|
10
|
+
#
|
|
11
|
+
# This library is distributed in the hope that it will be useful, but WITHOUT
|
|
12
|
+
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
13
|
+
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
|
|
14
|
+
# License for more details.
|
|
15
|
+
#
|
|
16
|
+
# You should have received a copy of the GNU Library General Public License
|
|
17
|
+
# along with this library; if not, write to the Free Software Foundation,
|
|
18
|
+
# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
|
|
19
|
+
#
|
|
20
|
+
# Correspondence concerning AIPS++ should be adressed as follows:
|
|
21
|
+
# Internet email: casa-feedback@nrao.edu.
|
|
22
|
+
# Postal address: AIPS++ Project Office
|
|
23
|
+
# National Radio Astronomy Observatory
|
|
24
|
+
# 520 Edgemont Road
|
|
25
|
+
# Charlottesville, VA 22903-2475 USA
|
|
26
|
+
#
|
|
27
|
+
########################################################################
|
|
28
|
+
'''Functions for palette access.'''
|
|
29
|
+
import re
|
|
30
|
+
from bokeh import palettes as __palettes
|
|
31
|
+
from ...utils import static_vars
|
|
32
|
+
|
|
33
|
+
__palette_list = sorted( [ p for p in dir(__palettes) if isinstance(getattr(__palettes,p), tuple) if len(getattr( __palettes, p )) == 256 ] )
|
|
34
|
+
__palette_names = [ re.sub(r'\d+$', '', p) for p in __palette_list ]
|
|
35
|
+
|
|
36
|
+
__palette_map = dict( zip( __palette_names, __palette_list ) )
|
|
37
|
+
|
|
38
|
+
def available_palettes ( ):
|
|
39
|
+
'''returns list of palette pretty names'''
|
|
40
|
+
return __palette_names
|
|
41
|
+
|
|
42
|
+
def find_palette( name ):
|
|
43
|
+
'''fetches palette by the pretty name'''
|
|
44
|
+
if name not in __palette_map:
|
|
45
|
+
return None
|
|
46
|
+
return getattr( __palettes, __palette_map[name] )
|
|
47
|
+
|
|
48
|
+
@static_vars( raw=None, pretty=None )
|
|
49
|
+
def default_palette( raw=False ):
|
|
50
|
+
'''returns the full name (raw or pretty version)'''
|
|
51
|
+
if default_palette.pretty is None:
|
|
52
|
+
if 'Plasma' in __palette_map:
|
|
53
|
+
default_palette.pretty = 'Plasma'
|
|
54
|
+
default_palette.raw = __palette_map['Plasma']
|
|
55
|
+
else:
|
|
56
|
+
default_palette.pretty = __palette_names[0]
|
|
57
|
+
default_palette.raw = __palette_map[__palette_names[0]]
|
|
58
|
+
return default_palette.raw if raw else default_palette.pretty
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
########################################################################
|
|
2
|
+
#
|
|
3
|
+
# Copyright (C) 2022
|
|
4
|
+
# Associated Universities, Inc. Washington DC, USA.
|
|
5
|
+
#
|
|
6
|
+
# This script is free software; you can redistribute it and/or modify it
|
|
7
|
+
# under the terms of the GNU Library General Public License as published by
|
|
8
|
+
# the Free Software Foundation; either version 2 of the License, or (at your
|
|
9
|
+
# option) any later version.
|
|
10
|
+
#
|
|
11
|
+
# This library is distributed in the hope that it will be useful, but WITHOUT
|
|
12
|
+
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
13
|
+
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
|
|
14
|
+
# License for more details.
|
|
15
|
+
#
|
|
16
|
+
# You should have received a copy of the GNU Library General Public License
|
|
17
|
+
# along with this library; if not, write to the Free Software Foundation,
|
|
18
|
+
# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
|
|
19
|
+
#
|
|
20
|
+
# Correspondence concerning AIPS++ should be adressed as follows:
|
|
21
|
+
# Internet email: casa-feedback@nrao.edu.
|
|
22
|
+
# Postal address: AIPS++ Project Office
|
|
23
|
+
# National Radio Astronomy Observatory
|
|
24
|
+
# 520 Edgemont Road
|
|
25
|
+
# Charlottesville, VA 22903-2475 USA
|
|
26
|
+
#
|
|
27
|
+
########################################################################
|
|
28
|
+
'''Functions for session management.'''
|
|
29
|
+
from bokeh.io import output_notebook
|
|
30
|
+
|
|
31
|
+
def setup_session():
|
|
32
|
+
'''Configure session for notebook or terminal'''
|
|
33
|
+
|
|
34
|
+
#session_settings = {
|
|
35
|
+
# "ZMQInteractiveShell": "Running in a Jupyter notebook",
|
|
36
|
+
# "TerminalInteractiveShell": "Running in a terminal",
|
|
37
|
+
#}
|
|
38
|
+
try:
|
|
39
|
+
session = get_ipython().__class__.__name__
|
|
40
|
+
except NameError:
|
|
41
|
+
session = "Unknown"
|
|
42
|
+
|
|
43
|
+
if session == "ZMQInteractiveShell":
|
|
44
|
+
output_notebook()
|