diff --git a/examples/howto_examples/gam-tract-profiles-example.Rmd b/examples/howto_examples/gam-tract-profiles-example.Rmd new file mode 100644 index 000000000..5088a8f50 --- /dev/null +++ b/examples/howto_examples/gam-tract-profiles-example.Rmd @@ -0,0 +1,101 @@ +--- +title: "AFQ-GAMS-Tutorial" +author: "Jason Yeatman" +date: "2024-03-30" +output: html_document +--- + +```{r setup, include=FALSE} +knitr::opts_chunk$set(echo = TRUE) +``` + +## GAMs Tutorial + +First we'll pull the Sarica data and merge nodes.csv (diffusion data) with subjects.csv (participant meta data) + +```{r, warning=FALSE, message=FALSE} +library(dplyr) +library(mgcv) +library(gratia) +library(ggplot2) +df <- read.csv('https://raw.githubusercontent.com/yeatmanlab/Sarica_2017/gh-pages/data/nodes.csv') +df <- inner_join(df, read.csv('https://raw.githubusercontent.com/yeatmanlab/Sarica_2017/gh-pages/data/subjects.csv')) +mutate(df, class = factor(class), subjectID = factor(subjectID))-> df + +``` + +```{r, message=FALSE, warning=FALSE} +# Fit a simple GAM with a random effect of subject and smoothers that +# differ by class (control or ALS) +g1 <- gam(md ~ s(nodeID,class, bs='fs') + s(subjectID, bs= 're'), data=df) +# Get smooth estimates +dfs <- smooth_estimates(g1) %>% add_confint(coverage=.68) + +# Remove random effects and plot +filter(dfs, type != 'Random effect') %>% +ggplot(aes(x=nodeID,y=est, color=class)) + + geom_line() + + geom_ribbon(aes(ymin = lower_ci, ymax=upper_ci),alpha = 0.2 ) + +``` + +```{r, message=FALSE, warning=FALSE} +# The above plot looks good but now let's let the curves vary across # subjects too. What I notice here is that it dramatically effects the standard error +g2 <- gam(md ~ s(nodeID,class, bs='fs') + s(nodeID, subjectID, bs= 're'), data=df) +# Get smooth estimates +dfs <- smooth_estimates(g2) %>% add_confint(coverage=.68) + +# Remove random effects and plot +filter(dfs, type != 'Random effect') %>% +ggplot(aes(x=nodeID,y=est, color=class)) + + geom_line() + + geom_ribbon(aes(ymin = lower_ci, ymax=upper_ci),alpha = 0.2 ) +``` + +```{r, message=FALSE, warning=FALSE} +# Yet another way to do the same thing and I don't get the difference +g3 <- gam(md ~ s(nodeID,by=class, bs='fs', k=10) + s(subjectID, bs= 're'), data=df) +# Get smooth estimates +dfs <- smooth_estimates(g3) %>% add_confint(coverage=.68) + +# Remove random effects and plot +filter(dfs, type != 'Random effect') %>% +ggplot(aes(x=nodeID,y=est, color=class)) + + geom_line() + + geom_ribbon(aes(ymin = lower_ci, ymax=upper_ci),alpha = 0.2 ) +``` + +Now calculate differences between the smooths for the different factors and plot out the difference an 95% CI + +```{r} +ds<-difference_smooths(g3, smooth="s(nodeID)") +ggplot(ds,aes(x=nodeID,y=diff)) + + geom_line() + + geom_ribbon(aes(ymin = lower, ymax=upper),alpha = 0.2 ) + + geom_hline(yintercept=0) +``` + +Now look at continuous measures along the tract profile + +```{r} +# Yet another way to do the same thing and I don't get the difference +g4 <- gam(md ~ s(nodeID,ALSFRSbulbar, bs='fs', k=10) + s(subjectID, bs= 're'), data=df) +dfs <- smooth_estimates(g4) %>% add_confint(coverage=.68) +#filter(dfs,smooth=='s(nodeID)') %>% +# ggplot(aes(x=nodeID,y=est)) + +# geom_line() + +# geom_ribbon(aes(ymin = lower_ci, ymax=upper_ci),alpha = 0.2 ) + +# 2d plot showing how tract profiles vary as a function of AFS bulbar +filter(dfs,smooth=='s(nodeID,ALSFRSbulbar)') %>% +ggplot(aes(x=nodeID, y=ALSFRSbulbar))+ + geom_raster(aes(fill=est)) + +# Now plot separate tract profiles by bulbar +dfs %>% mutate(ALSFRSbulbar.factor=factor(ALSFRSbulbar)) %>% filter(ALSFRSbulbar== sort(unique(dfs$ALSFRSbulbar))[2] | ALSFRSbulbar== sort(unique(dfs$ALSFRSbulbar))[99]) %>% + filter(smooth=='s(nodeID,ALSFRSbulbar)') %>% + ggplot(aes(x=nodeID,y=est,color=ALSFRSbulbar.factor)) + + geom_line(show.legend = FALSE) + + geom_ribbon(aes(ymin = lower_ci, ymax=upper_ci),alpha = 0.2 ) + +``` diff --git a/examples/howto_examples/gam-tract-profiles-example.html b/examples/howto_examples/gam-tract-profiles-example.html new file mode 100644 index 000000000..2579c29f0 --- /dev/null +++ b/examples/howto_examples/gam-tract-profiles-example.html @@ -0,0 +1,482 @@ + + + + +
+ + + + + + + + + + +First we’ll pull the Sarica data and merge nodes.csv (diffusion data) +with subjects.csv (participant meta data)
+library(dplyr)
+library(mgcv)
+library(gratia)
+library(ggplot2)
+df <- read.csv('https://raw.githubusercontent.com/yeatmanlab/Sarica_2017/gh-pages/data/nodes.csv')
+df <- inner_join(df, read.csv('https://raw.githubusercontent.com/yeatmanlab/Sarica_2017/gh-pages/data/subjects.csv'))
+mutate(df, class = factor(class), subjectID = factor(subjectID))-> df
+# Fit a simple GAM with a random effect of subject and smoothers that
+# differ by class (control or ALS)
+g1 <- gam(md ~ s(nodeID,class, bs='fs') + s(subjectID, bs= 're'), data=df)
+# Get smooth estimates
+dfs <- smooth_estimates(g1) %>% add_confint(coverage=.68)
+
+# Remove random effects and plot
+filter(dfs, type != 'Random effect') %>%
+ggplot(aes(x=nodeID,y=est, color=class)) +
+ geom_line() +
+ geom_ribbon(aes(ymin = lower_ci, ymax=upper_ci),alpha = 0.2 )
+
+# The above plot looks good but now let's let the curves vary across # subjects too. What I notice here is that it dramatically effects the standard error
+g2 <- gam(md ~ s(nodeID,class, bs='fs') + s(nodeID, subjectID, bs= 're'), data=df)
+# Get smooth estimates
+dfs <- smooth_estimates(g2) %>% add_confint(coverage=.68)
+
+# Remove random effects and plot
+filter(dfs, type != 'Random effect') %>%
+ggplot(aes(x=nodeID,y=est, color=class)) +
+ geom_line() +
+ geom_ribbon(aes(ymin = lower_ci, ymax=upper_ci),alpha = 0.2 )
+
+# Yet another way to do the same thing and I don't get the difference
+g3 <- gam(md ~ s(nodeID,by=class, bs='fs', k=10) + s(subjectID, bs= 're'), data=df)
+# Get smooth estimates
+dfs <- smooth_estimates(g3) %>% add_confint(coverage=.68)
+
+# Remove random effects and plot
+filter(dfs, type != 'Random effect') %>%
+ggplot(aes(x=nodeID,y=est, color=class)) +
+ geom_line() +
+ geom_ribbon(aes(ymin = lower_ci, ymax=upper_ci),alpha = 0.2 )
+
+Now calculate differences between the smooths for the different +factors and plot out the difference an 95% CI
+ds<-difference_smooths(g3, smooth="s(nodeID)")
+ggplot(ds,aes(x=nodeID,y=diff)) +
+ geom_line() +
+ geom_ribbon(aes(ymin = lower, ymax=upper),alpha = 0.2 ) +
+ geom_hline(yintercept=0)
+
+Now look at continuous measures along the tract profile
+# Yet another way to do the same thing and I don't get the difference
+g4 <- gam(md ~ s(nodeID,ALSFRSbulbar, bs='fs', k=10) + s(subjectID, bs= 're'), data=df)
+dfs <- smooth_estimates(g4) %>% add_confint(coverage=.68)
+#filter(dfs,smooth=='s(nodeID)') %>%
+# ggplot(aes(x=nodeID,y=est)) +
+# geom_line() +
+# geom_ribbon(aes(ymin = lower_ci, ymax=upper_ci),alpha = 0.2 )
+
+# 2d plot showing how tract profiles vary as a function of AFS bulbar
+filter(dfs,smooth=='s(nodeID,ALSFRSbulbar)') %>%
+ggplot(aes(x=nodeID, y=ALSFRSbulbar))+
+ geom_raster(aes(fill=est))
+
+# Now plot separate tract profiles by bulbar
+dfs %>% mutate(ALSFRSbulbar.factor=factor(ALSFRSbulbar)) %>% filter(ALSFRSbulbar== sort(unique(dfs$ALSFRSbulbar))[2] | ALSFRSbulbar== sort(unique(dfs$ALSFRSbulbar))[99]) %>%
+ filter(smooth=='s(nodeID,ALSFRSbulbar)') %>%
+ ggplot(aes(x=nodeID,y=est,color=ALSFRSbulbar.factor)) +
+ geom_line(show.legend = FALSE) +
+ geom_ribbon(aes(ymin = lower_ci, ymax=upper_ci),alpha = 0.2 )
+
+