1 package nom.tam.fits; 2 3 import java.util.NoSuchElementException; 4 5 import nom.tam.fits.header.GenericKey; 6 import nom.tam.fits.header.IFitsHeader; 7 import nom.tam.fits.header.Standard; 8 9 import static nom.tam.fits.header.Standard.NAXISn; 10 import static nom.tam.fits.header.Standard.TFIELDS; 11 import static nom.tam.fits.header.Standard.TFORMn; 12 import static nom.tam.fits.header.Standard.TTYPEn; 13 14 /* 15 * #%L 16 * nom.tam FITS library 17 * %% 18 * Copyright (C) 2004 - 2024 nom-tam-fits 19 * %% 20 * This is free and unencumbered software released into the public domain. 21 * 22 * Anyone is free to copy, modify, publish, use, compile, sell, or 23 * distribute this software, either in source code form or as a compiled 24 * binary, for any purpose, commercial or non-commercial, and by any 25 * means. 26 * 27 * In jurisdictions that recognize copyright laws, the author or authors 28 * of this software dedicate any and all copyright interest in the 29 * software to the public domain. We make this dedication for the benefit 30 * of the public at large and to the detriment of our heirs and 31 * successors. We intend this dedication to be an overt act of 32 * relinquishment in perpetuity of all present and future rights to this 33 * software under copyright law. 34 * 35 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 36 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 37 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 38 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 39 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 40 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 41 * OTHER DEALINGS IN THE SOFTWARE. 42 * #L% 43 */ 44 45 /** 46 * Base class for binary and ASCII table implementations. 47 * 48 * @param <T> the generic type of table data contained in this HDU instance. 49 */ 50 @SuppressWarnings("deprecation") 51 public abstract class TableHDU<T extends AbstractTableData> extends BasicHDU<T> { 52 53 /** 54 * Returns the default name for a columns with the specified index, to use if no column name was explicitly defined 55 * 56 * @param col The zero-based Java index of the column 57 * 58 * @return The default column name to use if no other name was defined. 59 * 60 * @since 1.20 61 * 62 * @see #setColumnName(int, String, String) 63 */ 64 public static String getDefaultColumnName(int col) { 65 return "Column " + (col + 1); 66 } 67 68 /** 69 * Create the TableHDU. Note that this will normally only be invoked by subclasses in the FITS package. 70 * 71 * @deprecated intended for internal use. Its visibility should be reduced to package level in the future. 72 * 73 * @param hdr the header 74 * @param td The data for the table. 75 */ 76 @Deprecated 77 protected TableHDU(Header hdr, T td) { 78 super(hdr, td); 79 } 80 81 /** 82 * Add a column to the table without any associated header information. 83 * 84 * @param newCol the new column information. the newCol should be an Object[] where type of all of the 85 * constituents is identical. The length of data should match the other columns. <b> 86 * Note:</b> It is valid for data to be a 2 or higher dimensionality primitive array. In 87 * this case the column index is the first (in Java speak) index of the array. E.g., if 88 * called with int[30][20][10], the number of rows in the table should be 30 and this 89 * column will have elements which are 2-d integer arrays with TDIM = (10,20). 90 * 91 * @return the number of columns in the adapted table 92 * 93 * @throws FitsException if the operation failed 94 */ 95 public int addColumn(Object newCol) throws FitsException { 96 int nCols = getNCols(); 97 myHeader.findCard(TFIELDS).setValue(nCols); 98 return nCols; 99 } 100 101 /** 102 * Add a row to the end of the table. If this is the first row, then this will add appropriate columns for each of 103 * the entries. The rows to add must be supplied as column based array of arrays. 104 * 105 * @return the number of rows in the adapted table 106 * 107 * @param newRows rows to add to the table 108 * 109 * @throws FitsException if the operation failed 110 */ 111 public int addRow(Object[] newRows) throws FitsException { 112 int row = myData.addRow(newRows); 113 myHeader.findCard(NAXISn.n(2)).setValue(getNRows()); 114 return row; 115 } 116 117 /** 118 * Returns the list of column description keyword stems that descrive this column in the FITS header. 119 * 120 * @return the stems of the keywords that are associated with table columns. Users can supplement this with their 121 * own and call the appropriate deleteColumns fields. 122 */ 123 protected abstract IFitsHeader[] columnKeyStems(); 124 125 /** 126 * Delete a set of columns from a table. 127 * 128 * @param column The one-indexed start column. 129 * @param len The number of columns to delete. 130 * 131 * @throws FitsException if the operation failed 132 * 133 * @deprecated It is not entirely foolproof for keeping the header in sync -- it is better to use 134 * {@link TableData#deleteColumns(int, int)} to edit tables before wrapping them in an 135 * HDU and editing the header as necessary to incorporate custom entries. May be 136 * removed from the API in the future. 137 */ 138 @Deprecated 139 public void deleteColumnsIndexOne(int column, int len) throws FitsException { 140 deleteColumnsIndexZero(column - 1, len); 141 } 142 143 /** 144 * Delete a set of columns from a table. 145 * 146 * @param column The one-indexed start column. 147 * @param len The number of columns to delete. 148 * @param fields Stems for the header fields to be removed for the table. 149 * 150 * @throws FitsException if the operation failed 151 * 152 * @deprecated It is not entirely foolproof for keeping the header in sync -- it is better to use 153 * {@link TableData#deleteColumns(int, int)} to edit tables before wrapping them in an 154 * HDU and editing the header as necessary to incorporate custom entries. May be 155 * removed from the API in the future. 156 */ 157 @Deprecated 158 public void deleteColumnsIndexOne(int column, int len, String[] fields) throws FitsException { 159 deleteColumnsIndexZero(column - 1, len, GenericKey.create(fields)); 160 } 161 162 /** 163 * Delete a set of columns from a table. 164 * 165 * @param column The one-indexed start column. 166 * @param len The number of columns to delete. 167 * 168 * @throws FitsException if the operation failed 169 * 170 * @deprecated It is not entirely foolproof for keeping the header in sync -- it is better to use 171 * {@link TableData#deleteColumns(int, int)} to edit tables before wrapping them in an 172 * HDU and editing the header as necessary to incorporate custom entries. May be 173 * removed from the API in the future. 174 */ 175 @Deprecated 176 public void deleteColumnsIndexZero(int column, int len) throws FitsException { 177 deleteColumnsIndexZero(column, len, columnKeyStems()); 178 } 179 180 /** 181 * Delete a set of columns from a table. 182 * 183 * @param column The zero-indexed start column. 184 * @param len The number of columns to delete. 185 * @param fields Stems for the header fields to be removed for the table. 186 * 187 * @throws FitsException if the operation failed 188 * 189 * @deprecated It is not entirely foolproof for keeping the header in sync -- it is better to use 190 * {@link TableData#deleteColumns(int, int)} to edit tables before wrapping them in an 191 * HDU and editing the header as necessary to incorporate custom entries. May be 192 * removed from the API in the future. 193 */ 194 @Deprecated 195 public void deleteColumnsIndexZero(int column, int len, IFitsHeader[] fields) throws FitsException { 196 197 if (column < 0 || len < 0 || column + len > getNCols()) { 198 throw new FitsException("Illegal columns deletion request- Start:" + column + " Len:" + len 199 + " from table with " + getNCols() + " columns"); 200 } 201 202 if (len == 0) { 203 return; 204 } 205 206 int ncol = getNCols(); 207 myData.deleteColumns(column, len); 208 209 // Get rid of the keywords for the deleted columns 210 for (int col = column; col < column + len; col++) { 211 for (IFitsHeader field : fields) { 212 myHeader.deleteKey(field.n(col + 1)); 213 } 214 } 215 216 // Shift the keywords for the columns after the deleted columns 217 for (int col = column + len; col < ncol; col++) { 218 for (IFitsHeader field : fields) { 219 IFitsHeader oldKey = field.n(col + 1); 220 IFitsHeader newKey = field.n(col + 1 - len); 221 if (myHeader.containsKey(oldKey)) { 222 myHeader.replaceKey(oldKey, newKey); 223 } 224 } 225 } 226 // Update the number of fields. 227 myHeader.getCard(TFIELDS).setValue(getNCols()); 228 229 // Give the data sections a chance to update the header too. 230 myData.updateAfterDelete(ncol, myHeader); 231 } 232 233 /** 234 * Remove all rows from the table starting at some specific index from the table. Inspired by a routine by R. Mathar 235 * but re-implemented using the DataTable and changes to AsciiTable so that it can be done easily for both Binary 236 * and ASCII tables. 237 * 238 * @param row the (0-based) index of the first row to be deleted. 239 * 240 * @throws FitsException if an error occurs. 241 * 242 * @deprecated It is not entirely foolproof for keeping the header in sync -- it is better to use 243 * {@link TableData#deleteRows(int, int)} to edit tables before wrapping them in an 244 * HDU and editing the header as necessary to incorporate custom entries. May be 245 * removed from the API in the future. 246 */ 247 @Deprecated 248 public void deleteRows(final int row) throws FitsException { 249 deleteRows(row, getNRows() - row); 250 } 251 252 /** 253 * Remove a number of adjacent rows from the table. This routine was inspired by code by R.Mathar but re-implemented 254 * using changes in the ColumnTable class abd AsciiTable so that we can do it for all FITS tables. 255 * 256 * @param firstRow the (0-based) index of the first row to be deleted. This is zero-based indexing: 257 * 0<=firstrow< number of rows. 258 * @param nRow the total number of rows to be deleted. 259 * 260 * @throws FitsException If an error occurs in the deletion. 261 * 262 * @deprecated It is not entirely foolproof for keeping the header in sync -- it is better to use 263 * {@link TableData#deleteRows(int, int)} to edit tables before wrapping them in an 264 * HDU and editing the header as necessary to incorporate custom entries. May be 265 * removed from the API in the future. 266 */ 267 @Deprecated 268 public void deleteRows(final int firstRow, int nRow) throws FitsException { 269 270 // Just ignore invalid requests. 271 if (nRow <= 0 || firstRow >= getNRows() || firstRow <= 0) { 272 return; 273 } 274 275 /* correct if more rows are requested than available */ 276 if (nRow > getNRows() - firstRow) { 277 nRow = getNRows() - firstRow; 278 } 279 280 myData.deleteRows(firstRow, nRow); 281 myHeader.setNaxis(2, getNRows()); 282 } 283 284 /** 285 * Find the 0-based column index corresponding to a particular column name. 286 * 287 * @return index of the column 288 * 289 * @param colName the name of the column 290 */ 291 public int findColumn(String colName) { 292 for (int i = 0; i < getNCols(); i++) { 293 String val = myHeader.getStringValue(TTYPEn.n(i + 1)); 294 if (val != null && val.trim().equals(colName)) { 295 return i; 296 } 297 } 298 return -1; 299 } 300 301 /** 302 * <p> 303 * Returns the data for a particular column in as an array of elements. See {@link TableData#addColumn(Object)} for 304 * more information about the format of data elements in general. 305 * </p> 306 * 307 * @param col The 0-based column index. 308 * 309 * @return an array of primitives (for scalar columns), or else an <code>Object[]</code> array, or 310 * possibly <code>null</code> 311 * 312 * @throws FitsException if the table could not be accessed 313 * 314 * @see TableData#getColumn(int) 315 * @see #setColumn(int, Object) 316 * @see #getElement(int, int) 317 * @see #getNCols() 318 */ 319 public Object getColumn(int col) throws FitsException { 320 return myData.getColumn(col); 321 } 322 323 /** 324 * <p> 325 * Returns the data for a particular column in as an array of elements. See {@link TableData#addColumn(Object)} for 326 * more information about the format of data elements in general. 327 * </p> 328 * 329 * @param colName The name or ID of the column as stored by the <code>TTYPE</code><i>n</i> FITS header 330 * keyword. 331 * 332 * @return an array of primitives (for scalar columns), or else an <code>Object[]</code> array, or 333 * <code>null</code> if there is no column by that name. 334 * 335 * @throws FitsException if the table could not be accessed 336 * 337 * @see TableData#getColumn(int) 338 * @see #setColumn(int, Object) 339 * @see #getElement(int, int) 340 * @see #getNCols() 341 */ 342 public Object getColumn(String colName) throws FitsException { 343 int col = findColumn(colName); 344 return col < 0 ? null : getColumn(col); 345 } 346 347 /** 348 * Get the FITS type of a column in the table. 349 * 350 * @param index0 The 0-based index of the column. 351 * 352 * @return The FITS type. 353 * 354 * @throws FitsException if the index is less than 0 or greater than or equals to the number of columns in the 355 * table. 356 */ 357 public String getColumnFormat(int index0) throws FitsException { 358 if (index0 < 0 || index0 >= getNCols()) { 359 throw new FitsException("Bad column index " + index0 + " (only " + getNCols() + " columns)"); 360 } 361 362 return myHeader.getStringValue(TFORMn.n(index0 + 1)).trim(); 363 } 364 365 /** 366 * Convenience method for getting column metadata, as a string. Note, that the return value is always a string even 367 * if the underlying metadata is some other type in the FITS header. For accessing column descriptions specified via 368 * standard FITS keywords, you should prefer using `{@link #getColumnMeta(int, IFitsHeader)}. And, to get metadata 369 * of known other types (e.g. integers), you may use one of the type-specific getter methods of {@link Header}, such 370 * as <code>getHeader().getIntValue(...)</code>. 371 * 372 * @param index0 zero-based index index of the colum 373 * @param keyBase the base header keyword of the descriptor, without the column index, e.g. 374 * `"TTYPE"`. 375 * 376 * @return column meta data as a string, or <code>null</code> if there is no such metadata 377 * in the header. 378 * 379 * @throws IndexOutOfBoundsException if the index is less than 0 or greater than or equals to the number of columns 380 * in the table. 381 * 382 * @see #getColumnMeta(int, IFitsHeader) 383 * @see #getHeader() 384 */ 385 public String getColumnMeta(int index0, String keyBase) throws IndexOutOfBoundsException { 386 if (index0 < 0 || index0 >= getNCols()) { 387 throw new IndexOutOfBoundsException("Zero-based column index " + index0 + " is out of range"); 388 } 389 390 HeaderCard c = myHeader.getCard(keyBase + (index0 + 1)); 391 return c == null ? null : c.getValue(); 392 } 393 394 /** 395 * Convenience method for getting column metadata, as a string. Note, that the return value is always a string even 396 * if the underlying metadata is some other type@throws IndexOutOfBoundsException if the index is less than 0 or 397 * greater than or equals to the number of columns in the table. in the FITS header. To get metadata of known other 398 * types (e.g. integers), you may use one of the type-specific getter methods of {@link Header}, such as 399 * <code>getHeader().getIntValue(...)</code>. 400 * 401 * @param index0 zero-based index index of the colum 402 * @param keyBase the standard FITS key to get, without the column indexing, e.g. 403 * `Standard.TTYPEn`. 404 * 405 * @return column meta data as a string, or <code>null</code> if there is no such metadata 406 * in the header. 407 * 408 * @throws IndexOutOfBoundsException if the index is less than 0, or greater than or equals to the number of columns 409 * in the table. 410 * @throws HeaderCardException if the resulting indexed keyword exceeds the maximum 8-bytes allowed for 411 * standard FITS keywords. 412 * @throws NoSuchElementException If more indices were supplied than can be filled for this keyword. 413 * 414 * @since 1.22.3 415 * 416 * @see #getHeader() 417 */ 418 public String getColumnMeta(int index0, IFitsHeader keyBase) 419 throws IndexOutOfBoundsException, HeaderCardException, NoSuchElementException { 420 if (index0 < 0 || index0 >= getNCols()) { 421 throw new IndexOutOfBoundsException("Zero-based column index " + index0 + " is out of range"); 422 } 423 424 HeaderCard c = myHeader.getCard(keyBase.n(index0 + 1)); 425 return c == null ? null : c.getValue(); 426 } 427 428 /** 429 * Gets the name of a column in the table, as it appears in this HDU's header. It may differ from a more currently 430 * assigned name of the binary table data column after the HDU creation or reading. 431 * 432 * @param index0 The 0-based column index. 433 * 434 * @return The column name, or <code>null</code> if it was undefined. 435 * 436 * @throws IndexOutOfBoundsException if the index is less than 0, or greater than or equals to the number of columns 437 * in the table. 438 * 439 * @see BinaryTable.ColumnDesc#name() 440 */ 441 public String getColumnName(int index0) throws IndexOutOfBoundsException { 442 return getColumnMeta(index0, Standard.TTYPEn); 443 } 444 445 /** 446 * <p> 447 * Returns the data for all columns in as an array. See {@link TableData#addColumn(Object)} for more information 448 * about the column format of each element in the returned array. 449 * </p> 450 * 451 * @return An array containing the column data for all columns. Each entry in the returned array is 452 * itself an array of primitives (for scalar columns), or else an <code>Object[]</code> 453 * array, or possibly <code>null</code>. 454 * 455 * @throws FitsException if the table could not be accessed 456 * 457 * @see TableData#getColumn(int) 458 * @see #setColumn(int, Object) 459 * @see #getElement(int, int) 460 * @see #getNCols() 461 */ 462 public Object[] getColumns() throws FitsException { 463 Object[] result = new Object[getNCols()]; 464 for (int i = 0; i < result.length; i++) { 465 result[i] = getColumn(i); 466 } 467 return result; 468 } 469 470 /** 471 * Returns a specific element from this table 472 * 473 * @return a specific element of the table using 0-based indices. 474 * 475 * @param row the row index of the element 476 * @param col the column index of the element 477 * 478 * @throws FitsException if the operation failed 479 * 480 * @see #getElement(int, int) 481 */ 482 public Object getElement(int row, int col) throws FitsException { 483 return myData.getElement(row, col); 484 } 485 486 /** 487 * Get the number of columns for this table 488 * 489 * @return The number of columns in the table. 490 */ 491 public int getNCols() { 492 return myData.getNCols(); 493 } 494 495 /** 496 * Get the number of rows for this table 497 * 498 * @return The number of rows in the table. 499 */ 500 public int getNRows() { 501 return myData.getNRows(); 502 } 503 504 /** 505 * Returns a specific row from this table 506 * 507 * @return a specific row of the table. 508 * 509 * @param row the index of the row to retreive 510 * 511 * @throws FitsException if the operation failed 512 * 513 * @see #setRow(int, Object[]) 514 */ 515 public Object[] getRow(int row) throws FitsException { 516 return myData.getRow(row); 517 } 518 519 /** 520 * Update a column within a table. The new column should have the same format ast the column being replaced. See 521 * {@link TableData#addColumn(Object)} for more information about the column data format. 522 * 523 * @param col index of the column to replace 524 * @param newCol the replacement column 525 * 526 * @throws FitsException if the operation failed 527 * 528 * @see #getColumn(int) 529 * @see #setColumn(String, Object) 530 * @see TableData#addColumn(Object) 531 */ 532 public void setColumn(int col, Object newCol) throws FitsException { 533 myData.setColumn(col, newCol); 534 } 535 536 /** 537 * Update a column within a table. The new column should have the same format as the column being replaced. See 538 * {@link TableData#addColumn(Object)} for more information about the column data format. 539 * 540 * @param colName name of the column to replace 541 * @param newCol the replacement column 542 * 543 * @throws FitsException if the operation failed 544 * 545 * @see #getColumn(String) 546 * @see #setColumn(int, Object) 547 * @see TableData#addColumn(Object) 548 */ 549 public void setColumn(String colName, Object newCol) throws FitsException { 550 setColumn(findColumn(colName), newCol); 551 } 552 553 /** 554 * Specify column metadata for a given column in a way that allows all of the column metadata for a given column to 555 * be organized together. 556 * 557 * @param index0 The 0-based index of the column 558 * @param key The column key. I.e., the keyword will be key+(index+1) 559 * @param value The value to be placed in the header. 560 * @param comment The comment for the header 561 * @param after Should the header card be after the current column metadata block 562 * (<code>true</code>), or immediately before the TFORM card 563 * (<code>false</code>). 564 * 565 * @throws HeaderCardException if the header could not be updated, or if the indexed FITS keyword is too long 566 * (exceeds the maximum 8 bytes allowed by the FITS standard). 567 * @throws IndexOutOfBoundsException if the index is less than 0 or greater than or equals to the number of columns 568 * in t@throws IndexOutOfBoundsException if the index is less than 0 or 569 * greater than or equals to the number of columns in the table. 570 */ 571 public void setColumnMeta(int index0, IFitsHeader key, String value, String comment, boolean after) 572 throws IndexOutOfBoundsException, HeaderCardException { 573 setCurrentColumn(index0, after); 574 myHeader.addLine(new HeaderCard(key.n(index0 + 1).key(), value, comment)); 575 } 576 577 /** 578 * Specify column metadata for a given column in a way that allows all of the column metadata for a given column to 579 * be organized together. 580 * 581 * @param index0 The 0-based index of the column 582 * @param key The column key. I.e., the keyword will be key+(index+1) 583 * @param value The value to be placed in the header. 584 * @param comment The comment for the header 585 * @param after Should the header card be after the current column metadata block 586 * (<code>true</code>), or immediately before the TFORM card 587 * (<code>false</code>). 588 * 589 * @throws HeaderCardException if the header could not be updated, or if the indexed FITS keyword is too long 590 * (exceeds the maximum 8 bytes allowed by the FITS standard). 591 * @throws IndexOutOfBoundsException if the index is less than 0 or greater than or equals to the number of columns 592 * in t@throws IndexOutOfBoundsException if the index is less than 0 or 593 * greater than or equals to the number of columns in the table. 594 * 595 * @since 1.16 596 */ 597 public void setColumnMeta(int index0, IFitsHeader key, Number value, String comment, boolean after) 598 throws IndexOutOfBoundsException, HeaderCardException { 599 setCurrentColumn(index0, after); 600 myHeader.addLine(new HeaderCard(key.n(index0 + 1).key(), value, comment)); 601 } 602 603 /** 604 * Specify column metadata for a given column in a way that allows all of the column metadata for a given column to 605 * be organized together. 606 * 607 * @param index0 The 0-based index of the column 608 * @param key The column key. I.e., the keyword will be key+(index+1) 609 * @param value The value to be placed in the header. 610 * @param comment The comment for the header 611 * @param after Should the header card be after the current column metadata block 612 * (<code>true</code>), or immediately before the TFORM card 613 * (<code>false</code>). 614 * 615 * @throws HeaderCardException if the header could not be updated, or if the indexed FITS keyword is too long 616 * (exceeds the maximum 8 bytes allowed by the FITS standard). 617 * @throws IndexOutOfBoundsException if the index is less than 0 or greater than or equals to the number of columns 618 * in t@throws IndexOutOfBoundsException if the index is less than 0 or 619 * greater than or equals to the number of columns in the table. 620 */ 621 public void setColumnMeta(int index0, String key, Boolean value, String comment, boolean after) 622 throws IndexOutOfBoundsException, HeaderCardException { 623 setCurrentColumn(index0, after); 624 myHeader.addLine(new HeaderCard(key + (index0 + 1), value, comment)); 625 } 626 627 /** 628 * Specify column metadata for a given column in a way that allows all of the column metadata for a given column to 629 * be organized together. 630 * 631 * @param index0 The 0-based index of the column 632 * @param key The column key. I.e., the keyword will be key+(index+1) 633 * @param value The value to be placed in the header. 634 * @param comment The comment for the header 635 * @param after Should the header card be after the current column metadata block 636 * (<code>true</code>), or immediately before the TFORM card 637 * (<code>false</code>). 638 * 639 * @throws HeaderCardException if the header could not be updated, or if the indexed FITS keyword is too long 640 * (exceeds the maximum 8 bytes allowed by the FITS standard). 641 * @throws IndexOutOfBoundsException if the index is less than 0 or greater than or equals to the number of columns 642 * in t@throws IndexOutOfBoundsException if the index is less than 0 or 643 * greater than or equals to the number of columns in the table. 644 */ 645 public void setColumnMeta(int index0, String key, Number value, String comment, boolean after) 646 throws IndexOutOfBoundsException, HeaderCardException { 647 setCurrentColumn(index0, after); 648 myHeader.addLine(new HeaderCard(key + (index0 + 1), value, comment)); 649 } 650 651 /** 652 * Specify column metadata for a given column in a way that allows all of the column metadata for a given column to 653 * be organized together. 654 * 655 * @param index0 The 0-based index of the column 656 * @param key The column key. I.e., the keyword will be key+(index+1) 657 * @param value The value to be placed in the header. 658 * @param precision The maximum number of decimal places to show after the leading figure. 659 * (Trailing zeroes will be ommitted.) 660 * @param comment The comment for the header 661 * @param after Should the header card be after the current column metadata block 662 * (<code>true</code>), or immediately before the TFORM card 663 * (<code>false</code>). 664 * 665 * @throws HeaderCardException if the header could not be updated, or if the indexed FITS keyword is too long 666 * (exceeds the maximum 8 bytes allowed by the FITS standard). 667 * @throws IndexOutOfBoundsException if the index is less than 0 or greater than or equals to the number of columns 668 * in t@throws IndexOutOfBoundsException if the index is less than 0 or 669 * greater than or equals to the number of columns in the table. 670 */ 671 public void setColumnMeta(int index0, String key, Number value, int precision, String comment, boolean after) 672 throws IndexOutOfBoundsException, HeaderCardException { 673 setCurrentColumn(index0, after); 674 myHeader.addLine(new HeaderCard(key + (index0 + 1), value, precision, comment)); 675 } 676 677 /** 678 * Specify column metadata for a given column in a way that allows all of the column metadata for a given column to 679 * be organized together. 680 * 681 * @param index0 The 0-based index of the column 682 * @param key The column key. I.e., the keyword will be key+(index+1) 683 * @param value The value to be placed in the header. 684 * @param comment The comment for the header 685 * 686 * @throws HeaderCardException if the header could not be updated, or if the indexed FITS keyword is too long 687 * (exceeds the maximum 8 bytes allowed by the FITS standard). 688 * @throws IndexOutOfBoundsException if the index is less than 0 or greater than or equals to the number of columns 689 * in t@throws IndexOutOfBoundsException if the index is less than 0 or 690 * greater than or equals to the number of columns in the table. 691 */ 692 public void setColumnMeta(int index0, String key, String value, String comment) 693 throws IndexOutOfBoundsException, HeaderCardException { 694 setColumnMeta(index0, key, value, comment, true); 695 } 696 697 /** 698 * Specify column metadata for a given column in a way that allows all of the column metadata for a given column to 699 * be organized together. 700 * 701 * @param index0 The 0-based index of the column 702 * @param key The column key. I.e., the keyword will be key+(index+1) 703 * @param value The value to be placed in the header. 704 * @param comment The comment for the header 705 * @param after Should the header card be after the current column metadata block (true), 706 * or immediately before the TFORM card (false). @throws FitsException if 707 * the operation failed 708 * 709 * @throws HeaderCardException if the header could not be updated, or if the indexed FITS keyword is too 710 * long (exceeds the maximum 8 bytes allowed by the FITS standard). 711 * @throws IndexOutOfBoundsException if the index is less than 0 or greater than or equals to the number of 712 * columns in t@throws IndexOutOfBoundsException if the index is less than 713 * 0 or greater than or equals to the number of columns in the table. 714 * 715 * @deprecated use {@link #setColumnMeta(int, IFitsHeader, String, String, boolean)} 716 */ 717 @Deprecated 718 public void setColumnMeta(int index0, String key, String value, String comment, boolean after) 719 throws IndexOutOfBoundsException, HeaderCardException { 720 setCurrentColumn(index0, after); 721 myHeader.addLine(new HeaderCard(key + (index0 + 1), value, comment)); 722 } 723 724 /** 725 * Sets the name / ID of a specific column in this table. Naming columns is generally a good idea so that people can 726 * figure out what sort of data actually appears in specific table columns. 727 * 728 * @param index0 the 0-based column index 729 * @param name the name or ID we want to assing to the column 730 * @param comment Any additional comment we would like to store alongside in the FITS header. 731 * (The comment may be truncated or even ommitted, depending on space 732 * constraints in the FITS header. 733 * 734 * @throws HeaderCardException if there was a problem wil adding the associated descriptive FITS header 735 * keywords to this table's header. 736 * @throws IndexOutOfBoundsException if the table has no column matching the index 737 * 738 * @see #getColumnName(int) 739 * @see #getDefaultColumnName(int) 740 */ 741 public void setColumnName(int index0, String name, String comment) 742 throws IndexOutOfBoundsException, HeaderCardException { 743 setColumnMeta(index0, TTYPEn, name, comment, true); 744 } 745 746 /** 747 * Set the cursor in the header to point after the metadata for the specified column 748 * 749 * @param col The 0-based index of the column 750 * 751 * @throws IndexOutOfBoundsException if the index is less than 0 or greater than or equals to the number of 752 * columns in t@throws IndexOutOfBoundsException if the index is less than 753 * 0 or greater than or equals to the number of columns in the table. 754 * 755 * @deprecated (<i>for internal use</i>) Will be removed int the future (no longer used). 756 */ 757 @Deprecated 758 public void setCurrentColumn(int col) throws IndexOutOfBoundsException { 759 setCurrentColumn(col, true); 760 } 761 762 /** 763 * Set the cursor in the header to point either before the TFORMn value or after the column metadata 764 * 765 * @param col0 The 0-based index of the column 766 * @param after True if the cursor should be placed after the existing column metadata or 767 * false if the cursor is to be placed before the TFORM value. If no 768 * corresponding TFORM is found, the cursor will be placed at the end of 769 * current header. 770 * 771 * @throws IndexOutOfBoundsException if the index is less than 0 or greater than or equals to the number of 772 * columns in t@throws IndexOutOfBoundsException if the index is less than 773 * 0 or greater than or equals to the number of columns in the table. 774 * 775 * @deprecated (<i>for internal use</i>) Will have private access in the future. 776 */ 777 @Deprecated 778 public void setCurrentColumn(int col0, boolean after) throws IndexOutOfBoundsException { 779 if (col0 < 0 || col0 >= getNCols()) { 780 throw new IndexOutOfBoundsException("Zero-based column index " + col0 + " is out of range"); 781 } 782 783 if (after) { 784 myHeader.positionAfterIndex(TFORMn, col0 + 1); 785 } else { 786 myHeader.findCard(TFORMn.n(col0 + 1)); 787 } 788 } 789 790 /** 791 * Update a single element within the table. 792 * 793 * @param row the row index 794 * @param col the column index 795 * @param element the replacement element 796 * 797 * @throws FitsException if the operation failed 798 * 799 * @see #getElement(int, int) 800 */ 801 public void setElement(int row, int col, Object element) throws FitsException { 802 myData.setElement(row, col, element); 803 } 804 805 /** 806 * Update a row within a table. 807 * 808 * @param row row index 809 * @param newRow the replacement row 810 * 811 * @throws FitsException if the operation failed 812 * 813 * @see #getRow(int) 814 */ 815 public void setRow(int row, Object[] newRow) throws FitsException { 816 myData.setRow(row, newRow); 817 } 818 }