In this vignette, we discuss a few additional topics that might be of interest to some, but likely not all users.
The developers of flowdiagramr have also been developing an R package called modelbuilder which allows users to graphically build and analyze compartmental simulation models. In fact, flowdiagramr started as a function inside
modelbuilder to draw diagrams of user-built models. At some point, we decided to make flowdiagramr a stand-alone package. But it still works with and is used by modelbuilder. If you use modelbuilder and want to use flowdiagramr to generate a diagram for that model outside the auto-generated one shown inside modelbuilder, here are the steps.
Once you built a model with modelbuilder, you can save it as an
Rds file. This file contains a single object, the user-created model specified as a list object. Since modelbuilder models and flowdiagramr models are slightly different, we provide a convenience function that converts one format into the other.
This is a very simple process, and is done with the function
convert_from_modelbuilder. This function takes as input the modelbuilder object and produces a list that conforms to the flowdiagramr model specification. The following examples illustrate this.
Assume you built a basic SIR model with modelbuilder and saved it as an
R object inside a
.Rds file. First, we load the file and assign it to some variable.
mbmodel <- readRDS('SIR_model.Rds')
Next, we convert the object.
mymodel <- convert_from_modelbuilder(mbmodel)
If you print the content, you can see it has the required
model_list with the
flows objects. You can now use this
model_list object when you call
print(mymodel) #> $variables #>  "S" "I" "R" #> #> $flows #> $flows$S_flows #>  "-b*S*I" #> #> $flows$I_flows #>  "+b*S*I" "-g*I" #> #> $flows$R_flows #>  "+g*I"
You can now proceed with the usual steps.
diagram_list <- prepare_diagram(model_list = mymodel) sir_diagram <- make_diagram(diagram_list) plot(sir_diagram)
Just to show one more example, this is a model from the modelbuilder example library called
Complex ID control. It is a model that includes a good number of details and allows exploration of different intervention strategies. If you are not too familiar with compartmental models yet, just consider it as an example that illustrates the work flow. You can find some more details about the model in the modelbuilder package, or even more details in another of our packages, DSAIDE, which is targeted toward learning about such infectious disease models.
First, we load the model, then convert it and print it.
mbmodel <- readRDS('Complex_ID_Control.Rds') mymodel <- convert_from_modelbuilder(mbmodel) print(mymodel) #> $variables #>  "S" "P" "A" "I" "R" "D" "E" "Sv" "Iv" #> #> $flows #> $flows$S_flows #>  "+nH" "-S*bP*P" "-S*bA*A" "-S*bI*I" "-S*bE*E" "-S*bV*Iv" "+w*R" #>  "-mH*S" #> #> $flows$P_flows #>  "+S*bP*P" "+S*bA*A" "+S*bI*I" "+S*bE*E" "+S*bV*Iv" #>  "-f*gP*P" "-(1-f)*gP*P" "-mH*P" #> #> $flows$A_flows #>  "+f*gP*P" "-gA*A" "-mH*A" #> #> $flows$I_flows #>  "+(1-f)*gP*P" "-(1-d)*gI*I" "-d*gI*I" "-mH*I" #> #> $flows$R_flows #>  "+gA*A" "+(1-d)*gI*I" "-w*R" "-mH*R" #> #> $flows$D_flows #>  "+d*gI*I" #> #> $flows$E_flows #>  "+pI*I" "+pA*A" "-c*E" #> #> $flows$Sv_flows #>  "+nV" "-bH*I*Sv" "-mV*Sv" #> #> $flows$Iv_flows #>  "+bH*I*Sv" "-mV*Iv"
As promised, this is a much more complex model. We don’t expect the default diagram for this model to look great, but let’s give it a try.
The diagram is not ideal. But you now know how to make it better, once you have done the model conversion, you can use the usual approaches. As an example, let’s specify the layout for the variables/nodes. We can use the existing
model_settings object stored in
mymodel and can add
The rationale of how to place the variables is determined by the meaning of each of them and what makes logical sense. I’m not discussing this here, if you want to learn more about the model, see the Complex Control Scenarios app inside DSAIDE.
diagram_list <- prepare_diagram(mymodel, model_settings) my_diagram <- make_diagram(diagram_list) plot(my_diagram)
This is better, but of course still not quite good enough. Fortunately, you have learned how to use flowdiagramr to fairly easily turn this into a publication-quality diagram :).
It is quite likely that the diagram you get back from
make_diagram contains a good bit of white space. This is often a problem when trying to use the figure in publications.
As example, consider the above diagram. If we write it into a file, then load the file and show it, it looks like this.
As you can see, the saved image file contains a lot of unwanted white space. There are different options you can use to change the white space. Here are some we are aware of.
One approach is to play with the margins of the gpplot object returned from
make_diagram until things look ok. Here is an example:
This looks better. You will likely have to fiddle a bit with the margin settings until you get it cropped the way you want.
magick package allows for automated trimming of a file. This means you first need to save your diagram into a file, then load, trim and resave. Here is an example
library(magick) fig <- magick::image_read("sirdiag.png") fig2 <- magick::image_trim(fig) magick::image_write(fig2,'sirdiag2.png')
The disadvantages of this approach is that you need to use another R package and that the cropping is very tight. The advantages are that the
magick package can do a lot more, so there might be some additional useful tweaks possible that you can apply to your figure to get it exactly the way you want.
By now, you are familiar with the main functions of **flowdiagramr
andwrite_diagram()`. The package contains additional helper functions. Those are generally not very useful by themselves and do work behind the scenes. However, a few might be occasionally useful, therefore we describe them briefly.
check_model_list() - This function does what its name implies. It takes a model list, consisting of the
flows entry and checks if everything seems to make sense. If everything is fine, nothing is returned. Otherwise, a hopefully somewhat informative error message is provided.
These checking functions are run behind the scenes as part of the the main functions