def adjustTokens(self, transitionItemObject, acquired, emitted): preserved = {} emittedNames = {} for tokenName in emitted.keys(): emittedNames[tokenName] = tokenName for token in acquired: if not token.getName() in emittedNames: self.petriNet.getTokenList().remove(token) else: preserved[token.getName()] = token token.setProperty("prevTransition", self.getName()) # create or re-emit the required number of tokens with inherited or transition specified properties for stateName in emittedNames.keys(): if not stateName in preserved: properties = {} properties["prevTransition"] = self.getName() tokenSpec = emitted[stateName] for i in xrange(tokenSpec[1]): token = Token(stateName, properties, None) self.petriNet.getTokenList().addToken(token) # implies unlock properties = {} tokens = self.petriNet.getTokenList().getTokensByOwnerAndSpec( stateName, transitionItemObject, properties, lockedState=True ) properties = emitted[stateName][0] for prop, value in properties.items(): for token in tokens: token.setProperty(prop, value)
def IsEnabled(self, tokenList): # First get common properties across required tokens commonValuesByTokenName = {} for transitionProperty in self.properties.keys(): commonValuesByTokenName[transitionProperty] = {} for reqTokenName, tokenSpec in self.requiredTokensByState.items(): tokensAvailable = 0 numRequired = tokenSpec[1] if reqTokenName in tokenList.list: tokens = tokenList.getTokensByOwnerAndSpec( reqTokenName, transitionOwnerObject=None, properties=tokenSpec[0], lockedState=False ) for token in tokens: tokensAvailable += 1 for transitionPropertyName in self.properties.keys(): if transitionPropertyName in token.getProperties(): if not token.getName() in commonValuesByTokenName[transitionPropertyName]: commonValuesByTokenName[transitionPropertyName][token.getName()] = [] commonValuesByTokenName[transitionPropertyName][token.getName()].append( token.getProperty(transitionPropertyName) ) if tokensAvailable < numRequired: utils.log("Cannot run " + self.getName() + " because not enough " + reqTokenName + "'s available.'") return False, {} else: utils.log("Cannot run " + self.getName() + " because token " + reqTokenName + " not available.") return False, {} # So commonValuesByTokenName is owned by the transitionItem and manages the properties that it cares about. # For each one of these properties, it contains a list of all of its required tokens and the values of that property # across those tokens. The idea is that the transition can specify that for a given property if the tokens available # contain that property then their values must match. For example, if the "dosing" transition requires an "assay plate" # and a "source plate" token then it may require that the common assay plate barcode be the same in both tokens for # those tokens to be acquired by the instance of the transition. intersections = {} intersect = [] for transitionPropertyName in commonValuesByTokenName.keys(): prev = [] req = ["any"] if transitionPropertyName in self.properties and self.properties[transitionPropertyName] != None: req = self.properties[transitionPropertyName] if transitionPropertyName == "prevTransition" and "prevTransition" in self.properties: prev = prev + self.properties["prevTransition"] if "any" in req: intersections[transitionPropertyName] = intersect for tokenName in commonValuesByTokenName[transitionPropertyName].keys(): current = commonValuesByTokenName[transitionPropertyName][tokenName] if len(prev) > 0 and len(current) > 0: intersect = [val for val in prev if val in current] if len(intersect) == 0: utils.log( "Cannot run " + self.getName() + " because no matching on " + transitionPropertyName + " for " + tokenName ) return False, {} prev = intersect else: prev = current intersect = current intersections[transitionPropertyName] = intersect for tokenName in intersections.keys(): valueList = intersections[tokenName] # We may have found more than one set of common property values. Choose one set only. intersections[tokenName] = [valueList[0]] # Choose single member of overlap utils.log("Candidate " + self.getName() + " intersection " + repr(intersections)) return True, intersections