Skip to content

Commit

Permalink
Merge pull request #819 from jbellister-slac/fix_archiver_plot_scroll
Browse files Browse the repository at this point in the history
FIX: Don't keep the rolling window moving when zooming in on archiver plots
  • Loading branch information
YektaY authored Apr 6, 2022
2 parents 9564906 + f6e089a commit d110bcd
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 13 deletions.
3 changes: 0 additions & 3 deletions pydm/tests/widgets/test_archiver_timeplot.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,6 @@ def test_request_data_from_archiver(qtbot):
plot.requestDataFromArchiver(100, 200)

# Verify that the data is requested for the time period specified, and since it is only 100 seconds, it is raw data
assert not plot._archive_request_queued # Request is completed, so this should be false now
assert inspect_data_request.min_x == 100
assert inspect_data_request.max_x == 199
assert inspect_data_request.processing_command == ''
Expand All @@ -138,7 +137,6 @@ def test_request_data_from_archiver(qtbot):
# returned in 10 bins as specified by the "optimized_data_bins" param above
plot._archive_request_queued = True
plot.requestDataFromArchiver(100, 100000)
assert not plot._archive_request_queued
assert inspect_data_request.min_x == 100
assert inspect_data_request.max_x == 99999
assert inspect_data_request.processing_command == 'optimized_10'
Expand All @@ -155,7 +153,6 @@ def test_request_data_from_archiver(qtbot):
plot._min_x = 50 # This is the minimum timestamp visible on the x-axis, representing what the user panned to
plot._archive_request_queued = True
plot.requestDataFromArchiver()
assert not plot._archive_request_queued
# The min_x requested should have defaulted to 50 since that is what the user requested as mentioned above
assert inspect_data_request.min_x == 50
# Because the oldest live timestamp in the data buffer was 300, the ending timestamp for the request should
Expand Down
36 changes: 26 additions & 10 deletions pydm/widgets/archiver_time_plot.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,11 +89,12 @@ def receiveArchiveData(self, data: np.ndarray) -> None:
archive_data_length = len(data[0])
max_x = data[0][archive_data_length-1]

while max_x > self.data_buffer[0][-self.points_accumulated]:
# Sometimes optimized queries return data past the current timestamp, this will delete those data points
data = np.delete(data, len(data[0]) - 1, axis=1)
archive_data_length -= 1
max_x = data[0][archive_data_length-1]
if self.points_accumulated != 0:
while max_x > self.data_buffer[0][-self.points_accumulated]:
# Sometimes optimized queries return data past the current timestamp, this will delete those data points
data = np.delete(data, len(data[0]) - 1, axis=1)
archive_data_length -= 1
max_x = data[0][archive_data_length-1]

self.archive_data_buffer[0, len(self.archive_data_buffer[0]) - archive_data_length:] = data[0]
self.archive_data_buffer[1, len(self.archive_data_buffer[0]) - archive_data_length:] = data[1]
Expand Down Expand Up @@ -232,13 +233,15 @@ def updateXAxis(self, update_immediately: bool = False) -> None:

min_x = self.plotItem.getAxis('bottom').range[0] # Gets the leftmost timestamp displayed on the x-axis
max_x = max([curve.max_x() for curve in self._curves])
max_range = self.plotItem.getAxis('bottom').range[1]
if min_x == 0: # This is zero when the plot first renders
min_x = time.time()
self._min_x = min_x
self._starting_timestamp = min_x - 60
self._starting_timestamp = min_x - DEFAULT_TIME_SPAN # A bit of a buffer so we don't overwrite live data
if self.getTimeSpan() != DEFAULT_TIME_SPAN:
# Initialize x-axis based on the time span as well as trigger a call to the archiver below
self._min_x = self._min_x - self.getTimeSpan()
self._archive_request_queued = True
self.requestDataFromArchiver()
self.plotItem.setXRange(self._min_x, time.time(), padding=0.0, update=update_immediately)
elif min_x < self._min_x and not self.plotItem.isAnyXAutoRange():
Expand All @@ -251,7 +254,9 @@ def updateXAxis(self, update_immediately: bool = False) -> None:
# and consolidate what would be many requests to archiver into just one.
self._archive_request_queued = True
QTimer.singleShot(1000, self.requestDataFromArchiver)
elif not self.plotItem.isAnyXAutoRange(): # Only update the x-axis if the user hasn't asked for autorange
# Here we only update the x-axis if the user hasn't asked for autorange and they haven't zoomed in (as
# detected by the max range showing on the plot being less than the data available)
elif not self.plotItem.isAnyXAutoRange() and not max_range < max_x - 10:
if min_x > (self._prev_x + 15) or min_x < (self._prev_x - 15):
# The plus/minus 15 just makes sure we don't do this on every update tick of the graph
self.setTimeSpan(max_x - min_x)
Expand Down Expand Up @@ -292,7 +297,6 @@ def requestDataFromArchiver(self, min_x: Optional[float] = None, max_x: Optional
if requested_seconds > max_data_request:
processing_command = 'optimized_' + str(self.optimized_data_bins)
curve.archive_data_request_signal.emit(min_x, max_x - 1, processing_command)
self._archive_request_queued = False

def getArchiveBufferSize(self) -> int:
""" Returns the size of the data buffer used to store archived data """
Expand All @@ -303,11 +307,23 @@ def getArchiveBufferSize(self) -> int:
def createCurveItem(self, y_channel: str, plot_by_timestamps: bool, name: str, color: Union[QColor, str],
yAxisName: str, useArchiveData: bool, **plot_opts) -> ArchivePlotCurveItem:
""" Create and return a curve item to be plotted """
return ArchivePlotCurveItem(y_channel, use_archive_data=useArchiveData, plot_by_timestamps=plot_by_timestamps,
name=name, color=color, yAxisName=yAxisName, **plot_opts)
curve_item = ArchivePlotCurveItem(y_channel, use_archive_data=useArchiveData, plot_by_timestamps=plot_by_timestamps,
name=name, color=color, yAxisName=yAxisName, **plot_opts)
curve_item.archive_data_received_signal.connect(self.archive_data_received)
return curve_item

@Slot()
def archive_data_received(self):
""" Take any action needed when this plot receives new data from archiver appliance """
max_x = max([curve.max_x() for curve in self._curves])
# Assure the user sees all data available whenever the request data is returned
self.plotItem.setXRange(max_x - self.getTimeSpan(), max_x, padding=0.0, update=True)
self._archive_request_queued = False

def setTimeSpan(self, value):
""" Set the value of the plot's timespan """
if value < DEFAULT_TIME_SPAN: # Less than 5 seconds will break the plot
return
self._time_span = value

def getCurves(self) -> List[str]:
Expand Down

0 comments on commit d110bcd

Please sign in to comment.