vidavis 0.1.3__py3-none-any.whl → 0.1.5__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.
- vidavis/__version__.py +1 -1
- vidavis/apps/_ms_raster.py +12 -10
- vidavis/data/measurement_set/processing_set/_ps_raster_data.py +1 -1
- vidavis/plot/ms_plot/_locate_points.py +60 -65
- vidavis/plot/ms_plot/_ms_plot.py +100 -37
- vidavis/plot/ms_plot/_ms_plot_selectors.py +2 -1
- vidavis/plot/ms_plot/_raster_plot.py +47 -47
- vidavis/plot/ms_plot/_raster_plot_gui.py +4 -4
- {vidavis-0.1.3.dist-info → vidavis-0.1.5.dist-info}/METADATA +1 -1
- {vidavis-0.1.3.dist-info → vidavis-0.1.5.dist-info}/RECORD +12 -12
- {vidavis-0.1.3.dist-info → vidavis-0.1.5.dist-info}/WHEEL +0 -0
- {vidavis-0.1.3.dist-info → vidavis-0.1.5.dist-info}/licenses/LICENSE +0 -0
vidavis/__version__.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = '0.1.
|
|
1
|
+
__version__ = '0.1.5'
|
vidavis/apps/_ms_raster.py
CHANGED
|
@@ -521,15 +521,16 @@ class MsRaster(MsPlot):
|
|
|
521
521
|
# Add plot inputs to GUI, change plot button to outline, and stop spinner
|
|
522
522
|
self._update_plot_status(False)
|
|
523
523
|
self._update_plot_spinner(False)
|
|
524
|
-
|
|
525
524
|
# pylint: enable=too-many-arguments, too-many-positional-arguments
|
|
526
525
|
|
|
527
|
-
def _locate_gui_points(self, x, y, data,
|
|
526
|
+
def _locate_gui_points(self, x, y, data, boxes):
|
|
528
527
|
''' Callback for locate streams '''
|
|
529
528
|
if self._gui_plot_data:
|
|
529
|
+
if super()._locate_points(data, self._gui_plot_data, self._gui_panel[2]):
|
|
530
|
+
return self._last_gui_plot
|
|
531
|
+
if super()._locate_boxes(boxes, self._gui_plot_data, self._gui_panel[3]):
|
|
532
|
+
return self._last_gui_plot
|
|
530
533
|
super()._locate_cursor(x, y, self._gui_plot_data, self._gui_panel[0][1])
|
|
531
|
-
super()._locate_points(data, self._gui_plot_data, self._gui_panel[2])
|
|
532
|
-
super()._locate_box(bounds, self._gui_plot_data, self._gui_panel[3])
|
|
533
534
|
return self._last_gui_plot
|
|
534
535
|
|
|
535
536
|
def _do_gui_selection(self):
|
|
@@ -578,17 +579,18 @@ class MsRaster(MsPlot):
|
|
|
578
579
|
return self._empty_plot
|
|
579
580
|
|
|
580
581
|
def _create_empty_plot(self):
|
|
581
|
-
''' Create empty Overlay plot for DynamicMap with colormap params
|
|
582
|
+
''' Create empty Overlay plot for DynamicMap with colormap params enabled '''
|
|
582
583
|
plot_params = self._raster_plot.get_plot_params()
|
|
583
584
|
self._empty_plot = hv.Overlay(
|
|
584
585
|
hv.QuadMesh([]).opts(
|
|
585
|
-
colorbar=plot_params['style']['show_flagged_colorbar'],
|
|
586
|
-
cmap=plot_params['style']['flagged_cmap'],
|
|
587
|
-
responsive=True,
|
|
588
|
-
) * hv.QuadMesh([]).opts(
|
|
589
586
|
colorbar=plot_params['style']['show_colorbar'],
|
|
590
|
-
colorbar_position='left',
|
|
591
587
|
cmap=plot_params['style']['unflagged_cmap'],
|
|
588
|
+
colorbar_position='left',
|
|
589
|
+
responsive=True,
|
|
590
|
+
) * hv.QuadMesh([]).opts(
|
|
591
|
+
colorbar=plot_params['style']['show_flagged_colorbar'],
|
|
592
|
+
colorbar_position='right',
|
|
593
|
+
cmap=plot_params['style']['flagged_cmap'],
|
|
592
594
|
responsive=True,
|
|
593
595
|
)
|
|
594
596
|
)
|
|
@@ -30,7 +30,7 @@ def raster_data(ps_xdt, plot_inputs, logger):
|
|
|
30
30
|
raise RuntimeError("Plot failed: raster plane selection yielded data with all nan values.")
|
|
31
31
|
|
|
32
32
|
# Compute complex component of vis data
|
|
33
|
-
raster_xds[correlated_data] = get_axis_data(raster_xds, plot_inputs['vis_axis'], data_group)
|
|
33
|
+
raster_xds[correlated_data] = get_axis_data(raster_xds, plot_inputs['vis_axis'], data_group)
|
|
34
34
|
|
|
35
35
|
# Convert float time to datetime
|
|
36
36
|
set_datetime_coordinate(raster_xds)
|
|
@@ -10,32 +10,41 @@ import panel as pn
|
|
|
10
10
|
|
|
11
11
|
from vidavis.plot.ms_plot._ms_plot_constants import TIME_FORMAT
|
|
12
12
|
|
|
13
|
-
def
|
|
14
|
-
'''
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
return
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
return
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
if
|
|
35
|
-
return False #
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
13
|
+
def get_locate_value(xds, coord, value):
|
|
14
|
+
''' Convert index coordinates to int and float time coordinate to datetime. Select nearest value <= value. '''
|
|
15
|
+
if coord in ['baseline', 'antenna_name', 'polarization']:
|
|
16
|
+
# Convert float to int index value
|
|
17
|
+
return round(value)
|
|
18
|
+
|
|
19
|
+
if coord in ['time', 'frequency']:
|
|
20
|
+
if coord=='time' and isinstance(value, float):
|
|
21
|
+
# Convert float to datetime value
|
|
22
|
+
# Bokeh datetime values are floating point values that represent milliseconds-since-epoch (unix time)
|
|
23
|
+
value = to_datetime(value, unit='ms')
|
|
24
|
+
value_sel = {coord: value}
|
|
25
|
+
nearest_value = xds[coord].sel(indexers=None, method='nearest', tolerance=None, drop=False, **value_sel).values
|
|
26
|
+
return nearest_value
|
|
27
|
+
|
|
28
|
+
return value
|
|
29
|
+
|
|
30
|
+
def data_changed(data, last_data):
|
|
31
|
+
''' Check whether data changed, input as list of tuples '''
|
|
32
|
+
if not data:
|
|
33
|
+
return False # not callback for this data
|
|
34
|
+
if last_data and len(last_data) == len(data) and last_data == data:
|
|
35
|
+
return False # same data
|
|
36
|
+
return True # new data, data changed, or data removed
|
|
37
|
+
|
|
38
|
+
def get_new_data(data, last_data):
|
|
39
|
+
''' Return data not in last_data, input as list of tuples '''
|
|
40
|
+
new_data = []
|
|
41
|
+
if last_data:
|
|
42
|
+
for info in data:
|
|
43
|
+
if info not in last_data:
|
|
44
|
+
new_data.append(info)
|
|
45
|
+
else:
|
|
46
|
+
new_data = data
|
|
47
|
+
return new_data
|
|
39
48
|
|
|
40
49
|
def update_cursor_location(cursor, plot_axes, xds, cursor_locate_box):
|
|
41
50
|
''' Show data values for cursor x,y position in cursor location box (pn.WidgetBox) '''
|
|
@@ -47,42 +56,40 @@ def update_cursor_location(cursor, plot_axes, xds, cursor_locate_box):
|
|
|
47
56
|
cursor_position = {x_axis: x, y_axis: y}
|
|
48
57
|
cursor_location = _locate_point(xds, cursor_position, vis_axis)
|
|
49
58
|
|
|
50
|
-
location_column = pn.Column(pn.widgets.StaticText(name="CURSOR LOCATION"))
|
|
51
59
|
# Add row of columns to column layout
|
|
60
|
+
location_column = pn.Column(pn.widgets.StaticText(name="CURSOR LOCATION"))
|
|
52
61
|
location_row = _layout_point_location(cursor_location)
|
|
53
62
|
location_column.append(location_row)
|
|
63
|
+
|
|
54
64
|
# Add location column to widget box
|
|
55
65
|
cursor_locate_box.append(location_column)
|
|
56
66
|
|
|
57
|
-
def update_points_location(
|
|
67
|
+
def update_points_location(points, plot_axes, xds, points_tab_feed):
|
|
58
68
|
''' Show data values for points in point_draw in tab and log '''
|
|
59
|
-
points_tab_feed.clear()
|
|
60
69
|
locate_log = []
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
location_list = [f"{static_text.name}={static_text.value}" for static_text in point_location]
|
|
76
|
-
locate_log.append(", ".join(location_list))
|
|
70
|
+
x_axis, y_axis, vis_axis = plot_axes
|
|
71
|
+
for point in points:
|
|
72
|
+
# Locate point
|
|
73
|
+
point_position = {x_axis: point[0], y_axis: point[1]}
|
|
74
|
+
point_location = _locate_point(xds, point_position, vis_axis)
|
|
75
|
+
|
|
76
|
+
# Format location and add to points locate column
|
|
77
|
+
location_layout = _layout_point_location(point_location)
|
|
78
|
+
points_tab_feed.append(location_layout)
|
|
79
|
+
points_tab_feed.append(pn.layout.Divider())
|
|
80
|
+
|
|
81
|
+
# Format and add to log
|
|
82
|
+
location_list = [f"{static_text.name}={static_text.value}" for static_text in point_location]
|
|
83
|
+
locate_log.append(", ".join(location_list))
|
|
77
84
|
return locate_log
|
|
78
85
|
|
|
79
|
-
|
|
86
|
+
# pylint: disable=too-many-locals
|
|
87
|
+
def update_boxes_location(boxes, plot_axes, xds, box_tab_feed):
|
|
80
88
|
''' Show data values for points in box_select in tab and log '''
|
|
81
|
-
box_tab_feed.clear()
|
|
82
89
|
locate_log = []
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
box_bounds = {x_axis: (
|
|
90
|
+
x_axis, y_axis, vis_axis = plot_axes
|
|
91
|
+
for box in boxes:
|
|
92
|
+
box_bounds = {x_axis: (box[0], box[2]), y_axis: (box[1], box[3])}
|
|
86
93
|
npoints, point_locations = _locate_box(xds, box_bounds, vis_axis)
|
|
87
94
|
|
|
88
95
|
message = f"Locate {npoints} points"
|
|
@@ -100,6 +107,7 @@ def update_box_location(bounds, plot_axes, xds, box_tab_feed):
|
|
|
100
107
|
location_list = [f"{static_text.name}={static_text.value}" for static_text in point]
|
|
101
108
|
locate_log.append(", ".join(location_list))
|
|
102
109
|
return locate_log
|
|
110
|
+
# pylint: enable=too-many-locals
|
|
103
111
|
|
|
104
112
|
def _locate_point(xds, position, vis_axis):
|
|
105
113
|
'''
|
|
@@ -141,8 +149,9 @@ def _locate_box(xds, bounds, vis_axis):
|
|
|
141
149
|
selection = {}
|
|
142
150
|
for coord, val in bounds.items():
|
|
143
151
|
# Round index values to int for selection
|
|
144
|
-
selection[coord] = slice(
|
|
152
|
+
selection[coord] = slice(get_locate_value(xds, coord, val[0]), get_locate_value(xds, coord, val[1]))
|
|
145
153
|
sel_xds = xds.sel(indexers=None, method=None, tolerance=None, drop=False, **selection)
|
|
154
|
+
sel_xds.compute()
|
|
146
155
|
|
|
147
156
|
x_coord, y_coord = bounds.keys()
|
|
148
157
|
npoints = sel_xds.sizes[x_coord] * sel_xds.sizes[y_coord]
|
|
@@ -175,10 +184,6 @@ def _get_point_location(xds, position, vis_axis):
|
|
|
175
184
|
|
|
176
185
|
if xds:
|
|
177
186
|
try:
|
|
178
|
-
for coord, value in position.items():
|
|
179
|
-
# Round index coordinates to int and convert time to datetime if float for selection
|
|
180
|
-
position[coord] = _get_selection_value(coord, value)
|
|
181
|
-
|
|
182
187
|
sel_xds = xds.sel(indexers=None, method='nearest', tolerance=None, drop=False, **position)
|
|
183
188
|
for coord in sel_xds.coords:
|
|
184
189
|
if coord == 'uvw_label' or ('baseline_antenna' in coord and 'baseline_name' in sel_xds.coords):
|
|
@@ -206,16 +211,6 @@ def _get_point_location(xds, position, vis_axis):
|
|
|
206
211
|
values[vis_axis.upper()] = values.pop('VISIBILITY')
|
|
207
212
|
return values, units
|
|
208
213
|
|
|
209
|
-
def _get_selection_value(coord, value):
|
|
210
|
-
''' Convert index coordinates to int and float time coordinate to datetime '''
|
|
211
|
-
if coord in ['baseline', 'antenna_name', 'polarization']:
|
|
212
|
-
# Round index coordinates to int for selecction
|
|
213
|
-
value = round(value)
|
|
214
|
-
elif coord == 'time' and isinstance(value, float):
|
|
215
|
-
# Bokeh datetime values are floating-point numbers: milliseconds since the Unix epoch
|
|
216
|
-
value = to_datetime(value, unit='ms', origin='unix')
|
|
217
|
-
return value
|
|
218
|
-
|
|
219
214
|
def _get_xda_val_unit(xda):
|
|
220
215
|
''' Return value and unit of xda (selected so only one value) '''
|
|
221
216
|
# Value
|
vidavis/plot/ms_plot/_ms_plot.py
CHANGED
|
@@ -17,7 +17,7 @@ from selenium import webdriver
|
|
|
17
17
|
from toolviper.utils.logger import setup_logger
|
|
18
18
|
|
|
19
19
|
from vidavis.data.measurement_set._ms_data import MsData
|
|
20
|
-
from vidavis.plot.ms_plot._locate_points import
|
|
20
|
+
from vidavis.plot.ms_plot._locate_points import get_locate_value, data_changed, get_new_data, update_cursor_location, update_points_location, update_boxes_location
|
|
21
21
|
from vidavis.toolbox import AppContext
|
|
22
22
|
|
|
23
23
|
class MsPlot:
|
|
@@ -73,9 +73,9 @@ class MsPlot:
|
|
|
73
73
|
self._plot_axes = None
|
|
74
74
|
self._last_cursor = None
|
|
75
75
|
self._last_points = None
|
|
76
|
-
self.
|
|
76
|
+
self._last_boxes = None
|
|
77
77
|
self._locate_plot_options = {
|
|
78
|
-
'
|
|
78
|
+
'muted_alpha': 0,
|
|
79
79
|
'selection_fill_alpha': 0.2, # dim selected areas of plot
|
|
80
80
|
'nonselection_fill_alpha': 1.0, # do not dim unselected areas of plot
|
|
81
81
|
}
|
|
@@ -189,10 +189,11 @@ class MsPlot:
|
|
|
189
189
|
if inputs_column:
|
|
190
190
|
self._show_panel.append(('Plot Inputs', inputs_column))
|
|
191
191
|
else:
|
|
192
|
-
plot = plot.
|
|
192
|
+
plot = plot.options(
|
|
193
193
|
hv.opts.QuadMesh(**self._locate_plot_options),
|
|
194
|
-
hv.opts.Scatter(**self._locate_plot_options)
|
|
194
|
+
hv.opts.Scatter(**self._locate_plot_options),
|
|
195
195
|
)
|
|
196
|
+
|
|
196
197
|
# Add DynamicMap for streams for single plot
|
|
197
198
|
dmap = self._get_locate_dmap(self._locate)
|
|
198
199
|
|
|
@@ -210,8 +211,11 @@ class MsPlot:
|
|
|
210
211
|
# Add tabs for inputs and locate
|
|
211
212
|
if inputs_column:
|
|
212
213
|
self._show_panel.append(('Plot Inputs', inputs_column))
|
|
213
|
-
self._show_panel.append(('Locate
|
|
214
|
-
self._show_panel.append(('Locate
|
|
214
|
+
self._show_panel.append(('Locate Points', pn.Feed(height_policy='max')))
|
|
215
|
+
self._show_panel.append(('Locate Box', pn.Feed(height_policy='max')))
|
|
216
|
+
|
|
217
|
+
# Compute coordinate values for locate
|
|
218
|
+
self._compute_plot_metadata(self._plot_data)
|
|
215
219
|
|
|
216
220
|
# return value for locate callback
|
|
217
221
|
self._last_plot = plot
|
|
@@ -397,21 +401,28 @@ class MsPlot:
|
|
|
397
401
|
str_pane.margin = (0, 10)
|
|
398
402
|
inputs_tab_column.append(str_pane)
|
|
399
403
|
|
|
404
|
+
def _compute_plot_metadata(self, xds):
|
|
405
|
+
''' Compute coordinate dask arrays to numpy arrays in memory '''
|
|
406
|
+
for coord in xds.coords:
|
|
407
|
+
xds[coord] = xds[coord].compute()
|
|
408
|
+
|
|
400
409
|
def _get_locate_dmap(self, callback):
|
|
401
410
|
''' Return DynamicMap with streams callback to locate points '''
|
|
402
411
|
points = hv.Points([]).opts(
|
|
403
412
|
size=5,
|
|
404
413
|
fill_color='white'
|
|
405
414
|
)
|
|
415
|
+
boxes = hv.Rectangles([])
|
|
406
416
|
dmap = hv.DynamicMap(
|
|
407
417
|
callback,
|
|
408
418
|
streams=[
|
|
409
|
-
hv.streams.PointerXY(),
|
|
410
|
-
hv.streams.PointDraw(source=points),
|
|
411
|
-
hv.streams.
|
|
419
|
+
hv.streams.PointerXY(), # cursor location (x, y)
|
|
420
|
+
hv.streams.PointDraw(source=points), # fixed points location (data)
|
|
421
|
+
hv.streams.BoxEdit(source=boxes).rename(data='boxes') # box location (boxes)
|
|
412
422
|
]
|
|
413
423
|
)
|
|
414
|
-
return dmap * points
|
|
424
|
+
return (dmap * points * boxes).options(
|
|
425
|
+
hv.opts.Rectangles(fill_alpha=0.5, line_color='white'))
|
|
415
426
|
|
|
416
427
|
def _unlink_plot_locate(self):
|
|
417
428
|
''' Disconnect streams when plot data is going to be replaced '''
|
|
@@ -432,45 +443,97 @@ class MsPlot:
|
|
|
432
443
|
self._plot_axes = (x_axis, y_axis, vis_axis)
|
|
433
444
|
return self._plot_axes
|
|
434
445
|
|
|
435
|
-
def _locate(self, x, y, data,
|
|
446
|
+
def _locate(self, x, y, data, boxes):
|
|
436
447
|
''' Callback for all show plot streams '''
|
|
448
|
+
if self._locate_points(data, self._plot_data, self._show_panel[2]):
|
|
449
|
+
return self._last_plot
|
|
450
|
+
|
|
451
|
+
if self._locate_boxes(boxes, self._plot_data, self._show_panel[3]):
|
|
452
|
+
return self._last_plot
|
|
453
|
+
|
|
437
454
|
self._locate_cursor(x, y, self._plot_data, self._show_panel[0][1])
|
|
438
|
-
self._locate_points(data, self._plot_data, self._show_panel[2])
|
|
439
|
-
self._locate_box(bounds, self._plot_data, self._show_panel[3])
|
|
440
455
|
return self._last_plot
|
|
441
456
|
|
|
442
457
|
def _locate_cursor(self, x, y, plot_data, cursor_box):
|
|
443
458
|
''' Show location from cursor position in cursor locate box '''
|
|
459
|
+
if not x and not y: # not cursor callback
|
|
460
|
+
return False
|
|
461
|
+
plot_axes = self._get_plot_axes()
|
|
462
|
+
x = get_locate_value(plot_data, plot_axes[0], x)
|
|
463
|
+
y = get_locate_value(plot_data, plot_axes[1], y)
|
|
444
464
|
cursor = (x, y)
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
465
|
+
|
|
466
|
+
if not data_changed(cursor, self._last_cursor):
|
|
467
|
+
return False
|
|
468
|
+
|
|
469
|
+
# new cursor position - update cursor location box
|
|
470
|
+
update_cursor_location(cursor, plot_axes, plot_data, cursor_box)
|
|
471
|
+
self._last_cursor = cursor
|
|
472
|
+
return True
|
|
449
473
|
|
|
450
474
|
def _locate_points(self, point_data, plot_data, points_tab):
|
|
451
475
|
''' Show points locations from point_draw tool '''
|
|
452
|
-
if
|
|
453
|
-
|
|
454
|
-
|
|
476
|
+
if not point_data or len(point_data['x']) == 0: # not points callback
|
|
477
|
+
return False
|
|
478
|
+
|
|
479
|
+
plot_axes = self._get_plot_axes()
|
|
480
|
+
x_vals = point_data['x']
|
|
481
|
+
y_vals = point_data['y']
|
|
482
|
+
point_data['x'] = [get_locate_value(plot_data, plot_axes[0], x) for x in x_vals]
|
|
483
|
+
point_data['y'] = [get_locate_value(plot_data, plot_axes[1], y) for y in y_vals]
|
|
484
|
+
data_points = list(zip(point_data['x'], point_data['y']))
|
|
485
|
+
|
|
486
|
+
if not data_changed(data_points, self._last_points):
|
|
487
|
+
return False
|
|
488
|
+
|
|
489
|
+
# update selected points location tab with new points
|
|
490
|
+
points_to_locate = get_new_data(data_points, self._last_points)
|
|
491
|
+
self._last_points = data_points
|
|
455
492
|
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
for info in location_info:
|
|
459
|
-
self._logger.info(info)
|
|
460
|
-
self._logger.addHandler(self._stdout_handler)
|
|
493
|
+
if not points_to_locate: # point deleted
|
|
494
|
+
return False
|
|
461
495
|
|
|
462
|
-
|
|
496
|
+
if len(points_to_locate) == len(data_points):
|
|
497
|
+
points_tab.clear() # clear for locating all points
|
|
463
498
|
|
|
464
|
-
|
|
499
|
+
location_info = update_points_location(points_to_locate, self._get_plot_axes(), plot_data, points_tab)
|
|
500
|
+
self._log_to_file_only(location_info)
|
|
501
|
+
return True
|
|
502
|
+
|
|
503
|
+
def _locate_boxes(self, boxes, plot_data, box_tab):
|
|
465
504
|
''' Show points locations in box from box_select tool '''
|
|
466
|
-
if
|
|
467
|
-
|
|
468
|
-
location_info = update_box_location(box_bounds, self._get_plot_axes(), plot_data, box_tab)
|
|
505
|
+
if not boxes or len(boxes['x0']) == 0: # not box callback
|
|
506
|
+
return False
|
|
469
507
|
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
508
|
+
plot_axes = self._get_plot_axes()
|
|
509
|
+
x0_vals = boxes['x0']
|
|
510
|
+
y0_vals = boxes['y0']
|
|
511
|
+
x1_vals = boxes['x1']
|
|
512
|
+
y1_vals = boxes['y1']
|
|
513
|
+
boxes['x0'] = [get_locate_value(plot_data, plot_axes[0], x0) for x0 in x0_vals]
|
|
514
|
+
boxes['y0'] = [get_locate_value(plot_data, plot_axes[1], y0) for y0 in y0_vals]
|
|
515
|
+
boxes['x1'] = [get_locate_value(plot_data, plot_axes[0], x1) for x1 in x1_vals]
|
|
516
|
+
boxes['y1'] = [get_locate_value(plot_data, plot_axes[1], y1) for y1 in y1_vals]
|
|
517
|
+
box_list = list(zip(boxes['x0'], boxes['y0'], boxes['x1'], boxes['y1']))
|
|
518
|
+
|
|
519
|
+
if not data_changed(box_list, self._last_boxes):
|
|
520
|
+
return False
|
|
475
521
|
|
|
476
|
-
|
|
522
|
+
# update selected box location tab with new boxes
|
|
523
|
+
boxes_to_locate = get_new_data(box_list, self._last_boxes)
|
|
524
|
+
self._last_boxes = box_list
|
|
525
|
+
|
|
526
|
+
if not boxes_to_locate: # box deleted
|
|
527
|
+
return False
|
|
528
|
+
|
|
529
|
+
box_tab.clear()
|
|
530
|
+
location_info = update_boxes_location(boxes_to_locate, self._get_plot_axes(), plot_data, box_tab)
|
|
531
|
+
self._log_to_file_only(location_info)
|
|
532
|
+
return True
|
|
533
|
+
|
|
534
|
+
def _log_to_file_only(self, messages):
|
|
535
|
+
''' log messages to file only '''
|
|
536
|
+
self._logger.removeHandler(self._stdout_handler)
|
|
537
|
+
for message in messages:
|
|
538
|
+
self._logger.info(message)
|
|
539
|
+
self._logger.addHandler(self._stdout_handler)
|
|
@@ -80,7 +80,8 @@ def style_selector(style_callback, color_range_callback):
|
|
|
80
80
|
)
|
|
81
81
|
|
|
82
82
|
color_range_slider = pn.widgets.RangeSlider(
|
|
83
|
-
name="
|
|
83
|
+
name="Set manual color range",
|
|
84
|
+
align=('start', 'end'), # (horizontal, vertical) to place left (h=start) and bottom (v=end)
|
|
84
85
|
)
|
|
85
86
|
|
|
86
87
|
select_color_range = pn.bind(color_range_callback, color_mode_selector, color_range_slider)
|
|
@@ -95,31 +95,31 @@ class RasterPlot:
|
|
|
95
95
|
return None
|
|
96
96
|
|
|
97
97
|
data_params = self._plot_params['data']
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
x_axis = plot_params['axis_labels']['x']['axis']
|
|
101
|
-
y_axis = plot_params['axis_labels']['y']['axis']
|
|
102
|
-
c_axis = plot_params['axis_labels']['c']['axis']
|
|
103
|
-
|
|
104
|
-
# Set plot axes to numeric coordinates if needed
|
|
105
|
-
xds = set_index_coordinates(data, (x_axis, y_axis))
|
|
98
|
+
axis_labels = self._plot_params['plot']['axis_labels']
|
|
106
99
|
|
|
107
100
|
# Prefix c_axis name with aggregator
|
|
108
|
-
xda_name =
|
|
101
|
+
xda_name = axis_labels['c']['axis']
|
|
109
102
|
if data_params['aggregator']:
|
|
110
103
|
xda_name = "_".join([data_params['aggregator'], xda_name])
|
|
111
104
|
|
|
112
|
-
#
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
105
|
+
# Set plot axes to numeric coordinates if needed
|
|
106
|
+
xds = set_index_coordinates(data, (axis_labels['x']['axis'], axis_labels['y']['axis']))
|
|
107
|
+
xda = xds[data_params['correlated_data']].rename(xda_name)
|
|
108
|
+
|
|
109
|
+
# Calculate data range for flagged and unflagged data for color limits
|
|
110
|
+
unflagged_xda = xda.where(xds.FLAG == 0.0)
|
|
111
|
+
flagged_xda = xda.where(xds.FLAG == 1.0).rename("flagged " + xda_name)
|
|
112
|
+
unflagged_data_range = (unflagged_xda.min().values.item(), unflagged_xda.max().values.item())
|
|
113
|
+
flagged_data_range = (flagged_xda.min().values.item(), flagged_xda.max().values.item())
|
|
118
114
|
if is_gui: # update data range for colorbar
|
|
119
|
-
self._plot_params['data']['data_range'] =
|
|
115
|
+
self._plot_params['data']['data_range'] = unflagged_data_range
|
|
116
|
+
|
|
117
|
+
# Plot all data as unflagged (with hover tool), then overlay flagged data
|
|
118
|
+
unflagged_plot = self._plot_xda(xda, False, unflagged_data_range)
|
|
119
|
+
flagged_plot = self._plot_xda(flagged_xda, True, flagged_data_range)
|
|
120
120
|
|
|
121
121
|
# Make Overlay plot
|
|
122
|
-
return
|
|
122
|
+
return unflagged_plot.opts(tools=['hover']) * flagged_plot.opts(tools=[])
|
|
123
123
|
|
|
124
124
|
def _get_plot_title(self, data, plot_inputs, ms_name):
|
|
125
125
|
''' Form string containing ms name and selected values using data (xArray Dataset) '''
|
|
@@ -172,34 +172,34 @@ class RasterPlot:
|
|
|
172
172
|
self._plot_params['plot']['axis_labels'][axis]['label'] = axis_labels[1]
|
|
173
173
|
self._plot_params['plot']['axis_labels'][axis]['ticks'] = axis_labels[2]
|
|
174
174
|
|
|
175
|
-
def _plot_xda(self, xda, is_flagged=False):
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
175
|
+
def _plot_xda(self, xda, is_flagged=False, data_range=None):
|
|
176
|
+
''' Return Quadmesh plot if raster 2D data, Scatter plot if raster 1D data, or None if no data '''
|
|
177
|
+
# Color limits
|
|
178
|
+
c_lim = self._plot_params['plot']['color_limits']
|
|
179
|
+
c_lim = data_range if c_lim is None else c_lim
|
|
179
180
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
181
|
+
axis_labels = self._plot_params['plot']['axis_labels']
|
|
182
|
+
x_axis = axis_labels['x']['axis']
|
|
183
|
+
y_axis = axis_labels['y']['axis']
|
|
184
|
+
c_label = axis_labels['c']['label']
|
|
184
185
|
|
|
186
|
+
# Set time formatter
|
|
185
187
|
x_formatter = get_time_formatter() if x_axis == 'time' else None
|
|
186
188
|
y_formatter = get_time_formatter() if y_axis == 'time' else None
|
|
187
189
|
|
|
190
|
+
# Show colorbar
|
|
191
|
+
show_colorbar = False
|
|
188
192
|
if xda.count().values > 0:
|
|
189
|
-
if is_flagged
|
|
190
|
-
show_colorbar = style_params['show_flagged_colorbar']
|
|
191
|
-
else :
|
|
192
|
-
show_colorbar = style_params['show_colorbar']
|
|
193
|
-
else:
|
|
194
|
-
show_colorbar = False
|
|
193
|
+
show_colorbar = self._plot_params['style']['show_flagged_colorbar'] if is_flagged else self._plot_params['style']['show_colorbar']
|
|
195
194
|
|
|
195
|
+
# Set colorbar label and map
|
|
196
196
|
if is_flagged:
|
|
197
197
|
c_label = "Flagged " + c_label
|
|
198
|
-
colormap =
|
|
199
|
-
|
|
198
|
+
colormap = self._plot_params['style']['flagged_cmap']
|
|
199
|
+
self._plot_params['plot']['flagged_colorbar'] = show_colorbar
|
|
200
200
|
else:
|
|
201
|
-
colormap =
|
|
202
|
-
|
|
201
|
+
colormap = self._plot_params['style']['unflagged_cmap']
|
|
202
|
+
self._plot_params['plot']['unflagged_colorbar'] = show_colorbar
|
|
203
203
|
|
|
204
204
|
if xda[x_axis].size > 1 and xda[y_axis].size > 1:
|
|
205
205
|
# Raster 2D data
|
|
@@ -209,16 +209,16 @@ class RasterPlot:
|
|
|
209
209
|
clim=c_lim,
|
|
210
210
|
cmap=colormap,
|
|
211
211
|
clabel=c_label,
|
|
212
|
-
title=
|
|
213
|
-
xlabel=
|
|
214
|
-
ylabel=
|
|
212
|
+
title=self._plot_params['plot']['title'],
|
|
213
|
+
xlabel=axis_labels['x']['label'],
|
|
214
|
+
ylabel=axis_labels['y']['label'],
|
|
215
215
|
xformatter=x_formatter,
|
|
216
216
|
yformatter=y_formatter,
|
|
217
|
-
xticks=
|
|
218
|
-
yticks=
|
|
217
|
+
xticks=axis_labels['x']['ticks'],
|
|
218
|
+
yticks=axis_labels['y']['ticks'],
|
|
219
219
|
rot=45, # angle for x axis labels
|
|
220
220
|
colorbar=show_colorbar,
|
|
221
|
-
responsive=True, # resize to fill browser window
|
|
221
|
+
responsive=True, # resize to fill browser window
|
|
222
222
|
)
|
|
223
223
|
else:
|
|
224
224
|
# Cannot raster 1D data, use scatter from pandas dataframe
|
|
@@ -227,16 +227,16 @@ class RasterPlot:
|
|
|
227
227
|
x=x_axis,
|
|
228
228
|
y=y_axis,
|
|
229
229
|
c=xda.name,
|
|
230
|
-
clim=
|
|
230
|
+
clim=c_lim,
|
|
231
231
|
cmap=colormap,
|
|
232
232
|
clabel=c_label,
|
|
233
|
-
title=
|
|
234
|
-
xlabel=
|
|
235
|
-
ylabel=
|
|
233
|
+
title=self._plot_params['plot']['title'],
|
|
234
|
+
xlabel=axis_labels['x']['label'],
|
|
235
|
+
ylabel=axis_labels['y']['label'],
|
|
236
236
|
xformatter=x_formatter,
|
|
237
237
|
yformatter=y_formatter,
|
|
238
|
-
xticks=
|
|
239
|
-
yticks=
|
|
238
|
+
xticks=axis_labels['x']['ticks'],
|
|
239
|
+
yticks=axis_labels['y']['ticks'],
|
|
240
240
|
rot=45,
|
|
241
241
|
marker='s', # square
|
|
242
242
|
responsive=True,
|
|
@@ -26,10 +26,10 @@ def create_raster_gui(callbacks, plot_info, empty_plot):
|
|
|
26
26
|
pn.pane.HoloViews(empty_plot), # Row[0] plot
|
|
27
27
|
pn.WidgetBox(sizing_mode='stretch_width'), # Row[1] cursor location
|
|
28
28
|
)),
|
|
29
|
-
('Plot Inputs', pn.Column()),
|
|
30
|
-
('Locate
|
|
31
|
-
('Locate
|
|
32
|
-
('Plot Settings', pn.Column(
|
|
29
|
+
('Plot Inputs', pn.Column()), # Tabs[1]
|
|
30
|
+
('Locate Points', pn.Feed(sizing_mode='stretch_height')), # Tabs[2]
|
|
31
|
+
('Locate Box', pn.Feed(sizing_mode='stretch_height')), # Tabs[3]
|
|
32
|
+
('Plot Settings', pn.Column( # Tabs[4]
|
|
33
33
|
pn.Spacer(height=25), # Column[0]
|
|
34
34
|
selectors, # Column[1] selectors
|
|
35
35
|
init_plot, # Column[2] plot button and spinner
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
vidavis/LICENSE.rst,sha256=qzGpkvhDzf_MgF1PIn6rCmYPrcEhkfrBUchosLJj-U4,26371
|
|
2
2
|
vidavis/__init__.py,sha256=FVM92yTXUplR7tVHiGao0Y3Hd80pRTrwVIYDLjzICws,1709
|
|
3
3
|
vidavis/apps/__init__.py,sha256=ZQ5v1VFtjn3ztmuOHLOk5WbC1uLNIgL9rbHQ4v0zJwY,87
|
|
4
|
-
vidavis/apps/_ms_raster.py,sha256=
|
|
4
|
+
vidavis/apps/_ms_raster.py,sha256=frY1OfmNhFEwOqa3Yf06CmBrO3WI7dwDVDCh7ZTDqNY,41717
|
|
5
5
|
vidavis/bokeh/__init__.py,sha256=gdPPxBCe0enCSjvPFxkgMlhpVnAMFXKcw9GN28tVdXM,95
|
|
6
6
|
vidavis/bokeh/_palette.py,sha256=gzfJHuUgqxd8hJpZe-gQPFTCPq9f5I8uLEkHAK5FNDM,2480
|
|
7
7
|
vidavis/data/__init__.py,sha256=-RDRe0PYK6vPlhdRV2Dy1vGbnDGoXWDATmfxaR-gXcE,48
|
|
@@ -12,20 +12,20 @@ vidavis/data/measurement_set/processing_set/_ps_concat.py,sha256=uTuxE7krTu6SS7l
|
|
|
12
12
|
vidavis/data/measurement_set/processing_set/_ps_coords.py,sha256=SDp-0ebd94QjO_jPv00weiYmp-OD1XqsCzWvNc0D-94,3747
|
|
13
13
|
vidavis/data/measurement_set/processing_set/_ps_data.py,sha256=v6ARj5AJYsT30Gp8tWOZCoU7WxDb2_p8pfMbVBW4gVA,11689
|
|
14
14
|
vidavis/data/measurement_set/processing_set/_ps_io.py,sha256=VeNi-s1hozgCAGAGHs4NUXtlVFwUh-mkqrY9iYWOfW4,1717
|
|
15
|
-
vidavis/data/measurement_set/processing_set/_ps_raster_data.py,sha256=
|
|
15
|
+
vidavis/data/measurement_set/processing_set/_ps_raster_data.py,sha256=VbXM1yW0094spRnM7e06fYeRKjgLkoOXt13j91VAWpk,7361
|
|
16
16
|
vidavis/data/measurement_set/processing_set/_ps_select.py,sha256=AtEsLy3bSHEyFUFKM-OO6_-YwUdWOWcGkXkEgFxMaEE,10859
|
|
17
17
|
vidavis/data/measurement_set/processing_set/_ps_stats.py,sha256=4uLImKCANXLUM8jO8nFbBFMwfusS-JjsZ0ttbDFPrSE,8166
|
|
18
18
|
vidavis/data/measurement_set/processing_set/_xds_data.py,sha256=qLO2VkLINkSAQ7CGRFmpWQYpHrP4XoJJkwA4pp9DO8M,5253
|
|
19
19
|
vidavis/plot/__init__.py,sha256=thxe5vAGdpEiqoKPHLJoWUqKMVrUVx0ajpsGf5pVP98,95
|
|
20
20
|
vidavis/plot/ms_plot/__init__.py,sha256=wY0_7gY9M6K1D6tKQsr89L_uSs3seJlD-uicx7dx5Mo,74
|
|
21
21
|
vidavis/plot/ms_plot/_check_raster_inputs.py,sha256=a7u5wlDKTxWYW36-Xp3xd4c756SbYURdFkGHbUaX440,4786
|
|
22
|
-
vidavis/plot/ms_plot/_locate_points.py,sha256=
|
|
23
|
-
vidavis/plot/ms_plot/_ms_plot.py,sha256=
|
|
22
|
+
vidavis/plot/ms_plot/_locate_points.py,sha256=J6JguBTPQLbz0BsUU3yY6U1wHnYQf2uvw06Q26gcRW0,10586
|
|
23
|
+
vidavis/plot/ms_plot/_ms_plot.py,sha256=2TIpzTjZLmwwW8SCc3c84_8dqQ_ftZnpjSnULo5RQlw,22524
|
|
24
24
|
vidavis/plot/ms_plot/_ms_plot_constants.py,sha256=xbn_dEx4QWbZIsUDziJifrT7pXwO2Qr2B5CHyAy16So,940
|
|
25
|
-
vidavis/plot/ms_plot/_ms_plot_selectors.py,sha256=
|
|
25
|
+
vidavis/plot/ms_plot/_ms_plot_selectors.py,sha256=84rgzWFyqTl2sBcrbld_9C0iNvov43mj2Ev-YRmNTHU,11254
|
|
26
26
|
vidavis/plot/ms_plot/_plot_inputs.py,sha256=GeErBB3pYz6ecJiMTGQMNXkPeMLbWbYGmqL5dr8A46Q,687
|
|
27
|
-
vidavis/plot/ms_plot/_raster_plot.py,sha256=
|
|
28
|
-
vidavis/plot/ms_plot/_raster_plot_gui.py,sha256=
|
|
27
|
+
vidavis/plot/ms_plot/_raster_plot.py,sha256=9MU9W-rRRzfV3RTNsl030hf1DCIvYAZqnD0xJjz8yP8,11074
|
|
28
|
+
vidavis/plot/ms_plot/_raster_plot_gui.py,sha256=Q6RwzZUJSFrq7vj-0aftrv_DcvgFwf0gjKHHkN5XlSg,3527
|
|
29
29
|
vidavis/plot/ms_plot/_raster_plot_inputs.py,sha256=kxR6-1Qn4IyQ4FjgpVZ9HEZ7EnPHxJZWomb0n_zaRwo,4071
|
|
30
30
|
vidavis/plot/ms_plot/_time_ticks.py,sha256=j-DcPh7RfGE8iX2bPjLQDQPIbiAbmjiEWQnKmdMWA3I,1773
|
|
31
31
|
vidavis/plot/ms_plot/_xds_plot_axes.py,sha256=EeWvAbiKV33nEWdI8V3M0uwLTnycq4bFYBOyVWkxCu0,4429
|
|
@@ -33,8 +33,8 @@ vidavis/toolbox/__init__.py,sha256=jqFa-eziVz_frNnXxwjJFK36qNpz1H38s-VlpBcq-R8,1
|
|
|
33
33
|
vidavis/toolbox/_app_context.py,sha256=H7gtF8RrAH46FqDcMobv3KM1Osbnapgu6aTG-m3VCWA,3049
|
|
34
34
|
vidavis/toolbox/_logging.py,sha256=OEisrd8FM8VTNBMc7neLh9ekelf29ZILYB5pScebly0,2739
|
|
35
35
|
vidavis/toolbox/_static.py,sha256=HJLMtClppgOJXWAtV6Umn5EqN80u0oZiIouQ1JsB9PM,2346
|
|
36
|
-
vidavis/__version__.py,sha256=
|
|
37
|
-
vidavis-0.1.
|
|
38
|
-
vidavis-0.1.
|
|
39
|
-
vidavis-0.1.
|
|
40
|
-
vidavis-0.1.
|
|
36
|
+
vidavis/__version__.py,sha256=CjpRE9sT1AfD9Ft__Fhhop9Bh9IBCVEmm9E9TX1aV2k,21
|
|
37
|
+
vidavis-0.1.5.dist-info/WHEEL,sha256=B19PGBCYhWaz2p_UjAoRVh767nYQfk14Sn4TpIZ-nfU,87
|
|
38
|
+
vidavis-0.1.5.dist-info/METADATA,sha256=EuauQC6FnKTEXtAfi1WAzgFKgNyHNU6PvJANWeuYsts,2268
|
|
39
|
+
vidavis-0.1.5.dist-info/licenses/LICENSE,sha256=IMF9i4xIpgCADf0U-V1cuf9HBmqWQd3qtI3FSuyW4zE,26526
|
|
40
|
+
vidavis-0.1.5.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|