Skip to content

Commit dda2035

Browse files
authored
Merge pull request #123 from janithwanni/feat/highlight-enlarge-points
Feature: Highlight and Enlarge points
2 parents 370d9e5 + 854e1bd commit dda2035

21 files changed

+543
-22
lines changed

NAMESPACE

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,23 @@
33
S3method(as.list,detour)
44
export(add_edges)
55
export(add_points)
6+
export(clear_edges)
7+
export(clear_enlarge)
8+
export(clear_highlight)
9+
export(clear_points)
610
export(dependence_tour)
711
export(detour)
812
export(displayScatter2dOutput)
913
export(displayScatter3dOutput)
1014
export(display_scatter_proxy)
15+
export(enlarge_points)
16+
export(force_rerender)
1117
export(frozen_guided_tour)
1218
export(frozen_tour)
1319
export(grand_tour)
1420
export(guided_section_tour)
1521
export(guided_tour)
22+
export(highlight_points)
1623
export(is_detour)
1724
export(little_tour)
1825
export(local_tour)

R/shiny_bindings.r

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,9 @@ display_scatter_proxy <- function(id, session = shiny::getDefaultReactiveDomain(
8888
#' Defaults to the result of `attributes(scale(.data))[["scaled:center"]]`
8989
#' @param .scale_factor Numeric value to multiply the centered data.
9090
#' Defaults to `1 / max(sqrt(rowSums(scale(.data)^2)))`
91+
#' @param colour Vector or single value containing hex values of colors (or web colors)
92+
#' @param size Numeric value for the size of the added points
93+
#' @param alpha Transparency of the added points
9194
#' @return Proxy object to be used for piping
9295
#' @rdname detour-shiny
9396
#' @export
@@ -155,3 +158,90 @@ add_edges <- function(proxy, edge_list) {
155158
proxy$session$sendCustomMessage("add-edges", proxy$message)
156159
return(proxy)
157160
}
161+
162+
#' Function to highlight a given set of points
163+
#'
164+
#' The given points will have the original opacity while the other points
165+
#' will have reduced opacity
166+
#'
167+
#' @param proxy proxy object created by \code{\link{display_scatter_proxy}}
168+
#' @param point_list Numeric vector. indexes to highlight in the prinary dataset
169+
#' @param alpha The transparency value of the points outside of the point_list
170+
#' @rdname detour-shiny
171+
#' @export
172+
highlight_points <- function(proxy, point_list, alpha = 0.3) {
173+
if (length(point_list) == 1) {
174+
point_list <- list(point_list)
175+
}
176+
proxy$message$point_list <- point_list
177+
proxy$session$sendCustomMessage("highlight-points", proxy$message)
178+
return(proxy)
179+
}
180+
181+
#' Function to enlarge a given set of points
182+
#'
183+
#' The given points will have a larger size while the rest
184+
#' remains the same
185+
#'
186+
#' @param proxy proxy object created by \code{\link{display_scatter_proxy}}
187+
#' @param point_list Numeric vector. indexes to enlarge in the prinary dataset
188+
#' @param size the size of the points to be enlarged
189+
#' @rdname detour-shiny
190+
#' @export
191+
enlarge_points <- function(proxy, point_list, size = 2) {
192+
if (length(point_list) == 1) {
193+
point_list <- list(point_list)
194+
}
195+
proxy$message$enlarge_point_list <- point_list
196+
proxy$message$size <- size
197+
proxy$session$sendCustomMessage("enlarge-points", proxy$message)
198+
return(proxy)
199+
}
200+
201+
202+
#' Function to clear added points
203+
#' @param proxy proxy object created by \code{\link{display_scatter_proxy}}
204+
#' @rdname detour-shiny
205+
#' @export
206+
clear_points <- function(proxy) {
207+
proxy$session$sendCustomMessage("clear-points", list(id = proxy$id))
208+
return(proxy)
209+
}
210+
211+
#' Function to clear added edges
212+
#' @param proxy proxy object created by \code{\link{display_scatter_proxy}}
213+
#' @rdname detour-shiny
214+
#' @export
215+
clear_edges <- function(proxy) {
216+
proxy$session$sendCustomMessage("clear-edges", list(id = proxy$id))
217+
return(proxy)
218+
}
219+
220+
#' Function to clear highlighted points
221+
#' @param proxy proxy object created by \code{\link{display_scatter_proxy}}
222+
#' @rdname detour-shiny
223+
#' @export
224+
clear_highlight <- function(proxy) {
225+
proxy$session$sendCustomMessage("clear-highlight", list(id = proxy$id))
226+
return(proxy)
227+
}
228+
229+
#' Function to clear enlarged points
230+
#' @param proxy proxy object created by \code{\link{display_scatter_proxy}}
231+
#' @rdname detour-shiny
232+
#' @export
233+
clear_enlarge <- function(proxy) {
234+
proxy$session$sendCustomMessage("clear-enlarge", list(id = proxy$id))
235+
return(proxy)
236+
}
237+
238+
#' Function to force rerender of detourr
239+
#'
240+
#' Useful when detourr will not update unless put on focus
241+
#' @param proxy proxy object created by \code{\link{display_scatter_proxy}}
242+
#' @rdname detour-shiny
243+
#' @export
244+
force_rerender <- function(proxy) {
245+
proxy$session$sendCustomMessage("clear-enlarge", list(id = proxy$id))
246+
return(proxy)
247+
}

demo/shiny_detourr/add_points_edges.R

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ dataset <- tourr::flea |>
66

77
create_fake_box <- function(datum) {
88
# expected tibble needs to have two rows with ncols(datum) + 1 columns
9-
box_dist <- rnorm(1, mean = 3)
9+
box_dist <- 2
1010
bounds_list <- rbind(datum + box_dist, datum - box_dist) |>
1111
as.list()
1212
do.call(tidyr::expand_grid, bounds_list)
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
library(shiny)
2+
library(detourr)
3+
4+
dataset <- tourr::flea |>
5+
dplyr::mutate(id = dplyr::row_number())
6+
7+
create_fake_box <- function(datum) {
8+
# expected tibble needs to have two rows with ncols(datum) + 1 columns
9+
box_dist <- 2
10+
bounds_list <- rbind(datum + box_dist, datum - box_dist) |>
11+
as.list()
12+
do.call(tidyr::expand_grid, bounds_list)
13+
}
14+
15+
main_ui <- function(id) {
16+
ns <- NS(id)
17+
fluidPage(
18+
column(6,
19+
displayScatter2dOutput(
20+
ns("detourr_out"), width = "100%", height = "400px"
21+
),
22+
textOutput(ns("detour_click_output"))
23+
),
24+
column(6,
25+
h1(
26+
"Tour of aesthetic changes",
27+
"for points and edges added to detourr through Shiny"
28+
),
29+
p(
30+
"In this demonstration,",
31+
"clicking on points on the detourr instance to the left",
32+
"adds a box around the point.",
33+
"Click on the play button to view the box in different projections"
34+
),
35+
p(
36+
"A random set of points will be highlighted",
37+
"(By having a higher opacity than others)",
38+
"The point clicked on has a bigger radius"
39+
),
40+
p(
41+
"Click on an empty space in the dataset",
42+
"to remove the aesthetics completely.",
43+
"Or else click on the eraser (clear) button",
44+
"on the right handside of the controls"
45+
)
46+
)
47+
)
48+
}
49+
50+
main_server <- function(id) {
51+
moduleServer(id, function(input, output, session){
52+
output$detourr_out <- shinyRenderDisplayScatter2d({
53+
detour(dataset,
54+
tour_aes(projection = -c(id, species), colour = species, label = id)
55+
) |>
56+
tour_path(grand_tour(2), fps = 60) |>
57+
show_scatter(
58+
alpha = 0.7,
59+
axes = TRUE
60+
)
61+
})
62+
63+
output$detour_click_output <- renderText({
64+
input$detourr_out_detour_click
65+
})
66+
67+
observeEvent(input$detourr_out_detour_click, {
68+
if (
69+
is.null(
70+
input$detourr_out_detour_click
71+
) || input$detourr_out_detour_click == -1
72+
) {
73+
display_scatter_proxy(session$ns("detourr_out")) |>
74+
clear_points() |>
75+
clear_edges() |>
76+
clear_highlight() |>
77+
clear_enlarge()
78+
}
79+
req(
80+
!is.null(input$detourr_out_detour_click),
81+
input$detourr_out_detour_click != -1
82+
)
83+
data_to_send <- dataset |>
84+
dplyr::select(-species) |>
85+
dplyr::filter(id == input$detourr_out_detour_click) |>
86+
dplyr::select(-id)
87+
88+
box_to_send <- data_to_send |> create_fake_box()
89+
90+
cube_box <- geozoo::cube.iterate(p = ncol(data_to_send))
91+
92+
display_scatter_proxy(session$ns("detourr_out")) |>
93+
add_points(
94+
box_to_send,
95+
.data = dataset |> dplyr::select(-c(id, species)),
96+
colour = sample(
97+
c(
98+
"#d62b4d",
99+
"#01a760",
100+
"#9a0582",
101+
"#626300",
102+
"#ff9d4a"
103+
),
104+
nrow(box_to_send),
105+
replace = TRUE
106+
),
107+
size = 1,
108+
alpha = 0.6
109+
) |>
110+
add_edges(
111+
edge_list = cube_box$edges
112+
) |>
113+
highlight_points(
114+
point_list = sample(nrow(dataset))[1:(floor(nrow(dataset)*0.5))] # snap half of the points out
115+
) |>
116+
enlarge_points(
117+
input$detourr_out_detour_click, size = 3
118+
)
119+
})
120+
121+
})
122+
}
123+
124+
ui <- function() {
125+
main_ui("main")
126+
}
127+
128+
server <- function(input, output, session) {
129+
main_server("main")
130+
}
131+
132+
shinyApp(ui, server, options = list(port = 5534))

inst/htmlwidgets/lib/show_sage_2d.bundle.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

inst/htmlwidgets/lib/show_sage_3d.bundle.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

inst/htmlwidgets/lib/show_scatter_2d.bundle.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

inst/htmlwidgets/lib/show_scatter_3d.bundle.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

inst/htmlwidgets/lib/show_slice_2d.bundle.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

inst/htmlwidgets/lib/show_slice_3d.bundle.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)