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 }