import java.awt.Canvas;
import java.awt.event.*;
import java.awt.geom.*;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.Vector;
import javax.swing.AbstractAction;
import javax.swing.Box;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JMenuBar;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.ProgressMonitor;
import javax.swing.KeyStroke;
import javax.swing.ListSelectionModel;
import javax.swing.UIManager;
//import ChooseStringDialog; // dialog box for choosing from a list
/**
* BeadPlot - a tool for visual comparison of TREC result sets
*
* This class implements a tool for displaying a number of ranked result,
* sets for a given TREC topic. Each result is represented as a string of
* beads (colored rectangles) laid out horizontally with the highest ranked
* document represented by the leftmost bead in the strand.
*
* Each result is represented as a string of beads (colored rectangles)
* laid out horizontally with the highest ranked document represented by
* the leftmost bead in the strand. One of the results is designated as
* the reference result and colors are assigned in spectral sequence (ROYGBIV)
* to its documents' beads if they fall within a specified range (the
* reference range). Other documents in the reference result are represented
* by gray rectangles. If a document from the reference result appears in
* another result, it will be represented the same in there as in the
* reference result. Documents not retrieved in the reference result are not
* represented anywhere.
*
* @version 0.1 alpha
*
* @author
* This software was produced by NIST, an agency of the
* U.S. government, and by statute is not subject to copyright in the
* United States. Recipients of this software assume all
* responsibilities associated with its operation, modification and
* maintenance.
*/
public class BeadPlot extends JFrame {
/** Top frame */
private static JFrame f = null;
private static JPanel plot = null;
private static Component contents = null;
/** Dialog box for topic choice */
private static ChooseStringDialog topicDialog= null;
private static JMenu viewMenu = null;
/** Dialog box for result set files choice */
private static ChooseStringDialog resultFilesDialog= null;
/** Dialog box for choosing the reference run id */
private static ChooseStringDialog runIdDialog= null;
/** Topic for which data is to be displayed */
private static String topicForDisplay = null;
/** Run-id of the current reference result */
private static String refRunId = null;
/** The reference result */
private static DocData[] refResult = null;
/** File containing qrels */
private static String qrelsFileName = null;
/** Directory containing results */
private static String resultsDirName = null;
/** Hashed qrels (key = topic+docid) only rel docs included */
private static HashSet qrelsRelsHash = new HashSet();
/** Hashed topics from qrels */
private static TreeSet qrelsTopics = new TreeSet();
/** Hashed run-ids from results */
private static TreeSet runIdHash = new TreeSet();
private static int oldNumRunIds = 0;
/** DocData objects from the result sets hashed by docid */
private static Hashtable docsHash = new Hashtable();
/*
* resultsByTopic
* --------------
* Hashtable
* topic1 ------> results
* topic2 ---------------
* ... Hashtable
* topicT runid1 ------> resultSet
* runid2 ---------
* ... String[1000] of doc ids
* runidR
*/
/** results hashtables hashed by topic */
private static Hashtable resultsByTopic = new Hashtable();
/** Result set arrays hashed by runid */
private static TreeMap results = new TreeMap();
// Structures directly supporting the plot
/** Run-ids being displayed */
static String[] runIdsForDisplay = null;
/** Run-ids with data for current topic */
static int runsWithData = 0;
/** Result sets being displayed - corresponding to runIdsForDisplay */
static DocData[][]resultSetsForDisplay = null;
/** DocData for document to be highlighted */
static DocData highlightDocData = null;
/** Status of relevance filter for use in title */
static String filterStatus = "All";
/** Are we filtering by relevance? */
static boolean filteringByRelevance = false;
/** Relevance value required if filtering documents by relevance*/
static boolean requiredRelevance = false;
static final int numColors = 4;
static Color colors1[] = new Color[numColors*numColors];
static Color colors2[] = new Color[numColors*numColors];
/** */
private static String topics[] = null;
/** */
private static String runIds[] = null;
/** */
private static String resultFileNames[] = null;
private static int progressVal = 0;
private Integer selectedDisplayRangeStartValue = new Integer(0);
private Integer selectedRefRangeStartValue = new Integer(1);
private Integer selectedRefRangeSizeValue = new Integer(50);
final static int MAX_RESULT_SIZE = 2000;
static int MIN_DISPLAY_INDEX = 0;
static int MIN_REF_RANK = 1;
static int MAX_REF_RANK = 50;
final static int MAX_DISPLAY_RANK = 100;
final static int NUM_DISPLAYED_RANKS = 100;
final static int PREFERRED_PLOT_WIDTH = 800;
final static int VGAP = 2;
final static int BEAD_HEIGHTH = 8;
final static int HGAP = 3;
final static int BEAD_WIDTH = 5;
final static int RUN_ID_WIDTH = 25;
private Cursor waitCursor = Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR);
private Cursor defaultCursor = Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR);
/**
* Static initializer
*/
static {
makeSecondaryColors();
}
/**
* DocData
*
* This inner class represents a document from a result set
*/
public class DocData {
/** The document id */
String docId;
int rank = 0;
/** The red component of display color assigned to document */
float r1 = (float)0.75; // lightGray
/** The green component of display color assigned to document */
float g1 = (float)0.75;
/** The blue component of display color assigned to document */
float b1 = (float)0.75;
/** The second color assigned to document */
Color color2 = Color.lightGray;
/** The third color assigned to document */
Color color3 = Color.lightGray;
public DocData (String id, int rank) {
docId = id;
this.rank = rank;
}
public void setColor1(float red, float green, float blue) {
r1 = red;
g1 = green;
b1 = blue;
}
public void setColor2(Color c) {
color2 = c;
}
public void setColor3(Color c) {
color3 = c;
}
public void setRank(int rank){
this.rank = rank;
}
public Color getColor1(){
return new Color(r1,g1,b1);
}
public Color getColor2(){
return color2;
}
public Color getColor3(){
return color3;
}
public String getDocId(){
return docId;
}
public int getRank(){
return rank;
}
}
/**
* ResultSet
*
* This inner class represents a named result set
*/
public class ResultSet {
/** The result set name (e.g., the run id) */
String name;
/** The documents in this result; index 0 -> most highly ranked */
DocData result[];
public ResultSet(String name, int size) {
this.name = name;
result = new DocData[size];
}
}
/**
* Reads result sets in a separate thread since it may take a while
*/
public class ResultSetReader extends Thread {
String[] resultFileNames = null;
ProgressMonitor progressMon = null;
ResultSetReader(String[] results) {
resultFileNames = results;
}
public void run() {
int numFiles = resultFileNames.length;
progressMon =
new ProgressMonitor(f,
"Loading "+numFiles+" result files",
resultFileNames[0],
1,
numFiles);
progressMon.setMillisToDecideToPopup(0);
progressMon.setMillisToPopup(0);
progressMon.setProgress(0);
for (int i=0; i "
+ resultFileName + "-" +e);
return;
}
String line = "";
StringTokenizer tokenizer = null;
String topic = "";
String junk = "";
String docid = "";
String runid = "";
boolean gotRunId = false;
try { line = reader.readLine();}
catch (FileNotFoundException e) {
System.out.println("Beadplot.readResults: Unable to read results file -> "
+ resultFileName + "-" +e);
return;
}
catch (IOException e) {
System.out.println("Beadplot.readResults: Unable to read results file -> "
+ resultFileName+ "-" +e);
return;
}
while (line != null) // for each line in the result file
{
tokenizer = new StringTokenizer(line);
while (tokenizer.hasMoreTokens()) // for each token in the line
{
topic = Integer.toString(Integer.parseInt(tokenizer.nextToken()),10);
int len = topic.length();
if (len == 3)
{
topic = "0"+topic;
}
else if (len == 2)
{
topic = "00"+topic;
}
else if (len == 1)
{
topic = "000"+topic;
}
junk = tokenizer.nextToken();
docid = tokenizer.nextToken();
junk = tokenizer.nextToken();
junk = tokenizer.nextToken();
runid = tokenizer.nextToken();
//System.out.println(topic + " " + docid + " " + runid);
if (!gotRunId)
{
runIdHash.add(runid);
gotRunId = true;
}
docData = (DocData) docsHash.get(docid);
if (docData == null)
{
docData = new DocData(docid,9999);
docsHash.put(docid,docData);
}
/*-------------------------------------------------------------*
* When the topic changes:
*-------------------------------------------------------------*/
if (curTopic.compareTo(topic) != 0)
{
// Set the results vector - get the existing one for this
// topic or create a new one
results = (TreeMap) resultsByTopic.get(topic);
if (results == null)
{
results = new TreeMap();
resultsByTopic.put(topic,results);
System.out.println("Adding result for topic "+topic);
}
resultSet = new DocData[MAX_RESULT_SIZE]; // create new result set
docDataIndex = 0;
results.put(runid,resultSet); // add result to cur. results table
curTopic = topic;
}
resultSet[docDataIndex++] = docData;
}
try { line = reader.readLine();}
catch (FileNotFoundException e)
{
System.out.println("Beadplot.readResults: Unable to "+
"read results file -> " +
resultFileName + "-" +e);
return;
}
catch (IOException e)
{
System.out.println("Beadplot.readResults: Unable to "+
"read results file -> " +
resultFileName+ "-" +e);
return;
}
} // end while (line != null)
}
}
/**
* Plot
*
* This inner class models the beadplot itself.
*/
private class Plot extends JPanel {
/**------------------------------------------------------------------
* Paints the beadplot
* @param graphics a graphics context to work with
*/
public void paint(Graphics graphics) {
super.paint(graphics);
System.out.println("Painting");
Graphics2D g2 = (Graphics2D)graphics;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING,
RenderingHints.VALUE_COLOR_RENDER_QUALITY);
g2.setRenderingHint(RenderingHints.KEY_DITHERING,
RenderingHints.VALUE_DITHER_ENABLE);
g2.setRenderingHint(RenderingHints.KEY_RENDERING,
RenderingHints.VALUE_RENDER_QUALITY);
if (resultSetsForDisplay != null)
{
int maxDisplayedRank = MIN_DISPLAY_INDEX+1 + NUM_DISPLAYED_RANKS-1;
if (maxDisplayedRank >= MAX_RESULT_SIZE)
maxDisplayedRank = MAX_RESULT_SIZE;
if (highlightDocData == null)
f.setTitle("BeadPlot: " +filterStatus +" reference documents "+
" Ranks " + (MIN_DISPLAY_INDEX+1) + "->" +
maxDisplayedRank +
" Topic " + topicForDisplay);
else
f.setTitle("BeadPlot: " +filterStatus +" reference documents "+
" Ranks " + (MIN_DISPLAY_INDEX+1) + "->" +
maxDisplayedRank +
" Topic "+topicForDisplay+
" Highlighting document "+highlightDocData.getDocId());
int numResults = resultSetsForDisplay.length;
for (int row=0; row < numResults; row++)
{
if (runIdsForDisplay[row] == null)
continue;
// ----------- Set run-id color and draw it
if (runIdsForDisplay[row].compareTo(refRunId) == 0)
g2.setColor(Color.blue); // highlight ref run-id
else
g2.setColor(Color.black);
g2.drawString(runIdsForDisplay[row],
1,
((int)(row*2*BEAD_HEIGHTH*VGAP+BEAD_HEIGHTH+5)));
Color c = null;
DocData doc = null;
// ----------- Draw beads
if (highlightDocData == null)
{
for (int rank=0; rank < NUM_DISPLAYED_RANKS; rank++)
{
doc = resultSetsForDisplay[row][rank+MIN_DISPLAY_INDEX];
if (doc == null)
continue;
if ( filteringByRelevance &&
(requiredRelevance !=
qrelsRelsHash.contains(topicForDisplay+doc.getDocId())) )
continue;
g2.setColor(doc.getColor1());
g2.fillRect( ((int)((RUN_ID_WIDTH+rank-1)*(BEAD_WIDTH+HGAP))),
((int)(row*2*BEAD_HEIGHTH*VGAP+BEAD_HEIGHTH)),
(int)BEAD_WIDTH,
(int)BEAD_HEIGHTH);
g2.setColor(doc.getColor2());
g2.fillRect( ((int)((RUN_ID_WIDTH+rank-1)*(BEAD_WIDTH+HGAP))),
((int)(row*2*BEAD_HEIGHTH*VGAP+2.33*BEAD_HEIGHTH)),
(int)BEAD_WIDTH,
(int)BEAD_HEIGHTH/3);
g2.setColor(doc.getColor3());
g2.fillRect( ((int)((RUN_ID_WIDTH+rank-1)*(BEAD_WIDTH+HGAP))),
((int)(row*2*BEAD_HEIGHTH*VGAP+2.66*BEAD_HEIGHTH)),
(int)BEAD_WIDTH,
(int)BEAD_HEIGHTH/3);
}
}
else
{
for (int rank=0; rank < NUM_DISPLAYED_RANKS; rank++)
{
doc = resultSetsForDisplay[row][rank+MIN_DISPLAY_INDEX];
if (doc == null)
continue;
if ( filteringByRelevance &&
(requiredRelevance !=
qrelsRelsHash.contains(topicForDisplay+doc.getDocId())))
continue;
if (highlightDocData==doc)
{
//g2.setColor(doc.getColor1());
g2.setColor(Color.white);
g2.fillRect((int)((RUN_ID_WIDTH+rank-1)*(BEAD_WIDTH+HGAP)),
(int)(row*2*BEAD_HEIGHTH*VGAP),
(int)BEAD_WIDTH,
(int)BEAD_HEIGHTH*3);
}
else
{
g2.setColor(doc.getColor1());
g2.fillRect( ((int)((RUN_ID_WIDTH+rank-1)*(BEAD_WIDTH+HGAP))),
((int)(row*2*BEAD_HEIGHTH*VGAP+BEAD_HEIGHTH)),
(int)BEAD_WIDTH,
(int)BEAD_HEIGHTH);
g2.setColor(doc.getColor2());
g2.fillRect( ((int)((RUN_ID_WIDTH+rank-1)*(BEAD_WIDTH+HGAP))),
((int)(row*2*BEAD_HEIGHTH*VGAP+2.33*BEAD_HEIGHTH)),
(int)BEAD_WIDTH,
(int)BEAD_HEIGHTH/3);
g2.setColor(doc.getColor3());
g2.fillRect( ((int)((RUN_ID_WIDTH+rank-1)*(BEAD_WIDTH+HGAP))),
((int)(row*2*BEAD_HEIGHTH*VGAP+2.66*BEAD_HEIGHTH)),
(int)BEAD_WIDTH,
(int)BEAD_HEIGHTH/3);
}
}
}
}
} // end if (resultSetsForDisplay != null)
else
{
f.setTitle("BeadPlot");
}
} // end paint
} //end Plot
public static void makeSecondaryColors() {
Color[] colors = new Color[numColors];
int colorIndex = 0;
colors[0] = Color.red;
colors[1] = Color.yellow;
colors[2] = Color.blue;
colors[3] = Color.green;
//colors[4] = Color.black;
//colors[5] = Color.white;
colors1 = new Color[numColors*numColors];
colors2 = new Color[numColors*numColors];
int c = 0;
int i = 0;
int j = 0;
int x = 0;
int y = 0;
for (i=0; i=0 && x=0 && y=0 && x=0 && y=0 && x=0 && y=0 && x=0 && y= 0; i--)
{
if (refResult[i]!=null)
{
refResult[i].setColor1(notInRefRGB,notInRefRGB,notInRefRGB);
refResult[i].setColor2(Color.lightGray);
refResult[i].setColor3(Color.lightGray);
}
}
// Use the topicForDisplay and the refRunId to get the new
// reference result and assign it to refResult
TreeMap results = (TreeMap)resultsByTopic.get(topicForDisplay);
if (results == null)
{
System.out.println("No results for topic "+topicForDisplay);
}
else
{
refResult = (DocData[])results.get(refRunId);
if (refResult == null)
{
System.out.println("No results for "+refRunId+" and topic "+topicForDisplay);
}
else
{
// Step though the reference result setting each document's
// color based on its rank
float docnum;
float r,g,b;
int maxRefIndex = MAX_REF_RANK-1;
int minRefIndex = MIN_REF_RANK-1;
float mrr1 = ((float)(maxRefIndex-minRefIndex))/(float)7;
float mrr2 = 2*mrr1;
float mrr3 = 3*mrr1;
float mrr4 = 4*mrr1;
float mrr5 = 5*mrr1;
float mrr6 = 6*mrr1;
int numResults = refResult.length;
for (i=0; i maxRefIndex || i < minRefIndex)
{
refResult[i].setColor1(refButNotColoredRGB,
refButNotColoredRGB,
refButNotColoredRGB);
refResult[i].setColor2(Color.lightGray);
refResult[i].setColor3(Color.lightGray);
//refResult[i].setColor2(refButNotColoredColor);
//refResult[i].setColor3(refButNotColoredColor);
refResult[i].setRank(9999);
}
else
{
if (docnum <= mrr1)
{ r=docnum/mrr1; g=0; b=0;}
else if (docnum <= mrr2)
{ r=1; g=(docnum-mrr1)/mrr1; b=0;}
else if (docnum <= mrr3)
{ r=1-((docnum-mrr2)/mrr1); g=1; b=0;}
else if (docnum <= mrr4)
{ r=0; g=1; b=(docnum-mrr3)/mrr1;}
else if (docnum <= mrr5)
{ r=0; g=1-((docnum-mrr4)/mrr1); b=1;}
else if (docnum <= mrr6)
{ r=(docnum-mrr5)/mrr1; g=0; b=1;}
else
{ r=1; g=(docnum-mrr6)/mrr1; b=1;
if (g > 1) g = (float)1.0;} // sometimes g ends up a tiny
// fraction over 1.0; not sure why
refResult[i].setColor1(r,g,b);
refResult[i].setColor2(colors1[colorCount]);
refResult[i].setColor3(colors2[colorCount]);
colorCount = (colorCount+1)%(numColors*numColors);
}
refResult[i].setRank(i);
}
}
}
}
System.out.println("Reconstructing display structures");
// Reconstruct display structures
int numRunIds = runIds.length;
if (resultSetsForDisplay == null || numRunIds != oldNumRunIds)
{
// Structures don't exist or number of result sets changed
oldNumRunIds = numRunIds;
runIdsForDisplay = new String[numRunIds];
resultSetsForDisplay = new DocData[numRunIds][MAX_RESULT_SIZE];
TreeMap resultsForCurTopic =
(TreeMap)resultsByTopic.get(topicForDisplay);
if (resultsForCurTopic == null)
{
System.out.println("1 No result");
return (-1);
}
Set runIdSet = resultsForCurTopic.keySet();
Iterator iterator = runIdSet.iterator();
if (iterator == null)
{
System.out.println("1 No run id iterator");
return (-1);
}
String runId = null;
runsWithData = 0;
for (i = 0; i < numRunIds; i++)
{
try {
runId = (String)iterator.next();
runsWithData++;
runIdsForDisplay[i] = runId;
resultSetsForDisplay[i] = (DocData[])resultsForCurTopic.get(runId);
}
catch (java.util.NoSuchElementException e) {
}
}
}
else // preserve existing order of unchanged number of run-ids
{
System.out.println("preserve existing order of unchanged number of run-ids for topic "+topicForDisplay+"\n");
TreeMap resultsForCurTopic =
(TreeMap)resultsByTopic.get(topicForDisplay);
if (resultsForCurTopic == null)
{
System.out.println("2 No result");
return (-1);
}
Set runIdSet = resultsForCurTopic.keySet();
Iterator iterator = runIdSet.iterator();
if (iterator == null)
{
System.out.println("2 No run id iterator");
return (-1);
}
String runId = null;
for (i = 0; i < numRunIds; i++)
{
try {
runId = (String)iterator.next();
for (int j=0; j=0; i--)
resultFileNames[i] = path+resultFileNames[i];
if (resultFilesDialog == null)
{
resultFilesDialog.initialize(f,resultFileNames,
"Choose result sets",
"Result set files to choose from:",
ListSelectionModel.SINGLE_INTERVAL_SELECTION);
}
resultFileNames = (String[])resultFilesDialog.showDialog(f,null);
if (resultFileNames.length > 0)
{
ResultSetReader resultReader =
new ResultSetReader(resultFileNames);
resultReader.start();
}
}
}
}
}
/**--------------------------------------------------------------------
* Chooses qrels
*/
public class ChooseQrels extends AbstractAction {
public ChooseQrels(String description) {
super(description);
}
/**
* Chooses qrels and read them in
* @param event event which triggered this action
*/
public void actionPerformed(ActionEvent event) {
contents.setCursor(waitCursor);
String selectedValue = (String)JOptionPane.showInputDialog(
f,
"Enter the name of the qrels file to use",
"Enter name of qrels",
JOptionPane.QUESTION_MESSAGE);
if (selectedValue != null)
{
qrelsFileName = selectedValue;
readQrels(qrelsFileName);
topicForDisplay = topics[0]; // default to first
if (refRunId != null)
{
System.out.println("Enabling View");
viewMenu.setEnabled(true);
}
if (recalculateDisplay() == 0)
f.paintAll(f.getGraphics());
}
contents.setCursor(defaultCursor);
}
/**
* Read a qrels file in and stores the contents
* @param fileName qrels file name string
*/
public void readQrels(String qrelsFileName) {
BufferedReader reader = null;
try { reader = new BufferedReader(new FileReader(qrelsFileName));}
catch (FileNotFoundException e) {
System.out.println("Beadplot.readQrels: Unable to find qrels file -> "
+ qrelsFileName + "-" +e);
return;
}
String line = null;
StringTokenizer tokenizer = null;
String topic = null;
String junk = null;
String docid = null;
String judgement = null;
try { line = reader.readLine();}
catch (FileNotFoundException e) {
System.out.println("Beadplot.readQrels: Unable to read qrels file -> "
+ qrelsFileName + "-" +e);
return;
}
catch (IOException e) {
System.out.println("Beadplot.readQrels: Unable to read qrels file -> "
+ qrelsFileName+ "-" +e);
return;
}
while (line != null)
{
tokenizer = new StringTokenizer(line);
while (tokenizer.hasMoreTokens())
{
topic = tokenizer.nextToken();
junk = tokenizer.nextToken();
docid = tokenizer.nextToken();
judgement = tokenizer.nextToken();
qrelsTopics.add(topic);
if (judgement.compareTo("1") == 0)
qrelsRelsHash.add(topic+docid);
}
try { line = reader.readLine();}
catch (FileNotFoundException e)
{
System.out.println("Beadplot.readQrels: Unable to "+
"read qrels file -> " +
qrelsFileName + "-" +e);
return;
}
catch (IOException e)
{
System.out.println("Beadplot.readQrels: Unable to "+
"read qrels file -> " +
qrelsFileName+ "-" +e);
return;
}
} // end while (line != null)
Iterator iterator = qrelsTopics.iterator();
int numTopics = qrelsTopics.size();
topics = new String[numTopics];
int len = 0;
for (int i = 0; i < numTopics; i++)
{
topics[i] = (String)iterator.next();
len = topics[i].length();
if (len == 3)
{
topics[i] = "0"+topics[i];
}
else if (len == 2)
{
topics[i] = "00"+topics[i];
}
else if (len == 1)
{
topics[i] = "000"+topics[i];
}
}
}
}
/**--------------------------------------------------------------------
* Filters by relevance
*/
public class FilterByRelevance extends AbstractAction {
public FilterByRelevance(String description) {
super(description);
}
/**
* Filters by relevance
* @param event event which triggered this action
*/
public void actionPerformed(ActionEvent event) {
System.out.println("Filtering by relevance");
String[] possibleValues = { "All",
"Relevant",
"Non-relevant" };
int numPossibleValues = possibleValues.length;
String initialValue = null;
if (filteringByRelevance)
{
if (requiredRelevance == true)
initialValue = possibleValues[1];
else
initialValue = possibleValues[2];
}
else
initialValue = possibleValues[0];
String selectedValue = (String)JOptionPane.showInputDialog(f,
"Choose one", "Filter by documents by relevance?",
JOptionPane.QUESTION_MESSAGE, null,
possibleValues, initialValue);
if (selectedValue != null)
{
filterStatus = selectedValue;
if (selectedValue.compareTo(possibleValues[0]) == 0)
filteringByRelevance = false;
else if (selectedValue.compareTo(possibleValues[1]) == 0)
{
filteringByRelevance = true;
requiredRelevance = true;
}
else if (selectedValue.compareTo(possibleValues[2]) == 0)
{
filteringByRelevance = true;
requiredRelevance = false;
}
if (recalculateDisplay() == 0)
{
f.paintAll(f.getGraphics());
}
}
}
}
/**--------------------------------------------------------------------
* Set display range start
*/
public class SetDisplayRangeStart extends AbstractAction {
public SetDisplayRangeStart(String description) {
super(description);
}
/**
* Sets the display range start (lower bound)
* @param event event which triggered this action
*/
public void actionPerformed(ActionEvent event) {
int limit = (MAX_RESULT_SIZE-NUM_DISPLAYED_RANKS)/10;
Integer [] possibleValues = new Integer[limit+1];
for (int i=0; i<=limit; i++)
possibleValues[i]=new Integer(i*10+1);
Integer newSelectedDisplayRangeStartValue
= (Integer)JOptionPane.showInputDialog(f,
"Set the rank of the\nhighest ranked document\n"+
"to be displayed.\nSize is fixed at 100 documents",
"Set display range start",
JOptionPane.QUESTION_MESSAGE, null,
possibleValues, selectedDisplayRangeStartValue);
if (newSelectedDisplayRangeStartValue != null)
{
MIN_DISPLAY_INDEX = newSelectedDisplayRangeStartValue.intValue()-1;
selectedDisplayRangeStartValue = newSelectedDisplayRangeStartValue;
f.paintAll(f.getGraphics());
}
}
}
/**--------------------------------------------------------------------
* Set reference range start
*/
public class SetRefRangeStart extends AbstractAction {
public SetRefRangeStart(String description) {
super(description);
}
/**
* Sets the reference range start (lower bound)
* @param event event which triggered this action
*/
public void actionPerformed(ActionEvent event) {
int limit = (MAX_RESULT_SIZE - selectedRefRangeSizeValue.intValue())/10;
Integer [] possibleValues = new Integer[limit+1];
for (int i=0; i<=limit; i++)
possibleValues[i]=new Integer(i*10+1);
Integer newSelectedRefRangeStartValue
= (Integer)JOptionPane.showInputDialog(f,
"Set the rank of the\nhighest ranked document\n"+
"in the reference range\n(Range size is "+
selectedRefRangeSizeValue.intValue()+" )",
"Set reference range start",
JOptionPane.QUESTION_MESSAGE, null,
possibleValues, selectedRefRangeStartValue);
if (newSelectedRefRangeStartValue != null)
{
selectedRefRangeStartValue = newSelectedRefRangeStartValue;
MIN_REF_RANK = selectedRefRangeStartValue.intValue();
MAX_REF_RANK = MIN_REF_RANK + selectedRefRangeSizeValue.intValue()-1;
if (recalculateDisplay() == 0)
f.paintAll(f.getGraphics());
}
}
}
/**--------------------------------------------------------------------
* Set reference range size
*/
public class SetRefRangeSize extends AbstractAction {
public SetRefRangeSize(String description) {
super(description);
}
/**
* Sets the reference range size
* @param event event which triggered this action
*/
public void actionPerformed(ActionEvent event) {
int choices = (MAX_RESULT_SIZE - selectedRefRangeStartValue.intValue() +1)/10;
Integer [] possibleValues = new Integer[choices];
for (int i=1; i<=choices; i++)
possibleValues[i-1]=new Integer(i*10);
Integer newSelectedRefRangeSizeValue
= (Integer)JOptionPane.showInputDialog(f,
"Set the number of documents\nin the reference range\n"+
"(Range starts at rank "+
selectedRefRangeStartValue.intValue()+ " )",
"Set reference range size",
JOptionPane.QUESTION_MESSAGE, null,
possibleValues, selectedRefRangeSizeValue);
if (newSelectedRefRangeSizeValue != null)
{
selectedRefRangeSizeValue = newSelectedRefRangeSizeValue;
MIN_REF_RANK = selectedRefRangeStartValue.intValue();
MAX_REF_RANK = MIN_REF_RANK + selectedRefRangeSizeValue.intValue()-1;
System.out.println("MIN_REF_RANK="+MIN_REF_RANK+" MAX_REF_RANK="+MAX_REF_RANK);
if (recalculateDisplay() == 0)
f.paintAll(f.getGraphics());
}
}
}
/**--------------------------------------------------------------------
* Provides "about" help
*/
public class ProvideAboutHelp extends AbstractAction {
public ProvideAboutHelp(String description) {
super(description);
}
/**
* Provides "about" help
* @param event event which triggered this action
*/
public void actionPerformed(ActionEvent event) {
System.out.println("Providing 'About' help");
JOptionPane.showMessageDialog
(f,
"BeadPlot was developed by the NLP/IR group at the" +
"\nNational Institut of Standards and Technology, a US" +
"\ngovernment agency, and so is not subject to copyright"+
"\nwithin the US. See www-nlpir.nist.gov/projects/beadplot"+
"\nfor more information",
"About BeadPlot",
JOptionPane.INFORMATION_MESSAGE);
}
}
/**--------------------------------------------------------------------
* Provides application help
*/
public class ProvideApplHelp extends AbstractAction {
public ProvideApplHelp(String description) {
super(description);
}
/**
* Provides help
* @param event event which triggered this action
*/
public void actionPerformed(ActionEvent event) {
System.out.println("Providing BeadPlot application help");
JOptionPane.showMessageDialog
(f,
"1) Click on the 'File' menubar item and a menu will appear.\n\n"+
"2) Load qrels and result sets by clicking on the relevant menu\n"+
"items and following the directions. You can add more result sets\n"+
"later by the same process.\n\n"+
"Once both qrels and some result sets have been loaded, an initial\n"+
"beadplot will appear. The topic, for which results are displayed,\n"+
"appears at the top in the window frame. Every result set is re-\n"+
"presented by a line containing its run-id on the left, followed\n"+
"by a sequence of rectangles each representing a document, with the\n"+
"highest ranked document leftmost.\n\n"+
"One of the results sets, the reference result, is special. The\n"+
"plot only shows documents which appear in the reference set. Its\n"+
"run-id appears in blue. Each of its documents within a given\n"+
"range (the reference range) is assigned a spectral color. A\n"+
"given document always has the same color no matter where on the\n"+
"plot it appears: a spectral color if it (also) occurs in the\n"+
"reference range, otherwise gray.\n\n"+
"3) Here's how you can modify the plot:\n" +
" Use the items under the View menu to... \n" +
" - change the topic \n" +
" - look at a different subset of the result sets \n" +
" - move the starting rank of the reference range \n" +
" - make the reference range larger/smaller \n" +
" - see only (non)relevant documents \n\n" +
" Or use your mouse to... \n" +
" - pick a different reference result \n" +
" (left click on the run-id) \n" +
" - move a result to the bottom \n" +
" (right click on the run-id) \n" +
" - highlight a document everywhere it appears \n" +
" (left click on a doc's bead)\n" +
" - undo the document highlighting \n"+
" (right click on any bead) \n",
"About BeadPlot",
JOptionPane.INFORMATION_MESSAGE);
}
}
/*---------------------------------------------------------------------
* The BeadPlot application main method
* @param s IGNORED
*/
public static void main(String s[]) {
try {
UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName());
} catch (Exception e) { }
BeadPlot bP = new BeadPlot();
f = bP; // clean up - dont need both variables
Container contentPane = bP.getContentPane();
// Create the menus and add
JMenuBar menuBar = bP.createMenuBar();
bP.setJMenuBar(menuBar);
// Create the contents below the menubar and add
contents = bP.createComponents();
contentPane.add(contents);
bP.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e)
{System.exit(0);}
});
bP.pack();
bP.setVisible(true);
} // end main
} // end BeadPlot