//

/*
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);
    }


}

 

Ads help maintain this website.