          """ Set up tensorboard callback """
          if self.model.training_opts["no_logs"]:
              logger.verbose("TensorBoard logging disabled")
              return None
          if self.pingpong.active:
              # Currently TensorBoard uses the tf.session, meaning that VRAM does not
              # get cleared when model switching
              # TODO find a fix for this
              logger.warning("Currently TensorBoard logging is not supported for Ping-Pong "
                             "training. Session stats and graphing will not be available for this "
 
</s> remove     def set_tensorboard(self):
        """ Set up tensorboard callback """
        if self.model.training_opts["no_logs"]:
 </s> add         alignments = TrainingAlignments(self._model.training_opts, self._images)
        if self._landmarks_required:
            logger.debug("Adding landmarks to training opts dict")
            self._model.training_opts["landmarks"] = alignments.landmarks

        if self._use_mask:
            logger.debug("Adding masks to training opts dict")
            self._model.training_opts["masks"] = alignments.masks

    def _set_tensorboard(self):
        """ Set up Tensorboard callback for logging loss.

        Bypassed if command line option "no-logs" has been selected.

        Returns
        -------
        dict:
            2 Dictionary keys of "a" and "b" the values of which are the
        :class:`tf.keras.callbacks.TensorBoard` objects for the respective sides.
        """
        if self._model.training_opts["no_logs"]: </s> remove     def process_training_opts(self):
        """ Override for processing model specific training options """
        logger.debug(self.model.training_opts)
        if self.landmarks_required:
            landmarks = Landmarks(self.model.training_opts).landmarks
            self.model.training_opts["landmarks"] = landmarks
 </s> add     def _process_training_opts(self):
        """ Extrapolate alignments and masks from the alignments file into
        :attr:`_model.training_opts`."""
        logger.debug(self._model.training_opts)
        if not self._landmarks_required and not self._use_mask:
            return </s> remove         """ Indicate training end to Tensorboard """
        if not self.tensorboard:
 </s> add         """ Stop Tensorboard logging.

        Tensorboard logging needs to be explicitly shutdown on training termination. Called from
        :class:`scripts.train.Train` when training is stopped.
         """
        if not self._tensorboard: </s> remove     def tensorboard_kwargs(self):
        """ TF 1.13 + needs an additional kwarg which is not valid for earlier versions """
 </s> add     def _tensorboard_kwargs(self):
        """ dict: The keyword arguments to be passed to :class:`tf.keras.callbacks.TensorBoard`.
        NB: Tensorflow 1.13 + needs an additional keyword argument which is not valid for earlier
        versions """ </s> remove     def log_tensorboard(self, side, loss):
        """ Log loss to TensorBoard log """
        if not self.tensorboard:
 </s> add     def _log_tensorboard(self, side, loss):
        """ Log current loss to Tensorboard log files

        Parameters
        ----------
        side: {"a", "b"}
            The side to store the loss for
        loss: list
            The list of loss ``floats`` for this side
        """
        if not self._tensorboard:
        if self._pingpong.active:
          """ Set up tensorboard callback """
          if self.model.training_opts["no_logs"]:
              logger.verbose("TensorBoard logging disabled")
              return None
        if self._pingpong.active:
              # Currently TensorBoard uses the tf.session, meaning that VRAM does not
              # get cleared when model switching
              # TODO find a fix for this
              logger.warning("Currently TensorBoard logging is not supported for Ping-Pong "
                             "training. Session stats and graphing will not be available for this "
keep keep keep keep 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/trainer/_base.py