uk.ac.diamond.scisoft.analysis.rcp.views.PlotViewStatsAndMaths.java Source code

Java tutorial

Introduction

Here is the source code for uk.ac.diamond.scisoft.analysis.rcp.views.PlotViewStatsAndMaths.java

Source

/*
 * Copyright 2012 Diamond Light Source Ltd.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package uk.ac.diamond.scisoft.analysis.rcp.views;

import gda.observable.IObserver;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.math3.complex.Complex;
import org.eclipse.dawnsci.analysis.dataset.impl.Dataset;
import org.eclipse.dawnsci.analysis.dataset.impl.Maths;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.IViewPart;
import org.eclipse.ui.IViewReference;
import org.eclipse.ui.part.ViewPart;

import uk.ac.diamond.scisoft.analysis.plotserver.AxisMapBean;
import uk.ac.diamond.scisoft.analysis.plotserver.DataBean;
import uk.ac.diamond.scisoft.analysis.plotserver.DatasetWithAxisInformation;
import uk.ac.diamond.scisoft.analysis.plotserver.GuiPlotMode;
import uk.ac.diamond.scisoft.analysis.plotserver.NexusDataBean;

/**
 * Panel that observes a PlotView to show additional information
 * allow allows maths and moving of data
 */
public class PlotViewStatsAndMaths extends ViewPart implements IObserver {
    protected Composite parentComp;
    protected DataBean dataBeanA, dataBeanB, currentBean;
    protected PlotView plotView;

    private String doubleFormat = "%5.5g";
    private Button btnPlotA;
    private Button btnPlotAb;
    private Button btnPlotB;
    private Button btnPlotBa;
    private Button btnPlotAnB;
    private Button btnStoreCurrentAsA;
    private Button btnStoreCurrentAsB;
    private Composite composite;
    private Combo spinner;
    private Button btnNewButton;
    private Label labelA;
    private Label labelB;
    private Text textMaxVal;
    private Text textMaxPos;
    private Text textMinVal;
    private Text textMinPos;
    private Text textSum;
    private Text textMean;
    private Map<String, PlotView> viewMap = new HashMap<String, PlotView>();

    private SelectionListener updatePlotList = new SelectionListener() {

        @Override
        public void widgetSelected(SelectionEvent event) {
            String selected = spinner.getText();
            viewMap.clear();
            IViewReference[] viewReferences = getSite().getPage().getViewReferences();
            for (IViewReference viewref : viewReferences) {
                IViewPart view = viewref.getView(false);
                if (view != null && view instanceof PlotView) {
                    viewMap.put(view.getTitle(), (PlotView) view);
                }
            }
            int i = 0, sel = 0;
            spinner.setItems(new String[] {});
            for (String label : viewMap.keySet()) {
                spinner.add(label);
                if (label.equals(selected))
                    sel = i;
                i++;
            }
            spinner.select(sel);
            updatePlotSelection.widgetSelected(null);
        }

        @Override
        public void widgetDefaultSelected(SelectionEvent e) {
        }
    };

    private SelectionListener updatePlotSelection = new SelectionListener() {

        @Override
        public void widgetSelected(SelectionEvent event) {
            unobserve(plotView);
            plotView = viewMap.get(spinner.getText());
            if (plotView == null) // this can happen if bogus one is entered
                return;
            DataBean bean = plotView.getPlotWindow().getDataBean();
            if (bean == null) {
                btnStoreCurrentAsA.setEnabled(false);
                btnStoreCurrentAsB.setEnabled(false);

                textMaxVal.setText("");
                textMaxPos.setText("");
                textMinVal.setText("");
                textMinPos.setText("");
                textSum.setText("");
                textMean.setText("");
            } else {
                update(plotView, bean);
            }
            observe(plotView);
        }

        @Override
        public void widgetDefaultSelected(SelectionEvent e) {
        }
    };

    private void observe(PlotView pv) {
        if (pv != null)
            pv.addDataObserver(this);
    }

    private void unobserve(PlotView pv) {
        if (pv != null)
            pv.deleteDataObserver(this);
    }

    /**
     * Controls the server side display of live or near live data and displays statistics
     */
    public PlotViewStatsAndMaths() {
    }

    @Override
    public void createPartControl(Composite parent) {

        GridLayout layout = new GridLayout();

        parent.setLayout(layout);
        parentComp = parent;

        composite = new Composite(parent, SWT.NONE);
        composite.setLayout(new RowLayout(SWT.HORIZONTAL));

        Label lblNewLabel = new Label(composite, SWT.NONE);
        lblNewLabel.setText("Choose Plot View to operate on: ");

        spinner = new Combo(composite, SWT.BORDER | SWT.READ_ONLY);
        spinner.setItems(new String[] { "                    " });
        spinner.addSelectionListener(updatePlotSelection);

        btnNewButton = new Button(composite, SWT.NONE);
        btnNewButton.setText("update choices");
        btnNewButton.addSelectionListener(updatePlotList);

        Composite grpMaths = new Composite(parent, SWT.NONE);
        grpMaths.setLayout(new GridLayout(5, false));
        grpMaths.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));

        btnStoreCurrentAsA = new Button(grpMaths, SWT.NONE);
        btnStoreCurrentAsA.setText("Store current as A");
        btnStoreCurrentAsA.setEnabled(false);
        btnStoreCurrentAsA.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                dataBeanA = currentBean;
                labelA.setText(getLabel(dataBeanA) + " (latest)");
                labelB.setText(getLabel(dataBeanB));
                enableDisableMaths();
            }
        });

        btnPlotA = new Button(grpMaths, SWT.NONE);
        btnPlotA.setText("Plot A");
        btnPlotA.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                pushToPlotView(dataBeanA);
            }
        });

        btnPlotAb = new Button(grpMaths, SWT.NONE);
        btnPlotAb.setText("Plot A-B");
        btnPlotAb.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                pushToPlotView(dataBeanSubtract(dataBeanA, dataBeanB));
            }
        });

        btnPlotAnB = new Button(grpMaths, SWT.NONE);
        btnPlotAnB.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 1, 2));
        btnPlotAnB.setText("Plot A + B");
        btnPlotAnB.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                pushToPlotView(dataBeanAdd(dataBeanA, dataBeanB));
            }
        });

        labelA = new Label(grpMaths, SWT.NONE);
        labelA.setText(
                "                                                                                             ");

        btnStoreCurrentAsB = new Button(grpMaths, SWT.NONE);
        btnStoreCurrentAsB.setText("Store current as B");
        btnStoreCurrentAsB.setEnabled(false);
        btnStoreCurrentAsB.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                dataBeanB = currentBean;
                labelA.setText(getLabel(dataBeanA));
                labelB.setText(getLabel(dataBeanB) + " (latest)");
                enableDisableMaths();
            }
        });

        btnPlotB = new Button(grpMaths, SWT.NONE);
        btnPlotB.setText("Plot B");
        btnPlotB.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                pushToPlotView(dataBeanB);
            }
        });

        btnPlotBa = new Button(grpMaths, SWT.NONE);
        btnPlotBa.setText("Plot B-A");

        labelB = new Label(grpMaths, SWT.NONE);
        labelB.setText(
                "                                                                                             ");
        btnPlotBa.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                pushToPlotView(dataBeanSubtract(dataBeanB, dataBeanA));
            }
        });

        Group grpStatistics = new Group(parent, SWT.NONE);
        grpStatistics.setText("Statistics");
        grpStatistics.setLayout(new GridLayout(3, false));
        grpStatistics.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));

        new Label(grpStatistics, SWT.NONE);

        Label txtValue = new Label(grpStatistics, SWT.NONE);
        txtValue.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, false, false, 1, 1));
        txtValue.setAlignment(SWT.CENTER);
        txtValue.setText("value");

        Label txtPosition = new Label(grpStatistics, SWT.NONE);
        txtPosition.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, false, false, 1, 1));
        txtPosition.setAlignment(SWT.CENTER);
        txtPosition.setText("position");

        Label txtMax = new Label(grpStatistics, SWT.NONE);
        txtMax.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
        txtMax.setAlignment(SWT.RIGHT);
        txtMax.setText("max");

        textMaxVal = new Text(grpStatistics, SWT.RIGHT);
        textMaxVal.setText("0");
        GridData gd_textMaxVal = new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1);
        gd_textMaxVal.widthHint = 120;
        textMaxVal.setLayoutData(gd_textMaxVal);
        textMaxVal.setEditable(false);

        textMaxPos = new Text(grpStatistics, SWT.RIGHT);
        textMaxPos.setText("0");
        GridData gd_textMaxPos = new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1);
        gd_textMaxPos.widthHint = 120;
        textMaxPos.setLayoutData(gd_textMaxPos);
        textMaxPos.setEditable(false);

        Label txtMin = new Label(grpStatistics, SWT.NONE);
        txtMin.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
        txtMin.setAlignment(SWT.RIGHT);
        txtMin.setText("min");

        textMinVal = new Text(grpStatistics, SWT.RIGHT);
        textMinVal.setText("0");
        GridData gd_textMinVal = new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1);
        gd_textMinVal.widthHint = 120;
        textMinVal.setLayoutData(gd_textMinVal);
        textMinVal.setEditable(false);

        textMinPos = new Text(grpStatistics, SWT.RIGHT);
        textMinPos.setText("0");
        GridData gd_textMinPos = new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1);
        gd_textMinPos.widthHint = 120;
        textMinPos.setLayoutData(gd_textMinPos);
        textMinPos.setEditable(false);

        Label txtSum = new Label(grpStatistics, SWT.NONE);
        txtSum.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
        txtSum.setAlignment(SWT.RIGHT);
        txtSum.setText("sum");

        textSum = new Text(grpStatistics, SWT.RIGHT);
        textSum.setText("0");
        GridData gd_textSum = new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1);
        gd_textSum.widthHint = 120;
        textSum.setLayoutData(gd_textSum);
        textSum.setEditable(false);

        new Label(grpStatistics, SWT.NONE);

        Label txtMean = new Label(grpStatistics, SWT.NONE);
        txtMean.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
        txtMean.setAlignment(SWT.RIGHT);
        txtMean.setText("mean");

        textMean = new Text(grpStatistics, SWT.RIGHT);
        textMean.setText("0");
        GridData gd_textMean = new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1);
        gd_textMean.widthHint = 120;
        textMean.setLayoutData(gd_textMean);
        textMean.setEditable(false);

        new Label(grpStatistics, SWT.NONE);

        enableDisableMaths();
    }

    private static String getLabel(DataBean db) {
        try {
            Dataset ds = db.getData().get(0).getData();
            return ds.getName() + " (" + formatIntArray(ds.getShape()) + ")";
        } catch (Throwable t) {
            return "";
        }
    }

    public static DataBean dataBeanSubtract(DataBean dataBean1, DataBean dataBean2) {
        DataBean result = (dataBean1 instanceof NexusDataBean) ? new NexusDataBean() : new DataBean();

        Dataset dataSet1 = dataBean1.getData().get(0).getData();
        Dataset dataSet2 = dataBean2.getData().get(0).getData();

        Dataset dataSet = Maths.subtract(dataSet1, dataSet2);

        AxisMapBean axismap = dataBean1.getData().get(0).getAxisMap();
        List<DatasetWithAxisInformation> coll = new ArrayList<DatasetWithAxisInformation>();
        DatasetWithAxisInformation dswai = new DatasetWithAxisInformation();
        dswai.setAxisMap(axismap);
        dswai.setData(dataSet);
        coll.add(dswai);

        result.setData(coll);
        if (dataBean1 instanceof NexusDataBean)
            ((NexusDataBean) result).setNexusTrees(((NexusDataBean) dataBean1).getNexusTrees());
        result.setAxisData(dataBean1.getAxisData());
        return result;
    }

    public static DataBean dataBeanAdd(DataBean dataBean1, DataBean dataBean2) {
        DataBean result = (dataBean1 instanceof NexusDataBean) ? new NexusDataBean() : new DataBean();

        Dataset dataSet1 = dataBean1.getData().get(0).getData();
        Dataset dataSet2 = dataBean2.getData().get(0).getData();
        Dataset dataSet = Maths.add(dataSet1, dataSet2);

        AxisMapBean axismap = dataBean1.getData().get(0).getAxisMap();
        List<DatasetWithAxisInformation> coll = new ArrayList<DatasetWithAxisInformation>();
        DatasetWithAxisInformation dswai = new DatasetWithAxisInformation();
        dswai.setAxisMap(axismap);
        dswai.setData(dataSet);
        coll.add(dswai);

        result.setData(coll);
        if (dataBean1 instanceof NexusDataBean)
            ((NexusDataBean) result).setNexusTrees(((NexusDataBean) dataBean1).getNexusTrees());
        result.setAxisData(dataBean1.getAxisData());
        return result;
    }

    protected void enableDisableMaths() {
        btnPlotA.setEnabled(dataBeanA != null);
        btnPlotB.setEnabled(dataBeanB != null);

        boolean samerank = false;
        if (dataBeanA != null && dataBeanB != null) {
            int[] dimA = dataBeanA.getData().get(0).getData().getShape();
            int[] dimB = dataBeanB.getData().get(0).getData().getShape();
            samerank = Arrays.equals(dimA, dimB);
        }
        btnPlotAb.setEnabled(samerank);
        btnPlotBa.setEnabled(samerank);
        btnPlotAnB.setEnabled(samerank);
    }

    @Override
    public void setFocus() {
    }

    @Override
    public void update(Object theObserved, Object changeCode) {
        if (parentComp.isDisposed()) {
            return;
        }

        //      if (changeCode instanceof NexusDataBean) {
        //         currentBean = (NexusDataBean) changeCode;
        //         processData(currentBean);
        //      }
        if (changeCode instanceof DataBean) {
            currentBean = (DataBean) changeCode;
            processData(currentBean);
        }
    }

    protected void processData(DataBean bean) {
        // do stuff with new data
        List<DatasetWithAxisInformation> dc = bean.getData();
        final Dataset d = dc.get(0).getData();
        parentComp.getDisplay().asyncExec(new Runnable() {
            @Override
            public void run() {
                btnStoreCurrentAsA.setEnabled(true);
                btnStoreCurrentAsB.setEnabled(true);
                try {
                    textMaxVal.setText(formatNumber(d.max()));
                    textMaxPos.setText(formatIntArray(d.maxPos()));
                } catch (UnsupportedOperationException e) {
                    textMaxVal.setText("n/a");
                    textMaxPos.setText("");
                }
                try {
                    textMinVal.setText(formatNumber(d.min()));
                    textMinPos.setText(formatIntArray(d.minPos()));
                } catch (UnsupportedOperationException e) {
                    textMinVal.setText("n/a");
                    textMinPos.setText("");
                }
                textSum.setText(formatObject(d.sum()));
                textMean.setText(formatObject(d.mean()));
            }
        });
    }

    private String formatObject(Object o) {
        if (o instanceof Number) {
            return formatNumber((Number) o);
        } else if (o instanceof double[]) {
            return formatDoubleArray((double[]) o);
        } else if (o instanceof Complex) {
            Complex z = (Complex) o;
            double i = z.getImaginary();
            if (i < 0)
                return String.format(doubleFormat + " - " + doubleFormat + "j", z.getReal(), i);
            return String.format(doubleFormat + " + " + doubleFormat + "j", z.getReal(), i);
        }

        return o.toString();
    }

    private String formatNumber(Number n) {
        if (n instanceof Double || n instanceof Float) {
            return String.format(doubleFormat, n.doubleValue());
        }
        return n.toString();
    }

    private String formatDoubleArray(double[] array) {
        if (array == null || array.length == 0) {
            return "";
        }

        StringBuilder sb = new StringBuilder(String.format(doubleFormat, array[0]));
        for (int i = 1; i < array.length; i++) {
            sb.append(", ");
            sb.append(String.format(doubleFormat, array[array.length - i]));
        }
        return sb.toString();
    }

    private static String formatIntArray(int[] array) {
        if (array == null || array.length == 0) {
            return "";
        }

        StringBuilder sb = new StringBuilder(String.format("%d", array[0]));
        for (int i = 1; i < array.length; i++) {
            sb.append(String.format(", %d", array[array.length - i]));
        }
        return sb.toString();
    }

    protected void pushToPlotView(DataBean dBean) {
        if (plotView == null) {
            return;
        }

        List<DatasetWithAxisInformation> dc = dBean.getData();
        Dataset data = dc.get(0).getData();
        if (data.getRank() == 1) {
            plotView.updatePlotMode(GuiPlotMode.ONED);
        } else if (data.getRank() == 2) {
            plotView.updatePlotMode(GuiPlotMode.TWOD);
        }

        plotView.processPlotUpdate(dBean);
        currentBean = dBean;
    }
}