Is there different about fruit shape between four Cecropia species: C. distachya, C. latiloba, C. obtusa and C. sciadophylla?
Libungan (2015) developed ShapeR package in R software to study Otolith shape among fish populations. This tool works well for this study in two dimensions objects. So I want to try this approach in study about fruit shape among some species of Cecropia.
I used 10 images of fruit for each species in this test. Each picture is a different fruit. Images of the same species were to be placed in the same folder that was coded by the two letters of species name. “DI”-distachya; “LA”-latiloba; “OB”-obtusa and “SC”-sciadophylla. All of these folders have been put together in “Original” folder. The “Fixed” folder was created by a copy “Original” folder and rename it. This folder was used for control the outline of fruit shape.
For this analysis, I need a csv file with these basic information of fruit and two important columns: “folder” and “picname” that help the package located the images to analyze. I added a “cal” column in this dataset with the information about 1 mm in pixels of my images.
dataset <- read.csv("Cecropia.csv", stringsAsFactors = F)
DT::datatable(dataset)
library(shapeR)
library(wavethresh)
#library(shapeR)
shape_df <- shapeR("D:/ShapeAnalysisCecropia/","Cecropia.csv")
This step is very important. Incorrect outline detection will affect the results of the analysis. This detection is affected by image quality and contrast between object and background. Because the color of Cecropia’s fruits are dark, so I need to fix their outline in the “Fixed” folder.
shape <- detect.outline(shape_df, threshold = 0.2, write.outline.w.org = TRUE)
Look at some images after outline dectected
show.original.with.outline(shape,"DI","BG035_3")
show.original.with.outline(shape,"LA","BG083_1")
show.original.with.outline(shape,"OB","BG122_2")
show.original.with.outline(shape,"SC","BG183_3")
#Contour smoothing
shape <- smoothout(shape, n=100)
#Shape coefficient
shape <- generateShapeCoefficients(shape)
##
|
| | 0%
|
|== | 2%
|
|=== | 5%
|
|===== | 8%
|
|====== | 10%
|
|======== | 12%
|
|========== | 15%
|
|=========== | 18%
|
|============= | 20%
|
|=============== | 22%
|
|================ | 25%
|
|================== | 28%
|
|==================== | 30%
|
|===================== | 32%
|
|======================= | 35%
|
|======================== | 38%
|
|========================== | 40%
|
|============================ | 42%
|
|============================= | 45%
|
|=============================== | 48%
|
|================================ | 50%
|
|================================== | 52%
|
|==================================== | 55%
|
|===================================== | 58%
|
|======================================= | 60%
|
|========================================= | 62%
|
|========================================== | 65%
|
|============================================ | 68%
|
|============================================== | 70%
|
|=============================================== | 72%
|
|================================================= | 75%
|
|================================================== | 78%
|
|==================================================== | 80%
|
|====================================================== | 82%
|
|======================================================= | 85%
|
|========================================================= | 88%
|
|========================================================== | 90%
|
|============================================================ | 92%
|
|============================================================== | 95%
|
|=============================================================== | 98%
|
|=================================================================| 100%
shape <- enrich.master.list(shape)
measure <- getMeasurements(shape)
colnames(measure) <- c("area","length","width","perimeter")
DT::datatable(measure)
We can see there is different in mean outline shape between four species. They seem to split into two groups of C. distachy - C. obtusa and C. latiloba - C. sciadophylla.
plotWaveletShape_b(shape, "code", show.angle = TRUE, lwd = 2,lty = 1)
shape@master.list$length <- getMeasurements(shape)$otolith.length
shape <- stdCoefs(shape, classes = "code", std.by = "length")
est.list = estimate.outline.reconstruction(shape)
##
|
| | 0%
|
|== | 2%
|
|=== | 5%
|
|===== | 8%
|
|====== | 10%
|
|======== | 12%
|
|========== | 15%
|
|=========== | 18%
|
|============= | 20%
|
|=============== | 22%
|
|================ | 25%
|
|================== | 28%
|
|==================== | 30%
|
|===================== | 32%
|
|======================= | 35%
|
|======================== | 38%
|
|========================== | 40%
|
|============================ | 42%
|
|============================= | 45%
|
|=============================== | 48%
|
|================================ | 50%
|
|================================== | 52%
|
|==================================== | 55%
|
|===================================== | 58%
|
|======================================= | 60%
|
|========================================= | 62%
|
|========================================== | 65%
|
|============================================ | 68%
|
|============================================== | 70%
|
|=============================================== | 72%
|
|================================================= | 75%
|
|================================================== | 78%
|
|==================================================== | 80%
|
|====================================================== | 82%
|
|======================================================= | 85%
|
|========================================================= | 88%
|
|========================================================== | 90%
|
|============================================================ | 92%
|
|============================================================== | 95%
|
|=============================================================== | 98%
|
|=================================================================| 100%
outline.reconstruction.plot(est.list, max.num.harmonics = 15)
par(mfrow=c(1,1))
plotWavelet(shape, level = 5, class.name = "code", useStdcoef = TRUE)
library(vegan)
stdw = getStdWavelet(shape)
sp = factor(getMasterlist(shape)$code)
cap.res = capscale(stdw ~ sp)
#plot(cap.res)
anova(cap.res, by = "terms", step = 1000)
## Permutation test for capscale under reduced model
## Terms added sequentially (first to last)
## Permutation: free
## Number of permutations: 999
##
## Model: capscale(formula = stdw ~ sp)
## Df Variance F Pr(>F)
## sp 3 21.415 32.018 0.001 ***
## Residual 36 8.026
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
P-value of ANOVA test is 0.001 ==> The different about fruit shape between four species is significant.
Fruit shape of C. obtusa differs with other species along the first discriminating axis (CAP1) with value positif and the fruit shape of C. distachya differs with C. sciadophylla and C. latiloba by along the second axis (CAP2) with value negatif.
eig = eigenvals(cap.res,constrained = T)
eig.ratio = eig/sum(eig)
cluster.plot(scores(cap.res)$sites[,1:2],getMasterlist(shape)$code,
xlim = range(scores(cap.res)$sites[,1]),
ylim = range(scores(cap.res)$sites[,2]),
xlab = paste("CAP1 (",round(eig.ratio[1]*100,1),"%)",sep = ""),
ylab = paste("CAP2 (",round(eig.ratio[2]*100,1),"%)",sep = ""),
plotCI = TRUE,conf.level = 0.95,las = 1)
If we zoom in the area of C. sciadophylla and C. latiloba, we can see them is distance by the second axis too.
cluster.plot(scores(cap.res)$sites[,1:2],sp, xlim=c(-0.6,-0.2), ylim = c(0.5,1.5),
plotCI = TRUE,conf.level = 0.95,las = 1)
Libungan, Snæbjörn, Lísa Anne AND Pálsson. 2015. “ShapeR: An R Package to Study Otolith Shape Variation Among Fish Populations.” PLOS ONE 10 (3). Public Library of Science: 1–12. https://doi.org/10.1371/journal.pone.0121102.