code: def surface(self, param):
          
          squeeze_out = (np.shape(param) == ())
          param = np.array(param, dtype=float, copy=False, ndmin=1)
          if self.check_bounds and not is_inside_bounds(param, self.params):
              raise ValueError('`param` {} not in the valid range '
                               '{}'.format(param, self.params))
  
          # Create outer product of `params` and `axis`, resulting in shape
          # params.shape + axis.shape
          surf = np.multiply.outer(param, self.axis)
          if squeeze_out:
              surf = surf.squeeze()
  
          return surf
docs: Return the detector surface point corresponding to ``param``.
  
          For parameter value ``p``, the surface point is given by ::
  
              surf = p * axis
  
          Parameters
          ----------
          param : float or `array-like`
              Parameter value(s) at which to evaluate.
  
          Returns
          -------
          point : `numpy.ndarray`
              Vector(s) pointing from the origin to the detector surface
              point at ``param``.
              If ``param`` is a single parameter, the returned array has
              shape ``(2,)``, otherwise ``param.shape + (2,)``.
  
          Examples
          --------
          The method works with a single parameter, resulting in a single
          vector:
  
          >>> part = odl.uniform_partition(0, 1, 10)
          >>> det = Flat1dDetector(part, axis=[1, 0])
          >>> det.surface(0)
          array([ 0.,  0.])
          >>> det.surface(1)
          array([ 1.,  0.])
  
          It is also vectorized, i.e., it can be called with multiple
          parameters at once (or an n-dimensional array of parameters):
  
          >>> det.surface([0, 1])
          array([[ 0.,  0.],
                 [ 1.,  0.]])
          >>> det.surface(np.zeros((4, 5))).shape
          (4, 5, 2)