/*- * Copyright 2015 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 org.eclipse.dawnsci.analysis.dataset.slicer; import org.eclipse.january.DatasetException; import org.eclipse.january.dataset.Dataset; import org.eclipse.january.dataset.DatasetFactory; import org.eclipse.january.dataset.DatasetUtils; import org.eclipse.january.dataset.IDataset; import org.eclipse.january.dataset.IDynamicDataset; import org.eclipse.january.dataset.ILazyDataset; import org.eclipse.january.dataset.SliceND; import org.eclipse.january.metadata.AxesMetadata; import org.eclipse.january.metadata.DynamicMetadataUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class DynamicSliceViewIterator implements ISliceViewIterator { private static final Logger logger = LoggerFactory.getLogger(DynamicSliceViewIterator.class); private DynamicSliceNDIterator iterator = null; int count; private IDynamicDataset lazy; private IDynamicDataset[] keys; private IDynamicDataset finished; private int[] axes; private SourceInformation source; private boolean next = false; boolean last = false; private int maxTimeout = 60000; private int timeout = 1000; public DynamicSliceViewIterator(IDynamicDataset lazy, IDynamicDataset[] keys, IDynamicDataset finished, int dataSize) { try { iterator = new DynamicSliceNDIterator(lazy.getShape(), mergeKeys(keys), lazy.getRank()-dataSize); } catch (DatasetException e) { logger.error("Could not get data from lazy dataset", e); } this.lazy = lazy; this.keys = keys; this.finished = finished; int lr = lazy.getRank(); this.axes = new int[dataSize]; for (int i = 0; i < axes.length; i++) { axes[i] = lr - 1 -i; } updateShape(); next = iterator.hasNext(); Object ssm = lazy.getFirstMetadata(SliceFromSeriesMetadata.class); if (ssm != null && ssm instanceof SliceFromSeriesMetadata && ((SliceFromSeriesMetadata)ssm).getSourceInfo() != null) source = ((SliceFromSeriesMetadata)ssm).getSourceInfo(); else logger.warn("Lazy dataset contains no source information"); } public void setMaxTimeout(int maxTimeout) { this.maxTimeout = maxTimeout; timeout = maxTimeout/50; } public void updateShape() { try { lazy.refreshShape(); int[] current = lazy.getShape(); for (IDynamicDataset k : keys) k.refreshShape(); int[] s = DynamicMetadataUtils.refreshDynamicAxesMetadata(lazy.getMetadata(AxesMetadata.class), lazy.getShape()); for (int i = 0; i < axes.length;i++) { s[axes[i]] = current[axes[i]]; } lazy.resize(s); iterator.updateShape(lazy.getShape(), mergeKeys(keys)); } catch (Exception e) { logger.error("Error refreshing axes",e); } } @Override public boolean hasNext() { boolean hasNext = next; double time = 0; while (time < maxTimeout && !iterator.peekHasNext() && !last) { try { Thread.sleep(timeout); updateShape(); finished.refreshShape(); last = finished.getSlice().getInt(0) == 1; time += timeout; } catch (InterruptedException e) { break; } catch (DatasetException e) { logger.error("Could not get data from lazy dataset", e); } } if (time >= maxTimeout) { last = true; logger.error("Dynamic slice view iterator has timed-out"); } return hasNext; } /** * Resets the iterator */ @Override public void reset() { count = 0; iterator.reset(); last = false; updateShape(); next = iterator.hasNext(); } /** * Get the current view on the ILazyDataset * * @return lazyDataset */ @Override public ILazyDataset next() { count++; SliceND current = iterator.getCurrentSlice().clone(); ILazyDataset view; try { view = lazy.getSlice(current); } catch (DatasetException e) { logger.error("Could not get data from lazy dataset", e); return null; } view.clearMetadata(SliceFromSeriesMetadata.class); SliceInformation sl = new SliceInformation(current, current.clone(), new SliceND(lazy.getShape()), axes, last ? count : -1, count); SliceFromSeriesMetadata m = new SliceFromSeriesMetadata(source, sl); view.setMetadata(m); next = iterator.hasNext(); return view; } /** * Get the total number of views to be iterated over * * @return total; */ public int getTotal(){ return -1; } /** * Get the number of the current ILazyDataset * * @return current */ public int getCurrent(){ return count; } /** * Get the shape of the subsampled view * * @return shape */ @Override public int[] getShape(){ return lazy.getShape().clone(); } @Override public void remove() { //TODO throw something? } private IDataset mergeKeys(IDynamicDataset[] keys) throws DatasetException { if (keys.length == 1) return keys[0].getSlice(); Dataset[] dk = new Dataset[keys.length]; int[] maxShape = new int[keys[0].getRank()]; int minSize = Integer.MAX_VALUE; for (int i = 0; i < keys.length; i++) { dk[i] = DatasetUtils.convertToDataset(keys[i].getSlice()); int[] shape = dk[i].getShape(); for (int j = 0 ; j < shape.length; j++) if (maxShape[j] < shape[j]) maxShape[j] = shape[j]; if (dk[i].getSize() < minSize) minSize = dk[i].getSize(); } Dataset key = DatasetFactory.zeros(new int[]{minSize}, Dataset.INT64); for (int i = 0; i < minSize ; i++) { for (Dataset k : dk) { if (i > k.getSize()) return key; if (k.getElementLongAbs(i) == 0) return key; } key.set(i+1, i); } return key; } }