/* @(#)FitsColumn.java $Revision: 1.6 $ $Date: 2004/01/12 13:13:23 $ * * Copyright (C) 1999 European Southern Observatory * License: GNU General Public License version 2 or later */ package fr.unistra.pelican.util.jFits; import java.io.*; /** FitsColumn class represents a FITS table column in either ASCII or * BINARY table format. Note: only binary data formats A,L,I,J,E,D * are fully supported. * * @version $Revision: 1.6 $ $Date: 2004/01/12 13:13:23 $ * @author P.Grosbol, ESO, <pgrosbol@eso.org> */ public class FitsColumn { private String stringNull = null; private long intNull; private boolean intNullDefined = false; private int repeat = 1; private char dataType = '\0'; private long columnOffset = 0; private int recordSize = 0; private FitsTform format; private int bytesPerData = 0; private long noRows = 0; private boolean binColumn = true; private String display; private String label; private String unit; private double zero; private double scale; private boolean scaling = false; private RandomAccessFile dataFile = null; private long dataOffset = 0; private boolean isRAFile = true; private byte[] dataArray = null; /** Constructor for FitsColumn class from a file * * @param type storage type of column i.e. Fits.ATABLE or * Fits.BTABLE, by default Fits.BTABLE is assumed * @param tform storage format of data in column * @param label name of column * @param rows no. of rows in the column * @exception FitsException */ public FitsColumn(int type, String tform, String label, int rows) throws FitsException { this.format = new FitsTform(tform); this.dataType = format.getDataType(); this.repeat = format.getRepeat(); this.bytesPerData = format.getWidth(); this.label = label; this.noRows = rows; this.binColumn = (type == Fits.BTABLE); } /** Sets data matrix with the table data as a RandomAcessFile. * * @param file associated RandomAccessFile with FITS data * @param dataOffset byte offset of the table data unit in the FITS file * @param position relative byte start position of of column data * within record (first byte is 0) * @param recordSize byte size of table record */ public void setData(RandomAccessFile file, long dataOffset, int position, int recordSize) { dataFile = file; this.dataOffset = dataOffset; isRAFile = true; this.columnOffset = position; this.recordSize = recordSize; } /** Sets data matrix with the table data as a byte array * * @param array byte array with table data matrix * @param position relative byte start position of of column data * within record (first byte is 0) * @param recordSize byte size of table record */ public void setData(byte[] array, int position, int recordSize) { dataArray = array; isRAFile = false; this.columnOffset = position; this.recordSize = recordSize; } /** Read single column element as integer value. An ndefined * value is returned as Integer.MIN_VALUE. The following column * types are supported i.e. binary I/J formats. For array type * elements only the first element is read. Note: ASCII table * columns are read with free format and does not conform to the * FITS standard in the current implementation. * * @param row no. of element in column (starting with 0) */ public int getInt(int row) { int value = Integer.MIN_VALUE; byte[] dbuf = getBytes(row); try { if (binColumn) { DataInputStream di = new DataInputStream(new ByteArrayInputStream(dbuf)); switch (dataType) { case 'I' : value = (int) di.readShort(); break; case 'J' : value = di.readInt(); break; } if (intNullDefined && value==intNull) { value = Integer.MIN_VALUE; } else if (scaling) { value = (int) (zero + scale*value); } } else { String str = new String(dbuf); if (stringNull == null || !str.startsWith(stringNull)) { value = (Integer.valueOf(str)).intValue(); if (scaling) { value = (int) (zero + scale*value); } } } } catch (Exception e) { } return value; } /** Read single column element as integer array. Undefined values * are returned as Integer.MIN_VALUE. The following column types * are supported i.e. binary I/J formats. Note: ASCII table * columns are read with free format and does not conform to the * FITS standard in the current implementation. * * @param row no. of element in column (starting with 0) */ public int[] getInts(int row) { int[] arr = new int[repeat]; byte[] dbuf = getBytes(row); try { if (binColumn) { DataInputStream di = new DataInputStream(new ByteArrayInputStream(dbuf)); int value; for (int n=0; n<repeat; n++) { value = Integer.MIN_VALUE; switch (dataType) { case 'I' : value = (int) di.readShort(); break; case 'J' : value = di.readInt(); break; } if (intNullDefined && value==intNull) { value = Integer.MIN_VALUE; } else if (scaling) { value = (int) (zero + scale*value); } arr[n] = value; } } else { String str = new String(dbuf); arr[0] = Integer.MIN_VALUE; if (stringNull == null || !str.startsWith(stringNull)) { arr[0] = (Integer.valueOf(str)).intValue(); if (scaling) { arr[0] = (int) (zero + scale*arr[0]); } } } } catch (Exception e) { } return arr; } /** Read single column element as double value. An undefined * value is returned as Double.NaN. The following column types * are supported i.e. binary I/J/E/D formats. For array type * elements only the first element is read. Note: ASCII table * columns are read with free format and does not conform to the * FITS standard in the current implementation. * * @param row no. of element in column (starting with 0) */ public double getReal(int row) { double value = Double.NaN; byte[] dbuf = getBytes(row); try { if (binColumn) { DataInputStream di = new DataInputStream(new ByteArrayInputStream(dbuf)); switch (dataType) { case 'I' : value = (double) di.readShort(); break; case 'J' : value = (double) di.readInt(); break; case 'E' : value = (double) di.readFloat(); break; case 'D' : value = di.readDouble(); break; } if (scaling) { value = zero + scale*value; } } else { String str = new String(dbuf); if ((stringNull == null) || !str.startsWith(stringNull)) { value = (Double.valueOf(str)).doubleValue(); if (scaling) { value = zero + scale*value; } } } } catch (Exception e) { } return value; } /** Read single column element as double array. Undefined value * are returned as Double.NaN. The following column types are * supported: binary I/J/E/D formats. Note: ASCII table columns * are read with free format and does not conform to the FITS * standard in the current implementation. * * @param row no. of element in column (starting with 0) */ public double[] getReals(int row) { double[] arr = new double[repeat]; byte[] dbuf = getBytes(row); try { if (binColumn) { DataInputStream di = new DataInputStream(new ByteArrayInputStream(dbuf)); for (int n=0; n<repeat; n++) { switch (dataType) { case 'I' : arr[n] = (double) di.readShort(); break; case 'J' : arr[n] = (double) di.readInt(); break; case 'E' : arr[n] = (double) di.readFloat(); break; case 'D' : arr[n] = di.readDouble(); break; } if (scaling) { arr[n] = zero + scale*arr[n]; } } } else { double value = Double.NaN; String str = new String(dbuf); if ((stringNull == null) || !str.startsWith(stringNull)) { arr[0] = (Double.valueOf(str)).doubleValue(); if (scaling) { arr[0] = zero + scale*arr[0]; } } } } catch (Exception e) { } return arr; } /** Read single column element as string. An undefined value * is returned as a NULL string. The following column types are * supported: A/L formats. * * @param row number of element in column (starting with 0) */ public String getString(int row) { String str = null; if ((dataType == 'A') || (dataType == 'L')) { byte[] dbuf = getBytes(row); if (dbuf != null) { if ((stringNull == null) || !str.startsWith(stringNull)) { str = new String(dbuf); } } } return str; } /** Extract a column element from the 'file' as byte array. * * @param row number of element in column (starting with 0) */ private byte[] getBytes(int row) { if (row<0 || noRows<=row) return null; byte[] dbuf = new byte[getWidth()]; if (isRAFile) { try { if (dataFile == null) return null; dataFile.seek(dataOffset + columnOffset + row*recordSize); dataFile.read(dbuf); } catch (IOException e) { return null; } } else { if (dataArray == null) return null; int k = 0; int n = (int) (columnOffset + row*recordSize); int nsize = getWidth(); while (0 < nsize--) dbuf[k++] = dataArray[n++]; } return dbuf; } /** Define NULL string for ASCII table column. * * @param nullValue string with null value */ public void setNull(String nullValue){ this.stringNull = nullValue; } /** Define NULL value for interger format Binary table columns * @param nullValue value of NULL integer */ public void setNull(int nullValue){ this.intNull = nullValue; intNullDefined = true; } /** Define dimension of binary table column. Note: This is not * used in the current implementation * * @param dim string with dimension soecification for column */ public void setDim(String dim){ } /** Retrieve repeat factor that is number of values per column element */ public int getRepeat() { return this.repeat; } /** Get the data type character for column as given in the TFORM * FITS keyword. */ public char getDataType() { return this.dataType; } /** Calculate the number of bytes associated to a column entry. */ protected int getWidth() { return repeat*bytesPerData; } /** Retrieve the display format for the column (ref. TDISP keyword). */ public String getDisplay(){ return display; } /** Set the display format of the column. * * @param display string with the display format for the column */ public void setDisplay(String display){ this.display = display; } /** Retrieve unit string for the column. */ public String getUnit(){ return unit; } /** Set unit string for column. * * @param unit string with the unit of the column */ public void setUnit(String unit){ this.unit = unit; } /** Retrieve column label. */ public String getLabel(){ return label; } /** Set label of the column. * * @param label string with the column label */ public void setLabel(String label){ this.label = label; } /** Get scaling zero point for table column. */ public double getZero(){ return zero; } /** Define scaling zero point for table column. * * @param zero scaling zero point applied on raw data values */ public void setZero(double zero){ this.zero = zero; this.scaling = true; } /** Get scaling factor for table column. */ public double getScale(){ return scale; } /** Define scaling factor for table column. * * @param scale scaling factor applied on raw data values */ public void setScale(double scale){ this.scale = scale; this.scaling = true; } }