/*- * 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 java.util.Arrays; import javax.vecmath.Matrix3d; import javax.vecmath.Vector3d; import org.eclipse.dawnsci.analysis.api.diffraction.DetectorProperties; import org.eclipse.dawnsci.analysis.api.diffraction.DiffractionCrystalEnvironment; import org.eclipse.dawnsci.analysis.api.roi.IParametricROI; import org.eclipse.dawnsci.analysis.api.roi.IROI; import org.eclipse.dawnsci.analysis.dataset.roi.EllipticalROI; import org.eclipse.dawnsci.analysis.dataset.roi.HyperbolicROI; import org.eclipse.dawnsci.analysis.dataset.roi.ParabolicROI; import org.junit.Assert; import org.junit.Before; import org.junit.Test; /** * Class that will test calculating */ public class DSpacingTest { DetectorProperties detector; DiffractionCrystalEnvironment diffexp; /** * build the detector and diffraction experiment */ @Before public void initialise() { double pixelSize = 0.1026; // static double pixelSize = 1.0; int[] imageSizePix = { 3072, 3072 }; Vector3d detectorOrigin = new Vector3d(105.37, 108.86, 170); // Vector3d detectorOrigin = new Vector3d(0, 0, 170); Vector3d beamCentre = new Vector3d(0, 0, 1); Matrix3d orientationMatrix = new Matrix3d( // 0.999846172301652, 0.017452379855755, -0.001745328365898, // -0.017451490332376, 0.999847574048345, 0.000523597954187, // 0.001754200362949, -0.000493058829215, 0.999998339835661); 0.984657762021401, 0.017187265168157, -0.17364817766693, 0.012961831885909, 0.985184016468007, 0.171010071662834, 0.174014604574351, -0.170637192932859, 0.969846310392954); // orientationMatrix.setIdentity(); double lambda = 0.97966; detector = new DetectorProperties(detectorOrigin, beamCentre, imageSizePix[0], imageSizePix[1], pixelSize, pixelSize, orientationMatrix); diffexp = new DiffractionCrystalEnvironment(lambda); } /** * Calculates the d spacing between peaks in pixels */ @Test public void dspacingFromPx() { int[] testingPix = { 854, 899, 864, 897,864, 897, 874, 894, 884, 892, 894, 889, 904, 886, 914, 884, 924, 882 }; double[] dspacing; try { dspacing = DSpacing.dSpacingsFromPixelCoords(detector, diffexp, testingPix); double average = 0; for (int i = 0; i < dspacing.length;) { average += dspacing[i++]; } average = average / dspacing.length; Assert.assertEquals(161, average, 1); // 171 <- is the old value but the method appears to be mathematically // correct } catch (Exception e) { e.printStackTrace(); } } @Test public void testEllipses() { DiffractionCrystalEnvironment env = new DiffractionCrystalEnvironment(0.5); DetectorProperties det = DetectorProperties.getDefaultDetectorProperties(new int[] {100, 100}); IROI roi = DSpacing.conicFromDSpacing(det, env, 1); EllipticalROI eroi = (EllipticalROI) roi; Assert.assertTrue("Circle", eroi.isCircular()); Assert.assertEquals("Radius", det.getBeamCentreDistance()*Math.tan(2*Math.asin(0.25))/det.getVPxSize(), eroi.getSemiAxis(0), 1e-7); det.setNormalAnglesInDegrees(0, 0, 30); roi = DSpacing.conicFromDSpacing(det, env, 1); eroi = (EllipticalROI) roi; Assert.assertEquals("Angle", 30, eroi.getAngleDegrees(), 1e-7); Assert.assertTrue("Circle", eroi.isCircular()); Assert.assertEquals("Radius", det.getBeamCentreDistance()*Math.tan(2*Math.asin(0.25))/det.getVPxSize(), eroi.getSemiAxis(0), 1e-7); det.setNormalAnglesInDegrees(0, 0, -30); roi = DSpacing.conicFromDSpacing(det, env, 1); eroi = (EllipticalROI) roi; Assert.assertEquals("Angle", 360-30, eroi.getAngleDegrees(), 1e-7); Assert.assertTrue("Circle", eroi.isCircular()); Assert.assertEquals("Radius", det.getBeamCentreDistance()*Math.tan(2*Math.asin(0.25))/det.getVPxSize(), eroi.getSemiAxis(0), 1e-7); det.setNormalAnglesInDegrees(30, 0, 0); roi = DSpacing.conicFromDSpacing(det, env, 1); eroi = (EllipticalROI) roi; Assert.assertFalse("Ellipse", eroi.isCircular()); Assert.assertEquals("Angle", 180, eroi.getAngleDegrees(), 1e-7); // Assert.assertEquals("Radius", det.getBeamCentreDistance()*Math.tan(2*Math.asin(0.25))/det.getVPxSize(), eroi.getSemiAxis(0), 1e-7); det.setNormalAnglesInDegrees(30, 0, 180); roi = DSpacing.conicFromDSpacing(det, env, 1); eroi = (EllipticalROI) roi; Assert.assertFalse("Ellipse", eroi.isCircular()); Assert.assertEquals("Angle", 0, eroi.getAngleDegrees(), 1e-7); det.setNormalAnglesInDegrees(30, 0, -180); roi = DSpacing.conicFromDSpacing(det, env, 1); eroi = (EllipticalROI) roi; Assert.assertFalse("Ellipse", eroi.isCircular()); Assert.assertEquals("Angle", 0, eroi.getAngleDegrees(), 1e-7); det.setNormalAnglesInDegrees(-30, 0, 0); roi = DSpacing.conicFromDSpacing(det, env, 1); eroi = (EllipticalROI) roi; Assert.assertFalse("Ellipse", eroi.isCircular()); Assert.assertEquals("Angle", 0, eroi.getAngleDegrees(), 1e-7); // Assert.assertEquals("Radius", det.getBeamCentreDistance()*Math.tan(2*Math.asin(0.25))/det.getVPxSize(), eroi.getSemiAxis(0), 1e-7); det.setNormalAnglesInDegrees(0, 30, 0); roi = DSpacing.conicFromDSpacing(det, env, 1); eroi = (EllipticalROI) roi; Assert.assertFalse("Ellipse", eroi.isCircular()); Assert.assertEquals("Angle", 360-90, eroi.getAngleDegrees(), 1e-7); det.setNormalAnglesInDegrees(0, -30, 0); roi = DSpacing.conicFromDSpacing(det, env, 1); eroi = (EllipticalROI) roi; Assert.assertFalse("Ellipse", eroi.isCircular()); Assert.assertEquals("Angle", 90, eroi.getAngleDegrees(), 1e-7); det.setNormalAnglesInDegrees(0, 30, 30); roi = DSpacing.conicFromDSpacing(det, env, 1); eroi = (EllipticalROI) roi; Assert.assertFalse("Ellipse", eroi.isCircular()); Assert.assertEquals("Angle", 360-90+30, eroi.getAngleDegrees(), 1e-7); det.setNormalAnglesInDegrees(0, 30, -30); roi = DSpacing.conicFromDSpacing(det, env, 1); eroi = (EllipticalROI) roi; Assert.assertFalse("Ellipse", eroi.isCircular()); Assert.assertEquals("Angle", 360-90-30, eroi.getAngleDegrees(), 1e-7); det.setNormalAnglesInDegrees(0, -30, 30); roi = DSpacing.conicFromDSpacing(det, env, 1); eroi = (EllipticalROI) roi; Assert.assertFalse("Ellipse", eroi.isCircular()); Assert.assertEquals("Angle", 90+30, eroi.getAngleDegrees(), 1e-7); det.setNormalAnglesInDegrees(0, -30, -30); roi = DSpacing.conicFromDSpacing(det, env, 1); eroi = (EllipticalROI) roi; Assert.assertFalse("Ellipse", eroi.isCircular()); Assert.assertEquals("Angle", 90-30, eroi.getAngleDegrees(), 1e-7); det.setNormalAnglesInDegrees(30, 0, 30); roi = DSpacing.conicFromDSpacing(det, env, 1); eroi = (EllipticalROI) roi; Assert.assertFalse("Ellipse", eroi.isCircular()); Assert.assertEquals("Angle", 180+30, eroi.getAngleDegrees(), 1e-7); det.setNormalAnglesInDegrees(30, 0, -30); roi = DSpacing.conicFromDSpacing(det, env, 1); eroi = (EllipticalROI) roi; Assert.assertFalse("Ellipse", eroi.isCircular()); Assert.assertEquals("Angle", 180-30, eroi.getAngleDegrees(), 1e-7); det.setNormalAnglesInDegrees(-30, 0, 30); roi = DSpacing.conicFromDSpacing(det, env, 1); eroi = (EllipticalROI) roi; Assert.assertFalse("Ellipse", eroi.isCircular()); Assert.assertEquals("Angle", 30, eroi.getAngleDegrees(), 1e-7); det.setNormalAnglesInDegrees(-30, 0, -30); roi = DSpacing.conicFromDSpacing(det, env, 1); eroi = (EllipticalROI) roi; Assert.assertFalse("Ellipse", eroi.isCircular()); Assert.assertEquals("Angle", 360-30, eroi.getAngleDegrees(), 1e-7); det.setNormalAnglesInDegrees(0, 0, 0); try { roi = DSpacing.conicFromAngle(det, Math.PI*0.5); } catch (UnsupportedOperationException e) { // do nothing Assert.fail("Now should not have thrown an exception"); } } @SuppressWarnings("deprecation") @Test public void testConics() { DetectorProperties det = DetectorProperties.getDefaultDetectorProperties(new int[] {100, 100}); double alpha = 60; double[] alphas = new double[] {Math.toRadians(alpha)}; IROI[] rois; rois = DSpacing.conicsFromAngles(det, alphas); Assert.assertTrue(rois[0] instanceof EllipticalROI); checkEllipses((EllipticalROI) DSpacing.oldConicFromAngle(det, alphas[0]), (EllipticalROI) rois[0]); System.err.println(rois[0]); double delta = 0.1; det.setNormalAnglesInDegrees(90 - alpha - delta, 0, 0); rois = DSpacing.conicsFromAngles(det, alphas); Assert.assertTrue(rois[0] instanceof EllipticalROI); checkEllipses((EllipticalROI) DSpacing.oldConicFromAngle(det, alphas[0]), (EllipticalROI) rois[0]); double[] apt = ((EllipticalROI) rois[0]).getPoint(Math.PI); System.err.println(rois[0] + ", point=" + Arrays.toString(apt)); det.setNormalAnglesInDegrees(30, 0, 0); rois = DSpacing.conicsFromAngles(det, alphas); Assert.assertTrue(rois[0] instanceof ParabolicROI); double[] bpt = ((ParabolicROI) rois[0]).getPoint(Math.PI); System.err.println(rois[0] + ", point=" + Arrays.toString(bpt)); det.setNormalAnglesInDegrees(30.1, 0, 0); rois = DSpacing.conicsFromAngles(det, alphas); Assert.assertTrue(rois[0] instanceof HyperbolicROI); double[] cpt = ((HyperbolicROI) rois[0]).getPoint(Math.PI); System.err.println(rois[0] + ", point=" + Arrays.toString(cpt)); // check a point is close Assert.assertEquals(apt[0], bpt[0], 2); Assert.assertEquals(apt[1], bpt[1], 1e-8); Assert.assertEquals(apt[0], cpt[0], 4); Assert.assertEquals(apt[1], cpt[1], 1e-8); } @Test public void testAllConics() { double d = 100; DetectorProperties det = new DetectorProperties(d, 0, 0, 100, 100, 1, 1); double[] alphas = new double[] {Math.toRadians(30), Math.toRadians(45), Math.toRadians(60)}; IROI[] rois; rois = DSpacing.conicsFromAngles(det, alphas); for (int i = 0; i < alphas.length; i++) { IROI roi = rois[i]; Assert.assertTrue(roi instanceof EllipticalROI); double r = d * Math.tan(alphas[i]); checkEllipses(new EllipticalROI(r, r, 0, 0, 0), (EllipticalROI) roi); System.err.println(roi); } double eta = Math.toRadians(45); det.setNormalAnglesInDegrees(Math.toDegrees(eta), 0, 0); rois = DSpacing.conicsFromAngles(det, alphas); IParametricROI roi = (IParametricROI) rois[0]; double alpha = alphas[0]; Assert.assertTrue(roi instanceof EllipticalROI); double a = d * Math.sqrt(1.5); double b = a * 0.5 / Math.cos(alpha); double t = d * Math.cos(eta) * Math.tan(eta - alpha) - d * Math.sin(eta); // AQ - PQ = -AP double x = a + t; // CA - AP = CP double[] pt = roi.getPoint(Math.PI); Assert.assertEquals(-t, pt[0], 1e-10); Vector3d v = det.pixelPosition(pt[0], pt[1]); Assert.assertEquals(-d * Math.sin(alpha) * Math.cos(eta) / Math.cos(eta - alpha), v.getX(), 1e-10); checkEllipses(new EllipticalROI(a, b, Math.PI, -x, 0), (EllipticalROI) roi); System.err.println(roi); roi = (IParametricROI) rois[1]; alpha = alphas[1]; Assert.assertTrue(roi instanceof ParabolicROI); pt = roi.getPoint(Math.PI); v = det.pixelPosition(pt[0], pt[1]); Assert.assertEquals(-d * Math.sin(alpha) * Math.cos(eta) / Math.cos(eta - alpha), v.getX(), 1e-10); a = 0.5 * d * Math.cos(eta) * Math.tan(alpha); // aka focal parameter t = d * Math.cos(eta) / Math.tan(2 * alpha); x = a + t; checkParabolas(new ParabolicROI(a, Math.PI, x, 0), (ParabolicROI) roi); System.err.println(roi); roi = (IParametricROI) rois[2]; alpha = alphas[2]; Assert.assertTrue(roi instanceof HyperbolicROI); pt = roi.getPoint(Math.PI); v = det.pixelPosition(pt[0], pt[1]); Assert.assertEquals(-d * Math.sin(alpha) * Math.cos(eta) / Math.cos(eta - alpha), v.getX(), 1e-10); a = d * Math.cos(eta) * Math.tan(alpha); // l x = 4 * d * Math.cos(eta) * Math.sin(eta) * (Math.sin(alpha) - Math.cos(eta)) - d * Math.sin(eta); checkHyperbolas(new HyperbolicROI(a, Math.sin(eta) / Math.cos(alpha), Math.PI, -x, 0), (HyperbolicROI) roi); System.err.println(roi); alphas = new double[90]; for (int j = 0; j < alphas.length; j++) { alphas[j] = Math.toRadians(j); } for (int i = 0; i < 90; i++) { det.setNormalAnglesInDegrees(i, 0, 0); eta = Math.toRadians(i); rois = DSpacing.conicsFromAngles(det, alphas); for (int j = 0; j < alphas.length; j++) { alpha = alphas[j]; roi = (IParametricROI) rois[j]; int k = i + j; if (k < 90) { Assert.assertTrue(roi instanceof EllipticalROI); } else if (k == 90) { Assert.assertTrue(roi instanceof ParabolicROI); } else { Assert.assertTrue(roi instanceof HyperbolicROI); } pt = roi.getPoint(i == 0 ? 0 : Math.PI); v = det.pixelPosition(pt[0], pt[1]); Assert.assertEquals(-d * Math.sin(alpha) * Math.cos(eta) / Math.cos(eta - alpha), v.getX(), 1e-10); } } } private void checkEllipses(EllipticalROI ea, EllipticalROI eb) { double tol = 1e-7; Assert.assertEquals(ea.getSemiAxis(0), eb.getSemiAxis(0), tol); Assert.assertEquals(ea.getSemiAxis(1), eb.getSemiAxis(1), tol); Assert.assertEquals(ea.getAngle(), eb.getAngle(), tol); Assert.assertEquals(ea.getPointX(), eb.getPointX(), tol); Assert.assertEquals(ea.getPointY(), eb.getPointY(), tol); } private void checkParabolas(ParabolicROI pa, ParabolicROI pb) { double tol = 1e-8; Assert.assertEquals(pa.getFocalParameter(), pb.getFocalParameter(), tol); Assert.assertEquals(pa.getAngle(), pb.getAngle(), tol); Assert.assertEquals(pa.getPointX(), pb.getPointX(), tol); Assert.assertEquals(pa.getPointY(), pb.getPointY(), tol); } private void checkHyperbolas(HyperbolicROI ha, HyperbolicROI hb) { double tol = 1e-8; Assert.assertEquals(ha.getSemilatusRectum(), hb.getSemilatusRectum(), tol); Assert.assertEquals(ha.getEccentricity(), hb.getEccentricity(), tol); Assert.assertEquals(ha.getAngle(), hb.getAngle(), tol); Assert.assertEquals(ha.getPointX(), hb.getPointX(), tol); Assert.assertEquals(ha.getPointY(), hb.getPointY(), tol); } }