Got Visualization work

This commit is contained in:
2013-10-17 07:55:49 +02:00
parent e2921ff1f4
commit 855535134e
8 changed files with 285 additions and 194 deletions
@@ -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);
@@ -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
@@ -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 <http://www.gnu.org/licenses/>.
*
*/
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<SeriesDataFilter> mapVisualizations(List<Visualization> vl){
List<SeriesDataFilter> filters = new ArrayList<SeriesDataFilter>();
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<Object> 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<Object> 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<arraySize){
size = mp.getSize();
}
else{
size=arraySize-offset;
}
double minY, maxY;
int nY;
double minX = offset;
double maxX = offset+size-1;
int nX = size;
String idY, idZ;
// 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 if(mp.getY() instanceof ContinuousPositioner){
ContinuousPositioner conp = ((ContinuousPositioner)mp.getY());
idY = conp.getId();
minY = (Math.min(conp.getStart(), conp.getEnd()));
maxY = (Math.max(conp.getStart(), conp.getEnd()));
nY = ((int) Math.floor((Math.abs(maxY-minY))/conp.getStepSize()) + 1);
}
else{
// Fail as we cannot determine the min, max and number of steps
throw new RuntimeException(mp.getY().getClass().getName()+" is not supported as x-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);
XYZSeriesArrayDataFilter filter = new XYZSeriesArrayDataFilter(idY, idZ, offset, size, plot);
filters.add(filter);
}
else{
// Visualization type (currently) not supported
throw new RuntimeException(v.getClass().getName()+" is not supported as visualization type");
}
}
return filters;
}
}
@@ -32,7 +32,6 @@ import com.google.common.eventbus.Subscribe;
import ch.psi.fda.core.messages.DataMessage;
import ch.psi.fda.core.messages.StreamDelimiterMessage;
import ch.psi.fda.core.messages.EndOfStreamMessage;
import ch.psi.fda.model.v1.Visualization;
import ch.psi.plot.Plot;
import ch.psi.plot.xy.LinePlot;
import ch.psi.plot.xy.XYSeriesCollectionP;
@@ -42,15 +41,11 @@ import ch.psi.plot.xyz.MatrixPlotData;
/**
* Visualizer for visualizing data
* @author ebner
*
*/
public class Visualizer {
private static Logger logger = Logger.getLogger(Visualizer.class.getName());
// private List<Plot> plots = new ArrayList<Plot>();
private boolean updateAtStreamElement = true;
private boolean updateAtStreamDelimiter = true;
private boolean updateAtEndOfStream = false;
@@ -59,11 +54,10 @@ public class Visualizer {
private boolean clearPlot;
private List<SeriesDataFilter> filters;
private List<Visualization> visualizations;
private boolean first = true;
public Visualizer(List<Visualization> vl){
this.visualizations = vl;
public Visualizer(List<SeriesDataFilter> 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);
@@ -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
*/
@@ -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;
}
@@ -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;
}
@@ -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;
}