3 import java.util.Iterator;
4 import nom.tam.util.Cursor;
6 /** This class allows FITS binary and ASCII tables to
7 * be accessed via a common interface.
9 * Bug Fix: 3/28/01 to findColumn.
11 public abstract class TableHDU extends BasicHDU {
13 private TableData table;
14 private int currentColumn;
16 /** Create the TableHDU. Note that this
17 * will normally only be invoked by subclasses
18 * in the FITS package.
19 * @param td The data for the table.
21 TableHDU(TableData td) {
25 /** Get a specific row of the table */
26 public Object[] getRow(int row) throws FitsException {
27 return table.getRow(row);
30 /** Get a specific column of the table where
31 * the column name is specified using the TTYPEn keywords
33 * @param colName The name of the column to be extracted.
34 * @throws FitsException
36 public Object getColumn(String colName) throws FitsException {
37 return getColumn(findColumn(colName));
40 /** Get a specific column from the table using 0-based column
43 public Object getColumn(int col) throws FitsException {
44 return table.getColumn(col);
47 /** Get all of the columns of the table.
49 public Object[] getColumns() throws FitsException {
50 Object[] result = new Object[getNCols()];
51 for (int i = 0; i < result.length; i += 1) {
52 result[i] = getColumn(i);
57 /** Get a specific element of the table using 0-based indices.
60 public Object getElement(int row, int col) throws FitsException {
61 return table.getElement(row, col);
64 /** Update a row within a table.
67 public void setRow(int row, Object[] newRow) throws FitsException {
68 table.setRow(row, newRow);
71 /** Update a column within a table. The new column should have the
72 * same format as the column being replaced.
74 public void setColumn(String colName, Object newCol) throws FitsException {
75 setColumn(findColumn(colName), newCol);
78 /** Update a column within a table. The new column should have the same
79 * format ast the column being replaced.
81 public void setColumn(int col, Object newCol) throws FitsException {
82 table.setColumn(col, newCol);
85 /** Update a single element within the table.
87 public void setElement(int row, int col, Object element) throws FitsException {
88 table.setElement(row, col, element);
91 /** Add a row to the end of the table. If this is the first row,
92 * then this will add appropriate columns for each of the entries.
94 public int addRow(Object[] newRow) throws FitsException {
96 int row = table.addRow(newRow);
97 myHeader.addValue("NAXIS2", row, "ntf::tablehdu:naxis2:1");
101 /** Find the 0-based column index corresponding to a particular
104 public int findColumn(String colName) {
106 for (int i = 0; i < getNCols(); i += 1) {
108 String val = myHeader.getStringValue("TTYPE" + (i + 1));
109 if (val != null && val.trim().equals(colName)) {
116 /** Add a column to the table. */
117 public abstract int addColumn(Object data) throws FitsException;
119 /** Get the number of columns for this table
120 * @return The number of columns in the table.
122 public int getNCols() {
123 return table.getNCols();
126 /** Get the number of rows for this table
127 * @return The number of rows in the table.
129 public int getNRows() {
130 return table.getNRows();
133 /** Get the name of a column in the table.
134 * @param index The 0-based column index.
135 * @return The column name.
136 * @exception FitsException if an invalid index was requested.
138 public String getColumnName(int index) {
140 String ttype = myHeader.getStringValue("TTYPE" + (index + 1));
142 ttype = ttype.trim();
147 public void setColumnName(int index, String name, String comment)
148 throws FitsException {
149 setColumnMeta(index, "TTYPE", name, comment, true);
152 /** Specify column metadata for a given column in a way that
153 * allows all of the column metadata for a given column
154 * to be organized together.
156 * @param index The 0-based index of the column
157 * @param key The column key. I.e., the keyword will be key+(index+1)
158 * @param value The value to be placed in the header.
159 * @param comment The comment for the header
160 * @param after Should the header card be after the current column metadata block
161 * (true), or immediately before the TFORM card (false).
162 * @throws FitsException
164 public void setColumnMeta(int index, String key, String value, String comment, boolean after)
165 throws FitsException {
166 setCurrentColumn(index, after);
167 myHeader.addValue(key + (index + 1), value, comment);
170 /** Convenience method for getting column data. Note that this works
171 * only for metadata that returns a string value. This is equivalent
172 * to getStringValue(type+index);
174 public String getColumnMeta(int index, String type) {
175 return myHeader.getStringValue(type+(index+1));
178 public void setColumnMeta(int index, String key, String value, String comment)
179 throws FitsException {
180 setColumnMeta(index, key, value, comment, true);
183 public void setColumnMeta(int index, String key, long value, String comment, boolean after)
184 throws FitsException {
185 setCurrentColumn(index, after);
186 myHeader.addValue(key + (index + 1), value, comment);
189 public void setColumnMeta(int index, String key, double value, String comment, boolean after)
190 throws FitsException {
191 setCurrentColumn(index, after);
192 myHeader.addValue(key + (index + 1), value, comment);
195 public void setColumnMeta(int index, String key, boolean value, String comment, boolean after)
196 throws FitsException {
197 setCurrentColumn(index, after);
198 myHeader.addValue(key + (index + 1), value, comment);
201 /** Get the FITS type of a column in the table.
202 * @param index The 0-based index of the column.
203 * @return The FITS type.
204 * @exception FitsException if an invalid index was requested.
206 public String getColumnFormat(int index)
207 throws FitsException {
208 int flds = myHeader.getIntValue("TFIELDS", 0);
209 if (index < 0 || index >= flds) {
210 throw new FitsException("Bad column index " + index + " (only " + flds
214 return myHeader.getStringValue("TFORM" + (index + 1)).trim();
217 /** Set the cursor in the header to point after the
218 * metadata for the specified column
219 * @param col The 0-based index of the column
221 public void setCurrentColumn(int col) {
222 setCurrentColumn(col, true);
225 /** Set the cursor in the header to point either before the
226 * TFORM value or after the column metadat
227 * @param col The 0-based index of the column
228 * @param after True if the cursor should be placed after the existing column
229 * metadata or false if the cursor is to be placed before the TFORM value.
230 * If no corresponding TFORM is found, the cursoe will be placed at the end of
233 public void setCurrentColumn(int col, boolean after) {
235 myHeader.positionAfterIndex("TFORM", col + 1);
237 String tform = "TFORM" + (col + 1);
238 myHeader.findCard(tform);
243 * Remove all rows from the table starting at some specific index from the table.
244 * Inspired by a routine by R. Mathar but re-implemented using the DataTable and
245 * changes to AsciiTable so that it can be done easily for both Binary and ASCII tables.
246 * @param row the (0-based) index of the first row to be deleted.
247 * @throws FitsExcpetion if an error occurs.
249 public void deleteRows(final int row) throws FitsException {
250 deleteRows(row, getNRows() - row);
254 * Remove a number of adjacent rows from the table. This routine
255 * was inspired by code by R.Mathar but re-implemented using changes
256 * in the ColumnTable class abd AsciiTable so that we can do
257 * it for all FITS tables.
258 * @param firstRow the (0-based) index of the first row to be deleted.
259 * This is zero-based indexing: 0<=firstrow< number of rows.
260 * @param nRow the total number of rows to be deleted.
261 * @throws FitsException If an error occurs in the deletion.
263 public void deleteRows(final int firstRow, int nRow) throws FitsException {
265 // Just ignore invalid requests.
266 if (nRow <= 0 || firstRow >= getNRows() || nRow <= 0) {
270 /* correct if more rows are requested than available */
271 if (nRow > getNRows() - firstRow) {
272 nRow = getNRows() - firstRow;
275 table.deleteRows(firstRow, nRow);
276 myHeader.setNaxis(2, getNRows());
279 /** Delete a set of columns from a table.
281 public void deleteColumnsIndexOne(int column, int len) throws FitsException {
282 deleteColumnsIndexZero(column - 1, len);
285 /** Delete a set of columns from a table.
287 public void deleteColumnsIndexZero(int column, int len) throws FitsException {
288 deleteColumnsIndexZero(column, len, columnKeyStems());
291 /** Delete a set of columns from a table.
292 * @param column The one-indexed start column.
293 * @param len The number of columns to delete.
294 * @param fields Stems for the header fields to be removed
297 public void deleteColumnsIndexOne(int column, int len, String[] fields) throws FitsException {
298 deleteColumnsIndexZero(column - 1, len, fields);
301 /** Delete a set of columns from a table.
302 * @param column The zero-indexed start column.
303 * @param len The number of columns to delete.
304 * @param fields Stems for the header fields to be removed
307 public void deleteColumnsIndexZero(int column, int len, String[] fields) throws FitsException {
309 if (column < 0 || len < 0 || column + len > getNCols()) {
310 throw new FitsException("Illegal columns deletion request- Start:" + column + " Len:" + len + " from table with " + getNCols() + " columns");
317 int ncol = getNCols();
318 table.deleteColumns(column, len);
321 // Get rid of the keywords for the deleted columns
322 for (int col = column; col < column + len; col += 1) {
323 for (int fld = 0; fld < fields.length; fld += 1) {
324 String key = fields[fld] + (col + 1);
325 myHeader.deleteKey(key);
329 // Shift the keywords for the columns after the deleted columns
330 for (int col = column + len; col < ncol; col += 1) {
331 for (int fld = 0; fld < fields.length; fld += 1) {
332 String oldKey = fields[fld] + (col + 1);
333 String newKey = fields[fld] + (col + 1 - len);
334 if (myHeader.containsKey(oldKey)) {
335 myHeader.replaceKey(oldKey, newKey);
339 // Update the number of fields.
340 myHeader.addValue("TFIELDS", getNCols(), "ntf::tablehdu:tfields:1");
342 // Give the data sections a chance to update the header too.
343 table.updateAfterDelete(ncol, myHeader);
346 /** Get the stems of the keywords that are associated
347 * with table columns. Users can supplement this
348 * with their own and call the appropriate deleteColumns fields.
350 public abstract String[] columnKeyStems();