/* * 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.diffraction.powder; import static org.junit.Assert.*; import java.util.Arrays; import org.eclipse.january.dataset.DatasetFactory; import org.eclipse.january.dataset.DoubleDataset; import org.junit.Before; import org.junit.Test; import uk.ac.diamond.scisoft.analysis.diffraction.powder.SurfaceQ; public class SurfaceQTest { // The sample is at an angle of 1° to the vertical static final double alpha = Math.PI/180.; DoubleDataset sampleNormal; SurfaceQ testQ; @Before public void setUp() throws Exception { testQ = new SurfaceQ(); sampleNormal = (DoubleDataset) DatasetFactory.createFromList(Arrays.asList(0., Math.cos(alpha), -Math.sin(alpha))); testQ.setSurfaceNormal(sampleNormal); } @Test public void testQPerpendicularDoubleDatasetDoubleDatasetDouble() { double qPerpTrig = 0, qPerpVect = 0; classCommonCode(true, qPerpTrig, qPerpVect); assertEquals(qPerpTrig, qPerpVect, 1e-3); } @Test public void testQParallelDoubleDatasetDoubleDatasetDouble() { double qPerpTrig = 0, qPerpVect = 0; classCommonCode(true, qPerpTrig, qPerpVect); assertEquals(qPerpTrig, qPerpVect, 1e-3); } @Test public void testQPerpendicularDoubleDatasetDoubleDatasetDoubleDatasetDouble() { double qPerpTrig = 0, qPerpVect = 0; staticCommonCode(true, qPerpTrig, qPerpVect); assertEquals(qPerpTrig, qPerpVect, 1e-3); } @Test public void testQParallelDoubleDatasetDoubleDatasetDoubleDatasetDouble() { double qParaTrig = 0, qParaVect = 0; staticCommonCode(false, qParaTrig, qParaVect); assertEquals(qParaTrig, qParaVect, 1e-3); } void classCommonCode(boolean getPerp, double trig, double vect) { // Let the scattered beam lie at (0.15, 0.08, 2.0) DoubleDataset scatteredBeam = DatasetFactory.createFromList(DoubleDataset.class, Arrays.asList(0.15, 0.08, 2.0)); DoubleDataset incidentBeam = DatasetFactory.createFromList(DoubleDataset.class, Arrays.asList(0.0, 0.0, 1.0)); double energy = 12.0; // 12 keV ~= 1 Å double qPerpTrig = 0, qParaTrig = 0; trigCalculation(scatteredBeam, energy, qPerpTrig, qParaTrig); double qPerpVect = testQ.qPerpendicular(scatteredBeam, incidentBeam, energy), qParaVect = testQ.qParallel(scatteredBeam, incidentBeam, energy); if (getPerp) { trig = qPerpTrig; vect = qPerpVect; } else { trig = qParaTrig; vect = qParaVect; } } void staticCommonCode(boolean getPerp, double trig, double vect) { // Let the scattered beam lie at (0.05, 0.1, 2.0) DoubleDataset scatteredBeam = DatasetFactory.createFromList(DoubleDataset.class, Arrays.asList(0.05, 0.1, 2.0)); DoubleDataset incidentBeam = DatasetFactory.createFromList(DoubleDataset.class, Arrays.asList(0.0, 0.0, 1.0)); double energy = 12.0; // 12 keV ~= 1 Å double qPerpTrig = 0, qParaTrig = 0; trigCalculation(scatteredBeam, energy, qPerpTrig, qParaTrig); double qPerpVect = SurfaceQ.qPerpendicular(scatteredBeam, incidentBeam, sampleNormal, energy), qParaVect = SurfaceQ.qParallel(scatteredBeam, incidentBeam, sampleNormal, energy); if (getPerp) { trig = qPerpTrig; vect = qPerpVect; } else { trig = qParaTrig; vect = qParaVect; } } private static void trigCalculation(DoubleDataset scatteredBeam, double energy, double qPerpTrig, double qParaTrig) { // trigonometric answer double psi0 = Math.atan2(scatteredBeam.get(0), scatteredBeam.get(2)); double beta0 = Math.atan2(scatteredBeam.get(1), addQuadrature(scatteredBeam.get(0), scatteredBeam.get(2))); double beta = beta0 - alpha * Math.cos(psi0); double psi = psi0; double qx = Math.cos(beta) * Math.cos(psi) - Math.cos(alpha); double qy = Math.cos(beta) * Math.sin(psi); double qz = Math.sin(beta) + Math.sin(alpha); double k = energy/1.9732697879296464; // wavenumber in 1/Å qx *= k; qy *= k; qz *= k; qPerpTrig = qz; qParaTrig = addQuadrature(qx, qy); } private static double addQuadrature(double a, double b) { return Math.sqrt(a*a + b*b); } }