/*- * Copyright 2016 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 uk.ac.diamond.scisoft.analysis.processing.operations.twod; import java.util.Arrays; import org.eclipse.dawnsci.analysis.api.processing.OperationData; import org.eclipse.dawnsci.analysis.api.processing.OperationException; import org.eclipse.dawnsci.analysis.api.processing.OperationRank; import org.eclipse.dawnsci.analysis.dataset.operations.AbstractOperation; import org.eclipse.january.IMonitor; import org.eclipse.january.dataset.BooleanDataset; import org.eclipse.january.dataset.Comparisons; import org.eclipse.january.dataset.Dataset; import org.eclipse.january.dataset.DatasetFactory; import org.eclipse.january.dataset.DatasetUtils; import org.eclipse.january.dataset.DoubleDataset; import org.eclipse.january.dataset.IDataset; import org.eclipse.january.dataset.ILazyDataset; import org.eclipse.january.dataset.Maths; import org.eclipse.january.dataset.Stats; import org.eclipse.january.metadata.AxesMetadata; import org.eclipse.january.metadata.MetadataFactory; import uk.ac.diamond.scisoft.analysis.processing.operations.twod.FilterDataModel.FilterDataAxis; public class FilterDataOperation extends AbstractOperation<FilterDataModel, OperationData> { @Override public String getId() { return "uk.ac.diamond.scisoft.analysis.processing.operations.twod.FilterDataOperation"; } @Override public OperationRank getInputRank() { return OperationRank.TWO; } @Override public OperationRank getOutputRank() { return OperationRank.TWO; } @Override protected OperationData process(IDataset input, IMonitor monitor) throws OperationException { IDataset rv = null; try { if (model.getAxis() == FilterDataAxis.X_THEN_Y ) { IDataset temp = processOneDirection(input, FilterDataAxis.X); rv = processOneDirection(temp, FilterDataAxis.Y); } else if (model.getAxis() == FilterDataAxis.Y_THEN_X) { IDataset temp = processOneDirection(input, FilterDataAxis.Y); rv = processOneDirection(temp, FilterDataAxis.X); } else { rv = processOneDirection(input, model.getAxis()); } } catch (Exception e) { throw new OperationException(this, e); } return new OperationData(rv); } private IDataset processOneDirection(IDataset input, FilterDataAxis axis /* must be X or Y */) throws Exception { Dataset inputD = DatasetUtils.convertToDataset(input); Dataset reduced = null; switch (model.getSource()) { case AVERAGE: reduced = inputD.mean(axis.getAxis()); break; case SUM: reduced = inputD.sum(axis.getAxis()); break; case MEDIAN: reduced = Stats.median(inputD, axis.getAxis()); break; case MINIMUM: reduced = inputD.min(axis.getAxis()); break; case MAXIMUM: reduced = inputD.max(axis.getAxis()); break; } BooleanDataset goodPositions = null; Dataset thresholdOnes = DatasetFactory.ones(reduced).imultiply(model.getThreshold()); switch (model.getOperator()) { case EQUAL: goodPositions = Comparisons.equalTo(reduced, thresholdOnes); break; case GREATERTHAN: goodPositions = Comparisons.greaterThan(reduced, thresholdOnes); break; case GREATERTHANOREQUAL: goodPositions = Comparisons.greaterThanOrEqualTo(reduced, thresholdOnes); break; case LESSTHAN: goodPositions = Comparisons.lessThan(reduced, thresholdOnes); break; case LESSTHANOREQUAL: goodPositions = Comparisons.lessThanOrEqualTo(reduced, thresholdOnes); break; case NOTEQUAL: goodPositions = Comparisons.equalTo(reduced, thresholdOnes); // invert Comparisons.logicalNot(goodPositions); break; } if (goodPositions.all()) return input; // let the processing begin... int count = (int) Math.floor((double) goodPositions.sum()); if (count == 0) { throw new Exception("No data was found that satisfies the matches the provided data filter parameters"); } Dataset extracted = null; Dataset mask = null; if (axis == FilterDataAxis.X) { mask = Maths.multiply(DatasetFactory.ones(inputD), goodPositions); mask = DatasetUtils.cast(BooleanDataset.class, mask); extracted = DatasetUtils.extract(inputD, mask); extracted.setShape(inputD.getShape()[0], count); } else if (axis == FilterDataAxis.Y) { mask = Maths.multiply(DatasetFactory.ones(inputD).getTransposedView().getSlice(), goodPositions).getTransposedView().getSlice(); mask = DatasetUtils.cast(BooleanDataset.class, mask); extracted = DatasetUtils.extract(inputD, mask); extracted.setShape(count, inputD.getShape()[1]); } /* The data has been processed, now the axes need updating too if necessary * Start by copying the non-AxesMetadata */ copyMetadata(input, extracted, false); ILazyDataset[] axes = getFirstAxes(input); if (axes != null && axes.length == 2) { AxesMetadata axma = MetadataFactory.createMetadata(AxesMetadata.class, 2); ILazyDataset axisX = null, axisY = null; if (axis == FilterDataAxis.X) { if (axes[0] != null) { // update the X-axis if (axes[0].getShape()[1] == 1) { // copy the original X axis if it is 1D (after a hypothetical squeeze) axisX = axes[0]; } else { // otherwise, extract new axis with mask axisX = DatasetUtils.extract(DatasetUtils.sliceAndConvertLazyDataset(axes[0]), mask); axisX.setShape(extracted.getShape()); } axisX.setName(axes[0].getName()); } if (axes[1] != null) { // update Y-axis if (axes[1].getShape()[0] == 1) { // 1D axis axisY = DatasetUtils.extract( DatasetUtils.copy( DoubleDataset.class, DatasetUtils.sliceAndConvertLazyDataset( axes[1]) ) .squeeze(), goodPositions); axisY.setShape(1, axisY.getSize()); } else { // 2D axis axisY = DatasetUtils.extract(DatasetUtils.sliceAndConvertLazyDataset(axes[1]), mask); axisY.setShape(extracted.getShape()); } axisY.setName(axes[1].getName()); } } else if (axis == FilterDataAxis.Y) { if (axes[1] != null) { if (axes[1].getShape()[0] == 1) { axisY = axes[1]; } else { axisY = DatasetUtils.extract(DatasetUtils.sliceAndConvertLazyDataset(axes[1]), mask); axisY.setShape(extracted.getShape()); } axisY.setName(axes[1].getName()); } if (axes[0] != null) { if (axes[0].getShape()[1] == 1) { axisX = DatasetUtils.extract( DatasetUtils.copy( DoubleDataset.class, DatasetUtils.sliceAndConvertLazyDataset( axes[0]) ) .squeeze(), goodPositions); axisX.setShape(axisX.getSize(), 1); } else { axisX = DatasetUtils.extract(DatasetUtils.sliceAndConvertLazyDataset(axes[0]), mask); axisX.setShape(extracted.getShape()); } axisX.setName(axes[0].getName()); } } axma.setAxis(0, axisX); axma.setAxis(1, axisY); extracted.addMetadata(axma); } return extracted; } }