[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Trying to clip a multi-array



Hi Scottie,

> I found ConcreteIndexMap, which then lead to ClipMap. So based on what the
> ClipMap documentation said I thought that to get a clipping map that would
> go from array index 0 to 4 (5 elements total) I should use new
> ClipMap(0,1,5). The definitions of positions and dimensions are still
> getting me into trouble. The input variables were (position, low, extent)
> which according to the docs is supposed to be (dimension, min value, length).
> I took that to mean (which array index (0 based), initial position in array
> (1 based, due to note bellow), how many values to grab).

All the offsets in the IndexMaps are zero-based, so to clip out the 0
through 4 elements of a MultiArray dimension, you need to use
ClipMap(0, 0, 5).  The javadoc documentation could be clearer about
this, but the annotated example at 

  http://www.unidata.ucar.edu/packages/netcdf/java/examples/DemoMultiArrays.java

has several examples of using ClipMaps and composing them with other
IndexMaps.

> The constructor and class documentation for ClipMap do not explain the
> intentions very clearly. But, the real kicker is this:
> "low - the minimum value. 0 will map to this". What is "this" and how
> does it apply?

Yes, "this" is a loaded word to use in Java documentation, since it's
also a keyword referring to the current instance.  In this case,
"this" was referring to the value of the "low" parameter.

> The above efforts produced a java.lang.ArrayIndexOutOfBoundsException... I am
> including my modified version of the class and the run output bellow. Any
> suggestions on what I am doing that is wrong would be greatly appreciated.

I've appended a working example that does what you want to do.  I hope
this makes it clearer.  You want to apply the ClipMap to the input
MultiArrays xma and yma, but you want to apply the DecimateMap to the
output MultiArray pts.  Thus these IndexMaps should not be composed,
since they work on different objects.

The fact that this interlacing operation can be done with a Java
program containing no loops but only using MultiArray methods
demonstrates that the existing MultiArray methods are adequate for
this sort of manipulation.

--Russ

package ucar.demo;

import java.io.IOException;
import ucar.multiarray.*;

/**
 * Simple example program demonstrating clipping and interlacing two MultiArrays
 * into another MultiArray.
 *
 * @author Russ Rew
 * @version $Id: Interlace2.java,v 1.2 1998/05/20 16:18:31 russ Exp $ */
public class Interlace2 {

    public static void main (String[] args)
        throws java.io.IOException{ // no I/O here, so this won't really happen

        // Start with two 1-dimensional MultiArrays for x and y values
        double[] xx = new double[] {0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 
8.0, 9.0};
        double[] yy = new double[] {0.5, 1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 
8.5, 9.5};
        MultiArray xma = new ArrayMultiArray(xx);
        MultiArray yma = new ArrayMultiArray(yy);

        // Now limit the scope of the copy to a specific range
        ClipMap cim = new ClipMap(0,0,5); // the first five elements

        // Now get the clipped MultiArrays for the limited values of x, y 
MultiArrays
        MultiArray xma2 = new MultiArrayProxy(xma, cim);// {0.0, 1.0, ..., 4.0}
        MultiArray yma2 = new MultiArrayProxy(yma, cim);// {0.5, 1.5, ..., 4.5}

        // Create a new 2*nn element MultiArray for interlaced values.
        int nn = xma2.getLengths()[0];  // 5, the length of xma2 in its zeroth 
dim.
        MultiArray pts = new ArrayMultiArray(double.class, new int[] {2 * nn} );

        // first copyin the xma2 values in every other position
        boolean[] xPlaces = new boolean[] {true, false};
        IndexMap xMap = new DecimateMap(0, xPlaces);
        MultiArray xpts = new MultiArrayProxy(pts, xMap);
        // xpts is just a "view" of the {[0], [2], [4], [6], [8]} elements of 
pts
        xpts.copyin(new int[] {0}, xma2);
        System.out.println("pts = " + MultiArrayToString(pts));
        // pts is now {0.0, 0.0, 1.0, 0.0, 2.0, 0.0, 3.0, 0.0, 4.0, 0.0}

        // then copyin the yma2 values in remaining positions, similarly
        boolean[] yPlaces = new boolean[] {false, true};
        IndexMap yMap = new DecimateMap(0, yPlaces);
        MultiArray ypts = new MultiArrayProxy(pts, yMap );
        ypts.copyin(new int[] {0}, yma2);

        System.out.println("pts = " + MultiArrayToString(pts));
        // result is {0.0, 0.5, 1.0, 1.5, ..., 4.0, 4.5}
    }

    public static String
    MultiArrayToString(MultiArray ma) {
        StringBuffer buf = new StringBuffer(
            ((Object)ma).toString() + " (" + 
            ma.getComponentType() + ", " +
            "[" );
        int[] shape = ma.getLengths();
        int rank = ma.getRank();
        for(int i=0; i < rank - 1; i++) {
            buf.append(shape[i] + ", ");
        }
        if (rank > 0) {
            buf.append(shape[rank - 1]);
        }
        try {
            buf.append("])" +
                       MultiArrayToStringHelper(ma, new IndentLevel()));
        } catch (java.io.IOException e) {
            e.printStackTrace();
        }
        return buf.toString();
    }

    /**
     * Maintains indentation level for printing nested structures.
     */
    static class IndentLevel {
        private int level = 0;
        private int indentation;
        private StringBuffer indent;
        private StringBuffer blanks;

        public IndentLevel() {
            this(4);
        }
    
        public IndentLevel(int indentation) {
            if (indentation > 0)
                this.indentation = indentation;
            indent = new StringBuffer();
            blanks = new StringBuffer();
            for (int i=0; i < indentation; i++)
                blanks.append(" ");
        }

        public void incr() {
            level += indentation;
            indent.append(blanks);
        }

        public void decr() {
            level -= indentation;
            indent.setLength(level);
        }
    
        public String getIndent() {
            return indent.toString();
        }
    }

    private static String
    MultiArrayToStringHelper(MultiArray ma, IndentLevel ilev)
        throws java.io.IOException{ // no I/O here, so this won't really happen
        
        final int rank = ma.getRank();
        if (rank == 0) {
            try {
                return ma.get((int[])null).toString();
            } catch (IOException ee) {
            }
        }
        StringBuffer buf = new StringBuffer();
        buf.append("\n" + ilev.getIndent() + "{");
        ilev.incr();
        final int [] dims = ma.getLengths();
        final int last = dims[0];
        for(int ii = 0; ii < last; ii++)
        {
            final MultiArray inner =
                new MultiArrayProxy(ma, new SliceMap(0, ii));
            buf.append(MultiArrayToStringHelper(inner, ilev));
            if(ii != last - 1)
                buf.append(", ");
        }
        ilev.decr();
        if (rank > 1) {
            buf.append("\n" + ilev.getIndent());
        }
        buf.append("}");
        
        return buf.toString();
    }    
}