org-roam-server icon indicating copy to clipboard operation
org-roam-server copied to clipboard

Suggestion: Simpler, more helpful color scheme for graph view

Open thriveth opened this issue 3 years ago • 10 comments

The current scheme seems like it works really well with tree-structured notes, because each branch gets colored in neat groups and leaf nodes get the same color as their twigs, etc.

But in a highly interconnected network, which (org-)roam encourages, with few leaf nodes and many connections (see attached screenshot), the current coloring scheme -- even if it is very pretty -- is not very helpful and actually makes my work navigating the network graph harder rather than easier.

So I suggest a coloring policy more in line with e.g. obsidian. My wish list is a scheme that:

  • Has one color (e.g., gray) for all non-highlighted nodes,
  • Dims inactivte nodes slightly when a node is highlighted,
  • Highlights currently hovered node and all first-order connections, as well as the connecting edges, by a not too strong color and thicker lines,
  • If possible activates labels of all first-order connections as well as the selected/hovered node itself,
  • Perhaps has different highlight colors for selected (by click) nodes and hovered nodes, but all others are a neutral gray.

image

thriveth avatar Dec 16 '20 01:12 thriveth

Cool suggestion!

The way it's implemented right now, groups are created and colors are assigned using it. So if you try to define the color using the variable org-roam-server-vis-options, it won't change.

To play with your suggestion, I've commented the following code from the index.html file to stop assigning groups to the nodes:

              // Group the nodes
              let group = 0;
              const keys = Object.keys(nodes).sort(compareNodeValues);
              // for (let i = 0; i < keys.length; i++) {
              //     const k = keys[i];
              //     if (!nodes[k].group) {
              //         const connectedNodes = tempNetwork.getConnectedNodes(k);
              //         if (connectedNodes.length > 0) {
              //             const node = connectedNodes.max(compareNodeValues);
              //             if (!nodes[node].group) {
              //                 nodes[node].group = group;
              //                 group += 1;
              //             }
              //             nodes[k].group = nodes[node].group;
              //         } else {
              //             nodes[k].group = group;
              //             group += 1;
              //         }
              //     }
              // }

Then I could change the color using the vis options, this is my config:

	org-roam-server-network-vis-options "{\"physics\": {\"enabled\": false, \"stabilization\": {\"enabled\": false, \"iterations\": 100}}, \"edges\": {\"physics\": false, \"length\": 5, \"hidden\": false, \"smooth\": {\"enabled\": true, \"type\": \"continuous\"}, \"color\": {\"border\": \"#2B7CE9\", \"background\": \"#97C2FC\", \"highlight\": \"#3f308e\", \"hover\": \"#3f308e\"}}, \"nodes\": {\"mass\": 3, \"font\": {\"size\": 32}, \"color\": {\"border\": \"#D6D5D3\", \"background\": \"#161616\", \"highlight\": \"#3f308e\", \"hover\": \"#3f308e\"}}, \"options\": {\"highlightNearest\": {\"enable\": true, \"degree\": 2}}}"

You don't need all of them, just the edges and nodes color option. And this is the result:

image

I liked the result but then searching on how to highlight the neighbors I've found this example, which would be cool to implement here.

lgmoneda avatar Dec 19 '20 14:12 lgmoneda

@lgmoneda Cool! I played a bit with your suggested settings and got this, where the selected node and its connecting edges are green, and the hovered one is yellow.

image

I think this already makes the graph much more useful in terms of localizing connections, but would totally love to also get:

  • Highlighting of the first degree connected nodes (although perhaps only the border, to distinguish them from the central one?)
  • More subdued highlighting of second degree connections like in the example you linked.

thriveth avatar Dec 19 '20 22:12 thriveth

Cool! I'm happy it was useful.

I've been playing with the example provided, here's what I have so far:

image

So it highlights the first connection in green and the second connection in pink. It also excludes the labels from the not selected nodes. It becomes really close to the idea of the buffer network, but this option is cool because you can just keep exploring the large graph while you highlight different parts of it. In the buffer network, there's "disruption" by changing the nodes' positions.

I also created a button to enable and disable it. I could totally keep developing this feature and open a PR, but I'd need some directions from @goktug97 to know how to deal with the group stuff, to polish the idea a little bit, and so on.

lgmoneda avatar Dec 20 '20 12:12 lgmoneda

Wow! It looks awesome!!

Maybe something like this can be implemented?

(defcustom org-roam-server-options nil
  "Options TODO: Better Docstring"
  :group 'org-roam-server
  :type 'string)

(defcustom org-roam-server-color-scheme "default"
  "Color scheme TODO: Better Docstring"
  :group 'org-roam-server
  :type '(choice
          ("default" :tag "Default color scheme")
          ("test" :tag "Test color scheme")
          (function :tag "Custom color scheme function")))

(defun default-color-scheme ()
  ;; Revert everything to default (Colors, Options etc.)
  )

(defun test-color-scheme ()
  ;; Instead of setting org-roam-server-network-vis-options directly, it should change it so that it doesn't affect user's options`
  (setq org-roam-server-network-vis-options "{\"color\": {\"border\": \"#2B7CE9\", \"background\": \"#97C2FC\", \"highlight\": \"#3f308e\", \"hover\": \"#3f308e\"}}, \"nodes\": {\"mass\": 3, \"font\": {\"size\": 32}, \"color\": {\"border\": \"#D6D5D3\", \"background\": \"#161616\", \"highlight\": \"#3f308e\", \"hover\": \"#3f308e\"}}, \"options\": {\"highlightNearest\": {\"enable\": true, \"degree\": 2}}}"
        org-roam-server-options (json-encode (list (cons 'disable_grouping t)))))

(defun org-roam-server-color-scheme-fn ()
  (pcase org-roam-server-color-scheme
    ("default" default-color-scheme)
    ("test" test-color-scheme)
    ((pred functionp)
     (funcall org-roam-server-color-scheme))))

(defun org-roam-server-change-color-scheme (color-scheme)
  (setq org-roam-server-color-scheme color-scheme)
  (org-roam-server-color-scheme-fn))

(defservlet* server-options application/json (token)
  (if org-roam-server-authenticate
      (if (not (string= org-roam-server-token token))
          (httpd-error httpd-current-proc 403)))
  (insert (or org-roam-server-options "{}")))

and in .html

var serverOptions = {}
$.ajax({
    async: false,
    type: 'GET',
    url: `/server-options?token=${token}`,
    success: function(data) {
         serverOptions = data;
    }
});
// ...
          if (!serverOptions.disable_grouping) {
              for (let i = 0; i < keys.length; i++) {
                  const k = keys[i];
                  if (!nodes[k].group) {
                      const connectedNodes = tempNetwork.getConnectedNodes(k);
                      if (connectedNodes.length > 0) {
                          const node = connectedNodes.max(compareNodeValues);
                          if (!nodes[node].group) {
                              nodes[node].group = group;
                              group += 1;
                          }
                          nodes[k].group = nodes[node].group;
                      } else {
                          nodes[k].group = group;
                          group += 1;
                      }
                  }
              }
          }
// ...

goktug97 avatar Dec 20 '20 13:12 goktug97

@goktug97 I haven't checked your code yet, but I guess your idea is to give us a direction to adapt this feature to play along with the existing code, right?

image

That's the result of a highlight that makes the selected node yellow, the first connections green (nodes and edges), and the second connections pink (nodes and edges). I'm also excluding all the other edges and node names to make it more readable.

I had to iterate on edges since I didn't want to colorize the second-order connections that are not connected to the first order nodes, so I couldn't inherit color from the nodes. So it makes it a little bit slow.

https://user-images.githubusercontent.com/3893078/103312517-16eab980-49fc-11eb-9816-f84682686eab.mov

In the end, as said, it becomes like the "buffer network" but visualized on top of the whole network the user might get used to. I liked the colors to show the connection degree, I'd love to have it in the buffer network.

lgmoneda avatar Dec 29 '20 20:12 lgmoneda

@lgmoneda That looks really good!

I was thinking something: I really like that the central node has the same color as the edges, as in my screenshot higher up.

As far as I can see, we have both the face and the edge color of the nodes to play with. How about something like this:

  • Central node gets Color1 on both edge and face
  • First-degree edges get Color1
  • First-degree connection nodes get face Color1, edge Color2
  • Second-degree edges get Color2
  • Second degree connection nodes get face and edges both in Color2

As far as I can see superficially, this would also solve the problem of having to iterate over the edges. Unfortunately I don't have the lisp/JS/JSON skillz to code my example.

thriveth avatar Dec 29 '20 23:12 thriveth

@goktug97 I haven't checked your code yet, but I guess your idea is to give us a direction to adapt this feature to play along with the existing code, right?

image

That's the result of a highlight that makes the selected node yellow, the first connections green (nodes and edges), and the second connections pink (nodes and edges). I'm also excluding all the other edges and node names to make it more readable.

I had to iterate on edges since I didn't want to colorize the second-order connections that are not connected to the first order nodes, so I couldn't inherit color from the nodes. So it makes it a little bit slow.

org-roam-short.mov In the end, as said, it becomes like the "buffer network" but visualized on top of the whole network the user might get used to. I liked the colors to show the connection degree, I'd love to have it in the buffer network.

It looks visually appealing!! Yeah, above code is for integration.

Are you using getConnectedEdges to get list of edges that are connected to a first order node

goktug97 avatar Dec 30 '20 07:12 goktug97

@goktug97 yes, I'm doing this:

// get the second degree nodes
for (i = 1; i < degrees; i++) {
    for (j = 0; j < connectedNodes.length; j++) {
        allConnectedNodes = allConnectedNodes.concat(
	    globalNetwork.getConnectedNodes(connectedNodes[j])
        );
    }
}

Considering degrees here is set to 2.

So should I invest in creating it as a feature? Should we use a button to activate this "highlight mode" or create the option as a param in the elisp code? Or would we make it the default behavior when someone clicks a node to highlight it?

lgmoneda avatar Dec 31 '20 11:12 lgmoneda

Well if you have time and want to contribute I think this is a really good feature.

goktug97 avatar Jan 01 '21 09:01 goktug97

@goktug97 ok! I'll see if I can find time to do it. If I can't, I'll send a message here so someone else can keep developing it.

Thanks!

lgmoneda avatar Jan 05 '21 16:01 lgmoneda