bupaverse / processmapR

Visualize event logs using directed graphs, i.e. process maps.
https://bupaverse.github.io/processmapR/
Other
9 stars 6 forks source link

specify fixed positions #26

Open kkmann opened 4 years ago

kkmann commented 4 years ago

Hi,

first of all, thanks for putting this package together - very useful indeed!

I was running into problems with specifying fixed positions for my layout, see below:

library(tidyverse)
library(bupaR)

tbl_pos <- tribble(
                       ~act, ~x, ~y,
               "Blood test",  1,  1,           
                "Check-out",  2,  1,           
          "Discuss Results",  3,  1,     
                 "MRI SCAN",  4,  1,   
             "Registration",  5,  1,  
    "Triage and Assessment",  6,  1,
                    "X-Ray",  7,  1
)

patients %>% 
    process_map(
        layout = layout_pm(
            fixed_positions = tbl_pos
        )
    )

this gives me

Error: node 2, position ,!, expected two doubles

in the Rstudio Viewer. I also tried to turn tbl_pos into a data.frame without any effect. Any ideas what the problem might be and how to fix it?

fmannhardt commented 4 years ago

Could reproduce this, will try to look into it. Somehow it ends up writing pos = "2,1!" into the GraphViz DOT code.

teofiln commented 1 year ago

As of the current CRAN and github versions, the error I am getting when trying this is:

Error: node 2, position NA,NA!, expected two doubles

I could bypass it by storing the generated graph in a variable and then manually modifying the x and y coordinate for the (artificial) Start and End activities:

library(bupaR)
library(processmapR)

tbl_pos <- tidytable::tribble(
    ~act, ~x, ~y,
    "Blood test", 2, 1,
    "Check-out", 4, 1,
    "Discuss Results", 6, 1,
    "MRI SCAN", 8, 1,
    "Registration", 10, 1,
    "Triage and Assessment", 12, 1,
    "X-Ray", 14, 1
)

x <- patients %>%
    process_map(
        render = FALSE,
        layout = layout_pm(
            fixed_positions = tbl_pos
        )
    ) 

x$nodes_df[x$nodes_df$label == "Start", "x"] <- 0
x$nodes_df[x$nodes_df$label == "Start", "y"] <- 1

x$nodes_df[x$nodes_df$label == "End", "x"] <- max(x$nodes_df$x, na.rm = TRUE) + 2
x$nodes_df[x$nodes_df$label == "End", "y"] <- 1

render_map(x)

image

There is still some work to do to avoid the overlap of the edges.

teofiln commented 1 year ago

Based on this post: https://stackoverflow.com/a/7954615/8543257

Here is a workaround for the edges overlap when using fixed positions and neato engine. Not great, not terrible.

x |>
 DiagrammeR::add_global_graph_attrs(
    attr = "splines",
    value = "true",
    attr_type = "graph"
) |>
    DiagrammeR::add_global_graph_attrs(
        attr = "overlap",
        value = "false",
        attr_type = "graph"
    ) |>
        render_map()

x |>
    DiagrammeR::add_global_graph_attrs(
        attr = "splines",
        value = "true",
        attr_type = "graph"
    ) |>
    DiagrammeR::add_global_graph_attrs(
        attr = "overlap",
        value = "false",
        attr_type = "graph"
    ) |>
        DiagrammeR::generate_dot()

image

teofiln commented 1 year ago

The issue traces back to this line: https://github.com/bupaverse/processmapR/blob/5b3a53f7dde51d5873e1d0c01c79d6879d0fdff2/R/process_map.R#L306

At the time the fixed_positions data frame is joined to the nodes data frame, the nodes data frame already contains rows for ARTIFICIAL_START and ARTIFICIAL_END. The user supplied fixed_positions table, however, does not have act entries for these 'activities', so in the modified nodes data frame, the x and y coordinates become NA. In theory, it would be straightforward to patch the process_map method to replace the NAs with values. The hard part is how to guess the intentions of the user. i.e. where do they want Start and End to be on the graph.

For this reason, probably the best thing to do is to update the layout_pm documentation to explain that the fixed_positions data frame must include rows with activities and coordinates for ARTIFICIAL START and ARTIFICIAL END.

I thought that an alternative might be to use bupaR::add_start/end_activity() before creating the graph and fixed positions table, but it seems that the ARTIFICIAL* nodes are added regardless of the presence of activities called Start and End for all cases in the event log.