vidavis 0.0.13__py3-none-any.whl → 0.0.14__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 +152 -271
- vidavis/plot/ms_plot/_locate_points.py +90 -8
- vidavis/plot/ms_plot/_ms_plot.py +174 -54
- vidavis/plot/ms_plot/_raster_plot_inputs.py +114 -0
- {vidavis-0.0.13.dist-info → vidavis-0.0.14.dist-info}/METADATA +1 -1
- {vidavis-0.0.13.dist-info → vidavis-0.0.14.dist-info}/RECORD +9 -8
- {vidavis-0.0.13.dist-info → vidavis-0.0.14.dist-info}/WHEEL +0 -0
- {vidavis-0.0.13.dist-info → vidavis-0.0.14.dist-info}/licenses/LICENSE +0 -0
|
@@ -10,8 +10,9 @@ import panel as pn
|
|
|
10
10
|
|
|
11
11
|
from vidavis.plot.ms_plot._ms_plot_constants import TIME_FORMAT
|
|
12
12
|
|
|
13
|
-
def cursor_changed(
|
|
13
|
+
def cursor_changed(cursor, last_cursor):
|
|
14
14
|
''' Check whether cursor position changed '''
|
|
15
|
+
x, y = cursor
|
|
15
16
|
if not x and not y:
|
|
16
17
|
return False # not cursor callback
|
|
17
18
|
if last_cursor and last_cursor == (x, y):
|
|
@@ -21,7 +22,7 @@ def cursor_changed(x, y, last_cursor):
|
|
|
21
22
|
def points_changed(data, last_points):
|
|
22
23
|
''' Check whether point positions changed '''
|
|
23
24
|
# No data = {'x': [], 'y': []}
|
|
24
|
-
if len(data['x']) == 0 and len(data['y']) == 0:
|
|
25
|
+
if not data or (len(data['x']) == 0 and len(data['y']) == 0):
|
|
25
26
|
return False # not points callback
|
|
26
27
|
if last_points and last_points == data:
|
|
27
28
|
return False # same points
|
|
@@ -36,7 +37,67 @@ def box_changed(bounds, last_box):
|
|
|
36
37
|
return False # same box
|
|
37
38
|
return True # new box, box changed, or box deleted
|
|
38
39
|
|
|
39
|
-
def
|
|
40
|
+
def update_cursor_location(cursor, plot_axes, xds, cursor_locate_box):
|
|
41
|
+
''' Show data values for cursor x,y position in cursor location box (pn.WidgetBox) '''
|
|
42
|
+
# Convert plot values to selection values to select plot data
|
|
43
|
+
cursor_locate_box.clear()
|
|
44
|
+
|
|
45
|
+
x, y = cursor
|
|
46
|
+
x_axis, y_axis, vis_axis = plot_axes
|
|
47
|
+
cursor_position = {x_axis: x, y_axis: y}
|
|
48
|
+
cursor_location = _locate_point(xds, cursor_position, vis_axis)
|
|
49
|
+
|
|
50
|
+
location_column = pn.Column(pn.widgets.StaticText(name="Cursor Location"))
|
|
51
|
+
# Add row of columns to column layout
|
|
52
|
+
location_row = _layout_point_location(cursor_location)
|
|
53
|
+
location_column.append(location_row)
|
|
54
|
+
# Add location column to widget box
|
|
55
|
+
cursor_locate_box.append(location_column)
|
|
56
|
+
|
|
57
|
+
def update_points_location(data, plot_axes, xds, points_tab_column, logger):
|
|
58
|
+
''' Show data values for points in point_draw in tab and log '''
|
|
59
|
+
points_tab_column.clear()
|
|
60
|
+
if data:
|
|
61
|
+
x_axis, y_axis, vis_axis = plot_axes
|
|
62
|
+
logger.info("Locate selected points:")
|
|
63
|
+
|
|
64
|
+
for point in list(zip(data['x'], data['y'])):
|
|
65
|
+
# Locate point
|
|
66
|
+
point_position = {x_axis: point[0], y_axis: point[1]}
|
|
67
|
+
point_location = _locate_point(xds, point_position, vis_axis)
|
|
68
|
+
# Format location and add to points locate column
|
|
69
|
+
location_layout = _layout_point_location(point_location)
|
|
70
|
+
points_tab_column.append(location_layout)
|
|
71
|
+
points_tab_column.append(pn.layout.Divider())
|
|
72
|
+
|
|
73
|
+
# Format and add to log
|
|
74
|
+
location_list = [f"{static_text.name}={static_text.value}" for static_text in point_location]
|
|
75
|
+
logger.info(", ".join(location_list))
|
|
76
|
+
|
|
77
|
+
def update_box_location(bounds, plot_axes, xds, box_tab_column, logger):
|
|
78
|
+
''' Show data values for points in box_select in tab and log '''
|
|
79
|
+
box_tab_column.clear()
|
|
80
|
+
if bounds:
|
|
81
|
+
x_axis, y_axis, vis_axis = plot_axes
|
|
82
|
+
box_bounds = {x_axis: (bounds[0], bounds[2]), y_axis: (bounds[1], bounds[3])}
|
|
83
|
+
npoints, point_locations = _locate_box(xds, box_bounds, vis_axis)
|
|
84
|
+
|
|
85
|
+
message = f"Locate {npoints} points"
|
|
86
|
+
message += " (only first 100 shown):" if npoints > 100 else ":"
|
|
87
|
+
logger.info(message)
|
|
88
|
+
box_tab_column.append(pn.pane.Str(message))
|
|
89
|
+
|
|
90
|
+
for point in point_locations:
|
|
91
|
+
# Format and add to box locate column
|
|
92
|
+
location_layout = _layout_point_location(point)
|
|
93
|
+
box_tab_column.append(location_layout)
|
|
94
|
+
box_tab_column.append(pn.layout.Divider())
|
|
95
|
+
|
|
96
|
+
# Format and add to log
|
|
97
|
+
location_list = [f"{static_text.name}={static_text.value}" for static_text in point]
|
|
98
|
+
logger.info(", ".join(location_list))
|
|
99
|
+
|
|
100
|
+
def _locate_point(xds, position, vis_axis):
|
|
40
101
|
'''
|
|
41
102
|
Get cursor location as values of coordinates and data vars.
|
|
42
103
|
xds (Xarray Dataset): data for plot
|
|
@@ -48,15 +109,18 @@ def locate_point(xds, position, vis_axis):
|
|
|
48
109
|
static_text_list = []
|
|
49
110
|
values, units = _get_point_location(xds, position, vis_axis)
|
|
50
111
|
|
|
51
|
-
#
|
|
52
|
-
|
|
112
|
+
# List indexed coordinate int value with with str value
|
|
113
|
+
index_coords = {'baseline': 'baseline_name', 'antenna_name': 'antenna', 'polarization': 'polarization_name'}
|
|
53
114
|
for name, value in values.items():
|
|
54
|
-
|
|
115
|
+
if name in index_coords.values():
|
|
116
|
+
continue
|
|
117
|
+
if name in index_coords and isinstance(value, int):
|
|
118
|
+
value = f"{values[index_coords[name]]} ({value})" # append name to index
|
|
55
119
|
static_text = _get_location_text(name, value, units)
|
|
56
120
|
static_text_list.append(static_text)
|
|
57
121
|
return static_text_list
|
|
58
122
|
|
|
59
|
-
def
|
|
123
|
+
def _locate_box(xds, bounds, vis_axis):
|
|
60
124
|
'''
|
|
61
125
|
Get location of each point in box bounds as values of coordinate and data vars.
|
|
62
126
|
xds (Xarray Dataset): data for plot
|
|
@@ -83,7 +147,7 @@ def locate_box(xds, bounds, vis_axis):
|
|
|
83
147
|
for y in sel_xds[y_coord].values:
|
|
84
148
|
for x in sel_xds[x_coord].values:
|
|
85
149
|
position = {x_coord: x, y_coord: y}
|
|
86
|
-
points.append(
|
|
150
|
+
points.append(_locate_point(sel_xds, position, vis_axis))
|
|
87
151
|
counter += 1
|
|
88
152
|
if counter == 100:
|
|
89
153
|
break
|
|
@@ -183,3 +247,21 @@ def _get_location_text(name, value, units):
|
|
|
183
247
|
units.pop(name) # no unit for datetime string
|
|
184
248
|
unit = units[name] if name in units else ""
|
|
185
249
|
return pn.widgets.StaticText(name=name, value=f"{value} {unit}")
|
|
250
|
+
|
|
251
|
+
def _layout_point_location(text_list):
|
|
252
|
+
''' Layout list of StaticText in row of columns containing 3 rows '''
|
|
253
|
+
location_row = pn.Row()
|
|
254
|
+
location_col = pn.Column()
|
|
255
|
+
|
|
256
|
+
for static_text in text_list:
|
|
257
|
+
# 3 entries per column; append to row and start new column
|
|
258
|
+
if len(location_col.objects) == 3:
|
|
259
|
+
location_row.append(location_col)
|
|
260
|
+
location_col = pn.Column()
|
|
261
|
+
|
|
262
|
+
static_text.margin = (0, 10) # default (5, 10)
|
|
263
|
+
location_col.append(static_text)
|
|
264
|
+
|
|
265
|
+
# Add last column
|
|
266
|
+
location_row.append(location_col)
|
|
267
|
+
return location_row
|
vidavis/plot/ms_plot/_ms_plot.py
CHANGED
|
@@ -20,6 +20,7 @@ except ImportError:
|
|
|
20
20
|
_HAVE_TOOLVIPER = False
|
|
21
21
|
|
|
22
22
|
from vidavis.data.measurement_set._ms_data import MsData
|
|
23
|
+
from vidavis.plot.ms_plot._locate_points import cursor_changed, points_changed, box_changed, update_cursor_location, update_points_location, update_box_location
|
|
23
24
|
from vidavis.toolbox import AppContext, get_logger
|
|
24
25
|
|
|
25
26
|
class MsPlot:
|
|
@@ -45,39 +46,42 @@ class MsPlot:
|
|
|
45
46
|
# Set up temp dir for output html files
|
|
46
47
|
self._app_context = AppContext(app_name)
|
|
47
48
|
|
|
49
|
+
# Initialize plot inputs and params
|
|
50
|
+
self._plot_inputs = None # object to manage plot inputs
|
|
51
|
+
|
|
52
|
+
# Initialize plots
|
|
53
|
+
self._plot_init = False
|
|
54
|
+
self._plots = []
|
|
55
|
+
self._last_plot = None
|
|
56
|
+
self._plot_params = [] # for plot inputs tab
|
|
57
|
+
|
|
48
58
|
if show_gui:
|
|
49
59
|
# Enable "toast" notifications
|
|
50
60
|
pn.config.notifications = True
|
|
51
61
|
self._toast = None # for destroy() with new plot or new notification
|
|
52
62
|
|
|
53
63
|
# Initialize gui panel for callbacks
|
|
64
|
+
self._gui_plot_data = None
|
|
65
|
+
self._gui_selection = {}
|
|
54
66
|
self._gui_layout = None
|
|
55
67
|
self._first_gui_plot = True
|
|
56
|
-
self._last_gui_plot = None
|
|
57
|
-
self._gui_plot_data = None
|
|
58
68
|
|
|
59
|
-
# For _update_plot callback: check
|
|
69
|
+
# For _update_plot callback: check if inputs changed
|
|
60
70
|
self._last_plot_inputs = None
|
|
61
71
|
self._last_style_inputs = None
|
|
62
|
-
self._last_cursor = None
|
|
63
|
-
self._last_points = None
|
|
64
|
-
self._last_box = None
|
|
65
72
|
|
|
66
|
-
#
|
|
67
|
-
self.
|
|
68
|
-
self.
|
|
73
|
+
# For locate callback: check if points changed
|
|
74
|
+
self._plot_axes = None
|
|
75
|
+
self._last_cursor = None
|
|
76
|
+
self._last_points = None
|
|
77
|
+
self._last_box = None
|
|
69
78
|
|
|
70
|
-
# Initialize
|
|
71
|
-
self._plot_init = False
|
|
72
|
-
self._plots_locked = False
|
|
73
|
-
self._plots = []
|
|
74
|
-
|
|
75
|
-
# Initialize show() panel for callbacks
|
|
79
|
+
# Initialize non-gui show() panel for callbacks
|
|
76
80
|
self._show_layout = None
|
|
77
81
|
self._plot_data = None
|
|
78
82
|
|
|
79
83
|
# Set data (if ms)
|
|
80
|
-
self.
|
|
84
|
+
self._ms_data = None
|
|
81
85
|
self._ms_info = {}
|
|
82
86
|
self._set_ms(ms)
|
|
83
87
|
# pylint: enable=too-many-arguments, too-many-positional-arguments
|
|
@@ -94,15 +98,15 @@ class MsPlot:
|
|
|
94
98
|
'field_name', 'source_name', 'field_coords', 'start_frequency', 'end_frequency'
|
|
95
99
|
Returns: list of unique values when single column is requested, else None
|
|
96
100
|
'''
|
|
97
|
-
if self.
|
|
98
|
-
self.
|
|
101
|
+
if self._ms_data:
|
|
102
|
+
self._ms_data.summary(data_group, columns)
|
|
99
103
|
else:
|
|
100
104
|
self._logger.error("Error: MS path has not been set")
|
|
101
105
|
|
|
102
106
|
def data_groups(self):
|
|
103
107
|
''' Returns set of data groups from all ProcessingSet ms_xds. '''
|
|
104
|
-
if self.
|
|
105
|
-
return self.
|
|
108
|
+
if self._ms_data:
|
|
109
|
+
return self._ms_data.data_groups()
|
|
106
110
|
self._logger.error("Error: MS path has not been set")
|
|
107
111
|
return None
|
|
108
112
|
|
|
@@ -111,8 +115,8 @@ class MsPlot:
|
|
|
111
115
|
Dimension options include 'time', 'baseline' (for visibility data), 'antenna' (for spectrum data), 'antenna1',
|
|
112
116
|
'antenna2', 'frequency', 'polarization'.
|
|
113
117
|
'''
|
|
114
|
-
if self.
|
|
115
|
-
return self.
|
|
118
|
+
if self._ms_data:
|
|
119
|
+
return self._ms_data.get_dimension_values(dimension)
|
|
116
120
|
self._logger.error("Error: MS path has not been set")
|
|
117
121
|
return None
|
|
118
122
|
|
|
@@ -120,8 +124,8 @@ class MsPlot:
|
|
|
120
124
|
''' Plot antenna positions.
|
|
121
125
|
label_antennas (bool): label positions with antenna names.
|
|
122
126
|
'''
|
|
123
|
-
if self.
|
|
124
|
-
self.
|
|
127
|
+
if self._ms_data:
|
|
128
|
+
self._ms_data.plot_antennas(label_antennas)
|
|
125
129
|
else:
|
|
126
130
|
self._logger.error("Error: MS path has not been set")
|
|
127
131
|
|
|
@@ -130,23 +134,33 @@ class MsPlot:
|
|
|
130
134
|
data_group (str): data group to use for field and source xds.
|
|
131
135
|
label_fields (bool): label all fields on the plot if True, else label central field only
|
|
132
136
|
'''
|
|
133
|
-
if self.
|
|
134
|
-
self.
|
|
137
|
+
if self._ms_data:
|
|
138
|
+
self._ms_data.plot_phase_centers(data_group, label_fields)
|
|
135
139
|
else:
|
|
136
140
|
self._logger.error("Error: MS path has not been set")
|
|
137
141
|
|
|
138
142
|
def clear_plots(self):
|
|
139
143
|
''' Clear plot list '''
|
|
140
|
-
while self._plots_locked:
|
|
141
|
-
time.sleep(1)
|
|
142
144
|
self._plots.clear()
|
|
145
|
+
self._plot_params.clear()
|
|
146
|
+
self._plot_axes = None
|
|
147
|
+
|
|
148
|
+
def unlink_plot_streams(self):
|
|
149
|
+
''' Disconnect streams when plot data is going to be replaced '''
|
|
150
|
+
if self._show_layout and len(self._show_layout.objects) == 4:
|
|
151
|
+
# Remove dmap (streams with callback) from previous plot
|
|
152
|
+
self._show_layout[0][0] = self._last_plot.opts(tools=['hover'])
|
|
153
|
+
# Remove locate widgets
|
|
154
|
+
self._show_layout[0].pop(1) # cursor locate box
|
|
155
|
+
self._show_layout.pop(3) # box locate tab
|
|
156
|
+
self._show_layout.pop(2) # points locate tab
|
|
143
157
|
|
|
144
158
|
def clear_selection(self):
|
|
145
159
|
''' Clear data selection and restore original ProcessingSet '''
|
|
146
|
-
if self.
|
|
147
|
-
self.
|
|
160
|
+
if self._ms_data:
|
|
161
|
+
self._ms_data.clear_selection()
|
|
148
162
|
|
|
149
|
-
self._plot_inputs
|
|
163
|
+
self._plot_inputs.remove_input('selection')
|
|
150
164
|
|
|
151
165
|
def show(self):
|
|
152
166
|
'''
|
|
@@ -155,24 +169,61 @@ class MsPlot:
|
|
|
155
169
|
if not self._plots:
|
|
156
170
|
raise RuntimeError("No plots to show. Run plot() to create plot.")
|
|
157
171
|
|
|
158
|
-
# Do not delete plot list until rendered
|
|
159
|
-
self._plots_locked = True
|
|
160
|
-
|
|
161
172
|
# Single plot or combine plots into layout using subplots (rows, columns)
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
# Render plot as Bokeh Figure or GridPlot so can show() in script without tying up thread
|
|
165
|
-
bokeh_fig = hv.render(layout_plot)
|
|
173
|
+
subplots = self._plot_inputs.get_input('subplots')
|
|
174
|
+
layout_plot = self._layout_plots(subplots)
|
|
166
175
|
|
|
167
|
-
|
|
176
|
+
# Add plot inputs column tab
|
|
177
|
+
inputs_column = None
|
|
168
178
|
if self._plot_params:
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
179
|
+
inputs_column = pn.Column()
|
|
180
|
+
self._fill_inputs_column(inputs_column)
|
|
181
|
+
|
|
182
|
+
# Show plot and plot inputs in tabs
|
|
183
|
+
if self._plot_inputs.is_layout():
|
|
184
|
+
self._show_layout = pn.Tabs(('Plot', layout_plot))
|
|
185
|
+
if inputs_column:
|
|
186
|
+
self._show_layout.append(('Plot Inputs', inputs_column))
|
|
174
187
|
else:
|
|
175
|
-
|
|
188
|
+
plot = layout_plot.opts(
|
|
189
|
+
hv.opts.QuadMesh(
|
|
190
|
+
tools=['hover', 'box_select'],
|
|
191
|
+
selection_fill_alpha=0.2, # dim selected areas of plot
|
|
192
|
+
nonselection_fill_alpha=1.0, # do not dim unselected areas of plot
|
|
193
|
+
)
|
|
194
|
+
)
|
|
195
|
+
# Add DynamicMap for streams for single plot
|
|
196
|
+
points = hv.Points([]).opts(
|
|
197
|
+
size=5,
|
|
198
|
+
fill_color='white'
|
|
199
|
+
)
|
|
200
|
+
dmap = hv.DynamicMap(
|
|
201
|
+
self._locate,
|
|
202
|
+
streams=[
|
|
203
|
+
hv.streams.PointerXY(), # cursor location (x, y)
|
|
204
|
+
hv.streams.PointDraw(source=points), # fixed points location (data)
|
|
205
|
+
hv.streams.BoundsXY() # box location (bounds)
|
|
206
|
+
]
|
|
207
|
+
)
|
|
208
|
+
|
|
209
|
+
# Create panel layout
|
|
210
|
+
self._show_layout = pn.Tabs(
|
|
211
|
+
('Plot', pn.Column(
|
|
212
|
+
plot * dmap * points,
|
|
213
|
+
pn.WidgetBox(), # cursor info
|
|
214
|
+
)
|
|
215
|
+
),
|
|
216
|
+
sizing_mode='stretch_width',
|
|
217
|
+
)
|
|
218
|
+
if inputs_column:
|
|
219
|
+
self._show_layout.append(('Plot Inputs', inputs_column))
|
|
220
|
+
self._show_layout.append(('Locate Selected Points', pn.Column()))
|
|
221
|
+
self._show_layout.append(('Locate Selected Box', pn.Column()))
|
|
222
|
+
|
|
223
|
+
# return value for locate callback
|
|
224
|
+
self._last_plot = plot
|
|
225
|
+
|
|
226
|
+
# Show panel layout
|
|
176
227
|
self._show_layout.show(title=self._app_name, threaded=True)
|
|
177
228
|
|
|
178
229
|
def save(self, filename='ms_plot.png', fmt='auto', width=900, height=600):
|
|
@@ -193,11 +244,14 @@ class MsPlot:
|
|
|
193
244
|
|
|
194
245
|
# Combine plots into layout using subplots (rows, columns) if not single plot.
|
|
195
246
|
# Set fixed size for export.
|
|
196
|
-
|
|
247
|
+
subplots = self._plot_inputs.get_input('subplots')
|
|
248
|
+
layout_plot = self._layout_plots(subplots, (width, height))
|
|
197
249
|
|
|
198
|
-
|
|
250
|
+
iter_axis = self._plot_inputs.get_input('iter_axis')
|
|
251
|
+
if not isinstance(layout_plot, hv.Layout) and iter_axis:
|
|
199
252
|
# Save iterated plots individually, with index appended to filename
|
|
200
|
-
|
|
253
|
+
iter_range = self._plot_inputs.get_input('iter_range')
|
|
254
|
+
plot_idx = 0 if iter_range is None else iter_range[0]
|
|
201
255
|
for plot in self._plots:
|
|
202
256
|
exportname = f"{name}_{plot_idx}{ext}"
|
|
203
257
|
self._save_plot(plot, exportname, fmt)
|
|
@@ -266,22 +320,22 @@ class MsPlot:
|
|
|
266
320
|
Return whether ms changed (false if ms_path is None, not set yet), even if error. '''
|
|
267
321
|
self._ms_info['ms'] = ms_path
|
|
268
322
|
ms_error = ""
|
|
269
|
-
if not ms_path or (self.
|
|
323
|
+
if not ms_path or (self._ms_data and self._ms_data.is_ms_path(ms_path)):
|
|
270
324
|
return False
|
|
271
325
|
|
|
272
326
|
try:
|
|
273
327
|
# Set new MS data
|
|
274
|
-
self.
|
|
275
|
-
data_path = self.
|
|
328
|
+
self._ms_data = MsData(ms_path, self._logger)
|
|
329
|
+
data_path = self._ms_data.get_path()
|
|
276
330
|
self._ms_info['ms'] = data_path
|
|
277
331
|
root, ext = os.path.splitext(os.path.basename(data_path))
|
|
278
332
|
while ext != '':
|
|
279
333
|
root, ext = os.path.splitext(root)
|
|
280
334
|
self._ms_info['basename'] = root
|
|
281
|
-
self._ms_info['data_dims'] = self.
|
|
335
|
+
self._ms_info['data_dims'] = self._ms_data.get_data_dimensions()
|
|
282
336
|
except RuntimeError as e:
|
|
283
337
|
ms_error = str(e)
|
|
284
|
-
self.
|
|
338
|
+
self._ms_data = None
|
|
285
339
|
if ms_error:
|
|
286
340
|
self._notify(ms_error, 'error', 0)
|
|
287
341
|
return True
|
|
@@ -320,4 +374,70 @@ class MsPlot:
|
|
|
320
374
|
del plot_inputs[key]
|
|
321
375
|
except KeyError:
|
|
322
376
|
pass
|
|
323
|
-
self._plot_params
|
|
377
|
+
if not self._plot_params:
|
|
378
|
+
self._plot_params = plot_inputs
|
|
379
|
+
else:
|
|
380
|
+
for param, value in self._plot_params.items():
|
|
381
|
+
if plot_inputs[param] != value:
|
|
382
|
+
if isinstance(value, list):
|
|
383
|
+
# append new value to existing list if not repeat
|
|
384
|
+
if plot_inputs[param] != value[-1]:
|
|
385
|
+
value.append(plot_inputs[param])
|
|
386
|
+
else:
|
|
387
|
+
# make list to include new value
|
|
388
|
+
value = [value, plot_inputs[param]]
|
|
389
|
+
self._plot_params[param] = value
|
|
390
|
+
|
|
391
|
+
def _fill_inputs_column(self, inputs_tab_column):
|
|
392
|
+
''' Format plot inputs and list in Panel column '''
|
|
393
|
+
if self._plot_params:
|
|
394
|
+
inputs_tab_column.clear()
|
|
395
|
+
plot_params = sorted([f"{key}={value}" for key, value in self._plot_params.items()])
|
|
396
|
+
for param in plot_params:
|
|
397
|
+
str_pane = pn.pane.Str(param)
|
|
398
|
+
str_pane.margin = (0, 10)
|
|
399
|
+
inputs_tab_column.append(str_pane)
|
|
400
|
+
|
|
401
|
+
def _get_plot_axes(self):
|
|
402
|
+
''' Return x, y, vis axes '''
|
|
403
|
+
if not self._plot_axes:
|
|
404
|
+
x_axis = self._plot_inputs.get_input('x_axis')
|
|
405
|
+
y_axis = self._plot_inputs.get_input('y_axis')
|
|
406
|
+
vis_axis = self._plot_inputs.get_input('vis_axis')
|
|
407
|
+
self._plot_axes = (x_axis, y_axis, vis_axis)
|
|
408
|
+
return self._plot_axes
|
|
409
|
+
|
|
410
|
+
def _locate(self, x, y, data, bounds):
|
|
411
|
+
''' Callback for all show plot streams '''
|
|
412
|
+
self._locate_cursor(x, y, self._plot_data, self._show_layout)
|
|
413
|
+
self._locate_points(data, self._plot_data, self._show_layout)
|
|
414
|
+
self._locate_box(bounds, self._plot_data, self._show_layout)
|
|
415
|
+
return self._last_plot
|
|
416
|
+
|
|
417
|
+
def _locate_cursor(self, x, y, plot_data, tabs):
|
|
418
|
+
''' Show location from cursor position in cursor locate box '''
|
|
419
|
+
cursor = (x, y)
|
|
420
|
+
if cursor_changed(cursor, self._last_cursor):
|
|
421
|
+
# new cursor position - update cursor location box
|
|
422
|
+
plot_axes = self._get_plot_axes()
|
|
423
|
+
cursor_box = tabs[0][1]
|
|
424
|
+
update_cursor_location(cursor, plot_axes, plot_data, cursor_box)
|
|
425
|
+
self._last_cursor = cursor
|
|
426
|
+
|
|
427
|
+
def _locate_points(self, point_data, plot_data, tabs):
|
|
428
|
+
''' Show points locations from point_draw tool '''
|
|
429
|
+
if points_changed(point_data, self._last_points):
|
|
430
|
+
# new points position - update selected points location tab
|
|
431
|
+
plot_axes = self._get_plot_axes()
|
|
432
|
+
points_tab = tabs[2]
|
|
433
|
+
update_points_location(point_data, plot_axes, plot_data, points_tab, self._logger)
|
|
434
|
+
self._last_points = point_data
|
|
435
|
+
|
|
436
|
+
def _locate_box(self, box_bounds, plot_data, tabs):
|
|
437
|
+
''' Show points locations in box from box_select tool '''
|
|
438
|
+
if box_changed(box_bounds, self._last_box):
|
|
439
|
+
# new box_select position - update selected box location tab
|
|
440
|
+
plot_axes = self._get_plot_axes()
|
|
441
|
+
box_tab = tabs[3]
|
|
442
|
+
update_box_location(box_bounds, plot_axes, plot_data, box_tab, self._logger)
|
|
443
|
+
self._last_box = box_bounds
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
'''
|
|
2
|
+
Class to check and hold inputs for raster plot.
|
|
3
|
+
'''
|
|
4
|
+
|
|
5
|
+
from vidavis.plot.ms_plot._check_raster_inputs import check_inputs
|
|
6
|
+
|
|
7
|
+
class RasterPlotInputs:
|
|
8
|
+
'''
|
|
9
|
+
Class to set inputs for raster plots from MsRaster functions or GUI.
|
|
10
|
+
'''
|
|
11
|
+
|
|
12
|
+
def __init__(self):
|
|
13
|
+
self._plot_inputs = {}
|
|
14
|
+
|
|
15
|
+
def get_inputs(self):
|
|
16
|
+
''' Getter for stored plot inputs '''
|
|
17
|
+
return self._plot_inputs
|
|
18
|
+
|
|
19
|
+
def get_input(self, name):
|
|
20
|
+
''' Getter for stored plot input by name '''
|
|
21
|
+
try:
|
|
22
|
+
return self._plot_inputs[name]
|
|
23
|
+
except KeyError:
|
|
24
|
+
return None
|
|
25
|
+
|
|
26
|
+
def set_input(self, name, value):
|
|
27
|
+
''' Set plot input by name and value '''
|
|
28
|
+
self._plot_inputs[name] = value
|
|
29
|
+
if name == 'selection' and 'data_group_name' in value:
|
|
30
|
+
self._plot_inputs['data_group'] = value['data_group_name']
|
|
31
|
+
|
|
32
|
+
def set_selection(self, selection):
|
|
33
|
+
''' Add selection dict to existing selection in plot inputs '''
|
|
34
|
+
if 'selection' not in self._plot_inputs:
|
|
35
|
+
self._plot_inputs['selection'] = {}
|
|
36
|
+
self._plot_inputs['selection'] |= selection
|
|
37
|
+
if 'data_group_name' in selection:
|
|
38
|
+
self._plot_inputs['data_group'] = selection['data_group_name']
|
|
39
|
+
|
|
40
|
+
def get_selection(self, key):
|
|
41
|
+
''' Return value for selection key '''
|
|
42
|
+
try:
|
|
43
|
+
return self.get_input('selection')[key]
|
|
44
|
+
except (TypeError, KeyError):
|
|
45
|
+
# TypeError: get_input returned None for 'selection'
|
|
46
|
+
# KeyError: key not in selection
|
|
47
|
+
return None
|
|
48
|
+
|
|
49
|
+
def set_inputs(self, plot_inputs):
|
|
50
|
+
''' Setter for storing plot inputs from MsRaster.plot() '''
|
|
51
|
+
check_inputs(plot_inputs)
|
|
52
|
+
for key, val in plot_inputs.items():
|
|
53
|
+
self._plot_inputs[key] = val
|
|
54
|
+
|
|
55
|
+
def remove_input(self, name):
|
|
56
|
+
''' Remove plot input with name, if it exists '''
|
|
57
|
+
try:
|
|
58
|
+
del self._plot_inputs[name]
|
|
59
|
+
except KeyError:
|
|
60
|
+
pass
|
|
61
|
+
|
|
62
|
+
def check_inputs(self):
|
|
63
|
+
''' Check input values are valid, adjust for data dims '''
|
|
64
|
+
check_inputs(self._plot_inputs)
|
|
65
|
+
|
|
66
|
+
def is_layout(self):
|
|
67
|
+
''' Determine if plot is a layout using plot inputs '''
|
|
68
|
+
# Check if subplots is a layout
|
|
69
|
+
subplots = self.get_input('subplots')
|
|
70
|
+
if subplots is None or subplots == (1, 1):
|
|
71
|
+
return False
|
|
72
|
+
|
|
73
|
+
# Subplots is a layout, check if multi plot
|
|
74
|
+
if not self.get_input('clear_plots'):
|
|
75
|
+
return True
|
|
76
|
+
|
|
77
|
+
# Check if iteration set and iter_range more than one plot
|
|
78
|
+
iter_length = 0
|
|
79
|
+
if self.get_input('iter_axis') is not None:
|
|
80
|
+
iter_range = self.get_input('iter_range')
|
|
81
|
+
if iter_range is None or iter_range[1] == -1:
|
|
82
|
+
iter_range = self.get_input('auto_iter_range')
|
|
83
|
+
iter_length = len(range(iter_range[0], iter_range[1] + 1))
|
|
84
|
+
return iter_length > 1
|
|
85
|
+
|
|
86
|
+
#--------------
|
|
87
|
+
# GUI CALLBACKS
|
|
88
|
+
#--------------
|
|
89
|
+
|
|
90
|
+
def set_color_inputs(self, color_mode, color_range):
|
|
91
|
+
''' Set style params from gui '''
|
|
92
|
+
color_mode = color_mode.split()[0]
|
|
93
|
+
color_mode = None if color_mode == 'No' else color_mode
|
|
94
|
+
self.set_input('color_mode', color_mode)
|
|
95
|
+
self.set_input('color_range', color_range)
|
|
96
|
+
|
|
97
|
+
def set_axis_inputs(self, x_axis, y_axis, vis_axis):
|
|
98
|
+
''' Set plot axis inputs from gui '''
|
|
99
|
+
self.set_input('x_axis', x_axis)
|
|
100
|
+
self.set_input('y_axis', y_axis)
|
|
101
|
+
self.set_input('vis_axis', vis_axis)
|
|
102
|
+
|
|
103
|
+
def set_aggregation_inputs(self, aggregator, agg_axes):
|
|
104
|
+
''' Set aggregation inputs from gui '''
|
|
105
|
+
aggregator = None if aggregator== 'None' else aggregator
|
|
106
|
+
self.set_input('aggregator', aggregator)
|
|
107
|
+
self.set_input('agg_axis', agg_axes) # ignored if aggregator not set
|
|
108
|
+
|
|
109
|
+
def set_iteration_inputs(self, iter_axis, iter_range, subplot_rows, subplot_columns):
|
|
110
|
+
''' Set iteration inputs from gui '''
|
|
111
|
+
iter_axis = None if iter_axis == 'None' else iter_axis
|
|
112
|
+
self.set_input('iter_axis', iter_axis)
|
|
113
|
+
self.set_input('iter_range', iter_range)
|
|
114
|
+
self.set_input('subplots', (subplot_rows, subplot_columns))
|
|
@@ -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=MtW55gRm9EYKR-E86-YrfSnNiYg-xa6WJNar-0-Rsac,43139
|
|
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
|
|
@@ -19,21 +19,22 @@ vidavis/data/measurement_set/processing_set/_xds_data.py,sha256=qLO2VkLINkSAQ7CG
|
|
|
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=f2sOeq1Ba6SR7uk7pX2vS2TLPsQsWZti2VJkOcFx6Gw,10899
|
|
23
|
+
vidavis/plot/ms_plot/_ms_plot.py,sha256=B0_81JtBD9k7M8frwlgoJNH6vZzW17aGmytPjD_xQqw,18706
|
|
24
24
|
vidavis/plot/ms_plot/_ms_plot_constants.py,sha256=cX_TQhKJ3hJzPuRYmuRJxue1sjq82yl_ZN2_w6TshmI,930
|
|
25
25
|
vidavis/plot/ms_plot/_ms_plot_selectors.py,sha256=BZQwARvMPdk78n6Rh2tOaSc8GenZBrxHZb14oFD9gJM,10785
|
|
26
26
|
vidavis/plot/ms_plot/_plot_inputs.py,sha256=pZL63n9FHSoo9cntf7lppQj44nkpiwnCz6VH-9Oh6ho,671
|
|
27
27
|
vidavis/plot/ms_plot/_raster_plot.py,sha256=lNa9i_eJ8F8Fc2zcHLRcaxKKOELk3x_QmXT__T76pg8,10999
|
|
28
28
|
vidavis/plot/ms_plot/_raster_plot_gui.py,sha256=Kb0BLmkwtYHCqlVaSipbTTStst8RYggqwf1Wf5v8F4Q,4261
|
|
29
|
+
vidavis/plot/ms_plot/_raster_plot_inputs.py,sha256=AMIvEz2b4QLH03P6EJXOAnkQ-v2uNKEukdaoA6g070Y,4166
|
|
29
30
|
vidavis/plot/ms_plot/_time_ticks.py,sha256=j-DcPh7RfGE8iX2bPjLQDQPIbiAbmjiEWQnKmdMWA3I,1773
|
|
30
31
|
vidavis/plot/ms_plot/_xds_plot_axes.py,sha256=EeWvAbiKV33nEWdI8V3M0uwLTnycq4bFYBOyVWkxCu0,4429
|
|
31
32
|
vidavis/toolbox/__init__.py,sha256=jqFa-eziVz_frNnXxwjJFK36qNpz1H38s-VlpBcq-R8,1402
|
|
32
33
|
vidavis/toolbox/_app_context.py,sha256=H7gtF8RrAH46FqDcMobv3KM1Osbnapgu6aTG-m3VCWA,3049
|
|
33
34
|
vidavis/toolbox/_logging.py,sha256=OEisrd8FM8VTNBMc7neLh9ekelf29ZILYB5pScebly0,2739
|
|
34
35
|
vidavis/toolbox/_static.py,sha256=HJLMtClppgOJXWAtV6Umn5EqN80u0oZiIouQ1JsB9PM,2346
|
|
35
|
-
vidavis/__version__.py,sha256=
|
|
36
|
-
vidavis-0.0.
|
|
37
|
-
vidavis-0.0.
|
|
38
|
-
vidavis-0.0.
|
|
39
|
-
vidavis-0.0.
|
|
36
|
+
vidavis/__version__.py,sha256=DT3lXVWSM0vxCDfBsBbQ4k1SOUtDSFBhl094H35FE2w,22
|
|
37
|
+
vidavis-0.0.14.dist-info/WHEEL,sha256=B19PGBCYhWaz2p_UjAoRVh767nYQfk14Sn4TpIZ-nfU,87
|
|
38
|
+
vidavis-0.0.14.dist-info/METADATA,sha256=fZDo9_lUcwhVToPrllG6fE5SJj0XcyDcgbzoOvVf_zY,2238
|
|
39
|
+
vidavis-0.0.14.dist-info/licenses/LICENSE,sha256=IMF9i4xIpgCADf0U-V1cuf9HBmqWQd3qtI3FSuyW4zE,26526
|
|
40
|
+
vidavis-0.0.14.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|