001/*- 002 ******************************************************************************* 003 * Copyright (c) 2011, 2016 Diamond Light Source Ltd. 004 * All rights reserved. This program and the accompanying materials 005 * are made available under the terms of the Eclipse Public License v1.0 006 * which accompanies this distribution, and is available at 007 * http://www.eclipse.org/legal/epl-v10.html 008 * 009 * Contributors: 010 * Peter Chang - initial API and implementation and/or initial documentation 011 *******************************************************************************/ 012 013package org.eclipse.january.dataset; 014 015import java.util.Arrays; 016import java.util.Collection; 017import java.util.Iterator; 018import java.util.List; 019 020/** 021 * Statistics of data set lists. Used for image processing. 022 */ 023public class CollectionStats { 024 025 private static interface StatFunction { 026 double evaluate(Dataset set); 027 } 028 029 /** 030 * Used to get a mean image from a set of images for instance. 031 * 032 * @param sets 033 * @return mean data set of the same shape as those passed in. 034 * @throws Exception 035 */ 036 public static Dataset mean(final List<IDataset> sets) throws Exception { 037 038 return process(sets, new StatFunction() { 039 @Override 040 public double evaluate(Dataset set) { 041 return (Double)set.mean(); 042 } 043 }); 044 } 045 046 /** 047 * Used to get a median image from a set of images for instance. 048 * 049 * @param sets 050 * @return median data set of the same shape as those passed in. 051 * @throws Exception 052 */ 053 public static Dataset median(final List<IDataset> sets) throws Exception { 054 055 return process(sets, new StatFunction() { 056 @Override 057 public double evaluate(Dataset set) { 058 return (Double)Stats.median(set); 059 } 060 }); 061 } 062 063 /** 064 * Used to get a median image from a set of images for instance. 065 * 066 * @param sets 067 * @return median data set of the same shape as those passed in. 068 * @throws Exception 069 */ 070 private static Dataset process(final List<IDataset> sets, 071 final StatFunction function) throws Exception { 072 073 int[] shape = assertShapes(sets); 074 final DoubleDataset result = DatasetFactory.zeros(DoubleDataset.class, shape); 075 final double[] rData = result.getData(); 076 final IndexIterator iter = new PositionIterator(shape); 077 final int[] pos = iter.getPos(); 078 079 final int len = sets.size(); 080 final DoubleDataset pixel = DatasetFactory.zeros(DoubleDataset.class, len); 081 final double[] pData = pixel.getData(); 082 for (int i = 0; iter.hasNext(); i++) { 083 for (int ipix = 0; ipix < len; ipix++) { 084 pData[ipix] = sets.get(ipix).getDouble(pos); 085 } 086 pixel.setDirty(); 087 rData[i] = function.evaluate(pixel); 088 } 089 090 return result; 091 } 092 093 private static int[] assertShapes(final Collection<IDataset> sets) throws Exception{ 094 095 if (sets.size()<2) throw new Exception("You must take the median of at least two sets!"); 096 097 final Iterator<IDataset> it = sets.iterator(); 098 final int[] shape = it.next().getShape(); 099 while (it.hasNext()) { 100 IDataset d = it.next(); 101 final int[] nextShape = d.getShape(); 102 if (!Arrays.equals(shape, nextShape)) throw new Exception("All data sets should be the same shape!"); 103 } 104 return shape; 105 } 106}