          landmarks = np.array([face.landmarks for face in aligned])
          cropped = np.array([align.extract_face(img) for align, img in zip(aligned, batch)])
          return cropped, landmarks
  
      def _apply_mask(self, filenames, cache, batch, side):
          """ Applies the mask to the 4th channel of the image. If masks are not being used
          applies a dummy all ones mask.
  
          If the configuration options `eye_multiplier` and/or `mouth_multiplier` are greater than 1
          then these masks are applied to the final channels of the batch respectively.
  
          Parameters
 
</s> remove         landmarks = np.array([face.landmarks for face in aligned])
        cropped = np.array([align.extract_face(img) for align, img in zip(aligned, batch)])
        return cropped, landmarks
 </s> add  </s> remove         If the configuration options `eye_multiplier` and/or `mouth_multiplier` are greater than 1
        then these masks are applied to the final channels of the batch respectively.
 </s> add     This class is called from :mod:`plugins.train.trainer._base` and launches a background
    iterator that compiles sample preview data for feeding the model's predict function and for
    display.

    Parameters
    ----------
    model: :class:`~plugins.train.model.ModelBase`
        The model that this data generator is feeding
    config: dict
        The configuration `dict` generated from :file:`config.train.ini` containing the trainer
        plugin configuration options.
    side: {'a' or 'b'}
        The side of the model that this iterator is for.
    images: list
        A list of image paths that will be used to compile the final images.
    batch_size: int
        The batch size for this iterator. Images will be returned in :class:`numpy.ndarray`
        objects of this size from the iterator.
    """
    def _create_samples(self,
                        images: np.ndarray,
                        detected_faces: List[DetectedFace]) -> List[np.ndarray]:
        """ Compile the 'sample' images. These are the 100% coverage images which hold the model
        output in the preview window. </s> remove         self._extract_version = min(alignment_version, self._extract_version)
 </s> add         If the configuration options `eye_multiplier` and/or `mouth_multiplier` are greater than 1
        then these masks are applied to the final channels of the batch respectively. </s> remove         if self._face_cache.extract_version == 1.0:
            # Legacy extract. Don't crop, just return batch with landmarks
            return batch, np.array([face.landmarks for face in aligned])
 </s> add         for filename, src_points in zip(filenames, batch_src_points):
            closest = (np.mean(np.square(src_points - dst_points), axis=(1, 2))).argsort()[:10]
            closest_matches = tuple(dst_landmarks[i][0] for i in closest)
            self._nearest_landmarks[os.path.basename(filename)] = closest_matches
            batch_closest_matches.append(closest_matches)
        logger.trace("Cached closest matches")  # type:ignore
        return batch_closest_matches </s> remove     def _crop_to_center(self, filenames, cache, batch, side):
        """ Crops the training image out of the full extract image based on the centering used in
        the user's configuration settings.
 </s> add         return feed, targets
class PreviewDataGenerator(DataGenerator):
    """ Generator for compiling images for generating previews.
          landmarks = np.array([face.landmarks for face in aligned])
          cropped = np.array([align.extract_face(img) for align, img in zip(aligned, batch)])
          return cropped, landmarks
  
class PreviewDataGenerator(DataGenerator):
    """ Generator for compiling images for generating previews.
class PreviewDataGenerator(DataGenerator):
    """ Generator for compiling images for generating previews.
class PreviewDataGenerator(DataGenerator):
    """ Generator for compiling images for generating previews.
  
          If the configuration options `eye_multiplier` and/or `mouth_multiplier` are greater than 1
          then these masks are applied to the final channels of the batch respectively.
  
          Parameters
keep keep keep keep 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