ggseg / ggseg3d

ggseg3d R package for cisualising brain atlases through plotly
https://ggseg.github.io/ggseg3d/
Other
27 stars 9 forks source link

Set scale limits in ggseg3d #1

Closed narunpat closed 4 years ago

narunpat commented 4 years ago

I hope to use the same color scale for the left and right cortical images and the subcortical image in ggseg3d. This is so that the same “red” means that same thing across the three.

However, I could not find an option to set scale limits (i.e., min and max values) for the color scale in ggseg3d.

If there is no such option, I would appreciate a work around.

Thank you!

daidak commented 4 years ago

Hi Thanks for the question,

Plotly is quite annoying in this regard, so the best way to solve this is by creating an external palette and subsetting it based on the relative min, max values of each plot relative to the absolute min/max. Here you can find and example (with a red - green palette), though you might have to change it a little bit depending on your results data.frame. Let me know if it works for you, Thanks, Didac

library(dplyr) library(ggseg) ncols <- 100 mypalette <- colorRampPalette(c("#d7191c","#fdae61","#a6d96a","#1a9641"))(ncols)

result <- data.frame(label = c("lh_superiorfrontal", "lh_middletemporal", "lh_superiorparietal", "rh_superiorfrontal", "rh_middletemporal", "rh_superiorparietal"), values = c(5,6,3,2,4,5)) print(result) col2values <- seq(min(result$values), max(result$values), length.out = ncols)

plot.hemi <- result %>% filter(grepl("lh_",label)) nmin <- which.min(abs(col2values - min(plot.hemi$values))) nmax <- which.min(abs(col2values - max(plot.hemi$values)))

ggseg3d(plot.hemi, atlas = "dkt_3d", surf = "LCBC", hemisphere = "left", palette = mypalette[nmin:nmax], colour = "values")

plot.hemi <- result %>% filter(grepl("rh_",label)) nmin <- which.min(abs(col2values - min(plot.hemi$values))) nmax <- which.min(abs(col2values - max(plot.hemi$values))) ggseg3d(plot.hemi, atlas = "dkt_3d", surf = "LCBC", hemisphere = "right", palette = mypalette[nmin:nmax], colour = "values")

Missatge de narunpat notifications@github.com del dia ds., 24 d’ag. 2019 a les 10:41:

I hope to use the same color scale for the left and right cortical images and the subcortical image in ggseg3d. This is so that the same “red” means that same thing across the three.

However, I could not find an option to set scale limits (i.e., min and max values) for the color scale in ggseg3d.

If there is no such option, I would appreciate a work around.

Thank you!

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/LCBC-UiO/ggseg/issues/17?email_source=notifications&email_token=ACMZ4JWKMSVP4K2S6CXRNF3QGDX35A5CNFSM4IPFTDAKYY3PNVWWK3TUL52HS4DFUVEXG43VMWVGG33NNVSW45C7NFSM4HHFMEIQ, or mute the thread https://github.com/notifications/unsubscribe-auth/ACMZ4JVPUQBP7C7QK7VQ5F3QGDX35ANCNFSM4IPFTDAA .

-- Dídac Vidal Piñeiro

narunpat commented 4 years ago

Thank you so much. This workaround works well!

drmowinckels commented 4 years ago

From commit 2f771f313d9 you can now use a named numeric vector as a palette for ggseg3d, where the colours are the name, and the breakpoints are the numbers. This should make it easier to make a colourbar that is the same across multiple plots.

data.frame(
    area = c("transverse temporal", "insula",
             "pre central","superior parietal"),
    p = sample(seq(0,.5,.001), 4),
    stringsAsFactors = F) %>%

     ggseg3d( colour = "p", text = "p", 
                   palette = c("black" = 0 ,
                               "yellow" =. 5,
                               "white" = 1, 
                               "hotpink" = 2))

image

narunpat commented 4 years ago

Thanks so much. This is great!

Related, with this change, is it possible to make a certain part of the color bar to be one color? For instance, I may like to show only the values from regions that pass a certain threshold. That is, those that pass the threshold (either in the positive or negative directions) will be in gradients, while those that do not will be all solid gray. So similar to the example above, but says between .5 - 1.5, the color bar will be a solid gray.

Thanks again.

drmowinckels commented 4 years ago

if you only want to colour something that passes a certain threshold, I would alter the data the do not pass the threshold in your data to ba NA values, so they would rather just be grey.

But yes, you could in theory do that also using the new option.

narunpat commented 4 years ago

NA works on the color bar too? Thank you.

ellenkimc commented 3 years ago

Hi, I am trying to get the same in ggseg: one gradient colour scale for different plots (so that one colour means the same in all plots). I combined my ggseg plots with the function ggcow. Is there a way to get one scale for different plots in ggseg? I also tried the two options for doing it in ggseg3d but it doesn't work. I would really like to use the option where you set the scale according to numbers in ggseg, is this possible?

And is it also possible to scale plots in the ggcow so that they look the same size? I plotted two plots which include left and right hemisphere, and then another which only has the left hemisphere. The plot with only the left hemisphere is bigger, also when you combine the plots. is there a way to get all the plots in a combined cowplot have the same size?

Thank you very much Ellen

drmowinckels commented 3 years ago

Hi @ellenkimc

I'm a little confused, are you talking about ggseg or ggseg3d? You opened an issue in ggseg3d, so I was assuming it was about that, but from your text it does not seem so? In the future, please open an issue in the package you want to use, this makes it easier for us to help out and keep track of issues.

Also, I dont know about the ggcow-package, I tried googling it but nothing comes up. Do you mean cowplot?

The functionality you ask for already exists in other packages than ggseg. Altering the colourbar can be done with the scale_fill functions from ggplot2 (or other colour packages), and arranging layouts of subplots is something you would do with other packages like cowplot or patchwork. So the information you are looking for comes with those packages, not ggseg.

I would rather use patchwork with ggplots, because it provides a lot of good options for altering all plots in a subplot arrangement at once.

library(ggseg)
#> Loading required package: ggplot2
library(dplyr)
#> 
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#> 
#>     filter, lag
#> The following objects are masked from 'package:base':
#> 
#>     intersect, setdiff, setequal, union
library(patchwork)

data <- data.frame(
  region = c("transverse temporal", "insula",
             "precentral","superior parietal"),
  p = sample(seq(0,.5,.001), 4),
  stringsAsFactors = FALSE)

left <- data %>% 
  ggseg(atlas = dk, 
        hemisphere = "left", 
        colour = "grey37",
        mapping = aes(fill = p)) 

right <- data %>% 
  ggseg(atlas = dk, 
        hemisphere = "right", 
        colour = "grey37",
        mapping = aes(fill = p))

right_med <- data %>% 
  ggseg(atlas = dk, 
        hemisphere = "right", 
        view = "lateral",
        colour = "grey37",
        mapping = aes(fill = p))

right / left / right_med + # Combine plots with patchwork, here / means first on top of second
  plot_layout(guides = 'collect') & # merge the colourbar if it can
  scale_fill_viridis_c(limits = c(0, .5)) # control the colour and colourbar scale


# Adaptation to control the size of the last plot
right / left / right_med +
  plot_layout(guides = 'collect', 
              heights = 1) & # Force all plots to have same height
  scale_fill_viridis_c(limits = c(0, .5)) 

Created on 2020-10-06 by the reprex package (v0.3.0)

ellenkimc commented 3 years ago

Yes you are right, I did mean ggseg and cowplot. I'm sorry I asked this question in the wrong place.

Thank you so much!! This is exactly what I needed!!

Some follow up questions:

I have added a picture of what i get when using +.

Thank you so much in advance. You are such a great help!!!

Rplot_question

ellenkimc commented 3 years ago

Hi!

I just noticed that if I plot more than one under each other, which is what i'd like in the end (with different data everywhere), the problems with size and title distance are solved! I used this code:

(e1 + e2 +e3 ) / (e1 + e2 +e3 )/(e1 + e2 +e3 )/ (e1 + e2 +e3 ) / (e1 + e2 +e3 )/(e1 + e2 +e3 )+ plot_layout(guides = 'collect', heights = 1) & scale_fill_gradient(low="yellow", high="red", limits=c(0,50))

example

So than only the last question remains unsolved:

Is it possible to get rid of the text 'hemispere' and to add text under/next to 'left'? I would like to have 'left, n=x' and 'right, n=x'.

Thanks again!! I'm loving this package.

drmowinckels commented 3 years ago

Hi.

The reason that the plots when next to each other are different size is that when they are placed next to each other the height for all plots is the same, but the space the polygons take within that plot is different when plotting a single hemisphere. You therefore need to tweak the widths argument in stead of heights. both widths and heights can take a vector of number the same length as the number of subplots you are adding. You can therefore adjust the subplots relative size to each other using a vector.

When it comes to adding your own custom axis information, that will require using custom annotations. You can read about custom annotations in ggplot2 here: https://ggplot2-book.org/annotations.html#custom-annotations

using the annotate function you can place any text on the plot. You will likely need to do some trial and error to find the correct x and y coordinates for you text. You might find that easier if you set adapt_scales = FALSE in the main ggseg call for a plot, until you find the coordinates that work for you.

library(ggseg)
#> Loading required package: ggplot2
library(dplyr)
#> 
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#> 
#>     filter, lag
#> The following objects are masked from 'package:base':
#> 
#>     intersect, setdiff, setequal, union
library(patchwork)

data <- data.frame(
  region = c("transverse temporal", "insula",
             "precentral","superior parietal"),
  p = sample(seq(0,.5,.001), 4),
  stringsAsFactors = FALSE)

# Have a look at the plot coordinates
data %>% 
  ggseg(atlas = dk, 
        colour = "grey37",
        adapt_scales = FALSE,
        mapping = aes(fill = p)) 


left <- data %>% 
  ggseg(atlas = dk, 
        hemisphere = "left", 
        colour = "grey37",
        mapping = aes(fill = p))  +
  annotate("text", 
           x = c(410), 
           label = c("left, n = x"),
           size = 5,
           y = -30)

right <- data %>% 
  ggseg(atlas = dk, 
        hemisphere = "right", 
        colour = "grey37",
        mapping = aes(fill = p)) +
  annotate("text", 
           x = c(1290), 
           label = c( "right, n = x"),
           size = 5,
           y = -30)

right_med <- data %>% 
  ggseg(atlas = dk, 
        hemisphere = "right", 
        view = "lateral",
        colour = "grey37",
        mapping = aes(fill = p)) +
  annotate("text", 
           x = c(1510), 
           label = c("right, n = x"),
           size = 5,
           y = -30)

right + left + right_med +
  plot_layout(guides = 'collect', 
              # Adjust so that each plot has it's own height
              widths = c(1,1,.48)) & 
  scale_fill_viridis_c(limits = c(0, .5)) &

  # remove axis information
  theme(axis.text = element_blank(),
        axis.title = element_blank()) &

  # turn clip off, so that annotated text still appears 
  # if outside the plotting area
  coord_fixed(clip = "off")
#> Coordinate system already present. Adding new coordinate system, which will replace the existing one.
#> Coordinate system already present. Adding new coordinate system, which will replace the existing one.
#> Coordinate system already present. Adding new coordinate system, which will replace the existing one.

Created on 2020-10-08 by the reprex package (v0.3.0)

ellenkimc commented 3 years ago

Yes thank you so much!! It works and looks great!