class_docstr: Finds the intersection points of rays with the implicit surface defined
  by a signed distance function (SDF). The algorithm follows the pipeline:
  1. Initialise start and end points on rays by the intersections with
      the circumscribing sphere.
  2. Run sphere tracing from both ends.
  3. Divide the untraced segments of non-convergent rays into uniform
      intervals and find the one with the sign transition.
  4. Run the secant method to estimate the point of the sign transition.
  
  Args:
      object_bounding_sphere: The radius of the initial sphere circumscribing
          the object.
      sdf_threshold: Absolute SDF value small enough for the sphere tracer
          to consider it a surface.
      line_search_step: Length of the backward correction on sphere tracing
          iterations.
      line_step_iters: Number of backward correction iterations.
      sphere_tracing_iters: Maximum number of sphere tracing iterations
          (the actual number of iterations may be smaller if all ray
          intersections are found).
      n_steps: Number of intervals sampled for unconvergent rays.
      n_secant_steps: Number of iterations in the secant algorithm.
class_docstr_tok: ["Finds","the","intersection","points","of","rays","with","the","implicit","surface","defined","by","a","signed","distance","function","(","SDF",")",".","The","algorithm","follows","the","pipeline",":","1",".","Initialise","start","and","end","points","on","rays","by","the","intersections","with","the","circumscribing","sphere",".","2",".","Run","sphere","tracing","from","both","ends",".","3",".","Divide","the","untraced","segments","of","non-convergent","rays","into","uniform","intervals","and","find","the","one","with","the","sign","transition",".","4",".","Run","the","secant","method","to","estimate","the","point","of","the","sign","transition",".","Args",":","object_bounding_sphere",":","The","radius","of","the","initial","sphere","circumscribing","the","object",".","sdf_threshold",":","Absolute","SDF","value","small","enough","for","the","sphere","tracer","to","consider","it","a","surface",".","line_search_step",":","Length","of","the","backward","correction","on","sphere","tracing","iterations",".","line_step_iters",":","Number","of","backward","correction","iterations",".","sphere_tracing_iters",":","Maximum","number","of","sphere","tracing","iterations","(","the","actual","number","of","iterations","may","be","smaller","if","all","ray","intersections","are","found",")",".","n_steps",":","Number","of","intervals","sampled","for","unconvergent","rays",".","n_secant_steps",":","Number","of","iterations","in","the","secant","algorithm","."]
docstr: Sample the ray in a given range and run secant on rays which have sign transition.
  
  Args:
      sdf:
      cam_loc:
      object_mask:
      ray_directions:
      sampler_min_max:
      sampler_mask:
  
  Returns:
docstr_tok: ["Sample","the","ray","in","a","given","range","and","run","secant","on","rays","which","have","sign","transition",".","Args",":","sdf",":","cam_loc",":","object_mask",":","ray_directions",":","sampler_min_max",":","sampler_mask",":","Returns",":"]
code: def ray_sampler(
      self,
      sdf: Callable[[torch.Tensor], torch.Tensor],
      cam_loc: torch.Tensor,
      object_mask: torch.Tensor,
      ray_directions: torch.Tensor,
      sampler_min_max: torch.Tensor,
      sampler_mask: torch.Tensor,
  ) -> Tuple[torch.Tensor, torch.Tensor, torch.Tensor]:
      """
      Sample the ray in a given range and run secant on rays which have sign transition.
  
      Args:
          sdf:
          cam_loc:
          object_mask:
          ray_directions:
          sampler_min_max:
          sampler_mask:
  
      Returns:
  
      """
  
      batch_size, num_pixels, _ = ray_directions.shape
      device = cam_loc.device
      n_total_pxl = batch_size * num_pixels
      sampler_pts = torch.zeros(n_total_pxl, 3, device=device)
      sampler_dists = torch.zeros(n_total_pxl, device=device)
  
      intervals_dist = torch.linspace(
          0, 1, steps=self.n_steps, device=device
      ).view(1, 1, -1)
  
      pts_intervals = sampler_min_max[:, :, 0].unsqueeze(
          -1
      ) + intervals_dist * (
          sampler_min_max[:, :, 1] - sampler_min_max[:, :, 0]
      ).unsqueeze(
          -1
      )
      points = (
          cam_loc[..., None, :]
          + pts_intervals[..., None] * ray_directions[..., None, :]
      )
  
      # Get the non convergent rays
      mask_intersect_idx = torch.nonzero(sampler_mask).flatten()
      points = points.reshape((-1, self.n_steps, 3))[sampler_mask, :, :]
      pts_intervals = pts_intervals.reshape((-1, self.n_steps))[
          sampler_mask
      ]
  
      sdf_val_all = []
      for pnts in torch.split(points.reshape(-1, 3), 100000, dim=0):
          sdf_val_all.append(sdf(pnts))
      sdf_val = torch.cat(sdf_val_all).reshape(-1, self.n_steps)
  
      tmp = torch.sign(sdf_val) * torch.arange(
          self.n_steps, 0, -1, device=device, dtype=torch.float32
      ).reshape(1, self.n_steps)
      # Force argmin to return the first min value
      sampler_pts_ind = torch.argmin(tmp, -1)
      sampler_pts[mask_intersect_idx] = points[
          torch.arange(points.shape[0]), sampler_pts_ind, :
      ]
      sampler_dists[mask_intersect_idx] = pts_intervals[
          torch.arange(pts_intervals.shape[0]), sampler_pts_ind
      ]
  
      true_surface_pts = object_mask.reshape(-1)[sampler_mask]
      net_surface_pts = (
          sdf_val[torch.arange(sdf_val.shape[0]), sampler_pts_ind] < 0
      )
  
      # take points with minimal SDF value for P_out pixels
      p_out_mask = ~(true_surface_pts & net_surface_pts)
      n_p_out = p_out_mask.sum()
      if n_p_out > 0:
          out_pts_idx = torch.argmin(sdf_val[p_out_mask, :], -1)
          sampler_pts[mask_intersect_idx[p_out_mask]] = points[
              p_out_mask, :, :
          ][
              # pyre-fixme[6]: For 1st param expected `Union[bool, float, int]`
              #  but got `Tensor`.
              torch.arange(n_p_out),
              out_pts_idx,
              :,
          ]
          sampler_dists[mask_intersect_idx[p_out_mask]] = pts_intervals[
              p_out_mask,
              :
              # pyre-fixme[6]: For 1st param expected `Union[bool, float, int]` but
              #  got `Tensor`.
          ][torch.arange(n_p_out), out_pts_idx]
  
      # Get Network object mask
      sampler_net_obj_mask = sampler_mask.clone()
      sampler_net_obj_mask[mask_intersect_idx[~net_surface_pts]] = False
  
      # Run Secant method
      secant_pts = (
          net_surface_pts & true_surface_pts
          if self.training
          else net_surface_pts
      )
      n_secant_pts = secant_pts.sum()
      if n_secant_pts > 0:
          # Get secant z predictions
          z_high = pts_intervals[
              torch.arange(pts_intervals.shape[0]), sampler_pts_ind
          ][secant_pts]
          sdf_high = sdf_val[
              torch.arange(sdf_val.shape[0]), sampler_pts_ind
          ][secant_pts]
          z_low = pts_intervals[secant_pts][
              # pyre-fixme[6]: For 1st param expected `Union[bool, float, int]`
              #  but got `Tensor`.
              torch.arange(n_secant_pts),
              sampler_pts_ind[secant_pts] - 1,
          ]
          sdf_low = sdf_val[secant_pts][
              # pyre-fixme[6]: For 1st param expected `Union[bool, float, int]`
              #  but got `Tensor`.
              torch.arange(n_secant_pts),
              sampler_pts_ind[secant_pts] - 1,
          ]
          cam_loc_secant = cam_loc.reshape(-1, 3)[
              mask_intersect_idx[secant_pts]
          ]
          ray_directions_secant = ray_directions.reshape((-1, 3))[
              mask_intersect_idx[secant_pts]
          ]
          z_pred_secant = self.secant(
              sdf_low,
              sdf_high,
              z_low,
              z_high,
              cam_loc_secant,
              ray_directions_secant,
              # pyre-fixme[6]: For 7th param expected `Module` but got `(Tensor)
              #  -> Tensor`.
              sdf,
          )
  
          # Get points
          sampler_pts[mask_intersect_idx[secant_pts]] = (
              cam_loc_secant
              + z_pred_secant.unsqueeze(-1) * ray_directions_secant
          )
          sampler_dists[mask_intersect_idx[secant_pts]] = z_pred_secant
  
      return sampler_pts, sampler_net_obj_mask, sampler_dists
  
file_path: pytorch3d/pytorch3d/implicitron/models/renderer/ray_tracing.py
imports: from typing import Any, Callable, Tuple
  import torch
  import torch.nn
  from pytorch3d.implicitron.tools.config import Configurable
label_desc: Use image node_id 3 for calling the RayTracing obj's underlying member method code with example usage: obj.ray_sampler(sdf, cam_loc, object_mask, ray_directions, sampler_min_max, sampler_mask) and returns: sampler_pts,  sampler_net_obj_mask,  sampler_dists