From 855535134e3ff08c309367ea54af8f1548fe3cb0 Mon Sep 17 00:00:00 2001 From: Simon Ebner Date: Thu, 17 Oct 2013 07:55:49 +0200 Subject: [PATCH] Got Visualization work --- .../main/java/ch/psi/fda/AcquisitionMain.java | 6 +- .../java/ch/psi/fda/VisualizationMain.java | 3 +- .../ch/psi/fda/aq/VisualizationMapper.java | 271 ++++++++++++++++++ .../ch/psi/fda/visualizer/Visualizer.java | 16 +- .../visualizer/XYSeriesArrayDataFilter.java | 17 -- .../fda/visualizer/XYSeriesDataFilter.java | 16 -- .../visualizer/XYZSeriesArrayDataFilter.java | 71 +---- .../fda/visualizer/XYZSeriesDataFilter.java | 79 ----- 8 files changed, 285 insertions(+), 194 deletions(-) create mode 100644 ch.psi.fda/src/main/java/ch/psi/fda/aq/VisualizationMapper.java diff --git a/ch.psi.fda/src/main/java/ch/psi/fda/AcquisitionMain.java b/ch.psi.fda/src/main/java/ch/psi/fda/AcquisitionMain.java index 2925168..d49dd87 100644 --- a/ch.psi.fda/src/main/java/ch/psi/fda/AcquisitionMain.java +++ b/ch.psi.fda/src/main/java/ch/psi/fda/AcquisitionMain.java @@ -54,6 +54,7 @@ import com.google.common.eventbus.EventBus; import sun.misc.Signal; import sun.misc.SignalHandler; import ch.psi.fda.aq.Acquisition; +import ch.psi.fda.aq.VisualizationMapper; import ch.psi.fda.gui.ProgressPanel; import ch.psi.fda.gui.ScrollableFlowPanel; import ch.psi.fda.install.ApplicationConfigurator; @@ -267,8 +268,11 @@ public class AcquisitionMain { // Only register data visualization task/processor if there are visualizations if(vis){ - visualizer = new Visualizer(c.getVisualization()); + visualizer = new Visualizer(VisualizationMapper.mapVisualizations(c.getVisualization())); b.register(visualizer); + + // TODO eventually set update on delimiter/dim boundary here + // If there is a continous dimension only update plot at the end of a line if(c.getScan() != null && c.getScan().getCdimension()!=null){ visualizer.setUpdateAtStreamElement(false); diff --git a/ch.psi.fda/src/main/java/ch/psi/fda/VisualizationMain.java b/ch.psi.fda/src/main/java/ch/psi/fda/VisualizationMain.java index cf102f8..e975538 100644 --- a/ch.psi.fda/src/main/java/ch/psi/fda/VisualizationMain.java +++ b/ch.psi.fda/src/main/java/ch/psi/fda/VisualizationMain.java @@ -48,6 +48,7 @@ import org.xml.sax.SAXException; import com.google.common.eventbus.AsyncEventBus; import com.google.common.eventbus.EventBus; +import ch.psi.fda.aq.VisualizationMapper; import ch.psi.fda.deserializer.DataDeserializer; import ch.psi.fda.deserializer.DataDeserializerTXT; import ch.psi.fda.gui.ScrollableFlowPanel; @@ -121,7 +122,7 @@ public class VisualizationMain { DataDeserializer deserializer = new DataDeserializerTXT(bus, data); // Create Visualizer - Visualizer visualizer = new Visualizer(configuration.getVisualization()); + Visualizer visualizer = new Visualizer(VisualizationMapper.mapVisualizations(configuration.getVisualization())); // visualizer.setTerminateAtEOS(true); // Adapt default visualizer behavior to optimize performance for visualization diff --git a/ch.psi.fda/src/main/java/ch/psi/fda/aq/VisualizationMapper.java b/ch.psi.fda/src/main/java/ch/psi/fda/aq/VisualizationMapper.java new file mode 100644 index 0000000..24e327b --- /dev/null +++ b/ch.psi.fda/src/main/java/ch/psi/fda/aq/VisualizationMapper.java @@ -0,0 +1,271 @@ +/** + * + * Copyright 2013 Paul Scherrer Institute. All rights reserved. + * + * This code is free software: you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * This code is distributed in the hope that it will be useful, but without any + * warranty; without even the implied warranty of merchantability or fitness for + * a particular purpose. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this code. If not, see . + * + */ +package ch.psi.fda.aq; + +import java.util.ArrayList; +import java.util.List; + +import ch.psi.fda.model.v1.ArrayDetector; +import ch.psi.fda.model.v1.ContinuousPositioner; +import ch.psi.fda.model.v1.Detector; +import ch.psi.fda.model.v1.LinearPositioner; +import ch.psi.fda.model.v1.Positioner; +import ch.psi.fda.model.v1.PseudoPositioner; +import ch.psi.fda.model.v1.Visualization; +import ch.psi.fda.visualizer.SeriesDataFilter; +import ch.psi.fda.visualizer.XYSeriesArrayDataFilter; +import ch.psi.fda.visualizer.XYSeriesDataFilter; +import ch.psi.fda.visualizer.XYZSeriesArrayDataFilter; +import ch.psi.fda.visualizer.XYZSeriesDataFilter; +import ch.psi.plot.xyz.MatrixPlot; +import ch.psi.plot.xyz.MatrixPlotData; + +/** + * @author ebner + * + */ +public class VisualizationMapper { + + + /** + * Retrieve id string of the passed object + * @param object + * @return Id string of object + */ + private static String getId(Object object){ + String id; + if(object instanceof Positioner){ + id = ((Positioner)object).getId(); + } + else if (object instanceof Detector){ + id = ((Detector)object).getId(); + } + else if (object instanceof ch.psi.fda.model.v1.Manipulation){ + id = ((ch.psi.fda.model.v1.Manipulation)object).getId(); + } + // For testing purposes + else if(object instanceof String){ + id = (String) object; + } + else{ + throw new RuntimeException("Unable to identify id of object reference "+object); + } + return id; + } + + public static List mapVisualizations(List vl){ + List filters = new ArrayList(); + + for(Visualization v: vl){ + if(v instanceof ch.psi.fda.model.v1.LinePlot){ + ch.psi.fda.model.v1.LinePlot lp = (ch.psi.fda.model.v1.LinePlot) v; + + // Create plot for visualization + ch.psi.plot.xy.LinePlot plot = new ch.psi.plot.xy.LinePlot(lp.getTitle()); + + // Create data filter for visualization + String idX = getId(lp.getX()); + + List l = lp.getY(); + for(Object o: l){ + String idY = getId(o); + XYSeriesDataFilter filter = new XYSeriesDataFilter(idX, idY, plot); + filter.setSeriesName(idY); + filters.add(filter); + } + } + else if(v instanceof ch.psi.fda.model.v1.LinePlotArray){ + // Array visualization + ch.psi.fda.model.v1.LinePlotArray lp = (ch.psi.fda.model.v1.LinePlotArray) v; + + // Create plot for visualization + ch.psi.plot.xy.LinePlot plot = new ch.psi.plot.xy.LinePlot(lp.getTitle()); + + // Create data filter for visualization + List l = lp.getY(); + for(Object o: l){ + String idY = getId(o); + + XYSeriesArrayDataFilter filter = new XYSeriesArrayDataFilter(idY, plot); + filter.setMaxSeries(lp.getMaxSeries()*lp.getY().size()); // Workaround - keep for each array max series + filter.setOffset(lp.getOffset()); + filter.setSize(lp.getSize()); + filter.setSeriesName(idY); + filters.add(filter); + } + } + else if(v instanceof ch.psi.fda.model.v1.MatrixPlot){ + + // MatrixPlot does currently not support RegionPositioners because of the + // plotting problems this would cause. If regions of the positioner have different + // step sizes it is not easily possible (without (specialized) rasterization) to plot the data. + + ch.psi.fda.model.v1.MatrixPlot mp = (ch.psi.fda.model.v1.MatrixPlot) v; + + + double minX, maxX; + int nX; + double minY, maxY; + int nY; + + String idX, idY, idZ; + + // X Axis + if(mp.getX() instanceof LinearPositioner){ + LinearPositioner linp = ((LinearPositioner)mp.getX()); + idX = linp.getId(); + + minX = (Math.min(linp.getStart(), linp.getEnd())); + maxX = (Math.max(linp.getStart(), linp.getEnd())); + nX = ((int) Math.floor((Math.abs(maxX-minX))/linp.getStepSize()) + 1); + } + else if(mp.getX() instanceof PseudoPositioner){ + PseudoPositioner pp = ((PseudoPositioner)mp.getX()); + idX = pp.getId(); + minX = (1); // Count starts at 1 + maxX = (pp.getCounts()); + nX = (pp.getCounts()); + } + else if(mp.getX() instanceof ContinuousPositioner){ + ContinuousPositioner conp = ((ContinuousPositioner)mp.getX()); + idX = conp.getId(); + + minX = (Math.min(conp.getStart(), conp.getEnd())); + maxX = (Math.max(conp.getStart(), conp.getEnd())); + nX = ((int) Math.floor((Math.abs(maxX-minX))/conp.getStepSize()) + 1); + } + else{ + // Fail as we cannot determine the min, max and number of steps + throw new RuntimeException(mp.getX().getClass().getName()+" is not supported as x-axis of a MatrixPlot"); + } + + // Y Axis + if(mp.getY() instanceof LinearPositioner){ + LinearPositioner linp = ((LinearPositioner)mp.getY()); + idY = linp.getId(); + minY = (Math.min(linp.getStart(), linp.getEnd())); + maxY = (Math.max(linp.getStart(), linp.getEnd())); + nY = ((int) Math.floor((Math.abs(maxY-minY))/linp.getStepSize()) + 1); + } + else if(mp.getY() instanceof PseudoPositioner){ + PseudoPositioner pp = ((PseudoPositioner)mp.getY()); + idY = pp.getId(); + minY = (1); // Count starts at 1 + maxY = (pp.getCounts()); + nY = (pp.getCounts()); + } + else{ + // Fail as we cannot determine the min, max and number of steps + throw new RuntimeException(mp.getY().getClass().getName()+" is not supported as y-axis of a MatrixPlot"); + } + + // Z Dimension + idZ = getId(mp.getZ()); + + // Create plot for visualization + MatrixPlotData data = new MatrixPlotData(minX, maxX, nX, minY, maxY, nY); + MatrixPlot plot = new MatrixPlot(mp.getTitle(), data); + + XYZSeriesDataFilter filter = new XYZSeriesDataFilter(idX, idY, idZ, plot); + filters.add(filter); + } + else if(v instanceof ch.psi.fda.model.v1.MatrixPlotArray){ + // Support for 2D waveform plots + ch.psi.fda.model.v1.MatrixPlotArray mp = (ch.psi.fda.model.v1.MatrixPlotArray) v; + + // Get size of the array detector + int arraySize = 0; + Object o = mp.getZ(); + if(o instanceof ArrayDetector){ + ArrayDetector ad = (ArrayDetector) o; + arraySize = ad.getArraySize(); + } + else{ + // Workaround + arraySize = mp.getSize(); // of array is from a manipulation the size is not known. Then the size will indicate the size of the array to display + } + + int offset = mp.getOffset(); + // Determine size for array + int size = mp.getSize(); + if(size>0 && offset+size plots = new ArrayList(); - private boolean updateAtStreamElement = true; private boolean updateAtStreamDelimiter = true; private boolean updateAtEndOfStream = false; @@ -59,11 +54,10 @@ public class Visualizer { private boolean clearPlot; private List filters; - private List visualizations; private boolean first = true; - public Visualizer(List vl){ - this.visualizations = vl; + public Visualizer(List filters){ + this.filters = filters; } @@ -72,7 +66,8 @@ public class Visualizer { if(first){ first=false; - filters = VisMapper.mapVisualizations(message.getMetadata(), visualizations); +// filters = VisMapper.mapVisualizations(visualizations); + // TODO somehow handle dimension / clear } // Clear is here as the plot should not be cleared after the last point is plotted @@ -194,7 +189,8 @@ public class Visualizer { if(filter instanceof XYSeriesDataFilter){ // Create new series XYSeriesDataFilter xyfilter = (XYSeriesDataFilter) filter; - if (message.getNumber() == xyfilter.getDimensionX()) { +// if (message.getNumber() == xyfilter.getDimensionX()) { + if (message.getNumber() == 0) { // TODO need to check this - here we assume that always at the lowest level we create a new series // Indicate to create new series at the next message xyfilter.setCount(xyfilter.getCount()+1); // Increment count of the filter xyfilter.setNewseries(true); diff --git a/ch.psi.fda/src/main/java/ch/psi/fda/visualizer/XYSeriesArrayDataFilter.java b/ch.psi.fda/src/main/java/ch/psi/fda/visualizer/XYSeriesArrayDataFilter.java index a9aabcc..781dba1 100644 --- a/ch.psi.fda/src/main/java/ch/psi/fda/visualizer/XYSeriesArrayDataFilter.java +++ b/ch.psi.fda/src/main/java/ch/psi/fda/visualizer/XYSeriesArrayDataFilter.java @@ -36,9 +36,6 @@ public class XYSeriesArrayDataFilter implements SeriesDataFilter { // Name of the series generated by this filter private String seriesName = ""; - // Dimension of the x,y value - used to determine whether a new series should be created for this filter - private int dimensionY; - // Number of series generated for this filter private int count = 0; @@ -78,20 +75,6 @@ public class XYSeriesArrayDataFilter implements SeriesDataFilter { this.seriesName = seriesName; } - /** - * @return the dimensionY - */ - public int getDimensionY() { - return dimensionY; - } - - /** - * @param dimensionY the dimensionY to set - */ - public void setDimensionY(int dimensionY) { - this.dimensionY = dimensionY; - } - /** * @return the count */ diff --git a/ch.psi.fda/src/main/java/ch/psi/fda/visualizer/XYSeriesDataFilter.java b/ch.psi.fda/src/main/java/ch/psi/fda/visualizer/XYSeriesDataFilter.java index e298c69..18b0324 100644 --- a/ch.psi.fda/src/main/java/ch/psi/fda/visualizer/XYSeriesDataFilter.java +++ b/ch.psi.fda/src/main/java/ch/psi/fda/visualizer/XYSeriesDataFilter.java @@ -38,10 +38,6 @@ public class XYSeriesDataFilter implements SeriesDataFilter{ // Name of the series generated by this filter private String seriesName = ""; - // Dimension of the x,y value - used to determine whether a new series should be created for this filter - private int dimensionX; - private int dimensionY; - // Number of series generated for this filter private int count = 0; @@ -71,18 +67,6 @@ public class XYSeriesDataFilter implements SeriesDataFilter{ public void setSeriesName(String seriesName) { this.seriesName = seriesName; } - public int getDimensionX() { - return dimensionX; - } - public int getDimensionY() { - return dimensionY; - } - public void setDimensionY(int dimensionY) { - this.dimensionY = dimensionY; - } - public void setDimensionX(int dimensionX) { - this.dimensionX = dimensionX; - } public int getCount() { return count; } diff --git a/ch.psi.fda/src/main/java/ch/psi/fda/visualizer/XYZSeriesArrayDataFilter.java b/ch.psi.fda/src/main/java/ch/psi/fda/visualizer/XYZSeriesArrayDataFilter.java index e5c46e7..024b33b 100644 --- a/ch.psi.fda/src/main/java/ch/psi/fda/visualizer/XYZSeriesArrayDataFilter.java +++ b/ch.psi.fda/src/main/java/ch/psi/fda/visualizer/XYZSeriesArrayDataFilter.java @@ -32,11 +32,7 @@ public class XYZSeriesArrayDataFilter implements SeriesDataFilter { // Name of the series generated by this filter private String seriesName = ""; - - // Dimension of the x,y value - used to determine whether a new series should be created for this filter - private int dimensionY; - private int dimensionZ; - + // Number of series generated for this filter private int count = 0; @@ -56,101 +52,36 @@ public class XYZSeriesArrayDataFilter implements SeriesDataFilter { this.plot = plot; } - /** - * @return the zId - */ public String getIdZ() { return idZ; } - - public int getDimensionZ() { - return dimensionZ; - } - - /** - * @param dimensionZ the dimensionZ to set - */ - public void setDimensionZ(int dimensionZ) { - this.dimensionZ = dimensionZ; - } - - /** - * @return the seriesName - */ public String getSeriesName() { return seriesName; } - - /** - * @param seriesName the seriesName to set - */ public void setSeriesName(String seriesName) { this.seriesName = seriesName; } - - /** - * @return the dimensionX - */ - public int getDimensionY() { - return dimensionY; - } - - /** - * @param dimensionY the dimensionX to set - */ - public void setDimensionY(int dimensionY) { - this.dimensionY = dimensionY; - } - - /** - * @return the count - */ public int getCount() { return count; } - - /** - * @param count the count to set - */ public void setCount(int count) { this.count = count; } - - /** - * @return the newseries - */ public boolean isNewseries() { return newseries; } - - /** - * @param newseries the newseries to set - */ public void setNewseries(boolean newseries) { this.newseries = newseries; } - - /** - * @return the idY - */ public String getIdY() { return idY; } - public int getOffset() { return offset; } - - /** - * @return the arraySize - */ public int getSize() { return size; } - - /** - * @return the plot - */ public Plot getPlot() { return plot; } diff --git a/ch.psi.fda/src/main/java/ch/psi/fda/visualizer/XYZSeriesDataFilter.java b/ch.psi.fda/src/main/java/ch/psi/fda/visualizer/XYZSeriesDataFilter.java index 04186be..57a19de 100644 --- a/ch.psi.fda/src/main/java/ch/psi/fda/visualizer/XYZSeriesDataFilter.java +++ b/ch.psi.fda/src/main/java/ch/psi/fda/visualizer/XYZSeriesDataFilter.java @@ -34,11 +34,6 @@ public class XYZSeriesDataFilter implements SeriesDataFilter { // Name of the series generated by this filter private String seriesName = ""; - // Dimension of the x,y value - used to determine whether a new series should be created for this filter - private int dimensionX; - private int dimensionY; - private int dimensionZ; - // Number of series generated for this filter private int count = 0; @@ -55,104 +50,30 @@ public class XYZSeriesDataFilter implements SeriesDataFilter { this.plot = plot; } - /** - * @return the zId - */ public String getIdZ() { return idZ; } - - public int getDimensionZ() { - return dimensionZ; - } - - /** - * @param dimensionZ the dimensionZ to set - */ - public void setDimensionZ(int dimensionZ) { - this.dimensionZ = dimensionZ; - } - - /** - * @return the seriesName - */ public String getSeriesName() { return seriesName; } - - /** - * @param seriesName the seriesName to set - */ public void setSeriesName(String seriesName) { this.seriesName = seriesName; } - - /** - * @return the dimensionX - */ - public int getDimensionX() { - return dimensionX; - } - - /** - * @param dimensionX the dimensionX to set - */ - public void setDimensionX(int dimensionX) { - this.dimensionX = dimensionX; - } - - /** - * @return the dimensionY - */ - public int getDimensionY() { - return dimensionY; - } - - /** - * @param dimensionY the dimensionY to set - */ - public void setDimensionY(int dimensionY) { - this.dimensionY = dimensionY; - } - - /** - * @return the count - */ public int getCount() { return count; } - - /** - * @param count the count to set - */ public void setCount(int count) { this.count = count; } - - /** - * @return the newseries - */ public boolean isNewseries() { return newseries; } - - /** - * @param newseries the newseries to set - */ public void setNewseries(boolean newseries) { this.newseries = newseries; } - - /** - * @return the idX - */ public String getIdX() { return idX; } - - /** - * @return the idY - */ public String getIdY() { return idY; }