This archive contains answers to questions sent to Unidata support through mid-2025. Note that the archive is no longer being updated. We provide the archive for reference; many of the answers presented here remain technically correct, even if somewhat outdated. For the most up-to-date information on the use of NSF Unidata software and data services, please consult the Software Documentation first.
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(); } }