Exemple #1
0
def get_traces_from_log(log):
    classifier = XEventNameClassifier()
    traces = list()
    for trace in log:
        decoded_trace = list()
        for event in trace:
            decoded_trace.append(classifier.get_class_identity(event))

        traces.append(decoded_trace)

    return traces
Exemple #2
0
def log():
    log = XFactory.create_log()
    # add log classifier
    clf = XEventNameClassifier()
    log.get_classifiers().append(clf)
    # add global trace attributes
    glb_t_attr = XFactory.create_attribute_discrete('glb_t_attr', 0)
    log.get_global_trace_attributes().append(glb_t_attr)
    # add global event attributes
    glb_e_attr = XFactory.create_attribute_discrete('glb_e_attr', 0)
    log.get_global_event_attributes().append(glb_e_attr)
    # add log attributes
    str_attr = XFactory.create_attribute_literal('l_attr', 'UNKNOWN')
    log.get_attributes()['l_attr'] = str_attr
    # add extension
    meta_concept = XExtensionParser().parse(
        "http://www.xes-standard.org/meta_concept.xesext")
    log.get_extensions().add(meta_concept)
    # add a trace
    tracelen = 2
    trace0 = XFactory.create_trace()
    # add some trace attributes
    bool_attr = XFactory.create_attribute_boolean('t_attr', True)
    # add some trace features
    trace0.get_attributes()['t_attr'] = bool_attr
    for i in range(tracelen):
        event = XFactory.create_event()
        # add an attribute
        int_attr = XFactory.create_attribute_discrete('e_attr', 0)
        event.get_attributes()['e_attr0'] = int_attr
        trace0.append(event)
    log.append(trace0)
    return log
Exemple #3
0
def create_event_int_mapping(log):
    classifier = XEventNameClassifier()
    event_name_list = []
    for trace in log[0]:
        for event in trace:
            event_name = classifier.get_class_identity(event)
            if not str(event_name) in event_name_list:
                event_name_list.append(event_name)
    event_int_mapping = {}
    event_int_mapping[TRACE_START] = 0
    current_int = 1
    for event_name in event_name_list:
        event_int_mapping[event_name] = current_int
        current_int = current_int + 1
    event_int_mapping[TRACE_END] = current_int
    return event_int_mapping
Exemple #4
0
 def get_df_frequencies(log, event_int_mapping):
     classifier = XEventNameClassifier()
     df_relations = np.zeros((len(event_int_mapping),len(event_int_mapping)), dtype=int)
     for trace in log[0]:
         current_event = TRACE_START
         for event in trace:
             next_event = classifier.get_class_identity(event)
             current_event_int = event_int_mapping[current_event]
             next_event_int = event_int_mapping[next_event]
             df_relations[current_event_int, next_event_int] += 1
             current_event = next_event
         
         current_event_int = event_int_mapping[current_event]
         next_event = TRACE_END
         next_event_int = event_int_mapping[next_event]
         df_relations[current_event_int, next_event_int] += 1
         
     return df_relations
Exemple #5
0
def get_prefix_frequencies_from_log(log):
    classifier = XEventNameClassifier()
    prefix_frequencies = {}
    for trace in log[0]:
        current_prefix = ""
        for event in trace:
            current_prefix = current_prefix + classifier.get_class_identity(
                event) + EVENT_DELIMETER
            if current_prefix in prefix_frequencies:
                prefix_frequencies[current_prefix] += 1
            else:
                prefix_frequencies[current_prefix] = 1
        current_prefix = current_prefix + TRACE_END
        if current_prefix in prefix_frequencies:
            prefix_frequencies[current_prefix] += 1
        else:
            prefix_frequencies[current_prefix] = 1
    return prefix_frequencies
Exemple #6
0
class XMxmlParser:
    """Parser for the MXML format for event logs (deprecated).

    :param factory: The factory to use for XES model building.
    :type factory: XFactory
    """
    MXML_CLASSIFIERS = [
        XEventAttributeClassifier("MXML Legacy Classifier",
                                  ["concept:name", "lifecycle:transition"]),
        XEventNameClassifier(),
        XEventResourceClassifier()
    ]

    def __init__(self, factory=None):
        if factory:
            self.factory = factory
        else:
            self.factory = XFactoryRegistry().current_default()

    def can_parse(self, file):
        """Checks whether this parser can handle the given file.

        :param file: path of the file to check against parser.
        :type file: str
        :return: Whether this parser can handle the given file.
        :rtype: bool
        """
        return self.ends_with_ignore_case(
            file, ".mxml") or self.ends_with_ignore_case(file, ".xml")

    def parse(self, file):
        """Parses a set of logs from the given input stream, which is supposed
        to deliver an MXML serialization.



        :param file: file generated by the function 'open(path)', which is
          supposed to deliver an MXML serialization.
        :type file: _io.TextIOWrapper
        :return: The parsed list of logs.
        :rtype: list[XLog]
        """
        handler = XMxmlParser.MxmlHandler()

        xml_parse(file, handler)

        return handler.get_logs()

    @staticmethod
    def ends_with_ignore_case(name, suffix):
        """Returns whether the given file name ends (ignoring the case) with the given suffix.

        :param name: The given file name.
        :type name: str
        :param suffix: The given suffix.
        :type suffix: str
        :return: Whether the given file name ends (ignoring the case) with the given suffix.
        :rtype: bool
        """
        i = len(name) - len(suffix)
        if i > 0:
            return suffix in name[i:]
        return False

    class MxmlHandler(ContentHandler):
        """SAX handler class for XES in XML representation.

        """
        def __init__(self):
            super().__init__()
            self.__buffer = list()
            self.__logs = list()
            self.__currentProcess = None
            self.__currentInstance = None
            self.__entry = None
            self.__sourceAttribute = None
            self.__genericAttribute = None
            self.__eventTypeAttribute = None
            self.__originatorAttribute = None
            self.__sourceOpen = False
            self.__timestamp = None
            self.__lastTimestamp = None
            self.__numUnorderedEntries = 0

        def get_logs(self):
            """Retrieves the parsed list of logs.

            :return: The parsed list of logs.
            :rtype: list[XLog]
            """
            return self.__logs

        def startElement(self, element_name, attributes):
            """ Overrides startElement in class ContentHandler

            :param element_name: Contains the raw XML 1.0 name of the element type.
            :type element_name: str
            :param attributes: An instance of the Attributes class containing
              the attributes of the element
            :type attributes: xml.sax.xmlreader.AttributesImpl
            """
            tag_name = element_name
            if tag_name != "WorkflowLog":
                if tag_name == "Source":
                    self.__sourceOpen = True
                    description_string = attributes.get("program")
                    self.__sourceAttribute = XMxmlParser(
                    ).factory.create_attribute_literal("source",
                                                       description_string,
                                                       None)
                    self.__add_model_reference__(attributes,
                                                 self.__sourceAttribute)
                elif tag_name == "Process":
                    description_string = attributes.get("id")
                    description = attributes.get("description")

                    self.__currentProcess = XMxmlParser().factory.create_log()
                    self.__currentProcess.get_extensions().add(
                        XConceptExtension())
                    self.__currentProcess.get_extensions().add(
                        XOrganizationalExtension())
                    self.__currentProcess.get_extensions().add(
                        XLifecycleExtension())
                    self.__currentProcess.get_extensions().add(
                        XSemanticExtension())
                    self.__currentProcess.get_extensions().add(
                        XTimeExtension())
                    if self.__sourceAttribute:
                        self.__currentProcess.get_attributes()[
                            self.__sourceAttribute.get_key(
                            )] = self.__sourceAttribute

                    XConceptExtension().assign_name(self.__currentProcess,
                                                    description_string)
                    XLifecycleExtension().assign_model(self.__currentProcess,
                                                       "standard")

                    if description and len(description.lower()) > 0:

                        description1 = XMxmlParser(
                        ).factory.create_attribute_literal(
                            "description", description, None)
                        self.__currentProcess.get_attributes()[
                            description1.get_key()] = description1

                    self.__add_model_reference__(attributes,
                                                 self.__currentProcess)

                elif tag_name == "ProcessInstance":
                    self.__currentInstance = XMxmlParser(
                    ).factory.create_trace()
                    name = attributes.get("id")
                    if name is None:
                        name = "None"

                    XConceptExtension().assign_name(self.__currentInstance,
                                                    name)
                    description_string = attributes.get("description")

                    if description_string and len(
                            description_string.strip()) > 0:
                        description2 = XMxmlParser(
                        ).factory.create_attribute_literal(
                            "description", description_string, None)
                        self.__currentInstance.get_attributes()[
                            description2.get_key()] = description2

                    self.__add_model_reference__(attributes,
                                                 self.__currentInstance)

                elif tag_name == "AuditTrailEntry":
                    self.__entry = XMxmlParser().factory.create_event()

                elif tag_name == "Attribute":
                    self.__genericAttribute = XMxmlParser(
                    ).factory.create_attribute_literal(
                        attributes.get("name").strip(), "DEFAULT_VALUE", None)
                    self.__add_model_reference__(attributes,
                                                 self.__genericAttribute)

                elif tag_name == "EventType":
                    self.__eventTypeAttribute = XLifecycleExtension(
                    ).ATTR_TRANSITION.clone()
                    unknown_type = attributes.get("unknowntype")
                    if unknown_type:
                        self.__eventTypeAttribute.set_value(unknown_type)
                    else:
                        self.__eventTypeAttribute.set_value("UNKNOWN")

                    self.__add_model_reference__(attributes,
                                                 self.__eventTypeAttribute)

                elif tag_name == "WorkflowModelElement":
                    self.__add_model_reference__(attributes, self.__entry)

                elif tag_name == "Originator":
                    self.__originatorAttribute = XOrganizationalExtension(
                    ).ATTR_RESOURCE.clone()
                    self.__add_model_reference__(attributes,
                                                 self.__originatorAttribute)

        def endElement(self, local_name):
            """ Overrides endElement in class ContentHandler

            :param local_name: The name of the element type, just as with the startElement event
            :type local_name: str
            """
            tag_name = local_name

            if tag_name == "WorkflowLog":
                if self.__numUnorderedEntries > 0:
                    XLogging().log(
                        "LogData: Log contains " +
                        str(self.__numUnorderedEntries) +
                        " audit trail entries in non-natural order!",
                        XLogging.Importance.ERROR)
                    XLogging().log(
                        "LogData: The log file you have loaded is not MXML compliant! (error compensated transparently)",
                        XLogging.Importance.ERROR)

            elif tag_name == "Process":
                self.__currentProcess.get_classifiers().extend(
                    XMxmlParser.MXML_CLASSIFIERS)
                self.__currentProcess.get_global_trace_attributes().append(
                    XConceptExtension().ATTR_NAME.clone())
                self.__currentProcess.get_global_event_attributes().append(
                    XConceptExtension().ATTR_NAME.clone())
                self.__currentProcess.get_global_event_attributes().append(
                    XLifecycleExtension().ATTR_TRANSITION.clone())
                self.__logs.append(self.__currentProcess)
                self.__currentProcess = None

            elif tag_name == "Process":
                self.__sourceOpen = False

            elif tag_name == "ProcessInstance":
                if len(self.__currentInstance) > 0:
                    self.__currentProcess.append(self.__currentInstance)

                self.__currentInstance = None
                self.__lastTimestamp = None

            elif tag_name == "AuditTrailEntry":
                if self.__timestamp is None:
                    self.__currentInstance.append(self.__entry)
                elif self.__lastTimestamp is None:
                    self.__currentInstance.append(self.__entry)
                    self.__lastTimestamp = self.__timestamp
                elif self.__timestamp > self.__lastTimestamp:
                    self.__currentInstance.append(self.__entry)
                    self.__lastTimestamp = self.__timestamp
                else:
                    self.__currentInstance.append(self.__entry)

                self.__entry = None

            else:
                if tag_name == "Attribute":
                    originator = "".join(self.__buffer).strip()
                    if len(originator) > 0:
                        self.__genericAttribute.set_value("".join(
                            self.__buffer).strip())
                        if self.__entry:
                            self.__entry.get_attributes()[
                                self.__genericAttribute.get_key(
                                )] = self.__genericAttribute
                        elif self.__currentInstance:
                            self.__currentInstance.get_attributes()[
                                self.__genericAttribute.get_key(
                                )] = self.__genericAttribute
                        elif self.__currentProcess:
                            self.__currentProcess.get_attributes()[
                                self.__genericAttribute.get_key(
                                )] = self.__genericAttribute
                        elif self.__sourceOpen:
                            self.__sourceAttribute.get_attributes()[
                                self.__genericAttribute.get_key(
                                )] = self.__genericAttribute
                    self.__genericAttribute = None

                elif tag_name == "EventType":
                    if self.__eventTypeAttribute.get_value() == "UNKNOWN":
                        originator = "".join(self.__buffer).strip()
                        if len(originator) > 0:
                            self.__eventTypeAttribute.set_value(originator)
                            self.__entry.get_attributes()[
                                self.__eventTypeAttribute.get_key(
                                )] = self.__eventTypeAttribute
                    else:
                        self.__entry.get_attributes()[
                            self.__eventTypeAttribute.get_key(
                            )] = self.__eventTypeAttribute
                    self.__eventTypeAttribute = None

                elif tag_name == "WorkflowModelElement":
                    XConceptExtension().assign_name(
                        self.__entry, "".join(self.__buffer).strip())

                elif tag_name == "Timestamp":
                    originator = "".join(self.__buffer).strip()
                    self.__timestamp = parse_date_time(originator)
                    if self.__timestamp:
                        timestamp_attribute = XTimeExtension(
                        ).ATTR_TIMESTAMP.clone()
                        timestamp_attribute.set_value(self.__timestamp)
                        self.__entry.get_attributes(
                        )[timestamp_attribute.get_key()] = timestamp_attribute

                elif tag_name == "Originator":
                    originator = "".join(self.__buffer).strip()
                    if len(originator) > 0:
                        self.__originatorAttribute.set_value(originator)

                    self.__entry.get_attributes()[
                        self.__originatorAttribute.get_key(
                        )] = self.__originatorAttribute
                    self.__originatorAttribute = None

            self.__buffer.clear()

        @staticmethod
        def __add_model_reference__(attrib, subject):
            try:
                model_reference = attrib.getValue("modelReference")
            except KeyError:
                model_reference = None

            if model_reference:
                attribute = XSemanticExtension().ATTR_MODELREFERENCE.clone()
                attribute.set_value(model_reference)
                subject.get_attributes()[attribute.get_key()] = attribute

        def ignorableWhitespace(self, whitespace):
            """ Overrides ignorableWhitespace in class ContentHandler

            :param whitespace: The whitespace characters.
            :type whitespace: str
            """
            self.__buffer.append(whitespace)

        def characters(self, content):
            """ Overrides characters in class ContentHandler

            :param content: The characters.
            :type content: str
            """
            self.__buffer.append(content)
Exemple #7
0
class XLogInfo:
    """This class implements a bare-bones log info summary which can be created
    on demand by using applications. The log info summary is based on an event
    classifier, which is used to identify event class abstractions.

    :param log: The event log to create an info summary for.
    :type log: XLog
    :param default_classifier: The default event classifier to be used
    :type default_classifier: XEventAttributeClassifier
    :param classifiers: A collection of additional event classifiers to be
     covered by the created log info instance.
    :type classifiers: list[XEventAttributeClassifier]
    """
    STANDARD_CLASSIFIER = XEventAttributeClassifier(
        "MXML Legacy Classifier", ["concept:name", "lifecycle:transition"])
    NAME_CLASSIFIER = XEventNameClassifier()
    RESOURCE_CLASSIFIER = XEventResourceClassifier()
    LIFECYCLE_TRANSITION_CLASSIFIER = XEventLifeTransClassifier()

    @staticmethod
    def create(log, default_classifier=None, classifiers=None):
        """Creates a new log info summary with the standard event classifier.

        :param log: The event log to create an info summary for.
        :type log: XLog
        :param default_classifier: The default event classifier to be used
        :type default_classifier: XEventAttributeClassifier
        :param classifiers: A collection of additional event classifiers to be
         covered by the created log info instance.
        :type classifiers: list[XEventAttributeClassifier]
        :return: The log info summary for this log.
        :rtype: XLogInfo
        """
        if default_classifier is None:
            return XLogInfo(log, XLogInfo.STANDARD_CLASSIFIER, classifiers)
        return XLogInfo(log, default_classifier, classifiers)

    def __init__(self, log, default_classifier, classifiers):
        self.__log = log
        self.__default_classifier = default_classifier
        if classifiers is None:
            classifiers = list()
        self.__event_classes = dict()
        for classifier in classifiers:
            self.__event_classes[classifier] = XEventClasses(classifier)

        self.__event_classes[self.__default_classifier] = XEventClasses(
            self.__default_classifier)
        self.__event_classes[self.NAME_CLASSIFIER] = XEventClasses(
            self.NAME_CLASSIFIER)
        self.__event_classes[self.RESOURCE_CLASSIFIER] = XEventClasses(
            self.RESOURCE_CLASSIFIER)
        self.__event_classes[
            self.LIFECYCLE_TRANSITION_CLASSIFIER] = XEventClasses(
                self.LIFECYCLE_TRANSITION_CLASSIFIER)

        self.__number_of_events = 0
        self.__number_of_traces = 0
        self.__log_boundaries = XTimeBounds()
        self.__trace_boundaries = dict()
        self.__log_attribute_info = XAttributeInfo()
        self.__trace_attribute_info = XAttributeInfo()
        self.__event_attribute_info = XAttributeInfo()
        self.__meta_attribute_info = XAttributeInfo()
        self.setup()

    def setup(self):
        """Creates the internal data structures of this summary on setup from
        the log.

        """
        self.register_attributes(self.__log_attribute_info, self.__log)

        for trace in self.__log:
            self.__number_of_traces += 1
            self.register_attributes(self.__trace_attribute_info, trace)
            trace_bounds = XTimeBounds()

            for event in trace:
                self.__number_of_events += 1
                self.register_attributes(self.__event_attribute_info, event)

                for classes in self.__event_classes.values():
                    classes.register(event)

                trace_bounds.register(event)

            self.__trace_boundaries[trace] = trace_bounds
            self.__log_boundaries.register(trace_bounds)

        for classes in self.__event_classes.values():
            classes.harmonize_indices()

    def register_attributes(self, attribute_info, attributable):
        """Registers all attributes of a given attributable, i.e. model type
        hierarchy element, in the given attribute info registry.

        :param attribute_info: Attribute info registry to use for registration.
        :type attribute_info: XAttributeInfo
        :param attributable: Attributable whose attributes to register.
        :type attributable: XAttributable
        """
        if attributable.has_attributes():
            for attribute in attributable.get_attributes().values():
                attribute_info.register(attribute)
                self.register_attributes(self.__meta_attribute_info, attribute)

    def get_log(self):
        """Retrieves the log used for this summary.

        :return: The event log which this summary describes.
        :rtype: XLog
        """
        return self.__log

    def get_number_of_event(self):
        """Retrieves the total number of events in this log.

        :return: Total number of events.
        :rtype: int
        """
        return self.__number_of_events

    def get_number_of_traces(self):
        """Retrieves the number of traces in this log.

        :return: Number of traces available in this log.
        :rtype: int
        """
        return self.__number_of_traces

    def get_event_classes(self, classifier=None):
        """Retrieves the event classes for a given classifier.
        *Note:* The given event classifier must be covered by this log info,
        i.e., the log info must have been created with this classifier.
        Otherwise, this method will return null. You can retrieve the collection
        of event classifiers covered by this log info instance by calling the
        method getEventClassifiers().

        :param classifier: The classifier for which to retrieve the event classes.
        :type classifier: XEventAttributeClassifier or None
        :return: The requested event classes, or null if the given event
         classifier is not covered by this log info instance.
        :rtype: XEventClasses
        """
        if classifier is None:
            return self.__event_classes.get(self.__default_classifier)
        return self.__event_classes.get(classifier)

    def get_event_classifiers(self):
        """Retrieves the set of event classifiers covered by this log info,
        i.e., for which event classes are registered in this log info instance.

        :return: The tuple of event classifiers covered by this log info instance.
        :rtype: tuple
        """
        return set(self.__event_classes.keys())

    def get_resource_classes(self):
        """Retrieves the resource classes of the summarized log.

        :return: The resource classes of the summarized log.
        :rtype: XEventClasses
        """
        return self.__event_classes.get(self.RESOURCE_CLASSIFIER)

    def get_name_classes(self):
        """Retrieves the event name classes of the summarized log.

        :return: The event name classes of the summarized log.
        :rtype: XEventClasses
        """
        return self.__event_classes.get(self.NAME_CLASSIFIER)

    def get_transition_classes(self):
        """Retrieves the lifecycle transition classes of the summarized log.

        :return: The lifecycle transition classes of the summarized log.
        :rtype: XEventClasses
        """
        return self.__event_classes.get(self.LIFECYCLE_TRANSITION_CLASSIFIER)

    def get_log_time_boundaries(self):
        """Retrieves the global timestamp boundaries of this log.

        :return: Timestamp boundaries for the complete log.
        :rtype XTimeBounds
        """
        return self.__log_boundaries

    def get_trace_time_boundaries(self, trace):
        """ Retrieves the timestamp boundaries for a specified trace.

        :param trace: Trace to be queried for.
        :return: Timestamp boundaries for the indicated trace.
        :rtype: XTimeBounds
        """
        return self.__trace_boundaries.get(trace)

    def get_log_attribute_info(self):
        """Retrieves attribute information about all attributes this log
        contains on the log level.

        :return: Attribute information on the log level.
        :rtype: XAttributeInfo
        """
        return self.__log_attribute_info

    def get_trace_attribute_info(self):
        """Retrieves attribute information about all attributes this log
        contains on the trace level.

        :return: Attribute information on the trace level.
        :rtype: XAttributeInfo
        """
        return self.__trace_attribute_info

    def get_event_attribute_info(self):
        """Retrieves attribute information about all attributes this log
        contains on the event level.

        :return: Attribute information on the event level.
        :rtype: XAttributeInfo
        """
        return self.__event_attribute_info

    def get_meta_attribute_info(self):
        """Retrieves attribute information about all attributes this log
        contains on the meta (i.e., attribute) level.

        :return: Attribute information on the meta level.
        :rtype: XAttributeInfo
        """
        return self.__meta_attribute_info
Exemple #8
0
    ['3', 'Archive order', 1.0, 'complete', 'sales', dt(year=2017, month=3, day=17, hour=8, minute=15, second=0)]
]

EVENT_DF = pd.DataFrame(EVENTS, columns=EVENT_DF_COLUMNS)

TRACE_DF_COLUMNS = [const.CONCEPT_NAME, const.COST_TOTAL]

TRACES = [
    ['1', 100.0],
    ['2', 1300.0],
    ['3', 1400.0]
]

TRACE_DF = pd.DataFrame(TRACES, columns=TRACE_DF_COLUMNS)

NAME_AND_LIFECYCLE_CLF = XEventAndClassifier([XEventNameClassifier(), XEventLifeTransClassifier()])

CLASSIFIERS = {
    XEventNameClassifier().name(): [const.CONCEPT_NAME],
    NAME_AND_LIFECYCLE_CLF.name(): [const.CONCEPT_NAME, const.LIFECYCLE_TRANS]
}

LOG_TABLE = LogTable(event_df=EVENT_DF, trace_df=TRACE_DF,
                     attributes=LOG_ATTRIBUTE_DICT, classifiers=CLASSIFIERS)

XLOG = XFactory.create_log()
XLOG_NAME = 'Test log'
CONCEPT_EXTENSION.assign_name(XLOG, XLOG_NAME)
TOTAL_TIME = 100
TOTAL_TIME_ATTRIBUTE = XFactory.create_attribute_continuous('total_time', TOTAL_TIME)
XLOG.get_attributes()['total_time'] = TOTAL_TIME_ATTRIBUTE