Skip to content

Instantly share code, notes, and snippets.

@geotheory
Created November 16, 2020 11:14
Show Gist options
  • Save geotheory/6d552b4cc0f85c69c637d9c22c0be1c1 to your computer and use it in GitHub Desktop.
Save geotheory/6d552b4cc0f85c69c637d9c22c0be1c1 to your computer and use it in GitHub Desktop.
require(R6)
# depends: {purrr}, {tibble}, {tidy} for graph conversion
Step = R6Class("Step", list(
id = NA,
stage = NA,
state = NA,
parent = NA,
children = list(),
open = TRUE,
initialize = function(id, parent, stage = NA, state = NA){
self$id = id
self$parent = parent
self$stage = stage
self$state = state
},
add_child = function(id){ self$children = c(self$children, id) }
))
Process = R6Class("Process", list(
graph = list(),
tree = c(1),
k = 1,
initialize = function(){ self$graph[[1]] = Step$new(1, NA, 'root', NA) },
add = function(stage = NA, state = NA){
self$k = self$k + 1 # iterate to next ID
parent = self$tree[length(self$tree)]
self$graph[[parent]]$add_child(self$k) # fails
self$graph[[self$k]] = Step$new(self$k, parent, stage, state)
self$tree = c(self$tree, self$k)
return(self$k)
},
close = function(){ self$tree = self$tree[-length(self$tree)] }
))
trace_nodes = function(x){
purrr::map_df(x$graph, ~ tibble::tibble(id = .x$id, stage = .x$stage, state = .x$state))
}
trace_edges = function(x){
tidyr::unnest(purrr::map_df(x$graph, ~ tibble::tibble(from = .x$id, to = .x$children)), to)
}
trace_to_graph = function(x){
nodes = trace_nodes(x)
edges = trace_edges(x)
tidygraph::tbl_graph(nodes = nodes, edges = edges)
}
#-------------------------------------------------------------
# EXAMPLE USAGE
# requires {stringr}
test_fun = function(max_depth, min_children = 0){
stage_name = sample(stringr::words,1) # any unique identifier for the function
state_val = head(iris,sample(150)[1]) # any state information you wish to log
# the important bit
trace$add(stage_name, list(state_val)) # registers the process
on.exit(expr = trace$close()) # set callback to log exit
if(max_depth == 0) return()
n = max(min_children, sample(0:2 ,1))
if(n > 0) for(i in 1:n) test_fun(max_depth-1)
}
# initialise the logger
trace = Process$new()
# simulate some sequences of function calls
test_fun(4, 3)
test_fun(3, 2)
# visualise the flow
require(ggraph)
require(tidygraph)
trace_nodes(trace)
g = trace_to_graph(trace)
g %>% activate(nodes) %>% mutate(state = purrr::map_dbl(state, object.size)) %>%
ggraph('tree') +
geom_edge_elbow() +
geom_node_label(aes(label = paste0(id, '. <', stage, '>\n\nsize: ', state)))
@geotheory
Copy link
Author

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment