Re: Tuples with reals cause an exception

Hi Andrew,

> I've been wanting to get some data like (n)->(lat, lon, name) onto the
> screen, but I'm having trouble.
> 
> I've observed that I can write a program with:
> 
> 1. RealType->RealType it does work.
> 2. RealType->(RealType, RealType) it does not work!
> 3. RealType->(TextType, RealType) it does work.
> 
> In all these cases the domain type is mapped to Display.XAxis and one
> of the range types is mapped to Display.Text
> 
> Attached is my program that implements number 2 above, I would
> appreciate
> help getting this to work.
> 
> The output looks like:
> java.lang.ClassCastException: visad.Tuple
>         at visad.FieldImpl.getRangeCoordinateSystem(FieldImpl.java,
> Compiled Code)
> ...

Congrats, you've found a bug in VisAD. The first one in a
long time.

Tuple.java shouldn't let you construct a Tuple whose
components are all Reals - it should tell you to construct
a RealTuple instead. I've attached the fixed version of
Tuple.java, which will be in the ftp source distribution
the next time I run the tests.

In your simple.java, replace:

                Data[] data = {
                        new Real(RealType.Latitude, 33.5),
                        new Real(RealType.Longitude, 33.5),
                        new Real(cnameType, 33.5)
                };
                Tuple rangeTuple = new Tuple(rangeTupleType, data);

with:

                Real[] data = {
                        new Real(RealType.Latitude, 33.5),
                        new Real(RealType.Longitude, 33.5),
                        new Real(cnameType, 33.5)
                };
                RealTuple rangeTuple = new RealTuple(data);

Thanks for finding this.

Cheers,
Bill
----------------------------------------------------------
Bill Hibbard, SSEC, 1225 W. Dayton St., Madison, WI  53706
hibbard@xxxxxxxxxxxxxxxxx  608-263-4427  fax: 608-263-6738
http://www.ssec.wisc.edu/~billh/vis.html
//
// Tuple.java
//

/*
VisAD system for interactive analysis and visualization of numerical
data.  Copyright (C) 1996 - 2000 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;

import java.rmi.*;
import java.util.Vector;

/**
   Tuple is the general VisAD data class for vectors.
   Tuple objects are immutable.<P>
*/
public class Tuple extends DataImpl implements TupleIface {

  Data[] tupleComponents;

  /** construct a Tuple object with missing value */
  public Tuple(TupleType type) {
    super(type);
    if (type instanceof RealTupleType &&
        !(this instanceof RealTuple)) {
      throw new VisADError("must construct as RealTupleType");
    }
  }

  /** construct a Tuple object from a type and an array of Data objects */
  public Tuple(TupleType type, Data[] datums)
         throws VisADException, RemoteException {
    this(type, datums, true);
  }

  /** construct a Tuple object from a type and an array of Data objects */
  public Tuple(TupleType type, Data[] datums, boolean copy)
         throws VisADException, RemoteException {
    super(type);
    if (!checkTupleType(type, datums)) {
      throw new TypeException("Tuple: type does not match data");
    }
    if (type instanceof RealTupleType &&
        !(this instanceof RealTuple)) {
      throw new TypeException("must construct as RealTupleType");
    }
    int n = datums.length;
    tupleComponents = new Data[n];
    for (int i=0; i<n; i++) {
      if (copy) {
        tupleComponents[i] = (Data) datums[i].dataClone();
      }
      else {
        tupleComponents[i] = datums[i];
      }
      if (tupleComponents[i] instanceof DataImpl) {
        ((DataImpl) tupleComponents[i]).setParent(this);
      }
    }
  }

  /** construct a Tuple object from an array of Data objects;
      this constructs its MathType from the MathTypes of the
      data array; only copy data if copy == true */
  public Tuple(Data[] datums, boolean copy)
         throws VisADException, RemoteException {
    this(buildTupleType(datums), datums, copy);
  }

  /** construct a Tuple object from an array of Data objects;
      this constructs its MathType from the MathTypes of the
      data array; components are copies of data */
  public Tuple(Data[] datums)
         throws VisADException, RemoteException {
    this(buildTupleType(datums), datums, true);
  }

  public static Tuple makeTuple(Data[] datums)
         throws VisADException, RemoteException {
    return new Tuple(datums);
  }

  /** check a TupleType for an array of Data */
  static boolean checkTupleType(TupleType type, Data[] datums)
         throws VisADException, RemoteException {
    if (datums == null || type == null) return false;
    int n = datums.length;
    if (n != type.getDimension()) return false;
    for (int i=0; i<n; i++) {
      if (!type.getComponent(i).equals(datums[i].getType())) return false;
    }
    return true;
  }

  /** make a TupleType for an array of Data */
  public static TupleType buildTupleType(Data[] datums)
         throws VisADException, RemoteException {
    if (datums == null) {
      throw new TypeException("Tuple: # components must be > 0");
    }
    int n = datums.length;
    if (n < 1) {
      throw new TypeException("Tuple: # components must be > 0");
    }
    MathType[] types = new MathType[n];
    boolean allReal = true;
    for (int i=0; i<n; i++) {
      types[i] = datums[i].getType();
      if (!(types[i] instanceof RealType)) allReal = false;
    }
    if (allReal) {
      RealType[] real_types = new RealType[n];
      for (int i=0; i<n; i++) real_types[i] = (RealType) types[i];
      return new RealTupleType(real_types);
    }
    else {
      return new TupleType(types);
    }
  }

  public Real[] getRealComponents()
         throws VisADException, RemoteException {
    if (tupleComponents == null) return null;
    Vector reals = new Vector();
    for (int i=0; i<tupleComponents.length; i++) {
      if (tupleComponents[i] instanceof Real) {
        reals.addElement(tupleComponents[i]);
      }
      else if (tupleComponents[i] instanceof RealTuple) {
        RealTuple rt = (RealTuple) tupleComponents[i]; 
        for (int j=0; j<rt.getDimension(); j++) {
          reals.addElement(rt.getComponent(j));
        }
      }
    }
    if (reals.size() == 0) return null;
    Real[] realComponents = new Real[reals.size()];
    for (int i=0; i<reals.size(); i++) {
      realComponents[i] = (Real) reals.elementAt(i);
    }
    return realComponents;
  }

  /** return array of components */
  public Data[] getComponents() {
    return tupleComponents;
  }

  /** return number of components */
  public int getDimension() {
    if (tupleComponents != null) {
      return tupleComponents.length;
    }
    else {
      return ((TupleType) getType()).getDimension();
    }
  }

  /** return component for i between 0 and getDimension() - 1 */
  public Data getComponent(int i) throws VisADException, RemoteException {
    if (isMissing()) {
      return ((TupleType) Type).getComponent(i).missingData();
    }
    else if (0 <= i && i < tupleComponents.length) {
      return (Data) tupleComponents[i];
    }
    else {
      throw new TypeException("Tuple: component index out of range");
    }
  }

  public boolean isMissing() {
    return (tupleComponents == null);
  }

/*-  TDR May 1998
  public Data binary(Data data, int op, int sampling_mode, int error_mode)
              throws VisADException, RemoteException {
 */
  public Data binary(Data data, int op, MathType new_type,
                    int sampling_mode, int error_mode )
             throws VisADException, RemoteException {
    /* BINARY - TDR May 28, 1998 */
    if ( new_type == null ) {
      throw new TypeException("binary: new_type may not be null" );
    }
    MathType m_type;
    /* BINARY - end */
    if (data instanceof RealTuple) {
      throw new TypeException("Tuple.binary: types don't match");
    }
    else if (data instanceof Tuple) {
      if (!Type.equalsExceptName(data.getType())) {
        throw new TypeException("Tuple.binary: types don't match");
      }
      /* BINARY - TDR May 28, 1998 */
      if ( !Type.equalsExceptName(new_type) ) {
        throw new TypeException();
      }
      /* BINARY - end */
      if (isMissing() || data.isMissing()) {
        return new Tuple((TupleType) new_type);
      }
      Data[] datums = new Data[tupleComponents.length];
      for (int j=0; j<tupleComponents.length; j++) {
        /* BINARY - TDR June 2, 1998 */
        m_type = ((TupleType)new_type).getComponent(j);
        /* end  */
        datums[j] = tupleComponents[j].binary(((Tuple) data).getComponent(j), 
op,
                                              m_type, sampling_mode, 
error_mode);
      }
      return new Tuple(datums);
    }
    else if (data instanceof Real) {
      /* BINARY - TDR May 28, 1998 */
      if ( !Type.equalsExceptName(new_type) ) {
        throw new TypeException();
      }
      /* BINARY - end */
      if (isMissing() || data.isMissing()) {
        return new Tuple((TupleType) new_type);
      }
      Data[] datums = new Data[tupleComponents.length];
      for (int j=0; j<tupleComponents.length; j++) {
        /* BINARY - TDR June 2, 1998 */
        m_type = ((TupleType)new_type).getComponent(j);
        /* end  */
        datums[j] = tupleComponents[j].binary(data, op, m_type, sampling_mode, 
error_mode);
      }
      return new Tuple(datums);
    }
    else if (data instanceof Text) {
      throw new TypeException("Tuple.binary: types don't match");
    }
    else if (data instanceof Field) {
     /* BINARY - TDR May 28, 1998
      return data.binary(this, invertOp(op), sampling_mode, error_mode);
      */
      /* BINARY - TDR June 3, 1998 */
      if ( !(data.getType()).equalsExceptName(new_type) ) {
        throw new TypeException();
      }
      return data.binary(this, invertOp(op), new_type, sampling_mode, 
error_mode);
      /* BINARY - end  */
    }
    else {
      throw new TypeException("Tuple.binary");
    }
  }

  /*- TDR  July 1998
  public Data unary(int op, int sampling_mode, int error_mode)
         throws VisADException, RemoteException {
  */
  public Data unary(int op, MathType new_type,
                    int sampling_mode, int error_mode)
         throws VisADException, RemoteException {
    if ( new_type == null ) {
      throw new TypeException("unary: new_type may not be null");
    }

    if ( !Type.equalsExceptName( new_type )) {
       throw new TypeException("unary: new_type doesn't match return type");
    }
    TupleType T_type = (TupleType)new_type;

    if (isMissing()) return new Tuple((TupleType) new_type);

    Data[] datums = new Data[tupleComponents.length];
    for (int j=0; j<tupleComponents.length; j++) {
      datums[j] = tupleComponents[j].unary(op, T_type.getComponent(j),
                                           sampling_mode, error_mode);
    }
    return new Tuple(datums);
  }

  public DataShadow computeRanges(ShadowType type, DataShadow shadow)
         throws VisADException, RemoteException {
    if (isMissing()) return shadow;
    for (int i=0; i<tupleComponents.length; i++) {
      shadow =
        tupleComponents[i].computeRanges(((ShadowTupleType) 
type).getComponent(i),
                                         shadow);
    }
    return shadow;
  }

  /** return a Tuple that clones this, except its ErrorEstimate-s
      are adjusted for sampling errors in error */
  public Data adjustSamplingError(Data error, int error_mode)
         throws VisADException, RemoteException {
    if (isMissing() || error == null || error.isMissing()) return this;
    int n = tupleComponents.length;
    Data[] newComponents = new Data[n];
    for (int i=0; i<n; i++) {
      Data errorComponent = ((Tuple) error).getComponent(i);
      newComponents[i] =
        tupleComponents[i].adjustSamplingError(errorComponent, error_mode);
    }
    return new Tuple(newComponents);
  }

  /**
   * A wrapper around {@link #getComponent(int) getComponent} for JPython.
   *
   * @return The requested Data object.
   */
  public Data __getitem__(int index) throws VisADException, RemoteException {
    return getComponent(index);
  }

  /**
   * A wrapper around {@link #getDimension() getDimension} for JPython.
   *
   * @return Number of components.
   */
  public int getLength() {
    return getDimension();
  }

  public Object clone() {
    Tuple tuple;
    try {
      if (tupleComponents == null) {
        tuple = new Tuple((TupleType )getType());
      } else {
        int n = tupleComponents.length;
        Data[] datums = new Data[n];
        for (int i=0; i<n; i++) {
          datums[i] = (Data) tupleComponents[i].dataClone();
        }
        tuple = new Tuple(datums);
      }
    }
    catch (VisADException e) {
      throw new VisADError("Tuple.clone: VisADException occurred");
    }
    catch (RemoteException e) {
      throw new VisADError("Tuple.clone: RemoteException occurred");
    }
    return tuple;
  }

  public String longString(String pre)
         throws VisADException, RemoteException {
    String s = pre + "Tuple\n" + pre + "  Type: " + Type.toString() + "\n";
    if (isMissing()) return s + "  missing\n";
    for (int i=0; i<tupleComponents.length; i++) {
      s = s + pre + "  Tuple Component " + i + ":\n" +
              tupleComponents[i].longString(pre + "    ");
    }
    return s;
  }

  /**
   * Indicates if this Tuple is identical to another object.
   * @param obj         The other object.
   * @return            <code>true</code> if and only if the other object is
   *                    a Tuple and both Tuple-s have identical component
   *                    sequences.
   */
  public boolean equals(Object obj) {
    boolean     equals;
    if (!(obj instanceof Tuple)) {
      equals = false;
    }
    else {
      Tuple     that = (Tuple)obj;
      if (this == that) {
        equals = true;
      }
      else if (tupleComponents == null || that.tupleComponents == null) {
        equals = tupleComponents == that.tupleComponents;
      }
      else if (tupleComponents.length != that.tupleComponents.length) {
        equals = false;
      }
      else {
        equals = true;
        for (int i = 0; i < tupleComponents.length; ++i)
          if (!(tupleComponents[i].equals(that.tupleComponents[i]))) {
            equals = false;
            break;
          }
      }
    }
    return equals;
  }

  /**
   * Returns the hash code of this object.
   * @return            The hash code of this object.
   */
  public int hashCode() {
    int hashCode = 0;
    if (tupleComponents != null)
      for (int i = 0; i < tupleComponents.length; ++i)
        hashCode ^= tupleComponents[i].hashCode();
    return hashCode;
  }

}

  • 2001 messages navigation, sorted by:
    1. Thread
    2. Subject
    3. Author
    4. Date
    5. ↑ Table Of Contents
  • Search the visad archives: