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; /** 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 = 1000; 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 = 15; 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); junk = tokenizer.nextToken(); docid = tokenizer.nextToken(); junk = tokenizer.nextToken(); junk = tokenizer.nextToken(); runid = tokenizer.nextToken(); 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); } 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++) { // ----------- 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) ;// error message else { refResult = (DocData[])results.get(refRunId); if (refResult == null) ;// error message 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); Set runIdSet = resultsForCurTopic.keySet(); Iterator iterator = runIdSet.iterator(); String runId = null; for (i = 0; i < numRunIds; i++) { runId = (String)iterator.next(); runIdsForDisplay[i] = runId; resultSetsForDisplay[i] = (DocData[])resultsForCurTopic.get(runId); } } else // preserve existing order of unchanged number of run-ids { TreeMap resultsForCurTopic = (TreeMap)resultsByTopic.get(topicForDisplay); Set runIdSet = resultsForCurTopic.keySet(); Iterator iterator = runIdSet.iterator(); String runId = null; for (i = 0; i < numRunIds; i++) { 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]; for (int i = 0; i < numTopics; i++) { topics[i] = (String)iterator.next();} } } /**-------------------------------------------------------------------- * 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