org.dawnsci.plotting.tools.diffraction.DiffractionTool.java Source code

Java tutorial

Introduction

Here is the source code for org.dawnsci.plotting.tools.diffraction.DiffractionTool.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.plotting.tools.diffraction;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;

import javax.measure.quantity.Quantity;
import javax.swing.tree.TreeNode;

import org.dawb.common.ui.menu.CheckableActionGroup;
import org.dawb.common.ui.menu.MenuAction;
import org.dawb.common.ui.monitor.ProgressMonitorWrapper;
import org.dawb.common.ui.util.EclipseUtils;
import org.dawb.common.ui.util.GridUtils;
import org.dawb.common.ui.viewers.TreeNodeContentProvider;
import org.dawb.common.ui.wizard.persistence.PersistenceExportWizard;
import org.dawb.common.ui.wizard.persistence.PersistenceImportWizard;
import org.dawnsci.common.widgets.tree.ClearableFilteredTree;
import org.dawnsci.common.widgets.tree.DelegatingProviderWithTooltip;
import org.dawnsci.common.widgets.tree.IResettableExpansion;
import org.dawnsci.common.widgets.tree.NodeFilter;
import org.dawnsci.common.widgets.tree.NodeLabelProvider;
import org.dawnsci.common.widgets.tree.NumericNode;
import org.dawnsci.common.widgets.tree.UnitEditingSupport;
import org.dawnsci.common.widgets.tree.ValueEditingSupport;
import org.dawnsci.plotting.tools.Activator;
import org.dawnsci.plotting.tools.preference.DiffractionDefaultsPreferencePage;
import org.dawnsci.plotting.tools.preference.detector.DiffractionDetectorPreferencePage;
import org.dawnsci.plotting.tools.preference.diffraction.DiffractionPreferencePage;
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.diffraction.DetectorProperties;
import org.eclipse.dawnsci.analysis.api.diffraction.DetectorPropertyEvent;
import org.eclipse.dawnsci.analysis.api.diffraction.DiffractionCrystalEnvironment;
import org.eclipse.dawnsci.analysis.api.diffraction.DiffractionCrystalEnvironmentEvent;
import org.eclipse.dawnsci.analysis.api.diffraction.IDetectorPropertyListener;
import org.eclipse.dawnsci.analysis.api.diffraction.IDiffractionCrystalEnvironmentListener;
import org.eclipse.dawnsci.analysis.api.io.ILoaderService;
import org.eclipse.dawnsci.analysis.api.metadata.IDiffractionMetadata;
import org.eclipse.dawnsci.analysis.api.metadata.IMetadata;
import org.eclipse.dawnsci.analysis.api.roi.IROI;
import org.eclipse.dawnsci.analysis.dataset.impl.BooleanDataset;
import org.eclipse.dawnsci.analysis.dataset.impl.Dataset;
import org.eclipse.dawnsci.analysis.dataset.roi.CircularFitROI;
import org.eclipse.dawnsci.analysis.dataset.roi.CircularROI;
import org.eclipse.dawnsci.analysis.dataset.roi.EllipticalFitROI;
import org.eclipse.dawnsci.analysis.dataset.roi.EllipticalROI;
import org.eclipse.dawnsci.analysis.dataset.roi.PolylineROI;
import org.eclipse.dawnsci.analysis.dataset.roi.SectorROI;
import org.eclipse.dawnsci.plotting.api.IPlottingSystem;
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.region.RegionUtils;
import org.eclipse.dawnsci.plotting.api.region.IRegion.RegionType;
import org.eclipse.dawnsci.plotting.api.tool.AbstractToolPage;
import org.eclipse.dawnsci.plotting.api.tool.IToolPage;
import org.eclipse.dawnsci.plotting.api.tool.IToolPageSystem;
import org.eclipse.dawnsci.plotting.api.trace.IImageTrace;
import org.eclipse.dawnsci.plotting.api.trace.ITraceListener;
import org.eclipse.dawnsci.plotting.api.trace.TraceEvent;
import org.eclipse.draw2d.ColorConstants;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.preference.JFacePreferences;
import org.eclipse.jface.preference.PreferenceDialog;
import org.eclipse.jface.resource.ColorRegistry;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.viewers.ColumnViewerToolTipSupport;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.TreeViewerColumn;
import org.eclipse.jface.wizard.IWizard;
import org.eclipse.jface.wizard.WizardDialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
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.swt.widgets.Label;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IViewPart;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.dialogs.PreferencesUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import uk.ac.diamond.scisoft.analysis.crystallography.CalibrantSelectedListener;
import uk.ac.diamond.scisoft.analysis.crystallography.CalibrantSelectionEvent;
import uk.ac.diamond.scisoft.analysis.crystallography.CalibrationFactory;
import uk.ac.diamond.scisoft.analysis.crystallography.CalibrationStandards;
import uk.ac.diamond.scisoft.analysis.crystallography.HKL;
import uk.ac.diamond.scisoft.analysis.diffraction.PowderRingsUtils;
import uk.ac.diamond.scisoft.analysis.diffraction.QSpace;
import uk.ac.diamond.scisoft.analysis.fitting.functions.IPeak;

public class DiffractionTool extends AbstractToolPage
        implements CalibrantSelectedListener, IResettableExpansion, IROIListener {

    private static final Logger logger = LoggerFactory.getLogger(DiffractionTool.class);

    private ClearableFilteredTree filteredTree;
    private TreeViewer viewer;
    private Composite control;
    private DiffractionTreeModel model;
    private ILoaderService service;
    private Label statusMessage;
    private String[] statusString = new String[1];

    private static DiffractionTool activeDiffractionTool = null;

    //Region and region listener added for 1-click beam centring
    private IRegion tmpRegion;
    private IRegionListener regionListener;
    private ITraceListener.Stub traceListener;
    private IROIListener roiListener;
    private IDetectorPropertyListener detpropListener;
    private IDiffractionCrystalEnvironmentListener difcrysListener;

    private int lastWavelengthUnit = 0;

    protected DiffractionImageAugmenter augmenter;

    /**
     * Boolean used for Powder diffraction view
     */
    private boolean hide = false;

    @Override
    public ToolPageRole getToolPageRole() {
        return ToolPageRole.ROLE_2D;
    }

    public DiffractionTool() {
        super();

        this.traceListener = new ITraceListener.Stub() {
            protected void update(TraceEvent evt) {
                if (getImageTrace() != null)
                    createDiffractionModel(true);
                updateIntensity();
            }
        };

        this.service = (ILoaderService) PlatformUI.getWorkbench().getService(ILoaderService.class);

    }

    protected void updateIntensity() {
        try {
            if (model == null)
                return;
            model.setIntensityValues(getImageTrace());
        } catch (Exception e) {
            logger.error("Updating intensity values!", e);
        }
    }

    @Override
    public void createControl(final Composite parent) {

        this.control = new Composite(parent, SWT.NONE);
        control.setBackground(Display.getDefault().getSystemColor(SWT.COLOR_WHITE));
        control.setLayout(new GridLayout(1, false));
        GridUtils.removeMargins(control);

        this.filteredTree = new ClearableFilteredTree(control,
                SWT.FULL_SELECTION | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER, new NodeFilter(this), true,
                "Enter search string to filter the tree.\nThis will match on name, value or units");
        viewer = filteredTree.getViewer();
        viewer.getControl().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
        createColumns(viewer);
        viewer.setContentProvider(new TreeNodeContentProvider()); // Swing tree nodes
        viewer.getTree().setLinesVisible(true);
        viewer.getTree().setHeaderVisible(true);

        Composite status = new Composite(control, SWT.NONE);
        status.setLayoutData(new GridData(SWT.FILL, GridData.FILL, true, false));
        status.setBackground(Display.getDefault().getSystemColor(SWT.COLOR_WHITE));
        status.setLayout(new GridLayout(2, true));
        GridUtils.removeMargins(status);

        statusMessage = new Label(status, SWT.LEFT);
        statusMessage.setLayoutData(new GridData(SWT.FILL, GridData.CENTER, true, false));
        ColorRegistry colorRegistry = JFaceResources.getColorRegistry();
        statusMessage.setForeground(
                new Color(statusMessage.getDisplay(), colorRegistry.getRGB(JFacePreferences.QUALIFIER_COLOR)));
        statusMessage.setBackground(Display.getDefault().getSystemColor(SWT.COLOR_WHITE));
        if (statusString != null && statusString[0] != null)
            statusMessage.setText(statusString[0]);

        final Label label = new Label(status, SWT.RIGHT);
        label.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, true, false));
        label.setForeground(new Color(label.getDisplay(), colorRegistry.getRGB(JFacePreferences.QUALIFIER_COLOR)));
        label.setBackground(Display.getDefault().getSystemColor(SWT.COLOR_WHITE));
        label.setText("* Click to change value  ");

        createDiffractionModel(false);
        createActions();
        createListeners();
        //false by default
        if (!hide)
            createToolPageActions();

    }

    public void activate() {
        super.activate();
        createDiffractionModel(true);

        IPlottingSystem plotting = getPlottingSystem();
        if (plotting != null) {
            if (regionListener != null)
                plotting.addRegionListener(regionListener);
            if (traceListener != null)
                plotting.addTraceListener(traceListener);
            if (tmpRegion != null) {
                tmpRegion.setVisible(true);
            }
        }

        if (augmenter != null)
            augmenter.activate();
        CalibrationFactory.addCalibrantSelectionListener(this);
        activeDiffractionTool = this;

        if (calibrantActions != null && calibrantActions.getSelectedAction() != null) {
            calibrantActions.getSelectedAction().run();
        }

        final IDiffractionMetadata dmd = getDiffractionMetaData();
        if (viewer != null && viewer.getInput() != null && model != null && dmd != null
                && dmd.getDetector2DProperties() != null
                && dmd.getOriginalDiffractionCrystalEnvironment() != null) {
            try {
                viewer.refresh();
            } catch (Throwable ne) {
                // Sometimes model could not be resolved at this point.
            }
        }
    }

    public void deactivate() {

        if (!isActive()) {
            return;
        }

        super.deactivate();
        IPlottingSystem plotting = getPlottingSystem();
        if (plotting != null) {
            plotting.removeRegionListener(regionListener);
            if (traceListener != null)
                plotting.removeTraceListener(traceListener);
            if (tmpRegion != null) {
                tmpRegion.setVisible(false);
            }
        }

        CalibrationFactory.removeCalibrantSelectionListener(this);
        if (augmenter != null)
            augmenter.deactivate(service.getLockedDiffractionMetaData() != null);
        if (activeDiffractionTool == this)
            activeDiffractionTool = null;
        if (model != null)
            model.deactivate();

        IDiffractionMetadata data = getDiffractionMetaData();
        if (data != null && data.getDetector2DProperties() != null
                && data.getDiffractionCrystalEnvironment() != null) {
            data.getDetector2DProperties().removeDetectorPropertyListener(detpropListener);
            data.getDiffractionCrystalEnvironment().removeDiffractionCrystalEnvironmentListener(difcrysListener);
        }
    }

    public void dispose() {
        super.dispose();
        if (model != null)
            model.dispose();
        if (augmenter != null)
            augmenter.dispose();
    }

    private void createDiffractionModel(boolean force) {

        if (!force && model != null)
            return;

        if (force && model != null) {
            TreeNode node = model.getNode("/experimental information/wavelength");
            if (node != null) {
                try {
                    lastWavelengthUnit = ((NumericNode<?>) node).getUnitIndex();
                } catch (Exception e) {
                    //nothing
                }

            }
            model.dispose();
            model = null;
        }
        if (viewer == null)
            return;

        IDiffractionMetadata data = null;
        try {
            data = getDiffractionMetaData();
            if (data == null || data.getDetector2DProperties() == null
                    || data.getDiffractionCrystalEnvironment() == null) {
                return;
            }
            model = new DiffractionTreeModel(data, hide);

            model.setViewer(viewer);
            model.activate();
            if (augmenter != null) {
                augmenter.setDiffractionMetadata(data);
            }

            updateIntensity();

            detpropListener = new IDetectorPropertyListener() {
                @Override
                public void detectorPropertiesChanged(DetectorPropertyEvent evt) {
                    if (evt.getSource() instanceof DetectorProperties)
                        DiffractionDefaultMetadata
                                .setPersistedDetectorPropertieValues((DetectorProperties) evt.getSource());

                }
            };

            difcrysListener = new IDiffractionCrystalEnvironmentListener() {
                @Override
                public void diffractionCrystalEnvironmentChanged(DiffractionCrystalEnvironmentEvent evt) {
                    if (evt.getSource() instanceof DiffractionCrystalEnvironment)
                        DiffractionDefaultMetadata.setPersistedDiffractionCrystalEnvironmentValues(
                                (DiffractionCrystalEnvironment) evt.getSource());

                }
            };

            data.getDetector2DProperties().addDetectorPropertyListener(detpropListener);
            data.getDiffractionCrystalEnvironment().addDiffractionCrystalEnvironmentListener(difcrysListener);

            TreeNode node = model.getNode("/experimental information/wavelength");
            if (node != null) {
                try {
                    ((NumericNode<?>) node).setUnitIndex(lastWavelengthUnit);
                } catch (Exception e) {
                    //nothing
                }

            }

        } catch (Exception e) {
            logger.error("Cannot create model!", e);
            return;
        }

        viewer.setInput(model.getRoot());
        model.activate();

        resetExpansion();
        getSite().setSelectionProvider(viewer);

    }

    public void resetExpansion() {
        try {
            if (model == null)
                return;
            final List<?> top = model.getRoot().getChildren();
            for (Object element : top) {
                filteredTree.expand(element);
            }
        } catch (Throwable ne) {
            // intentionally silent
        }
    }

    private IDiffractionMetadata getDiffractionMetaData() {
        IDataset image = getImageTrace() == null ? null : getImageTrace().getData();
        if (image == null)
            return null;
        IWorkbenchPart part = getPart();
        String altPath = null;
        if (part instanceof IEditorPart) {
            altPath = EclipseUtils.getFilePath(((IEditorPart) part).getEditorInput());
        } else if (part instanceof IViewPart) {
            try {
                IMetadata md = image.getMetadata();
                if (md != null)
                    altPath = md.getFilePath();
            } catch (Exception e) {
                logger.debug("Exception getting the image metadata", e);
            }
        }
        //Add the meta data to the data set
        IDiffractionMetadata md = DiffractionUtils.getDiffractionMetadata(image, altPath, service, statusString);
        image.setMetadata(md);
        return md;
    }

    private TreeViewerColumn defaultColumn;

    private void createColumns(TreeViewer viewer) {

        viewer.setColumnProperties(new String[] { "Name", "Original", "Value", "Unit" });
        ColumnViewerToolTipSupport.enableFor(viewer);

        TreeViewerColumn var = new TreeViewerColumn(viewer, SWT.LEFT, 0);
        var.getColumn().setText("Name"); // Selected
        var.getColumn().setWidth(260);
        var.setLabelProvider(new NodeLabelProvider(0));

        var = new TreeViewerColumn(viewer, SWT.LEFT, 1);
        var.getColumn().setText("Original"); // Selected
        var.getColumn().setWidth(0);
        var.getColumn().setResizable(false);
        var.setLabelProvider(new DelegatingProviderWithTooltip(new NodeLabelProvider(1)));
        defaultColumn = var;

        var = new TreeViewerColumn(viewer, SWT.LEFT, 2);
        var.getColumn().setText("Value"); // Selected
        var.getColumn().setWidth(100);
        var.setLabelProvider(new DelegatingProviderWithTooltip(new NodeLabelProvider(2)));
        var.setEditingSupport(new ValueEditingSupport(viewer));

        var = new TreeViewerColumn(viewer, SWT.LEFT, 3);
        var.getColumn().setText("Unit"); // Selected
        var.getColumn().setWidth(90);
        var.setLabelProvider(new DelegatingProviderWithTooltip(new NodeLabelProvider(3)));
        var.setEditingSupport(new UnitEditingSupport(viewer));
    }

    /**
     * 
     * @return model
     */
    public DiffractionTreeModel getModel() {
        return model;
    }

    /**
     * 
     * @return augmenter
     */
    public DiffractionImageAugmenter getAugmenter() {
        return augmenter;
    }

    private TreeNode copiedNode;
    private MenuAction calibrantActions;
    private CheckableActionGroup calibrantGroup;
    private Action calPref;

    private Action refine;
    private Action findOuter;
    private Action calibrate;

    private static Action lock;

    private void createActions() {

        final Action exportMeta = new Action("Export metadata to file",
                Activator.getImageDescriptor("icons/mask-export-wiz.png")) {
            public void run() {
                try {
                    IWizard wiz = EclipseUtils.openWizard(PersistenceExportWizard.ID, false);
                    WizardDialog wd = new WizardDialog(Display.getCurrent().getActiveShell(), wiz);
                    wd.setTitle(wiz.getWindowTitle());
                    wd.open();
                } catch (Exception e) {
                    logger.error("Problem opening export!", e);
                }
            }
        };

        final Action importMeta = new Action("Import metadata from file",
                Activator.getImageDescriptor("icons/mask-import-wiz.png")) {
            public void run() {
                try {
                    IWizard wiz = EclipseUtils.openWizard(PersistenceImportWizard.ID, false);
                    WizardDialog wd = new WizardDialog(Display.getCurrent().getActiveShell(), wiz);
                    wd.setTitle(wiz.getWindowTitle());
                    wd.open();
                } catch (Exception e) {
                    logger.error("Problem opening import!", e);
                }
            }
        };

        final Action showDefault = new Action("Show the original/default value column",
                Activator.getImageDescriptor("icons/plot-tool-diffraction-default.gif")) {
            public void run() {
                defaultColumn.getColumn().setWidth(isChecked() ? 80 : 0);
                defaultColumn.getColumn().setResizable(!isChecked());
            }
        };
        showDefault.setChecked(false);

        final Action reset = new Action("Reset selected field", Activator.getImageDescriptor("icons/reset.gif")) {
            @Override
            public void run() {
                final TreeNode node = (TreeNode) ((StructuredSelection) viewer.getSelection()).getFirstElement();
                if (node instanceof NumericNode) {
                    ((NumericNode<?>) node).reset();
                    viewer.refresh(node);
                }
            }
        };
        final Action resetAll = new Action("Reset all fields",
                Activator.getImageDescriptor("icons/reset_red.png")) {
            @Override
            public void run() {

                boolean ok = MessageDialog.openConfirm(Display.getDefault().getActiveShell(), "Confirm Reset All",
                        "Are you sure that you would like to reset all values?");
                if (!ok)
                    return;
                filteredTree.clearText();
                if (service.getLockedDiffractionMetaData() != null) {
                    model.reset();
                    viewer.refresh();
                    resetExpansion();
                } else {
                    model.reset();
                    createDiffractionModel(true);
                    viewer.refresh();
                }
            }
        };

        final Action copy = new Action("Copy value", Activator.getImageDescriptor("icons/copy.gif")) {
            @Override
            public void run() {
                copiedNode = (TreeNode) ((StructuredSelection) viewer.getSelection()).getFirstElement();
            }
        };

        final Action paste = new Action("Paste value", Activator.getImageDescriptor("icons/paste.gif")) {
            @SuppressWarnings("unchecked")
            @Override
            public void run() {
                if (copiedNode != null) {
                    Object object = ((StructuredSelection) viewer.getSelection()).getFirstElement();
                    if (object instanceof NumericNode) {
                        NumericNode<Quantity> nn = (NumericNode<Quantity>) object;
                        if (!nn.isEditable()) {
                            MessageDialog.openWarning(Display.getDefault().getActiveShell(), "Cannot paste",
                                    "The item '" + nn.getLabel()
                                            + "' is not writable.\n\nPlease choose a different value to paste to.");
                            return;
                        }

                        try {
                            nn.mergeValue(copiedNode);
                        } catch (Throwable e) {
                            try {
                                if (EclipseUtils.getActivePage()
                                        .findView("org.eclipse.pde.runtime.LogView") == null) {
                                    EclipseUtils.getActivePage().showView("org.eclipse.pde.runtime.LogView");
                                }
                            } catch (PartInitException pe) {
                                // Ignored.
                            }
                            IStatus status = new Status(IStatus.INFO, Activator.PLUGIN_ID,
                                    "Cannot past into '" + nn.getLabel() + "'", e);
                            Activator.getPluginLog().log(status);
                        }
                        viewer.refresh(object);
                    }
                }
            }
        };

        final Action centre = new Action("One-click beam centre", IAction.AS_PUSH_BUTTON) {
            @Override
            public void run() {
                logger.debug("1-click clicked");

                IPlottingSystem plotter = getPlottingSystem();
                if (plotter == null) {
                    logger.debug("No plotting system found");
                    return;
                }

                try {
                    clearRegions(plotter);
                    if (tmpRegion != null) {
                        plotter.removeRegion(tmpRegion);
                    }
                    tmpRegion = plotter.createRegion(RegionUtils.getUniqueName("BeamCentrePicker", plotter),
                            IRegion.RegionType.POINT);
                    tmpRegion.setUserRegion(false);
                    tmpRegion.setVisible(false);
                    refine.setEnabled(true);
                } catch (Exception e) {
                    logger.error("Cannot add beam centre", e);
                }

            }
        };
        centre.setImageDescriptor(Activator.getImageDescriptor("icons/centre.png"));

        final Action fitRing = new Action("Fit ring", IAction.AS_PUSH_BUTTON) {
            @Override
            public void run() {
                logger.debug("Fit ring clicked");

                IPlottingSystem plotter = getPlottingSystem();
                if (plotter == null) {
                    logger.debug("No plotting system found");
                    return;
                }

                try {
                    clearRegions(plotter);
                    if (tmpRegion != null) {
                        plotter.removeRegion(tmpRegion);
                    }
                    tmpRegion = plotter.createRegion(RegionUtils.getUniqueName("RingPicker", plotter),
                            IRegion.RegionType.ELLIPSEFIT);
                    tmpRegion.setShowLabel(false);
                    tmpRegion.setUserRegion(false);
                    tmpRegion.addROIListener(roiListener);
                    findOuter.setEnabled(true);
                    refine.setEnabled(true);
                } catch (Exception e) {
                    logger.error("Cannot add ring", e);
                }
            }
        };
        fitRing.setImageDescriptor(Activator.getImageDescriptor("icons/eclipsecirclepoints.png"));
        fitRing.setToolTipText("Select 3 or 4 points on ring to fit a circle or 5 points or more for an ellipse");

        refine = new Action("Refine beam centre", IAction.AS_PUSH_BUTTON) {

            class Compare implements Comparator<IPeak> {

                @Override
                public int compare(IPeak o1, IPeak o2) {
                    if (o1.getPosition() > o2.getPosition()) {
                        return 1;
                    }
                    if (o1.getPosition() < o2.getPosition()) {
                        return -1;
                    }
                    return 0;
                }

            }

            @SuppressWarnings("unchecked")
            private List<IPeak> loadPeaks() {
                IToolPage radialTool = getToolSystem()
                        .getToolPage("org.dawb.workbench.plotting.tools.radialProfileTool");
                IToolPage fittingTool = ((IToolPageSystem) radialTool.getToolPlottingSystem())
                        .getToolPage("org.dawb.workbench.plotting.tools.fittingTool");
                if (fittingTool != null) {
                    List<IPeak> fittedPeaks = (List<IPeak>) fittingTool.getAdapter(IPeak.class);

                    if (fittedPeaks != null) {
                        Collections.sort(fittedPeaks, new Compare());

                        ArrayList<IPeak> peaks = new ArrayList<IPeak>(fittedPeaks.size());
                        if (peaks != null && peaks.size() > 0)
                            peaks.clear();
                        for (IPeak peak : fittedPeaks) {
                            peaks.add(peak);
                        }
                        return peaks;
                    }
                }

                return null;
            }

            @Override
            public void run() {
                final IPlottingSystem plotter = getPlottingSystem();
                final IImageTrace t = getImageTrace();
                if (tmpRegion.getRegionType() == RegionType.ELLIPSEFIT
                        || tmpRegion.getRegionType() == RegionType.CIRCLEFIT) {
                    final Display display = control.getDisplay();
                    if (t != null) {
                        Job job = new Job("Circle fit refinement") {
                            @Override
                            protected IStatus run(final IProgressMonitor monitor) {
                                IROI roi = runEllipseFit(monitor, display, plotter, t, tmpRegion.getROI(), true,
                                        RADIAL_DELTA);
                                if (roi == null)
                                    return Status.CANCEL_STATUS;

                                return drawRing(monitor, display, plotter, roi, true);
                            }
                        };
                        job.setPriority(Job.SHORT);
                        //                  job.setUser(true);
                        job.schedule();

                    }
                    return;
                }
                try {

                    Collection<IRegion> regions = plotter.getRegions(RegionType.SECTOR);
                    if (regions.size() == 0) {
                        throw new IllegalStateException();
                    }
                    SectorROI sroi = (SectorROI) regions.iterator().next().getROI();
                    Dataset dataset = (Dataset) t.getData();
                    Dataset mask = (Dataset) t.getMask();
                    final BeamCenterRefinement beamOffset = new BeamCenterRefinement(dataset, mask, sroi);
                    List<IPeak> peaks = loadPeaks();
                    if (peaks == null)
                        throw new Exception("Cannot find peaks!");
                    beamOffset.setInitPeaks(peaks);

                    beamOffset.optimize(getDiffractionMetaData().getDetector2DProperties().getBeamCentreCoords());
                } catch (Throwable ne) {

                    /**
                     * Long discussion with Iralki on this. The algorithm must be set up in a particular way to 
                     * run at the moment. 
                     */
                    ConfigurableMessageDialog dialog = new ConfigurableMessageDialog(
                            Display.getDefault().getActiveShell(), "Experimental Refinement Algorithm Incomplete",
                            null,
                            "Could not read peak positions to start refinement.\nThis tool is still under development. To perform the refinement, use the following procedure:\n\n"
                                    + "1. Open the 'Diffraction' tool in a dedicated view (action on the right of the toolbar).\n"
                                    + "2. Open the 'Radial Profile' tool (from the plot containing the image).\n"
                                    + "3. Select a sector which bisects the rings wanted.\n"
                                    + "4. In the 'Radial Profile' tool press 'Lock to Metadata' button.\n"
                                    + "5. Select 'q' from the 'Select x axis values' list in the 'Radial Profile' toolbar.\n"
                                    + "6. In the 'Radial Profile' tool select peak fitting.\n"
                                    + "7. Set up a peak fit on all the rings which the radial profile found.\n"
                                    + "8. Now run the refine action in the diffraction tool again.\n\n"
                                    + "Please note that the algorithm may not converge. A job is run for the refinement which may be stopped.\n"
                                    + "Please contact your support representative for more training/help with refinement.\n\n"
                                    + "(NOTE: This dialog can be kept open as a guide while doing the proceedure.)",
                            MessageDialog.INFORMATION, new String[] { IDialogConstants.OK_LABEL }, 0);
                    dialog.setShellStyle(SWT.SHELL_TRIM | SWT.MODELESS);
                    dialog.open();
                }
            }
        };
        refine.setImageDescriptor(Activator.getImageDescriptor("icons/refine.png"));
        refine.setEnabled(false);

        findOuter = new Action("Find outer rings", IAction.AS_PUSH_BUTTON) {
            @Override
            public void run() {
                logger.debug("Find outer rings clicked");

                if (tmpRegion.getRegionType() == RegionType.ELLIPSEFIT
                        || tmpRegion.getRegionType() == RegionType.CIRCLEFIT) {
                    final IPlottingSystem plotter = getPlottingSystem();
                    final IImageTrace t = getImageTrace();
                    final Display display = control.getDisplay();
                    if (t != null) {
                        Job job = new Job("Ellipse rings finding") {
                            @Override
                            protected IStatus run(final IProgressMonitor monitor) {
                                IROI roi = tmpRegion.getROI();
                                boolean circle = roi instanceof CircularROI;
                                roi = runEllipseFit(monitor, display, plotter, t, roi, circle, RADIAL_DELTA);
                                if (roi == null)
                                    return Status.CANCEL_STATUS;

                                IStatus stat = drawRing(monitor, display, plotter, roi, circle);
                                if (stat.isOK()) {
                                    stat = runFindOuterRings(monitor, display, plotter, t, roi);
                                }
                                return stat;
                            }
                        };
                        job.setPriority(Job.SHORT);
                        //                  job.setUser(true);
                        job.schedule();
                    }
                    return;
                } else {
                    ConfigurableMessageDialog dialog = new ConfigurableMessageDialog(
                            Display.getDefault().getActiveShell(), "Rings locator - no initial ring", null,
                            "Please define an initial ring", MessageDialog.INFORMATION,
                            new String[] { IDialogConstants.OK_LABEL }, 0);
                    dialog.setShellStyle(SWT.SHELL_TRIM | SWT.MODELESS);
                    dialog.open();

                }
            }
        };
        findOuter.setImageDescriptor(Activator.getImageDescriptor("icons/findmorerings.png"));
        findOuter.setToolTipText("Find outer rings");
        findOuter.setEnabled(false);

        calibrate = new Action("Calibrate against standard", IAction.AS_PUSH_BUTTON) {
            @Override
            public void run() {
                CalibrationStandards standards = CalibrationFactory.getCalibrationStandards();
                String name = standards.getSelectedCalibrant();
                if (name != null) {
                    logger.debug("Calibrating against {}", name);
                    final List<HKL> spacings = standards.getCalibrationPeakMap(name).getHKLs();

                    final IPlottingSystem plotter = getPlottingSystem();
                    final IImageTrace t = getImageTrace();
                    final Display display = control.getDisplay();
                    if (t != null) {
                        Job job = new Job("Calibrating detector") {
                            @Override
                            protected IStatus run(final IProgressMonitor monitor) {
                                return runCalibrateDetector(monitor, display, plotter, spacings);
                            }
                        };
                        job.setPriority(Job.SHORT);
                        //                  job.setUser(true);
                        job.schedule();

                    }
                    return;
                } else {
                    ConfigurableMessageDialog dialog = new ConfigurableMessageDialog(
                            Display.getDefault().getActiveShell(), "Calibrator - no standard selected", null,
                            "Please define calibrant", MessageDialog.INFORMATION,
                            new String[] { IDialogConstants.OK_LABEL }, 0);
                    dialog.setShellStyle(SWT.SHELL_TRIM | SWT.MODELESS);
                    dialog.open();

                }
            }
        };
        calibrate.setImageDescriptor(Activator.getImageDescriptor("icons/findmorerings.png"));
        calibrate.setToolTipText(
                "Calibrate detector using rings - this is an experimental feature and does not work robustly");
        calibrate.setEnabled(false);

        if (lock == null)
            lock = new Action(
                    "Lock the diffraction data and apply it to newly opened files.\nThis will also leave the rings on the image when the tool is deactivated.",
                    IAction.AS_CHECK_BOX) {
                @Override
                public void run() {
                    if (isChecked()) {
                        IDiffractionMetadata data = activeDiffractionTool.getDiffractionMetaData().clone();
                        service.setLockedDiffractionMetaData(data);
                    } else {
                        // Also clears cached data because we may have
                        // changed the meta data.
                        service.setLockedDiffractionMetaData(null);
                    }
                    activeDiffractionTool.createDiffractionModel(true);
                }
            };
        lock.setImageDescriptor(Activator.getImageDescriptor("icons/lock.png"));

        this.calPref = new Action("Configure Calibrants...") {
            @Override
            public void run() {
                PreferenceDialog pref = PreferencesUtil.createPreferenceDialogOn(
                        PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(),
                        DiffractionPreferencePage.ID, null, null);
                if (pref != null)
                    pref.open();
            }
        };

        Action configDetectors = new Action("Configure Detectors...") {
            @Override
            public void run() {
                PreferenceDialog pref = PreferencesUtil.createPreferenceDialogOn(
                        PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(),
                        DiffractionDetectorPreferencePage.ID, null, null);
                if (pref != null)
                    pref.open();
            }
        };

        Action configDefaultMeta = new Action("Configure Default Metadata...") {
            @Override
            public void run() {
                PreferenceDialog pref = PreferencesUtil.createPreferenceDialogOn(
                        PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(),
                        DiffractionDefaultsPreferencePage.ID, null, null);
                if (pref != null)
                    pref.open();
            }
        };

        this.calibrantActions = new MenuAction("Calibrants");
        calibrantActions.setImageDescriptor(Activator.getImageDescriptor("/icons/calibrant_rings.png"));
        this.calibrantGroup = new CheckableActionGroup();
        updateCalibrationActions(CalibrationFactory.getCalibrationStandards());

        MenuAction dropdown = new MenuAction("Resolution rings");
        dropdown.setImageDescriptor(Activator.getImageDescriptor("/icons/resolution_rings.png"));

        if (!hide) {
            augmenter = new DiffractionImageAugmenter(getPlottingSystem());
            augmenter.addActions(dropdown);
        }

        IToolBarManager toolMan = getSite().getActionBars().getToolBarManager();
        final MenuManager menuMan = new MenuManager();

        // false by default
        if (!hide) {
            toolMan.add(importMeta);
            toolMan.add(exportMeta);
            toolMan.add(new Separator());
            toolMan.add(lock);
            toolMan.add(new Separator());
            toolMan.add(dropdown);
            toolMan.add(calibrantActions);
            toolMan.add(new Separator());
            toolMan.add(centre);
            toolMan.add(fitRing);
            toolMan.add(refine);
            toolMan.add(findOuter);
            toolMan.add(calibrate);
            toolMan.add(new Separator());
            toolMan.add(reset);
            toolMan.add(resetAll);
            toolMan.add(new Separator());
            toolMan.add(showDefault);
            toolMan.add(new Separator());
        }

        menuMan.add(dropdown);
        menuMan.add(centre);
        menuMan.add(fitRing);
        menuMan.add(refine);
        menuMan.add(findOuter);
        menuMan.add(calibrate);
        menuMan.add(new Separator());
        menuMan.add(reset);
        menuMan.add(resetAll);
        menuMan.add(new Separator());
        menuMan.add(copy);
        menuMan.add(paste);
        menuMan.add(new Separator());
        menuMan.add(showDefault);
        menuMan.add(new Separator());
        menuMan.add(calPref);

        final Menu menu = menuMan.createContextMenu(viewer.getControl());
        viewer.getControl().setMenu(menu);

        if (!hide) {
            getSite().getActionBars().getMenuManager().add(new Separator());
            getSite().getActionBars().getMenuManager().add(calPref);
            getSite().getActionBars().getMenuManager().add(configDetectors);
            getSite().getActionBars().getMenuManager().add(configDefaultMeta);
            getSite().getActionBars().getMenuManager().add(new Separator());
        }
    }

    public void hideToolBar(boolean hide) {
        this.hide = hide;
    }

    private static final String RING_PREFIX = "Ring";

    private void clearRegions(IPlottingSystem plotter) {
        Collection<IRegion> regions = plotter.getRegions();
        for (IRegion r : regions) {
            String n = r.getName();
            if (n.startsWith(RING_PREFIX))
                plotter.removeRegion(r);
        }
    }

    private static final double ARC_LENGTH = 8;
    private static final double RADIAL_DELTA = 10;
    private static final int MAX_POINTS = 200;

    public static IROI runEllipseFit(final IProgressMonitor monitor, Display display, final IPlottingSystem plotter,
            IImageTrace t, IROI roi, final boolean circle, double radialDelta) {
        if (roi == null)
            return null;

        String shape = circle ? "circle" : "ellipse";
        final ProgressMonitorWrapper mon = new ProgressMonitorWrapper(monitor);
        monitor.beginTask("Refine " + shape + " fit", IProgressMonitor.UNKNOWN);
        monitor.subTask("Find POIs near initial " + shape);
        Dataset image = (Dataset) t.getData();
        BooleanDataset mask = (BooleanDataset) t.getMask();
        PolylineROI points;
        EllipticalFitROI efroi;
        monitor.subTask("Fit POIs");
        points = roi instanceof CircularROI
                ? PowderRingsUtils.findPOIsNearCircle(mon, image, mask, (CircularROI) roi, ARC_LENGTH, radialDelta,
                        MAX_POINTS)
                : PowderRingsUtils.findPOIsNearEllipse(mon, image, mask, (EllipticalROI) roi, ARC_LENGTH,
                        radialDelta, MAX_POINTS);
        if (points.getNumberOfPoints() < 3) {
            throw new IllegalArgumentException("Could not find enough points to trim");
        }

        monitor.subTask("Trim POIs");
        efroi = PowderRingsUtils.fitAndTrimOutliers(mon, points, 2, circle);
        logger.debug("Found {}...", efroi);

        int npts = efroi.getPoints().getNumberOfPoints();
        int lpts;
        do {
            lpts = npts;
            points = PowderRingsUtils.findPOIsNearEllipse(mon, image, mask, (EllipticalROI) efroi);

            efroi = PowderRingsUtils.fitAndTrimOutliers(mon, points, 2, circle);
            npts = efroi.getPoints().getNumberOfPoints();
        } while (lpts > npts);

        if (monitor.isCanceled())
            return null;

        final IROI froi = circle ? new CircularFitROI(efroi.getPoints()) : efroi;
        monitor.worked(1);
        logger.debug("Fitted {} from peaks: {}", shape, froi);

        return froi;
    }

    private IStatus drawRing(final IProgressMonitor monitor, Display display, final IPlottingSystem plotter,
            final IROI froi, final boolean circle) {
        final boolean[] status = { true };
        display.syncExec(new Runnable() {

            public void run() {
                try {
                    long t = -System.currentTimeMillis();
                    IRegion region = plotter.createRegion(RegionUtils.getUniqueName("Pixel peaks", plotter),
                            circle ? RegionType.CIRCLEFIT : RegionType.ELLIPSEFIT);
                    region.setROI(froi);
                    region.setRegionColor(circle ? ColorConstants.cyan : ColorConstants.orange);
                    plotter.removeRegion(tmpRegion);
                    monitor.subTask("Add region");
                    tmpRegion = region;
                    tmpRegion.setUserRegion(false);
                    tmpRegion.addROIListener(roiListener);
                    roiListener.roiSelected(new ROIEvent(tmpRegion, froi)); // trigger beam centre update
                    plotter.addRegion(region);
                    System.err.println("Time taken " + (t + System.currentTimeMillis()) + "ms");
                    monitor.worked(1);
                    findOuter.setEnabled(true);
                } catch (Exception e) {
                    status[0] = false;
                }
            }
        });

        return status[0] ? Status.OK_STATUS : Status.CANCEL_STATUS;
    }

    private IStatus runFindOuterRings(final IProgressMonitor monitor, Display display,
            final IPlottingSystem plotter, IImageTrace t, IROI roi) {
        final ProgressMonitorWrapper mon = new ProgressMonitorWrapper(monitor);
        monitor.beginTask("Find elliptical rings", IProgressMonitor.UNKNOWN);
        monitor.subTask("Find rings");
        if (roi instanceof CircularFitROI) {
            roi = new EllipticalFitROI(((CircularFitROI) roi).getPoints(), true);
        }
        final List<EllipticalROI> ells = PowderRingsUtils.findOtherEllipses(mon, (Dataset) t.getData(),
                (BooleanDataset) t.getMask(), (EllipticalROI) roi);
        final boolean[] status = { true };
        display.syncExec(new Runnable() {

            public void run() {
                try {
                    int emax = ells.size();
                    if (emax > 0)
                        plotter.removeRegion(tmpRegion);
                    for (int i = 0; i < emax; i++) {
                        monitor.subTask("Add region: " + i);
                        EllipticalROI e = ells.get(i);
                        logger.debug("Ellipse from peaks: {}, {}", i, e);
                        IRegion region = plotter.createRegion(RegionUtils.getUniqueName(RING_PREFIX, plotter),
                                e instanceof EllipticalFitROI ? RegionType.ELLIPSEFIT : RegionType.ELLIPSE);
                        region.setMobile(false);
                        region.setROI(e);
                        region.setRegionColor(ColorConstants.orange);
                        region.setUserRegion(false);
                        plotter.addRegion(region);
                        monitor.worked(1);
                    }
                    // TODO set beam centre in case of all circles
                    calibrate.setEnabled(true);
                    findOuter.setEnabled(false);
                } catch (Exception e) {
                    status[0] = false;
                }
            }
        });

        return status[0] ? Status.OK_STATUS : Status.CANCEL_STATUS;
    }

    private IStatus runCalibrateDetector(final IProgressMonitor monitor, Display display,
            final IPlottingSystem plotter, List<HKL> spacings) {
        final ProgressMonitorWrapper mon = new ProgressMonitorWrapper(monitor);
        monitor.beginTask("Calibrate detector from rings", IProgressMonitor.UNKNOWN);
        monitor.subTask("Find rings");
        Collection<IRegion> regions = plotter.getRegions();
        List<EllipticalROI> rois = new ArrayList<EllipticalROI>();
        for (IRegion r : regions) {
            String n = r.getName();
            if (n.startsWith(RING_PREFIX))
                rois.add((EllipticalROI) r.getROI());
        }
        monitor.worked(1);

        monitor.subTask("Fit detector");
        try {
            IDiffractionMetadata md = getDiffractionMetaData();
            final DetectorProperties det = md.getDetector2DProperties();
            final DiffractionCrystalEnvironment env = md.getDiffractionCrystalEnvironment();
            //         final QSpace q = PowderRingsUtils.fitEllipsesToQSpace(mon, det, env, rois, spacings, true);
            final QSpace q = PowderRingsUtils.fitEllipsesToQSpace(mon, det, env, rois, spacings, false);
            //         final QSpace q = PowderRingsUtils.fitAllEllipsesToQSpace(mon, det, env, rois, spacings, false);
            if (q == null)
                return Status.CANCEL_STATUS;
            display.syncExec(new Runnable() {
                @Override
                public void run() {
                    det.setGeometry(q.getDetectorProperties());
                    env.setWavelength(q.getWavelength());
                }
            });
        } catch (Exception e) {
            return Status.CANCEL_STATUS;
        }

        return Status.OK_STATUS;
    }

    private void updateCalibrationActions(final CalibrationStandards standards) {
        this.calibrantActions.clear();
        this.calibrantGroup.clear();
        final String selected = standards.getSelectedCalibrant();
        Action selectedAction = null;
        for (final String calibrant : standards.getCalibrantList()) {
            final Action calibrantAction = new Action(calibrant, IAction.AS_CHECK_BOX) {
                public void run() {
                    standards.setSelectedCalibrant(calibrant, true);
                }
            };
            calibrantGroup.add(calibrantAction);
            if (selected != null && selected.equals(calibrant))
                selectedAction = calibrantAction;
            calibrantActions.add(calibrantAction);
        }
        calibrantActions.addSeparator();
        calibrantActions.add(calPref);
        if (selected != null)
            selectedAction.setChecked(true);
    }

    private void createListeners() {

        this.regionListener = new IRegionListener.Stub() {
            @Override
            public void regionAdded(RegionEvent evt) {
                //test if our region
                if (evt.getRegion() == tmpRegion) {
                    //               logger.debug("Region added (type: {})", tmpRegion.getRegionType());
                    double[] point = tmpRegion.getROI().getPointRef();
                    //               logger.debug("Clicked here X: {} Y : {}", point[0], point[1]);

                    if (tmpRegion.getRegionType() == RegionType.POINT)
                        getPlottingSystem().removeRegion(tmpRegion);
                    IDiffractionMetadata data = getDiffractionMetaData();
                    DetectorProperties detprop = data.getDetector2DProperties();
                    detprop.setBeamCentreCoords(point);
                    if (augmenter != null && !augmenter.isShowingBeamCenter()) {
                        augmenter.drawBeamCentre(true);
                    }
                    //               tmpRegion.setShowLabel(true);
                }
                if (evt.getRegion() != null)
                    evt.getRegion().addROIListener(DiffractionTool.this);
            }

            @Override
            public void regionRemoved(RegionEvent evt) {
                IRegion region = evt.getRegion();
                if (region != null) {
                    region.removeROIListener(DiffractionTool.this);
                }
            }

            @Override
            public void regionCreated(RegionEvent evt) {
                IRegion region = evt.getRegion();
                if (region != null) {
                    region.addROIListener(DiffractionTool.this);
                }
            }

            @Override
            public void regionsRemoved(RegionEvent evt) {
                IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
                if (page != null) {
                    Iterator<IRegion> it = getPlottingSystem().getRegions().iterator();
                    while (it.hasNext()) {
                        IRegion region = it.next();
                        region.removeROIListener(DiffractionTool.this);
                    }
                }
            }
        };

        roiListener = new IROIListener.Stub() {
            @Override
            public void update(ROIEvent evt) {
                IROI r = evt.getROI();
                if (r instanceof CircularFitROI
                        || (r instanceof EllipticalFitROI && ((EllipticalFitROI) r).isCircular())) {
                    double[] point = r.getPointRef();
                    //               logger.debug("ROI moved here X: {} Y : {}", point[0], point[1]);
                    IDiffractionMetadata data = getDiffractionMetaData();
                    DetectorProperties detprop = data.getDetector2DProperties();
                    detprop.setBeamCentreCoords(point);
                    if (augmenter != null && !augmenter.isShowingBeamCenter()) {
                        augmenter.drawBeamCentre(true);
                    }
                }
            }
        };
    }

    @Override
    public Control getControl() {
        return control;
    }

    public void refresh() {
        viewer.refresh();
    }

    @Override
    public void setFocus() {
        if (viewer != null && !viewer.getControl().isDisposed())
            viewer.getControl().setFocus();
    }

    @Override
    public void calibrantSelectionChanged(CalibrantSelectionEvent evt) {
        updateCalibrationActions((CalibrationStandards) evt.getSource());
    }

    @Override
    public void roiDragged(ROIEvent evt) {
        updateBeamCentre(evt);
    }

    @Override
    public void roiChanged(ROIEvent evt) {
        updateBeamCentre(evt);
    }

    @Override
    public void roiSelected(ROIEvent evt) {
    }

    private void updateBeamCentre(ROIEvent evt) {
        //      IROI roi = evt.getROI();
        //      if(roi == null)return;
        //      PointROI eroi = roi instanceof PointROI ? (PointROI)roi : null;      
        //      if(eroi == null) return;
        //      if (!(evt.getSource() instanceof IRegion)) return;
        //      
        //      IRegion point = (IRegion)evt.getSource();
        //      Object ob = point.getUserObject();
        //      if (ob == null) return;
        //      
        //      String ringType = ob.toString(); // TODO this is hacky!
        //      if (!"CALIBRANT".equals(ringType) && !"BEAM_POSITION_HANDLE".equals(ringType)) return;
        //      
        //      double ptx = eroi.getPointX();
        //      double pty = eroi.getPointY();
        //      IDiffractionMetadata data = getDiffractionMetaData();
        //      DetectorProperties detprop = data.getDetector2DProperties();
        //      detprop.setBeamCentreCoords(new double[]{ptx, pty});
    }

}