cubevis 0.5.13__py3-none-any.whl → 0.5.15__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.
Potentially problematic release.
This version of cubevis might be problematic. Click here for more details.
- cubevis/__version__.py +1 -1
- cubevis/private/apps/__init__.py +5 -1
- cubevis/toolbox/_cube.py +14 -11
- {cubevis-0.5.13.dist-info → cubevis-0.5.15.dist-info}/METADATA +1 -1
- {cubevis-0.5.13.dist-info → cubevis-0.5.15.dist-info}/RECORD +7 -27
- cubevis/data/measurement_set/__init__.py +0 -7
- cubevis/data/measurement_set/_ms_data.py +0 -178
- cubevis/data/measurement_set/processing_set/__init__.py +0 -30
- cubevis/data/measurement_set/processing_set/_ps_concat.py +0 -98
- cubevis/data/measurement_set/processing_set/_ps_coords.py +0 -78
- cubevis/data/measurement_set/processing_set/_ps_data.py +0 -213
- cubevis/data/measurement_set/processing_set/_ps_io.py +0 -55
- cubevis/data/measurement_set/processing_set/_ps_raster_data.py +0 -154
- cubevis/data/measurement_set/processing_set/_ps_select.py +0 -91
- cubevis/data/measurement_set/processing_set/_ps_stats.py +0 -218
- cubevis/data/measurement_set/processing_set/_xds_data.py +0 -149
- cubevis/plot/__init__.py +0 -1
- cubevis/plot/ms_plot/__init__.py +0 -29
- cubevis/plot/ms_plot/_ms_plot.py +0 -242
- cubevis/plot/ms_plot/_ms_plot_constants.py +0 -22
- cubevis/plot/ms_plot/_ms_plot_selectors.py +0 -348
- cubevis/plot/ms_plot/_raster_plot.py +0 -292
- cubevis/plot/ms_plot/_raster_plot_inputs.py +0 -116
- cubevis/plot/ms_plot/_xds_plot_axes.py +0 -110
- cubevis/private/apps/_ms_raster.py +0 -815
- {cubevis-0.5.13.dist-info → cubevis-0.5.15.dist-info}/WHEEL +0 -0
- {cubevis-0.5.13.dist-info → cubevis-0.5.15.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,348 +0,0 @@
|
|
|
1
|
-
'''
|
|
2
|
-
Create panel widgets for various functions
|
|
3
|
-
'''
|
|
4
|
-
|
|
5
|
-
import panel as pn
|
|
6
|
-
|
|
7
|
-
from cubevis.bokeh.state._palette import available_palettes
|
|
8
|
-
from cubevis.plot.ms_plot._ms_plot_constants import VIS_AXIS_OPTIONS, AGGREGATOR_OPTIONS, DEFAULT_UNFLAGGED_CMAP, DEFAULT_FLAGGED_CMAP
|
|
9
|
-
|
|
10
|
-
def file_selector(description, start_dir, callback):
|
|
11
|
-
''' Return a layout for file selection with input description and start directory.
|
|
12
|
-
Includes a TextInput and a FileSelector, with a callback to set TextInput from FileSelector.
|
|
13
|
-
'''
|
|
14
|
-
filename = pn.widgets.TextInput(
|
|
15
|
-
description=description,
|
|
16
|
-
name="Filename",
|
|
17
|
-
placeholder='Enter filename or use file browser below',
|
|
18
|
-
sizing_mode='stretch_width',
|
|
19
|
-
)
|
|
20
|
-
|
|
21
|
-
file_select = pn.widgets.FileSelector(
|
|
22
|
-
start_dir,
|
|
23
|
-
)
|
|
24
|
-
select_file = pn.bind(callback, file_select)
|
|
25
|
-
|
|
26
|
-
fs_card = pn.Card(
|
|
27
|
-
file_select,
|
|
28
|
-
title='File browser',
|
|
29
|
-
collapsed=True,
|
|
30
|
-
collapsible=True,
|
|
31
|
-
sizing_mode='stretch_width',
|
|
32
|
-
)
|
|
33
|
-
|
|
34
|
-
return pn.Column(
|
|
35
|
-
pn.Row( # [0]
|
|
36
|
-
filename, # [0]
|
|
37
|
-
select_file # [1]
|
|
38
|
-
),
|
|
39
|
-
fs_card, # [1]
|
|
40
|
-
width_policy='min',
|
|
41
|
-
)
|
|
42
|
-
|
|
43
|
-
def style_selector(style_callback, color_range_callback):
|
|
44
|
-
''' Return a layout for style parameters.
|
|
45
|
-
Currently supports colormaps, colorbar, and color limits.
|
|
46
|
-
'''
|
|
47
|
-
cmaps = available_palettes()
|
|
48
|
-
|
|
49
|
-
cmap_selector = pn.widgets.Select(
|
|
50
|
-
name="Unflagged data colormap",
|
|
51
|
-
options=cmaps,
|
|
52
|
-
value=DEFAULT_UNFLAGGED_CMAP,
|
|
53
|
-
sizing_mode='scale_width',
|
|
54
|
-
)
|
|
55
|
-
|
|
56
|
-
flagged_cmap_selector = pn.widgets.Select(
|
|
57
|
-
name="Flagged data colormap",
|
|
58
|
-
options=cmaps,
|
|
59
|
-
value=DEFAULT_FLAGGED_CMAP,
|
|
60
|
-
sizing_mode='scale_width',
|
|
61
|
-
)
|
|
62
|
-
|
|
63
|
-
colorbar_checkbox = pn.widgets.Checkbox(
|
|
64
|
-
name="Show colorbar",
|
|
65
|
-
value=True,
|
|
66
|
-
)
|
|
67
|
-
|
|
68
|
-
flagged_colorbar_checkbox = pn.widgets.Checkbox(
|
|
69
|
-
name="Show flagged colorbar",
|
|
70
|
-
value=True,
|
|
71
|
-
)
|
|
72
|
-
|
|
73
|
-
select_style = pn.bind(style_callback, cmap_selector, flagged_cmap_selector, colorbar_checkbox, flagged_colorbar_checkbox)
|
|
74
|
-
|
|
75
|
-
color_mode_selector = pn.widgets.RadioBoxGroup(
|
|
76
|
-
options=["No color range", "Auto color range", "Manual color range"],
|
|
77
|
-
)
|
|
78
|
-
|
|
79
|
-
color_range_slider = pn.widgets.RangeSlider(
|
|
80
|
-
name="Colorbar range",
|
|
81
|
-
)
|
|
82
|
-
|
|
83
|
-
select_color_range = pn.bind(color_range_callback, color_mode_selector, color_range_slider)
|
|
84
|
-
|
|
85
|
-
return pn.Column(
|
|
86
|
-
pn.Row( # [0]
|
|
87
|
-
cmap_selector, # [0]
|
|
88
|
-
flagged_cmap_selector, # [1]
|
|
89
|
-
),
|
|
90
|
-
pn.Row( # [1]
|
|
91
|
-
colorbar_checkbox, # [0]
|
|
92
|
-
flagged_colorbar_checkbox, # [1]
|
|
93
|
-
),
|
|
94
|
-
select_style, # [2]
|
|
95
|
-
pn.Row( # [3]
|
|
96
|
-
color_mode_selector, # [0]
|
|
97
|
-
color_range_slider, # [1]
|
|
98
|
-
),
|
|
99
|
-
select_color_range, # [4]
|
|
100
|
-
width_policy='min',
|
|
101
|
-
)
|
|
102
|
-
|
|
103
|
-
def title_selector(callback):
|
|
104
|
-
''' Return a layout for title input using TextInput '''
|
|
105
|
-
title_input = pn.widgets.TextInput(
|
|
106
|
-
name="Title",
|
|
107
|
-
placeholder="Enter title for plot ('ms' to use MS name)",
|
|
108
|
-
sizing_mode='stretch_width',
|
|
109
|
-
)
|
|
110
|
-
select_title = pn.bind(callback, title_input)
|
|
111
|
-
return pn.Row(
|
|
112
|
-
title_input,
|
|
113
|
-
select_title,
|
|
114
|
-
width_policy='min',
|
|
115
|
-
)
|
|
116
|
-
|
|
117
|
-
def axis_selector(x_axis, y_axis, axis_options, include_vis, callback):
|
|
118
|
-
''' Return layout of selectors for x-axis, y-axis, and vis-axis '''
|
|
119
|
-
x_options = axis_options if axis_options else [x_axis]
|
|
120
|
-
x_selector = pn.widgets.Select(
|
|
121
|
-
name="X Axis",
|
|
122
|
-
options=x_options,
|
|
123
|
-
value=x_axis,
|
|
124
|
-
sizing_mode='scale_width',
|
|
125
|
-
)
|
|
126
|
-
|
|
127
|
-
y_options = axis_options if axis_options else [y_axis]
|
|
128
|
-
y_selector = pn.widgets.Select(
|
|
129
|
-
name="Y Axis",
|
|
130
|
-
options=y_options,
|
|
131
|
-
value=y_axis,
|
|
132
|
-
sizing_mode='scale_width',
|
|
133
|
-
)
|
|
134
|
-
|
|
135
|
-
if include_vis:
|
|
136
|
-
# for raster plot
|
|
137
|
-
vis_label = pn.pane.LaTeX(
|
|
138
|
-
r"Vis Axis",
|
|
139
|
-
)
|
|
140
|
-
vis_selector = pn.widgets.RadioBoxGroup(
|
|
141
|
-
options=VIS_AXIS_OPTIONS,
|
|
142
|
-
inline=True,
|
|
143
|
-
)
|
|
144
|
-
select_axes = pn.bind(callback, x_selector, y_selector, vis_selector)
|
|
145
|
-
return pn.Column(
|
|
146
|
-
pn.Row( # [0]
|
|
147
|
-
x_selector, # [0]
|
|
148
|
-
y_selector # [1]
|
|
149
|
-
),
|
|
150
|
-
vis_label, # [1]
|
|
151
|
-
vis_selector, # [2]
|
|
152
|
-
select_axes,
|
|
153
|
-
width_policy='min',
|
|
154
|
-
)
|
|
155
|
-
|
|
156
|
-
# for scatter plot
|
|
157
|
-
select_axes = pn.bind(callback, x_selector, y_selector)
|
|
158
|
-
return pn.Column(
|
|
159
|
-
pn.Row( # [0]
|
|
160
|
-
x_selector, # [0]
|
|
161
|
-
y_selector # [1]
|
|
162
|
-
),
|
|
163
|
-
select_axes,
|
|
164
|
-
width_policy='min',
|
|
165
|
-
)
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
def aggregation_selector(axis_options, callback):
|
|
169
|
-
''' Return layout of selectors for aggregator and agg axes '''
|
|
170
|
-
agg_selector = pn.widgets.Select(
|
|
171
|
-
name="Aggregator",
|
|
172
|
-
options=AGGREGATOR_OPTIONS,
|
|
173
|
-
description="Select aggregation type",
|
|
174
|
-
sizing_mode='scale_width',
|
|
175
|
-
)
|
|
176
|
-
|
|
177
|
-
agg_axis_selector = pn.widgets.MultiSelect(
|
|
178
|
-
name="Agg axis or axes",
|
|
179
|
-
options=axis_options,
|
|
180
|
-
description="Select one or more axes to aggregate",
|
|
181
|
-
sizing_mode='scale_width',
|
|
182
|
-
)
|
|
183
|
-
|
|
184
|
-
select_agg = pn.bind(callback, agg_selector, agg_axis_selector)
|
|
185
|
-
|
|
186
|
-
return pn.Row(
|
|
187
|
-
agg_selector, # [0]
|
|
188
|
-
agg_axis_selector, # [1]
|
|
189
|
-
select_agg,
|
|
190
|
-
width_policy='min',
|
|
191
|
-
)
|
|
192
|
-
|
|
193
|
-
def iteration_selector(axis_options, axis_callback, iter_callback):
|
|
194
|
-
''' Return layout of selectors for iteration axis and player selector for value.
|
|
195
|
-
Callback sets values in iter value player and iter value range selectors when iter_axis is selected.
|
|
196
|
-
'''
|
|
197
|
-
iter_options = ['None']
|
|
198
|
-
iter_options.extend(axis_options)
|
|
199
|
-
|
|
200
|
-
iter_axis_selector = pn.widgets.Select(
|
|
201
|
-
name="Iteration axis",
|
|
202
|
-
options=iter_options,
|
|
203
|
-
description="Select axis over which to iterate",
|
|
204
|
-
sizing_mode='scale_width',
|
|
205
|
-
)
|
|
206
|
-
|
|
207
|
-
update_iter_values = pn.bind(axis_callback, iter_axis_selector)
|
|
208
|
-
|
|
209
|
-
iter_value_type = pn.widgets.RadioBoxGroup(
|
|
210
|
-
options=['By Value', 'By Range'],
|
|
211
|
-
inline=True,
|
|
212
|
-
)
|
|
213
|
-
|
|
214
|
-
# Single value
|
|
215
|
-
iter_value_player = pn.widgets.DiscretePlayer(
|
|
216
|
-
name="Iteration value",
|
|
217
|
-
show_loop_controls=False,
|
|
218
|
-
show_value=False,
|
|
219
|
-
value_align='start',
|
|
220
|
-
visible_buttons=['first', 'previous', 'next', 'last'],
|
|
221
|
-
sizing_mode='scale_width',
|
|
222
|
-
)
|
|
223
|
-
|
|
224
|
-
# Range
|
|
225
|
-
iter_range_start = pn.widgets.IntInput(
|
|
226
|
-
name="Iteration start",
|
|
227
|
-
start=0,
|
|
228
|
-
value=0,
|
|
229
|
-
description="Index of first value in iteration",
|
|
230
|
-
sizing_mode='scale_width',
|
|
231
|
-
)
|
|
232
|
-
iter_range_end = pn.widgets.IntInput(
|
|
233
|
-
name="Iteration end",
|
|
234
|
-
start=0,
|
|
235
|
-
value=0,
|
|
236
|
-
description="Index of last value in iteration",
|
|
237
|
-
sizing_mode='scale_width',
|
|
238
|
-
)
|
|
239
|
-
subplot_rows = pn.widgets.IntInput(
|
|
240
|
-
name="Subplot rows",
|
|
241
|
-
start=1,
|
|
242
|
-
end=10,
|
|
243
|
-
description="Number of rows to display iteration plots",
|
|
244
|
-
sizing_mode='scale_width',
|
|
245
|
-
)
|
|
246
|
-
subplot_columns = pn.widgets.IntInput(
|
|
247
|
-
name="Subplot columns",
|
|
248
|
-
start=1,
|
|
249
|
-
end=10,
|
|
250
|
-
description="Number of columns to display iteration plots",
|
|
251
|
-
sizing_mode='scale_width',
|
|
252
|
-
)
|
|
253
|
-
iter_range_widgets = pn.Column(
|
|
254
|
-
pn.Row( # [0]
|
|
255
|
-
iter_range_start, # [0]
|
|
256
|
-
iter_range_end, # [1]
|
|
257
|
-
),
|
|
258
|
-
pn.Row( # [1]
|
|
259
|
-
subplot_rows, # [0]
|
|
260
|
-
subplot_columns, # [1]
|
|
261
|
-
),
|
|
262
|
-
pn.pane.LaTeX(
|
|
263
|
-
r"Multiple subplots will be shown in new tab",
|
|
264
|
-
),
|
|
265
|
-
)
|
|
266
|
-
|
|
267
|
-
# Put iter value/range into accordion
|
|
268
|
-
iter_value_selectors = pn.Accordion(
|
|
269
|
-
('Select Single Iteration Value', iter_value_player), # [0]
|
|
270
|
-
('Select Iteration Index Range', iter_range_widgets), # [1]
|
|
271
|
-
toggle=True,
|
|
272
|
-
sizing_mode='stretch_width',
|
|
273
|
-
)
|
|
274
|
-
|
|
275
|
-
select_iter = pn.bind(iter_callback, iter_axis_selector, iter_value_type, iter_value_player, iter_range_start, iter_range_end, subplot_rows, subplot_columns)
|
|
276
|
-
|
|
277
|
-
return pn.Column(
|
|
278
|
-
pn.Row( # [0]
|
|
279
|
-
iter_axis_selector, # [0]
|
|
280
|
-
iter_value_type, # [1]
|
|
281
|
-
update_iter_values,
|
|
282
|
-
),
|
|
283
|
-
iter_value_selectors, # [1]
|
|
284
|
-
select_iter,
|
|
285
|
-
width_policy='min',
|
|
286
|
-
)
|
|
287
|
-
|
|
288
|
-
def selection_selector(ps_callback):
|
|
289
|
-
''' Return layout of selectors for ProcessingSet and MSv4 selection. '''
|
|
290
|
-
# Create column of ps selectors; values added from PS summary later.
|
|
291
|
-
ps_selection = pn.Column(
|
|
292
|
-
height_policy='min',
|
|
293
|
-
)
|
|
294
|
-
ps_selection.append(
|
|
295
|
-
pn.widgets.TextInput(
|
|
296
|
-
name="Query",
|
|
297
|
-
placeholder='Enter query for summary columns',
|
|
298
|
-
sizing_mode='stretch_width',
|
|
299
|
-
)
|
|
300
|
-
)
|
|
301
|
-
select_ps = pn.bind(ps_callback, ps_selection[0])
|
|
302
|
-
ps_selection.append(select_ps)
|
|
303
|
-
|
|
304
|
-
selection_cards = pn.Accordion(
|
|
305
|
-
("Select ProcessingSet", ps_selection), # [0]
|
|
306
|
-
toggle=True,
|
|
307
|
-
sizing_mode='stretch_width',
|
|
308
|
-
)
|
|
309
|
-
|
|
310
|
-
return pn.Column(
|
|
311
|
-
selection_cards,
|
|
312
|
-
width_policy='min',
|
|
313
|
-
)
|
|
314
|
-
|
|
315
|
-
def _add_multi_choice(ps_selection, names):
|
|
316
|
-
''' Add Panel Select widgets for list of names with option 'None'.
|
|
317
|
-
ps_selection is a Column to which to add selectors.
|
|
318
|
-
'''
|
|
319
|
-
for name in names:
|
|
320
|
-
ps_selection.append(
|
|
321
|
-
pn.widgets.MultiChoice(
|
|
322
|
-
name=name,
|
|
323
|
-
sizing_mode='stretch_width',
|
|
324
|
-
)
|
|
325
|
-
)
|
|
326
|
-
|
|
327
|
-
def plot_starter(callback):
|
|
328
|
-
''' Create a row with a Plot button and spinner with a button callback to start spinner. '''
|
|
329
|
-
plot_button = pn.widgets.Button(
|
|
330
|
-
name='Plot',
|
|
331
|
-
button_style='outline',
|
|
332
|
-
button_type='primary',
|
|
333
|
-
sizing_mode='fixed',
|
|
334
|
-
width=100,
|
|
335
|
-
)
|
|
336
|
-
|
|
337
|
-
plot_spinner = pn.indicators.LoadingSpinner(
|
|
338
|
-
value=False,
|
|
339
|
-
size=25,
|
|
340
|
-
)
|
|
341
|
-
|
|
342
|
-
start_spinner = pn.bind(callback, plot_button)
|
|
343
|
-
|
|
344
|
-
return pn.Row(
|
|
345
|
-
plot_button, # [0]
|
|
346
|
-
plot_spinner, # [1]
|
|
347
|
-
start_spinner,
|
|
348
|
-
)
|
|
@@ -1,292 +0,0 @@
|
|
|
1
|
-
'''
|
|
2
|
-
Class to create a raster plot of visibility/spectrum data using plot parameters.
|
|
3
|
-
'''
|
|
4
|
-
|
|
5
|
-
import holoviews as hv
|
|
6
|
-
|
|
7
|
-
# hvPlot extensions used to plot xarray DataArray and pandas DataFrame
|
|
8
|
-
# pylint: disable=unused-import
|
|
9
|
-
import hvplot.xarray
|
|
10
|
-
import hvplot.pandas
|
|
11
|
-
# pylint: enable=unused-import
|
|
12
|
-
|
|
13
|
-
from cubevis.bokeh.format import get_time_formatter
|
|
14
|
-
from cubevis.data.measurement_set.processing_set._ps_coords import set_index_coordinates
|
|
15
|
-
from cubevis.plot.ms_plot._xds_plot_axes import get_axis_labels, get_vis_axis_labels, get_coordinate_labels
|
|
16
|
-
|
|
17
|
-
class RasterPlot:
|
|
18
|
-
'''
|
|
19
|
-
Class to create a raster plot from MS data.
|
|
20
|
-
Implemented with xArray Dataset and hvPlot, but could change data and plotting backends using same interface.
|
|
21
|
-
'''
|
|
22
|
-
|
|
23
|
-
def __init__(self):
|
|
24
|
-
self._plot_params = {'data': {}, 'plot': {'params': False}, 'style': {}}
|
|
25
|
-
self._spw_color_limits = {}
|
|
26
|
-
self.set_style_params() # use defaults unless set externally
|
|
27
|
-
|
|
28
|
-
def set_style_params(self, unflagged_cmap='Viridis', flagged_cmap='Reds', show_colorbar=True, show_flagged_colorbar=True):
|
|
29
|
-
'''
|
|
30
|
-
Set styling parameters for the plot. Currently only colorbar settings.
|
|
31
|
-
Placeholder for future styling such as fonts.
|
|
32
|
-
|
|
33
|
-
Args:
|
|
34
|
-
unflagged_cmap (str): colormap to use for unflagged data.
|
|
35
|
-
flagged_cmap (str): colormap to use for flagged data.
|
|
36
|
-
show_colorbar (bool): Whether to show colorbar with plot. Default True.
|
|
37
|
-
|
|
38
|
-
Colormap options: Bokeh palettes
|
|
39
|
-
https://docs.bokeh.org/en/latest/docs/reference/palettes.html
|
|
40
|
-
'''
|
|
41
|
-
style_params = self._plot_params['style']
|
|
42
|
-
style_params['unflagged_cmap'] = unflagged_cmap
|
|
43
|
-
style_params['flagged_cmap'] = flagged_cmap
|
|
44
|
-
style_params['show_colorbar'] = show_colorbar
|
|
45
|
-
style_params['show_flagged_colorbar'] = show_flagged_colorbar
|
|
46
|
-
|
|
47
|
-
def get_plot_params(self):
|
|
48
|
-
''' Return dict of plot params (default only if data params not set) '''
|
|
49
|
-
return self._plot_params
|
|
50
|
-
|
|
51
|
-
def set_plot_params(self, data, plot_inputs, ms_name):
|
|
52
|
-
'''
|
|
53
|
-
Set parameters needed for raster plot from data and plot inputs.
|
|
54
|
-
data (xarray Dataset): selected dataset of MSv4 data to plot
|
|
55
|
-
plot_inputs (dict): user inputs to plot.
|
|
56
|
-
'''
|
|
57
|
-
self._plot_params['data']['correlated_data'] = plot_inputs['correlated_data']
|
|
58
|
-
self._plot_params['data']['aggregator'] = plot_inputs['aggregator']
|
|
59
|
-
|
|
60
|
-
color_mode = plot_inputs['color_mode']
|
|
61
|
-
if color_mode == 'manual':
|
|
62
|
-
self._plot_params['plot']['color_limits'] = plot_inputs['color_range']
|
|
63
|
-
elif color_mode == 'auto':
|
|
64
|
-
self._plot_params['plot']['color_limits'] = plot_inputs['auto_color_range']
|
|
65
|
-
else:
|
|
66
|
-
self._plot_params['plot']['color_limits'] = None
|
|
67
|
-
|
|
68
|
-
# Set title from user inputs or auto (ms name and iterator value)
|
|
69
|
-
if plot_inputs['title']:
|
|
70
|
-
title = plot_inputs['title']
|
|
71
|
-
if title in ['ms', "'ms'"]:
|
|
72
|
-
self._plot_params['plot']['title'] = self._get_plot_title(data, plot_inputs, ms_name)
|
|
73
|
-
else:
|
|
74
|
-
self._plot_params['plot']['title'] = title
|
|
75
|
-
else:
|
|
76
|
-
self._plot_params['plot']['title'] = ''
|
|
77
|
-
|
|
78
|
-
# Set x, y, c axis labels and ticks
|
|
79
|
-
self._set_axis_labels(data, plot_inputs)
|
|
80
|
-
|
|
81
|
-
self._plot_params['plot']['params'] = True
|
|
82
|
-
|
|
83
|
-
def reset_plot_params(self):
|
|
84
|
-
''' Remove and invalidate data plot params '''
|
|
85
|
-
self._plot_params['plot'] = {'params': False}
|
|
86
|
-
|
|
87
|
-
def raster_plot(self, data, logger, is_gui=False):
|
|
88
|
-
''' Create raster plot (hvPlot) for input data (xarray Dataset) using plot params.
|
|
89
|
-
Returns Overlay of unflagged and flagged plots.
|
|
90
|
-
Optionally add the unflagged data min/max to plot params for interactive gui colorbar range.
|
|
91
|
-
'''
|
|
92
|
-
if not self._plot_params['plot']['params']:
|
|
93
|
-
logger.error('Parameters have not been set from plot data. Cannot plot.')
|
|
94
|
-
return None
|
|
95
|
-
|
|
96
|
-
data_params = self._plot_params['data']
|
|
97
|
-
plot_params = self._plot_params['plot']
|
|
98
|
-
|
|
99
|
-
x_axis = plot_params['axis_labels']['x']['axis']
|
|
100
|
-
y_axis = plot_params['axis_labels']['y']['axis']
|
|
101
|
-
c_axis = plot_params['axis_labels']['c']['axis']
|
|
102
|
-
|
|
103
|
-
# Set plot axes to numeric coordinates if needed
|
|
104
|
-
xds = set_index_coordinates(data, (x_axis, y_axis))
|
|
105
|
-
|
|
106
|
-
# Prefix c_axis name with aggregator
|
|
107
|
-
xda_name = c_axis
|
|
108
|
-
if data_params['aggregator']:
|
|
109
|
-
xda_name = "_".join([data_params['aggregator'], xda_name])
|
|
110
|
-
|
|
111
|
-
# Plot unflagged and flagged data
|
|
112
|
-
xda = xds[data_params['correlated_data']].where(xds.FLAG == 0.0).rename(xda_name)
|
|
113
|
-
unflagged_plot = self._plot_xda(xda)
|
|
114
|
-
flagged_xda = xds[data_params['correlated_data']].where(xds.FLAG == 1.0).rename("flagged_" + xda_name)
|
|
115
|
-
flagged_plot = self._plot_xda(flagged_xda, True)
|
|
116
|
-
|
|
117
|
-
if is_gui: # update data range for colorbar
|
|
118
|
-
self._plot_params['data']['data_range'] = (xda.min().values.item(), xda.max().values.item())
|
|
119
|
-
|
|
120
|
-
# Make Overlay plot with hover tools
|
|
121
|
-
return (flagged_plot * unflagged_plot).opts(
|
|
122
|
-
hv.opts.QuadMesh(tools=['hover'])
|
|
123
|
-
)
|
|
124
|
-
|
|
125
|
-
def _get_plot_title(self, data, plot_inputs, ms_name, include_selections=False):
|
|
126
|
-
''' Form string containing ms name and selected values using data (xArray Dataset) '''
|
|
127
|
-
title = f"{ms_name}\n"
|
|
128
|
-
|
|
129
|
-
if include_selections:
|
|
130
|
-
# TBD: include complete selection?
|
|
131
|
-
title = self._add_title_selections(data, title, plot_inputs)
|
|
132
|
-
else:
|
|
133
|
-
# Add iter_axis selection only
|
|
134
|
-
iter_axis = plot_inputs['iter_axis']
|
|
135
|
-
if iter_axis:
|
|
136
|
-
iter_label = get_coordinate_labels(data, iter_axis)
|
|
137
|
-
title += f"{iter_axis} {iter_label}"
|
|
138
|
-
return title
|
|
139
|
-
|
|
140
|
-
def _add_title_selections(self, data, title, plot_inputs):
|
|
141
|
-
''' Add ProcessingSet and data dimension selections to title '''
|
|
142
|
-
selection = plot_inputs['selection'] if 'selection' in plot_inputs else None
|
|
143
|
-
dim_selection = plot_inputs['dim_selection'] if 'dim_selection' in plot_inputs else None
|
|
144
|
-
data_dims = plot_inputs['data_dims'] if 'data_dims' in plot_inputs else None
|
|
145
|
-
|
|
146
|
-
ps_selections = []
|
|
147
|
-
dim_selections = []
|
|
148
|
-
|
|
149
|
-
for key in selection:
|
|
150
|
-
# Add processing set selection: spw, field, source, and intent
|
|
151
|
-
# TBD: add data group?
|
|
152
|
-
if key == 'spw_name':
|
|
153
|
-
spw_selection = f"spw: {selection[key]}"
|
|
154
|
-
if 'frequency' in data:
|
|
155
|
-
spw_selection += f" ({data.frequency.spectral_window_id})"
|
|
156
|
-
ps_selections.append(spw_selection)
|
|
157
|
-
elif key == 'field_name':
|
|
158
|
-
ps_selections.append(f"field: {selection[key]}")
|
|
159
|
-
elif key == 'source_name':
|
|
160
|
-
ps_selections.append(f"source: {selection[key]}")
|
|
161
|
-
elif key == 'intents':
|
|
162
|
-
ps_selections.append(f"intents: {selection[key]}")
|
|
163
|
-
elif key in data_dims:
|
|
164
|
-
# Add user-selected dimensions to title: name (index)
|
|
165
|
-
label = get_coordinate_labels(data, key)
|
|
166
|
-
index = selection[key] if isinstance(selection[key], int) else None
|
|
167
|
-
selected_dim = f"{key}: {label}"
|
|
168
|
-
if index is not None:
|
|
169
|
-
index_label = f" (ch {index}) " if key == 'frequency' else f" ({index}) "
|
|
170
|
-
selected_dim += index_label
|
|
171
|
-
dim_selections.append(selected_dim)
|
|
172
|
-
|
|
173
|
-
for key in dim_selection:
|
|
174
|
-
# Add auto- or iter-selected dimensions to title: name (index)
|
|
175
|
-
label = get_coordinate_labels(data, key)
|
|
176
|
-
index = dim_selection[key] if isinstance(dim_selection[key], int) else None
|
|
177
|
-
selected_dim = f"{key}: {label}"
|
|
178
|
-
if index is not None:
|
|
179
|
-
index_label = f" (ch {index}) " if key == 'frequency' else f" ({index}) "
|
|
180
|
-
selected_dim += index_label
|
|
181
|
-
dim_selections.append(selected_dim)
|
|
182
|
-
|
|
183
|
-
title += '\n'.join(ps_selections) + '\n'
|
|
184
|
-
title += ' '.join(dim_selections)
|
|
185
|
-
return title
|
|
186
|
-
|
|
187
|
-
def _set_axis_labels(self, data, plot_inputs):
|
|
188
|
-
''' Set axis, label, and ticks for x, y, and vis axis '''
|
|
189
|
-
x_axis_labels = get_axis_labels(data, plot_inputs['x_axis'])
|
|
190
|
-
y_axis_labels = get_axis_labels(data, plot_inputs['y_axis'])
|
|
191
|
-
c_axis_labels = self._get_c_axis_labels(data, plot_inputs)
|
|
192
|
-
|
|
193
|
-
self._set_axis_label_params('x', x_axis_labels)
|
|
194
|
-
self._set_axis_label_params('y', y_axis_labels)
|
|
195
|
-
self._set_axis_label_params('c', c_axis_labels)
|
|
196
|
-
|
|
197
|
-
def _get_c_axis_labels(self, data, plot_inputs):
|
|
198
|
-
''' Set axis and label for c axis using input data xArray Dataset. '''
|
|
199
|
-
data_group = plot_inputs['selection']['data_group_name']
|
|
200
|
-
correlated_data = plot_inputs['correlated_data']
|
|
201
|
-
vis_axis = plot_inputs['vis_axis']
|
|
202
|
-
aggregator = plot_inputs['aggregator']
|
|
203
|
-
|
|
204
|
-
axis, label = get_vis_axis_labels(data, data_group, correlated_data, vis_axis)
|
|
205
|
-
if aggregator:
|
|
206
|
-
label = " ".join([aggregator.capitalize(), label])
|
|
207
|
-
return (axis, label, None)
|
|
208
|
-
|
|
209
|
-
def _set_axis_label_params(self, axis, axis_labels):
|
|
210
|
-
# Axis labels are (axis, label, ticks).
|
|
211
|
-
if 'axis_labels' not in self._plot_params['plot']:
|
|
212
|
-
self._plot_params['plot']['axis_labels'] = {}
|
|
213
|
-
self._plot_params['plot']['axis_labels'][axis] = {}
|
|
214
|
-
self._plot_params['plot']['axis_labels'][axis]['axis'] = axis_labels[0]
|
|
215
|
-
self._plot_params['plot']['axis_labels'][axis]['label'] = axis_labels[1]
|
|
216
|
-
self._plot_params['plot']['axis_labels'][axis]['ticks'] = axis_labels[2]
|
|
217
|
-
|
|
218
|
-
def _plot_xda(self, xda, is_flagged=False):
|
|
219
|
-
# Returns Quadmesh plot if raster 2D data, Scatter plot if raster 1D data, or None if no data
|
|
220
|
-
plot_params = self._plot_params['plot']
|
|
221
|
-
style_params = self._plot_params['style']
|
|
222
|
-
|
|
223
|
-
x_axis = plot_params['axis_labels']['x']['axis']
|
|
224
|
-
y_axis = plot_params['axis_labels']['y']['axis']
|
|
225
|
-
c_label = plot_params['axis_labels']['c']['label']
|
|
226
|
-
c_lim = plot_params['color_limits']
|
|
227
|
-
|
|
228
|
-
x_formatter = get_time_formatter() if x_axis == 'time' else None
|
|
229
|
-
y_formatter = get_time_formatter() if y_axis == 'time' else None
|
|
230
|
-
|
|
231
|
-
# Hide flagged colorbar if unflagged colorbar is shown
|
|
232
|
-
if xda.count().values > 0:
|
|
233
|
-
if is_flagged:
|
|
234
|
-
show_colorbar = style_params['show_flagged_colorbar']
|
|
235
|
-
else :
|
|
236
|
-
show_colorbar = style_params['show_colorbar']
|
|
237
|
-
else:
|
|
238
|
-
show_colorbar = False
|
|
239
|
-
|
|
240
|
-
if is_flagged:
|
|
241
|
-
c_label = "Flagged " + c_label
|
|
242
|
-
colormap = style_params['flagged_cmap']
|
|
243
|
-
plot_params['flagged_colorbar'] = show_colorbar
|
|
244
|
-
else:
|
|
245
|
-
colormap = style_params['unflagged_cmap']
|
|
246
|
-
plot_params['unflagged_colorbar'] = show_colorbar
|
|
247
|
-
|
|
248
|
-
if xda[x_axis].size > 1 and xda[y_axis].size > 1:
|
|
249
|
-
# Raster 2D data
|
|
250
|
-
plot = xda.hvplot.quadmesh(
|
|
251
|
-
x_axis,
|
|
252
|
-
y_axis,
|
|
253
|
-
clim=c_lim,
|
|
254
|
-
cmap=colormap,
|
|
255
|
-
clabel=c_label,
|
|
256
|
-
title=plot_params['title'],
|
|
257
|
-
xlabel=plot_params['axis_labels']['x']['label'],
|
|
258
|
-
ylabel=plot_params['axis_labels']['y']['label'],
|
|
259
|
-
xformatter=x_formatter,
|
|
260
|
-
yformatter=y_formatter,
|
|
261
|
-
xticks=plot_params['axis_labels']['x']['ticks'],
|
|
262
|
-
yticks=plot_params['axis_labels']['y']['ticks'],
|
|
263
|
-
rot=45, # angle for x axis labels
|
|
264
|
-
colorbar=show_colorbar,
|
|
265
|
-
responsive=True, # resize to fill browser window if True
|
|
266
|
-
)
|
|
267
|
-
else:
|
|
268
|
-
# Cannot raster 1D data, use scatter from pandas dataframe
|
|
269
|
-
df = xda.to_dataframe().reset_index() # convert x and y axis from index to column
|
|
270
|
-
plot = df.hvplot.scatter(
|
|
271
|
-
x=x_axis,
|
|
272
|
-
y=y_axis,
|
|
273
|
-
c=xda.name,
|
|
274
|
-
clim=plot_params['color_limits'],
|
|
275
|
-
cmap=colormap,
|
|
276
|
-
clabel=c_label,
|
|
277
|
-
title=plot_params['title'],
|
|
278
|
-
xlabel=plot_params['axis_labels']['x']['label'],
|
|
279
|
-
ylabel=plot_params['axis_labels']['y']['label'],
|
|
280
|
-
xformatter=x_formatter,
|
|
281
|
-
yformatter=y_formatter,
|
|
282
|
-
xticks=plot_params['axis_labels']['x']['ticks'],
|
|
283
|
-
yticks=plot_params['axis_labels']['y']['ticks'],
|
|
284
|
-
rot=45,
|
|
285
|
-
marker='s', # square
|
|
286
|
-
hover=True,
|
|
287
|
-
responsive=True,
|
|
288
|
-
)
|
|
289
|
-
|
|
290
|
-
if show_colorbar and not is_flagged:
|
|
291
|
-
plot = plot.opts(colorbar_position='left')
|
|
292
|
-
return plot
|