1

I am still struggling to find a way in R to interactively display successive images.

In the following, I am generating a 3d object mat3d.

mat <- matrix(dnorm(seq(
  from = -10,
  to = 10,
  length.out = 100 * 100
), sd = 5),
c(100, 100))

mat2d <- mat * t(mat)

mat3d <- array(c(mat2d, mat2d * 0.9, mat2d * 0.8), c(100, 100, 3))

image(mat3d[, , 1],
      useRaster = TRUE,
      asp = 1,
      zlim = c(0, 0.01))

I would like to be able to display mat3d[, , 1], mat3d[, , 2], mat3d[, , k] by simply moving a cursor below the 2D image.

I would also like to be able to switch dimensions, so that I could display mat3d[, 1, ], mat3d[, 2, ], mat3d[, j, ], or mat3d[1, , ], mat3d[2, , ], mat3d[i, , ].

Can I obtain this using plotly or javascript in R?

Many thanks in advance for your help.

leparc
  • 133
  • 5

1 Answers1

2

This is a good job for a Shiny app. Here is a starting point.

mat <- matrix(dnorm(seq(
  from = -10,
  to = 10,
  length.out = 100 * 100
), sd = 5),
c(100, 100))

mat2d <- mat * t(mat)

mat3d <- array(c(mat2d, mat2d * 0.9, mat2d * 0.8), c(100, 100, 3))


library(shiny)
ui <- fluidPage(
  fluidRow(
    column(
      12,
      radioButtons(
        "index", label = "Choose the index", 
        choices = c("1", "2", "3"), inline = TRUE
      )
    ),
    column(
      12,
      plotOutput("img")
    )    
  )
)

server <- function(input, output, session) {
  
  output[["img"]] <- renderPlot({
    index <- as.integer(input[["index"]])
    image(mat3d[, , index],
          useRaster = TRUE,
          asp = 1,
          zlim = c(0, 0.01))
  })
}

shinyApp(ui, server)

enter image description here

To display the three slices, I would do three images:

mat <- matrix(dnorm(seq(
  from = -10,
  to = 10,
  length.out = 100 * 100
), sd = 5),
c(100, 100))

mat2d <- mat * t(mat)

mat3d <- array(c(mat2d, mat2d * 0.9, mat2d * 0.8), c(100, 100, 3))

image(mat3d[70, , ],
      useRaster = TRUE,
      asp = 1,
      zlim = c(0, 0.01))

library(shiny)
ui <- fluidPage(
  fluidRow(
    column(
      4,
      numericInput(
        "ix", label = "Slice x", 
        min = 1, max = 100, step = 1, value = 50
      ),
      br(),
      plotOutput("imgx")
    ),
    column(
      4,
      numericInput(
        "iy", label = "Slice y", 
        min = 1, max = 100, step = 1, value = 20
      ),
      br(),
      plotOutput("imgy")
    ),
    column(
      4,
      radioButtons(
        "iz", label = "Slice z", 
        choices = c("1", "2", "3"), inline = TRUE
      ),
      br(),
      plotOutput("imgz")
    )
  )
)

server <- function(input, output, session) {
  
  output[["imgx"]] <- renderPlot({
    index <- input[["ix"]]
    image(mat3d[index, , ],
          useRaster = TRUE,
          asp = 1,
          zlim = c(0, 0.01))
  })
  
  output[["imgy"]] <- renderPlot({
    index <- input[["iy"]]
    image(mat3d[, index, ],
          useRaster = TRUE,
          asp = 1,
          zlim = c(0, 0.01))
  })
  
  output[["imgz"]] <- renderPlot({
    index <- as.integer(input[["iz"]])
    image(mat3d[, , index],
          useRaster = TRUE,
          asp = 1,
          zlim = c(0, 0.01))
  })
  
}

shinyApp(ui, server)

enter image description here

Stéphane Laurent
  • 75,186
  • 15
  • 119
  • 225
  • this is AWESOME! Just a last question, I would prefer having a slider than either setting a value or having a radio button. Is this doable with `Shiny`. I would like the value to still be displayed close to the cursor. – leparc Jul 08 '23 at 19:05
  • 1
    @leparc Everything is doable ;-) Use `sliderInput`. – Stéphane Laurent Jul 08 '23 at 19:10
  • It works like a charm! The only limitation I find is that I have to release the slider for the value to change. This does not allow the slider to scan through the values smoothly while the image gets continuously updated. – leparc Jul 08 '23 at 19:50
  • I assume my last question is answered here: https://stackoverflow.com/questions/69033403/how-to-refresh-sliderinput-in-shiny-in-real-time-not-only-when-the-sliding-en – leparc Jul 09 '23 at 03:41
  • 1
    @leparc It seems this was the opposite behavior before. Because I opened this issue: https://github.com/rstudio/shiny/issues/3509 – Stéphane Laurent Jul 09 '23 at 08:08
  • @leparc How quickly are you moving the slider? I tried the app above and as long as I don't move the slider too quickly it updates at intermediate values (without releasing the slider). If that's not the case for you, would you mind commenting in the issue linked above to include more details, such as your browser and OS info? – grrrck Jul 10 '23 at 15:02
  • 1
    @leparc You might also like to try the `animate = TRUE` option of `sliderInput()`. It adds a small play button that automatically steps through the slider values when clicked. – grrrck Jul 10 '23 at 15:03