nom.tam.fits.BinaryTableHDU Maven / Gradle / Ivy
package nom.tam.fits;
/*
* #%L
* nom.tam FITS library
* %%
* Copyright (C) 2004 - 2015 nom-tam-fits
* %%
* This is free and unencumbered software released into the public domain.
*
* Anyone is free to copy, modify, publish, use, compile, sell, or
* distribute this software, either in source code form or as a compiled
* binary, for any purpose, commercial or non-commercial, and by any
* means.
*
* In jurisdictions that recognize copyright laws, the author or authors
* of this software dedicate any and all copyright interest in the
* software to the public domain. We make this dedication for the benefit
* of the public at large and to the detriment of our heirs and
* successors. We intend this dedication to be an overt act of
* relinquishment in perpetuity of all present and future rights to this
* software under copyright law.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
* #L%
*/
import static nom.tam.fits.header.Standard.NAXIS1;
import static nom.tam.fits.header.Standard.NAXIS2;
import static nom.tam.fits.header.Standard.PCOUNT;
import static nom.tam.fits.header.Standard.TDIMn;
import static nom.tam.fits.header.Standard.TDISPn;
import static nom.tam.fits.header.Standard.TFIELDS;
import static nom.tam.fits.header.Standard.TFORMn;
import static nom.tam.fits.header.Standard.THEAP;
import static nom.tam.fits.header.Standard.TNULLn;
import static nom.tam.fits.header.Standard.TSCALn;
import static nom.tam.fits.header.Standard.TTYPEn;
import static nom.tam.fits.header.Standard.TUNITn;
import static nom.tam.fits.header.Standard.TZEROn;
import static nom.tam.fits.header.Standard.XTENSION;
import static nom.tam.fits.header.Standard.XTENSION_BINTABLE;
import java.io.PrintStream;
import nom.tam.fits.header.IFitsHeader;
import nom.tam.fits.header.Standard;
import nom.tam.util.ArrayDataOutput;
import nom.tam.util.ArrayFuncs;
/** FITS binary table header/data unit */
public class BinaryTableHDU extends TableHDU {
/** The standard column keywords for a binary table. */
private static final IFitsHeader[] KEY_STEMS = {
TTYPEn,
TFORMn,
TUNITn,
TNULLn,
TSCALn,
TZEROn,
TDISPn,
TDIMn
};
public BinaryTableHDU(Header hdr, BinaryTable datum) {
super(hdr, datum);
}
/**
* @return Encapsulate data in a BinaryTable data type
* @param o
* data to encapsulate
* @throws FitsException
* if the type of the data is not usable as data
*/
public static BinaryTable encapsulate(Object o) throws FitsException {
if (o instanceof nom.tam.util.ColumnTable) {
return new BinaryTable((nom.tam.util.ColumnTable>) o);
} else if (o instanceof Object[][]) {
return new BinaryTable((Object[][]) o);
} else if (o instanceof Object[]) {
return new BinaryTable((Object[]) o);
} else {
throw new FitsException("Unable to encapsulate object of type:" + o.getClass().getName() + " as BinaryTable");
}
}
/*
* Check if this data object is consistent with a binary table. There are
* three options: a column table object, an Object[][], or an Object[]. This
* routine doesn't check that the dimensions of arrays are properly
* consistent.
*/
public static boolean isData(Object o) {
return o instanceof nom.tam.util.ColumnTable || o instanceof Object[][] || o instanceof Object[];
}
/**
* Check that this is a valid binary table header.
*
* @param header
* to validate.
* @return true
if this is a binary table header.
*/
public static boolean isHeader(Header header) {
String xten = header.getStringValue(XTENSION);
if (xten == null) {
return false;
}
xten = xten.trim();
return xten.equals(XTENSION_BINTABLE) || xten.equals("A3DTABLE");
}
/**
* @return a new created data from a binary table header.
* @param header
* the template specifying the binary table.
* @throws FitsException
* if there was a problem with the header.
*/
public static BinaryTable manufactureData(Header header) throws FitsException {
return new BinaryTable(header);
}
/**
* @return a newly created binary table HDU from the supplied data.
* @param data
* the data used to build the binary table. This is typically
* some kind of array of objects.
* @throws FitsException
* if there was a problem with the data.
*/
public static Header manufactureHeader(Data data) throws FitsException {
Header hdr = new Header();
data.fillHeader(hdr);
return hdr;
}
@Override
public int addColumn(Object data) throws FitsException {
this.myData.addColumn(data);
this.myData.pointToColumn(getNCols() - 1, this.myHeader);
return super.addColumn(data);
}
protected static IFitsHeader[] binaryTableColumnKeyStems() {
return KEY_STEMS;
}
/**
* What are the standard column stems for a binary table?
*/
@Override
protected IFitsHeader[] columnKeyStems() {
return BinaryTableHDU.KEY_STEMS;
}
/**
* Print out some information about this HDU.
*/
@Override
public void info(PrintStream stream) {
BinaryTable myData = this.myData;
stream.println(" Binary Table");
stream.println(" Header Information:");
int nhcol = this.myHeader.getIntValue(TFIELDS, -1);
int nrow = this.myHeader.getIntValue(NAXIS2, -1);
int rowsize = this.myHeader.getIntValue(NAXIS1, -1);
stream.print(" " + nhcol + " fields");
stream.println(", " + nrow + " rows of length " + rowsize);
for (int i = 1; i <= nhcol; i += 1) {
stream.print(" " + i + ":");
prtField(stream, "Name", TTYPEn.n(i).key());
prtField(stream, "Format", TFORMn.n(i).key());
prtField(stream, "Dimens", TDIMn.n(i).key());
stream.println("");
}
stream.println(" Data Information:");
if (myData == null || this.myData.getNRows() == 0 || this.myData.getNCols() == 0) {
stream.println(" No data present");
if (this.myData.getHeapSize() > 0) {
stream.println(" Heap size is: " + this.myData.getHeapSize() + " bytes");
}
} else {
stream.println(" Number of rows=" + this.myData.getNRows());
stream.println(" Number of columns=" + this.myData.getNCols());
if (this.myData.getHeapSize() > 0) {
stream.println(" Heap size is: " + this.myData.getHeapSize() + " bytes");
}
Object[] cols = this.myData.getFlatColumns();
for (int i = 0; i < cols.length; i += 1) {
stream.println(" " + i + ":" + ArrayFuncs.arrayDescription(cols[i]));
}
}
}
/**
* Check that this HDU has a valid header.
*
* @return true
if this HDU has a valid header.
*/
public boolean isHeader() {
return isHeader(this.myHeader);
}
private void prtField(PrintStream stream, String type, String field) {
String val = this.myHeader.getStringValue(field);
if (val != null) {
stream.print(type + '=' + val + "; ");
}
}
/**
* Convert a column in the table to complex. Only tables with appropriate
* types and dimensionalities can be converted. It is legal to call this on
* a column that is already complex.
*
* @param index
* The 0-based index of the column to be converted.
* @return Whether the column can be converted
* @throws FitsException
* if the header could not be adapted
*/
public boolean setComplexColumn(int index) throws FitsException {
Standard.context(BinaryTable.class);
boolean status = false;
if (this.myData.setComplexColumn(index)) {
// No problem with the data. Make sure the header
// is right.
BinaryTable.ColumnDesc colDesc = this.myData.getDescriptor(index);
int dim = 1;
String tdim = "";
String sep = "";
// Don't loop over all values.
// The last is the [2] for the complex data.
int[] dimens = colDesc.getDimens();
for (int i = 0; i < dimens.length - 1; i += 1) {
dim *= dimens[i];
tdim = dimens[i] + sep + tdim;
sep = ",";
}
String suffix = "C"; // For complex
// Update the TFORMn keyword.
if (colDesc.getBase() == double.class) {
suffix = "M";
}
// Worry about variable length columns.
String prefix = "";
if (this.myData.getDescriptor(index).isVarying()) {
prefix = "P";
dim = 1;
if (this.myData.getDescriptor(index).isLongVary()) {
prefix = "Q";
}
}
// Now update the header.
this.myHeader.findCard(TFORMn.n(index + 1));
HeaderCard hc = this.myHeader.nextCard();
String oldComment = hc.getComment();
if (oldComment == null) {
oldComment = "Column converted to complex";
}
this.myHeader.card(TFORMn.n(index + 1)).value(dim + prefix + suffix).comment(oldComment);
if (tdim.length() > 0) {
this.myHeader.addValue(TDIMn.n(index + 1), "(" + tdim + ")");
} else {
// Just in case there used to be a TDIM card that's no longer
// needed.
this.myHeader.deleteKey(TDIMn.n(index + 1));
}
status = true;
}
Standard.context(null);
return status;
}
// Need to tell header about the Heap before writing.
@Override
public void write(ArrayDataOutput ado) throws FitsException {
int oldSize = this.myHeader.getIntValue(PCOUNT);
if (oldSize != this.myData.getHeapSize()) {
this.myHeader.addValue(PCOUNT, this.myData.getHeapSize());
}
if (this.myHeader.getIntValue(PCOUNT) == 0) {
this.myHeader.deleteKey(THEAP);
} else {
this.myHeader.getIntValue(TFIELDS);
int offset = this.myHeader.getIntValue(NAXIS1) * this.myHeader.getIntValue(NAXIS2) + this.myData.getHeapOffset();
this.myHeader.addValue(THEAP, offset);
}
super.write(ado);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy