/*- * 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 java.util.List; import org.eclipse.january.dataset.Dataset; /** * The class for cylindrical components of the experimental target. This class * is <code>public</code> because it needs to be visible in the * uk...xpdf.operations package * @author Timothy Spain timothy.spain@diamond.ac.uk * @since 2015-09-11 * */ public abstract class XPDFComponentGeometry { // Larger and smaller measurements of the component protected double rInner, rOuter; // Is this component up/down stream of the sample. The sample component is // neither upstream nor downstream of itself protected boolean isUpstream, isDownstream; protected int gridSize; // Euler angles of the component in radians protected double[] eulerAngles; /** * Empty constructor */ public XPDFComponentGeometry() { this.rInner = 0.0; this.rOuter = 0.0; this.isUpstream = false; this.isDownstream = false; this.gridSize = 4096; this.eulerAngles = new double[] {0, 0, 0}; } /** * Copy constructor for general geometries. * @param inGeom * component geometry to be copied */ public XPDFComponentGeometry(XPDFComponentGeometry inGeom) { this.rInner = inGeom.rInner; this.rOuter = inGeom.rOuter; this.isUpstream = inGeom.isUpstream; this.isDownstream = inGeom.isDownstream; this.gridSize = inGeom.gridSize; this.eulerAngles = Arrays.copyOf(inGeom.eulerAngles, 3); } /** * Clone method. */ @Override protected abstract XPDFComponentGeometry clone(); /** * Sets the sizes of the geometry. * @param inIn * smaller distance (inner radius, downstream face,...) * @param inOut * larger distance (outer radius, upstream face,...) */ public void setDistances(double inIn, double inOut) { this.rInner = inIn; this.rOuter = inOut; } /** * Sets the streamality of the geometry. * @param is_up * is it present upstream? * @param is_down * is it present downstream? */ public void setStreamality(boolean is_up, boolean is_down) { this.isUpstream = is_up; this.isDownstream = is_down; } /** * The name of the shape. * @return the name of the shape. */ abstract public String getShape(); /** * Gets the distances of the geometry. * @return the distances defining the geometry as a two element double array. */ public double[] getDistances() { double[] distances = new double[2]; distances[0] = rInner; distances[1] = rOuter; return distances; } /** * Gets the streamality of the geometry. * @return the distances defining the geometry as a two element boolean array. */ public boolean[] getStreamality() { boolean[] strity = new boolean[2]; strity[0] = isUpstream; strity[1] = isDownstream; return strity; } /** * Sets the size of the absorption grid. * @param gridSize * The total number of gridpoints to use in calculating the * absorption coefficients. */ public void setGridSize(int gridSize) { this.gridSize = gridSize; } /** * 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])}; } // return the volume of this component illuminated by the beam geometry // encapsulated in beamData /** * Returns the volume of this geometry illuminated by the beam. * <p> * Returns the volume of this component illuminated by the beam geometry * encapsulated in beamData. * @param beamData * the beam doing the illuminating * @return the number of atoms illuminated. */ public abstract double getIlluminatedVolume(XPDFBeamData beamData); /* * Path length of the object upstream of the sample, as measured at the * point (x, y) in the beam. x is in the direction measured as beam width, y * in the direction measured as beam height. */ /** * Returns the path length upstream of the given points. * <p> * Path length of the object upstream of the sample, as measured at the * point (x, y) in the beam. x is in the direction measured as beam width, y * in the direction measured as beam height. * @param x * distance perpendicular to the beam, and for a cylinder to the * cylindrical axis. * @param y * distance perpendicular to the beam and to x. * @param z * distance along the beam. z increases in the direction the beam * propagates. * @return the path length upstream of every point defined. */ public abstract Dataset getUpstreamPathLength(Dataset x, Dataset y, Dataset z); /** * Returns the path length downstream of the given points, in the given direction. * <p> * Path length of the object downstream of the sample, as measured at the * point x,y,z in the beam. x,y are as above, whereas z is the depth into * the target assembly in the direction of the beam, with zero at the * sample. * <p> * The path length is measured in the direction γ, δ, where γ is the * vertical scattering angle and δ is the horizontal scattering angle. * @param x * distance perpendicular to the beam, and for a cylinder to the * cylindrical axis. * @param y * distance perpendicular to the beam and to x. * @param z * distance along the beam. z increases in the direction the beam * propagates. * @return the path length downstream of every point defined. */ public abstract Dataset getDownstreamPathLength(Dataset x, Dataset y, Dataset z, double gamma, double delta); /** * Calculates the absorption correction map when attenuatorGeometry is attenuating. * <p> * Given an attenuator geometry and its attenuation coefficient (in cm²/g), * as well as its existence up- and downstream, calculate the absorption * map for the horizontal and vertical scattering angles given in the * input datasets. * <p> * The absorption is measured in the scattering direction γ, δ, where γ is the * vertical scattering angle and δ is the horizontal scattering angle. These angles are provided as 2 dimensional Datasets, not necessarily forming a regular grid * @param gamma * vertical scattering angle in radians. * @param delta * horizontal scattering angle in radians. * @param attenuatorGeometry * geometry of the object doing the absorption. * @param attenuationCoefficient * attenuation coefficient of the substance in cm²/g. * @param beamData * properties of the beam. * @param doUpstreamAbsorption * perform upstream absorption for this pair of objects. * @param doDownstreamAbsorption * perform downstream absorption for this pair of objects. * @return the absorption correction map. */ public abstract Dataset calculateAbsorptionCorrections(Dataset gamma, Dataset delta, XPDFComponentGeometry attenuatorGeometry, double attenuationCoefficient, XPDFBeamData beamData, boolean doUpstreamAbsorption, boolean doDownstreamAbsorption); public boolean isEqualToForAbsorption(XPDFComponentGeometry inGeometry) { return (inGeometry != null) && rInner == inGeometry.rInner && rOuter == inGeometry.rOuter && isUpstream == inGeometry.isUpstream && isDownstream == inGeometry.isDownstream && gridSize == inGeometry.gridSize && getShape() == inGeometry.getShape(); } /** * Calculates the fluorescence of an object. * <p> * Calculates the fluorescence of an object after passing through all the * listed attenuators in the given directions. The attenuators also * attenuate the incoming beam, which recapitulates the upstream absorption * maps calculation. * @param gamma * horizontal scattering angles in radians. * @param delta * vertical scattering angle in radians. * @param attenuators * a list of the attenuator geometries to be considered. * @param attenuationsIn * the attenuation coefficients of the attenuator * materials at the beam energy. * @param attenuationsOut * the attenuation coefficients of the attenuator * materials at the fluorescence energy. * @param beamData * properties of the inbound beam. * @param doIncomingAbsorption * perform the attenuation on the beam. * @param doOutgoingAbsorption * perform the attenuation on the fluorescence. * @return the fluorescence intensity as a function of angle */ public abstract Dataset calculateFluorescence(Dataset gamma, Dataset delta, List<XPDFComponentGeometry> attenuators, List<Double> attenuationsIn, List<Double> attenuationsOut, XPDFBeamData beamData, boolean doIncomingAbsorption, boolean doOutgoingAbsorption); }