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,286 @@
|
|
|
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
|
+
"""
|
|
29
|
+
plotants module
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
import os
|
|
33
|
+
|
|
34
|
+
import numpy as np
|
|
35
|
+
from bokeh.io import export_png, export_svgs
|
|
36
|
+
from bokeh.models import ColumnDataSource, LabelSet
|
|
37
|
+
from bokeh.plotting import figure, show
|
|
38
|
+
|
|
39
|
+
try:
|
|
40
|
+
from cairosvg import svg2pdf
|
|
41
|
+
_have_svg2pdf = True
|
|
42
|
+
except ImportError:
|
|
43
|
+
_have_svg2pdf = False
|
|
44
|
+
|
|
45
|
+
try:
|
|
46
|
+
import casatools as ct
|
|
47
|
+
from casatools import table, msmetadata, quanta, ms, measures
|
|
48
|
+
except:
|
|
49
|
+
ct = None
|
|
50
|
+
from cubevis.utils import warn_import
|
|
51
|
+
warn_import('casatools')
|
|
52
|
+
|
|
53
|
+
_FIGURE_PLOT_WIDTH = 450
|
|
54
|
+
_FIGURE_PLOT_HEIGHT = 450
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def __get_observatory_info(msname):
|
|
58
|
+
"""Extract the observatory information from `msname`.
|
|
59
|
+
|
|
60
|
+
Parameters
|
|
61
|
+
----------
|
|
62
|
+
msname: string
|
|
63
|
+
Path to a CASA measurement set.
|
|
64
|
+
|
|
65
|
+
Returns
|
|
66
|
+
-------
|
|
67
|
+
( string, list )
|
|
68
|
+
string is the telescope name and the list is the array position
|
|
69
|
+
"""
|
|
70
|
+
metadata = ct.msmetadata()
|
|
71
|
+
metadata.open(msname)
|
|
72
|
+
telescope = metadata.observatorynames()[0]
|
|
73
|
+
positions = metadata.observatoryposition()
|
|
74
|
+
metadata.close()
|
|
75
|
+
return telescope, positions
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def __get_antenna_info(msname, log, exclude, checkbaselines):
|
|
79
|
+
"""Return the antenna position info.
|
|
80
|
+
|
|
81
|
+
Parameters
|
|
82
|
+
----------
|
|
83
|
+
msname: string
|
|
84
|
+
Path to the CASA measurement set.
|
|
85
|
+
log: boolean
|
|
86
|
+
whether to plot logarithmic positions
|
|
87
|
+
exclude: [ int ]
|
|
88
|
+
list antenna name/id selection to exclude from plot
|
|
89
|
+
checkbaselines: boolean
|
|
90
|
+
whether to check baselines in the main table
|
|
91
|
+
"""
|
|
92
|
+
if ct is None:
|
|
93
|
+
raise RuntimeError('casatools is not available')
|
|
94
|
+
|
|
95
|
+
me = ct.measures()
|
|
96
|
+
qa = ct.quanta()
|
|
97
|
+
tb = ct.table()
|
|
98
|
+
|
|
99
|
+
telescope, positions = __get_observatory_info(msname)
|
|
100
|
+
positions_wgs84 = me.measure(positions, "WGS84")
|
|
101
|
+
array_lon, array_lat, = [positions_wgs84[i]["value"] for i in ["m0", "m1", "m2"]]
|
|
102
|
+
|
|
103
|
+
# Open the ANTENNA subtable to get the names of the antennas in this MS and
|
|
104
|
+
# their positions. Note that the entries in the ANTENNA subtable are pretty
|
|
105
|
+
# much in random order, so antenna_names translates between their index and name
|
|
106
|
+
# (e.g., index 11 = STD155). We'll need these indices for later, since the
|
|
107
|
+
# main data table refers to the antennas by their indices, not names.
|
|
108
|
+
|
|
109
|
+
anttabname = msname + "/ANTENNA"
|
|
110
|
+
tb.open(anttabname)
|
|
111
|
+
# Get antenna names from antenna table
|
|
112
|
+
antenna_names = np.array(tb.getcol("NAME")).tolist()
|
|
113
|
+
station_names = np.array(tb.getcol("STATION")).tolist()
|
|
114
|
+
if telescope == "VLBA": # names = ant@station
|
|
115
|
+
antenna_names = ["@".join(antsta) for antsta in zip(antenna_names, station_names)]
|
|
116
|
+
# Get antenna positions from antenna table
|
|
117
|
+
antenna_positions = np.array(
|
|
118
|
+
[
|
|
119
|
+
me.position("ITRF", qa.quantity(x, "m"), qa.quantity(y, "m"), qa.quantity(z, "m"))
|
|
120
|
+
for (x, y, z) in tb.getcol("POSITION").transpose()
|
|
121
|
+
]
|
|
122
|
+
)
|
|
123
|
+
tb.close()
|
|
124
|
+
|
|
125
|
+
all_ant_ids = range(len(antenna_names))
|
|
126
|
+
if checkbaselines:
|
|
127
|
+
# Get antenna ids from main table; this will add to runtime
|
|
128
|
+
tb.open(msname)
|
|
129
|
+
ants1 = tb.getcol("ANTENNA1")
|
|
130
|
+
ants2 = tb.getcol("ANTENNA2")
|
|
131
|
+
tb.close()
|
|
132
|
+
ant_ids_used = list(set(np.append(ants1, ants2)))
|
|
133
|
+
else:
|
|
134
|
+
# use them all!
|
|
135
|
+
ant_ids_used = all_ant_ids
|
|
136
|
+
|
|
137
|
+
# handle exclude -- remove from ant_ids_used
|
|
138
|
+
for ant_id in exclude:
|
|
139
|
+
try:
|
|
140
|
+
ant_name_id = antenna_names[ant_id] + " (id " + str(ant_id) + ")"
|
|
141
|
+
ant_ids_used.remove(ant_id)
|
|
142
|
+
print( f'''Exclude antenna {ant_name_id}''' )
|
|
143
|
+
except ValueError:
|
|
144
|
+
print( f'''Cannot exclude antenna {ant_name_id}: not in main table''' )
|
|
145
|
+
|
|
146
|
+
# apply ant_ids_used mask
|
|
147
|
+
antenna_names = [antenna_names[i] for i in ant_ids_used]
|
|
148
|
+
antenna_positions = [antenna_positions[i] for i in ant_ids_used]
|
|
149
|
+
station_names = [station_names[i] for i in ant_ids_used]
|
|
150
|
+
|
|
151
|
+
n_ants = len(ant_ids_used)
|
|
152
|
+
# casalog.post("Number of points being plotted: " + str(n_ants))
|
|
153
|
+
if n_ants == 0: # excluded all antennas
|
|
154
|
+
return telescope, antenna_names, [], [], [], []
|
|
155
|
+
|
|
156
|
+
# Get the names, indices, and lat/lon/alt coords of "good" antennas.
|
|
157
|
+
ant_wgs84s = np.array([me.measure(pos, "WGS84") for pos in antenna_positions])
|
|
158
|
+
|
|
159
|
+
# Convert from lat, lon, alt to X, Y, Z (unless VLBA)
|
|
160
|
+
# where X is east, Y is north, Z is up,
|
|
161
|
+
# and 0, 0, 0 is the center
|
|
162
|
+
# Note: this conversion is NOT exact, since it doesn't take into account
|
|
163
|
+
# Earth's ellipticity! But it's close enough.
|
|
164
|
+
if telescope == "VLBA" and not log:
|
|
165
|
+
ant_lons, ant_lats = [[pos[i] for pos in ant_wgs84s] for i in ["m0", "m1"]]
|
|
166
|
+
ant_xs = [qa.convert(lon, "deg")["value"] for lon in ant_lons]
|
|
167
|
+
ant_ys = [qa.convert(lat, "deg")["value"] for lat in ant_lats]
|
|
168
|
+
else:
|
|
169
|
+
ant_lons, ant_lats = [np.array([pos[i]["value"] for pos in ant_wgs84s]) for i in ["m0", "m1"]]
|
|
170
|
+
rade = 6370000.0 # radE
|
|
171
|
+
ant_xs = (ant_lons - array_lon) * rade * np.cos(array_lat)
|
|
172
|
+
ant_ys = (ant_lats - array_lat) * rade
|
|
173
|
+
return telescope, antenna_names, ant_ids_used, ant_xs, ant_ys, station_names
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
def __plot_antennas_log(telescope, names, ids, xpos, ypos, antindex, stations, title):
|
|
177
|
+
raise NotImplementedError("This is a placeholder for another type of plot. It is not implemented yet.")
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
def __plot_antennas(telescope, names, ids, xpos, ypos, antindex, stations, title):
|
|
181
|
+
if telescope == "VLBA":
|
|
182
|
+
labelx = "Longitude (deg)"
|
|
183
|
+
labely = "Latitude (deg)"
|
|
184
|
+
else:
|
|
185
|
+
# use m or km units
|
|
186
|
+
units = " (m)"
|
|
187
|
+
if np.median(xpos) > 1e6 or np.median(ypos) > 1e6:
|
|
188
|
+
xpos /= 1e3
|
|
189
|
+
ypos /= 1e3
|
|
190
|
+
units = " (km)"
|
|
191
|
+
labelx = "X" + units
|
|
192
|
+
labely = "Y" + units
|
|
193
|
+
if antindex:
|
|
194
|
+
names = [f"{name} ({idx})" for name, idx in zip(names, ids)]
|
|
195
|
+
source = ColumnDataSource(data=dict(x=[], y=[], labels=[]))
|
|
196
|
+
source.data = dict(x=xpos, y=ypos, labels=names)
|
|
197
|
+
labels = LabelSet(x="x", y="y", text="labels", x_offset=5, y_offset=5, source=source, text_font_size="10pt")
|
|
198
|
+
plot = figure(plot_height=_FIGURE_PLOT_HEIGHT, plot_width=_FIGURE_PLOT_WIDTH)
|
|
199
|
+
plot.scatter("x", "y", source=source, size=5, line_color="red", fill_color="red", fill_alpha=0.5)
|
|
200
|
+
plot.title.text = title
|
|
201
|
+
plot.xaxis[0].axis_label = labelx
|
|
202
|
+
plot.yaxis[0].axis_label = labely
|
|
203
|
+
plot.add_layout(labels)
|
|
204
|
+
return plot
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
def plotants(vis, figfile="", antindex=False, logpos=False, exclude=[], checkbaselines=False, title="", showgui=True):
|
|
208
|
+
"""Plot the antenna distribution in the local reference frame:
|
|
209
|
+
The location of the antennas in the MS will be plotted with
|
|
210
|
+
X-toward local east; Y-toward local north. The name of each
|
|
211
|
+
antenna is shown next to its respective location.
|
|
212
|
+
|
|
213
|
+
Parameters
|
|
214
|
+
----------
|
|
215
|
+
vis: string
|
|
216
|
+
Path to the input visibility file
|
|
217
|
+
|
|
218
|
+
antindex: boolean, default: False
|
|
219
|
+
Label antennas with name and antenna ID
|
|
220
|
+
|
|
221
|
+
logpos: boolean, default: False
|
|
222
|
+
Produce a logarithmic position plot.
|
|
223
|
+
|
|
224
|
+
exclude: list, default: []
|
|
225
|
+
antenna IDs or names to exclude from plotting, for example:
|
|
226
|
+
exclude=[2,3,4], exclude=['DV15']
|
|
227
|
+
|
|
228
|
+
checkbaselines: boolean, default: False
|
|
229
|
+
Only plot antennas in the MAIN table. This can be useful after a split.
|
|
230
|
+
WARNING: Setting checkbaselines to True will add to runtime in proportion
|
|
231
|
+
to the number of rows in the dataset.
|
|
232
|
+
|
|
233
|
+
title: string, default: ''
|
|
234
|
+
Title written along top of plot
|
|
235
|
+
"""
|
|
236
|
+
if os.path.exists(vis) is False:
|
|
237
|
+
raise Exception(f"Visibility file {vis} does not exist") # could be a print + return
|
|
238
|
+
# remove trailing / for title basename
|
|
239
|
+
if vis.endswith("/"):
|
|
240
|
+
vis = vis[:-1]
|
|
241
|
+
|
|
242
|
+
myms = ct.ms()
|
|
243
|
+
try:
|
|
244
|
+
exclude = myms.msseltoindex(vis, baseline=exclude)["antenna1"].tolist()
|
|
245
|
+
except RuntimeError as rterr: # MSSelection failed
|
|
246
|
+
errmsg = str(rterr)
|
|
247
|
+
errmsg = errmsg.replace("specificion", "specification")
|
|
248
|
+
errmsg = errmsg.replace("Antenna Expression: ", "")
|
|
249
|
+
raise RuntimeError("Exclude selection error: " + errmsg) from rterr
|
|
250
|
+
|
|
251
|
+
# Get the antenna positions
|
|
252
|
+
telescope, names, ids, xpos, ypos, stations = __get_antenna_info(vis, logpos, exclude, checkbaselines)
|
|
253
|
+
if not names:
|
|
254
|
+
raise ValueError("No antennas selected. Exiting plotants.")
|
|
255
|
+
|
|
256
|
+
if title == "":
|
|
257
|
+
msname = os.path.basename(vis)
|
|
258
|
+
title = "Antenna Positions for "
|
|
259
|
+
if len(msname) > 55:
|
|
260
|
+
title += "\n"
|
|
261
|
+
title += msname
|
|
262
|
+
|
|
263
|
+
if logpos:
|
|
264
|
+
fig = __plot_antennas_log(telescope, names, ids, xpos, ypos, antindex, stations, title)
|
|
265
|
+
else:
|
|
266
|
+
fig = __plot_antennas(telescope, names, ids, xpos, ypos, antindex, stations, title)
|
|
267
|
+
|
|
268
|
+
if showgui is not False:
|
|
269
|
+
show(fig)
|
|
270
|
+
|
|
271
|
+
if figfile != "":
|
|
272
|
+
if figfile.endswith(".png"):
|
|
273
|
+
export_png(fig, filename=figfile)
|
|
274
|
+
elif figfile.endswith(".svg"):
|
|
275
|
+
fig.output_backend = "svg"
|
|
276
|
+
export_svgs(fig, filename=figfile)
|
|
277
|
+
elif figfile.endswith(".pdf"):
|
|
278
|
+
if _have_svg2pdf == True:
|
|
279
|
+
fig.output_backend = "svg"
|
|
280
|
+
export_svgs(fig, filename=figfile.replace(".pdf", ".svg"))
|
|
281
|
+
svg2pdf(url=figfile.replace(".pdf", ".svg"), write_to=figfile)
|
|
282
|
+
os.system("rm " + figfile.replace(".pdf", ".svg"))
|
|
283
|
+
else:
|
|
284
|
+
raise RuntimeError("cairosvg is required for generating PDF output, but it is not available")
|
|
285
|
+
else:
|
|
286
|
+
raise ValueError("Invalid output file type. Must be .png or .svg or .pdf")
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
########################################################################
|
|
2
|
+
#
|
|
3
|
+
# Copyright (C) 2021, 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
|
+
'''This module contains the extensions and additions to the functionality
|
|
29
|
+
provided by Bokeh'''
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from ._ev_poly_annotation import EvPolyAnnotation
|
|
@@ -0,0 +1,28 @@
|
|
|
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
|
+
'''Custom Bokeh GUI Components'''
|
|
@@ -0,0 +1,31 @@
|
|
|
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
|
+
'''Implementation of Bokeh formatting extensions provided by ``cubevis``'''
|
|
29
|
+
|
|
30
|
+
from ._time_ticks import get_time_formatter
|
|
31
|
+
from ._wcs_ticks import WcsTicks
|
|
@@ -0,0 +1,44 @@
|
|
|
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
|
+
|
|
29
|
+
''' Format time ticks for consistency at various zoom levels '''
|
|
30
|
+
|
|
31
|
+
from bokeh.models.formatters import DatetimeTickFormatter
|
|
32
|
+
|
|
33
|
+
def get_time_formatter():
|
|
34
|
+
''' Tick formatter which includes H:M:S in most ticks '''
|
|
35
|
+
return DatetimeTickFormatter(
|
|
36
|
+
context_which = 'all',
|
|
37
|
+
microseconds='%fus',
|
|
38
|
+
milliseconds='%H:%M:%S %3Nms',
|
|
39
|
+
seconds='%H:%M:%S',
|
|
40
|
+
minsec='%H:%M:%S',
|
|
41
|
+
minutes='%H:%M:%S',
|
|
42
|
+
hourmin='%H:%M:%S',
|
|
43
|
+
hours='%H:%M:%S',
|
|
44
|
+
days='%F')
|
|
@@ -0,0 +1,45 @@
|
|
|
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
|
+
from bokeh.models import TickFormatter
|
|
29
|
+
from bokeh.util.compiler import TypeScript
|
|
30
|
+
from bokeh.core.properties import Instance, String
|
|
31
|
+
from cubevis.bokeh.sources import ImageDataSource
|
|
32
|
+
from ..state import casalib_url, cubevisjs_url
|
|
33
|
+
|
|
34
|
+
class WcsTicks(TickFormatter):
|
|
35
|
+
|
|
36
|
+
## which axis are we labeling
|
|
37
|
+
axis = String( )
|
|
38
|
+
|
|
39
|
+
## source containing the WCS information
|
|
40
|
+
image_source = Instance(ImageDataSource)
|
|
41
|
+
|
|
42
|
+
__javascript__ = [ casalib_url( ), cubevisjs_url( ) ]
|
|
43
|
+
|
|
44
|
+
def __init__( self, *args, **kwargs ):
|
|
45
|
+
super( ).__init__( *args, **kwargs )
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
from bokeh.models import Tooltip
|
|
2
|
+
from bokeh.models.layouts import LayoutDOM, UIElement
|
|
3
|
+
from bokeh.core.properties import Instance, Required, Float, Int, Either
|
|
4
|
+
|
|
5
|
+
class Tip(LayoutDOM):
|
|
6
|
+
'''Display a tooltip for the child element
|
|
7
|
+
'''
|
|
8
|
+
|
|
9
|
+
def __init__(self, *args, **kwargs) -> None:
|
|
10
|
+
if len(args) != 1 and "child" not in kwargs:
|
|
11
|
+
raise ValueError("a 'child' argument must be supplied")
|
|
12
|
+
elif len(args) == 1 and "child" in kwargs:
|
|
13
|
+
raise ValueError("'child' supplied as both a positional argument and a keyword")
|
|
14
|
+
elif len(args) > 1:
|
|
15
|
+
raise ValueError("only one 'child' can be supplied as a positional argument")
|
|
16
|
+
elif len(args) > 0:
|
|
17
|
+
kwargs["child"] = args[0]
|
|
18
|
+
|
|
19
|
+
super().__init__(**kwargs)
|
|
20
|
+
|
|
21
|
+
child = Required(Instance(UIElement), help="""
|
|
22
|
+
A child, which can be other components including plots, rows, columns, and widgets.
|
|
23
|
+
""")
|
|
24
|
+
|
|
25
|
+
tooltip = Required(Instance(Tooltip), help="""
|
|
26
|
+
A tooltip with plain text or rich HTML contents, providing general help or
|
|
27
|
+
description of a widget's or component's function.
|
|
28
|
+
""")
|
|
29
|
+
|
|
30
|
+
hover_wait = Either( Float, Int, default=1.5, help='''
|
|
31
|
+
amount of time (in seconds) to wait before displaying
|
|
32
|
+
''' )
|
|
33
|
+
|
|
34
|
+
def _sphinx_height_hint(self):
|
|
35
|
+
if child._sphinx_height_hint() is None:
|
|
36
|
+
return None
|
|
37
|
+
return child._sphinx_height_hint()
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
|
|
2
|
+
from bokeh.models.callbacks import Callback
|
|
3
|
+
from bokeh.util.callback_manager import EventCallback
|
|
4
|
+
from bokeh.events import ButtonClick
|
|
5
|
+
from bokeh.models.widgets.buttons import AbstractButton
|
|
6
|
+
from bokeh.models.ui.icons import BuiltinIcon
|
|
7
|
+
from bokeh.core.properties import Instance, Required, Override, Nullable, Float, Int, Either
|
|
8
|
+
from bokeh.models import Tooltip
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class TipButton(AbstractButton):
|
|
13
|
+
""" A button with a help symbol that displays additional text when hovered
|
|
14
|
+
over or clicked.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
# explicit __init__ to support Init signatures
|
|
18
|
+
def __init__(self, *args, **kwargs) -> None:
|
|
19
|
+
super().__init__(*args, **kwargs)
|
|
20
|
+
|
|
21
|
+
tooltip = Required(Instance(Tooltip), help="""
|
|
22
|
+
A tooltip with plain text or rich HTML contents, providing general help or
|
|
23
|
+
description of a widget's or component's function.
|
|
24
|
+
""")
|
|
25
|
+
|
|
26
|
+
hover_wait = Either( Float, Int, default=1.5, help='''
|
|
27
|
+
amount of time (in seconds) to wait before displaying
|
|
28
|
+
''' )
|
|
29
|
+
|
|
30
|
+
label = Override(default="")
|
|
31
|
+
|
|
32
|
+
icon = Override(default=lambda: BuiltinIcon("help", size=18))
|
|
33
|
+
|
|
34
|
+
button_type = Override(default="default")
|
|
35
|
+
|
|
36
|
+
def on_click(self, handler: EventCallback) -> None:
|
|
37
|
+
''' Set up a handler for button clicks.
|
|
38
|
+
|
|
39
|
+
Args:
|
|
40
|
+
handler (func) : handler function to call when button is clicked.
|
|
41
|
+
|
|
42
|
+
Returns:
|
|
43
|
+
None
|
|
44
|
+
|
|
45
|
+
'''
|
|
46
|
+
self.on_event(ButtonClick, handler)
|
|
47
|
+
|
|
48
|
+
def js_on_click(self, handler: Callback) -> None:
|
|
49
|
+
''' Set up a JavaScript handler for button clicks. '''
|
|
50
|
+
self.js_on_event(ButtonClick, handler)
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
########################################################################
|
|
2
|
+
#
|
|
3
|
+
# Copyright (C) 2021,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
|
+
'''Implementation of the Bokeh data source extensions provided by
|
|
29
|
+
``cubevis``'''
|
|
30
|
+
|
|
31
|
+
from ._data_pipe import DataPipe
|
|
32
|
+
from ._image_pipe import ImagePipe
|
|
33
|
+
from ._image_data_source import ImageDataSource
|
|
34
|
+
from ._spectra_data_source import SpectraDataSource
|
|
35
|
+
from ._updatable_data_source import UpdatableDataSource
|