class_docstr: resample inputs according to ``sample_coords``
class_docstr_tok: ["resample","inputs","according","to","``","sample_coords","``"]
docstr: Bilinear or trilinear resampling.
  
  :param inputs:
  :param sample_coords:
  :return:
docstr_tok: ["Bilinear","or","trilinear","resampling",".",":","param","inputs",":",":","param","sample_coords",":",":","return",":"]
code: def _resample_linear(self, inputs, sample_coords):
      """
      Bilinear or trilinear resampling.
  
      :param inputs:
      :param sample_coords:
      :return:
      """
  
      # read input shape
      in_size = inputs.shape
      partial_shape = not in_size.is_fully_defined()
  
      try:
          batch_size = int(in_size[0])
          n_coords = int(sample_coords.shape[0])
          in_spatial_rank = infer_spatial_rank(inputs)
          in_spatial_size = (
              None if partial_shape else in_size.as_list()[1:-1]
          )
      except (TypeError, AssertionError, ValueError):
          tf.logging.fatal(
              "Unknown input shape, at least batch size "
              "and rank of the inputs are required."
          )
          raise
  
      # read output shape
      out_spatial_rank = infer_spatial_rank(sample_coords)
      out_spatial_size = sample_coords.shape.as_list()[1:-1]
  
      if in_spatial_rank == 2 and self.boundary == "ZERO":
          # calling TF's resampler
          inputs = tf.transpose(inputs, [0, 2, 1, 3])
          if batch_size == n_coords:
              return tf.contrib.resampler.resampler(
                  inputs, sample_coords
              )
          outputs = [
              tf.contrib.resampler.resampler(
                  tf.expand_dims(img), sample_coords
              )
              for img in tf.unstack(inputs)
          ]
          return tf.concat(outputs, axis=0)
  
      xy = tf.unstack(sample_coords, axis=-1)
      base_coords = [tf.floor(coords) for coords in xy]
      if partial_shape:
          # if input shape is not defined, unable to compute
          # boundary elements
          floor_coords = [coord for coord in base_coords]
          ceil_coords = [coord + 1.0 for coord in base_coords]
      else:
          floor_coords = [
              self.boundary_func(x, in_spatial_size[idx])
              for (idx, x) in enumerate(base_coords)
          ]
          ceil_coords = [
              self.boundary_func(x + 1.0, in_spatial_size[idx])
              for (idx, x) in enumerate(base_coords)
          ]
  
      if self.boundary == "ZERO":
          weight_0 = [
              tf.expand_dims(x - i, -1)
              for (x, i) in zip(xy, floor_coords)
          ]
          weight_1 = [
              tf.expand_dims(i - x, -1)
              for (x, i) in zip(xy, ceil_coords)
          ]
      else:
          weight_0 = [
              tf.expand_dims(x - i, -1)
              for (x, i) in zip(xy, base_coords)
          ]
          weight_1 = [1.0 - w for w in weight_0]
  
      sc = (
          tf.cast(floor_coords, COORDINATES_TYPE),
          tf.cast(ceil_coords, COORDINATES_TYPE),
      )
  
      if n_coords == 1 and batch_size > 1:
          # fetch neighbours with the same coordinates across the input batch
          inputs = tf.unstack(inputs)
  
          def _get_knot(bc):
              coord = [sc[c][i] for i, c in enumerate(bc)]
              coord = tf.stack(coord, axis=-1)
              batch_samples = [
                  tf.gather_nd(img, coord) for img in inputs
              ]
              batch_samples = tf.concat(batch_samples, axis=0)
              return batch_samples
  
      elif n_coords == batch_size:
          batch_ids = tf.reshape(
              tf.range(batch_size),
              [batch_size] + [1] * out_spatial_rank,
          )
          batch_ids = tf.tile(batch_ids, [1] + out_spatial_size)
  
          def _get_knot(bc):
              coord = [batch_ids] + [sc[c][i] for i, c in enumerate(bc)]
              coord = tf.stack(coord, axis=-1)
              return tf.gather_nd(inputs, coord)
  
      else:
          raise NotImplementedError
  
      def _pyramid_combination(samples, w_0, w_1):
          # the case where n_coords = 1 and batch_size > 1 is handled by
          # shape broadcasting
          if len(w_0) == 1:
              return samples[0] * w_1[0] + samples[1] * w_0[0]
          f_0 = _pyramid_combination(samples[::2], w_0[:-1], w_1[:-1])
          f_1 = _pyramid_combination(samples[1::2], w_0[:-1], w_1[:-1])
          return f_0 * w_1[-1] + f_1 * w_0[-1]
  
      binary_neighbour_ids = _binary_neighbour_ids(in_spatial_rank)
      samples = [_get_knot(bc) for bc in binary_neighbour_ids]
  
      return _pyramid_combination(samples, weight_0, weight_1)
  
file_path: NiftyNet/niftynet/layer/resampler.py
imports: from __future__ import absolute_import, division, print_function
  import tensorflow
  from niftynet.layer.base_layer import Layer
  from niftynet.layer.layer_util import infer_spatial_rank
  from niftynet.utilities.util_common import look_up_operations
label_desc: Use image node_id 4 for calling the ResamplerLayer obj's underlying member method code with example usage: obj._resample_linear(inputs, sample_coords) and returns: _pyramid_combination, tf, unknown, tf, batch_samples, unknown, tf