4 * Copyright: Thomas McGlynn 1997-1998.
5 * This code may be used for any purpose, non-commercial
6 * or commercial so long as this copyright notice is retained
7 * in the source code or included in or referred to in any
10 * Many thanks to David Glowacki (U. Wisconsin) for substantial
11 * improvements, enhancements and bug fixes.
13 import nom.tam.util.ArrayFuncs;
14 import nom.tam.util.*;
15 import java.io.IOException;
16 import java.lang.reflect.Array;
17 import java.io.ByteArrayOutputStream;
18 import java.io.ByteArrayInputStream;
20 /** FITS binary table header/data unit */
21 public class BinaryTableHDU
24 private BinaryTable table;
25 /** The standard column keywords for a binary table. */
26 private String[] keyStems = {"TTYPE", "TFORM", "TUNIT", "TNULL", "TSCAL", "TZERO", "TDISP", "TDIM"};
28 public BinaryTableHDU(Header hdr, Data datum) {
30 super((TableData) datum);
33 table = (BinaryTable) datum;
37 /** Create data from a binary table header.
38 * @param header the template specifying the binary table.
39 * @exception FitsException if there was a problem with the header.
41 public static Data manufactureData(Header header) throws FitsException {
42 return new BinaryTable(header);
45 public Data manufactureData() throws FitsException {
46 return manufactureData(myHeader);
49 /** Build a binary table HDU from the supplied data.
50 * @param table the array used to build the binary table.
51 * @exception FitsException if there was a problem with the data.
53 public static Header manufactureHeader(Data data) throws FitsException {
54 Header hdr = new Header();
59 /** Encapsulate data in a BinaryTable data type */
60 public static Data encapsulate(Object o) throws FitsException {
62 if (o instanceof nom.tam.util.ColumnTable) {
63 return new BinaryTable((nom.tam.util.ColumnTable) o);
64 } else if (o instanceof Object[][]) {
65 return new BinaryTable((Object[][]) o);
66 } else if (o instanceof Object[]) {
67 return new BinaryTable((Object[]) o);
69 throw new FitsException("Unable to encapsulate object of type:"
70 + o.getClass().getName() + " as BinaryTable");
74 /** Check that this is a valid binary table header.
75 * @param header to validate.
76 * @return <CODE>true</CODE> if this is a binary table header.
78 public static boolean isHeader(Header header) {
79 String xten = header.getStringValue("XTENSION");
84 if (xten.equals("BINTABLE") || xten.equals("A3DTABLE")) {
91 /** Check that this HDU has a valid header.
92 * @return <CODE>true</CODE> if this HDU has a valid header.
94 public boolean isHeader() {
95 return isHeader(myHeader);
98 /* Check if this data object is consistent with a binary table. There
99 * are three options: a column table object, an Object[][], or an Object[].
100 * This routine doesn't check that the dimensions of arrays are properly
103 public static boolean isData(Object o) {
105 if (o instanceof nom.tam.util.ColumnTable || o instanceof Object[][]
106 || o instanceof Object[]) {
113 /** Add a column without any associated header information.
115 * @param data The column data to be added. Data should be an Object[] where
116 * type of all of the constituents is identical. The length
117 * of data should match the other columns. <b> Note:</b> It is
118 * valid for data to be a 2 or higher dimensionality primitive
119 * array. In this case the column index is the first (in Java speak)
120 * index of the array. E.g., if called with int[30][20][10], the
121 * number of rows in the table should be 30 and this column
122 * will have elements which are 2-d integer arrays with TDIM = (10,20).
123 * @exception FitsException the column could not be added.
125 public int addColumn(Object data) throws FitsException {
127 int col = table.addColumn(data);
128 table.pointToColumn(getNCols() - 1, myHeader);
132 // Need to tell header about the Heap before writing.
133 public void write(ArrayDataOutput ado) throws FitsException {
135 int oldSize = myHeader.getIntValue("PCOUNT");
136 if (oldSize != table.getHeapSize()) {
137 myHeader.addValue("PCOUNT", table.getHeapSize(), "ntf::binarytablehdu:pcount:1");
140 if (myHeader.getIntValue("PCOUNT") == 0) {
141 myHeader.deleteKey("THEAP");
143 myHeader.getIntValue("TFIELDS");
144 int offset = myHeader.getIntValue("NAXIS1")
145 * myHeader.getIntValue("NAXIS2")
146 + table.getHeapOffset();
147 myHeader.addValue("THEAP", offset, "ntf::binarytablehdu:theap:1");
154 * Convert a column in the table to complex. Only tables with appropriate
155 * types and dimensionalities can be converted. It is legal to call this on
156 * a column that is already complex.
158 * @param index The 0-based index of the column to be converted.
159 * @return Whether the column can be converted
160 * @throws FitsException
162 public boolean setComplexColumn(int index) throws FitsException {
163 boolean status = false;
164 if (table.setComplexColumn(index)) {
166 // No problem with the data. Make sure the header
169 int[] dimens = table.getDimens()[index];
170 Class base = table.getBases()[index];
175 // Don't loop over all values.
176 // The last is the [2] for the complex data.
177 for (int i = 0; i < dimens.length - 1; i += 1) {
179 tdim = dimens[i] + sep + tdim;
182 String suffix = "C"; // For complex
183 // Update the TFORMn keyword.
184 if (base == double.class) {
188 // Worry about variable length columns.
190 if (table.isVarCol(index)) {
193 if (table.isLongVary(index)) {
198 // Now update the header.
199 myHeader.findCard("TFORM" + (index + 1));
200 HeaderCard hc = myHeader.nextCard();
201 String oldComment = hc.getComment();
202 if (oldComment == null) {
203 oldComment = "Column converted to complex";
205 myHeader.addValue("TFORM" + (index + 1), dim + prefix + suffix, oldComment);
206 if (tdim.length() > 0) {
207 myHeader.addValue("TDIM" + (index + 1), "(" + tdim + ")", "ntf::binarytablehdu:tdimN:1");
209 // Just in case there used to be a TDIM card that's no longer needed.
210 myHeader.removeCard("TDIM" + (index + 1));
217 private void prtField(String type, String field) {
218 String val = myHeader.getStringValue(field);
220 System.out.print(type + '=' + val + "; ");
224 /** Print out some information about this HDU.
228 BinaryTable myData = (BinaryTable) this.myData;
230 System.out.println(" Binary Table");
231 System.out.println(" Header Information:");
233 int nhcol = myHeader.getIntValue("TFIELDS", -1);
234 int nrow = myHeader.getIntValue("NAXIS2", -1);
235 int rowsize = myHeader.getIntValue("NAXIS1", -1);
237 System.out.print(" " + nhcol + " fields");
238 System.out.println(", " + nrow + " rows of length " + rowsize);
240 for (int i = 1; i <= nhcol; i += 1) {
241 System.out.print(" " + i + ":");
242 prtField("Name", "TTYPE" + i);
243 prtField("Format", "TFORM" + i);
244 prtField("Dimens", "TDIM" + i);
245 System.out.println("");
248 System.out.println(" Data Information:");
250 || table.getNRows() == 0 || table.getNCols() == 0) {
251 System.out.println(" No data present");
252 if (table.getHeapSize() > 0) {
253 System.out.println(" Heap size is: " + table.getHeapSize() + " bytes");
257 System.out.println(" Number of rows=" + table.getNRows());
258 System.out.println(" Number of columns=" + table.getNCols());
259 if (table.getHeapSize() > 0) {
260 System.out.println(" Heap size is: " + table.getHeapSize() + " bytes");
262 Object[] cols = table.getFlatColumns();
263 for (int i = 0; i < cols.length; i += 1) {
264 System.out.println(" " + i + ":" + ArrayFuncs.arrayDescription(cols[i]));
269 /** What are the standard column stems for a binary table?
271 public String[] columnKeyStems() {