Hello, I am analysing Huprot protein microarray data using limma, and I am trying to perform print-tip normalisation. I used both IgG and IgA secondary antibodies in a two-channel experiment. I am encountering the error "printer layout information does not match M row dimension" when I try to run
> MA<-normalizeWithinArrays(RG).
The issue seems to be with the printer layout. After checking one of the gpr files, I found that I have 20 blocks, 32 columns and 92 rows- giving a total of 52736 spots. However, the printer layout differs across blocks: blocks 1 to 16 contain 2944 spots each, while blocks 17 to 20 contain 1408 spots each. As a result, the current layout configuration gives more spots (58,880) than are currently present (52,736).
> dim(RG)
[1] 52736 95
> RG$printer$ngrid.r # Rows in the layout grid
[1] 5
> RG$printer$ngrid.c # Columns in the layout grid
[1] 4
> RG$printer$nspot.r # Number of spots per row
[1] 92
> RG$printer$nspot.c # Number of spots per column
[1] 32
Total spots=ngrid.r×ngrid.c×nspot.r×nspot.c=5×4×92×32=58,880. Based on this information I should have 58 880 spots, which is incorrect (52736 spots is correct).
MA<-normalizeWithinArrays(RG)
Error in normalizeWithinArrays(RG) :
printer layout information does not match M row dimension
> spots_per_block <- c(rep(2944, 16), rep(1408, 4))
>
> # Verify the total number of spots is correct
> total_spots <- sum(spots_per_block)
> total_spots
[1] 52736
> # Define the layout for the first 16 blocks (22 rows x 22 columns)
> layout1 <- list(ngrid.r = 12, # 12 grid rows
+ ngrid.c = 4, # 4 grid columns
+ nspot.r = 22, # 22 rows per block
+ nspot.c = 22) # 22 columns per block
>
> # Define the layout for blocks 17-20 (16 rows x 22 columns)
> layout2 <- list(ngrid.r = 4, # 4 grid rows
+ ngrid.c = 4, # 4 grid columns
+ nspot.r = 16, # 16 rows per block
+ nspot.c = 22) # 22 columns per block
>
> # Manually assign the correct layout for each block
> RG$printer$layout[1:16] <- layout1 # For blocks 1 to 16 (22x22 spots)
> RG$printer$layout[17:20] <- layout2 # For blocks 17 to 20 (16x22 spots)
>
> # Create a layout vector for all blocks
> layout_full <- rep(list(list(ngrid.r = 12, ngrid.c = 4, nspot.r = 22, nspot.c = 22)), 16) # Blocks 1 to 16
> layout_full <- c(layout_full, rep(list(list(ngrid.r = 4, ngrid.c = 4, nspot.r = 16, nspot.c = 22)), 4)) # Blocks 17 to 20
>
> RG$printer$layout <- layout_full
>
> # Apply print-tip loess normalization
> MA <- normalizeWithinArrays(RG, layout = RG$printer$layout, method = "printtiploess")
Error in if (nprobes2 != nprobes) stop("printer layout information does not match M row dimension") :
argument is of length zero
> printer <- list(ngrid.r=5, ngrid.c=4, nspot.r=92, nspot.c=c(rep(32, 16), rep(16, 4)))
> MA <- normalizeWithinArrays(RG, layout=printer)
Error in if (nprobes2 != nprobes) stop("printer layout information does not match M row dimension") :
the condition has length > 1
Any help would be greatly appreciated!
> sessionInfo( )
R version 4.3.1 (2023-06-16 ucrt)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows 10 x64 (build 19045)
Matrix products: default
locale:
[1] LC_COLLATE=English_Australia.utf8 LC_CTYPE=English_Australia.utf8 LC_MONETARY=English_Australia.utf8
[4] LC_NUMERIC=C LC_TIME=English_Australia.utf8
time zone: Australia
tzcode source: internal
attached base packages:
[1] grid stats4 stats graphics grDevices utils datasets methods base
other attached packages:
[1] vsn_3.68.0 edgeR_3.42.4 limma_3.56.2 genomation_1.32.0 methylKit_1.26.0
[6] GenomicRanges_1.52.1 GenomeInfoDb_1.36.4 IRanges_2.34.1 S4Vectors_0.38.2 affy_1.78.2
[11] Biobase_2.60.0 BiocGenerics_0.46.0
loaded via a namespace (and not attached):
[1] bitops_1.0-7 pROC_1.18.4 rlang_1.1.1 magrittr_2.0.3
[5] gridBase_0.4-7 matrixStats_1.2.0 compiler_4.3.1 vctrs_0.6.3
[9] reshape2_1.4.4 stringr_1.5.1 pkgconfig_2.0.3 crayon_1.5.3
[13] XVector_0.40.0 labeling_0.4.3 utf8_1.2.3 Rsamtools_2.16.0
[17] tzdb_0.4.0 preprocessCore_1.62.1 zlibbioc_1.46.0 DelayedArray_0.26.7
[21] BiocParallel_1.34.2 parallel_4.3.1 R6_2.5.1 stringi_1.8.3
[25] rtracklayer_1.60.1 numDeriv_2016.8-1.1 Rcpp_1.0.11 SummarizedExperiment_1.30.2
[29] R.utils_2.12.3 readr_2.1.5 Matrix_1.6-5 splines_4.3.1
[33] tidyselect_1.2.1 qvalue_2.32.0 rstudioapi_0.16.0 abind_1.4-5
[37] yaml_2.3.8 seqPattern_1.32.0 codetools_0.2-19 lattice_0.21-8
[41] tibble_3.2.1 plyr_1.8.8 withr_3.0.1 coda_0.19-4.1
[45] mclust_6.1.1 Biostrings_2.68.1 pillar_1.9.0 affyio_1.70.0
[49] BiocManager_1.30.22 MatrixGenerics_1.12.3 KernSmooth_2.23-21 generics_0.1.3
[53] RCurl_1.98-1.14 emdbook_1.3.13 hms_1.1.3 ggplot2_3.5.1
[57] munsell_0.5.1 scales_1.3.0 gtools_3.9.5 glue_1.6.2
[61] tools_4.3.1 BiocIO_1.10.0 hexbin_1.28.3 data.table_1.15.4
[65] BSgenome_1.68.0 locfit_1.5-9.8 GenomicAlignments_1.36.0 mvtnorm_1.2-5
[69] XML_3.99-0.16.1 impute_1.74.1 plotrix_3.8-4 bbmle_1.0.25.1
[73] bdsmatrix_1.3-7 colorspace_2.1-0 GenomeInfoDbData_1.2.10 restfulr_0.0.15
[77] cli_3.6.1 fastseg_1.46.0 fansi_1.0.4 S4Arrays_1.0.6
[81] dplyr_1.1.2 gtable_0.3.5 R.methodsS3_1.8.2 rjson_0.2.21
[85] farver_2.1.2 R.oo_1.26.0 lifecycle_1.0.4 MASS_7.3-60
- List item
Thank you so much for your reply! I am sincerely sorry- of course I do not have multiple GAL files- just one- I meant gpr files! I am so sorry!
MA <- normalizeWithinArrays(RG, method="loess")
works perfectly well:) Thank you!The reason I wanted to get the layout right is so I can view the individual plots generated for assessing the background of each array.
Both codes above work.
Thanks for extra info, but be careful that the Bioconductor support site requires code to be an markdown format. Copying code with prompts (">") straight from the screen will be interpretted as a quotation instead of as code. I agree that is unintuitive, and it trips up almost all new users to this forum. I've edited your question and comment to fix the code formatting. Please have a look at how I did that.
Sorry, limma just doesn't have the capability to create an imageplot of a HuProt array. HuProt arrays seem to have multiple blocks with different layouts, and limma doesn't have the generality to accommodate that. The imageplot() code was written 20 years ago, long before the HuProt technology existed.
One more suggestion. I never use intensity-dependent quality weights myself when analysing GenePix data. I don't think there's any need to introduce NAs in this way. You can instead allow limma to estimate an intensity-dependent variance trend when running eBayes(), and that will account for low-intensity spots in a more graduated and consistent way.
Thank you so much for all of your help! I really appreciate it!