// /* 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.meteorology; import java.rmi.RemoteException; import visad.*; import visad.georef.*; import java.rmi.RemoteException; import visad.util.DataUtility; /** * An implementation for representing single-banded planar * satellite or radar imagery. */ public class SingleBandedImageImpl extends FlatField implements SingleBandedImage { private DateTime startTime; private String description; private Real minValue; private Real maxValue; private boolean copyOnClone = true; /** * Construct a SingleBandedImageImpl without any data. * * @param function FunctionType for this image. It must have a * Range that has only one (Real) component. * @param domain DomainSet for this image. * @param startTime starting time of the image. * @param desc description * * @throws VisADException couldn't create the SingleBandedImageImpl */ public SingleBandedImageImpl(FunctionType function, Set domain, DateTime startTime, String desc) throws VisADException { this(new FlatField(function, domain), startTime, desc); } /** * Construct a SingleBandedImageImpl from a FlatField. * * @param image FlatField representing an image. It must * have a Range that only has one (Real) component. * @param startTime starting time of the image. * @param desc description * * @throws VisADException couldn't create the SingleBandedImageImpl */ public SingleBandedImageImpl(FlatField image, DateTime startTime, String desc) throws VisADException { this(image, startTime, desc, true); } /** * Construct a SingleBandedImage from the FlatField specified. * * @param image FlatField representing an image. It must * have a Range that only has one (Real) component. * @param startTime starting time of the image. * @param desc description * @param copyData make a copy of the data on setSample call * * @throws VisADException couldn't create the SingleBandedImageImpl */ public SingleBandedImageImpl(FlatField image, DateTime startTime, String desc, boolean copyData) throws VisADException { super((FunctionType) image.getType(), image.getDomainSet(), image.getRangeCoordinateSystem()[0], image.getRangeSets(), DataUtility.getRangeUnits(image)); // vet the range if (((FunctionType) getType()).getFlatRange().getNumberOfRealComponents() > 1) { throw new VisADException( "SingleBandedImageImpl: Range must be a RealType or " + "RealTupleType with one component"); } // add in the data try { if (!image.isMissing()) { setSamples( //image.getFloats(false), image.getRangeErrors(), copyData); image.getFloats(false), copyData); } } catch (java.rmi.RemoteException re) {;} // can't happen since local // set some local variables this.startTime = startTime; description = desc; } /** * Get the start time of the image. * @return DateTime representing the start time of the image. */ public DateTime getStartTime() { return startTime; } /** * Return a descriptive string for this image. * @return description */ public String getDescription() { return description; } /** * Get the minimum possible value for this image * @return a Real representing the minimum possible value. Using a * Real allows us to associate units and error estimates with * the value */ public Real getMinRangeValue() { checkMaxMinValues(); return minValue; } /** * Get the maximum possible value for this image * @return a Real representing the maximum possible value. Using a * Real allows us to associate units and error estimates with * the value */ public Real getMaxRangeValue() { checkMaxMinValues(); return maxValue; } /** * Check to see if this image has a domain that can map to Latitude * and Longitude. * * @return true if it has navigation, otherwise false */ public boolean isNavigated() { return getDomainCoordinateSystem() instanceof NavigatedCoordinateSystem; } /** * Set the range values of the function including ErrorEstimate-s; * the order of range values must be the same as the order of * domain indices in the DomainSet. Overridden so we can set * max and min values. * * @param range pixel values as doubles * @param errors ErrorEstimates for values (may be null); * @param copy flag to make a copy of value array or not * * @throws VisADException couldn't set values * @throws RemoteException couldn't set remote object */ public void setSamples(float[][] range, ErrorEstimate[] errors, boolean copy) throws VisADException, RemoteException { super.setSamples(range, errors, copy); minValue = maxValue = null; } /** * Set the range values of the function including ErrorEstimate-s; * the order of range values must be the same as the order of * domain indices in the DomainSet. Overridden so we can set * max and min values. * * @param range pixel values as doubles * @param errors ErrorEstimates for values (may be null); * @param copy flag to make a copy of value array or not * * @throws VisADException couldn't set values * @throws RemoteException couldn't set remote object */ public void setSamples(double[][] range, ErrorEstimate[] errors, boolean copy) throws VisADException, RemoteException { super.setSamples(range, errors, copy); minValue = maxValue = null; } /** return new SingleBandedImageImpl with value 'op this' */ public Data unary(int op, MathType new_type, int sampling_mode, int error_mode) throws VisADException { return new SingleBandedImageImpl( (FlatField) super.unary(op, new_type, sampling_mode, error_mode), startTime, description, false); } private void checkMaxMinValues() { if(minValue == null) { try { setMaxMinValues(); } catch(Exception exc) { System.err.println ("error:" + exc); exc.printStackTrace(); } } } private void setMaxMinValues() throws VisADException { Unit units = null; RealType type = RealType.Generic; ErrorEstimate errors = null; float min = Float.POSITIVE_INFINITY; float max = Float.NEGATIVE_INFINITY; try { Set rangeSet = getRangeSets()[0]; units = getRangeUnits()[0][0]; type = (RealType) ((RealTupleType) ((SetType) rangeSet.getType()).getDomain()).getComponent(0); errors = getRangeErrors()[0]; if (rangeSet instanceof SampledSet) { min = ((SampledSet) rangeSet).getLow()[0]; max = ((SampledSet) rangeSet).getHi()[0]; } else { float[] values = getFloats(false)[0]; final int len = values.length; for (int i = 0; i < len; i++) { float value = values[i]; if (value < min) min = value; if (value > max) max = value; } } } catch (Exception e) {;} minValue = new Real(type, min, units, errors); maxValue = new Real(type, max, units, errors); } /** * Return the result of a binary operation between this instance and another * operand. If the other operand is an object of this class and the result * of the {@link FlatField#binary(Data, int, int, int)} method is a * {@link FlatField} from which an object of this class can be constructed, * then this method returns an instance of this class with a description * determined by the input descriptions and the operation and a time equal * to the average times of the input; otherwise, the object resulting from * the {@link FlatField#binary} method is returned. * * @param data The other operand of the operation. * @param op The operation to perform (e.g. {@link * Data#ADD}, {@link Data#DIVIDE}, etc.). * @param samplingMode The sampling mode. One of {@link * Data#NEAREST_NEIGHBOR} or {@link * Data#WEIGHTED_AVERAGE}. * @param errorMode The error propagation mode. One of {@link * Data#NO_ERRORS}, {@link Data#INDEPENDENT}, * or {@link Data#DEPENDENT}. * @return The result of the operation on this * instance and the other operand. * @throws VisADException if a VisAD failure occurs. * @throws RemovetException if a Java RMI failure occurs. */ public Data binary(Data data, int op, int samplingMode, int errorMode) throws VisADException, RemoteException { Data result = super.binary(data, op, samplingMode, errorMode); if (data instanceof SingleBandedImage && result instanceof FlatField) { SingleBandedImage that = (SingleBandedImage)data; double time1 = startTime.getReal().getValue(); double time2 = that.getStartTime().getReal().getValue(); DateTime time = new DateTime((time1 + time2) / 2); String desc; String desc1 = description; String desc2 = that.getDescription(); if (desc1.indexOf(' ') != -1) desc1 = "(" + desc1 + ")"; if (desc2.indexOf(' ') != -1) desc2 = "(" + desc2 + ")"; switch (op) { case ADD: desc = desc1 + " + " + desc2; break; case SUBTRACT: desc = desc1 + " - " + desc2; break; case MULTIPLY: desc = desc1 + " * " + desc2; break; case DIVIDE: desc = desc1 + " / " + desc2; break; case POW: desc = "POW(" + desc1 + ", " + desc2 + ")"; break; case MAX: desc = "MAX(" + desc1 + ", " + desc2 + ")"; break; case MIN: desc = "MIN(" + desc1 + ", " + desc2 + ")"; break; case ATAN: desc = "ATAN2(" + desc1 + ", " + desc2 + ")"; break; case ATAN2_DEGREES: desc = "ATAN2_DEGREES(" + desc1 + ", " + desc2 + ")"; break; case REMAINDER: desc = "REMAINDER(" + desc1 + ", " + desc2 + ")"; break; default: throw new Error("Assertion Failure"); } try { result = new SingleBandedImageImpl((FlatField)result, time, desc, false); } catch (VisADException ex) { // do nothing: return the original result } } return result; } /** * Return the result of a unary operation on this instance. If the result * of the {@link FlatField#unary(int, int, int)} method is a {@link * FlatField} from which an object of this class can be constructed, * then this method returns an instance of this class with a description * determined by the input description and the operation and a time equal * to the time of this instance; otherwise, the object resulting from the * {@link FlatField#unary} method is returned. * * @param op The operation to perform (e.g. {@link * Data#ABS}, {@link Data#COS}, etc.). * @param samplingMode The sampling mode. One of {@link * Data#NEAREST_NEIGHBOR} or {@link * Data#WEIGHTED_AVERAGE}. * @param errorMode The error propagation mode. One of {@link * Data#NO_ERRORS}, {@link Data#INDEPENDENT}, * or {@link Data#DEPENDENT}. * @return The result of the operation on this instance. * @throws VisADException if a VisAD failure occurs. * @throws RemovetException if a Java RMI failure occurs. */ public Data unary(int op, int samplingMode, int errorMode) throws VisADException, RemoteException { Data result = super.unary(op, samplingMode, errorMode); if (result instanceof FlatField) { String desc = description; switch (op) { case ABS: desc = "ABS(" + desc + ")"; break; case ACOS: desc = "ACOS(" + desc + ")"; break; case ACOS_DEGREES: desc = "ACOS_DEGREES(" + desc + ")"; break; case ASIN: desc = "ASIN(" + desc + ")"; break; case ASIN_DEGREES: desc = "ASIN_DEGREES(" + desc + ")"; break; case ATAN: desc = "ATAN(" + desc + ")"; break; case ATAN_DEGREES: desc = "ATAN_DEGREES(" + desc + ")"; break; case CEIL: desc = "CEIL(" + desc + ")"; break; case COS: desc = "COS(" + desc + ")"; break; case COS_DEGREES: desc = "COS_DEGREES(" + desc + ")"; break; case EXP: desc = "EXP(" + desc + ")"; break; case FLOOR: desc = "FLOOR(" + desc + ")"; break; case LOG: desc = "LOG(" + desc + ")"; break; case RINT: desc = "RINT(" + desc + ")"; break; case ROUND: desc = "ROUND(" + desc + ")"; break; case SIN: desc = "SIN(" + desc + ")"; break; case SIN_DEGREES: desc = "SIN_DEGREES(" + desc + ")"; break; case SQRT: desc = "SQRT(" + desc + ")"; break; case TAN: desc = "TAN(" + desc + ")"; break; case TAN_DEGREES: desc = "TAN_DEGREES(" + desc + ")"; break; case NEGATE: desc = "NEGATE(" + desc + ")"; break; default: throw new Error("Assertion Failure"); } try { result = new SingleBandedImageImpl((FlatField)result, startTime, desc, false); } catch (VisADException ex) { // do nothing: return the original result } } return result; } /** * for effeciency provide access to the uncopied floats */ public float[][] getImageData() throws VisADException { return unpackFloats(false); } }