Drawing tree in OCaml GUI, best option?

Do you have code to do this already, @anon72795300, or is it an idea at present? If you have the code, even in a bad state, you could release it and perhaps some of the rest of us could try documenting it and cleaning it with your help.

This works already. Or atleast it did with the version I worked with. It has been in proprietary code used industrially. There s a test file in the repo which can also serve as an example. Will post a link tomorrow.

My idea was to spin this off and have even been tempted about a pure Ocaml + QML library.

1 Like

Is it possible to open source just the Qt/QtQuick/QML portions?

If you are talking about the bindings then yes, they are here:

https://github.com/Kakadu/lablqml/blob/master/lib/lablqml.ml
https://github.com/Kakadu/lablqml/blob/master/lib/stubs/object_ml.cpp

The test files I mentioned:

https://github.com/Kakadu/lablqml/blob/master/lib/src_tests/test3.ml
https://github.com/Kakadu/lablqml/blob/master/lib/src_tests/test3.qml

I’ve started a stand alone library too, but haven’t pushed it yet.

1 Like

Ah, @anon72795300 , I didn’t understand that you had contributed to the lablqml work. It is shared between you and @Kakadu ?

There’s also this:

that lets you run the vizualisation in your browser.

I developed and contributed the binding method I mentioned above. I think I helped a bit along the way of tidying up the repo. Is that what you meant to know?

Yes, that’s more or less what I wanted to know.

Thanks very much again for everyone’s reply. I managed to cobble something that’s basically exactly what I had in mind over past few days.

Below is an attached screenshot for people who might be interested in doing something similar and wondering if very feasible.

(The black bars are not part of the graphics, it’s just for censoring as the program is part of a research project that’s not published yet)

The whole program basically loads a file of some kind, runs a parser over it, then produce a tree.

Some technical details

  • Parsing is done on OCaml’s side using mparser
  • All core stuff(e.g. AST manipulation, heavy lifting) is done in OCaml
  • Graphing is done with Javascript libraries dagre(for DAG layout calculation) and cytoscape.js for actual rendering and interactive interface
    • Was using sigma initially for graphing, but moved to cytoscape. The transition was fairly easy cause the libraries were kept in separate OCaml modules
  • Javascript calls are done via js_of_ocaml
  • 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
6 Likes

Attached an animated GIF showing it in action with a test graph.

3 Likes

Just out of curiosity, how big is the generated JavaScript file?

Tokei’s output for code base size

-------------------------------------------------------------------------------
 Language            Files        Lines         Code     Comments       Blanks
-------------------------------------------------------------------------------
 OCaml                  15         1755         1490           64          201
-------------------------------------------------------------------------------
 Total                  15         1755         1490           64          201
-------------------------------------------------------------------------------

EDIT: Roughly 200-300 LOC is binding/wrapper of JS libraries.

Sizes of program.bc.js

profile size in bytes size in KiB
dev profile, build command : dune build @js 8961453 8751
minified dev build, minified with uglifyjs 4366132 4264
release profile, build command : dune build -p program @js 513518 501
minified release build, minified with uglifyjs 511684 500

Note: js is a custom alias that has multiple dependencies on rules that deal with file copying, generation etc. One dependency is program.bc.js

EDIT: Added more figures to table

2 Likes

Hello everyone,

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.

Cheers,
Darren

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.

2 Likes

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?

Do you have a small example of the graph you have in mind?

I think at the very least cytoscape.ml is a good starting point if you find Cytoscape a good option.

The graph layout algorithm is run separately from Cytoscape, so you can always swap to another algorithm easily using a similar design in graph.ml.

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…

1 Like

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!