Created
November 16, 2020 11:14
-
-
Save geotheory/6d552b4cc0f85c69c637d9c22c0be1c1 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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))) | |
Author
geotheory
commented
Nov 16, 2020
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment