Exemple #1
0
    def pseudoevent(self, score=True, update=True):
        """Called once per pseudoevent.

        If 'score' is True, run the consumer algorithm.
        If 'update' is True, run the producer algorithm.
        """

        self.pseudoEventNumber += 1
        outputRecord = OutputRecord(self.pseudoEventNumber,
                                    SELECTALL,
                                    pseudo=True)

        for segment in self.segmentRecords:
            currentContext = segment.pmmlModel.dataContext
            while not isinstance(currentContext, pmml.DataContext):
                currentContext.clear()
                currentContext = currentContext.parentContext
            currentContext.clear()

            groupsToKeys = {}
            for aggregate in segment.aggregates:
                groupName = aggregate.groupField
                if groupName is not None and groupName not in groupsToKeys:
                    # find aggregates for this segment
                    groupsToKeys[groupName] = aggregate.updators.keys()

            outputSegment = OutputSegment(segment)
            if len(groupsToKeys) == 0:
                if score:
                    if segment.state() is MATURE or segment.state() is LOCKED:
                        scores = segment.consumerAlgorithm.score(
                            self.pseudoEventNumber,
                            segment.pmmlModel.dataContext.get)
                    else:
                        scores = IMMATURE
                else:
                    scores = INVALID

                if segment.pmmlOutput is not None:
                    outputSegment.fields = segment.pmmlOutput.evaluate(
                        segment.pmmlModel.dataContext.get, scores)

                if update and segment.state() is not LOCKED:
                    self.updateSegment(segment, pseudoEvent=True)

            else:
                groupFields = groupsToKeys.keys()
                groupFields.sort()
                for groupField in groupFields:
                    groupValues = groupsToKeys[groupField]
                    for value in groupValues:
                        segment.pmmlModel.dataContext.setOverride(
                            {groupField: value}, False)
                        if score:
                            if segment.state() is MATURE or segment.state(
                            ) is LOCKED:
                                scores = segment.consumerAlgorithm.score(
                                    self.pseudoEventNumber,
                                    segment.pmmlModel.dataContext.get)
                            else:
                                scores = IMMATURE
                        else:
                            scores = INVALID
                        outputMiniEvent = OutputMiniEvent()
                        if segment.pmmlOutput is not None:
                            outputMiniEvent.fields = segment.pmmlOutput.evaluate(
                                segment.pmmlModel.dataContext.get, scores)

                        segment.pmmlModel.dataContext.releaseOverride()

                        if segment.consumerAlgorithm.pseudoOutputAll:
                            outputSegment.minievents.append(outputMiniEvent)

                    if not segment.consumerAlgorithm.pseudoOutputAll:
                        outputSegment.minievents.append(outputMiniEvent)

                    if update and segment.state() is not LOCKED:
                        self.updateSegment(segment, pseudoEvent=True)

            outputRecord.segments.append(outputSegment)

            # clear all of the aggregates
            for aggregate in segment.aggregates:
                aggregate.flush()

        return outputRecord
Exemple #2
0
    def event(self,
              score=True,
              update=True,
              explicitSegments=None,
              predictedName=None):
        """Called once per event.

        If 'score' is True, run the consumer algorithm.
        If 'update' is True, run the producer algorithm.
        If 'explicitSegments' is a list of SegmentRecords, use these segments instead of finding the right ones.
        If 'predictedName' is a string, use this instead of what Output requires (for the case of no Output block).
        """

        logInfo = self.logger.getEffectiveLevel() <= logging.INFO
        logDebug = self.logger.getEffectiveLevel() <= logging.DEBUG

        # increment the data stream
        self.eventNumber += 1
        if logDebug:
            self.logger.debug("========== Starting event %d" %
                              self.eventNumber)
        elif self.eventNumber % 1000 == 0:
            self.logger.info("========== Starting event %d" % self.eventNumber)

        self.metadata.startTiming("Time to advance through data")
        self.dataStream.next()
        self.metadata.stopTiming("Time to advance through data")

        self.logger.debug("Loaded a record from the data stream.")

        # update the PMML's header
        self.eventStamp.attrib["number"] = self.eventNumber
        self.timeStamp.children[0].text = [
            datetime.datetime.today().isoformat()
        ]

        # find the matching segments
        if explicitSegments is None:
            segmentMatches = []
            self.metadata.startTiming("Time searching for blacklisted items")
            blacklisted = self.segmentationScheme.blacklisted(
                self.pmmlModel.dataContext.get)
            self.metadata.stopTiming("Time searching for blacklisted items")

            if not blacklisted:
                self.metadata.startTiming("Time to look up existing segments")
                matchCandidates = self._getMatchCandidates()
                if self.multipleModelMethod is SELECTFIRST:

                    for index in matchCandidates:
                        segmentRecord = self.segmentRecords[index]
                        if segmentRecord.predicateMatches(
                                self.pmmlModel.dataContext.get):
                            segmentMatches = [segmentRecord]
                            break

                elif self.multipleModelMethod is SELECTALL:
                    segmentMatches = [
                        self.segmentRecords[index] for index in matchCandidates
                        if self.segmentRecords[index].predicateMatches(
                            self.pmmlModel.dataContext.get)
                    ]

                elif self.multipleModelMethod is SELECTONLY:
                    segmentMatches = [self.segmentRecords[0]]

                self.metadata.stopTiming("Time to look up existing segments")

                if len(segmentMatches) == 0:
                    self.metadata.startTiming(
                        "Time to find and create new PMML segments")
                    match = self.segmentationScheme.getMatch(
                        self.pmmlModel.dataContext.get)
                    self.metadata.stopTiming(
                        "Time to find and create new PMML segments")

                    if not match:
                        if logInfo:
                            self.logger.info(" ".join([
                                "Event %d did not match any segment descriptions; discarding."
                                % self.eventNumber,
                                "Data=%s" %
                                self.pmmlModel.dataContext.contextString()
                            ]))

                    else:
                        match = self._makeSegmentRecord(match,
                                                        autoSegment=True)
                        segmentMatches.append(match)
            else:
                if logInfo:
                    self.logger.info(" ".join([
                        "Event %d matches a user blacklisted item, and will be ignored."
                        % self.eventNumber,
                        "Data=%s" % self.pmmlModel.dataContext.contextString()
                    ]))

        else:
            segmentMatches = explicitSegments

        syncNumberSource = getattr(self.consumerUpdateScheme, "timeFieldName",
                                   None)
        if syncNumberSource is None:
            syncNumber = self.eventNumber
        else:
            syncNumber = self.pmmlModel.dataContext.get(syncNumberSource)

        # possibly do custom processing
        if self.customProcessing is not None:
            self.metadata.startTiming("Score calculation, total")

            matchingSegments = [s.userFriendly for s in segmentMatches]
            if logDebug:
                self.logger.debug(
                    "About to enter customProcessing.doEvent() for event %d." %
                    self.eventNumber)
            output = self.customProcessing.doEvent(
                syncNumber, self.eventNumber, self.pmmlModel.dataContext.get,
                matchingSegments)
            if logDebug:
                self.logger.debug("Finished customProcessing.doEvent().")

            for segmentMatch in segmentMatches:
                segmentMatch.pmmlModel.dataContext.clear()
            self.pmmlModel.dataContext.clear()

            self.metadata.stopTiming("Score calculation, total")
            return output

        # run the algorithms and create the output
        self.metadata.startTiming("Score calculation, total")
        outputRecord = OutputRecord(self.eventNumber, self.multipleModelMethod)

        ### big loop over segmentMatches
        for segmentMatch in segmentMatches:

            for l in self.logger, self.metadata:
                if "segment" in l.differentLevel:
                    seglevels = l.differentLevel["segment"]
                    segname = segmentMatch.name()
                    if segname in seglevels:
                        l.setLevel(seglevels[segname])
                    else:

                        l.setLevel(l.eventLogLevel)
                else:
                    l.setLevel(l.eventLogLevel)
            logInfo = self.logger.getEffectiveLevel() <= logging.INFO
            logDebug = self.logger.getEffectiveLevel() <= logging.DEBUG

            if logDebug:
                self.logger.debug(
                    "Segment %s (%s) matched in event %d." %
                    (segmentMatch.name(), segmentMatch.expressionTree,
                     self.eventNumber))

            if syncNumberSource is not None:
                syncNumber = segmentMatch.pmmlModel.dataContext.get(
                    syncNumberSource)

            for aggregate in segmentMatch.aggregates:
                aggregate.increment(syncNumber,
                                    segmentMatch.pmmlModel.dataContext.get)

            if score and segmentMatch.pmmlModel.isScorable:
                if segmentMatch.state() is MATURE or segmentMatch.state(
                ) is LOCKED:
                    if logDebug:
                        self.logger.debug(
                            "About to enter consumerAlgorithm.score() for event %d, segment %s."
                            % (self.eventNumber, segmentMatch.name()))
                    scores = segmentMatch.consumerAlgorithm.score(
                        syncNumber, segmentMatch.pmmlModel.dataContext.get)
                    if logDebug:
                        self.logger.debug(
                            "Finished consumerAlgorithm.score().")
                else:
                    scores = IMMATURE
            else:
                scores = INVALID

            outputSegment = OutputSegment(segmentMatch)

            # override Output block
            if predictedName is not None:
                if scores is INVALID or scores is IMMATURE:
                    outputSegment.fields = [(predictedName, scores)]
                elif scores is None:
                    outputSegment.fields = [(predictedName, MISSING)]
                else:
                    outputSegment.fields = [
                        (predictedName,
                         scores.get(pmml.OutputField.predictedValue, MISSING))
                    ]

            # use Output block
            elif segmentMatch.pmmlOutput is not None:
                outputSegment.fields = segmentMatch.pmmlOutput.evaluate(
                    segmentMatch.pmmlModel.dataContext.get, scores)

            outputRecord.segments.append(outputSegment)

            if update and segmentMatch.state() is not LOCKED:
                if logDebug:
                    self.logger.debug(
                        "About to enter producerAlgorithm.update() for event %d, segment %s."
                        % (self.eventNumber, segmentMatch.name()))
                self.updateSegment(segmentMatch)
                if logDebug:
                    self.logger.debug("Finished producerAlgorithm.update().")

            # clear the cache of each of the segment DataContexts
            segmentMatch.pmmlModel.dataContext.clear()

        # END big loop over segmentMatches

        for l in self.logger, self.metadata:
            l.setLevel(l.eventLogLevel)

        self.pmmlModel.dataContext.clear()

        self.metadata.stopTiming("Score calculation, total")
        return outputRecord
Exemple #3
0
def verify(modelVerificationConfig, engine, logger, outputWriter):
    modelsWithVerification = []

    if modelVerificationConfig.attrib.get("checkModel", True):
        if engine.pmmlModel.exists(pmml.ModelVerification):
            engine.pmmlModel.segmentRecord = None
            modelsWithVerification.append(engine.pmmlModel)

    if modelVerificationConfig.attrib.get("checkSegments", True):
        for segment in engine.segmentRecords:
            if segment.pmmlModel.exists(pmml.ModelVerification):
                segment.pmmlModel.segmentRecord = segment

                if segment.pmmlModel not in modelsWithVerification:
                    modelsWithVerification.append(segment.pmmlModel)

    haltOnFailures = (modelVerificationConfig.attrib.get("onFailures", "halt") == "halt")
    reportInScores = modelVerificationConfig.attrib.get("reportInScores", False)

    for model in modelsWithVerification:
        logger.info("Evaluating ModelVerification in model %s%s." % (model.tag, model.fileAndLine()))

        for verificationBlockCounter, verification in enumerate(model.matches(pmml.ModelVerification)):
            verification.initialize()

            # the verificaiton block acts as a fake data stream
            engine.resetDataStream(verification)

            segmentRecord = model.segmentRecord
            while True:
                try:
                    if segmentRecord is None:
                        outputRecord = engine.event(score=True, update=False, explicitSegments=None, predictedName=verification.predictedName)
                    else:
                        outputRecord = engine.event(score=True, update=False, explicitSegments=[segmentRecord], predictedName=verification.predictedName)

                    if len(outputRecord.segments) == 0:
                        results = [(f, MISSING) for f in verification.predicted]
                    else:
                        results = outputRecord.segments[0].fields

                    if reportInScores and outputWriter:
                        verificationErrorsBlock = OutputRecord(outputRecord.eventNumber, SELECTONLY)
                        verificationErrorsSegment = OutputSegment(None)
                        verificationErrorsBlock.segments = [verificationErrorsSegment]

                    for name, resultValue in results:
                        if name in verification.column:
                            expectedValue = verification.get(name)

                            if isinstance(resultValue, (float, int, long)):
                                try:
                                    expectedValue = float(expectedValue)
                                except AttributeError:
                                    verified = False
                                else:
                                    zeroThreshold = verification.zeroThreshold[name]

                                    if abs(expectedValue) <= zeroThreshold:
                                        verified = (abs(resultValue) <= zeroThreshold)

                                    else:
                                        precision = verification.precision[name]
                                        verified = ((expectedValue * (1. - precision)) <= resultValue <= (expectedValue * (1. + precision)))

                            else:
                                verified = (expectedValue == resultValue)

                            if not verified:
                                modelName = model.attrib.get("modelName", None)
                                if modelName is not None:
                                    modelName = ", modelName \"%s\"" % modelName
                                else:
                                    modelName = ""

                                errorString = "Verification failure in ModelVerification %d%s in model %s%s%s, row %d (\"<%s>\"): %s (\"%s\") expected to be %s, calculated to be %s" % (verificationBlockCounter, verification.fileAndLine(), model.tag, model.fileAndLine(), modelName, verification.table.index, verification.table.rows[verification.table.index].content(), name, verification.column[name], str(expectedValue), str(resultValue))

                                if haltOnFailures:
                                    raise ModelVerificationError, errorString
                                else:
                                    logger.error(errorString)
                                    if reportInScores and outputWriter:
                                        verificationErrorsSegment.fields.append((name, resultValue))

                    if reportInScores and outputWriter:
                        eventTags = [("model", "%s on line %s" % (model.tag, str(getattr(model, "lineStart", "unknown"))))]
                        modelName = model.attrib.get("modelName", None)
                        if modelName is not None:
                            eventTags.append(("modelName", modelName))
                        eventTags.append(("block", str(verificationBlockCounter)))

                        outputWriter.write(verificationErrorsBlock, eventTags=eventTags, eventName="ModelVerificationFailures")

                except StopIteration:
                    break
        
        logger.info("Done with ModelVerification in model %s%s." % (model.tag, model.fileAndLine()))
Exemple #4
0
    def pseudoevent(self, score=True, update=True):
        """Called once per pseudoevent.

        If 'score' is True, run the consumer algorithm.
        If 'update' is True, run the producer algorithm.
        """

        self.pseudoEventNumber += 1
        outputRecord = OutputRecord(self.pseudoEventNumber, SELECTALL, pseudo=True)

        for segment in self.segmentRecords:
            currentContext = segment.pmmlModel.dataContext
            while not isinstance(currentContext, pmml.DataContext):
                currentContext.clear()
                currentContext = currentContext.parentContext
            currentContext.clear()

            groupsToKeys = {}
            for aggregate in segment.aggregates:
                groupName = aggregate.groupField
                if groupName is not None and groupName not in groupsToKeys:
                    # find aggregates for this segment
                    groupsToKeys[groupName] = aggregate.updators.keys()

            outputSegment = OutputSegment(segment)
            if len(groupsToKeys) == 0:
                if score:
                    if segment.state() is MATURE or segment.state() is LOCKED:
                        scores = segment.consumerAlgorithm.score(self.pseudoEventNumber, segment.pmmlModel.dataContext.get)
                    else:
                        scores = IMMATURE
                else:
                    scores = INVALID

                if segment.pmmlOutput is not None:
                    outputSegment.fields = segment.pmmlOutput.evaluate(segment.pmmlModel.dataContext.get, scores)

                if update and segment.state() is not LOCKED:
                    self.updateSegment(segment, pseudoEvent=True)

            else:
                groupFields = groupsToKeys.keys()
                groupFields.sort()
                for groupField in groupFields:
                    groupValues = groupsToKeys[groupField]
                    for value in groupValues:
                        segment.pmmlModel.dataContext.setOverride({groupField: value}, False)
                        if score:
                            if segment.state() is MATURE or segment.state() is LOCKED:
                                scores = segment.consumerAlgorithm.score(self.pseudoEventNumber, segment.pmmlModel.dataContext.get)
                            else:
                                scores = IMMATURE
                        else:
                            scores = INVALID
                        outputMiniEvent = OutputMiniEvent()
                        if segment.pmmlOutput is not None:
                            outputMiniEvent.fields = segment.pmmlOutput.evaluate(segment.pmmlModel.dataContext.get, scores)

                        segment.pmmlModel.dataContext.releaseOverride()

                        if segment.consumerAlgorithm.pseudoOutputAll:
                            outputSegment.minievents.append(outputMiniEvent)

                    if not segment.consumerAlgorithm.pseudoOutputAll:
                        outputSegment.minievents.append(outputMiniEvent)

                    if update and segment.state() is not LOCKED:
                        self.updateSegment(segment, pseudoEvent=True)

            outputRecord.segments.append(outputSegment)

            # clear all of the aggregates
            for aggregate in segment.aggregates:
                aggregate.flush()

        return outputRecord
Exemple #5
0
    def event(self, score=True, update=True, explicitSegments=None, predictedName=None):
        """Called once per event.

        If 'score' is True, run the consumer algorithm.
        If 'update' is True, run the producer algorithm.
        If 'explicitSegments' is a list of SegmentRecords, use these segments instead of finding the right ones.
        If 'predictedName' is a string, use this instead of what Output requires (for the case of no Output block).
        """

        # increment the data stream
        self.eventNumber += 1
        self.metadata.startTiming("Time to advance through data")
        self.dataStream.next()
        self.metadata.stopTiming("Time to advance through data")

        # update the PMML's header
        self.eventStamp.attrib["number"] = self.eventNumber
        self.timeStamp.children[0].text = [datetime.datetime.today().isoformat()]

        # find the matching segments
        if explicitSegments is None:
            segmentMatches = []
            self.metadata.startTiming("Time searching for blacklisted items")
            blacklisted = self.segmentationScheme.blacklisted(self.pmmlModel.dataContext.get)
            self.metadata.stopTiming("Time searching for blacklisted items")

            if not blacklisted:
                self.metadata.startTiming("Time to look up existing segments")
                matchCandidates = self._getMatchCandidates()
                if self.multipleModelMethod is SELECTFIRST:

                    for index in matchCandidates:
                        segmentRecord = self.segmentRecords[index]
                        if segmentRecord.predicateMatches(self.pmmlModel.dataContext.get):
                            segmentMatches = [segmentRecord]
                            break

                elif self.multipleModelMethod is SELECTALL:
                    segmentMatches = [
                        self.segmentRecords[index] for index in matchCandidates if
                        self.segmentRecords[index].predicateMatches(self.pmmlModel.dataContext.get)]

                elif self.multipleModelMethod is SELECTONLY:
                    segmentMatches = [self.segmentRecords[0]]

                self.metadata.stopTiming("Time to look up existing segments")

                if len(segmentMatches) == 0:
                    self.metadata.startTiming("Time to find and create new PMML segments")
                    match = self.segmentationScheme.getMatch(self.pmmlModel.dataContext.get)
                    self.metadata.stopTiming("Time to find and create new PMML segments")

                    if not match:
                        if self.logInfo:
                            self.logger.info(" ".join([
                                "Event %d did not match any segment descriptions; discarding." % self.eventNumber,
                                "Data=%s" % self.pmmlModel.dataContext.contextString() ]))

                    else:
                        match = self._makeSegmentRecord(match, autoSegment=True)
                        segmentMatches.append(match)
            else:
                if self.logInfo:
                    self.logger.info(" ".join([
                        "Event %d matches a user blacklisted item, and will be ignored." % self.eventNumber,
                        "Data=%s" % self.pmmlModel.dataContext.contextString() ]))

        else:
            segmentMatches = explicitSegments

        # run the algorithms and create the output
        self.metadata.startTiming("Score calculation, total")
        outputRecord = OutputRecord(self.eventNumber, self.multipleModelMethod)
        for segmentMatch in segmentMatches:
            if self.logDebug:
                self.logger.debug("Segment %s matched." % segmentMatch.expressionTree)

            syncNumberSource = getattr(self.consumerUpdateScheme, "timeFieldName", None)
            if syncNumberSource is None:
                syncNumber = self.eventNumber
            else:
                syncNumber = segmentMatch.pmmlModel.dataContext.get(syncNumberSource)

            for aggregate in segmentMatch.aggregates:
                aggregate.increment(syncNumber, segmentMatch.pmmlModel.dataContext.get)

            if score and segmentMatch.pmmlModel.isScorable:
                if segmentMatch.state() is MATURE or segmentMatch.state() is LOCKED:

                    scores = segmentMatch.consumerAlgorithm.score(syncNumber, segmentMatch.pmmlModel.dataContext.get)
                else:
                    scores = IMMATURE
            else:
                scores = INVALID

            outputSegment = OutputSegment(segmentMatch)

            # override Output block
            if predictedName is not None:
                if scores is INVALID or scores is IMMATURE:
                    outputSegment.fields = [(predictedName, scores)]
                elif scores is None:
                    outputSegment.fields = [(predictedName, MISSING)]
                else:
                    outputSegment.fields = [(predictedName, scores.get(pmml.OutputField.predictedValue, MISSING))]

            # use Output block
            elif segmentMatch.pmmlOutput is not None:
                outputSegment.fields = segmentMatch.pmmlOutput.evaluate(segmentMatch.pmmlModel.dataContext.get, scores)

            outputRecord.segments.append(outputSegment)

            if update and segmentMatch.state() is not LOCKED:
                self.updateSegment(segmentMatch)

            # clear the cache of each of the segment DataContexts
            segmentMatch.pmmlModel.dataContext.clear()
        self.pmmlModel.dataContext.clear()

        self.metadata.stopTiming("Score calculation, total")
        return outputRecord
Exemple #6
0
    def event(self, score=True, update=True, explicitSegments=None, predictedName=None):
        """Called once per event.

        If 'score' is True, run the consumer algorithm.
        If 'update' is True, run the producer algorithm.
        If 'explicitSegments' is a list of SegmentRecords, use these segments instead of finding the right ones.
        If 'predictedName' is a string, use this instead of what Output requires (for the case of no Output block).
        """

        logInfo = self.logger.getEffectiveLevel() <= logging.INFO
        logDebug = self.logger.getEffectiveLevel() <= logging.DEBUG

        # increment the data stream
        self.eventNumber += 1
        if logDebug:
            self.logger.debug("========== Starting event %d" % self.eventNumber)
        elif self.eventNumber % 1000 == 0:
            self.logger.info("========== Starting event %d" % self.eventNumber)

        self.metadata.startTiming("Time to advance through data")
        self.dataStream.next()
        self.metadata.stopTiming("Time to advance through data")

        self.logger.debug("Loaded a record from the data stream.")

        # update the PMML's header
        self.eventStamp.attrib["number"] = self.eventNumber
        self.timeStamp.children[0].text = [datetime.datetime.today().isoformat()]

        # find the matching segments
        if explicitSegments is None:
            segmentMatches = []
            self.metadata.startTiming("Time searching for blacklisted items")
            blacklisted = self.segmentationScheme.blacklisted(self.pmmlModel.dataContext.get)
            self.metadata.stopTiming("Time searching for blacklisted items")

            if not blacklisted:
                self.metadata.startTiming("Time to look up existing segments")
                matchCandidates = self._getMatchCandidates()
                if self.multipleModelMethod is SELECTFIRST:

                    for index in matchCandidates:
                        segmentRecord = self.segmentRecords[index]
                        if segmentRecord.predicateMatches(self.pmmlModel.dataContext.get):
                            segmentMatches = [segmentRecord]
                            break

                elif self.multipleModelMethod is SELECTALL:
                    segmentMatches = [
                        self.segmentRecords[index] for index in matchCandidates if
                        self.segmentRecords[index].predicateMatches(self.pmmlModel.dataContext.get)]

                elif self.multipleModelMethod is SELECTONLY:
                    segmentMatches = [self.segmentRecords[0]]

                self.metadata.stopTiming("Time to look up existing segments")

                if len(segmentMatches) == 0:
                    self.metadata.startTiming("Time to find and create new PMML segments")
                    match = self.segmentationScheme.getMatch(self.pmmlModel.dataContext.get)
                    self.metadata.stopTiming("Time to find and create new PMML segments")

                    if not match:
                        if logInfo:
                            self.logger.info(" ".join([
                                "Event %d did not match any segment descriptions; discarding." % self.eventNumber,
                                "Data=%s" % self.pmmlModel.dataContext.contextString() ]))

                    else:
                        match = self._makeSegmentRecord(match, autoSegment=True)
                        segmentMatches.append(match)
            else:
                if logInfo:
                    self.logger.info(" ".join([
                        "Event %d matches a user blacklisted item, and will be ignored." % self.eventNumber,
                        "Data=%s" % self.pmmlModel.dataContext.contextString() ]))

        else:
            segmentMatches = explicitSegments

        syncNumberSource = getattr(self.consumerUpdateScheme, "timeFieldName", None)
        if syncNumberSource is None:
            syncNumber = self.eventNumber
        else:
            syncNumber = self.pmmlModel.dataContext.get(syncNumberSource)

        # possibly do custom processing
        if self.customProcessing is not None:
            self.metadata.startTiming("Score calculation, total")

            matchingSegments = [s.userFriendly for s in segmentMatches]
            if logDebug:
                self.logger.debug("About to enter customProcessing.doEvent() for event %d." % self.eventNumber)
            output = self.customProcessing.doEvent(syncNumber, self.eventNumber, self.pmmlModel.dataContext.get, matchingSegments)
            if logDebug:
                self.logger.debug("Finished customProcessing.doEvent().")

            for segmentMatch in segmentMatches:
                segmentMatch.pmmlModel.dataContext.clear()
            self.pmmlModel.dataContext.clear()

            self.metadata.stopTiming("Score calculation, total")
            return output

        # run the algorithms and create the output
        self.metadata.startTiming("Score calculation, total")
        outputRecord = OutputRecord(self.eventNumber, self.multipleModelMethod)

        ### big loop over segmentMatches
        for segmentMatch in segmentMatches:

            for l in self.logger, self.metadata:
                if "segment" in l.differentLevel:
                    seglevels = l.differentLevel["segment"]
                    segname = segmentMatch.name()
                    if segname in seglevels:
                        l.setLevel(seglevels[segname])
                    else:
                        
                        l.setLevel(l.eventLogLevel)
                else:
                    l.setLevel(l.eventLogLevel)
            logInfo = self.logger.getEffectiveLevel() <= logging.INFO
            logDebug = self.logger.getEffectiveLevel() <= logging.DEBUG

            if logDebug:
                self.logger.debug("Segment %s (%s) matched in event %d." % (segmentMatch.name(), segmentMatch.expressionTree, self.eventNumber))

            if syncNumberSource is not None:
                syncNumber = segmentMatch.pmmlModel.dataContext.get(syncNumberSource)

            for aggregate in segmentMatch.aggregates:
                aggregate.increment(syncNumber, segmentMatch.pmmlModel.dataContext.get)

            if score and segmentMatch.pmmlModel.isScorable:
                if segmentMatch.state() is MATURE or segmentMatch.state() is LOCKED:
                    if logDebug:
                        self.logger.debug("About to enter consumerAlgorithm.score() for event %d, segment %s." % (self.eventNumber, segmentMatch.name()))
                    scores = segmentMatch.consumerAlgorithm.score(syncNumber, segmentMatch.pmmlModel.dataContext.get)
                    if logDebug:
                        self.logger.debug("Finished consumerAlgorithm.score().")
                else:
                    scores = IMMATURE
            else:
                scores = INVALID

            outputSegment = OutputSegment(segmentMatch)

            # override Output block
            if predictedName is not None:
                if scores is INVALID or scores is IMMATURE:
                    outputSegment.fields = [(predictedName, scores)]
                elif scores is None:
                    outputSegment.fields = [(predictedName, MISSING)]
                else:
                    outputSegment.fields = [(predictedName, scores.get(pmml.OutputField.predictedValue, MISSING))]

            # use Output block
            elif segmentMatch.pmmlOutput is not None:
                outputSegment.fields = segmentMatch.pmmlOutput.evaluate(segmentMatch.pmmlModel.dataContext.get, scores)

            outputRecord.segments.append(outputSegment)

            if update and segmentMatch.state() is not LOCKED:
                if logDebug:
                    self.logger.debug("About to enter producerAlgorithm.update() for event %d, segment %s." % (self.eventNumber, segmentMatch.name()))
                self.updateSegment(segmentMatch)
                if logDebug:
                    self.logger.debug("Finished producerAlgorithm.update().")

            # clear the cache of each of the segment DataContexts
            segmentMatch.pmmlModel.dataContext.clear()

        # END big loop over segmentMatches

        for l in self.logger, self.metadata:
            l.setLevel(l.eventLogLevel)

        self.pmmlModel.dataContext.clear()

        self.metadata.stopTiming("Score calculation, total")
        return outputRecord