          self._samples.toggle_mask_display()
  
      def train_one_step(self,
                         viewer: Optional[Callable[[np.ndarray, str], None]],
                         timelapse_kwargs: Optional[Dict[str, str]]) -> None:
          """ Running training on a batch of images for each side.
  
          Triggered from the training cycle in :class:`scripts.train.Train`.
  
          * Runs a training batch through the model.
 
</s> remove                         timelapse_kwargs: Optional[Dict[str, str]]) -> None:
 </s> add                         timelapse_kwargs: Optional[Dict[Literal["input_a",
                                                                "input_b",
                                                                "output"], str]]) -> None: </s> remove     def request_refresh(self) -> None:
        """ Handle a GUI trigger or a training thread trigger (after a mask toggle) request to set
        the refresh trigger to ``True`` to request a refresh on the next pass of the
        training loop. """
        with self._lock:
            self._triggers["refresh"] = True

    def request_mask_toggle(self) -> None:
        """ Handle a GUI trigger request to set the mask toggle to ``True`` to
        request a mask toggle on next pass of the training loop. """
        logger.verbose("Toggle mask display requested...")  # type:ignore
        with self._lock:
            self._triggers["toggle_mask"] = True

    def add_image(self, name: str, image: np.ndarray) -> None:
        """ Add a preview image to the preview buffer.

        Parameters
        ----------
        name: str
            The name of the preview image to add to the buffer
        image: :class:`numpy.ndarray`
            The preview image to add to the buffer in BGR format.
        """
        with self._lock:
            logger.debug("Adding image '%s' of shape %s to preview buffer", name, image.shape)
            self._preview_buffer[name] = image[..., 2::-1]  # Switch to RGB
            self._needs_update = True

    def display_preview(self) -> None:
        """ Display an image preview in a resizable window. """
        if self._needs_update:
            logger.debug("Updating preview")
            with self._lock:
                for name, image in self._preview_buffer.items():
                    if (name not in self._images or  # new preview or preview was closed
                            not plt.fignum_exists(self._images[name][0].number)):
                        self._create_resizable_window(name, image.shape)
                        if self._triggers["full_size"]:  # Can only be true if preview was closed
                            self._set_resize_callback()
                    plt.figure(name)
                    plt.imshow(image)
                self._needs_update = False
            plt.show(block=False)
            logger.debug("preview updated")  # type: ignore
        plt.pause(0.1)

    def _create_resizable_window(self, name: str, image_shape: tuple) -> None:
        """ Create a resizable Matplotlib window to hold the preview image.
 </s> add     def _launch_thread(self) -> Optional[FSThread]:
        """ Launch the preview viewer in it's own thread if preview has been selected </s> remove     def get_trainer(name: str, disable_logging: bool = False) -> "TrainerBase":
 </s> add     def get_trainer(name: str, disable_logging: bool = False) -> Type["TrainerBase"]: </s> remove class Preview():
    """ Holds the pop up preview window and options relating to the preview in the window and the
    GUI. Thread safe to take requests from the main thread and the training thread. """
    def __init__(self) -> None:
        self._lock = Lock()
        self._dpi: float = 0.0
        self._triggers: Dict[str, bool] = dict(toggle_mask=False,
                                               full_size=False,
                                               refresh=False,
                                               save=False,
                                               quit=False)
        self._needs_update: bool = False
        self._preview_buffer: Dict[str, np.ndarray] = {}
        self._images: Dict[str, Tuple[figure.Figure, Tuple[float, float]]] = {}
        self._resize_ids: List[Tuple[figure.Figure, int]] = []
        self._callbacks = dict(f="full_size",
                               m="toggle_mask",
                               r="refresh",
                               s="save",
                               enter="quit")
        self._configure_matplotlib()

    def _toggle_size(self) -> None:  # pylint:disable=unused-argument
        """ Toggle between actual size and screen-fit size. """
        self._triggers["full_size"] = not self._triggers["full_size"]
        self._set_resize_callback()

    @classmethod
    def _configure_matplotlib(cls):
        """ Remove `F`, 'S' and 'R' from their default bindings and stop Matplotlib from stealing
        focus """
        rcParams["keymap.fullscreen"] = [k for k in rcParams["keymap.fullscreen"] if k != "f"]
        rcParams["keymap.save"] = [k for k in rcParams["keymap.save"] if k != "s"]
        rcParams["keymap.home"] = [k for k in rcParams["keymap.home"] if k != "r"]
        rcParams["figure.raise_window"] = False
 </s> add class PreviewInterface():
    """ Run the preview window in a thread and interface with it </s> remove             self._setup(**timelapse_kwargs)
 </s> add             self._setup(**cast(Dict[str, str], timelapse_kwargs))
                       timelapse_kwargs: Optional[Dict[Literal["input_a",
                                                               "input_b",
                                                               "output"], str]]) -> None:
          self._samples.toggle_mask_display()
  
      def train_one_step(self,
                         viewer: Optional[Callable[[np.ndarray, str], None]],
                       timelapse_kwargs: Optional[Dict[Literal["input_a",
                                                               "input_b",
                                                               "output"], str]]) -> None:
          """ Running training on a batch of images for each side.
  
          Triggered from the training cycle in :class:`scripts.train.Train`.
  
          * Runs a training batch through the model.
keep keep keep keep replace keep keep keep keep keep
 Training - Use custom preview pop-out 
plugins/train/trainer/_base.py