/* @(#)FitsRGroup.java $Revision: 1.2 $ $Date: 2004/01/12 13:13:23 $ * * Copyright (C) 2000 European Southern Observatory * License: GNU General Public License version 2 or later */ package fr.unistra.pelican.util.jFits; import java.io.*; /** FitsRGroup class represents a FITS data matrix in the Random Group * format. * * @version $Revision: 1.2 $ $Date: 2004/01/12 13:13:23 $ * @author P.Grosbol, ESO, <pgrosbol@eso.org> */ public class FitsRGroup extends FitsData { private int noValues; private int dataFormat = Fits.FLOAT; private int bytesPerData = 4; private boolean scaling = false; private double zero = 0.0; private double scale = 1.0; private FitsWCS wcs; /** Constructor for FitsRGroup class given a FITS prime matrix or * an image extension header with associated data unit as a file. * * @param header FitsHeader object with the image header * @param file RandomAccess file positioned at the start of the * associated data unit * @param sflag Flag for storing data matrix internally * @exception FitsException */ public FitsRGroup(FitsHeader header, DataInput file, boolean sflag) throws FitsException { super(header, file, sflag); if (type != Fits.RGROUP) { throw new FitsException("Wrong header type", FitsException.HEADER); } int nax = naxis.length; FitsKeyword kw = header.getKeyword("BITPIX"); if ((kw == null) || (kw.getType() != FitsKeyword.INTEGER)) { throw new FitsException("Invalid or missing BITPIX", FitsException.HEADER); } dataFormat = kw.getInt(); bytesPerData = Math.abs(dataFormat)/8; noValues = (int) (size / bytesPerData); wcs = new FitsWCS(header); kw = header.getKeyword("BSCALE"); // check if scale is given if (kw!=null) { scale = kw.getReal(); if (scale != 1.0) { scaling = true; } } kw = header.getKeyword("BZERO"); // check if zero point is given if (kw!=null) { zero = kw.getReal(); if (zero != 0.0) { scaling = true; } } } /** Create and return a minimum FITS header for data Matrix. */ public FitsHeader getHeader() { FitsHeader hdr = new FitsHeader(); hdr.addKeyword(new FitsKeyword("SIMPLE", true, "Standard FITS format; NOST 100-2.0")); hdr.addKeyword(new FitsKeyword("BITPIX", bitpix, "No. of bits per pixel")); hdr.addKeyword(new FitsKeyword("NAXIS", naxis.length+1, "No. of axes in image")); hdr.addKeyword(new FitsKeyword("NAXIS1",0,"Random Groups convension")); for (int n=2; n<=naxis.length+1; n++) { hdr.addKeyword(new FitsKeyword("NAXIS"+n, naxis[n-2], "No. of pixels")); } hdr.addKeyword(new FitsKeyword("PCOUNT", noParm, "Parameter count")); hdr.addKeyword(new FitsKeyword("GCOUNT", noGroup, "Group count")); hdr.addKeyword(new FitsKeyword("GROUPS", true, "Random Groups format")); return hdr; } /** Gets set of data points from the matrix as a short values. * Only FITS file with BITPIX 8, 16 and 32 are read. * * @param offset pixel offset within hte data matrix * @param size no. of pixel values to be read * @param data array which will hold the return values. * If null an array of size is created. * @return data[] array updated with pixel values * @exception FitsException */ public short[] getShortValues(int offset, int size, short data[]) throws FitsException { if ((offset<0) || (size<1)) return data; if (noValues < offset+size) size = (int) (noValues - offset); if ((data == null) || (data.length<size)) data = new short[size]; int n = 0; DataInputStream dis = getStream(offset, size); try { switch (dataFormat) { case Fits.BYTE: while (n<size) data[n++] = (short) dis.readUnsignedByte(); break; case Fits.SHORT: while (n<size) data[n++] = dis.readShort(); break; case Fits.INT: while (n<size) data[n++] = (short) dis.readInt(); break; case Fits.FLOAT: case Fits.DOUBLE: default: return data; } } catch (IOException e) { throw new FitsException("Cannot convert data", FitsException.DATA); } if (scaling) { for (int i=0; i<n; i++) data[i] = (short) (scale*data[i]+zero); } return data; } /** Gets set of data points from the matrix as a int values. * Only FITS file with BITPIX 8, 16 and 32 are read. * * @param offset pixel offset within hte data matrix * @param size no. of pixel values to be read * @param data array which will hold the return values. * If null an array of size is created. * @return data[] array updated with pixel values * @exception FitsException */ public int[] getFloatValues(int offset, int size, int data[]) throws FitsException { if ((offset<0) || (size<1)) return data; if (noValues < offset+size) size = (int) (noValues - offset); if ((data == null) || (data.length<size)) data = new int[size]; int n = 0; DataInputStream dis = getStream(offset, size); try { switch (dataFormat) { case Fits.BYTE: while (n<size) data[n++] = (int) dis.readUnsignedByte(); break; case Fits.SHORT: while (n<size) data[n++] = (int) dis.readShort(); break; case Fits.INT: while (n<size) data[n++] = dis.readInt(); break; case Fits.FLOAT: case Fits.DOUBLE: default: return data; } } catch (IOException e) { throw new FitsException("Cannot convert data", FitsException.DATA); } if (scaling) { for (int i=0; i<n; i++) data[i] = (int) (scale*data[i]+zero); } return data; } /** Read set of data values from the matrix as a float array. The * values are returned as a float array. * * @param offset pixel offset within hte data matrix * @param size no. of pixel values to be read * @param data array which will hold the return values. * If null an array of size is created. * @return data[] array updated with pixel values * @exception FitsException */ public float[] getFloatValues(int offset, int size, float data[]) throws FitsException { if ((offset<0) || (size<1)) return data; if (noValues < offset+size) size = (int) (noValues - offset); if ((data == null) || (data.length<size)) data = new float[size]; int n = 0; DataInputStream dis = getStream(offset, size); try { switch (dataFormat) { case Fits.BYTE: while (n<size) data[n++] = (float) dis.readUnsignedByte(); break; case Fits.SHORT: while (n<size) data[n++] = (float) dis.readShort(); break; case Fits.INT: while (n<size) data[n++] = (float) dis.readInt(); break; case Fits.FLOAT: while (n<size) data[n++] = dis.readFloat(); break; case Fits.DOUBLE: while (n<size) data[n++] = (float) dis.readDouble(); break; default: return data; } } catch (IOException e) { throw new FitsException("Cannot convert data", FitsException.DATA); } if (scaling) { for (int i=0; i<n; i++) data[i] = (float) (scale*data[i]+zero); } return data; } private DataInputStream getStream(int offset, int size) throws FitsException { DataInputStream di; try { dataFile.seek(dataOffset+offset*bytesPerData); if (noValues < offset + size) { size = (int) (noValues - offset); } byte[] dbuf = new byte[size*bytesPerData]; dataFile.read(dbuf); di = new DataInputStream(new ByteArrayInputStream(dbuf)); } catch (IOException e) { throw new FitsException("Cannot read data", FitsException.DATA); } return di; } /** Gets the total number of data values in the data matrix. */ public int getNoValues(){ return noValues; } /** Gets reference pixel for the axes (see CRPIXn). */ public double[] getCrpix(){ return wcs.crpix; } /** Gets coordinate value for the reference pixel of the axes * (see CRVALn). */ public double[] getCrval(){ return wcs.crval; } /** Gets step size for the axes (see CDELTn). */ public double[] getCdelt(){ return wcs.cdelt; } /** Gets the WCS object for the image. */ public FitsWCS getWCS(){ return wcs; } /** Compute World Coordinates from pixel coordinates. * * @param pix Array with pixel coordinates */ public double[] toWCS(double[] pix) { return wcs.toWCS(pix); } /** Compute pixel coordinates from a set of World Coordinates. * * @param wc Array with World Coordinates */ public double[] toPixel(double[] wc) { return wcs.toPixel(wc); } }