gda.device.detector.addetector.ADDetectorTest.java Source code

Java tutorial

Introduction

Here is the source code for gda.device.detector.addetector.ADDetectorTest.java

Source

/*-
 * Copyright  2011 Diamond Light Source Ltd.
 *
 * This file is part of GDA.
 *
 * GDA is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 as published by the Free
 * Software Foundation.
 *
 * GDA is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 * details.
 *
 * You should have received a copy of the GNU General Public License along
 * with GDA. If not, see <http://www.gnu.org/licenses/>.
 */

package gda.device.detector.addetector;

import static org.apache.commons.lang.ArrayUtils.addAll;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import gda.data.nexus.tree.INexusTree;
import gda.device.Detector;
import gda.device.DeviceException;
import gda.device.detector.NXDetectorData;
import gda.device.detector.areadetector.v17.ADBase;
import gda.device.detector.areadetector.v17.NDArray;
import gda.device.detector.areadetector.v17.NDPluginBase;
import gda.device.detector.areadetector.v17.NDStats;
import gda.device.detector.nxdetector.AsyncNXCollectionStrategy;
import gda.device.detector.nxdetector.NXFileWriterPlugin;
import gda.jython.ICurrentScanInformationHolder;
import gda.jython.InterfaceProvider;
import gda.scan.ScanInformation;

import org.apache.commons.lang.ArrayUtils;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Matchers;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

public class ADDetectorTest {

    private ADDetector adDet;
    @Mock
    protected ADBase adBase;
    @Mock
    protected AsyncNXCollectionStrategy collectionStrategy;
    @Mock
    protected NXFileWriterPlugin fileWriter;
    @Mock
    protected NDArray ndArray;
    @Mock
    protected NDStats ndStats;
    @Mock
    protected NDPluginBase ndArrayBase;
    @Mock
    protected NDPluginBase ndStatsBase;

    protected static String[] STATS_NAMES = new String[] { "min", "max", "total", "net", "mean", "sigma" };
    protected static String[] STATS_FORMATS = new String[] { "%5.5g", "%5.5g", "%5.5g", "%5.5g", "%5.5g", "%5.5g" };
    protected static String[] CENTROID_NAMES = new String[] { "centroidX", "centroidY", "centroid_sigmaX",
            "centroid_sigmaY", "centroid_sigmaXY" };
    protected static String[] CENTROID_FORMATS = new String[] { "%5.5g", "%5.5g", "%5.5g", "%5.5g", "%5.5g" };

    protected double READOUT_TIME = 0.1;

    protected ScanInformation scanInfo;

    public Detector det() {
        return adDet;
    }

    protected ADDetector adDet() {
        return adDet;
    }

    @Before
    public void setUp() throws Exception {
        MockitoAnnotations.initMocks(this);
        setUpNoConfigure();
        adDet().configure();
        configureScanInformationHolder();
    }

    protected void configureScanInformationHolder() {
        scanInfo = mock(ScanInformation.class);
        ICurrentScanInformationHolder currentScanHolder = mock(ICurrentScanInformationHolder.class);
        when(currentScanHolder.getCurrentScanInformation()).thenReturn(scanInfo);
        when(scanInfo.getScanNumber()).thenReturn(12345);
        InterfaceProvider.setCurrentScanInformationHolderForTesting(currentScanHolder);
    }

    protected void setUpNoConfigure() throws Exception {
        createDetector();
        det().setName("testdet");
        adDet().setAdBase(adBase);
        adDet().setNdArray(ndArray);
        adDet().setNdStats(ndStats);
        adDet().setFileWriter(fileWriter);
        adDet().afterPropertiesSet();
        when(ndArray.getPluginBase()).thenReturn(ndArrayBase);
        when(ndStats.getPluginBase()).thenReturn(ndStatsBase);
        when(fileWriter.appendsFilepathStrings()).thenReturn(true);
    }

    protected void createDetector() {
        adDet = new ADDetector();
        adDet.setCollectionStrategy(collectionStrategy);
    }

    protected void enableStatsAndCentroid(boolean computeStats, boolean computeCentroid) {
        adDet().setComputeStats(computeStats);
        adDet().setComputeCentroid(computeCentroid);
    }

    protected void enableArrayReadout(boolean enableArrayReadout) {
        adDet().setReadArray(enableArrayReadout);
    }

    protected void enableReadAcquisitionTimeAndPeriod(boolean enableTime, boolean enablePeriod) {
        adDet().setReadAcquisitionTime(enableTime);
        adDet().setReadAcquisitionPeriod(enablePeriod);
    }

    protected void enableFileWriter(boolean enableFileWriter) throws Exception {
        adDet().setReadFilepath(enableFileWriter);
    }

    @Test
    public void testConstructor() throws Exception {
        setUpNoConfigure();
        assertFalse(adDet().isComputeStats());
        assertFalse(adDet().isComputeCentroid());
        assertFalse(det().createsOwnFiles());
        assertTrue(adDet().isLocal());
        assertTrue(adDet().isReadAcquisitionTime());
        assertFalse(adDet().isReadAcquisitionPeriod());
        assertFalse(adDet().isReadFilepath());
    }

    @Test
    public void testReadsArrayByDefault() throws Exception {
        setUpNoConfigure();
        assertTrue(adDet().isReadArray());
    }

    // The behaviour expected in this test is different from what DetectorBase does.
    // Having this throw exceptions lead to a 7GB logfile in 1 day on I05, because
    // under certain conditions the exception is logged, then ignored and isBusy()
    // called again immediately. Finding and fixing that loop would be a good idea,
    // but for consistency (see first sentence) not throwing an exception here is
    // also reasonable.
    //   @Test(expected=RuntimeException.class)
    //   public void testAsynchronousMoveTo() throws DeviceException {
    //      det().asynchronousMoveTo(1.);
    //   }

    @Test(expected = RuntimeException.class)
    public void testGetPosition() throws DeviceException {
        det().getPosition();
    }

    // The behaviour expected in this test is different from what DetectorBase does.
    // Having this throw exceptions lead to a 7GB logfile in 1 day on I05, because
    // under certain conditions the exception is logged, then ignored and isBusy()
    // called again immediately. Finding and fixing that loop would be a good idea,
    // but for consistency (see first sentence) not throwing an exception here is
    // also reasonable.
    //   @Test(expected=RuntimeException.class)
    //   public void testIsBusy() throws DeviceException {
    //      det().isBusy();
    //   }

    @Test
    public void testConfigure() throws Exception {
        setUpNoConfigure();
        adDet().configure();
        // duplicated below
        verify(adBase, times(2)).reset();
        verify(ndArray, times(2)).reset();
        verify(ndStats, times(2)).reset();
    }

    @Test
    public void testReset() throws Exception {
        setUpNoConfigure();
        adDet().reset();
        verify(adBase, times(2)).reset();
        verify(ndArray, times(2)).reset();
        verify(ndStats, times(2)).reset();
    }

    @Test
    public void testGetInputNames() {
        assertArrayEquals(new String[] {}, det().getInputNames());
        enableReadAcquisitionTimeAndPeriod(false, false);
        assertArrayEquals(new String[] {}, det().getInputNames());

    }

    @Test
    public void testGetExtraNamesNostats() throws Exception {
        enableStatsAndCentroid(false, false);
        assertArrayEquals(new String[] { "count_time" }, det().getExtraNames());
        enableReadAcquisitionTimeAndPeriod(true, true);
        assertArrayEquals(new String[] { "count_time", "period" }, det().getExtraNames());
        enableFileWriter(true);
        assertArrayEquals(new String[] { "count_time", "period", "filepath" }, det().getExtraNames());
    }

    @Test
    public void testGetExtraNamesCentroid() {
        enableStatsAndCentroid(false, true);
        assertArrayEquals(ArrayUtils.addAll(new String[] { "count_time" }, CENTROID_NAMES), det().getExtraNames());
    }

    @Test
    public void testGetExtraNamesStats() {
        enableStatsAndCentroid(true, false);
        assertArrayEquals(ArrayUtils.addAll(new String[] { "count_time" }, STATS_NAMES), det().getExtraNames());
    }

    @Test
    public void testGetExtraNamesStatsAndCentroidAndPeriod() {
        enableStatsAndCentroid(true, true);
        enableReadAcquisitionTimeAndPeriod(true, true);
        assertArrayEquals(addAll(new String[] { "count_time", "period" }, addAll(STATS_NAMES, CENTROID_NAMES)),
                det().getExtraNames());
    }

    @Test
    public void testGetOutputFormat() throws Exception {
        enableReadAcquisitionTimeAndPeriod(false, false);
        enableStatsAndCentroid(false, false);
        assertArrayEquals(new String[] {}, det().getOutputFormat());

        enableReadAcquisitionTimeAndPeriod(true, false);
        assertArrayEquals(new String[] { "%.2f" }, det().getOutputFormat());

        enableFileWriter(true);
        //the 2nd value in position is a number that represents the file.
        assertArrayEquals(new String[] { "%.2f", "%.2f" }, det().getOutputFormat());
        enableFileWriter(false);

        enableReadAcquisitionTimeAndPeriod(true, true);
        assertArrayEquals(new String[] { "%.2f", "%.2f" }, det().getOutputFormat());

        enableFileWriter(true);
        enableReadAcquisitionTimeAndPeriod(true, true);
        //the 3rd value in position is a number that represents the file.
        assertArrayEquals(new String[] { "%.2f", "%.2f", "%.2f" }, det().getOutputFormat());
        enableFileWriter(false);

        enableStatsAndCentroid(true, false);
        assertArrayEquals(new String[] { "%.2f", "%.2f", "%5.5g", "%5.5g", "%5.5g", "%5.5g", "%5.5g", "%5.5g" },
                det().getOutputFormat());

        enableStatsAndCentroid(true, true);
        assertArrayEquals(new String[] { "%.2f", "%.2f", "%5.5g", "%5.5g", "%5.5g", "%5.5g", "%5.5g", "%5.5g",
                "%5.5g", "%5.5g", "%5.5g", "%5.5g", "%5.5g" }, det().getOutputFormat());
    }

    @Test
    public void testStatus() throws Exception {
        when(collectionStrategy.getStatus()).thenReturn(Detector.IDLE);
        assertEquals(Detector.IDLE, det().getStatus());

        when(collectionStrategy.getStatus()).thenReturn(Detector.BUSY);
        assertEquals(Detector.BUSY, det().getStatus());
    }

    @Test
    public void waitWhileBusy() throws Exception {
        det().waitWhileBusy();
        verify(collectionStrategy).waitWhileBusy();

    }

    @Test
    public void testAtScanStart() throws Exception {
        enableStatsAndCentroid(true, true);
        enableArrayReadout(true);
        det().setCollectionTime(1.);
        det().atScanStart();
        verify(adBase).setArrayCallbacks((short) 1);
        verify(ndArrayBase).enableCallbacks();
        verify(ndArrayBase).setBlockingCallbacks((short) 1);
        //      verify(ndStats).setComputeStatistics((short) 1);
        //      verify(ndStats).setComputeCentroid((short) 1);
        //      verify(ndStatsBase).setBlockingCallbacks((short) 1);
        verify(collectionStrategy).prepareForCollection(1., 1, null);
    }

    @Test
    public void testAtScanStartAllOff() throws Exception {
        enableStatsAndCentroid(false, false);
        enableArrayReadout(false);
        det().atScanStart();
        verify(adBase).setArrayCallbacks((short) 1);
        verify(ndArrayBase).disableCallbacks();
        verify(ndArrayBase).setBlockingCallbacks((short) 0);
        verify(ndStats).setComputeStatistics((short) 0);
        verify(ndStats).setComputeCentroid((short) 0);
        verify(ndStatsBase).setBlockingCallbacks((short) 0);
    }

    @Test
    public void testAtScanStartAllOffDisableCallbacks() throws Exception {
        enableArrayReadout(false);
        adDet().setDisableCallbacks(true);
        det().atScanStart();
        verify(adBase).setArrayCallbacks((short) 0);
        verify(ndArrayBase).disableCallbacks();
        verify(ndArrayBase).setBlockingCallbacks((short) 0);
        verify(ndStats).setComputeStatistics((short) 0);
        verify(ndStats).setComputeCentroid((short) 0);
        verify(ndStatsBase).setBlockingCallbacks((short) 0);
    }

    @Test
    public void testCollectData() throws Exception {
        enableStatsAndCentroid(true, true);
        enableArrayReadout(true);

        det().setCollectionTime(1);
        det().collectData();
        when(collectionStrategy.getStatus()).thenReturn(Detector.BUSY);

        verify(collectionStrategy).collectData();
    }

    @Test
    public void testCollectDataPutsTimesOnlyOncePerScan() throws Exception {
        det().setCollectionTime(1);
        det().atScanStart();
        det().collectData();
        det().collectData();
        det().collectData();
        verify(collectionStrategy, times(1)).prepareForCollection(1., 1, null);
    }

    @Test
    public void testGetStatusAfterCollectDataGoesWhenAllBusy() throws Exception {
        testCollectData();
        assertEquals(Detector.BUSY, det().getStatus());
    }

    @Test
    public void testGetStatusAfterCollectDataGoesWhenNotBusy() throws Exception {
        testCollectData();
        assertEquals(Detector.BUSY, det().getStatus());
        when(collectionStrategy.getStatus()).thenReturn(Detector.IDLE);
        assertEquals(Detector.IDLE, det().getStatus());
    }

    @Test
    public void testGetStatusWithAdBaseFault() throws DeviceException, Exception {
        when(collectionStrategy.getStatus()).thenReturn(Detector.FAULT);
        assertEquals(Detector.FAULT, det().getStatus());
    }

    @Test
    public void testReadoutNoArrayStatsOrCentroid() throws DeviceException {
        enableStatsAndCentroid(false, false);
        enableArrayReadout(false);
        enableReadAcquisitionTimeAndPeriod(false, false);
        NXDetectorData data = (NXDetectorData) det().readout();
        assertEquals("", data.toString());
        //      Double[] doubleVals = data.getDoubleVals();
        //      assertArrayEquals(new Double[] { }, doubleVals);
        // the behaviour tested here is wrong. The detector declares extraNames, so some value needs to be returned to fulfil the contract
    }

    @Test
    public void testReadoutArray() throws Exception {
        enableStatsAndCentroid(false, false);
        enableArrayReadout(true);
        enableReadAcquisitionTimeAndPeriod(false, false);
        byte[] byteArray = new byte[] { 0, 1, 2, 3, 4, 6 };
        when(ndArrayBase.getNDimensions_RBV()).thenReturn(2);
        when(ndArrayBase.getArraySize0_RBV()).thenReturn(2);
        when(ndArrayBase.getArraySize1_RBV()).thenReturn(3);
        when(ndArrayBase.getArraySize2_RBV()).thenReturn(0);
        when(ndArray.getByteArrayData(Matchers.anyInt())).thenReturn(byteArray);

        NXDetectorData data = (NXDetectorData) det().readout();
        assertEquals("", data.toString());
        //      assertArrayEquals(new Double[] { }, data.getDoubleVals());
        // the behaviour tested here is wrong. The detector declares extraNames, so some value needs to be returned to fulfil the contract
    }

    @Test
    public void testReadoutStats() throws Exception {
        enableArrayReadout(false);
        enableStatsAndCentroid(true, false);
        enableReadAcquisitionTimeAndPeriod(false, false);

        when(ndStats.getMinValue_RBV()).thenReturn(0.);
        when(ndStats.getMaxValue_RBV()).thenReturn(1.);
        when(ndStats.getTotal_RBV()).thenReturn(2.);
        when(ndStats.getNet_RBV()).thenReturn(3.);
        when(ndStats.getMeanValue_RBV()).thenReturn(4.);
        when(ndStats.getSigma_RBV()).thenReturn(5.);
        // private static String[] STATS_NAMES = new String[]{"min", "max", "total", "net", "mean", "sigma"};

        NXDetectorData readout = (NXDetectorData) det().readout();
        assertEquals("0.0000\t1.0000\t2.0000\t3.0000\t4.0000\t5.0000", readout.toString());
        assertArrayEquals(new Double[] { 0., 1., 2., 3., 4., 5. }, readout.getDoubleVals());

        INexusTree rootNode = readout.getNexusTree().getChildNode(0);
        assertEquals("testdet", rootNode.getName());
        assertArrayEquals(new double[] { 0. }, (double[]) rootNode.getChildNode("min", "SDS").getData().getBuffer(),
                .001);
        assertArrayEquals(new double[] { 5. },
                (double[]) rootNode.getChildNode("sigma", "SDS").getData().getBuffer(), .001);
    }

    @Test
    public void testReadoutTimes() throws Exception {
        enableReadAcquisitionTimeAndPeriod(true, true);
        enableArrayReadout(false);
        enableStatsAndCentroid(false, false);

        when(collectionStrategy.getAcquireTime()).thenReturn(0.5);
        when(collectionStrategy.getAcquirePeriod()).thenReturn(0.55);
        NXDetectorData readout = (NXDetectorData) det().readout();
        assertEquals("0.50\t0.55", readout.toString());
        assertArrayEquals(new Double[] { 0.5, 0.55 }, readout.getDoubleVals());

        INexusTree rootNode = readout.getNexusTree().getChildNode(0);
        assertArrayEquals(new double[] { 0.5 },
                (double[]) rootNode.getChildNode("count_time", "SDS").getData().getBuffer(), .001);
        assertArrayEquals(new double[] { 0.55 },
                (double[]) rootNode.getChildNode("period", "SDS").getData().getBuffer(), .001);

    }

    // "CentroidX", "CentroidY", "Centroid_sigmaX", "Centroid_sigmaY", "Centroid_sigmaXY"};
    @Test
    public void testReadoutCentroid() throws Exception {
        enableArrayReadout(false);
        enableStatsAndCentroid(false, true);
        enableReadAcquisitionTimeAndPeriod(false, false);
        when(ndStats.getCentroidX_RBV()).thenReturn(0.);
        when(ndStats.getCentroidY_RBV()).thenReturn(1.);
        when(ndStats.getSigmaX_RBV()).thenReturn(2.);
        when(ndStats.getSigmaY_RBV()).thenReturn(3.);
        when(ndStats.getSigmaXY_RBV()).thenReturn(4.);

        NXDetectorData readout = (NXDetectorData) det().readout();
        assertEquals("0.0000\t1.0000\t2.0000\t3.0000\t4.0000", readout.toString());
        assertArrayEquals(new Double[] { 0., 1., 2., 3., 4. }, readout.getDoubleVals());

        INexusTree rootNode = readout.getNexusTree().getChildNode(0);
        assertEquals("testdet", rootNode.getName());
        assertArrayEquals(new double[] { 0. },
                (double[]) rootNode.getChildNode("centroidX", "SDS").getData().getBuffer(), .001);
        assertArrayEquals(new double[] { 4. },
                (double[]) rootNode.getChildNode("centroid_sigmaXY", "SDS").getData().getBuffer(), .001);
        assertArrayEquals(new double[] { 4. },
                (double[]) rootNode.getChildNode("centroid_sigmaXY", "SDS").getData().getBuffer(), .001);
    }

    @Test
    public void testReadoutWithFilename() throws Exception {
        enableArrayReadout(false);
        enableStatsAndCentroid(false, false);
        enableReadAcquisitionTimeAndPeriod(false, false);
        enableFileWriter(true);

        when(fileWriter.getFullFileName()).thenReturn("/full/path/to/file99.cbf");
        det().atScanStart();
        NXDetectorData readout = (NXDetectorData) det().readout();
        Double[] doubleVals = readout.getDoubleVals();
        assertArrayEquals(new Double[] { 0.0 }, doubleVals);
        assertEquals("/full/path/to/file99.cbf", readout.toString());
        INexusTree rootNode = readout.getNexusTree().getChildNode(0);
        assertEquals("testdet", rootNode.getName());
        String actualPath = ((String[]) rootNode.getChildNode("data_file", "NXnote")
                .getChildNode("file_name", "SDS").getData().getBuffer())[0];
        assertEquals("/full/path/to/file99.cbf", actualPath.trim()); // trim gets rid of the internal null bytes from
        // actualString
    }

    @Test
    public void testReadoutWithFilenameAndTimes() throws Exception {
        setupForReadoutAndGetPositionWithFilenameAndTimes();
        det().atScanStart();
        NXDetectorData readout = (NXDetectorData) det().readout();
        assertArrayEquals(new String[] { "count_time", "period", "filepath" }, readout.getExtraNames());
        assertArrayEquals(new Double[] { 0.5, 0.55, 0.0 }, readout.getDoubleVals());
        assertEquals("0.50\t0.55\t/full/path/to/file99.cbf", readout.toString());
    }

    protected void setupForReadoutAndGetPositionWithFilenameAndTimes() throws Exception {
        enableReadAcquisitionTimeAndPeriod(true, true);
        enableArrayReadout(false);
        enableStatsAndCentroid(false, false);
        enableFileWriter(true);

        when(fileWriter.getFullFileName()).thenReturn("/full/path/to/file99.cbf");

        when(collectionStrategy.getAcquireTime()).thenReturn(0.5);
        when(collectionStrategy.getAcquirePeriod()).thenReturn(0.55);
    }

    protected void checkReadoutWithFilenameAndTimes(NXDetectorData readout, String pathname) {
        INexusTree rootNode = readout.getNexusTree().getChildNode(0);
        assertArrayEquals(new double[] { 0.5 },
                (double[]) rootNode.getChildNode("count_time", "SDS").getData().getBuffer(), .001);
        assertArrayEquals(new double[] { 0.55 },
                (double[]) rootNode.getChildNode("period", "SDS").getData().getBuffer(), .001);
        String actualPath = new String((byte[]) rootNode.getChildNode("data_file", "NXnote")
                .getChildNode("file_name", "SDS").getData().getBuffer());
        assertEquals(pathname, actualPath.trim()); // trim gets rid of the internal null bytes from
    }

    @Test
    public void testStop() throws Exception {
        det().stop();
        verify(collectionStrategy).stop();

    }
}