tbates / umx

Making Structural Equation Modeling (SEM) in R quick & powerful
https://tbates.github.io/
44 stars 17 forks source link

Help with small wrapper for custom model #194

Closed lf-araujo closed 2 years ago

lf-araujo commented 2 years ago

Dear Tim,

We have recently put out a DoC variation that allows bidirectional causality and full confounding here and I wanted to see if I could make a umx wrapper for it.

It works partially, but it does not conform to what umxSummary expects to provide a pretty print out.

Error incurred trying to run umxSummary
model 'MRDoC2' does not use RAM expectation> summary(model)
umxMRDoC2 <- function(pheno, prss,
                      mzData = NULL, dzData = NULL,
                      data = NULL, zyg = NULL,
                    sep = "_T", rf = NULL,
                    name = "MRDoC2", autoRun = getOption("umx_auto_run"),
                     tryHard = c("no", "yes", "ordinal", "search"),
                    optimizer = NULL) {

  tryHard <- match.arg(tryHard)

  # Managing data
  if (!is.null(data)) {
    if ("tbl" %in% class(data)) {
      data = as.data.frame(data)
    }
    mzData = data[data[, zyg] %in% ifelse(is.null(mzData), "MZ", mzData), ]
    dzData = data[data[, zyg] %in% ifelse(is.null(dzData), "DZ", dzData), ]
  } else {
    if ("tbl" %in% class(mzData)) {
      mzData = as.data.frame(mzData)
      dzData = as.data.frame(dzData)
    }
  }

  vnames = tvars(c(pheno, prss), sep = sep)

  xmu_twin_check(
    selDVs = c(pheno, prss),
    sep = sep, dzData = dzData, mzData = mzData, enforceSep = TRUE,
    nSib = 2, optimizer = optimizer
  )

  mzData = xmu_make_mxData(mzData, manifests = vnames)
  dzData = xmu_make_mxData(dzData, manifests = vnames)

  ny = 8
  ne_ = 4
  ny1 = ny-2

  x=1 # x
  y=1

  mxlabelsBE <- matrix(c(
    NA, "g2", "b1", "b4",
    "g1", NA, "b2", "b3",
    NA, NA, NA, NA,
    NA, NA, NA, NA
  ),4,4, byrow = T)

  mxfreeBE <- matrix(c(
    F, T, T, F,
    T, F, F, T,
    F, F, F, F,
    F, F, F,F
  ),4,4, byrow = T)

  mxfreeA <- matrix(c(
    T,T,F,F,
    T,T,F,F,
    F,F,T,T,
    F,F,T,T), 4, 4, byrow=T)

  mxvaluesA <- matrix(c(
    1, 1, 0,0,
    1, 1, 0,0,
    0,0, x^2,x*y*rf,
    0, 0, x*y*rf,y^2), 4,4, byrow = T)

  mxlabelsA <- matrix(c(
    "ab2","abraas",NA,NA,
    "abraas","as2",NA,NA,
    NA,NA,"x2","xrfy",
    NA,NA,"xrfy","y2"), 4, 4, byrow=T)

  mxfreeC <- matrix(c(
    T,T,F,F,
    T,T,F,F,
    F,F,F,F,
    F,F,F,F),4, 4, byrow=T)

  mxlabelsC <- matrix(c(
    "cb2","cbrccs",NA,NA,
    "cbrccs","cs2",NA,NA,
    NA,NA,NA,NA,
    NA,NA,NA,NA),4, 4, byrow=T)

  mxfreeE <- matrix(c(
    T,T,F,F,
    T,T,F,F,
    F,F,F,F,
    F,F,F,F),4, 4, byrow=T)

  mxlabelsE <- matrix(c(
    "eb2","ebrees",NA,NA,
    "ebrees","es2",NA,NA,
    NA,NA,NA,NA,
    NA,NA,NA,NA),4, 4, byrow=T)

  mxFilt <- matrix(c(
    1,0,0,0,0,0,0,0,
    0,1,0,0,0,0,0,0,
    0,0,1,0,0,0,0,0,
    0,0,0,1,0,0,0,0,
    0,0,0,0,1,0,0,0,
    0,0,0,0,0,1,0,0),ny1,ny,byrow=T)

top=mxModel('TwRM',
    mxMatrix(type='Full',nrow=ne_,ncol=ne_,
       free=mxfreeBE,labels=mxlabelsBE,
       ubound=10,lbound=-10, name='BE'),
    mxMatrix(type='Iden',nrow=ne_,ncol=ne_,name='I'),
    mxMatrix(type='Full',nrow=6,ncol=8,free=F,values=mxFilt, name='F'),

    mxMatrix(type='Full',nrow=ne_,ncol=ne_,
     free = F,value = diag(ne_),labels = NA,
       ubound=10,lbound=-10,name='LY'),

    mxMatrix(type='Symm',nrow=ne_,ncol=ne_,
       free=mxfreeA,labels=mxlabelsA,
       ubound=10,lbound=-10,name='A'),

    mxMatrix(type='Symm',nrow=ne_,ncol=ne_,
       free=mxfreeC,labels=mxlabelsC,
       ubound=10,lbound=-10,name='C'),

    mxMatrix(type='Symm',nrow=ne_,ncol=ne_,
       free=mxfreeE,labels=mxlabelsE,
       ubound=10,lbound=-10,name='E'),

    mxMatrix(type='Full',nrow=1,ncol=ny,
     free=T,value=0,
       labels=c('meB','meS','meFB','meFS','meB','meS','meFB','meFS'),
       ubound=10,lbound=-10,name='dzmu'),
    mxAlgebra(expression=dzmu%*%t(F), name='mzmu'),

    mxAlgebra(expression=solve(I-BE),name='iBE'),

    mxAlgebra(expression=iBE %*% A %*% t(iBE), name='A_'),
    mxAlgebra(expression=iBE %*% C %*%t(iBE), name='C_'),
    mxAlgebra(expression=iBE%*%E%*%t(iBE), name='E_'),
    mxAlgebra(expression=A_ + C_ + E_, name='SPh'),
    mxAlgebra(expression=rbind(
                         cbind(SPh, A_+C_),
                         cbind(A_+C_, SPh)),name='Smz_'),
    mxAlgebra(expression=rbind(
                         cbind(SPh, .5%x%A_+C_),
                         cbind(.5%x%A_+C_, SPh)),name='Sdz'),

    mxAlgebra(expression=F%*%Smz_%*%t(F),name='Smz')
 )

MZ=mxModel("MZ",mzData,
  mxExpectationNormal(covariance="TwRM.Smz",means="TwRM.mzmu",vnames[1:6]),
  mxFitFunctionML()
)

DZ=mxModel("DZ",dzData,
     mxExpectationNormal(covariance="TwRM.Sdz",means="TwRM.dzmu",vnames),
     mxFitFunctionML()
)

model =  mxModel("MRDoC2", top, MZ, DZ, mxFitFunctionMultigroup( c("MZ","DZ") ))

  # model = as(model, "MxModel")
  model = mxAutoStart(model)
  # model = umxModify(model, update = c("x2", "y2"),  value = 1)

  model = xmu_safe_run_summary(model, autoRun = autoRun, tryHard = tryHard,
                               std = T)
}

You can find data to test in this gist

and a MWE:

library(readr)
library(umx)
library(dplyr)

dataDz <- read_csv("../data/DZ.csv")
dataMz <- read_csv("../data/MZ.csv")  %>%
  bind_cols(dataDz %>% select( GVSBP2, GVBMI2))

model  <- umxMRDoC2(pheno = c("BMI", "SBP"), prss = c("GVBMI", "GVSBP"),
                    dzData = dataDz, mzData = dataMz,
                     sep = "", rf = 0.1)

summary(model)
tbates commented 2 years ago

nice!

So to make this work in umx, you would want to set a class for the model, right above call to xmu_safe_run_summary

# set class so that S3s dispatch e.g. umxSummary, plot
model = as(model, "MxModelDoC2")

And copy a umxSummary method, and set it to this new class

#' @aliases umxSummary.MxModelDoC2

Now it will try and dispatch on your neat new DoC model.

At the simplest level, you could simply bury a call to print(summary()) in the normal model.

To do what the other umxSummary models do - i.e a more customised output, you need to process all your custom matrices and algebras like SPh in the ways you want to show the user.

Same with plot: Need to copy an existing umxPlot function, recluse it, and then rework the internals to find the cells that correspond to circles and boxes and paths in your model, loop through the model assembling those into a graphviz description of edges and nodes, and print it using DiagrammeR

tbates commented 1 year ago

Cool!

In brief, for non RAM models, you. Have to write a model specific umxSummary function to do what you want with it (I.e there no generic way to know which matrices mean what etc). So umx has umxSummaryACE CP DoC etc

They get called using R’s object methods because I also set a unique type for each model, so the generic unxSummary methods dispatches to the right owner. And that falls back to RAM, which is why you get the error you got.

Same sorry for plot (which would be nice to implement for DoC

You might have a look at some of the umxSummary* functions (search the package code) and get back to me if you have questions?

You could copy one that seems close, and change the .suffix to .MxModelDoC2

lf-araujo commented 1 year ago

Thanks, I will look into this soon, as we are working to apply the model to real data. I spent some time trying understanding S3 and S4, there were some concepts that went above my head. These are not similar to methods in other languages.

tbates commented 1 year ago

S3 is pretty simple, and I would ignore S4.

S3 calls the right version of a function by looking at the class of the first parameter. Setting the class is as simple as model = as(model, "MxModelDoC2")

then when you say plot(model), R will look for a function called plot.MxModelDoC2() and call that for you.

So you also need to write those umxSummary.MxModelDoC2 and plot.MxModelDoC2 functions.

lf-araujo commented 1 year ago

Thanks,

I am ready to tackle this. It seems I just need to make small modifications to the umxSummary general function. The issue I face currently is in the line (fit_and_reporting.R):

    parameterTable = mxStandardizeRAMpaths(model, SE = SE) # Compute standard errors

As I don't follow that typical RAM matrix structure, see code below. How you suggest is the easiest way of getting the list of parameters in this case?

My function currently looks like: ```r umxMRDoC <- function(pheno, prss, mzData = NULL, dzData = NULL, data = NULL, zyg = NULL, sep = "_T", name = NULL, autoRun = getOption("umx_auto_run"), tryHard = c("no", "yes", "ordinal", "search"), optimizer = NULL, refModels = NULL, ci = F) { tryHard <- match.arg(tryHard) options(mxByrow = TRUE) umx_set_silent(TRUE) # Managing data if (!is.null(data)) { if ("tbl" %in% class(data)) { data = as.data.frame(data) } mzData = data[data[, zyg] %in% ifelse(is.null(mzData), "MZ", mzData), ] dzData = data[data[, zyg] %in% ifelse(is.null(dzData), "DZ", dzData), ] } else { if ("tbl" %in% class(mzData)) { mzData = as.data.frame(mzData) dzData = as.data.frame(dzData) } } vnames = tvars(c(pheno, prss), sep = sep) xmu_twin_check( selDVs = c(pheno, prss), sep = sep, dzData = dzData, mzData = mzData, enforceSep = TRUE, nSib = 2, optimizer = optimizer ) mzData = xmu_make_mxData(mzData, manifests = vnames) dzData = xmu_make_mxData(dzData, manifests = vnames) x=y=1 if (length(prss)==1) { message("WARNING: still under testing, do not use in your research yet") if (is.null(name)) { name = "MRDoC"} top = mxModel("top", umxMatrix("BE", type = "Full",nrow=3, ncol = 3, labels = c(NA, "g2", "b1", "g1", NA, "b2", NA, NA, NA), free = c(F, F, T, T, F, T, F, F, F)), umxMatrix('I', type='Iden', nrow= 3,ncol= 3 ), umxMatrix('F', type='Full', nrow=5, ncol=6, free=F, values=c(1,0,0,0,0,0, 0,1,0,0,0,0, 0,0,1,0,0,0, 0,0,0,1,0,0, 0,0,0,0,1,0)), umxMatrix('LY', type='Full',nrow=3, ncol = 3, free = F, values = diag(3), labels = NA), umxMatrix('A', type='Symm', nrow=3,ncol = 3, labels=c("ab2","abraas",NA, "abraas","as2",NA, NA,NA,"x2"), free=c(T,T,F, T,T,F, F,F,T)), umxMatrix('C', type='Symm',nrow=3, ncol = 3, labels =c("cb2","cbrccs",NA, "cbrccs","cs2",NA, NA,NA,NA), free=c(T,T,F, T,T,F, F,F,F)), umxMatrix('E', type='Symm', nrow=3, ncol = 3, labels =c("eb2",NA,NA, NA,"es2",NA, NA,NA,NA), free= c(T,F,F, F,T,F, F,F,F)), umxMatrix('dzmu', type='Full', nrow=1, ncol=6, free=T, value=0, labels=c('muPh1','muPh2','muPS1','muPh1','muPh2','muPS1')), mxAlgebra('mzmu', expression = dzmu%*%t(F)), mxAlgebra('A_', expression = solve(I - BE)%&%A), mxAlgebra('C_', expression = solve(I - BE)%&%C), mxAlgebra('E_', expression = solve(I - BE)%&%E), mxAlgebra('SPh', expression= A_ + C_ + E_), mxAlgebra('Smz_', expression=rbind( cbind(SPh,A_+C_), cbind(A_+C_,SPh))), mxAlgebra('Sdz', expression=rbind( cbind(SPh,.5%x%A_+C_), cbind(.5%x%A_+C_,SPh))), mxAlgebra('Smz', expression= F%&%Smz_) ) MZ = mxModel("MZ", mzData, mxExpectationNormal(covariance = "top.Smz",means = "top.mzmu", vnames[1:5]), mxFitFunctionML() ) DZ = mxModel("DZ", dzData, mxExpectationNormal(covariance = "top.Sdz",means = "top.dzmu", vnames), mxFitFunctionML() ) model = mxModel(name, top, MZ, DZ, mxFitFunctionMultigroup(c("MZ","DZ") )) } else if (length(prss)==2) { if (is.null(name)) { name = "MRDoC2"} top = mxModel("top", umxMatrix("BE", type = "Full",nrow=4, ncol = 4, # FROM? X, Y, PRSx, PRSy labels = c(NA, "g2", "b1", "b4", "g1", NA, "b2", "b3", NA, NA, NA, NA, NA, NA, NA, NA), free = c(F, T, T, F, T, F, F, T, F, F, F, F, F, F, F, F)), umxMatrix('I', type='Iden', nrow= 4,ncol= 4 ), umxMatrix('F', type='Full', nrow=6, ncol=8, free=F, values=c(1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,0,1,0,0,0, 0,0,0,0,0,1,0,0)), umxMatrix('LY', type='Full',nrow=4, ncol = 4, free = F, values = diag(4), labels = NA), umxMatrix('A', type='Symm', nrow=4,ncol = 4, labels=c("ab2","abraas",NA,NA, "abraas","as2",NA,NA, NA,NA,"x2","xrfy", NA,NA,"xrfy","y2"), free=c(T,T,F,F, T,T,F,F, F,F,T,T, F,F,T,T)), umxMatrix('C', type='Symm',nrow=4, ncol = 4, labels =c("cb2","cbrccs",NA,NA, "cbrccs","cs2",NA,NA, NA,NA,NA,NA, NA,NA,NA,NA), free=c(T,T,F,F, T,T,F,F, F,F,F,F, F,F,F,F)), umxMatrix('E', type='Symm', nrow=4, ncol = 4, labels =c("eb2","ebrees",NA,NA, "ebrees","es2",NA,NA, NA,NA,NA,NA, NA,NA,NA,NA), free= c(T,T,F,F, T,T,F,F, F,F,F,F, F,F,F,F)), umxMatrix('dzmu', type='Full', nrow=1, ncol=8, free=T, value=0, labels=c('muPh1','muPh2','muPS1','muPS2','muPh1','muPh2','muPS1','muPS2')), mxAlgebra('mzmu', expression = dzmu %*% t(F)), mxAlgebra('A_', expression = solve(I - BE) %&% A), mxAlgebra('C_', expression = solve(I - BE) %&% C), mxAlgebra('E_', expression = solve(I - BE) %&% E), mxAlgebra('SPh', expression= A_ + C_ + E_), mxAlgebra('Smz_', expression=rbind( cbind(SPh,A_+C_), cbind(A_+C_,SPh))), mxAlgebra('Sdz', expression=rbind( cbind(SPh,.5%x%A_+C_), cbind(.5%x%A_+C_,SPh))), mxAlgebra('Smz', expression= F%&%Smz_) ) MZ = mxModel("MZ", mzData, mxExpectationNormal(covariance = "top.Smz",means = "top.mzmu", vnames[1:6]), mxFitFunctionML() ) DZ = mxModel("DZ", dzData, mxExpectationNormal(covariance = "top.Sdz",means = "top.dzmu", vnames), mxFitFunctionML() ) model = mxModel(name, top, MZ, DZ, mxFitFunctionMultigroup(c("MZ","DZ") )) } else { stop("Only 1 or 2 PRSs are supported") } model = mxAutoStart(model) if (tryHard == "yes"){ model=mxTryHard(model) } else { model = mxRun(model) } if (ci == T) model <- umxCI(model, run = "if necessary") model0 <- summary(model, refModels = mxRefModels(model, run = T)) if (ci == T) { model0$parameters |> left_join(model0$CI, by = c("Estimate" = "estimate")) |> select(1,5:6,11:12) |> kable(digits = 3, caption = "Parameter estimates") |> print() } else { model0$parameters |> select(1,5:8) |> kable(digits = 3) |> print() } model0[c("fit", "numObs","degreesOfFreedom", "AIC.Mx", "BIC.Mx", "CFI", "TLI", "optimizerEngine", "RMSEA", "RMSEACI")] |> as_tibble() |> mutate(lower = RMSEACI[1], upper = RMSEACI[2]) |> select(-RMSEACI) |> slice(-2) |> t() |> kable(col.names="", format = "simple", digits = 3, capion = "Model fit") |> print() return(model) } ``` <\details>
mcneale commented 1 year ago

Hi coef() is a handy way to get the list of free parameters from an mxModel.

Cheers Mike

tbates commented 1 year ago

great to see!

A couple of things. For summary, I sketch out the table/plot I want, and work backward to populate that from the model (which is usually just walking over the matrices grabbing the (small for DOC2) set of parameters you want.

But, your model code already generates a small summary: Perhaps pull that into a umxSummary.MxModelDOC2 function and then iterate?

FYI, umx contains no hadleyverse/pipe style code. It's also unsafe to rely on T being TRUE.

Most umx summary models are non-RAM. Look in those to borrow some useful patterns. It those also show how to use umx helpers like umxPrint

Here's a stub summary with roxygen that might work?

#' Present the results of a Direction of Causation Model in table and graphical form
#'
#' Summarizes a Direction of Causation model, as returned by [umxDOC2()]
#'
#' @aliases umxSummary.MxModelDOC2
#' @param model A fitted [umxDOC2()] model to summarize
#' @param digits Round to how many digits (default = 2)
#' @param std Whether to show the standardized model (TRUE) (ignored: used extended = TRUE to get unstandardized)
#' @param CIs Confidence intervals (default FALSE)
#' @param comparison Run mxCompare on a comparison model (default NULL)
#' @param report Print tables to the console (as 'markdown'), or open in browser ('html')
#' @param file The name of the dot file to write: NA = none; "name" = use the name of the model
#' @param ... Optional additional parameters
#' @return - nothing
#' @export
#' @family Summary functions
#' @seealso - \code{\link{umxCP}()}, [plot()], [umxSummary()] work for IP, CP, GxE, SAT, and ACE models.
#' @md
#' @examples
#' # examples here

umxSummary.MxModelDOC2 <- function(model, digits = 2, std = TRUE, CIs = FALSE, comparison = NULL, report = c("markdown", "html"), file = getOption("umx_auto_plot"), ...) {

    if (CIs){ model = umxCI(model, run = "if necessary")}
    model_summary = summary(model, refModels = mxRefModels(model, run = TRUE))

    if (CIs == TRUE) {
        model_summary$parameters |> 
          left_join(model_summary$CI, by = c("Estimate" = "estimate")) |> 
          select(1,5:6,11:12) |> 
          kable(digits = 3, caption = "Parameter estimates") |> 
          print()
    } else {
        model_summary$parameters |>  select(1,5:8) |> kable(digits = 3) |> print()
    }

    model_summary[c("fit", "numObs","degreesOfFreedom", "AIC.Mx", "BIC.Mx", "CFI", "TLI", "optimizerEngine", "RMSEA", "RMSEACI")]   |> as_tibble() |> mutate(lower = RMSEACI[1], upper = RMSEACI[2]) |>
    select(-RMSEACI) |> slice(-2) |> t() |>
    kable(col.names="", format = "simple", digits = 3, capion = "Model fit") |>
    print()
lf-araujo commented 1 year ago

Thanks,

This is exactly what I needed to start on it! Will remove the pipes and try to get as close as I can to usual umx summary output. Best, Luis

tbates commented 1 year ago
#' Present the results of a Direction of Causation Model in table and graphical form
#'
#' Summarizes a Direction of Causation model, as returned by [umxDOC2()]
#'
#' @aliases umxSummary.MxModelDOC2
#' @param model A fitted [umxDOC2()] model to summarize
#' @param digits Round to how many digits (default = 2)
#' @param std Whether to show the standardized model (TRUE) (ignored: used extended = TRUE to get unstandardized)
#' @param CIs Confidence intervals (default FALSE)
#' @param comparison Run mxCompare on a comparison model (default NULL)
#' @param report Print tables to the console (as 'markdown'), or open in browser ('html')
#' @param file The name of the dot file to write: NA = none; "name" = use the name of the model
#' @param ... Optional additional parameters
#' @return - nothing
#' @export
#' @family Summary functions
#' @seealso - \code{\link{umxCP}()}, [plot()], [umxSummary()] work for IP, CP, GxE, SAT, and ACE models.
#' @md
#' @examples
#' # examples here
umxSummary.MxModelDOC2 <- function(model, digits = 2, std = TRUE, CIs = FALSE, comparison = NULL, report = c("markdown", "html"), file = getOption("umx_auto_plot"), ...) {
    if (CIs){ model = umxCI(model, run = "if necessary")}
    model_summary = summary(model, refModels = mxRefModels(model, run = TRUE))

    if (CIs == TRUE) {
        tmp = left_join(model_summary$parameters, model_summary$CI, by = c("Estimate" = "estimate")) 
        tmp = tmp[, c(1, 5:6, 11:12))
    } else {
        tmp = model_summary$parameters
        tmp[, c(1, 5:8))
    }
    umx_print(tmp, digits = digits, zero.print = ".", report =report, caption = "Parameter estimates")

    tmp = model_summary[c("fit", "numObs","degreesOfFreedom", "AIC.Mx", "BIC.Mx", "CFI", "TLI", "optimizerEngine", "RMSEA", "RMSEACI")]
    tmp = as_tibble(tmp)
    tmp = mutate(tmp, lower = RMSEACI[1], upper = RMSEACI[2])
    tmp = select(tmp, -RMSEACI)
    tmp = tmp[-2, ]
    umx_print(tmp, digits = digits, zero.print = ".", report =report, caption = "Model fit")
}
tbates commented 1 year ago

Just fyi for your umxDOC2 model function, umx has support for human-friendly tryHard options, and also uses xmu_safe_run_summary to give error-safe execution (copes with models that fail, supports no-summary mode for simulations).

your_function(tryHard = c( "yes", "no", "ordinal", "search"), summary = !umx_set_silent(silent = TRUE) ){
   tryHard   = match.arg(tryHard)
   model  = xmu_safe_run_summary(model, autoRun = TRUE,  summary = summary, tryHard =  tryHard)
}
lf-araujo commented 1 year ago

Thanks! This was all very useful, and I think I got it!

But still struggling with umx_make(). Asking it for tests did not return errors, but when I try to install the package with the changes it complains of not being able to install srcdir:

> umx_make("~/R/x86_64-solus-linux-gnu-library/4.1/umx",what= "quick_install")
ℹ Updating umx documentation
Warning: Version of roxygen2 last used with this package is 7.1.2.  You only have version 7.1.1
ℹ Loading umx
Writing NAMESPACE
Running /usr/lib64/R/bin/R CMD INSTALL \
  /home/luis/R/x86_64-solus-linux-gnu-library/4.1/umx --install-tests \
  --no-docs --no-multiarch --no-demo 
* installing to library ‘/home/luis/R/x86_64-solus-linux-gnu-library/4.1’
ERROR: cannot install to srcdir for package ‘umx’
* removing ‘/home/luis/R/x86_64-solus-linux-gnu-library/4.1/umx’
Error in (function (command = NULL, args = character(), error_on_status = TRUE,  : 
  System command 'R' failed, exit status: 1, stdout & stderr were printed
Type .Last.error.trace to see where the error occurred
In addition: Warning messages:
1: S3 methods ‘RMSEA.MxModel’, ‘RMSEA.summary.mxmodel’, ‘extractAIC.MxModel’, ‘loadings.MxModel’, ‘loadings.default’, ‘plot.MxLISRELModel’, ‘plot.MxModel’, ‘plot.MxModelACE’, ‘plot.MxModelACEco
v’, ‘plot.MxModelACEv’, ‘plot.MxModelCP’, ‘plot.MxModelDoC’, ‘plot.MxModelGxE’, ‘plot.MxModelGxEbiv’, ‘plot.MxModelIP’, ‘plot.MxModelSexLim’, ‘plot.MxModelSimplex’, ‘plot.MxModelTwinMaker’, ‘pl
ot.MxRAMModel’, ‘plot.percent’, ‘print.RMSEA’, ‘print.money’, ‘print.oddsratio’, ‘print.percent’, ‘print.reliability’, ‘residuals.MxModel’, ‘tmx_show.MxMatrix’, ‘tmx_show.MxModel’, ‘umxReduce.M
xModelACE’, ‘umxReduce.MxModelGxE’, ‘umxReduce.default’, ‘umxRotate.MxModelCP’, ‘umxRotate.default’, ‘umxSummary.MxModel’, ‘umxSummary.MxModelACE’, ‘umxSummary.MxModelACEcov’, ‘umxSummary.MxMod
elACEv’, ‘umxSummary.MxModelCP’, ‘umxSummary.MxModelDoC’, ‘umxSummary.MxM [... truncated] 
2: In setup_ns_exports(path, export_all, export_imports) :
  Objects listed as exports, but not present in namespace: FishersMethod, RMSEA, SE_from_p, bucks, deg2rad, dl_from_dropbox, fin_NI, fin_interest, fin_percent, fin_valuation, geometric_mean, ha
rmonic_mean, install.OpenMx, libs, loadings, namez, noNAs, oddsratio, parameters, power.ACE.test, qm, rad2deg, reliability, summaryAPA, tmx_genotypic_effect, tmx_is.identified, tmx_show, tvars,
 umx2ord, umxACE, umxACEcov, umxACEv, umxAPA, umxAlgebra, umxBrownie, umxCI, umxCI_boot, umxCP, umxCompare, umxConfint, umxCov2cor, umxDiagnose, umxDoC, umxDoCp, umxEFA, umxEquate, umxExamples,
 umxExpCov, umxExpMeans, umxFactanal, umxFactor, umxFactorScores, umxFitIndices, umxFixAll, umxGetLatents, umxGetManifests, umxGetModel, umxGetParameters, umxGxE, umxGxE_window, umxGxEbiv, umxH
etCor, umxIP, umxJiggle, umxLav2RAM, umxMI, umxMR, umxMatrix, umxModel, umxModelNames, umxModify, umxParameters, umxPath, umxPlotACE, umxPlotACEcov, umxPlotACEv, umxPlotCP, umxPlotDoC, umxPlotF
un, umxPlotGxE, umxPlotGxEbiv, umxPlo [... truncated]
lf-araujo commented 1 year ago

Nevermind, too dumb to figure out that I should have passed the umx folder I was working in! LOL.

Ok, so the function is done, together with a nice umxSummary report. Very useful to learn how S3 works, thanks for the help! No test unit in this PR, although I run the tests and the changes did not introduce new problems it seems.

Thanks again!

tbates commented 1 year ago

Looks like a permission problems in srcdir?

lf-araujo commented 1 year ago

Yes, I figured out what I was doing incorrectly. Also, forgot to link the PR https://github.com/tbates/umx/pull/211

tbates commented 1 year ago

I should add a link to this when umx_make() is called with a bad directory :-)

But probably should also make the users preferred directory sticky with a preference setting. It's hard because most people don't use R startup scripts which are as far as I can tell the only place to store customisable stuff like that.

Maybe if the error says Call umx_set_umx_loc("~/my/path/to/umx" to store location of your umx development directory