def compute_scale(wcs: WCS, fiducial: Union[tuple, np.ndarray]) -> float: """Compute scaling transform. Parameters ---------- wcs : `~gwcs.wcs.WCS` Reference WCS object from which to compute a scaling factor. fiducial : tuple Input fiducial of (RA, DEC) used in calculating reference points. Returns ------- scale : float Scaling factor for x and y. """ if len(fiducial) != 2: raise ValueError(f'Input fiducial must contain only (RA, DEC); Instead recieved: {fiducial}') crpix = np.array(wcs.invert(*fiducial)) crpix_with_offsets = np.vstack((crpix, crpix + (1, 0), crpix + (0, 1))).T crval_with_offsets = wcs(*crpix_with_offsets) coords = SkyCoord(ra=crval_with_offsets[0], dec=crval_with_offsets[1], unit="deg") xscale = np.abs(coords[0].separation(coords[1]).value) yscale = np.abs(coords[0].separation(coords[2]).value) return np.sqrt(xscale * yscale)
def compute_scale(wcs: WCS, fiducial: Union[tuple, np.ndarray], disp_axis: int = None, pscale_ratio: float = None) -> float: """Compute scaling transform. Parameters ---------- wcs : `~gwcs.wcs.WCS` Reference WCS object from which to compute a scaling factor. fiducial : tuple Input fiducial of (RA, DEC) or (RA, DEC, Wavelength) used in calculating reference points. disp_axis : int Dispersion axis integer. Assumes the same convention as `wcsinfo.dispersion_direction` pscale_ratio : int Ratio of input to output pixel scale Returns ------- scale : float Scaling factor for x and y or cross-dispersion direction. """ spectral = 'SPECTRAL' in wcs.output_frame.axes_type if spectral and disp_axis is None: raise ValueError('If input WCS is spectral, a disp_axis must be given') crpix = np.array(wcs.invert(*fiducial)) delta = np.zeros_like(crpix) spatial_idx = np.where( np.array(wcs.output_frame.axes_type) == 'SPATIAL')[0] delta[spatial_idx[0]] = 1 crpix_with_offsets = np.vstack( (crpix, crpix + delta, crpix + np.roll(delta, 1))).T crval_with_offsets = wcs(*crpix_with_offsets) coords = SkyCoord(ra=crval_with_offsets[spatial_idx[0]], dec=crval_with_offsets[spatial_idx[1]], unit="deg") xscale = np.abs(coords[0].separation(coords[1]).value) yscale = np.abs(coords[0].separation(coords[2]).value) if pscale_ratio is not None: xscale = xscale * pscale_ratio yscale = yscale * pscale_ratio if spectral: # Assuming scale doesn't change with wavelength # Assuming disp_axis is consistent with DataModel.meta.wcsinfo.dispersion.direction return yscale if disp_axis == 1 else xscale return np.sqrt(xscale * yscale)