/* @(#)FitsData.java $Revision: 1.8 $ $Date: 2004/01/12 13:13:23 $ * * Copyright (C) 2002 European Southern Observatory * License: GNU General Public License version 2 or later */ package fr.unistra.pelican.util.jFits; import java.io.*; /** FitsData class represents a FITS data unit * * @version $Revision: 1.8 $ $Date: 2004/01/12 13:13:23 $ * @author P.Grosbol, ESO, <pgrosbol@eso.org> */ public class FitsData { protected int type; protected int[] naxis; protected long size; protected int bitpix = 0; protected int noParm = 0; protected int noGroup = 1; protected boolean changeData = false; protected RandomAccessFile dataFile = null; protected long dataOffset = 0; protected byte[] dataArray = null; protected boolean isRAFile = false; /** Constructor for FitsData class given a FITS 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 FitsData(FitsHeader header, DataInput file, boolean sflag) throws FitsException { if (file instanceof RandomAccessFile) { dataFile = (RandomAccessFile) file; try { dataOffset = dataFile.getFilePointer(); } catch (IOException e) { throw new FitsException("Cannot read data offset", FitsException.FILE); } isRAFile = true; } size = header.getDataSize(); type = header.getType(); long skip = size; if (size%Fits.RECORD != 0) { skip = (size/Fits.RECORD+1)*Fits.RECORD; } try { if (sflag && !isRAFile) { dataArray = new byte[(int) skip]; file.readFully(dataArray); } else { file.skipBytes((int) skip); } } catch (IOException e) { throw new FitsException("Cannot read/skip over data matrix", FitsException.FILE); } decodeBasicHeader(header); } /** Constructor for FitsData class given the size of the data matrix. * An array equal to the size of the data matrix will be allocated. * * @param bitpix value of FITS BITPIX keyword bits/pixel * @param nax Integer array defining the dimensions of the * data matrix or for BINTABLE the heap size * @exception FitsException */ public FitsData(int bitpix, int nax[]) throws FitsException { switch (bitpix) { case Fits.BYTE : case Fits.SHORT : case Fits.INT : case Fits.FLOAT : case Fits.DOUBLE : this.bitpix = bitpix; break; default: throw new FitsException("Invalid BITPIX value", FitsException.DATA); } type = Fits.UNKNOWN; size = 1; naxis = new int[nax.length]; for (int n=0; n<nax.length; n++) { naxis[n] = nax[n]; size *= naxis[n]; } size *= Math.abs(this.bitpix)/8; if (size < 0) throw new FitsException("Data size less than zero", FitsException.DATA); long skip = size; if (size%Fits.RECORD != 0) { skip = (size/Fits.RECORD+1)*Fits.RECORD; } dataArray = new byte[(int) skip]; } /** Decodes basic header information for data matrix. * * @param header FITS header */ private void decodeBasicHeader(FitsHeader header) throws FitsException { FitsKeyword kw = header.getKeyword("NAXIS"); if (kw == null) { throw new FitsException("Missing NAXIS keyword", FitsException.HEADER); } int nax = kw.getInt(); naxis = new int[nax]; kw = header.getKeyword("BITPIX"); if (kw == null) { throw new FitsException("Missing BITPIX keyword", FitsException.HEADER); } bitpix = kw.getInt(); for (int n=1; n<=nax; n++) { kw = header.getKeyword("NAXIS"+n); if (kw == null) { throw new FitsException("Missing NAXISn keyword", FitsException.HEADER); } naxis[n-1] = kw.getInt(); } kw = header.getKeyword("GCOUNT"); noGroup = (kw == null) ? 1 : kw.getInt(); kw = header.getKeyword("PCOUNT"); noParm = (kw == null) ? 0 : kw.getInt(); changeData = false; } /** 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, "No. of axes in image")); for (int n=1; n<=naxis.length; n++) { hdr.addKeyword(new FitsKeyword("NAXIS"+n, naxis[n-1], "No. of pixels")); } hdr.addKeyword(new FitsKeyword("PCOUNT", 0, "Parameter count")); hdr.addKeyword(new FitsKeyword("GCOUNT", 1, "Groupe count")); return hdr; } /** Write data martix to DataOutput stream. * * @param file DataOutput stream to which data are written * @exception IOException, FitsException */ public void writeFile(DataOutput file) throws IOException, FitsException { byte[] buf; int nbytes = 0; int block = 10*Fits.RECORD; if (isRAFile) { buf = new byte[block]; dataFile.seek(dataOffset); int nrec = (int) size/block; // write large block first while (0<nrec--) { dataFile.read(buf); file.write(buf); } nbytes = (int) size%block; // and then the remaining blocks if (nbytes == 0) return; buf = new byte[nbytes]; dataFile.read(buf); file.write(buf); } else if (dataArray != null) { file.write(dataArray); } if (nbytes%Fits.RECORD != 0) { // finally fill with zeros nbytes = Fits.RECORD*(nbytes/Fits.RECORD + 1) - nbytes; buf = new byte[nbytes]; if (type == Fits.ATABLE) { // or if ASCII table the space fill for (int n=0; n<nbytes; n++) buf[n] = 0x20; } file.write(buf); } } /** Closes the associated data file */ public void closeFile(){ dataFile = null; dataOffset = 0; size = 0; type = 0; } /** Retrives number of axes defined for the data unit (ref. NAXIS) */ public int getNoAxes(){ return naxis.length; } /** Gets FITS type of data unit. This is specified in the * assocated header such as Fits.IMAGE or Fits.BTABLE */ public int getType(){ return type; } /** Gets the dimentions of the axes. This is defined for the data * unit by the NAXISn keywords. */ public int[] getNaxis(){ return naxis; } }