Java tutorial
/* * 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.rcp.editors; import java.io.File; import java.io.Serializable; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import java.util.SortedMap; import java.util.TreeMap; import org.apache.commons.math3.util.MultidimensionalCounter; import org.eclipse.core.resources.IFile; import org.eclipse.core.runtime.IConfigurationElement; import org.eclipse.core.runtime.IExtensionPoint; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.PlatformObject; import org.eclipse.dawnsci.analysis.api.dataset.IDataset; import org.eclipse.dawnsci.analysis.api.dataset.ILazyDataset; import org.eclipse.dawnsci.analysis.api.dataset.IMetadataProvider; import org.eclipse.dawnsci.analysis.api.dataset.SliceND; import org.eclipse.dawnsci.analysis.api.io.IDataHolder; import org.eclipse.dawnsci.analysis.api.io.ILazyLoader; import org.eclipse.dawnsci.analysis.api.io.ScanFileHolderException; import org.eclipse.dawnsci.analysis.api.metadata.IMetadata; import org.eclipse.dawnsci.analysis.api.metadata.MetadataType; import org.eclipse.dawnsci.analysis.api.monitor.IMonitor; import org.eclipse.dawnsci.analysis.api.tree.Node; import org.eclipse.dawnsci.analysis.dataset.impl.AbstractDataset; import org.eclipse.dawnsci.analysis.dataset.impl.AggregateDataset; import org.eclipse.dawnsci.analysis.dataset.impl.Dataset; import org.eclipse.dawnsci.analysis.dataset.impl.DatasetFactory; import org.eclipse.dawnsci.analysis.dataset.impl.DatasetUtils; import org.eclipse.dawnsci.analysis.dataset.impl.IndexIterator; import org.eclipse.dawnsci.analysis.dataset.impl.IntegerDataset; import org.eclipse.dawnsci.analysis.dataset.impl.LazyDataset; import org.eclipse.dawnsci.analysis.dataset.impl.Maths; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.viewers.ArrayContentProvider; import org.eclipse.jface.viewers.CellEditor; import org.eclipse.jface.viewers.CellLabelProvider; import org.eclipse.jface.viewers.CheckboxCellEditor; import org.eclipse.jface.viewers.ComboBoxViewerCellEditor; import org.eclipse.jface.viewers.EditingSupport; import org.eclipse.jface.viewers.ICellEditorListener; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.ISelectionProvider; import org.eclipse.jface.viewers.IStructuredContentProvider; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.LabelProvider; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.viewers.TableViewer; import org.eclipse.jface.viewers.TableViewerColumn; import org.eclipse.jface.viewers.TextCellEditor; import org.eclipse.jface.viewers.Viewer; import org.eclipse.jface.viewers.ViewerCell; import org.eclipse.jface.viewers.ViewerDropAdapter; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.SashForm; import org.eclipse.swt.dnd.DND; import org.eclipse.swt.dnd.FileTransfer; import org.eclipse.swt.dnd.Transfer; import org.eclipse.swt.dnd.TransferData; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.FileDialog; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Menu; import org.eclipse.swt.widgets.MenuItem; import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.TableColumn; import org.eclipse.ui.IEditorDescriptor; import org.eclipse.ui.IEditorInput; import org.eclipse.ui.IEditorRegistry; import org.eclipse.ui.IEditorSite; import org.eclipse.ui.IPersistableElement; import org.eclipse.ui.IWorkbenchPartSite; import org.eclipse.ui.PartInitException; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.forms.events.ExpansionAdapter; import org.eclipse.ui.forms.events.ExpansionEvent; import org.eclipse.ui.forms.widgets.ExpandableComposite; import org.eclipse.ui.part.EditorPart; import org.nfunk.jep.JEP; import org.nfunk.jep.ParseException; import org.nfunk.jep.SymbolTable; import org.nfunk.jep.Variable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import uk.ac.diamond.scisoft.analysis.axis.AxisChoice; import uk.ac.diamond.scisoft.analysis.io.AbstractFileLoader; import uk.ac.diamond.scisoft.analysis.io.Utils; import uk.ac.diamond.scisoft.analysis.rcp.AnalysisRCPActivator; import uk.ac.diamond.scisoft.analysis.rcp.explorers.AbstractExplorer; import uk.ac.diamond.scisoft.analysis.rcp.explorers.MetadataSelection; import uk.ac.diamond.scisoft.analysis.rcp.hdf5.HDF5Selection; import uk.ac.diamond.scisoft.analysis.rcp.inspector.AxisSelection; import uk.ac.diamond.scisoft.analysis.rcp.inspector.DatasetSelection; import uk.ac.diamond.scisoft.analysis.rcp.inspector.DatasetSelection.InspectorType; /** * This editor allows a set of files which can be loaded by one type of loader to be compared. It * lets the user select the dataset per file and which (metadata) value(s) to use per dataset. This * selection is pushed onto the dataset inspector. */ public class CompareFilesEditor extends EditorPart implements ISelectionChangedListener, ISelectionProvider { /** * Name of index dataset */ public final static String INDEX = "index"; /** * Factory to create proper input object for this editor * @param sel * @return compare files editor input */ public static IEditorInput createComparesFilesEditorInput(IStructuredSelection sel) { return new CompareFilesEditorInput(sel); } private static final Logger logger = LoggerFactory.getLogger(CompareFilesEditor.class); public final static String ID = "uk.ac.diamond.scisoft.analysis.rcp.editors.CompareFilesEditor"; private SashForm sashComp; private List<SelectedFile> fileList; private List<SelectedNode> expressionList; private SortedMap<String, VariableMapping> variableMap; private TableViewer viewer, expressionViewer, variableViewer; private Class<? extends AbstractExplorer> expClass = null; private AbstractExplorer explorer; private String firstFileName; private boolean useRowIndexAsValue = true; private DatasetSelection currentDatasetSelection; // from explorer private DatasetSelection multipleSelection; // from this editor private TableColumn valueColumn, variableColumn; private FileDialog fileDialog; private String editorName; private CFEditingSupport variableEditor; private final static String VALUE_DEFAULT_TEXT = "Index"; private final static String DEFAULT_EXPRESSION = "a + b"; @Override public void doSave(IProgressMonitor monitor) { } @Override public void doSaveAs() { } @Override public void init(IEditorSite site, IEditorInput input) throws PartInitException { if (!(input instanceof CompareFilesEditorInput)) throw new PartInitException("Invalid input for comparison"); setSite(site); try { setInput(input); } catch (Exception e) { throw new PartInitException("Invalid input for comparison", e); } } @Override @SuppressWarnings({ "unchecked", "rawtypes" }) public void setInput(IEditorInput input) { if (!(input instanceof CompareFilesEditorInput)) { return; } super.setInput(input); CompareFilesEditorInput filesInput = (CompareFilesEditorInput) input; fileList = new ArrayList<SelectedFile>(); expressionList = new ArrayList<SelectedNode>(); variableMap = new TreeMap<String, VariableMapping>(); int n = 0; int l = 0; while (l < filesInput.list.length) { Object o = filesInput.list[l++]; if (o instanceof IFile) { IFile f = (IFile) o; try { fileList.add(new SelectedFile(n, f)); n++; break; } catch (IllegalArgumentException e) { logger.warn("Problem with selection: ", e); } } else if (o instanceof File) { File pf = (File) o; try { fileList.add(new SelectedFile(n, pf)); n++; break; } catch (IllegalArgumentException e) { logger.warn("Problem with selection: ", e); } } } if (n == 0) { // TODO error return; } firstFileName = fileList.get(0).getAbsolutePath(); List<String> eList = getEditorCls(firstFileName); editorName = null; for (String e : eList) { try { Class edClass = Class.forName(e); Method m = edClass.getMethod("getExplorerClass"); editorName = e; expClass = (Class) m.invoke(null); break; } catch (Exception e1) { } } if (expClass == null) { throw new IllegalArgumentException("No explorer available to read " + firstFileName); } while (l < filesInput.list.length) { Object o = filesInput.list[l++]; if (o instanceof IFile) { IFile f = (IFile) o; try { SelectedFile sf = new SelectedFile(n, f); String name = sf.getAbsolutePath(); if (!getEditorCls(name).contains(editorName)) { logger.warn("Editor cannot read file: {}", name); } fileList.add(sf); n++; } catch (IllegalArgumentException e) { logger.warn("Problem with selection: ", e); } } else if (o instanceof File) { File pf = (File) o; try { SelectedFile sf = new SelectedFile(n, pf); String name = sf.getAbsolutePath(); if (!getEditorCls(name).contains(editorName)) { logger.warn("Editor cannot read file: {}", name); } fileList.add(sf); n++; } catch (IllegalArgumentException e) { logger.warn("Problem with selection: ", e); } } } if (n != filesInput.list.length) { // TODO warning } setPartName(input.getToolTipText()); } /** * Add new file to comparison list * @param path * @return true, if file can be added */ public boolean addFile(String path) { return addFile(path, getNewIndex()); } /** * Add new file to comparison list at index * @param path * @param index * @return true, if file can be added */ private boolean addFile(String path, int index) { if (path == null) { return false; } SelectedFile sf = createSelectedFile(path); if (sf == null) { return false; } if (index == 0) { logger.warn("Cannot add file to top of order"); index = 1; } sf.setIndex(index); fileList.add(sf); if (currentDatasetSelection != null) { changeSelection(); } else { viewer.refresh(); } return true; } private SelectedFile createSelectedFile(String path) { try { SelectedFile sf = new SelectedFile(fileList.size(), path); String name = sf.getAbsolutePath(); if (!getEditorCls(name).contains(editorName)) { logger.warn("Editor cannot read file: {}", name); return null; } return sf; } catch (IllegalArgumentException e) { logger.warn("Problem with new file: ", e); return null; } } /** * call to bring up a file dialog */ public void addFileUsingFileDialog() { if (fileDialog == null) { fileDialog = new FileDialog(getSite().getShell(), SWT.OPEN); } final String path = fileDialog.open(); if (path != null) { addFile(path); } } @Override public boolean isDirty() { return false; } @Override public boolean isSaveAsAllowed() { return false; } @Override public void dispose() { explorer.dispose(); sashComp.dispose(); viewer.getControl().dispose(); expressionViewer.getControl().dispose(); variableViewer.getControl().dispose(); super.dispose(); } private enum Column { TICK, COMBO, PATH, VALUE, EXPRESSION, VARIABLE; } private class TickLabelProvider extends CellLabelProvider { private final Image TICK = AnalysisRCPActivator.getImageDescriptor("icons/tick.png").createImage(); private Display display; public TickLabelProvider(Display display) { this.display = display; } @Override public void update(ViewerCell cell) { Object obj = cell.getElement(); if (obj instanceof SelectedObject) { SelectedObject sf = (SelectedObject) obj; if (sf.doUse()) { cell.setImage(TICK); } else { cell.setImage(null); } Color colour = null; if (currentDatasetSelection != null && (!sf.hasData() || !sf.isDataOK())) { colour = display.getSystemColor(SWT.COLOR_YELLOW); } cell.setBackground(colour); } } } private class VariableLabelProvider extends CellLabelProvider { @Override public void update(ViewerCell cell) { Object element = cell.getElement(); if (element instanceof SelectedFile) { SelectedFile sf = (SelectedFile) element; String var = sf.getVariableName(); if (var != null) { cell.setText(var); } } } } private static class PathLabelProvider extends CellLabelProvider { private Display display; public PathLabelProvider(Display display) { this.display = display; } @Override public void update(ViewerCell cell) { SelectedFile sf = (SelectedFile) cell.getElement(); String path = sf.getAbsolutePath(); if (path != null) { cell.setText(new File(path).getName()); } cell.setForeground(sf.doUse() ? null : display.getSystemColor(SWT.COLOR_GRAY)); } } private class ValueLabelProvider extends CellLabelProvider { private Display display; public ValueLabelProvider(Display display) { this.display = display; } @Override public void update(ViewerCell cell) { SelectedObject sf = (SelectedObject) cell.getElement(); Color colour = null; if (useRowIndexAsValue) { cell.setText(String.valueOf(sf.getIndex())); } else { cell.setText(sf.toString()); if (!sf.hasMetadataValue()) { colour = display.getSystemColor(SWT.COLOR_YELLOW); } } cell.setBackground(colour); cell.setForeground(sf.doUse() ? null : display.getSystemColor(SWT.COLOR_GRAY)); } } private class ExpressionLabelProvider extends CellLabelProvider { @Override public void update(ViewerCell cell) { SelectedNode expr = (SelectedNode) cell.getElement(); cell.setText(expr.toString()); } } private class VariableNameLabelProvider extends CellLabelProvider { @Override public void update(ViewerCell cell) { VariableMapping var = (VariableMapping) cell.getElement(); cell.setText(var.getName()); } } private class ComboLabelProvider extends CellLabelProvider { @Override public void update(ViewerCell cell) { VariableMapping vm = (VariableMapping) cell.getElement(); cell.setText(vm.getMathOp().name()); } } private class IndexLabelProvider extends CellLabelProvider { @Override public void update(ViewerCell cell) { VariableMapping var = (VariableMapping) cell.getElement(); String name = var.getName(); List<String> idx = new ArrayList<String>(); if (variableMap.containsKey(name)) { VariableMapping vm = variableMap.get(name); for (SelectedObject obj : vm.getDatasets()) { idx.add(String.valueOf(obj.getIndex())); } } Collections.sort(idx); cell.setText(idx.toString()); } } private class FileSelection extends StructuredSelection implements IMetadataProvider { private IMetadata metadata = null; public FileSelection(SelectedFile f) { super(f.f); if (!f.hasDataHolder()) { try { IDataHolder holder = explorer.loadFile(f.getAbsolutePath(), null); if (holder != null) { f.setDataHolder(holder); } } catch (Exception e) { } } if (f.hasMetadata()) { metadata = f.m; } } @Override public IMetadata getMetadata() throws Exception { return metadata; } @SuppressWarnings("unchecked") @Override public <T extends MetadataType> List<T> getMetadata(Class<T> clazz) throws Exception { if (IMetadata.class.isAssignableFrom(clazz)) { List<T> result = new ArrayList<T>(); result.add((T) getMetadata()); return result; } throw new UnsupportedOperationException( "getMetadata(clazz) does not currently support anything other than IMetadata"); // If it should only support this, simply return null here, otherwise implement the method fully } } @Override public void createPartControl(Composite parent) { Display display = parent.getDisplay(); sashComp = new SashForm(parent, SWT.VERTICAL); sashComp.setLayout(new FillLayout(SWT.VERTICAL)); try { explorer = expClass .getConstructor(Composite.class, IWorkbenchPartSite.class, ISelectionChangedListener.class) .newInstance(sashComp, getSite(), this); } catch (Exception e) { throw new IllegalArgumentException("Cannot make explorer", e); } try { explorer.loadFileAndDisplay(firstFileName, null); } catch (Exception e) { throw new IllegalArgumentException("Explorer cannot load file", e); } final ExpandableComposite viewerComp = new ExpandableComposite(sashComp, SWT.BORDER); viewerComp.setText("Datasets"); viewerComp.setToolTipText("List of selected datasets"); viewerComp.setLayout(new FillLayout()); final Composite vg = new Composite(viewerComp, SWT.NONE); vg.setLayout(new FillLayout()); viewer = new TableViewer(vg, SWT.V_SCROLL); viewer.addSelectionChangedListener(new ISelectionChangedListener() { @Override public void selectionChanged(SelectionChangedEvent event) { // inform metadata table view of currently selected file ISelection is = event.getSelection(); if (is instanceof StructuredSelection) { Object e = ((StructuredSelection) is).getFirstElement(); if (e instanceof SelectedFile) { SelectedFile f = (SelectedFile) e; setSelection(new FileSelection(f)); } } } }); TableViewerColumn tVCol; TableColumn tCol; tVCol = new TableViewerColumn(viewer, SWT.CENTER); tCol = tVCol.getColumn(); tCol.setText("Use"); tCol.setToolTipText( "Toggle to use in dataset inspector (a yellow background indicates a missing or incompatible dataset)"); tCol.setWidth(40); tCol.setMoveable(false); tVCol.setEditingSupport(new CFEditingSupport(viewer, Column.TICK, null)); tVCol.setLabelProvider(new TickLabelProvider(display)); tVCol = new TableViewerColumn(viewer, SWT.CENTER); valueColumn = tVCol.getColumn(); valueColumn.setText(VALUE_DEFAULT_TEXT); valueColumn.setToolTipText("Value of resource (a yellow background indicates a missing value)"); valueColumn.setWidth(40); valueColumn.setMoveable(false); tVCol.setEditingSupport(new CFEditingSupport(viewer, Column.VALUE, null)); tVCol.setLabelProvider(new ValueLabelProvider(display)); tVCol = new TableViewerColumn(viewer, SWT.CENTER); tCol = tVCol.getColumn(); tCol.setText("Var"); tCol.setToolTipText("Select mathematical operation to apply on this file"); tCol.setWidth(150); tCol.setMoveable(false); variableEditor = new CFEditingSupport(viewer, Column.VARIABLE, null); tVCol.setEditingSupport(variableEditor); tVCol.setLabelProvider(new VariableLabelProvider()); tVCol = new TableViewerColumn(viewer, SWT.LEFT); tCol = tVCol.getColumn(); tCol.setText("File name"); tCol.setToolTipText("Name of resource"); tCol.setWidth(100); tCol.setMoveable(false); tVCol.setEditingSupport(new CFEditingSupport(viewer, Column.PATH, null)); tVCol.setLabelProvider(new PathLabelProvider(display)); viewer.setContentProvider(new IStructuredContentProvider() { @Override public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { } @Override public void dispose() { } @Override public Object[] getElements(Object inputElement) { return fileList == null ? null : fileList.toArray(); } }); // drop support viewer.addDropSupport(DND.DROP_COPY | DND.DROP_MOVE, new Transfer[] { FileTransfer.getInstance() }, new CFDropAdapter(viewer)); // add context menus final Table table = viewer.getTable(); table.setHeaderVisible(true); final Menu headerMenu = new Menu(sashComp.getShell(), SWT.POP_UP); headerMenu.addListener(SWT.Show, new Listener() { @Override public void handleEvent(Event event) { // get selection and decide for (MenuItem m : headerMenu.getItems()) { m.setEnabled(!useRowIndexAsValue); } } }); MenuItem item = new MenuItem(headerMenu, SWT.PUSH); item.setText("Use row index as value"); item.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event event) { useRowIndexAsValue = true; valueColumn.setText(VALUE_DEFAULT_TEXT); viewer.refresh(); changeSelection(); } }); table.setMenu(headerMenu); final Menu tableMenu = null; table.addListener(SWT.MenuDetect, new Listener() { @Override public void handleEvent(Event event) { Point pt = sashComp.getDisplay().map(null, table, new Point(event.x, event.y)); Rectangle clientArea = table.getClientArea(); boolean header = clientArea.y <= pt.y && pt.y < (clientArea.y + table.getHeaderHeight()); table.setMenu(header ? headerMenu : tableMenu); } }); if (fileList != null) { viewer.setInput(fileList); for (TableColumn tc : viewer.getTable().getColumns()) { tc.pack(); } } viewerComp.setClient(vg); viewerComp.setExpanded(true); viewerComp.addExpansionListener(new ExpansionAdapter() { @Override public void expansionStateChanged(ExpansionEvent e) { sashComp.layout(); } }); ExpandableComposite expComp = new ExpandableComposite(sashComp, SWT.BORDER); expComp.setText("Mathematical Expressions"); expComp.setToolTipText("Define mathematical expressions using datasets"); expComp.setLayout(new FillLayout()); expComp.addExpansionListener(new ExpansionAdapter() { @Override public void expansionStateChanged(ExpansionEvent e) { sashComp.layout(); } }); { Composite g = new Composite(expComp, SWT.NONE); g.setLayout(new FillLayout()); createExpressionTable(g, display); expComp.setClient(g); expComp.setExpanded(false); } ExpandableComposite varComp = new ExpandableComposite(sashComp, SWT.BORDER); varComp.setText("Variable Assignments"); varComp.setToolTipText("List of dataset indecies assigned to every variable"); varComp.setLayout(new FillLayout()); varComp.addExpansionListener(new ExpansionAdapter() { @Override public void expansionStateChanged(ExpansionEvent e) { sashComp.layout(); } }); { Composite g = new Composite(varComp, SWT.NONE); g.setLayout(new FillLayout()); createVariableTable(g); varComp.setClient(g); varComp.setExpanded(false); } sashComp.setWeights(new int[] { 5, 1, 1, 1 }); explorer.addSelectionChangedListener(this); getSite().setSelectionProvider(this); } private void createExpressionTable(Composite g, Display display) { expressionViewer = new TableViewer(g, SWT.V_SCROLL); TableViewerColumn tVCol; TableColumn tCol; tVCol = new TableViewerColumn(expressionViewer, SWT.CENTER); tCol = tVCol.getColumn(); tCol.setText("Use"); tCol.setToolTipText( "Toggle to use in dataset inspector (a yellow background indicates a missing or incompatible dataset)"); tCol.setWidth(40); tCol.setMoveable(false); tVCol.setEditingSupport(new CFEditingSupport(expressionViewer, Column.TICK, null)); tVCol.setLabelProvider(new TickLabelProvider(display)); tVCol = new TableViewerColumn(expressionViewer, SWT.CENTER); tCol = tVCol.getColumn(); tCol.setText(VALUE_DEFAULT_TEXT); tCol.setToolTipText("Value of resource (a yellow background indicates a missing value)"); tCol.setWidth(40); tCol.setMoveable(false); tVCol.setLabelProvider(new ValueLabelProvider(display)); tVCol = new TableViewerColumn(expressionViewer, SWT.LEFT); tCol = tVCol.getColumn(); tCol.setText("Expression"); tCol.setToolTipText("Mathematical exprossion evaluated on the input data"); tCol.setWidth(250); tCol.setMoveable(false); tVCol.setEditingSupport(new CFEditingSupport(expressionViewer, Column.EXPRESSION, null)); tVCol.setLabelProvider(new ExpressionLabelProvider()); final Table table = expressionViewer.getTable(); table.setHeaderVisible(true); final Menu exprMenu = new Menu(expressionViewer.getControl().getShell(), SWT.POP_UP); MenuItem item = new MenuItem(exprMenu, SWT.PUSH); item.setText("Add new expression"); item.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event event) { expressionList.add(new SelectedNode(getNewIndex(), DEFAULT_EXPRESSION)); updateVariableMappings(); expressionViewer.refresh(); } }); table.setMenu(exprMenu); expressionViewer.setContentProvider(ArrayContentProvider.getInstance()); expressionViewer.setInput(expressionList); } private void createVariableTable(Composite g) { variableViewer = new TableViewer(g, SWT.V_SCROLL); TableViewerColumn tVCol; TableColumn tCol; tVCol = new TableViewerColumn(variableViewer, SWT.CENTER); variableColumn = tVCol.getColumn(); variableColumn.setText("Var"); variableColumn.setToolTipText("Value of resource (a yellow background indicates a missing value)"); variableColumn.setWidth(40); variableColumn.setMoveable(false); tVCol.setLabelProvider(new VariableNameLabelProvider()); tVCol = new TableViewerColumn(variableViewer, SWT.CENTER); tCol = tVCol.getColumn(); tCol.setText("Math"); tCol.setToolTipText("Select mathematical operation to apply on this file"); tCol.setWidth(150); tCol.setMoveable(false); tVCol.setEditingSupport(new CFEditingSupport(variableViewer, Column.COMBO, null)); tVCol.setLabelProvider(new ComboLabelProvider()); tVCol = new TableViewerColumn(variableViewer, SWT.LEFT); tCol = tVCol.getColumn(); tCol.setText("Indices"); tCol.setToolTipText("List of indicies of datasets mapped to this variable"); tCol.setWidth(150); tCol.setMoveable(false); tVCol.setLabelProvider(new IndexLabelProvider()); final Table table = variableViewer.getTable(); table.setHeaderVisible(true); variableViewer.setContentProvider(ArrayContentProvider.getInstance()); variableViewer.setInput(variableMap.values()); } private void changeSelection() { if (currentDatasetSelection != null) { selectionChanged(new SelectionChangedEvent(this, currentDatasetSelection)); } } /** * Generate new index values from current list of included files and expressions * @return New index equal to the maximum index incremented by one */ private int getNewIndex() { List<Integer> idxList = new ArrayList<Integer>(); for (SelectedObject obj : fileList) { idxList.add(obj.getIndex()); } for (SelectedObject obj : expressionList) { idxList.add(obj.getIndex()); } int idxNew = Collections.max(idxList) + 1; return idxNew; } final private class CFDropAdapter extends ViewerDropAdapter { protected CFDropAdapter(Viewer viewer) { super(viewer); } @Override public boolean performDrop(Object data) { // find position SelectedFile file = (SelectedFile) getCurrentTarget(); int index = file == null ? 0 : fileList.indexOf(file); if (index < 0) { index = fileList.size(); } String[] files = (String[]) data; boolean ok = true; for (String f : files) { ok |= addFile(f, getNewIndex()); } return ok; } @Override public boolean validateDrop(Object target, int operation, TransferData transferType) { return FileTransfer.getInstance().isSupportedType(transferType); } } final private class CFEditingSupport extends EditingSupport { private CellEditor editor = null; private Column column; public CFEditingSupport(TableViewer viewer, Column column, ICellEditorListener listener) { super(viewer); if (column == Column.TICK) { editor = new CheckboxCellEditor(viewer.getTable(), SWT.CHECK); if (listener != null) { editor.addListener(listener); } } if (column == Column.COMBO) { editor = new ComboBoxViewerCellEditor(viewer.getTable(), SWT.READ_ONLY); ((ComboBoxViewerCellEditor) editor).setLabelProvider(new LabelProvider()); ((ComboBoxViewerCellEditor) editor).setContentProvider(new ArrayContentProvider()); ((ComboBoxViewerCellEditor) editor).setInput(MathOp.values()); if (listener != null) { editor.addListener(listener); } } if (column == Column.VARIABLE) { editor = new ComboBoxViewerCellEditor(viewer.getTable(), SWT.READ_ONLY); ((ComboBoxViewerCellEditor) editor).setLabelProvider(new LabelProvider()); ((ComboBoxViewerCellEditor) editor).setContentProvider(new ArrayContentProvider()); if (listener != null) { editor.addListener(listener); } } if (column == Column.EXPRESSION) { editor = new TextCellEditor(viewer.getTable()); if (listener != null) { editor.addListener(listener); } } this.column = column; } @Override protected boolean canEdit(Object element) { return ((column == Column.TICK) || (column == Column.COMBO) || (column == Column.VARIABLE) || (column == Column.EXPRESSION)); } @Override protected CellEditor getCellEditor(Object element) { return editor; } @SuppressWarnings("unchecked") @Override protected Object getValue(Object element) { if (element instanceof SelectedObject) { SelectedObject so = (SelectedObject) element; if (column == Column.TICK) { return so.doUse(); } } if (element instanceof SelectedFile) { SelectedFile sf = (SelectedFile) element; if (column == Column.VARIABLE) { if (expressionList != null) { Set<String> vars = new HashSet<String>(); for (SelectedNode tmp : expressionList) { vars.addAll(tmp.symbolTable.keySet()); } List<String> varList = new ArrayList<String>(vars); Collections.sort(varList); ((ComboBoxViewerCellEditor) variableEditor.getCellEditor(null)).setInput(varList.toArray()); } return sf.getVariableName(); } } if (element instanceof SelectedNode) { if (column == Column.EXPRESSION) { SelectedNode expr = (SelectedNode) element; return expr.toString(); } } if (element instanceof VariableMapping) { VariableMapping vm = (VariableMapping) element; if (column == Column.COMBO) { return vm.getMathOp(); } } return null; } @Override protected void setValue(Object element, Object value) { if (value == null) { return; } if (element instanceof SelectedObject) { SelectedObject so = (SelectedObject) element; if (column == Column.TICK) { so.setUse((Boolean) value); } if (column == Column.VARIABLE) { String variableName = (String) value; so.setVariableName(variableName); updateVariableMappings(); } } if (element instanceof SelectedNode) { if (column == Column.EXPRESSION) { int idx = expressionViewer.getTable().getSelectionIndex(); SelectedNode expr = (SelectedNode) element; expr.setExpression(String.valueOf(value)); expressionList.set(idx, expr); updateVariableMappings(); } } if (element instanceof VariableMapping) { VariableMapping vm = (VariableMapping) element; if (column == Column.COMBO) { vm.setMathOp((MathOp) value); variableMap.get(vm.getName()).setMathOp((MathOp) value); } } getViewer().update(element, null); changeSelection(); } } /** * Loop over all expressions and assign to every variable a set of SelectionObjects associated with it */ @SuppressWarnings("unchecked") private void updateVariableMappings() { List<SelectedFile> selFiles = (List<SelectedFile>) viewer.getInput(); Set<String> varNames = new HashSet<String>(); if (expressionList != null) { for (SelectedNode expr : expressionList) { SymbolTable st = expr.symbolTable; if (st != null) { Iterator<String> itr = st.keySet().iterator(); while (itr.hasNext()) { String varName = itr.next(); Variable var = st.getVar(varName); var.setValue(new HashSet<SelectedObject>()); for (SelectedFile sf : selFiles) { String sfVarName = sf.getVariableName(); if (sfVarName != null && sfVarName.equals(varName)) { ((Set<SelectedObject>) var.getValue()).add(sf); } } varNames.add(varName); } } } } Set<String> oldNames = new HashSet<String>(variableMap.keySet()); for (String oldName : oldNames) { if (!varNames.contains(oldName)) variableMap.remove(oldName); } if (expressionList != null) { for (SelectedNode expr : expressionList) { SymbolTable st = expr.symbolTable; if (st != null) { Iterator<String> itr = st.keySet().iterator(); while (itr.hasNext()) { String varName = itr.next(); Variable var = st.getVar(varName); List<SelectedObject> objList = new ArrayList<SelectedObject>( (Set<SelectedObject>) var.getValue()); VariableMapping newMap = new VariableMapping(varName); newMap.setDatasets(objList); newMap.setMathOp(variableMap.containsKey(varName) ? variableMap.get(varName).getMathOp() : MathOp.IDX); variableMap.put(varName, newMap); } } } } variableViewer.setInput(variableMap.values()); } /** * Get editor classes that can handle given file * @param fileName * @return list of editor class names */ public static List<String> getEditorCls(final String fileName) { IEditorRegistry reg = PlatformUI.getWorkbench().getEditorRegistry(); IEditorDescriptor[] eds = reg.getEditors(fileName); List<String> edId = new ArrayList<String>(); for (IEditorDescriptor e : eds) { if (e.isInternal()) { edId.add(e.getId()); } } List<String> edCls = new ArrayList<String>(); IExtensionPoint ept = Platform.getExtensionRegistry().getExtensionPoint("org.eclipse.ui.editors"); IConfigurationElement[] cs = ept.getConfigurationElements(); for (IConfigurationElement l : cs) { String id = l.getAttribute("id"); String cls = l.getAttribute("class"); if (id != null && cls != null && edId.contains(id)) { edCls.add(cls); } } return edCls; } @Override public void setFocus() { } @Override public void selectionChanged(SelectionChangedEvent e) { ISelection sel = e.getSelection(); // TODO this should be in job/progress service if (sel instanceof MetadataSelection) { final String metaValue = ((MetadataSelection) sel).getPathname(); loadMetaValues(metaValue); useRowIndexAsValue = false; valueColumn.setText(metaValue); } else if (sel instanceof DatasetSelection) { currentDatasetSelection = (DatasetSelection) sel; String name; String node; if (currentDatasetSelection instanceof HDF5Selection) { name = ((HDF5Selection) currentDatasetSelection).getNode(); node = name.substring(0, name.lastIndexOf(Node.SEPARATOR) + 1); } else { name = currentDatasetSelection.getFirstElement().getName(); int i = name.indexOf(AbstractFileLoader.FILEPATH_DATASET_SEPARATOR); if (i >= 0) { name = name.substring(i + 1); } node = null; } logger.debug("Selected data = {}", name); loadDatasets(name); if (useRowIndexAsValue) setMetaValuesAsIndexes(); loadAxisSelections(fileList, currentDatasetSelection.getAxes(), node); loadAxisSelections(expressionList, currentDatasetSelection.getAxes(), node); } else { return; } if (currentDatasetSelection != null) { List<ILazyDataset> dataList = new ArrayList<ILazyDataset>(); List<ILazyDataset> metaList = new ArrayList<ILazyDataset>(); List<List<AxisSelection>> axesList = new ArrayList<List<AxisSelection>>(); for (SelectedFile f : fileList) { if (f.doUse() && f.hasData() && f.hasMetadataValue()) { f.setDataOK(true); // blindly set okay (check later) dataList.addAll(f.getDataset()); metaList.add(f.getMetadataValue()); axesList.add(new ArrayList<AxisSelection>(f.getAxisSelections())); } } boolean extend = true; for (ILazyDataset m : metaList) { // if all metadata is multi-valued then do not extend aggregate shape if (m.getSize() > 1) { extend = false; break; } } if (dataList.size() == 0) { logger.warn("No datasets found or selected"); return; } // squeeze all datasets for (ILazyDataset d : dataList) d.squeezeEnds(); // remove incompatible data int[][] shapes = AggregateDataset.calcShapes(extend, dataList.toArray(new ILazyDataset[0])); int j = shapes.length - 1; int[] s = shapes[0]; final int axis = extend ? 0 : -1; for (int k = fileList.size() - 1; k >= 0 && j > 0; k--) { SelectedFile f = fileList.get(k); if (f.doUse() && f.hasData() && f.hasMetadataValue()) { boolean ok = AbstractDataset.areShapesCompatible(s, shapes[j], axis); f.setDataOK(ok); if (!ok) { dataList.remove(j); metaList.remove(j); axesList.remove(j); } j--; } } // Add datasets calculated from the expressions for (SelectedNode expr : expressionList) { if (expr.doUse() && expr.hasData()) { expr.setDataOK(true); // blindly set okay (check later) List<ILazyDataset> exprData = expr.getDataset(); dataList.addAll(exprData); Iterator<ILazyDataset> itr = exprData.iterator(); while (itr.hasNext()) { metaList.add(expr.getMetadataValue()); axesList.add(new ArrayList<AxisSelection>(expr.getAxisSelections())); itr.next(); } } } //List<ILazyDataset> processedDataList = new ArrayList<ILazyDataset>(); //List<ILazyDataset> processedMetaList = new ArrayList<ILazyDataset>(); //List<List<AxisSelection>> processedAxesList = new ArrayList<List<AxisSelection>>(); //processSelection(dataList, metaList, axesList, mathList, processedDataList, processedMetaList, processedAxesList); InspectorType itype; switch (currentDatasetSelection.getType()) { case IMAGE: itype = InspectorType.IMAGE; break; case LINE: default: itype = InspectorType.LINESTACK; break; } setSelection(createSelection(itype, extend, dataList, metaList, axesList, firstFileName)); } viewer.refresh(); expressionViewer.refresh(); } /** * */ private void setMetaValuesAsIndexes() { for (SelectedFile f : fileList) { f.setMetadataValueAsIndex(); } for (SelectedNode expr : expressionList) { expr.setMetadataValueAsIndex(); } } /** * Load metadata values from selected files */ private void loadMetaValues(String key) { logger.debug("Selected metadata = {}", key); for (SelectedFile f : fileList) { if (!f.hasMetadata() && !f.hasDataHolder()) { try { IDataHolder holder = explorer.loadFile(f.getAbsolutePath(), null); f.setDataHolder(holder); } catch (Exception e) { continue; } } f.setMetadataValue(key); } } /** * Load datasets from selected files */ private void loadDatasets(String key) { for (SelectedFile f : fileList) { if (!f.hasDataHolder()) { try { IDataHolder holder = explorer.loadFile(f.getAbsolutePath(), null); if (holder == null) { continue; } f.setDataHolder(holder); } catch (Exception e) { continue; } } f.setDataset(key); } } /** * Load axis selections from selected files */ @SuppressWarnings("null") private void loadAxisSelections(List<? extends SelectedObject> selectedList, List<AxisSelection> axes, String node) { boolean isFirst = true; List<AxisSelection> laxes = new ArrayList<AxisSelection>(); if (axes != null) { for (AxisSelection as : axes) laxes.add(as.clone()); } for (SelectedObject f : selectedList) { if (f.doUse() && f.hasData() && (useRowIndexAsValue || f.hasMetadataValue())) { if (isFirst) { isFirst = false; f.setAxisSelections(laxes); } else { f.setAxisSelections(makeAxes(laxes, f, node)); } } } // prune missing choices List<String> choices = new ArrayList<String>(); int rank = axes == null ? 0 : axes.size(); for (int i = 0; i < rank; i++) { choices.clear(); choices.addAll(axes.get(i).getNames()); for (SelectedObject f : selectedList) { if (f.hasData()) { AxisSelection as = f.getAxisSelections().get(i); for (String n : as) { if (as.getAxis(n) == null) { logger.warn("Removing choice {} as it is missing in {}", n, f.getName()); choices.remove(n); } } } } for (SelectedObject f : selectedList) { if (f.hasData()) { AxisSelection as = f.getAxisSelections().get(i); ArrayList<String> names = new ArrayList<String>(as.getNames()); for (String n : names) { if (!choices.contains(n)) { as.removeChoice(n); } } } } } } /** * Create axes from file based on other axes * @param oldAxes * @param file * @param node * @return list of axis selections */ private List<AxisSelection> makeAxes(List<AxisSelection> oldAxes, SelectedObject file, String node) { List<AxisSelection> newAxes = new ArrayList<AxisSelection>(); for (AxisSelection a : oldAxes) { AxisSelection n = a.clone(); for (int i = 0, imax = n.size(); i < imax; i++) { AxisChoice c = n.getAxis(i); String name = c.getName(); ILazyDataset d = file.getAxis(node != null ? node + name : name); // can be null (from Index or dim:) if (d == null) { if (name.startsWith(AbstractExplorer.DIM_PREFIX)) { d = c.getValues().clone(); } } c.setValues(d); } newAxes.add(n); } return newAxes; } /** * Create a data selection from given lists of datasets, metadata value datasets and axis selection lists * @param itype * @param datasets * @param metavalues * @param axisSelectionLists * @param path * @return data selection */ public static DatasetSelection createSelection(InspectorType itype, List<ILazyDataset> datasets, List<ILazyDataset> metavalues, List<List<AxisSelection>> axisSelectionLists, String path) { boolean extend = true; for (ILazyDataset m : metavalues) { // if all metadata is multi-valued then do not extend aggregate shape if (m.getSize() > 1) { extend = false; break; } } return createSelection(itype, extend, datasets, metavalues, axisSelectionLists, path); } /** * Create a data selection from given lists of datasets, metadata value datasets and axis selection lists * @param itype * @param extend * @param datasets * @param metavalues * @param axisSelectionLists * @param path * @return data selection */ public static DatasetSelection createSelection(InspectorType itype, boolean extend, List<ILazyDataset> datasets, List<ILazyDataset> metavalues, List<List<AxisSelection>> axisSelectionLists, String path) { AggregateDataset allData = new AggregateDataset(extend, datasets.toArray(new ILazyDataset[0])); ILazyDataset[] mvs = metavalues.toArray(new ILazyDataset[0]); ILazyDataset mv = mvs[0]; ILazyDataset allMeta; if (mv instanceof Dataset && mv.getRank() == 1) { // concatenate 1D meta-values Dataset[] mva = new Dataset[mvs.length]; for (int i = 0; i < mvs.length; i++) { ILazyDataset m = mvs[i]; mva[i] = (m instanceof Dataset) ? (Dataset) m : DatasetUtils.convertToDataset(m); } allMeta = DatasetUtils.concatenate(mva, 0); allMeta.setName(mv.getName()); } else { allMeta = new AggregateDataset(extend, mvs); } List<AxisSelection> newAxes = new ArrayList<AxisSelection>(); if (extend) { // extra entries as aggregate datasets can have extra dimension for (List<AxisSelection> asl : axisSelectionLists) { asl.add(0, null); } } // mash together axes int[] shape = allData.getShape(); int rank = shape.length; AxisSelection as; List<ILazyDataset> avalues = new ArrayList<ILazyDataset>(); // for each dimension, for (int i = 0; i < rank; i++) { as = new AxisSelection(rank, i); newAxes.add(as); if (i == 0) { // add meta values first AxisChoice nc = new AxisChoice(allMeta, 1); int[] map = new int[allMeta.getRank()]; for (int j = 0; j < map.length; j++) { map[j] = j; } nc.setIndexMapping(map); nc.setAxisNumber(0); as.addChoice(nc, 1); } AxisSelection ias = axisSelectionLists.get(0).get(i); // initial if (ias == null) { continue; } for (int k = 0, kmax = ias.size(); k < kmax; k++) { // for each choice avalues.clear(); final AxisChoice c = ias.getAxis(k); final int[] map = c.getIndexMapping(); for (List<AxisSelection> asl : axisSelectionLists) { // for each file AxisSelection a = asl.get(i); if (a == null) break; // this dimension was extended ILazyDataset ad = a.getAxis(k).getValues(); if (ad == null) { avalues.clear(); logger.warn("Missing data for choice {} in dim:{} ", ias.getName(k), i); break; } avalues.add(ad); } if (avalues.size() == 0) continue; // consume list for choice ILazyDataset allAxis = new AggregateDataset(extend, avalues.toArray(new ILazyDataset[0])); AxisChoice nc = new AxisChoice(allAxis, c.getPrimary()); String name = ias.getName(k); if (extend) { final int arank = allAxis.getRank(); if (arank > 1) { int[] nmap = new int[arank]; // first entry is zero for (int l = 0; l < map.length; l++) { nmap[l + 1] = map[l] + 1; } nc.setIndexMapping(nmap); } if (name.startsWith(AbstractExplorer.DIM_PREFIX)) { // increment dim: number int d = Integer.parseInt(name.substring(AbstractExplorer.DIM_PREFIX.length())); allAxis.setName(AbstractExplorer.DIM_PREFIX + (d + 1)); } } else { nc.setIndexMapping(map.clone()); } nc.setAxisNumber(i); as.addChoice(name, nc, ias.getOrder(k)); } } if (rank == 1) // override when rank-deficit itype = InspectorType.LINE; return new DatasetSelection(itype, path, newAxes, allData); } private List<ISelectionChangedListener> listeners = new ArrayList<ISelectionChangedListener>(); @Override public void addSelectionChangedListener(ISelectionChangedListener listener) { if (!listeners.contains(listener)) { listeners.add(listener); } } @Override public ISelection getSelection() { if (multipleSelection == null) { return new StructuredSelection(); // Eclipse requires that we do not return null } return multipleSelection; } @Override public void removeSelectionChangedListener(ISelectionChangedListener listener) { listeners.remove(listener); } @Override public void setSelection(ISelection selection) { if (selection instanceof DatasetSelection) { multipleSelection = (DatasetSelection) selection; } else { if (!(selection instanceof FileSelection)) { return; } } SelectionChangedEvent e = new SelectionChangedEvent(this, selection); for (ISelectionChangedListener listener : listeners) { listener.selectionChanged(e); } } private enum MathOp { IDX, ADD, AVR, MUL, MAX, MIN; } private class SelectedObject { boolean hasMV = false; boolean use = true; boolean canUseData = false; Object f; IntegerDataset i; List<ILazyDataset> d; IMetadata m; Serializable mv; String variable; List<AxisSelection> asl; public boolean doUse() { return use; } public void setUse(boolean doUse) { use = doUse; } public String getName() { return d.get(0).getName(); } public boolean isDataOK() { return canUseData; } public void setDataOK(boolean dataOK) { canUseData = dataOK; } public boolean hasData() { return d != null; } public boolean hasMetadataValue() { return hasMV; } public boolean hasMetadata() { return m != null; } public List<ILazyDataset> getDataset() { return d; } public ILazyDataset getMetadataValue() { if (!hasMV) { return null; } if (mv instanceof ILazyDataset) { return (ILazyDataset) mv; } return DatasetFactory.createFromObject(mv); } public void setMetadataValueAsIndex() { hasMV = true; mv = i; } @SuppressWarnings("unused") public void setMetadataValue(String key) { if (m == null) { hasMV = false; return; } try { mv = m.getMetaValue(key); if (mv instanceof String) { mv = Utils.parseValue((String) mv); // TODO parse common multiple values string if (mv != null) { Dataset a = DatasetFactory.createFromObject(mv); a.setName(key); mv = a; } } } catch (Exception e) { } hasMV = mv != null; } public void setIndex(int index) { i = new IntegerDataset(new int[] { index }, null); i.setName(CompareFilesEditor.INDEX); } public int getIndex() { return i.get(0); } public String getVariableName() { return variable; } public void setVariableName(String name) { this.variable = name; } public void setAxisSelections(List<AxisSelection> axisSelectionList) { asl = axisSelectionList; } public ILazyDataset getAxis(@SuppressWarnings("unused") String key) { return null; } public List<AxisSelection> getAxisSelections() { return asl; } @SuppressWarnings("unused") public boolean hasAxisSelections() { return asl != null; } } private class SelectedFile extends SelectedObject { IDataHolder h; public SelectedFile(int index, IFile file) { f = new File(file.getLocationURI()); if (f == null || !((File) f).canRead()) { throw new IllegalArgumentException( "File '" + file.getName() + "' does not exist or can not be read"); } setIndex(index); } public SelectedFile(int index, File file) { f = file; if (f == null || !((File) f).canRead()) { throw new IllegalArgumentException( "File '" + file.getName() + "' does not exist or can not be read"); } setIndex(index); } public SelectedFile(int index, String file) { f = new File(file); if (f == null || !((File) f).canRead()) { throw new IllegalArgumentException("File '" + file + "' does not exist or can not be read"); } setIndex(index); } public String getAbsolutePath() { return ((File) f).getAbsolutePath(); } @Override public String getName() { return ((File) f).getName(); } @Override public String toString() { if (mv == null) { return null; } return mv.toString(); } public boolean hasDataHolder() { return h != null; } // public void setMetadata(IMetadata metadata) { // m = metadata; // } public void setDataHolder(IDataHolder holder) { h = holder; if (h != null) { m = h.getMetadata(); } else { d = null; } } public void setDataset(String key) { if (h.contains(key)) { d = new ArrayList<ILazyDataset>(); d.add(h.getLazyDataset(key)); } else { int n = h.size(); d = null; for (int i = 0; i < n; i++) { ILazyDataset l = h.getLazyDataset(i); if (key.equals(l.getName())) { d = new ArrayList<ILazyDataset>(); d.add(l); break; } } } } // public void resetDataset() { // d = null; // } @Override public ILazyDataset getAxis(String key) { return h != null ? h.getLazyDataset(key) : null; } @Override public void setMetadataValue(String key) { if (m == null) { hasMV = false; return; } try { mv = m.getMetaValue(key); if (mv instanceof String) { mv = Utils.parseValue((String) mv); // TODO parse common multiple values string if (mv != null) { Dataset a = DatasetFactory.createFromObject(mv); a.setName(key); mv = a; } } if (mv == null && h != null) { mv = h.getDataset(key); } } catch (Exception e) { } hasMV = mv != null; } } private class SelectedNode extends SelectedObject { private SymbolTable symbolTable; private JEP jepParser, eval; public SelectedNode(int index, String str) { resetJep(); if (str != null) { setExpression(str); setIndex(index); } } @Override public String toString() { if (f == null) { return null; } return (String) f; } @SuppressWarnings("unchecked") @Override public boolean hasData() { Set<String> vars = symbolTable.keySet(); if (vars.isEmpty()) { return false; } Iterator<String> itr = vars.iterator(); while (itr.hasNext()) { String varName = itr.next(); Variable var = symbolTable.getVar(varName); Object val = var.getValue(); if (val == null) { return false; } Set<SelectedObject> datasets = (Set<SelectedObject>) val; if (datasets.isEmpty()) { return false; } for (SelectedObject data : datasets) { if (!(data.hasData())) { return false; } } } return true; } @SuppressWarnings("unchecked") @Override public boolean isDataOK() { Iterator<String> itr = symbolTable.keySet().iterator(); while (itr.hasNext()) { String varName = itr.next(); Variable var = symbolTable.getVar(varName); Object val = var.getValue(); if (val == null) { canUseData = false; return canUseData; } Set<SelectedObject> datasets = (Set<SelectedObject>) val; if (datasets.isEmpty()) { canUseData = false; return canUseData; } for (SelectedObject data : datasets) { if (!(data.isDataOK())) { canUseData = false; return canUseData; } } } canUseData = true; return canUseData; } @SuppressWarnings("unchecked") @Override public ILazyDataset getAxis(String key) { Iterator<String> itr = symbolTable.keySet().iterator(); ILazyDataset defAxes = null; while (itr.hasNext()) { String varName = itr.next(); Variable var = symbolTable.getVar(varName); ArrayList<SelectedObject> lzdList = new ArrayList<SelectedObject>( (Set<SelectedObject>) var.getValue()); for (SelectedObject obj : lzdList) { if (defAxes == null) { defAxes = obj.getAxis(key); } if (defAxes != null && !defAxes.equals(obj.getAxis(key))) { return null; } } } return defAxes; } public void setExpression(String str) { resetJep(); jepParser.parseExpression(str); eval.parseExpression(str); symbolTable = jepParser.getSymbolTable(); f = str; } private void resetJep() { // This JEP instance is used to keep track of datasets assign to variable jepParser = new JEP(); jepParser.setAllowUndeclared(true); //jepParser.addStandardConstants(); jepParser.addStandardFunctions(); // This JEP instance is used during dataset evaluation to assign double values to variables eval = new JEP(); eval.setAllowUndeclared(true); //eval.addStandardConstants(); eval.addStandardFunctions(); } private class VariableLazyLoader implements ILazyLoader { private HashMap<String, ILazyDataset> varMapping; public VariableLazyLoader(HashMap<String, ILazyDataset> varMapping) { this.varMapping = varMapping; } @Override public boolean isFileReadable() { return hasData(); } @SuppressWarnings("unchecked") @Override public Dataset getDataset(IMonitor mon, SliceND slice) throws ScanFileHolderException { SymbolTable evalSymbolTable = eval.getSymbolTable(); HashMap<String, IDataset> dataSlices = new HashMap<String, IDataset>(); Iterator<String> itr = evalSymbolTable.keySet().iterator(); int[] sliceShape = null; while (itr.hasNext()) { String varName = itr.next(); ILazyDataset lzd = varMapping.get(varName); // TODO: This only works for SelectedFile objects IDataset lzdSlice = lzd.getSlice(slice); dataSlices.put(varName, lzdSlice); // All datasets and slices should have the same shape if (sliceShape == null) { sliceShape = lzdSlice.getShape(); } } Dataset ds = DatasetFactory.zeros(sliceShape, Dataset.FLOAT64); IndexIterator iter = ds.getIterator(true); int[] idx = iter.getPos(); while (iter.hasNext()) { itr = evalSymbolTable.keySet().iterator(); while (itr.hasNext()) { String varName = itr.next(); double val = dataSlices.get(varName).getDouble(idx); evalSymbolTable.setVarValue(varName, val); } double res; try { res = (Double) eval.evaluate(eval.getTopNode()); } catch (ParseException e) { throw new IllegalArgumentException("Parsing input expression failed", e); } ds.set(res, idx); } return ds; } } private List<ILazyDataset> processSelection(final VariableMapping varMap) { final MathOp mathOp = varMap.getMathOp(); final List<ILazyDataset> dataList = new ArrayList<ILazyDataset>(); for (SelectedObject obj : varMap.getDatasets()) { dataList.addAll(obj.getDataset()); } switch (mathOp) { case IDX: return dataList; default: ILazyDataset refData = dataList.get(0); ILazyLoader processingLoader = new ILazyLoader() { @Override public boolean isFileReadable() { return true; } @Override public Dataset getDataset(IMonitor mon, SliceND slice) throws ScanFileHolderException { Dataset accDataset = null; for (int idx = 0; idx < dataList.size(); idx++) { Dataset tmpData = DatasetUtils.convertToDataset(dataList.get(idx).getSlice(slice)); if (accDataset == null) { switch (mathOp) { case ADD: case AVR: accDataset = DatasetFactory.zeros(tmpData.getShape(), tmpData.getDtype()); break; case MUL: accDataset = DatasetFactory.ones(tmpData.getShape(), tmpData.getDtype()); break; case MAX: case MIN: accDataset = DatasetFactory.zeros(tmpData.getShape(), tmpData.getDtype()); IndexIterator iter = accDataset.getIterator(); tmpData.fillDataset(accDataset, iter); break; default: break; } } if (accDataset == null) { return null; } switch (mathOp) { case ADD: case AVR: accDataset.iadd(tmpData); break; case MUL: accDataset.imultiply(tmpData); break; case MAX: accDataset = Maths.maximum(tmpData, accDataset); break; case MIN: accDataset = Maths.minimum(tmpData, accDataset); break; default: break; } } if (accDataset != null && mathOp.equals(MathOp.AVR)) { accDataset.idivide(dataList.size()); } return accDataset; } }; List<ILazyDataset> res = new ArrayList<ILazyDataset>(); res.add(new LazyDataset(varMap.getName(), AbstractDataset.getDType(refData), refData.getShape(), processingLoader)); return res; } } @SuppressWarnings("unchecked") @Override public List<ILazyDataset> getDataset() { // Generate all combinations of datasets assigned to variables List<String> varNameList = new ArrayList<String>(symbolTable.keySet()); Map<String, List<ILazyDataset>> varMap = new HashMap<String, List<ILazyDataset>>(); Iterator<String> itr = symbolTable.keySet().iterator(); while (itr.hasNext()) { String varName = itr.next(); List<ILazyDataset> processedDataList = processSelection(variableMap.get(varName)); varMap.put(varName, processedDataList); } int[] idxDataset = new int[varNameList.size()]; for (int idx = 0; idx < idxDataset.length; idx++) { String varName = varNameList.get(idx); idxDataset[idx] = varMap.get(varName).size(); } // Iterate over flat index in idxDataset to loop over all // variable assignment combinations MultidimensionalCounter datasetCounter = new MultidimensionalCounter(idxDataset); org.apache.commons.math3.util.MultidimensionalCounter.Iterator iter = datasetCounter.iterator(); d = new ArrayList<ILazyDataset>(); while (iter.hasNext()) { iter.next(); HashMap<String, ILazyDataset> tmpMap = new HashMap<String, ILazyDataset>(); int[] datasetIdx = iter.getCounts(); for (int idx = 0; idx < datasetIdx.length; idx++) { String tmpName = varNameList.get(idx); ILazyDataset tmpVar = varMap.get(tmpName).get(datasetIdx[idx]); tmpMap.put(tmpName, tmpVar); } ILazyLoader dataLoader = new VariableLazyLoader(tmpMap); d.add(new LazyDataset("Function " + Arrays.toString(datasetIdx), Dataset.FLOAT64, getShape(), dataLoader)); } return d; } @SuppressWarnings("unchecked") private int[] getShape() { int[] tmpShape = null; Iterator<String> itr = symbolTable.keySet().iterator(); while (itr.hasNext()) { Variable var = symbolTable.getVar(itr.next()); Set<SelectedFile> sfList = (Set<SelectedFile>) var.getValue(); if (sfList == null || sfList.isEmpty()) { return null; } for (SelectedFile sf : sfList) { if (!sf.hasData()) { return null; } if (tmpShape == null) { tmpShape = sf.getDataset().get(0).getShape(); // All datasets should be the same shape } else { if (!AbstractDataset.areShapesCompatible(tmpShape, sf.getDataset().get(0).getShape(), -1)) { return null; } } } } return tmpShape; } } private class VariableMapping { private String name; private MathOp mathOp; private List<SelectedObject> datasets; public VariableMapping(String name) { super(); this.name = name; } public String getName() { return name; } public MathOp getMathOp() { return mathOp; } public void setMathOp(MathOp mathOp) { this.mathOp = mathOp; } public List<SelectedObject> getDatasets() { return datasets; } public void setDatasets(List<SelectedObject> datasets) { this.datasets = datasets; } } } class CompareFilesEditorInput extends PlatformObject implements IEditorInput { Object[] list; private String name; public CompareFilesEditorInput(IStructuredSelection selection) { list = selection.toArray(); name = createName(); } @Override public boolean exists() { return false; } @Override public ImageDescriptor getImageDescriptor() { return null; } @Override public String getName() { return name; } @Override public IPersistableElement getPersistable() { return null; } @Override public String getToolTipText() { return name; } private String createName() { StringBuilder s = new StringBuilder(); if (list == null || list.length < 1) { s.append("Invalid list"); } else { s.append("Comparing "); for (Object o : list) { if (o instanceof IFile) { IFile f = (IFile) o; s.append(f.getFullPath().toString()); s.append(", "); } else if (o instanceof File) { File pf = (File) o; s.append(pf.getAbsolutePath()); s.append(", "); } } int end = s.length(); s.delete(end - 2, end); } return s.toString(); } }