//
// MathType.java
//

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

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

/**
   MathType is the superclass for VisAD's hierarchy of mathematical types.
   It encompasses the mathematical concepts of scalars, tuples (i.e.,
   n-dimensional vectors), functions, and certain forms of sets.

VisAD Data objects are finite approximations to math objects. Every Data object possesses a MathType, which characterizes the mathematical object that the data approximate. This MathType is not synonymous with the class of the Data object, even though the class names for a Data object and its corresponding MathType object (Set and SetType, e.g.) may be similar.

MathType objects are immutable; one implication is that the setDefaultSet method (in RealTupleType) can be invoked only prior to using the related getDefaultSet method.

*/ public abstract class MathType extends Object implements java.io.Serializable { /** true if this MathType is defined by the system */ boolean SystemIntrinsic; /** this constructor assumes it is not creating an instrinsic MathType */ public MathType() { this(false); } /** * Create a MathType * * @param b true if this is an intrinsic MathType */ MathType(boolean b) { super(); SystemIntrinsic = b; } /** ScalarTypes are equal if they have the same name; TupleTypes are equal if their components are equal; FunctionTypes are equal if their domains and ranges are equal */ public abstract boolean equals(Object type); /** this is useful for determining compatibility of Data objects for binary mathematical operations; any RealTypes are equal; any TextTypes are equal; TupleTypes are equal if their components are equal; FunctionTypes are equal if their domains and ranges are equal */ public abstract boolean equalsExceptName(MathType type); /* TDR - May 1998. As above, except units must be convertible */ public abstract boolean equalsExceptNameButUnits( MathType type ) throws VisADException; /* TDR - June 1998 */ public abstract MathType cloneDerivative( RealType d_partial ) throws VisADException; /* TDR - July 1998 */ public abstract MathType binary( MathType type, int op, Vector names ) throws VisADException; /* TDR - July 1998 */ public abstract MathType unary( int op, Vector names ) throws VisADException; /** returns a missing Data object for any MathType */ public abstract Data missingData() throws VisADException, RemoteException; public abstract ShadowType buildShadowType(DataDisplayLink link, ShadowType parent) throws VisADException, RemoteException; /* WLH 5 Jan 2000 public abstract String toString(); */ public String toString() { return prettyString(0); } /** return a String that indents complex MathTypes for human readability */ public String prettyString() { return prettyString(0); } public abstract String prettyString(int indent); /** create a MathType from its string representation; essentially the inverse of the prettyString method */ public static MathType stringToType(String s) throws VisADException { int length = s.length(); String r = ""; for (int i=0; i")) { if (!(type0 instanceof RealType) && !(type0 instanceof RealTupleType)) { throw new TypeException("MathType.stringToType: badly formed string"); } String tr = t.substring(2); int[] lentr = {tr.length()}; MathType type1 = stringToType(tr, lentr); t = tr.substring(lentr[0]); if (!t.startsWith(")") || type1 == null) { throw new TypeException("MathType.stringToType: badly formed string"); } len[0] = 1 + lensr[0] + 2 + lentr[0] + 1; ret_type = new FunctionType(type0, type1); return ret_type; } else { Vector v = new Vector(); v.addElement(type0); int lentup = 1 + lensr[0]; while (t.startsWith(",")) { String tr = t.substring(1); int[] lentr = {tr.length()}; MathType type1 = stringToType(tr, lentr); if (type1 == null) { throw new TypeException("MathType.stringToType: badly formed string"); } v.addElement(type1); lentup = lentup + 1 + lentr[0]; t = tr.substring(lentr[0]); } if (!t.startsWith(")")) { throw new TypeException("MathType.stringToType: badly formed string"); } len[0] = lentup + 1; MathType[] types = new MathType[v.size()]; boolean all_real = true; for (int i=0; i") || // also eliminate regex chars s0.equals(".") || s0.equals("*") || s0.equals("?") || s0.equals("|")) { len[0] = i; break; } } String rs = s.substring(0, len[0]); String t = s.substring(len[0]); if (t.startsWith("(Text)")) { ret_type = TextType.getTextType(rs); len[0] += 6; } else { ret_type = RealType.getRealType(rs); } return ret_type; } else { throw new TypeException("MathType.stringToType: badly formed string"); } } private static Vector timeAliases = makeTimeAliasVector(); private static Vector makeTimeAliasVector() { Vector v = new Vector(); v.add("time"); v.add("Time"); v.add("TIME"); return v; } /** Adds a ScalarType name that guessMaps should map to Animation. */ public static void addTimeAlias(String name) { synchronized (timeAliases) { timeAliases.add(name); } } /** Guesses at a set of "default" mappings for this MathType. Intuitively, first we look for a FunctionType with domain dimension 3, then a nested group of FunctionTypes with 'cumulative' domain dimension 3. Next we look for a FunctionType or nested group of FunctionTypes with domain dimension 2. Then, we look for a FunctionType with domain dimension 1. Nested groups of FunctionTypes may be nested with TupleTypes, which is indicated by some of the MathType templates. Lastly, if no matching FunctionTypes are found, then we look for 3-D, 2-D, or 1-D SetTypes. */ public ScalarMap[] guessMaps(boolean threeD) { MathType m = this; // set up aliases for "time" RealType to be mapped to Animation DataStruct[][] ds; synchronized (timeAliases) { int len = timeAliases.size(); ds = new DataStruct[1][len]; for (int i=0; i 0) { timeFunc = i; break; } } // compile a FunctionType and SetType list to search for template matches Vector flist = new Vector(); // functions Vector slist = new Vector(); // sets Vector tlist = new Vector(); // tuples of reals if (timeFunc < 0) buildTypeList(m, flist, slist, tlist); else { // found a "time" RealType; only search ranges of "time" FunctionTypes for (int i=0; i (..., a, ...)) // ((x, y, z) -> a) // x -> X, y -> Y, z -> Z, a -> IsoContour if (!ft.getFlat()) break; RealTupleType domain = ft.getDomain(); if (domain.getDimension() != 3) break; MathType range = ft.getRange(); RealType x, y, z; CoordinateSystem cs = domain.getCoordinateSystem(); if (cs != null) { RealTupleType ref = cs.getReference(); try { x = (RealType) ref.getComponent(0); y = (RealType) ref.getComponent(1); z = (RealType) ref.getComponent(2); } catch (VisADException exc) { break; } } else { try { x = (RealType) domain.getComponent(0); y = (RealType) domain.getComponent(1); z = (RealType) domain.getComponent(2); } catch (VisADException exc) { break; } } RealType a; if (range instanceof RealType) { a = (RealType) range; try { ScalarMap[] smaps = new ScalarMap[timeFunc < 0 ? 4 : 5]; if (RealType.Latitude.equals(x)) { smaps[0] = new ScalarMap(x, Display.YAxis); smaps[1] = new ScalarMap(y, Display.XAxis); } else { smaps[0] = new ScalarMap(x, Display.XAxis); smaps[1] = new ScalarMap(y, Display.YAxis); } smaps[2] = new ScalarMap(z, Display.ZAxis); smaps[3] = new ScalarMap(a, Display.IsoContour); if (timeFunc >= 0) { Object o = ds[0][timeFunc].funcs.elementAt(0); RealTupleType rtt = ((FunctionType) o).getDomain(); RealType time = (RealType) rtt.getComponent(0); smaps[4] = new ScalarMap(time, Display.Animation); } return smaps; } catch (VisADException exc) { } } else if (range instanceof TupleType) { TupleType tt = (TupleType) range; for (int i=0; i= 0) { Object o = ds[0][timeFunc].funcs.elementAt(0); RealTupleType rtt = ((FunctionType) o).getDomain(); RealType time = (RealType) rtt.getComponent(0); smaps[4] = new ScalarMap(time, Display.Animation); } return smaps; } catch (VisADException exc) { break; } } } } break; case 1: // 3-D ONLY // (z -> ((x, y) -> (..., a, ...))) // (z -> (..., ((x, y) -> (..., a, ...)), ...)) // (z -> ((x, y) -> a)) // (z -> (..., ((x, y) -> a), ...)) // x -> X, y -> Y, z -> Z, a -> IsoContour domain = ft.getDomain(); if (domain.getDimension() != 1) break; cs = domain.getCoordinateSystem(); if (cs != null) { RealTupleType ref = cs.getReference(); try { z = (RealType) ref.getComponent(0); } catch (VisADException exc) { break; } } else { try { z = (RealType) domain.getComponent(0); } catch (VisADException exc) { break; } } range = ft.getRange(); FunctionType rf = null; if (range instanceof FunctionType) { rf = (FunctionType) range; if (!rf.getFlat() || rf.getDomain().getDimension() != 2) break; } else if (range instanceof TupleType) { TupleType tt = (TupleType) range; for (int i=0; i= 0) { Object o = ds[0][timeFunc].funcs.elementAt(0); RealTupleType rtt = ((FunctionType) o).getDomain(); RealType time = (RealType) rtt.getComponent(0); smaps[4] = new ScalarMap(time, Display.Animation); } return smaps; } catch (VisADException exc) { } case 2: // 3-D ONLY // ((x, y) -> (z -> (..., a, ...))) // ((x, y) -> (..., (z -> (..., a, ...)), ...)) // ((x, y) -> (z -> a)) // ((x, y) -> (..., (z -> a), ...)) // x -> X, y -> Y, z -> Z, a -> RGB // domain = ft.getDomain(); if (domain.getDimension() != 2) break; cs = domain.getCoordinateSystem(); if (cs != null) { RealTupleType ref = cs.getReference(); try { x = (RealType) ref.getComponent(0); y = (RealType) ref.getComponent(1); } catch (VisADException exc) { break; } } else { try { x = (RealType) domain.getComponent(0); y = (RealType) domain.getComponent(1); } catch (VisADException exc) { break; } } range = ft.getRange(); rf = null; if (range instanceof FunctionType) { rf = (FunctionType) range; if (!rf.getFlat() || rf.getDomain().getDimension() != 1) break; } else if (range instanceof TupleType) { TupleType tt = (TupleType) range; for (int i=0; i= 0) { Object o = ds[0][timeFunc].funcs.elementAt(0); RealTupleType rtt = ((FunctionType) o).getDomain(); RealType time = (RealType) rtt.getComponent(0); smaps[4] = new ScalarMap(time, Display.Animation); } return smaps; } catch (VisADException exc) { } case 3: // 3-D ONLY // (x -> (y -> (z -> (..., a, ...)))) // (x -> (..., (y -> (z -> (..., a, ...))), ...)) // (x -> (y -> (..., z -> (..., a, ...)), ...)) // (x -> (..., (y -> (..., (z -> (..., a, ...)), ...)), ...)) // (x -> (y -> (z -> a))) // (x -> (..., (y -> (z -> a)), ...)) // (x -> (y -> (..., (z -> a), ...))) // (x -> (..., (y -> (..., (z -> a), ...)), ...)) // x -> X, y -> Y, z -> Z, a -> RGB domain = ft.getDomain(); if (domain.getDimension() != 1) break; cs = domain.getCoordinateSystem(); if (cs != null) { RealTupleType ref = cs.getReference(); try { x = (RealType) ref.getComponent(0); } catch (VisADException exc) { break; } } else { try { x = (RealType) domain.getComponent(0); } catch (VisADException exc) { break; } } // find nested "y" range = ft.getRange(); rf = null; if (range instanceof FunctionType) { rf = (FunctionType) range; if (rf.getDomain().getDimension() != 1) break; } else if (range instanceof TupleType) { TupleType tt = (TupleType) range; for (int i=0; i= 0) { Object o = ds[0][timeFunc].funcs.elementAt(0); RealTupleType rtt = ((FunctionType) o).getDomain(); RealType time = (RealType) rtt.getComponent(0); smaps[4] = new ScalarMap(time, Display.Animation); } return smaps; } catch (VisADException exc) { } case 4: // 2-D or 3-D // ((x, y) -> (..., r, ..., g, ..., b, ...)) // x -> X, y -> Y, r -> Red, g -> Green, b -> Blue // ((x, y) -> (..., a, ...)) // ((x, y) -> a) // x -> X, y -> Y, a -> RGB if (!ft.getFlat()) break; domain = ft.getDomain(); if (domain.getDimension() != 2) break; cs = domain.getCoordinateSystem(); if (cs != null) { RealTupleType ref = cs.getReference(); try { x = (RealType) ref.getComponent(0); y = (RealType) ref.getComponent(1); } catch (VisADException exc) { break; } } else { try { x = (RealType) domain.getComponent(0); y = (RealType) domain.getComponent(1); } catch (VisADException exc) { break; } } range = ft.getRange(); RealType[] rgb = new RealType[3]; int rgbc = 0; if (range instanceof TupleType) { TupleType tt = (TupleType) range; for (int i=0; i= 0) { Object o = ds[0][timeFunc].funcs.elementAt(0); RealTupleType rtt = ((FunctionType) o).getDomain(); RealType time = (RealType) rtt.getComponent(0); smaps[3] = new ScalarMap(time, Display.Animation); } return smaps; } catch (VisADException exc) { } } else { try { ScalarMap[] smaps = new ScalarMap[timeFunc < 0 ? 5 : 6]; if (RealType.Latitude.equals(x)) { smaps[0] = new ScalarMap(x, Display.YAxis); smaps[1] = new ScalarMap(y, Display.XAxis); } else { smaps[0] = new ScalarMap(x, Display.XAxis); smaps[1] = new ScalarMap(y, Display.YAxis); } smaps[2] = new ScalarMap(rgb[0], Display.Red); smaps[3] = new ScalarMap(rgb[1], Display.Green); smaps[4] = new ScalarMap(rgb[2], Display.Blue); if (timeFunc >= 0) { Object o = ds[0][timeFunc].funcs.elementAt(0); RealTupleType rtt = ((FunctionType) o).getDomain(); RealType time = (RealType) rtt.getComponent(0); smaps[5] = new ScalarMap(time, Display.Animation); } return smaps; } catch (VisADException exc) { } } break; case 5: // 2-D or 3-D // (x -> (y -> (..., a, ...))) // (x -> (y -> a)) // 3-D: x -> X, y -> Y, a -> Z // 2-D: x -> X, y -> Y, a -> RGB domain = ft.getDomain(); if (domain.getDimension() != 1) break; cs = domain.getCoordinateSystem(); if (cs != null) { RealTupleType ref = cs.getReference(); try { x = (RealType) ref.getComponent(0); } catch (VisADException exc) { break; } } else { try { x = (RealType) domain.getComponent(0); } catch (VisADException exc) { break; } } range = ft.getRange(); if (!(range instanceof FunctionType)) break; ft = (FunctionType) range; if (!ft.getFlat()) break; domain = ft.getDomain(); if (domain.getDimension() != 1) break; cs = domain.getCoordinateSystem(); if (cs != null) { RealTupleType ref = cs.getReference(); try { y = (RealType) ref.getComponent(0); } catch (VisADException exc) { break; } } else { try { y = (RealType) domain.getComponent(0); } catch (VisADException exc) { break; } } range = ft.getRange(); a = null; if (range instanceof RealType) { a = (RealType) range; } else if (range instanceof TupleType) { TupleType tt = (TupleType) range; for (int i=0; i= 0) { Object o = ds[0][timeFunc].funcs.elementAt(0); RealTupleType rtt = ((FunctionType) o).getDomain(); RealType time = (RealType) rtt.getComponent(0); smaps[3] = new ScalarMap(time, Display.Animation); } return smaps; } catch (VisADException exc) { } case 6: // 2-D or 3-D // (x -> (..., a, ...)) // (x -> a) // x -> X, a -> Y if (!ft.getFlat()) break; domain = ft.getDomain(); if (domain.getDimension() != 1) break; cs = domain.getCoordinateSystem(); if (cs != null) { RealTupleType ref = cs.getReference(); try { x = (RealType) ref.getComponent(0); } catch (VisADException exc) { break; } } else { try { x = (RealType) domain.getComponent(0); } catch (VisADException exc) { break; } } range = ft.getRange(); a = null; if (range instanceof RealType) { a = (RealType) range; } else if (range instanceof TupleType) { TupleType tt = (TupleType) range; for (int i=0; i= 0) { Object o = ds[0][timeFunc].funcs.elementAt(0); RealTupleType rtt = ((FunctionType) o).getDomain(); RealType time = (RealType) rtt.getComponent(0); smaps[2] = new ScalarMap(time, Display.Animation); } return smaps; } catch (VisADException exc) { } break; } } } // look for matches between Set templates and SetTypes list final DisplayRealType[] spatial = {Display.XAxis, Display.YAxis, Display.ZAxis}; final boolean[] mark = {false, false, false}; int maxdim = threeD ? 3 : 2; int numsets = slist.size(); for (int dim=maxdim; dim>=1; --dim) { for (int si=0; si X, y -> Y, z -> Z // Set(x, y) // x -> X, y -> Y // Set(x) // x -> X SetType st = (SetType) slist.elementAt(si); RealTupleType domain = st.getDomain(); CoordinateSystem cs = domain.getCoordinateSystem(); if (cs != null) { // use CoordinateSystem reference instead of original RealTupleType domain = cs.getReference(); } if (domain.getDimension() != dim) continue; try { ScalarMap[] smaps = new ScalarMap[timeFunc < 0 ? dim : dim + 1]; for (int i=0; i= 0) { Object o = ds[0][timeFunc].funcs.elementAt(0); RealTupleType rtt = ((FunctionType) o).getDomain(); RealType time = (RealType) rtt.getComponent(0); smaps[dim] = new ScalarMap(time, Display.Animation); } return smaps; } catch (VisADException exc) { } } } // if the only match is a RealTupleType, map to first few tuple elements int numtuples = tlist.size(); if (numtuples >= 1) { // use first RealTupleType - (x, y, z, ...) // x -> X, y -> Y, z -> Z RealTupleType domain = (RealTupleType) tlist.elementAt(0); CoordinateSystem cs = domain.getCoordinateSystem(); if (cs != null) { // use CoordinateSystem reference instead of original RealTupleType domain = cs.getReference(); } int dim = domain.getDimension(); if (dim > maxdim) dim = maxdim; try { ScalarMap[] smaps = new ScalarMap[timeFunc < 0 ? dim : dim + 1]; for (int i=0; i= 0) { Object o = ds[0][timeFunc].funcs.elementAt(0); RealTupleType rtt = ((FunctionType) o).getDomain(); RealType time = (RealType) rtt.getComponent(0); smaps[dim] = new ScalarMap(time, Display.Animation); } return smaps; } catch (VisADException exc) { } } return null; } /** used by guessMaps to recursively build a list of FunctionTypes to attempt template matching with */ private void buildTypeList(MathType mt, Vector flist, Vector slist, Vector tlist) { if (mt instanceof TupleType) { TupleType tt = (TupleType) mt; if (tt instanceof RealTupleType) { // found a tuple of reals; add it to RealTuple list tlist.addElement(mt); } else { // search each tuple component for (int i=0; i " + ds.getName()); } } String s3 = "((Row, Col, Lev) -> Radiance)"; String s3s = stringToType(s3).prettyString(); System.out.println("s3 = \n" + s3 + "\ns3s = \n" + s3s); } /** used by guessMaps to store miscellaneous information throughout findTimeFunction's recursive calls */ private class DataStruct { /** whether this DataStruct's funcs are valid */ boolean fvalid = true; /** The name of the RealType in the domain of the FunctionTypes in funcs */ String name; /** FunctionType objects with 1-D domains which match name */ Vector funcs = new Vector(); /** constructor */ DataStruct(String s) { name = s; } } }

Ads help maintain this website.