Skip to content

Commit b3710d3

Browse files
committed
Merge branch 'devel'
2 parents bdecaeb + 0c73279 commit b3710d3

8 files changed

Lines changed: 47 additions & 54 deletions

File tree

DESCRIPTION

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
Package: miloR
22
Type: Package
33
Title: Differential neighbourhood abundance testing on a graph
4-
Version: 2.5.1
4+
Version: 2.5.2
55
Authors@R:
66
c(person("Mike", "Morgan", role=c("aut", "cre"), email="michael.morgan@abdn.ac.uk",
77
comment=c(ORCID="0000-0003-0757-0711")),
@@ -15,9 +15,7 @@ URL: https://marionilab.github.io/miloR
1515
BugReports: https://github.com/MarioniLab/miloR/issues
1616
biocViews: SingleCell, MultipleComparison, FunctionalGenomics, Software
1717
LinkingTo: Rcpp,
18-
RcppArmadillo,
19-
RcppEigen,
20-
RcppML
18+
RcppArmadillo
2119
Depends: R (>= 4.0.0),
2220
edgeR
2321
Imports: BiocNeighbors,

NAMESPACE

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ importFrom(BiocParallel,bpstopOnError)
9797
importFrom(BiocParallel,bptry)
9898
importFrom(BiocSingular,bsparam)
9999
importFrom(Matrix,Matrix)
100+
importFrom(Matrix,chol)
100101
importFrom(Matrix,colSums)
101102
importFrom(Matrix,crossprod)
102103
importFrom(Matrix,diag)

R/glmm.R

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@
7676
#' @name fitGLMM
7777
#'
7878
#' @importMethodsFrom Matrix %*%
79-
#' @importFrom Matrix Matrix solve crossprod kronecker
79+
#' @importFrom Matrix Matrix solve crossprod kronecker chol
8080
#' @importFrom stats runif var
8181
#' @importFrom BiocParallel bpstopOnError
8282
#' @export
@@ -131,7 +131,10 @@ fitGLMM <- function(X, Z, y, offsets, init.theta=NULL, Kin=NULL,
131131
}
132132

133133
# create full Z with expanded random effect levels
134+
# add a residual variance parameter
134135
full.Z <- initializeFullZ(Z=Z, cluster_levels=random.levels)
136+
# random.levels <- c(random.levels, list("Residual"=rownames(Z)))
137+
135138
if(is.null(glmm.control[["init.u"]])){
136139
curr_u <- matrix(runif(ncol(full.Z), 0, 1), ncol=1)
137140
} else{
@@ -172,13 +175,18 @@ fitGLMM <- function(X, Z, y, offsets, init.theta=NULL, Kin=NULL,
172175
} else{
173176
curr_sigma <- Matrix(glmm.control[["init.sigma"]], ncol=1, sparse=TRUE)
174177
}
175-
rownames(curr_sigma) <- colnames(Z)
178+
179+
rownames(curr_sigma) <- names(random.levels)
176180

177181
## add the genetic components
178182
## augment Z with I
179-
geno.I <- diag(nrow(full.Z))
183+
## Use K=LD^1/2(LD^1/2)^T instead of ZZ^T for GRM
184+
## chol return L^T
185+
geno.I <- t(chol(Kin))
186+
# geno.I <- diag(nrow(full.Z))
180187
colnames(geno.I) <- paste0("CovarMat", seq_len(ncol(geno.I)))
181188
full.Z <- do.call(cbind, list(full.Z, geno.I))
189+
182190
# add a genetic variance component
183191
sigma_g <- Matrix(runif(1, 0, 1), ncol=1, nrow=1, sparse=TRUE)
184192
rownames(sigma_g) <- "CovarMat"
@@ -201,7 +209,10 @@ fitGLMM <- function(X, Z, y, offsets, init.theta=NULL, Kin=NULL,
201209

202210
# if we only have a GRM then Z _is_ full.Z?
203211
# full.Z <- initializeFullZ(Z, cluster_levels=random.levels)
204-
full.Z <- Z
212+
## Use K=LD^1/2(LD^1/2)^T instead of ZZ^T for GRM
213+
## chol return L^T
214+
full.Z <- t(chol(Kin))
215+
# full.Z <- Z
205216
# should this be the matrix R?
206217
colnames(full.Z) <- paste0(names(random.levels), seq_len(ncol(full.Z)))
207218

@@ -255,6 +266,7 @@ fitGLMM <- function(X, Z, y, offsets, init.theta=NULL, Kin=NULL,
255266
} else if(is.null(Kin)){
256267
# create full Z with expanded random effect levels
257268
full.Z <- initializeFullZ(Z=Z, cluster_levels=random.levels)
269+
# random.levels <- c(random.levels, list("Residual"=rownames(Z)))
258270

259271
# random value initiation from runif
260272
if(is.null(glmm.control[["init.u"]])){
@@ -456,7 +468,7 @@ initialiseG <- function(cluster_levels, sigmas, Kin=NULL){
456468
diag(G[c(i:(i+x.q-1)), c(i:(i+x.q-1)), drop=FALSE]) <- sigmas[x, ] # is this sufficient to transform the sigma to the model scale?
457469
} else{
458470
if(rownames(sigmas[x, , drop=FALSE]) %in% c("Genetic")){
459-
diag(G[c(i:(i+x.q-1)), c(i:(i+x.q-1)), drop=FALSE]) <- sigmas[x, ] * Kin
471+
diag(G[c(i:(i+x.q-1)), c(i:(i+x.q-1)), drop=FALSE]) <- sigmas[x, ] #* Kin
460472
}else{
461473
diag(G[c(i:(i+x.q-1)), c(i:(i+x.q-1)), drop=FALSE]) <- sigmas[x, ] # is this sufficient to transform the sigma to the model scale?
462474
}
@@ -565,7 +577,12 @@ initializeFullZ <- function(Z, cluster_levels, stand.cols=FALSE){
565577

566578
i.z.list[[colnames(Z)[i]]] <- i.z
567579
}
580+
# # Add the residual variance
581+
# resid.eye <- diag(nrow(Z))
582+
# colnames(resid.eye) <- rownames(Z)
583+
# i.z.list[["Residual"]] <- resid.eye
568584
full.Z <- do.call(cbind, i.z.list)
585+
569586
return(full.Z)
570587
}
571588

R/testNhoods.R

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -539,7 +539,7 @@ testNhoods <- function(x, design, design.df, kinship=NULL,
539539
if(isTRUE(geno.only)){
540540
message("Running genetic model with ", nrow(kinship), " individuals")
541541
} else{
542-
message("Running genetic model with ", nrow(z.model), " observations")
542+
message("Running genetic+ model with ", nrow(z.model), " observations")
543543
}
544544
}
545545

src/paramEst.cpp

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
#include "paramEst.h"
33
#include "computeMatrices.h"
44
#include "utils.h"
5-
#include "solveQP.h"
65
#include<RcppArmadillo.h>
76
#ifdef _OPENMP
87
#include <omp.h>
@@ -358,8 +357,7 @@ arma::vec estHasemanElstonConstrained(const arma::mat& Z, const arma::mat& PREML
358357
// solve by linear least squares
359358
arma::vec _he_update(c+1);
360359

361-
// use RcppML NNLS (needs casting Eigen <-> arma)
362-
// _he_update = solveQP(vecZ, Ybig, _he_update);
360+
// Tried RcppML NNLS but arma <> eigen cast is too expensive
363361
_he_update = nnlsSolve(vecZ, Ybig, _he_update, Iters);
364362

365363
return _he_update;
@@ -390,7 +388,6 @@ arma::vec estHasemanElstonConstrainedML(const arma::mat& Z, const Rcpp::List& u_
390388

391389
// solve by linear least squares
392390
arma::vec _he_update(c+1);
393-
// _he_update = solveQP(vecZ, Ybig, _he_update);
394391
_he_update = nnlsSolve(vecZ, Ybig, _he_update, Iters);
395392

396393
return _he_update;
@@ -424,7 +421,6 @@ arma::vec estHasemanElstonConstrainedGenetic(const arma::mat& Z, const arma::mat
424421
arma::mat vecZ = vectoriseZGenetic(Z, u_indices, PREML, PZ, Kin); // projection already applied
425422

426423
arma::vec _he_update(c+1);
427-
// _he_update = solveQP(vecZ, Ybig, _he_update);
428424
_he_update = nnlsSolve(vecZ, Ybig, _he_update, Iters);
429425

430426
return _he_update;
@@ -455,11 +451,10 @@ arma::vec estHasemanElstonConstrainedGeneticML(const arma::mat& Z,
455451
arma::mat vecZ = vectoriseZGeneticML(Z, u_indices, Kin); // projection already applied
456452

457453
arma::vec _he_update(c+1);
458-
// _he_update = solveQP(vecZ, Ybig, _he_update);
459454
_he_update = nnlsSolve(vecZ, Ybig, _he_update, Iters);
460455

461-
return _he_update;
462-
}
456+
return _he_update;}
457+
463458

464459

465460
arma::vec nnlsSolve(const arma::mat& vecZ, const arma::vec& Y, arma::vec nnls_update, const int& Iters){
@@ -700,7 +695,12 @@ arma::mat vectoriseZGenetic(const arma::mat& Z, const Rcpp::List& u_indices,
700695

701696
// always set the last component to the genetic variance if there is a kinship matrix
702697
if(i == c-1){
703-
arma::vec _vecZ = Kin(lower_indices);
698+
// arma::vec _vecZ = Kin(lower_indices);
699+
// Cholesky LL^T of kinship == ZZ^T
700+
arma::mat _ZZT = PZ.cols(u_idx - 1) * Z.cols(u_idx - 1).t() * P.t(); // REML projection
701+
702+
// vectorise
703+
arma::vec _vecZ = _ZZT(lower_indices);
704704
vecMat.col(i+1) = _vecZ;
705705
// vecMat.col(i) = _vecZ;
706706
} else{
@@ -741,7 +741,12 @@ arma::mat vectoriseZGeneticML(const arma::mat& Z, const Rcpp::List& u_indices,
741741

742742
// always set the last component to the genetic variance if there is a kinship matrix
743743
if(i == c-1){
744-
arma::vec _vecZ = Kin(lower_indices);
744+
// arma::vec _vecZ = Kin(lower_indices);
745+
// Cholesky LL^T of kinship == ZZ^T
746+
arma::mat _ZZT = Z.cols(u_idx - 1) * Z.cols(u_idx - 1).t();
747+
748+
// vectorise
749+
arma::vec _vecZ = _ZZT(lower_indices);
745750
vecMat.col(i+1) = _vecZ;
746751
// vecMat.col(i) = _vecZ;
747752
} else{

src/pseudovarPartial.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,8 @@ List computePZList_G(const List& u_indices, const arma::mat& PZ, const arma::mat
7575
arma::mat _pzz(n, n);
7676

7777
if(i == c - 1){
78-
_pzz = PZ.cols(u_idx-1) * K * Z.cols(u_idx-1).t(); // convert 1-based to 0-based
78+
// _pzz = PZ.cols(u_idx-1) * K * Z.cols(u_idx-1).t(); // convert 1-based to 0-based
79+
_pzz = PZ.cols(u_idx-1) * Z.cols(u_idx-1).t(); // convert 1-based to 0-based
7980
} else{
8081
_pzz = PZ.cols(u_idx-1) * Z.cols(u_idx-1).t(); // convert 1-based to 0-based
8182
}
@@ -160,7 +161,8 @@ List pseudovarPartial_VG(const List& u_indices, const arma::mat& Z, const arma::
160161
arma::mat Zcols = Z.cols(u_idx-1).t();
161162

162163
if(i == c - 1){
163-
omat = VstarZ.cols(u_idx-1) * K * Zcols;
164+
//omat = VstarZ.cols(u_idx-1) * K * Zcols;
165+
omat = VstarZ.cols(u_idx-1) * Zcols;
164166
} else{
165167
omat = VstarZ.cols(u_idx-1) * Zcols;
166168
}
@@ -181,7 +183,8 @@ List pseudovarPartial_G(arma::mat Z, const arma::mat& K, List u_indices){
181183
for(unsigned int i = 0; i < items; i++){
182184
if(i == items - 1){
183185
arma::uvec icols = u_indices[i];
184-
arma::mat _omat(Z.cols(icols - 1) * K * Z.cols(icols - 1).t());
186+
// arma::mat _omat(Z.cols(icols - 1) * K * Z.cols(icols - 1).t());
187+
arma::mat _omat(K);
185188
outlist[i] = _omat; // K is equivalent to ZZ^T
186189
} else{
187190
arma::uvec icols = u_indices[i];

src/solveQP.cpp

Lines changed: 0 additions & 23 deletions
This file was deleted.

src/solveQP.h

Lines changed: 0 additions & 8 deletions
This file was deleted.

0 commit comments

Comments
 (0)