Get annotation selection

Help
2006-10-04
2013-05-15
  • Martin Szugat

    Martin Szugat - 2006-10-04

    Hi!

    I have another question: How to get the indices of those gene headers that were selected in the annotations dialog? I already found the class responsible for storing the indices, the HeaderSummary class, but I don't know how to get to the HeaderSummary instance from the ViewFrame object.

    Best regards

    Martin

     
    • Alok Saldanha

      Alok Saldanha - 2006-10-04

      This is a great question! There's no easy way,
      because the HeaderSummary in question is part of
      the Dendrogram plugin, not the core per se!

      I'm going to need to work around this, and it probably won't be pretty... I just added a "getMainPanelsByName()" method to the ViewFrame interface in CVS, and I had to touch a few other files so you'll need to do a "cvs update src".

      With the new changes, you should be able to do something like this:

      MainPanel [] dendrograms = viewFrame.getMainPanelsByName("Dendrogram");
      HeaderSummary geneSummary = ((DendroView) dendrograms[0]).getTextView().getHeaderSummary();

      You can do likewise for the array annotations, and the gene tree and array tree annotations. In retrospect I should have provided a general mechanism to retrieve plugin instances by name in the first place.

      I also added a general "getMainPanels()" call to ViewFrame that lets you get a list of all plugin instances, in anticipation of future demands.

       
    • Alok Saldanha

      Alok Saldanha - 2006-10-04

      Also, it seems that if many plugins are making summaries of annotations it might make sense to centralize the HeaderSummary objects, either in the ViewFrame or the DataModel. Perhaps the most reasonable thing is to just add it to the HeaderInfo objects, so each HeaderInfo would have a single associated HeaderSummary.

      As it stands, you could have multiple Dendrogram plugins open with different sets of annotations selected for display in each. that might be more general than necessary...

       
    • Martin Szugat

      Martin Szugat - 2006-10-04

      Thanks again! Works fine :)

       
    • Martin Szugat

      Martin Szugat - 2006-10-06

      Works fine only within Eclipse. However, if I rebuild the LinkedView distribution and copy the JAR of my plugin into the plugins directory I get the following exception:

      Exception in thread "AWT-EventQueue-0" java.lang.NoClassDefFoundError: edu/stanf
      ord/genetics/treeview/plugin/dendroview/DendroView

      Nevertheless, Java Tree View loads the Dendrogram and the view of my plugin but my plugin can not access the DendroView class?! Any hints why this does not work?

       
      • Alok Saldanha

        Alok Saldanha - 2006-10-06

        Hmm... I should have thought of this possibility. Classes in java are defined by both their name and the classloader that loads them. The problem most likely stems from the fact that the classloader that loads your plugin is different from the one that loads the Dendrogram... Indeed, as the classloader that loaded your plugin traverses it's hierarchy, it  will never find the DendroView because none of it's parents have Dendrogram.jar in their classpaths either.

        So... One way to solve this is to use a single classloader to load all the plugins. I went so far as to implement this, I split up the loadPlugins(File []) into two parts, a first pass that creates a classloader with access to all the plugin jars, and a second that sweeps over them looking for the tv_plugins.cd files. This will work as long as all plugin jars are present at application startup (i.e. when scanForPlugins() is called).

        However, I am actually not sure that this is a good idea... The classloader system is designed so that two plugins that share the same namespace will not conflict if they are packaged up into different jars. You could actually have two versions of a plugin running in the same treeview without the classes getting confused. It boggles the mind - for some serious boggling,check out:
        http://www.onjava.com/pub/a/onjava/2003/11/12/classloader.html
        The upshot is that it wouldn't help even if bundle some/all of the code of the Dendrogram into your plugin jar, you would just get a ClassCastException instead of a NoClassDef, because the DendroView in your plugin jar is not the same to the JVM as that in the Dendrogram jar.

        There is an intractable conflict between keeping plugins isolated from each other, and allowing them to access each other's instance variables. So... before I commit the new code, I would like to browse the web and consult with my friends who are actually CS pros...

        The only way around this that I can think of is to use reflection. If my analysis is correct, and it may not be, you should be able to access the header summary of interest using something like:

        MainPanel [] mp = viewFrame.getMainPanelsByName("Dendrogram");
        Method getTextView = mp[0].getClass().getMethod("getTextview", new Class [0]);
        Object textViewInstance = getTextView.invoke(mp[0], new Object[0]);
        Class textViewClass = textViewInstance.getClass();
        Method getHeaderSummary = textViewClass.getMethod("getHeaderSummary", new Class[0]);
        HeaderSummary geneHeaderSummary = (HeaderSummary) getHeaderSummary.invoke(textViewInstance, new Object[0]);

        Please let me know if the above code works for you.

        It might be easier if I added a getHeaderSummary() call to HeaderInfo that let you get the "default summary" for a given HeaderInfo, and switched the Dendrogram over to using it... this would free you from a dependency on the Dendrogram.

         
        • Alok Saldanha

          Alok Saldanha - 2006-10-06

          incidentally, I just checked and the following code

          DendroView dendroView = (DendroView) mp[0];
          HeaderSummary headerSummary = dendroView.getTextview().getHeaderSummary();
          JOptionPane.showMessageDialog(KaryoPanel.this, headerSummary);

          throws a NoClassDef just like the one you're reporting. So try the reflection,it will probably work.

           
          • Alok Saldanha

            Alok Saldanha - 2006-10-06

            Incidentally, the exact reflection equivalent of the above code is

            MainPanel [] mp = viewFrame.getMainPanelsByName("Dendrogram");
            Method getTextView = mp[0].getClass().getMethod("getTextview", new Class [0]);
            Object textViewInstance = getTextView.invoke(mp[0], new Object[0]);
            Class textViewClass = textViewInstance.getClass();
            Method getHeaderSummary = textViewClass.getMethod("getHeaderSummary", new Class[0]);
            HeaderSummary geneHeaderSummary = (HeaderSummary) getHeaderSummary.invoke(textViewInstance, new Object[0]);
            JOptionPane.showMessageDialog(KaryoPanel.this, geneHeaderSummary);

            OF course, you'll have to add a bunch of try-catch blocks too... just try pasting it in even if you don't get it right away, enlightenment can wait.

             
    • Martin Szugat

      Martin Szugat - 2006-10-06

      Works as you suggested. However, it would be better if the header summary and the annotations dialog would be assigned to the main app and not to the dendroview. So the annotations dialog would be also accessible from within my plugin view.

      Thanks a lot again!

      Martin

       
      • Alok Saldanha

        Alok Saldanha - 2006-10-07

        I will probably move the HeaderSummary into the DataModel, making it accessible via something like

        viewFrame.getDataModel().getGeneHeaderInfo().getHeaderSummary().

        It may be reasonable to move the dialog too, but I have to think about it more. Once you can get the HeaderSummary and HeaderInfo, it's easy to open a dialog, for instance this should work in your plugin:

        HeaderInfo geneHeaderInfo = viewFrame.getDataModel().getGeneHeaderInfo();
        MainPanel [] mp = viewFrame.getMainPanelsByName("Dendrogram");
        Method getTextView = mp[0].getClass().getMethod("getTextview", new Class [0]);
        Object textViewInstance = textViewInstance = getTextView.invoke(mp[0], new Object[0]);
        Class textViewClass = textViewInstance.getClass();
        Method getHeaderSummary = textViewClass.getMethod("getHeaderSummary", new Class[0]);
        HeaderSummary geneHeaderSummary = (HeaderSummary) getHeaderSummary.invoke(textViewInstance, new Object[0]);
        HeaderSummaryPanel genePanel = new HeaderSummaryPanel(geneHeaderInfo, geneHeaderSummary);
        JDialog settingsDialog = new ModelessSettingsDialog(viewFrame, "Gene Annotation Settings", genePanel);
        settingsDialog.addWindowListener(XmlConfig.getStoreOnWindowClose(viewFrame.getDataModel().getDocumentConfig()));
        settingsDialog.pack();
        settingsDialog.setVisible(true);

         

Log in to post a comment.