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

nom.tam.util.Quantizer 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.21.1
Show newest version
package nom.tam.util;

/*-
 * #%L
 * nom.tam.fits
 * %%
 * Copyright (C) 1996 - 2024 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 nom.tam.fits.Header;
import nom.tam.fits.HeaderCard;
import nom.tam.fits.header.Standard;

/**
 * 

* Quantizes floating point values as integers. FITS allows representing * floating-point values as integers, e.g. to allow more compact storage at some * tolerable level of precision loss. For example, you may store floating-point * values (4 bytes) discretized into 64k levels as 16-bit integers. The * conversion involves a linear transformation: *

* *
 *   {float-value}= {scaling} * {int-value} + {offset}
 * 
*

* and the inverse transformation: *

* *
 *   {int-value} = round(({float-value} - {offset}) / {scaling})
 * 
*

* The latter floating-point to integer conversion naturally results in some * loss of precision, comparable to the level of the scaling factor, i.e. the * peration of discrete levels at which information is preserved. *

*

* In addition to the scaling conversion, FITS also allows designating an * integer blanking value to indicate missing or invalid data, which is mapped * to NaN in the floating point representation. *

*

* Fits allows for quantized representations of floating-point data both in * image HDUs and for columns in binary table HDUs. The quantization parameters * are stored differently for the two types of HDUs, using the BSCALE, BZERO, * and BLANK keywords for images, and the TSCALn, TZEROn, and TNULLn keywords * for individual columns in a table. *

* * @author Attila Kovacs * @since 1.20 */ public class Quantizer { private Long blankingValue; private double scale = 1.0; private double offset; /** * Constructs a new decimal/integer conversion rule. * * @param scale * The scaling value, that is the spacing of the qunatized levels * @param offset * The floating-point value that corresponds to an integer value * of 0 (zero). * @param blankingValue * The value to use to represent NaN values in the integer * representation, that is missing or invalid data. */ public Quantizer(double scale, double offset, int blankingValue) { this(scale, offset, (long) blankingValue); } /** * Constructs a new decimal/integer conversion rule. * * @param scale * The scaling value, that is the spacing of the qunatized levels * @param offset * The floating-point value that corresponds to an integer value * of 0 (zero). * @param blankingValue * The value to use to represent NaN values in the integer * representation, that is missing or invalid data. It may be * null if the floating-point data is not expected * to contain NaN values ever. */ public Quantizer(double scale, double offset, Long blankingValue) { this.scale = scale; this.offset = offset; this.blankingValue = blankingValue; } /** * Converts a floating point value to its integer representation using the * quantization. * * @param value * the floating point value * @return the corresponding qunatized integer value * @see #toDouble(long) */ public long toLong(double value) { if (!Double.isFinite(value)) { if (blankingValue == null) { throw new IllegalStateException("No blanking value was defined."); } return blankingValue; } return Math.round((value - offset) / scale); } /** * Converts an integer value to the floating-point value it represents under * the qunatization. * * @param value * the integer value * @return the corresponding floating-point value, which may be NaN. * @see #toLong(double) */ public double toDouble(long value) { if (blankingValue != null && value == blankingValue) { return Double.NaN; } return scale * value + offset; } /** * Checks if the quantization is the same as the default quantization. For * example, maybe we don't need to (want to) write the quantization keywords * into the FITS headers if these are irrelevant and/or not meaningful. So * this method might help us decide when quantization is necessary / * meaningful vs when it is irrelevant. * * @return true if the scaling is 1.0, the offset 0.0, and the * blanking value is null. Otherwise false * . */ public boolean isDefault() { return scale == 1.0 && offset == 0.0 && blankingValue == null; } /** * Adds the quantization parameters to an image header, * * @param h * the image header. * @see #fromImageHeader(Header) * @see #editTableHeader(Header, int) */ public void editImageHeader(Header h) { h.addValue(Standard.BSCALE, scale); h.addValue(Standard.BZERO, offset); if (blankingValue != null) { h.addValue(Standard.BLANK, blankingValue); } else { h.deleteKey(Standard.BLANK); } } /** * Adds the quantization parameters to a binaty table header, * * @param h * the binary table header. * @param col * the zero-based Java column index * @see #fromTableHeader(Header, int) * @see #editImageHeader(Header) */ public void editTableHeader(Header h, int col) { Cursor c = h.iterator(); c.setKey(Standard.TFORMn.n(col + 1).key()); c.add(HeaderCard.create(Standard.TSCALn.n(col + 1), scale)); c.add(HeaderCard.create(Standard.TZEROn.n(col + 1), offset)); if (blankingValue != null) { c.add(HeaderCard.create(Standard.TNULLn.n(col + 1), blankingValue)); } else { h.deleteKey(Standard.TNULLn.n(col + 1)); } } /** * Returns the quantizer that is described by an image header. * * @param h * an image header * @return the quantizer that id described by the header. It may be the * default quantizer if the header does not contain any of the * quantization keywords. * @see #editImageHeader(Header) * @see #fromTableHeader(Header, int) * @see #isDefault() */ public static Quantizer fromImageHeader(Header h) { return new Quantizer(h.getDoubleValue(Standard.BSCALE, 1.0), h.getDoubleValue(Standard.BZERO, 0.0), // h.containsKey(Standard.BLANK) ? h.getLongValue(Standard.BLANK) : null); } /** * Returns the quantizer that is described by a binary table header. * * @param h * a binary table header * @param col * the zero-based Java column index * @return the quantizer that id described by the header. It may be the * default quantizer if the header does not contain any of the * quantization keywords. * @see #editTableHeader(Header, int) * @see #fromImageHeader(Header) * @see #isDefault() */ public static Quantizer fromTableHeader(Header h, int col) { return new Quantizer(h.getDoubleValue(Standard.TSCALn.n(col + 1), 1.0), // h.getDoubleValue(Standard.TZEROn.n(col + 1), 0.0), // h.containsKey(Standard.TNULLn.n(col + 1)) ? h.getLongValue(Standard.TNULLn.n(col + 1)) : null); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy