casperhart / detourr Goto Github PK
View Code? Open in Web Editor NEWAnimations for {tourr} using htmlwidgets for performance and portability.
Home Page: https://casperhart.github.io/detourr/
License: Other
Animations for {tourr} using htmlwidgets for performance and portability.
Home Page: https://casperhart.github.io/detourr/
License: Other
Rather than removing the palette
argument entirely, I think we could restrict it to being a function, and not allow a vector of colours to be used. That way we can simplify the logic significantly, and users can use tour_aes(colour = I(...))
if they need more granular control.
would you like to add a "snapshot" button and then be able to export to svg/png/jpg? it is useful for your thesis writing too.
library(detourr)
library(crosstalk)
library(plotly)
library(DT)
shared_flea <- SharedData$new(tourr::flea)
a <- plot_ly(shared_flea, x = ~ tars1, y = ~ head) %>%
add_markers() %>%
highlight(on = "plotly_click", dynamic = TRUE)
b <- animate_tour(
shared_flea,
tour_path = tourr::grand_tour(2),
display = display_scatter(tour_aes(colour = species)),
width = "100%"
)
c <- datatable(shared_flea, width = "100%")
bscols(widths = 4,
list(
filter_checkbox("species", "Species", shared_flea, ~species),
filter_slider("head", "Head", shared_flea, ~head, width = "100%"),
c
),
a, b
)
Axis labels should not be visible outside the boundary of the canvas
Ability to select points and modify colour when the animation is paused, such that the colour persists when the animation is played again.
Would require a controls panel to be completed first, so that you can switch between orbit controls and point selection.
Infer 2D vs. 3D animation based on the dimension of the supplied projection matrices. I.e. the dimension of the tour specified by the user.
library(d3tourr)
animate_tour(
tourr::olive, -area,
display = display_scatter(tour_aes(colour = region)),
render_opts = list(max_bases = 10)
)
#> Error in warn("`colour` aesthetic is of type double, but only discrete colours are implemented"): could not find function "warn"
Created on 2021-07-18 by the reprex package (v2.0.0)
We can leverage other html widgets in R through {crosstalk} to link with animate_tour()
, so we don't need to reinvent the wheel for 1-dimensional graphics or parallel coordinates etc.
Add axis labels to visual
The Three.js code should be bundled separately from the main JS code because it seldom changes, and should reduce the size at which the repository grows as the TS code changes.
I personally find the current user interface a bit clunky, especially the need to use render_opts = list(...)
to change the max_bases
argument, and usingtour_aes
for aesthetics.
I propose the following changes:
render_opts
in favour of individual arguments for max_bases
, fps
, etc.So instead of:
library(d3tourr)
animate_tour(
tourr::olive, -area,
display = display_scatter(tour_aes(colour = region)),
render_opts = list(max_bases = 10)
)
We would have:
library(d3tourr)
animate_tour(
tourr::olive, -area,
display = display_scatter(colour = ~region),
max_bases = 10
)
@earowang let me know what you think
Points don't render well on low DPI monitors. This can be improved by adding antialiasing to the shaders.
A couple of useful resources for helping with R packages:
demo/
folder on the top leveldemo/
to .Rbuildignore
to ignore demo/
when building the R packageControls for play / pause, orbiting, restart, etc.
Currently we have one HTML Widget implemented, which is scatter_widget
. However this is starting to get pretty big and unwieldy, so I propose splitting it out in to separate widgets, and renaming to display_scatter
to match the R function e.g. splitting in to multiple classes such as:
display_scatter
(core, abstract class)
display_scatter_3d
(inherits from display_scatter)display_scatter_2d
(inherits from display_scatter)The 2d and 3d versions differ only by their shaders, control behaviour, camera, and matrix multiplication function, so the extensions for 2d and 3d would be relatively small. Once this is implemented, further extensions like the slice tour would become much easier. For instance, we could create:
display_slice_3d
(inherits from display_scatter_3d
)display_slice_2d
(inherits from display_scatter_2d
)display_depth
(inherits from display_scatter_3d
(no 2d version))Note that in R, we would still use a single display_scatter
function, and infer whether the 2d or 3d version should be used based on the tour path provided.
Let me know your thoughts on this @earowang. I know inheritance can become a bit of a mess if not done properly, so I want to make sure I'm not overcomplicating it.
For very large datasets, if cache_frames=FALSE
, the cost of multiplying the data by a projection matrix at each frame is fairly high, increasing total CPU by several times. If cache_frames=TRUE
, memory usage can get very high.
It could be worth investigating the use of web assembly for this step to improve performance.
https://medium.com/samsung-internet-dev/performance-testing-web-assembly-vs-javascript-e07506fd5875
Add size parameter to display_scatter
, and remove the existing size calculation code based on n
. This is a simple size parameter, and NOT an aesthetic.
@earowang should this parameter be called size
, or cex
?
Can we start to use unit testing, which would help to prevent regression bugs when new features are implemented?
remotes::install_github
This might also include a darker coloured background for both 2D and 3D plots. Similar to default background in {ggplot2}, or background colour in tourr::display_depth
.
perhaps a very simple example to demonstrate the dev workflow
just jotting down some ideas about UI:
animate_tour(
data, # data set
cols, # data columns for tours, tidy eval with {tidyselect}
tour_path = grand_tour(),
display = d3_display_xy(tour_aes(...), center = TRUE, axes = "center"), # ... => <colour =, shape =, size =,>
rescale = TRUE,
sphere = FALSE,
render_opts = list(
start = NULL,
aps = 1,
fps = 10,
max_frames = Inf)
)
Add axes
argument which takes values center
, bottomleft
, or off
.
With viridis
as the default palette, the yellow can be hard to see. Defaulting to a light grey background similar to ggplot2 should help, with a parameter so it can be overridden.
This could be achieved by overlaying an SVG over the canvas, and drawing the legend using d3-legend.js
Will look in to how crosstalk works with this.
Add support for edges
argument in display_scatter
, similar to tourr::display_xy
pkgdown
(i.e. gh pages), preferably with support for embedded htmlwidgets in examples.main
TensorFlow's embedding projector:
https://projector.tensorflow.org/
The open-sourced version:
https://pair-code.github.io/scatter-gl/
The source code:
https://github.com/PAIR-code/scatter-gl
cc @earowang
When displaying lots of points, alpha
for point transparency is more useful than size
#15.
It may be worthwhile making a flow chart for this README section https://github.com/casperhart/detourr#adding-a-new-widget for clean and clear instruction. It will be used in your thesis too.
library(d3tourr)
library(tourr)
big_olive <- olive[rep(1:nrow(olive), 300), ]
dim(big_olive)
animate_tour(
big_olive, -area,
display = display_scatter(tour_aes(colour = region)),
render_opts = list(max_bases = 10)
)
Can't render for a data set of 171K obs. What's the maximum number of obs can we handle atm? Shall we give an informative error message when it exceeds the limit?
Like zoom in/out, brush colour updates, persistent brushes, clickable & draggable slider etc. (with a large-ish built-in dataset)
Actually, it may be worth adding a slider to be able to forward/backward and play/pause/reset at the bottom, which is more flexible than play/pause
and reset
buttons.
Implement dynamic default for max_bases so that it works well with bot grand_tour and guided_tour
Add a parameter pal
in display_scatter
to allow the user to specify the colour palette.
palette()
function.n
and returns a vector similar to above. e.g. gray.colors
, 'palette.colors`, or a palette function from an external package.For continuous colour aesthetics, the values will be binned accordingly, with a default of n=8
if pal
is a function. This will allow continuous palettes to be used.
For character / factor colour aesthetics, n
will default to the number of levels. If pal
is a character vector and there is a length mismatch between the palette and number of factor levels, recycle the palette with a warning.
So that the user can have full control of the colours, we may also want to check if the specified aesthetic column is a valid hex colour vector, and use that if no palette is specified.
Add filtering capabilities to crosstalk.
Also refactor to move crosstalk out of scatter_widget.ts
and in to display_scatter.js
. This seems to be a common pattern in other libraries like {DT} and {d3scatter}, and avoids awkwardly referencing globals from TS.
(with a small built-in dataset)
Just a temporary solution for synced colours
Add label
aesthetic so that individual points can be identified by hovering the mouse over them.
Can we merge axes and labels into one arg, i.e. axes = TRUE
TRUE: default to column names for axis labels
FALSE: remove both axes and labels
NULL: axes without labels
An unnamed vector of labels with the same length as cols
A named vector in the form c("h" = "head"), where head is renamed to h.
Not sure why b
isn't showing up with Safari?
library(detourr)
library(crosstalk)
library(plotly)
library(DT)
shared_flea <- SharedData$new(tourr::flea)
a <- plot_ly(shared_flea, x = ~ tars1, y = ~ head) %>%
add_markers() %>%
highlight(on = "plotly_click", dynamic = TRUE)
b <- animate_tour(
shared_flea,
tour_path = tourr::grand_tour(2),
display = display_scatter(tour_aes(colour = species)),
width = "100%"
)
c <- datatable(shared_flea)
bscols(
list(
filter_checkbox("species", "Species", shared_flea, ~species),
filter_slider("head", "Head", shared_flea, ~head, width = "100%")
),
a, b, c
)
The default pause behaviour continues to redraw the elements on the canvas to support interactions like panning, orbit, zoom, etc.. If there are no interactions the drawing should be stopped entirely to reduce GPU / CPU usage.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.