1+ library(SeuratObject )
2+ library(Matrix )
3+
14suppressWarnings(RNGversion(vstr = " 3.5.3" ))
25
6+ # LSI / RunTFIDF reference values ---------------------------------------------
7+
38test_that(" LSI works" , {
49 set.seed(seed = 1 )
510 mat <- matrix (data = rbinom(n = 25 , size = 5 , prob = 0.2 ), nrow = 5 )
@@ -23,10 +28,7 @@ test_that("LSI works", {
2328 expected = c(0.000000 , 5.516015 , 0.000000 , 4.943317 , 6.103178 ),
2429 tolerance = 1 / 1000
2530 )
26- expect_equal(
27- object = method4 [1 , ],
28- expected = c(0 , 2 , 0 , 1 , 2 )
29- )
31+ expect_equal(object = method4 [1 , ], expected = c(0 , 2 , 0 , 1 , 2 ))
3032
3133 lsi <- suppressWarnings(RunSVD(object = mat ))
3234 embeddings <- SeuratObject :: Embeddings(object = lsi )
@@ -44,9 +46,162 @@ test_that("LSI works", {
4446 )
4547})
4648
49+ # Jaccard ----------------------------------------------------------------------
50+
4751test_that(" Jaccard works" , {
4852 set.seed(1 )
49- mat <- matrix (data = sample(x = c(0 , 1 ), size = 25 , replace = TRUE ), nrow = 5 )
53+ mat <- matrix (
54+ data = sample(x = c(0 , 1 ), size = 25 , replace = TRUE ),
55+ nrow = 5
56+ )
5057 jm <- Jaccard(x = mat , y = mat )
5158 expect_equal(object = jm [1 , ], expected = c(1 , 1 / 3 , 2 / 5 , 1 / 3 , 0 ))
5259})
60+
61+ test_that(" Jaccard computes a matrix between two matrices" , {
62+ set.seed(1 )
63+ X <- matrix (sample(c(0 , 1 ), 100 , replace = TRUE ), 10 , 10 )
64+ Y <- matrix (sample(c(0 , 1 ), 100 , replace = TRUE ), 10 , 10 )
65+ res <- Jaccard(X , Y )
66+ expect_equal(dim(res ), c(10 , 10 ))
67+ })
68+
69+ test_that(" Jaccard warns on values > 1" , {
70+ X <- matrix (sample(0 : 3 , 100 , replace = TRUE ), 10 , 10 )
71+ Y <- matrix (sample(0 : 3 , 100 , replace = TRUE ), 10 , 10 )
72+ expect_warning(Jaccard(X , Y ), regexp = " binarize" )
73+ })
74+
75+ # RunSVD -----------------------------------------------------------------------
76+
77+ test_that(" RunSVD on matrix returns DimReduc" , {
78+ set.seed(1 )
79+ m <- matrix (rnorm(500 ), nrow = 50 , ncol = 10 )
80+ res <- RunSVD(m , n = 5 , verbose = FALSE )
81+ expect_s4_class(res , " DimReduc" )
82+
83+ embeddings <- Embeddings(object = res )
84+ # one row per column (cell) of the input, one column per requested component
85+ expect_equal(object = dim(embeddings ), expected = c(10 , 5 ))
86+ expect_equal(object = Key(object = res ), expected = " LSI_" )
87+ expect_equal(
88+ object = colnames(embeddings ),
89+ expected = paste0(" LSI_" , 1 : 5 )
90+ )
91+ # default scale.embeddings = TRUE => each component has mean 0, SD 1
92+ expect_equal(
93+ object = unname(apply(X = embeddings , MARGIN = 2 , FUN = mean )),
94+ expected = rep(0 , 5 ),
95+ tolerance = 1 / 1000
96+ )
97+ expect_equal(
98+ object = unname(apply(X = embeddings , MARGIN = 2 , FUN = sd )),
99+ expected = rep(1 , 5 ),
100+ tolerance = 1 / 1000
101+ )
102+ expect_equal(
103+ object = as.vector(embeddings [1 , ]),
104+ expected = c(- 1.2330585 , 0.2963341 , - 0.0124394 , - 0.9656036 , 0.5545593 ),
105+ tolerance = 1 / 1000
106+ )
107+ })
108+
109+ test_that(" RunSVD with pca = TRUE works" , {
110+ set.seed(1 )
111+ m <- matrix (rnorm(500 ), nrow = 50 , ncol = 10 )
112+ res <- RunSVD(m , n = 5 , pca = TRUE , verbose = FALSE )
113+ expect_s4_class(res , " DimReduc" )
114+
115+ # pca = TRUE uses the PCA_ key (not LSI_)
116+ expect_equal(object = Key(object = res ), expected = " PCA_" )
117+
118+ emb.pca <- Embeddings(object = res )
119+ expect_equal(object = dim(emb.pca ), expected = c(10 , 5 ))
120+ expect_equal(
121+ object = colnames(emb.pca ),
122+ expected = paste0(" PCA_" , 1 : 5 )
123+ )
124+
125+ # The pca branch weights embeddings by eigenvalues and does NOT scale them
126+ # to unit variance, so the result must differ from pca = FALSE. If pca were
127+ # ignored these embeddings would equal the scaled (unit-variance) LSI result.
128+ set.seed(1 )
129+ m2 <- matrix (rnorm(500 ), nrow = 50 , ncol = 10 )
130+ res.lsi <- RunSVD(m2 , n = 5 , pca = FALSE , verbose = FALSE )
131+ emb.lsi <- Embeddings(object = res.lsi )
132+
133+ expect_false(
134+ isTRUE(all.equal(
135+ target = unname(emb.pca ),
136+ current = unname(emb.lsi ),
137+ tolerance = 1 / 1000
138+ ))
139+ )
140+ # unscaled, eigenvalue-weighted: component SDs are not all 1
141+ expect_false(
142+ isTRUE(all.equal(
143+ target = unname(apply(X = emb.pca , MARGIN = 2 , FUN = sd )),
144+ current = rep(1 , 5 ),
145+ tolerance = 1 / 1000
146+ ))
147+ )
148+ expect_equal(
149+ object = as.vector(emb.pca [1 , ]),
150+ expected = c(- 1.2143982 , 0.4486555 , - 0.2778468 , - 0.3807493 , - 0.6286513 ),
151+ tolerance = 1 / 1000
152+ )
153+ })
154+
155+ test_that(" RunSVD with scale.max clipping works" , {
156+ set.seed(1 )
157+ m <- matrix (rnorm(500 ), nrow = 50 , ncol = 10 )
158+
159+ # without clipping the embeddings exceed 0.5 in magnitude, so a scale.max
160+ # of 0.5 must actually clip them
161+ res.unclipped <- RunSVD(m , n = 5 , verbose = FALSE )
162+ expect_gt(max(abs(Embeddings(object = res.unclipped ))), 0.5 )
163+
164+ res <- RunSVD(m , n = 5 , scale.max = 0.5 , verbose = FALSE )
165+ expect_s4_class(res , " DimReduc" )
166+
167+ embeddings <- Embeddings(object = res )
168+ expect_equal(object = dim(embeddings ), expected = c(10 , 5 ))
169+ # clipping bound is respected
170+ expect_lte(max(abs(embeddings )), 0.5 )
171+ # and clipping actually bit (some values were pushed to the bound)
172+ expect_equal(object = max(abs(embeddings )), expected = 0.5 )
173+ })
174+
175+ test_that(" RunSVD on Seurat returns updated Seurat" , {
176+ obj <- atac_small
177+ VariableFeatures(obj ) <- rownames(obj [[" peaks" ]])
178+ res <- RunSVD(obj , n = 5 , verbose = FALSE )
179+ expect_s4_class(res , " Seurat" )
180+ expect_true(" lsi" %in% names(res @ reductions ))
181+
182+ embeddings <- Embeddings(object = res , reduction = " lsi" )
183+ # one row per cell, one column per requested component
184+ expect_equal(object = dim(embeddings ), expected = c(ncol(obj ), 5 ))
185+ expect_equal(object = Key(object = res [[" lsi" ]]), expected = " LSI_" )
186+ expect_equal(
187+ object = as.vector(embeddings [1 , ]),
188+ expected = c(- 0.9426501 , 1.0001435 , 0.7316286 , 0.4466094 , 0.1253871 ),
189+ tolerance = 1 / 1000
190+ )
191+ })
192+
193+ test_that(" RunSVD on assay returns DimReduc" , {
194+ a <- atac_small [[" peaks" ]]
195+ VariableFeatures(a ) <- rownames(a )
196+ res <- RunSVD(a , n = 5 , verbose = FALSE )
197+ expect_s4_class(res , " DimReduc" )
198+
199+ embeddings <- Embeddings(object = res )
200+ expect_equal(object = dim(embeddings ), expected = c(ncol(a ), 5 ))
201+ expect_equal(object = Key(object = res ), expected = " LSI_" )
202+ expect_equal(
203+ object = as.vector(embeddings [1 , ]),
204+ expected = c(- 0.9426501 , 1.0001435 , 0.7316286 , 0.4466094 , 0.1253871 ),
205+ tolerance = 1 / 1000
206+ )
207+ })
0 commit comments