001/* 002 * Copyright (c) 2004-2010 The Regents of the University of California. 003 * All rights reserved. 004 * 005 * '$Author: welker $' 006 * '$Date: 2010-05-06 05:21:26 +0000 (Thu, 06 May 2010) $' 007 * '$Revision: 24234 $' 008 * 009 * Permission is hereby granted, without written agreement and without 010 * license or royalty fees, to use, copy, modify, and distribute this 011 * software and its documentation for any purpose, provided that the above 012 * copyright notice and the following two paragraphs appear in all copies 013 * of this software. 014 * 015 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY 016 * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 017 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF 018 * THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF 019 * SUCH DAMAGE. 020 * 021 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, 022 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 023 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE 024 * PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF 025 * CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, 026 * ENHANCEMENTS, OR MODIFICATIONS. 027 * 028 */ 029 030package org.sdm.spa; 031 032import java.awt.BorderLayout; 033import java.awt.Color; 034import java.awt.Dimension; 035import java.text.DecimalFormat; 036import java.text.NumberFormat; 037import java.util.Collections; 038import java.util.Comparator; 039import java.util.HashMap; 040import java.util.HashSet; 041import java.util.Iterator; 042import java.util.Map; 043import java.util.StringTokenizer; 044import java.util.Vector; 045 046import javax.swing.BoxLayout; 047import javax.swing.JFrame; 048import javax.swing.JLabel; 049import javax.swing.JPanel; 050import javax.swing.JScrollPane; 051import javax.swing.JTable; 052import javax.swing.SwingUtilities; 053import javax.swing.table.DefaultTableModel; 054 055import ptolemy.actor.TypedAtomicActor; 056import ptolemy.actor.TypedIOPort; 057import ptolemy.data.StringToken; 058import ptolemy.data.type.BaseType; 059import ptolemy.kernel.CompositeEntity; 060import ptolemy.kernel.util.IllegalActionException; 061import ptolemy.kernel.util.NameDuplicationException; 062 063////////////////////////////////////////////////////////////////////////// 064//// MatchDisplay 065/** 066 * Show the Match Results in a tabulated form. 067 * 068 * @author Zhengang Cheng, Xiaowen Xin 069 * @version $Revision: 24234 $ 070 */ 071 072public class MatchDisplay extends TypedAtomicActor { 073 TfDisplay frame = null; 074 075 int m_intCount = 0; 076 HashMap m_mapFreq = new HashMap(); 077 078 SequenceSet m_sequenceSet = new SequenceSet(); 079 080 /** 081 * Construct an actor with the given container and name. 082 * 083 * @param container 084 * The container. 085 * @param name 086 * The name of this actor. 087 * @exception IllegalActionException 088 * If the actor cannot be contained by the proposed 089 * container. 090 * @exception NameDuplicationException 091 * If the container already has an actor with this name. 092 */ 093 public MatchDisplay(CompositeEntity container, String name) 094 throws NameDuplicationException, IllegalActionException { 095 super(container, name); 096 097 // default tokenConsumptionRate is 1. 098 input = new TypedIOPort(this, "GI", true, false); 099 input.setTypeEquals(BaseType.STRING); 100 101 context = new TypedIOPort(this, "Context", true, false); 102 context.setTypeEquals(BaseType.STRING); 103 104 // Set the icon. 105 _attachText("_iconDescription", "<svg>\n" 106 + "<polygon points=\"-15,-15 15,15 15,-15 -15,15\" " 107 + "style=\"fill:white\"/>\n" + "</svg>\n"); 108 } 109 110 // -- Part of the Actor 111 112 public TypedIOPort input; 113 public TypedIOPort context; 114 115 // ///////////////////////////////////////////////////////////////// 116 // // public methods //// 117 118 public void initialize() throws IllegalActionException { 119 super.initialize(); 120 // if (frame == null) 121 frame = new TfDisplay(); 122 m_intCount = 0; 123 m_mapFreq = new HashMap(); 124 } // end of initialize 125 126 /** 127 * It receives GI number and the Match result in a string. 128 * 129 * */ 130 public void fire() throws IllegalActionException { 131 super.fire(); 132 133 String in = ((StringToken) (input.get(0))).stringValue(); 134 // Get the context of the result 135 final String ctx = ((StringToken) (context.get(0))).stringValue(); 136 _debug("Process:" + in); 137 138 // The results are in several lines. 139 // Each field in a line is separated by \t 140 String temp; 141 StringTokenizer st1, st2; 142 final Vector mn, pom, cs, ms, seq, ln, tfm, lnt, freq; 143 mn = new Vector(); 144 pom = new Vector(); 145 cs = new Vector(); 146 ms = new Vector(); 147 seq = new Vector(); 148 ln = new Vector(); 149 tfm = new Vector(); 150 lnt = new Vector(); 151 152 st1 = new StringTokenizer(in, "\n"); 153 while (st1.hasMoreTokens()) { 154 String line = st1.nextToken(); 155 // Each line will look like: 156 // M00108 V$NRF2_01 980 (+) 1.000 0.922 gacGGAAGtg NRF-2 157 st2 = new StringTokenizer(line, "\t"); 158 temp = st2.nextToken(); 159 ln.add(temp); // Link 160 mn.add(st2.nextToken()); 161 pom.add(st2.nextToken()); 162 cs.add(st2.nextToken()); 163 ms.add(st2.nextToken()); 164 seq.add(st2.nextToken()); 165 tfm.add(st2.nextToken()); 166 } 167 168 freq = processTfbs(mn); 169 170 // Modify link vector to add information: 171 for (int i = 0; i < ln.size(); i++) { 172 lnt 173 .addElement("http://www.gene-regulation.com/cgi-bin/pub/databases/transfac/getTF.cgi?AC=" 174 + (String) ln.elementAt(i)); 175 } 176 177 final DefaultTableModel dtm = new DefaultTableModel(); 178 179 // Create a new table instance 180 dtm.addColumn("matrixName", mn); 181 dtm.addColumn("link", lnt); 182 dtm.addColumn("positionOfMatrix", pom); 183 dtm.addColumn("coreSimilarity", cs); 184 dtm.addColumn("matrixSimilarity", ms); 185 dtm.addColumn("sequence", seq); 186 dtm.addColumn("frequencies", freq); 187 188 SwingUtilities.invokeLater(new Runnable() { 189 public void run() { 190 191 // add tables showing Transfac results and frequencies 192 frame.addResult(ctx, dtm); 193 frame.addResult("Frequencies", getFrequencyPerRun(mn)); 194 195 // update table showing overall frequencies 196 frame.addOverallFreq("Overall", getFrequencyOverall(mn)); 197 198 // update table showing overall counts 199 frame 200 .addOverallCounts("Counts", m_sequenceSet.addData(mn, 201 ctx)); 202 203 // play with frame size--make sure it's not too big 204 if (!frame.isShowing()) { 205 frame.pack(); 206 207 double width = java.awt.Toolkit.getDefaultToolkit() 208 .getScreenSize().getWidth(); 209 double height = java.awt.Toolkit.getDefaultToolkit() 210 .getScreenSize().getHeight(); 211 212 if (frame.getWidth() < width) { 213 width = frame.getWidth(); 214 } 215 216 if (frame.getHeight() < height) { 217 height = frame.getHeight(); 218 } 219 220 frame.setSize(new Dimension((int) width, (int) height)); 221 } 222 frame.show(); 223 224 } 225 }); 226 227 } 228 229 class TfDisplay extends JFrame { 230 JPanel outpanel; 231 232 JPanel panelOverallFreq; 233 234 JPanel panelOverallCounts; 235 236 public JPanel addResult(String ctx, DefaultTableModel dtm) { 237 JPanel cellpanel; 238 JTable table; 239 JScrollPane scrollPane; 240 241 // Create a panel to hold all other components 242 cellpanel = new JPanel(); 243 cellpanel.setLayout(new BorderLayout()); 244 table = new JTable(dtm); 245 table.setCellSelectionEnabled(true); 246 table.setAutoResizeMode(1); 247 table.setColumnSelectionAllowed(true); 248 table.setRowSelectionAllowed(true); 249 JScrollPane cellsp = new JScrollPane(table); 250 cellpanel.setLayout(new BorderLayout()); 251 cellpanel.add(new JLabel("Context:" + ctx), BorderLayout.NORTH); 252 cellpanel.add(cellsp, BorderLayout.CENTER); 253 outpanel.add(cellpanel); 254 255 return cellpanel; 256 } 257 258 public void addOverallFreq(String ctx, DefaultTableModel dtm) { 259 if (null != panelOverallFreq) { 260 outpanel.remove(panelOverallFreq); 261 } 262 panelOverallFreq = addResult(ctx, dtm); 263 } 264 265 public void addOverallCounts(String ctx, DefaultTableModel dtm) { 266 if (null != panelOverallCounts) { 267 outpanel.remove(panelOverallCounts); 268 } 269 panelOverallCounts = addResult(ctx, dtm); 270 } 271 272 TfDisplay() { 273 setTitle("Match(Transfac) Result Display"); 274 setBackground(Color.gray); 275 outpanel = new JPanel(); 276 outpanel.setLayout(new BoxLayout(outpanel, BoxLayout.Y_AXIS)); 277 JScrollPane outsp = new JScrollPane(outpanel); 278 getContentPane().add(outsp); 279 280 } 281 } 282 283 private Vector processTfbs(Vector mn) { 284 String str, str1; 285 double tfCount; 286 double mnCount = mn.size(); 287 double frequency; 288 Vector uniqueTF = new Vector(); 289 Vector tfFrequency = new Vector(); 290 Vector frequencies = new Vector(); 291 for (int i = 0; i < mn.size(); i++) { 292 int index = ((String) mn.elementAt(i)).indexOf("_"); 293 str = ((String) mn.elementAt(i)).substring(0, index); 294 if (uniqueTF.contains(str)) { 295 } else { 296 uniqueTF.addElement(str); 297 } 298 } 299 300 NumberFormat formatter = new DecimalFormat("0.000"); 301 302 for (int i = 0; i < uniqueTF.size(); i++) { 303 tfCount = 0; 304 for (int j = 0; j < mn.size(); j++) { 305 if (((String) mn.elementAt(j)).startsWith(((String) uniqueTF 306 .elementAt(i)) 307 + "_")) { 308 tfCount++; 309 } 310 } 311 // We allow only 3 digits 312 frequency = (tfCount / mnCount) * 100; 313 314 tfFrequency.add(i, formatter.format(frequency)); 315 316 } 317 318 for (int i = 0; i < mn.size(); i++) { 319 int index = ((String) mn.elementAt(i)).indexOf("_"); 320 str = ((String) mn.elementAt(i)).substring(0, index); 321 int freqIndex = uniqueTF.indexOf(str); 322 frequencies.addElement(tfFrequency.elementAt(freqIndex) + "%"); 323 } 324 325 return frequencies; 326 } 327 328 private DefaultTableModel getFrequencyPerRun(Vector tfSites) { 329 // create hashmap mapping from tf binding site to frequency 330 HashMap mapFrequencies = new HashMap(); 331 332 Iterator itFreq = tfSites.iterator(); 333 while (itFreq.hasNext()) { 334 String strSite = (String) itFreq.next(); 335 strSite = strSite.split("_")[0]; 336 337 if (mapFrequencies.containsKey(strSite)) { 338 Integer count = (Integer) mapFrequencies.get(strSite); 339 mapFrequencies.put(strSite, new Integer(count.intValue() + 1)); 340 } else { 341 mapFrequencies.put(strSite, new Integer(1)); 342 } 343 } 344 return createTableModel(mapFrequencies, tfSites.size()); 345 } 346 347 private DefaultTableModel getFrequencyOverall(Vector tfSites) { 348 // create a set with only unique tf binding sites 349 HashSet setSites = new HashSet(); 350 Iterator itSites = tfSites.iterator(); 351 while (itSites.hasNext()) { 352 String strSite = (String) itSites.next(); 353 setSites.add(strSite.split("_")[0]); 354 } 355 356 // update m_mapFreq 357 itSites = setSites.iterator(); 358 while (itSites.hasNext()) { 359 String strSite = (String) itSites.next(); 360 361 if (m_mapFreq.containsKey(strSite)) { 362 Integer count = (Integer) m_mapFreq.get(strSite); 363 m_mapFreq.put(strSite, new Integer(count.intValue() + 1)); 364 } else { 365 m_mapFreq.put(strSite, new Integer(1)); 366 } 367 } 368 369 // update m_intCount 370 m_intCount++; 371 372 return createTableModel(m_mapFreq, m_intCount); 373 } 374 375 /** 376 * Create a DefaultTableModel representing the HashMap 377 * 378 * @param map 379 * a map from transcription factor binding sites to the number of 380 * times they appear 381 * @param count 382 * total number of transcription factor binding sites 383 * @return an object fit to be displayed sorted by frequency 384 */ 385 private DefaultTableModel createTableModel(HashMap map, int count) { 386 // put the entries of the HashMap in a vector 387 Vector vec = new Vector(map.entrySet()); 388 389 // sort the vector by frequency 390 Collections.sort(vec, new Comparator() { 391 public int compare(Object o1, Object o2) { 392 if (!((o1 instanceof Map.Entry && o2 instanceof Map.Entry))) { 393 throw new ClassCastException( 394 "Comparator called with arguments not of Map.Entry type."); 395 } 396 397 Map.Entry entry1 = (Map.Entry) o1; 398 Map.Entry entry2 = (Map.Entry) o2; 399 400 if (!((entry1.getKey() instanceof String) && (entry2.getKey() instanceof String))) { 401 throw new ClassCastException( 402 "Inputs to Comparator don't have keys of String type."); 403 } 404 if (!((entry1.getValue() instanceof Integer) && (entry2 405 .getValue() instanceof Integer))) { 406 throw new ClassCastException( 407 "Inputs to Comparator don't have values of Integer type."); 408 } 409 410 String key1 = (String) entry1.getKey(); 411 String key2 = (String) entry2.getKey(); 412 413 Integer value1 = (Integer) entry1.getValue(); 414 Integer value2 = (Integer) entry2.getValue(); 415 416 int comp = value1.compareTo(value2); 417 if (0 != comp) { 418 return -comp; 419 } else { 420 return key1.compareTo(key2); 421 } 422 } 423 }); 424 425 // populate table model 426 DefaultTableModel tableModel = new DefaultTableModel(); 427 tableModel.addColumn("MatrixName"); 428 tableModel.addColumn("Frequency"); 429 tableModel.addColumn("MatrixName"); 430 tableModel.addColumn("Frequency"); 431 tableModel.addColumn("MatrixName"); 432 tableModel.addColumn("Frequency"); 433 434 NumberFormat formatter = new DecimalFormat("0.000"); 435 int size = vec.size(); 436 Vector vecRow = new Vector(); 437 for (int i = 0; i < size; i++) { 438 Map.Entry entry = (Map.Entry) vec.elementAt(i); 439 String strSite = (String) entry.getKey(); 440 String strFreq = formatter.format(((Integer) entry.getValue()) 441 .intValue() 442 * 100.0 / count); 443 444 vecRow.add(strSite); 445 vecRow.add(strFreq + "% (" + entry.getValue() + "/" + count + ")"); 446 447 if (i % 3 == 2) { 448 tableModel.addRow(vecRow); 449 vecRow = new Vector(); 450 } 451 } 452 if (vecRow.size() > 0) { 453 tableModel.addRow(vecRow); 454 } 455 456 return tableModel; 457 } 458 459 /** 460 * Class to keep track of counts This class remembers the counts of tfbs' 461 * for all sequences it has processed so far. 462 */ 463 class SequenceSet { 464 // set of strings representing transcription factor binding sites 465 HashSet setTfs = new HashSet(); 466 467 // vector of Sequence objects 468 Vector vecSequences = new Vector(); 469 470 /** 471 * Class to store data related to one specific sequence 472 */ 473 class Sequence { 474 // name of the sequence 475 String strName; 476 477 // maps name of tfbs to number of times it occurred 478 HashMap mapCount; 479 } 480 481 /** 482 * Create a DefaultTableModel representing all data so far 483 * 484 * @param vecTfs 485 * vector of tfbs' 486 * @param name 487 * name of the sequence 488 * @return an object fit to be displayed sorted by tfbs name 489 */ 490 public DefaultTableModel addData(Vector vecTfs, String name) { 491 // create sequence 492 Sequence sequence = createSequence(vecTfs, name); 493 494 // update member variables of this class 495 vecSequences.add(sequence); 496 setTfs.addAll(sequence.mapCount.keySet()); 497 498 // initialize the DefaultTableModel to be returned 499 DefaultTableModel dtm = new DefaultTableModel(); 500 501 // create the left-most column 502 vecTfs = new Vector(setTfs); 503 Collections.sort(vecTfs); 504 dtm.addColumn("TFBS", vecTfs); 505 506 // loop over sequences 507 Iterator it = vecSequences.iterator(); 508 while (it.hasNext()) { 509 sequence = (Sequence) it.next(); 510 511 Vector vecCounts = new Vector(); 512 513 // loop over each TF 514 Iterator itTf = vecTfs.iterator(); 515 while (itTf.hasNext()) { 516 String strTf = (String) itTf.next(); 517 518 if (sequence.mapCount.containsKey(strTf)) { 519 vecCounts.add(sequence.mapCount.get(strTf)); 520 } else { 521 vecCounts.add(new Integer(0)); 522 } 523 } 524 525 // add a column corresponding to this sequence to dtm 526 dtm.addColumn(sequence.strName, vecCounts); 527 } 528 529 return dtm; 530 } 531 532 /** 533 * Create a Sequence object 534 * 535 * @param vecTfs 536 * vector of tfbs' 537 * @param name 538 * name of the sequence 539 * @return Sequence object containing representing input data 540 */ 541 public Sequence createSequence(Vector vecTfs, String name) { 542 // create hashmap mapping from tf binding site to frequency 543 HashMap mapFrequencies = new HashMap(); 544 545 // loop over tfbs' 546 Iterator itFreq = vecTfs.iterator(); 547 while (itFreq.hasNext()) { 548 String strSite = (String) itFreq.next(); 549 strSite = strSite.split("_")[0]; 550 551 if (mapFrequencies.containsKey(strSite)) { 552 Integer count = (Integer) mapFrequencies.get(strSite); 553 mapFrequencies.put(strSite, new Integer( 554 count.intValue() + 1)); 555 } else { 556 mapFrequencies.put(strSite, new Integer(1)); 557 } 558 } 559 560 // create sequence object and return it 561 Sequence sequence = new Sequence(); 562 sequence.strName = name; 563 sequence.mapCount = mapFrequencies; 564 565 return sequence; 566 } 567 568 } 569 570} 571 572// vim: noet ts=4 sw=4