Public Geometry API
The pyampp.geometry package is the public, headless geometry surface for
observer-aware projection and field-of-view calculations. It promotes the
tested gxbox geometry kernel into an import path that downstream code can rely
on without depending on the GUI or viewer entrypoints.
Canonical Model Loading Requirement
Geometry consumers should use pyampp.io for model restore so contract
completion and observer normalization happen before geometry APIs are called.
Use:
pyampp.io.load_model
Avoid direct application-level restores through low-level readers such as
pyampp.gxbox.boxutils.read_b3d_h5 for new code.
read_b3d_h5 now delegates to pyampp.io.load_model and therefore
inherits contract completion and observer normalization, but pyampp.io
remains the canonical, stable app-level surface with clearer return-type
expectations.
Scope of This Update
This update cycle establishes the public Python geometry contract in pyAMPP. The immediate goals are:
expose the stable import surface through
pyampp.geometrypreserve existing gxbox behavior by routing current methods through wrappers
keep all transforms vectorized for arbitrary point sets and box corners
defer downstream adoption in gximagecomputing until this API is reviewed and merged upstream
Public Import Surface
Downstream consumers should import from pyampp.geometry rather than from
pyampp.gxbox internals.
Current public exports include:
local_cartesian_to_worldproject_world_to_observer_hpcproject_world_to_observer_hcccompute_inscribing_fov_from_hpccompute_inscribing_fov_from_worldcompute_inscribing_fov_box_from_worldobserver_fov_box_to_world_cornersobserver_rectangle_to_hpc_cornersproject_coordinate_edges_to_observer_hpcproject_box_front_face_to_observer_hpcproject_world_to_pixelobserver-resolution helpers re-exported from
pyampp.geometry.observer
Compatibility wrappers are still exposed through Box and
BoxGeometryMixin, but these names are transitional compatibility surfaces.
New downstream code should prefer the function-level API where possible.
Current Migration Status
Already migrated in this branch:
box local-to-world conversion
observer HPC/HCC projection for box corners
inscribing FOV and observer-aligned FOV-box computation
saved
fov_boxworld-corner reconstructionfield-line projection in the 2D viewer
FOV-box projected edge and front-face overlays in the 2D viewer
Still intentionally wrapper-backed:
existing gxbox box methods remain available and delegate into the public core
public observer helpers currently forward to the tested gxbox observer module
Deferred until after pyAMPP merge:
replacing gximagecomputing’s local Python geometry implementation with imports from
pyampp.geometry
Function Contracts
local_cartesian_to_world(local_points_mm, frame, z_base_mm=0.0)
Input: an
(N, 3)array of local Cartesian points in MmOutput: a vectorized
SkyCoordin the supplied world frameReturns
Nonewhen inputs are missing, invalid, or contain non-finite rows
project_world_to_observer_hpc(world, observer=None, obstime=None, frame_obs=None)
Input: any vectorized coordinates with a meaningful frame
Output: helioprojective coordinates for the resolved observer frame
Returns
Nonewhen the observer context cannot be resolved
compute_inscribing_fov_from_world(world, ...)
Input: arbitrary 3D world-space point set
Output: smallest axis-aligned observer HPC rectangle covering the projected points
Returns a dictionary with center, extent, bounds, and projected coordinates
compute_inscribing_fov_box_from_world(world, ...)
Input: arbitrary 3D world-space point set
Output: observer-aligned 3D
fov_boxmetadata with 2D footprint and Z extentZ padding remains explicit through
pad_z_frac
observer_fov_box_to_world_corners(...)
Input: saved observer
fov_boxmetadata and target frameOutput: 8 reconstructed world-space corners suitable for reprojection or parity checks
observer_rectangle_to_hpc_corners(...)
Input: observer-centered 2D rectangle definition in arcsec
Output: 4 helioprojective rectangle corners in the specified observer frame
project_coordinate_edges_to_observer_hpc(coords, edge_pairs, ...)
Input: vectorized coordinates and an edge-pair list
Output: list of projected 2-point
SkyCoordedges in observer HPCIntended for box overlays and arbitrary polyline edge sets
project_box_front_face_to_observer_hpc(world_corners, ...)
Input: 8 world-space box corners
Output: the observer-nearest projected face as a closed 5-point
SkyCoordpolygon
project_world_to_pixel(world, smap)
Input: vectorized world coordinates and a SunPy map
Output: two NumPy arrays
(x, y)in pixel coordinates
Examples
Load a model through the canonical I/O path, then call geometry:
from pyampp import io, geometry
model = io.load_model("/path/to/model.h5")
contract = model["metadata"]["geometry_contract"]
red_world = geometry.world_corners_from_geometry_contract(contract)
Convert local model points to world coordinates:
world = local_cartesian_to_world(local_points_mm, frame=box_center.frame, z_base_mm=grid_z_base)
Project arbitrary 3D points into an observer image plane:
coords_hpc = project_world_to_observer_hpc(world, frame_obs=frame_obs)
xpix, ypix = project_world_to_pixel(coords_hpc, smap)
Compute an inscribing 2D FOV or 3D FOV-box from one vectorized point set:
fov = compute_inscribing_fov_from_world(world, frame_obs=frame_obs)
fov_box = compute_inscribing_fov_box_from_world(world, frame_obs=frame_obs)
Reconstruct and reproject a saved observer fov_box:
corners_world = observer_fov_box_to_world_corners(
xc_arcsec=meta["xc_arcsec"],
yc_arcsec=meta["yc_arcsec"],
xsize_arcsec=meta["xsize_arcsec"],
ysize_arcsec=meta["ysize_arcsec"],
zmin_mm=meta["zmin_mm"],
zmax_mm=meta["zmax_mm"],
observer=observer,
obstime=obs_time,
target_frame=box_center.frame,
)
face = project_box_front_face_to_observer_hpc(corners_world, frame_obs=frame_obs)
Reviewer Notes
The intended review standard for this PR is behavioral parity with the current gxbox workflows, not a broad geometry rewrite. The public API is designed to be adopted downstream first, then become the single shared geometry path in later repo updates.