OneZoom / OZtree

OneZoom Tree of Life Explorer
Other
87 stars 18 forks source link

Improvements to flight and navigation performance for polytomy view #91

Open jrosindell opened 6 years ago

jrosindell commented 6 years ago

Currently it’s using a linear zoom which doesn’t always feel it’s tracking the path towards a location.

We're worried about a jittery solution that makes people feel seasick

Perhaps the solution is to mostly zoom out without panning and then smoothly transition to pan near the end.

jrosindell commented 6 years ago

Possible extension - flights from one leaf to another with mostly zooming out then smooth panning then mostly zooming in

lentinj commented 6 years ago

I'm struggling a bit converting this into code changes. There seems to be a selection of flight methods in the controller:

What in particular are we trying to fix? Seems like plotting a course between ~10 nodes along the path in transition_animation would be easier and more generically solve the problem. Although maybe this is what we thought would make us seasick.

In addition many attempts in polytomy view result in Uncaught TypeError: Cannot read property 'is_interior_node' of undefined. I'm guessing this a good place to start, even if it isn't the main event of this ticket.

lentinj commented 6 years ago

Naziha also wants the quick links to be in flight mode.

jrosindell commented 6 years ago

I think perform flight animation is what you want to fix first.

perform flight transition was for zooming from leaf A to the common ancestor of that and leaf B and then to leaf B - this is the only sensible way to get from A to B more generally.

If the transition from a leaf / node to a node higher in the hierarchy could be got working in a smoother way, and similarly from a node to a descendent of some kind (the other direction of the above) then anything else could be strung together by seeking common ancestors. You'd need to pause for a moment on the common ancestor before zooming in to leaf B but that's probably overall better than building something that does the whole path entirely smoothly which would certainly be more complex. That would enable perform flight transition to be fixed which will be needed for what Naziha wants...

I think the reason why flight transition is not in operation is that no current UI features demand the function so it was never kept working. You will need perform flight transition because you need to find the common ancestor of the current view of the tree with the place you're wanting to zoom to - then zoom to that ancestor before zooming in again on the desired place. This is the only way to get a nice fight to e.g. birds if you are already zoomed deeply into primates - you must zoom out to amniotes and then in again to birds as two separate stages with a short pause inbetween.

To make the quick links be in flight mode (or have a switch of some kind) should be pretty easy and entirely doable from the UIKit part of the code over the OZtree JS package. Essentially you just need to switch the jump_to_OZid for perform_flight_transition when the latter is fixed...

Sorry it's a bit complex!

lentinj commented 6 years ago

The above is starting to work, although temperamental:

lentinj commented 6 years ago

Moths seem to be a particularly nasty case that reduce rendering to a crawl. It could be mitigated to a certain extent, but I'm not sure what can be done in general.

lentinj commented 6 years ago

@jrosindell I seem to remember that there are parameters that control loading of detail whilst in flight mode, but I can't find them. Do you remember where to look?

Currently flights in look very bare as a result.

jrosindell commented 6 years ago

I have a memory that all the details are pre fetched before the flight begins - this is so that the flight is guaranteed to be of reasonable quality and smoothness. This makes me think that it's a consideration for more complex flights too which should prefetch the tree for the whole flight (i.e. the zoom out part and the zoom in part of a more complex transition). Hopefully this helps - I don't recall precisely where to look off hand and am writing in a hurry but will look again later.

lentinj commented 6 years ago

I have a memory that all the details are pre fetched before the flight begins

Yes, they are. Without it wouldn't know where to go.

I think I've seen something in the rendering pipeline that reduces detail to cope with flights, which would solve all my problems. I must be able to find it again :)

lentinj commented 6 years ago

Okay, when I said "they are", apparently I was confusing developing nodes and fetching their details. I presumed that developing nodes also meant we would fetch the detail. That's not the case.

fetch_node_detail() is disabled during flight, re-enabling solves our problems, but can't be the way forward.

But I've found another flight mechanism, fly_to_node here: https://github.com/OneZoom/OZtree/blob/master/OZprivate/rawJS/OZTreeModule/src/navigation/page_loading.js#L11 get_details_of_nodes_in_view_during_fly() I'm guessing is what I want.

lentinj commented 6 years ago

Okay, so the above:

There's lots of commonality between the various code paths, ideally there'd be just one but I think that's a task for another day. Specifically when organising the tours, since then transition_animation()'s fate can also be decided.

jrosindell commented 6 years ago

Thanks Jamie - I've been looking on your Shuttlethread hosted version and see that something has changed they look smooth and I definitely saw a smoother zoom in some cases but it’s not clear which functions have used improved zoom and which functions have not yet. In particular, I don’t think panning and zooming have been decoupled yet and this was going to be part of the plan to have more logical paths to the destination. At least it doesn't look as though they have.

lentinj commented 6 years ago

I don’t think panning and zooming have been decoupled yet

See here:

https://github.com/OneZoom/OZtree/blob/3.3/OZprivate/rawJS/OZTreeModule/src/position_helper.js#L337

There's separate functions for pan and zoom, pan ramps up half-way through the first zoom, then back down again in the second. Zoom OTOH accelerates and decelerates the same on the way in and out, giving a rest at the final location.

For example: onezoom.controller.perform_flight_transition(-835084, -796335) you see it zoom out from the elephant, then just as the elephant picture goes out of zoom it moves off to the right.

However, on long zooms where there's reanchoring it's still linear (onezoom.controller.perform_flight_transition(-835084, -294475)), because the number of steps isn't known. However, if such re-anchoring animation steps just zoom, then the end result is fairly similar, if a little more crude. I'll change that.

lentinj commented 6 years ago

improved zoom and which functions have not yet

jrosindell commented 6 years ago

This is great Jamie! The transitions work really well. I have a couple of small thoughts on this...

I think your solution is a good one... just to reiterate and check we're on the same page here if you're on a node that requires re-anchoring during the zoom out to a common ancestor then you zoom out with re-anchoring and have no panning, then at some point you turn off reanchoring and use a normal smooth transition that combines panning and zooming right? Then similarly if the destination requires reanchoring then you zoom so far in to it using the smooth transition then switch to zooming only? I'm not sure if this last part is what you've done from looking at it. The results would be nicest if you continued the smooth transition for the first part of the zoom in to a distant leaf or node, then transition not to zooming only but to linear zooming and panning - the reason for this is that with linear zooming and panning the minute errors in x,y are automatically corrected during zoom in a way that's imperceptible to the user, however if you do zoom only it'll miss the the target by a chunk due to not being possibly lined up accurately enough to begin with. Note that I had no choice but to do re-anchoring every time step (or not at all) when I implemented this otherwise it's impossible to make it smooth during the re-anchoring phase.

lentinj commented 6 years ago

if you're on a node that requires re-anchoring during the zoom out to a common ancestor then you zoom out with re-anchoring and have no panning, then at some point you turn off reanchoring and use a normal smooth transition that combines panning and zooming right?

Currently a reanchoring step will zoom out linearly (with no pan), then the final non-reanchoring stage will zoom and pan linearly. This could also ease in a similar fashion, but just being linear looked fine to my eyes. Given the speed at which the zoom will be going you don't notice that it's not smoothed out IMO.

Then similarly if the destination requires reanchoring then you zoom so far in to it using the smooth transition then switch to zooming only?

There'll be a smooth panning state as a result of the flight to the common ancestor, then the majority of (reanghoring) zoom will be linear, then there'll be a final adjustment.

The results would be nicest if you continued the smooth transition for the first part of the zoom in to a distant leaf or node, then transition not to zooming only but to linear zooming and panning

I think explaining this would work a lot better with some example flights if you mind dredging some up. But yes, it should be reasonably easy to apply some acceleration to the first reanchoring step. They do lurch somewhat.

jrosindell commented 6 years ago

I think (onezoom.controller.perform_flight_transition(-835084, -294475)) that you already used illustrates what I'm saying....

You get: zoom out, zoom out, zoom out, zoom linear out, zoom linear in, zoom linear in, zoom linear in, zoom linear in

I'd instead suggest... zoom out, zoom out, zoom out, zoom linear out, zoom linear in such that the majority of panning is complete and only fine adjustments needed from now on, zoom linear in, zoom linear in, zoom linear in. This routine would mean that the zoom in with re-anchoring is the exact reverse of a zoom out with re-anhoring. I think this should be pretty easy to implement - what do you think of the idea?

lentinj commented 6 years ago

Hrm, that wasn't the best commit wording, ooops.

jrosindell commented 5 years ago

Before this issue is closed I'd like to make sure that the whole site does use this improved flight animation and also that there are not outstanding performance issues relating to flight

jrosindell commented 5 years ago

I think there are still issues with flight....

when users click on search results there is often a long wait before the flight starts and the user misses the start of the flight.

jrosindell commented 5 years ago

Naziha tested the frame rate against the earlier version created by Leila and found that the frame rate was much worse on OneZoom than on Leila's version. Unfortunately the test was not a fair test because she was running Leila's version locally on a 192.168..... address whereas OneZoom was being run on the OneZoom beta site over the net. Still, I think we do need to think about performance issues in deployment over the web. This particular issue is very important to Naziha

jrosindell commented 5 years ago

Sometimes the flight is not smooth, and jerks suddenly - it feels unstable / unreliable.

jrosindell commented 5 years ago

I've noticed some polytomies still have performance issues

http://beta.onezoom.org/life/@Acontiinae=156830?vis=polytomy#x895,y681,w0.0208

the node can be found by seeking common ancestor node between Hesperiidae and Riodinidae

lentinj commented 5 years ago

when users click on search results there is often a long wait before the flight starts and the user misses the start of the flight.

It's not actually waiting a long time, it's a refresh-loop-not-activated bug. You're actually waiting until you get bored and start moving the mouse around, which restarts the refresh loop and you get to see the flight again.

Fixed in the above.

You do still have to wait for the download & nodes to develop, but that doesn't cause you to miss the start of the flight.

lentinj commented 5 years ago

I've noticed some polytomies still have performance issues...

I'm not sure what I'm supposed to be looking at here, and/or what the desired result is.

jrosindell commented 5 years ago

I've noticed some polytomies still have performance issues... I'm not sure what I'm supposed to be looking at here, and/or what the desired result is.

This issue is that if you go here /OTOP/@Acontiinae=156830 then zoom out a little you reach a large polytomy for which performance is still unacceptably jerky and slow. I'm not sure if this is a bug or a tweak needed to the performance improvements already coded or a new limitation that I've randomly unearthed with user testing.

jrosindell commented 5 years ago

Thanks for fixing the other issues mentioned.

The other really important thing here is the performance issue

Naziha tested the frame rate against the earlier version created by Leila and found that the frame rate was much worse on OneZoom than on Leila's version. Unfortunately the test was not a fair test because she was running Leila's version locally on a 192.168..... address whereas OneZoom was being run on the OneZoom beta site over the net. Still, I think we do need to think about performance issues in deployment over the web. This particular issue is very important to Naziha

jrosindell commented 5 years ago

Maybe it's not appropriate for OTOP and should be labelled separately as an enhancement for non OTOP time, but I would like the other views to benefit from the improved flight dynamics that @lentinj has developed - e.g. polytomy, natural, spiral and so on within life. I'd also like those views to do the flights all the time but with an option to switch off from settings.

lentinj commented 5 years ago

This issue is that if you go here /OTOP/@Acontiinae=156830 then zoom out a little you reach a large polytomy for which performance is still unacceptably jerky and slow.

Too many nodes to develop in one go. The jerks are when ~1000 nodes are being developed as part of one cycle. Telling _create_undeveloped_nodes() to stop when it gets beyond ~25 largely cures matters. However:

jrosindell commented 5 years ago

Telling _create_undeveloped_nodes() to stop when it gets beyond ~25 largely cures matters.

I guess you didn't push changes here as you don't consider the issue solved by just this

The nodes wouldn't be developed in the first place mid-flight. Maybe the steps of a zoom-in / zoom-out aren't being categorised as flight.

Ah, it's true I may be posting this in the wrong place if the jerkiness is on mouse interaction this doesn't mean necessarily it's jerky on flight.

Node developing shouldn't be in the render loop anyway. Both because we obviously want to keep the render as fast as possible, and the render loop won't happen when the view is idle now, so that time can't be used to fill gaps.

Agreed, also because the renderer needs to be called as part of flight, but flight should have redeveloped a suitable amount of the tree

Node developing shouldn't be this slow: The numbers involved are paltry. Converting nodes back to traditional Javascript objects with prototype inheritance could be interesting.

If you think this is not too much work and could make a big difference please try. This feels like quite a lot of surgery to the code from my perspective, but I'll leave it up to you.

jrosindell commented 5 years ago

Another related point is the idea of rendering the elements on multiple canvases instead of sorting them for their position in the layers as is currently done - this was discussed in #122 but maybe is a lot of work.

lentinj commented 5 years ago

Yup, didn't get to comment last night. Whole bunch of render-loop speedups when there's many nodes to deal with, see above.

I did try re-writing the ObjectPool, but that's unearthed bugs elsewhere, see #142.

The final commit, https://github.com/OneZoom/OZtree/commit/12a2cf7e1d32b5c0e14172c162cea412e872ac9e as a result has the limit far higher than my previous comments. Still a bit ugly, but far less of a worry than before.

jrosindell commented 5 years ago

This feels much better and faster, but there is still something now quite right with the layout of the fake leaves. I took the attached screenshot from a zoom from the root to insects under popular places but many flights do yield the same issue which I think is caused by improper handling of fake leaves (either the positioning or the type of leaf isn't quite right.

jrosindell commented 5 years ago

otop bug1

jrosindell commented 5 years ago

the problem is the orange circle just above 'copepod' which seems not at teh topics of the tree but on a node somehow - maybe this should be a fan sprite and that's the problem? I'm not sure but it doesn't look right.

lentinj commented 5 years ago

the problem is the orange circle just above 'copepod'

These are undeveloped nodes, I believe. has_child() works off node.children.length, which isn't populated before the node is developed.

This isn't as simple as fixing has_child, doing that has all sorts of side-effects.

jrosindell commented 5 years ago

Ah, you mean that the node is partially developed, some of its children can be drawn but not all hence we get an additional fake leaf that appears to be higher up the tree as well as some developed children too? If that is so then I'm not sure what the solution is here are some ideas, but I don't see any as a high priority right now - I'm relabelling this as non essential.

ideas to fix

a node drawn as a fake leaf unless all its children are developed a node with partially developed children draws a fake additional child (the circle in the issue above thus appears on the end of a stem) in this case no fake leaf is drawn

none are ideal, hence I suggest leaving it for now.

lentinj commented 5 years ago

No, it's simpler than this (I think!). When drawing a node, it's decided based on has_child() what shape to draw, no children then we should get a leaf (or circle in OTOP), otherwise fake a node (i.e. fan).

Problem is, has_child() bases it's answer on children.length, which is populated at develop_node() time. So an undeveloped node's has_child() is false regardless of whether it actually has children, thus a leaf shape is drawn. Somewhere there'll be a has_child() to replace with full_children_length > 0.

This is particularly noticeable on flights, where the developing outside the main path is minimal.

jrosindell commented 5 years ago

Ah I see.... you're right. Hopefully this would not be too bad to fix then with simple search through the rendering logic.

lentinj commented 5 years ago

@jrosindell As part of looking at what one might want to change in #139 for an improved rendering mode, I've done the above.

The first few sort out the giant nodes above, which whilst we marked non-essential are really obvious in flight views, and are going to result in questions. So I fixed it.

As a result of this, it was more obvious my fake fans weren't centered, so the third fixes that. On long flights you now get the impression of the tree growing which is quite nice.

Finally, the values I was trying to loosen actually aren't so critical, thanks to previous work in this ticket, so I've just loosened them for all views.

lentinj commented 5 years ago

(hrm, I never submitted this comment from yesterday)

@jrosindell As part of looking at what one might want to change in #139 for an improved rendering mode, I've done the above.

The first few sort out the giant nodes above, which whilst we marked non-essential are really obvious in flight views, and are going to result in questions. So I fixed it.

As a result of this, it was more obvious my fake fans weren't centered, so the third fixes that. On long flights you now get the impression of the tree growing which is quite nice.

Finally, the values I was trying to loosen actually aren't so critical, thanks to previous work in this ticket, so I've just loosened them for all views.

jrosindell commented 5 years ago

Thanks @lentinj this is looking a lot better. Having played with it for a while I see that the flights are smooth (on both my iPhone and laptop). Let's see what the other testers have to say. Meanwhile, there are a few issues remaining still.

1.) the images on signposts no longer load in advance of the flight animation starting so that actually one can get a flight with no images at all. This happens especially when visiting a URL with ?init=zoom. This includes an issue that seems new to me where the circular borders around an image get loaded on the ordinary OneZoom view at times when the image itself is not loaded. 2.) the logic around clicking on signposts to zoom in doesn't seem to use the same (efficient) flight logic as the search and popular places. 3.) the normal view (non polytomy) is still not what it was before in terms of the fake leaves - they are still large and grey, rather than smaller, leaf shaped and green. 4.) (lower priority as at some point I guess it will be impossible to go further) the popular places area for mushrooms continues to have not great performance around the (giant) polytomy.

lentinj commented 5 years ago

4.) (lower priority as at some point I guess it will be impossible to go further) the popular places area for mushrooms continues to have not great performance around the (giant) polytomy.

https://github.com/OneZoom/OZtree/commit/26c82688395787469ee7762eb7342dd46829307b made this slightly worse again by loosening the restrictions that made it work. My hope is that the remaining issue in https://github.com/OneZoom/OZtree/issues/108 will get around having to tighten these restrictions again.

lentinj commented 5 years ago

3.) the normal view (non polytomy) is still not what it was before in terms of the fake leaves - they are still large and grey, rather than smaller, leaf shaped and green.

There's 2 problems:

  1. The large grey "baubels" are created by branch_layout_helper:draw_interior_node. The attempt to hide the line joins is going wrong (ooo look, another case affected by a miscalculated arcr).
  2. But whereas before they would have been covered by a leaf (thanks to the above bug it was assumed these were leaf nodes when fake), they're now exposed.

I'm not entirely decided how to fix this. the first may be solved by https://github.com/OneZoom/OZtree/issues/143, but we need to put this explicit decision that fake nodes with children get a leaf somewhere regardless.

lentinj commented 5 years ago

2.) the logic around clicking on signposts to zoom in doesn't seem to use the same (efficient) flight logic as the search and popular places.

It's the same code-path, just with a linear acceleration function. You can accellerate into the signpost but it seems a bit silly on the small flights that you do.

jrosindell commented 5 years ago

2.) the logic around clicking on signposts to zoom in doesn't seem to use the same (efficient) flight logic as the search and popular places.

It's` the same code-path, just with a linear acceleration function. You can accellerate into the signpost but it seems a bit silly on the small flights that you do.

What I mean is not so much that I'd like an accelerating fancy flight path for such a short journey, but rather that the outright performance is poor for some reason, jerky unlike the longer flights.

jrosindell commented 3 years ago

I'm leaving this issue open because the polytomy view on the main side (not on OTOP) has quite poor performance compared to the polytomy view on OTOP. It would be great to look again at the performance issues, particularly for the main site polytomy view. https://www.onezoom.org/life/@=93302?vis=polytomy&img=best_any&anim=flight#x672,y1468,w3.2739

I'll add that this isn't just about the flights - it's also about navigation performance.

lentinj commented 3 years ago

Do you have a particular example here? My standard -> "Elephant Hawk-Moth" -> "Elephant" -> ... is looking like it gets just as many frames as OTOP under Chrome.

Navigation zoom performance is a harder problem anyway since content is being loaded on the fly, which both makes it harder on the system and harder to have a consistent test, but doesn't look obviously broken.

What however does look obviously broken is the size of some of the signposts whilst flying to the elephant hawk moth. The massively branching nodes seem to be an edge case the visibility parameters aren't covering.

lentinj commented 3 years ago

@jrosindell You said you were going to see if the publication correction had a particular example? Failing that if you have a chance to find something that is failing predictably then I can have a look. From memory the worst case is loading a page whilst already zoomed into something and zooming back out. However, it could have been they tried something like that and just didn't have the network bandwidth to make it work smoothly.

If we don't have a reproducible example, then I'll compare OTOP and polytomy setups to see if there's something that could be copied over.

hyanwong commented 3 years ago

All that the reviewer said was:

I was pleased to see that the interface in OneZoom provides the user an option to display "polytomies", and what a difference that makes! Large polytomies are rendered as semi-circular fans, which changes the look and feel of the tree in places quite significantly. However, for large polytomies it can dramatically slow down rendering speed compared to the binary tree rendering mode. This detracts from the otherwise exceptional experience provided by the code. One approach to fixing this would be to render a translucent semicircle with no edges per se, until the zoom level warrants display of actual edges.

The only other comment I can find related to polytomy navigation is this:

Related to that, tree navigation using mouse-dragging does not always work flawlessly, especially not in the polytomies projection. If one tries to explore a clade and move along a longer branch, one gets stuck once no nodes are visible anymore.