/*-
* Copyright (c) 2013 Diamond Light Source Ltd.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package uk.ac.diamond.scisoft.analysis.fitting.functions;
import java.util.Arrays;
import java.util.Iterator;
import org.eclipse.january.dataset.IDataset;
import org.eclipse.january.dataset.IndexIterator;
/**
* <p>Class to provide iteration through a set of coordinates
* <p>Instantiate an iterator and use it in a while loop:
* <pre>
* CoordinatesIterator iter = new HypergridIterator(values);
* double[] coords = iter.getCoordinates(); // this array's values change on each iteration
* while (iter.hasNext()) {
* value = someFunction(coords);
* ...
* }
* </pre>
*/
public abstract class CoordinatesIterator implements Iterator<double[]> {
protected IDataset[] values;
protected IndexIterator it;
protected int[] pos;
protected double[] coords;
protected int[] shape;
@Override
public double[] next() {
return coords;
}
/**
* @return coordinates
*/
public double[] getCoordinates() {
return coords;
}
/**
* @return shape of iterator (can be null, if not known or applicable)
*/
public int[] getShape() {
return shape;
}
@Override
public void remove() {
}
public IDataset[] getValues() {
return values;
}
public void reset() {
it.reset();
}
/**
* Create a coordinates iterator from <tt>m</tt> independent coordinate datasets and
* an optional output dataset shape of <tt>n</tt> dimensions.
* <p>
* The simplest mode (<tt>m</tt>=1) requires a single dataset which can be compound. The output
* shape matches the input shape.
* <p>
* The next mode requires <tt>m</tt> nD datasets possessing the same shape and where each dataset
* specifies one of <tt>m</tt> coordinates. The output shape matches the input shape. An exception
* is made for matching 1D shapes where a hypergrid is used if no output shape is specified.
* <p>
* Most general mode has <tt>n = m</tt> and the coordinates evaluated on an nD hypergrid of
* flattened input datasets. Its output shape is determined by sizes of the input datasets.
*
* @param outShape output dataset shape (can be null)
* @param coords
* @return a coordinates iterator
*/
static final public CoordinatesIterator createIterator(int[] outShape, IDataset... coords) {
if (coords == null || coords.length == 0) {
throw new IllegalArgumentException("No coordinates given to evaluate function");
}
CoordinatesIterator it;
int[] shape = coords[0].getShape();
if (coords.length == 1) {
it = coords[0].getElementsPerItem() == 1 ? new DatasetsIterator(coords) : new CoordinateDatasetIterator(coords[0]);
} else {
boolean same = true;
for (int i = 1; i < coords.length; i++) {
if (!Arrays.equals(shape, coords[i].getShape())) {
same = false;
break;
}
}
if (same && shape.length == 1) { // may override for 1D datasets
same = outShape == null ? false : Arrays.equals(outShape, shape);
}
it = same ? new DatasetsIterator(coords) : new HypergridIterator(coords);
}
if (outShape != null && !Arrays.equals(outShape, it.getShape())) {
throw new IllegalArgumentException("Iterator created does not match given output shape");
}
return it;
}
}