/* @(#)FitsWCS.java $Revision: 1.4 $ $Date: 2004/01/12 13:13:23 $ * * Copyright (C) 2003 European Southern Observatory * License: GNU General Public License version 2 or later */ package fr.unistra.pelican.util.jFits; /** FitsData class represents a FITS data unit * * @version $Revision: 1.4 $ $Date: 2004/01/12 13:13:23 $ * @author P.Grosbol, DMD/ESO, <pgrosbol@eso.org> */ public class FitsWCS { public final static int LIN = 0; public final static int TAN = 1; public final static int ARC = 2; private final static int MPS = 20; protected int type; protected int nax = 0; protected int[] cproj; protected double[] crpix; protected double[] crval; protected double[] cdelt; protected double[] crota; protected String[] ctype; protected double[][] cdMatrix; protected double[][] pcMatrix; protected boolean hasPcMatrix = false; protected boolean hasCdMatrix = false; protected double[] amdx = new double[MPS]; protected double[] amdy = new double[MPS]; /** Default constructor for FitsWCS class. */ public FitsWCS() { type = Fits.UNKNOWN; } /** Constructor for FitsWCS class given a FITS header with * associated data unit as a file. * * @param header FitsHeader object with the image header */ public FitsWCS(FitsHeader header) { this(); setHeader(header, ' '); } /** Constructor for FitsWCS class given a FITS header with * associated data unit as a file. * * @param header FitsHeader object with the image header * @param ver version of WCS i.e. ' ' or 'A'..'Z' */ public FitsWCS(FitsHeader header, char ver) { this(); setHeader(header, ver); } /** Constructor for FitsWCS given number of axes * * @param nax Number of axes in data matrix */ public FitsWCS(int nax) { this(); init(nax); } /** Define FITS header for FitsWCS object. * * @param header FitsHeader object with the image header * @param ver version of WCS i.e. ' ' or 'A'..'Z' */ public void setHeader(FitsHeader header, char ver) { type = header.getType(); FitsKeyword kw = header.getKeyword("NAXIS"); nax = (kw == null) ? 0 : kw.getInt(); init(nax); String sver = String.valueOf(ver).toUpperCase().trim(); for (int j=1; j<=nax; j++) { kw = header.getKeyword("CRPIX"+j+sver); crpix[j-1] = (kw == null) ? 0.0 : kw.getReal(); kw = header.getKeyword("CRVAL"+j+sver); crval[j-1] = (kw == null) ? 0.0 : kw.getReal(); kw = header.getKeyword("CDELT"+j+sver); cdelt[j-1] = (kw == null) ? 1.0 : kw.getReal(); cdMatrix[j-1][j-1] = cdelt[j-1]; kw = header.getKeyword("CTYPE"+j+sver); ctype[j-1] = (kw == null) ? " " : kw.getString(); if (7<ctype[j-1].length()) { String wctype = ctype[j-1].substring(5, 7); if (wctype.equals("TAN")) { cproj[j-1] = TAN; } else if (wctype.equals("ARC")) { cproj[j-1] = ARC; } else { cproj[j-1] = LIN; } } else { cproj[j-1] = LIN; } for (int i=1; i<=nax; i++) { kw = header.getKeyword("CD"+j+"_"+j+sver); if (kw != null) { cdMatrix[j-1][i-1] = kw.getReal(); hasCdMatrix = true; } } for (int i=1; i<=nax; i++) { kw = header.getKeyword("PC"+j+"_"+i+sver); if (kw != null) { pcMatrix[j-1][i-1] = kw.getReal(); hasPcMatrix = true; } } } for (int j=1; j<MPS; j++) { kw = header.getKeyword("AMDX"+j); amdx[j-1] = (kw == null) ? 0.0 : kw.getReal(); kw = header.getKeyword("AMDY"+j); amdy[j-1] = (kw == null) ? 0.0 : kw.getReal(); } } /** Initiate internal WCS data structures. * * @param nax No. of axies of data array */ private void init(int nax) { cproj = new int[nax]; crpix = new double[nax]; crval = new double[nax]; cdelt = new double[nax]; ctype = new String[nax]; cdMatrix = new double[nax][nax]; pcMatrix = new double[nax][nax]; ctype = new String[nax]; for (int n=0; n<nax; n++) { cproj[n] = LIN; crpix[n] = 0.0; crval[n] = 0.0; cdelt[n] = 1.0; ctype[n] = " "; for (int i=0; i<nax; i++) { cdMatrix[n][i] = (i==n) ? 1.0 : 0.0; pcMatrix[n][i] = (i==n) ? 1.0 : 0.0; } } } /** Compute World Coordinates from pixel coordinates. * * @param p Array with pixel coordinates */ public double[] toWCS(double[] p) { double[] w; double[] q; for (int j=0; j<nax; j++) p[j] -= crpix[j]; if (hasPcMatrix) { q = matrixMult(pcMatrix, p); for (int j=0; j<nax; j++) q[j] *= cdelt[j]; } else if (hasCdMatrix) { q = matrixMult(cdMatrix, p); } else { q = p; for (int j=0; j<nax; j++) q[j] *= cdelt[j]; } switch (cproj[0]) { case TAN: case LIN: for (int j=0; j<nax; j++) q[j] += crval[j]; } return q; } /** Compute pixel coordinates from a set of World Coordinates. * * @param wcs Array with World Coordinates */ public double[] toPixel(double[] wcs) { double[] pix = new double[nax]; double[] wc = new double[nax]; for (int n=0; n<nax; n++) { pix[n] = (wcs[n]-crval[n])/cdelt[n] + crpix[n]; } return pix; } private double[] matrixMult(double[][] mtx, double[] vec) { int nv = vec.length; double[] res = new double[nv]; for (int j=0; j<nv; j++) { res[j] = 0; for (int i=0; i<nv; i++) { res[j] += mtx[j][i] * vec[i]; } } return res; } }