001 package hep.aida.ref.sql.JAS3Plugin; 002 003 import hep.aida.ref.sql.SQLTupleFactory; 004 005 // FreeHEP 006 import org.freehep.application.studio.Studio; 007 import org.freehep.application.studio.PluginInfo; 008 import org.freehep.application.RecentItemTextField; 009 import org.freehep.util.commanddispatcher.CommandProcessor; 010 import org.freehep.util.commanddispatcher.CommandSourceAdapter; 011 import org.freehep.util.commanddispatcher.CommandState; 012 import org.freehep.util.commanddispatcher.BooleanCommandState; 013 014 // AIDA 015 import hep.aida.IAnalysisFactory; 016 import hep.aida.ITupleFactory; 017 import hep.aida.IHistogramFactory; 018 import hep.aida.IBaseHistogram; 019 import hep.aida.IHistogram; 020 import hep.aida.IHistogram1D; 021 import hep.aida.IHistogram2D; 022 import hep.aida.ICloud; 023 import hep.aida.ICloud1D; 024 import hep.aida.ICloud2D; 025 import hep.aida.IProfile; 026 import hep.aida.IProfile1D; 027 import hep.aida.IEvaluator; 028 import hep.aida.ITree; 029 import hep.aida.ITuple; 030 import hep.aida.ref.tuple.FTupleColumn; 031 032 // SQLTuple 033 import hep.aida.ref.sql.SQLTuple; 034 import hep.aida.ref.sql.SQLTupleException; 035 036 // JAS 037 import org.freehep.jas.plugin.console.ConsoleService; 038 import org.freehep.jas.services.TextEditorService; 039 import org.freehep.jas.services.PlotFactory; 040 import org.freehep.jas.services.PlotPage; 041 import org.freehep.jas.services.PlotRegion; 042 import org.freehep.jas.services.Plotter; 043 import org.freehep.jas.plugin.tree.FTreeNodeAddedNotification; 044 import org.freehep.jas.plugin.tree.FTreeProvider; 045 import org.freehep.jas.plugin.tree.FTree; 046 import org.freehep.jas.plugin.tree.FTreeNode; 047 import org.freehep.jas.services.WebBrowser; 048 import org.freehep.jas.plugin.web.SimpleWebBrowser; 049 050 // Swing 051 import javax.swing.JOptionPane; 052 import javax.swing.ImageIcon; 053 054 // Java 055 import java.util.List; 056 import java.io.PrintWriter; 057 import java.io.IOException; 058 import java.net.URL; 059 import java.net.MalformedURLException; 060 061 /** <code>SQLTupleCommands</code> contains SQLTuple commands for JAS3 plugin of SQLTuple. 062 * It uses directly AIDA {@link ITuple} calls so it profits from {@link hep.aida.ref.sql.SQLTuple} 063 * optimisation. 064 * <p><font color="#880088"> 065 * $Id: SQLTupleCommands.java,v 1.10 2007/09/26 07:58:51 hrivnac Exp $ 066 * <pre> 067 * $Log: SQLTupleCommands.java,v $ 068 * Revision 1.10 2007/09/26 07:58:51 hrivnac 069 * cache savable fromjas menu 070 * 071 * Revision 1.9 2007/05/23 16:38:44 hrivnac 072 * logical connections for Plotter; better UML 073 * 074 * Revision 1.8 2006/12/19 14:31:08 hrivnac 075 * news added into WS 076 * 077 * Revision 1.7 2006/04/22 12:05:27 hrivnac 078 * help included in JAS plugin 079 * 080 * Revision 1.6 2005/10/10 10:05:33 hrivnac 081 * prepared for 1.0.2 082 * 083 * Revision 1.5 2005/09/29 16:08:38 hrivnac 084 * javadoc fixed 085 * 086 * Revision 1.4 2005/09/29 14:31:32 hrivnac 087 * clouds and profiles added 088 * 089 * Revision 1.3 2005/09/29 13:02:39 hrivnac 090 * histograms can be plotted in a different way in JAS3 091 * 092 * Revision 1.2 2005/09/29 09:22:59 hrivnac 093 * jas3 plugin improved 094 * 095 * Revision 1.1 2005/09/28 22:49:55 hrivnac 096 * added SQLTuple-aware projections 097 * 098 * </pre> 099 * </font></p> 100 * @opt attributes 101 * @opt operations 102 * @opt types 103 * @opt visibility 104 * @version $Id: SQLTupleCommands.java,v 1.10 2007/09/26 07:58:51 hrivnac Exp $ 105 * @author <a href="mailto:Julius.Hrivnac@cern.ch">J.Hrivnac</a> */ 106 public class SQLTupleCommands extends CommandProcessor { 107 108 /** Initialise and connect to JAS3. 109 * @param plugin The connected {@link SQLTuplePlugin}. */ 110 public SQLTupleCommands(SQLTuplePlugin plugin) { 111 // Register environment 112 _plugin = plugin; 113 _app = ((Studio)plugin.getApplication()); 114 TextEditorService textEditor = (TextEditorService)_app.getLookup().lookup(TextEditorService.class); 115 FTreeProvider treeProvider = (FTreeProvider )_app.getLookup().lookup(FTreeProvider.class); 116 _plotFactory = (PlotFactory )_app.getLookup().lookup(PlotFactory.class); 117 _tree = treeProvider.tree(); 118 // Register Adaptors 119 treeProvider.treeNodeAdapterRegistry().registerNodeAdapter(new SQLTupleColumnAdapter(_app, this), FTupleColumn.class); 120 // Create Console 121 ConsoleService cs = (ConsoleService)_app.getLookup().lookup(ConsoleService.class); 122 if (cs != null) { 123 try { 124 _log = new PrintWriter(cs.getConsoleOutputStream("SQLTuple", null), true); 125 } 126 catch (IOException e) { 127 JOptionPane.showMessageDialog(_app, "Can't open SQLTuple Console: " + e, "SQLTuple Projector Warning", JOptionPane.WARNING_MESSAGE); 128 } 129 } 130 } 131 132 /** Project {@link IHistogram} in Current Region. */ 133 public void onProjectHistogramInCurrentRegion() { 134 histogram(false, false, false); 135 setChanged(); 136 } 137 138 /** Project {@link IHistogram} in New Region. */ 139 public void onProjectHistogramInNewRegion() { 140 histogram(false, false, true); 141 setChanged(); 142 } 143 144 /** Project {@link IHistogram} in New Page. */ 145 public void onProjectHistogramInNewPage() { 146 histogram(true, false, false); 147 setChanged(); 148 } 149 150 /** Project {@link IHistogram} Overlay. */ 151 public void onProjectHistogramOverlay() { 152 histogram(false, true, false); 153 setChanged(); 154 } 155 156 /** Project {@link ICloud} in Current Region. */ 157 public void onProjectCloudInCurrentRegion() { 158 cloud(false, false, false); 159 setChanged(); 160 } 161 162 /** Project {@link ICloud} in New Region. */ 163 public void onProjectCloudInNewRegion() { 164 cloud(false, false, true); 165 setChanged(); 166 } 167 168 /** Project {@link ICloud} in New Page. */ 169 public void onProjectCloudInNewPage() { 170 cloud(true, false, false); 171 setChanged(); 172 } 173 174 /** Project {@link ICloud} Overlay. */ 175 public void onProjectCloudOverlay() { 176 cloud(false, true, false); 177 setChanged(); 178 } 179 180 /** Project {@link IProfile} in Current Region. */ 181 public void onProjectProfileInCurrentRegion() { 182 profile(false, false, false); 183 setChanged(); 184 } 185 186 /** Project {@link IProfile} in New Region. */ 187 public void onProjectProfileInNewRegion() { 188 profile(false, false, true); 189 setChanged(); 190 } 191 192 /** Project {@link IProfile} in New Page. */ 193 public void onProjectProfileInNewPage() { 194 profile(true, false, false); 195 setChanged(); 196 } 197 198 /** Project {@link IProfile} Overlay. */ 199 public void onProjectProfileOverlay() { 200 profile(false, true, false); 201 setChanged(); 202 } 203 204 /** Act on Save Cache click. Saves database schema cache into a file. */ 205 public void onSaveCache() { 206 SQLTupleFactory.saveCache(); 207 setChanged(); 208 } 209 210 /** Enable Save Cache. Always enabled. 211 * @param state Ignored. */ 212 public void enableSaveCache(CommandState state) { 213 state.setEnabled(true); 214 } 215 216 /** Act on Help click. Open a window with a help page. */ 217 public void onHelpSQLTuple() { 218 if (_webBrowser == null) { 219 _webBrowser = (SimpleWebBrowser)_app.getLookup().lookup(WebBrowser.class); 220 } 221 try { 222 URL homePage = new URL(_homePageString); 223 _webBrowser.showURL(homePage); 224 } 225 catch (MalformedURLException e) { 226 JOptionPane.showMessageDialog(_app, "Can't show help: " + e, "SQLTuple Error", JOptionPane.ERROR_MESSAGE); 227 } 228 setChanged(); 229 } 230 231 /** Enable Help. Always enabled. 232 * @param state Ignored. */ 233 public void enableHelpSQLTuple(CommandState state) { 234 state.setEnabled(true); 235 } 236 237 /** Project {@link ITuple} into {@link IHistogram}. 238 * Depending on number of selected columns, following 239 * {@link IHistogram}s are produced: 240 * <ol> 241 * <li>{@link IHistogram1D}</li> 242 * <li>{@link IHistogram2D}</li> 243 * <li>{@link IHistogram2D} with weight</li> 244 * </ol> 245 * @param newPage Whether plot on a new page. 246 * @param overlay Whether overlay current plot. 247 * @param newPlot Whether create new plot. 248 * @return The created {@link IHistogram}. */ 249 private IHistogram histogram(boolean newPage, 250 boolean overlay, 251 boolean newPlot) { 252 ITree tree = (ITree)(_app.getLookup().lookup(ITree.class)); 253 IAnalysisFactory af = IAnalysisFactory.create(); 254 ITupleFactory tf = af.createTupleFactory(tree); 255 IHistogramFactory hf = af.createHistogramFactory(tree); 256 FTreeNode[] nodes = _tree.selectedNodes(); 257 FTreeNode parent = nodes[0].parent(); 258 ITuple tuple = (ITuple)(parent.objectForClass(ITuple.class)); 259 IHistogram histogram = null; 260 tree.mkdirs(parent.path() + "-histograms"); 261 if (nodes.length == 1) { 262 String columnX = nodes[0].toString(); 263 int indexX = tuple.findColumn(columnX); 264 IEvaluator evaluatorX = tf.createEvaluator(columnX); 265 histogram = hf.createHistogram1D(parent.path() + "-histograms/" + columnX, 266 50, 267 tuple.columnMin(indexX), 268 tuple.columnMax(indexX)); 269 plot(histogram, newPage, overlay, newPlot); 270 tuple.project((IHistogram1D)histogram, evaluatorX); 271 } 272 else if (nodes.length == 2) { 273 String columnX = nodes[0].toString(); 274 String columnY = nodes[1].toString(); 275 int indexX= tuple.findColumn(columnX); 276 int indexY= tuple.findColumn(columnY); 277 IEvaluator evaluatorX = tf.createEvaluator(columnX); 278 IEvaluator evaluatorY = tf.createEvaluator(columnY); 279 histogram = hf.createHistogram2D(parent.path() + "-histograms/" + columnX + " x " + columnY, 280 50, 281 tuple.columnMin(indexX), 282 tuple.columnMax(indexX), 283 50, 284 tuple.columnMin(indexY), 285 tuple.columnMax(indexY)); 286 plot(histogram, newPage, overlay, newPlot); 287 tuple.project((IHistogram2D)histogram, evaluatorX, evaluatorY); 288 } 289 else if (nodes.length == 3) { 290 String columnX = nodes[0].toString(); 291 String columnY = nodes[1].toString(); 292 String columnW = nodes[2].toString(); 293 int indexX = tuple.findColumn(columnX); 294 int indexY = tuple.findColumn(columnY); 295 int indexW = tuple.findColumn(columnW); 296 IEvaluator evaluatorX = tf.createEvaluator(columnX); 297 IEvaluator evaluatorY = tf.createEvaluator(columnY); 298 IEvaluator weight = tf.createEvaluator(columnW); 299 histogram = hf.createHistogram2D(parent.path() + "-histograms/" + columnX + " x " + columnY + " x " + columnW, 300 50, 301 tuple.columnMin(indexX), 302 tuple.columnMax(indexX), 303 50, 304 tuple.columnMin(indexY), 305 tuple.columnMax(indexY)); 306 plot(histogram, newPage, overlay, newPlot); 307 tuple.project((IHistogram2D)histogram, evaluatorX, evaluatorY, weight); 308 } 309 else { 310 JOptionPane.showMessageDialog(_app, "Can't project IHistogram from " + nodes.length + " columns", "SQLTuple Projector Warning", JOptionPane.WARNING_MESSAGE); 311 } 312 return histogram; 313 } 314 315 /** Project {@link ITuple} into {@link ICloud}. 316 * Depending on number of selected columns, following 317 * {@link IHistogram}s are produced: 318 * <ol> 319 * <li>{@link ICloud1D}</li> 320 * <li>{@link ICloud2D}</li> 321 * <li>{@link ICloud2D} with weight</li> 322 * </ol> 323 * @param newPage Whether plot on a new page. 324 * @param overlay Whether overlay current plot. 325 * @param newPlot Whether create new plot. 326 * @return The created {@link ICloud}. */ 327 private ICloud cloud(boolean newPage, 328 boolean overlay, 329 boolean newPlot) { 330 ITree tree = (ITree)(_app.getLookup().lookup(ITree.class)); 331 IAnalysisFactory af = IAnalysisFactory.create(); 332 ITupleFactory tf = af.createTupleFactory(tree); 333 IHistogramFactory hf = af.createHistogramFactory(tree); 334 FTreeNode[] nodes = _tree.selectedNodes(); 335 FTreeNode parent = nodes[0].parent(); 336 ITuple tuple = (ITuple)(parent.objectForClass(ITuple.class)); 337 ICloud cloud = null; 338 tree.mkdirs(parent.path() + "-clouds"); 339 if (nodes.length == 1) { 340 String columnX = nodes[0].toString(); 341 int indexX = tuple.findColumn(columnX); 342 IEvaluator evaluatorX = tf.createEvaluator(columnX); 343 cloud = hf.createCloud1D(parent.path() + "-clouds/" + columnX); 344 plot(cloud, newPage, overlay, newPlot); 345 tuple.project((ICloud1D)cloud, evaluatorX); 346 } 347 else if (nodes.length == 2) { 348 String columnX = nodes[0].toString(); 349 String columnY = nodes[1].toString(); 350 int indexX= tuple.findColumn(columnX); 351 int indexY= tuple.findColumn(columnY); 352 IEvaluator evaluatorX = tf.createEvaluator(columnX); 353 IEvaluator evaluatorY = tf.createEvaluator(columnY); 354 cloud = hf.createCloud2D(parent.path() + "-clouds/" + columnX + " x " + columnY); 355 tuple.project((ICloud2D)cloud, evaluatorX, evaluatorY); 356 } 357 else if (nodes.length == 3) { 358 String columnX = nodes[0].toString(); 359 String columnY = nodes[1].toString(); 360 String columnW = nodes[2].toString(); 361 int indexX = tuple.findColumn(columnX); 362 int indexY = tuple.findColumn(columnY); 363 int indexW = tuple.findColumn(columnW); 364 IEvaluator evaluatorX = tf.createEvaluator(columnX); 365 IEvaluator evaluatorY = tf.createEvaluator(columnY); 366 IEvaluator weight = tf.createEvaluator(columnW); 367 cloud = hf.createCloud2D(parent.path() + "-clouds/" + columnX + " x " + columnY + " x " + columnW); 368 plot(cloud, newPage, overlay, newPlot); 369 tuple.project((ICloud2D)cloud, evaluatorX, evaluatorY, weight); 370 } 371 else { 372 JOptionPane.showMessageDialog(_app, "Can't project ICloud from " + nodes.length + " columns", "SQLTuple Projector Warning", JOptionPane.WARNING_MESSAGE); 373 } 374 return cloud; 375 } 376 377 /** Project {@link ITuple} into {@link IProfile}. 378 * Depending on number of selected columns, following 379 * {@link IProfile}s are produced: 380 * <ol> 381 * <li></li> 382 * <li>{@link IProfile1D}</li> 383 * <li>{@link IProfile1D} with weight</li> 384 * </ol> 385 * @param newPage Whether plot on a new page. 386 * @param overlay Whether overlay current plot. 387 * @param newPlot Whether create new plot. 388 * @return The created {@link IProfile}. */ 389 private IProfile profile(boolean newPage, 390 boolean overlay, 391 boolean newPlot) { 392 ITree tree = (ITree)(_app.getLookup().lookup(ITree.class)); 393 IAnalysisFactory af = IAnalysisFactory.create(); 394 ITupleFactory tf = af.createTupleFactory(tree); 395 IHistogramFactory hf = af.createHistogramFactory(tree); 396 FTreeNode[] nodes = _tree.selectedNodes(); 397 FTreeNode parent = nodes[0].parent(); 398 ITuple tuple = (ITuple)(parent.objectForClass(ITuple.class)); 399 IProfile profile = null; 400 tree.mkdirs(parent.path() + "-profiles"); 401 if (nodes.length == 2) { 402 String columnX = nodes[0].toString(); 403 String columnY = nodes[1].toString(); 404 int indexX= tuple.findColumn(columnX); 405 int indexY= tuple.findColumn(columnY); 406 IEvaluator evaluatorX = tf.createEvaluator(columnX); 407 IEvaluator evaluatorY = tf.createEvaluator(columnY); 408 profile = hf.createProfile1D(parent.path() + "-profiles/" + columnX + " x " + columnY, 409 50, 410 tuple.columnMin(indexX), 411 tuple.columnMax(indexX), 412 tuple.columnMin(indexY), 413 tuple.columnMax(indexY)); 414 plot(profile, newPage, overlay, newPlot); 415 tuple.project((IProfile1D)profile, evaluatorX, evaluatorY); 416 } 417 else if (nodes.length == 3) { 418 String columnX = nodes[0].toString(); 419 String columnY = nodes[1].toString(); 420 String columnW = nodes[2].toString(); 421 int indexX = tuple.findColumn(columnX); 422 int indexY = tuple.findColumn(columnY); 423 int indexW = tuple.findColumn(columnW); 424 IEvaluator evaluatorX = tf.createEvaluator(columnX); 425 IEvaluator evaluatorY = tf.createEvaluator(columnY); 426 IEvaluator weight = tf.createEvaluator(columnW); 427 profile = hf.createProfile1D(parent.path() + "-profiles/" + columnX + " x " + columnY + " x " + columnW, 428 50, 429 tuple.columnMin(indexX), 430 tuple.columnMax(indexX), 431 tuple.columnMin(indexY), 432 tuple.columnMax(indexY)); 433 434 plot(profile, newPage, overlay, newPlot); 435 tuple.project((IProfile1D)profile, evaluatorX, evaluatorY, weight); 436 } 437 else { 438 JOptionPane.showMessageDialog(_app, "Can't project IProfile from " + nodes.length + " columns", "SQLTuple Projector Warning", JOptionPane.WARNING_MESSAGE); 439 } 440 return profile; 441 } 442 443 /** Enable EventSelector. Always enbabled. 444 * @param state Ignored. */ 445 public void enableProjector(CommandState state) { 446 state.setEnabled(true); 447 } 448 449 /** Plot {@link IBaseHistogram} according to selected options. 450 * @param histogram The {@link IBaseHistogram} to plot. 451 * @param newPage Whether plot on a new page. 452 * @param overlay Whether overlay current plot. 453 * @param newPlot Whether create new plot. */ 454 private void plot(IBaseHistogram histogram, 455 boolean newPage, 456 boolean overlay, 457 boolean newPlot) { 458 PlotPage plotPage = newPage ? null : _plotFactory.currentPage(); 459 boolean justCreated = false; 460 if (plotPage == null) { 461 plotPage = _plotFactory.createPage(null); 462 plotPage.showPage(); 463 justCreated = true; 464 } 465 PlotRegion region = plotPage.currentRegion(); 466 if (region == null) { 467 region = plotPage.createRegion(0, 0, 1, 1); 468 } 469 else if (newPlot && !justCreated) { 470 region = plotPage.addRegion(); 471 } 472 Plotter plotter = region.currentPlot(); 473 if (plotter == null) { 474 plotter = _plotFactory.createPlotterFor(histogram.getClass()); 475 } 476 plotter.plot(histogram, overlay ? plotter.OVERLAY : plotter.NORMAL); 477 region.showPlot(plotter); 478 } 479 480 private SQLTuplePlugin _plugin; 481 482 private Studio _app; 483 484 private FTree _tree; 485 486 private PlotFactory _plotFactory; 487 488 private PrintWriter _log; 489 490 private SimpleWebBrowser _webBrowser; 491 492 private static String _homePageString = "classpath:/hep/aida/ref/sql/JAS3Plugin/doc-files/JAS3.html"; 493 494 }