This notebook describes the data analysis pipeline for side-view images collected for last cowpea screen (Cowpea 06), performend between June 17th and July 21st, 2022 by Hayley Sussman, assisted by high-school research intern, Ting Fei. The data was analyzed using the PlantCV pipeline by Magda Julkowska, and used here as an input.

Collating all side-views into one value for each plant

Since all of the plants were imaged from 7 angles, we first need to summarize the total plant size, by summarizing the pixels assigned as “plant” from all different side views. We will do it based on the time-stamp, for all of the imaging campaigns.

Let’s establish the pipeline first for the first file:

my_files <- list.files(pattern = "traits.csv")
length(my_files)
## [1] 8
data <- read.csv(my_files[1]) 
my_data <- data[,c(31, 18:25,27:30)]
my_data

Let’s split the ROI into specific information - including the timestamp!

for(i in 1:nrow(my_data)){
  my_data$timestamp[i] <- strsplit(my_data$roi[i], "_")[[1]][1]
  }
my_data
#install.packages("doBy")
library(doBy)
sum_data <- summaryBy(area + convex_hull_area + solidity + perimeter + width + height ~ timestamp, data = my_data, FUN = function(x) c(mean = mean(x), sum=sum(x), max=max(x)))
sum_data

let’s keep only the information we find valuable:

colnames(sum_data)
##  [1] "timestamp"             "area.mean"             "area.sum"             
##  [4] "area.max"              "convex_hull_area.mean" "convex_hull_area.sum" 
##  [7] "convex_hull_area.max"  "solidity.mean"         "solidity.sum"         
## [10] "solidity.max"          "perimeter.mean"        "perimeter.sum"        
## [13] "perimeter.max"         "width.mean"            "width.sum"            
## [16] "width.max"             "height.mean"           "height.sum"           
## [19] "height.max"
sum_clean <- sum_data[,c(1, 3, 5, 8, 11, 16, 19)]
sum_clean

Great - before moving forward - let’s add also info on DAY:

for(i in 1:nrow(sum_clean)){
  sum_clean$day[i] <- strsplit(sum_clean$timestamp[i], "-")[[1]][1]
  sum_clean$time[i] <- strsplit(sum_clean$timestamp[i], "-")[[1]][2]
  }
sum_clean <- sum_clean[,c(1,8:9,2:7)]
sum_clean

For this experiment - I see in the lab notebook that “Pots 93 and 98 (TVu-9393, control and drought) did not germinate for the duration of the experiment. One seed in pot 93 did begin to germinate as of 7/7/22, but was not able to emerge out of the seed coat (picture below). Pots 114 and 119 (TVu-15400, control and drought) germinated late, and so pot 114 was not imaged on 7/7/22”. I also discovered that pot 114 is also missing at 7/9/22.

So - our pot numbers are ranging from 1-140 But for this round we dont have 93 and 98, as well as 114 So three pots are out, which would make it 137

So now we need to make a list of numbers from 1-140 and remove these missing numbers and merge them inside this data:

pots <- 1:140
nots <- c(93, 98, 114)
pots <- subset(pots, !(pots %in% nots))
pots
##   [1]   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15  16  17  18
##  [19]  19  20  21  22  23  24  25  26  27  28  29  30  31  32  33  34  35  36
##  [37]  37  38  39  40  41  42  43  44  45  46  47  48  49  50  51  52  53  54
##  [55]  55  56  57  58  59  60  61  62  63  64  65  66  67  68  69  70  71  72
##  [73]  73  74  75  76  77  78  79  80  81  82  83  84  85  86  87  88  89  90
##  [91]  91  92  94  95  96  97  99 100 101 102 103 104 105 106 107 108 109 110
## [109] 111 112 113 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
## [127] 130 131 132 133 134 135 136 137 138 139 140
sum_clean$pot.no <- pots
sum_clean
CP06 <- sum_clean

OK - now let’s do next day but much quicker:

data <- read.csv(my_files[2]) 
my_data <- data[,c(31, 18:25,27:30)]
for(i in 1:nrow(my_data)){
  my_data$timestamp[i] <- strsplit(my_data$roi[i], "_")[[1]][1]
}
sum_data <- summaryBy(area + convex_hull_area + solidity + perimeter + width + height ~ timestamp, data = my_data, FUN = function(x) c(mean = mean(x), sum=sum(x), max=max(x)))
sum_clean <- sum_data[,c(1, 3, 5, 8, 11, 16, 19)]
for(i in 1:nrow(sum_clean)){
  sum_clean$day[i] <- strsplit(sum_clean$timestamp[i], "-")[[1]][1]
  sum_clean$time[i] <- strsplit(sum_clean$timestamp[i], "-")[[1]][2]
  }
sum_clean <- sum_clean[,c(1,8:9,2:7)]
sum_clean
pots <- 1:140
nots <- c(93, 98, 114)
pots <- subset(pots, !(pots %in% nots))
pots
##   [1]   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15  16  17  18
##  [19]  19  20  21  22  23  24  25  26  27  28  29  30  31  32  33  34  35  36
##  [37]  37  38  39  40  41  42  43  44  45  46  47  48  49  50  51  52  53  54
##  [55]  55  56  57  58  59  60  61  62  63  64  65  66  67  68  69  70  71  72
##  [73]  73  74  75  76  77  78  79  80  81  82  83  84  85  86  87  88  89  90
##  [91]  91  92  94  95  96  97  99 100 101 102 103 104 105 106 107 108 109 110
## [109] 111 112 113 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
## [127] 130 131 132 133 134 135 136 137 138 139 140
sum_clean$pot.no <- pots
sum_clean
CP06 <- rbind(CP06, sum_clean)
data <- read.csv(my_files[3]) 
my_data <- data[,c(31, 18:25,27:30)]
for(i in 1:nrow(my_data)){
  my_data$timestamp[i] <- strsplit(my_data$roi[i], "_")[[1]][1]
}
sum_data <- summaryBy(area + convex_hull_area + solidity + perimeter + width + height ~ timestamp, data = my_data, FUN = function(x) c(mean = mean(x), sum=sum(x), max=max(x)))
sum_clean <- sum_data[,c(1, 3, 5, 8, 11, 16, 19)]
for(i in 1:nrow(sum_clean)){
  sum_clean$day[i] <- strsplit(sum_clean$timestamp[i], "-")[[1]][1]
  sum_clean$time[i] <- strsplit(sum_clean$timestamp[i], "-")[[1]][2]
  }
sum_clean <- sum_clean[,c(1,8:9,2:7)]
sum_clean
pots <- 1:140
nots <- c(93, 98)
pots <- subset(pots, !(pots %in% nots))
pots
##   [1]   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15  16  17  18
##  [19]  19  20  21  22  23  24  25  26  27  28  29  30  31  32  33  34  35  36
##  [37]  37  38  39  40  41  42  43  44  45  46  47  48  49  50  51  52  53  54
##  [55]  55  56  57  58  59  60  61  62  63  64  65  66  67  68  69  70  71  72
##  [73]  73  74  75  76  77  78  79  80  81  82  83  84  85  86  87  88  89  90
##  [91]  91  92  94  95  96  97  99 100 101 102 103 104 105 106 107 108 109 110
## [109] 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
## [127] 129 130 131 132 133 134 135 136 137 138 139 140
sum_clean$pot.no <- pots
sum_clean
CP06 <- rbind(CP06, sum_clean)
data <- read.csv(my_files[4]) 
my_data <- data[,c(31, 18:25,27:30)]
for(i in 1:nrow(my_data)){
  my_data$timestamp[i] <- strsplit(my_data$roi[i], "_")[[1]][1]
}
sum_data <- summaryBy(area + convex_hull_area + solidity + perimeter + width + height ~ timestamp, data = my_data, FUN = function(x) c(mean = mean(x), sum=sum(x), max=max(x)))
sum_clean <- sum_data[,c(1, 3, 5, 8, 11, 16, 19)]
for(i in 1:nrow(sum_clean)){
  sum_clean$day[i] <- strsplit(sum_clean$timestamp[i], "-")[[1]][1]
  sum_clean$time[i] <- strsplit(sum_clean$timestamp[i], "-")[[1]][2]
  }
sum_clean <- sum_clean[,c(1,8:9,2:7)]
sum_clean
pots <- 1:140
nots <- c(93, 98)
pots <- subset(pots, !(pots %in% nots))
pots
##   [1]   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15  16  17  18
##  [19]  19  20  21  22  23  24  25  26  27  28  29  30  31  32  33  34  35  36
##  [37]  37  38  39  40  41  42  43  44  45  46  47  48  49  50  51  52  53  54
##  [55]  55  56  57  58  59  60  61  62  63  64  65  66  67  68  69  70  71  72
##  [73]  73  74  75  76  77  78  79  80  81  82  83  84  85  86  87  88  89  90
##  [91]  91  92  94  95  96  97  99 100 101 102 103 104 105 106 107 108 109 110
## [109] 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
## [127] 129 130 131 132 133 134 135 136 137 138 139 140
sum_clean$pot.no <- pots
sum_clean
CP06 <- rbind(CP06, sum_clean)
data <- read.csv(my_files[5]) 
my_data <- data[,c(31, 18:25,27:30)]
for(i in 1:nrow(my_data)){
  my_data$timestamp[i] <- strsplit(my_data$roi[i], "_")[[1]][1]
}
sum_data <- summaryBy(area + convex_hull_area + solidity + perimeter + width + height ~ timestamp, data = my_data, FUN = function(x) c(mean = mean(x), sum=sum(x), max=max(x)))
sum_clean <- sum_data[,c(1, 3, 5, 8, 11, 16, 19)]
for(i in 1:nrow(sum_clean)){
  sum_clean$day[i] <- strsplit(sum_clean$timestamp[i], "-")[[1]][1]
  sum_clean$time[i] <- strsplit(sum_clean$timestamp[i], "-")[[1]][2]
  }
sum_clean <- sum_clean[,c(1,8:9,2:7)]
sum_clean
pots <- 1:140
nots <- c(93, 98)
pots <- subset(pots, !(pots %in% nots))
pots
##   [1]   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15  16  17  18
##  [19]  19  20  21  22  23  24  25  26  27  28  29  30  31  32  33  34  35  36
##  [37]  37  38  39  40  41  42  43  44  45  46  47  48  49  50  51  52  53  54
##  [55]  55  56  57  58  59  60  61  62  63  64  65  66  67  68  69  70  71  72
##  [73]  73  74  75  76  77  78  79  80  81  82  83  84  85  86  87  88  89  90
##  [91]  91  92  94  95  96  97  99 100 101 102 103 104 105 106 107 108 109 110
## [109] 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
## [127] 129 130 131 132 133 134 135 136 137 138 139 140
sum_clean$pot.no <- pots
sum_clean
CP06 <- rbind(CP06, sum_clean)
data <- read.csv(my_files[6]) 
my_data <- data[,c(31, 18:25,27:30)]
for(i in 1:nrow(my_data)){
  my_data$timestamp[i] <- strsplit(my_data$roi[i], "_")[[1]][1]
}
sum_data <- summaryBy(area + convex_hull_area + solidity + perimeter + width + height ~ timestamp, data = my_data, FUN = function(x) c(mean = mean(x), sum=sum(x), max=max(x)))
sum_clean <- sum_data[,c(1, 3, 5, 8, 11, 16, 19)]
for(i in 1:nrow(sum_clean)){
  sum_clean$day[i] <- strsplit(sum_clean$timestamp[i], "-")[[1]][1]
  sum_clean$time[i] <- strsplit(sum_clean$timestamp[i], "-")[[1]][2]
  }
sum_clean <- sum_clean[,c(1,8:9,2:7)]
sum_clean

In here - I figured that pots 49 and 50 were missing - by looking at the images.

pots <- 1:140
nots <- c(49, 50, 93, 98)
pots <- subset(pots, !(pots %in% nots))
pots
##   [1]   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15  16  17  18
##  [19]  19  20  21  22  23  24  25  26  27  28  29  30  31  32  33  34  35  36
##  [37]  37  38  39  40  41  42  43  44  45  46  47  48  51  52  53  54  55  56
##  [55]  57  58  59  60  61  62  63  64  65  66  67  68  69  70  71  72  73  74
##  [73]  75  76  77  78  79  80  81  82  83  84  85  86  87  88  89  90  91  92
##  [91]  94  95  96  97  99 100 101 102 103 104 105 106 107 108 109 110 111 112
## [109] 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
## [127] 131 132 133 134 135 136 137 138 139 140
sum_clean$pot.no <- pots
sum_clean
CP06 <- rbind(CP06, sum_clean)
data <- read.csv(my_files[7]) 
my_data <- data[,c(31, 18:25,27:30)]
for(i in 1:nrow(my_data)){
  my_data$timestamp[i] <- strsplit(my_data$roi[i], "_")[[1]][1]
}
sum_data <- summaryBy(area + convex_hull_area + solidity + perimeter + width + height ~ timestamp, data = my_data, FUN = function(x) c(mean = mean(x), sum=sum(x), max=max(x)))
sum_clean <- sum_data[,c(1, 3, 5, 8, 11, 16, 19)]
for(i in 1:nrow(sum_clean)){
  sum_clean$day[i] <- strsplit(sum_clean$timestamp[i], "-")[[1]][1]
  sum_clean$time[i] <- strsplit(sum_clean$timestamp[i], "-")[[1]][2]
  }
sum_clean <- sum_clean[,c(1,8:9,2:7)]
sum_clean
pots <- 1:140
nots <- c(93, 98)
pots <- subset(pots, !(pots %in% nots))
pots
##   [1]   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15  16  17  18
##  [19]  19  20  21  22  23  24  25  26  27  28  29  30  31  32  33  34  35  36
##  [37]  37  38  39  40  41  42  43  44  45  46  47  48  49  50  51  52  53  54
##  [55]  55  56  57  58  59  60  61  62  63  64  65  66  67  68  69  70  71  72
##  [73]  73  74  75  76  77  78  79  80  81  82  83  84  85  86  87  88  89  90
##  [91]  91  92  94  95  96  97  99 100 101 102 103 104 105 106 107 108 109 110
## [109] 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
## [127] 129 130 131 132 133 134 135 136 137 138 139 140
sum_clean$pot.no <- pots
sum_clean
CP06 <- rbind(CP06, sum_clean)
data <- read.csv(my_files[8]) 
my_data <- data[,c(31, 18:25,27:30)]
for(i in 1:nrow(my_data)){
  my_data$timestamp[i] <- strsplit(my_data$roi[i], "_")[[1]][1]
}
sum_data <- summaryBy(area + convex_hull_area + solidity + perimeter + width + height ~ timestamp, data = my_data, FUN = function(x) c(mean = mean(x), sum=sum(x), max=max(x)))
sum_clean <- sum_data[,c(1, 3, 5, 8, 11, 16, 19)]
for(i in 1:nrow(sum_clean)){
  sum_clean$day[i] <- strsplit(sum_clean$timestamp[i], "-")[[1]][1]
  sum_clean$time[i] <- strsplit(sum_clean$timestamp[i], "-")[[1]][2]
  }
sum_clean <- sum_clean[,c(1,8:9,2:7)]
sum_clean
pots <- 1:140
nots <- c(93, 98)
pots <- subset(pots, !(pots %in% nots))
pots
##   [1]   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15  16  17  18
##  [19]  19  20  21  22  23  24  25  26  27  28  29  30  31  32  33  34  35  36
##  [37]  37  38  39  40  41  42  43  44  45  46  47  48  49  50  51  52  53  54
##  [55]  55  56  57  58  59  60  61  62  63  64  65  66  67  68  69  70  71  72
##  [73]  73  74  75  76  77  78  79  80  81  82  83  84  85  86  87  88  89  90
##  [91]  91  92  94  95  96  97  99 100 101 102 103 104 105 106 107 108 109 110
## [109] 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
## [127] 129 130 131 132 133 134 135 136 137 138 139 140
sum_clean$pot.no <- pots
sum_clean
CP06 <- rbind(CP06, sum_clean)

Decoding the pot information using the FW data

We will load the data containing fresh and dry weight, as well as all of the decoding information:

decode <- read.csv("FWDW_exp6.csv")
colnames(decode)[1] <- "pot.no"
FW_data <- decode
decode <- decode[,1:3]
decode <- subset(decode, !(decode$pot.no %in% nots))

CP06 <- CP06[,c(1:3,10,4:9)]
CP06
CP06_decoded <- merge(CP06, decode, all = TRUE)
unique(CP06_decoded$day)
## [1] "2022.07.07" "2022.07.17" "2022.07.09" "2022.07.19" "2022.07.11"
## [6] "2022.07.21" "2022.07.13" "2022.07.15"
CP06_decoded

Visualize the data over time:

For this - we need to rename the date into a numeric day of experiment:

CP06_decoded$day <- gsub("2022.07.07", 0, CP06_decoded$day)
CP06_decoded$day <- gsub("2022.07.09", 2, CP06_decoded$day)
CP06_decoded$day <- gsub("2022.07.11", 4, CP06_decoded$day)
CP06_decoded$day <- gsub("2022.07.13", 6, CP06_decoded$day)
CP06_decoded$day <- gsub("2022.07.15", 8, CP06_decoded$day)
CP06_decoded$day <- gsub("2022.07.17", 10, CP06_decoded$day)
CP06_decoded$day <- gsub("2022.07.19", 12, CP06_decoded$day)
CP06_decoded$day <- gsub("2022.07.21", 14, CP06_decoded$day)
CP06_decoded$day <- as.numeric(as.character(CP06_decoded$day))
CP06_decoded

Now - let’s visualize the area.sum over time for each pot, and divide colours by treatments:

unique(CP06_decoded$Treatment)
## [1] "Control " "Drought"
CP06_decoded$Treatment <- gsub(" ", "", CP06_decoded$Treatment)
CP06_decoded$Treatment <- factor(CP06_decoded$Treatment, levels = c("Control", "Drought"))

library(ggplot2)
library(ggpubr)
library("ggsci")

CP06_decoded$day <- as.factor(CP06_decoded$day)

Area_lgraph_CP06 <- ggplot(data=CP06_decoded, aes(x= day, y=area.sum, group = pot.no, color = Treatment)) 
Area_lgraph_CP06 <- Area_lgraph_CP06 + geom_line(alpha = 0.1) 
Area_lgraph_CP06 <- Area_lgraph_CP06 + stat_summary(fun.data = mean_se, geom="ribbon", linetype=0, aes(group= Treatment), alpha=0.3)
Area_lgraph_CP06 <- Area_lgraph_CP06 + stat_summary(fun=mean, aes(group= Treatment),  size=0.7, geom="line", linetype = "dashed")
Area_lgraph_CP06 <- Area_lgraph_CP06 + stat_compare_means(aes(group = Treatment), label = "p.signif", method = "t.test", hide.ns = T)
Area_lgraph_CP06 <- Area_lgraph_CP06 + ylab("Shoot Size (7 x SV pixels)") + xlab("Days After Stress") + scale_color_jco()
Area_lgraph_CP06

Let’s save the data too into a clean and separate csv file:

write.csv(CP06_decoded, "Cowpea_06_Clean_data.csv", row.names = FALSE)

Visualize the correlation between FW and pixels at final day:

last_day <- subset(CP06_decoded, CP06_decoded$day == 14)
unique(last_day$Treatment)
## [1] Control Drought
## Levels: Control Drought
unique(FW_data$Treatment)
## [1] "Control " "Drought"
FW_data$Treatment <- gsub(" ", "", FW_data$Treatment)
last_day_FW <- merge(last_day, FW_data, by=c("pot.no", "Genotype", "Treatment"), all=TRUE)
last_day_FW
FW_Area_CP06 <- ggscatter(last_day_FW, x = "area.sum", y = "FW",rug = TRUE) + stat_cor()   
FW_Area_CP06
## Warning: Removed 2 rows containing non-finite values (stat_cor).
## Warning: Removed 2 rows containing missing values (geom_point).