how to warp 3D meshes for 2 block PLS

198 views
Skip to first unread message

chip...@unimelb.edu.au

unread,
Feb 22, 2018, 1:10:00 AM2/22/18
to geomorph R package
Hi all,

Can someone please help me with code to warp my 3D meshes in a 2-block PLS? I've managed to get my reference mesh working for other plots like PCA, but I don't know how to specify the 2 separate meshes for each of the blocks, in this case cranium and mandibles, in the plot(PLS, label = NULL, warpgrids = TRUE) code. 

Thanks for any help!

Christy


Mike Collyer

unread,
Feb 22, 2018, 2:31:11 AM2/22/18
to geomorph R package
Hi Christy,

Could you be more specific with your question, please?  Are you stating that the warpgrids = TRUE argument is not producing any plots?  Or are you stating that you want the mesh = TRUE option for the plots that are produced but are not getting that in the plot?

If the latter and if you tried to add mesh = TRUE to the plot arguments to no avail, please let me know and I will see if I can fix the function (might take a day or two).  You could always use shape.predictor and plotRefToTarget to generate your own 3D mesh plots for any point in the plot n the interim.  There should be an example for pls plots in the shape.predictor help page.

Cheers!
Mike

--
You received this message because you are subscribed to the Google Groups "geomorph R package" group.
To unsubscribe from this group and stop receiving emails from it, send an email to geomorph-r-pack...@googlegroups.com.
To post to this group, send email to geomorph-...@googlegroups.com.
Visit this group at https://groups.google.com/group/geomorph-r-package.
To view this discussion on the web, visit https://groups.google.com/d/msgid/geomorph-r-package/88f1490d-ff00-4a0a-aedb-875ec606eaf1%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

chip...@unimelb.edu.au

unread,
Feb 22, 2018, 9:12:31 PM2/22/18
to geomorph R package
Hi Mike,

So far I only have one of the meshes (cranium) entered as the reference, and when I run the code 
plot(phyintresults, warpgrids = TRUE, shapes = TRUE)
I get 2 plots, one of cranium and one of mandibles, but they are only the landmarks and not the warped meshes. However since I've only entered one, this might be the problem. Is it possible to specify which mesh is Block 1 and which is Block 2 to create the relevant warps? Or do I rather take the generated shape coordinates and use those to warp my meshes myself? 

Thanks for your response, and sorry I'm so crappy at plotting in R!
Christy

On Thursday, February 22, 2018 at 6:31:11 PM UTC+11, Michael Collyer wrote:
Hi Christy,

Could you be more specific with your question, please?  Are you stating that the warpgrids = TRUE argument is not producing any plots?  Or are you stating that you want the mesh = TRUE option for the plots that are produced but are not getting that in the plot?

If the latter and if you tried to add mesh = TRUE to the plot arguments to no avail, please let me know and I will see if I can fix the function (might take a day or two).  You could always use shape.predictor and plotRefToTarget to generate your own 3D mesh plots for any point in the plot n the interim.  There should be an example for pls plots in the shape.predictor help page.

Cheers!
Mike

On Feb 22, 2018, at 6:10 AM, chip...@unimelb.edu.au wrote:

Hi all,

Can someone please help me with code to warp my 3D meshes in a 2-block PLS? I've managed to get my reference mesh working for other plots like PCA, but I don't know how to specify the 2 separate meshes for each of the blocks, in this case cranium and mandibles, in the plot(PLS, label = NULL, warpgrids = TRUE) code. 

Thanks for any help!

Christy



--
You received this message because you are subscribed to the Google Groups "geomorph R package" group.
To unsubscribe from this group and stop receiving emails from it, send an email to geomorph-r-package+unsub...@googlegroups.com.

Jasmine Croghan

unread,
Feb 22, 2018, 10:09:29 PM2/22/18
to geomorph R package

Hi Christy,

As far as I know, this function does not yet exist for the 2-block PLS, but I have run into the same issue.  I have created a work around where I stole some of the source code from the old two.b.pls function and created a monster that I have to hand edit, but that outputs the coordinates at either end of the PLS plot for one axis.  I believe that if Emma wished to do so, she could modify the current function to output the 'pls1.max' and 'pls1.min' at the end of the block to which we could plotreftotarget.  I'm not knowledgeable enough in R to actually bind it as a function myself so I've just been sharing around this code:



###The following block of code was extracted from the two.b.pls function code.  PROVIDING YOU CHANGE THE ***** OBJECT TO THE PLS YOU JUST RAN, It can all be run in a group and the end result will be two objects that we need to warp the ref shape to the max and min values of pls1 for block 1 (the shape coordinate data)

plsnew<-function (x, y, RV = FALSE, verbose = FALSE) 
{
  x <- as.matrix(x)
  y <- as.matrix(y)
  px <- ncol(x)
  py <- ncol(y)
  pmin <- min(px, py)
  S <- var(cbind(x, y))
  S12 <- matrix(S[1:px, -(1:px)], px, py)
  pls <- La.svd(S12, pmin, pmin)
  U <- pls$u
  V <- t(pls$vt)
  XScores <- x %*% U
  YScores <- y %*% V
  r.pls <- cor(XScores[, 1], YScores[, 1])
  if (RV == TRUE) {
    S11 <- S[1:px, 1:px]
    S22 <- S[-(1:px), -(1:px)]
    RV <- sum(colSums(S12^2))/sqrt(sum(S11^2) * sum(S22^2))
  }
  else RV <- NULL
  if (verbose == TRUE) {
    XScores <- as.matrix(XScores)
    Y <- as.matrix(YScores)
    rownames(U) = colnames(x)
    rownames(V) = colnames(y)
    out <- list(pls.svd = pls, r.pls = r.pls, RV = RV, left.vectors = U, 
                right.vectors = V, XScores = XScores, YScores = YScores)
  }
  else out <- r.pls
  out
}


p<-PPLS #********************************CHANGE THIS TO THE NAME OF THE PLS YOU JUST RAN

A1 <- p$A1
A2 <- p$A2
XScores <- p$XScores
YScores <- p$YScores
if (is.matrix(XScores)) 
  XScores <- XScores[, 1]
if (is.matrix(YScores)) 
  YScores <- YScores[, 1]
plsRaw <- plsnew(p$A1.matrix, p$A2.matrix, verbose = TRUE)
XScoresRaw <- plsRaw$XScores[, 1]
YScoresRaw <- plsRaw$YScores[, 1]
pc <- prcomp(cbind(XScores, YScores))$x[, 1]
px <- predict(lm(XScores ~ pc))
py <- predict(lm(YScores ~ pc))
pxmax <- max(px)
pxmin <- min(px)
pymax <- max(py)
pymin <- min(py)
pcRaw <- prcomp(cbind(XScoresRaw, YScoresRaw))$x[, 1]
pxRaw <- predict(lm(XScoresRaw ~ pcRaw))
pyRaw <- predict(lm(YScoresRaw ~ pcRaw))
pxmaxRaw <- max(pxRaw)
pxminRaw <- min(pxRaw)
pymaxRaw <- max(pyRaw)
pyminRaw <- min(pyRaw)
if (length(dim(A1)) == 3) {
  A1.ref <- mshape(A1)
  A1.min <- arrayspecs(pxminRaw * p$left.pls.vectors[, 
                                                     1], nrow(A1.ref), ncol(A1.ref))[, , 1]
  A1.max <- arrayspecs(pxmaxRaw * p$left.pls.vectors[, 
                                                     1], nrow(A1.ref), ncol(A1.ref))[, , 1]
  pls1.min <- A1.ref + A1.min
  pls1.max <- A1.ref + A1.max
  pls1.mid <- A1.ref + 0.5*A1.max
}

#********************************************************************************************END OF BLOCK********************************
#saves the coords we just created as .csv file
write.csv (pls1.max, file = "pls1maxcoords.csv")
write.csv (pls1.min, file = "pls1mincoords.csv")

pls.min <- read.csv("pls1mincoords.csv")

#Now let's visualize the differences between these:
PLS1Max<-plotRefToTarget(M1=ref, M2=pls1.max, mesh = averagemesh, method = c("surface"), links = NULL)
PLS1Min<-plotRefToTarget(M1=ref, M2=pls1.min, mesh = averagemesh, method = c("surface"), links = NULL)

I hope that you can modify this to your needs to output both axes.
Good luck,
~Jasmine

chip...@unimelb.edu.au

unread,
Feb 22, 2018, 11:58:43 PM2/22/18
to geomorph R package

Hi Jasmine,

 

Thanks for your answer. Aren’t the pls coordinates the same as what is spit out if one chooses shapes=TRUE in the 
plot code? Mine gives a list of min and max for pls1 and pls2. I was thinking I could simply save those and use them 
to warp my reference mesh, or would that be totally different to what you are doing? Sorry if I’m missing something,
because I'm not experienced enough experience to follow your code, although I’ll give it a try.
 
Thanks,
Christy

Mike Collyer

unread,
Feb 23, 2018, 1:52:39 AM2/23/18
to geomorph-...@googlegroups.com
Christy, Jasmine,

Yes, it is true that there is currently no mesh option with plot.pls but there is no need to overwrite code and do something complicated.  The function, shape.predictor, can be used to generate coordinates for plotRefToTarget for any point anywhere in a PLS (or other) plot.  There is an example showing exactly how to do this for PLS on the help page for this function.

To answer your other question, yes, your intuition is correct.  You can save the shapes generated and go straight to plotRefToTarget.  Either way (shape.predictor or export the shapes after the shapes = TRUE argument is used) will give you the coordinates to use in plotRefToTarget.

The reason for this irregularity is that plot.pls has ellipsis capability - meaning that arguments can be passed to other functions - but it is currently set up to pass the arguments to the default plot but not the additional plots for warp grids or meshes.  I’ll try to update this soon, but in the meantime, you can use plotRefToTarget in 1-2 extra steps to make your extreme mesh plots.

Cheers!
Mike

-- 
You received this message because you are subscribed to the Google Groups "geomorph R package" group.
To unsubscribe from this group and stop receiving emails from it, send an email to geomorph-r-pack...@googlegroups.com.

To post to this group, send email to geomorph-...@googlegroups.com.
Visit this group at https://groups.google.com/group/geomorph-r-package.
Reply all
Reply to author
Forward
0 new messages