/*-
* Copyright (c) 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.backgroundsubtraction;
//import org.apache.commons.lang.ArrayUtils;
// Imports from org.eclipse
import org.eclipse.january.IMonitor;
import org.eclipse.january.dataset.Dataset;
import org.eclipse.january.dataset.IDataset;
import org.eclipse.january.dataset.DatasetUtils;
import org.eclipse.january.dataset.DatasetFactory;
import org.eclipse.dawnsci.analysis.api.processing.OperationData;
import org.eclipse.dawnsci.analysis.api.processing.OperationRank;
import org.eclipse.dawnsci.analysis.api.processing.OperationException;
import org.eclipse.dawnsci.analysis.dataset.operations.AbstractOperation;
import org.eclipse.dawnsci.analysis.dataset.slicer.SliceFromSeriesMetadata;
// Imports from uk.ac.diamond
import uk.ac.diamond.scisoft.analysis.processing.operations.ErrorPropagationUtils;
import uk.ac.diamond.scisoft.analysis.processing.operations.utils.ProcessingUtils;
import uk.ac.diamond.scisoft.analysis.processing.operations.backgroundsubtraction.Pauw1DBackgroundSubtractionModel;
//More information and the equation for this background subtraction routine can be found in:
//Everything SAXS: small-angle scattering pattern collection and correction
//B. R. Pauw, Journal of Physics: Condensed Matter, 2013, 25, 383201.
//DOI: 10.1088/0953-8984/25/38/383201
//@author Tim Snow
//The model for a DAWN processing plugin to perform background subtraction on a scattered diffraction pattern
public class Pauw1DBackgroundSubtractionOperation extends AbstractOperation<Pauw1DBackgroundSubtractionModel, OperationData> {
// Let's give this process an ID tag
@Override
public String getId() {
return "uk.ac.diamond.scisoft.analysis.processing.operations.backgroundsubtraction.Pauw1DBackgroundSubtractionOperation";
}
// Before we start, let's make sure we know how many dimensions of data are going in...
@Override
public OperationRank getInputRank() {
return OperationRank.ONE;
}
// ...and out
@Override
public OperationRank getOutputRank() {
return OperationRank.ONE;
}
// Now let's define the main calculation process
@Override
public OperationData process(IDataset sampleDataset, IMonitor monitor) throws OperationException {
// Get metadata about the file/frame passed to this process
SliceFromSeriesMetadata sliceSeriesMetadata = getSliceSeriesMetadata(sampleDataset);
// Get the file/frame path and then from there extract out the thickness, I_0 and I_t values as floats.
String sampleFilePath = sliceSeriesMetadata.getFilePath();
double sampleThickness = (ProcessingUtils.getDataset(this, sampleFilePath, model.getThicknessPath())).getDouble(0);
double sampleIZero = (ProcessingUtils.getDataset(this, sampleFilePath, model.getIZeroPath())).getDouble(0);
double sampleITransmission = (ProcessingUtils.getDataset(this, sampleFilePath, model.getITransmissionPath())).getDouble(0);
// Get the background file name and then from there extract out the thickness, I_0 and I_t values as floats.
String backgroundFilePath = model.getBackgroundFilePath();
double backgroundThickness = (ProcessingUtils.getDataset(this, backgroundFilePath, model.getThicknessPath())).getDouble(0);
double backgroundIZero = (ProcessingUtils.getDataset(this, backgroundFilePath, model.getIZeroPath())).getDouble(0);
double backgroundITransmission = (ProcessingUtils.getDataset(this, backgroundFilePath, model.getITransmissionPath())).getDouble(0);
// Get the absolute scan file name and then from there extract out the reduced data
IDataset reducedAbsoluteScanDataset = ProcessingUtils.getDataset(this, model.getAbsoluteScanFilepath(), model.getReducedBackgroundData());
// Get the reduced background file name and then from there extract out the reduced data
IDataset reducedBackgroundDataset = ProcessingUtils.getDataset(this, model.getReducedBackgroundFilePath(), model.getReducedBackgroundData());
// Take the IDatasets we've been given and make them a bit more workable
Dataset absoluteScanData = DatasetUtils.convertToDataset(reducedAbsoluteScanDataset);
Dataset backgroundData = DatasetUtils.convertToDataset(reducedBackgroundDataset);
Dataset sampleData = DatasetUtils.convertToDataset(sampleDataset);
// Now we can calculate the required absorption coefficients
// TODO Serious thinking about whether this is good - should we be halving the background abs coeff as it passes through two walls?
double backgroundLinearAbsorptionCoefficient = backgroundITransmission / backgroundIZero;
double sampleLinearAbsorptionCoefficient = sampleITransmission / sampleIZero;
// The equation we're going to solve takes the form:
// TODO Fill this in!
// Sort out all the factors for the equation
double sampleFractionFactor = 1 / Math.exp(-((2 * backgroundLinearAbsorptionCoefficient * backgroundThickness) + (sampleLinearAbsorptionCoefficient * sampleThickness)));
double backgroundFractionFactor = 1 / Math.exp(-(2 * backgroundLinearAbsorptionCoefficient * backgroundThickness));
double equationPrefactor = 1 / sampleThickness;
// Now cast into float datasets so we can go through using the error propogation utilities
Dataset sampleFractionFactorData = DatasetFactory.createFromObject(Dataset.FLOAT64, sampleFractionFactor);
Dataset backgroundFractionFactorData = DatasetFactory.createFromObject(Dataset.FLOAT64, backgroundFractionFactor);
Dataset equationPrefactorData = DatasetFactory.createFromObject(Dataset.FLOAT64, equationPrefactor);
// Dataset hermanOrientationDataset = DatasetFactory.zeros(1, datasetSize, Dataset.FLOAT64);
// hermanOrientationDataset.set(hermanOrientationFactor, 0);
// Solve the first term of the equation inside the brackets
Dataset sampleOverAbsoluteScatterData = ErrorPropagationUtils.divideWithUncertainty(sampleData, absoluteScanData);
Dataset firstEquationTerm = ErrorPropagationUtils.multiplyWithUncertainty(sampleOverAbsoluteScatterData, sampleFractionFactorData);
//sampleOverAbsoluteScatterData = null;
// Solve the second term of the equation inside the brackets
Dataset backgroundOverAbsoluteScatterData = ErrorPropagationUtils.divideWithUncertainty(backgroundData, absoluteScanData);
Dataset secondEquationTerm = ErrorPropagationUtils.multiplyWithUncertainty(backgroundOverAbsoluteScatterData, backgroundFractionFactorData);
//backgroundOverAbsoluteScatterData = null;
// Solve the equation
Dataset equationTermInsideBrackets = ErrorPropagationUtils.subtractWithUncertainty(firstEquationTerm, secondEquationTerm);
Dataset sampleScatterProbabilityData = ErrorPropagationUtils.multiplyWithUncertainty(equationTermInsideBrackets, equationPrefactorData);
//equationTermInsideBrackets = null;
// Apply it to the diffraction image
Dataset backgroundSubtractedData = ErrorPropagationUtils.multiplyWithUncertainty(sampleData, sampleScatterProbabilityData);
//sampleScatterProbabilityData = null;
// Finally, we can create the operation data object that will hold this
OperationData toReturn = new OperationData();
// Fill it
toReturn.setData(backgroundSubtractedData);
//backgroundSubtractedData = null;
// And then return it
return toReturn;
}
}