                       session_id, loss.shape, timestamps.shape)
          if not np.any(loss) and not np.any(timestamps):
              return
  
          cache = self._data[session_id]
          for metric in ("loss", "timestamps"):
              data = locals()[metric]
              dtype = "float32" if metric == "loss" else "float64"
  
              old = np.frombuffer(zlib.decompress(cache[metric]), dtype=dtype)
              if data.ndim > 1:
                  old = old.reshape(-1, *data.shape[1:])
  
              new = np.concatenate((old, data))
  
              logger.debug("'%s' old_shape: %s new_shape: %s",
                           metric, cache[f"{metric}_shape"], new.shape)
              cache[f"{metric}_shape"] = new.shape
              cache[metric] = zlib.compress(new)
  
              del old
  
      def get_data(self, session_id, metric):
          """ Retrieve the decompressed cached data from the cache for the given session id.
 
</s> remove             del old

    def get_data(self, session_id, metric):
 </s> add     def get_data(self, session_id: int, metric: Literal["loss", "timestamps"]
                 ) -> Optional[Dict[int, Dict[str, Union[np.ndarray, List[str]]]]]: </s> remove             buff = np.frombuffer(zlib.decompress(data[metric]), dtype=dtype)
            shape = data[f"{metric}_shape"]
            if len(shape) > 1:
                buff = buff.reshape(-1, *shape[1:])
            val = {metric: buff}
 </s> add             array = data.loss if metric == "loss" else data.timestamps
            val: Dict[str, Union[np.ndarray, List[str]]] = {str(metric): array} </s> remove         dtype = "float32" if metric == "loss" else "float64"

        retval = {}
 </s> add         retval: Dict[int, Dict[str, Union[np.ndarray, List[str]]]] = {} </s> remove     def __init__(self, session_ids):
        logger.debug("Initializing: %s: (session_ids: %s)", self.__class__.__name__, session_ids)
        self._data = {idx: None for idx in session_ids}
        self._carry_over = {}
        self._loss_labels = []
 </s> add     def __init__(self, labels: List[str], timestamps: np.ndarray, loss: np.ndarray) -> None:
        self.labels = labels
        self._loss = zlib.compress(cast(bytes, loss))
        self._timestamps = zlib.compress(cast(bytes, timestamps))
        self._timestamps_shape = timestamps.shape
        self._loss_shape = loss.shape

    @property
    def loss(self) -> np.ndarray:
        """ :class:`numpy.ndarray`: The loss values for this session """
        retval: np.ndarray = np.frombuffer(zlib.decompress(self._loss), dtype="float32")
        if len(self._loss_shape) > 1:
            retval = retval.reshape(-1, *self._loss_shape[1:])
        return retval

    @property
    def timestamps(self) -> np.ndarray:
        """ :class:`numpy.ndarray`: The timestamps for this session """
        retval: np.ndarray = np.frombuffer(zlib.decompress(self._timestamps), dtype="float64")
        if len(self._timestamps_shape) > 1:
            retval = retval.reshape(-1, *self._timestamps_shape[1:])
        return retval

    def add_live_data(self, timestamps: np.ndarray, loss: np.ndarray) -> None:
        """ Add live data to the end of the stored data

        loss: :class:`numpy.ndarray`
            The latest loss values to add to the cache
        timestamps: :class:`numpy.ndarray`
            The latest timestamps  to add to the cache
        """
        new_buffer: List[bytes] = []
        new_shapes: List[Tuple[int, ...]] = []
        for data, buffer, dtype, shape in zip([timestamps, loss],
                                              [self._timestamps, self._loss],
                                              ["float64", "float32"],
                                              [self._timestamps_shape, self._loss_shape]):

            old = np.frombuffer(zlib.decompress(buffer), dtype=dtype)
            if data.ndim > 1:
                old = old.reshape(-1, *data.shape[1:])

            new = np.concatenate((old, data))

            logger.debug("old_shape: %s new_shape: %s", shape, new.shape)
            new_buffer.append(zlib.compress(new))
            new_shapes.append(new.shape)
            del old

        self._timestamps = new_buffer[0]
        self._loss = new_buffer[1]
        self._timestamps_shape = new_shapes[0]
        self._loss_shape = new_shapes[1]


class _Cache():
    """ Holds parsed Tensorflow log event data in a compressed cache in memory. """
    def __init__(self) -> None:
        logger.debug("Initializing: %s", self.__class__.__name__)
        self._data: Dict[int, _CacheData] = {}
        self._carry_over: Dict[int, EventData] = {}
        self._loss_labels: List[str] = [] </s> remove                 val["labels"] = data["labels"]
 </s> add                 val["labels"] = data.labels
        self._data[session_id].add_live_data(timestamps, loss)
                       session_id, loss.shape, timestamps.shape)
          if not np.any(loss) and not np.any(timestamps):
              return
  
        self._data[session_id].add_live_data(timestamps, loss)
        self._data[session_id].add_live_data(timestamps, loss)
        self._data[session_id].add_live_data(timestamps, loss)
        self._data[session_id].add_live_data(timestamps, loss)
        self._data[session_id].add_live_data(timestamps, loss)
        self._data[session_id].add_live_data(timestamps, loss)
        self._data[session_id].add_live_data(timestamps, loss)
        self._data[session_id].add_live_data(timestamps, loss)
        self._data[session_id].add_live_data(timestamps, loss)
        self._data[session_id].add_live_data(timestamps, loss)
        self._data[session_id].add_live_data(timestamps, loss)
        self._data[session_id].add_live_data(timestamps, loss)
        self._data[session_id].add_live_data(timestamps, loss)
        self._data[session_id].add_live_data(timestamps, loss)
        self._data[session_id].add_live_data(timestamps, loss)
  
              del old
  
      def get_data(self, session_id, metric):
          """ Retrieve the decompressed cached data from the cache for the given session id.
keep keep keep keep replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace keep keep keep keep keep
 Bugfixes
  - plugin.train.unbalanced - decoder b
  - gui.stats - crash when log folder deleted
  - setup.py - install gcc=12.1.0 on linux (scipy dep)
  - setup.py - don't test ROCm unless valid
  - typofix - cli_args extract singleprocess help
typing
  - lib.gui.analysis.event_reader
  - lib.gpu_stats.directml - make platform specific
unit tests
  - lib.gui.analysis.event_reader 
lib/gui/analysis/event_reader.py