org.dawnsci.slicing.tools.hyper.HyperComponent.java Source code

Java tutorial

Introduction

Here is the source code for org.dawnsci.slicing.tools.hyper.HyperComponent.java

Source

/*
 * 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 org.dawnsci.slicing.tools.hyper;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;

import org.dawb.common.ui.util.GridUtils;
import org.dawb.common.ui.widgets.ActionBarWrapper;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.dawnsci.analysis.api.dataset.IDataset;
import org.eclipse.dawnsci.analysis.api.dataset.ILazyDataset;
import org.eclipse.dawnsci.analysis.api.dataset.Slice;
import org.eclipse.dawnsci.analysis.api.roi.IROI;
import org.eclipse.dawnsci.analysis.dataset.impl.Dataset;
import org.eclipse.dawnsci.analysis.dataset.impl.DatasetFactory;
import org.eclipse.dawnsci.plotting.api.IPlottingSystem;
import org.eclipse.dawnsci.plotting.api.PlotType;
import org.eclipse.dawnsci.plotting.api.PlottingFactory;
import org.eclipse.dawnsci.plotting.api.region.IROIListener;
import org.eclipse.dawnsci.plotting.api.region.IRegion;
import org.eclipse.dawnsci.plotting.api.region.IRegionListener;
import org.eclipse.dawnsci.plotting.api.region.ROIEvent;
import org.eclipse.dawnsci.plotting.api.region.RegionEvent;
import org.eclipse.dawnsci.plotting.api.tool.IToolPage.ToolPageRole;
import org.eclipse.dawnsci.plotting.api.tool.IToolPageSystem;
import org.eclipse.dawnsci.plotting.api.trace.ColorOption;
import org.eclipse.dawnsci.plotting.api.trace.ILineTrace;
import org.eclipse.dawnsci.plotting.api.trace.ITrace;
import org.eclipse.dawnsci.plotting.api.trace.TraceUtils;
import org.eclipse.dawnsci.slicing.api.util.ProgressMonitorWrapper;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IContributionItem;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.part.Page;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Display a 3D dataset across two plots with ROI slicing
 */
public class HyperComponent {

    private IPlottingSystem mainSystem;
    private IPlottingSystem sideSystem;
    private IRegionListener regionListenerLeft;
    private IRegionListener regionListenerRight;
    private IROIListener roiListenerLeft;
    private IROIListener roiListenerRight;
    private HyperDelegateJob leftJob;
    private HyperDelegateJob rightJob;
    private Composite mainComposite;
    private IWorkbenchPart part;
    private SashForm sashForm;
    private final static Logger logger = LoggerFactory.getLogger(HyperComponent.class);
    private List<IAction> leftActions;
    private List<IAction> rightActions;

    private static final String SS1 = "uk.ac.diamond.scisoft.analysis.rcp.views.HyperPlotView.reducerGroup1";
    private static final String SS2 = "uk.ac.diamond.scisoft.analysis.rcp.views.HyperPlotView.reducerGroup2";
    private static final String STARTGROUP = "/org.dawb.common.ui.plot.groupAll";
    private static final String HYPERIMAGE = "HyperImage";
    private static final String HYPERTRACE = "HyperTrace";

    public HyperComponent(IWorkbenchPart part) {
        this.part = part;
    }

    public void createControl(Composite parent) {

        this.sashForm = new SashForm(parent, SWT.HORIZONTAL);
        sashForm.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 2, 1));
        sashForm.setBackground(new Color(parent.getDisplay(), 192, 192, 192));

        createPlottingSystems(sashForm);

        leftActions = new ArrayList<IAction>();
        rightActions = new ArrayList<IAction>();
    }

    public Control getControl() {
        return sashForm;
    }

    public void setData(ILazyDataset lazy, List<IDataset> daxes, Slice[] slices, int[] order) {
        this.setData(lazy, daxes, slices, order, new TraceReducer(), new ImageTrapeziumBaselineReducer());
    }

    public void setData(ILazyDataset lazy, List<IDataset> daxes, Slice[] slices, int[] order,
            IDatasetROIReducer mainReducer, IDatasetROIReducer sideReducer) {
        //FIXME needs to be made more generic
        this.leftJob = new HyperDelegateJob("Left update", sideSystem, lazy, daxes, slices, order, mainReducer);

        this.rightJob = new HyperDelegateJob("Right update", mainSystem, lazy, daxes, slices, order, sideReducer);

        cleanUpActions(sideSystem, rightActions);
        cleanUpActions(mainSystem, leftActions);

        if (rightJob.getReducer() instanceof IProvideReducerActions) {
            createActions((IProvideReducerActions) rightJob.getReducer(), sideSystem, rightActions,
                    roiListenerRight, HYPERTRACE);
        }
        if (leftJob.getReducer() instanceof IProvideReducerActions) {
            createActions((IProvideReducerActions) leftJob.getReducer(), mainSystem, leftActions, roiListenerLeft,
                    HYPERIMAGE);
        }

        IROI rroi = mainReducer.getInitialROI(daxes, order);
        IROI broi = sideReducer.getInitialROI(daxes, order);

        mainSystem.clear();
        mainSystem.getAxes().clear();

        int axisCount = 0;

        if (mainReducer.isOutput1D()) {
            axisCount++;
        } else {
            List<IDataset> ax2d = new ArrayList<IDataset>();
            ax2d.add(daxes.get(axisCount++));
            ax2d.add(daxes.get(axisCount++));
            mainSystem.createPlot2D(
                    DatasetFactory.zeros(new int[] { ax2d.get(0).getSize(), ax2d.get(1).getSize() }, Dataset.INT16),
                    ax2d, null);
        }

        for (IRegion region : mainSystem.getRegions()) {
            mainSystem.removeRegion(region);
        }

        sideSystem.clear();
        sideSystem.getAxes().clear();

        if (mainReducer.isOutput1D()) {
            List<IDataset> xd = new ArrayList<IDataset>();
            IDataset axis = daxes.get(axisCount++);
            xd.add(DatasetFactory.zeros(new int[] { (int) axis.getSize() }, Dataset.INT16));

            sideSystem.createPlot1D(axis, xd, null);
        } else {
            List<IDataset> xd = new ArrayList<IDataset>();
            xd.add(DatasetFactory.createRange(10, Dataset.INT32));
            xd.add(daxes.get(axisCount++));
            sideSystem.createPlot2D(DatasetFactory.ones(new int[] { 10, (int) xd.get(1).getSize() }, Dataset.INT32),
                    xd, null);
        }

        for (IRegion region : sideSystem.getRegions()) {
            sideSystem.removeRegion(region);
        }

        try {
            IRegion region = mainSystem.createRegion("Image Region 1", mainReducer.getSupportedRegionType().get(0));

            mainSystem.addRegion(region);

            region.setROI(rroi);
            region.addROIListener(this.roiListenerLeft);
            sideSystem.clear();
            updateRight(region, rroi);

            IRegion windowRegion = sideSystem.createRegion("Trace Region 1",
                    sideReducer.getSupportedRegionType().get(0));

            windowRegion.setROI(broi);
            windowRegion.setUserRegion(false);
            windowRegion.addROIListener(this.roiListenerRight);
            sideSystem.addRegion(windowRegion);
            updateLeft(windowRegion, broi);

        } catch (Exception e) {
            logger.error("Error adding regions to hyperview: " + e.getMessage());
        }
    }

    public void setFocus() {
        mainComposite.setFocus();
    }

    public void dispose() {

        if (mainSystem != null && !mainSystem.isDisposed())
            mainSystem.dispose();
        if (sideSystem != null && !sideSystem.isDisposed())
            sideSystem.dispose();

        if (leftJob != null)
            leftJob.cancel();
        if (rightJob != null)
            rightJob.cancel();

    }

    private void createPlottingSystems(SashForm sashForm) {
        try {
            mainSystem = PlottingFactory.createPlottingSystem();
            mainSystem.setColorOption(ColorOption.NONE);
            mainComposite = new Composite(sashForm, SWT.NONE);
            mainComposite.setLayout(new GridLayout(1, false));
            GridUtils.removeMargins(mainComposite);

            ActionBarWrapper actionBarWrapper = ActionBarWrapper.createActionBars(mainComposite, null);

            Composite displayPlotComp = new Composite(mainComposite, SWT.BORDER);
            displayPlotComp.setLayout(new FillLayout());
            displayPlotComp.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
            mainSystem.createPlotPart(displayPlotComp, HYPERIMAGE, actionBarWrapper, PlotType.IMAGE, part);

            mainSystem.repaint();

            sideSystem = PlottingFactory.createPlottingSystem();
            sideSystem.setColorOption(ColorOption.NONE);
            Composite sideComp = new Composite(sashForm, SWT.NONE);
            sideComp.setLayout(new GridLayout(1, false));
            GridUtils.removeMargins(sideComp);
            ActionBarWrapper actionBarWrapper1 = ActionBarWrapper.createActionBars(sideComp, null);
            Composite sidePlotComp = new Composite(sideComp, SWT.BORDER);
            sidePlotComp.setLayout(new FillLayout());
            sidePlotComp.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));

            sideSystem.createPlotPart(sidePlotComp, HYPERTRACE, actionBarWrapper1, PlotType.XY, null);

            regionListenerLeft = getRegionListenerToLeft();
            mainSystem.addRegionListener(regionListenerLeft);
            regionListenerRight = getRegionListenerToRight();
            sideSystem.addRegionListener(regionListenerRight);

            roiListenerLeft = getROIListenerToRight();
            roiListenerRight = getROIListenerLeft();

            mainSystem.getActionBars().getToolBarManager().remove(ToolPageRole.ROLE_1D.getId());
            mainSystem.getActionBars().getToolBarManager().remove(ToolPageRole.ROLE_2D.getId());
            mainSystem.getActionBars().getToolBarManager().update(true);

            sideSystem.getActionBars().getToolBarManager().remove(ToolPageRole.ROLE_1D.getId());
            sideSystem.getActionBars().getToolBarManager().remove(ToolPageRole.ROLE_2D.getId());
            sideSystem.getActionBars().getToolBarManager().update(true);
        } catch (Exception e) {
            logger.error("Error creating hyperview plotting systems: " + e.getMessage());
        }
    }

    public Object getAdapter(@SuppressWarnings("rawtypes") final Class clazz) {

        if (clazz == Page.class) {
            // TODO Page for helping with part
        } else if (clazz == IToolPageSystem.class || clazz == IPlottingSystem.class) {
            return mainSystem;
        }
        return null;
    }

    private void cleanUpActions(IPlottingSystem system, List<IAction> cached) {
        IActionBars actionBars = system.getActionBars();
        IToolBarManager toolBarManager = actionBars.getToolBarManager();
        IMenuManager menuManager = actionBars.getMenuManager();

        for (IAction action : cached) {
            toolBarManager.remove(action.getId());
            menuManager.remove(action.getId());
        }

        toolBarManager.remove(SS1);
        toolBarManager.remove(SS2);
        menuManager.remove(SS1);
        menuManager.remove(SS2);
        cached.clear();
        toolBarManager.update(true);
    }

    private void createActions(IProvideReducerActions provider, IPlottingSystem system, List<IAction> cached,
            IROIListener listener, String barName) {

        IActionBars actionBars = system.getActionBars();
        IToolBarManager toolBarManager = actionBars.getToolBarManager();
        IMenuManager menuManager = actionBars.getMenuManager();
        List<IAction> actions = provider.getActions(system);

        IContributionItem s1 = new Separator(SS1);

        toolBarManager.insertBefore(barName + STARTGROUP, s1);
        menuManager.add(s1);

        for (IAction action : actions) {
            toolBarManager.insertBefore(barName + STARTGROUP, action);
            menuManager.add(action);
            cached.add(action);
        }
        IContributionItem s2 = new Separator(SS2);
        toolBarManager.insertBefore(barName + STARTGROUP, s2);
        menuManager.add(s2);
        toolBarManager.update(true);
    }

    private IRegionListener getRegionListenerToLeft() {
        return new IRegionListener.Stub() {

            @Override
            public void regionsRemoved(RegionEvent evt) {

                for (ITrace trace : sideSystem.getTraces(ILineTrace.class)) {
                    if (trace.getUserObject() instanceof IRegion) {
                        if (((IRegion) trace.getUserObject()).isUserRegion()) {
                            sideSystem.removeTrace(trace);
                        }
                    }
                }
            }

            @Override
            public void regionRemoved(RegionEvent evt) {

                for (ITrace trace : sideSystem.getTraces(ILineTrace.class)) {
                    if (trace.getUserObject() == evt.getSource()) {
                        sideSystem.removeTrace(trace);
                    }
                }
            }

            @Override
            public void regionAdded(RegionEvent evt) {
                if (evt.getRegion() != null) {
                    evt.getRegion().setUserRegion(true);
                    evt.getRegion().addROIListener(roiListenerLeft);
                    updateRight((IRegion) evt.getSource(), ((IRegion) evt.getSource()).getROI());
                }

            }
        };
    }

    private IRegionListener getRegionListenerToRight() {
        return new IRegionListener.Stub() {

            @Override
            public void regionsRemoved(RegionEvent evt) {

                for (ITrace trace : mainSystem.getTraces(ILineTrace.class)) {
                    if (trace.getUserObject() instanceof IRegion) {
                        if (((IRegion) trace.getUserObject()).isUserRegion()) {
                            mainSystem.removeTrace(trace);
                        }
                    }
                }
            }

            @Override
            public void regionRemoved(RegionEvent evt) {

                for (ITrace trace : mainSystem.getTraces(ILineTrace.class)) {
                    if (trace.getUserObject() == evt.getSource()) {
                        mainSystem.removeTrace(trace);
                    }
                }
            }

            @Override
            public void regionAdded(RegionEvent evt) {
                if (evt.getRegion() != null) {
                    evt.getRegion().setUserRegion(true);
                    evt.getRegion().addROIListener(roiListenerRight);
                    updateLeft((IRegion) evt.getSource(), ((IRegion) evt.getSource()).getROI());
                }

            }
        };
    }

    private IROIListener getROIListenerToRight() {

        return new IROIListener.Stub() {

            @Override
            public void roiDragged(ROIEvent evt) {
                updateRight((IRegion) evt.getSource(), evt.getROI());

            }

            @Override
            public void roiChanged(ROIEvent evt) {
                updateRight((IRegion) evt.getSource(), evt.getROI());
            }
        };
    }

    private IROIListener getROIListenerLeft() {
        return new IROIListener.Stub() {

            @Override
            public void roiDragged(ROIEvent evt) {
                updateLeft((IRegion) evt.getSource(), evt.getROI());

            }

            @Override
            public void roiChanged(ROIEvent evt) {
                updateLeft((IRegion) evt.getSource(), evt.getROI());

            }
        };
    }

    protected void updateRight(IRegion r, IROI rb) {

        leftJob.profile(r, rb);
    }

    protected void updateLeft(IRegion r, IROI rb) {

        rightJob.profile(r, rb);
    }

    private void updateImage(final IPlottingSystem plot, final IDataset image, final List<IDataset> axes) {

        plot.updatePlot2D(image, axes, null);

    }

    private void updateTrace(final IPlottingSystem plot, final IDataset axis, final IDataset data,
            final boolean update, final IRegion region) {

        if (update) {
            plot.updatePlot1D(axis, Arrays.asList(new IDataset[] { data }), null);
            plot.repaint();
        } else {
            final List<ITrace> traceOut = plot.createPlot1D(axis, Arrays.asList(new IDataset[] { data }), null);

            Display.getDefault().syncExec(new Runnable() {
                @Override
                public void run() {
                    for (ITrace trace : traceOut) {
                        trace.setUserObject(region);
                        if (trace instanceof ILineTrace) {
                            region.setRegionColor(((ILineTrace) trace).getTraceColor());
                        }
                    }
                }
            });
        }
    }

    private void updateTrace(final IPlottingSystem plot, final IDataset axis, final IDataset data) {

        Display.getDefault().syncExec(new Runnable() {
            @Override
            public void run() {

                Collection<ITrace> traces = plot.getTraces(ILineTrace.class);

                List<IDataset> datasets = convertFrom2DToListOf1D(axis, data);

                if (traces == null || traces.isEmpty()) {
                    plot.createPlot1D(axis, datasets, null);
                    return;
                }
                int i = 0;
                for (ITrace trace : traces) {
                    if (i < datasets.size())
                        ((ILineTrace) trace).setData(axis, datasets.get(i));
                    else
                        plot.removeTrace(trace);
                    i++;
                }

                if (i >= datasets.size()) {
                    plot.repaint();
                    return;
                }

                List<IDataset> subdatasets = new ArrayList<IDataset>(datasets.size() - i);

                for (; i < datasets.size(); ++i) {
                    subdatasets.add(datasets.get(i));
                }

                plot.createPlot1D(axis, subdatasets, null);
                plot.repaint();
            }
        });
    }

    private List<IDataset> convertFrom2DToListOf1D(IDataset axis, IDataset data) {

        int[] dataShape = data.getShape();

        List<IDataset> datasets = new ArrayList<IDataset>(dataShape[0]);
        Slice[] slices = new Slice[2];
        slices[0] = new Slice(0, 1, 1);

        for (int i = 0; i < dataShape[0]; i++) {
            slices[0].setStart(i);
            slices[0].setStop(i + 1);

            IDataset out = data.getSlice(slices);

            out.setName("trace_" + i);

            datasets.add(out.squeeze());
        }

        return datasets;

    }

    private class HyperDelegateJob extends Job {

        private IRegion currentRegion;
        private IROI currentROI;
        private IPlottingSystem plot;
        private ILazyDataset data;
        private List<IDataset> axes;
        private int[] order;
        private Slice[] slices;
        private IDatasetROIReducer reducer;

        public HyperDelegateJob(String name, IPlottingSystem plot, ILazyDataset data, List<IDataset> axes,
                Slice[] slices, int[] order, IDatasetROIReducer reducer) {

            super(name);
            this.plot = plot;
            this.data = data;
            this.axes = axes;
            this.order = order;
            this.slices = slices;
            this.reducer = reducer;
            setSystem(false);
            setUser(false);
        }

        public void profile(IRegion r, IROI rb) {

            cancel(); // Needed for large datasets but makes small ones look less responsive.
            this.currentRegion = r;
            this.currentROI = rb;

            schedule();
        }

        public IDatasetROIReducer getReducer() {
            return reducer;
        }

        @Override
        protected IStatus run(IProgressMonitor monitor) {
            try {
                if (monitor.isCanceled())
                    return Status.CANCEL_STATUS;

                IDataset output = this.reducer.reduce(data, axes, currentROI, slices, order,
                        new ProgressMonitorWrapper(monitor));
                if (output == null)
                    return Status.CANCEL_STATUS;

                List<IDataset> outputAxes = this.reducer.getAxes();

                if (!this.reducer.isOutput1D()) {
                    output.setName("Image");
                    updateImage(plot, output, outputAxes);
                } else {

                    IDataset axis = null;

                    if (outputAxes != null && !outputAxes.isEmpty()) {
                        axis = outputAxes.get(0);
                    }

                    if (output.getRank() == 1) {
                        Collection<ITrace> traces = plot.getTraces();
                        for (ITrace trace : traces) {
                            Object uo = trace.getUserObject();
                            if (uo == currentRegion) {
                                output.setName(trace.getName());
                                updateTrace(plot, axis, output, true, currentRegion);
                                return Status.OK_STATUS;
                            }
                        }

                        String name = TraceUtils.getUniqueTrace("trace", plot, (String[]) null);
                        output.setName(name);

                        updateTrace(plot, axis, output, false, currentRegion);
                    } else {
                        updateTrace(plot, axis, output);
                    }

                }

                return Status.OK_STATUS;
            } catch (Throwable ne) {
                return Status.CANCEL_STATUS;
            }
        }
    }
}