Package de.torstennahm.integrate.visualize

Source Code of de.torstennahm.integrate.visualize.ResultVisualizer$ResultEntry

/*
* Created on Jan 9, 2004
*/
package de.torstennahm.integrate.visualize;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.AdjustmentEvent;
import java.awt.event.AdjustmentListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollBar;
import javax.swing.JTextField;
import javax.swing.JToggleButton;

import de.torstennahm.integrate.IntegrationResult;
import de.torstennahm.integrate.error.FastConvergenceEstimator;
import de.torstennahm.integrate.visualizerdata.CorrectValue;
import de.torstennahm.integrate.visualizerdata.NewResult;
import de.torstennahm.integrate.visualizerdata.VisualizerData;
import de.torstennahm.math.MathTN;

/**
* Plots the estimated integration result as function of the number of evaluations.
* If the correct result is known and provided via <code>CorrectValue</code>, this
* is displayed as well.
*
* @see de.torstennahm.integrate.visualizerdata.CorrectValue
*
* @author Torsten Nahm
*/
public class ResultVisualizer implements Visualizer {
  static private final double SAMPLEFACTOR = 1.05;
 
  private final JFrame frame;
 
  private boolean destroyed = false;
 
  private JPanel resultPanel;
  private JPanel mainPanel = new JPanel();
  private JScrollBar zoomXBar = new JScrollBar(JScrollBar.HORIZONTAL, 100, 1, 1, 500);
  private JScrollBar zoomYBar = new JScrollBar(JScrollBar.VERTICAL, -101, 1, -500, -100);
  private JScrollBar shiftYBar = new JScrollBar(JScrollBar.VERTICAL, 0, 1, -100, 100);
  private JTextField yField = new JTextField();
  private JTextField callsField = new JTextField();
  private JPanel plotPanel = new JPanel();
  private JToggleButton[] plotButton;
  private String[] plotButtonName = { "Error", "Var1", "Var2", "Reg", "Error Est" };
 
  /* synchronized by resultList */
  private List<ResultEntry> resultList = new LinkedList<ResultEntry>();
  private double correctResult = Double.NaN;
  long calls;
  private FastConvergenceEstimator estimator = new FastConvergenceEstimator();
 
  /**
   * Creates the visualizer within the specified <code>JFrame</code>.
   *
   * @param frame <code>JFrame</code> for the visualizer's graphical output.
   */
  public ResultVisualizer(JFrame frame) {
    this.frame = frame;
  }
 
  public void init() {
    if (destroyed) { return; }
   
    resultPanel = new ResultPanel();
   
    plotPanel.setLayout(new GridLayout(1, 0));
    plotButton = new JToggleButton[plotButtonName.length];
    for (int i = 0; i < plotButton.length; i++) {
      plotButton[i] = new JToggleButton(plotButtonName[i]);
      plotButton[i].addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
          resultPanel.repaint();
        }});
      plotPanel.add(plotButton[i]);
    }
    plotButton[0].setSelected(true);
    plotButton[4].setSelected(true);
   
    GridBagLayout g = new GridBagLayout();
    GridBagConstraints c = new GridBagConstraints();
    mainPanel.setLayout(g);
    c.fill = GridBagConstraints.BOTH;
    c.gridwidth = GridBagConstraints.REMAINDER;
    c.weightx = 1.0;
    c.weighty = 0.0;
    mainPanel.add(plotPanel, c);
    yField.setEditable(false);
    callsField.setEditable(false);
    JPanel panel = new JPanel(new GridLayout(1, 2));
    panel.add(yField);
    panel.add(callsField);
    mainPanel.add(panel, c);
    mainPanel.add(zoomXBar, c);
    c.gridwidth = 3;
    c.weightx = 1.0;
    c.weighty = 1.0;
    mainPanel.add(resultPanel, c);
    c.weightx = 0.0;
    mainPanel.add(zoomYBar, c);
    mainPanel.add(shiftYBar, c);
   
    AdjustmentListener listener = new AdjustmentListener() {
      public void adjustmentValueChanged(AdjustmentEvent e) {
        resultPanel.repaint();
      }
    };
    zoomXBar.addAdjustmentListener(listener);
    zoomYBar.addAdjustmentListener(listener);
    shiftYBar.addAdjustmentListener(listener);
   
    frame.getContentPane().add(mainPanel);
   
    frame.setVisible(true);
  }
 
  public void destroy() {
    if (destroyed) { return; }
   
    destroyed = true;
    frame.dispose();
  }
 
  public void start() {
    if (destroyed) { return; }
   
    synchronized (resultList) {
      resultList = new LinkedList<ResultEntry>();
      correctResult = Double.NaN;
      calls = 0;
      estimator = new FastConvergenceEstimator();
    }
    resultPanel.repaint();
  }
 
  public void stop() {
  }
 
  public void submit(VisualizerData data) {
    if (destroyed) { return; }
   
    if (data instanceof CorrectValue) {
      correctResult = ((CorrectValue) data).correctValue;
    } else if (data instanceof NewResult) {
      IntegrationResult result = ((NewResult) data).result;
      synchronized (resultList) {
        if (calls < 100 || result.functionCalls() >= calls * SAMPLEFACTOR) {
          calls = result.functionCalls();
          resultList.add(new ResultEntry(calls, result.value(), result.errorEstimate()));
          resultPanel.repaint();
        }
        estimator.log(result.functionCalls(), result.value());
      }
    }
  }
 
  private class ResultPanel extends JPanel implements MouseMotionListener {
    private static final long serialVersionUID = -9206803170275527901L;
   
    ResultPanel() {
      addMouseMotionListener(this);
    }
   
    @Override
    synchronized public void paintComponent(Graphics g) {
      super.paintComponent(g);
     
      int width = getWidth();
      int height = getHeight();
       
      for (int i = -20; i < 30; i++) {
        g.setColor(i % 5 == 0 ? new Color(0, 0, 0.6f) : Color.GRAY);
        int y = (int) (-foldY(Math.pow(0.1, i)) * height) + height;
        g.drawLine(0, y, width - 1, y);
      }
      synchronized (resultList) {
        g.setColor(Color.GRAY);
        for (long callRun = 1; callRun < calls * 10; callRun *= 10) {
          int x = (int) (foldX(callRun) * width);
          g.drawLine(x, 0, x, height);
        }
       
        int x, y;
        ListIterator<ResultEntry> iter;
        Connect connect;
       
        if (plotButton[0].isSelected() && ! Double.isNaN(correctResult)) {
          connect = new Connect(g);
          iter = resultList.listIterator();
          while (iter.hasNext()) {
            ResultEntry entry = iter.next();
            double err = entry.result - correctResult;
            x = (int) (foldX(entry.points) * width);
            y = (int) (-foldY(Math.abs(err)) * height) + height;
           
            g.setColor(err >= 0 ? Color.BLACK : Color.RED);
            connect.to(x, y);
          }
        }
       
        if (plotButton[4].isSelected()) {
          g.setColor(Color.MAGENTA);
          connect = new Connect(g);
          iter = resultList.listIterator();
          while (iter.hasNext()) {
            ResultEntry entry = iter.next();
            if (! Double.isNaN(entry.estimate)){
              x = (int) (foldX(entry.points) * width);
              y = (int) (-foldY(entry.estimate) * height) + height;
              connect.to(x, y);
            } else {
              connect.init();
            }
          }
        }
       
        if (plotButton[1].isSelected()) {
          g.setColor(new Color(0.0f, 1.0f, 0.0f));
          connect = new Connect(g);
          double max = 0.0;
          double curResult = Double.NaN;
          iter = resultList.listIterator(resultList.size());
          while (iter.hasPrevious()) {
            ResultEntry entry = iter.previous();
            if (Double.isNaN(curResult)) {
              curResult = entry.result;
            } else {
              max = Math.max(max, Math.abs(entry.result - curResult));
            }
           
            if (max > 0.0) {
              x = (int) (foldX(entry.points) * width);
              y = (int) (-foldY(max) * height) + height;
              connect.to(x, y);
            }
          }
        }
       
        if (plotButton[2].isSelected()) {
          List<Double> varList = new LinkedList<Double>();
         
          g.setColor(Color.BLUE);
          connect = new Connect(g);
          iter = resultList.listIterator(resultList.size());
          double eMax = Double.NEGATIVE_INFINITY, eMin = Double.POSITIVE_INFINITY;
          while (iter.hasPrevious()) {
            ResultEntry entry = iter.previous();
            eMax = Math.max(eMax, entry.result);
            eMin = Math.min(eMin, entry.result);
           
            if (eMin != eMax) {
              varList.add(0, new Double(eMax - eMin));
              x = (int) (foldX(entry.points) * width);
              y = (int) (-foldY(eMax - eMin) * height) + height;
              connect.to(x, y);
            }
          }
        }
       
        if (plotButton[3].isSelected()) {
          double currErr = estimator.getEstimate();
          double slope = estimator.getSlope();
         
          g.setColor(Color.CYAN);
          x = (int) (foldX(calls) * width);
          y = (int) (-foldY(currErr) * height) + height;
          int x2 = (int) (foldX(1) * width);
          int y2 = (int) (-foldY(currErr * Math.pow(calls, -slope)) * height) + height;
          g.drawLine(x, y, x2, y2);
        }
      }
    }

    public void mouseDragged(MouseEvent e) {}

    public void mouseMoved(MouseEvent e) {
      int width = getWidth();
      int height = getHeight();
      double x = unfoldX((double) e.getX() / width);
      double y = unfoldY(-((double) e.getY() - height) / height);
      yField.setText("Y: " + y);
      callsField.setText("Calls: " + (long) x);
    }
  }
 
  private double foldX(double x) {
    double maxX;
    synchronized (resultList) {
      maxX = calls;
    }
    double mul = zoomXBar.getValue() / 100.0;
    return MathTN.log10(x / maxX) / 10 * mul + 0.98;
  }
 
  private double foldY(double y) {
    double mul = -zoomYBar.getValue() / 2000.0;
    return (MathTN.log10(y + 1e-100) + 15 + (shiftYBar.getValue() / 10.0)) * mul;
  }
 
  private double unfoldX(double foldedX) {
    double maxX;
    synchronized (resultList) {
      maxX = calls;
    }
    double mul = zoomXBar.getValue() / 100.0;
    return maxX * Math.pow(10.0, (foldedX - 0.98) * 10.0 / mul);
  }
 
  private double unfoldY(double foldedY) {
    double mul = -zoomYBar.getValue() / 2000.0;
    return Math.pow(10.0, foldedY / mul - 15 - shiftYBar.getValue() / 10.0) + 1e-100;
  }
 
  static private class Connect {
    int lastx, lasty;
    Graphics g;
   
    Connect(Graphics g) {
      this.g = g;
      init();
    }
   
    void init() {
      lastx = -1;
    }
   
    void to(int x, int y) {
      if (lastx != -1) {
        g.drawLine(lastx, lasty, x, y);
      }
         
      lastx = x;
      lasty = y;
    }
  }
 
  static private class ResultEntry {
    long points;
    double result;
    double estimate;
   
    ResultEntry(long calls, double result, double estimate) {
      points = calls;
      this.result = result;
      this.estimate = estimate;
    }
  }
}
TOP

Related Classes of de.torstennahm.integrate.visualize.ResultVisualizer$ResultEntry

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.