Threading and synchronisation is done using Lwt, and some related Lwt modules in js_of_ocaml
This includes synchronisation between a Javascript event handler and OCaml code, uses Lwt_condition specifically.
Comments on experience
Always use class types for binding Javascript libraries in js_of_ocaml, otherwise typing will get very, very weird when you try to use the objects across modules, and also when you type up .mli files
(Not specific to Javascript+OCaml context) You will need a light text editor that can deal with large text files if you want to go through the generated Javascript file for debugging. I used vim
js_of_ocaml’s Jstable(Javascript hashtable that uses Javascript string as keys) almost kinda work as an associative array, but not really
There was an instance where I was trying to make a Javascript object that has a field “foo-bar”, but hyphens can’t be used in field names, so I had to try to make an associative array of some form(you can do this via named indexes in Javascript).
So to do this on OCaml’s side, I tried to use Jstable, it worked kinda, except when passed as an object to a Javascript function, it will complain and state that the key is “foo-bar_”
I.e. Jstable when passed as object, the key has an extra underscore at the end instead of just the raw string you used
Overall result
Have an interface on the left side of the screen that shows a tree that you can select nodes, click, drag, move, zoom etc
Have a control panel on the right side(just a list of buttons with event handlers tied to Lwt threads etc) for opening files, etc
Core stuff still coded in OCaml(which is fantastic), and Javascript components can be swapped fairly easily
So @grayswandyr messaged me a few days ago about publishing of the Javascript bindings and other related OCaml files of the project. Unfortunately the source code will stay private until publication process has been finished, but I reckon I can publish the Javascript bindings and a stripped down version of the knowledge graph module and make a small demo which people can use as a template to make similar GUI software or site.
However, I always find myself completely out of touch on anything related to UI/UX, and have always needed other people’s guidance on the matter from my experience.
So I’d like to ask for suggestions of some particular features or examples that you’d like me to give a shot at in the demo. Feel free to leave a comment or PM me to make suggestions.
The project is finally published, here is the link to the relevant OCaml sources for drawing knowledge graph and HTML. src/cytoscape.ml is the binding to the Cytoscape JS library, src/dagre.ml is the binding to Dagre JS graph layout library.
We have a demo site where you can see it in action. You’ll need to click “Show knowledge graph” to see the display of knowledge graph however.
The demo site looks nice! I have a specific graph layout problem and I’m wondering if i could use some of your work to solve it.
I want to visualize trees in which each node carries a ‘time’ in such a way that times always increase as you descend. The trees get very deep but they are thinned such that the width of the tree at any given time remains bounded. I would like to visualize these trees so that the time is the y coordinate and the x coordinate is adjusted so as to fit the width of the tree into a given window, maybe like in a force-directed graph layout. It does not need to be interactive.
Is it easy to reuse some of your code? Where would I have to start?
I had a look at cytoscape and at graphviz; their layout algorithms unfortunately do not match my requirements. So I guess I would have to make my own layout. But then I can also just export the graph in some way as .dot and use graphviz with precomputed layout…
Well writing a layout algorithm would be fairly easy I think.
Is the graph layout the only bit you’re looking for?
EDIT: Read your question again and realised I somewhat misinterpreted it - so uh graph.ml might be useful as it provides a graph implementation that handles arrows and also bi-directional traversal, but really depends on how you plan to represent your graph.
Hi,
So if I understand you want to represent a tree that is embedded in time ?
I’m not sure I understand the part about “they are thinned such”.
It seems to me like algorithms to plot phylogenies and genealogies might be useful. https://itol.embl.de/ for instance is pretty good at that.
yes, it’s a tree embedded in time. however, as time progresses, many branches of the tree end without children, so that on average, at any given time, a constant, small number of branches are present. i’ll have a look at the embl library, thanks!
interesting project! in fact i my tree is also a biological one: cell lifetimes in a cell culture. i tried cloning an installing your repo but cannot build it.
File "tree/lib/draw.ml", line 69, characters 34-39:
Error: The function applied to this argument has type
string -> w:float -> h:float -> Cairo.Surface.t
This argument cannot be applied with label ~fname
this appears after some warnings like this one:
File "tree/lib/tree.ml", line 15, characters 13-22:
Error (warning 49): no cmi file was found in path for module Tree__Sig
I suspect the “Layered” algorithm would be sufficient for your purpose, but you can also find lot’s of different type of tree visualisation here. Formally, what you are looking for is an algorithm for layered trees where the rank of nodes is prescribed. There are several such algorithms.
If you end up implementing something from the literature (or improving on it), I would be happy to add it to the collection!
Yes, the rank is prescribed but i would also want to constrain the width; this may require bending some branches inwards, towards a straight centerline. What I would imagine could work is a constrained force-directed layout where only the width-coordinates are allowed to adapt in order to 1. keep edges non-overlapping and short and 2. keep vertices close to a centerline (in the width coordinate x) and 3. keep vertices separated.
We present two new drawing conventions which reduce the layout width to be less than some maximum width while still maintaining the essential layered drawing convention.
Yes sorry the master branch is very behind right now.
If you want to build you can pull branch devel-john, but apparently there’s a problem with the Cairo version.
But I implemented this as a quick hack, so don’t hesitate to grab the code to adapt it to your needs, but otherwise Drup’s pointers might be more useful.
thanks for all the pointers. the stacktrees do look similar to what i was imagining; the first link you gave seems to deal mainly with integer ranks, which is not exactly my use case.
Yeah I was thinking something else entirely at the time of writing, that didn’t sound right at all. I think I meant to say for a very specific case the algorithm could be simple, but didn’t mean to suggest it’d be easy in general.
And interesting project - I recall seeing it quite recently, I was thinking about replacing Dagre with it as well, but I was too busy to commit to that.