stdpipe.astrometry_wcs module

stdpipe.astrometry_wcs.fit_zpn_wcs_from_points(xy: ndarray, sky: SkyCoord, wcs_init: WCS, pv_deg: int = 5, fit_crpix: bool = True, fit_crval: bool = True, fit_cd: bool = True, fit_pv: bool = True, robust_loss: str = 'soft_l1', f_scale_arcsec: float = 2.0, max_nfev: int = 200, verbose: bool = False)[source]

Fit a ZPN WCS by optimizing WCS parameters against matched (x,y) <-> (ra,dec).

Parameters:
xy(N,2) array

Pixel coordinates (0-based as in astropy WCS, i.e. origin=0).

skySkyCoord (N)

Reference sky positions.

wcs_initastropy.wcs.WCS

Initial WCS; MUST already be ZPN (RA—ZPN/DEC–ZPN) or at least usable as base.

pv_degint

Degree for PV2_m coefficients to fit (PV2_0..PV2_pv_deg).

fit_*bool

Toggle which parameter blocks to optimize.

robust_lossstr

Passed to scipy.optimize.least_squares(loss=…). Good options: ‘linear’, ‘soft_l1’, ‘huber’, ‘cauchy’.

f_scale_arcsecfloat

Robust loss scale in arcsec.

max_nfevint

Optimization iterations (SciPy).

verbosebool or callable

Whether to show verbose messages during the run of the function or not. May also be a print-like function.

Returns:
wcs_bestastropy.wcs.WCS
resultscipy OptimizeResult (or None if nothing was fitted)

Notes

For stability, the solver runs in two stages when fit_pv is True: it first fits CRPIX/CRVAL/CD with PV fixed, then fits all free parameters (including PV) with conservative bounds to prevent invalid projections.

stdpipe.astrometry_wcs.tan_wcs_to_zpn(w_tan: WCS, pv_deg: int = 5, n_samples: int = 256, theta_max_deg: float | None = None) WCS[source]

Convert a celestial TAN WCS into a ZPN WCS with PV2_m initialized to approximate TAN.

Parameters:
w_tanastropy.wcs.WCS

Input TAN WCS (2D celestial).

pv_degint

Highest PV degree to initialize (PV2_0..PV2_pv_deg). 5–9 is usually plenty; higher can get wiggly.

n_samplesint

Samples used for the polynomial fit.

theta_max_degfloat or None

Max angular radius (deg) over which to match TAN. If None, estimated from image footprint corners using pixel_shape.

Returns:
w_zpnastropy.wcs.WCS

A ZPN WCS with same CRVAL/CRPIX/CD and PV2_m initialized.

Notes

TAN (gnomonic) radial law: r = tan(theta) [in radians] In “degrees” units (common in FITS WCS plane coordinates), that’s:

r_deg = tan(theta_rad) * (180/pi)

ZPN radial law: r_deg ≈ sum_{m=0..M} PV2_m * theta_deg^m We set PV2_0 = 0 and fit PV2_1..PV2_M to approximate the TAN law over theta in [0, theta_max_deg].

SIP and other pixel-space distortions of the input WCS are dropped (they are not representable in the radial ZPN model); refit them on top of the result if needed, e.g. with _fit_zpn_sip().

stdpipe.astrometry_wcs.convert_wcs_projection(wcs_input: WCS, target_projection: str, pv_deg: int = 5) WCS[source]

Convert a celestial WCS to a different projection type.

Parameters:
wcs_inputWCS

Input WCS (any celestial projection).

target_projectionstr

Target projection code, e.g. 'TAN', 'ZPN', 'STG', 'ARC', 'ZEA', 'SIN', etc.

pv_degint, optional

ZPN PV polynomial degree (only used when target_projection is 'ZPN'). Default 5.

Returns:
WCS

New WCS with the target projection. For ZPN the PV coefficients are initialised from the TAN radial law — an exact match for TAN input, and a generic starting point (meant to be refined by a subsequent fit) for other input projections. For other targets CRPIX/CRVAL/CD are copied and CTYPE is replaced, so the mapping away from the reference point changes; refit afterwards.

stdpipe.astrometry_wcs.fit_wcs_from_points(xy, world_coords, proj_point='center', projection=None, sip_degree=None, pv_deg=5, verbose=False)[source]

Drop-in wrapper around astropy.wcs.utils.fit_wcs_from_points() that also handles ZPN projection (which astropy does not natively fit) and ZPN-SIP (ZPN radial distortion plus SIP polynomial corrections).

Parameters:
xytuple of arrays (x, y) or (2, N) array

Pixel coordinates (same convention as the astropy function).

world_coords~astropy.coordinates.SkyCoord

Reference sky positions.

proj_pointstr, optional

Passed through to astropy for non-ZPN projections. Ignored for ZPN, where the projection center comes from the template WCS.

projection~astropy.wcs.WCS or other, optional

Projection template. If this is a WCS with RA---ZPN / DEC--ZPN CTYPEs, the ZPN fitter is used instead of astropy’s.

sip_degreeint or None, optional

SIP polynomial degree. For TAN projections, controls SIP distortion order. For ZPN projections, if > 0, SIP corrections are fitted on top of ZPN PV parameters to capture non-radial distortions. For other projections it is ignored (SIP is not standard there).

pv_degint, optional

ZPN PV polynomial degree (PV2_0 PV2_pv_deg). Default 5.

verbosebool or callable, optional

Whether to show verbose messages during the run of the function or not. May also be a print-like function.

Returns:
wcs~astropy.wcs.WCS

Fitted WCS (same return type as the astropy function).