          # magnitude of edges -- unified x & y edges don't work well with Neural Networks
          return output
  
  
  class LossWrapper(tf.keras.losses.Loss):
      """ A wrapper class for multiple keras losses to enable multiple weighted loss functions on a
      single output.
      """
      def __init__(self):
          logger.debug("Initializing: %s", self.__class__.__name__)
          super().__init__(name="LossWrapper")
          self._loss_functions = []
 
</s> remove     def __init__(self):
 </s> add     def __init__(self) -> None: </s> remove         super().__init__(name="LossWrapper")
 </s> add  </s> remove     def add_loss(self, function, weight=1.0, mask_channel=-1):
 </s> add     def add_loss(self,
                 function: tf.keras.losses.Loss,
                 weight: float = 1.0,
                 mask_channel: int = -1) -> None: </s> remove                              self.max_value,
                             filter_size=self.filter_size,
                             filter_sigma=self.filter_sigma,
                             k1=self.k_1,
                             k2=self.k_2)
 </s> add                              self._max_value,
                             filter_size=self._filter_size,
                             filter_sigma=self._filter_sigma,
                             k1=self._k_1,
                             k2=self._k_2) </s> remove             self._names.extend(["{}_{}{}".format(name, side,
                                                 "" if output_types.count(name) == 1
                                                 else f"_{idx}")
                                for idx, name in enumerate(output_types)])
 </s> add             for idx, name in enumerate(output_types):
                suffix = "" if output_types.count(name) == 1 else f"_{idx}"
                self._names.append(f"{name}_{side}{suffix}")
class LossWrapper():
    """ A wrapper class for multiple keras losses to enable multiple masked weighted loss
    functions on a single output.

    Notes
    -----
    Whilst Keras does allow for applying multiple weighted loss functions, it does not allow
    for an easy mechanism to add additional data (in our case masks) that are batch specific
    but are not fed in to the model.

    This wrapper receives this additional mask data for the batch stacked onto the end of the
    color channels of the received :param:`y_true` batch of images. These masks are then split
    off the batch of images and applied to both the :param:`y_true` and :param:`y_pred` tensors
    prior to feeding into the loss functions.

    For example, for an image of shape (4, 128, 128, 3) 3 additional masks may be stacked onto
    the end of y_true, meaning we receive an input of shape (4, 128, 128, 6). This wrapper then
    splits off (4, 128, 128, 3:6) from the end of the tensor, leaving the original y_true of
    shape (4, 128, 128, 3) ready for masking and feeding through the loss functions.
          # magnitude of edges -- unified x & y edges don't work well with Neural Networks
          return output
  
  
class LossWrapper():
    """ A wrapper class for multiple keras losses to enable multiple masked weighted loss
    functions on a single output.

    Notes
    -----
    Whilst Keras does allow for applying multiple weighted loss functions, it does not allow
    for an easy mechanism to add additional data (in our case masks) that are batch specific
    but are not fed in to the model.

    This wrapper receives this additional mask data for the batch stacked onto the end of the
    color channels of the received :param:`y_true` batch of images. These masks are then split
    off the batch of images and applied to both the :param:`y_true` and :param:`y_pred` tensors
    prior to feeding into the loss functions.

    For example, for an image of shape (4, 128, 128, 3) 3 additional masks may be stacked onto
    the end of y_true, meaning we receive an input of shape (4, 128, 128, 6). This wrapper then
    splits off (4, 128, 128, 3:6) from the end of the tensor, leaving the original y_true of
    shape (4, 128, 128, 3) ready for masking and feeding through the loss functions.
class LossWrapper():
    """ A wrapper class for multiple keras losses to enable multiple masked weighted loss
    functions on a single output.

    Notes
    -----
    Whilst Keras does allow for applying multiple weighted loss functions, it does not allow
    for an easy mechanism to add additional data (in our case masks) that are batch specific
    but are not fed in to the model.

    This wrapper receives this additional mask data for the batch stacked onto the end of the
    color channels of the received :param:`y_true` batch of images. These masks are then split
    off the batch of images and applied to both the :param:`y_true` and :param:`y_pred` tensors
    prior to feeding into the loss functions.

    For example, for an image of shape (4, 128, 128, 3) 3 additional masks may be stacked onto
    the end of y_true, meaning we receive an input of shape (4, 128, 128, 6). This wrapper then
    splits off (4, 128, 128, 3:6) from the end of the tensor, leaving the original y_true of
    shape (4, 128, 128, 3) ready for masking and feeding through the loss functions.
class LossWrapper():
    """ A wrapper class for multiple keras losses to enable multiple masked weighted loss
    functions on a single output.

    Notes
    -----
    Whilst Keras does allow for applying multiple weighted loss functions, it does not allow
    for an easy mechanism to add additional data (in our case masks) that are batch specific
    but are not fed in to the model.

    This wrapper receives this additional mask data for the batch stacked onto the end of the
    color channels of the received :param:`y_true` batch of images. These masks are then split
    off the batch of images and applied to both the :param:`y_true` and :param:`y_pred` tensors
    prior to feeding into the loss functions.

    For example, for an image of shape (4, 128, 128, 3) 3 additional masks may be stacked onto
    the end of y_true, meaning we receive an input of shape (4, 128, 128, 6). This wrapper then
    splits off (4, 128, 128, 3:6) from the end of the tensor, leaving the original y_true of
    shape (4, 128, 128, 3) ready for masking and feeding through the loss functions.
      """
      def __init__(self):
          logger.debug("Initializing: %s", self.__class__.__name__)
          super().__init__(name="LossWrapper")
          self._loss_functions = []
keep keep keep keep replace replace replace keep keep keep keep keep
 bugfix: distibuted training with dssim 
lib/model/losses_tf.py