          """ Return the inputs for the model """
          logger.debug("Getting inputs")
          inputs = [Input(shape=self.input_shape, name="face_in")]
          output_network = [network for network in self.networks.values() if network.is_output][0]
          mask_idx = [idx for idx, name in enumerate(output_network.output_names)
                      if name.startswith("mask")]
          if mask_idx:
              # Add the final mask shape as input
              mask_shape = output_network.output_shapes[mask_idx[0]]
              inputs.append(Input(shape=mask_shape[1:], name="mask_in"))
          logger.debug("Got inputs: %s", inputs)
          return inputs
  
      def build_autoencoders(self, inputs):
          """ Override for Model Specific autoencoder builds
 
</s> remove     def use_mask(self):
        """ Return True if a mask is requested """
        retval = bool(self.model.training_opts.get("mask_type", None))
 </s> add     def _use_mask(self):
        """ bool: ``True`` if a mask is required otherwise ``False`` """
        retval = (self._model.training_opts["learn_mask"] or
                  self._model.training_opts["penalized_mask_loss"]) </s> remove         src_points = [self._landmarks[side].get(sha1(face).hexdigest(), None) for face in batch]

 </s> add         src_points = [self._landmarks[side].get(filename, None) for filename in filenames] </s> remove         """ Perform timelapse """
        logger.debug("Getting timelapse samples: '%s'", side)
        if not self.output_file:
            self.setup(**timelapse_kwargs)
        self.samples.images[side] = self.batchers[side].compile_timelapse_sample()
        logger.debug("Got timelapse samples: '%s' - %s", side, len(self.samples.images[side]))

    def setup(self, input_a=None, input_b=None, output=None):
        """ Set the timelapse output folder """
        logger.debug("Setting up timelapse")
 </s> add         """ Compile the time-lapse preview

        Parameters
        ----------
        side: {"a" or "b"}
            The side that the time-lapse is being generated for
        timelapse_kwargs: dict
            The keyword arguments for setting up the time-lapse. All values should be full paths
            the keys being `input_a`, `input_b`, `output`
        """
        logger.debug("Getting time-lapse samples: '%s'", side)
        if not self._output_file:
            self._setup(**timelapse_kwargs)
        self._samples.images[side] = self._batchers[side].compile_timelapse_sample()
        logger.debug("Got time-lapse samples: '%s' - %s", side, len(self._samples.images[side]))

    def _setup(self, input_a=None, input_b=None, output=None):
        """ Setup the time-lapse folder locations and the time-lapse feed.

        Parameters
        ----------
        input_a: str
            The full path to the time-lapse input folder containing faces for the "a" side
        input_b: str
            The full path to the time-lapse input folder containing faces for the "b" side
        output: str, optional
            The full path to the time-lapse output folder. If ``None`` is provided this will
            default to the model folder
        """
        logger.debug("Setting up time-lapse") </s> remove         preds["a_a"] = self.model.predictors["a"].predict(feed_a)
        preds["b_a"] = self.model.predictors["b"].predict(feed_a)
        preds["a_b"] = self.model.predictors["a"].predict(feed_b)
        preds["b_b"] = self.model.predictors["b"].predict(feed_b)
 </s> add         preds["a_a"] = self._model.predictors["a"].predict(feed_a)
        preds["b_a"] = self._model.predictors["b"].predict(feed_a)
        preds["a_b"] = self._model.predictors["a"].predict(feed_b)
        preds["b_b"] = self._model.predictors["b"].predict(feed_b) </s> remove     def get_next(self, do_preview):
        """ Return the next batch from the generator
            Items should come out as: (warped, target [, mask]) """
        batch = next(self.feed)
        if self.use_mask:
            batch = [[batch["feed"], batch["masks"]], batch["targets"] + [batch["masks"]]]
        else:
            batch = [batch["feed"], batch["targets"]]
        self.generate_preview(do_preview)
        return batch
 </s> add     def _get_next(self):
        """ Return the next batch from the :class:`lib.training_data.TrainingDataGenerator` for
        this batcher ready for feeding into the model.

        Returns
        -------
        model_inputs: list
            A list of :class:`numpy.ndarray` for feeding into the model
        model_targets: list
            A list of :class:`numpy.ndarray` for comparing the output of the model
        """
        logger.trace("Generating targets")
        batch = next(self._feed)
        targets_use_mask = self._model.training_opts["learn_mask"]
        model_inputs = batch["feed"] + batch["masks"] if self._use_mask else batch["feed"]
        model_targets = batch["targets"] + batch["masks"] if targets_use_mask else batch["targets"]
        return model_inputs, model_targets
        if self.feed_mask:
            # TODO penalized mask doesn't have a mask output, so we can't use output shapes
            # mask should always be last output..this needs to be a rule
            mask_shape = output_network.output_shapes[-1]
            inputs.append(Input(shape=(mask_shape[1:-1] + (1,)), name="mask_in"))
          """ Return the inputs for the model """
          logger.debug("Getting inputs")
          inputs = [Input(shape=self.input_shape, name="face_in")]
          output_network = [network for network in self.networks.values() if network.is_output][0]
        if self.feed_mask:
            # TODO penalized mask doesn't have a mask output, so we can't use output shapes
            # mask should always be last output..this needs to be a rule
            mask_shape = output_network.output_shapes[-1]
            inputs.append(Input(shape=(mask_shape[1:-1] + (1,)), name="mask_in"))
        if self.feed_mask:
            # TODO penalized mask doesn't have a mask output, so we can't use output shapes
            # mask should always be last output..this needs to be a rule
            mask_shape = output_network.output_shapes[-1]
            inputs.append(Input(shape=(mask_shape[1:-1] + (1,)), name="mask_in"))
        if self.feed_mask:
            # TODO penalized mask doesn't have a mask output, so we can't use output shapes
            # mask should always be last output..this needs to be a rule
            mask_shape = output_network.output_shapes[-1]
            inputs.append(Input(shape=(mask_shape[1:-1] + (1,)), name="mask_in"))
        if self.feed_mask:
            # TODO penalized mask doesn't have a mask output, so we can't use output shapes
            # mask should always be last output..this needs to be a rule
            mask_shape = output_network.output_shapes[-1]
            inputs.append(Input(shape=(mask_shape[1:-1] + (1,)), name="mask_in"))
        if self.feed_mask:
            # TODO penalized mask doesn't have a mask output, so we can't use output shapes
            # mask should always be last output..this needs to be a rule
            mask_shape = output_network.output_shapes[-1]
            inputs.append(Input(shape=(mask_shape[1:-1] + (1,)), name="mask_in"))
        if self.feed_mask:
            # TODO penalized mask doesn't have a mask output, so we can't use output shapes
            # mask should always be last output..this needs to be a rule
            mask_shape = output_network.output_shapes[-1]
            inputs.append(Input(shape=(mask_shape[1:-1] + (1,)), name="mask_in"))
          logger.debug("Got inputs: %s", inputs)
          return inputs
  
      def build_autoencoders(self, inputs):
          """ Override for Model Specific autoencoder builds
keep keep keep keep replace replace replace replace replace replace keep keep keep keep keep
 Smart Masks - Training Implementation (#914)

* Smart Masks - Training

- Reinstate smart mask training code
- Reinstate mask_type back to model.config
- change 'replicate_input_mask to 'learn_mask'
- Add learn mask option
- Add mask loading from alignments to plugins.train.trainer
- Add mask_blur and mask threshold options
- _base.py - Pass mask options through training_opts dict
- plugins.train.model - check for mask_type not None for learn_mask and penalized_mask_loss
- Limit alignments loading to just those faces that appear in the training folder
- Raise error if not all training images have an alignment, and alignment file is required
- lib.training_data - Mask generation code
- lib.faces_detect - cv2 dimension stripping bugfix
- Remove cv2 linting code

* Update mask helptext in cli.py

* Fix Warp to Landmarks
Remove SHA1 hashing from training data

* Update mask training config

* Capture missing masks at training init

* lib.image.read_image_batch - Return filenames with batch for ordering

* scripts.train - Documentation

* plugins.train.trainer - documentation

* Ensure backward compatibility.
Fix convert for new predicted masks

* Update removed masks to components for legacy models. 
plugins/train/model/_base.py