[Bio] / PyGUI / RecoElempanel.py Repository:
ViewVC logotype

View of /PyGUI/RecoElempanel.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.41 - (download) (as text) (annotate)
Mon Oct 4 19:56:54 2004 UTC (15 years, 1 month ago) by efrank
Branch: MAIN
CVS Tags: MigrateToNewPackage, HEAD
Changes since 1.40: +13 -2 lines
uses new graph library code to compute total edge multiplicty on a node and
then uses that to decide when to replicate that node in a viz-graph layout.

import copy
from wxPython.wx         import *
from KahApp.KahConfigMgr import KahConfigMgr
from FaST.BssFactory     import BssFactory
from KahOM.RecoElem      import RecoElem
import os
from tempfile            import mktemp 
from tempfile            import TemporaryFile


#------------------------------------------------------------------------
class TreeData:
#------------------------------------------------------------------------
    """
    TreeData instances are associated with wxTree nodes via
    SetPyData(). TreeData is just a struct to keep us sane
    when fetching things back. It holds a RecoElem and the
    CatalogEntry that owns it.
    """

    def __init__(self, itemId, aRecoElem, aCatalogEntry):
        self.re       = aRecoElem
        self.ce       = aCatalogEntry
        self.itemId   = itemId
        return

        


#------------------------------------------------------------------------
class RecoElempanel:
#------------------------------------------------------------------------
#    def __init__(self, parent):
#    def initEvents(self):
#    def ID_NUM(self,event):
#    def AddRecoElemTree( self, treeItemId, aRecoElem, aCatalogEntry ):
#    def onSelectReaction(self,event):
#    def onSelect(self, treeEvent):
#    def redrawRecoElemRxList(self, re):
#    def onRightListClick( self, event):
#    def setupRecoElemRxListEditMenu(self):
#    def rightTreeClick( self, event):
#    def setupRecoElemEditMenu(self):
#    def updateTreeBranchText(self, sourceRXNum):
#    def recoElemPasteRx(self, event):
#    def recoElemPasteFromSelectedRxGrid(self, event):
#    def recoElemAddKid(self, event):
#    def recoElemAddRoot(self, event):
#    def recoElemRxListCut(self, event):
#    def recoElemRxListCopy(self, event):
#    def recoElemRxListPaste(self, event):

    #------------------------------------------------------------------
    def __init__(self, parent):
    #------------------------------------------------------------------
        self.selectedItem    = None      # last thing selected. Instance of TreeItem
        self.cutOrCopiedRx   = None
        self.cutOrCopiedRE   = None
        self._pluginDict      = {}        # used to dispatch calls to plugins.
        self.parent = parent

        self.parent.rootId = self.parent.tree_ctr.AddRoot("top item")

 
        #set up menu for editing recoelem
        self.recoElemEditMenu = wxMenu()
        self.recoElemNewKidId = wxNewId()
        self.recoElemCopyREBranchId = wxNewId()
        self.recoElemCutREBranchId = wxNewId()
        self.recoElemPasteREBranchId = wxNewId()

        self.recoElemPasteRxId = wxNewId()
        self.recoElemPasteFromSelectedRxGridId = wxNewId()
        self.recoElemVizWithCytoScapeId = wxNewId()
        self.recoElemWriteToBssId = wxNewId()
        self.setupRecoElemEditMenu()

        #set up menu for list
        self.recoElemRxListEditMenu = wxMenu()
        self.recoElemRxListCutId = wxNewId()
        self.recoElemRxListCopyId = wxNewId()
        self.recoElemRxListPasteId = wxNewId()
        self.setupRecoElemRxListEditMenu()

        self.initEvents()
        return

    #------------------------------------------------------------------
    def initEvents(self):
    #------------------------------------------------------------------

        #button1= self.parent.OK_button
        # select in list of reactions
        EVT_LISTBOX(self.parent, self.parent.list_box.GetId(),
                    self.onSelectReaction)

        # hit the button that loads a RecoElem id
        #EVT_BUTTON(self.parent, button1.GetId(), self.ID_NUM)

        # select in tree
        EVT_TREE_SEL_CHANGED(self.parent.tree_ctr, 
                             self.parent.tree_ctr.GetId(), self.onSelect)

        # Right click on tree (presumably after selection)
        EVT_RIGHT_DOWN(self.parent.tree_ctr, self.rightTreeClick)

        # Right click on List (presumably after selection)
        EVT_RIGHT_DOWN(self.parent.list_box, self.onRightListClick)

        # this does not work for some reason.
        #EVT_LISTBOX(self.parent.list_box, self.parent.list_box.GetId(),
        #  self.onRightListClick)
        
        
        return


    #------------------------------------------------------------------
    def addRecoElemTree( self, treeItemId, aRecoElem, aCatalogEntry ):
    #------------------------------------------------------------------
        
        numrx= len(aRecoElem.Reactions)
        if numrx > 0:
            rxitem = "(" + str(numrx) + "rx"+ ") " + aRecoElem.Name
        else:
            rxitem = aRecoElem.Name

        itemId=self.parent.tree_ctr.AppendItem(treeItemId, rxitem )
        self.parent.tree_ctr.SetPyData(itemId,
                                       TreeData( itemId, aRecoElem, aCatalogEntry))
        
        for kid in aRecoElem.SubElems:
            self.addRecoElemTree( itemId, kid, aCatalogEntry )
            
        return

    #------------------------------------------------------------------
    def onSelectReaction(self,event):
    #------------------------------------------------------------------
        return

        pt=self.parent.list_box.GetPosition()
        item =self.parent.list_box.HitTest(pt)

        selectedlist=self.parent.list_box.GetSelections()

        for count in selectedlist:
            rx = self.parent.list_boxData[count]

        return

    #------------------------------------------------------------------
    def onSelect(self, treeEvent):
    #------------------------------------------------------------------
        item = treeEvent.GetItem()
        re = self.parent.tree_ctr.GetPyData(item).re
        self.selectedItem=item
      
        self.redrawRecoElemRxList( re )
        return

    #------------------------------------------------------------------
    def redrawRecoElemRxList(self, re):
    #------------------------------------------------------------------
        """
        @type re: KahOM.RecoElem
        @rtype: none
        """
        wxBeginBusyCursor()
        self.parent.list_box.Clear()
        offset = 0
        self.parent.list_boxData.clear()
        for rx in re.Reactions:
            item = rx.asString()
            listnum = self.parent.list_box.Append(item)
            itemNo =  self.parent.list_box.GetCount()-1
            # we store the recoElem ptr too in case we have to rm the rx
            self.parent.list_boxData[itemNo] = (rx, offset, re)
            offset += 1
           
        wxEndBusyCursor()

        return

    #------------------------------------------------------------------
    def onRightListClick( self, event):
    #------------------------------------------------------------------
                
        listBoxObject = event.GetEventObject()
        listBoxObject.PopupMenu(self.recoElemRxListEditMenu, event.GetPosition())
        
        return
    
    #------------------------------------------------------------------
    def setupRecoElemRxListEditMenu(self):
    #------------------------------------------------------------------
        self.recoElemRxListEditMenu.Append( self.recoElemRxListCutId, 
                                          "Cut", "Cut" )
        EVT_MENU(self.parent, self.recoElemRxListCutId, self.recoElemRxListCut)
        

        self.recoElemRxListEditMenu.Append( self.recoElemRxListCopyId,
                                          "Copy","Copy")
        EVT_MENU(self.parent, self.recoElemRxListCopyId,self.recoElemRxListCopy)
        self.recoElemRxListEditMenu.Append( self.recoElemRxListPasteId,
                                          "Paste", "Paste")
        EVT_MENU(self.parent, self.recoElemRxListPasteId,
                 self.recoElemRxListPaste)

        self.recoElemRxListEditMenu.Append( self.recoElemPasteFromSelectedRxGridId,
                                            "Paste From Selected Rx Table", 
                                            "Paste From Selected Rx Table")
        EVT_MENU(self.parent, self.recoElemPasteFromSelectedRxGridId,
                 self.recoElemPasteFromSelectedRxGrid)


        return

    #------------------------------------------------------------------
    def rightTreeClick( self, event):
    #------------------------------------------------------------------
        #pt=event.GetPosition()
        #if self.selectedItem != None:
        if 1:
            treeObject = event.GetEventObject()
            treeObject.PopupMenu(self.recoElemEditMenu, event.GetPosition() )

        return
    
    #------------------------------------------------------------------
    def setupRecoElemEditMenu(self):
    #------------------------------------------------------------------
        self.recoElemEditMenu.Append( self.recoElemNewKidId,
                                      "New Sub Element", "New kid arg3" )
        EVT_MENU(self.parent, self.recoElemNewKidId, self.recoElemNewKid)
        #
        self.recoElemEditMenu.Append( self.recoElemCopyREBranchId,
                                      "Copy Tree Branch", "Copy Tree Branch" )
        EVT_MENU(self.parent, self.recoElemCopyREBranchId, self.recoElemCopyREBranch)
        #
        self.recoElemEditMenu.Append( self.recoElemCutREBranchId,
                                      "Cut Tree Branch", "Cut Tree Branch" )
        EVT_MENU(self.parent, self.recoElemCutREBranchId, self.recoElemCutREBranch)
        #
        self.recoElemEditMenu.Append( self.recoElemPasteREBranchId,
                                      "Paste Tree Branch", "Paste Tree Branch" )
        EVT_MENU(self.parent, self.recoElemPasteREBranchId, self.recoElemPasteREBranch)
        #
        # Rx related
        #

        #
        self.recoElemEditMenu.AppendSeparator()
        #

        self.recoElemEditMenu.Append( self.recoElemPasteRxId,
                                      "Paste Rx", "Add kid arg3" )
        EVT_MENU(self.parent, self.recoElemPasteRxId, self.recoElemPasteRx)
        #
        self.recoElemEditMenu.Append( self.recoElemPasteFromSelectedRxGridId,
                                      "Paste From Selected Rx Table", 
                                      "Paste From Selected Rx Table")
        EVT_MENU(self.parent, self.recoElemPasteFromSelectedRxGridId,
                 self.recoElemPasteFromSelectedRxGrid)
        #
        self.recoElemEditMenu.AppendSeparator()
        #
        self.recoElemEditMenu.Append( self.recoElemWriteToBssId,
                                      "Write to BSS",
                                      "Write to BSS")
        EVT_MENU(self.parent, self.recoElemWriteToBssId,
                 self.recoElemWriteToBss)
        

        #
        # plug-ins will be added beyond here via extendRecoElemEditMenu.
        #

        self.recoElemEditMenu.AppendSeparator()

        self.recoElemEditMenu.Append( self.recoElemVizWithCytoScapeId,
                                      "Visualize in CytoScape",
                                      "Visualize in CytoScape")
        EVT_MENU(self.parent, self.recoElemVizWithCytoScapeId,
                 self.recoElemVizWithCytoScape)

        return

    #------------------------------------------------------------------
    def extendRecoElemEditMenu(self, menuText, helpText,  handler):
    #------------------------------------------------------------------
        """
        Used for plugins.  Adds them to the RecoElemEditMenu

        @type menuText: string   The text to be shown in the menu.
        @type helpText: string   The help text for the item.
        @type handler:  function taking a RecoElem returning nothing.
        """

        theNewId = wxNewId()
        try:
            self._pluginDict[theNewId] = handler
        except LookupError:
            self.parent.error( "Program error extendRecoelemEditMenu: plugin not registerd")
            return

        self.recoElemEditMenu.Append( theNewId, menuText, helpText )
        EVT_MENU(self.parent, theNewId, self.pluginHandler)

        return
    
    #------------------------------------------------------------------
    def pluginHandler(self, event):
    #------------------------------------------------------------------
        """
        Dispatches a wxCommandEvent that arose from an EVT_MENU
        registration to the actual plugin.
        """

        if (self.selectedItem == None):
            self.parent.error( "Select a RecoElem first" )
            return
        
        # form the arg list to the plugin

        treeData = self.parent.tree_ctr.GetPyData( self.selectedItem)
        re = treeData.re

        ##
        # find and call the plugin
        #
        # this is a little wonky right now.  we'r exposing the execution
        # rules and have the config file hardwired.  its a start.  don't
        # copy this code.
        ##

        theModule = self._pluginDict[ event.GetId() ]
        mgr       = KahConfigMgr()

        mgr.newSection( theModule.name() )
        cfg = mgr.getSection( theModule.name() )
        theModule.config( cfg )
        print "h"
        cfg.dump()
        print "h"
        mgr.dump()
        mgr.loadConfigFile( "ModelEditor.cfg" )
        print "now"
        mgr.dump()
        theModule.process( re, cfg )
        theModule.finish( cfg )

        # the plugin may have changed the recoelem, so we have to
        # bring the display up to date.  this is really inefficient,
        # but we're going to destroy everything for the recoelem
        # and rebuilt from scratch to make sure we get it right.
        
        id=treeData.itemId
        self.parent.tree_ctr.DeleteChildren( id )
        self.parent.tree_ctr.Delete( id )
        parentId = self.parent.tree_ctr.GetItemParent( id )

        self.addRecoElemTree( parentId, re, treeData.ce )

        return

    #------------------------------------------------------------------
    def updateTreeBranchText(self, sourceRXNum, recoElemName):
    #------------------------------------------------------------------

        rxPrevName = self.parent.tree_ctr.GetItemText(self.selectedItem)
        newLabel = "(" + str(sourceRXNum) + "rx" ") " + recoElemName

        #sylistic purposes get rid of (0 rx) if it exist
        if newLabel[1] == '0':
            newLabel = newLabel[6:]
        

        self.parent.tree_ctr.SetItemText(self.selectedItem, newLabel)
        return
    
    #------------------------------------------------------------------
    def recoElemNewKid(self, event):
    #------------------------------------------------------------------
        if (self.selectedItem == None): return
        treeData = self.parent.tree_ctr.GetPyData( self.selectedItem)
        re = treeData.re
        
        prompt = "Name of new child for " + re.Name
        dlg = wxTextEntryDialog(self.parent, message=prompt, style=wxOK)

        if ( dlg.ShowModal() == wxID_OK):
            kidName = dlg.GetValue()
            if ( kidName=="" ): return
            dlg.Destroy()
        else:
            #didn't get a kid name
            dlg.Destroy()
            return

        newKid = RecoElem( kidName )
        re.SubElems.append( newKid )
        self.addRecoElemTree( self.selectedItem, newKid, treeData.ce)
        
        return
    
    #------------------------------------------------------------------
    def recoElemCopyREBranch(self, event):
    #------------------------------------------------------------------
        if (self.selectedItem == None): return
        self.cutOrCopiedRE   = self.selectedItem
        return

    #------------------------------------------------------------------
    def recoElemCutREBranch(self, event):
    #------------------------------------------------------------------
        if (self.selectedItem == None): return
        
        # first, modify the actual recoElem tree.
        parentItem   = self.parent.tree_ctr.GetItemParent(self.selectedItem)
        parentRe     = self.parent.tree_ctr.GetPyData( parentItem ).re
        selectedRe   = self.parent.tree_ctr.GetPyData(self.selectedItem ).re

        # if we have a parent, i.e., if we are not the top of the tree,
        # then remove ourself from our parents kid-list
        
        if (parentRe != None):
            parentRe.SubElems.remove( selectedRe )

        # this no longer points anyplace valid
        self.cutOrCopiedRE = None
        self.selectedItem == None
        
        # now modify the display
        self.parent.tree_ctr.Delete(self.selectedItem)
        return

    #------------------------------------------------------------------
    def recoElemPasteREBranch(self, event):
    #------------------------------------------------------------------
        if (self.selectedItem == None):
            self.parent.error( "Select a tree branch first as target.")
            return

        if (self.cutOrCopiedRE == None):
            self.parent.error( "Select and copy a tree branch first.")
            return

        reSource = self.parent.tree_ctr.GetPyData( self.cutOrCopiedRE ).re
        reTarget = self.parent.tree_ctr.GetPyData( self.selectedItem).re
        ceTarget = self.parent.tree_ctr.GetPyData( self.selectedItem).ce

        reSourceCopy = copy.deepcopy( reSource )
        reTarget.SubElems.append( reSourceCopy )

        self.addRecoElemTree( self.selectedItem, reSourceCopy, ceTarget )

        return

    #------------------------------------------------------------------
    def recoElemPasteRx(self, event):
    #------------------------------------------------------------------

        if ( None == self.selectedItem ): return
        if ( None == self.cutOrCopiedRx ): return
        
        
        re = self.parent.tree_ctr.GetPyData( self.selectedItem).re

        re.Reactions.append( self.cutOrCopiedRx )

        rxListNum = len(re.Reactions)
        
        self.updateTreeBranchText(rxListNum, re.Name)
        self.redrawRecoElemRxList(re)

        return


    #------------------------------------------------------------------
    def recoElemPasteFromSelectedRxGrid(self, event):
    #------------------------------------------------------------------
        if (self.selectedItem == None): return

        re = self.parent.tree_ctr.GetPyData( self.selectedItem).re

        rxList = self.parent.rx.getSelectedRx()
        rxListNum = len(re.Reactions)

        for rx in rxList:
            re.Reactions.append( rx )

        self.updateTreeBranchText(rxListNum, re.Name)
        self.redrawRecoElemRxList(re)
                
        return

    #------------------------------------------------------------------
    def recoElemVizWithCytoScape(self, event):
    #------------------------------------------------------------------
        if (self.selectedItem == None): return
        re = self.parent.tree_ctr.GetPyData( self.selectedItem).re

        # "not connectable" is for things like ATP that happen so much
        # that you can't just draw one node or you get a mess.  But cytoscape
        # SIF files uses "same name, same node."  So we're going to bump up
        # a counter every time we hit a not-connectible and tack it on the
        # end of the name.
        #
        nNotConnect = 0
        
        #
        # KEGG provides isConnected as an attribute of a reactant.  We're
        # going to try something here and ignore the isConnected int he
        # Reactant object and make our decions based upon the number of
        # edges coming into a reactant node in the full graph of the
        # system

        rxGraph = re.getGraph()
        thresh = 5


	allRxList = []
	re.gatherReactions( allRxList )

	output          = mktemp(suffix=".sif")
	nodeAttribs     = mktemp(suffix=".node")
        out_file        = open(output, "w")      # Create temporary
        nodeAttrib_file = open(nodeAttribs, "w")      # Create temporary
	print output, nodeAttribs

        nodeAttrib_file.write("NodeType\n")

	nRx = 0
	for r in allRxList:
	    nRx += 1
            rxKind="enzymatic"
            if (len(r.enzymeNames) > 0):
                enzName= r.enzymeNames[0]
                if (enzName == "spontaneous"): rxKind = "spontaneous"
                enzName.replace(' ', '_')
            else:
                enzName= ""
                rxKind="spontaneous"
            rxName = "Rx%d-%s" % ( nRx, enzName)
            nodeAttrib_file.write("%s = %s\n" % ( rxName, rxKind) )
            if (r.Direction == "forward"):
                edgeName = "ci"           # compound to irreversible rx
            else:
                edgeName = "cr"           # compound to reversible rx
	    for i in r.Inputs:
                if (not i.isConnected or (rxGraph.all_degree( i.Name) > thresh) ):
                    theName=i.Name.replace(' ','_')+ ":%d" % (nNotConnect)
                    nNotConnect += 1
                else:
                    theName=i.Name.replace(' ','_')
		out_file.write( "%s %s %s\n" % (theName, edgeName, rxName) )
                nodeAttrib_file.write("%s = reactant\n" % (theName) )

            for o in r.Outputs:
                if (not o.isConnected or (rxGraph.all_degree( o.Name)>thresh) ):
                    theName=o.Name.replace(' ','_')+ ":%d" % (nNotConnect)
                    nNotConnect += 1
                else:
                    theName=o.Name.replace(' ','_')
		out_file.write( "%s rc %s\n" % (rxName, theName))
                nodeAttrib_file.write("%s = reactant\n" % (theName) )

	out_file.close()
	cytoInstallDir = os.getenv( 'CYTOSCAPE_HOME' )
	cytoCmd        = os.getenv( 'CYTOSCAPE_COMMAND' )

        #cmd = "(cd $CYTOSCAPE_HOME; java -jar cytoscape.jar -i %s -n %s&)" % (output, nodeAttribs)
        cmd = "(cd %s; %s -i %s -n %s&)" % (cytoInstallDir, cytoCmd, output, nodeAttribs)
	print cytoInstallDir
	print cytoCmd
	print cmd

	os.system( cmd )

	#os.unlink( output )

	return

    #------------------------------------------------------------------
    def recoElemWriteToBss(self, event):
    #------------------------------------------------------------------
        # there are so many problems here it's not funny.  We _will_
        # corrupt the DB with this but have to start somewhere.  Example:
        # How do we know we've not been passed a REcoElem that is
        # owned by a higher entity?  The system needs to be extended to
        # understand the ownership model and catalog arch.

        if (self.selectedItem == None): return
        re = self.parent.tree_ctr.GetPyData( self.selectedItem).re
        catalogEntry = self.parent.tree_ctr.GetPyData( self.selectedItem).ce

        foundryItemKey = catalogEntry.write( re )

        if (foundryItemKey == None ):
            self.parent.error( "Write failed.")
        else:
            self.parent.error( "Write succeeded" )
        return

    #------------------------------------------------------------------
    def recoElemRxListCut(self, event):
    #------------------------------------------------------------------
    # this has gotta be wrong...what were we thinking?  It's ok for a
    # single selection.
    
        re = None
        for count in self.parent.list_box.GetSelections():
            (rx,offset, re) = self.parent.list_boxData[count]
            del( re.Reactions[offset:offset+1] )
            self.redrawRecoElemRxList(re)
            self.cutOrCopiedRx   = rx

        if (re == None):
            return
        else:
            rxListNum = len(re.Reactions)    
            self.updateTreeBranchText(rxListNum, re.Name)
        
        return

    #------------------------------------------------------------------
    def recoElemRxListCopy(self, event):
    #------------------------------------------------------------------
        for count in self.parent.list_box.GetSelections():
            (rx,offset,re) = self.parent.list_boxData[count]
            self.cutOrCopiedRx   = rx

        return    

    #------------------------------------------------------------------
    def recoElemRxListPaste(self, event):
    #------------------------------------------------------------------
        # we're pasting into a list_box.  This list box is being
        # shown *because* a recoElem has been selected.  that means
        # _it_ is the recoElem to modify.

        #since the listbox is only allowing single select.
        #we won't count how big the selection is

        if (self.selectedItem == None): return
        re = self.parent.tree_ctr.GetPyData( self.selectedItem).re
        re.Reactions.append( self.cutOrCopiedRx )

        rxListNum = len(re.Reactions)
        self.updateTreeBranchText(rxListNum, re.Name)
        self.redrawRecoElemRxList(re)

        return    

MCS Webmaster
ViewVC Help
Powered by ViewVC 1.0.3