304 self.mpl_connect('button_release_event', self.OnCanvasButtonReleased) |
304 self.mpl_connect('button_release_event', self.OnCanvasButtonReleased) |
305 self.mpl_connect('scroll_event', self.OnCanvasScroll) |
305 self.mpl_connect('scroll_event', self.OnCanvasScroll) |
306 |
306 |
307 # Add buttons for zooming on current displayed data range |
307 # Add buttons for zooming on current displayed data range |
308 self.Buttons.append( |
308 self.Buttons.append( |
309 GraphButton(0, 0, "fit_graph", self.OnZoomFitButton)) |
309 GraphButton(0, 0, "fit_graph", self.OnZoomFitButton)) |
310 |
310 |
311 # Add buttons for changing canvas size with predefined height |
311 # Add buttons for changing canvas size with predefined height |
312 for size, bitmap in zip( |
312 for size, bitmap in zip( |
313 [SIZE_MINI, SIZE_MIDDLE, SIZE_MAXI], |
313 [SIZE_MINI, SIZE_MIDDLE, SIZE_MAXI], |
314 ["minimize_graph", "middle_graph", "maximize_graph"]): |
314 ["minimize_graph", "middle_graph", "maximize_graph"]): |
315 self.Buttons.append( |
315 self.Buttons.append(GraphButton(0, 0, bitmap, |
316 GraphButton(0, 0, bitmap, |
316 self.GetOnChangeSizeButton(size))) |
317 self.GetOnChangeSizeButton(size))) |
|
318 |
317 |
319 # Add buttons for exporting graph values to clipboard and close graph |
318 # Add buttons for exporting graph values to clipboard and close graph |
320 for bitmap, callback in [ |
319 for bitmap, callback in [ |
321 ("export_graph_mini", self.OnExportGraphButton), |
320 ("export_graph_mini", self.OnExportGraphButton), |
322 ("delete_graph", self.OnCloseButton)]: |
321 ("delete_graph", self.OnCloseButton)]: |
428 # Add other buttons to contextual menu |
427 # Add other buttons to contextual menu |
429 for bitmap, callback in [ |
428 for bitmap, callback in [ |
430 ("force", self.OnForceItemButton), |
429 ("force", self.OnForceItemButton), |
431 ("export_graph_mini", self.OnExportItemGraphButton), |
430 ("export_graph_mini", self.OnExportItemGraphButton), |
432 ("delete_graph", self.OnRemoveItemButton)]: |
431 ("delete_graph", self.OnRemoveItemButton)]: |
433 self.ContextualButtons.append( |
432 self.ContextualButtons.append(GraphButton(0, 0, bitmap, callback)) |
434 GraphButton(0, 0, bitmap, callback)) |
|
435 |
433 |
436 # If buttons are shown at left side or upper side of rect, positions |
434 # If buttons are shown at left side or upper side of rect, positions |
437 # will be set in reverse order |
435 # will be set in reverse order |
438 buttons = self.ContextualButtons[:] |
436 buttons = self.ContextualButtons[:] |
439 if direction in [wx.TOP, wx.LEFT]: |
437 if direction in [wx.TOP, wx.LEFT]: |
596 |
594 |
597 # Search for point that tick is the nearest from mouse X position |
595 # Search for point that tick is the nearest from mouse X position |
598 # and set cursor tick to the tick of this point |
596 # and set cursor tick to the tick of this point |
599 if len(data) > 0: |
597 if len(data) > 0: |
600 cursor_tick = data[numpy.argmin( |
598 cursor_tick = data[numpy.argmin( |
601 numpy.abs(data[:, 0] - event.xdata)), 0] |
599 numpy.abs(data[:, 0] - event.xdata)), 0] |
602 |
600 |
603 # Update cursor tick |
601 # Update cursor tick |
604 if cursor_tick is not None: |
602 if cursor_tick is not None: |
605 self.ParentWindow.SetCursorTick(cursor_tick) |
603 self.ParentWindow.SetCursorTick(cursor_tick) |
606 |
604 |
1115 CANVAS_PADDING * graph_ratio + |
1113 CANVAS_PADDING * graph_ratio + |
1116 (num_item - idx - 1) * VALUE_LABEL_HEIGHT * graph_ratio)) |
1114 (num_item - idx - 1) * VALUE_LABEL_HEIGHT * graph_ratio)) |
1117 else: |
1115 else: |
1118 # X coordinate labels are in figure lower side |
1116 # X coordinate labels are in figure lower side |
1119 self.AxesLabels[0].set_position( |
1117 self.AxesLabels[0].set_position( |
1120 (0.1, CANVAS_PADDING * graph_ratio)) |
1118 (0.1, CANVAS_PADDING * graph_ratio)) |
1121 self.Labels[0].set_position( |
1119 self.Labels[0].set_position( |
1122 (0.95, CANVAS_PADDING * graph_ratio)) |
1120 (0.95, CANVAS_PADDING * graph_ratio)) |
1123 |
1121 |
1124 # Y coordinate labels are vertical and in figure left side |
1122 # Y coordinate labels are vertical and in figure left side |
1125 self.AxesLabels[1].set_position( |
1123 self.AxesLabels[1].set_position( |
1126 (0.05, 2 * CANVAS_PADDING * graph_ratio)) |
1124 (0.05, 2 * CANVAS_PADDING * graph_ratio)) |
1127 self.Labels[1].set_position( |
1125 self.Labels[1].set_position( |
1128 (0.05, 1.0 - CANVAS_PADDING * graph_ratio)) |
1126 (0.05, 1.0 - CANVAS_PADDING * graph_ratio)) |
1129 |
1127 |
1130 # Update subplots |
1128 # Update subplots |
1131 self.Figure.subplots_adjust() |
1129 self.Figure.subplots_adjust() |
1132 |
1130 |
1133 def RefreshViewer(self, refresh_graphics=True): |
1131 def RefreshViewer(self, refresh_graphics=True): |
1147 ranges = [] |
1145 ranges = [] |
1148 |
1146 |
1149 # Get data and range for each variable displayed |
1147 # Get data and range for each variable displayed |
1150 for idx, item in enumerate(self.Items): |
1148 for idx, item in enumerate(self.Items): |
1151 data, min_value, max_value = item.GetDataAndValueRange( |
1149 data, min_value, max_value = item.GetDataAndValueRange( |
1152 start_tick, end_tick, not self.ZoomFit) |
1150 start_tick, end_tick, not self.ZoomFit) |
1153 |
1151 |
1154 # Check that data is not empty |
1152 # Check that data is not empty |
1155 if data is not None: |
1153 if data is not None: |
1156 # Add variable range to list of variable data range |
1154 # Add variable range to list of variable data range |
1157 ranges.append((min_value, max_value)) |
1155 ranges.append((min_value, max_value)) |
1197 end_tick = max(end_tick, start_tick) |
1195 end_tick = max(end_tick, start_tick) |
1198 items = self.ItemsDict.values() |
1196 items = self.ItemsDict.values() |
1199 |
1197 |
1200 # Get data and range for first variable (X coordinate) |
1198 # Get data and range for first variable (X coordinate) |
1201 x_data, x_min, x_max = items[0].GetDataAndValueRange( |
1199 x_data, x_min, x_max = items[0].GetDataAndValueRange( |
1202 start_tick, end_tick, not self.ZoomFit) |
1200 start_tick, end_tick, not self.ZoomFit) |
|
1201 |
1203 # Get data and range for second variable (Y coordinate) |
1202 # Get data and range for second variable (Y coordinate) |
1204 y_data, y_min, y_max = items[1].GetDataAndValueRange( |
1203 y_data, y_min, y_max = items[1].GetDataAndValueRange( |
1205 start_tick, end_tick, not self.ZoomFit) |
1204 start_tick, end_tick, not self.ZoomFit) |
1206 |
1205 |
1207 # Normalize X and Y coordinates value range |
1206 # Normalize X and Y coordinates value range |
1208 x_min, x_max = merge_ranges([(x_min, x_max)]) |
1207 x_min, x_max = merge_ranges([(x_min, x_max)]) |
1209 y_min, y_max = merge_ranges([(y_min, y_max)]) |
1208 y_min, y_max = merge_ranges([(y_min, y_max)]) |
1210 |
1209 |
1211 # Get X and Y coordinates for cursor if cursor tick is defined |
1210 # Get X and Y coordinates for cursor if cursor tick is defined |
1212 if self.CursorTick is not None: |
1211 if self.CursorTick is not None: |
1213 x_cursor, _x_forced = items[0].GetValue( |
1212 x_cursor, _x_forced = items[0].GetValue( |
1214 self.CursorTick, raw=True) |
1213 self.CursorTick, raw=True) |
1215 y_cursor, _y_forced = items[1].GetValue( |
1214 y_cursor, _y_forced = items[1].GetValue( |
1216 self.CursorTick, raw=True) |
1215 self.CursorTick, raw=True) |
1217 |
1216 |
1218 # Get common data length so that each value has an x and y |
1217 # Get common data length so that each value has an x and y |
1219 # coordinate |
1218 # coordinate |
1220 length = (min(len(x_data), len(y_data)) |
1219 length = (min(len(x_data), len(y_data)) |
1221 if x_data is not None and y_data is not None |
1220 if x_data is not None and y_data is not None |
1279 while len(self.Axes.lines) > 0: |
1278 while len(self.Axes.lines) > 0: |
1280 self.Axes.lines.pop() |
1279 self.Axes.lines.pop() |
1281 |
1280 |
1282 # Get data and range for third variable (Z coordinate) |
1281 # Get data and range for third variable (Z coordinate) |
1283 z_data, z_min, z_max = items[2].GetDataAndValueRange( |
1282 z_data, z_min, z_max = items[2].GetDataAndValueRange( |
1284 start_tick, end_tick, not self.ZoomFit) |
1283 start_tick, end_tick, not self.ZoomFit) |
1285 |
1284 |
1286 # Normalize Z coordinate value range |
1285 # Normalize Z coordinate value range |
1287 z_min, z_max = merge_ranges([(z_min, z_max)]) |
1286 z_min, z_max = merge_ranges([(z_min, z_max)]) |
1288 |
1287 |
1289 # Check that x, y and z data are not empty |
1288 # Check that x, y and z data are not empty |
1305 if self.CursorTick is not None and \ |
1304 if self.CursorTick is not None and \ |
1306 start_tick <= self.CursorTick <= end_tick: |
1305 start_tick <= self.CursorTick <= end_tick: |
1307 |
1306 |
1308 # Get Z coordinate for cursor |
1307 # Get Z coordinate for cursor |
1309 z_cursor, _z_forced = items[2].GetValue( |
1308 z_cursor, _z_forced = items[2].GetValue( |
1310 self.CursorTick, raw=True) |
1309 self.CursorTick, raw=True) |
1311 |
1310 |
1312 # Add 3 lines parallel to x, y and z axis to display |
1311 # Add 3 lines parallel to x, y and z axis to display |
1313 # cursor position in 3D |
1312 # cursor position in 3D |
1314 for kwargs in [{"xs": numpy.array([x_min, x_max])}, |
1313 for kwargs in [{"xs": numpy.array([x_min, x_max])}, |
1315 {"ys": numpy.array([y_min, y_max])}, |
1314 {"ys": numpy.array([y_min, y_max])}, |
1330 self.Axes.set_ylim(y_min, y_max) |
1329 self.Axes.set_ylim(y_min, y_max) |
1331 |
1330 |
1332 # Get value and forced flag for each variable displayed in graph |
1331 # Get value and forced flag for each variable displayed in graph |
1333 # If cursor tick is not defined get value and flag of last received |
1332 # If cursor tick is not defined get value and flag of last received |
1334 # or get value and flag of variable at cursor tick |
1333 # or get value and flag of variable at cursor tick |
1335 values, forced = apply(zip, [ |
1334 values, forced = apply(zip, [( |
1336 (item.GetValue(self.CursorTick) |
1335 item.GetValue(self.CursorTick) |
1337 if self.CursorTick is not None |
1336 if self.CursorTick is not None |
1338 else (item.GetValue(), item.IsForced())) |
1337 else (item.GetValue(), item.IsForced()) |
1339 for item in self.Items]) |
1338 ) for item in self.Items]) |
1340 |
1339 |
1341 # Get path of each variable displayed simplified using panel variable |
1340 # Get path of each variable displayed simplified using panel variable |
1342 # name mask |
1341 # name mask |
1343 labels = [item.GetVariable(self.ParentWindow.GetVariableNameMask()) |
1342 labels = [item.GetVariable(self.ParentWindow.GetVariableNameMask()) |
1344 for item in self.Items] |
1343 for item in self.Items] |