diff --git a/pydm/widgets/archiver_time_plot.py b/pydm/widgets/archiver_time_plot.py index fdce32c38..eae4265a5 100644 --- a/pydm/widgets/archiver_time_plot.py +++ b/pydm/widgets/archiver_time_plot.py @@ -770,6 +770,8 @@ def __init__( init_y_channels: List[str] = [], background: str = "default", optimized_data_bins: int = 2000, + cache_data: bool = True, + show_all: bool = True, ): super(PyDMArchiverTimePlot, self).__init__( parent=parent, @@ -779,21 +781,42 @@ def __init__( bottom_axis=DateAxisItem("bottom"), ) self.optimized_data_bins = optimized_data_bins + self._show_all = False # Show all plotted data after archiver fetch + # self._show_all = show_all # Show all plotted data after archiver fetch self._starting_timestamp = time.time() # The timestamp at which the plot was first rendered self._min_x = self._starting_timestamp - DEFAULT_TIME_SPAN self._prev_x = self._min_x # Holds the minimum x-value of the previous update of the plot self._archive_request_queued = False self.setTimeSpan(DEFAULT_TIME_SPAN) - def updateXAxis(self, update_immediately: bool = False) -> None: + self.cache_data = False + # self.cache_data = cache_data + + @property + def cache_data(self): + return self._cache_data + + @cache_data.setter + def cache_data(self, retain: bool): + self._cache_data = retain + if retain: + try: + self.plotItem.sigXRangeChanged.disconnect(self.updateXAxis) + self.plotItem.sigXRangeChangedManually.disconnect(self.updateXAxis) + except TypeError: + pass + else: + self.plotItem.sigXRangeChanged.connect(self.updateXAxis) + self.plotItem.sigXRangeChangedManually.connect(self.updateXAxis) + + def updateXAxis(self, update_immediately: bool = False, *_) -> None: """Manages the requests to archiver appliance. When the user pans or zooms the x axis to the left, a request will be made for backfill data""" - if len(self._curves) == 0 or self.auto_scroll_timer.isActive(): + if len(self._curves) == 0: return min_x = self.plotItem.getAxis("bottom").range[0] # Gets the leftmost timestamp displayed on the x-axis max_x = self.plotItem.getAxis("bottom").range[1] - max_point = max([curve.max_x() for curve in self._curves]) if min_x == 0: # This is zero when the plot first renders self._max_x = time.time() self._min_x = self._max_x - DEFAULT_TIME_SPAN @@ -803,30 +826,40 @@ def updateXAxis(self, update_immediately: bool = False) -> None: self._min_x = self._min_x - self.getTimeSpan() self._archive_request_queued = True self.requestDataFromArchiver() - self.plotItem.setXRange( - time.time() - DEFAULT_TIME_SPAN, time.time(), padding=0.0, update=update_immediately - ) - elif min_x < self._min_x and not self.plotItem.isAnyXAutoRange(): - # This means the user has manually scrolled to the left, so request archived data - self._min_x = min_x - self.setTimeSpan(max_point - min_x) - if not self._archive_request_queued: - # Letting the user pan or scroll the plot is convenient, but can generate a lot of events in under - # a second that would trigger a request for data. By using a timer, we avoid this burst of events - # and consolidate what would be many requests to archiver into just one. - self._archive_request_queued = True - QTimer.singleShot(1000, self.requestDataFromArchiver) - # 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 max_x >= max_point - 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 + blocked = self.plotItem.blockSignals(True) + self.plotItem.setXRange(time.time() - DEFAULT_TIME_SPAN, time.time(), padding=0.0) + self.plotItem.blockSignals(blocked) + elif not self._cache_data: + if min_x != self._min_x or max_x != self._max_x: + # The timerange of the x-axis changed; user wants only archive data for the new range + self._min_x = min_x + self._max_x = max_x + self.setTimeSpan(max_x - min_x) + if not self._archive_request_queued: + self._archive_request_queued = True + QTimer.singleShot(1000, self.requestDataFromArchiver) + elif not self.plotItem.isAnyXAutoRange(): + max_point = max([curve.max_x() for curve in self._curves]) + if min_x < self._min_x: + # User has manually scrolled to the left, so request archived data + self._min_x = min_x self.setTimeSpan(max_point - min_x) - else: - # Keep the plot moving with a rolling window based on the current timestamp - self.plotItem.setXRange( - max_point - self.getTimeSpan(), max_point, padding=0.0, update=update_immediately - ) + if not self._archive_request_queued: + self._archive_request_queued = True + QTimer.singleShot(1000, self.requestDataFromArchiver) + elif max_x >= max_point - 10: + # Only update the x-axis if autorange is disabled and user hasn't zoomed in + 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_point - min_x) + else: + # Keep the plot moving with a rolling window based on the current timestamp + blocked = self.plotItem.blockSignals(True) + self.plotItem.setXRange( + max_point - self.getTimeSpan(), max_point, padding=0.0, update=update_immediately + ) + self.plotItem.blockSignals(blocked) + self._prev_x = min_x def requestDataFromArchiver(self, min_x: Optional[float] = None, max_x: Optional[float] = None) -> None: @@ -851,8 +884,10 @@ def requestDataFromArchiver(self, min_x: Optional[float] = None, max_x: Optional if curve.use_archive_data: if max_x is None: max_x = curve.min_x() + if not self._cache_data: + max_x = min(max_x, self._max_x) requested_seconds = max_x - min_x - if requested_seconds <= 5: + if requested_seconds <= MIN_TIME_SPAN: continue # Avoids noisy requests when first rendering the plot # Max amount of raw data to return before using optimized data max_data_request = int(0.80 * self.getArchiveBufferSize()) @@ -903,7 +938,7 @@ def createCurveItem(self, *args, **kwargs) -> ArchivePlotCurveItem: def archive_data_received(self): """Take any action needed when this plot receives new data from archiver appliance""" self._archive_request_queued = False - if self.auto_scroll_timer.isActive(): + if self.auto_scroll_timer.isActive() or not self._show_all: return max_x = max([curve.max_x() for curve in self._curves])