Limma- Print-tip loess normalisation-printer layout information does not match M row dimension
1
0
Entering edit mode
dseauer • 0
@63fac010
Last seen 5 days ago
Australia

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
  1. List item
Normalization limma within-arraynormalisation Printerlayout • 624 views
ADD COMMENT
2
Entering edit mode
@gordon-smyth
Last seen 54 minutes ago
WEHI, Melbourne, Australia

Your RG object does not seem to be correct, but you don't explain how you created it, so we can't tell where the error occurred.

You mention having gal files. The gal flle (GenePix Array List) was a file type that was created long in the past by GenePix image analysis software, but you don't mention using GenePix. There was only ever one gal file for a given experiment -- there can't be more than one. Even for GenePix, limma doesn't need to read the gal file because GenePix writes all the necessary information to the gpr files.

I am somewhat confused by your code and question because HuProt microarrays are not printed with multi-tip print heads as far as I know, so they don't have print-tip groups in the sense of limma objects. In any case, you can't manually create printer layouts in the way that you are doing. Your code doesn't correspond to the documented structure of the limma printer layout component. The printer layout can't be a list of lists.

You could simply use:

MA <- normalizeWithinArrays(RG, method="loess")

so that the printer layout information would be ignored.

ADD COMMENT
0
Entering edit mode

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!

targets <- readTargets("C:xxx s/modified_gpr_files/targets.txt", row.names="Name")

# Set the input directory containing the modified .gpr files
modified_input_directory <- "xxxx/modified_gpr_files"

RG <- read.maimages(targets, source = "genepix.median",modified_input_directory, wt.fun=wtflags(weight=0,cutoff=-50))  

> dim(RG)
[1] 52736    95

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.

> boxplot(data.frame(log2(RG$Gb)),main="Green background")
> boxplot(data.frame(log2(RG$Rb)),main="Red background")

Both codes above work.

> imageplot(log2(RG$Gb[,1]),RG$printer)
Error in imageplot(log2(RG$Gb[, 1]), RG$printer) : 
  Number of image spots does not agree with layout dimensions

Error in imageplot(log2(RG$Gb[, 1]), RG$printer) : 
  Number of image spots does not agree with layout dimensions

> imageplot3by2(RG, z = "Gb", 
+               prefix = "image_Gb",  #Prefix for the output file names
+               path = output_path_green, 
+               zlim = NULL,          
+               common.lim = TRUE)  
Error in imageplot(RG[[z]][, i], RG$printer, zlim = zlim, mar = c(2, 2,  : 
  Number of image spots does not agree with layout dimensions
ADD REPLY
1
Entering edit mode

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.

ADD REPLY
0
Entering edit mode

Thank you so much for all of your help! I really appreciate it!

ADD REPLY

Login before adding your answer.

Traffic: 511 users visited in the last hour
Help About
FAQ
Access RSS
API
Stats

Use of this site constitutes acceptance of our User Agreement and Privacy Policy.

Powered by the version 2.3.6