Package de.torstennahm.integrate.sparse.visualize

Source Code of de.torstennahm.integrate.sparse.visualize.ContributionVisualizer$IndexPanel

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

import java.awt.Color;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.AdjustmentEvent;
import java.awt.event.AdjustmentListener;
import java.text.DecimalFormat;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;

import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollBar;
import javax.swing.JTextField;
import javax.swing.JToggleButton;
import javax.swing.border.BevelBorder;

import de.torstennahm.integrate.IntegrationFailedException;
import de.torstennahm.integrate.sparse.evaluateindex.Evaluator;
import de.torstennahm.integrate.sparse.index.FlatIndexGenerator;
import de.torstennahm.integrate.sparse.index.Index;
import de.torstennahm.integrate.visualize.Visualizer;
import de.torstennahm.integrate.visualizerdata.Integrand;
import de.torstennahm.integrate.visualizerdata.StopIntegration;
import de.torstennahm.integrate.visualizerdata.VisualizerData;
import de.torstennahm.math.MathTN;
import de.torstennahm.util.Util;

/**
* This visualizer displays two sets of indices. The head set is displayed in the
* upper panel and shows the integral contributions for all indices that have
* been evaluated by the integrator. The tail set consists of all those indices
* that have not been evaluated, and is displayed in the lower panel.
* It is generated by a background thread after integration finishes.
* The logarithms of the absolute values are displayed, with black marking positive
* and red marking negative values.
*
* @author Torsten Nahm
*/
public class ContributionVisualizer implements Visualizer {
  private final JFrame frame;
  private String title;
 
  private JPanel[] indexPanel;
  private JPanel mainPanel;
  private JTextField ratingField;
  private JScrollBar scrollBar;
  private JScrollBar zoomYBar;
  private JToggleButton activeButton;
 
  private ContributionWorker worker = null;
 
  private Set<Index> evaluatedIndices = new TreeSet<Index>();
 
  /* synchronized by class */
  private boolean destroyed = false;
 
  /* synchronized by lock */
  Object lock = new Object();
  boolean stopped;
  boolean active;
  Evaluator evaluator;
 
  /* synchronized by headList */
  private List<IndexEntry> headList = new LinkedList<IndexEntry>();
 
  /* synchronized by tailSet */
  private SortedSet<IndexEntry> tailSet = new TreeSet<IndexEntry>();
 
  public ContributionVisualizer(JFrame frame) {
    this.frame = frame;
    if (frame != null) {
      title = frame.getTitle();
    }
  }
 
  public void init() {
    if (destroyed) { return; }
   
    if (frame != null) {
      initGUI();
     
      worker = new ContributionWorker(this);
      worker.start();
    }
  }
 
  private void initGUI() {
    indexPanel = new JPanel[2];
    mainPanel = new JPanel();
    ratingField = new JTextField();
    scrollBar = new JScrollBar(JScrollBar.HORIZONTAL);
    zoomYBar = new JScrollBar(JScrollBar.VERTICAL, -120, 1, -150, -40);
    activeButton = new JToggleButton("Active");
   
    for (int i = 0; i < 2; i++) {
      indexPanel[i] = new IndexPanel(i);
      indexPanel[i].setBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED));
    }
   
    ratingField.setEditable(false);
   
    GridBagLayout g = new GridBagLayout();
    GridBagConstraints c = new GridBagConstraints();
    mainPanel.setLayout(g);
    c.fill = GridBagConstraints.BOTH;
    c.weightx = 1.0;
    c.gridwidth = GridBagConstraints.REMAINDER;
   
    JPanel panel = new JPanel();
    GridBagConstraints cp = new GridBagConstraints();
    cp.fill = GridBagConstraints.BOTH;
   
    panel.setLayout(new GridBagLayout());
    cp.weightx = 3.0;
    panel.add(ratingField, cp);
    cp.weightx = 0.0;
    panel.add(activeButton, cp);
   
    c.weighty = 0.0;
    mainPanel.add(panel, c);
   
    panel = new JPanel();
    panel.setLayout(new GridBagLayout());
    cp.gridx = 0;
    cp.gridy = 0;
    cp.gridheight = 1;
    cp.weightx = 1.0;
    cp.weighty = 1.0;
    panel.add(indexPanel[0], cp);
    cp.gridx++;
    cp.gridheight = 2;
    cp.weightx = 0.0;
    cp.gridwidth = GridBagConstraints.REMAINDER;
    panel.add(zoomYBar, cp);
    cp.gridx = 0;
    cp.gridy++;
    cp.gridwidth = 1;
    cp.gridheight = 1;
    cp.weightx = 1.0;
    panel.add(indexPanel[1], cp);
   
    c.weighty = 1.0;
    mainPanel.add(panel, c);
   
    c.weighty = 0.0;
    mainPanel.add(scrollBar, c);
       
    AdjustmentListener listener = new AdjustmentListener() {
      public void adjustmentValueChanged(AdjustmentEvent e) {
        indexPanel[0].repaint();
        indexPanel[1].repaint();
      }
    };
    scrollBar.addAdjustmentListener(listener);
    zoomYBar.addAdjustmentListener(listener);
   
    frame.getContentPane().add(mainPanel);
   
    activeButton.setSelected(false);
    activeButton.setEnabled(false);
   
    activeButton.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        updateWorkerStatus();
      }
    });
   
    frame.setVisible(true);
  }

  public void start() {
    if (destroyed) { return; }
   
    synchronized (headList) {
      headList = new LinkedList<IndexEntry>();
    }
    synchronized (tailSet) {
      tailSet = new TreeSet<IndexEntry>();
    }
   
    evaluatedIndices = new HashSet<Index>();
   
    synchronized (lock) {
      active = false;
      evaluator = null;
    }
   
    updateWorkerStatus();
   
    if (frame != null) {
      activeButton.setEnabled(true);
      frame.setTitle(title);
      ratingField.setText("No rating data available");
      indexPanel[0].repaint();
      indexPanel[1].repaint();
    }
  }
 
  public void submit(VisualizerData data) {
    if (destroyed) { return; }
   
    if (data instanceof Integrand) {
      if (((Integrand) data).integrand instanceof Evaluator) {
        evaluator = (Evaluator) ((Integrand) data).integrand;
      }
    } else if (data instanceof StopIntegration) {
      updateDisplay();
     
      synchronized (lock) {
        active = true;
      }
      updateWorkerStatus();
     
      if (evaluator != null && worker != null) {
        worker.startWorker(evaluator, evaluatedIndices, tailSet);
      }
    } else if (data instanceof IndexContribution) {
      Index index = ((IndexContribution) data).index;
      double contribution = ((IndexContribution) data).contribution;
     
      double relResult = Double.NaN;
      if (evaluator != null) {
        relResult = contribution / evaluator.pointsForIndex(index);
        synchronized (headList) {
          headList.add(new IndexEntry(relResult));
        }
        if (frame != null) {
          indexPanel[0].repaint();
        }
      }

      evaluatedIndices.add(index);
    }
  }
 
  public void stop() {
    if (destroyed) { return; }
   
    if (frame != null) {
      frame.setTitle(title + " (stopped)");
      activeButton.setEnabled(false);
    }
   
    synchronized (lock) {
      active = false;
    }
    updateWorkerStatus();
  }
 
  synchronized public void destroy() {
    if (destroyed) { return; }
   
    destroyed = true;
   
    if (worker != null) {
      worker.terminate();
    }
    if (frame != null) {
      frame.dispose();
    }
  }
 
  private void updateWorkerStatus() {
    synchronized (lock) {
      if (worker != null) {
        worker.setActive(active && activeButton.isSelected());
      }
    }
  }
 
  public void updateDisplay() {
    if (frame != null) {
      double[] rating;
     
      synchronized (tailSet) {
        rating = getRatings(headList, tailSet);
        scrollBar.setValues(scrollBar.getValue(), headList.size(), 0, tailSet.size());
      }
     
      DecimalFormat df = new DecimalFormat("0.####");
      ratingField.setText("Quotient:" + Util.format(rating[0]) + " Plain: " + df.format(rating[1]) + " Weighted: " + df.format(rating[2]));
     
      indexPanel[1].repaint();
    }
  }
 
  public double[] getRatings(long numPoints) {
    if (evaluator != null) {
      SortedSet<IndexEntry> tailSet = new TreeSet<IndexEntry>();
      FlatIndexGenerator indexIter = new FlatIndexGenerator(evaluator.dimension());
     
      long points = 0;
      while (points < numPoints) {
        Index index = indexIter.next();
       
        if (! evaluatedIndices.contains(index)) {
          try {
            double contribution = evaluator.deltaEvaluate(index);
            points += evaluator.pointsForIndex(index);
           
            double relResult = contribution / evaluator.pointsForIndex(index);
            tailSet.add(new IndexEntry(relResult));
          } catch (IntegrationFailedException e) {
          }
        }
      }
    }
   
    return getRatings(headList, tailSet);
  }
 
  static private double[] getRatings(List<IndexEntry> headList, SortedSet<IndexEntry> tailSet) {
    SortedSet<IndexEntry> allSet;
    int headSize;
    double headContributionSum = 0;
    double tailContributionSum = 0;
   
    headSize = headList.size();
    allSet = new TreeSet<IndexEntry>();
    allSet.addAll(headList);
    allSet.addAll(tailSet);
   
    for (IndexEntry entry : headList) {
      headContributionSum += Math.abs(entry.relR);
    }
    for (IndexEntry entry : tailSet) {
      tailContributionSum += Math.abs(entry.relR);
    }
   
    int c1 = 0, c2 = 0;
    for (IndexEntry entry : tailSet) {
      int pos = allSet.headSet(entry).size();
      if (pos >= headSize) {
        break;
      }
     
      c1++;
      c2 += (headSize - pos);
    }
   
    double r1 = tailContributionSum / headContributionSum;
    double r2 = (double)c1 / headSize;
    double r3 = (double)c2 / (headSize * (headSize + 1) / 2);
   
    return new double[] { r1, r2, r3 };
  }
 
  static public class IndexEntry implements Comparable {
    static private int current = 0;
 
    public final double relR;
    public final int count;
   
    IndexEntry(double relResult) {
      relR = relResult;
      count = current++;
    }
   
    public int compareTo(Object o) {
      IndexEntry i = (IndexEntry) o;
      if (Math.abs(relR) < Math.abs(i.relR)) {
        return 1;
      } else if (Math.abs(relR) > Math.abs(i.relR)) {
        return -1;
      } else {
        return count - i.count;
      }
    }
  }
 
  private class IndexPanel extends JPanel {
    private static final long serialVersionUID = -3416547179794894270L;
   
    private int listNumber;
   
    public IndexPanel(int list) {
      this.listNumber = list;
    }
   
    @Override
    public void paintComponent(Graphics g) {
      super.paintComponent(g);
     
      int width = getWidth();
      int height = getHeight();
     
      int barY;
      int p = -14;
      do {
        g.setColor((p % 5 == 0) ? new Color(0, 0, 0.6f) : Color.GRAY);
        double barValue = Math.pow(10.0, p);
        barY = (int) (-foldY(barValue) * height + height);
        g.drawLine(0, barY, width - 1, barY);
        p++;
      } while (barY >= 0);
     
      int headEntries = 0;
      Iterator<IndexEntry> iter = null;
     
      int start = 0;
     
      if (listNumber == 0) {
        synchronized (headList) {
          iter = new LinkedList<IndexEntry>(headList).iterator();
          headEntries = headList.size();
        }
       
        start = 0;
      } else if (listNumber == 1) {
        synchronized (headList) {
          headEntries = headList.size();
        }
       
        synchronized (tailSet) {
          iter = new LinkedList<IndexEntry>(tailSet).iterator();
        }
       
        start = scrollBar.getValue();
      }
     
      for (int i = 0; i < start && iter.hasNext(); i++) {
        iter.next();
      }
     
      if (iter != null) {
        int x, lastx = -1, y, lasty = 0;
       
        for (int i = 0; i < headEntries && iter.hasNext(); i++) {
          IndexEntry entry = iter.next();
          x = (int) (foldX(i, headEntries) * width);
         
          double h = Math.abs(entry.relR);
          y = (int) (-foldY(h) * height + height);
         
          g.setColor(entry.relR >= 0 ? Color.BLACK : Color.RED);
          if (lastx != -1) {
            g.drawLine(lastx, lasty, x, y);
          }
         
          lastx = x;
          lasty = y;
        }
      }
     
//      if (! efficiency && regressionVisualizer != null) {
//        g.setColor(Color.GREEN);
//        double a, b;
//        a = regressionVisualizer.getSlope();
//        b = regressionVisualizer.getYIntercept();
//       
//        int firstIndex = (listNumber == 0) ? start : start + headEntries;
//        int y0 = (int) (-foldY(Math.exp(b + a * firstIndex)) * height + height);
//        int y1 = (int) (-foldY(Math.exp(b + a * (firstIndex + headEntries))) * height + height);
//        g.drawLine(0, y0, width, y1);
//      }
    }
  }
 
  private double foldX(double x, double maxX) {
    return x / maxX;
  }
 
  private double foldY(double y) {
    double mul = Math.pow(10.0, zoomYBar.getValue() / 100.0);
    double yy = MathTN.log10(y / 1e-14) * mul;
   
    return Math.max(0, yy);
  }
}
TOP

Related Classes of de.torstennahm.integrate.sparse.visualize.ContributionVisualizer$IndexPanel

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.