/* * Copyright (c) 2012 European Synchrotron Radiation Facility, * 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 */ /** * source code to implement the ZoomLineView view for plotting a user selected line */ package fable.imageviewer.views; import java.awt.Dimension; import java.awt.Font; import java.awt.Frame; import java.util.Vector; import javax.swing.JApplet; import jep.JepException; import org.dawb.fabio.FabioFile; import org.dawb.fabio.FabioFileException; //import org.dawb.fabio.FableJep; 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.jface.dialogs.MessageDialog; import org.eclipse.swt.SWT; import org.eclipse.swt.awt.SWT_AWT; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Spinner; import org.eclipse.ui.part.ViewPart; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import fable.framework.navigator.controller.SampleController; import fable.framework.toolbox.FableUtils; import fable.python.Sample; import fr.esrf.tangoatk.widget.util.chart.JLAxis; import fr.esrf.tangoatk.widget.util.chart.JLChart; import fr.esrf.tangoatk.widget.util.chart.JLDataView; /** * The RockingCurveView class implements an eclipse view for plotting a rocking * curve of a user selected area in an image. A rocking curve is a plot of the * integrated intensity of an area in an image for a series of images usually * taken at different orientations of the sample. The sample orientation is * normally represented by the angle "omega". * * It uses JLChart to do the plotting. It will plot the data set as a line. The * image view gathers the user's selection and sends the data to plot to the * RockingCurveView. The user can change the range of images over which to * integrate and plot. Fabio is used to read the image and integrate the * intensity. * * @author goetz */ public class RockingCurveView extends ViewPart { public final static String ID = "fable.imageviewer.views.RockingCurveView"; private JLDataView dataView; private JLChart chart; String title; private int rockStart = -1, rockCenter = -1, rockEnd = -1, rockRange; private int xAxis = 0, rockArea[] = new int[4]; private float rockX[], rockIntensity[]; private Spinner rockStartSpinner, rockEndSpinner; private Label rockStartLabel, rockEndLabel; private Button updateButton, averageButton; private Combo xAxisCombo; public static RockingCurveView view; private Composite swtAwtComponent; public SampleController controller = SampleController.getController(); public Sample sample = null; private Frame chartFrame; private JApplet chartContainer; private static final Logger logger = LoggerFactory.getLogger(RockingCurveView.class); private IProgressMonitor jobMonitor; private final String[] imageNumber = { "image number" }; private String[] xAxisItems = imageNumber; private boolean jobRunning = false; private boolean average = true; // private Composite parent; public RockingCurveView() { super(); } /* * (non-Javadoc) * * @see * org.eclipse.ui.part.WorkbenchPart#createPartControl(org.eclipse.swt.widgets * .Composite) */ @Override public void createPartControl(Composite parent) { view = this; // this.parent = parent; parent.setLayout(new GridLayout()); createChartFrame(parent); createChart(); Composite controlPanelComposite = new Composite(parent, SWT.NULL); GridLayout controlGridLayout = new GridLayout(); controlGridLayout.numColumns = 8; controlPanelComposite.setLayout(controlGridLayout); controlPanelComposite.setLayoutData(new GridData(SWT.FILL, SWT.NONE, true, false)); Label xAxisLabel = new Label(controlPanelComposite, SWT.NULL); xAxisLabel.setText("X Axis"); xAxisCombo = new Combo(controlPanelComposite, SWT.NULL); xAxisCombo.setItems(xAxisItems); xAxisCombo.select(0); xAxis = 0; xAxisCombo.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { xAxis = xAxisCombo.getSelectionIndex(); } }); rockStartLabel = new Label(controlPanelComposite, SWT.NULL); rockStartLabel.setText("Start"); rockStartSpinner = new Spinner(controlPanelComposite, SWT.NULL); rockEndLabel = new Label(controlPanelComposite, SWT.NULL); rockEndLabel.setText("End"); rockEndSpinner = new Spinner(controlPanelComposite, SWT.NULL); averageButton = new Button(controlPanelComposite, SWT.CHECK); averageButton.setText("Average"); averageButton.setSelection(true); average = true; averageButton.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { if (averageButton.getSelection()) { average = true; } else { average = false; } } }); updateButton = new Button(controlPanelComposite, SWT.NULL); updateButton.setText("Update"); updateButton.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { rockStart = rockStartSpinner.getSelection(); rockEnd = rockEndSpinner.getSelection(); runIntegratePlotJob(); } }); } /* * (non-Javadoc) * * @see org.eclipse.ui.part.WorkbenchPart#setFocus() */ @Override public void setFocus() { } private void createChartFrame(Composite parent) { swtAwtComponent = new Composite(parent, SWT.EMBEDDED | SWT.NO_BACKGROUND); swtAwtComponent.setLayout(new GridLayout()); swtAwtComponent.setLayoutData(new GridData(GridData.FILL_HORIZONTAL | GridData.FILL_VERTICAL)); chartFrame = SWT_AWT.new_Frame(swtAwtComponent); chartContainer = new JApplet(); chartFrame.add(chartContainer); } public void createChart() { chart = new JLChart(); chart.setHeader("Rocking Curve Plot"); chart.setHeaderFont(new Font("Dialog", Font.BOLD, 18)); chart.getY1Axis().setName("integrated intensity"); chart.getY1Axis().setAutoScale(true); chart.getXAxis().setAutoScale(true); chart.getXAxis().setName("image number"); chart.getXAxis().setGridVisible(true); chart.getXAxis().setSubGridVisible(true); chart.getXAxis().setAnnotation(JLAxis.VALUE_ANNO); chart.getY1Axis().setGridVisible(true); chart.getY1Axis().setSubGridVisible(true); dataView = new JLDataView(); dataView .setName("integrated intensity [" + rockArea[0] + "," + rockArea[1] + "] - [" + rockArea[2] + "," + rockArea[3] + "]"); chart.getY1Axis().addDataView(dataView); chartContainer.add(chart); } /** * Set the new area, center and sample to integrate and display it as a line * plot * * @param title * - title to display with plot * @param center * - center image * @param area * - area to integrate * @throws Throwable */ public void setCenterArea(String _title, int center, int y1, int z1, int y2, int z2) throws Throwable { if (!jobRunning) { jobRunning = true; if (sample == null || sample != controller.getCurrentsample()) { sample = controller.getCurrentsample(); if (sample == null) { FableUtils.errMsg(this, "Rocking curve requires a Sample." + " Cannot find a Sample."); return; } try { String[] headerItems = sample.getFilteredfiles().get(0) .getKeys(); xAxisItems = new String[1 + headerItems.length]; xAxisItems[0] = "image number"; for (int i = 0; i < headerItems.length; i++) { xAxisItems[i + 1] = headerItems[i]; } } catch (FabioFileException ex) { FableUtils.excNoTraceMsg(this, "Error setting center area", ex); } catch (JepException ex) { FableUtils.excNoTraceMsg(this, "Error setting center area", ex); } xAxisCombo.setItems(xAxisItems); xAxisCombo.select(0); xAxis = 0; } title = _title; rockStartSpinner.setMaximum(sample.getFilteredfiles().size() - 1); rockEndSpinner.setMaximum(sample.getFilteredfiles().size() - 1); rockArea[0] = y1; rockArea[1] = z1; rockArea[2] = y2; rockArea[3] = z2; rockCenter = center; rockRange = rockEnd - rockStart; if (rockRange <= 3) { rockStart = center - 3; } else { rockStart = center - rockRange / 2; } if (rockRange <= 3) { rockEnd = center + 3; } else { rockEnd = center + (rockRange + 1) / 2; } checkRockRange(); runIntegratePlotJob(); } } public void checkRockRange() { if (rockStart < 0) rockStart = 0; if (rockEnd > sample.getFilteredfiles().size() - 1) rockEnd = sample.getFilteredfiles().size() - 1; if (rockStart > rockEnd) { int temp = rockStart; rockStart = rockEnd; rockEnd = temp; } // logger.debug("rockCenter = "+rockCenter+" rockEnd = "+rockEnd+" // rockStart = "+rockStart); rockStartSpinner.setSelection(rockStart); rockEndSpinner.setSelection(rockEnd); } public void runIntegratePlotJob() { Job job = new Job("Integrate rocking curve for sample " + sample.getDirectoryName() + " ... ") { protected IStatus run(IProgressMonitor monitor) { jobMonitor = monitor; monitor.beginTask("Integrate rocking curve for sample " + sample.getDirectoryName() + " ... ", rockEnd - rockStart + 1); if (Integrate() != 0) { monitor.done(); return Status.CANCEL_STATUS; } Display.getDefault().asyncExec(new Runnable() { public void run() { Plot(); } }); monitor.done(); jobRunning = false; return Status.OK_STATUS; } }; job.setUser(false); job.schedule(); } // KE: Is this method name supposed to start with a cap? public int Integrate() { /* FableJep fableJep = null; try { fableJep = FableJep.getFableJep(); } catch (Throwable ex) { FableUtils.excMsg(this, "Error in Integrate creating FableJep", ex); } */ Vector<FabioFile> fabioFiles = sample.getFilteredfiles(); int width, height, npoints; FabioFile fabioFile; fabioFile = fabioFiles.get(rockCenter); try { width = fabioFile.getWidth(); height = fabioFile.getHeight(); npoints = (rockArea[2] - rockArea[0]) * (rockArea[3] - rockArea[1]); rockX = new float[rockEnd - rockStart + 1]; rockIntensity = new float[rockEnd - rockStart + 1]; int rockingCurveErrors = 0; for (int i = rockStart; i <= rockEnd; i++) { jobMonitor.worked(1); float imageFloat[]; fabioFile = fabioFiles.get(i); imageFloat = fabioFile.getImageAsFloat(); /* * only do rocking curve for those files which have the same * size as the center file */ if (fabioFile.getWidth() == width && fabioFile.getHeight() == height) { float sum = 0; for (int z = rockArea[1]; z < rockArea[3]; z++) { int zOffset; zOffset = width * z; for (int y = rockArea[0]; y < rockArea[2]; y++) { sum = sum + imageFloat[zOffset + y]; } } if (average) { rockIntensity[i - rockStart] = sum / (float) npoints; } else { rockIntensity[i - rockStart] = sum; } } else { rockIntensity[i - rockStart] = Float.NaN; rockingCurveErrors++; } if (xAxis != 0) { rockX[i - rockStart] = Float.NaN; String keyValue = ""; try { if (!fabioFile.isHeaderRead()) fabioFile.loadHeader(); keyValue = fabioFile.getValue(xAxisItems[xAxis]); } catch (FabioFileException ex) { FableUtils.excNoTraceMsg(this, "Error in Integrate loading header", ex); } try { rockX[i - rockStart] = Float.parseFloat(keyValue); } catch (NumberFormatException ex) { FableUtils.excNoTraceMsg(this, "Error in Integrate loading header", ex); rockingCurveErrors++; } } else { rockX[i - rockStart] = i; } } if (rockingCurveErrors != 0) { final String message; message = rockingCurveErrors + " files will not be plotted on the rocking curve " + "because their size differs or the key chosen for " + "the x axis does not exist"; Display.getDefault().asyncExec(new Runnable() { public void run() { MessageDialog.openConfirm(Display.getDefault() .getActiveShell(), "Confirm", message); } }); return 1; } } catch (Throwable ex) { FableUtils.excNoTraceMsg(this, "Error in Integrate", ex); } return 0; } public void Plot() { if (average) { chart.getY1Axis().setName("average intensity"); } else { chart.getY1Axis().setName("integrated intensity"); } chart.getXAxis().setName(xAxisItems[xAxis]); chart.setHeader(title); double[] x = new double[rockEnd - rockStart + 1]; double[] y = new double[rockEnd - rockStart + 1]; for (int i = 0; i < rockEnd - rockStart + 1; i++) { x[i] = rockX[i]; y[i] = Double.valueOf(rockIntensity[i]); } dataView.setData(x, y); dataView .setName("integrated intensity [" + rockArea[0] + "," + rockArea[1] + "] - [" + rockArea[2] + "," + rockArea[3] + "]"); Dimension chartSize = chartContainer.getSize(); chart.setSize(chartSize); javax.swing.SwingUtilities.invokeLater(new Runnable() { public void run() { chartContainer.repaint(); } }); } }