100% found this document useful (1 vote)
7 views

A Primer on Process Mining Practical Skills with Python and Graphviz 1st Edition Diogo R. Ferreira (Auth.) instant download

A Primer on Process Mining by Diogo R. Ferreira introduces the core concepts of process mining and demonstrates how to implement basic techniques using Python and Graphviz. The book aims to provide a foundational understanding of process mining without delving into complex models, making it suitable for beginners. It serves as a stepping stone for further exploration of the topic through existing literature.

Uploaded by

cairyyokunarv
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
100% found this document useful (1 vote)
7 views

A Primer on Process Mining Practical Skills with Python and Graphviz 1st Edition Diogo R. Ferreira (Auth.) instant download

A Primer on Process Mining by Diogo R. Ferreira introduces the core concepts of process mining and demonstrates how to implement basic techniques using Python and Graphviz. The book aims to provide a foundational understanding of process mining without delving into complex models, making it suitable for beginners. It serves as a stepping stone for further exploration of the topic through existing literature.

Uploaded by

cairyyokunarv
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 63

A Primer on Process Mining Practical Skills with

Python and Graphviz 1st Edition Diogo R.


Ferreira (Auth.) pdf download

https://textbookfull.com/product/a-primer-on-process-mining-
practical-skills-with-python-and-graphviz-1st-edition-diogo-r-
ferreira-auth/

Download more ebook from https://textbookfull.com


We believe these products will be a great fit for you. Click
the link to download now, or visit textbookfull.com
to discover even more!

Learning Data Mining with Python Layton

https://textbookfull.com/product/learning-data-mining-with-
python-layton/

Learning Data Mining with Python Robert Layton

https://textbookfull.com/product/learning-data-mining-with-
python-robert-layton/

Text Mining with R 1st Edition Julia Silge

https://textbookfull.com/product/text-mining-with-r-1st-edition-
julia-silge/

Data Mining A Tutorial Based Primer Second Edition


Roiger

https://textbookfull.com/product/data-mining-a-tutorial-based-
primer-second-edition-roiger/
Primer on Cerebrovascular Diseases Louis R. Caplan

https://textbookfull.com/product/primer-on-cerebrovascular-
diseases-louis-r-caplan/

Hands-On Entity Resolution: A Practical Guide to Data


Matching With Python 1st Edition Michael Shearer

https://textbookfull.com/product/hands-on-entity-resolution-a-
practical-guide-to-data-matching-with-python-1st-edition-michael-
shearer/

Data Ingestion with Python Cookbook: A practical guide


to ingesting, monitoring, and identifying errors in the
data ingestion process Esppenchutz

https://textbookfull.com/product/data-ingestion-with-python-
cookbook-a-practical-guide-to-ingesting-monitoring-and-
identifying-errors-in-the-data-ingestion-process-esppenchutz/

R Data Mining Implement data mining techniques through


practical use cases and real world datasets 1st Edition
Andrea Cirillo

https://textbookfull.com/product/r-data-mining-implement-data-
mining-techniques-through-practical-use-cases-and-real-world-
datasets-1st-edition-andrea-cirillo/

Neural Data Science A Primer with MATLAB and Python


Erik Lee Nylen And Pascal Wallisch (Auth.)

https://textbookfull.com/product/neural-data-science-a-primer-
with-matlab-and-python-erik-lee-nylen-and-pascal-wallisch-auth/
SPRINGER BRIEFS IN INFORMATION SYSTEMS

Diogo R. Ferreira

A Primer on
Process Mining
Practical Skills with
Python and Graphviz
SpringerBriefs in Information Systems

Series editor
Jörg Becker
More information about this series at http://www.springer.com/series/10189
Diogo R. Ferreira

A Primer on
Process Mining
Practical Skills with
Python and Graphviz

123
Diogo R. Ferreira
Instituto Superior Técnico
University of Lisbon
Oeiras, Portugal

ISSN 2192-4929 ISSN 2192-4937 (electronic)


SpringerBriefs in Information Systems
ISBN 978-3-319-56426-5 ISBN 978-3-319-56427-2 (eBook)
DOI 10.1007/978-3-319-56427-2

Library of Congress Control Number: 2017938642

© The Author(s) 2017


This work is subject to copyright. All rights are reserved by the Publisher, whether the whole or part of
the material is concerned, specifically the rights of translation, reprinting, reuse of illustrations, recitation,
broadcasting, reproduction on microfilms or in any other physical way, and transmission or information
storage and retrieval, electronic adaptation, computer software, or by similar or dissimilar methodology
now known or hereafter developed.
The use of general descriptive names, registered names, trademarks, service marks, etc. in this publication
does not imply, even in the absence of a specific statement, that such names are exempt from the relevant
protective laws and regulations and therefore free for general use.
The publisher, the authors and the editors are safe to assume that the advice and information in this book
are believed to be true and accurate at the date of publication. Neither the publisher nor the authors or
the editors give a warranty, express or implied, with respect to the material contained herein or for any
errors or omissions that may have been made. The publisher remains neutral with regard to jurisdictional
claims in published maps and institutional affiliations.

Printed on acid-free paper

This Springer imprint is published by Springer Nature


The registered company is Springer International Publishing AG
The registered company address is: Gewerbestrasse 11, 6330 Cham, Switzerland
Preface

Over the years, I had to introduce a number of M.Sc. and Ph.D. students to the
topic of process mining. Invariably, it was difficult to find a concise introduction
to the topic, despite the fact that some of the fundamental ideas of process mining
are quite simple. In principle, it should not be necessary to go through a series of
research papers in order to get a good grasp of those ideas.
On the other hand, I did not want my students to start using ProM1 or Disco2
right away, without understanding what is happening behind the scenes. Instead, I
would prefer to provide them with the working knowledge that would allow them to
implement some simple process mining techniques on their own, even if only in a
rudimentary form. It always seemed to me that being able to implement something
is the best way to develop a solid understanding of a new topic.
The main goal of this book is to explain the core ideas of process mining and
to show how these ideas can be implemented using just some basic tools that are
available to any computer scientist or data scientist. One of such tools is the Python
programming language, which has become very popular since it allows writing
complex programs in a clear and concise form. Another tool that is very useful is the
Graphviz library, which is able to display graphs and automatically calculate their
layout without requiring the programmer to do so. Graphviz provides an effortless
way to visualize the results of many process mining techniques.
Before going further, some disclaimers are in order; namely, this book is not
meant to be a reference on process mining. In that sense, it would be very
incomplete, since we will be using only a simplified version of a very small subset
of process mining techniques. Also, the text does not delve into a wide variety of
process models that can be generated by those techniques. Here, we will be using

1
http://www.promtools.org/.
2
https://fluxicon.com/disco/.

v
vi Preface

graphs (both directed and undirected, but just plain graphs) without getting into
more sophisticated process modeling languages, such as Petri nets3 and BPMN.4
Nevertheless, this bare-bones approach should suffice to provide a feeling for
what process mining is, while developing some skills that will definitely be useful
in practice.
I prepared this text to be a very first introduction to process mining, and hence I
called it a primer. After this, the reader can jump more confidently to the existing
literature, namely the book by Wil van der Aalst,5 and the extensive set of research
publications in this field. I hope that this text will contribute towards a deeper
understanding of process mining tools and techniques.

Lisbon, Portugal Diogo R. Ferreira


February 2017

3
http://www.informatik.uni-hamburg.de/TGI/PetriNets/.
4
http://www.bpmn.org/.
5
See [18] in the list of references on page 95.
Contents

1 Event Logs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. . . . . . . . . . . . . . . . . . . . . 1
1.1 Process Model vs. Process Instances .. . . . . . . . . . . . . .. . . . . . . . . . . . . . . . . . . . . 2
1.2 Task Allocation.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. . . . . . . . . . . . . . . . . . . . . 3
1.3 Identifying the Process Instances. . . . . . . . . . . . . . . . . . .. . . . . . . . . . . . . . . . . . . . . 4
1.4 Recording Events in an Event Log . . . . . . . . . . . . . . . . .. . . . . . . . . . . . . . . . . . . . . 5
1.5 Event Logs in CSV Format .. . . . . . . . . . . . . . . . . . . . . . . .. . . . . . . . . . . . . . . . . . . . . 6
1.6 Reading an Event Log with Python . . . . . . . . . . . . . . . .. . . . . . . . . . . . . . . . . . . . . 7
1.7 Sorting an Event Log with Python . . . . . . . . . . . . . . . . .. . . . . . . . . . . . . . . . . . . . . 9
1.8 Reading the Event Log as a Dictionary . . . . . . . . . . . .. . . . . . . . . . . . . . . . . . . . . 11
1.9 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. . . . . . . . . . . . . . . . . . . . . 12
2 Control-Flow Perspective . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. . . . . . . . . . . . . . . . . . . . . 15
2.1 The Transition Matrix .. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. . . . . . . . . . . . . . . . . . . . . 15
2.2 The Control-Flow Algorithm .. . . . . . . . . . . . . . . . . . . . . .. . . . . . . . . . . . . . . . . . . . . 16
2.3 Implementation in Python . . . . . . . . . . . . . . . . . . . . . . . . . .. . . . . . . . . . . . . . . . . . . . . 17
2.4 Introducing Graphviz . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. . . . . . . . . . . . . . . . . . . . . 18
2.5 Using PyGraphviz.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. . . . . . . . . . . . . . . . . . . . . 20
2.6 Edge Thickness.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. . . . . . . . . . . . . . . . . . . . . 21
2.7 Activity Counts.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. . . . . . . . . . . . . . . . . . . . . 24
2.8 Node Coloring.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. . . . . . . . . . . . . . . . . . . . . 26
2.9 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. . . . . . . . . . . . . . . . . . . . . 28
3 Organizational Perspective . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. . . . . . . . . . . . . . . . . . . . . 31
3.1 Handover of Work.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. . . . . . . . . . . . . . . . . . . . . 31
3.2 Implementing Handover of Work . . . . . . . . . . . . . . . . . .. . . . . . . . . . . . . . . . . . . . . 32
3.3 Working Together . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. . . . . . . . . . . . . . . . . . . . . 34
3.4 Implementing Working Together .. . . . . . . . . . . . . . . . . .. . . . . . . . . . . . . . . . . . . . . 35
3.5 Undirected Graphs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. . . . . . . . . . . . . . . . . . . . . 37
3.6 Edge Thickness.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. . . . . . . . . . . . . . . . . . . . . 39
3.7 Users and Activities .. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. . . . . . . . . . . . . . . . . . . . . 40
3.8 Work Distribution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. . . . . . . . . . . . . . . . . . . . . 42
3.9 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. . . . . . . . . . . . . . . . . . . . . 44

vii
viii Contents

4 Performance Perspective . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. . . . . . . . . . . . . . . . . . . . . 47
4.1 Dates and Times in Python . . . . . . . . . . . . . . . . . . . . . . . . .. . . . . . . . . . . . . . . . . . . . . 47
4.2 Parsing the Timestamps .. . . . . . . . . . . . . . . . . . . . . . . . . . . .. . . . . . . . . . . . . . . . . . . . . 49
4.3 Average Timestamp Difference . . . . . . . . . . . . . . . . . . . .. . . . . . . . . . . . . . . . . . . . . 50
4.4 Drawing the Graph .. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. . . . . . . . . . . . . . . . . . . . . 52
4.5 Analyzing the Timeline of Events .. . . . . . . . . . . . . . . . .. . . . . . . . . . . . . . . . . . . . . 54
4.6 Plotting the Dotted Chart . . . . . . . . . . . . . . . . . . . . . . . . . . .. . . . . . . . . . . . . . . . . . . . . 55
4.7 Using Relative Time . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. . . . . . . . . . . . . . . . . . . . . 57
4.8 Activity Duration.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. . . . . . . . . . . . . . . . . . . . . 60
4.9 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. . . . . . . . . . . . . . . . . . . . . 63
5 Process Mining in Practice .. . . . . . . . . . . . . . . . . . . . . . . . . . . . .. . . . . . . . . . . . . . . . . . . . . 65
5.1 The BPI Challenge 2012 .. . . . . . . . . . . . . . . . . . . . . . . . . . .. . . . . . . . . . . . . . . . . . . . . 65
5.2 Understanding the XES Format . . . . . . . . . . . . . . . . . . . .. . . . . . . . . . . . . . . . . . . . . 68
5.3 Reading XES with Python .. . . . . . . . . . . . . . . . . . . . . . . . .. . . . . . . . . . . . . . . . . . . . . 70
5.4 Analyzing the Control-Flow Perspective . . . . . . . . . .. . . . . . . . . . . . . . . . . . . . . 72
5.5 Analyzing the Organizational Perspective . . . . . . . . .. . . . . . . . . . . . . . . . . . . . . 75
5.6 Analyzing the Performance Perspective . . . . . . . . . . .. . . . . . . . . . . . . . . . . . . . . 78
5.7 Process Mining with Disco . . . . . . . . . . . . . . . . . . . . . . . . .. . . . . . . . . . . . . . . . . . . . . 82
5.8 Process Mining with ProM . . . . . . . . . . . . . . . . . . . . . . . . .. . . . . . . . . . . . . . . . . . . . . 86
5.9 Conclusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. . . . . . . . . . . . . . . . . . . . . 93

References .. .. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. . . . . . . . . . . . . . . . . . . . . 95
Chapter 1
Event Logs

Organizations have information systems that record activities of interest, such as


the registration of a new customer, the sale of a product, the approval of a purchase
request, the processing of a payment, etc. All of these activities result in one or more
events being recorded in some information system.
In the past, such events were mainly used for the purpose of record-keeping,
accounting, auditing, etc. More recently, organizations have started leveraging those
data for business analytics, namely the kind of analysis that can be performed with
data warehouses and online analytical processing (OLAP).1
Process mining is concerned with a different goal: the aim of process mining is
to take advantage of event data in order to understand how an organization works.
For example, with process mining it is possible to discover the sequence of tasks
that are performed in a certain business process, and also the interactions that take
place between the participants in that process.
Analyzing business processes in this way is important for a number of reasons,
namely to assess the internal performance of an organization, to raise awareness of
how people work and how they interact with each other, and ultimately to identify
opportunities for efficiency improvements and better usage of resources.
The starting point for process mining is an event log. This event log may be the
actual log of some information system (e.g. the log file of an application server), or it
may be a log file that is built from historical data recorded in a database, for example.
Whatever the source, the data in an event log must have (or must be converted to)
a specific structure. The goal of this chapter is to explain that structure. However,
to understand why an event log has such structure, it is useful to introduce some
general concepts about business processes first.

1
For a reference on this topic, see e.g. [16].

© The Author(s) 2017 1


D.R. Ferreira, A Primer on Process Mining, SpringerBriefs in Information Systems,
DOI 10.1007/978-3-319-56427-2_1
2 1 Event Logs

c. Archive
request
e. Receive f. Update
product stock
No
a. Fill out
request
b. Approve
request
Yes d. Order
product + + h. Close
request

Requisition
approved? g. Handle
payment

Fig. 1 Example of a process model (adapted from [3]). Adapted from Computers in Industry, 70,
Ferreira, D.R., Vasilyev, E.: Using logical decision trees to discover the cause of process delays
from event logs, pp 194-207, © 2015, with permission from Elsevier

1.1 Process Model vs. Process Instances

It is often said that a business process is a set of activities which, collectively,


produce some output that is of value for a business organization or for its
customers.2 Our main interest here is to understand how the process unfolds over
time while being executed. In particular, it is common to think of a business process
as sequence of discrete steps, called activities.
An activity is a unit of work that makes sense from a business point of view. For
example, creating a purchase order or approving a purchase request are examples of
what could be seen as activities in a purchase process. Figure 1 shows an example
of how such process could look like.
Here, an employee fills out a request form (activity a) and sends it to a manager
for approval (activity b). If the request is not approved, it is archived (activity c) and
the process ends. If the request is approved, the product is ordered from a supplier
(activity d). Then two things happen at the same time: the warehouse receives
the product (activity e) and updates the stock (activity f ), while the accounting
department takes care of payment to the supplier (activity g). When these activities
are over, the request is closed (activity h), and the process ends.
Figure 1 shows a representation of the process that is usually called a process
model. It is a graphical, step-by-step description of the process in a form that is
similar to a flowchart. In this particular example, it is a model of what happens
when an employee wants to buy something.
The process model describes the sequence of activities in a general, abstract form.
Every time someone wants to buy something in this organization, there will be an
instance of this process for that particular purchase request.
The instances of this process may have different behaviors. For example, suppose
that there two purchase requests, where one is approved and the other is not. Then
these two instances will follow different paths in the model of Fig. 1: the first will
go through activity d and the second will end up in activity c.

2
For similar definitions, see [27] and [1].
1.2 Task Allocation 3

Even if two instances follow the same path, there may be differences in their
behavior. For example, since activity g is in parallel with e and f , it may happen that
g is performed before e and f in one instance, and in another instance it is performed
after e and f , or even in between them.
With process mining, it is possible to analyze how this process is performed in the
organization. This is useful for a number of different purposes, such as determining
the percentage of purchase requests that get approved, discovering the most frequent
sequences of activities, estimating the time that it takes for the process to complete,
etc. In addition, sometimes it happens that a process instance displays a behavior that
does not comply with the model, such as executing activities in a different order, or
even executing activities that are not in the original model.
It is in these scenarios that process mining becomes a valuable tool to discover
how the process is actually being executed, as opposed to how the process was
supposed to be executed. In some scenarios, it will be possible to compare the
behavior of a process model defined at design-time with the behavior of process
instances observed at run-time, and this is also a important topic of research in
the field of process mining.3 Here, we will be focusing mostly on the problem of
discovering the run-time behavior of business processes.

1.2 Task Allocation

Following the example of the purchase process above, one could imagine an
organization with many employees, with several people trying to buy things every
now and then, or even at the same time. The business process will be instantiated
multiple times, one for each purchase request, and several of those process instances
may be active simultaneously at any given point in time.
Suppose that in one process instance the product is being ordered, while in
another process instance the product has already been received, and in yet another
process instance the request is still waiting for approval, etc. All of these process
instances are active at the same time, as people are working on them.
Additionally, suppose that there are eight people (employees) involved in this
process. We will refer to them generically as users. If there are four process instances
to be executed, then the allocation of all of these activities to the eight users could
be as shown in Fig. 2.
In these four process instances, two of them get approved and the other two do
not. We leave it as an exercise for the reader to determine how many instances of
each activity a; b; : : : ; h are there to be performed.
Each instance of these activities will have to be performed by someone. We refer
to each of these activity instances as a task. Figure 2 shows how these tasks have
been distributed among users.

3
This topic is usually referred to as conformance checking [12].
4 1 Event Logs

e. Receiv e f. Update
c. Archive
product stock
request

a. Fil l out b. Approv e


a. Fil l out
request
b. Approv e
request
d. Order
product + + h. Close
request

request request g. Handle


pay ment

e. Receiv e f. Update
c. Archive
product stock
request

a. Fil l out
request
b. Approv e
request
d. Order
product + + h. Close
request

a. Fil l out b. Approv e


g. Handle request request
pay ment

c
a h b e
tasks
h c b g d f
a a b b d g e f
u1 u2 u3 u4 u5 u6 u7 u8

users

Fig. 2 Allocation of tasks to users

It appears that this distribution is somewhat unbalanced, and this may be due to
several reasons, such as the length or complexity of each task, the responsibilities
of each user, the fact that some users may not be available at a certain moment, etc.
There may be some level of unpredictability in the allocation of work.
Also, Fig. 2 shows the allocation of tasks to users as if all tasks had been pre-
assigned at once. In reality, such allocation is dynamic and it happens on-the-fly as
the process is being executed. Usually, tasks are assigned to users at the moment
when those tasks need to be performed. Typically, this occurs when the previous
task has been completed.
For example, if a purchase request is approved (as a result of activity b), then the
next activity is d and it will be necessary to assign a new task d to some user. On the
other hand, if the request is not approved, then the next activity to be assigned is c
and the choice of user may be different.
Task allocation is another aspect of business processes that can be analyzed
through process mining techniques. Namely, it is possible to discover the workload
assigned to each user, and also how users interact and collaborate with each other
when performing a business process, i.e. who passes work to whom and who works
together with whom on each process instance.

1.3 Identifying the Process Instances

In practice, every process instance has some kind of unique identifier. For example,
in a sales process, each order has a unique number; in a technical support process,
each reported problem has a ticket number; and so on.
1.4 Recording Events in an Event Log 5

Similarly, in the purchase process above, each purchase request will have a
unique number. The purpose of having a unique identifier is to be able to track
the status and progress of each process instance.
In the purchase process above, an employee will want to know whether a certain
purchase request has been approved or not. For that purpose, the unique identifier of
the purchase request must be provided in order to distinguish it from other purchase
requests. This applies to other kinds of business process as well. For example, in a
technical support process, it is usually required to provide an issue number in any
follow-up contacts regarding a previously reported problem.
In the context of process mining, the identifier of a process instance is usually
called the case id. The reason for this is that, in many business scenarios, each
process instance is referred to as a case, so the term case id became popular.
This may be easier to understand if we think in terms of a patient that goes to
a hospital, for example. There will be several tasks performed by different people
(nurses, doctors, etc.) while taking care of a patient. The patient is referred to as a
case, and of course there will be many different cases to take care of, as new patients
keep entering the hospital. In this context, treating a patient (i.e. handling a certain
case) is equivalent to executing an instance of some clinical process.
In the purchase process above, we can also look at each purchase request as a
different case that needs to be handled, and we can identify each process instance
by its case id, which is the purchase request number.

1.4 Recording Events in an Event Log

When a user performs a task in a process instance, this represents an event of interest
that should be recorded. Gathering such events will allow a subsequent analysis with
process mining techniques. When a significant number of such events have been
recorded, we refer to that collection of events as an event log.
For the purpose of process mining, each event that is recorded in an event log
should contain at least the following information:
• a case id, which identifies the process instance;
• a task name, which identifies the activity that has been performed;
• a user name, which identifies the participant who performed the task;
• a timestamp, which indicates the date and time when the task was completed.
Table 1 shows a sample event log that resulted from the execution of three
instances of the purchase process. The event log contains the four columns
mentioned above, and the events are presented in chronological order (increasing
timestamp), which reflects the order in which they were recorded.
The events from these three process instances are somewhat intertwined. Namely,
events from case id 1 are interspersed with events from case id 2, and the same
happens with the events from case ids 2 and 3. This often happens in practice, when
there are multiple process instances running concurrently.
6 1 Event Logs

Table 1 Example of an event Case id Task User Timestamp


log
1 a u1 2016-04-09 17:36:47
1 b u3 2016-04-11 09:11:13
1 d u6 2016-04-12 10:00:12
1 e u7 2016-04-12 18:21:32
1 f u8 2016-04-13 13:27:41
2 a u2 2016-04-14 08:56:09
2 b u3 2016-04-14 09:36:02
2 d u5 2016-04-15 10:16:40
1 g u6 2016-04-18 19:14:14
2 g u6 2016-04-19 15:39:15
1 h u2 2016-04-19 16:48:16
2 e u7 2016-04-20 14:39:45
2 f u8 2016-04-22 09:16:16
3 a u2 2016-04-25 08:39:24
2 h u1 2016-04-26 12:19:46
3 b u4 2016-04-29 10:56:14
3 c u1 2016-04-30 15:41:22

In this sample event log, the tasks and users have been abbreviated with a single
letter and number. This was done mostly for simplicity, but it should be noted
that task names and user names in an event log are somewhat arbitrary. In some
scenarios, they can be anonymized due to privacy reasons.
Regardless of the actual names, what matters is their relationships, such as the
order in which they appear in the event log, and whether they appear within the same
case id or not. It is these relationships that process mining techniques will focus on,
in order to discover the behavior of the business process.

1.5 Event Logs in CSV Format

In practice, an event log may take different forms. The simplest form is a text file,
but an event log may also be stored in the form of a database table, for example. In
any case, it should be possible to export an event log as a text file.
The most common format for storing and exporting event logs is the well-known
text format known as CSV (comma-separated values). This format is commonly
used in spreadsheet applications, for example.
In a CSV file, each event is usually stored in a single line, and the four fields (case
id, task, user, and timestamp) are separated by some punctuation symbol, usually a
comma (,). If the comma is used as a decimal symbol or as a digit grouping symbol,
then it is common to separate the fields by a semicolon (;) instead.
1.6 Reading an Event Log with Python 7

Listing 1 Event log in CSV format


1 1;a;u1;2016-04-09 17:36:47
2 1;b;u3;2016-04-11 09:11:13
3 1;d;u6;2016-04-12 10:00:12
4 1;e;u7;2016-04-12 18:21:32
5 1;f;u8;2016-04-13 13:27:41
6 2;a;u2;2016-04-14 08:56:09
7 2;b;u3;2016-04-14 09:36:02
8 2;d;u5;2016-04-15 10:16:40
9 1;g;u6;2016-04-18 19:14:14
10 2;g;u6;2016-04-19 15:39:15
11 1;h;u2;2016-04-19 16:48:16
12 2;e;u7;2016-04-20 14:39:45
13 2;f;u8;2016-04-22 09:16:16
14 3;a;u2;2016-04-25 08:39:24
15 2;h;u1;2016-04-26 12:19:46
16 3;b;u4;2016-04-29 10:56:14
17 3;c;u1;2016-04-30 15:41:22

Listing 1 shows the same event log as in Table 1, but now in CSV format. Fields
are separated by semicolons, so there should be no semicolon inside a field, or else
it will be interpreted as a separator.
To avoid this problem, the CSV format allows the use of text delimiters, typically
a double quote (") to enclose any field that might have symbols that could be
misinterpreted as a separator. However, unless the task names or user names are
allowed to contain such symbols, the use of text delimiters is not very common in
event logs that are used for process mining.

1.6 Reading an Event Log with Python

Reading an event log in Python is relatively simple (simpler than reading it in C, for
example) since the Python language has built-in data structures such as lists, tuples,
and dictionaries that facilitate most programming tasks.
The fundamental idea for reading an event log in CSV format is to open the
file, read it line by line, and split each line wherever the separator symbol is found.
Listing 2 shows how this can be done in Python.4
The code in Listing 2 opens the file for reading and then creates an empty list to
store the events that will be read from the file. A for-loop iterates through the file,
reading it line by line, until the end-of-file (EOF) is reached.
For each line fetched from the file, the first thing to do is to trim (strip) the line
of any leading and trailing whitespace characters. This is being done here to remove
the newline character at the end of each line.

4
We use Python 2 because, in most systems, the python command defaults to that version.
8 1 Event Logs

Listing 2 Reading and printing an event log


1 f = open('eventlog.csv', 'r')
2
3 log = []
4
5 for line in f:
6 line = line.strip()
7 if len(line) == 0:
8 continue
9 parts = line.split(';')
10 caseid = parts[0]
11 task = parts[1]
12 user = parts[2]
13 timestamp = parts[3]
14 event = (caseid, task, user, timestamp)
15 log.append(event)
16
17 f.close()
18
19 for (caseid, task, user, timestamp) in log:
20 print caseid, task, user, timestamp

Listing 3 Output of the previous script


1 1 a u1 2016-04-09 17:36:47
2 1 b u3 2016-04-11 09:11:13
3 1 d u6 2016-04-12 10:00:12
4 1 e u7 2016-04-12 18:21:32
5 1 f u8 2016-04-13 13:27:41
6 2 a u2 2016-04-14 08:56:09
7 2 b u3 2016-04-14 09:36:02
8 2 d u5 2016-04-15 10:16:40
9 1 g u6 2016-04-18 19:14:14
10 2 g u6 2016-04-19 15:39:15
11 1 h u2 2016-04-19 16:48:16
12 2 e u7 2016-04-20 14:39:45
13 2 f u8 2016-04-22 09:16:16
14 3 a u2 2016-04-25 08:39:24
15 2 h u1 2016-04-26 12:19:46
16 3 b u4 2016-04-29 10:56:14
17 3 c u1 2016-04-30 15:41:22

If, as a result of this trimming, the line becomes empty, then this is just a blank
line and we can proceed to the next line. Sometimes, there is a blank line at the end
of the log file, so it is a good idea to skip it instead of attempting to parse it.
If the line is not empty, the script assumes that it will be possible to split the line
into four parts that are separated by semicolon. The split() function returns a list
of parts, and each of those parts is assigned to a different variable. If the event log
contains additional columns, which sometimes happens in practice, then there will
be some extra parts that will remain unused.
The script then creates a tuple with those variables (line 14), and appends this
tuple to the list of events (line 15). After having done this for every line, the script
closes the file (this is important not to forget).
Finally, just for illustrative purposes, the script iterates through the list of events
and prints their contents. The output is shown in Listing 3.
1.7 Sorting an Event Log with Python 9

For more complicated event logs with text delimiters, escape characters, different
line terminators, etc., the Python language provides a built-in csv module5 that can
handle all those variants. The NumPy library6 and the Pandas library7 also have
powerful routines to read CSV files, but they are more geared towards numerical
applications. Anyway, this is just a matter of getting familiar with the documentation
for those modules and libraries, so we leave it to the interested reader to explore
further. Our main goal here is to focus on the fundamental ideas.

1.7 Sorting an Event Log with Python

Listing 3 shows that the event log is sorted by timestamp, and this is usually what
happens in practice, as events are recorded sequentially in the order in which they
occurred. However, for the purpose of process mining, it is often convenient to bring
together all the events that belong to the same case id.
Sorting the event log must be done carefully in order to keep the relative order of
events within the same case id. Consider what happens when running log.sort()
on the list created in Listing 2. The sort() method will sort the events by case id
and then, if two events have the same case id, it will sort them by task. As a result,
we could end up with the output shown in Listing 4.
Here, the sorting has changed the order of events in case id 2. While, in Listing 3,
case id 2 had the task transitions g ! e ! f , in Listing 4 the transitions are
e ! f ! g because these tasks have been brought into alphabetical order.
Clearly, we need to sort the events by case id and timestamp in order to keep the
relative order of events within the same case id. In Python, we can do this by telling
the sort() method which fields should be used for sorting.
The sort() method accepts a named argument called key. This key is a function
that is called on each element of the list prior to sorting them. The idea is to use
this function to do some processing on the element and return a key to be used
for sorting. The elements end up being sorted by the key returned by the function
instead of being sorted based on their original contents.
The syntax for doing this in Python involves a so-called lambda function. A
lambda function is an anonymous function that has simply a list of arguments and
an expression to compute its result. For example, the lambda function in Listing 5
computes the square of its argument.
Going back to our problem, we need to sort the event log by case id and
timestamp. For this purpose, it is possible to use a lambda function that extracts
the case id and timestamp from a given event. The case id and timestamp will be
used as key for sorting. Listing 6 shows how to do this.

5
https://docs.python.org/2/library/csv.html.
6
http://www.numpy.org/.
7
http://pandas.pydata.org/.
10 1 Event Logs

Listing 4 Wrong sorting of the event log by case id


1 1 a u1 2016-04-09 17:36:47
2 1 b u3 2016-04-11 09:11:13
3 1 d u6 2016-04-12 10:00:12
4 1 e u7 2016-04-12 18:21:32
5 1 f u8 2016-04-13 13:27:41
6 1 g u6 2016-04-18 19:14:14
7 1 h u2 2016-04-19 16:48:16
8 2 a u2 2016-04-14 08:56:09
9 2 b u3 2016-04-14 09:36:02
10 2 d u5 2016-04-15 10:16:40
11 2 e u7 2016-04-20 14:39:45
12 2 f u8 2016-04-22 09:16:16
13 2 g u6 2016-04-19 15:39:15 # this event is misplaced
14 2 h u1 2016-04-26 12:19:46
15 3 a u2 2016-04-25 08:39:24
16 3 b u4 2016-04-29 10:56:14
17 3 c u1 2016-04-30 15:41:22

Listing 5 A simple lambda function


1 f = lambda x: x**2
2 y = f(2) + f(3) # the result is 4 + 9 = 13
3 print y

Listing 6 Sorting with a lambda function


1 log.sort(key = lambda event: (event[0], event[-1]))

Listing 7 Correct sorting of the event log by case id and timestamp


1 1 a u1 2016-04-09 17:36:47
2 1 b u3 2016-04-11 09:11:13
3 1 d u6 2016-04-12 10:00:12
4 1 e u7 2016-04-12 18:21:32
5 1 f u8 2016-04-13 13:27:41
6 1 g u6 2016-04-18 19:14:14
7 1 h u2 2016-04-19 16:48:16
8 2 a u2 2016-04-14 08:56:09
9 2 b u3 2016-04-14 09:36:02
10 2 d u5 2016-04-15 10:16:40
11 2 g u6 2016-04-19 15:39:15
12 2 e u7 2016-04-20 14:39:45
13 2 f u8 2016-04-22 09:16:16
14 2 h u1 2016-04-26 12:19:46
15 3 a u2 2016-04-25 08:39:24
16 3 b u4 2016-04-29 10:56:14
17 3 c u1 2016-04-30 15:41:22

Basically, the lambda function receives an event and returns a tuple containing
the case id and the timestamp from that event. Remember that an event is a 4-tuple
containing a case id, task, user, and timestamp. The lambda function retrieves only
the first and the last fields from that tuple, packs them into a 2-tuple, and returns this
as a key to be used for sorting.
As a result of this sorting, we get the correct result shown in Listing 7. Of course,
if we want to get back to the event log sorted globally by timestamp, we can use a
lambda function that returns only the timestamp from each event.
1.8 Reading the Event Log as a Dictionary 11

1.8 Reading the Event Log as a Dictionary

Another way to bring together the events that belong to the same case id is to read
the event log into a dictionary, instead of reading it into a list.
Similarly to a list, a Python dictionary is a data structure that holds a collection of
items. However, instead of having each item at certain position, in a dictionary each
item is associated with a certain key. A key and its corresponding item are usually
referred to as a key-value pair (even though the “value” here may be a complex data
structure). A dictionary is a collection of key-value pairs.
To bring together events within the same case id, the idea is to use the case id as
key. Associated with that key, there will be a list of events (i.e. the item or “value”
associated with the key is actually a list of events). In other words, each case id
(serving here as key) will be associated with the list of events that belong to that
case id. Naturally, this list of events must be sorted by timestamp.
Listing 8 shows how the events can be read into a dictionary.
The code is very similar to Listing 2 on page 8, but has the following differ-
ences:
• The log variable is now initialized as a dict() rather than as a list ([]).
• For each line that is read from the log file, it is necessary to check if the case id
already exists in the dictionary. If it does not exist (line 14), then a new key is
inserted into the dictionary (line 15). The list of events associated with this key
is initially empty.
• In contrast to Listing 2, each event is now a 3-tuple with task, user, and timestamp
(line 16). The event is appended to the list of events associated with the case id
(line 17).

Listing 8 Reading and printing an event log with a dictionary


1 f = open('eventlog.csv', 'r')
2
3 log = dict()
4
5 for line in f:
6 line = line.strip()
7 if len(line) == 0:
8 continue
9 parts = line.split(';')
10 caseid = parts[0]
11 task = parts[1]
12 user = parts[2]
13 timestamp = parts[3]
14 if caseid not in log:
15 log[caseid] = []
16 event = (task, user, timestamp)
17 log[caseid].append(event)
18
19 f.close()
20
21 for caseid in log:
22 for (task, user, timestamp) in log[caseid]:
23 print caseid, task, user, timestamp
12 1 Event Logs

Listing 9 Output of the previous script


1 1 a u1 2016-04-09 17:36:47
2 1 b u3 2016-04-11 09:11:13
3 1 d u6 2016-04-12 10:00:12
4 1 e u7 2016-04-12 18:21:32
5 1 f u8 2016-04-13 13:27:41
6 1 g u6 2016-04-18 19:14:14
7 1 h u2 2016-04-19 16:48:16
8 3 a u2 2016-04-25 08:39:24
9 3 b u4 2016-04-29 10:56:14
10 3 c u1 2016-04-30 15:41:22
11 2 a u2 2016-04-14 08:56:09
12 2 b u3 2016-04-14 09:36:02
13 2 d u5 2016-04-15 10:16:40
14 2 g u6 2016-04-19 15:39:15
15 2 e u7 2016-04-20 14:39:45
16 2 f u8 2016-04-22 09:16:16
17 2 h u1 2016-04-26 12:19:46

Listing 10 Sorting the output by caseid and the events by timestamp


1 for caseid in sorted(log.keys()):
2 log[caseid].sort(key = lambda event: event[-1])
3 for (task, user, timestamp) in log[caseid]:
4 print caseid, task, user, timestamp

• When iterating through the event log, we need to go through each key (line 21)
and then go through the list of events associated with that key (line 22).
The output of this script is shown in Listing 9. Note that case id 3 appears before
case id 2 because, in a dictionary, keys have no particular order. However, events
within the same case id appear together as desired.
If, for some reason, we would like to sort this output by case id (only the output,
not the dictionary itself), then this can be done by using a list of sorted keys, as
shown in Listing 10 (line 1).
For completeness, Listing 10 also includes an instruction to make sure that the
list of events for each case id is sorted by timestamp (line 2). This sorting is being
done in-place (i.e. by changing the list itself). The output of this code is the same as
in Listing 7.

1.9 Summary

Before we proceed to the next chapter, here is a recap of the main points so far:
• Business processes are often represented as graphical models that specify the
sequences of activities that are expected to be performed at run-time.
• A single process model may give origin to many process instances at run-time,
with variations in their behavior and in their participants.
• Tasks are assigned to users in a non-deterministic way, depending on the
conditions that are found at run-time when a process instance is being executed.
1.9 Summary 13

• Process mining is a means to analyze the run-time behavior of process instances,


in terms of their sequence of tasks and participating users.
• Each process instance is identified by a unique case id.
• An event log is a list of recorded events, where each event contains a case id,
task, user, and timestamp.
• When events logs are stored in CSV format, they can be easily parsed with the
split() function available in Python.
• An event log can be loaded as list of events, or as a dictionary where the key is
the case id and the value is the list of events associated with that case id.
• Events should be sorted by caseid and timestamp. This can be done in Python
with the sort() method and a lambda function.
Chapter 2
Control-Flow Perspective

The control-flow perspective is a type of analysis that focuses on the discovery of


the sequence of activities in a business process. The idea is that by analyzing how
tasks follow each other in the event log, it should be possible to come up with a
model that describes the overall behavior of the process.
There are several algorithms to discover the sequential behavior of a process,
with notable examples being the ˛-algorithm [19], the heuristics miner [25], the
genetic miner [9], and the fuzzy miner [4]. These algorithms employ different
approaches to arrive at essentially the same result, which is a model that depicts
the transitions between tasks.
The simplest way to do this is as follows: every time task a is followed by task b,
we count that transition. We do this for all pairs of consecutive tasks within the same
case id. (Transitions between tasks in different case ids do not count.) Doing this
across the whole event log will provide a count of how many times each transition
has occurred. Then, it is possible to combine these transitions in order to generate
an output graph that captures the sequential behavior of the process.
This idea is the essence of many control-flow algorithms. Rather than looking at
a range of different algorithms and their specific details, here we will focus on this
single fundamental idea. Armed with a good understanding of how this idea can be
implemented, the interested reader will find it easier to get acquainted with more
advanced algorithms in the field of process mining.

2.1 The Transition Matrix

As stated above, we will be looking at a simple version of a control-flow algorithm.


This algorithm will work with case ids and tasks. The algorithm will be described
mainly in abstract terms, meaning that we will refer to examples of tasks such as

© The Author(s) 2017 15


D.R. Ferreira, A Primer on Process Mining, SpringerBriefs in Information Systems,
DOI 10.1007/978-3-319-56427-2_2
16 2 Control-Flow Perspective

a and b without implying a connection to the purchase process from the previous
chapter. In the present context, a, b, c, etc., are just some arbitrary tasks.
Let us think for a moment on how we should store the information about the
transitions between these tasks. Before analyzing the event log, we do not know
which transitions have actually occurred, so we can only assume that any transition
between those activities is possible. If we have N activities, then there are N 2
possible transitions between these activities. For example, with three activities
fa; b; cg there are nine possible transitions, namely:

fa ! a; a ! b; a ! c; b ! a; b ! b; b ! c; c ! a; c ! b; c ! cg

To store the count of how many times each transition has occurred, it becomes
more convenient to represent these transitions in matrix form:

a b c
a
b
c

The nine cells in this matrix can be used to store the count of each transition.
This is called the transition matrix. The goal of the control-flow algorithm is to go
through the event log and to fill in this transition matrix with a count in each cell.
In particular, the transition matrix should be read in the following way: if in row
i we find activity a and in column j we find activity b, then the cell .i; j/ contains the
number of times that transition a ! b has been observed.
To formally describe the algorithm, it becomes more convenient to use the
notation ai for the activity in row i and aj for the activity in column j. The activities
are then fa1 ; a2 ; a3 ; : : :g and the transition matrix has the following form:

a1 a2 a3 : : :
a1
a2
a3
:::

2.2 The Control-Flow Algorithm

Let T be the set of distinct tasks recorded in an event log, and let jTj be the size of
that set. For example, if T D fa; b; c; d; e; f ; g; hg then jTj D 8.
In mathematical terms, the transition matrix is a function f W T T ! N0 which
gives the number of times that each possible transition between a pair of activities
2.3 Implementation in Python 17

Algorithm 1 Control-flow algorithm


1: Let F be a square matrix of size jTj2
2: Initialize Fij 0 for every position .i; j/
3: for each case id in the event log do
4: for each consecutive task transition ai ! aj in that case id do
5: Fij Fij C1
6: end for
7: end for

in T has been observed. The objective of the control-flow algorithm is to find all the
values for this function.
This can be done by initializing a transition matrix of size jTj2 with zeros. As we
go through the event log, every time a transition ai ! aj is observed, we increment
the value at position .i; j/ in the matrix. Algorithm 1 describes this procedure.
Since the values in matrix F are obtained through a counting procedure, we will
refer to those values as the transition counts.

2.3 Implementation in Python

There are several ways to implement the above algorithm in Python. The main
decision is which data structure should be used to store the transition matrix. The
matrix is bi-dimensional, so it makes sense to use a data structure that can be indexed
twice (for rows and columns). With the built-in data structures available in Python,
the natural choices are: a list of lists, or a dictionary of dictionaries.
Using a list of lists would involve indexing by position and it would require
having a value stored at each position, even if the corresponding transition never
occurs in the event log (those positions would remain with zero). This is what could
be called a dense representation of the transition matrix.
On the other hand, using a dictionary of dictionaries allows us to index by task
name and we have to introduce only the keys that correspond to the transitions that
actually occur in the event log. This is what could be called a sparse representation
of the transition matrix.
Given that the size of a full transition matrix is jTj2 but probably only a subset of
all possible transitions will be observed, it makes sense to use a sparse representation
which avoids having to store a relatively large amount of zeros. With these issues in
mind, here we will show how to implement the transition matrix as a dictionary of
dictionaries.
Also, we assume that the event log has been read into a dictionary as in Listing 8
on page 11. After that, we could write the code shown in Listing 11.
At the beginning of this code, the matrix F is initialized as a dictionary. Then the
script iterates through each case id in the log, and also through the list of events for
that case id. Here, ai and aj are two variables that hold a pair of consecutive tasks.
18 2 Control-Flow Perspective

Listing 11 Implementing the control-flow algorithm in Python


1 F = dict()
2 for caseid in log:
3 for i in range(0, len(log[caseid])-1):
4 ai = log[caseid][i][0]
5 aj = log[caseid][i+1][0]
6 if ai not in F:
7 F[ai] = dict()
8 if aj not in F[ai]:
9 F[ai][aj] = 0
10 F[ai][aj] += 1
11
12 for ai in sorted(F.keys()):
13 for aj in sorted(F[ai].keys()):
14 print ai, '->', aj, ':', F[ai][aj]

Listing 12 Output of the previous script


1 a -> b : 3
2 b -> c : 1
3 b -> d : 2
4 d -> e : 1
5 d -> g : 1
6 e -> f : 2
7 f -> g : 1
8 f -> h : 1
9 g -> e : 1
10 g -> h : 1

If ai is not present in the matrix (line 6), then that row is initialized as a
dictionary. If aj is not present in that row (line 8), then that position is initialized
with zero. Immediately after this, and regardless of any initialization that might have
been done before, the value at that position is incremented (line 10).
The rest of the script shows how to iterate through the matrix and print its
contents. For every row ai and column aj (with both being sorted in alphabetical
order), the script prints the value at position F[ai][aj]. The output of this code for
the event log in Listing 1 on page 7 is shown in Listing 12.

2.4 Introducing Graphviz

Graphviz1 is a wonderful piece of software. It can save enormous amounts of work


when creating graphs, since it takes care of the graph layout automatically. Graphviz
is very often used to visualize the results of process mining techniques.
To provide an idea of what Graphviz does, we will start with a simple example
in Listing 13. This is a text-based definition of a directed graph. Graphviz supports
both directed and undirected graphs, and this is a matter of specifying digraph or
graph at the beginning of the definition.

1
http://www.graphviz.org/.
2.4 Introducing Graphviz 19

Listing 13 Definition of a directed graph in Graphviz’s DOT language


1 digraph G {
2 rankdir=LR;
3 node [shape=box];
4 a -> b [label="3"];
5 b -> c [label="1"];
6 b -> d [label="2"];
7 d -> e [label="1"];
8 d -> g [label="1"];
9 e -> f [label="2"];
10 f -> g [label="1"];
11 f -> h [label="1"];
12 g -> e [label="1"];
13 g -> h [label="1"];
14 }

The graph has a name (in this case, G) and its structure comprises a series of
statements enclosed in curly braces ({. . . }) and separated by semicolons (;). Each
statement adds a piece of information to the graph definition.
The first statement rankdir=LR establishes the graph orientation from left to
right (the default is TB, i.e. top to bottom). The second statement says something
about the nodes in this graph. In particular, it says that the shape of nodes is a
box (rectangle). Technically, shape is an attribute of node, and it can be specified
individually for each node (in order to have nodes with different shapes, for
example). However, here the shape is being specified globally for every node.
The remaining statements define the edges in the graph. It should be noted that in
this example the nodes being are defined implicitly by the edges, i.e. the statement
a->b defines an edge between nodes a and b and, implicitly, it also defines the nodes
a and b since they have not been defined before.
Nodes and edges can also be defined separately. A common practice is to first
define nodes and their attributes, and only then define the edges between those
nodes. In the example of Listing 13, the edges and their attributes are being defined.
In this simple example, only one edge attribute (label) is being used.
With the label attribute, we are attaching a label to each edge. A possible use
for that label is to annotate the edges with the transition counts provided by the
control-flow algorithm.
Generating a graph from the definition in Listing 13 is as simple as running a
command such as: dot -Tpng listing13.gv -o graph.png.2 In this command,
dot is the Graphviz tool that calculates the graph layout and produces an image.
Several image formats are supported, including both raster graphics (e.g. PNG,
JPEG) and vector graphics (e.g. SVG).
Figure 3 shows the output generated by Graphviz. Note how Graphviz has
automatically decided on the positioning of each node and has also carefully
rendered the edges and their labels without any crossings or overlaps.

2
To be able to run this command, you may have to install Graphviz first. In Ubuntu, Graphviz can
be installed with: sudo apt-get install graphviz.
20 2 Control-Flow Perspective

1 c
3
a b
2
1
d 1
e 1
g
2 1 1
1 h
f

Fig. 3 Output generated by Graphviz from the definition in Listing 13

Finally, note how this graph depicts the behavior of the process show in Fig. 1 on
page 2. Naturally, this graph is not as expressive as a full-fledged process modeling
language, but it certainly captures the run-time behavior of the process from the
information recorded in the event log.

2.5 Using PyGraphviz

There are several ways in which one can use Python and Graphviz together. Python
is a good language to implement process mining algorithms, and Graphviz is a great
tool to visualize the results. The question now is how to plug these tools together in
order to generate the graph from the results of the control-flow algorithm.
The simplest solution would be to modify the Python code in Listing 11 on
page 18 to print the graph definition. After all, that Python script is already
generating the output in Listing 12. With a few tweaks, it could as well generate
the graph definition in Listing 13, which is not much different.
However, it can be a bit cumbersome to have complex graph definitions being
generated with print instructions in Python. In addition, this would still require
running dot manually in the command line in order to generate the graph.
A more elegant solution is to use a Python interface for Graphviz, such as pydot3
or PyGraphviz.4 Here, we use PyGraphviz which, at the time of this writing, has
been in active development in recent years.5
Listing 14 shows how to build and generate the graph, assuming that the
transition matrix has already been created by Listing 11 on page 18.

3
https://pypi.python.org/pypi/pydot/.
4
https://pypi.python.org/pypi/pygraphviz/.
5
In order to use PyGraphviz, you may have to install it first. In Ubuntu, it can be installed with:
sudo apt-get install python-pygraphviz.
2.6 Edge Thickness 21

Listing 14 Generating the output graph with PyGraphviz


1 import pygraphviz as pgv
2
3 G = pgv.AGraph(strict=False, directed=True)
4
5 G.graph_attr['rankdir'] = 'LR'
6 G.node_attr['shape'] = 'box'
7
8 for ai in F:
9 for aj in F[ai]:
10 G.add_edge(ai, aj, label=F[ai][aj])
11
12 G.draw('graph.png', prog='dot')

The script starts by importing PyGraphviz and then creates a directed graph,
as indicated by directed=True. The strict argument, if true, imposes certain
restrictions, such as not allowing self-loops and multiple edges between the same
pair of nodes. However, here we may have self-loops (i.e. transitions between the
same activity), so we do not impose such restrictions.
In lines 5–6, the script sets the graph attribute rankdir and the node attribute
shape in a similar way to what was done in Listing 13.
The most important part comes in lines 8–10 where the script iterates through the
rows and columns in the transition matrix F and adds an edge for each transition.
The edge is labeled with the transition count stored in the matrix.
Finally, in line 12 the script draws the graph by invoking the dot program, and
saves it into an image file.
Behind the scenes, PyGraphviz generates a graph definition that is very similar
to the one presented in Listing 13. The interested reader may want to try adding the
instruction print G.string() to the code in Listing 14 to see the graph definition
generated by PyGraphviz, and compare it to Listing 13.

2.6 Edge Thickness

It often happens in practice that the event log to be analyzed is quite large and
the resulting graph has a lot of edges with different transition counts, some being
relatively large and others being relatively small.
By labeling each edge with the corresponding transition count, as in Fig. 3, it
is possible to identify the most frequent transitions, but it still requires us to have
a look at every label in order to compare those transitions and to determine, for
example, which transition is the most frequent one.
Exploring the Variety of Random
Documents with Different Content
The Project Gutenberg eBook of Report on the Radiolaria
Collected by H.M.S. Challenger During the Years 1873-
1876, Plates
This ebook is for the use of anyone anywhere in the United States and most other
parts of the world at no cost and with almost no restrictions whatsoever. You may
copy it, give it away or re-use it under the terms of the Project Gutenberg License
included with this ebook or online at www.gutenberg.org. If you are not located in
the United States, you will have to check the laws of the country where you are
located before using this eBook.

Title: Report on the Radiolaria Collected by H.M.S. Challenger During the Years
1873-1876, Plates

Author: Ernst Haeckel

Release date: December 28, 2013 [eBook #44527]


Most recently updated: October 23, 2024

Language: English

Credits: E-text prepared by Charlene Taylor, Adrian Mastronardi, Keith Edkins, and
the Online Distributed Proofreading Team (http://www.pgdp.net) from
page images generously made available by Internet Archive
(https://archive.org)

*** START OF THE PROJECT GUTENBERG EBOOK REPORT ON THE RADIOLARIA


COLLECTED BY H.M.S. CHALLENGER DURING THE YEARS 1873-1876, PLATES ***
The Project Gutenberg eBook, Report on the Radiolaria Collected
by H.M.S. Challenger During the Years 1873-1876, Plates, by
Ernst Haeckel

Note: Images of the original pages are available through


Internet Archive. See
https://archive.org/details/reportonradiolar00haecrich

Project Gutenberg has the other two volumes of this


work.
First Part: Porulosa (Spumellaria and Acantharia): see
http://www.gutenberg.org/files/44525/44525-
h/44525-h.htm
Second Part: Subclass Osculosa; Index: see
http://www.gutenberg.org/files/44526/44526-
h/44526-h.htm

Transcriber's Some typographical errors in the printed work


note: have been corrected. The corrected text is
underscored in red like this. Hover the cursor
over the marked text and the explanation
should appear.

Click on any illustration to enlarge it.


REPORT
ON THE

S C I E N T I F I C R E S U LT S

OF THE

VOYAGE OF H.M.S. CHALLENGER


DURING THE YEARS 1873-76

UNDER THE COMMAND OF

Captain GEORGE S. NARES, R.N., F.R.S


AND THE LATE

Captain FRANK TOURLE THOMSON, R.N

PREPARED UNDER THE SUPERINTENDENCE OF

THE LATE
Sir C. WYVILLE THOMSON, Knt., F.R.S., &c
REGIUS PROFESSOR OF NATURAL HISTORY IN THE UNIVERSITY OF EDINBURGH

DIRECTOR OF THE CIVILIAN SCIENTIFIC STAFF ON BOARD


AND NOW OF

JOHN MURRAY
ONE OF THE NATURALISTS OF THE EXPEDITION

Zoology—Vol. XVIII.
PLATES

Published by Order of Her Majesty's Government

PRINTED FOR HER MAJESTY'S STATIONERY OFFICE

AND SOLD BY

LONDON:—EYRE & SPOTTISWOODE, EAST HARDING STREET, FETTER LANE

EDINBURGH:—ADAM & CHARLES BLACK

DUBLIN:—HODGES, FIGGIS, & CO

1887

Price (in Two Parts, with a Volume of Plates) £5, 10s.

CONTENTS.
Report on the Radiolaria collected by H.M.S. Challenger during the
years 1873-1876.

By Ernst Haeckel, M.D., Ph.D., Professor of Zoology in the


University of Jena.

PLATES.

CONTENTS.

PLATES 1- SPUMELLARIA.
50.
" 51- NASSELLARIA.
98.
" 99- PHÆODARIA.
128.
" 129- ACANTHARIA.
140.
MAP, showing the Geographical Distribution of the Radiolaria.

PLATE 1.

Legion SPUMELLARIA.

Order COLLOIDEA.

Family T h a l a s s i c o l l i d a .
PLATE 1.
Thalassicollida.
Diam. Page.

Fig. 1. Actissa princeps,


n. sp., × 300 13
The entire living
Spumellarium. c, The
spherical central capsule
containing finely
granulated protoplasm,
which is radially striated
in the cortical zone; v,
spherical vacuoles
enclosed by the
protoplasm; n, the
spherical nucleus in the
centre; l, the concentric
nucleolus; f, the radial
pseudopodia which
pierce the calymma or
the (yellowish) jelly-
envelope of the central
capsule and arise from
the granular
sarcomatrix.
Fig. 1a. Half of the central
capsule of another
specimen, in which the
original central nucleus
is cleft into numerous
small nuclei, × 400
Fig. 1b. Half of the central
capsule of another
specimen, filled up by
flagellate spores, × 400
Fig. 1c. Eight isolated
flagellate spores, × 800

Fig. 2. Thalassolampe
maxima, n. sp., × 8 17
The entire living
Spumellarium. c, The
big spherical central
capsule; a, the large
alveoles filling the
central capsule and
surrounding a central
nucleus; f, the
pseudopodia piercing
the extracapsular
calymma.
Fig. 2a. The nucleus
alone, with numerous
nucleoli, × 30

Fig. 3. Thalassopila
cladococcus, n. sp., × 20 17
c, The big central capsule;
a, numerous large
alveoles contained in
the central capsule; k,
oil globules, many of
which are placed in the
radially striped cortical
zone; the nucleus
placed centrally, is
covered with numerous
radial apophyses or
cæcal sacs. f, The
radially striped
calymma.

Fig. 4. Thalassicolla
maculata, n. sp., × 100 21
c, The central capsule; v,
vacuoles filling this
capsule; n, the central
nucleus; l, the
concentric nucleolus; g,
the voluminous
calymma, a small radial
piece of which is only
represented; a, the
large alveoles; b,
peculiar exoplasmatic
bodies; p, black pigment
in the inner zone; f, the
retracted pseudopodia
in the outer zone.
Fig. 4a. An exoplasmatic
body, × 300
Fig. 4b, Vacuoles in the
endoplasm, × 300
Fig. 5. Thalassicolla
melacapsa, n. sp., × 300 21
n, The large nucleus; l,
numerous small nucleoli
inside the nucleus; v,
the vacuoles filling up
the central capsule and
separated by black
pigment; a, large
alveoles in the
calymma; k, oil
globules; b,
exoplasmatic bodies; f,
the retracted
pseudopodia in the
outer zone of the
calymma.
Fig. 5a. An endoplasmatic
vacuole, resembling a
cell, × 600
Fig. 5b. A piece of the
central capsule, × 600

PLATE 2.

Legion SPUMELLARIA.

Order BELOIDEA.

Family T h a l a s s o s p h æ r i d a .
PLATE 2.
Thalassosphærida.
Diam. Page.

Fig. 1. Lampoxanthium
pandora, n. sp., × 120 38
The central capsule
exhibits distinct pore-
canals in its membrane,
and a clear interval
between this and the
coagulated and
vacuolated protoplasm.
The central nucleus
contains numerous dark
nucleoli. The spicula are
scattered throughout
the alveolate calymma.

Fig. 2. Thalassoplancta
brevispicula, n. sp. (vel
Lampoxanthium
brevispiculum), × 120 36
The central capsule
contains numerous clear
vacuoles, and in the
cortical zone a layer of
large oil-globules. The
central nucleus includes
numerous dark nucleoli.
The calymma is
alveolate. The spicula lie
only in the cortical zone.

Fig. 3.
Thalassoxanthium
cervicorne, n. sp., × 300 33
The central capsule is
filled up by clear
vacuoles and contains a
large central nucleus,
with a single nucleolus.
The spicula surround
the thin calymma.

Fig. 4. × 600 33
Thalassoxanthium
cervicorne, n. sp.,
A single spiculum.

Fig. 5.
Thalassoxanthium
medusinum, n. sp., × 120 32
The central capsule is
filled up by clear
vacuoles and contains
on its cortical zone a
layer of large oil-
globules. The central
nucleus contains
numerous dark nucleoli.
The calymma is radially
striped, contains
numerous small
xanthellæ, and is
surrounded by the
spicula.

Fig. 6.
Thalassoxanthium
octoceras, n. sp., × 400 34
Three isolated spicula.

PLATE 3.

Legion SPUMELLARIA.

Order COLLOIDEA.

Family C o l l o z o i d a .
PLATE 3.
Collozoida.
Diam. Page.

Fig. 1. Collozoum
serpentinum, n sp (vel
Collophidium
serpentinum, Hkl), × 10 26
A living cœnobium, with
expanded pseudopodia.
The spherical calymma
(or the common jelly-
mass of the colony) is
alveolate and contains
numerous cylindrical,
serpentine, central
capsules. Numerous
yellow cells or xanthellæ
are scattered between
the radial pseudopodia
in the periphery.

Fig. 2. Collozoum
serpentinum, n. sp., × 50 26
An isolated, cylindrical,
worm-shaped, central
capsule, with an axial
series of oil-globules;
the red points are
nuclei.

Fig. 3. Collozoum
serpentinum, n. sp., × 150 26
An isolated, cylindrical,
serpentine, central
capsule. k, Oil-globules
forming an axial series;
n, densely placed, red-
coloured nuclei;, c, the
capsule membrane
under which are
scattered small black
pigment spots in the
colourless cortical zone
of the endoplasm; a,
extracapsular alveoles;
x, xanthellæ or "yellow
cells."

Fig. 4. Collozoum
amœboides, n. sp., × 100 28
A spherical cœnobium or
jelly-colony. Each
amœboid central
capsule contains an oil-
globule; the small red
points are nuclei.

Fig. 5. Collozoum
amœboides, n. sp., × 400 28
c, A single isolated central
capsule; n, nuclei; k, oil-
globule.

Fig. 6. Collozoum
vermiforme, n. sp., × 30 27
g, A spherical cœnobium
or jelly-colony; a, large
alveoles, forming a
cortical zone; c, central
capsules; k, oil-globules.

Fig. 7. Collozoum
vermiforme, n. sp., × 100 27
c, A single isolated central
capsule; x, xanthellæ
surrounding this central
capsule; k, oil-globules;
n, nuclei.

Fig. 8. Collozoum
ellipsoides, n. sp., × 2 26
A spherical colony; the red
points are central
capsules.

Fig. 9. Collozoum
ellipsoides, n. sp., × 150 26
c, A single isolated central
capsule; k, oil-globules;
n, nuclei.
Fig. 10. Collozoum
inerme, Hkl., × 2 25
An old, cylindrical,
articulated cœnobium;
the red points are
centralcapsules.

Fig. 11. Collozoum


inerme, Hkl., × 2 25
A young cylindrical
cœnobium; the red
points are central
capsules.

Fig. 12. Collozoum


inerme, Hkl., × 400 25
A piece of a young colony
with eight small central
capsules, without oil-
globules. n, The central
nucleus in different
stages of division. Two
capsules are also
dividing. x, Xanthellæ in
the jelly-like calymma
(blue), which also
contains numerous
vacuoles.

PLATE 4.

Legion SPUMELLARIA.

Orders BELOIDEA.

Families Sphærozoida.
PLATE 4.
Sphærozoida
Diam. Page.

Fig. 1. Sphærozoum
trigeminum, n. sp., × 50 43
An annular colony. The
main mass of the jelly-
colony is filled up by
large alveoles; the
entire surface is densely
covered with spicula,
and beyond this
skeleton-cover lie the
spherical central
capsules, each with an
oil-globule. This species
is by mistake not
mentioned in the text.

Fig. 2. Sphærozoum
alveolatum, n. sp., × 50 43
Section through a
spherical colony;
displaying the inside of
a hemisphere. All the
central capsules lie in a
single stratum on the
surface of the jelly-
sphere, each being
surrounded by a thick-
walled alveole. The
spicula lie between the
alveole and the capsule,
which includes a central
oil-globule.

Fig. 3. Sphærozoum
alveolatum, n. sp., × 400 43
A single central capsule,
filled up by crystal-
spores. Numerous
geminato-radiate spicula
and spherical xanthellæ
lie between the capsule
and the including thick-
walled alveole. In the
jelly-calymma, between
the capsule and the
alveole, numerous thin
ramified pseudopodia
are expanded.

Fig. 4. Sphærozoum
geminatum, n. sp., × 400 45
A single central capsule,
with a central oil-
globule, surrounded by
numerous spicula and
spherical xanthellæ. The
jelly-substance of the
calymma is expanded
between the points of
the spicula.

Fig. 5. Sphærozoum
variabile, n. sp., × 300 45
Three isolated spicula.

Fig. 6. Sphærozoum
pandora, n. sp. (vel
Rhaphidozoum
pandora), × 300 49
A group of various spicula.

Fig. 7. Sphærozoum
verticillatum, n. sp., × 300 44
A single spiculum.

Fig. 8. Sphærozoum
arborescens, n. sp., × 300 44
A single spiculum.

Fig. 9. Sphærozoum
armatum, n. sp., × 300 43
A single spiculum.

PLATE 5.

Legion SPUMELLARIA.
Order SPHÆROIDEA.

Family C o l l o s p h æ r i d a .

PLATE 5.
Collosphærida.
Diam. Page.

Fig. 1. Trypanosphæra
transformata, n. sp., × 150 111
A living colony. The centre
of the spherical
cœnobium contains a
large alveole,
surrounded by a net of
sarcode. The entire
calymma is filled up by
smaller, thin-walled
alveoles. Its inner part
contains numerous
small, young, central
capsules (each with an
oil-globule) without
shells; in the cortical
zone of the calymma lie
larger capsules, each of
which is enclosed by a
fenestrated shell with
from two to four or
more dentated tubes.
Between the radiant
pseudopodia very
numerous small yellow
cells (xanthellæ), which
are scattered
everywhere.

Fig. 2. Trypanosphæra
transformata, n. sp., × 300 111
A single shell.

Fig. 3. Trypanosphæra
coronata, n. sp., × 300 110
Fig. 4. Trypanosphæra
trepanata, n. sp., × 300 110

Fig. 5. Odontosphæra
monodon, n. sp., × 300 102

Fig. 6. Odontosphæra
cyrtodon, n. sp., × 300 102

Fig. 7. Acrosphæra
inflata, n. sp., × 300 101

Fig. 8. Mazosphæra
hippotis, n. sp., × 400 108

Fig. 9. Mazosphæra
lagotis, n. sp., × 300 108

Fig. 10.
Pharyngosphæra
stomodæa, n. sp., × 400 98

Fig. 11. Buccinosphæra


invaginata. n. sp., × 500 99
Each shell contains
numerous larger and
smaller crystals.

Fig. 12. Tribonosphæra


centripetalis, n. sp., × 500 98
Each shell contains
numerous large crystals.

Fig. 13. Collosphæra


polygona, n. sp., × 200 96

PLATE 6.

Legion SPUMELLARIA.
Order SPHÆROIDEA.

Family C o l l o s p h æ r i d a .

PLATE 6.
Collosphærida.
Diam. Page.

Fig. 1. Siphonosphæra
socialis, n. sp., × 500 106
A small piece of the
surface of a living
cœnobium, seen from
the surface. Only four
individuals are visible,
the central capsule of
which contains
numerous small nuclei
and a central oil-
globule. The including
spherical lattice-shell is
provided with a few
(one to four) larger
apertures, which are
prolonged into short
cylindrical tubules.
Through these latter
radiate bundles of fine
pseudopodia, branching
and anastomosing, and
forming a fine sarcode
network between the
alveoles of the
calymma. On the
surface of the alveolated
jelly-sphere the
pseudopodia form a
dense radiating zone.
Xanthella or yellow cells
are everywhere
scattered.

Fig. 2. Siphonosphæra
socialis, n. sp., × 300 106
A small cœnobium or
colony in the state of
alveolation, forming a
jelly-sphere, composed
of a great number of
capsulated individuals,
densely aggregated.
Each central capsule
contains an oil-globule,
and is enclosed by a
spherical lattice-shell,
which bears a few (one
to four) short cylindrical
tubules. Each shell is
again enveloped by a
membranous polyhedral
alveole and separated
from it by structureless
jelly. The thick cortical
jelly-envelope, which
surrounds the whole
spherical colony,
exhibits a fine radial
striation, produced by
radiating pseudopodia;
many xanthellæ or
yellow cells are
scattered in the
calymma.

Fig. 3. Siphonosphæra
pipetta, n. sp., × 300 108

Fig. 4. Siphonosphæra
tubulosa, J. Müller, × 300 105
The central capsule,
enclosed in the cavity of
the shell, has a central
oil-globule, and is
surrounded by a few
xanthella.

Fig. 5. Siphonosphæra
chonophora, n. sp., × 300 107

Fig. 6. Siphonosphæra
serpula, n. sp., × 300 107
Fig. 7. Siphonosphæra
patinaria, n sp., × 300 105
The central capsule,
enclosed in the cavity of
the shell, contains a
central oil-globule, and
is surrounded by a few
xanthella.

Fig. 8. Siphonosphæra
patinaria, n. sp., × 300 105

Fig. 9. Siphonosphæra
conifera, n. sp., × 300 106

Fig. 10. Siphonosphæra


cyathina, n. sp., × 300 105

PLATE 7.

Legion SPUMELLARIA.

Order SPHÆROIDEA.

Family C o l l o s p h æ r i d a .
PLATE 7.
Collosphærida.
Diam. Page.

Fig. 1 Caminosphæra
dendrophora, n. sp., × 300 112

Fig. 2. Caminosphæra
dichotoma, n. sp., × 300 112

Fig. 3. Coronosphæra
diadema, n. sp., × 300 117

Fig. 4. Coronosphæra
calycina, n. sp., × 300 117

Fig. 5. Otosphæra
auriculata, n. sp., × 300 116

Fig. 6. Otosphæra
polymorpha, n. sp., × 300 116

Fig. 7. Solenosphæra
serpentina, n. sp., × 300 114

Fig. 8. Solenosphæra
cornucopia, n. sp., × 300 115

Fig. 9. Solenosphæra
ascensionis, n. sp., × 300 115

Fig. 10. Solenosphæra


pandora, n. sp., × 300 113

Fig. 11. Solenosphæra


pandora, n. sp., × 100 113
An entire spherical
cœnobium. The shells of
the colony bear a
variable number of
fenestrated radial tubes
and are densely
crowded in the jelly-
sphere of the calymma,
the cortical zone of
which is radially striped.

PLATE 8.

Legion SPUMELLARIA.

Order SPHÆROIDEA.

Family C o l l o s p h æ r i d a .

PLATE 8.
Collosphærida.
Diam. Page.

Fig. 1. Acrosphæra
echinoides, n. sp., × 400 100

Fig. 2. Acrosphæra
collina, n. sp., × 300 101

Fig. 3. Chænicosphæra
nassiterna, n. sp., × 400 103

Fig. 4. Chænicosphæra
murrayana, n. sp., × 300 102

Fig. 5. Chænicosphæra
flammabunda, n. sp., × 300 103

Fig. 6. Clathrosphæra
circumtexta, n. sp., × 400 118

Fig. 7. Clathrosphæra
arachnoides, n. sp., × 300 119

Fig. 8. Clathrosphæra
lamellosa, n. sp., × 300 119
Fig. 9. Xanthiosphæra
erinacea, n. sp., × 400 120

Fig. 10. Xanthiosphæra


lappacea, n. sp., × 300 120

Fig. 11. Xanthiosphæra


lappacea, n. sp., × 100 120
A complete spherical
cœnobium. The
associated central
capsules (each with a
double shell) are
densely crowded in the
central part of the
calymma, whilst its
peripheral part is
occupied by a layer of
large alveoles.
Numerous xanthellæ or
yellow cells an scattered
in the calymma.

PLATE 9.

Legion SPUMELLARIA.

Order LARCOIDEA.

Family P y l o n i d a .
PLATE 9.
Pylonida.
Diam. Page.

Fig. 1. Monozonium
alatum, n. sp., × 300 633
Dorsal view.
Fig. 1a. Apical view.

Fig. 2. Dizonium
pleuracanthum, n. sp., × 400 636

Fig. 3. Dizonium
stauracanthum, n. sp., × 300 636

Fig. 4. Trizonium
tricinctum, n. sp., × 300 637
Dorsal view.
Fig. 4a. Lateral view.
Fig. 4b. Apical view.

Fig. 5. Amphipyle
tetraceros, n. sp., × 400 642
Dorsal view.

Fig. 6. Amphipyle
callizona, n. sp., × 300 644
Dorsal view.

Fig. 7. Amphipyle
amphiptera, n. sp., × 300 642
Dorsal view.
Fig. 7a. Lateral view.

Fig. 8. Tetrapyle
circularis, n. sp., × 300 645
Dorsal view.

Fig. 9. Tetrapyle
pleuracantha, n. sp., × 400 646
Dorsal view. The
lentelliptical central
capsule is visible
between medullary and
cortical shell.

Fig. 10. Tetrapyle turrita,


n. sp., × 400 649
Oblique view, half dorsal,
half lateral.

Fig. 11. Octopyle


stenozona, n. sp., × 400 652
Dorsal view.

Fig. 12. Octopyle


sexangulata, n. sp., × 300 653
Dorsal view.

Fig. 13. Octopyle


decastyle, n. sp., × 300 654
Dorsal view.
Fig. 13a. Lateral view.

Fig. 14. Pylonium


quadricorne, n. sp., × 400 655
Dorsal view.

Fig. 15. Tetrapylonium


quadrangulare, n. sp., × 300 658
Dorsal view.

Fig. 16. Pylozonium


octacanthum, n. sp., × 300 660
Dorsal view.

PLATE 10.

Legion SPUMELLARIA.

Order LARCOIDEA.
Welcome to our website – the ideal destination for book lovers and
knowledge seekers. With a mission to inspire endlessly, we offer a
vast collection of books, ranging from classic literary works to
specialized publications, self-development books, and children's
literature. Each book is a new journey of discovery, expanding
knowledge and enriching the soul of the reade

Our website is not just a platform for buying books, but a bridge
connecting readers to the timeless values of culture and wisdom. With
an elegant, user-friendly interface and an intelligent search system,
we are committed to providing a quick and convenient shopping
experience. Additionally, our special promotions and home delivery
services ensure that you save time and fully enjoy the joy of reading.

Let us accompany you on the journey of exploring knowledge and


personal growth!

textbookfull.com

You might also like