animint2 icon indicating copy to clipboard operation
animint2 copied to clipboard

Move scale range calculation from compiler to the renderer.

Open lazycipher opened this issue 4 years ago • 8 comments

Currently, The computations of updating of axes/legends after changing the currently displayed data subset are done in the compiler but there are some limitations, so it will be good to move the computations to the renderer. We sometimes only have a subset of the whole data while computing the scales in the compiler so we are limited in our implementation. This can be solved by moving the computation to the renderer so that we have the whole data to compute new scale values.

lazycipher avatar Aug 20 '20 17:08 lazycipher

Hi, @tdhock, @faizan-khan-iit, Please let me know how do I proceed with this issue.

lazycipher avatar Aug 21 '20 14:08 lazycipher

Hi @lazycipher, regarding this issue, you will first need a little bit of understanding of how we compute the scale ranges to render the axes for different subsets of data.

As an overview, we essentially compute the scale ranges that a data subset would fit in for all possible (not really, that's the issue here) data subsets. When a user is viewing a data subset, we select the pre-saved range for that subset and change the axes accordingly <- this provides a zoom in effect where the user sees the data in the whole plot area.

Here is an example where we always take the full plot area in the right plot. So every time we select a new country, we use the y-axis scale which was pre-computed in the compiler and render that in the plot.

For more details, I highly recommend going through this PR where we implemented the feature. If you do not understand some comments you can just skip them for now or ping me and I will elaborate the important points.

The issue has been discussed here: https://github.com/tdhock/animint/pull/158#issuecomment-240789396 You will get more clarity once you go through the PR. Try running that example and you will understand the data subsets which do not get their scales computed by the compiler.

Hope this helps!

faizan-khan-iit avatar Aug 21 '20 14:08 faizan-khan-iit

there is a javascript function in https://github.com/tdhock/animint2/blob/master/inst/htmljs/animint.js called update_scales which I think needs to be modified. I think you should also modify the code which does the data subsetting after each click/selection. In addition to computing the subsets, it should save the ranges (for each panel), which could then be used in update_scales.

tdhock avatar Aug 21 '20 16:08 tdhock

Hi @tdhock @faizan-khan-iit , I started to look at the code for computing the domain from last week, As I understand it, the logic for update_axes on the compiler side can be found in these two files: z_animint.R , z_animintHelper.R.

  • The compute_domains function seems to compute the scale range for each geom. This function returns the computed domain (scale range) for the specific geom and data subset.
  • The get_domain function takes in a list of subset domains(from the above function) and computes the final domain. The final domain is computed such that it contains all the subset domains.

On the renderer's end (within the JS code) at update_scales(), the renderer would receive the subset data(the .tsv files) from the compiler, with other associated meta-data, like the saved ranges from plot.json.

I read through the original PR you mentioned above, it seems you're suggesting shifting the compute_domains and get_domain functions to the JS side. Is that correct?

Faye-yufan avatar Sep 26 '23 18:09 Faye-yufan

right!

tdhock avatar Sep 26 '23 21:09 tdhock

I'm looking into the for loop here to see if we can move all of its variables over to the JS side. I have some problem coming up with the implementation because it looks like not all ggplot info in the environment is making its way to plot.json.

For example, ggplot.list doesn't seem to be directly exported. This causes issues when trying to assign values in JS, like setting built_data based on this layers$data: https://github.com/animint/animint2/blob/12b57c9c03969cfdbdc41690162329102905fd48/R/z_animint.R#L493-L494, which is an input parameter for compute_domains.

From what I can tell, AllPlotsInfo is what gets sent to plot.json under the 'plots' field. It seems to originate from parsePlot(): https://github.com/animint/animint2/blob/12b57c9c03969cfdbdc41690162329102905fd48/R/z_animint.R#L331-L332 Another variable, g.list comes from Geom$export_animint() https://github.com/animint/animint2/blob/12b57c9c03969cfdbdc41690162329102905fd48/R/z_animint.R#L368-L376 and is used for compute_domains input as well.

I think I can get most of these parameters into plot.json so that we can work with them in JS. But I'm not sure what to do about data that only exists on the compiler side, like layers$data. Right now, animint2 only exports the bare minimum (.tsv files) for rendering the viz. Should we consider exporting the entire dataset?

Faye-yufan avatar Oct 02 '23 06:10 Faye-yufan

I'm not sure I understand what you are asking, can you please clarify? I'm not sure that exporting the entire dataset is a good idea (for efficiency). It should be possible to derive the scales/domains given the data that is already being exported. The logic should be: for each axis (x and y), and each showSelected subset, compute domains (over all geoms on that plot). This will probably be easier if we refactor the JS code to use OO, one object/class per geom, with a method get_domains() that returns a JS object that can tell us what is the min,max for each subset (or for the currently selected subset). Does that make sense?

tdhock avatar Oct 02 '23 20:10 tdhock

Thanks for clarifying how it works! I think I was focusing too much on directly converting the R function into JS, rather than focusing on the functionality itself. You're right, we can definitely calculate scales/domains with the data being exported. I'll go ahead and open a PR to start the refactor.

Faye-yufan avatar Oct 03 '23 15:10 Faye-yufan