class_docstr: Abstract interface for data aggregation functionality for plotly figures.
class_docstr_tok: ["Abstract","interface","for","data","aggregation","functionality","for","plotly","figures","."]
docstr: Check and update the passed ``trace`` its data properties based on the
  slice range.
  
  Note
  ----
  This is a pass by reference. The passed trace object will be updated and
  returned if found in ``hf_data``.
  
  Parameters
  ----------
  trace : BaseTraceType or dict
       - An instances of a trace class from the ``plotly.graph_objects`` (go)
          package (e.g, ``go.Scatter``, ``go.Bar``)
       - or a dict where:
  
            - The 'type' property specifies the trace type (e.g.
              'scatter', 'bar', 'area', etc.). If the dict has no 'type'
              property then 'scatter' is assumed.
            - All remaining properties are passed to the constructor
              of the specified trace type.
  
  start : Union[float, str], optional
      The start index for which we want resampled data to be updated to,
      by default None,
  end : Union[float, str], optional
      The end index for which we want the resampled data to be updated to,
      by default None
  
  Returns
  -------
  Optional[Union[dict, BaseTraceType]]
      If the matching ``hf_series`` is found in ``hf_dict``, an (updated) trace
      will be returned, otherwise None.
  
  Note
  ----
  * If ``start`` and ``stop`` are strings, they most likely represent time-strings
  * ``start`` and ``stop`` will always be of the same type (float / time-string)
     because their underlying axis is the same.
docstr_tok: ["Check","and","update","the","passed","``","trace","``","its","data","properties","based","on","the","slice","range",".","Note","--","--","This","is","a","pass","by","reference",".","The","passed","trace","object","will","be","updated","and","returned","if","found","in","``","hf_data","``",".","Parameters","--","--","--","--","--","trace",":","BaseTraceType","or","dict","-","An","instances","of","a","trace","class","from","the","``","plotly.graph_objects","``","(","go",")","package","(","e.g",",","``","go.Scatter","``",",","``","go.Bar","``",")","-","or","a","dict","where",":","-","The","'type","'","property","specifies","the","trace","type","(","e.g",".","'scatter","'",",","'bar","'",",","'area","'",",","etc.",")",".","If","the","dict","has","no","'type'","property","then","'scatter","'","is","assumed",".","-","All","remaining","properties","are","passed","to","the","constructor","of","the","specified","trace","type",".","start",":","Union","[","float",",","str","]",",","optional","The","start","index","for","which","we","want","resampled","data","to","be","updated","to",",","by","default","None",",","end",":","Union","[","float",",","str","]",",","optional","The","end","index","for","which","we","want","the","resampled","data","to","be","updated","to",",","by","default","None","Returns","--","--","--","-","Optional","[","Union","[","dict",",","BaseTraceType","]","]","If","the","matching","``","hf_series","``","is","found","in","``","hf_dict","``",",","an","(","updated",")","trace","will","be","returned",",","otherwise","None",".","Note","--","--","*","If","``","start","``","and","``","stop","``","are","strings",",","they","most","likely","represent","time-strings","*","``","start","``","and","``","stop","``","will","always","be","of","the","same","type","(","float","\/","time-string",")","because","their","underlying","axis","is","the","same","."]
code: def _check_update_trace_data(
      self,
      trace: dict,
      start: Optional[Union[str, float]] = None,
      end: Optional[Union[str, float]] = None,
  ) -> Optional[Union[dict, BaseTraceType]]:
      """Check and update the passed ``trace`` its data properties based on the
      slice range.
  
      Note
      ----
      This is a pass by reference. The passed trace object will be updated and
      returned if found in ``hf_data``.
  
      Parameters
      ----------
      trace : BaseTraceType or dict
           - An instances of a trace class from the ``plotly.graph_objects`` (go)
              package (e.g, ``go.Scatter``, ``go.Bar``)
           - or a dict where:
  
                - The 'type' property specifies the trace type (e.g.
                  'scatter', 'bar', 'area', etc.). If the dict has no 'type'
                  property then 'scatter' is assumed.
                - All remaining properties are passed to the constructor
                  of the specified trace type.
  
      start : Union[float, str], optional
          The start index for which we want resampled data to be updated to,
          by default None,
      end : Union[float, str], optional
          The end index for which we want the resampled data to be updated to,
          by default None
  
      Returns
      -------
      Optional[Union[dict, BaseTraceType]]
          If the matching ``hf_series`` is found in ``hf_dict``, an (updated) trace
          will be returned, otherwise None.
  
      Note
      ----
      * If ``start`` and ``stop`` are strings, they most likely represent time-strings
      * ``start`` and ``stop`` will always be of the same type (float / time-string)
         because their underlying axis is the same.
  
      """
      hf_trace_data = self._query_hf_data(trace)
  
      if hf_trace_data is None:
          self._print("hf_data not found")
          return None
  
      # Parse trace data (necessary when updating the trace data)
      for k in _hf_data_container._fields:
          if isinstance(
              hf_trace_data[k],
              (np.ndarray, pd.RangeIndex, pd.DatetimeIndex),
          ):
              # is faster to escape the loop here than check inside the hasattr if
              continue
          elif pd.DatetimeTZDtype.is_dtype(hf_trace_data[k]):
              # When we use the .values method, timezone information is lost
              # so convert it to pd.DatetimeIndex, which preserves the tz-info
              hf_trace_data[k] = pd.Index(hf_trace_data[k])
          elif hasattr(hf_trace_data[k], "values"):
              # when not a range index or datetime index
              hf_trace_data[k] = hf_trace_data[k].values
  
      # Also check if the y-data is empty, if so, return an empty trace
      if len(hf_trace_data["y"]) == 0:
          trace["x"] = []
          trace["y"] = []
          trace["name"] = hf_trace_data["name"]
          return trace
  
      # Leverage the axis type to get the start and end indices
      # Note: the axis type specified in the figure layout takes precedence over the
      # the axis type which is inferred from the data (and stored in hf_trace_data)
      # TODO: verify if we need to use `axis`of anchor as key to determing axis type
      axis = trace.get("xaxis", "x")
      axis_type = self.layout._props.get(
          axis[:1] + "axis" + axis[1:], {}
      ).get("type", hf_trace_data["axis_type"])
      start_idx, end_idx = PlotlyAggregatorParser.get_start_end_indices(
          hf_trace_data, axis_type, start, end
      )
  
      # Return an invisible, single-point, trace when the sliced hf_series doesn't
      # contain any data in the current view
      if end_idx == start_idx:
          trace["x"] = [hf_trace_data["x"][0]]
          trace["y"] = [None]
          trace["name"] = hf_trace_data["name"]
          return trace
  
      agg_x, agg_y, indices = PlotlyAggregatorParser.aggregate(
          hf_trace_data, start_idx, end_idx
      )
  
      # -------------------- Set the hf_trace_data_props -------------------
      # Parse the data types to an orjson compatible format
      # NOTE: this can be removed once orjson supports f16
      trace["x"] = self._parse_dtype_orjson(agg_x)
      trace["y"] = self._parse_dtype_orjson(agg_y)
      trace["name"] = self._parse_trace_name(
          hf_trace_data, end_idx - start_idx, agg_x
      )
  
      def _nest_dict_rec(k: str, v: any, out: dict) -> None:
          """Recursively nest a dict based on the key whose '_' indicates level."""
          k, *rest = k.split("_", 1)
          if rest:
              _nest_dict_rec(rest[0], v, out.setdefault(k, {}))
          else:
              out[k] = v
  
      # Check if (hover)text also needs to be downsampled
      for k in [
          "text",
          "hovertext",
          "marker_size",
          "marker_color",
          "customdata",
      ]:
          k_val = hf_trace_data.get(k)
          if isinstance(k_val, (np.ndarray, pd.Series)):
              assert isinstance(
                  hf_trace_data["downsampler"], DataPointSelector
              ), "Only DataPointSelector can downsample non-data trace array props."
              _nest_dict_rec(k, k_val[start_idx + indices], trace)
          elif k_val is not None:
              trace[k] = k_val
  
      return trace
  
imports: from __future__ import annotations
  import itertools
  import re
  from abc import ABC
  from collections import namedtuple
  from copy import copy
  from typing import Dict, Iterable, List, Optional, Tuple, Union
  from uuid import uuid4
  import dash
  import numpy
  import pandas
  import plotly.graph_objects
  from pandas.io.json._normalize import nested_to_record
  from plotly.basedatatypes import BaseFigure, BaseTraceType
  from ..aggregation import AbstractAggregator, MedDiffGapHandler, MinMaxLTTB
  from ..aggregation.aggregation_interface import DataPointSelector
  from ..aggregation.gap_handler_interface import AbstractGapHandler
  from ..aggregation.plotly_aggregator_parser import PlotlyAggregatorParser
  from .utils import round_number_str, round_td_str
label_desc: Use image node_id 6 for calling the AbstractFigureAggregator obj's underlying member method code with example usage: obj._check_update_trace_data(trace, start, end) and returns: trace, None, trace, trace