          FaceswapError
              If the requested mask type is not available an error is returned along with a list
              of available masks
          """
          if not self._config["penalized_mask_loss"] and not self._config["learn_mask"]:
              return
  
          if not self._config["mask_type"]:
              logger.debug("No mask selected. Not validating")
              return
  
          if self._config["mask_type"] not in detected_face.mask:
              raise FaceswapError(
                  "You have selected the mask type '{}' but at least one face does not contain the "
                  "selected mask.\nThe face that failed was: '{}'\nThe masks that exist for this "
                  "face are: {}".format(
                      self._config["mask_type"], filename, list(detected_face.mask)))
  
          key = os.path.basename(filename)
          mask = detected_face.mask[self._config["mask_type"]]
          mask.set_blur_and_threshold(blur_kernel=self._config["mask_blur_kernel"],
                                      threshold=self._config["mask_threshold"])
  
          pose = self._cache[key]["aligned_face"].pose
          mask.set_sub_crop(pose.offset[mask.stored_centering],
                            pose.offset[self._centering],
                            self._centering)
 
</s> remove         Raises
        ------
        FaceswapError
            If the requested mask type is not available an error is returned along with a list
            of available masks
 </s> add         Returns
        -------
        list
            4-dimensional array of faces to feed the training the model.
        list
            List of 4-dimensional :class:`numpy.ndarray`. The number of channels here will vary.
            The first 3 channels are (rgb/bgr). The 4th channel is the face mask. Any subsequent
            channels are area masks (e.g. eye/mouth masks) </s> remove         pose = self._cache[key]["aligned_face"].pose
        mask.set_sub_crop(pose.offset[mask.stored_centering],
                          pose.offset[self._centering],
                          self._centering)
 </s> add     def _set_color_order(self, batch) -> None:
        """ Set the color order correctly for the model's input type. </s> remove         filename: str
            The file path for the current image
        detected_face: :class:`lib.align.DetectedFace`
            The detected face object that holds the masks
 </s> add         filenames: list
            List of full paths to image file names for a single batch
        images: :class:`numpy.ndarray`
            The batch of faces corresponding to the filenames
        detected_faces: list
            List of :class:`~lib.align.DetectedFace` objects with aligned data and masks loaded for
            the current batch
        batch: :class:`numpy.ndarray`
            The pre-allocated batch with images and masks populated for the selected coverage and
            centering </s> remove         Parameters
        ----------
        filename: str
            The file path for the current image
        detected_face: :class:`lib.align.DetectedFace`
            The detected face object that holds the masks
        area: str
            `"eye"` or `"mouth"`. The area of the face to obtain the mask for
 </s> add         in_array: :class:`numpy.ndarray`
            The input uint8 array </s> remove         if set_flag:
            logger.warning("You are using legacy extracted faces but have selected '%s' centering "
                           "which is incompatible. Switching centering to 'legacy'",
                           self._centering)
        self._config["centering"] = "legacy"
        self._centering = "legacy"
        self._cache = {key: dict(cached=False) for key in self._cache}
        self._cache_full = False
        self._size = None
        if set_flag:
            self._has_reset = True

    def _add_aligned_face(self, filename, alignments, image_size):
        """ Add a :class:`lib.align.AlignedFace` object to the cache.
 </s> add         if not self._use_mask:
            return

        masks = np.array([face.get_training_masks() for face in detected_faces])
        batch[..., 3:] = masks

        logger.trace("side: %s, masks: %s, batch: %s",  # type: ignore
                     self._side, masks.shape, batch.shape)

    def _process_batch(self, filenames: List[str]) -> BatchType:
        """ Prepares data for feeding through subclassed methods.

        If this is the first time a face has been loaded, then it's meta data is extracted from the
        png header and added to :attr:`_face_cache`
        raise NotImplementedError()
          FaceswapError
              If the requested mask type is not available an error is returned along with a list
              of available masks
          """
        raise NotImplementedError()
        raise NotImplementedError()
        raise NotImplementedError()
        raise NotImplementedError()
        raise NotImplementedError()
        raise NotImplementedError()
        raise NotImplementedError()
        raise NotImplementedError()
        raise NotImplementedError()
        raise NotImplementedError()
        raise NotImplementedError()
        raise NotImplementedError()
        raise NotImplementedError()
        raise NotImplementedError()
        raise NotImplementedError()
        raise NotImplementedError()
        raise NotImplementedError()
        raise NotImplementedError()
  
          pose = self._cache[key]["aligned_face"].pose
          mask.set_sub_crop(pose.offset[mask.stored_centering],
                            pose.offset[self._centering],
                            self._centering)
keep keep keep keep replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace keep keep keep keep keep
 Data Augmentation update (#1263)

- lib.detected_face
    - Subclass Masks for Landmark based masks
    - Add training mask propery + methods to DetectedFace
  - lib.training_training
    - subclass TrainingDataGenerator for training and preview data
    - Split cache into own module
    - Reduce thread count to 1 to prevent image corruption + data re-use
    - Process on largest model input/output size rather than stored image size
    - Size and crop masks during caching stage
    - Implement ring buffer for data flow
    - Fix preview reload bug
  - augmentation
    - typing
    - switch color aug order
    - better initialization
    - Fix warp + landmark warp to correctly apply at different image scales
    - Slightly improved warp caching
    - Don't store whether image is_preview. Handle all data as training images implicitly
  - plugins.trainer: Typing and fixes to work with trainingdata refactor 
lib/training/generator.py