/*- * Copyright 2017 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: * Jacob Filik - initial API and implementation and/or initial documentation * Matthew Gerring - initial API and implementation and/or initial documentation */ package org.eclipse.dawnsci.analysis.dataset; import java.util.Spliterator; import java.util.Spliterators; import java.util.function.Consumer; import java.util.stream.Stream; import java.util.stream.StreamSupport; import org.eclipse.dawnsci.analysis.dataset.slicer.SliceViewIterator; import org.eclipse.january.DatasetException; import org.eclipse.january.dataset.IDataset; import org.eclipse.january.dataset.ILazyDataset; /** * This class provides slices as streams for Lazy Datasets for instance: * * <pre> * <code> final ILazyDataset lz = Random.lazyRand(64, 64, 100, 100); List<Number> maxes = SliceStreamSupport.sliceStream(lz, 2, 3).map(set->set.max()).collect(Collectors.toList()); </code> *</pre> * @see StreamSupport */ public class SliceStreamSupport { private static final int FLAGS = Spliterator.SIZED | Spliterator.DISTINCT | Spliterator.CONCURRENT | Spliterator.IMMUTABLE | Spliterator.NONNULL; /** * Create a dataset stream from a Lazy Dataset by specifying the axes that you * would like to size over. * * @param lazy * @param omit * @return a stream of lazy data */ public static Stream<ILazyDataset> stream(ILazyDataset lazy, int... omit) { return stream(lazy, false, omit); } /** * * @param lazy * @param omit * @param parallel * @return stream of lazy datasets */ public static Stream<ILazyDataset> stream(ILazyDataset lazy, boolean parallel, int... omit) { SliceViewIterator it = new SliceViewIterator(lazy, null, omit); return StreamSupport.stream(new LazyDatasetSpliterator(it), parallel); } /** * Create a dataset stream from a Lazy Dataset by specifying the axes that you * would like to size over. * * @param lazy * @param omit * @return a stream of lazy data */ public static Stream<IDataset> sliceStream(ILazyDataset lazy, int... omit) { return sliceStream(lazy, false, omit); } /** * * @param lazy * @param omit * @param parallel * @return stream of lazy datasets */ public static Stream<IDataset> sliceStream(ILazyDataset lazy, boolean parallel, int... omit) { SliceViewIterator it = new SliceViewIterator(lazy, null, omit); return StreamSupport.stream(new DatasetSpliterator(it), parallel); } private static class LazyDatasetSpliterator extends Spliterators.AbstractSpliterator<ILazyDataset> { private final SliceViewIterator it; public LazyDatasetSpliterator(SliceViewIterator it){ super(it.getTotal(),FLAGS); this.it = it; } @Override public boolean tryAdvance(Consumer<? super ILazyDataset> action) { if (action == null) { throw new NullPointerException(); } boolean hasNext = it.hasNext(); if (hasNext) { action.accept(it.next()); } return hasNext; } } private static class DatasetSpliterator extends Spliterators.AbstractSpliterator<IDataset> { private final SliceViewIterator it; public DatasetSpliterator(SliceViewIterator it){ super(it.getTotal(),FLAGS); this.it = it; } @Override public boolean tryAdvance(Consumer<? super IDataset> action) { if (action == null) { throw new NullPointerException(); } boolean hasNext = it.hasNext(); if (hasNext) { try { action.accept(it.next().getSlice()); } catch (DatasetException e) { throw new RuntimeException("Could not slice dataset",e); } } return hasNext; } } }