Graphviz + Ruby script to visualize Zettel network starting at a particular note
I uploaded a public script here, which you can run to get graphviz/dot compatible output of link hierarchies:
https://gist.github.com/DivineDominion/b11982ae1ef555720000b362fe17d7af
Usage: extract_associated_zettel.rb [options] FILE -d, --depth [DEPTH] How many levels to traverse before aborting. Default is 10. -o, --output [OUTPUT] OUTPUT file to store the graphviz dot output instead of stdout -v, --verbose Print debug info to stdout. Only works with -o/--output to re-route result -h, --help Prints this help
Feel free to chime in and suggest changes to the code!
Example Output
dot
output of the David Epstein: Range note
$ ruby extract_associated_zettel.rb ~/Archiv/201909171553\ Range\ -\ David\ Epstein.txt digraph { rankdir=LR; overlap=false; splines=false; node [shape=box]; 0[label="201909171553 Range\n- David Epstein.txt\n"]; 1[label="201909171655 Ericsson\n- The Role of Deliberate\nPractice in the\nAcquisition of Expert\nPerformance.txt\n"]; 2[label="201909171706 Concept\nDeliberate practice.txt\n"]; 3[label="201909231546 Deliberate\npractice could be\nimpossible in wicked\nlearning environments.txt\n"]; 4[label="201909231536 Wicked\nlearning environments.txt\n"]; 5[label="201909231550 Kind\nlearning environments.txt\n"]; 6[label="201909231626 Validity\nof task environments\nas per Kahneman\nand Klein.txt"]; 7[label="201909231624 High-validity\nbut uncertain environments\nproduce games of\npossibilities.txt\n"]; 8[label="201105241557 Colvin\n-- Talent is Overrated.md\n"]; 9[label="201909171737 Cardiac\npatients less likely\nto die when cardiologists\nare absent.txt"]; 10[label="201908111523 Chess\ncomputers free resources\nof humans to produce\na strategy.txt"]; 11[label="201908111520 Automation\nfrees cognitive\ncapacity for important\nthings.txt"]; 12[label="201301092057 Difference\nstrategy and tactics.md\n"]; 13[label="201909231725 Giftedness\ndoes not imply genius.txt\n"]; 0 -> 1; 1 -> 2; 2 -> 3; 3 -> 2; 3 -> 4; 4 -> 5; 5 -> 4; 5 -> 6; 6 -> 7; 7 -> 6; 3 -> 5; 0 -> 2; 0 -> 8; 0 -> 9; 0 -> 5; 0 -> 4; 0 -> 10; 10 -> 11; 0 -> 12; 0 -> 11; 0 -> 13; 0 -> 4; 0 -> 3; }
Verbose/debug output of link hierarchies as plain text
$ ruby extract_associated_zettel.rb ~/Archiv/201909171553\ Range\ -\ David\ Epstein.txt --verbose --output out.txt Searching in `/Users/ctm/Archiv`, starting with: 201909171553 Range - David Epstein.txt 201909171655 Ericsson - The Role of Deliberate Practice in the Acquisition of Expert Performance.txt 201909171706 Concept Deliberate practice.txt 201909231546 Deliberate practice could be impossible in wicked learning environments.txt 201909171706 Concept Deliberate practice.txt (duplicate contents skipped) 201909231536 Wicked learning environments.txt 201909231550 Kind learning environments.txt 201909231536 Wicked learning environments.txt (duplicate contents skipped) 201909231626 Validity of task environments as per Kahneman and Klein.txt 201909231624 High-validity but uncertain environments produce games of possibilities.txt 201909231626 Validity of task environments as per Kahneman and Klein.txt (duplicate contents skipped) 201909231550 Kind learning environments.txt (duplicate contents skipped) 201909171706 Concept Deliberate practice.txt (duplicate contents skipped) 201105241557 Colvin -- Talent is Overrated.md 201909171737 Cardiac patients less likely to die when cardiologists are absent.txt 201909231550 Kind learning environments.txt (duplicate contents skipped) 201909231536 Wicked learning environments.txt (duplicate contents skipped) 201908111523 Chess computers free resources of humans to produce a strategy.txt 201908111520 Automation frees cognitive capacity for important things.txt 201301092057 Difference strategy and tactics.md 201908111520 Automation frees cognitive capacity for important things.txt (duplicate contents skipped) 201909231725 Giftedness does not imply genius.txt 201909231536 Wicked learning environments.txt (duplicate contents skipped) 201909231546 Deliberate practice could be impossible in wicked learning environments.txt (duplicate contents skipped)
Please note that the -v
/--verbose
option prints this to the standard output and requires the dot
output to be written to a file instead via -o
/--output
, so the standard output isn't occupied with the graphviz data anymore.
Example graph with neato
At maximum depth (more than the network link depth actually is)
The output of this:
$ ruby extract_associated_zettel.rb \ ~/Archiv/201909171553\ Range\ -\ David\ Epstein.txt \ | neato -Tpng -otest.png
... is this PNG image:
Limited depth to direct connections
And limiting the depth to 1:
$ ruby extract_associated_zettel.rb \ ~/Archiv/201909171553\ Range\ -\ David\ Epstein.txt \ -d1 \ | neato -Tpng -otest.png
Author at Zettelkasten.de • https://christiantietze.de/
Howdy, Stranger!
Comments
This is so great, thanks!
So...I haven't jumped into the waters yet, but what's the difficulty level on getting this thing set up? I don't know coding. @Will 's Keyboard Maestro macros are about the limit of my abilities.
I would say intermediate difficulty level, perhaps? It requires knowing a bit about using command line input in terminal, and there are some dependencies (do you have graphviz installed?).
I'm not super adept at computery things, so it took some amount of googling and fiddling on my end to get it working properly. (For example, I had to figure out that graphviz really doesn't like it when you have quotation marks
"
in file names. Lesson learned.) But I'm sorry to say that I wouldn't know where to begin to actually walk someone through a complete set up.I just updated the script to work with the Ruby version that comes with macOS Mojave. (I apparently used some newer methods that were not available.)
Assuming you're on a Mac, you will need to
brew install graphviz
The script execution command is
ruby PATH_TO_THE_SCRIPT PATH_TO_THE_ZETTEL
. You can typeruby
(note the space), then drag & drop your Ruby script file into Terminal. That should input the path for you. Then type another spaceand drag & drop the Zettel note into the Terminal. Hit enter. If everything succeeds after a short while, the program prints a couple of lines of graphviz code (see above).
To restore the previous command instructions so you don't have to type it again, press the "up" arrow key.
To turn the graphviz code into an image, you need to pipe the output through to graphviz's
neato
program that produces pretty nice layout. With the restored command, add|
(note the spaces around the pipe operator), and then the target command:neato -Tpng -oIMAGE_FILENAME.png
The result should be of the form
ruby PATH_TO_THE_SCRIPT PATH_TO_THE_ZETTEL | neato -Tpng -oIMAGE_FILENAME.png
To open the resulting PNG image, you can open the current directory in Finder:
open .
, and then open the image from there.Author at Zettelkasten.de • https://christiantietze.de/
Alright I lied, here's an attempt to walk someone through setup using Keyboard Maestro. Certainly not perfect, or particularly elegant, but perhaps it'll work.
Graph Zettel in Graphviz.kmmacros
Thanks @ctietze and @argonsnorts ! I look forward to working through those steps and working with the macro.
Wow, I got it to work. Before adding the limiter, it spit out this:
Then using the limiter as described in the orginal post, it formed something a bit more in line with my hopes:
@nickmilo22: You might also be interested in this discussion and this discussion. The KM macro I linked to on September 2nd in the latter discussion can do exactly what Christian's script does (as far as I can see), but does not use Ruby.
This is great stuff. And I really appriciate the KM experts in here. I got my macros of Will and they are great. But, I cannot not help thinking -could not these things, the visualizer, the lookup of other notes, templates and the most comon things related to the usage of TA be included in the app itself. Its almost as if you have to buy KM in addition to the archive app at this point.
@vinho I'm going to revisit those posts and put those KM macros to use, thanks for the suggestion!
@johnny hopefully over time our awesome TA team will judiciously incorporate these features in such a way as to avoid feature bloat.
@johnny Scripting integration is next on the to-do list, but fixing some unrelated problems stalls progress at the moment. With the scripting stuff, you will be able to replace a lot of the KM macros with in-app script invocations. (Though not all, e.g. not those that perform mouse movement and clicks for you.)
Author at Zettelkasten.de • https://christiantietze.de/
@vinho I kind of got your KM macros to work. Not perfectly, and not beyond 1 degree, and not after the first time (can't repeat it for some reason). I know I should provide more details, hopefully I will have the time to do so later.
@nickmilo22: I'm sorry to hear it doesn't work smoothly – let me know what the problem is when you have more detail. Thinking more about it, the macro I linked to on September 2nd doesn't do exactly what Christian's script does – it won't show any arrows between children notes.
The other macro would produce something similar to Christian's graph – but only if you selected all the notes belonging to the book in the note list of The Archive before you trigger the macro (which would be easy if they all had a book-tag). Also my graphs are made with the dot-programme of Graphviz, not neato as Christian's. If you want to use neato instead, just replace the
dot
command in the "Execute Shell Script" action at the end of the macro withneato
. You then also need to add the lineoverlap=false;
in the action where the .dot-file is created (e.g. under the line that starts with `label=) – otherwise the boxes in the graph will overlap a lot.I finally have the ctietze version working and it's brilliant.
I think I'm stating the obvious here, but having this functionality built into the Archive itself (or perhaps a companion app that one of you coding/scripting geniuses could build?) would be amazing. Especially if the maps had active links to edit the zettels in the Archive, like Vinho's version produces.
Use case: pick a zettel, active the map module or companion app, browse the network of linked zettels, click on a zettel to view or edit and have it open in The Archive, make your change, refresh the map and see any new links you just created updated on the map, rinse and repeat.
Come on.... awesome!