          logger.debug("Getting loss: (session_id: %s)", session_id)
          retval = {}
          for idx in [session_id] if session_id else self.session_ids:
              self._check_cache(idx)
              data = self._cache.get_data(idx, "loss")
              if not data:
                  continue
              data = data[idx]
              retval[idx] = {title: data["loss"][:, idx] for idx, title in enumerate(data["labels"])}
          logger.debug({key: {k: v.shape for k, v in val.items()}
                        for key, val in retval.items()})
 
</s> remove             data = data[idx]
            retval[idx] = {title: data["loss"][:, idx] for idx, title in enumerate(data["labels"])}
 </s> add             data = full_data[idx]
            loss = data["loss"]
            assert isinstance(loss, np.ndarray)
            retval[idx] = {title: loss[:, idx] for idx, title in enumerate(data["labels"])}
 </s> remove         retval = {}
 </s> add         retval: Dict[int, Dict[str, np.ndarray]] = {} </s> remove                 val["labels"] = data["labels"]
 </s> add                 val["labels"] = data.labels </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]]]] = {}
            full_data = self._cache.get_data(idx, "loss")
            if not full_data:
          logger.debug("Getting loss: (session_id: %s)", session_id)
          retval = {}
          for idx in [session_id] if session_id else self.session_ids:
              self._check_cache(idx)
            full_data = self._cache.get_data(idx, "loss")
            if not full_data:
            full_data = self._cache.get_data(idx, "loss")
            if not full_data:
                  continue
              data = data[idx]
              retval[idx] = {title: data["loss"][:, idx] for idx, title in enumerate(data["labels"])}
          logger.debug({key: {k: v.shape for k, v in val.items()}
                        for key, val in retval.items()})
keep keep keep keep 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