/*-
* 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 uk.ac.diamond.scisoft.xpdf;
import java.util.Arrays;
import org.eclipse.january.dataset.Dataset;
import org.eclipse.january.dataset.Maths;
public class XPDFDetector {
private XPDFSubstance substance;
private double thickness;
private double solidAngleSubtended;
// Euler angles of the detector in radians
protected double[] eulerAngles;
/**
* Default constructor.
*/
public XPDFDetector() {
substance = null;
this.eulerAngles = new double[] {0, 0, 0};
}
/**
* Copy constructor.
* @param inTect
* detector data to be copied.
*/
public XPDFDetector(XPDFDetector inTect) {
this.substance = (inTect.substance != null) ? new XPDFSubstance(inTect.substance) : null;
this.thickness = inTect.thickness;
this.solidAngleSubtended = inTect.solidAngleSubtended;
this.eulerAngles = Arrays.copyOf(inTect.eulerAngles, 3);
}
/**
* Applies a detector correction to a Dataset.
* @param data
* the data to be corrected
* @param twoTheta
* the Dataset of angles over which the data is to be corrected
* @param beamEnergy
* the beam energy at which the correction is to take place
* @return the corrected data
*/
public Dataset applyTransmissionCorrection(Dataset data, Dataset twoTheta, double beamEnergy){
return Maths.multiply(data, getTransmissionCorrection(twoTheta, beamEnergy));
}
/**
* Returns a multiplicative detector correction.
* @param twoTheta
* the Dataset of angles over which the data is to be corrected
* @param beamEnergy
* the beam energy at which the correction is to take place
* @return the corrected data
*/
public Dataset getTransmissionCorrection(Dataset twoTheta, double beamEnergy){
final double mu = substance.getPhotoionizationCoefficient(beamEnergy);
Dataset transmission = null;
if (twoTheta.getShape().length == 1) {
transmission = calculateTransmission(mu, twoTheta);
} else {
transmission = (new XPDFScaled2DCalculation(4096) {
@Override
protected Dataset calculateTwoTheta(Dataset twoThetaLow) {
return calculateTransmission(mu, twoThetaLow);
}
}).runTwoTheta(twoTheta);
}
return transmission;
}
private Dataset calculateTransmission(double mu, Dataset twoTheta) {
return Maths.subtract(
1,
Maths.exp(
Maths.divide(
-mu*thickness,
Maths.cos(twoTheta)
)
)
);
}
/**
* Sets the substance of which the detector is made.
* @param substance
* An XPDFSubstance class describing the material from which
* the detector is made.
*/
public void setSubstance(XPDFSubstance substance) {
this.substance = substance;
}
/**
* Sets the thickness of the detector in mm.
* @param thickness
* thickness of the detector, measured in mm.
*/
public void setThickness(double thickness) {
this.thickness = thickness;
}
/**
* Gets the solid angle of the detector.
* <p>
* Gets the solid angle subtended by the detector from the sample.
* @return the total solid angle the detector subtends from the sample.
*/
public double getSolidAngle() {
return solidAngleSubtended;
}
/**
*
* Sets the solid angle of the detector.
* <p>
* Sets the solid angle subtended by the detector from the sample,
* expressed in steradians.
* @param solidAngleSubtended
* the total solid angle the detector subtends from the sample.
*/
public void setSolidAngle(double solidAngleSubtended) {
this.solidAngleSubtended = solidAngleSubtended;
}
/**
* Sets the Euler angles in radians
* @param eulerAngles
* Euler angles in radians ordered as pitch, yaw, roll.
*/
public void setEulerAngles(double[] eulerAngles) {
this.eulerAngles = Arrays.copyOf(eulerAngles, 3);
}
/**
* Sets the individual Euler angles in radians
* @param pitch Pitch angle in radians
* @param yaw Yaw angle in radians
* @param roll Roll angle in radians
*/
public void setEulerAngles(double pitch, double yaw, double roll) {
this.setEulerAngles(new double[] {pitch, yaw, roll});
}
/**
* Sets the individual Euler angles in degrees of arc
* @param pitch Pitch angle in degrees of arc
* @param yaw Yaw angle in degrees of arc
* @param roll Roll angle in degrees of arc
*/
public void setEulerAnglesinDegrees(double pitch, double yaw, double roll) {
this.setEulerAngles(Math.toRadians(pitch), Math.toRadians(yaw), Math.toRadians(roll));
}
/**
* Gets the Euler angles as an array
* @return Euler angles as (pitch, yaw, roll) in radians.
*/
public double[] getEulerAngles() {
return Arrays.copyOf(eulerAngles, 3);
}
/**
* Gets the Euler angles as an array in degrees of arc
* @return Euler angles as (pitch, yaw, roll) in degrees
*/
public double[] getEulerAnglesinDegrees() {
return new double[] {Math.toDegrees(eulerAngles[0]), Math.toDegrees(eulerAngles[1]), Math.toDegrees(eulerAngles[2])};
}
}