0.1 getting the csv

Let’s load the demo Event Log and let’s change a bit the event, to better fit the data to our aims.

EventLog<-read.csv("./EL_CFM_Demo.csv")
EventLog$Event[which(EventLog$Event=="Technical Suspension" & EventLog$Stop_Reason %in% c("1","2"))]<-"Clinical Suspension"

0.2 Event Log loading and creation of a QOD() object

As previously described, the first step is loading the csv file by a dataLoader() class.

# DataLoader Class initialization: 
obj.DL<-dataLoader(verbose.mode = FALSE)
obj.DL$load.data.frame(mydata = EventLog,IDName = "ID",EVENTName = "Event",dateColumnName = "Date",format.column.date = "%Y-%m-%d")

# obj.out is the one we need to load the data into the CFM class
obj.out <- obj.DL$getData()

Then a QOD() object can be instantiated and the the dataLoader::getData() method can be used to load the data into the new QOD() object:

# QOD Class initialization: 

objQOD<-QOD()
objQOD$loadDataset(obj.out)

0.2.1 Querying an Event Log query by QOD::query()

The QOD::query() method allows to query the Event Log according to the required constraints. The list of the possible parameters includes:

  • from : the event to start from. It can also be BEGIN.

  • to : the target event. It can also be END

  • complement : the default value is FALSE. If set to TRUE, instaed of returning the ID of the patients satisfying the query, it return the one who do not satisfy the query.

  • time.range : is a two-element array containing the time window where a transition between from and to should be considered valid. The default value is c(0,Inf).

  • step.range : is a two-element array containing the number of transitions between from and to, to consider the trace valid. The default value is c(0,Inf).

  • UM : is the Unity of Measure. It can be “minutes”,“hours”, “days”, “weeks”, “months”. The default value is the value specified with the creation of the object QOD; if no unity of measure is passed, “minutes” is considered as a default.

  • arr.passingThrough : contains an array of events which should be in between the from and to. The order is not important: c(“A”,“B”) or C(“B”,“A”) are equivalent.

  • arr.NOTpassingThrough : contains an array of events which should NOT be in between the from and to. Again, the order is not important.

  • returnCompleteMatrix : By default this parameter is set to FALSE and only the array of the patient’s ID is returned. If the user wants to dig into the data and see more in details which couples from - to has been checked, switching this parameter to TRUE will return a more detailed matrix.

Here there are some examples.

On first, let’s get all the IDs of the patients moving from RT Start to RT End within 14 days:

arr.2weeks.ID <- objQOD$query(from = "RT Start",
                              to = "RT End",
                              time.range = c(0,14),
                              UM = "days")

If we want more details, we can ask to give back a matrix containing all the infos about where all the traces matched the constraints, also indicating the time

mtr.2weeks.ID <- objQOD$query(from = "RT Start",
                              to = "RT End",
                              time.range = c(0,14),
                              UM = "days",
                              returnCompleteMatrix = T)

mtr.2weeks.ID[1:6,] %>%
  kbl() %>%
  kable_minimal()
from to step time valid
1 3 4 1 14 1
114 3 4 1 13.9583333333333 1
139 3 4 1 11.9583333333333 1
162 3 4 1 12 1
165 3 4 1 12 1
168 2 3 1 14 1

More comples query can be written, for example, to ask which are the patient who moved from RT Start to RT End without suspensions.

arr.2weeksNoSusp.ID <- objQOD$query(from = "RT Start",
                                    to = "RT End",
                                    arr.NOTpassingThrough = c("Clinical Suspension","Technical Suspension"),
                                    time.range = c(0,14),
                                    UM = "days")

0.2.2 Plot traces time line: plotTimeline() function

The plotTimeline() function, to visualize the temporal evolution of the traces through the visualization of a timeline. It is possible to filter the number of trace to plot by passing the function an array containing the IDs of the cases you want to investigate.

the traces of the patients from RT Begin to RT End within 2 weeks

objQOD$plotTimeline(objDL.obj = obj.out, max.time = Inf,UM = "weeks",arr.ID = arr.2weeks.ID)

the traces of the patients from RT Begin to RT End within 2 weeks, without suspensions

objQOD$plotTimeline(objDL.obj = obj.out, max.time = Inf,UM = "weeks",arr.ID = arr.2weeksNoSusp.ID)

Note: the parameter objDL.out is optional: if not specified, QOD::plotTimeline() will use the data previously loaded with the class QOD::loadDataset().

More in general, the admitted parameters are the following:

  • objDL.obj : is the output of the method dataLoader::getData(). This is optional: if not specified, the method will use what previously loaded with the method QOD:loadDataset().

  • arr.ID : if specified it contains the set of Patient’s ID to plot. The default is c() and means “all”

  • max.time : is the max time to window the x-axes.

  • UM : the unit of measure. It cna be “minutes”, “hours”, “days”, “weeks”, “months”

  • arr.events : is the set of events to plot. The default is c() which means "all*

  • arr.evt.pch : by default the events are plotted with a pch equal to 3 or the one indicated in the evt.pch.default.value parameter. In this array the user can associate one or more event to a specific pch. The array names are the event names and the values are the wished pchs.

  • evt.pch.default.value : is the pch which should be used by default for all the events

  • ID.on.y.label : can be TRUE or FALSE. If set to TRUE the IDs will be plotted, for each trace, on the left

  • y.label.cex : the cex for the y-axes

  • Time.on.x.label : if TRUE it shows the time on the x-axes.

  • x.label.cex : the cex for the x-axes

  • plot.legend : it can be TRUE or FALSE and permits to plot the legend, in a desided position

  • legend.Pos : it permits to posiiton the legend.

  • legend.cex : the cex for the legend

  • ID.ordering : if set to TRUE (default) permits to order the traces from the shortest to the longest or vice versa;

  • ID.ordering.desc : if ID.ordering is set to TRUE, this parameter can be set to TRUE to have a descending or to FALSE for an ascending ordering of the traces.

0.3 HeatMap

This map plots how often (relative numners) from an Event we can move to another, in the traces of the Event Log. For example, in the following HeatMap:

objQOD$eventHeatmap(cex =0.8)

we can observe that in the 62% of the cases, after a IO therapy we can have (in one or more steps) a technical suspension. If we are intersted in focusing the attention on specific window of %, we can specify the window setting the lower of the upper bound :

objQOD$eventHeatmap(cex =0.8,threshold.low = 0.50,threshold.hi = 0.80  )

the parameters cex, show.diagonal and par.margin and meant for graphical use and specify respectively: the font size, the presence of not of numbers in the diagonal and the margins of the image.

0.4 Plotting the aligned traces

The method QOD::plotTraceEvolution it allows to paint the evolution of the tracks showing the density of events over time

objQOD$plotTraceEvolution(objDL.out = obj.out,UM = "weeks")

Cumulative plot are also permitted

objQOD$plotTraceEvolution(objDL.out = obj.out,UM = "weeks",cumulative = TRUE)

0.4.1 Some more cases

Let’s suppose we want to analyze the total duration of the workflow considering the presence or absence of suspension events. Specifically, we want to identify the workflow for:

  • Patients suspended for maintenance reasons
  • Patients suspended for both clinical and maintenance reasons
  • Patients not suspended

To identify these groups, we can create the following queries.

# patient with both clinical and maintenance suspension
ID.both <- objQOD$query(from = "RT Start",
             to = "RT End",
             arr.passingThrough = c("Clinical Suspension","Technical Suspension"),
             time.range = c(0,Inf),
             UM = "weeks",
             returnCompleteMatrix = F)

# patient with maintenance suspension
ID.NOTclinical <- objQOD$query(from = "RT Start",
             to = "RT End",
             arr.passingThrough = c("Technical Suspension"),
             arr.NOTpassingThrough = c("Clinical Suspension"),
             time.range = c(0,Inf),
             UM = "weeks",
             returnCompleteMatrix = F)

# not suspended patients
ID.none <- objQOD$query(from = "RT Start",
             to = "RT End",
             arr.NOTpassingThrough = c("Clinical Suspension","Technical Suspension"),
             time.range = c(0,Inf),
             UM = "weeks",
             returnCompleteMatrix = F)

# not suspended patients
ID.clinical <- objQOD$query(from = "RT Start",
             to = "RT End",
             arr.passingThrough = c("Clinical Suspension"),
             arr.NOTpassingThrough = c("Technical Suspension"),
             time.range = c(0,Inf),
             UM = "weeks",
             returnCompleteMatrix = F)

Let’s use the plotTimeline function to observe the traces evolution over time:

objQOD$plotTimeline(objDL.obj = obj.out, max.time = Inf,UM = "weeks",arr.ID = ID.both,ID.on.y.label = F,evt.pch.default.value = 20)

objQOD$plotTimeline(objDL.obj = obj.out, max.time = Inf,UM = "weeks",arr.ID = ID.clinical,ID.on.y.label = F,evt.pch.default.value = 20)

objQOD$plotTimeline(objDL.obj = obj.out, max.time = Inf,UM = "weeks",arr.ID = ID.NOTclinical, ID.on.y.label = F,evt.pch.default.value = 20)

objQOD$plotTimeline(objDL.obj = obj.out, max.time = Inf,UM = "weeks",arr.ID = ID.none, ID.on.y.label = F,evt.pch.default.value = 20)

0.4.2 the method QOD::cumulative.curve.compute()

Let’s enrich the Event Log with an additional columns, containing the group (no suspension, maintenance suspension ot both -clinical and maintenance- suspension)

On first we can load a new dataLoader()

EventLog$Group<-"both"
EventLog$Group[which(EventLog$ID %in% ID.NOTclinical)]<-"maintenance"
EventLog$Group[which(EventLog$ID %in% ID.none)]<-"none"
EventLog$Group[which(EventLog$ID %in% ID.clinical)]<-"clinical"

obj.newDL <- dataLoader(verbose.mode = FALSE)
obj.newDL$load.data.frame(mydata = EventLog,IDName = "ID",EVENTName = "Event",dateColumnName = "Date",format.column.date = "%Y-%m-%d")

obj.new.out <- obj.newDL$getData()

Istantiated a new QOD obj we can now use the cumulative.curve.compute to measure the kinetics during the time:

# QOD Class initialization: 
objQOD <- QOD()
objQOD$loadDataset(dataList = obj.new.out)

lst.out <- objQOD$cumulative.curve.compute(from = "RT Start",to = "RT End",UM = "days",time.range = c(0,Inf),plotIt = T,stratification.var = "Group",x.range = c(0,125),x.interval = 25)