          Returns
          -------
          tensor
              The DSSIM Loss value
  
          Notes
          -----
          There are additional parameters for this function. some of the 'modes' for edge behavior
          do not yet have a gradient definition in the Theano tree and cannot be used for learning
          """
  
          kernel = [self.kernel_size, self.kernel_size]
          y_true = K.reshape(y_true, [-1] + list(self._int_shape(y_pred)[1:]))
          y_pred = K.reshape(y_pred, [-1] + list(self._int_shape(y_pred)[1:]))
          patches_pred = self.extract_image_patches(y_pred,
                                                    kernel,
                                                    kernel,
                                                    'valid',
                                                    self.dim_ordering)
          patches_true = self.extract_image_patches(y_true,
                                                    kernel,
                                                    kernel,
                                                    'valid',
                                                    self.dim_ordering)
  
          # Get mean
          u_true = K.mean(patches_true, axis=-1)
          u_pred = K.mean(patches_pred, axis=-1)
          # Get variance
          var_true = K.var(patches_true, axis=-1)
          var_pred = K.var(patches_pred, axis=-1)
          # Get standard deviation
          covar_true_pred = K.mean(
              patches_true * patches_pred, axis=-1) - u_true * u_pred
  
          ssim = (2 * u_true * u_pred + self.c_1) * (
              2 * covar_true_pred + self.c_2)
          denom = (K.square(u_true) + K.square(u_pred) + self.c_1) * (
              var_pred + var_true + self.c_2)
          ssim /= denom  # no need for clipping, c_1 + c_2 make the denorm non-zero
          return (1.0 - ssim) / 2.0
  
      @staticmethod
      def _preprocess_padding(padding):
          """Convert keras padding to tensorflow padding.
  
          Parameters
          ----------
          padding: string,
              `"same"` or `"valid"`.
  
          Returns
          -------
          str
              `"SAME"` or `"VALID"`.
  
          Raises
          ------
          ValueError
              If `padding` is invalid.
          """
          if padding == 'same':
              padding = 'SAME'
          elif padding == 'valid':
              padding = 'VALID'
 
</s> remove         if padding == 'same':
            padding = 'SAME'
        elif padding == 'valid':
            padding = 'VALID'
        else:
            raise ValueError('Invalid padding:', padding)
        return padding

    def extract_image_patches(self, input_tensor, k_sizes, s_sizes,
                              padding='same', data_format='channels_last'):
        """ Extract the patches from an image.

        Parameters
        ----------
        input_tensor: tensor
            The input image
        k_sizes: tuple
            2-d tuple with the kernel size
        s_sizes: tuple
            2-d tuple with the strides size
        padding: str, optional
            `"same"` or `"valid"`. Default: `"same"`
        data_format: str, optional.
            `"channels_last"` or `"channels_first"`. Default: `"channels_last"`

        Returns
        -------
        The (k_w, k_h) patches extracted
            Tensorflow ==> (batch_size, w, h, k_w, k_h, c)
            Theano ==> (batch_size, w, h, c, k_w, k_h)
        """
        kernel = [1, k_sizes[0], k_sizes[1], 1]
        strides = [1, s_sizes[0], s_sizes[1], 1]
        padding = self._preprocess_padding(padding)
        if data_format == 'channels_first':
            input_tensor = K.permute_dimensions(input_tensor, (0, 2, 3, 1))
        patches = tf.image.extract_patches(input_tensor, kernel, strides, [1, 1, 1, 1], padding)
        return patches


class GeneralizedLoss(tf.keras.losses.Loss):
 </s> add         ssim = tf.image.ssim(y_true,
                             y_pred,
                             self.max_value,
                             filter_size=self.filter_size,
                             filter_sigma=self.filter_sigma,
                             k1=self.k_1,
                             k2=self.k_2)
        dssim_loss = 1. - ssim
        return dssim_loss


class GeneralizedLoss(tf.keras.losses.Loss):  # pylint:disable=too-few-public-methods </s> remove 

@pytest.mark.parametrize('dummy', [None], ids=[get_backend().upper()])
def test_dssim_channels_last(dummy):  # pylint:disable=unused-argument
    """ Basic test for DSSIM Loss """
    prev_data = K.image_data_format()
    K.set_image_data_format('channels_last')
    for input_dim, kernel_size in zip([32, 33], [2, 3]):
        input_shape = [input_dim, input_dim, 3]
        var_x = np.random.random_sample(4 * input_dim * input_dim * 3)
        var_x = var_x.reshape([4] + input_shape)
        var_y = np.random.random_sample(4 * input_dim * input_dim * 3)
        var_y = var_y.reshape([4] + input_shape)

        model = Sequential()
        model.add(Conv2D(32, (3, 3), padding='same', input_shape=input_shape,
                         activation='relu'))
        model.add(Conv2D(3, (3, 3), padding='same', input_shape=input_shape,
                         activation='relu'))
        adam = Adam(lr=0.001, beta_1=0.9, beta_2=0.999, epsilon=1e-8)
        model.compile(loss=losses.DSSIMObjective(kernel_size=kernel_size),
                      metrics=['mse'],
                      optimizer=adam)
        model.fit(var_x, var_y, batch_size=2, epochs=1, shuffle='batch')

        # Test same
        x_1 = K.constant(var_x, 'float32')
        x_2 = K.constant(var_x, 'float32')
        dssim = losses.DSSIMObjective(kernel_size=kernel_size)
        assert_allclose(0.0, K.eval(dssim(x_1, x_2)), atol=1e-4)

        # Test opposite
        x_1 = K.zeros([4] + input_shape)
        x_2 = K.ones([4] + input_shape)
        dssim = losses.DSSIMObjective(kernel_size=kernel_size)
        assert_allclose(0.5, K.eval(dssim(x_1, x_2)), atol=1e-4)

    K.set_image_data_format(prev_data)
 </s> add  </s> remove             partial_x, _ = tf.split(inputs,
                                    [partial_size, layer_size - partial_size],
                                    axis=self.axis)
 </s> add             partial_x, _ = tf.split(  # pylint:disable=redundant-keyword-arg,no-value-for-parameter
                inputs,
                [partial_size, layer_size - partial_size],
                axis=self.axis) </s> remove         self.c_1 = (self.k_1 * self.max_value) ** 2
        self.c_2 = (self.k_2 * self.max_value) ** 2
        self.dim_ordering = K.image_data_format()

    @staticmethod
    def _int_shape(input_tensor):
        """ Returns the shape of tensor or variable as a tuple of int or None entries.

        Parameters
        ----------
        input_tensor: tensor or variable
            The input to return the shape for

        Returns
        -------
        tuple
            A tuple of integers (or None entries)
        """
        return K.int_shape(input_tensor)
 </s> add  </s> remove         m_t_indices = tf.gather(m_t, indices)
 </s> add         m_t_indices = tf.gather(m_t, indices)  # pylint:disable=no-value-for-parameter
          Returns
          -------
          tensor
              The DSSIM Loss value
























































          """
          if padding == 'same':
              padding = 'SAME'
          elif padding == 'valid':
              padding = 'VALID'
keep keep keep keep replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace keep keep keep keep keep
 Update code to support Tensorflow versions up to 2.8 (#1213)

* Update maximum tf version in setup + requirements

* - bump max version of tf version in launcher
- standardise tf version check

* update keras get_custom_objects  for tf>2.6

* bugfix: force black text in GUI file dialogs (linux)

* dssim loss - Move to stock tf.ssim function

* Update optimizer imports for compatibility

* fix logging for tf2.8

* Fix GUI graphing for TF2.8

* update tests

* bump requirements.txt versions

* Remove limit on nvidia-ml-py

* Graphing bugfixes
  - Prevent live graph from displaying if data not yet available

* bugfix: Live graph. Collect loss labels correctly

* fix: live graph - swallow inconsistent loss errors

* Bugfix: Prevent live graph from clearing during training

* Fix graphing for AMD 
lib/model/losses_tf.py