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