All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.eclipse.dawnsci.nexus.NexusScanInfo Maven / Gradle / Ivy

/*-
 *******************************************************************************
 * Copyright (c) 2011, 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
 *
 * Contributors:
 *    Matthew Gerring - initial API and implementation and/or initial documentation
 *******************************************************************************/
package org.eclipse.dawnsci.nexus;

import static org.eclipse.dawnsci.nexus.NexusScanInfo.NexusRole.PER_POINT;
import static org.eclipse.dawnsci.nexus.NexusScanInfo.NexusRole.PER_SCAN;
import static org.eclipse.dawnsci.nexus.NexusScanInfo.ScanRole.MONITOR_PER_SCAN;

import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.eclipse.january.dataset.ILazyWriteableDataset;
import org.eclipse.january.dataset.SliceND;

/**
 * 
 * This class represents information about the scan which the NeXus device is running in.
 * 
 * For instance, names of scannables in the axes and the rank of the scan.
 * 
 * TODO mattd 2017-02-28: should this class be removed and we use ScanInformation / ScanModel instead?
 * 
 * @author Matthew Gerring
 *
 */
public class NexusScanInfo {
	
	public static enum NexusRole {
		PER_POINT, PER_SCAN
	}
	
	public static enum ScanRole {
		DETECTOR(PER_POINT),
		SCANNABLE(PER_POINT),
		MONITOR_PER_POINT(PER_POINT),
		MONITOR_PER_SCAN(PER_SCAN),
		NONE(PER_SCAN);
		
		private final NexusRole nexusRole;
		
		private ScanRole(NexusRole nexusRole) {
			this.nexusRole = nexusRole;
		}
		
		public NexusRole getNexusRole() {
			return nexusRole;
		}
		
	}
	
	private int rank;
	
	private final Map> deviceNames;
	
	private int[] shape;
	
	private String filePath;
	
	public NexusScanInfo() {
		this(Collections.emptyList());
	}
	
	/**
	 * 
	 * @param axisNames must be ordered correctly into indices
	 */
	public NexusScanInfo(List axisNames) {
		super();
		deviceNames = new EnumMap<>(ScanRole.class);
		deviceNames.put(ScanRole.SCANNABLE, axisNames);
		this.rank = 1;
	}
	
	public int getRank() {
		return rank;
	}
	
	public void setRank(int rank) {
		this.rank = rank;
	}
	
	private void setDeviceNames(ScanRole scanRole, Collection names) {
		// private so that we can ensure the correct type of collection for the role
		// e.g. List for Scannables
		deviceNames.put(scanRole, names);
	}
	
	public Collection getDeviceNames(ScanRole scanRole) {
		Collection names = deviceNames.get(scanRole);
		return names == null ? Collections.emptyList() : names;
	}
	
	public void setDetectorNames(Set detectorNames) {
		setDeviceNames(ScanRole.DETECTOR, detectorNames);
	}
	
	public Collection getDetectorNames() {
		return getDeviceNames(ScanRole.DETECTOR);
	}

	public List getScannableNames() {
		return (List) getDeviceNames(ScanRole.SCANNABLE);
	}
	
	public void setScannableNames(List axisNames) {
		setDeviceNames(ScanRole.SCANNABLE, axisNames);
	}
	
	public Set getPerPointMonitorNames() {
		return (Set) getDeviceNames(ScanRole.MONITOR_PER_POINT);
	}
	
	public void setPerPointMonitorNames(Set monitorNames) {
		setDeviceNames(ScanRole.MONITOR_PER_POINT, monitorNames);
	}
	
	public Set getPerScanMonitorNames() {
		return (Set) getDeviceNames(ScanRole.MONITOR_PER_SCAN);
	}
	
	public void setPerScanMonitorNames(Set metadataScannableNames) {
		setDeviceNames(ScanRole.MONITOR_PER_SCAN, metadataScannableNames);
	}
	
	public String getFilePath() {
		return filePath;
	}

	public void setFilePath(String filePath) {
		this.filePath = filePath;
	}

	public int[] getShape() {
		return shape;
	}

	public void setShape(int[] shape) {
		this.shape = shape;
	}

	/**
	 * Returns the {@link ScanRole} of the device with the given name within the scan. If the device
	 * is not in the scan {@link ScanRole#NONE} is returned.
	 * @param name name of device
	 * @return role or device within scan, never null
	 */
	public ScanRole getScanRole(String name) {
		for (ScanRole scanRole : deviceNames.keySet()) {
			Collection names = deviceNames.get(scanRole);
			if (names != null && names.contains(name)) {
				return scanRole;
			}
		}
		
		return ScanRole.NONE;
	}
	
	/**
	 * Returns whether the device with the given name should write its data
	 * once for the whole scan, or 
	 * @param name
	 * @return
	 */
	public boolean writeDataPerScan(String name) {
		final ScanRole scanRole = getScanRole(name);
		return scanRole == null || scanRole == MONITOR_PER_SCAN;
	}
	
	public int[] createChunk(int... datashape) {
		return createChunk(true, datashape);
	}

	/**
	 * Attempts to make a chunk size from the scan.
	 * NOTE This assumes that the datashape is a resonable size currently.
	 * If the datashape is small, the chunking can become too small to usefully
	 * read.
	 * 
	 * @param datashape
	 * @return the suggested chunk array
	 */
	public int[] createChunk(boolean append, int... datashape) {
		// Create chunk array of correct length
		final int[] chunk = append ? new int[rank+datashape.length] : new int[rank];

		// Initialise the array to all 1
		// TODO this is slightly redundant but ensures no zeros can ever be allowed through
		Arrays.fill(chunk, 1);

		// Change end of chunk array to match datashape
		int index = 0;
		for (int i = datashape.length; i>0; i--) {
			chunk[chunk.length-i] = datashape[index];
			index++;
		}
		return chunk;
	}
	

	/**
	 * Create a location for a slice of data from the list (correctly ordered) of
	 * scan names and thier relative indices. This information is available from the 
	 * IPosition which is sent into the device during the scan.
	 * 
	 * @param context LazyDataset we are writing to 
	 * @param names available from the IPosition for instance
	 * @param indices available from the IPosition for instance
	 * @param datashape shape of data that the device is adding to the nD stack
	 * @return
	 */
	@Deprecated
	public static SliceND createLocation(ILazyWriteableDataset context, Collection names, Map indices, int... datashape) {
		throw new IllegalArgumentException("Please use IScanRankService to determine the correct slice information during a scan!");
	}

	@Override
	public String toString() {
		return "NexusScanInfo [rank=" + rank + ", axisNames=" + getScannableNames() + "]";
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy