almende / vis

⚠️ This project is not maintained anymore! Please go to https://github.com/visjs
7.85k stars 1.48k forks source link

Order by id, label nodes #1927

Open salonso6 opened 8 years ago

salonso6 commented 8 years ago

Hi,

I´m using the version 4.15.0 I want to know if you can sort the nodes by id, label or other attribute which are at the same level. I can send my example.

hierarchical:{
  enabled: true,
  levelSeparation: 150,
  direction: 'LR',
  sortMethod: 'directed'
}
mojoaxel commented 7 years ago

I'm closing this issue due to inactivity. If this issue is still relevant please feel free to reopen.

mmcnl commented 7 years ago

Hi @mojoaxel and @wimrijnders , I believe I have the same question. I'm using hierarchical layout with the following settings and would love it if the LR order of my nodes followed the order that they are given in the dataset. Is that possible? Ideally I wouldn't want to specify a x coordinate for each node because I don't care about the exact x-value, only the L-R ordering on each level of the graph. Also, I saw in the comments mention about setting the x/y coordinates, but couldn't find an example of how to do that using vis.DataSet(nodes);.

      hierarchical: {
        direction: 'UD',
        levelSeparation: 120,
        nodeSpacing: 200,
        sortMethod: 'directed'
      }
wimrijnders commented 7 years ago

I'm trying to understand the question.....what I think you mean, is that network flips around the order of the nodes when building up the network, right?

I've been trying to hack a quick example of networks not following the dataset order, without success. I can show the converse though. I think this is what you want:

download 1

So, given that the node id's are the order in the dataset, the second level is strictly numbered. After that, the ordering breaks down because of the defined edges. But the ordering is maintained as much as possible.

Is this correct?


So a changed ordering is the network module trying to optimize (for space) the layout of a network. You do have some control over this; try disabling the following options (also read up on them in the docs):

The resulting layout will be less efficient in terms of space used, but it will probably be more like you want it.

mmcnl commented 7 years ago

image Thanks for the quick reply @wimrijnders ! What I'd like is to be able to sort nodes on a particular level. For example in the screenshot, despite sending an array sorted in order of the numbers in the labels (biggest to smallest), the network renders in some other order (that I'm not understanding). So specifically, I'd like to ensure that the last level is ordered [3998] [563] [87] [0] [0]. Is that possible?

mmcnl commented 7 years ago

I tried setting the options you mentioned, but it didn't seem to make any difference.

      hierarchical: {
        direction: 'UD',
        levelSeparation: 120,
        nodeSpacing: 200,
        blockShifting: false,
        edgeMinimization: false,
        sortMethod: 'directed'
      }
wimrijnders commented 7 years ago

OK. So my immediate reaction was 'Hold on, let me check the code...'

Then I realized that that meant the answer is 'No'. There is no out of the box support for sorting per level.

But I'll check the code anyway.

mmcnl commented 7 years ago

Oh, that's too bad. Is it possible to define a function to sort nodes based on a custom value added in their data?

wimrijnders commented 7 years ago

I tried setting the options you mentioned, but it didn't seem to make any difference.

Yeah, now that I understand the question a bit better, I realize that my suggestion is moot. What happens then, is that the order of definition in the DataSet is maintained, which is not what you want. You want an explicit sort on a given field of the DataSet items.

mmcnl commented 7 years ago

As I do have full control of the order of the dataset, I was sending in the array with its values sorted, so I was hoping that they would be put into levels in the same order, eg:

   1
  2 3
4 5 6 7
wimrijnders commented 7 years ago

And this didn't happen? The nodes don't get rendered in the order you enforced?

I think a simple example is in order if you want to pursue this further. Would you mind setting up a jsfiddle or suchlike?

wimrijnders commented 7 years ago

Is it possible to define a function to sort nodes based on a custom value added in their data?

Yes, in a roundabout way. Following code is untested, but it illustrates the process:

var data = new vis.DataSet(input_data);

var sorted_data = data.get({
  order: function(a, b) {
    // Your glorious sort routine here
  }
});

var data2 = new vis.DataSet(sorted_data);
var network = new vis.Network(container, data2, options);

... but TBH, network will still probably mangle the order in the way it sees fit. So actually, this is useless and I regard the above as an exercise to warm up my fingers for today's coding.


Edit: It did give me an idea, though, on adding sorting to DataView. So it wasn't completely pointless.

mmcnl commented 7 years ago

OK, here's a try: http://jsfiddle.net/ffq8ch6d/1/ . The nodes were passed in the order of their labels. image

mmcnl commented 7 years ago

Also, I realize what I really want is for ordering among sibling nodes. So in the above, my ideal would be:

                 x
     162276                      1162
57301   13173  325         498    326  26

I realize this is probably out of scope but it would be amazing if it could be accomplished.

wimrijnders commented 7 years ago

Oh my, the turnaround time is awesome here. It motivates me to check the code.

I realize what I really want is for ordering among sibling nodes

Yes, that is finally clear to me now.

wimrijnders commented 7 years ago

Interim note: It appears that the key method here is _setPositionForHierarchy() in lib/network/modules/LayoutEngine.js. This should somehow be manipulated for sorting purposes, and _condenseHierarchy() should not run - that shuffles up the network.

I'll let it rest for now; my evil pointy haired boss, which is me, is getting impatient.


Update: Have to ask, is this something you want RSN? Because it's not something I can offer a workaround for. You'll have to wait for its release (one month at the very least). In the meantime you might use an interim build of vis.js with a fix for this.

mmcnl commented 7 years ago

@wimrijnders I am trying to demo a prototype of my project soon (in the next 2 weeks), so I might investigate a monkeypatched version of vis.js and I'll keep my eyes out for a new release. Also, if there's a dev version of the code, I'm happy to use that if that would be available sooner than an official release. Once again, thanks so much for all of the gracious support with this!

mmcnl commented 7 years ago

Hi @wimrijnders , I'm looking into this issue again and was curious if there's been any movement in the dev channels on this. Thanks again for the help with this question.

Update: I've just realized that it appears that it seems possibly to reliably control the within-level node ordering by simply changing the order of the edges. For example, in this fiddle http://jsfiddle.net/ffq8ch6d/1/ changing the last two edges from:

{
  "from": 2915,
  "to": 2916
}, 
{
  "from": 2915,
  "to": 2917
}

to this:

{
  "from": 2915,
  "to": 2917
},
{
  "from": 2915,
  "to": 2916
},

reliably swaps the position of these nodes: image

wimrijnders commented 7 years ago

I'm looking into this issue again and was curious if there's been any movement in the dev channels on this.

Alas, no. I've been squashing bugs lately and haven't come around to handling stuff I regard as 'feature-requests'. Sorry.

it seems possibly to reliably control the within-level node ordering by simply changing the order of the edges

Genius thought! Of course, the strict handling on order also applies to edges. I should have been able to think of that myself (which is what makes it genius).

mmcnl commented 6 years ago

Hello again @wimrijnders, I've run into a case where the edge-ordering trick falls down: when there is even one node with more than one parent edge (i.e. it's not strictly hierarchical), it seems the edge-ordering is abandoned and the network reverts to sorting based on the ids of the nodes. I've made a jsfiddle to illustrate: For example, here the nodes are grouped by the ordering of the edges. http://jsfiddle.net/qz4s5724/2/ This is ideal for me, as I can easily control the insertion order of edges: image However in this next example, http://jsfiddle.net/qz4s5724/3/ by simply adding one additional edge , the ordering is scrambled and it seems the network reverts to sorting based on the ids of the nodes. image Is this what's actually taking place? This is not ideal for my application because I don't have control over the ids and nodes can add parents (and become a graph not a tree) at any time.

Do you have any ideas for workarounds? Or could I make a feature request to add an "order" field that would override the sorting at a given level of the hierarchy?

Thanks much for any ideas.

mmcnl commented 6 years ago

@wimrijnders, I wonder if you might have a moment to weigh in on my previous question? https://github.com/almende/vis/issues/1927#issuecomment-342757779 Thanks very much!