Package TEES :: Package Utils :: Package STFormat :: Module Equiv
[hide private]

Source Code for Module TEES.Utils.STFormat.Equiv

  1  from STTools import * 
  2  import Validate 
  3  thisPath = os.path.dirname(os.path.abspath(__file__)) 
  4  sys.path.append(os.path.abspath(os.path.join(thisPath,"../.."))) 
  5  import Utils.Libraries.combine as combine 
  6  import copy 
  7   
8 -def process(documents, debug=False):
9 """ 10 Resolves equivalences in place 11 """ 12 numOldEvents = 0 13 numNewEvents = 0 14 for doc in documents: 15 #if doc.id != "PMC-2806624-00-TIAB": 16 # continue 17 if debug: 18 print "Document:", doc.id 19 numOldEvents += len(doc.events) 20 # Get all top-level events 21 rootEvents = getRoots(doc) 22 # Build new top level events 23 newEvents = [] 24 # The same event that needs to be duplicated can be nested in several trees 25 # The duplDict makes sure that duplicates are generated only once, and shared 26 # between trees. 27 duplDict = {} 28 for rootEvent in rootEvents: 29 newEvents.extend(duplicateEquiv(rootEvent, duplDict, debug)) 30 # Regenerate the flat event list in the document 31 doc.events = rebuildEventList(newEvents) 32 doc.events.sort(key = lambda x: (x.id[0], int(x.id[1:].split(".")[0]), x.id[1:].split(".")[-1]) ) 33 numNewEvents += len(doc.events) 34 print >> sys.stderr, "Duplication created", numNewEvents - numOldEvents, "new events (new total", numNewEvents, "events)"
35
36 -def getRoots(document):
37 """ 38 Returns topmost events in event hierarchy 39 """ 40 eventDict = {} 41 for event in document.events: 42 eventDict[event.id] = event 43 for event in document.events: 44 for arg in event.arguments: 45 if arg[1].id[0] == "E": # arg[1] is a nested event... 46 if arg[1].id in eventDict: # ...if it hasn't been already removed... 47 del eventDict[arg[1].id] # ...remove it 48 rootEvents = [] 49 for key in sorted(eventDict.keys()): 50 rootEvents.append(eventDict[key]) 51 return rootEvents
52
53 -def getArgs(event, argList):
54 """ 55 Return the arguments of a nested event tree in a depth-first order. 56 Each argument is in a list, and has multiple items if that argument 57 is a protein with Equivs. 58 """ 59 hasEquiv = False 60 for arg in event.arguments: 61 if len(arg[1].equiv) == 0: 62 argList.append([arg[1]]) 63 else: 64 hasEquiv = True 65 argList.append([arg[1]] + arg[1].equiv) 66 assert arg[1] not in arg[1].equiv 67 if arg[1].id[0] == "E": # nested event 68 assert len(arg[1].equiv) == 0 69 if hasNestedEquivs(arg[1]): 70 rv = getArgs(arg[1], argList) 71 hasEquiv = rv or hasEquiv 72 else: 73 pass # stop recursion 74 return hasEquiv
75
76 -def hasNestedEquivs(event):
77 rv = False 78 for arg in event.arguments: 79 if len(arg[1].equiv) != 0: 80 rv = True 81 elif arg[1].id[0] == "E": # nested event 82 rv = rv or hasNestedEquivs(arg[1]) 83 return rv
84
85 -def makeEvent(model, argCombination, count, newEvent = None, finished=False, duplDict=None, debug=False, level=0):
86 """ 87 Given an argument list in depth-first order (argCombination), make 88 a copy of "model" event tree. 89 """ 90 createdEvents = [] 91 if newEvent == None: # First call, make a new root 92 if debug: 93 print "Arg.Comb.:", argCombination 94 #print "Mak", argCombination 95 newEvent = Annotation() 96 newEvent.trigger = model.trigger 97 newEvent.type = model.type 98 newEvent.id = model.id + ".d" + str(count) 99 newEvent.speculation = model.speculation 100 newEvent.negation = model.negation 101 createdEvents.append(newEvent) 102 for arg in model.arguments: 103 #if debug: print level * " ", model.id, [x[1].id for x in model.arguments], "/", arg[1].id, argCombination, "/", newEvent, newEvent.arguments 104 if arg[1].id[0] != "E": # not a nested event 105 # Non-event arguments never need to be duplicated 106 if not finished: 107 newEvent.arguments.append([arg[0], argCombination[0], arg[2]]) 108 argCombination.pop(0) # pop first (depth-first iteration) 109 if debug: print level * " ", "SIMP", model.id, [x[1].id for x in model.arguments], "/", arg[1].id, argCombination, "/", newEvent, newEvent.arguments 110 else: # is a nested event 111 assert arg[2] == None, (model.id, arg) 112 if not finished: 113 if hasNestedEquivs(arg[1]): 114 # For event arguments that have children with equiv, create a new copy 115 duplId = arg[1].id + ".d" + str(count) 116 #duplId = arg[1].id.split(".d")[0] + ".d" + str(count) 117 if duplId not in duplDict: 118 newArg = [arg[0], copy.copy(argCombination[0]), None] # Make a new event 119 createdEvents.append(newArg[1]) 120 argCombination.pop(0) # pop first (depth-first iteration) 121 newArg[1].arguments = [] # reset the argument list of the copy 122 newArg[1].id = duplId 123 newEvent.arguments.append(newArg) # add to parent copy 124 duplDict[duplId] = newArg[1] # add the new event to duplDict #duplDict[duplId] = newArg 125 if debug: print level * " ", "NEST(new)", model.id, [x[1].id for x in model.arguments], "/", arg[1].id, argCombination, "/", newEvent, newEvent.arguments 126 createdEvents += makeEvent(arg[1], argCombination, count, newArg[1], finished, duplDict, level=level+1, debug=debug) # Continue processing with next level of model and copy 127 else: 128 newArg = [arg[0], duplDict[duplId], None] 129 argCombination.pop(0) # pop first (depth-first iteration) 130 #newEvent.arguments.append(duplDict[duplId]) # add to parent copy 131 newEvent.arguments.append(newArg) # add to parent copy 132 if debug: print level * " ", "NEST(old)", model.id, [x[1].id for x in model.arguments], "/", arg[1].id, argCombination, "/", newEvent, newEvent.arguments 133 #makeEvent(arg[1], argCombination, count, duplDict[duplId][1], True, duplDict, level=level+1, debug=debug) # Continue processing with next level of model and copy 134 createdEvents += makeEvent(arg[1], argCombination, count, duplDict[duplId], True, duplDict, level=level+1, debug=debug) # Continue processing with next level of model and copy 135 else: 136 newArg = [arg[0], argCombination[0], None] 137 argCombination.pop(0) # pop first (depth-first iteration) 138 newEvent.arguments.append(newArg) # add to parent copy 139 if debug: print level * " ", "STOP", model.id, [x[1].id for x in model.arguments], "/", arg[1].id, argCombination, "/", newEvent, newEvent.arguments 140 # stop recursion here, it has been likewise stopped in getArgs 141 #makeEvent(arg[1], argCombination, count, newArg[1], True, duplDict, level=level+1) # Continue processing with next level of model and copy 142 return createdEvents
143
144 -def duplicateEquiv(event, duplDict, debug):
145 """ 146 If the event (event tree) has arguments which have Equiv-statements, create a new event 147 for each combination. Otherwise, return just the existing event. 148 """ 149 argList = [] # depth-first argument list 150 hasEquiv = getArgs(event, argList) 151 if not hasEquiv: 152 return [event] 153 if debug: 154 print "----------------------------------------------" 155 print "Event:", event.id, event.type, event.arguments 156 print " Orig. Duplicates:", argList 157 combinations = combine.combine(*argList) # make all combinations 158 if debug: 159 print " Dup. Combinations:", combinations 160 newEvents = [] 161 count = 0 # used only for marking duplicates' ids 162 for combination in combinations: 163 createdEvents = makeEvent(event, combination, count, duplDict=duplDict, debug=debug) 164 newEvent = createdEvents[0] 165 if debug: 166 for createdEvent in createdEvents: 167 if createdEvent == newEvent: 168 print " New Event (root):", createdEvent.id, createdEvent.type, createdEvent.arguments 169 else: 170 print " New Event:", createdEvent.id, createdEvent.type, createdEvent.arguments 171 Validate.validate([createdEvent], simulation=True) 172 newEvents.append(newEvent) 173 count += 1 174 return newEvents
175
176 -def rebuildEventList(events, eventList = None):
177 """ 178 Add all events (top and nested) from event trees to a list. 179 """ 180 if eventList == None: 181 eventList = [] 182 for event in events: 183 if event not in eventList: 184 eventList.append(event) 185 for arg in event.arguments: 186 if arg[1].id[0] == "E": 187 rebuildEventList([arg[1]], eventList) 188 return eventList
189 190 if __name__=="__main__": 191 import sys 192 from optparse import OptionParser 193 # Import Psyco if available 194 try: 195 import psyco 196 psyco.full() 197 print >> sys.stderr, "Found Psyco, using" 198 except ImportError: 199 print >> sys.stderr, "Psyco not installed" 200 201 optparser = OptionParser(description="Resolve annotated equivalences") 202 optparser.add_option("-i", "--input", default=None, dest="input", help="", metavar="FILE") 203 optparser.add_option("-o", "--output", default=None, dest="output", help="") 204 optparser.add_option("-d", "--debug", default=False, action="store_true", dest="debug", help="") 205 (options, args) = optparser.parse_args() 206 207 print >> sys.stderr, "Loading documents from", options.input 208 documents = loadSet(options.input) 209 print >> sys.stderr, "Resolving equivalences" 210 process(documents, debug=options.debug) 211 print >> sys.stderr, "Writing documents to", options.output 212 writeSet(documents, options.output, validate=False) 213