private IRunnableDevice<ScanModel> createGridScan( final IRunnableDevice<?> detector, List<ScanMetadata> scanMetadata, int... size) throws Exception { // Create scan points for a grid and make a generator GridModel gmodel = new GridModel(); gmodel.setFastAxisName("xNex"); gmodel.setFastAxisPoints(size[size.length - 1]); gmodel.setSlowAxisName("yNex"); gmodel.setSlowAxisPoints(size[size.length - 2]); gmodel.setBoundingBox(new BoundingBox(0, 0, 3, 3)); IPointGenerator<?> gen = gservice.createGenerator(gmodel); // We add the outer scans, if any if (size.length > 2) { for (int dim = size.length - 3; dim > -1; dim--) { final StepModel model; if (size[dim] - 1 > 0) { model = new StepModel("neXusScannable" + (dim + 1), 10, 20, 9.99d / (size[dim] - 1)); } else { model = new StepModel( "neXusScannable" + (dim + 1), 10, 20, 30); // Will generate one value at 10 } final IPointGenerator<?> step = gservice.createGenerator(model); gen = gservice.createCompoundGenerator(step, gen); } } // Create the model for a scan. final ScanModel smodel = new ScanModel(); smodel.setPositionIterable(gen); smodel.setDetectors(detector); smodel.setScanMetadata(scanMetadata); // Create a file to scan into. smodel.setFilePath(output.getAbsolutePath()); System.out.println("File writing to " + smodel.getFilePath()); // Create a scan and run it without publishing events IRunnableDevice<ScanModel> scanner = dservice.createRunnableDevice(smodel, null); final IPointGenerator<?> fgen = gen; ((IRunnableEventDevice<ScanModel>) scanner) .addRunListener( new IRunListener() { @Override public void runWillPerform(RunEvent evt) throws ScanningException { try { System.out.println("Running acquisition scan of size " + fgen.size()); } catch (GeneratorException e) { throw new ScanningException(e); } } }); return scanner; }
private void checkNexusFile( IRunnableDevice<ScanModel> scanner, List<ScanMetadata> scanMetadata, int... sizes) throws Exception { final ScanModel scanModel = ((AbstractRunnableDevice<ScanModel>) scanner).getModel(); assertEquals(DeviceState.READY, scanner.getDeviceState()); NXroot rootNode = getNexusRoot(scanner); NXentry entry = rootNode.getEntry(); checkMetadata(entry, scanMetadata); // check that the scan points have been written correctly assertScanPointsGroup(entry, sizes); NXinstrument instrument = entry.getInstrument(); LinkedHashMap<String, List<String>> signalFieldAxes = new LinkedHashMap<>(); // axis for additional dimensions of a datafield, e.g. image signalFieldAxes.put(NXdetector.NX_DATA, Arrays.asList("real", "imaginary")); signalFieldAxes.put("spectrum", Arrays.asList("spectrum_axis")); signalFieldAxes.put("value", Collections.emptyList()); String detectorName = scanModel.getDetectors().get(0).getName(); NXdetector detector = instrument.getDetector(detectorName); // map of detector data field to name of nxData group where that field // is the @signal field Map<String, String> expectedDataGroupNames = signalFieldAxes .keySet() .stream() .collect( Collectors.toMap( Function.identity(), x -> detectorName + (x.equals(NXdetector.NX_DATA) ? "" : "_" + x))); // validate the main NXdata generated by the NexusDataBuilder Map<String, NXdata> nxDataGroups = entry.getChildren(NXdata.class); assertEquals(signalFieldAxes.size(), nxDataGroups.size()); assertTrue(nxDataGroups.keySet().containsAll(expectedDataGroupNames.values())); for (String nxDataGroupName : nxDataGroups.keySet()) { NXdata nxData = entry.getData(nxDataGroupName); String sourceFieldName = nxDataGroupName.equals(detectorName) ? NXdetector.NX_DATA : nxDataGroupName.substring(nxDataGroupName.indexOf('_') + 1); assertSignal(nxData, sourceFieldName); // check the nxData's signal field is a link to the appropriate source data node of the // detector DataNode dataNode = detector.getDataNode(sourceFieldName); IDataset dataset = dataNode.getDataset().getSlice(); assertSame(dataNode, nxData.getDataNode(sourceFieldName)); assertTarget( nxData, sourceFieldName, rootNode, "/entry/instrument/" + detectorName + "/" + sourceFieldName); // check that the other primary data fields of the detector haven't been added to this NXdata for (String primaryDataFieldName : signalFieldAxes.keySet()) { if (!primaryDataFieldName.equals(sourceFieldName)) { assertNull(nxData.getDataNode(primaryDataFieldName)); } } int[] shape = dataset.getShape(); for (int i = 0; i < sizes.length; i++) assertEquals(sizes[i], shape[i]); // Make sure none of the numbers are NaNs. The detector // is expected to fill this scan with non-nulls. final PositionIterator it = new PositionIterator(shape); while (it.hasNext()) { int[] next = it.getPos(); assertFalse(Double.isNaN(dataset.getDouble(next))); } // Check axes final IPosition pos = scanModel.getPositionIterable().iterator().next(); final Collection<String> scannableNames = pos.getNames(); // Append _value_demand to each name in list, then add detector axis fields to result List<String> expectedAxesNames = Stream.concat( scannableNames.stream().map(x -> x + "_value_set"), signalFieldAxes.get(sourceFieldName).stream()) .collect(Collectors.toList()); assertAxes(nxData, expectedAxesNames.toArray(new String[expectedAxesNames.size()])); int[] defaultDimensionMappings = IntStream.range(0, sizes.length).toArray(); int i = -1; for (String scannableName : scannableNames) { i++; NXpositioner positioner = instrument.getPositioner(scannableName); assertNotNull(positioner); dataNode = positioner.getDataNode("value_set"); dataset = dataNode.getDataset().getSlice(); shape = dataset.getShape(); assertEquals(1, shape.length); assertEquals(sizes[i], shape[0]); String nxDataFieldName = scannableName + "_value_set"; assertSame(dataNode, nxData.getDataNode(nxDataFieldName)); assertIndices(nxData, nxDataFieldName, i); assertTarget( nxData, nxDataFieldName, rootNode, "/entry/instrument/" + scannableName + "/value_set"); // Actual values should be scanD dataNode = positioner.getDataNode(NXpositioner.NX_VALUE); dataset = dataNode.getDataset().getSlice(); shape = dataset.getShape(); assertArrayEquals(sizes, shape); nxDataFieldName = scannableName + "_" + NXpositioner.NX_VALUE; assertSame(dataNode, nxData.getDataNode(nxDataFieldName)); assertIndices(nxData, nxDataFieldName, defaultDimensionMappings); assertTarget( nxData, nxDataFieldName, rootNode, "/entry/instrument/" + scannableName + "/" + NXpositioner.NX_VALUE); } } }