              the keys being `input_a`, `input_b`, `output`
          """
          logger.debug("Ouputting time-lapse")
          if not self._output_file:
              self._setup(**timelapse_kwargs)
  
          logger.debug("Getting time-lapse samples")
          self._samples.images = self._feeder.generate_preview(is_timelapse=True)
          logger.debug("Got time-lapse samples: %s",
                       {side: len(images) for side, images in self._samples.images.items()})
 
</s> remove     def output_timelapse(self, timelapse_kwargs: Dict[str, str]) -> None:
 </s> add     def output_timelapse(self, timelapse_kwargs: Dict[Literal["input_a",
                                                              "input_b",
                                                              "output"], str]) -> None: </s> remove         parent_flags = dict(mask_toggle="request_mask_toggle", update="request_refresh")
        for trigger in ("mask_toggle", "update"):
            filename = self._gui_triggers[trigger]
 </s> add         for trigger, filename in self._gui_triggers.items(): </s> remove         logger.debug("Creating figure '%s' for image shape %s", name, image_shape)
        if not self._dpi:
            self._dpi = get_dpi()
        height, width = image_shape[:2]
        size = width / self._dpi, height / self._dpi
        fig = plt.figure(name, figsize=size)
        axes = plt.Axes(fig, [0., 0., 1., 1.])  # Remove axes and whitespace
        axes.set_axis_off()
        fig.add_axes(axes)
        fig.canvas.mpl_connect("key_press_event", self._on_key_press)
        fig.canvas.mpl_connect("close_event", self._on_close)
        logger.debug("Created display figure of size: %s", size)
        self._images[name] = (fig, size)

    def _set_resize_callback(self):
        """ Sets the resize callback if displaying preview at actual size or removes it if
        displaying at screen-fit size. """
        if self._triggers["full_size"]:
            logger.debug("Setting resize callback for actual size display")
            for fig, size in self._images.values():
                self._resize_ids.append((fig, fig.canvas.mpl_connect("resize_event",
                                                                     self._on_resize)))
                fig.set_size_inches(size)
        else:
            logger.debug("Removing resize callback for screen-fit display")
            for fig, cid in self._resize_ids:
                fig.canvas.mpl_disconnect(cid)
            self._resize_ids = []

    def _on_key_press(self, event: backend_bases.KeyEvent) -> None:
        """ Callbacks for keypresses to update the requested trigger.

        - `F` (toggle full-size/fit to window)
        - `M` (toggle mask),
        - `R` (refresh preview),
        - `S` (save now)
        - `Enter` (save and exit)
 </s> add         if not self._active:
            return None
        thread = FSThread(target=Preview,
                          name="preview",
                          args=(self._buffer, ),
                          kwargs=dict(triggers=self._triggers))
        thread.start()
        return thread </s> remove             return
 </s> add             return retval </s> remove         Parameters
        ----------
        name: str
            The name to display in the window header and for window identification
        shape: tuple
            The (`rows`, `columns`, `channels`) of the image to be displayed
 </s> add         Returns
        -------
        :class:`lib.multithreading.FSThread` or ``None``
            The thread that holds the preview viewer if preview is selected otherwise ``None``
            self._setup(**cast(Dict[str, str], timelapse_kwargs))
              the keys being `input_a`, `input_b`, `output`
          """
          logger.debug("Ouputting time-lapse")
          if not self._output_file:
            self._setup(**cast(Dict[str, str], timelapse_kwargs))
  
          logger.debug("Getting time-lapse samples")
          self._samples.images = self._feeder.generate_preview(is_timelapse=True)
          logger.debug("Got time-lapse samples: %s",
                       {side: len(images) for side, images in self._samples.images.items()})
keep keep keep keep replace keep keep keep keep keep
 Training - Use custom preview pop-out 
plugins/train/trainer/_base.py