
org.diirt.graphene.profile.VisualProfiler Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of graphene-profile Show documentation
Show all versions of graphene-profile Show documentation
Tools to profile the graph library.
/**
* Copyright (C) 2010-14 diirt developers. See COPYRIGHT.TXT
* All rights reserved. Use is subject to license terms. See LICENSE.TXT
*/
package org.diirt.graphene.profile;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Desktop;
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.DefaultComboBoxModel;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTabbedPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.JTree;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreePath;
import org.diirt.graphene.Graph2DRendererUpdate;
import org.diirt.graphene.profile.impl.ProfileAreaGraph2D;
import org.diirt.graphene.profile.impl.ProfileBubbleGraph2D;
import org.diirt.graphene.profile.impl.ProfileHistogram1D;
import org.diirt.graphene.profile.impl.ProfileIntensityGraph2D;
import org.diirt.graphene.profile.impl.ProfileLineGraph2D;
import org.diirt.graphene.profile.impl.ProfileMultiYAxisGraph2D;
import org.diirt.graphene.profile.impl.ProfileMultilineGraph2D;
import org.diirt.graphene.profile.impl.ProfileNLineGraphs2D;
import org.diirt.graphene.profile.impl.ProfileScatterGraph2D;
import org.diirt.graphene.profile.impl.ProfileSparklineGraph2D;
import org.diirt.graphene.profile.io.DateUtils;
import org.diirt.graphene.profile.io.DateUtils.DateFormat;
import org.diirt.graphene.profile.utils.DatasetFactory;
import org.diirt.graphene.profile.utils.ProfileAnalysis;
import org.diirt.graphene.profile.utils.Resolution;
import org.diirt.graphene.profile.utils.Statistics;
import org.diirt.graphene.profile.utils.StopWatch;
import org.diirt.graphene.profile.utils.StopWatch.TimeType;
/**
* Displays options and actions for profiling of the Graphene project
* in a graphical-user-interface.
*
* @author asbarber
*/
public class VisualProfiler extends JPanel{
//Data
//-------------------------------------------------------------------------
private SwingWorker thread;
private List actionButtons;
private ActionModel model;
private UserSettings userSettings;
//-------------------------------------------------------------------------
//Panel Data Members
//-------------------------------------------------------------------------
private JTabbedPane tabs;
private SettingsPanel settingsPanel;
private Profile1DTable profile1DTable;
private Profile2DTable profile2DTable;
private FileViewer fileViewer;
private AnalyzePanel analyzePanel;
private Console console;
//-------------------------------------------------------------------------
//Panel Structures
//-------------------------------------------------------------------------
private class SettingsPanel extends JPanel{
public JComboBox listRendererTypes;
private JLabel lblRendererTypes;
private JTextField txtTestTime;
private JLabel lblTestTime;
private JTextField txtMaxAttempts;
private JLabel lblMaxAttempts;
private JComboBox listTimeTypes;
private JLabel lblTimeTypes;
private JLabel lblSaveImage;
private JCheckBox chkSaveImage;
private JList listUpdateTypes;
private JLabel lblUpdateTypes;
private JLabel lblSaveMessage;
private JTextField txtSaveMessage;
private JLabel lblAuthorMessage;
private JTextField txtAuthorMessage;
public SettingsPanel(){
this.initComponents();
this.addComponents();
}
private void initComponents(){
listRendererTypes = new JComboBox(SUPPORTED_PROFILERS);
lblRendererTypes = new JLabel("Renderer Type: ");
txtTestTime = new JTextField("20");
lblTestTime = new JLabel("Test Time: ");
txtMaxAttempts = new JTextField("1000000");
lblMaxAttempts = new JLabel("Max Attempts: ");
listTimeTypes = new JComboBox(StopWatch.TimeType.values());
lblTimeTypes = new JLabel("Timing Based Off: ");
lblSaveImage = new JLabel("Save Images: ");
chkSaveImage = new JCheckBox("Save Image");
listUpdateTypes = new JList();
lblUpdateTypes = new JLabel("Apply Update: ");
lblSaveMessage = new JLabel("Save Message: ");
txtSaveMessage = new JTextField("");
lblAuthorMessage = new JLabel("Author: ");
txtAuthorMessage = new JTextField("");
}
private void addComponents(){
JPanel right = new JPanel();
right.setLayout(new BorderLayout());
right.add(this.lblUpdateTypes, BorderLayout.NORTH);
right.add(new JScrollPane(this.listUpdateTypes), BorderLayout.CENTER);
JPanel left = new JPanel();
left.setLayout(new GridLayout(0, 2));
left.add(this.lblRendererTypes);
left.add(this.listRendererTypes);
left.add(this.lblTestTime);
left.add(this.txtTestTime);
left.add(this.lblMaxAttempts);
left.add(this.txtMaxAttempts);
left.add(this.lblTimeTypes);
left.add(this.listTimeTypes);
left.add(this.lblSaveImage);
left.add(this.chkSaveImage);
left.add(lblSaveMessage);
left.add(txtSaveMessage);
left.add(lblAuthorMessage);
left.add(txtAuthorMessage);
this.setLayout(new GridLayout(0,2));
this.add(left);
this.add(right);
}
}
private class Profile1DTable extends JPanel{
private JLabel lblDatasetSize;
private JTextField txtDatasetSize;
private JLabel lblImageWidth;
private JTextField txtImageWidth;
private JLabel lblImageHeight;
private JTextField txtImageHeight;
private JLabel lblShowGraph;
private JCheckBox chkShowGraph;
public JButton btnProfile1D;
public JButton btnProfile1DAll;
public Profile1DTable(){
this.initComponents();
this.initMnemonics();
this.addComponents();
}
private void initComponents(){
lblDatasetSize = new JLabel("Number of Data Points: ");
lblDatasetSize .setToolTipText("Format for IntensityGraph2D: 1000x1000");
txtDatasetSize = new JTextField("10000");
lblImageWidth = new JLabel("Image Width: ");
txtImageWidth = new JTextField("640");
lblImageHeight = new JLabel("Image Height: ");
txtImageHeight = new JTextField("480");
lblShowGraph = new JLabel("Graph Results: ");
chkShowGraph = new JCheckBox("Show Graph");
btnProfile1D = new JButton("Profile");
actionButtons .add(btnProfile1D);
btnProfile1DAll = new JButton("Profile For All Renderers");
actionButtons .add(btnProfile1DAll);
}
private void initMnemonics(){
this.btnProfile1D.setMnemonic('P');
this.btnProfile1DAll.setMnemonic('A');
}
private void addComponents(){
this.setLayout(new GridLayout(0, 2));
this.add(lblDatasetSize);
this.add(txtDatasetSize);
this.add(lblImageWidth);
this.add(txtImageWidth);
this.add(lblImageHeight);
this.add(txtImageHeight);
this.add(lblShowGraph);
this.add(chkShowGraph);
this.add(blankPanel(btnProfile1D));
this.add(blankPanel(btnProfile1DAll));
}
/**
* Gets the input from the user interface on whether graphs of statistics
* are shown after profiling.
* @return true if graphs of profile statistics are shown after profiling,
* false if graphs of profile statistics are not shown
*/
public boolean getShowGraph(){
return profile1DTable.chkShowGraph.isSelected();
}
}
private class Profile2DTable extends JSplitPane{
private JLabel lblResolutions,
lblNPoints;
public JButton btnProfile2D;
private JList listResolutions;
private JList listNPoints;
private DefaultListModel modelResolutions;
private DefaultListModel modelNPoints;
public Profile2DTable(){
this.initComponents();
this.initMnemonics();
this.addComponents();
this.loadLists();
}
private void initComponents(){
lblResolutions = new JLabel("Resolutions");
lblNPoints = new JLabel("N Points");
btnProfile2D = new JButton("Start");
actionButtons .add(btnProfile2D);
listResolutions = new JList<>();
listNPoints = new JList<>();
}
private void initMnemonics(){
this.btnProfile2D.setMnemonic('S');
}
private void addComponents(){
JPanel multiLayerLeft = new JPanel();
multiLayerLeft.setLayout(new BorderLayout());
multiLayerLeft.add(lblResolutions, BorderLayout.NORTH);
multiLayerLeft.add(new JScrollPane(listResolutions), BorderLayout.CENTER);
JPanel multiLayerMiddle = new JPanel();
multiLayerMiddle.setLayout(new BorderLayout());
multiLayerMiddle.add(lblNPoints, BorderLayout.NORTH);
multiLayerMiddle.add(new JScrollPane(listNPoints), BorderLayout.CENTER);
JPanel multiLayerRight = new JPanel();
multiLayerRight.setLayout(new BorderLayout());
multiLayerRight.add(blankPanel(btnProfile2D), BorderLayout.NORTH);
final JSplitPane multiLayerInner = new JSplitPane();
multiLayerInner.setLeftComponent(multiLayerLeft);
multiLayerInner.setRightComponent(multiLayerMiddle);
this.setLeftComponent(multiLayerInner);
this.setRightComponent(multiLayerRight);
SwingUtilities.invokeLater(new Runnable(){
@Override
public void run() {
Profile2DTable.this.setDividerLocation(0.8);
multiLayerInner.setDividerLocation(0.8);
}
});
}
/**
* Loads the lists for Resolution
s and the
* dataset sizes for the MultiLevelProfiler
.
*/
private void loadLists(){
modelResolutions = new DefaultListModel<>();
modelNPoints = new DefaultListModel<>();
for (Resolution resolution : Resolution.defaultResolutions()){
modelResolutions.addElement(resolution);
}
for (Integer datasetSize : DatasetFactory.defaultDatasetSizes()){
modelNPoints.addElement(datasetSize);
}
listResolutions.setModel(modelResolutions);
listNPoints.setModel(modelNPoints);
}
}
private class AnalyzePanel extends JPanel{
public JButton btnCompare2DTables;
public JButton btnAnalyze1DTable;
public AnalyzePanel(){
this.initComponents();
this.addComponents();
}
private void initComponents(){
btnCompare2DTables = new JButton("Compare Profile Tables");
actionButtons .add(btnCompare2DTables);
btnAnalyze1DTable = new JButton("Analyze Single Profile Tables");
actionButtons .add(btnAnalyze1DTable);
}
private void addComponents(){
this.add(this.btnCompare2DTables);
this.add(this.btnAnalyze1DTable);
}
}
private class FileViewer extends JSplitPane{
private JTree tree;
private DefaultTreeModel treeModel;
private DefaultMutableTreeNode treeRoot;
public JButton btnOpenFiles;
public JButton btnDeleteFiles;
public JButton btnReloadFiles;
public FileViewer(){
this.initComponents();
this.initMenmonics();
this.addComponents();
}
private void initComponents(){
treeRoot = new DefaultMutableTreeNode(new File(ProfileGraph2D.LOG_FILEPATH));
treeModel = new DefaultTreeModel(treeRoot);
tree = new JTree(treeRoot){
@Override
public String convertValueToText(Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus){
DefaultMutableTreeNode node = (DefaultMutableTreeNode) value;
try{
File f = (File) node.getUserObject();
return f.getName();
}
catch(Exception e){
return node.toString();
}
}
};
tree .setModel(treeModel);
tree .expandRow(0);
tree .setShowsRootHandles(true);
btnOpenFiles = new JButton("Open File(s)");
actionButtons .add(btnOpenFiles);
btnDeleteFiles = new JButton("Delete File(s)");
actionButtons .add(btnDeleteFiles);
btnReloadFiles = new JButton("Refresh");
actionButtons .add(btnReloadFiles);
}
private void initMenmonics(){
this.btnOpenFiles.setMnemonic('O');
this.btnDeleteFiles.setMnemonic('D');
this.btnReloadFiles.setMnemonic('R');
}
private void addComponents(){
JPanel fileTabRight = new JPanel();
fileTabRight.setLayout(new BoxLayout(fileTabRight, BoxLayout.Y_AXIS));
fileTabRight.add(this.btnOpenFiles);
fileTabRight.add(this.btnDeleteFiles);
fileTabRight.add(this.btnReloadFiles);
this.setLeftComponent(new JScrollPane(tree));
this.setRightComponent(fileTabRight);
}
public void reloadNodes(){
//Resets
this.treeRoot.removeAllChildren();
//Re-adds
model.addNodes(treeRoot);
//Updates GUI
this.treeModel.nodeStructureChanged(this.treeRoot);
this.repaint();
}
}
private class Console extends JPanel{
private JTextArea txtConsole;
private JLabel lblConsole;
public JButton btnClearLog;
public JButton btnSaveLog;
private JLabel lblTime;
private JTextField txtTime;
public JButton btnCancelThread;
public Console(){
this.initComponents();
this.initMnemonics();
this.addComponents();
}
private void initComponents(){
txtConsole = new JTextArea(20, 50);
txtConsole.setEditable(false);
lblConsole = new JLabel("Console");
btnSaveLog = new JButton("Save Log");
actionButtons.add(btnSaveLog);
btnClearLog = new JButton("Clear Log");
actionButtons.add(btnClearLog);
lblTime = new JLabel("Timer:");
txtTime = new JTextField("00:00:00");
txtTime.setEditable(false);
btnCancelThread = new JButton("Cancel");
btnCancelThread.setEnabled(false);
actionButtons.add(btnCancelThread);
}
private void initMnemonics(){
this.btnSaveLog.setMnemonic('L');
this.btnClearLog.setMnemonic('C');
this.btnCancelThread.setMnemonic('T');
}
private void addComponents(){
this.setLayout(new BorderLayout());
this.setBorder(BorderFactory.createLineBorder(Color.black));
JPanel consoleBottom = new JPanel();
consoleBottom.setLayout(new GridLayout(3, 2));
consoleBottom.add(blankPanel(this.btnSaveLog));
consoleBottom.add(blankPanel(this.btnClearLog));
consoleBottom.add(blankPanel(this.lblTime));
consoleBottom.add(blankPanel(this.txtTime));
consoleBottom.add(blankPanel(this.btnCancelThread));
this.add(lblConsole, BorderLayout.NORTH);
this.add(new JScrollPane(txtConsole), BorderLayout.CENTER);
this.add(consoleBottom, BorderLayout.SOUTH);
}
public void print(List chunks){
for (String chunk: chunks){
txtConsole.append(chunk);
}
}
}
//-------------------------------------------------------------------------
//Values, Constants
//-------------------------------------------------------------------------
/**
* Package location for ProfileGraph2D
subclasses.
*/
public static final String PROFILE_PATH = "org.diirt.graphene.profile.impl";
/**
* Java class names of all ProfileGraph2D
subclasses.
*/
public static final String[] SUPPORTED_PROFILERS = {"AreaGraph2D",
"BubbleGraph2D",
"Histogram1D",
"IntensityGraph2D",
"LineGraph2D",
"MultiYAxisGraph2D",
"MultilineGraph2D",
"NLineGraphs2D",
"ScatterGraph2D",
"SparklineGraph2D"
};
/**
* File names of files that cannot be deleted (protected) by the
* VisualProfiler
's FileViewer
.
*/
public static final String[] PROTECTED_FILES = {"ProfileResults",
"1D Table Output",
"2D Table Output",
"Tests",
"README.txt"
};
/**
* Title of the auto-generated frame.
*/
public static final String FRAME_TITLE = "Visual Profiler";
/**
* Makes a Profile object based off of the class name.
* @param strClass name of Profile object to generate
*
* @return a ProfileGraph2D
object corresponding to the
* class name, returns null if no matching name
*/
public static ProfileGraph2D factory(String strClass){
switch (strClass) {
case "AreaGraph2D":
return new ProfileAreaGraph2D();
case "BubbleGraph2D":
return new ProfileBubbleGraph2D();
case "Histogram1D":
return new ProfileHistogram1D();
case "IntensityGraph2D":
return new ProfileIntensityGraph2D();
case "LineGraph2D":
return new ProfileLineGraph2D();
case "MultiYAxisGraph2D":
return new ProfileMultiYAxisGraph2D();
case "MultilineGraph2D":
return new ProfileMultilineGraph2D();
case "NLineGraphs2D":
return new ProfileNLineGraphs2D();
case "ScatterGraph2D":
return new ProfileScatterGraph2D();
case "SparklineGraph2D":
return new ProfileSparklineGraph2D();
}
return null;
}
//-------------------------------------------------------------------------
//Action Structure
//-------------------------------------------------------------------------
private class UserSettings{
public Integer getWidth(){
String strImageWidth = profile1DTable.txtImageWidth.getText();
int width;
try{
width = Integer.parseInt(strImageWidth);
if (width <= 0){
throw new NumberFormatException();
}
return width;
}catch(NumberFormatException e){
JOptionPane.showMessageDialog(null, "Enter a positive non-zero integer for the height.", "Error", JOptionPane.ERROR_MESSAGE);
return null;
}
}
public Integer getHeight(){
String strImageHeight = profile1DTable.txtImageHeight.getText();
int height;
try{
height = Integer.parseInt(strImageHeight);
if (height <= 0){
throw new NumberFormatException();
}
return height;
}catch(NumberFormatException e){
JOptionPane.showMessageDialog(null, "Enter a positive non-zero integer for the height.", "Error", JOptionPane.ERROR_MESSAGE);
return null;
}
}
public boolean getSaveImage(){
return settingsPanel.chkSaveImage.isSelected();
}
public Integer getTestTime(){
String strTestTime = settingsPanel.txtTestTime.getText();
Integer testTime;
try{
testTime = Integer.parseInt(strTestTime);
if (testTime <= 0){
throw new NumberFormatException();
}
return testTime;
}catch(NumberFormatException e){
JOptionPane.showMessageDialog(null, "Enter a positive non-zero integer for test time.", "Error", JOptionPane.ERROR_MESSAGE);
return null;
}
}
public Integer getMaxTries(){
String strMaxAttempts = settingsPanel.txtMaxAttempts.getText();
int maxAttempts;
try{
maxAttempts = Integer.parseInt(strMaxAttempts);
if (maxAttempts <= 0){
throw new NumberFormatException();
}
return maxAttempts;
}catch(NumberFormatException e){
JOptionPane.showMessageDialog(null, "Enter a positive non-zero integer for max attempts.", "Error", JOptionPane.ERROR_MESSAGE);
return null;
}
}
public TimeType getTimeType(){
return (StopWatch.TimeType) settingsPanel.listTimeTypes.getSelectedItem();
}
public List getUpdateDescriptionList(){
return settingsPanel.listUpdateTypes.getSelectedValuesList();
}
public String getAuthor(){
return settingsPanel.txtAuthorMessage.getText();
}
public String getSaveMessage(){
return settingsPanel.txtSaveMessage.getText();
}
public ProfileGraph2D getProfiler(){
ProfileGraph2D renderer = selectedProfiler();
if (renderer == null){ return null; }
return applyDataset(applySettings(renderer));
}
public ProfileGraph2D selectedProfiler(){
String strClass = settingsPanel.listRendererTypes.getSelectedItem().toString();
return makeProfiler(strClass);
}
public ProfileGraph2D makeProfiler(String strClass){
return factory(strClass);
}
public ProfileGraph2D applySettings(ProfileGraph2D renderer){
renderer.getProfileSettings().setTestTime(getTestTime());
renderer.getProfileSettings().setMaxTries(getMaxTries());
renderer.getProfileSettings().setTimeType(getTimeType());
renderer.getRenderSettings().setUpdate(getUpdateDescriptionList());
renderer.getResolution().setWidth(getWidth());
renderer.getResolution().setHeight(getHeight());
renderer.getSaveSettings().setAuthorMessage(getAuthor());
renderer.getSaveSettings().setSaveMessage(getSaveMessage());
return renderer;
}
public ProfileGraph2D applyDataset(ProfileGraph2D renderer){
String strSize = profile1DTable.txtDatasetSize.getText();
int size;
try{
if (renderer instanceof ProfileIntensityGraph2D){
ProfileIntensityGraph2D i = (ProfileIntensityGraph2D) renderer;
int w, h;
if (strSize.contains("x")){
w = Integer.parseInt(strSize.substring(0, strSize.indexOf("x")));
h = (Integer.parseInt(strSize.substring(strSize.indexOf("x")+1)));
i.setNumXDataPoints(w);
i.setNumYDataPoints(h);
return i;
}
}
size = Integer.parseInt(strSize);
renderer.setNumDataPoints(size);
if (size <= 0){
throw new NumberFormatException();
}
}catch (Exception e){
JOptionPane.showMessageDialog(null, "Enter a positive non-zero integer for the dataset size. Use 1000x1000 for 2D cell data.", "Error", JOptionPane.ERROR_MESSAGE);
return null;
}
return renderer;
}
}
private class ActionModel{
private void startTimer(){
SwingWorker worker = new SwingWorker
© 2015 - 2025 Weber Informatics LLC | Privacy Policy