Skip to content

Native equirectangular SPH projection

SPHProjector accepts a central mono camera with view: equirectangular. It projects particles directly onto a full sphere, using one particle pass per field and frame. No cube-face renders or stitching are required. [AI-Codex]

dataset_type: pointcloud_sph
driver_type: sphprojector
device: cpu-openmp
pointcloud_sph:
  loader: gadget
  gadget:
    path: /path/to/snapshot.hdf5
    fields: [Masses, MaxDist]
sphprojector:
  outputpath: panorama.zr
  overwrite: false
  pbc: false
  operators:
    projections:
      mode: manual
      view: equirectangular
      npixels: [3840, 1920]
      position: [0.5, 0.5, 0.5]
      direction: [1, 0, 0]
      up: [0, 0, 1]
      fields: [Masses]
      normalization: camera_flux
      near_clip: 0
      target_cells_per_h: 4

The dataset must supply MaxDist support radii through its existing loader or field recipe. This projection adds no neighbor search. Loading a point cloud may still build its spatial index. For TNG gas the existing mass/density MaxDist recipe can be retained.

Camera and array contract

The camera position and support radii use normalized loader-box coordinates. The center pixel looks along direction; north follows up, and screen-right is direction × up. Longitude wraps behind the camera. The output Zarr array has shape (width, height) with y increasing upward; convert to ordinary image order with np.flipud(array.T).

The requested dimensions must be positive and 2:1, and are preserved exactly, including non-power-of-two sizes such as 3840×1920. Omit widths and fov_up; the angular extent is always 360°×180°. near_clip is a radial distance along each ray, defaults to zero, and must be finite and nonnegative.

This first version supports mono and a finite dataset (pbc: false). It rejects stereoscopic spherical rasterization. Omnidirectional stereo requires a direction-dependent eye model. The historical raytracer's fixed world-axis equirectangular orientation is preserved explicitly; it is not the SPH camera-basis convention.

Kernel and units

The historical planar kernel is the complete line integral of

\[ W_{3D}(r,h)=\frac{15}{8\pi h^3}\max(1-r^2/h^2,0). \]

Spherical SPH integrates this same kernel along each forward ray from near_clip to infinity. The integral is analytic, including when a kernel contains the observer or intersects the near clip. A camera at the kernel center has finite, uniform intensity, rather than a singular point-source distance factor.

  • camera_flux returns sum(q * ray_integral), in quantity per normalized box length squared. There is no focal-plane scale and no extra 1/r² multiplier. For a compact distant source its solid-angle-integrated signal approaches q/distance².
  • mean divides the weighted quantity integral by the weight integral; weight: Masses is supported when that field is loaded. Empty rays are zero.
  • column_integral and mass_projection are rejected for this camera, since their planar conversions do not describe these spherical image values.

These are ray intensities, not flux integrated over a pixel. Integrate with pixel solid angles, which vary with latitude. The helper equirectangular::pixelSolidAngle gives their exact values.

Perspective camera_flux retains its previous focal-plane normalization. Calibrate new display limits for native spherical arrays; do not transplant perspective color limits. Keep raw arrays before colormaps and annotations.

Quality and validation

The common SPH deposition, field dispatch, and grid collapse are shared with planar rendering. Spherical footprints select candidate cells using angular caps; longitude wraps, and coarse-grid interpolation reflects across poles with a half-turn in longitude. Grid selection uses actual angular spacing. target_cells_per_h controls samples per angular support radius; the default is 4, and 8 improves the multilevel approximation. The finest image resolution still limits sampling of unresolved particles. single_level: true deposits directly on that finest grid and is useful as a numerical reference.

Run thor_tests '[sph_spherical]' for independent 3D quadrature, seam/pole coverage, near clipping, constant fields, inverse-square asymptotics, native rectangular output, and multilevel convergence. Existing planar, tetrahedron, camera and output-writer tests cover the shared paths. A standalone visual smoke is in companion thor_setups/validations/sph-equirectangular/smoke.py.