class_docstr: The fast BSpline Grid Warper defines a grid based on
      sampling coordinate values from a spatially varying displacement
      field  (passed as a tensor input) along a regular cartesian grid
      pattern aligned with the field. Specifically,
  this class defines a grid based on BSpline smoothing, as described by Rueckert et al.
      To ensure that it can be done efficiently, several assumptions are made:
      1) The grid is a cartesian grid aligned with the field.
      2) Knots occur every M,N,O grid points (in X,Y,Z) This allows the
         smoothing to be represented as a 4x4x4 convolutional kernel with MxNxO channels
class_docstr_tok: ["The","fast","BSpline","Grid","Warper","defines","a","grid","based","on","sampling","coordinate","values","from","a","spatially","varying","displacement","field","(","passed","as","a","tensor","input",")","along","a","regular","cartesian","grid","pattern","aligned","with","the","field",".","Specifically",",","this","class","defines","a","grid","based","on","BSpline","smoothing",",","as","described","by","Rueckert","et","al",".","To","ensure","that","it","can","be","done","efficiently",",","several","assumptions","are","made",":","1",")","The","grid","is","a","cartesian","grid","aligned","with","the","field",".","2",")","Knots","occur","every","M",",","N",",","O","grid","points","(","in","X",",","Y",",","Z",")","This","allows","the","smoothing","to","be","represented","as","a","4x4x4","convolutional","kernel","with","MxNxO","channels"]
code: def layer_op(self, field):
      batch_size = int(field.shape.as_list()[0])
      spatial_rank = int(field.shape.as_list()[-1])
      resampled_list = [
          tf.nn.conv3d(
              field[:, :, :, :, d : d + 1],
              self._psi,
              strides=[1] * 5,
              padding="VALID",
          )
          for d in [0, 1, 2]
      ]
      resampled = tf.stack(resampled_list, 5)
      permuted_shape = (
          [batch_size]
          + [f - 3 for f in self._coeff_shape]
          + self._knot_spacing
          + [spatial_rank]
      )
      permuted = tf.transpose(
          tf.reshape(resampled, permuted_shape),
          [0, 1, 4, 2, 5, 3, 6, 7],
      )
      valid_size = [
          (f - 3) * k
          for f, k in zip(self._coeff_shape, self._knot_spacing)
      ]
      reshaped = tf.reshape(
          permuted, [batch_size] + valid_size + [spatial_rank]
      )
      cropped = reshaped[
          :,
          : self._output_shape[0],
          : self._output_shape[1],
          : self._output_shape[2],
          :,
      ]
      return cropped
  
imports: from __future__ import absolute_import
  from __future__ import division
  from __future__ import print_function
  import numpy
  import tensorflow
  from niftynet.layer.grid_warper import GridWarperLayer
  from niftynet.layer.resampler import ResamplerLayer
label_desc: Use image node_id 3 for calling the BSplineFieldImageGridWarperLayer obj's underlying member method code with example usage: obj.layer_op(field) and returns: cropped