/* VisAD system for interactive analysis and visualization of numerical data. Copyright (C) 1996 - 2017 Bill Hibbard, Curtis Rueden, Tom Rink, Dave Glowacki, Steve Emmerson, Tom Whittaker, Don Murray, and Tommy Jasmin. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ package visad.data.dods; import dods.dap.*; import java.rmi.RemoteException; import visad.data.BadFormException; import visad.data.in.*; import visad.*; /** * Provides support for processing numeric values in a DODS dataset. Processing * includes checking for non-equality with "missing" or "fill" values, * unpacking into more capacious data types, and checking that the values lie * within a valid range. * * <P>Instances are immutable.</P> * * @author Steven R. Emmerson */ public abstract class Valuator { protected final ValueVetter vetter; protected final ValueUnpacker unpacker; protected final ValueRanger ranger; /** * Constructs from the attributes of a DODS variable. * * @param table The attribute table for a DODS variable. * @throws BadFormException The attribute table is corrupt. * @throws VisADException VisAD failure. * @throws RemoteException Java RMI failure. */ protected Valuator(AttributeTable table) throws BadFormException, VisADException, RemoteException { vetter = valueVetter(table); unpacker = valueUnpacker(table); ranger = valueRanger(table); } /** * Returns an instance of this class corresponding to the attributes for a * DODS variable. * * @param table The attribute table for a DODS variable. * @param type The type of packed variable: {@link * Attribute#BYTE}, {@link Attribute#INT16}, etc. * @throws BadFormException The attribute table is corrupt. * @throws VisADException VisAD failure. * @throws RemoteException Java RMI failure. */ public static Valuator valuator(AttributeTable table, int type) throws BadFormException, VisADException, RemoteException { Valuator valuator; switch (type) { case Attribute.BYTE: valuator = valueRanger(table).getMin() >= 0 ? UByteValuator.valuator(table) : ByteValuator.valuator(table); break; case Attribute.FLOAT32: valuator = Float32Valuator.valuator(table); break; case Attribute.FLOAT64: valuator = Float64Valuator.valuator(table); break; case Attribute.INT16: valuator = Int16Valuator.valuator(table); break; case Attribute.INT32: valuator = Int32Valuator.valuator(table); break; case Attribute.UINT16: valuator = UInt16Valuator.valuator(table); break; case Attribute.UINT32: valuator = UInt32Valuator.valuator(table); break; default: throw new BadFormException( "Valuator.valuator(AttributeTable,int): " + "Unknown variable type: " + type); } return valuator; } /** * Returns the set used to represent unpacked, numeric values associated * with this instance in the range of a VisAD {@link FlatField}. * * @return realType The VisAD real-type for the set. * @return The set used to represent numeric values * associated with this instance. * @throws VisADException VisAD failure. */ public abstract SimpleSet getRepresentationalSet(RealType realType) throws VisADException; /** * Processes a value. * * @param value The value to be processed. */ public float process(float value) { return ranger.process(unpacker.process(vetter.process(value))); } /** * Processes a value. * * @param values The values to be processed. */ public float[] process(float[] values) { return ranger.process(unpacker.process(vetter.process(values))); } /** * Processes values. * * @param value The value to be processed. */ public double process(double value) { return ranger.process(unpacker.process(vetter.process(value))); } /** * Processes values. * * @param values The values to be processed. */ public double[] process(double[] values) { return ranger.process(unpacker.process(vetter.process(values))); } /** * Decodes an attribute for a DODS variable. * * @param name The name of the attribute. * @param table The attribute table of the DODS variable. * @param index The index of the attribute element to be * decoded. * @throws BadFormException The DODS information is corrupt. * @throws VisADException VisAD failure. * @throws RemoteException Java RMI failure. */ protected static double decode(String name, AttributeTable table, int index) throws BadFormException, VisADException, RemoteException { double value = Double.NaN; // default value Attribute attr = table.getAttribute(name); if (attr != null) { DataImpl data = AttributeAdapterFactory.attributeAdapterFactory() .attributeAdapter(name, attr).data(false); if (data instanceof Real && index == 0) value = ((Real)data).getValue(); else if (data instanceof Gridded1DDoubleSet) value = ((Gridded1DSet)data).indexToDouble(new int[] {index})[0][0]; else if (data instanceof Gridded1DSet) value = ((Gridded1DSet)data).indexToValue(new int[] {index})[0][0]; else System.err.println( "ValueProcessor.decode(String,AttributeTable,int): " + "Attribute \"" + name + "\" has non-numeric type: " + attr.getTypeString()); } return value; } /** * Returns an instance of a value vetter corresponding to the attributes * of a DODS variable. * * @param table The DODS attribute table. May be * <code>null</code>, in which case a trivial * vetter is returned. * @return A value vetter. * @throws BadFormException The attribute table is corrupt. * @throws VisADException VisAD failure. * @throws RemoteException Java RMI failure. */ public static ValueVetter valueVetter(AttributeTable table) throws BadFormException, VisADException, RemoteException { double fill = Double.NaN; // default double missing = Double.NaN; // default if (table != null) { fill = decode("_FillValue", table, 0); missing = decode("missing_value", table, 0); } return ValueVetter.valueVetter(new double[] {fill, missing}); } /** * Returns an instance of a value unpacker corresponding to the attributes * of a DODS variable. * * @param table A DODS attribute table. May be * <code>null</code>, in which case a trivial * unpacker is returned. * @return A value unpacker. * @throws BadFormException The attribute table is corrupt. * @throws VisADException VisAD failure. * @throws RemoteException Java RMI exception. */ public static ValueUnpacker valueUnpacker( AttributeTable table) throws BadFormException, VisADException, RemoteException { ValueUnpacker unpacker; if (table == null) { unpacker = ValueUnpacker.valueUnpacker(); } else { double scale = decode("scale_factor", table, 0); double offset = decode("add_offset", table, 0); if (scale == scale && scale != 1 && offset == offset && offset != 0) { unpacker = ScaleAndOffsetUnpacker.scaleAndOffsetUnpacker( scale, offset); } else if (scale == scale && scale != 1) { unpacker = ScaleUnpacker.scaleUnpacker(scale); } else if (offset == offset && offset != 0) { unpacker = OffsetUnpacker.offsetUnpacker(offset); } else { unpacker = ValueUnpacker.valueUnpacker(); } } return unpacker; } /** * Returns an instance of a value ranger corresponding to the attributes of * a DODS variable. * * @param table A DODS attribute table. May be * <code>null</code>, in which case a trivial * ranger is returned. * @return A value ranger. * @throws BadFormException The attribute table is corrupt. * @throws VisADException VisAD failure. * @throws RemoteException Java RMI exception. */ public static ValueRanger valueRanger(AttributeTable table) throws BadFormException, VisADException, RemoteException { double lower = Double.NEGATIVE_INFINITY; double upper = Double.POSITIVE_INFINITY; if (table != null) { if (table.getAttribute("valid_range") == null) { lower = decode("valid_min", table, 0); upper = decode("valid_max", table, 0); } else { lower = decode("valid_range", table, 0); upper = decode("valid_range", table, 1); } } return ValueRanger.valueRanger(lower, upper); } }