Skip to content

Commit 9db01b4

Browse files
Subset matrices to smallest in com2links
com2links now selects the smallest provided relationship matrix (by column count) as the ID guide, extracts IDs from it, and subsets any larger matrices to that ID set and ordering. Adds error checks when no matrices or IDs are available and emits verbose messages when subsetting. Includes unit tests covering mismatched-dimension scenarios and updates NEWS.md to document the fix.
1 parent 2865017 commit 9db01b4

3 files changed

Lines changed: 114 additions & 12 deletions

File tree

NEWS.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* Optimized sliceFamilies to be more abstract
66
* Created `.require_openmx()` to make it easier to use OpenMx functions without making OpenMx a dependency
77
* Smarter string ID handling for ped2id
8-
8+
* fixed how different sized matrixes are handled by build links
99

1010
# BGmisc 1.7.0.0
1111
* Fixed bug in parList

R/makeLinks.R

Lines changed: 34 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -79,22 +79,45 @@ com2links <- function(
7979

8080
# Extract individual IDs from the first available matrix.
8181
ids <- NULL
82+
# Find the smallest matrix by ncol (avoids extracting IDs from large matrices).
83+
mat_refs <- list()
84+
if (!is.null(ad_ped_matrix)) mat_refs[["ad"]] <- ncol(ad_ped_matrix)
85+
if (!is.null(mit_ped_matrix)) mat_refs[["mt"]] <- ncol(mit_ped_matrix)
86+
if (!is.null(cn_ped_matrix)) mat_refs[["cn"]] <- ncol(cn_ped_matrix)
87+
88+
if (length(mat_refs) == 0L) {
89+
stop("At least one relationship matrix must be provided.")
90+
}
8291

92+
smallest <- names(which.min(unlist(mat_refs)))
93+
guide_mat <- switch(smallest,
94+
ad = ad_ped_matrix,
95+
mt = mit_ped_matrix,
96+
cn = cn_ped_matrix
97+
)
8398

84-
if (!is.null(cn_ped_matrix)) {
85-
ids <- as.numeric(dimnames(cn_ped_matrix)[[1]])
86-
nc <- ncol(cn_ped_matrix)
87-
} else if (!is.null(ad_ped_matrix)) {
88-
ids <- as.numeric(dimnames(ad_ped_matrix)[[1]])
89-
nc <- ncol(ad_ped_matrix)
90-
} else if (!is.null(mit_ped_matrix)) {
91-
ids <- as.numeric(dimnames(mit_ped_matrix)[[1]])
92-
nc <- ncol(mit_ped_matrix)
99+
# Extract IDs only from the smallest matrix.
100+
guide_ids <- dimnames(guide_mat)[[1]]
101+
if (is.null(guide_ids) || length(guide_ids) == 0L) {
102+
stop("Could not extract IDs from the smallest matrix.")
93103
}
104+
ids <- as.numeric(guide_ids)
105+
nc <- length(ids)
94106

95-
if (is.null(ids)) {
96-
stop("Could not extract IDs from the provided matrices.")
107+
# Subset only the larger matrices to match the smallest matrix's IDs and ordering.
108+
if (!is.null(ad_ped_matrix) && ncol(ad_ped_matrix) > nc) {
109+
if (verbose) message("Subsetting ad_ped_matrix from ", ncol(ad_ped_matrix), " to ", nc, " IDs.")
110+
ad_ped_matrix <- ad_ped_matrix[guide_ids, guide_ids, drop = FALSE]
97111
}
112+
if (!is.null(mit_ped_matrix) && ncol(mit_ped_matrix) > nc) {
113+
if (verbose) message("Subsetting mit_ped_matrix from ", ncol(mit_ped_matrix), " to ", nc, " IDs.")
114+
mit_ped_matrix <- mit_ped_matrix[guide_ids, guide_ids, drop = FALSE]
115+
}
116+
if (!is.null(cn_ped_matrix) && ncol(cn_ped_matrix) > nc) {
117+
if (verbose) message("Subsetting cn_ped_matrix from ", ncol(cn_ped_matrix), " to ", nc, " IDs.")
118+
cn_ped_matrix <- cn_ped_matrix[guide_ids, guide_ids, drop = FALSE]
119+
}
120+
98121

99122
# --- matrix_case construction and switch dispatch ---
100123
matrix_case <- paste(sort(c(

tests/testthat/test-makeLinks.R

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,3 +324,82 @@ test_that("com2links garbage collection does not affect output, using two compon
324324

325325
expect_equal(result_gc, result_no_gc)
326326
})
327+
328+
329+
test_that("com2links handles mismatched matrix dimensions by subsetting to smallest", {
330+
data(hazard)
331+
subset_ids <- hazard$ID[seq_len(ceiling(nrow(hazard) / 2))]
332+
333+
ad_small <- ped2add(hazard, sparse = TRUE, keep_ids = subset_ids)
334+
mit_ped_matrix <- ped2mit(hazard, sparse = TRUE)
335+
cn_ped_matrix <- ped2cn(hazard, sparse = TRUE)
336+
337+
# All three matrices, ad is smaller
338+
result_mismatch <- com2links(
339+
ad_ped_matrix = ad_small,
340+
mit_ped_matrix = mit_ped_matrix,
341+
cn_ped_matrix = cn_ped_matrix,
342+
writetodisk = FALSE
343+
)
344+
345+
# Reference: all three matrices built from the same subset
346+
result_ref <- com2links(
347+
ad_ped_matrix = ad_small,
348+
mit_ped_matrix = ped2mit(hazard, sparse = TRUE, keep_ids = subset_ids),
349+
cn_ped_matrix = ped2cn(hazard, sparse = TRUE, keep_ids = subset_ids),
350+
writetodisk = FALSE
351+
)
352+
353+
expect_equal(result_mismatch, result_ref)
354+
355+
# Only IDs from the smaller matrix should appear
356+
all_output_ids <- unique(c(result_mismatch$ID1, result_mismatch$ID2))
357+
expect_true(all(all_output_ids %in% as.numeric(dimnames(ad_small)[[1]])))
358+
})
359+
360+
test_that("com2links mismatched dimensions with two matrices", {
361+
data(hazard)
362+
subset_ids <- hazard$ID[seq_len(ceiling(nrow(hazard) / 2))]
363+
364+
ad_ped_matrix <- ped2add(hazard, sparse = TRUE)
365+
cn_small <- ped2cn(hazard, sparse = TRUE, keep_ids = subset_ids)
366+
367+
# cn is smaller than ad
368+
result_mismatch <- com2links(
369+
ad_ped_matrix = ad_ped_matrix,
370+
cn_ped_matrix = cn_small,
371+
writetodisk = FALSE
372+
)
373+
374+
result_ref <- com2links(
375+
ad_ped_matrix = ped2add(hazard, sparse = TRUE, keep_ids = subset_ids),
376+
cn_ped_matrix = cn_small,
377+
writetodisk = FALSE
378+
)
379+
380+
expect_equal(result_mismatch, result_ref)
381+
})
382+
383+
test_that("com2links mismatched dimensions with mit smaller", {
384+
data(hazard)
385+
subset_ids <- hazard$ID[seq_len(ceiling(nrow(hazard) / 2))]
386+
387+
ad_ped_matrix <- ped2add(hazard, sparse = TRUE)
388+
mit_small <- ped2mit(hazard, sparse = TRUE, keep_ids = subset_ids)
389+
390+
result_mismatch <- com2links(
391+
ad_ped_matrix = ad_ped_matrix,
392+
mit_ped_matrix = mit_small,
393+
writetodisk = FALSE
394+
)
395+
396+
result_ref <- com2links(
397+
ad_ped_matrix = ped2add(hazard, sparse = TRUE, keep_ids = subset_ids),
398+
mit_ped_matrix = mit_small,
399+
writetodisk = FALSE
400+
)
401+
402+
expect_equal(result_mismatch, result_ref)
403+
expect_true(all(unique(c(result_mismatch$ID1, result_mismatch$ID2)) %in% as.numeric(dimnames(mit_small)[[1]])))
404+
expect_true(all(unique(c(result_mismatch$ID1, result_mismatch$ID2)) %in% as.numeric(dimnames(ad_ped_matrix)[[1]])))
405+
})

0 commit comments

Comments
 (0)