code: def ray_marcher(
      rays, N_samples=64, lindisp=False, perturb=0, bbox_3D=None
  ):
      """
      sample points along the rays
      Inputs:
          rays: ()
  
      Returns:
  
      """
  
      # Decompose the inputs
      N_rays = rays.shape[0]
      rays_o, rays_d = rays[:, 0:3], rays[:, 3:6]  # both (N_rays, 3)
      near, far = rays[:, 6:7], rays[:, 7:8]  # both (N_rays, 1)
  
      if bbox_3D is not None:
          # cal aabb boundles
          near, far = dda(rays_o, rays_d, bbox_3D)
  
      # Sample depth points
      z_steps = torch.linspace(
          0, 1, N_samples, device=rays.device
      )  # (N_samples)
      if not lindisp:  # use linear sampling in depth space
          z_vals = near * (1 - z_steps) + far * z_steps
      else:  # use linear sampling in disparity space
          z_vals = 1 / (1 / near * (1 - z_steps) + 1 / far * z_steps)
  
      z_vals = z_vals.expand(N_rays, N_samples)
  
      if perturb > 0:  # perturb sampling depths (z_vals)
          z_vals_mid = 0.5 * (
              z_vals[:, :-1] + z_vals[:, 1:]
          )  # (N_rays, N_samples-1) interval mid points
          # get intervals between samples
          upper = torch.cat([z_vals_mid, z_vals[:, -1:]], -1)
          lower = torch.cat([z_vals[:, :1], z_vals_mid], -1)
  
          perturb_rand = perturb * torch.rand(
              z_vals.shape, device=rays.device
          )
          z_vals = lower + (upper - lower) * perturb_rand
  
      xyz_coarse_sampled = rays_o.unsqueeze(1) + rays_d.unsqueeze(
          1
      ) * z_vals.unsqueeze(
          2
      )  # (N_rays, N_samples, 3)
  
      return xyz_coarse_sampled, rays_o, rays_d, z_vals
  
file_path: slimmerf/dataLoader/ray_utils.py
imports: import torch, re
  import numpy
  from torch import searchsorted
  from kornia import create_meshgrid
label_desc: Use image node_id 10 for calling a global function with example usage: ray_marcher(rays, N_samples, lindisp, perturb, bbox_3D) and returns: xyz_coarse_sampled,  rays_o,  rays_d,  z_vals