class_docstr: Light wrapper around Lightning's ModelCheckpoint to force a saved checkpoint on train_end.
  Extends Lightning's on_save_checkpoint func to save the .nemo file. Saves the .nemo file based 
  on the best checkpoint saved (according to the monitor value).
  Also contains func to save the EMA copy of the model.
code: def nemo_topk_check_previous_run(self):
      try:
          self.best_k_models
          self.kth_best_model_path
          self.best_model_score
          self.best_model_path
      except AttributeError:
          raise AttributeError(
              "Lightning's ModelCheckpoint was updated. NeMoModelCheckpoint will need an update."
          )
      self.best_k_models = {}
      self.kth_best_model_path = ""
      self.best_model_score = None
      self.best_model_path = ""
  
      checkpoints = list(
          path
          for path in self._saved_checkpoint_paths
          if not self._is_ema_filepath(path)
      )
      for checkpoint in checkpoints:
          if "mp_rank" in str(checkpoint) or "tp_rank" in str(
              checkpoint
          ):
              checkpoint = uninject_model_parallel_rank(checkpoint)
          checkpoint = str(checkpoint)
          # second case is for distributed checkpoints, since they are a directory there's no extension
          if (
              checkpoint[-10:] == "-last.ckpt"
              or checkpoint[-5:] == "-last"
          ):
              continue
          index = (
              checkpoint.find(self.monitor) + len(self.monitor) + 1
          )  # Find monitor in str + 1 for '='
          if index != len(self.monitor):
              match = re.search("[A-z]", checkpoint[index:])
              if match:
                  value = checkpoint[
                      index : index + match.start() - 1
                  ]  # -1 due to separator hypen
                  self.best_k_models[checkpoint] = float(value)
      if len(self.best_k_models) < 1:
          return  # No saved checkpoints yet
  
      _reverse = False if self.mode == "min" else True
  
      best_k_models = sorted(
          self.best_k_models,
          key=self.best_k_models.get,
          reverse=_reverse,
      )
  
      # This section should be ok as rank zero will delete all excess checkpoints, since all other ranks are
      # instantiated after rank zero. models_to_delete should be 0 for all other ranks.
      if self.model_parallel_size is not None:
          # check for distributed checkpoint
          if checkpoints[0].is_dir():
              models_to_delete = len(best_k_models) - self.save_top_k
          else:
              models_to_delete = (
                  len(best_k_models)
                  - self.model_parallel_size * self.save_top_k
              )
      else:
          models_to_delete = len(best_k_models) - self.save_top_k
  
      models_to_delete = max(0, models_to_delete)
      logging.debug(f"Number of models to delete: {models_to_delete}")
  
      # If EMA enabled, delete the additional EMA weights
      ema_enabled = self._has_ema_ckpts(self._saved_checkpoint_paths)
  
      for _ in range(models_to_delete):
          model = best_k_models.pop(-1)
          self.best_k_models.pop(model)
          self._del_model_without_trainer(model)
          if ema_enabled and self._fs.exists(
              self._ema_format_filepath(model)
          ):
              self._del_model_without_trainer(
                  self._ema_format_filepath(model)
              )
          logging.debug(f"Removed checkpoint: {model}")
  
      self.kth_best_model_path = best_k_models[-1]
      self.best_model_path = best_k_models[0]
      self.best_model_score = self.best_k_models[self.best_model_path]
  
imports: import os
  import re
  import shutil
  from copy import deepcopy
  from pathlib import Path
  from typing import Any, Dict, Iterable, List, Optional, Tuple, Union
  import pytorch_lightning
  import torch
  from pytorch_lightning.callbacks import ModelCheckpoint
  from pytorch_lightning.utilities import rank_zero_info
  from nemo.collections.common.callbacks import EMA
  from nemo.utils import logging
  from nemo.utils.app_state import AppState
  from nemo.utils.get_rank import is_global_rank_zero
  from nemo.utils.model_utils import ckpt_to_dir, inject_model_parallel_rank, uninject_model_parallel_rank
label_desc: Use image node_id 2 for calling the NeMoModelCheckpoint obj's underlying member method code with example usage: obj.nemo_topk_check_previous_run() without return types