/*
* Copyright (c) 2012 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.diffraction;
import javax.vecmath.Vector3d;
import org.eclipse.dawnsci.analysis.api.diffraction.DetectorProperties;
import org.eclipse.dawnsci.analysis.api.diffraction.DiffractionCrystalEnvironment;
/**
* Q-space calculations
*
* q = k_f - k_i where |k| = 2 pi / lambda and |q| = 4 pi sin(theta)/lambda where
* lambda is wavelength (in Angstroms) and 2*theta is the scattering angle
*/
public class QSpace {
private static final double QSCALE_DEFAULT = 2. * Math.PI;
private DetectorProperties detProps;
private double kmod; // wave number
private Vector3d ki; // initial wave vector
private double qScale;
private double residual; // fitting mean of squared residuals
public QSpace(DetectorProperties detprops, DiffractionCrystalEnvironment diffexp, double scale) {
detProps = detprops;
qScale=scale;
setDiffractionCrystalEnvironment(diffexp);
}
public QSpace(DetectorProperties detprops, DiffractionCrystalEnvironment diffexp) {
this(detprops, diffexp, QSCALE_DEFAULT);
}
private void calculateInitalWavevector() {
ki = new Vector3d(detProps.getBeamVector());
ki.scale(kmod);
}
public void setDiffractionCrystalEnvironment(DiffractionCrystalEnvironment diffexp) {
kmod = qScale/diffexp.getWavelength();
calculateInitalWavevector();
}
/**
* @return wavelength in Angstroms
*/
public double getWavelength() {
return qScale/kmod;
}
public void setDetectorProperties(DetectorProperties detprops) {
detProps = detprops;
calculateInitalWavevector();
}
public DetectorProperties getDetectorProperties() {
return detProps;
}
public Vector3d getInitialWavevector() {
return ki;
}
/**
* Work out q from pixel coordinates
* @param x
* @param y
* @param q
*/
public void qFromPixelPosition(final double x, final double y, Vector3d q) {
detProps.pixelPosition(x, y, q);
q.normalize();
q.scale(kmod);
q.sub(ki);
}
/**
* Work out q from pixel coordinates
* @param x
* @param y
* @param q
*/
public void qFromPixelPosition(final int x, final int y, Vector3d q) {
qFromPixelPosition((double) x, (double) y, q);
}
/**
* @return q vector in inverse Angstroms
*/
public Vector3d qFromPixelPosition(final double x, final double y) {
Vector3d q = new Vector3d();
qFromPixelPosition(x, y, q);
return q;
}
/**
* @return q vector in inverse Angstroms
*/
public Vector3d qFromPixelPosition(final int x, final int y) {
return qFromPixelPosition((double) x, (double) y);
}
/**
* @return max |q| that detector can see
*/
public double maxModQ() {
double twotheta = detProps.getMaxScatteringAngle();
return 2.*kmod*Math.sin(0.5*twotheta);
}
/**
* Calculate pixel position from given q
* @param q
* @param p output position vector in reference frame
* @param t output vector (x and y components are pixel coordinates)
*/
public void pixelPosition(final Vector3d q, Vector3d p, Vector3d t) {
t.set(q);
t.add(ki);
t.normalize();
detProps.intersect(t, p);
detProps.pixelCoords(p, t);
}
/**
* Calculate pixel position from given q
* @param q
* @param t output vector (x and y components are pixel coordinates)
*/
public void pixelPosition(final Vector3d q, Vector3d t) {
Vector3d p = new Vector3d();
pixelPosition(q, p, t);
}
/**
* Calculate pixel position from given q
* @param q
* @return position of pixel
*/
public int[] pixelPosition(final Vector3d q) {
Vector3d t = new Vector3d(q);
t.add(ki);
t.normalize();
return detProps.pixelCoords(detProps.intersect(t));
}
/**
* Calculate scattering angle corresponding to given q vector
* @param q
* @return scattering angle (two-theta) in radians
*/
public double scatteringAngle(final Vector3d q) {
return 2.*Math.asin(0.5*q.length()/kmod);
}
/**
* Calculate solid angle subtended by pixel
* @param x
* @param y
* @return solid angle
*/
public double calculateSolidAngle(final int x, final int y) {
return detProps.calculateSolidAngle(x, y);
}
@Override
public String toString() {
return detProps + "; " + getWavelength();
}
/**
* @return mean of squared residuals
*/
public double getResidual() {
return residual;
}
/**
* Set mean of squared residuals
* @param residual
*/
public void setResidual(double residual) {
this.residual = residual;
}
}