[june22_2007_singlefeaturestuff
douglas@music.columbia.edu**20070623031610
 
 Started working on a new architecture for the visualizers. 
 
 SingleFeaturePanel panel that can be subclassed to 
 implement various visualization types. 
 SingleFeaturePanelTester shows how you can build
 a visualizer by simply adding multiple SFPs.
 This seems a lot easier and more extendable
 then the current monolithic version.
 
 .d
 
] {
hunk ./src/com/meapsoft/FeatFile.java 65
-    // it - its bad news.
+    // it - it's bad news.
addfile ./src/com/meapsoft/visualizer/MultiFileFeatureRenderer.java
hunk ./src/com/meapsoft/visualizer/MultiFileFeatureRenderer.java 1
+/*
+ *  Copyright 2006-2007 Columbia University.
+ *
+ *  This file is part of MEAPsoft.
+ *
+ *  MEAPsoft is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  MEAPsoft 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
+ *  General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with MEAPsoft; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ *  02110-1301 USA
+ *
+ *  See the file "COPYING" for the text of the license.
+ */
+
+/*
+ * Created on Nov 15, 2006
+ *
+ * various ways of viewing EDL files
+ * 
+ */
+package com.meapsoft.visualizer;
+
+import java.awt.Color;
+import java.awt.Graphics;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.event.ActionEvent;
+import java.awt.image.BufferedImage;
+import java.util.Vector;
+
+import javax.swing.BoxLayout;
+import javax.swing.JCheckBox;
+import javax.swing.JPanel;
+
+import com.meapsoft.DSP;
+import com.meapsoft.EDLFile;
+import com.meapsoft.FeatFile;
+
+/**
+ * displays multiple SingleFeaturePanels
+ *
+ * @author Douglas Repetto (douglas@music.columbia.edu)
+ * and the MEAP team
+ */
+
+public class MultiFileFeatureRenderer extends Renderer
+{
+	public MultiFileFeatureRenderer(FeatFile featFile, EDLFile eDLFile, String name) {
+		super(featFile, eDLFile, name);
+		// TODO Auto-generated constructor stub
+	}
+
+	@Override
+	public void draw(BufferedImage image, int width, int height) {
+		// TODO Auto-generated method stub
+		
+	}
+
+	@Override
+	public Vector getChunkVisInfosForPoint(Point p) {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	@Override
+	public String getFeatureNameForPoint(Point p) {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	@Override
+	public int getFeatureNumberForPoint(Point p) {
+		// TODO Auto-generated method stub
+		return 0;
+	}
+
+	@Override
+	public double getFeatureValueForPoint(Point p) {
+		// TODO Auto-generated method stub
+		return 0;
+	}
+
+	@Override
+	public void rangeFilterSelectionChanged() {
+		// TODO Auto-generated method stub
+		
+	}
+
+	@Override
+	public void setDragRect(Rectangle r, boolean dS) {
+		// TODO Auto-generated method stub
+		
+	}
+
+	public static void main(String[] args)
+	{	
+		//Schedule a job for the event-dispatching thread:
+		//creating and showing this application's GUI.
+		javax.swing.SwingUtilities.invokeLater(new Runnable() 
+		{
+			public void run() 
+			{
+				new MultiFileFeatureRenderer(null, null, null);
+			}
+		});
+	}
+}
+
+
+
addfile ./src/com/meapsoft/visualizer/SingleFeatureBarGraphPanel.java
hunk ./src/com/meapsoft/visualizer/SingleFeatureBarGraphPanel.java 1
+package com.meapsoft.visualizer;
+
+import java.awt.Color;
+import java.awt.Graphics;
+
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+
+import com.meapsoft.FeatChunk;
+import com.meapsoft.FeatFile;
+
+public class SingleFeatureBarGraphPanel extends SingleFeaturePanel
+{
+
+	public SingleFeatureBarGraphPanel(FeatFile featFile, String featureName) 
+	{
+		super(featFile, featureName);
+		
+		 numDrawableFeatures = 1;
+	}
+
+	public void drawData(Graphics g) 
+	{	
+		int w = this.getWidth();
+		int h = this.getHeight();
+		double yScaler = h/featureRange;
+		
+		double xScaler = w/timeRange;
+		//System.out.println("w: " + w + " h: " + h);
+		//System.out.println("xScaler: " + xScaler + " yScaler: " + yScaler);
+		//System.out.println("numChunks: " + numChunks);
+
+		g.setColor(bgColor);
+		g.fillRect(0, 0, w, h);
+		
+		g.setColor(defaultFGColor);
+		
+		for (int i = 0; i < numChunks; i++)
+		{
+			FeatChunk fC = (FeatChunk)events.elementAt(i);
+			int x = (int)((fC.startTime - firstEventTime) * xScaler);
+			int width = (int)(fC.length * xScaler) + 1;
+			//adjust to zero
+			double dataPoint = featureData[i][0] - lowestValue;
+			int y = (int)(dataPoint * yScaler);
+			//System.out.println("x: " + x + " y: " + y);
+
+			//g.drawLine(xPrev, yPrev, x, y);
+			g.fillRect(x, h - y, width, y);
+		}
+		
+		g.drawString(featureName, 20, 20);
+	}
+
+	public static void main(String[] args)
+	{
+		if (args.length < 2)
+		{
+			System.out.println("usage: SingleFeatureBarGraphPanel myfilename myfeaturename\n");
+			System.exit(-1);
+		}
+
+		final String fileName = args[0];
+		final String featureName = args[1];
+		final FeatFile fF = new FeatFile(fileName);
+		//Schedule a job for the event-dispatching thread:
+		//creating and showing this application's GUI.
+		javax.swing.SwingUtilities.invokeLater(new Runnable() 
+		{
+			public void run() 
+			{
+				JFrame frame = new JFrame("SingleFeatureBarGraphPanel");
+				
+				try
+				{
+					fF.readFile();
+				}
+				catch(Exception e)
+				{
+					e.printStackTrace();
+					System.exit(-1);
+				}
+				SingleFeaturePanel sFP = new SingleFeatureBarGraphPanel(fF, featureName);
+				if (sFP.initialize() == -1)
+				{
+					System.out.println("hmm, something wrong, bailing.");
+					System.exit(-1);
+				}
+				sFP.setSize(600, 400);
+				sFP.setBackgroundColor(Color.YELLOW);
+				sFP.setDefaultForegroundColor(Color.GREEN);
+				
+				frame.setContentPane(sFP);
+				frame.pack();
+				frame.setVisible(true);
+				frame.setBounds(100, 100, 600, 400);
+
+				sFP.repaint();
+			}
+		});
+	}
+}
addfile ./src/com/meapsoft/visualizer/SingleFeatureColorBarsPanel.java
hunk ./src/com/meapsoft/visualizer/SingleFeatureColorBarsPanel.java 1
+package com.meapsoft.visualizer;
+
+import java.awt.Color;
+import java.awt.Graphics;
+
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+
+import com.meapsoft.FeatChunk;
+import com.meapsoft.FeatFile;
+
+public class SingleFeatureColorBarsPanel extends SingleFeaturePanel
+{
+
+	public SingleFeatureColorBarsPanel(FeatFile featFile, String featureName) 
+	{
+		super(featFile, featureName);
+		
+		 numDrawableFeatures = -1;
+	}
+
+	public void drawData(Graphics g) 
+	{
+		int w = this.getWidth();
+		int h = this.getHeight();
+		double yScaler = h/featureRange;
+		
+		double xScaler = w/timeRange;
+		//System.out.println("w: " + w + " h: " + h);
+		//System.out.println("xScaler: " + xScaler + " yScaler: " + yScaler);
+		//System.out.println("numChunks: " + numChunks);
+
+		g.setColor(bgColor);
+		g.fillRect(0, 0, w, h);
+		
+		double yIncr = (double)h/featureSize;
+		//System.out.println("yIncr: " + yIncr);
+		
+		for (int i = 0; i < numChunks; i++)
+		{
+			FeatChunk fC = (FeatChunk)events.elementAt(i);
+			int x = (int)((fC.startTime - firstEventTime) * xScaler);
+			int width = (int)(fC.length * xScaler) + 1;
+			//adjust to zero
+			double dataPoints[] = featureData[i];
+			
+			if (featureSize > 1)
+			{
+				for (int j = 1; j < featureSize + 1; j++)
+				{
+					double dataPoint = dataPoints[j - 1] - lowestValue;
+					double colorIndex = (dataPoint/featureRange) * 255.0;
+					double y = j * yIncr;
+					//System.out.println("i: " + i + " j: " + j + " x: " + x + " y: " + y + " h: " + h + " yIncr: " + yIncr);
+					g.setColor(colormap.table[(int)colorIndex]);
+					g.fillRect(x, h - (int)(y), width, (int)yIncr + 1);
+				}
+			}
+			else
+			{
+				double dataPoint = dataPoints[0] - lowestValue;
+				double colorIndex = (dataPoint/featureRange) * 255.0;
+				g.setColor(colormap.table[(int)colorIndex]);
+				g.fillRect(x, 0, width, h);
+			}
+
+		}
+		
+		g.drawString(featureName, 20, 20);
+	}
+	
+	public static void main(String[] args)
+	{	
+		
+		if (args.length < 2)
+		{
+			System.out.println("usage: SingleFeatureBarGraphPanel myfilename myfeaturename\n");
+			System.exit(-1);
+		}
+
+		final String fileName = args[0];
+		final String featureName = args[1];
+		final FeatFile fF = new FeatFile(fileName);
+		//Schedule a job for the event-dispatching thread:
+		//creating and showing this application's GUI.
+		javax.swing.SwingUtilities.invokeLater(new Runnable() 
+		{
+			public void run() 
+			{
+				JFrame frame = new JFrame("SingleFeatureBarGraphPanel");
+				
+				try
+				{
+					fF.readFile();
+				}
+				catch(Exception e)
+				{
+					e.printStackTrace();
+					System.exit(-1);
+				}
+				SingleFeaturePanel sFP = new SingleFeatureColorBarsPanel(fF, featureName);
+				if (sFP.initialize() == -1)
+				{
+					System.out.println("hmm, something wrong, bailing.");
+					System.exit(-1);
+				}
+				sFP.setSize(600, 400);
+				sFP.setBackgroundColor(Color.YELLOW);
+				sFP.setDefaultForegroundColor(Color.GREEN);
+				
+				frame.setContentPane(sFP);
+				frame.pack();
+				frame.setVisible(true);
+				frame.setBounds(100, 100, 600, 400);
+
+				sFP.repaint();
+			}
+		});
+	}
+}
addfile ./src/com/meapsoft/visualizer/SingleFeatureLineGraphPanel.java
hunk ./src/com/meapsoft/visualizer/SingleFeatureLineGraphPanel.java 1
+package com.meapsoft.visualizer;
+
+import java.awt.Color;
+import java.awt.Graphics;
+
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+
+import com.meapsoft.FeatChunk;
+import com.meapsoft.FeatFile;
+
+public class SingleFeatureLineGraphPanel extends SingleFeaturePanel
+{
+
+	public SingleFeatureLineGraphPanel(FeatFile featFile, String featureName) 
+	{
+		super(featFile, featureName);
+	
+		 numDrawableFeatures = 1;
+	}
+
+	public void drawData(Graphics g) 
+	{
+		int w = this.getWidth();
+		int h = this.getHeight();
+		
+		if (featureSize > 1)
+		{
+			errorDrawer(g, "I can't draw that feature! Too many dimensions!");
+		}
+		else
+		{			
+			double yScaler = h/featureRange;			
+			double xScaler = w/timeRange;
+			
+			//System.out.println("w: " + w + " h: " + h);
+			//System.out.println("xScaler: " + xScaler + " yScaler: " + yScaler);
+			//System.out.println("numChunks: " + numChunks);
+
+			g.setColor(bgColor);
+			g.fillRect(0, 0, w, h);
+			
+			g.setColor(defaultFGColor);
+			
+			int xPrev = 0;
+			int yPrev = (int)(featureRange/2.0);
+			
+			for (int i = 0; i < numChunks; i++)
+			{
+				FeatChunk fC = (FeatChunk)events.elementAt(i);
+				int x = (int)((fC.startTime - firstEventTime) * xScaler);
+				//adjust to zero
+				double dataPoint = featureData[i][0] - lowestValue;
+				int y = (int)(dataPoint * yScaler);
+				//System.out.println("x: " + x + " y: " + y);
+				//don't draw the first one to avoid false line
+				if (i > 0)
+					g.drawLine(xPrev, yPrev, x, y);
+				xPrev = x; 
+				yPrev = y;
+			}
+			
+			g.drawString(featureName, 20, 20);
+		}
+	}
+	
+	public static void main(String[] args)
+	{	
+		
+		if (args.length < 2)
+		{
+			System.out.println("usage: SingleFeaturePanel myfilename myfeaturename\n");
+			System.exit(-1);
+		}
+
+		final String fileName = args[0];
+		final String featureName = args[1];
+		final FeatFile fF = new FeatFile(fileName);
+		//Schedule a job for the event-dispatching thread:
+		//creating and showing this application's GUI.
+		javax.swing.SwingUtilities.invokeLater(new Runnable() 
+		{
+			public void run() 
+			{
+				JFrame frame = new JFrame("SingleFeaturePanel");
+				
+				try
+				{
+					fF.readFile();
+				}
+				catch(Exception e)
+				{
+					e.printStackTrace();
+					System.exit(-1);
+				}
+				SingleFeaturePanel sFP = new SingleFeatureLineGraphPanel(fF, featureName);
+				if (sFP.initialize() == -1)
+				{
+					System.out.println("hmm, something wrong, bailing.");
+					System.exit(-1);
+				}
+				sFP.setSize(600, 400);
+				sFP.setBackgroundColor(Color.YELLOW);
+				sFP.setDefaultForegroundColor(Color.GREEN);
+				
+				frame.setContentPane(sFP);
+				frame.pack();
+				frame.setVisible(true);
+				frame.setBounds(100, 100, 600, 400);
+
+				sFP.repaint();
+			}
+		});
+	}
+}
addfile ./src/com/meapsoft/visualizer/SingleFeaturePanel.java
hunk ./src/com/meapsoft/visualizer/SingleFeaturePanel.java 1
-
+/*
+ *  Copyright 2006-2007 Columbia University.
+ *
+ *  This file is part of MEAPsoft.
+ *
+ *  MEAPsoft is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  MEAPsoft 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
+ *  General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with MEAPsoft; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ *  02110-1301 USA
+ *
+ *  See the file "COPYING" for the text of the license.
+ */
+
+
+package com.meapsoft.visualizer;
+
+import java.awt.Color;
+import java.awt.Graphics;
+import java.util.Vector;
+
+import com.meapsoft.EDLFile;
+import com.meapsoft.FeatChunk;
+import com.meapsoft.FeatFile;
+import com.meapsoft.gui.ColorMap;
+import com.meapsoft.gui.MEAPsoftGUI;
+
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+
+/**
+ * displays the a single feature
+ * meant to be stacked in various ways to create multi-file visualizations  
+ *
+ * @author Douglas Repetto (douglas@music.columbia.edu)
+ * and the MEAP team
+ */
+
+public abstract class SingleFeaturePanel extends JPanel
+{
+	FeatFile featFile;
+	String featureName;
+	//featureNumbers -1 -2 etc are special cases for Length, StartTime, etc.
+	//featureNumber -1000 is an error condition
+	int featureNumber = -1000;
+	//how many data points are in one chunk of this feature
+	int featureSize = -1;
+	
+	//can we draw multi-dimensional features?
+	//set max features, or -1 for don't care
+	int numDrawableFeatures = 1;
+	
+	//FeatFile featInputFile;
+	
+	Vector events = new Vector();
+	
+	double featureData[][];
+	int numChunks;
+	double highestValue = 0.0d;
+	double lowestValue = 0.0d;
+	double featureRange = 0.0;
+	double firstEventTime = 0.0;
+	double lastEventTime = 0.0;
+	double endTime = 0.0;
+	double timeRange = 0.0;
+	
+	int numColors = 256;
+	ColorMap colormap = ColorMap.getJet(numColors);
+	Color bgColor = Color.WHITE;
+	Color defaultFGColor = Color.BLACK;
+	
+	
+	public SingleFeaturePanel(FeatFile featFile, String featureName) 
+	{
+		setSize(600, 400);
+		
+		this.featFile = featFile;
+		this.featureName = featureName;
+		
+		//System.out.println("running with: " + featFile.filename + " " + featureName);
+	}
+	
+	int initialize()
+	{		
+		highestValue = 0.0d;
+		lowestValue = 0.0d;
+		featureRange = 0.0;
+		firstEventTime = 0.0;
+		lastEventTime = 0.0;
+		endTime = 0.0;
+		timeRange = 0.0;
+		
+		//check to see if our feature is in the input file
+		featureNumber = verifyFeature(featureName);
+		if (featureNumber == -1000)
+		{
+			System.out.println("hmm, I don't find that feature! Bye.");
+			return -1;
+		}
+		//System.out.println("using feature number: " + featureNumber);
+		
+		int elementsPerFeature[] = featFile.getFeatureLengths();
+		if (featureNumber >= 0)
+			featureSize = elementsPerFeature[featureNumber];
+		else
+			featureSize = 1;
+		
+		//System.out.println("featureSize: " + featureSize);
+		
+		//bail if we can't draw the feature
+		if (featureSize > numDrawableFeatures && numDrawableFeatures != -1)
+		{
+			System.out.println("I can't draw that feature, too many dimensions!");
+			return -1;
+		}
+		
+		events = featFile.chunks;
+	
+		//extract feature data, find highest/lowest feature values
+		numChunks = events.size();		
+		featureData = new double[numChunks][featureSize];
+		
+		if (featureNumber >= 0)
+		{
+			for (int i = 0; i < numChunks; i++)
+			{			
+				for (int j = 0; j < featureSize; j++)
+				{
+					FeatChunk fC = (FeatChunk)events.elementAt(i);
+					int[] dim = {featureNumber + j};
+					double feature = fC.getFeatures(dim)[0];
+					featureData[i][j] = feature;
+					
+					if (feature < lowestValue)
+						lowestValue = feature;
+				
+					if (feature > highestValue)
+						highestValue = feature;
+					
+					if (fC.startTime < firstEventTime)
+						firstEventTime = fC.startTime;
+					
+					if (fC.startTime > lastEventTime)
+						lastEventTime = fC.startTime;
+					
+					if (fC.startTime + fC.length > endTime)
+						endTime = fC.startTime + fC.length;
+				}
+			}
+		}
+		//do Length & StartTime features
+		else
+		{
+			for (int i = 0; i < numChunks; i++)
+			{			
+				FeatChunk fC = (FeatChunk)events.elementAt(i);
+				double feature = 0.0;
+				
+				//Length
+				if (featureNumber == -1)
+					feature = fC.length;
+				else if (featureNumber == -2)
+					feature = fC.startTime;
+				
+				featureData[i][0] = feature;
+				
+				if (feature < lowestValue)
+					lowestValue = feature;
+			
+				if (feature > highestValue)
+					highestValue = feature;
+				
+				if (fC.startTime < firstEventTime)
+					firstEventTime = fC.startTime;
+				
+				if (fC.startTime > lastEventTime)
+					lastEventTime = fC.startTime;
+				
+				if (fC.startTime + fC.length > endTime)
+					endTime = fC.startTime + fC.length;
+			}
+		}
+		//System.out.println("feature parsed -- highestValue: " + highestValue +
+		//		" lowestValue: " + lowestValue);
+		
+		featureRange = highestValue - lowestValue;
+		timeRange = endTime - firstEventTime;
+		
+		return 1;
+	}
+	
+	int setFeatureName(String fN)
+	{
+		String oldFeatureName = featureName;
+		int oldFeatureNumber = featureNumber;
+		
+		featureName = fN;
+		
+		int error = initialize();
+		
+		if (error == -1)
+		{
+			featureName = oldFeatureName;
+			featureNumber = oldFeatureNumber;
+			return error;
+		}
+		else
+			return 0;
+	}
+	
+	int verifyFeature(String fN)
+	{
+		int numFeats = featFile.featureDescriptions.size();
+		Vector featDescs = featFile.featureDescriptions;
+		
+		for (int i = 0; i < numFeats; i++)
+		{
+			String featDesc = (String)featDescs.elementAt(i);
+			System.out.println("checking: " + featDesc);
+			if (featDesc.contains(featureName))
+			{
+				//System.out.println("matched on: " + featureName + "!");
+				return i;
+			}
+		}
+		
+		if (fN.equals("Length"))
+		{
+			//System.out.println("matched on: Length!");
+			return -1;
+		}
+		else if (fN.equals("StartTime"))
+		{
+			//System.out.println("matched on: StartTime!");
+			return -2;
+		}
+		//we can't find that feature!
+		return -1000;
+	}
+	
+	protected void paintComponent(Graphics g)
+	{
+		if (featureSize <= numDrawableFeatures || numDrawableFeatures == -1)
+			drawData(g);
+		else
+			errorDrawer(g, "I can't draw that feature, too many dimensions!");
+	}
+	
+	public abstract void drawData(Graphics g);
+	
+	void errorDrawer(Graphics g, String error)
+	{
+		int w = this.getWidth();
+		int h = this.getHeight();
+		
+		g.setColor(bgColor);
+		g.fillRect(0, 0, w, h);
+		
+		g.setColor(defaultFGColor);
+		g.drawString(error, 10, 20);
+	}
+
+	void setBackgroundColor(Color c)
+	{
+		bgColor = c;
+		repaint();
+	}
+	
+	void setDefaultForegroundColor(Color c)
+	{
+		defaultFGColor = c;
+	}
+}
addfile ./src/com/meapsoft/visualizer/SingleFeaturePanelTester.java
hunk ./src/com/meapsoft/visualizer/SingleFeaturePanelTester.java 1
+package com.meapsoft.visualizer;
+
+import java.awt.Color;
+import java.awt.Rectangle;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseListener;
+import java.util.Vector;
+
+import javax.swing.BoxLayout;
+import javax.swing.JButton;
+import javax.swing.JFrame;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+
+import com.meapsoft.FeatFile;
+import com.meapsoft.MEAPUtil;
+import com.meapsoft.gui.GUIUtils;
+
+public class SingleFeaturePanelTester implements MouseListener, ActionListener
+{
+	JFrame frame;
+	JPanel panel;
+	JPanel controlsPanel;
+	
+	String meapsoftDirectory = null;
+	String dataDirectory = null;
+	String slash = null;
+	
+	Vector panels = new Vector();
+	Vector tFFs = new Vector();
+
+	
+	public SingleFeaturePanelTester() 
+	{	
+		String paths[] = MEAPUtil.getPaths();
+		if (paths != null)
+		{
+			meapsoftDirectory = paths[0];
+			dataDirectory = paths[1];
+		}
+		else
+			System.exit(-1);
+		
+		slash = MEAPUtil.slash;
+		
+		//System.out.println("meapsoftDirectory: " + meapsoftDirectory);
+		//System.out.println("dataDirectory: " + dataDirectory);
+
+		buildGUI();
+	}
+	
+	void buildGUI()
+	{
+		frame = new JFrame("SingleFeaturePanelTester");
+		panel = new JPanel();
+		panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
+		frame.setContentPane(panel);
+		
+		buildControlsPanel();
+		panel.add(controlsPanel);
+		
+		addAPanel(selectATFF());
+		
+		frame.pack();
+		frame.setVisible(true);
+		frame.setBounds(100, 100, 600, 400);
+	}
+	
+	void buildControlsPanel()
+	{
+		controlsPanel = new JPanel();
+		controlsPanel.setLayout(new BoxLayout(controlsPanel, BoxLayout.X_AXIS));
+		
+		JButton addPanelButton = new JButton("add panel");
+		addPanelButton.setActionCommand("newPanel");
+		addPanelButton.addActionListener(this);
+		controlsPanel.add(addPanelButton);
+	}
+	
+	void addAPanel(TypeFileFeature tFF)
+	{
+		SingleFeaturePanel sFP = null;
+		
+		if (tFF.panelType.equals("BarGraph"))
+			sFP = new SingleFeatureBarGraphPanel(tFF.featFile, tFF.featureName);
+		else if (tFF.panelType.equals("LineGraph"))
+			sFP = new SingleFeatureLineGraphPanel(tFF.featFile, tFF.featureName);
+		else if (tFF.panelType.equals("ColorBars"))
+			sFP = new SingleFeatureColorBarsPanel(tFF.featFile, tFF.featureName);
+		else
+		{
+			System.out.println("don't know that type of panel!");
+			System.exit(-1);
+		}
+		
+		if (sFP.initialize() == -1)
+		{
+			System.out.println("hmm, something wrong, bailing.");
+			System.exit(-1);
+		}
+		sFP.setSize(600, 400);
+		sFP.setBackgroundColor(Color.YELLOW);
+		sFP.setDefaultForegroundColor(Color.GREEN);
+		sFP.addMouseListener(this);
+		
+		Rectangle bounds = frame.getBounds();
+		frame.setVisible(false);
+		
+		panel.add(sFP);
+		panels.add(sFP);
+		
+		frame.pack();
+		frame.setVisible(true);
+		frame.setBounds(bounds);
+		
+		
+	}
+	
+	String getPanelType()
+	{
+		Object[] possibilities = {"BarGraph", "LineGraph", "ColorBars"};
+		String s = (String)JOptionPane.showInputDialog(
+		                    frame,
+		                    "Select a panel type:",
+		                    "Customized Dialog",
+		                    JOptionPane.PLAIN_MESSAGE,
+		                    null,
+		                    possibilities,
+		                    "BarGraph");
+		return s;
+	}
+	
+	String getFeatureFromFile(FeatFile fF)
+	{
+		Vector features = fF.featureDescriptions;
+		
+		Object[] choices = new Object[features.size()];
+		
+		for (int i = 0; i < features.size(); i++)
+		{
+			String name = (String)features.elementAt(i);
+			//we're splitting on "." but have to use an escape sequence!
+			String[] chunks = name.split("\\.");
+			choices[i] = chunks[chunks.length-1];
+		
+		}
+		//Object[] possibilities = {"BarGraph", "LineGraph", "ColorBars"};
+		String s = (String)JOptionPane.showInputDialog(
+		                    frame,
+		                    "Select a feature:",
+		                    "Customized Dialog",
+		                    JOptionPane.PLAIN_MESSAGE,
+		                    null,
+		                    choices,
+		                    "");
+
+		return s;
+	}
+	
+	
+	public TypeFileFeature selectATFF()
+	{		
+		String panelType = getPanelType();
+		
+		String names[] = GUIUtils.FileSelector(GUIUtils.OPENFEAT, dataDirectory, frame);
+		
+		if (names[0] == null)
+			return null;
+		
+		FeatFile fF = new FeatFile(names[0]);
+		try
+		{
+			fF.readFile();
+		}
+		catch(Exception e)
+		{
+			e.printStackTrace();
+			System.exit(-1);
+		}
+
+		String feature = getFeatureFromFile(fF);
+		TypeFileFeature fAF = new TypeFileFeature(panelType, fF, names[0], feature);
+		return fAF;
+	}
+	
+	public void mouseClicked(MouseEvent e) 
+	{
+		System.out.println("mouse click!");
+		
+		/*
+		String newFN = null;
+		
+		switch (sFP.featureNumber)
+		{
+			case -2:
+				newFN = "Length";
+				break;
+			case -1:
+				newFN = "AvgMelSpec";
+				break;
+			case 0:
+				newFN = "AvgPitchSimple";
+				break;
+			case 1:
+				newFN = "AvgSpecCentroid";
+				break;
+			case 2:
+				newFN = "ChunkPower";
+				break;
+			case 3:
+				newFN = "SpectralStability";
+				break;
+			case 4:
+				newFN = "StartTime";
+				break;
+		}
+		sFP.setFeatureName(newFN);
+		sFP.repaint();
+		*/
+	}
+
+	public void mouseEntered(MouseEvent e) {
+		// TODO Auto-generated method stub
+		
+	}
+
+	public void mouseExited(MouseEvent e) {
+		// TODO Auto-generated method stub
+		
+	}
+
+	public void mousePressed(MouseEvent e) {
+		// TODO Auto-generated method stub
+		
+	}
+
+	public void mouseReleased(MouseEvent e) {
+		// TODO Auto-generated method stub
+		
+	}
+
+	public static void main(String[] args)
+	{		
+		//Schedule a job for the event-dispatching thread:
+		//creating and showing this application's GUI.
+		javax.swing.SwingUtilities.invokeLater(new Runnable() 
+		{
+			public void run() 
+			{
+				new SingleFeaturePanelTester();
+			}
+		});
+	}
+	
+	public class TypeFileFeature
+	{
+		String panelType = null;
+		FeatFile featFile = null;
+		String fileName = null;
+		String featureName = null;
+		
+		public TypeFileFeature(String panelType, FeatFile fF, String fileName, String featureName)
+		{
+			this.panelType = panelType;
+			this.featFile = fF;
+			this.fileName = fileName;
+			this.featureName = featureName;
+		}
+	}
+
+	public void actionPerformed(ActionEvent arg0) 
+	{
+		String command = arg0.getActionCommand();
+		
+		if (command.equals("newPanel"))
+		{
+			addAPanel(selectATFF());
+		}
+		
+	}
+}
+
+
}
