Skip to content

Resource

Resource

Bases: BaseModel, ABC

Abstract base class for resources.

Attributes:

Name Type Description
label str | None

Optional human-readable label for this resource class.

description str | None

Optional human-readable description for this resource class.

Source code in src/ocelescope/src/ocelescope/resource/resource.py
class Resource(BaseModel, ABC):
    """Abstract base class for resources.

    Attributes:
        label: Optional human-readable label for this resource class.
        description: Optional human-readable description for this resource class.
    """

    label: ClassVar[str | None]
    description: ClassVar[str | None]

    @classmethod
    def get_type(cls):
        """Return the simple type name of this resource.

        Returns:
            str: The class name (e.g., ``"PetriNet"``).
        """
        return cls.__name__

    @abstractmethod
    def visualize(self) -> Visualization | None:
        """Produce a visualization for this resource.

        Implementations should return a concrete :class:`Visualization`
        or ``None`` if no visualization exists.

        Returns:
            Optional[Visualization]: A visualization object or ``None``.
        """
        pass

get_type classmethod

get_type()

Return the simple type name of this resource.

Returns:

Name Type Description
str

The class name (e.g., "PetriNet").

Source code in src/ocelescope/src/ocelescope/resource/resource.py
@classmethod
def get_type(cls):
    """Return the simple type name of this resource.

    Returns:
        str: The class name (e.g., ``"PetriNet"``).
    """
    return cls.__name__

visualize abstractmethod

visualize()

Produce a visualization for this resource.

Implementations should return a concrete :class:Visualization or None if no visualization exists.

Returns:

Type Description
Visualization | None

Optional[Visualization]: A visualization object or None.

Source code in src/ocelescope/src/ocelescope/resource/resource.py
@abstractmethod
def visualize(self) -> Visualization | None:
    """Produce a visualization for this resource.

    Implementations should return a concrete :class:`Visualization`
    or ``None`` if no visualization exists.

    Returns:
        Optional[Visualization]: A visualization object or ``None``.
    """
    pass

PetriNet

Bases: Resource

An object-centric Petri net representation.

Attributes:

Name Type Description
places list[Place]

List of places in the Petri net.

transitions list[Transition]

List of transitions in the Petri net.

arcs list[Arc]

List of arcs connecting places and transitions.

Source code in src/ocelescope/src/ocelescope/resource/default/petri_net.py
class PetriNet(Resource):
    """An object-centric Petri net representation.

    Attributes:
        places: List of places in the Petri net.
        transitions: List of transitions in the Petri net.
        arcs: List of arcs connecting places and transitions.
    """

    label = "Petri Net"
    description = "An object-centric petri net"

    places: list[Place]
    transitions: list[Transition]
    arcs: list[Arc]

    def visualize(self):
        # Use your color generator function
        object_types = list({p.object_type for p in self.places})
        color_map = generate_color_map(object_types)

        # Build nodes
        nodes: list[GraphNode] = []

        for place in self.places:
            nodes.append(
                GraphNode(
                    id=place.id,
                    label=place.object_type if place.place_type else None,
                    shape="circle",
                    color=color_map.get(place.object_type, "#cccccc"),
                    width=30,
                    label_pos="bottom",
                    height=30,
                )
            )

        for transition in self.transitions:
            label = transition.label or None
            nodes.append(
                GraphNode(
                    id=transition.id,
                    label=label,
                    width=None if label else 10,
                    height=None if label else 40,
                    shape="rectangle",
                    color="#ffffff" if label else "#000000",
                    border_color="#000000" if label else None,
                )
            )

        # Build edges
        edges: list[GraphEdge] = []

        for arc in self.arcs:
            object_type = next(
                (p.object_type for p in self.places if p.id in {arc.source, arc.target}),
                "default",
            )
            edges.append(
                GraphEdge(
                    source=arc.source,
                    target=arc.target,
                    arrows=(None, "triangle"),
                    color=color_map.get(object_type, "#cccccc"),
                )
            )

        return Graph(
            type="graph",
            nodes=nodes,
            edges=edges,
            layout_config=GraphvizLayoutConfig(
                engine="dot",
                graphAttrs={
                    "rankdir": "LR",
                    "ranksep": "0.7",
                    "nodesep": "0.7",
                },
            ),
        )

DirectlyFollowsGraph

Bases: Resource

[TODO:description]

Attributes:

Name Type Description
label

[TODO:attribute]

description

[TODO:attribute]

object_types list[str]

[TODO:attribute]

activities list[str]

[TODO:attribute]

edges list[Edge]

[TODO:attribute]

start_activities list[ObjectActivityEdge]

[TODO:attribute]

end_activities list[ObjectActivityEdge]

[TODO:attribute]

Source code in src/ocelescope/src/ocelescope/resource/default/dfg.py
class DirectlyFollowsGraph(Resource):
    """[TODO:description]

    Attributes:
        label: [TODO:attribute]
        description: [TODO:attribute]
        object_types: [TODO:attribute]
        activities: [TODO:attribute]
        edges: [TODO:attribute]
        start_activities: [TODO:attribute]
        end_activities: [TODO:attribute]
    """

    label = "Directly Follows Graph"
    description = "A object-centric directly follows graph"

    object_types: list[str]
    activities: list[str]
    edges: list[Edge]
    start_activities: list[ObjectActivityEdge]
    end_activities: list[ObjectActivityEdge]

    def visualize(self):
        color_map = generate_color_map(self.object_types)

        activity_nodes = [
            GraphNode(id=activity, label=activity, shape="rectangle")
            for activity in self.activities
        ]

        start_nodes = [
            GraphNode(
                id=f"start_{object_type}",
                label=object_type,
                shape="circle",
                color=color_map[object_type],
                width=40,
                height=40,
                label_pos="top",
            )
            for object_type in self.object_types
        ]

        end_nodes = [
            GraphNode(
                id=f"end_{object_type}",
                label=object_type,
                shape="circle",
                color=color_map[object_type],
                width=40,
                height=40,
                label_pos="bottom",
            )
            for object_type in self.object_types
        ]

        nodes: list[GraphNode] = activity_nodes + start_nodes + end_nodes

        # Create edges
        activity_edges = [
            GraphEdge(
                source=edge.source,
                target=edge.target,
                arrows=(None, "triangle"),
                color=color_map[edge.object_type],
            )
            for edge in self.edges
        ]

        start_edges = [
            GraphEdge(
                source=f"start_{start_edge.object_type}",
                target=start_edge.activity,
                arrows=(None, "triangle"),
                color=color_map[start_edge.object_type],
            )
            for start_edge in self.start_activities
        ]

        end_edges = [
            GraphEdge(
                target=f"end_{end_edge.object_type}",
                source=end_edge.activity,
                arrows=(None, "triangle"),
                color=color_map[end_edge.object_type],
            )
            for end_edge in self.end_activities
        ]

        edges: list[GraphEdge] = activity_edges + start_edges + end_edges

        return Graph(
            type="graph",
            nodes=nodes,
            edges=edges,
            layout_config=GraphvizLayoutConfig(
                engine="dot",
                graphAttrs={
                    "rankdir": "BT",
                    "splines": "True",
                    "nodesep": "0.8",
                    "ranksep": "0.5",
                },
            ),
        )