      # Use depth-wise convolution to calculate edge maps per channel.
      pad_sizes = [[0, 0], [2, 2], [2, 2], [0, 0]]
      padded = tf.pad(image, pad_sizes, mode='REFLECT')
  
      # Output tensor has shape [batch_size, h, w, d * num_kernels].
      strides = [1, 1, 1, 1]
      output = tf.nn.depthwise_conv2d(padded, kernels_tf, strides, 'VALID')
  
      # Reshape to [batch_size, h, w, d, num_kernels].
      shape = tf.concat([image_shape, [num_kernels]], 0)
      output = tf.reshape(output, shape=shape)
      output.set_shape(static_image_shape.concatenate([num_kernels]))
  
      if magnitude:  # magnitude of edges
          output = tf.sqrt(tf.reduce_sum(tf.square(output), axis=-1))
      else:  # direction of edges
          output = tf.atan(tf.squeeze(tf.div(output[:, :, :, :, 0]/output[:, :, :, :, 1])))
  
      return output
  
  
  def gmsd_loss(y_true, y_pred):
 
</s> remove     image_shape = tf.shape(image)

    # modified 3x3 Scharr
    # kernels = [[[-17.0, -61.0, -17.0], [0.0, 0.0, 0.0], [17.0, 61.0, 17.0]],
    #         [[-17.0, 0.0, 17.0], [-61.0, 0.0, 61.0], [-17.0, 0.0, 17.0]]]

    # 5x5 Scharr
    kernels = [[[-1.0, -2.0, -3.0, -2.0, -1.0],
                [-1.0, -2.0, -6.0, -2.0, -1.0],
                [0.0, 0.0, 0.0, 0.0, 0.0],
                [1.0, 2.0, 6.0, 2.0, 1.0],
                [1.0, 2.0, 3.0, 2.0, 1.0]],
               [[-1.0, -1.0, 0.0, 1.0, 1.0],
                [-2.0, -2.0, 0.0, 2.0, 2.0],
                [-3.0, -6.0, 0.0, 6.0, 3.0],
                [-2.0, -2.0, 0.0, 2.0, 2.0],
                [-1.0, -1.0, 0.0, 1.0, 1.0]]]
    num_kernels = len(kernels)
    kernels = np.transpose(np.asarray(kernels), (1, 2, 0))
    kernels = np.expand_dims(kernels, -2) / np.sum(np.abs(kernels))
    kernels_tf = tf.constant(kernels, dtype=image.dtype)
    kernels_tf = tf.tile(kernels_tf, [1, 1, image_shape[-1], 1], name='scharr_filters')
 </s> add     image_shape = K.shape(image)

    # 5x5 modified Scharr kernel ( reshape to (5,5,1,2) )
    matrix = [[[[0.00070, 0.00070]],
               [[0.00520, 0.00370]],
               [[0.03700, 0.00000]],
               [[0.00520, -0.0037]],
               [[0.00070, -0.0007]]],
              [[[0.00370, 0.00520]],
               [[0.11870, 0.11870]],
               [[0.25890, 0.00000]],
               [[0.11870, -0.1187]],
               [[0.00370, -0.0052]]],
              [[[0.00000, 0.03700]],
               [[0.00000, 0.25890]],
               [[0.00000, 0.00000]],
               [[0.00000, -0.2589]],
               [[0.00000, -0.0370]]],
              [[[-0.0037, 0.00520]],
               [[-0.1187, 0.11870]],
               [[-0.2589, 0.00000]],
               [[-0.1187, -0.1187]],
               [[-0.0037, -0.0052]]],
              [[[-0.0007, 0.00070]],
               [[-0.0052, 0.00370]],
               [[-0.0370, 0.00000]],
               [[-0.0052, -0.0037]],
               [[-0.0007, -0.0007]]]]
    num_kernels = [2]
    kernels = K.constant(matrix, dtype='float32')
    kernels = K.tile(kernels, [1, 1, image_shape[-1], 1])
 </s> remove 
    def diff_x(var_x):
        xleft = var_x[:, :, 1, :] - var_x[:, :, 0, :]
        xinner = tf.unstack(var_x[:, :, 2:, :] - var_x[:, :, :-2, :], axis=2)
        xright = var_x[:, :, -1, :] - var_x[:, :, -2, :]
        xout = [xleft] + xinner + [xright]
        xout = tf.stack(xout, axis=2)
        return xout * 0.5

    def diff_y(var_x):
        xtop = var_x[:, 1, :, :] - var_x[:, 0, :, :]
        xinner = tf.unstack(var_x[:, 2:, :, :] - var_x[:, :-2, :, :], axis=1)
        xbot = var_x[:, -1, :, :] - var_x[:, -2, :, :]
        xout = [xtop] + xinner + [xbot]
        xout = tf.stack(xout, axis=1)
        return xout * 0.5

    def diff_xx(var_x):
        xleft = var_x[:, :, 1, :] + var_x[:, :, 0, :]
        xinner = tf.unstack(var_x[:, :, 2:, :] + var_x[:, :, :-2, :], axis=2)
        xright = var_x[:, :, -1, :] + var_x[:, :, -2, :]
        xout = [xleft] + xinner + [xright]
        xout = tf.stack(xout, axis=2)
        return xout - 2.0 * var_x

    def diff_yy(var_x):
        xtop = var_x[:, 1, :, :] + var_x[:, 0, :, :]
        xinner = tf.unstack(var_x[:, 2:, :, :] + var_x[:, :-2, :, :], axis=1)
        xbot = var_x[:, -1, :, :] + var_x[:, -2, :, :]
        xout = [xtop] + xinner + [xbot]
        xout = tf.stack(xout, axis=1)
        return xout - 2.0 * var_x

    def diff_xy(var_x):
        # xout1
        top_left = var_x[:, 1, 1, :]+var_x[:, 0, 0, :]
        inner_left = tf.unstack(var_x[:, 2:, 1, :]+var_x[:, :-2, 0, :], axis=1)
        bot_left = var_x[:, -1, 1, :]+var_x[:, -2, 0, :]
        x_left = [top_left] + inner_left + [bot_left]
        x_left = tf.stack(x_left, axis=1)

        top_mid = var_x[:, 1, 2:, :]+var_x[:, 0, :-2, :]
        mid_mid = tf.unstack(var_x[:, 2:, 2:, :]+var_x[:, :-2, :-2, :], axis=1)
        bot_mid = var_x[:, -1, 2:, :]+var_x[:, -2, :-2, :]
        x_mid = [top_mid] + mid_mid + [bot_mid]
        x_mid = tf.stack(x_mid, axis=1)

        top_right = var_x[:, 1, -1, :]+var_x[:, 0, -2, :]
        inner_right = tf.unstack(var_x[:, 2:, -1, :]+var_x[:, :-2, -2, :], axis=1)
        bot_right = var_x[:, -1, -1, :]+var_x[:, -2, -2, :]
        x_right = [top_right] + inner_right + [bot_right]
        x_right = tf.stack(x_right, axis=1)

        x_mid = tf.unstack(x_mid, axis=2)
        xout1 = [x_left] + x_mid + [x_right]
        xout1 = tf.stack(xout1, axis=2)

        # xout2
        top_left = var_x[:, 0, 1, :]+var_x[:, 1, 0, :]
        inner_left = tf.unstack(var_x[:, :-2, 1, :]+var_x[:, 2:, 0, :], axis=1)
        bot_left = var_x[:, -2, 1, :]+var_x[:, -1, 0, :]
        x_left = [top_left] + inner_left + [bot_left]
        x_left = tf.stack(x_left, axis=1)

        top_mid = var_x[:, 0, 2:, :]+var_x[:, 1, :-2, :]
        mid_mid = tf.unstack(var_x[:, :-2, 2:, :]+var_x[:, 2:, :-2, :], axis=1)
        bot_mid = var_x[:, -2, 2:, :]+var_x[:, -1, :-2, :]
        x_mid = [top_mid] + mid_mid + [bot_mid]
        x_mid = tf.stack(x_mid, axis=1)

        top_right = var_x[:, 0, -1, :]+var_x[:, 1, -2, :]
        inner_right = tf.unstack(var_x[:, :-2, -1, :]+var_x[:, 2:, -2, :], axis=1)
        bot_right = var_x[:, -2, -1, :]+var_x[:, -1, -2, :]
        x_right = [top_right] + inner_right + [bot_right]
        x_right = tf.stack(x_right, axis=1)

        x_mid = tf.unstack(x_mid, axis=2)
        xout2 = [x_left] + x_mid + [x_right]
        xout2 = tf.stack(xout2, axis=2)

        return (xout1 - xout2) * 0.25

    loss += tv_weight * (generalized_loss_function(diff_x(y_true),
                                                   diff_x(y_pred),
                                                   var_a=1.999999) +
                         generalized_loss_function(diff_y(y_true),
                                                   diff_y(y_pred),
                                                   var_a=1.999999))

    loss += tv2_weight * (generalized_loss_function(diff_xx(y_true),
                                                    diff_xx(y_pred),
                                                    var_a=1.999999) +
                          generalized_loss_function(diff_yy(y_true),
                                                    diff_yy(y_pred),
                                                    var_a=1.999999) +
                          2.0 * generalized_loss_function(diff_xy(y_true),
                                                          diff_xy(y_pred),
                                                          var_a=1.999999))

    return loss / (tv_weight + tv2_weight)
 </s> add     loss += tv_weight * (generalized_loss(diff_x(y_true), diff_x(y_pred), alpha=1.9999) +
                         generalized_loss(diff_y(y_true), diff_y(y_pred), alpha=1.9999))
    loss += tv2_weight * (generalized_loss(diff_xx(y_true), diff_xx(y_pred), alpha=1.9999) +
                          generalized_loss(diff_yy(y_true), diff_yy(y_pred), alpha=1.9999) +
                          generalized_loss(diff_xy(y_true), diff_xy(y_pred), alpha=1.9999) * 2.)
    loss = loss / (tv_weight + tv2_weight)
    # TODO simplify to use MSE instead
    return loss </s> remove     assert K.ndim(y_true) == 4
    y_true.set_shape([None, 80, 80, 3])
    y_pred.set_shape([None, 80, 80, 3])
 </s> add     def diff_x(img):
        x_left = img[:, :, 1:2, :] - img[:, :, 0:1, :]
        x_inner = img[:, :, 2:, :] - img[:, :, :-2, :]
        x_right = img[:, :, -1:, :] - img[:, :, -2:-1, :]
        x_out = K.concatenate([x_left, x_inner, x_right], axis=2)
        return x_out * 0.5

    def diff_y(img):
        y_top = img[:, 1:2, :, :] - img[:, 0:1, :, :]
        y_inner = img[:, 2:, :, :] - img[:, :-2, :, :]
        y_bot = img[:, -1:, :, :] - img[:, -2:-1, :, :]
        y_out = K.concatenate([y_top, y_inner, y_bot], axis=1)
        return y_out * 0.5

    def diff_xx(img):
        x_left = img[:, :, 1:2, :] + img[:, :, 0:1, :]
        x_inner = img[:, :, 2:, :] + img[:, :, :-2, :]
        x_right = img[:, :, -1:, :] + img[:, :, -2:-1, :]
        x_out = K.concatenate([x_left, x_inner, x_right], axis=2)
        return x_out - 2.0 * img

    def diff_yy(img):
        y_top = img[:, 1:2, :, :] + img[:, 0:1, :, :]
        y_inner = img[:, 2:, :, :] + img[:, :-2, :, :]
        y_bot = img[:, -1:, :, :] + img[:, -2:-1, :, :]
        y_out = K.concatenate([y_top, y_inner, y_bot], axis=1)
        return y_out - 2.0 * img

    def diff_xy(img):
        # xout1
        top_left = img[:, 1:2, 1:2, :] + img[:, 0:1, 0:1, :]
        inner_left = img[:, 2:, 1:2, :] + img[:, :-2, 0:1, :]
        bot_left = img[:, -1:, 1:2, :] + img[:, -2:-1, 0:1, :]
        xy_left = K.concatenate([top_left, inner_left, bot_left], axis=1)

        top_mid = img[:, 1:2, 2:, :] + img[:, 0:1, :-2, :]
        mid_mid = img[:, 2:, 2:, :] + img[:, :-2, :-2, :]
        bot_mid = img[:, -1:, 2:, :] + img[:, -2:-1, :-2, :]
        xy_mid = K.concatenate([top_mid, mid_mid, bot_mid], axis=1)

        top_right = img[:, 1:2, -1:, :] + img[:, 0:1, -2:-1, :]
        inner_right = img[:, 2:, -1:, :] + img[:, :-2, -2:-1, :]
        bot_right = img[:, -1:, -1:, :] + img[:, -2:-1, -2:-1, :]
        xy_right = K.concatenate([top_right, inner_right, bot_right], axis=1)

        # Xout2
        top_left = img[:, 0:1, 1:2, :] + img[:, 1:2, 0:1, :]
        inner_left = img[:, :-2, 1:2, :] + img[:, 2:, 0:1, :]
        bot_left = img[:, -2:-1, 1:2, :] + img[:, -1:, 0:1, :]
        xy_left = K.concatenate([top_left, inner_left, bot_left], axis=1)

        top_mid = img[:, 0:1, 2:, :] + img[:, 1:2, :-2, :]
        mid_mid = img[:, :-2, 2:, :] + img[:, 2:, :-2, :]
        bot_mid = img[:, -2:-1, 2:, :] + img[:, -1:, :-2, :]
        xy_mid = K.concatenate([top_mid, mid_mid, bot_mid], axis=1)

        top_right = img[:, 0:1, -1:, :] + img[:, 1:2, -2:-1, :]
        inner_right = img[:, :-2, -1:, :] + img[:, 2:, -2:-1, :]
        bot_right = img[:, -2:-1, -1:, :] + img[:, -1:, -2:-1, :]
        xy_right = K.concatenate([top_right, inner_right, bot_right], axis=1)

        xy_out1 = K.concatenate([xy_left, xy_mid, xy_right], axis=2)
        xy_out2 = K.concatenate([xy_left, xy_mid, xy_right], axis=2)
        return (xy_out1 - xy_out2) * 0.25

    if not magnitude:  # direction of edges
        # Reshape to [batch_size, h, w, d, num_kernels].
        shape = K.concatenate([image_shape, num_kernels], axis=0)
        output = K.reshape(output, shape=shape)
        output.set_shape(static_image_shape.concatenate(num_kernels))
        output = tf.atan(K.squeeze(output[:, :, :, :, 0] / output[:, :, :, :, 1]))
    # magnitude of edges -- unified x & y edges don't work well with NN
      # Use depth-wise convolution to calculate edge maps per channel.
      pad_sizes = [[0, 0], [2, 2], [2, 2], [0, 0]]
      padded = tf.pad(image, pad_sizes, mode='REFLECT')
  
    if not magnitude:  # direction of edges
        # Reshape to [batch_size, h, w, d, num_kernels].
        shape = K.concatenate([image_shape, num_kernels], axis=0)
        output = K.reshape(output, shape=shape)
        output.set_shape(static_image_shape.concatenate(num_kernels))
        output = tf.atan(K.squeeze(output[:, :, :, :, 0] / output[:, :, :, :, 1]))
    # magnitude of edges -- unified x & y edges don't work well with NN
    if not magnitude:  # direction of edges
        # Reshape to [batch_size, h, w, d, num_kernels].
        shape = K.concatenate([image_shape, num_kernels], axis=0)
        output = K.reshape(output, shape=shape)
        output.set_shape(static_image_shape.concatenate(num_kernels))
        output = tf.atan(K.squeeze(output[:, :, :, :, 0] / output[:, :, :, :, 1]))
    # magnitude of edges -- unified x & y edges don't work well with NN
    if not magnitude:  # direction of edges
        # Reshape to [batch_size, h, w, d, num_kernels].
        shape = K.concatenate([image_shape, num_kernels], axis=0)
        output = K.reshape(output, shape=shape)
        output.set_shape(static_image_shape.concatenate(num_kernels))
        output = tf.atan(K.squeeze(output[:, :, :, :, 0] / output[:, :, :, :, 1]))
    # magnitude of edges -- unified x & y edges don't work well with NN
    if not magnitude:  # direction of edges
        # Reshape to [batch_size, h, w, d, num_kernels].
        shape = K.concatenate([image_shape, num_kernels], axis=0)
        output = K.reshape(output, shape=shape)
        output.set_shape(static_image_shape.concatenate(num_kernels))
        output = tf.atan(K.squeeze(output[:, :, :, :, 0] / output[:, :, :, :, 1]))
    # magnitude of edges -- unified x & y edges don't work well with NN
    if not magnitude:  # direction of edges
        # Reshape to [batch_size, h, w, d, num_kernels].
        shape = K.concatenate([image_shape, num_kernels], axis=0)
        output = K.reshape(output, shape=shape)
        output.set_shape(static_image_shape.concatenate(num_kernels))
        output = tf.atan(K.squeeze(output[:, :, :, :, 0] / output[:, :, :, :, 1]))
    # magnitude of edges -- unified x & y edges don't work well with NN
    if not magnitude:  # direction of edges
        # Reshape to [batch_size, h, w, d, num_kernels].
        shape = K.concatenate([image_shape, num_kernels], axis=0)
        output = K.reshape(output, shape=shape)
        output.set_shape(static_image_shape.concatenate(num_kernels))
        output = tf.atan(K.squeeze(output[:, :, :, :, 0] / output[:, :, :, :, 1]))
    # magnitude of edges -- unified x & y edges don't work well with NN
    if not magnitude:  # direction of edges
        # Reshape to [batch_size, h, w, d, num_kernels].
        shape = K.concatenate([image_shape, num_kernels], axis=0)
        output = K.reshape(output, shape=shape)
        output.set_shape(static_image_shape.concatenate(num_kernels))
        output = tf.atan(K.squeeze(output[:, :, :, :, 0] / output[:, :, :, :, 1]))
    # magnitude of edges -- unified x & y edges don't work well with NN
    if not magnitude:  # direction of edges
        # Reshape to [batch_size, h, w, d, num_kernels].
        shape = K.concatenate([image_shape, num_kernels], axis=0)
        output = K.reshape(output, shape=shape)
        output.set_shape(static_image_shape.concatenate(num_kernels))
        output = tf.atan(K.squeeze(output[:, :, :, :, 0] / output[:, :, :, :, 1]))
    # magnitude of edges -- unified x & y edges don't work well with NN
    if not magnitude:  # direction of edges
        # Reshape to [batch_size, h, w, d, num_kernels].
        shape = K.concatenate([image_shape, num_kernels], axis=0)
        output = K.reshape(output, shape=shape)
        output.set_shape(static_image_shape.concatenate(num_kernels))
        output = tf.atan(K.squeeze(output[:, :, :, :, 0] / output[:, :, :, :, 1]))
    # magnitude of edges -- unified x & y edges don't work well with NN
    if not magnitude:  # direction of edges
        # Reshape to [batch_size, h, w, d, num_kernels].
        shape = K.concatenate([image_shape, num_kernels], axis=0)
        output = K.reshape(output, shape=shape)
        output.set_shape(static_image_shape.concatenate(num_kernels))
        output = tf.atan(K.squeeze(output[:, :, :, :, 0] / output[:, :, :, :, 1]))
    # magnitude of edges -- unified x & y edges don't work well with NN
    if not magnitude:  # direction of edges
        # Reshape to [batch_size, h, w, d, num_kernels].
        shape = K.concatenate([image_shape, num_kernels], axis=0)
        output = K.reshape(output, shape=shape)
        output.set_shape(static_image_shape.concatenate(num_kernels))
        output = tf.atan(K.squeeze(output[:, :, :, :, 0] / output[:, :, :, :, 1]))
    # magnitude of edges -- unified x & y edges don't work well with NN
    if not magnitude:  # direction of edges
        # Reshape to [batch_size, h, w, d, num_kernels].
        shape = K.concatenate([image_shape, num_kernels], axis=0)
        output = K.reshape(output, shape=shape)
        output.set_shape(static_image_shape.concatenate(num_kernels))
        output = tf.atan(K.squeeze(output[:, :, :, :, 0] / output[:, :, :, :, 1]))
    # magnitude of edges -- unified x & y edges don't work well with NN
    if not magnitude:  # direction of edges
        # Reshape to [batch_size, h, w, d, num_kernels].
        shape = K.concatenate([image_shape, num_kernels], axis=0)
        output = K.reshape(output, shape=shape)
        output.set_shape(static_image_shape.concatenate(num_kernels))
        output = tf.atan(K.squeeze(output[:, :, :, :, 0] / output[:, :, :, :, 1]))
    # magnitude of edges -- unified x & y edges don't work well with NN
  
      return output
  
  
  def gmsd_loss(y_true, y_pred):
keep keep keep keep replace replace replace replace replace replace replace replace replace replace replace replace replace keep keep keep keep keep
 documentation, pep8, style, clarity updates  - Prep for Segmentation (#812)

* documentation, pep8, style, clarity updates

* Update cli.py

* Update _config.py

remove extra mask and coverage

mask type as dropdown

* Update training_data.py

move coverage / LR to global
cut down on loss description

style change
losses working in PR

* simpler logging

* legacy update 
lib/model/losses.py