Skip to content

Commit

Permalink
fits: BintableStarTable now reads HEALPix headers
Browse files Browse the repository at this point in the history
The standard FITS table input handler now looks for header cards
corresponding to the FITS HEALPix convention, and if consistent
ones are found it inserts the STIL headers defined in
uk.ac.starlink.table.HealpixTableInfo into the resulting StarTable.
  • Loading branch information
mbtaylor committed Jan 10, 2019
1 parent 824d791 commit a31f419
Show file tree
Hide file tree
Showing 2 changed files with 126 additions and 0 deletions.
118 changes: 118 additions & 0 deletions fits/src/main/uk/ac/starlink/fits/BintableStarTable.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,15 @@
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import nom.tam.fits.FitsException;
import nom.tam.fits.Header;
import uk.ac.starlink.table.AbstractStarTable;
import uk.ac.starlink.table.ColumnInfo;
import uk.ac.starlink.table.DefaultValueInfo;
import uk.ac.starlink.table.DescribedValue;
import uk.ac.starlink.table.HealpixTableInfo;
import uk.ac.starlink.table.RowSequence;
import uk.ac.starlink.table.TableSink;
import uk.ac.starlink.table.Tables;
Expand All @@ -35,6 +37,14 @@
* method to release them. Attempting to read data following
* such a call may result in an exception.
*
* <p>Limited support is provided for the
* <a href="https://healpix.sourceforge.io/data/examples/healpix_fits_specs.pdf"
* >HEALPix-FITS</a> convention;
* the relevant {@link uk.ac.starlink.table.HealpixTableInfo} table parameters
* are added, but any BAD_DATA keyword value is ignored,
* and the 1024-element array-valued column variant of the format is not
* understood.
*
* @author Mark Taylor
*/
public abstract class BintableStarTable extends AbstractStarTable
Expand Down Expand Up @@ -363,6 +373,22 @@ else if ( zIsInt && zInLongRange ) {
setName( tname );
}

/* Look for headers specific to the HEALPix-FITS encoding. */
if ( "HEALPIX".equals( cards.getStringValue( "PIXTYPE" ) ) ) {
HealpixTableInfo hpxInfo = null;
try {
hpxInfo = extractHealpixInfo( cards, colInfos_ );
}
catch ( Exception e ) {
logger_.log( Level.WARNING,
"HEALPix header parse failure: " + e.getMessage(),
e );
}
if ( hpxInfo != null ) {
getParameters().addAll( Arrays.asList( hpxInfo.toParams() ) );
}
}

/* Any unused header cards become table parameters. */
getParameters().addAll( Arrays.asList( cards.getUnusedParams() ) );
}
Expand Down Expand Up @@ -492,6 +518,98 @@ public void close() {
}
}

/**
* Investigates headers for cards specific to the HEALPix-FITS convention.
* If it looks like the headers describe a HEALPix map,
* a corresponding HealpixTableInfo object is returned,
* otherwise a RuntimeException with an informative message is thrown.
*
* @param cards header
* @param infos column metadata
* @return healpix metadata object if the headers look appropriate
* @throws RuntimeException if the headers don't look appropriate
* @see <a
href="https://healpix.sourceforge.io/data/examples/healpix_fits_specs.pdf"
* >HEALPix-FITS convention</a>
*/
private static HealpixTableInfo extractHealpixInfo( HeaderCards cards,
ColumnInfo[] infos ) {

/* Get NSIDE/level value. */
Long nSide = cards.getLongValue( "NSIDE" );
long nside = nSide.longValue();
if ( nSide == null ) {
throw new IllegalStateException( "No HEALPix NSIDE header" );
}
final int level = Long.numberOfTrailingZeros( nside );
if ( 1 << level != nside ) {
throw new IllegalStateException( "Invalid HEALPix header value "
+ "NSIDE=" + nside );
}

/* Get ordering scheme. */
final boolean isNest;
String ordering = cards.getStringValue( "ORDERING" );
if ( ordering == null ) {
throw new IllegalStateException( "Missing HEALPix header "
+ "ORDERING" );
}
else if ( "NESTED".equals( ordering ) ) {
isNest = true;
}
else if ( "RING".equals( ordering ) ) {
isNest = false;
}
else {
throw new IllegalStateException( "Unrecognised HEALPix header "
+ "ORDERING='" + ordering + "'" );
}

/* Get HEALPix index column, if any. */
final String ipixColName;
String indxschm = cards.getStringValue( "INDXSCHM" );
if ( indxschm == null ) {
logger_.warning( "Missing nominally required HEALPix header "
+ "INDXSCHM, assuming IMPLICIT" );
ipixColName = null;
}
else if ( "IMPLICIT".equals( indxschm ) ) {
ipixColName = null;
}
else if ( "EXPLICIT".equals( indxschm ) ) {
ipixColName = infos[ 0 ].getName();
}
else {
throw new IllegalStateException( "Unrecognised HEALPix header "
+ "INDXSCHM='" + indxschm + "'" );
}

/* Get coordinate system indicator, if any. */
final HealpixTableInfo.HpxCoordSys csys;
String coordsys = cards.getStringValue( "COORDSYS" );
if ( coordsys != null ) {
csys = coordsys.length() == 1
? HealpixTableInfo.HpxCoordSys
.fromCharacter( coordsys.charAt( 0 ) )
: null;
if ( csys == null ) {
logger_.warning( "Unknown HEALPix header COORDSYS='"
+ coordsys + "'" );
}
}
else {
csys = null;
}

/* Note that the nominally required BAD_DATA value is currently
* ignored. It is against the spirit of normal FITS bad value
* handling, and would require considerable complication
* and inefficiency to handle correctly. */

/* Return a new metadata object. */
return new HealpixTableInfo( level, isNest, ipixColName, csys );
}

/**
* Sequential-only BintableStarTable concrete subclass.
*/
Expand Down
8 changes: 8 additions & 0 deletions fits/src/main/uk/ac/starlink/fits/FitsTableBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,14 @@
* file location as a URL (e.g. "file:spec23.fits" rather than "spec23.fits"),
* which fools the handler into thinking that it can't be mapped.
*
* <p>Limited support is provided for the
* <a href="https://healpix.sourceforge.io/data/examples/healpix_fits_specs.pdf"
* >HEALPix-FITS</a> convention;
* the relevant {@link uk.ac.starlink.table.HealpixTableInfo} table parameters
* are added, but any BAD_DATA keyword value is ignored,
* and the 1024-element array-valued column variant of the format is not
* understood.
*
* @author Mark Taylor (Starlink)
*/
public class FitsTableBuilder implements TableBuilder, MultiTableBuilder {
Expand Down

0 comments on commit a31f419

Please sign in to comment.