/*- ******************************************************************************* * Copyright (c) 2011, 2014 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 * * Contributors: * Peter Chang - initial API and implementation and/or initial documentation *******************************************************************************/ package org.eclipse.dawnsci.analysis.dataset.impl.function; import java.util.ArrayList; import java.util.List; import org.eclipse.january.dataset.Dataset; import org.eclipse.january.dataset.DatasetFactory; import org.eclipse.january.dataset.DoubleDataset; import org.eclipse.january.dataset.IDataset; import org.eclipse.january.dataset.PositionIterator; /** * Find centroid of each dataset and return list of centroids along each dataset's axes * */ public class Centroid implements DatasetToNumberFunction { private Dataset[] bases = null; /** * * @param baseCoordinates is optional array of coordinate values to use as weights. * Defaults to midpoint values of indices */ public Centroid(Dataset... baseCoordinates) { bases = baseCoordinates; } private void checkCompatibility(IDataset d) { final int rank = d.getRank(); final int[] shape = d.getShape(); if (rank == bases.length) { int i = 0; for (; i < rank; i++) { if (shape[i] != bases[i].getSize()) { break; } } if (i == rank) return; } throw new IllegalArgumentException("Dataset shape does not match given or default coordinate base"); } /** * @param datasets input datasets * @return a list of 1D datasets which are centroids in every dimension */ @Override public List<Double> value(IDataset... datasets) { if (datasets.length == 0) return null; List<Double> result = new ArrayList<Double>(); for (IDataset ds : datasets) { final int rank = ds.getRank(); final int[] shape = ds.getShape(); if (bases == null || bases.length == 0) { bases = new Dataset[rank]; for (int i = 0; i < rank; i++) { final int len = shape[i]; final DoubleDataset axis = DatasetFactory.zeros(DoubleDataset.class, len); bases[i] = axis; for (int j = 0; j < len; j++) { axis.setAbs(j, j + 0.5); } } } else { checkCompatibility(ds); } final PositionIterator iter = new PositionIterator(ds.getShape()); final int[] pos = iter.getPos(); double tsum = 0.0; final double[] xsum = new double[rank]; while (iter.hasNext()) { double val = ds.getDouble(pos); tsum += val; for (int d = 0; d < rank; d++) { xsum[d] += bases[d].getElementDoubleAbs(pos[d])*val; } } for (int d = 0; d < rank; d++) { result.add(xsum[d] / tsum); } } return result; } }