Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move scale range calculation from compiler to the renderer. #48

Open
lazycipher opened this issue Aug 20, 2020 · 8 comments
Open

Move scale range calculation from compiler to the renderer. #48

lazycipher opened this issue Aug 20, 2020 · 8 comments

Comments

@lazycipher
Copy link
Contributor

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
Copy link
Contributor Author

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

@faizan-khan-iit
Copy link
Contributor

faizan-khan-iit commented Aug 21, 2020

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: tdhock/animint#158 (comment)
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!

@tdhock
Copy link
Collaborator

tdhock commented Aug 21, 2020

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 tdhock changed the title Move data subset calculation from compiler to the renderer. Move scale range calculation from compiler to the renderer. Sep 15, 2022
@Faye-yufan
Copy link
Contributor

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?

@tdhock
Copy link
Collaborator

tdhock commented Sep 26, 2023

right!

@Faye-yufan
Copy link
Contributor

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:

animint2/R/z_animint.R

Lines 493 to 494 in 12b57c9

built_data <-
ggplot.list[[p.name]]$built$plot$layers[[layer.i]]$data
, 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():

animint2/R/z_animint.R

Lines 331 to 332 in 12b57c9

parsed_info <- parsePlot(meta, p, list.name) # calls ggplot_build.
AllPlotsInfo[[list.name]] <- parsed_info$plot.info
Another variable, g.list comes from Geom$export_animint()

animint2/R/z_animint.R

Lines 368 to 376 in 12b57c9

gl <- Geom$export_animint(
L, df, meta, layer_name,
ggplot.info$ggplot, ggplot.info$built, AnimationInfo)
## Save Animation Info separately
AnimationInfo$timeValues <- gl$timeValues
gl$timeValues <- NULL
## Save to a list before saving to tsv
## Helps during axis updates and Inf values
g.list[[p.name]][[gl$g$classed]] <- gl
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?

@tdhock
Copy link
Collaborator

tdhock commented Oct 2, 2023

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?

@Faye-yufan
Copy link
Contributor

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants