All Downloads are FREE. Search and download functionalities are using the official Maven repository.

nom.tam.fits.RandomGroupsHDU Maven / Gradle / Ivy

Go to download

Java library for reading and writing FITS files. FITS, the Flexible Image Transport System, is the format commonly used in the archiving and transport of astronomical data.

There is a newer version: 1.20.2
Show newest version
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.BITPIX;
import static nom.tam.fits.header.Standard.GCOUNT;
import static nom.tam.fits.header.Standard.GROUPS;
import static nom.tam.fits.header.Standard.NAXIS;
import static nom.tam.fits.header.Standard.NAXISn;
import static nom.tam.fits.header.Standard.PCOUNT;
import static nom.tam.fits.header.Standard.SIMPLE;
import static nom.tam.fits.header.Standard.XTENSION;
import static nom.tam.fits.header.Standard.XTENSION_IMAGE;

import java.io.PrintStream;
import java.util.logging.Logger;

import nom.tam.util.ArrayFuncs;

/**
 * Random groups HDUs. Note that the internal storage of random groups is a
 * Object[ngroup][2] array. The first element of each group is the parameter
 * data from that group. The second element is the data. The parameters should
 * be a one dimensional array of the primitive types byte, short, int, long,
 * float or double. The second element is a n-dimensional array of the same
 * type. When analyzing group data structure only the first group is examined,
 * but for a valid FITS file all groups must have the same structure.
 */
public class RandomGroupsHDU extends BasicHDU {

    private static final Logger LOG = Logger.getLogger(RandomGroupsHDU.class.getName());

    public static RandomGroupsData encapsulate(Object o) throws FitsException {
        if (o instanceof Object[][]) {
            return new RandomGroupsData((Object[][]) o);
        } else {
            throw new FitsException("Attempt to encapsulate invalid data in Random Group");
        }
    }

    static Object[] generateSampleRow(Header h) throws FitsException {

        int ndim = h.getIntValue(NAXIS, 0) - 1;
        int[] dims = new int[ndim];

        int bitpix = h.getIntValue(BITPIX, 0);

        Class baseClass;

        switch (bitpix) {
            case BasicHDU.BITPIX_BYTE:
                baseClass = Byte.TYPE;
                break;
            case BasicHDU.BITPIX_SHORT:
                baseClass = Short.TYPE;
                break;
            case BasicHDU.BITPIX_INT:
                baseClass = Integer.TYPE;
                break;
            case BasicHDU.BITPIX_LONG:
                baseClass = Long.TYPE;
                break;
            case BasicHDU.BITPIX_FLOAT:
                baseClass = Float.TYPE;
                break;
            case BasicHDU.BITPIX_DOUBLE:
                baseClass = Double.TYPE;
                break;
            default:
                throw new FitsException("Invalid BITPIX:" + bitpix);
        }

        // Note that we have to invert the order of the axes
        // for the FITS file to get the order in the array we
        // are generating. Also recall that NAXIS1=0, so that
        // we have an 'extra' dimension.

        for (int i = 0; i < ndim; i += 1) {
            long cdim = h.getIntValue(NAXISn.n(i + 2), 0);
            if (cdim < 0) {
                throw new FitsException("Invalid array dimension:" + cdim);
            }
            dims[ndim - i - 1] = (int) cdim;
        }

        Object[] sample = new Object[2];
        sample[0] = ArrayFuncs.newInstance(baseClass, h.getIntValue(PCOUNT));
        sample[1] = ArrayFuncs.newInstance(baseClass, dims);

        return sample;
    }

    /**
     * Check if this data is compatible with Random Groups structure. Must be an
     * Object[ngr][2] structure with both elements of each group having the same
     * base type and the first element being a simple primitive array. We do not
     * check anything but the first row.
     * 
     * @param potentialData
     *            data to check
     * @return is this data compatible with Random Groups structure
     */
    public static boolean isData(Object potentialData) {
        if (potentialData instanceof Object[][]) {
            Object[][] o = (Object[][]) potentialData;
            if (o.length > 0 && o[0].length == 2 && //
                    ArrayFuncs.getBaseClass(o[0][0]) == ArrayFuncs.getBaseClass(o[0][1])) {
                String cn = o[0][0].getClass().getName();
                if (cn.length() == 2 && cn.charAt(1) != 'Z' || cn.charAt(1) != 'C') {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * @return Is this a random groups header?
     * @param hdr
     *            The header to be tested.
     */
    public static boolean isHeader(Header hdr) {

        if (hdr.getBooleanValue(SIMPLE)) {
            return hdr.getBooleanValue(GROUPS);
        }

        String xtension = hdr.getStringValue(XTENSION);
        xtension = xtension == null ? "" : xtension.trim();
        if (XTENSION_IMAGE.equals(xtension)) {
            return hdr.getBooleanValue(GROUPS);
        }

        return false;
    }

    /**
     * @return Create FITS data object corresponding to a given header.
     * @param header
     *            header for the data creation
     * @throws FitsException
     *             if the operation failed
     */
    public static RandomGroupsData manufactureData(Header header) throws FitsException {

        int gcount = header.getIntValue(GCOUNT, -1);
        int pcount = header.getIntValue(PCOUNT, -1);

        if (!header.getBooleanValue(GROUPS) || header.getIntValue(NAXISn.n(1), -1) != 0 || gcount < 0 || pcount < 0 || header.getIntValue(NAXIS) < 2) {
            throw new FitsException("Invalid Random Groups Parameters");
        }

        // Allocate the object.
        Object[][] dataArray;

        if (gcount > 0) {
            dataArray = new Object[gcount][2];
        } else {
            dataArray = new Object[0][];
        }

        Object[] sampleRow = generateSampleRow(header);
        for (int i = 0; i < gcount; i += 1) {
            dataArray[i][0] = ((Object[]) ArrayFuncs.deepClone(sampleRow))[0];
            dataArray[i][1] = ((Object[]) ArrayFuncs.deepClone(sampleRow))[1];
        }
        return new RandomGroupsData(dataArray);

    }

    /**
     * @return Make a header point to the given object.
     * @param d
     *            The random groups data the header should describe.
     * @throws FitsException
     *             if the operation failed
     */
    static Header manufactureHeader(Data d) throws FitsException {

        if (d == null) {
            throw new FitsException("Attempt to create null Random Groups data");
        }
        Header h = new Header();
        d.fillHeader(h);
        return h;

    }

    /**
     * Create an HDU from the given header and data .
     * 
     * @param header
     *            header to use
     * @param data
     *            data to use
     */
    public RandomGroupsHDU(Header header, RandomGroupsData data) {
        super(header, data);
    }

    @Override
    protected boolean canBePrimary() {
        return true;
    }

    @Override
    public void info(PrintStream stream) {

        stream.println("Random Groups HDU");
        if (this.myHeader != null) {
            stream.println("   HeaderInformation:");
            stream.println("     Ngroups:" + this.myHeader.getIntValue(GCOUNT));
            stream.println("     Npar:   " + this.myHeader.getIntValue(PCOUNT));
            stream.println("     BITPIX: " + this.myHeader.getIntValue(BITPIX));
            stream.println("     NAXIS:  " + this.myHeader.getIntValue(NAXIS));
            for (int i = 0; i < this.myHeader.getIntValue(NAXIS); i += 1) {
                stream.println("      NAXIS" + (i + 1) + "= " + this.myHeader.getIntValue(NAXISn.n(i + 1)));
            }
        } else {
            stream.println("    No Header Information");
        }

        Object[][] data = null;
        if (this.myData != null) {
            data = (Object[][]) this.myData.getData();
        }

        if (data == null || data.length < 1 || data[0].length != 2) {
            stream.println("    Invalid/unreadable data");
        } else {
            stream.println("    Number of groups:" + data.length);
            stream.println("    Parameters: " + ArrayFuncs.arrayDescription(data[0][0]));
            stream.println("    Data:" + ArrayFuncs.arrayDescription(data[0][1]));
        }
    }

    /**
     * Check that this HDU has a valid header.
     * 
     * @return true if this HDU has a valid header.
     */
    public boolean isHeader() {
        return isHeader(this.myHeader);
    }

    /**
     * Move a RandomGroupsHDU to or from the beginning of a FITS file. Note that
     * the FITS standard only supports Random Groups data at the beginning of
     * the file, but we allow it within Image extensions.
     * 
     * @param status
     *            true if the header should be primary
     */
    @Override
    protected void setPrimaryHDU(boolean status) throws FitsException {
        super.setPrimaryHDU(status);
        if (status) {
            this.myHeader.setSimple(true);
        } else {
            this.myHeader.setXtension(XTENSION_IMAGE);
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy