0
# Object-Centric Operations
1
2
Specialized operations for Object-Centric Event Logs (OCEL) that handle multi-dimensional process data with objects, relationships, and complex event-object interactions. OCEL extends traditional process mining to scenarios with multiple interacting business objects.
3
4
## Capabilities
5
6
### Core OCEL Operations
7
8
Basic operations for extracting information from Object-Centric Event Logs.
9
10
```python { .api }
11
def ocel_get_object_types(ocel):
12
"""
13
Get list of object types present in the OCEL.
14
15
Parameters:
16
- ocel (OCEL): Object-centric event log
17
18
Returns:
19
List[str]: List of object type names
20
"""
21
22
def ocel_get_attribute_names(ocel):
23
"""
24
Get all attribute names from events and objects in OCEL.
25
26
Parameters:
27
- ocel (OCEL): Object-centric event log
28
29
Returns:
30
List[str]: List of attribute names
31
"""
32
33
def ocel_flattening(ocel, object_type):
34
"""
35
Flatten OCEL to traditional event log based on specific object type.
36
Creates a traditional case-activity-timestamp log from object lifecycle.
37
38
Parameters:
39
- ocel (OCEL): Object-centric event log
40
- object_type (str): Object type to use for flattening
41
42
Returns:
43
pd.DataFrame: Traditional event log format
44
"""
45
46
def ocel_object_type_activities(ocel):
47
"""
48
Get activities performed for each object type.
49
50
Parameters:
51
- ocel (OCEL): Object-centric event log
52
53
Returns:
54
Dict[str, Collection[str]]: Activities per object type
55
"""
56
57
def ocel_objects_ot_count(ocel):
58
"""
59
Get count of objects per object type.
60
61
Parameters:
62
- ocel (OCEL): Object-centric event log
63
64
Returns:
65
Dict[str, int]: Object counts per type
66
"""
67
```
68
69
### OCEL Analysis Functions
70
71
Analytical operations for understanding OCEL characteristics and patterns.
72
73
```python { .api }
74
def ocel_objects_interactions_summary(ocel):
75
"""
76
Get comprehensive summary of object interactions in OCEL.
77
Analyzes how different object types interact through events.
78
79
Parameters:
80
- ocel (OCEL): Object-centric event log
81
82
Returns:
83
Dict[str, Any]: Interaction summary including frequencies and patterns
84
"""
85
86
def ocel_temporal_summary(ocel):
87
"""
88
Get temporal summary showing time-based patterns in OCEL.
89
90
Parameters:
91
- ocel (OCEL): Object-centric event log
92
93
Returns:
94
Dict[str, Any]: Temporal patterns including event frequencies over time
95
"""
96
97
def ocel_objects_summary(ocel):
98
"""
99
Get comprehensive summary of objects in OCEL.
100
101
Parameters:
102
- ocel (OCEL): Object-centric event log
103
104
Returns:
105
Dict[str, Any]: Object statistics including lifecycle information
106
"""
107
```
108
109
### OCEL Discovery Algorithms
110
111
Discover process models from Object-Centric Event Logs using specialized algorithms.
112
113
```python { .api }
114
def discover_ocdfg(ocel, **kwargs):
115
"""
116
Discover Object-Centric Directly-Follows Graph.
117
Shows relationships between activities considering object interactions.
118
119
Parameters:
120
- ocel (OCEL): Object-centric event log
121
- **kwargs: Additional parameters for discovery algorithm
122
123
Returns:
124
Dict[str, Any]: Object-centric DFG structure with object type information
125
"""
126
127
def discover_oc_petri_net(ocel, **kwargs):
128
"""
129
Discover Object-Centric Petri Net from OCEL.
130
Creates Petri net that models object lifecycles and interactions.
131
132
Parameters:
133
- ocel (OCEL): Object-centric event log
134
- **kwargs: Additional parameters for discovery algorithm
135
136
Returns:
137
Tuple[PetriNet, Marking, Marking]: Object-centric Petri net model
138
"""
139
140
def discover_objects_graph(ocel, **kwargs):
141
"""
142
Discover object interaction graph showing object relationships.
143
144
Parameters:
145
- ocel (OCEL): Object-centric event log
146
- **kwargs: Additional parameters for graph construction
147
148
Returns:
149
Dict[str, Any]: Object interaction graph structure
150
"""
151
```
152
153
### OCEL Manipulation Functions
154
155
Transform and modify OCEL data for specific analysis needs.
156
157
```python { .api }
158
def sample_ocel_objects(ocel, num_objects, object_type=None):
159
"""
160
Sample OCEL by selecting specific number of objects.
161
162
Parameters:
163
- ocel (OCEL): Object-centric event log
164
- num_objects (int): Number of objects to sample
165
- object_type (Optional[str]): Specific object type to sample from
166
167
Returns:
168
OCEL: Sampled object-centric event log
169
"""
170
171
def sample_ocel_connected_components(ocel, num_cc):
172
"""
173
Sample OCEL by selecting connected components.
174
Maintains object relationships within components.
175
176
Parameters:
177
- ocel (OCEL): Object-centric event log
178
- num_cc (int): Number of connected components to sample
179
180
Returns:
181
OCEL: Sampled object-centric event log
182
"""
183
184
def ocel_drop_duplicates(ocel):
185
"""
186
Remove duplicate events from OCEL based on event attributes.
187
188
Parameters:
189
- ocel (OCEL): Object-centric event log
190
191
Returns:
192
OCEL: Cleaned object-centric event log
193
"""
194
195
def ocel_merge_duplicates(ocel):
196
"""
197
Merge duplicate events in OCEL by combining their attributes.
198
199
Parameters:
200
- ocel (OCEL): Object-centric event log
201
202
Returns:
203
OCEL: Merged object-centric event log
204
"""
205
206
def ocel_sort_by_additional_column(ocel, column):
207
"""
208
Sort OCEL events by additional column while preserving temporal order.
209
210
Parameters:
211
- ocel (OCEL): Object-centric event log
212
- column (str): Column name to sort by
213
214
Returns:
215
OCEL: Sorted object-centric event log
216
"""
217
218
def ocel_add_index_based_timedelta(ocel):
219
"""
220
Add index-based time delta to OCEL for synthetic temporal ordering.
221
222
Parameters:
223
- ocel (OCEL): Object-centric event log
224
225
Returns:
226
OCEL: Enhanced object-centric event log with time deltas
227
"""
228
```
229
230
### OCEL Enrichment Functions
231
232
Enrich OCEL with additional information about object relationships and lifecycles.
233
234
```python { .api }
235
def ocel_o2o_enrichment(ocel, **kwargs):
236
"""
237
Add object-to-object relationships to OCEL.
238
Discovers and adds relationships between objects based on event co-occurrence.
239
240
Parameters:
241
- ocel (OCEL): Object-centric event log
242
- **kwargs: Parameters for relationship discovery
243
244
Returns:
245
OCEL: Enriched OCEL with object relationships
246
"""
247
248
def ocel_e2o_lifecycle_enrichment(ocel, **kwargs):
249
"""
250
Add event-to-object lifecycle information to OCEL.
251
Enriches events with object lifecycle context.
252
253
Parameters:
254
- ocel (OCEL): Object-centric event log
255
- **kwargs: Parameters for lifecycle enrichment
256
257
Returns:
258
OCEL: Enriched OCEL with lifecycle information
259
"""
260
261
def cluster_equivalent_ocel(ocel, **kwargs):
262
"""
263
Cluster equivalent objects in OCEL based on behavior patterns.
264
Groups objects with similar lifecycles and interaction patterns.
265
266
Parameters:
267
- ocel (OCEL): Object-centric event log
268
- **kwargs: Parameters for clustering algorithm
269
270
Returns:
271
OCEL: OCEL with clustered object information
272
"""
273
```
274
275
## Usage Examples
276
277
### Basic OCEL Operations
278
279
```python
280
import pm4py
281
282
# Load OCEL
283
ocel = pm4py.read_ocel('ocel_data.csv', objects_path='objects.csv')
284
285
# Get basic information
286
object_types = pm4py.ocel_get_object_types(ocel)
287
print(f"Object types: {object_types}")
288
289
attributes = pm4py.ocel_get_attribute_names(ocel)
290
print(f"Attributes: {attributes}")
291
292
# Get object counts per type
293
object_counts = pm4py.ocel_objects_ot_count(ocel)
294
print(f"Object counts: {object_counts}")
295
296
# Get activities per object type
297
activities_per_type = pm4py.ocel_object_type_activities(ocel)
298
for obj_type, activities in activities_per_type.items():
299
print(f"{obj_type}: {list(activities)}")
300
```
301
302
### OCEL Analysis and Summaries
303
304
```python
305
import pm4py
306
307
# Get comprehensive summaries
308
objects_summary = pm4py.ocel_objects_summary(ocel)
309
print("Objects Summary:")
310
print(f" Total objects: {objects_summary['total_objects']}")
311
print(f" Average lifecycle length: {objects_summary['avg_lifecycle_length']}")
312
313
interactions_summary = pm4py.ocel_objects_interactions_summary(ocel)
314
print("Interactions Summary:")
315
for interaction, count in interactions_summary['interaction_counts'].items():
316
print(f" {interaction}: {count}")
317
318
temporal_summary = pm4py.ocel_temporal_summary(ocel)
319
print("Temporal Summary:")
320
print(f" Time span: {temporal_summary['time_span']}")
321
print(f" Peak activity period: {temporal_summary['peak_period']}")
322
```
323
324
### Flattening OCEL to Traditional Logs
325
326
```python
327
import pm4py
328
329
# Flatten OCEL for each object type
330
object_types = pm4py.ocel_get_object_types(ocel)
331
332
flattened_logs = {}
333
for obj_type in object_types:
334
flattened_log = pm4py.ocel_flattening(ocel, obj_type)
335
flattened_logs[obj_type] = flattened_log
336
337
print(f"Flattened log for {obj_type}:")
338
print(f" Cases: {flattened_log['case:concept:name'].nunique()}")
339
print(f" Events: {len(flattened_log)}")
340
print(f" Activities: {flattened_log['concept:name'].nunique()}")
341
342
# Apply traditional process mining to flattened logs
343
for obj_type, log in flattened_logs.items():
344
print(f"\nProcess discovery for {obj_type}:")
345
net, im, fm = pm4py.discover_petri_net_inductive(log)
346
fitness = pm4py.fitness_alignments(log, net, im, fm)
347
print(f" Fitness: {fitness['log_fitness']:.3f}")
348
```
349
350
### Object-Centric Discovery
351
352
```python
353
import pm4py
354
355
# Discover Object-Centric DFG
356
ocdfg = pm4py.discover_ocdfg(ocel)
357
print("OC-DFG discovered")
358
359
# Visualize OC-DFG
360
pm4py.view_ocdfg(ocdfg)
361
pm4py.save_vis_ocdfg(ocdfg, 'ocdfg.png')
362
363
# Discover Object-Centric Petri Net
364
ocpn = pm4py.discover_oc_petri_net(ocel)
365
print("OC Petri Net discovered")
366
367
# Visualize OC Petri Net
368
pm4py.view_ocpn(ocpn)
369
pm4py.save_vis_ocpn(ocpn, 'ocpn.png')
370
371
# Discover object interaction graph
372
obj_graph = pm4py.discover_objects_graph(ocel)
373
pm4py.view_object_graph(ocel)
374
pm4py.save_vis_object_graph(ocel, 'object_graph.png')
375
```
376
377
### OCEL Sampling and Manipulation
378
379
```python
380
import pm4py
381
382
# Sample OCEL by number of objects
383
sampled_ocel = pm4py.sample_ocel_objects(ocel, 100)
384
print(f"Sampled OCEL: {len(sampled_ocel.events)} events")
385
386
# Sample by specific object type
387
order_sample = pm4py.sample_ocel_objects(ocel, 50, object_type='Order')
388
print(f"Order sample: {len(order_sample.events)} events")
389
390
# Sample by connected components
391
cc_sample = pm4py.sample_ocel_connected_components(ocel, 10)
392
print(f"Connected component sample: {len(cc_sample.events)} events")
393
394
# Clean OCEL data
395
clean_ocel = pm4py.ocel_drop_duplicates(ocel)
396
print(f"After removing duplicates: {len(clean_ocel.events)} events")
397
398
merged_ocel = pm4py.ocel_merge_duplicates(ocel)
399
print(f"After merging duplicates: {len(merged_ocel.events)} events")
400
```
401
402
### OCEL Enrichment
403
404
```python
405
import pm4py
406
407
# Add object-to-object relationships
408
enriched_ocel = pm4py.ocel_o2o_enrichment(
409
ocel,
410
min_support=0.1, # Minimum support for relationship
411
window_size=5 # Event window for relationship detection
412
)
413
print("Added object-to-object relationships")
414
415
# Add lifecycle enrichment
416
lifecycle_ocel = pm4py.ocel_e2o_lifecycle_enrichment(
417
ocel,
418
lifecycle_stages=['start', 'active', 'complete']
419
)
420
print("Added lifecycle information")
421
422
# Cluster equivalent objects
423
clustered_ocel = pm4py.cluster_equivalent_ocel(
424
ocel,
425
similarity_threshold=0.8,
426
clustering_method='kmeans'
427
)
428
print("Clustered equivalent objects")
429
```
430
431
### OCEL Filtering and Analysis Pipeline
432
433
```python
434
import pm4py
435
436
def analyze_ocel_object_type(ocel, object_type):
437
"""Complete analysis pipeline for specific object type."""
438
439
print(f"Analyzing object type: {object_type}")
440
441
# Filter OCEL to focus on specific object type
442
filtered_ocel = pm4py.filter_ocel_object_types(ocel, [object_type])
443
444
# Get basic statistics
445
obj_count = pm4py.ocel_objects_ot_count(filtered_ocel)[object_type]
446
activities = pm4py.ocel_object_type_activities(filtered_ocel)[object_type]
447
448
print(f" Objects: {obj_count}")
449
print(f" Activities: {len(activities)} - {list(activities)}")
450
451
# Flatten for traditional analysis
452
flattened = pm4py.ocel_flattening(filtered_ocel, object_type)
453
454
# Discover process model
455
net, im, fm = pm4py.discover_petri_net_inductive(flattened)
456
457
# Measure quality
458
fitness = pm4py.fitness_alignments(flattened, net, im, fm)
459
precision = pm4py.precision_alignments(flattened, net, im, fm)
460
461
print(f" Model Quality - Fitness: {fitness['log_fitness']:.3f}, Precision: {precision:.3f}")
462
463
# Create visualizations
464
pm4py.save_vis_petri_net(net, im, fm, f'{object_type}_petri_net.png')
465
466
# Discover OC-DFG for this subset
467
ocdfg = pm4py.discover_ocdfg(filtered_ocel)
468
pm4py.save_vis_ocdfg(ocdfg, f'{object_type}_ocdfg.png')
469
470
return {
471
'object_count': obj_count,
472
'activities': list(activities),
473
'fitness': fitness['log_fitness'],
474
'precision': precision,
475
'flattened_log': flattened,
476
'petri_net': (net, im, fm)
477
}
478
479
# Analyze each object type
480
object_types = pm4py.ocel_get_object_types(ocel)
481
results = {}
482
483
for obj_type in object_types:
484
results[obj_type] = analyze_ocel_object_type(ocel, obj_type)
485
486
# Compare results
487
print("\nComparison across object types:")
488
for obj_type, result in results.items():
489
print(f"{obj_type}: {result['object_count']} objects, "
490
f"fitness={result['fitness']:.3f}, "
491
f"precision={result['precision']:.3f}")
492
```
493
494
### Cross-Object Type Analysis
495
496
```python
497
import pm4py
498
499
def analyze_object_interactions(ocel):
500
"""Analyze interactions between different object types."""
501
502
interactions = pm4py.ocel_objects_interactions_summary(ocel)
503
504
print("Object Type Interactions:")
505
for interaction, metrics in interactions['interaction_matrix'].items():
506
obj_type1, obj_type2 = interaction
507
frequency = metrics['frequency']
508
strength = metrics['strength']
509
print(f" {obj_type1} <-> {obj_type2}: {frequency} interactions (strength: {strength:.3f})")
510
511
# Discover object graph
512
obj_graph = pm4py.discover_objects_graph(ocel)
513
pm4py.save_vis_object_graph(ocel, 'full_object_graph.png')
514
515
# Create connected component analysis
516
object_types = pm4py.ocel_get_object_types(ocel)
517
518
for obj_type in object_types:
519
# Filter by connected components containing this object type
520
cc_filtered = pm4py.filter_ocel_cc_otype(ocel, obj_type)
521
522
# Analyze component characteristics
523
summary = pm4py.ocel_objects_summary(cc_filtered)
524
525
print(f"Connected components with {obj_type}:")
526
print(f" Components: {summary['num_components']}")
527
print(f" Avg component size: {summary['avg_component_size']:.1f}")
528
529
# Run interaction analysis
530
analyze_object_interactions(ocel)
531
```
532
533
### OCEL Data Quality Assessment
534
535
```python
536
import pm4py
537
538
def assess_ocel_quality(ocel):
539
"""Comprehensive OCEL data quality assessment."""
540
541
print("OCEL Data Quality Assessment")
542
print("="*40)
543
544
# Basic statistics
545
object_types = pm4py.ocel_get_object_types(ocel)
546
object_counts = pm4py.ocel_objects_ot_count(ocel)
547
548
print(f"Object Types: {len(object_types)}")
549
for obj_type in object_types:
550
count = object_counts[obj_type]
551
activities = pm4py.ocel_object_type_activities(ocel)[obj_type]
552
print(f" {obj_type}: {count} objects, {len(activities)} activities")
553
554
# Temporal quality
555
temporal_summary = pm4py.ocel_temporal_summary(ocel)
556
print(f"\nTemporal Span: {temporal_summary['time_span']}")
557
print(f"Event Rate: {temporal_summary['avg_events_per_day']:.1f} events/day")
558
559
# Object interactions
560
interactions = pm4py.ocel_objects_interactions_summary(ocel)
561
print(f"\nObject Interactions: {interactions['total_interactions']}")
562
print(f"Interaction Density: {interactions['interaction_density']:.3f}")
563
564
# Check for duplicates
565
original_events = len(ocel.events)
566
deduplicated = pm4py.ocel_drop_duplicates(ocel)
567
duplicate_events = original_events - len(deduplicated.events)
568
569
print(f"\nData Quality:")
570
print(f" Total Events: {original_events}")
571
print(f" Duplicate Events: {duplicate_events} ({100*duplicate_events/original_events:.1f}%)")
572
573
# Completeness check
574
attributes = pm4py.ocel_get_attribute_names(ocel)
575
print(f" Attributes: {len(attributes)}")
576
577
return {
578
'object_types': len(object_types),
579
'total_objects': sum(object_counts.values()),
580
'total_events': original_events,
581
'duplicate_rate': duplicate_events/original_events,
582
'interaction_density': interactions['interaction_density']
583
}
584
585
# Assess quality
586
quality_metrics = assess_ocel_quality(ocel)
587
```