/*- ******************************************************************************* * 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.roi; import org.eclipse.dawnsci.analysis.dataset.impl.function.LineSample; import org.eclipse.january.IMonitor; 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.ILazyDataset; import org.eclipse.january.dataset.Maths; import org.eclipse.january.dataset.Slice; /** * Class with utils methods for slicing 3D datasets with ROIs */ public class ROISliceUtils { /** * Method to find the index of matching the value closest to val in the dataset<br> * * @param dataset * @param val * @return position */ public static int findPositionOfClosestValueInAxis(IDataset dataset, Double val) { return Maths.abs(Maths.subtract(dataset, val)).argMin(); } /** * Method to get x,y slices from a rectangular roi<br> * * If length of roi is less than 1, slice of width 1 is returned<br> * * @param roi * @param step * @return slices */ public static Slice[] getSlicesFromRectangularROI(RectangularROI roi, int step) { Slice[] slices = new Slice[2]; int[] roiStart = roi.getIntPoint(); int[] roiLength = roi.getIntLengths(); if (roiLength[0] < 1) roiLength[0] = 1; if (roiLength[1] < 1) roiLength[1] = 1; slices[0] = new Slice(roiStart[0], roiStart[0] + roiLength[0], step); slices[1] = new Slice(roiStart[1], roiStart[1] + roiLength[1], step); return slices; } /** * Method to slice a dataset using an roi to define the sliced range <br> * Order must be at least 2 ints long and defines the x,y slice dimensions<br> * * @param lz * @param slices * @param order * @param step * @return slices * @throws Exception */ public static Dataset getDataset(ILazyDataset lz, RectangularROI roi, Slice[] slices, int[] order, int step, IMonitor monitor) throws Exception { Slice[] roiSlice = getSlicesFromRectangularROI(roi, step); if (monitor != null && monitor.isCancelled()) return null; Slice[] sl = checkSlices(lz.getRank(), slices); sl[order[0]] = roiSlice[0]; sl[order[1]] = roiSlice[1]; if (monitor != null && monitor.isCancelled()) return null; return DatasetUtils.convertToDataset(lz.getSlice(monitor, sl)); } /** * Method to return the slice corresponding to the area selected by an x-axis range roi<br> * * Only for ROIs on 1D plots. * * @param roi * @param axis * @param step * @return slice */ public static Slice getSliceFromRectangularXAxis1D(RectangularROI roi, IDataset axis, int step) { double[] roiStart = roi.getPoint(); double[] roiLength = roi.getLengths(); int start = findPositionOfClosestValueInAxis(axis, roiStart[0]); int end = findPositionOfClosestValueInAxis(axis, roiStart[0]+roiLength[0]); if (start > end) { int tmp = start; start = end; end = tmp; } Slice xSlice = new Slice(start, end+1, step); return xSlice; } /** * Method to get trapezium integration corresponding to the area selected by an x-axis range roi<br> * * Only for ROIs on 1D plots, along the dimension dim of the lazy dataset.<br> * * @param lz * @param axis * @param roi * @param slices * @param dim * @param step * * @return dataset * @throws Exception */ public static Dataset getAxisDatasetTrapzSum(ILazyDataset lz, IDataset axis, RectangularROI roi, Slice[] slices, int dim, int step, IMonitor monitor) throws Exception { Slice[] sl = checkSlices(lz.getRank(), slices); sl[dim] = getSliceFromRectangularXAxis1D(roi,axis, step); if (monitor != null && monitor.isCancelled()) return null; int start = sl[dim].getStart(); int end = sl[dim].getEnd(); Dataset dataBlock = DatasetUtils.convertToDataset(lz.getSlice(monitor, sl)); if (monitor != null && monitor.isCancelled()) return null; sl = new Slice[lz.getRank()]; sl[dim] = new Slice(0,1); Dataset datasetStart = DatasetUtils.cast(dataBlock.getSlice(monitor, sl),Dataset.FLOAT32); Dataset result = DatasetFactory.zeros(datasetStart, Dataset.FLOAT32); Dataset datasetEnd = DatasetFactory.zeros(datasetStart); for (int i = 1; i < (end-start+1); i++) { if (monitor != null && monitor.isCancelled()) return null; sl[dim].setStart(i); sl[dim].setStop(i+1); datasetEnd = DatasetUtils.cast(dataBlock.getSlice(monitor, sl),Dataset.FLOAT32); datasetStart.iadd(datasetEnd); datasetStart.idivide(2.0); double val = Math.abs(axis.getDouble(start+i)-axis.getDouble(start+i-1)); datasetStart.imultiply(val); result.iadd(datasetStart); datasetStart = datasetEnd; } return result.squeeze(); } /** * Method to get trapezium area corresponding to the region selected by an x-axis range roi (start-end)<br> * * Only for ROIs on 1D plots, along the dimension dim of the lazy dataset.<br> * * @param lz * @param axis * @param roi * @param slices * @param dim * @param step * @return dataset */ public static Dataset getTrapiziumArea(ILazyDataset lz, IDataset axis, RectangularROI roi, Slice[] slices, int dim, int step, IMonitor monitor) throws Exception { Slice[] sl = checkSlices(lz.getRank(), slices); if (monitor != null && monitor.isCancelled()) return null; sl[dim] = getSliceFromRectangularXAxis1D(roi,axis, step); int start = sl[dim].getStart(); int end = sl[dim].getEnd(); sl[dim].setStop(start+1); if (monitor != null && monitor.isCancelled()) return null; Dataset dataStart = DatasetUtils.cast(lz.getSlice(monitor, sl),Dataset.FLOAT32); sl[dim].setStart(end); sl[dim].setStop(end+1); if (monitor != null && monitor.isCancelled()) return null; dataStart.iadd(DatasetUtils.cast(lz.getSlice(monitor, sl),Dataset.FLOAT32)); dataStart.idivide(2.0); if (monitor != null && monitor.isCancelled()) return null; dataStart.imultiply(Maths.abs(axis.getDouble(end)-axis.getDouble(start))); return dataStart.squeeze(); } /** * Method to trapezium integration minus linear baseline corresponding to the region selected by an x-axis range roi<br> * * Only for ROIs on 1D plots, along the dimension dim of the lazy dataset.<br> * * @param lz * @param axis * @param roi * @param slices * @param dim * @param step * @return dataset * @throws Exception */ public static Dataset getAxisDatasetTrapzSumBaselined(ILazyDataset lz, IDataset axis, RectangularROI roi, Slice[] slices, int dim, int step,boolean baseline,IMonitor monitor) throws Exception { final Dataset output = getAxisDatasetTrapzSum( lz, axis, roi, slices, dim, step, monitor); if (baseline) { if (monitor != null && monitor.isCancelled()) return null; final Dataset datasetBasline = getTrapiziumArea( lz, axis, roi, slices, dim, step, monitor); output.isubtract(datasetBasline); } return output; } /** * Method to return the dataset corresponding to the area selected by an y-axis range roi<br> * * Only for ROIs on 1D plots. * * @param lz * @param roi * @param slices * @param dim * @return dataset * @throws Exception */ public static IDataset getYAxisDataset2D(ILazyDataset lz, RectangularROI roi, Slice[] slices, int dim, IMonitor monitor) throws Exception{ Slice[] sl = checkSlices(lz.getRank(), slices); int[] roiStart = roi.getIntPoint(); Slice xSlice = new Slice(roiStart[1], roiStart[1]+1, 1); sl[dim] = xSlice; if (monitor != null && monitor.isCancelled()) return null; IDataset out = lz.getSlice(monitor, sl); return out.squeeze(); } /** * Method to return the dataset corresponding to the area selected by an y-axis range roi<br> * * Only for ROIs on 1D plots. * * @param lz * @param roi * @param slices * @param dim * @return dataset * @throws Exception */ public static Dataset getYAxisDataset2DAverage(ILazyDataset lz, RectangularROI roi, Slice[] slices, int dim, IMonitor monitor) throws Exception{ Slice[] sl = checkSlices(lz.getRank(), slices); int[] roiStart = roi.getIntPoint(); int[] roiEnd = roi.getIntLengths(); Slice xSlice = new Slice(roiStart[1], roiStart[1]+roiEnd[1], 1); sl[dim] = xSlice; Dataset out = DatasetUtils.convertToDataset(lz.getSlice(monitor, sl)); if (monitor != null && monitor.isCancelled()) return null; out = out.mean(dim); return out.squeeze(); } /** * Method to slice a dataset using an roi to define the sliced range <br> * Order must be at least 2 ints long and defines the x,y slice dimensions<br> * * @param lz * @param slices * @param order * @param step * @return slices */ public static IDataset getDataset(ILazyDataset lz, LinearROI roi, Slice[] slices, int[] order, int step, IMonitor monitor) throws Exception { int[] start = roi.getIntPoint(); int[] end = roi.getIntEndPoint(); LineSample ls = new LineSample(start[1], start[0], end[1], end[0], 1); int len = (int)Math.floor(roi.getLength()) +1; IDataset[] ds = new IDataset[len]; Slice[] sl = checkSlices(lz.getRank(), slices); Slice xSlice = new Slice(); Slice ySlice = new Slice(); sl[order[1]] = xSlice; sl[order[0]] = ySlice; int[] points; int[] shape = new int[]{1,1}; for (int i = 0; i < len; i++) { if (monitor != null && monitor.isCancelled()) return null; points = ls.getPoint(i); sl[order[0]].setStart(points[0]); sl[order[0]].setStop(points[0]+1); sl[order[1]].setStart(points[1]); sl[order[1]].setStop(points[1]+1); //ds[i] = lz.getSlice(sl).squeeze().getSlice(); ds[i] = lz.getSlice(monitor, sl).squeeze(); shape = ds[i].getShape(); ds[i].setShape(new int[]{1,shape[0]}); } return DatasetUtils.concatenate(ds, 0); } private static Slice[] checkSlices(int rank, Slice[] slices) { Slice[] sl = new Slice[rank]; if (slices != null && rank == slices.length) { sl = slices.clone(); } else if ( slices != null && rank > slices.length){ sl = new Slice[rank]; for (int i = 0 ; i < slices.length ; i++) { sl[i] = slices[i]; } } else if ( slices != null && rank < slices.length){ sl = new Slice[rank]; for (int i = 0 ; i < rank ; i++) { sl[i] = slices[i]; } } return sl; } }