├── .github └── workflows │ └── main.yml ├── .gitignore ├── DESCRIPTION ├── LICENSE ├── NAMESPACE ├── NEWS ├── R ├── SpatialOverlay-class.R ├── SpatialPosition-class.R ├── addImage.R ├── addPlottingFactor.R ├── coordinateGeneration.R ├── imageManipulation.R ├── omeExtraction.R ├── plottingBasics.R ├── readSpatialOverlay.R ├── removeSamples.R ├── utils.R └── xmlParsing.R ├── README.md ├── inst └── extdata │ ├── muBrainSubset_SpatialOverlay.zip │ ├── muBrain_GxT.zip │ ├── muBrain_LabWorksheet.txt │ ├── muBrain_subset_LabWorksheet.txt │ └── testData │ ├── kidney.zip │ └── test_LabWorksheet.txt ├── longtests ├── testthat.R └── testthat │ ├── _snaps │ ├── addImage │ │ ├── add-image-file.svg │ │ ├── add-ometiff-res-6.svg │ │ └── add-ometiff-res-8.svg │ ├── imageManipulation │ │ ├── cropsamples-all-rois.svg │ │ ├── cropsamples-sampsonly.svg │ │ ├── croptissue.svg │ │ ├── croptissue4chan.svg │ │ ├── flipx.svg │ │ ├── flipy.svg │ │ ├── imagecoloring.svg │ │ └── recolor.svg │ └── plotting │ │ ├── fluorlegend-1-row.svg │ │ ├── fluorlegend-2-row.svg │ │ ├── fluorlegend-4-row.svg │ │ ├── image-scalebar.svg │ │ ├── lowres-fluorlegend.svg │ │ ├── lowres-no-scalebar-no-legend.svg │ │ ├── lowres-no-scalebar.svg │ │ ├── no-image-scalebar.svg │ │ ├── scale-bar-check-1.svg │ │ ├── scale-bar-check-2.svg │ │ └── scale-bar-check-3.svg │ ├── test_SpatialOverlay.R │ ├── test_SpatialPosition.R │ ├── test_addImage.R │ ├── test_addPlottingFactor.R │ ├── test_coordinateGeneration.R │ ├── test_extraction.R │ ├── test_imageManipulation.R │ ├── test_parsing.R │ ├── test_plotting.R │ ├── test_readSpatialOverlay.R │ ├── test_removeSamples.R │ └── test_utils.R ├── man ├── SpatialOverlay-class.Rd ├── SpatialPosition-class.Rd ├── add4ChannelImage.Rd ├── addImageFile.Rd ├── addImageOmeTiff.Rd ├── addPlottingFactor.Rd ├── annotMatching.Rd ├── bookendStr.Rd ├── changeColoringIntensity.Rd ├── changeImageColoring.Rd ├── checkValidRes.Rd ├── createCoordFile.Rd ├── createMask.Rd ├── cropSamples.Rd ├── cropTissue.Rd ├── downloadMouseBrainImage.Rd ├── flipX.Rd ├── flipY.Rd ├── fluorLegend.Rd ├── moveCoords.Rd ├── parseOverlayAttrs.Rd ├── parseScanMetadata.Rd ├── plotSpatialOverlay.Rd ├── readLabWorksheet.Rd ├── readSpatialOverlay.Rd ├── recolor.Rd ├── removeSample.Rd └── xmlExtraction.Rd ├── reqs.md ├── specs.md ├── tests ├── testthat.R └── testthat │ └── test_all.R └── vignettes ├── SpatialOmicsOverlay.Rmd └── images └── pyramidalTIFF.png /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | on: 2 | issues: 3 | types: [opened] 4 | 5 | 6 | jobs: 7 | welcome: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: EddieHubCommunity/gh-action-community/src/welcome@main 11 | with: 12 | github-token: ${{ secrets.GITHUB_TOKEN }} 13 | issue-message: "Thank you for contacting us about our tools! To receive assistance, kindly email support.spatial@bruker.com with detailed information about your issue. If applicable, attach a screenshot of any encountered errors and include a copy of the modified script in Notepad. Our customer support team will help facilitate a review and resolution of the issue." 14 | footer: "Thank you for choosing Bruker Spatial Biology,\nBruker Spatial Biology Dev Team" 15 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | core. 2 | .html 3 | -------------------------------------------------------------------------------- /DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: SpatialOmicsOverlay 2 | Title: Spatial Overlay for Omic Data from Nanostring GeoMx Data 3 | Description: Tools for NanoString Technologies GeoMx Technology. Package to 4 | easily graph on top of an OME-TIFF image. Plotting annotations 5 | can range from tissue segment to gene expression. 6 | Version: 1.8.1 7 | Encoding: UTF-8 8 | Authors@R: c(person("Maddy", "Griswold", email = "mgriswold@nanostring.com", role = c("cre","aut")), 9 | person("Megan", "Vandenberg", email = "mvandenberg@nanostring.com", role = c("ctb")), 10 | person("Stephanie", "Zimmerman", role = c("ctb"))) 11 | Depends: R (>= 4.1.0) 12 | Imports: S4Vectors, Biobase, base64enc, EBImage, ggplot2, XML, 13 | scattermore, dplyr, pbapply, data.table, readxl, magick, grDevices, 14 | stringr, plotrix, GeomxTools, BiocFileCache, stats, utils, methods, 15 | ggtext, tools, RBioFormats 16 | Suggests: 17 | knitr, 18 | BiocStyle, 19 | rmarkdown, 20 | testthat (>= 3.0.0), 21 | stringi, 22 | qpdf, 23 | pheatmap, 24 | viridis, 25 | cowplot, 26 | vdiffr, 27 | sf 28 | License: MIT 29 | Collate: addImage.R 30 | addPlottingFactor.R 31 | coordinateGeneration.R 32 | imageManipulation.R 33 | omeExtraction.R 34 | plottingBasics.R 35 | readSpatialOverlay.R 36 | removeSamples.R 37 | SpatialPosition-class.R 38 | SpatialOverlay-class.R 39 | utils.R 40 | xmlParsing.R 41 | biocViews: GeneExpression, Transcription, CellBasedAssays, DataImport, 42 | Transcriptomics, Proteomics, ProprietaryPlatforms, RNASeq, Spatial, 43 | DataRepresentation, Visualization 44 | VignetteEngine: knitr::rmarkdown 45 | VignetteBuilder: knitr 46 | RoxygenNote: 7.3.1 47 | Config/testthat/edition: 3 48 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Nanostring-Biostats 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /NAMESPACE: -------------------------------------------------------------------------------- 1 | ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2 | ### Imports 3 | import(S4Vectors) 4 | import(XML) 5 | import(ggplot2) 6 | import(GeomxTools) 7 | 8 | importFrom(base64enc,base64decode) 9 | importFrom(BiocFileCache,BiocFileCache) 10 | importFrom(BiocFileCache,bfcadd) 11 | importFrom(BiocFileCache,bfccache) 12 | importFrom(BiocFileCache,bfcremove) 13 | importFrom(BiocFileCache,bfcrpath) 14 | importFrom(BiocFileCache,bfcquery) 15 | importFrom(Biobase,assayDataElement) 16 | importFrom(data.table,fread) 17 | importFrom(dplyr,bind_rows) 18 | importFrom(dplyr,distinct) 19 | importFrom(EBImage,as.Image) 20 | importFrom(EBImage,Color) 21 | importFrom(EBImage,display) 22 | importFrom(EBImage,Image) 23 | importFrom(EBImage,imageData) 24 | importFrom(EBImage,"imageData<-") 25 | importFrom(EBImage,normalize) 26 | importFrom(ggtext,element_markdown) 27 | importFrom(grDevices,col2rgb) 28 | importFrom(grDevices,dev.off) 29 | importFrom(grDevices,jpeg) 30 | importFrom(grDevices,png) 31 | importFrom(grDevices,tiff) 32 | importFrom(magick,as_EBImage) 33 | importFrom(magick,image_crop) 34 | importFrom(magick,image_flip) 35 | importFrom(magick,image_flop) 36 | importFrom(magick,image_info) 37 | importFrom(magick,image_ggplot) 38 | importFrom(magick,image_read) 39 | importFrom(methods,as) 40 | importFrom(methods,callNextMethod) 41 | importFrom(methods,is) 42 | importFrom(methods,new) 43 | importFrom(pbapply,pbapply) 44 | importFrom(plotrix,color.id) 45 | importFrom(RBioFormats,coreMetadata) 46 | importFrom(RBioFormats,read.image) 47 | importFrom(RBioFormats,read.metadata) 48 | importFrom(RBioFormats,read.omexml) 49 | importFrom(readxl,read_xlsx) 50 | importFrom(scattermore,geom_scattermore) 51 | importFrom(stats,setNames) 52 | importFrom(stringr,str_to_title) 53 | importFrom(tools,R_user_dir) 54 | importFrom(utils,read.table) 55 | importFrom(utils,str) 56 | importFrom(utils,untar) 57 | 58 | importClassesFrom(GeomxTools,NanoStringGeoMxSet) 59 | 60 | ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 61 | ### Export S4 classes 62 | exportClasses(SpatialOverlay) 63 | exportClasses(SpatialPosition) 64 | 65 | ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 66 | ### Export S4 generics 67 | 68 | export(SpatialOverlay, SpatialPosition, position, meta, spatialPos, slideName, 69 | overlay, scanMeta, coords, plotFactors, labWork, outline, scaleBarRatio, 70 | fluor, seg, sampNames, showImage, res, scaled, imageInfo, workflow) 71 | 72 | ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 73 | ### Export S4 methods 74 | 75 | exportMethods(SpatialOverlay, SpatialPosition, position, meta, spatialPos, show, 76 | slideName, overlay, scanMeta, coords, plotFactors, labWork, 77 | outline, scaleBarRatio, fluor, seg, sampNames, showImage, res, 78 | scaled, imageInfo, workflow) 79 | 80 | ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 81 | ### Export non-generic functions 82 | 83 | export(add4ChannelImage) 84 | export(addImageFile) 85 | export(addImageOmeTiff) 86 | export(bookendStr) 87 | export(changeColoringIntensity) 88 | export(changeImageColoring) 89 | export(checkValidRes) 90 | export(createCoordFile) 91 | export(createMask) 92 | export(cropSamples) 93 | export(cropTissue) 94 | export(downloadMouseBrainImage) 95 | export(flipX) 96 | export(flipY) 97 | export(fluorLegend) 98 | export(moveCoords) 99 | export(parseOverlayAttrs) 100 | export(parseScanMetadata) 101 | export(plotSpatialOverlay) 102 | export(readLabWorksheet) 103 | export(readSpatialOverlay) 104 | export(recolor) 105 | export(removeSample) 106 | export(xmlExtraction) 107 | 108 | ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 109 | ### Export S3 methods 110 | 111 | exportMethods(addPlottingFactor) 112 | 113 | -------------------------------------------------------------------------------- /NEWS: -------------------------------------------------------------------------------- 1 | v1.8.1 (2025-9-29) 2 | + Added troubleshooting documentation 3 | + fixed ggplot2 4.0.0 compatibility issues 4 | 5 | v1.4.0 6 | + Compatibility with updated labworksheet 7 | + IPA compatibility 8 | 9 | Changes in 1.2.1 (2023-10-5) 10 | + Corrected labworksheet attached to package 11 | + Added tibble plottingFactor 12 | + scale bar printing in mm 13 | + Bugs fixes: 14 | - SpatialPosition printing 15 | - saving xml files 16 | - ROI matching on string values 17 | - overcropping on recolored images 18 | 19 | v1.0.0 (2023-04-21) 20 | + Initial Bioconductor release 21 | 22 | v0.99.0 (2022-04-01) 23 | + Submitted to Bioconductor 24 | -------------------------------------------------------------------------------- /R/SpatialOverlay-class.R: -------------------------------------------------------------------------------- 1 | setClassUnion("dfOrNULL", c("data.frame", "NULL")) 2 | 3 | # Class definition 4 | setClass("SpatialOverlay", 5 | slots = c(slideName = "character", 6 | scanMetadata = "list", 7 | overlayData = "SpatialPosition", 8 | coords = "dfOrNULL", 9 | plottingFactors = "dfOrNULL", 10 | workflow = "list", 11 | image = "list"), 12 | prototype = prototype( 13 | new("VersionedBiobase", 14 | versions = c(SpatialOverlay = "1.0")), 15 | slideName = "slide", 16 | scanMetadata = list(), 17 | overlayData = SpatialPosition(), 18 | coords = NULL, 19 | plottingFactors = NULL, 20 | workflow = list(), 21 | image = list())) 22 | 23 | # Show method 24 | setMethod("show", signature = "SpatialOverlay", 25 | function(object) { 26 | cat(class(object), "\n") 27 | cat("Slide Name:", slideName(object), "\n") 28 | rows <- nrow(meta(overlay(object))) 29 | cat("Overlay Data:", rows, "samples", "\n") 30 | cat(" Overlay Names:", sampNames(object)[1], "...", 31 | sampNames(object)[rows], "(", rows, "total )", "\n") 32 | cat("Scan Metadata", "\n") 33 | cat(" Panels:", paste(scanMeta(object)$Panels, sep = ", "), "\n") 34 | cat(" Segmentation:", scanMeta(object)$Segmentation, "\n") 35 | if(!is.null(plotFactors(object))){ 36 | cat("Plotting Factors:", "\n") 37 | cat(" varLabels:", colnames(plotFactors(object)), "\n") 38 | } 39 | if(!is.null(coords(object))){ 40 | cat("Outline:", outline(object), "\n") 41 | } 42 | if(!is.null(object@image$filePath)){ 43 | cat("Image:", object@image$filePath,"\n") 44 | } 45 | }) 46 | 47 | # Constructors 48 | setGeneric("SpatialOverlay", 49 | function(slideName, 50 | scanMetadata, 51 | overlayData, 52 | coords = NULL, 53 | plottingFactors = NULL, 54 | workflow = list(outline=FALSE, 55 | labWorksheet=TRUE, 56 | scaled=FALSE), 57 | image = list(filePath = NULL, 58 | imagePointer = NULL, 59 | resolution = NULL)) 60 | standardGeneric("SpatialOverlay")) 61 | 62 | setMethod("SpatialOverlay", "character", 63 | function(slideName, scanMetadata, overlayData, coords, 64 | plottingFactors, workflow, image) 65 | { 66 | new2("SpatialOverlay", 67 | slideName = slideName, scanMetadata = scanMetadata, 68 | overlayData = overlayData, coords = coords, 69 | plottingFactors = plottingFactors, workflow = workflow, 70 | image = image) 71 | }) 72 | 73 | # setMethod("SpatialOverlay", "environment", 74 | # function(slideName, scanMetadata, overlayData, coords, 75 | # plottingFactors, workflow, image) 76 | # { 77 | # new2("SpatialOverlay", 78 | # slideName = slideName, scanMetadata = scanMetadata, 79 | # overlayData = overlayData, coords = coords, 80 | # plottingFactors = plottingFactors, workflow = workflow, 81 | # image = image) 82 | # }) 83 | 84 | # setMethod("SpatialOverlay", "character", 85 | # function(slideName, scanMetadata, overlayData, coords, 86 | # plottingFactors, workflow, image) 87 | # { 88 | # new2("SpatialOverlay", 89 | # slideName = slideName, scanMetadata = scanMetadata, 90 | # overlayData = overlayData, coords = coords, 91 | # plottingFactors = plottingFactors, workflow = workflow, 92 | # image = image) 93 | # }) 94 | 95 | # Validity 96 | setValidity2("SpatialOverlay", function(object){ 97 | msg <- NULL 98 | if (any(names(scanMeta(object)) != c("Panels", "PhysicalSizes", 99 | "Fluorescence", "Segmentation"))) { 100 | msg <- c(msg, "Names in Scan Metadata are not valid") 101 | } 102 | if(!is(scanMeta(object)$Panels,"character")){ 103 | msg <- c(msg, "Panels in Scan Metadata must be a character") 104 | } 105 | if(all(names(scanMeta(object)$PhysicalSizes) != c("X", "Y"))){ 106 | msg <- c(msg, "PhysicalSizes in Scan Metadata does not contain X and Y ratio") 107 | } 108 | if(!is(scanMeta(object)$PhysicalSizes$X,"numeric") | 109 | !is(scanMeta(object)$PhysicalSizes$Y,"numeric")){ 110 | msg <- c(msg, "PhysicalSizes in Scan Metadata must be numeric") 111 | } 112 | if(!is(scanMeta(object)$Fluorescence,"data.frame")){ 113 | msg <- c(msg, "Fluorescence in Scan Metadata must be a data.frame") 114 | } 115 | if(all(!c("Dye", "DisplayName", "Color", "WaveLength", 116 | "Target", "ExposureTime", "ColorCode") %in% 117 | names(scanMeta(object)$Fluorescence))){ 118 | msg <- c(msg, "Column names in Fluorescence do not match expected") 119 | } 120 | 121 | if(!is.null(plotFactors(object))){ 122 | if(any(rownames(plotFactors(object)) != sampNames(object))){ 123 | msg <- c(msg, "plotFactors and overlay are in a different order") 124 | } 125 | char <- NULL 126 | for(i in seq_len(ncol(plotFactors(object)))){ 127 | char <- c(char, class(plotFactors(object)[,i] %in% c("factor", 128 | "numeric"))) 129 | } 130 | if(any(char == FALSE)){ 131 | msg <- c(msg, "plotFactors classes must be either factors or numeric") 132 | } 133 | } 134 | 135 | if(all(!names(object@workflow) %in% c("labWorksheet", "outline", "scaled"))){ 136 | msg <- c(msg, "workflow names are not valid") 137 | } 138 | 139 | if(!is.null(coords(object))){ 140 | if(any(!coords(object)$sampleID %in% sampNames(object))){ 141 | msg <- c(msg, "coordinates for extra samples") 142 | } 143 | } 144 | 145 | if(all(!names(object@image) %in% c("filePath", "imagePointer", "resolution"))){ 146 | msg <- c(msg, "image names are not valid") 147 | } 148 | 149 | if (is.null(msg)) TRUE else msg 150 | }) 151 | 152 | 153 | # Accessors 154 | setGeneric("slideName", signature = "object", 155 | function(object) standardGeneric("slideName")) 156 | setMethod("slideName", "SpatialOverlay", function(object) 157 | object@slideName) 158 | 159 | setGeneric("overlay", signature = "object", 160 | function(object) standardGeneric("overlay")) 161 | setMethod("overlay", "SpatialOverlay", function(object) 162 | object@overlayData) 163 | 164 | setGeneric("scanMeta", signature = "object", 165 | function(object) standardGeneric("scanMeta")) 166 | setMethod("scanMeta", "SpatialOverlay", function(object) 167 | object@scanMetadata) 168 | 169 | setGeneric("coords", signature = "object", 170 | function(object) standardGeneric("coords")) 171 | setMethod("coords", "SpatialOverlay", function(object) object@coords) 172 | 173 | setGeneric("plotFactors", signature = "object", 174 | function(object) standardGeneric("plotFactors")) 175 | setMethod("plotFactors", "SpatialOverlay", function(object) object@plottingFactors) 176 | 177 | setGeneric("labWork", signature = "object", 178 | function(object) standardGeneric("labWork")) 179 | setMethod("labWork", "SpatialOverlay", function(object) 180 | object@workflow$labWorksheet) 181 | 182 | setGeneric("outline", signature = "object", 183 | function(object) standardGeneric("outline")) 184 | setMethod("outline", "SpatialOverlay", function(object) 185 | object@workflow$outline) 186 | 187 | setGeneric("seg", signature = "object", 188 | function(object) standardGeneric("seg")) 189 | setMethod("seg", "SpatialOverlay", function(object) 190 | object@scanMetadata$Segmentation) 191 | 192 | setGeneric("scaleBarRatio", signature = "object", 193 | function(object) standardGeneric("scaleBarRatio")) 194 | setMethod("scaleBarRatio", "SpatialOverlay", function(object) 195 | object@scanMetadata$PhysicalSizes$X) 196 | 197 | setGeneric("fluor", signature = "object", 198 | function(object) standardGeneric("fluor")) 199 | setMethod("fluor", "SpatialOverlay", function(object) 200 | object@scanMetadata$Fluorescence) 201 | 202 | setGeneric("sampNames", signature = "object", 203 | function(object) standardGeneric("sampNames")) 204 | setMethod("sampNames", "SpatialOverlay", function(object) 205 | meta(overlay(object))$Sample_ID) 206 | 207 | setGeneric("showImage", signature = "object", 208 | function(object) standardGeneric("showImage")) 209 | setMethod("showImage", "SpatialOverlay", function(object) 210 | object@image$imagePointer) 211 | 212 | setGeneric("res", signature = "object", 213 | function(object) standardGeneric("res")) 214 | setMethod("res", "SpatialOverlay", function(object) 215 | object@image$resolution) 216 | 217 | setGeneric("workflow", signature = "object", 218 | function(object) standardGeneric("workflow")) 219 | setMethod("workflow", "SpatialOverlay", function(object) 220 | object@workflow) 221 | 222 | setGeneric("scaled", signature = "object", 223 | function(object) standardGeneric("scaled")) 224 | setMethod("scaled", "SpatialOverlay", function(object) 225 | object@workflow$scaled) 226 | 227 | setGeneric("imageInfo", signature = "object", 228 | function(object) standardGeneric("imageInfo")) 229 | setMethod("imageInfo", "SpatialOverlay", function(object) 230 | object@image) 231 | -------------------------------------------------------------------------------- /R/SpatialPosition-class.R: -------------------------------------------------------------------------------- 1 | VALIDNAMES <- c("ROILabel", "Sample_ID", "Height", "Width", "X", "Y", 2 | "Segmentation", "Position") 3 | 4 | # Class definition 5 | setClass("SpatialPosition", 6 | slots = c(position="data.frame")) 7 | 8 | setMethod("show", signature = "SpatialPosition", 9 | function(object) { 10 | suppressWarnings(print(cbind(meta(object), 11 | Position=unlist(lapply(position(object), bookendStr))))) 12 | }) 13 | 14 | # Constructors 15 | setGeneric("SpatialPosition", 16 | function(position) 17 | standardGeneric("SpatialPosition")) 18 | 19 | setMethod("SpatialPosition", "missing", 20 | function(position) 21 | { 22 | position <- data.frame(matrix(integer(), nrow = 0L, 23 | ncol = length(VALIDNAMES))) 24 | colnames(position) <- VALIDNAMES 25 | new2("SpatialPosition", 26 | position = position) 27 | }) 28 | # 29 | # setMethod("SpatialPosition", "environment", 30 | # function(position) 31 | # { 32 | # new2("SpatialPosition", 33 | # position = position) 34 | # }) 35 | 36 | setMethod("SpatialPosition", "matrix", 37 | function(position) 38 | { 39 | new2("SpatialPosition", 40 | position = as.data.frame(position)) 41 | }) 42 | 43 | setMethod("SpatialPosition", "data.frame", 44 | function(position) 45 | { 46 | new2("SpatialPosition", 47 | position = position) 48 | }) 49 | 50 | 51 | # Validity 52 | setValidity2("SpatialPosition", function(object){ 53 | msg <- NULL 54 | if (!all(VALIDNAMES %in% colnames(object@position))) { 55 | msg <- c(msg, "Column names in SpatialPosition are not valid") 56 | } 57 | if(nrow(object@position) > 0){ 58 | numericCols <- c("Height", "Width", "X", "Y") 59 | stringCols <- c("ROILabel", "Sample_ID", "Segmentation", "Position") 60 | if(!all(apply(object@position[,numericCols], 2, class) == "numeric")){ 61 | msg <- c(msg, "Numeric columns in SpatialPosition are not valid") 62 | } 63 | if(!all(apply(object@position[,stringCols], 2, class) == "character")){ 64 | msg <- c(msg, "Character columns in SpatialPosition are not valid") 65 | } 66 | if(any(duplicated(object@position$Sample_ID))){ 67 | msg <- c(msg, "All Sample_IDs in SpatialPosition must be unique") 68 | } 69 | } 70 | 71 | if (is.null(msg)) TRUE else msg 72 | }) 73 | 74 | 75 | # Accessors 76 | setGeneric("meta", signature = "object", 77 | function(object) standardGeneric("meta")) 78 | setMethod("meta", "SpatialPosition", function(object) { 79 | object@position[,-(which(colnames(object@position) == "Position"))]}) 80 | 81 | setGeneric("position", signature = "object", 82 | function(object) standardGeneric("position")) 83 | setMethod("position", "SpatialPosition", function(object){ 84 | object@position[,which(colnames(object@position) == "Position")]}) 85 | 86 | setGeneric("spatialPos", signature = "object", 87 | function(object) standardGeneric("spatialPos")) 88 | setMethod("spatialPos", "SpatialPosition", function(object){ 89 | object@position}) 90 | -------------------------------------------------------------------------------- /R/addImage.R: -------------------------------------------------------------------------------- 1 | #' Add image to SpatialOverlay from OME-TIFF 2 | #' 3 | #' @param overlay SpatialOverlay object 4 | #' @param ometiff File path to OME-TIFF. NULL indicates pull info from overlay 5 | #' @param res resolution layer, 1 = largest & higher values = smaller. The 6 | #' images increase in resolution and memory. The largest image your 7 | #' environment can hold is recommended. NULL indicates pull info 8 | #' from overlay 9 | #' @param ... Extra variables 10 | #' 11 | #' @return SpatialOverlay object with image 12 | #' 13 | #' @examples 14 | #' 15 | #' muBrain <- readRDS(unzip(system.file("extdata", "muBrainSubset_SpatialOverlay.zip", 16 | #' package = "SpatialOmicsOverlay"))) 17 | #' 18 | #' image <- downloadMouseBrainImage() 19 | #' 20 | #' muBrain <- addImageOmeTiff(overlay = muBrain, 21 | #' ometiff = image, res = 8) 22 | #' showImage(muBrain) 23 | #' 24 | #' @export 25 | addImageOmeTiff <- function(overlay, ometiff = NULL, res = NULL, ...){ 26 | if(!is(overlay,"SpatialOverlay")){ 27 | stop("overlay must be a SpatialOverlay object") 28 | } 29 | 30 | if(is.null(ometiff)){ 31 | ometiff <- imageInfo(overlay)$filePath 32 | } 33 | if(is.null(res)){ 34 | res <- res(overlay) 35 | } 36 | 37 | overlay@image <- list(filePath = ometiff, 38 | imagePointer = imageExtraction(ometiff = ometiff, 39 | res = res, 40 | ...), 41 | resolution = res) 42 | 43 | message("Calculating and scaling coordinates") 44 | overlay <- createCoordFile(overlay, outline(overlay)) 45 | overlay <- scaleCoords(overlay) 46 | 47 | return(overlay) 48 | } 49 | 50 | #' Add image to SpatialOverlay from disk 51 | #' 52 | #' @param overlay SpatialOverlay object 53 | #' @param imageFile path to image 54 | #' @param res what resolution is the image given? 55 | #' 1 = largest, higher number = smaller 56 | #' This value will affect the coordinates of the overlays. 57 | #' res = 2, resolution is 1/2 the size as the raw image 58 | #' res = 3, resolution is 1/4 the size as the raw image 59 | #' res = 4, resolution is 1/8 the size as the raw image 60 | #' resolution = 1/2^(res-1) 61 | #' 62 | #' @return SpatialOverlay object with image 63 | #' 64 | #' @importFrom magick image_read 65 | #' 66 | #' @export 67 | addImageFile <- function(overlay, imageFile = NULL, res = NULL){ 68 | .Deprecated("addImageOmeTiff") 69 | 70 | if(!is(overlay,"SpatialOverlay")){ 71 | stop("overlay must be a SpatialOverlay object") 72 | } 73 | 74 | if(is.null(res)){ 75 | res <- res(overlay) 76 | } 77 | 78 | overlay@image <- list(filePath = imageFile, 79 | imagePointer = image_read(imageFile), 80 | resolution = res) 81 | 82 | message("Calculating and scaling coordinates") 83 | overlay <- createCoordFile(overlay, outline(overlay)) 84 | overlay <- scaleCoords(overlay) 85 | 86 | return(overlay) 87 | } 88 | 89 | #' Add 4-channel image to SpatialOverlay from OME-TIFF. Allows for recoloring 90 | #' of image 91 | #' 92 | #' @param overlay SpatialOverlay object 93 | #' @param ometiff File path to OME-TIFF. NULL indicates pull info from overlay 94 | #' @param res resolution layer, 1 = largest & higher values = smaller. The 95 | #' images increase in resolution and memory. The largest image your 96 | #' environment can hold is recommended. NULL indicates pull info 97 | #' from overlay 98 | #' @param ... Extra variables 99 | #' 100 | #' @return SpatialOverlay object with image 101 | #' 102 | #' @examples 103 | #' 104 | #' muBrain <- readRDS(unzip(system.file("extdata", "muBrainSubset_SpatialOverlay.zip", 105 | #' package = "SpatialOmicsOverlay"))) 106 | #' 107 | #' image <- downloadMouseBrainImage() 108 | #' 109 | #' muBrain <- add4ChannelImage(overlay = muBrain, 110 | #' ometiff = image, res = 8) 111 | #' 112 | #' dim(EBImage::imageData(showImage(muBrain))) 113 | #' 114 | #' @export 115 | add4ChannelImage <- function(overlay, ometiff = NULL, res = NULL, ...){ 116 | if(!is(overlay,"SpatialOverlay")){ 117 | stop("overlay must be a SpatialOverlay object") 118 | } 119 | 120 | if(is.null(ometiff)){ 121 | ometiff <- imageInfo(overlay)$filePath 122 | } 123 | if(is.null(res)){ 124 | res <- res(overlay) 125 | } 126 | 127 | overlay@image <- list(filePath = ometiff, 128 | imagePointer = imageExtraction(ometiff = ometiff, 129 | res = res, 130 | color = FALSE, 131 | ...), 132 | resolution = res) 133 | 134 | message("Calculating and scaling coordinates") 135 | overlay <- createCoordFile(overlay, outline(overlay)) 136 | overlay <- scaleCoords(overlay) 137 | 138 | return(overlay) 139 | } 140 | -------------------------------------------------------------------------------- /R/coordinateGeneration.R: -------------------------------------------------------------------------------- 1 | DIRECTIONS <- c("left", "right", "up", "down") 2 | 3 | 4 | #' Create coordinate file for entire scan 5 | #' 6 | #' @param overlay SpatialOverlay object 7 | #' @param outline returned coordinates only contain boundaries, 8 | #' will not work for segmented ROIs 9 | #' 10 | #' @return df of coordinates for every AOI in the scan 11 | #' 12 | #' @examples 13 | #' 14 | #' muBrain <- readRDS(unzip(system.file("extdata", "muBrainSubset_SpatialOverlay.zip", 15 | #' package = "SpatialOmicsOverlay"))) 16 | #' 17 | #' muBrain <- createCoordFile(muBrain, outline = FALSE) 18 | #' 19 | #' head(coords(muBrain)) 20 | #' 21 | #' @importFrom dplyr bind_rows 22 | #' @importFrom pbapply pbapply 23 | #' 24 | #' @export 25 | #' 26 | createCoordFile <- function(overlay, outline = TRUE){ 27 | if(!is(overlay,"SpatialOverlay")){ 28 | stop("Overlay must be a SpatialOverlay object") 29 | } 30 | 31 | if(seg(overlay) == "Segmented" & outline == TRUE){ 32 | outline <- FALSE 33 | 34 | warning("Outline coordinates do not work in segmented data. Continuing with all coordinates", 35 | immediate. = TRUE) 36 | } 37 | 38 | overlayData <- overlay(overlay) 39 | 40 | numericCols <- c("Height", "Width", "X", "Y") 41 | 42 | coordValues <- suppressWarnings(pbapply(spatialPos(overlayData), 1, 43 | function(x){ 44 | metadata <- as.data.frame(x[which(names(x) != "Position")]) 45 | if(nrow(metadata) > ncol(metadata)){ 46 | metadata <- as.data.frame(t(metadata)) 47 | } 48 | for(i in numericCols){ 49 | metadata[[i]] <- as.numeric(metadata[[i]]) 50 | } 51 | 52 | cbind(sampleID=x["Sample_ID"], 53 | coordsFromMask(mask = createMask(b64string = x["Position"], 54 | metadata = metadata, 55 | outline = outline), 56 | metadata = metadata, 57 | outline = outline)) 58 | })) 59 | 60 | coordValues <- dplyr::bind_rows(coordValues) 61 | coordValues$xcoor <- as.numeric(coordValues$xcoor) 62 | coordValues$ycoor <- as.numeric(coordValues$ycoor) 63 | 64 | overlay@coords <- coordValues 65 | 66 | overlay@workflow$outline <- outline 67 | overlay@workflow$scaled <- FALSE 68 | 69 | return(overlay) 70 | } 71 | 72 | #' Create a binary mask from a base 64 string 73 | #' 74 | #' @param b64string base 64 string 75 | #' @param metadata metadata of AOI including: Height, Width of AOI 76 | #' @param outline only the outline points should be returned 77 | #' 78 | #' @return binary mask image 79 | #' 80 | #' @examples 81 | #' 82 | #' muBrain <- readRDS(unzip(system.file("extdata", "muBrainSubset_SpatialOverlay.zip", 83 | #' package = "SpatialOmicsOverlay"))) 84 | #' 85 | #' samp <- which(sampNames(muBrain) == "DSP-1012999073013-A-F12") 86 | #' 87 | #' ROIMask <- createMask(b64string = position(overlay(muBrain))[samp], 88 | #' metadata = meta(overlay(muBrain))[samp,], 89 | #' outline = TRUE) 90 | #' 91 | #' pheatmap::pheatmap(ROIMask, cluster_rows = FALSE, cluster_cols = FALSE) 92 | #' 93 | #' @export 94 | #' 95 | createMask <- function(b64string, metadata, outline = TRUE){ 96 | base8 <- decodeB64(b64string = b64string, 97 | height = metadata$Height, 98 | width = metadata$Width) 99 | 100 | mask <- matrix(as.numeric(base8), 101 | nrow = metadata$Height, 102 | ncol = metadata$Width, 103 | byrow = TRUE) 104 | 105 | if(outline == TRUE){ 106 | outlines <- NULL 107 | 108 | outlines <- as.vector(mask) 109 | neighbors <- boundary(mask) 110 | 111 | # points with all neighbors with 1 are inside points and can be removed 112 | outlines[which(neighbors == 8)] <- 0 113 | 114 | mask <- matrix(outlines, 115 | nrow = metadata$Height, 116 | ncol = metadata$Width, 117 | byrow = FALSE) 118 | } 119 | return(mask) 120 | } 121 | 122 | #' Return positive coordinates from mask 123 | #' 124 | #' @param mask base 64 string 125 | #' @param metadata metadata of AOI including: X,Y position in full image 126 | #' @param outline only the outline points should be returned 127 | #' 128 | #' @return df of positive coordinates of AOI 129 | #' 130 | #' @noRd 131 | coordsFromMask <- function(mask, metadata, outline = TRUE){ 132 | coords <- as.data.frame(which(mask != 0, arr.ind = TRUE)) 133 | names(coords) <- c("ycoor", "xcoor") 134 | 135 | # put AOI in scheme of entire image 136 | # while R is 1-based, magick images are 0-based 137 | coords$xcoor <- coords$xcoor + metadata$X - 1 138 | coords$ycoor <- coords$ycoor + metadata$Y - 1 139 | 140 | if(outline == TRUE){ 141 | coords <- pencilCoordSorting(coords) 142 | } 143 | 144 | return(coords) 145 | } 146 | 147 | #' Sort coordinates like a pencil drawing 148 | #' 149 | #' @description 150 | #' When outline coordinates are generated they are ordered by column but 151 | #' geom_polygon expects them to be in order like you are tracing the shape 152 | #' with a pencil. This function orders them by finding the closest x,y 153 | #' coordinate to the previous point 154 | #' 155 | #' @param coords All x,y coordinates for an ROI 156 | #' @param rangeWidth size of range to search for closest coordinate 157 | #' 158 | #' @return df of ordered coordinates 159 | #' 160 | #' @noRd 161 | pencilCoordSorting <- function(coords, rangeWidth = 100){ 162 | outlineCoords <- coords[1L,] 163 | used <- NULL 164 | for(i in seq_len(nrow(coords))){ 165 | lastPoint <- as.numeric(rownames(outlineCoords)[nrow(outlineCoords)]) 166 | used <- c(used, lastPoint) 167 | range <- (lastPoint-rangeWidth):(lastPoint+rangeWidth) 168 | available <- coords[range[-which(range %in% used | 169 | range <= 0 | 170 | range > nrow(coords))],] 171 | if(nrow(available) == 0){ 172 | next 173 | } 174 | closest <- order(abs(coords$ycoor[lastPoint] - available$ycoor) + 175 | abs(coords$xcoor[lastPoint] - available$xcoor), 176 | decreasing = FALSE)[1] 177 | if((abs(outlineCoords$ycoor[i] - available$ycoor[closest]) + 178 | abs(outlineCoords$xcoor[i] - available$xcoor[closest])) > 50){ 179 | range <- seq_len(nrow(coords)) 180 | available <- coords[range[-which(range %in% used)],] 181 | if(nrow(available) == 0){ 182 | next 183 | } 184 | closest <- order(abs(outlineCoords$ycoor[i] - available$ycoor) + 185 | abs(outlineCoords$xcoor[i] - available$xcoor), 186 | decreasing = FALSE)[1] 187 | } 188 | 189 | outlineCoords <- rbind(outlineCoords, 190 | available[closest,]) 191 | } 192 | 193 | return(outlineCoords) 194 | } 195 | 196 | #' Return points for boundary mask 197 | #' 198 | #' @note 199 | #' code modified from Stack Overflow 200 | #' https://stackoverflow.com/questions/29105175/find-neighbouring-elements-of-a-matrix-in-r 201 | #' 202 | #' @param mat mask 203 | #' 204 | #' @return total number of neighbors for each pixel 205 | #' 206 | #' @noRd 207 | boundary <- function(mat) { 208 | mat.pad <- rbind(NA, cbind(NA, mat, NA), NA) 209 | indrow <- 2:(nrow(mat) + 1) # row indices of the "middle" 210 | indcol <- 2:(ncol(mat) + 1) # column indices of the "middle" 211 | neigh <- colSums(na.rm = TRUE, 212 | rbind(N = as.vector(mat.pad[indrow - 1, indcol ]), 213 | NE = as.vector(mat.pad[indrow - 1, indcol + 1]), 214 | E = as.vector(mat.pad[indrow , indcol + 1]), 215 | SE = as.vector(mat.pad[indrow + 1, indcol + 1]), 216 | S = as.vector(mat.pad[indrow + 1, indcol ]), 217 | SW = as.vector(mat.pad[indrow + 1, indcol - 1]), 218 | W = as.vector(mat.pad[indrow , indcol - 1]), 219 | NW = as.vector(mat.pad[indrow - 1, indcol - 1]))) 220 | return(neigh) 221 | } 222 | 223 | #' Scale coordinates to the size of the image 224 | #' 225 | #' @param overlay SpatialOverlay object 226 | #' 227 | #' @return SpatialOverlay object 228 | #' 229 | #' @importFrom dplyr distinct 230 | #' @importFrom magick image_info 231 | #' @importFrom magick image_read 232 | #' 233 | #' @noRd 234 | scaleCoords <- function(overlay){ 235 | if(!is(overlay,"SpatialOverlay")){ 236 | stop("overlay must be a SpatialOverlay") 237 | } 238 | if(scaled(overlay) == TRUE){ 239 | stop("Coordinates are already scaled and can't be scaled again") 240 | } 241 | if(is.null(showImage(overlay))){ 242 | warning("No image has been added to the SpatialOverlay object, no scaling will be done") 243 | }else{ 244 | scaling <- 1/2^(res(overlay)-1) 245 | 246 | if(is(showImage(overlay),"AnnotatedImage")){ 247 | temp <- image_read(imageColoring(showImage(overlay), 248 | scanMeta(overlay))) 249 | }else{ 250 | temp <- showImage(overlay) 251 | } 252 | 253 | #scale and center y axis 254 | overlay@coords$ycoor <- image_info(temp)$height - 255 | round(coords(overlay)$ycoor * scaling) 256 | 257 | overlay@coords$xcoor <- round(coords(overlay)$xcoor * scaling) 258 | 259 | overlay@coords <- distinct(coords(overlay)) 260 | 261 | overlay@workflow$scaled <- TRUE 262 | } 263 | 264 | return(overlay) 265 | } 266 | 267 | #' Move coordinates if they don't match image 268 | #' 269 | #' @description If generated coordinates do not match the image use this 270 | #' function to move coordinates. Coordinates are only changed 1 pixel at a time. 271 | #' 272 | #' @param overlay SpatialOverlay object 273 | #' @param direction which direction should coordinates move: left, right, up, down 274 | #' 275 | #' @return SpatialOverlay object 276 | #' 277 | #' @examples 278 | #' 279 | #' muBrain <- readRDS(unzip(system.file("extdata", "muBrainSubset_SpatialOverlay.zip", 280 | #' package = "SpatialOmicsOverlay"))) 281 | #' head(coords(muBrain), 3) 282 | #' head(coords(moveCoords(muBrain, direction = "up")), 3) 283 | #' 284 | #' @export 285 | moveCoords <- function(overlay, direction = "right"){ 286 | if(!is(overlay,"SpatialOverlay")){ 287 | stop("Overlay must be a SpatialOverlay object") 288 | } 289 | 290 | direction <- tolower(direction) 291 | if(!direction %in% DIRECTIONS){ 292 | stop(paste("direction is not valid: options -", 293 | paste(DIRECTIONS, collapse = ", "))) 294 | } 295 | 296 | if(direction == "right"){ 297 | overlay@coords$xcoor <- overlay@coords$xcoor + 1 298 | }else if(direction == "left"){ 299 | overlay@coords$xcoor <- overlay@coords$xcoor - 1 300 | }else if(direction == "up"){ 301 | overlay@coords$ycoor <- overlay@coords$ycoor + 1 302 | }else{ 303 | overlay@coords$ycoor <- overlay@coords$ycoor - 1 304 | } 305 | 306 | return(overlay) 307 | } 308 | -------------------------------------------------------------------------------- /R/omeExtraction.R: -------------------------------------------------------------------------------- 1 | #' Extract xml from OME-TIFF 2 | #' 3 | #' @param ometiff path to OME-TIFF 4 | #' @param saveFile should xml be saved, file is saved in working directory with 5 | #' same name as OME-TIFF 6 | #' @param outdir output directory for saved xml. If NULL, saved in same directory as OME-TIFF 7 | #' 8 | #' @return list of xml data 9 | #' 10 | #' @examples 11 | #' 12 | #' image <- downloadMouseBrainImage() 13 | #' xml <- xmlExtraction(ometiff = image) 14 | #' 15 | #' @importFrom XML xmlInternalTreeParse 16 | #' @importFrom XML xmlToList 17 | #' @importFrom RBioFormats read.omexml 18 | #' 19 | #' @export 20 | 21 | # Need to update error checking & saving for URIs 22 | 23 | xmlExtraction <- function(ometiff, saveFile = FALSE, outdir = NULL){ 24 | if(!file.exists(ometiff)){ 25 | stop("ometiff file does not exist") 26 | } 27 | 28 | # auto catches NULL POINTER error that occurs on first try 29 | try(omexml <- read.omexml(ometiff), silent = TRUE) 30 | 31 | if(!exists("omexml")){ 32 | omexml <- xmlInternalTreeParse(read.omexml(ometiff), 33 | options = HUGE) 34 | }else{ 35 | omexml <- xmlInternalTreeParse(omexml, 36 | options = HUGE) 37 | } 38 | 39 | 40 | if(saveFile){ 41 | xmlName <- gsub(pattern = "tiff", 42 | replacement = "xml", 43 | x = basename(ometiff)) 44 | 45 | if(is.null(outdir)){ 46 | xmlName <- paste0(dirname(ometiff), "/", xmlName) 47 | }else{ 48 | if(!exists(outdir)){ 49 | dir.create(outdir, recursive = TRUE) 50 | } 51 | xmlName <- paste0(outdir, "/", xmlName) 52 | } 53 | 54 | saveXML(doc = omexml, file = xmlName) 55 | } 56 | 57 | omexml <- xmlToList(omexml, simplify = TRUE) 58 | 59 | return(omexml) 60 | } 61 | 62 | #' Extract image from OME-TIFF 63 | #' 64 | #' @param ometiff path to OME-TIFF 65 | #' @param res resolution layer, 1 = largest & higher values = smaller. The 66 | #' images increase in resolution and memory. The largest image 67 | #' your environment can hold is recommended. 68 | #' @param scanMeta scan metadata from parseScanMetadata(). If NULL, that 69 | #' function is automatically called. 70 | #' @param saveFile should xml be saved, file is saved in working directory with 71 | #' same name as OME-TIFF 72 | #' @param fileType type of image file. Options: tiff, png, jpeg 73 | #' @param color should image be colored RGB or 4-channel BW 74 | #' @param outdir output directory for saved image. If NULL, saved in same directory as OME-TIFF 75 | #' 76 | #' @return omeImage magick pointer 77 | #' 78 | #' @importFrom EBImage normalize 79 | #' @importFrom EBImage imageData 80 | #' @importFrom EBImage imageData<- 81 | #' @importFrom magick image_read 82 | #' @importFrom EBImage display 83 | #' @importFrom RBioFormats read.image 84 | #' @importFrom RBioFormats coreMetadata 85 | #' 86 | #' @noRd 87 | 88 | imageExtraction <- function(ometiff, res = 6, scanMeta = NULL, saveFile = FALSE, 89 | fileType = "tiff", color = TRUE, outdir = NULL){ 90 | if(!file.exists(ometiff)){ 91 | stop("ometiff file does not exist") 92 | } 93 | 94 | if(!fileType %in% c("png", "jpeg", "tiff", "jpg")){ 95 | stop("fileType not valid: options are 'tiff', png', or 'jpeg'") 96 | } 97 | 98 | lowRes <- checkValidRes(ometiff) 99 | 100 | if(!res %in% c(seq_len(lowRes))){ 101 | msg <- paste("valid res integers for this image must be between 1 and", 102 | lowRes) 103 | stop(msg) 104 | } 105 | 106 | if(is.null(scanMeta)){ 107 | scanMeta <- parseScanMetadata(xmlExtraction(ometiff)) 108 | } 109 | 110 | omeImage <- read.image(file = ometiff, resolution = res, 111 | read.metadata = FALSE, normalize = FALSE) 112 | 113 | if(color == TRUE){ 114 | omeImage <- imageColoring(omeImage, scanMeta) 115 | }else{ 116 | if(saveFile == TRUE){ 117 | warning("file can only be saved if color == TRUE, will not save file", 118 | immediate. = TRUE) 119 | saveFile <- FALSE 120 | } 121 | } 122 | 123 | if(saveFile == TRUE){ 124 | width <- coreMetadata(omeImage)$sizeX 125 | height <- coreMetadata(omeImage)$sizeY 126 | 127 | if(is.null(outdir)){ 128 | imageName <- gsub(pattern = ".ome", 129 | replacement = "", 130 | x = basename(ometiff)) 131 | 132 | imageName <- paste0(dirname(ometiff), "/", imageName) 133 | }else{ 134 | imageName <- paste0(outdir, "/", imageName) 135 | } 136 | 137 | if(fileType == "png"){ 138 | imageName <- gsub(pattern = "tiff", replacement = "png", 139 | x = imageName) 140 | png(imageName, width = width, height = height, units = "px") 141 | }else if(fileType == "jpeg" | fileType == "jpg"){ 142 | imageName <- gsub(pattern = "tiff", replacement = "jpeg", 143 | x = imageName) 144 | jpeg(imageName, width = width, height = height, units = "px") 145 | }else{ 146 | tiff(imageName, width = width, height = height, units = "px") 147 | } 148 | 149 | display(omeImage, method = "raster") 150 | dev.off() 151 | } 152 | 153 | if(color == TRUE){ 154 | omeImage <- image_read(omeImage) 155 | } 156 | 157 | return(omeImage) 158 | } 159 | 160 | #' Determine lowest resolution image in OME-TIFF 161 | #' 162 | #' @param ometiff path to OME-TIFF 163 | #' 164 | #' @return value of lowest res image 165 | #' 166 | #' @importFrom RBioFormats read.metadata 167 | #' 168 | #' @examples 169 | #' 170 | #' image <- downloadMouseBrainImage() 171 | #' checkValidRes(ometiff = image) 172 | #' 173 | #' @export 174 | #' 175 | checkValidRes <- function(ometiff){ 176 | meta <- read.metadata(ometiff) 177 | 178 | return(length(meta)) 179 | } 180 | -------------------------------------------------------------------------------- /R/readSpatialOverlay.R: -------------------------------------------------------------------------------- 1 | #' Read in \code{\linkS4class{SpatialOverlay}} from tiff file and annotations 2 | #' 3 | #' @description Create an instance of class \code{\linkS4class{SpatialOverlay}} 4 | #' by reading data from OME-TIFF and annotation sheet. 5 | #' 6 | #' @param ometiff path to OME-TIFF 7 | #' @param annots path to annotation file: can be labWorksheet, DA excel file, or 8 | #' delimted file 9 | #' @param slideName name of slide 10 | #' @param image should image be extracted from OME-TIFF 11 | #' @param res resolution of image 12 | #' 1 = largest, higher number = smaller 13 | #' This value will affect the coordinates of the overlays. 14 | #' res = 2, resolution is 1/2 the size as the raw image 15 | #' res = 3, resolution is 1/4 the size as the raw image 16 | #' res = 4, resolution is 1/8 the size as the raw image 17 | #' resolution = 1/2^(res-1) 18 | #' @param saveFile should xml & image be saved, file is saved in working 19 | #' directory with same name as OME-TIFF 20 | #' @param outline returned coordinates only contain outlinearies, 21 | #' will not work for segmented ROIs 22 | #' @param ... additional parameters for `readLabWorksheet` like `roiCol` and `slideCol` 23 | #' @param segCol additional parameter for `annotMatching` if default search doesn't work. 24 | #' For default search, set to NULL 25 | #' 26 | #' @return \code{\linkS4class{SpatialOverlay}} of slide 27 | #' 28 | #' @examples 29 | #' 30 | #' muBrain_GxT <- readRDS(unzip(system.file("extdata", "muBrain_GxT.zip", 31 | #' package = "SpatialOmicsOverlay"))) 32 | #' 33 | #' image <- downloadMouseBrainImage() 34 | #' 35 | #' muBrain <- readSpatialOverlay(ometiff = image, annots = muBrain_GxT[,1:5], 36 | #' slideName = "D5761 (3)", image = TRUE, res = 8, 37 | #' saveFile = FALSE, outline = FALSE) 38 | #' 39 | #' @importFrom readxl read_xlsx 40 | #' @importFrom data.table fread 41 | #' @importFrom GeomxTools sData 42 | #' 43 | #' @seealso \code{\link{SpatialOverlay-class}} 44 | #' 45 | #' @export 46 | #' 47 | 48 | readSpatialOverlay <- function(ometiff, annots, slideName, image = FALSE, 49 | res = NULL, saveFile = FALSE, outline = TRUE, ..., 50 | segCol = NULL){ 51 | labWorksheet <- FALSE 52 | if(is(annots,"NanoStringGeoMxSet")){ 53 | annots <- sData(annots) 54 | annots <- annots[annots$`slide name` == slideName,] 55 | 56 | if(nrow(annots) == 0){ 57 | stop("No ROIs match given slideName") 58 | } 59 | 60 | annots$Sample_ID <- gsub(".dcc", "", rownames(annots)) 61 | 62 | labWorksheet <- TRUE 63 | colnames(annots)[colnames(annots) == "roi"] <- "ROILabel" 64 | }else if(endsWith(tolower(annots), "_labworksheet.txt")){ 65 | annots <- readLabWorksheet(lw = annots, slideName = slideName, ...) 66 | labWorksheet <- TRUE 67 | }else if(endsWith(annots, ".xlsx")){ 68 | annots <- readxl::read_xlsx(annots, sheet = "SegmentProperties") 69 | }else{ 70 | annots <- as.data.frame(data.table::fread(file = annots)) 71 | } 72 | 73 | if(image == TRUE & is.null(res)){ 74 | warning("No res was given so default res of 6 will be used") 75 | res <- 6 76 | } 77 | 78 | message("Extracting XML") 79 | xml <- xmlExtraction(ometiff = ometiff, saveFile = saveFile) 80 | 81 | message("Parsing XML - scan metadata") 82 | scan_metadata <- parseScanMetadata(omexml = xml) 83 | 84 | message("Parsing XML - overlay data") 85 | AOIattrs <- parseOverlayAttrs(omexml = xml, annots = annots, 86 | labworksheet = labWorksheet, segCol = segCol) 87 | 88 | if(any(meta(AOIattrs)$Segmentation == "Segmented")){ 89 | scan_metadata[["Segmentation"]] <- "Segmented" 90 | }else{ 91 | scan_metadata[["Segmentation"]] <- "Geometric" 92 | } 93 | 94 | so <- SpatialOverlay(slideName = slideName, 95 | scanMetadata = scan_metadata, 96 | overlayData = AOIattrs, 97 | workflow = list(labWorksheet=labWorksheet, 98 | outline=outline, 99 | scaled=FALSE), 100 | image = list(filePath = NULL, 101 | imagePointer = NULL, 102 | resolution = NULL)) 103 | 104 | if(image == TRUE){ 105 | message("Adding Image") 106 | so <- addImageOmeTiff(overlay = so, ometiff = ometiff, res = res, 107 | scanMeta = scan_metadata, saveFile = saveFile) 108 | so <- cropTissue(overlay = so) 109 | }else{ 110 | message("Generating Coordinates") 111 | so <- createCoordFile(overlay = so, outline = outline) 112 | } 113 | 114 | return(so) 115 | } 116 | 117 | -------------------------------------------------------------------------------- /R/removeSamples.R: -------------------------------------------------------------------------------- 1 | #' Remove sample(s) from SpatialOverlay 2 | #' 3 | #' @param overlay SpatialOverlay object 4 | #' @param remove sampNames of overlay to remove 5 | #' 6 | #' @return SpatialOverlay object without samples in remove 7 | #' 8 | #' @examples 9 | #' 10 | #' muBrain <- readRDS(unzip(system.file("extdata", "muBrainSubset_SpatialOverlay.zip", 11 | #' package = "SpatialOmicsOverlay"))) 12 | #' 13 | #' muBrainLW <- system.file("extdata", "muBrain_LabWorksheet.txt", 14 | #' package = "SpatialOmicsOverlay") 15 | #' 16 | #' muBrainLW <- readLabWorksheet(muBrainLW, slideName = "D5761 (3)") 17 | #' 18 | #' samps <- muBrainLW$Sample_ID[muBrainLW$segment != "Full ROI"] 19 | #' 20 | #' muBrainSub <- removeSample(overlay = muBrain, remove = samps) 21 | #' 22 | #' muBrain 23 | #' muBrainSub 24 | #' 25 | #' @export 26 | #' 27 | 28 | removeSample <- function(overlay, remove){ 29 | w2kp <- which(!sampNames(overlay) %in% remove) 30 | 31 | if(length(w2kp) == length(sampNames(overlay))){ 32 | warning("No valid sample names; returning original overlay") 33 | return(overlay) 34 | }else{ 35 | AOIattrs <- SpatialPosition(spatialPos(overlay(overlay))[w2kp,]) 36 | 37 | scan_metadata <- scanMeta(overlay) 38 | 39 | if(any(meta(AOIattrs)$Segmentation == "Segmented")){ 40 | scan_metadata[["Segmentation"]] <- "Segmented" 41 | }else{ 42 | scan_metadata[["Segmentation"]] <- "Geometric" 43 | } 44 | 45 | if(!is.null(coords(overlay))){ 46 | newCoords <- coords(overlay)[!coords(overlay)$sampleID %in% remove,] 47 | }else{ 48 | newCoords <- coords(overlay) 49 | } 50 | 51 | if(!is.null(plotFactors(overlay))){ 52 | plotFacts <- as.data.frame(plotFactors(overlay)[w2kp,]) 53 | colnames(plotFacts) <- colnames(plotFactors(overlay)) 54 | rownames(plotFacts) <- rownames(plotFactors(overlay))[w2kp] 55 | 56 | for(i in seq_len(ncol(plotFacts))){ 57 | if(is(plotFacts[,i],"character")){ 58 | plotFacts[,i] <- as.factor(plotFacts[,i]) 59 | } 60 | } 61 | }else{ 62 | plotFacts <- plotFactors(overlay) 63 | } 64 | 65 | return(SpatialOverlay(slideName = slideName(overlay), 66 | scanMetadata = scan_metadata, 67 | overlayData = AOIattrs, 68 | coords = newCoords, 69 | plottingFactors = plotFacts, 70 | workflow = workflow(overlay), 71 | image = imageInfo(overlay))) 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /R/utils.R: -------------------------------------------------------------------------------- 1 | URL <- "https://external-soa-downloads-p-1.s3.us-west-2.amazonaws.com" 2 | IMAGES <- "mu_brain_image_files.tar.gz" 3 | IMAGEFILE <- "image_files/mu_brain_004.ome.tiff" 4 | 5 | #' Print long string in more managable fashion 6 | #' 7 | #' @description 8 | #' Print first and last n characters of string in this format: 9 | #' "### ... ### (x total char)" 10 | #' 11 | #' @param x long string 12 | #' @param bookend number of characters on either side to print 13 | #' 14 | #' @return reformatted string 15 | #' 16 | #' @examples 17 | #' 18 | #' start_string <- stringi::stri_rand_strings(n = 1, length = 250) 19 | #' bookendStr(start_string, bookend = 6) 20 | #' 21 | #' @export 22 | bookendStr <- function(x, bookend = 8){ 23 | if(!is(x,"character")){ 24 | x <- as.character(x) 25 | } 26 | if(nchar(x) > bookend*2){ 27 | x <- paste(substr(x = x, start = 1, stop = bookend), "...", 28 | substr(x = x, start = nchar(x)-(bookend-1), stop = nchar(x)), 29 | paste0("(", nchar(x), " total char)")) 30 | } 31 | 32 | return(x) 33 | } 34 | 35 | #' Read lab worksheet into dataframe of annotations 36 | #' 37 | #' @param lw lab worksheet file path 38 | #' @param slideName name of slide 39 | #' @param roiCol column containing ROI information, if NULL function will determine automatically 40 | #' @param slideCol column containing slide name, if NULL function will determine automatically 41 | #' 42 | #' @return df of ROI annotations 43 | #' 44 | #' @examples 45 | #' 46 | #' muBrainLW <- system.file("extdata", "muBrain_LabWorksheet.txt", 47 | #' package = "SpatialOmicsOverlay") 48 | #' 49 | #' muBrainLW <- readLabWorksheet(muBrainLW, slideName = "D5761 (3)") 50 | #' 51 | #' @export 52 | readLabWorksheet <- function(lw, slideName, roiCol = NULL, slideCol = NULL){ 53 | if(!file.exists(lw)){ 54 | stop("Lab worksheet path is invalid") 55 | } 56 | 57 | startLine <- grep(readLines(lw), pattern = "^Annotations") 58 | 59 | lw <- read.table(lw, header = TRUE, sep = "\t", skip = startLine, 60 | fill = TRUE) 61 | 62 | if(is.null(roiCol)){ 63 | roiCol <- colnames(lw)[grepl("^roi$", tolower(colnames(lw)))] 64 | if(length(roiCol) > 1L){ 65 | warning("First matched ROI column used. If not correct specify roiCol in fuction call") 66 | roiCol <- roiCol[1L] 67 | } 68 | }else if(!roiCol %in% colnames(lw)){ 69 | stop("Provided roiCol not valid") 70 | } 71 | 72 | if(is.null(slideCol)){ 73 | slideCol <- colnames(lw)[grepl("^slide", tolower(colnames(lw)))] 74 | if(length(slideCol) > 1L){ 75 | warning("First matched ROI column used. If not correct specify slideCol in fuction call") 76 | slideCol <- slideCol[1L] 77 | } 78 | }else if(!slideCol %in% colnames(lw)){ 79 | stop("Provided slideCol not valid") 80 | } 81 | 82 | lw$ROILabel <- gsub("\\W", "", lw[[roiCol]]) 83 | lw <- lw[lw[[slideCol]] == slideName,] 84 | 85 | if(nrow(lw) == 0){ 86 | stop("No ROIs match given slideName") 87 | } 88 | 89 | return(lw) 90 | } 91 | 92 | 93 | #' Download Mouse Brain OME-TIFF from NanoString's Spatial Organ Atlas 94 | #' 95 | #' @details https://nanostring.com/products/geomx-digital-spatial-profiler/spatial-organ-atlas/mouse-brain/ 96 | #' 97 | #' @return mouse brain OME-TIFF 98 | #' 99 | #' @importFrom BiocFileCache bfcquery 100 | #' @importFrom BiocFileCache bfcrpath 101 | #' @importFrom BiocFileCache bfcadd 102 | #' @importFrom BiocFileCache bfccache 103 | #' @importFrom BiocFileCache bfcremove 104 | #' 105 | #' @examples 106 | #' 107 | #' image <- downloadMouseBrainImage() 108 | #' 109 | #' @export 110 | downloadMouseBrainImage <- function(){ 111 | fileURL <- paste(URL, IMAGES, sep = "/") 112 | 113 | bfc <- .get_cache() 114 | rid <- bfcquery(bfc, IMAGEFILE)$rid 115 | 116 | if (length(rid) == 0) { 117 | if(interactive()){ 118 | continue <- readline(prompt = "This function will temporarily download a 13 GB tar file and keep a 4 GB OME-TIFF in BiocFileCache, should we continue? (y/n): ") 119 | }else{ 120 | continue <- "y" 121 | } 122 | 123 | if(tolower(continue) %in% c("y", "yes", "true")){ 124 | message("Downloading file") 125 | rid <- names(bfcadd(bfc, IMAGES, fileURL)) 126 | 127 | message( "Untaring file" ) 128 | untar(bfcrpath(bfc, rids = rid), 129 | files = IMAGEFILE, 130 | exdir = bfccache(bfc)) 131 | 132 | bfcremove(x = bfc, rid) 133 | 134 | imageFile <- paste(bfccache(bfc), IMAGEFILE, sep = "/") 135 | 136 | rid <- names(bfcadd(bfc, rname = basename(IMAGEFILE), 137 | fpath = imageFile)) 138 | 139 | unlink(dirname(imageFile), recursive = TRUE) 140 | }else{ 141 | message("Mouse Brain file not downloaded, please provide your own NanoString GeoMx OME-TIFF to use this package") 142 | } 143 | } 144 | 145 | if(length(rid) >0){ 146 | return(normalizePath(bfcrpath(bfc, rids=rid))) 147 | } 148 | } 149 | 150 | #' get BiocFileCache 151 | #' 152 | #' @importFrom tools R_user_dir 153 | #' @importFrom BiocFileCache BiocFileCache 154 | #' 155 | #' @return BioFileCache 156 | #' 157 | #' @noRd 158 | #' 159 | .get_cache <- function(){ 160 | cache <- R_user_dir("SpatialOmicsOverlay", which="cache") 161 | 162 | return(BiocFileCache(cache)) 163 | } 164 | 165 | -------------------------------------------------------------------------------- /R/xmlParsing.R: -------------------------------------------------------------------------------- 1 | COLORS <- c(Blue = "#0000feff", 2 | Red = "#fe0000ff", 3 | Green = "#00fe00ff", 4 | Purple = "#7f00feff", 5 | Yellow = "#fefe00ff", 6 | GreenYellow = "#7ffe00ff", 7 | Cyan = "#00fefeff", 8 | Magenta = "#fe00feff", 9 | Grey = "#7f7f7fff") 10 | 11 | #' Parse the xml file for the scan metadata of GeoMx images 12 | #' 13 | #' @param omexml xml file from OME-TIFF, can provide path to OME-TIFF and 14 | #' xml will automatically be extracted 15 | #' 16 | #' @return metadata for entire scan 17 | #' 18 | #' @importFrom XML xmlToList 19 | #' 20 | #' @examples 21 | #' 22 | #' image <- downloadMouseBrainImage() 23 | #' 24 | #' xml <- xmlExtraction(ometiff = image) 25 | #' 26 | #' scan_metadata <- parseScanMetadata(omexml = xml) 27 | #' 28 | #' @export 29 | #' 30 | 31 | parseScanMetadata <- function(omexml){ 32 | if(any(is(omexml,"XMLInternalDocument"))){ 33 | omexml <- xmlToList(omexml) 34 | } 35 | 36 | if(is(omexml,"character")){ 37 | if(endsWith(omexml, suffix = ".ome.tiff")){ 38 | omexml <- xmlExtraction(ometiff = omexml) 39 | } 40 | } 41 | 42 | panels <- omexml$Screen$Reagent[["ReagentIdentifier"]] 43 | 44 | scanMetadata <- list(Panels=panels, 45 | PhysicalSizes=physicalSizes(omexml), 46 | Fluorescence=fluorData(omexml)) 47 | 48 | return(scanMetadata) 49 | } 50 | 51 | #' Parse the xml file for AOI attributes in GeoMx images 52 | #' 53 | #' @param omexml xml file from OME-TIFF, can provide path to OME-TIFF and xml 54 | #' will automatically be extracted 55 | #' @param annots df of annotations 56 | #' @param labworksheet annots are from lab worksheet file 57 | #' @param ... segCol in annotMatching, if auto detection doesn't work. 58 | #' 59 | #' @return SpatialPosition of AOIs containing metadata and base64encoded positions 60 | #' 61 | #' @importFrom XML xmlToList 62 | #' 63 | #' @examples 64 | #' 65 | #' image <- downloadMouseBrainImage() 66 | #' 67 | #' xml <- xmlExtraction(ometiff = image) 68 | #' 69 | #' muBrainLW <- system.file("extdata", "muBrain_LabWorksheet.txt", 70 | #' package = "SpatialOmicsOverlay") 71 | #' 72 | #' muBrainLW <- readLabWorksheet(muBrainLW, slideName = "D5761 (3)") 73 | #' 74 | #' overlay <- parseOverlayAttrs(omexml = xml, 75 | #' annots = muBrainLW, 76 | #' labworksheet = TRUE) 77 | #' 78 | #' @export 79 | #' 80 | 81 | parseOverlayAttrs <- function(omexml, annots, labworksheet, ...){ 82 | if(!is(annots,"data.frame")){ 83 | stop("File must be read into R and passed as a dataframe") 84 | } 85 | 86 | if(any(is(omexml,"XMLInternalDocument"))){ 87 | omexml <- xmlToList(omexml) 88 | } 89 | 90 | if(is(omexml,"character")){ 91 | if(endsWith(omexml, suffix = ".ome.tiff")){ 92 | omexml <- xmlExtraction(ometiff = omexml) 93 | } 94 | } 95 | 96 | ROIs <- omexml[which(names(omexml) == "ROI")] 97 | names(ROIs) <- paste0(names(ROIs), 0:(length(ROIs)-1)) 98 | 99 | AOIattrs <- NULL 100 | 101 | # Time trial with lapply showed minimal time difference 102 | for(ROI in names(ROIs)){ 103 | ROInum <- ROIs[[ROI]]$AnnotationRef 104 | ROInum <- as.numeric(gsub("Annotation:", "", ROInum)) 105 | 106 | ROInum <- omexml$StructuredAnnotations[ROInum]$XMLAnnotation$Value$ChannelThresholds$RoiName 107 | ROInum <- gsub("\\W", "", ROInum) 108 | 109 | ROI <- ROIs[[ROI]]$Union 110 | 111 | masks <- which(names(ROI) == "Mask") 112 | 113 | for(mask in masks){ 114 | 115 | maskNum <- which(masks == mask) 116 | 117 | segmentation <- ifelse(length(masks) == 1, "Geometric", "Segmented") 118 | 119 | mask.attrs <- ROI[[mask]]$.attrs 120 | 121 | if(labworksheet == TRUE & !"Text" %in% names(mask.attrs)){ 122 | stop("Scan was not exported on version 2.4+, please use DA annotation instead of Lab Worksheet") 123 | }else if(labworksheet == TRUE){ 124 | maskText <- mask.attrs[["Text"]] 125 | }else{ 126 | maskText <- NULL 127 | } 128 | 129 | ROIannot <- annotMatching(annots, ROInum, maskNum, maskText, ...) 130 | 131 | if(is.null(ROIannot) ){ 132 | next 133 | }else if(nrow(ROIannot) == 0){ 134 | next 135 | } 136 | 137 | AOIattr <- as.data.frame(c(ROILabel=ROInum, 138 | ROIannot, 139 | mask.attrs[c("Height", "Width", "X", "Y")], 140 | Segmentation=segmentation)) 141 | 142 | AOIattr$Height <- as.numeric(AOIattr$Height) 143 | AOIattr$Width <- as.numeric(AOIattr$Width) 144 | AOIattr$X <- as.numeric(AOIattr$X) 145 | AOIattr$Y <- as.numeric(AOIattr$Y) 146 | 147 | AOIattrs <- rbind(AOIattrs, 148 | cbind(AOIattr, 149 | Position=ROI[[mask]]$BinData$text)) 150 | } 151 | } 152 | 153 | if(nrow(AOIattrs) < nrow(annots)){ 154 | names(annots)[names(annots) == "SegmentDisplayName"] <- "Sample_ID" 155 | warning(paste("Some AOIs do not match annotation file. \nNot Matched:", 156 | paste(annots$Sample_ID[!annots$Sample_ID %in% AOIattrs$Sample_ID], 157 | collapse = ", "))) 158 | } 159 | 160 | return(SpatialPosition(position = AOIattrs)) 161 | } 162 | 163 | #' Parse physicalSize data from xml 164 | #' 165 | #' @param omexml xml file from OME-TIFF 166 | #' 167 | #' @return physicalSizes info from xml 168 | #' 169 | #' @noRd 170 | physicalSizes <- function(omexml){ 171 | physicalSizeX <- as.numeric(omexml$Image$Pixels$.attrs[["PhysicalSizeX"]]) 172 | names(physicalSizeX) <- paste0(omexml$Image$Pixels$.attrs[["PhysicalSizeXUnit"]], 173 | "/pixel") 174 | 175 | physicalSizeY <- as.numeric(omexml$Image$Pixels$.attrs[["PhysicalSizeY"]]) 176 | names(physicalSizeY) <- paste0(omexml$Image$Pixels$.attrs[["PhysicalSizeYUnit"]], 177 | "/pixel") 178 | 179 | return(list(X=physicalSizeX, 180 | Y=physicalSizeY)) 181 | } 182 | 183 | #' Parse fluorescence data from xml 184 | #' 185 | #' @param omexml xml file from OME-TIFF 186 | #' 187 | #' @return fluorescence info from xml 188 | #' 189 | #' @noRd 190 | #' 191 | fluorData <- function(omexml){ 192 | fluorescence <- NULL 193 | planeLine <- min(which(names(omexml$Image$Pixels) == "Plane"))-1 194 | addition <- 0 195 | 196 | for(chan in seq_len(length(which(names(omexml$Image$Pixels) == "Channel")))){ 197 | fluor <- omexml$Image$Pixels[chan]$Channel$.attrs 198 | exposure <- omexml$Image$Pixels[planeLine + chan]$Plane 199 | 200 | hex <- paste(as.hexmode(as.integer(fluor[["Color"]]))) 201 | 202 | if(nchar(hex) != 8){ 203 | hex <- paste0(paste(rep(0, 8-nchar(hex)), collapse = ""), hex) 204 | } 205 | 206 | colorCode <- paste0("#", hex) 207 | col <- names(which(COLORS == colorCode)) 208 | 209 | if(identical(col, character(0))){ 210 | col <- fluorAnnots[["Name"]] 211 | } 212 | 213 | chan <- chan + addition 214 | 215 | # Some xml files have 2 lines per Fluor. The addition catches this and keeps 216 | # grabbing correct line needed info is only in ChannelInfo 217 | if(names(omexml$StructuredAnnotations[chan]$XMLAnnotation$Value) != "ChannelInfo"){ 218 | addition <- addition + 1 219 | 220 | chan <- chan + 1 221 | } 222 | 223 | fluorAnnots <- omexml$StructuredAnnotations[chan]$XMLAnnotation$Value$ChannelInfo 224 | 225 | if(fluor[["Fluor"]] != fluorAnnots[["Dye"]]){ 226 | stop("Fluor and Dye doesn't match") 227 | } 228 | 229 | if(names(omexml$StructuredAnnotations[chan+1]$XMLAnnotation$Value) == "ChannelInfo"){ 230 | fluorescence <- as.data.frame(rbind(fluorescence, 231 | c(Dye = fluor[["Fluor"]], 232 | DisplayName = fluorAnnots[["DyeDisplayName"]], 233 | Color = col, 234 | WaveLength = fluorAnnots[["DyeWavelength"]], 235 | Target = fluorAnnots[["BiologicalTarget"]], 236 | ExposureTime = paste(exposure[["ExposureTime"]], 237 | exposure[["ExposureTimeUnit"]]), 238 | ColorCode = colorCode))) 239 | }else{ 240 | intensities <- omexml$StructuredAnnotations[chan+1]$XMLAnnotation$Value$ChannelIntensity 241 | 242 | if(is.null(intensities)){ 243 | fluorescence <- as.data.frame(rbind(fluorescence, 244 | c(Dye = fluor[["Fluor"]], 245 | DisplayName = fluorAnnots[["DyeDisplayName"]], 246 | Color = col, 247 | WaveLength = fluorAnnots[["DyeWavelength"]], 248 | Target = fluorAnnots[["BiologicalTarget"]], 249 | ExposureTime = paste(exposure[["ExposureTime"]], 250 | exposure[["ExposureTimeUnit"]]), 251 | ColorCode = colorCode))) 252 | }else{ 253 | fluorescence <- as.data.frame(rbind(fluorescence, 254 | c(Dye = fluor[["Fluor"]], 255 | DisplayName = fluorAnnots[["DyeDisplayName"]], 256 | Color = col, 257 | WaveLength = fluorAnnots[["DyeWavelength"]], 258 | Target = fluorAnnots[["BiologicalTarget"]], 259 | ExposureTime = paste(exposure[["ExposureTime"]], 260 | exposure[["ExposureTimeUnit"]]), 261 | MinIntensity = intensities[["Minintensity"]], 262 | MaxIntensity = intensities[["Maxintensity"]], 263 | ColorCode = colorCode))) 264 | } 265 | } 266 | 267 | 268 | rm(fluor, exposure, fluorAnnots) 269 | 270 | if(addition != 0){ 271 | addition <- addition + 1 272 | } 273 | } 274 | 275 | return(fluorescence) 276 | } 277 | 278 | #' Decode a base 64 string into 8 bit binary image mask 279 | #' 280 | #' @param b64string base 64 string 281 | #' @param width width of image 282 | #' @param height height of image 283 | #' 284 | #' @return binary vector mask 285 | #' 286 | #' @importFrom base64enc base64decode 287 | #' 288 | #' @noRd 289 | decodeB64 <- function(b64string, width, height){ 290 | # rawToBits returns the reverse of the actual binary sequence, needs to be 291 | # reversed for real image 292 | # example from https://kb.iu.edu/d/afdl 293 | # Dec Hex Bin 294 | # 192 c0 11000000 295 | # rawToBits(as.raw(192)) 296 | # returns 00 00 00 00 00 00 01 01 297 | 298 | base8 <- vapply(X = base64decode(b64string), 299 | FUN = function(x){rev(rawToBits(x))}, 300 | FUN.VALUE = raw(8)) 301 | 302 | base8 <- base8[seq_len((width*height))] 303 | 304 | return(base8) 305 | } 306 | 307 | #' Match ROIs in annotation file to xml 308 | #' 309 | #' @param annots df of annotations 310 | #' @param ROInum ROI number from xml file 311 | #' @param maskNum number of masks for ROI, used for AOI matching in software 312 | #' <= v2.4 313 | #' @param maskText segment name, used for AOI matching in software v2.4+ 314 | #' @param segCol column containing segment name, if NULL function will determine automatically 315 | #' 316 | #' @return df with ROI unique identifiers 317 | #' 318 | #' 319 | 320 | annotMatching <- function(annots, ROInum, maskNum, maskText, segCol = NULL){ 321 | if(!"ROILabel" %in% colnames(annots)){ 322 | stop("The column ROILabel is not in annots. ") 323 | } 324 | 325 | if(suppressWarnings(!is.na(as.numeric(ROInum)))){ 326 | ROInum <- as.numeric(ROInum) 327 | annots$ROILabel <- as.numeric(annots$ROILabel) 328 | } 329 | 330 | w2kp <- which(annots$ROILabel == ROInum) 331 | 332 | if(length(w2kp) == 0){ 333 | return(NULL) 334 | } 335 | 336 | annots <- annots[w2kp,] 337 | 338 | if(!is.null(maskText)){ 339 | if(is.null(segCol)){ 340 | segCol <- colnames(annots)[grepl("^segment", tolower(colnames(annots)))] 341 | if(length(segCol) > 1L){ 342 | warning("First matched ROI column used. If not correct specify segCol in fuction call") 343 | segCol <- segCol[1L] 344 | } 345 | }else if(!segCol %in% colnames(annots)){ 346 | stop("Provided segCol not valid") 347 | } 348 | 349 | annots <- annots[which(annots[[segCol]] == maskText),] 350 | annots <- as.data.frame(annots[,c("Sample_ID")]) 351 | colnames(annots) <- "Sample_ID" 352 | }else{ 353 | if(nrow(annots) < maskNum){ 354 | stop("incorrect number of masks in annotation, was this file filtered?") 355 | } 356 | 357 | if(!"SegmentID" %in% colnames(annots)){ 358 | stop("Please change labWorksheet to TRUE") 359 | } 360 | 361 | #sort by SegmentID 362 | #software versions #### missing the segment ID value in xml 363 | #software versions #### will match on segment ID 364 | annots <- annots[order(annots$SegmentID), ] 365 | 366 | annots <- annots[maskNum,] 367 | if("SegmentDisplayName" %in% colnames(annots)){ 368 | sampCol <- "SegmentDisplayName" 369 | } 370 | if("Sample_ID" %in% colnames(annots)){ 371 | sampCol <- "Sample_ID" 372 | } 373 | 374 | annots <- annots[,c(sampCol, "SegmentID")] 375 | colnames(annots) <- c("Sample_ID", "SegmentID") 376 | } 377 | 378 | return(annots) 379 | } 380 | 381 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SpatialOmicsOverlay 2 | 3 | ## Overview 4 | 5 | The SpatialOmicsOverlay package contains tools for analyzing data on the image from 6 | NanoString GeoMx Digital Spatial Profiler (DSP). It provides functions 7 | to extract image and XML from OME-TIFFs, overlay Regions of Interest (ROIs) onto 8 | the image, and manipulate the image (coloring, orientation, cropping). Output 9 | figures are ggplot based allowing for easy customization of images to include 10 | spatial images into data visualization. 11 | 12 | ## Installation 13 | 14 | ### Download the release version from Bioconductor 15 | 16 | 17 | ### Install the release version from Bioconductor 18 | ``` r 19 | if (!requireNamespace("BiocManager", quietly=TRUE)) 20 | install.packages("BiocManager") 21 | 22 | BiocManager::install(version="release") 23 | 24 | BiocManager::install("SpatialOmicsOverlay") 25 | ``` 26 | 27 | ### Install the development version from GitHub 28 | ``` r 29 | install.packages("devtools") 30 | library("devtools") 31 | devtools::install_github("Nanostring-Biostats/SpatialOmicsOverlay", 32 | build_vignettes = TRUE, ref = "dev") 33 | ``` 34 | 35 | ## Documentation 36 | 37 | To learn how to start using SpatialOmicsOverlay, view documentation for the 38 | version of this package installed in your system, start R and enter: 39 | 40 | ``` r 41 | browseVignettes("SpatialOmicsOverlay") 42 | ``` 43 | 44 | or download vignette from NanoString website 45 | (pending) 46 | 47 | ## Branches 48 | The dev branch on GitHub is under active development and no guarantee 49 | is made on usability at any given time. 50 | 51 | 52 | ## Citation 53 | Griswold, M. 54 | SpatialOmicsOverlay: Spatial Overlay for Omic Data From Nanostring GeoMx data. 55 | R Package Version 0.99.10. 56 | NanoString Technologies Inc.; Seattle, WA 98109, USA. 2021. 57 | 58 | ## License 59 | This project is licensed under the [MIT license](LICENSE). 60 | -------------------------------------------------------------------------------- /inst/extdata/muBrainSubset_SpatialOverlay.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Nanostring-Biostats/SpatialOmicsOverlay/fa91a50f1b6b668920697ed685b16717f2fb0454/inst/extdata/muBrainSubset_SpatialOverlay.zip -------------------------------------------------------------------------------- /inst/extdata/muBrain_GxT.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Nanostring-Biostats/SpatialOmicsOverlay/fa91a50f1b6b668920697ed685b16717f2fb0454/inst/extdata/muBrain_GxT.zip -------------------------------------------------------------------------------- /inst/extdata/muBrain_LabWorksheet.txt: -------------------------------------------------------------------------------- 1 | Experiment Summary 2 | Readout group name 04June2021_msWTA 3 | Date 15 Jun 2021 9:58 PM 4 | Readout mode NGS 5 | Number of Collection Plates 1 6 | Number Of AOIs 93 7 | Library Prep Protocol Version 8 | 9 | Library Prep Summary 10 | Library Prep Plate Collection Plate Primer Plate Rows 11 | 04June2021_msWTA-A "=""1012999073013""" GeoMx Seq Code A A - H 12 | Total Area 5572977 13 | 14 | Annotations 15 | Sample_ID slide name scan name panel roi segment aoi area tags 16 | DSP-1012999073013-A-A01 No Template Control 17 | DSP-1012999073013-A-A02 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""001""" Full ROI Full ROI-aoi-001 70624.23 18 | DSP-1012999073013-A-A03 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""002""" Full ROI Full ROI-aoi-001 81013.22 19 | DSP-1012999073013-A-A04 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""003""" Full ROI Full ROI-aoi-001 100893.41 20 | DSP-1012999073013-A-A05 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""004""" Full ROI Full ROI-aoi-001 153435.75 21 | DSP-1012999073013-A-A06 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""005""" Full ROI Full ROI-aoi-001 113976.40 22 | DSP-1012999073013-A-A07 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""006""" Full ROI Full ROI-aoi-001 70624.23 23 | DSP-1012999073013-A-A08 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""007""" Full ROI Full ROI-aoi-001 70624.23 24 | DSP-1012999073013-A-A09 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""008""" Full ROI Full ROI-aoi-001 70624.23 25 | DSP-1012999073013-A-A10 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""009""" Full ROI Full ROI-aoi-001 70624.23 26 | DSP-1012999073013-A-A11 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""010""" Full ROI Full ROI-aoi-001 70624.23 27 | DSP-1012999073013-A-A12 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""011""" Full ROI Full ROI-aoi-001 70624.23 28 | DSP-1012999073013-A-B01 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""012""" Full ROI Full ROI-aoi-001 70624.23 29 | DSP-1012999073013-A-B02 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""013""" Full ROI Full ROI-aoi-001 70624.23 30 | DSP-1012999073013-A-B03 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""014""" Full ROI Full ROI-aoi-001 70624.23 31 | DSP-1012999073013-A-B04 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""015""" Full ROI Full ROI-aoi-001 70624.23 32 | DSP-1012999073013-A-B05 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""016""" Full ROI Full ROI-aoi-001 70624.23 33 | DSP-1012999073013-A-B06 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""017""" Full ROI Full ROI-aoi-001 193581.87 34 | DSP-1012999073013-A-B07 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""018""" Full ROI Full ROI-aoi-001 163940.64 35 | DSP-1012999073013-A-B08 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""019""" DNA DNA-aoi-001 35680.36 36 | DSP-1012999073013-A-B09 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""020""" DNA DNA-aoi-001 19980.58 37 | DSP-1012999073013-A-B10 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""021""" DNA DNA-aoi-001 57667.69 38 | DSP-1012999073013-A-B11 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""022""" Full ROI Full ROI-aoi-001 70624.23 39 | DSP-1012999073013-A-B12 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""023""" Full ROI Full ROI-aoi-001 70624.23 40 | DSP-1012999073013-A-C01 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""024""" Full ROI Full ROI-aoi-001 70624.23 41 | DSP-1012999073013-A-C02 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""025""" Full ROI Full ROI-aoi-001 98671.32 42 | DSP-1012999073013-A-C03 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""026""" Full ROI Full ROI-aoi-001 98603.70 43 | DSP-1012999073013-A-C04 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""027""" Full ROI Full ROI-aoi-001 70624.23 44 | DSP-1012999073013-A-C05 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""028""" Full ROI Full ROI-aoi-001 70624.23 45 | DSP-1012999073013-A-C06 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""029""" Full ROI Full ROI-aoi-001 70624.23 46 | DSP-1012999073013-A-C07 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""030""" Full ROI Full ROI-aoi-001 28910.82 47 | DSP-1012999073013-A-C08 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""031""" Full ROI Full ROI-aoi-001 34682.66 48 | DSP-1012999073013-A-C09 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""032""" Full ROI Full ROI-aoi-001 42324.89 49 | DSP-1012999073013-A-C10 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""033""" Full ROI Full ROI-aoi-001 31383.73 50 | DSP-1012999073013-A-C11 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""034""" Full ROI Full ROI-aoi-001 31383.73 51 | DSP-1012999073013-A-C12 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""035""" NeuN+ NeuN+-aoi-001 187.84 52 | DSP-1012999073013-A-D01 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""036""" Full ROI Full ROI-aoi-001 31383.73 53 | DSP-1012999073013-A-D02 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""037""" Full ROI Full ROI-aoi-001 31383.73 54 | DSP-1012999073013-A-D03 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""038""" Full ROI Full ROI-aoi-001 31383.73 55 | DSP-1012999073013-A-D04 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""039""" Full ROI Full ROI-aoi-001 31383.73 56 | DSP-1012999073013-A-D05 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""040""" Full ROI Full ROI-aoi-001 70624.23 57 | DSP-1012999073013-A-D06 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""041""" Full ROI Full ROI-aoi-001 70624.23 58 | DSP-1012999073013-A-D07 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""042""" Full ROI Full ROI-aoi-001 70624.23 59 | DSP-1012999073013-A-D08 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""043""" Full ROI Full ROI-aoi-001 43677.00 60 | DSP-1012999073013-A-D09 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""044""" Full ROI Full ROI-aoi-001 182449.84 61 | DSP-1012999073013-A-D10 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""045""" Full ROI Full ROI-aoi-001 60118.71 62 | DSP-1012999073013-A-D11 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""046""" Full ROI Full ROI-aoi-001 120949.92 63 | DSP-1012999073013-A-D12 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""047""" Full ROI Full ROI-aoi-001 141720.70 64 | DSP-1012999073013-A-E01 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""048""" NeuN+ NeuN+-aoi-001 6847.39 65 | DSP-1012999073013-A-E02 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""048""" DNA DNA-aoi-001 39238.42 66 | DSP-1012999073013-A-E03 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""049""" NeuN+ NeuN+-aoi-001 24080.25 67 | DSP-1012999073013-A-E04 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""049""" DNA DNA-aoi-001 65319.99 68 | DSP-1012999073013-A-E05 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""050""" NeuN+ NeuN+-aoi-001 14484.19 69 | DSP-1012999073013-A-E06 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""050""" DNA DNA-aoi-001 28672.31 70 | DSP-1012999073013-A-E07 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""051""" NeuN+ NeuN+-aoi-001 12773.98 71 | DSP-1012999073013-A-E08 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""051""" DNA DNA-aoi-001 68801.00 72 | DSP-1012999073013-A-E09 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""052""" NeuN+ NeuN+-aoi-001 17982.30 73 | DSP-1012999073013-A-E10 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""052""" DNA DNA-aoi-001 75677.65 74 | DSP-1012999073013-A-E11 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""053""" Full ROI Full ROI-aoi-001 34093.25 75 | DSP-1012999073013-A-E12 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""054""" Full ROI Full ROI-aoi-001 153498.42 76 | DSP-1012999073013-A-F01 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""055""" Full ROI Full ROI-aoi-001 59683.40 77 | DSP-1012999073013-A-F02 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""056""" Full ROI Full ROI-aoi-001 144684.39 78 | DSP-1012999073013-A-F03 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""057""" Full ROI Full ROI-aoi-001 117561.95 79 | DSP-1012999073013-A-F04 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""058""" NeuN+ NeuN+-aoi-001 7553.35 80 | DSP-1012999073013-A-F05 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""058""" DNA DNA-aoi-001 34406.58 81 | DSP-1012999073013-A-F06 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""059""" NeuN+ NeuN+-aoi-001 28746.80 82 | DSP-1012999073013-A-F07 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""059""" DNA DNA-aoi-001 35946.21 83 | DSP-1012999073013-A-F08 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""060""" NeuN+ NeuN+-aoi-001 9160.76 84 | DSP-1012999073013-A-F09 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""060""" DNA DNA-aoi-001 11229.06 85 | DSP-1012999073013-A-F10 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""061""" NeuN+ NeuN+-aoi-001 14309.62 86 | DSP-1012999073013-A-F11 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""061""" DNA DNA-aoi-001 74500.74 87 | DSP-1012999073013-A-F12 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""062""" NeuN+ NeuN+-aoi-001 15432.97 88 | DSP-1012999073013-A-G01 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""062""" DNA DNA-aoi-001 50511.61 89 | DSP-1012999073013-A-G02 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""063""" NeuN+ NeuN+-aoi-001 1168.91 90 | DSP-1012999073013-A-G03 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""064""" Full ROI Full ROI-aoi-001 134973.22 91 | DSP-1012999073013-A-G04 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""065""" Full ROI Full ROI-aoi-001 102930.06 92 | DSP-1012999073013-A-G05 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""066""" Full ROI Full ROI-aoi-001 159717.55 93 | DSP-1012999073013-A-G06 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""067""" Full ROI Full ROI-aoi-001 191969.02 94 | DSP-1012999073013-A-G07 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""068""" NeuN+ NeuN+-aoi-001 10100.44 95 | DSP-1012999073013-A-G08 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""068""" DNA DNA-aoi-001 32479.75 96 | DSP-1012999073013-A-G09 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""069""" NeuN+ NeuN+-aoi-001 15459.67 97 | DSP-1012999073013-A-G10 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""069""" DNA DNA-aoi-001 39632.16 98 | DSP-1012999073013-A-G11 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""070""" NeuN+ NeuN+-aoi-001 7524.41 99 | DSP-1012999073013-A-G12 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""070""" DNA DNA-aoi-001 18408.65 100 | DSP-1012999073013-A-H01 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""071""" NeuN+ NeuN+-aoi-001 14727.50 101 | DSP-1012999073013-A-H02 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""071""" DNA DNA-aoi-001 71368.23 102 | DSP-1012999073013-A-H03 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""072""" NeuN+ NeuN+-aoi-001 12480.95 103 | DSP-1012999073013-A-H04 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""072""" DNA DNA-aoi-001 42711.75 104 | DSP-1012999073013-A-H05 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""073""" NeuN+ NeuN+-aoi-001 5238.70 105 | DSP-1012999073013-A-H06 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""073""" DNA DNA-aoi-001 39285.10 106 | DSP-1012999073013-A-H07 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""074""" NeuN+ NeuN+-aoi-001 6437.03 107 | DSP-1012999073013-A-H08 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""074""" DNA DNA-aoi-001 34464.77 108 | DSP-1012999073013-A-H09 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""075""" NeuN+ NeuN+-aoi-001 6649.48 109 | DSP-1012999073013-A-H10 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""075""" DNA DNA-aoi-001 36174.66 110 | -------------------------------------------------------------------------------- /inst/extdata/muBrain_subset_LabWorksheet.txt: -------------------------------------------------------------------------------- 1 | Experiment Summary 2 | Readout group name 04June2021_msWTA 3 | Date 15 Jun 2021 9:58 PM 4 | Readout mode NGS 5 | Number of Collection Plates 1 6 | Number Of AOIs 93 7 | Library Prep Protocol Version 8 | 9 | Library Prep Summary 10 | Library Prep Plate Collection Plate Primer Plate Rows 11 | 04June2021_msWTA-A "=""1012999073013""" GeoMx Seq Code A A - H 12 | Total Area 5572977 13 | 14 | Annotations 15 | Sample_ID slide name scan name panel roi segment aoi area tags 16 | DSP-1012999073013-A-A01 No Template Control 17 | DSP-1012999073013-A-A02 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""001""" Full ROI Full ROI-aoi-001 70624.23 18 | DSP-1012999073013-A-A03 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""002""" Full ROI Full ROI-aoi-001 81013.22 19 | DSP-1012999073013-A-A04 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""003""" Full ROI Full ROI-aoi-001 100893.41 20 | DSP-1012999073013-A-E01 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""048""" NeuN+ NeuN+-aoi-001 6847.39 21 | DSP-1012999073013-A-E02 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""048""" DNA DNA-aoi-001 39238.42 22 | DSP-1012999073013-A-E03 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""049""" NeuN+ NeuN+-aoi-001 24080.25 23 | DSP-1012999073013-A-E04 D5761 (3) D5761 (3) (v1.0) TAP Mouse Whole Transcriptome Atlas "=""049""" DNA DNA-aoi-001 65319.99 24 | -------------------------------------------------------------------------------- /inst/extdata/testData/kidney.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Nanostring-Biostats/SpatialOmicsOverlay/fa91a50f1b6b668920697ed685b16717f2fb0454/inst/extdata/testData/kidney.zip -------------------------------------------------------------------------------- /inst/extdata/testData/test_LabWorksheet.txt: -------------------------------------------------------------------------------- 1 | Experiment Summary 2 | Readout group name 01SEPT2021_HWTA 3 | Date 29 Sep 2021 7:39 PM 4 | Readout mode NGS 5 | Number of Collection Plates 1 6 | Number Of AOIs 63 7 | Library Prep Protocol Version 8 | 9 | Library Prep Summary 10 | Library Prep Plate Collection Plate Primer Plate Rows 11 | 01SEPT2021_HWTA-G "=""1009880000092""" GeoMx Seq Code G A - F 12 | Total Area 6400139 13 | 14 | Annotations 15 | Sample_ID slide name scan name panel roi segment aoi area tags 16 | DSP-1009880000092-G-A01 No Template Control 17 | DSP-1009880000092-G-A02 hu_brain_004b Hippocampus_84 (v1.0) Human NGS Whole Transcriptome Atlas RNA "=""001""" Neuron Neuron-aoi-001 15671.41 18 | DSP-1009880000092-G-A03 hu_brain_004b Hippocampus_84 (v1.0) Human NGS Whole Transcriptome Atlas RNA "=""001""" Iba1 Iba1-aoi-001 14745.13 19 | DSP-1009880000092-G-A04 hu_brain_004b Hippocampus_84 (v1.0) Human NGS Whole Transcriptome Atlas RNA "=""001""" Neuropil Neuropil-aoi-001 114295.82 20 | DSP-1009880000092-G-A05 hu_brain_004b Hippocampus_84 (v1.0) Human NGS Whole Transcriptome Atlas RNA "=""002""" Full ROI Full ROI-aoi-001 308421.43 21 | DSP-1009880000092-G-A06 hu_brain_004b Hippocampus_84 (v1.0) Human NGS Whole Transcriptome Atlas RNA "=""003""" Neuron Neuron-aoi-001 20980.74 22 | DSP-1009880000092-G-A07 hu_brain_004b Hippocampus_84 (v1.0) Human NGS Whole Transcriptome Atlas RNA "=""003""" Iba1 Iba1-aoi-001 17778.95 23 | DSP-1009880000092-G-A08 hu_brain_004b Hippocampus_84 (v1.0) Human NGS Whole Transcriptome Atlas RNA "=""003""" Neuropil Neuropil-aoi-001 137759.74 24 | DSP-1009880000092-G-A09 hu_brain_004b Hippocampus_84 (v1.0) Human NGS Whole Transcriptome Atlas RNA "=""004""" Full ROI Full ROI-aoi-001 314502.92 25 | DSP-1009880000092-G-A10 hu_brain_004b Hippocampus_84 (v1.0) Human NGS Whole Transcriptome Atlas RNA "=""005""" Neuron Neuron-aoi-001 10149.79 26 | DSP-1009880000092-G-A11 hu_brain_004b Hippocampus_84 (v1.0) Human NGS Whole Transcriptome Atlas RNA "=""005""" Iba1 Iba1-aoi-001 12949.96 27 | DSP-1009880000092-G-A12 hu_brain_004b Hippocampus_84 (v1.0) Human NGS Whole Transcriptome Atlas RNA "=""005""" Neuropil Neuropil-aoi-001 118023.22 28 | DSP-1009880000092-G-B01 hu_brain_004b Hippocampus_84 (v1.0) Human NGS Whole Transcriptome Atlas RNA "=""006""" Full ROI Full ROI-aoi-001 28215.45 29 | DSP-1009880000092-G-B02 hu_brain_004b Hippocampus_84 (v1.0) Human NGS Whole Transcriptome Atlas RNA "=""007""" Full ROI Full ROI-aoi-001 40123.59 30 | DSP-1009880000092-G-B03 hu_brain_004b Hippocampus_84 (v1.0) Human NGS Whole Transcriptome Atlas RNA "=""008""" Full ROI Full ROI-aoi-001 29860.17 31 | DSP-1009880000092-G-B04 hu_brain_004b Hippocampus_84 (v1.0) Human NGS Whole Transcriptome Atlas RNA "=""009""" Neuron Neuron-aoi-001 31976.79 32 | DSP-1009880000092-G-B05 hu_brain_004b Hippocampus_84 (v1.0) Human NGS Whole Transcriptome Atlas RNA "=""009""" Neuropil Neuropil-aoi-001 373251.24 33 | DSP-1009880000092-G-B06 hu_brain_004b Hippocampus_84 (v1.0) Human NGS Whole Transcriptome Atlas RNA "=""010""" Neuron Neuron-aoi-001 43027.68 34 | DSP-1009880000092-G-B07 hu_brain_004b Hippocampus_84 (v1.0) Human NGS Whole Transcriptome Atlas RNA "=""010""" Neuropil Neuropil-aoi-001 352200.22 35 | DSP-1009880000092-G-B08 hu_brain_004b Hippocampus_84 (v1.0) Human NGS Whole Transcriptome Atlas RNA "=""011""" Neuron Neuron-aoi-001 31539.95 36 | DSP-1009880000092-G-B09 hu_brain_004b Hippocampus_84 (v1.0) Human NGS Whole Transcriptome Atlas RNA "=""011""" Neuropil Neuropil-aoi-001 381950.43 37 | DSP-1009880000092-G-B10 hu_brain_004b Hippocampus_84 (v1.0) Human NGS Whole Transcriptome Atlas RNA "=""012""" Full ROI Full ROI-aoi-001 308421.43 38 | DSP-1009880000092-G-B11 hu_brain_004a Cortex_29 (v1.0) Human NGS Whole Transcriptome Atlas RNA "=""001""" Full ROI Full ROI-aoi-001 81534.12 39 | DSP-1009880000092-G-B12 hu_brain_004a Cortex_29 (v1.0) Human NGS Whole Transcriptome Atlas RNA "=""002""" Full ROI Full ROI-aoi-001 79843.65 40 | DSP-1009880000092-G-C01 hu_brain_004a Cortex_29 (v1.0) Human NGS Whole Transcriptome Atlas RNA "=""003""" Full ROI Full ROI-aoi-001 230949.71 41 | DSP-1009880000092-G-C02 hu_brain_004a Cortex_29 (v1.0) Human NGS Whole Transcriptome Atlas RNA "=""004""" Full ROI Full ROI-aoi-001 133091.88 42 | DSP-1009880000092-G-C03 hu_brain_004a Cortex_29 (v1.0) Human NGS Whole Transcriptome Atlas RNA "=""005""" Full ROI Full ROI-aoi-001 174730.15 43 | DSP-1009880000092-G-C04 hu_brain_004a Cortex_29 (v1.0) Human NGS Whole Transcriptome Atlas RNA "=""006""" Full ROI Full ROI-aoi-001 174730.15 44 | DSP-1009880000092-G-C05 hu_brain_004a Cortex_29 (v1.0) Human NGS Whole Transcriptome Atlas RNA "=""007""" Neuron Neuron-aoi-001 4236.76 45 | DSP-1009880000092-G-C06 hu_brain_004a Cortex_29 (v1.0) Human NGS Whole Transcriptome Atlas RNA "=""007""" Iba1 Iba1-aoi-001 13494.70 46 | DSP-1009880000092-G-C07 hu_brain_004a Cortex_29 (v1.0) Human NGS Whole Transcriptome Atlas RNA "=""007""" GFAP GFAP-aoi-001 17775.44 47 | DSP-1009880000092-G-C08 hu_brain_004a Cortex_29 (v1.0) Human NGS Whole Transcriptome Atlas RNA "=""007""" Neuropil Neuropil-aoi-001 11617.93 48 | DSP-1009880000092-G-C09 hu_brain_004a Cortex_29 (v1.0) Human NGS Whole Transcriptome Atlas RNA "=""008""" Neuron Neuron-aoi-001 9675.50 49 | DSP-1009880000092-G-C10 hu_brain_004a Cortex_29 (v1.0) Human NGS Whole Transcriptome Atlas RNA "=""008""" Iba1 Iba1-aoi-001 16741.11 50 | DSP-1009880000092-G-C11 hu_brain_004a Cortex_29 (v1.0) Human NGS Whole Transcriptome Atlas RNA "=""008""" GFAP GFAP-aoi-001 8837.84 51 | DSP-1009880000092-G-C12 hu_brain_004a Cortex_29 (v1.0) Human NGS Whole Transcriptome Atlas RNA "=""008""" Neuropil Neuropil-aoi-001 73413.30 52 | DSP-1009880000092-G-D01 hu_brain_004a Cortex_29 (v1.0) Human NGS Whole Transcriptome Atlas RNA "=""009""" Neuron Neuron-aoi-001 9322.65 53 | DSP-1009880000092-G-D02 hu_brain_004a Cortex_29 (v1.0) Human NGS Whole Transcriptome Atlas RNA "=""009""" Iba1 Iba1-aoi-001 23861.71 54 | DSP-1009880000092-G-D03 hu_brain_004a Cortex_29 (v1.0) Human NGS Whole Transcriptome Atlas RNA "=""009""" GFAP GFAP-aoi-001 9029.88 55 | DSP-1009880000092-G-D04 hu_brain_004a Cortex_29 (v1.0) Human NGS Whole Transcriptome Atlas RNA "=""009""" Neuropil Neuropil-aoi-001 79278.52 56 | DSP-1009880000092-G-D05 hu_brain_004a Cortex_29 (v1.0) Human NGS Whole Transcriptome Atlas RNA "=""010""" Neuron Neuron-aoi-001 10066.76 57 | DSP-1009880000092-G-D06 hu_brain_004a Cortex_29 (v1.0) Human NGS Whole Transcriptome Atlas RNA "=""010""" Iba1 Iba1-aoi-001 15006.34 58 | DSP-1009880000092-G-D07 hu_brain_004a Cortex_29 (v1.0) Human NGS Whole Transcriptome Atlas RNA "=""010""" GFAP GFAP-aoi-001 16427.95 59 | DSP-1009880000092-G-D08 hu_brain_004a Cortex_29 (v1.0) Human NGS Whole Transcriptome Atlas RNA "=""010""" Neuropil Neuropil-aoi-001 34655.05 60 | DSP-1009880000092-G-D09 hu_brain_004a Cortex_29 (v1.0) Human NGS Whole Transcriptome Atlas RNA "=""011""" Full ROI Full ROI-aoi-001 77782.17 61 | DSP-1009880000092-G-D10 hu_brain_004a Cortex_29 (v1.0) Human NGS Whole Transcriptome Atlas RNA "=""012""" Full ROI Full ROI-aoi-001 117065.71 62 | DSP-1009880000092-G-D11 hu_brain_004a Cortex_29 (v1.0) Human NGS Whole Transcriptome Atlas RNA "=""013""" Full ROI Full ROI-aoi-001 287615.20 63 | DSP-1009880000092-G-D12 hu_brain_004a Cortex_29 (v1.0) Human NGS Whole Transcriptome Atlas RNA "=""014""" Full ROI Full ROI-aoi-001 158733.78 64 | DSP-1009880000092-G-E01 hu_brain_004a Cortex_29 (v1.0) Human NGS Whole Transcriptome Atlas RNA "=""015""" Full ROI Full ROI-aoi-001 198942.80 65 | DSP-1009880000092-G-E02 hu_brain_004a Cortex_29 (v1.0) Human NGS Whole Transcriptome Atlas RNA "=""016""" Full ROI Full ROI-aoi-001 278355.19 66 | DSP-1009880000092-G-E03 hu_brain_004a Cortex_29 (v1.0) Human NGS Whole Transcriptome Atlas RNA "=""017""" Neuron Neuron-aoi-001 9491.90 67 | DSP-1009880000092-G-E04 hu_brain_004a Cortex_29 (v1.0) Human NGS Whole Transcriptome Atlas RNA "=""017""" Iba1 Iba1-aoi-001 21879.92 68 | DSP-1009880000092-G-E05 hu_brain_004a Cortex_29 (v1.0) Human NGS Whole Transcriptome Atlas RNA "=""017""" GFAP GFAP-aoi-001 11179.34 69 | DSP-1009880000092-G-E06 hu_brain_004a Cortex_29 (v1.0) Human NGS Whole Transcriptome Atlas RNA "=""017""" Neuropil Neuropil-aoi-001 89141.92 70 | DSP-1009880000092-G-E07 hu_brain_004a Cortex_29 (v1.0) Human NGS Whole Transcriptome Atlas RNA "=""018""" Neuron Neuron-aoi-001 7878.57 71 | DSP-1009880000092-G-E08 hu_brain_004a Cortex_29 (v1.0) Human NGS Whole Transcriptome Atlas RNA "=""018""" Iba1 Iba1-aoi-001 14183.82 72 | DSP-1009880000092-G-E09 hu_brain_004a Cortex_29 (v1.0) Human NGS Whole Transcriptome Atlas RNA "=""018""" GFAP GFAP-aoi-001 46531.48 73 | DSP-1009880000092-G-E10 hu_brain_004a Cortex_29 (v1.0) Human NGS Whole Transcriptome Atlas RNA "=""018""" Neuropil Neuropil-aoi-001 10767.20 74 | DSP-1009880000092-G-E11 hu_brain_004a Cortex_29 (v1.0) Human NGS Whole Transcriptome Atlas RNA "=""019""" Full ROI Full ROI-aoi-001 106973.14 75 | DSP-1009880000092-G-E12 hu_brain_004a Cortex_29 (v1.0) Human NGS Whole Transcriptome Atlas RNA "=""020""" Full ROI Full ROI-aoi-001 126048.90 76 | DSP-1009880000092-G-F01 hu_brain_004a Cortex_29 (v1.0) Human NGS Whole Transcriptome Atlas RNA "=""021""" Full ROI Full ROI-aoi-001 249769.84 77 | DSP-1009880000092-G-F02 hu_brain_004a Cortex_29 (v1.0) Human NGS Whole Transcriptome Atlas RNA "=""022""" Full ROI Full ROI-aoi-001 146032.60 78 | DSP-1009880000092-G-F03 hu_brain_004a Cortex_29 (v1.0) Human NGS Whole Transcriptome Atlas RNA "=""023""" Full ROI Full ROI-aoi-001 253799.41 79 | DSP-1009880000092-G-F04 hu_brain_004a Cortex_29 (v1.0) Human NGS Whole Transcriptome Atlas RNA "=""024""" Full ROI Full ROI-aoi-001 253799.41 80 | -------------------------------------------------------------------------------- /longtests/testthat.R: -------------------------------------------------------------------------------- 1 | library(testthat) 2 | library(vdiffr) 3 | library(SpatialOmicsOverlay) 4 | 5 | # #run tests 6 | test_check("SpatialOmicsOverlay") 7 | 8 | 9 | -------------------------------------------------------------------------------- /longtests/testthat/_snaps/addImage/add-image-file.svg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Nanostring-Biostats/SpatialOmicsOverlay/fa91a50f1b6b668920697ed685b16717f2fb0454/longtests/testthat/_snaps/addImage/add-image-file.svg -------------------------------------------------------------------------------- /longtests/testthat/_snaps/addImage/add-ometiff-res-6.svg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Nanostring-Biostats/SpatialOmicsOverlay/fa91a50f1b6b668920697ed685b16717f2fb0454/longtests/testthat/_snaps/addImage/add-ometiff-res-6.svg -------------------------------------------------------------------------------- /longtests/testthat/_snaps/addImage/add-ometiff-res-8.svg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Nanostring-Biostats/SpatialOmicsOverlay/fa91a50f1b6b668920697ed685b16717f2fb0454/longtests/testthat/_snaps/addImage/add-ometiff-res-8.svg -------------------------------------------------------------------------------- /longtests/testthat/_snaps/imageManipulation/cropsamples-all-rois.svg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Nanostring-Biostats/SpatialOmicsOverlay/fa91a50f1b6b668920697ed685b16717f2fb0454/longtests/testthat/_snaps/imageManipulation/cropsamples-all-rois.svg -------------------------------------------------------------------------------- /longtests/testthat/_snaps/imageManipulation/cropsamples-sampsonly.svg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Nanostring-Biostats/SpatialOmicsOverlay/fa91a50f1b6b668920697ed685b16717f2fb0454/longtests/testthat/_snaps/imageManipulation/cropsamples-sampsonly.svg -------------------------------------------------------------------------------- /longtests/testthat/_snaps/imageManipulation/croptissue.svg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Nanostring-Biostats/SpatialOmicsOverlay/fa91a50f1b6b668920697ed685b16717f2fb0454/longtests/testthat/_snaps/imageManipulation/croptissue.svg -------------------------------------------------------------------------------- /longtests/testthat/_snaps/imageManipulation/croptissue4chan.svg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Nanostring-Biostats/SpatialOmicsOverlay/fa91a50f1b6b668920697ed685b16717f2fb0454/longtests/testthat/_snaps/imageManipulation/croptissue4chan.svg -------------------------------------------------------------------------------- /longtests/testthat/_snaps/imageManipulation/flipx.svg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Nanostring-Biostats/SpatialOmicsOverlay/fa91a50f1b6b668920697ed685b16717f2fb0454/longtests/testthat/_snaps/imageManipulation/flipx.svg -------------------------------------------------------------------------------- /longtests/testthat/_snaps/imageManipulation/flipy.svg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Nanostring-Biostats/SpatialOmicsOverlay/fa91a50f1b6b668920697ed685b16717f2fb0454/longtests/testthat/_snaps/imageManipulation/flipy.svg -------------------------------------------------------------------------------- /longtests/testthat/_snaps/imageManipulation/imagecoloring.svg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Nanostring-Biostats/SpatialOmicsOverlay/fa91a50f1b6b668920697ed685b16717f2fb0454/longtests/testthat/_snaps/imageManipulation/imagecoloring.svg -------------------------------------------------------------------------------- /longtests/testthat/_snaps/imageManipulation/recolor.svg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Nanostring-Biostats/SpatialOmicsOverlay/fa91a50f1b6b668920697ed685b16717f2fb0454/longtests/testthat/_snaps/imageManipulation/recolor.svg -------------------------------------------------------------------------------- /longtests/testthat/_snaps/plotting/fluorlegend-1-row.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | GFAP 31 | DNA 32 | Iba-1 33 | NeuN 34 | 35 | 36 | fluorLegend 1 row 37 | 38 | 39 | -------------------------------------------------------------------------------- /longtests/testthat/_snaps/plotting/fluorlegend-2-row.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | GFAP 31 | DNA 32 | Iba-1 33 | NeuN 34 | 35 | 36 | fluorLegend 2 row 37 | 38 | 39 | -------------------------------------------------------------------------------- /longtests/testthat/_snaps/plotting/fluorlegend-4-row.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | GFAP 31 | DNA 32 | Iba-1 33 | NeuN 34 | 35 | 36 | fluorLegend 4 row 37 | 38 | 39 | -------------------------------------------------------------------------------- /longtests/testthat/test_SpatialOverlay.R: -------------------------------------------------------------------------------- 1 | if(!file.exists("muBrain.RDS")){ 2 | tifFile <- downloadMouseBrainImage() 3 | annots <- system.file("extdata", "muBrain_LabWorksheet.txt", 4 | package = "SpatialOmicsOverlay") 5 | 6 | overlay <- suppressWarnings(readSpatialOverlay(ometiff = tifFile, annots = annots, 7 | slideName = "D5761 (3)", outline = FALSE)) 8 | 9 | saveRDS(overlay, "muBrain.RDS") 10 | }else{ 11 | overlay <- readRDS( "muBrain.RDS") 12 | } 13 | 14 | annots <- system.file("extdata", "muBrain_LabWorksheet.txt", 15 | package = "SpatialOmicsOverlay") 16 | 17 | overlay <- addImageOmeTiff(overlay, 18 | ometiff = downloadMouseBrainImage(), 19 | res = 8) 20 | 21 | annots <- readLabWorksheet(annots, "D5761 (3)") 22 | 23 | overlay <- addPlottingFactor(overlay, annots, "segment") 24 | 25 | testthat::test_that("SpatialOverlay is formatted correctly",{ 26 | #Spec 1. The class is formatted correctly. 27 | expect_true(all(names(scanMeta(overlay)) == c("Panels", "PhysicalSizes", 28 | "Fluorescence", 29 | "Segmentation"))) 30 | expect_true(class(scanMeta(overlay)$Panels) == "character") 31 | expect_true(all(names(scanMeta(overlay)$PhysicalSizes) == c("X", "Y"))) 32 | expect_true(class(scanMeta(overlay)$PhysicalSizes$X) == "numeric") 33 | expect_true(class(scanMeta(overlay)$PhysicalSizes$Y) == "numeric") 34 | expect_true(class(scanMeta(overlay)$Fluorescence) == "data.frame") 35 | expect_true(all(names(scanMeta(overlay)$Fluorescence) == c("Dye", 36 | "DisplayName", 37 | "Color", 38 | "WaveLength", 39 | "Target", 40 | "ExposureTime", 41 | "MinIntensity", 42 | "MaxIntensity", 43 | "ColorCode"))) 44 | expect_true(all(names(overlay@workflow) %in% c("labWorksheet", "outline", 45 | "scaled"))) 46 | expect_true(all(coords(overlay)$sampleID %in% sampNames(overlay))) 47 | expect_true(all(rownames(plotFactors(overlay)) == sampNames(overlay))) 48 | 49 | expect_true(all(names(overlay@image) %in% c("filePath", "imagePointer", 50 | "resolution"))) 51 | }) 52 | 53 | testthat::test_that("SpatialOverlay accessor work as expected",{ 54 | #Spec 2. The class accessors work as expected. 55 | expect_true(slideName(overlay) == "D5761 (3)") 56 | expect_identical(slideName(overlay), overlay@slideName) 57 | 58 | expect_true(class(overlay(overlay)) == "SpatialPosition") 59 | expect_identical(overlay(overlay), overlay@overlayData) 60 | 61 | expect_true(class(scanMeta(overlay)) == "list") 62 | expect_identical(scanMeta(overlay), overlay@scanMetadata) 63 | 64 | expect_true(class(coords(overlay)) == "data.frame") 65 | expect_identical(coords(overlay), overlay@coords) 66 | 67 | expect_true(class(plotFactors(overlay)) == "data.frame") 68 | expect_identical(plotFactors(overlay), overlay@plottingFactors) 69 | 70 | expect_true(class(labWork(overlay)) == "logical") 71 | expect_identical(labWork(overlay), overlay@workflow$labWorksheet) 72 | 73 | expect_true(class(outline(overlay)) == "logical") 74 | expect_identical(outline(overlay), overlay@workflow$outline) 75 | 76 | expect_true(class(scaleBarRatio(overlay)) == "numeric") 77 | expect_identical(scaleBarRatio(overlay), overlay@scanMetadata$PhysicalSizes$X) 78 | 79 | expect_true(class(fluor(overlay)) == "data.frame") 80 | expect_identical(fluor(overlay), overlay@scanMetadata$Fluorescence) 81 | 82 | expect_true(class(seg(overlay)) == "character") 83 | expect_identical(seg(overlay), overlay@scanMetadata$Segmentation) 84 | 85 | expect_true(class(sampNames(overlay)) == "character") 86 | expect_identical(sampNames(overlay), meta(overlay(overlay))$Sample_ID) 87 | 88 | expect_true(class(res(overlay)) == "numeric") 89 | expect_true(res(overlay) == overlay@image$resolution) 90 | 91 | expect_true(class(showImage(overlay)) == "magick-image") 92 | expect_identical(showImage(overlay), overlay@image$imagePointer) 93 | 94 | expect_true(class(scaled(overlay)) == "logical") 95 | expect_identical(scaled(overlay), overlay@workflow$scaled) 96 | 97 | expect_true(class(imageInfo(overlay)) == "list") 98 | expect_identical(imageInfo(overlay), overlay@image) 99 | 100 | expect_true(class(workflow(overlay)) == "list") 101 | expect_identical(workflow(overlay), overlay@workflow) 102 | }) 103 | 104 | 105 | -------------------------------------------------------------------------------- /longtests/testthat/test_SpatialPosition.R: -------------------------------------------------------------------------------- 1 | if(!file.exists("muBrain.RDS")){ 2 | tifFile <- downloadMouseBrainImage() 3 | annots <- system.file("extdata", "muBrain_LabWorksheet.txt", 4 | package = "SpatialOmicsOverlay") 5 | 6 | overlay <- suppressWarnings(readSpatialOverlay(ometiff = tifFile, annots = annots, 7 | slideName = "D5761 (3)", outline = FALSE)) 8 | 9 | saveRDS(overlay, "muBrain.RDS") 10 | }else{ 11 | overlay <- readRDS( "muBrain.RDS") 12 | } 13 | 14 | annots <- system.file("extdata", "muBrain_LabWorksheet.txt", 15 | package = "SpatialOmicsOverlay") 16 | 17 | AOIattrs <- overlay(overlay) 18 | 19 | testthat::test_that("SpatialPosition is formatted correctly",{ 20 | #Spec 1. The class is formatted correctly. 21 | expect_true(class(AOIattrs) == "SpatialPosition") 22 | expect_true(class(AOIattrs@position) == "data.frame") 23 | expect_true(all(names(AOIattrs) == c("ROILabel", "Sample_ID", "Height", 24 | "Width", "X", "Y", "Segmentation", 25 | "Position"))) 26 | expect_true(class(AOIattrs@position$ROILabel) == "character") 27 | expect_true(class(AOIattrs@position$Sample_ID) == "character") 28 | expect_true(class(AOIattrs@position$Height) == "numeric") 29 | expect_true(class(AOIattrs@position$Width) == "numeric") 30 | expect_true(class(AOIattrs@position$X) == "numeric") 31 | expect_true(class(AOIattrs@position$Y) == "numeric") 32 | expect_true(class(AOIattrs@position$Segmentation) == "character") 33 | expect_true(class(AOIattrs@position$Position) == "character") 34 | 35 | expect_true(all(AOIattrs@position$Segmentation %in% c("Segmented", "Geometric"))) 36 | 37 | expect_false(any(duplicated(AOIattrs@position$Sample_ID))) 38 | }) 39 | 40 | testthat::test_that("SpatialPosition accessors are correct",{ 41 | #Spec 2. The class accessors work as expected. 42 | expect_identical(meta(AOIattrs), AOIattrs@position[,1:7]) 43 | expect_true(class(meta(AOIattrs)) == "data.frame") 44 | expect_identical(position(AOIattrs), AOIattrs@position$Position) 45 | expect_true(class(position(AOIattrs)) == "character") 46 | expect_identical(spatialPos(AOIattrs), AOIattrs@position) 47 | expect_true(class(spatialPos(AOIattrs)) == "data.frame") 48 | }) 49 | 50 | -------------------------------------------------------------------------------- /longtests/testthat/test_addImage.R: -------------------------------------------------------------------------------- 1 | tiff <- downloadMouseBrainImage() 2 | 3 | if(!file.exists("muBrain.RDS")){ 4 | tifFile <- downloadMouseBrainImage() 5 | annots <- system.file("extdata", "muBrain_LabWorksheet.txt", 6 | package = "SpatialOmicsOverlay") 7 | 8 | overlay <- suppressWarnings(readSpatialOverlay(ometiff = tifFile, annots = annots, 9 | slideName = "D5761 (3)", outline = FALSE)) 10 | 11 | saveRDS(overlay, "muBrain.RDS") 12 | }else{ 13 | overlay <- readRDS( "muBrain.RDS") 14 | } 15 | 16 | overlayImage6 <- addImageOmeTiff(overlay, tiff, res = 6) 17 | overlayImage8 <- addImageOmeTiff(overlay, tiff, res = 8) 18 | 19 | testthat::test_that("Image is added correctly",{ 20 | #Spec 5. The function must have SpatialOverlay object input. 21 | expect_error(addImageOmeTiff("overlay", tiff, res = 7), 22 | regexp = "overlay must be a SpatialOverlay object") 23 | 24 | #Spec 1. The function outputs a list in the image slot containing the 25 | # expected filePath, imagePointer, and resolution. 26 | expect_true(all(names(overlayImage6@image) == c("filePath", 27 | "imagePointer", 28 | "resolution"))) 29 | expect_true(all(names(overlayImage8@image) == c("filePath", 30 | "imagePointer", 31 | "resolution"))) 32 | 33 | expect_true(overlayImage6@image$filePath == tiff) 34 | expect_true(overlayImage8@image$filePath == tiff) 35 | 36 | expect_true(overlayImage6@image$resolution == 6) 37 | expect_true(overlayImage8@image$resolution == 8) 38 | 39 | #Spec 2. The imagePointer is an magick-image with the correct dimensions 40 | expect_true(class(showImage(overlayImage6)) == "magick-image") 41 | expect_true(class(showImage(overlayImage8)) == "magick-image") 42 | 43 | expect_true(image_info(showImage(overlayImage6))$width == 1024) 44 | expect_true(image_info(showImage(overlayImage6))$height == 1024) 45 | 46 | expect_true(image_info(showImage(overlayImage8))$width == 256) 47 | expect_true(image_info(showImage(overlayImage8))$height == 256) 48 | 49 | #Spec 4. The function produces reproducible results 50 | vdiffr::expect_doppelganger("add ometiff res 6", showImage(overlayImage6)) 51 | vdiffr::expect_doppelganger("add ometiff res 8", showImage(overlayImage8)) 52 | }) 53 | 54 | testthat::test_that("Coordinates are scaled",{ 55 | #Spec 3. The function scales the coordinates. 56 | expect_true(overlayImage6@workflow$scaled) 57 | expect_true(overlayImage8@workflow$scaled) 58 | 59 | #Spec 1. The function scales the coordinates based on the size of the image. 60 | expect_true(nrow(coords(overlayImage6)) > 61 | nrow(coords(overlayImage8))) 62 | expect_true(max(coords(overlayImage6)$xcoor) > 63 | max(coords(overlayImage8)$xcoor)) 64 | expect_true(max(coords(overlayImage6)$ycoor) > 65 | max(coords(overlayImage8)$ycoor)) 66 | 67 | #Spec 2. The coordinates are all smaller than the image size. 68 | expect_true(all(coords(overlayImage6)$xcoor < 1024)) 69 | expect_true(all(coords(overlayImage6)$ycoor < 1024)) 70 | 71 | expect_true(all(coords(overlayImage8)$xcoor < 256)) 72 | expect_true(all(coords(overlayImage8)$ycoor < 256)) 73 | 74 | #Spec 3. There are no duplicated coordinates. 75 | expect_false(any(duplicated(coords(overlayImage6)))) 76 | expect_false(any(duplicated(coords(overlayImage8)))) 77 | }) 78 | 79 | testthat::test_that("scaleCoords errors",{ 80 | #Spec 4. Coordinates can't be rescaled. 81 | expect_error(scaleCoords(overlayImage6), 82 | regexp = "Coordinates are already scaled and can't be scaled again") 83 | #Spec 5. An image must be in object to scale coordinates. 84 | expect_warning(scaleCoords(overlay), 85 | regexp = "No image has been added") 86 | }) 87 | 88 | overlayImage4Chan6 <- add4ChannelImage(overlay, tiff, res = 6) 89 | overlayImage4Chan8 <- add4ChannelImage(overlay, tiff, res = 8) 90 | 91 | testthat::test_that("4 channel image is added correctly",{ 92 | #Spec 5. The function must have SpatialOverlay object input. 93 | expect_error(add4ChannelImage("overlay", tiff, res = 7), 94 | regexp = "overlay must be a SpatialOverlay object") 95 | 96 | #Spec 1. The function outputs a list in the image slot containing the 97 | # expected filePath, imagePointer, and resolution. 98 | expect_true(all(names(overlayImage4Chan6@image) == c("filePath", 99 | "imagePointer", 100 | "resolution"))) 101 | expect_true(all(names(overlayImage4Chan8@image) == c("filePath", 102 | "imagePointer", 103 | "resolution"))) 104 | 105 | expect_true(overlayImage4Chan6@image$filePath == tiff) 106 | expect_true(overlayImage4Chan8@image$filePath == tiff) 107 | 108 | expect_true(overlayImage4Chan6@image$resolution == 6) 109 | expect_true(overlayImage4Chan8@image$resolution == 8) 110 | 111 | #Spec 2. The imagePointer is an AnnotatedImage with the correct dimensions. 112 | expect_true(class(showImage(overlayImage4Chan6)) == "AnnotatedImage") 113 | expect_true(class(showImage(overlayImage4Chan8)) == "AnnotatedImage") 114 | 115 | expect_true(all(dim(imageData(overlayImage4Chan6)) == c(1024,1024,4))) 116 | expect_true(all(dim(imageData(overlayImage4Chan8)) == c(256,256,4))) 117 | }) 118 | 119 | testthat::test_that("Coordinates are scaled",{ 120 | #Spec 3. The function scales the coordinates. 121 | expect_true(overlayImage4Chan6@workflow$scaled) 122 | expect_true(overlayImage4Chan8@workflow$scaled) 123 | 124 | expect_true(nrow(coords(overlayImage4Chan6)) > 125 | nrow(coords(overlayImage4Chan8))) 126 | expect_true(max(coords(overlayImage4Chan6)$xcoor) > 127 | max(coords(overlayImage4Chan8)$xcoor)) 128 | expect_true(max(coords(overlayImage4Chan6)$ycoor) > 129 | max(coords(overlayImage4Chan8)$ycoor)) 130 | 131 | expect_true(all(coords(overlayImage4Chan6)$xcoor < 1024)) 132 | expect_true(all(coords(overlayImage4Chan6)$ycoor < 1024)) 133 | 134 | expect_true(all(coords(overlayImage4Chan8)$xcoor < 256)) 135 | expect_true(all(coords(overlayImage4Chan8)$ycoor < 256)) 136 | 137 | expect_false(any(duplicated(coords(overlayImage4Chan6)))) 138 | expect_false(any(duplicated(coords(overlayImage4Chan8)))) 139 | 140 | #Spec 4. The function produces reproducible results 141 | expect_true(all(coords(overlayImage4Chan6) == coords(overlayImage6))) 142 | expect_true(all(coords(overlayImage4Chan8) == coords(overlayImage8))) 143 | }) 144 | 145 | image <- imageExtraction(ometiff = tiff, res = 8, scanMeta = scanMeta(overlay), 146 | saveFile = TRUE, fileType = "png", color = TRUE) 147 | 148 | pngFile <- gsub(".ome.tiff", ".png", tiff) 149 | 150 | overlayImageFile <- addImageFile(overlay, imageFile = pngFile, res = 8) 151 | 152 | testthat::test_that("Image from file works", { 153 | #Spec 5. The function must have SpatialOverlay object input. 154 | expect_error(addImageFile("overlay", tiff, res = 7), 155 | regexp = "overlay must be a SpatialOverlay object") 156 | 157 | #Spec 1. The function outputs a list in the image slot containing the 158 | # expected filePath, imagePointer, and resolution. 159 | expect_true(all(names(overlayImageFile@image) == c("filePath", 160 | "imagePointer", 161 | "resolution"))) 162 | 163 | expect_true(overlayImageFile@image$filePath == pngFile) 164 | 165 | expect_true(overlayImageFile@image$resolution == 8) 166 | 167 | #Spec 2. The imagePointer is a magick-image with the correct dimensions. 168 | expect_true(class(showImage(overlayImageFile)) == "magick-image") 169 | 170 | expect_true(image_info(showImage(overlayImageFile))$width == 256) 171 | expect_true(image_info(showImage(overlayImageFile))$height == 256) 172 | 173 | #Spec 4. The function produces reproducible results 174 | vdiffr::expect_doppelganger("add image file", showImage(overlayImageFile)) 175 | }) 176 | 177 | testthat::test_that("Coordinates are scaled",{ 178 | #Spec 3. The function scales the coordinates. 179 | expect_true(overlayImageFile@workflow$scaled) 180 | 181 | expect_true(all(coords(overlayImageFile)$xcoor < 256)) 182 | expect_true(all(coords(overlayImageFile)$ycoor < 256)) 183 | 184 | expect_false(any(duplicated(coords(overlayImageFile)))) 185 | 186 | expect_true(all(coords(overlayImageFile) == coords(overlayImage8))) 187 | }) 188 | -------------------------------------------------------------------------------- /longtests/testthat/test_addPlottingFactor.R: -------------------------------------------------------------------------------- 1 | if(!file.exists("muBrain.RDS")){ 2 | tifFile <- downloadMouseBrainImage() 3 | annots <- system.file("extdata", "muBrain_LabWorksheet.txt", 4 | package = "SpatialOmicsOverlay") 5 | 6 | overlay <- suppressWarnings(readSpatialOverlay(ometiff = tifFile, annots = annots, 7 | slideName = "D5761 (3)", outline = FALSE)) 8 | 9 | saveRDS(overlay, "muBrain.RDS") 10 | }else{ 11 | overlay <- readRDS( "muBrain.RDS") 12 | } 13 | 14 | annots <- system.file("extdata", "muBrain_LabWorksheet.txt", 15 | package = "SpatialOmicsOverlay") 16 | annots <- readLabWorksheet(annots, "D5761 (3)") 17 | 18 | samples <- sampNames(overlay)[-c(1:4)] 19 | counts <- as.data.frame(matrix(ncol = length(samples), nrow = 10, 20 | data = runif(length(samples)*10, max = 50))) 21 | colnames(counts) <- samples 22 | rownames(counts) <- stringi::stri_rand_strings(n = 10, length = 5) 23 | 24 | testthat::test_that("annotation dataframe can be added as plotting Factor",{ 25 | #Spec 1. The function only works on one factor at a time regardless of input 26 | # type. 27 | #Spec 3. The function works with a data.frame input, column name 28 | # plotting factor. 29 | expect_warning(overlay <- addPlottingFactor(overlay, as.data.frame(annots), 30 | c("segment", "area")), 31 | regexp = "Plotting factors must be added 1 at a time") 32 | expect_true(names(plotFactors(overlay)) == "segment") 33 | expect_true(class(plotFactors(overlay)$segment) == "factor") 34 | expect_identical(as.character(plotFactors(overlay)$segment), 35 | annots$segment[match(rownames(plotFactors(overlay)), 36 | annots$Sample_ID, nomatch = 0)]) 37 | 38 | geneName <- rownames(counts)[6] 39 | 40 | #Spec 2. The function gives warning for annotation missing for samples 41 | # in object regardless of input type. 42 | #Spec 4. The function works with a data.frame input, row name plotting 43 | # factor. 44 | expect_warning(overlay <- addPlottingFactor(overlay, as.data.frame(counts), 45 | geneName), 46 | regexp = "Missing annotations in annots") 47 | expect_true(all(names(plotFactors(overlay)) == c("segment", geneName))) 48 | expect_true(class(plotFactors(overlay)[[geneName]]) == "numeric") 49 | expect_identical(plotFactors(overlay)[[geneName]], 50 | as.numeric(counts[geneName, match(rownames(plotFactors(overlay)), 51 | colnames(counts), nomatch = 0)])) 52 | 53 | #Spec 14. The function can handle NULL inputs. 54 | expect_error(addPlottingFactor(overlay, as.data.frame(counts), 55 | NULL), 56 | regexp = "Please provide valid plottingFactor") 57 | }) 58 | 59 | testthat::test_that("annotation matrix can be added as plotting Factor",{ 60 | #Spec 1. The function only works on one factor at a time regardless of input 61 | # type. 62 | #Spec 5. The function works with a matrix input, column name plotting factor. 63 | expect_warning(overlay <- addPlottingFactor(overlay, as.matrix(annots), 64 | c("segment", "area")), 65 | regexp = "Plotting factors must be added 1 at a time") 66 | expect_true(names(plotFactors(overlay)) == "segment") 67 | expect_true(class(plotFactors(overlay)$segment) == "factor") 68 | expect_identical(as.character(plotFactors(overlay)$segment), 69 | annots$segment[match(rownames(plotFactors(overlay)), 70 | annots$Sample_ID, nomatch = 0)]) 71 | 72 | geneName <- rownames(counts)[6] 73 | 74 | #Spec 2. The function gives warning for annotation missing for samples 75 | # in object regardless of input type. 76 | #Spec 6. The function works with a matrix input, row name plotting factor. 77 | expect_warning(overlay <- addPlottingFactor(overlay, as.matrix(counts), 78 | geneName), 79 | regexp = "Missing annotations in annots") 80 | expect_true(all(names(plotFactors(overlay)) == c("segment", geneName))) 81 | expect_true(class(plotFactors(overlay)[[geneName]]) == "numeric") 82 | expect_identical(plotFactors(overlay)[[geneName]], 83 | as.numeric(counts[geneName, match(rownames(plotFactors(overlay)), 84 | colnames(counts), 85 | nomatch = 0)])) 86 | 87 | #Spec 14. The function can handle NULL inputs. 88 | expect_error(addPlottingFactor(overlay, as.matrix(counts), 89 | NULL), 90 | regexp = "Please provide valid plottingFactor") 91 | }) 92 | 93 | testthat::test_that("annotation vectors can be added as plotting Factor",{ 94 | #Spec 7. If vectors aren't named they must be the same length as number of 95 | # samples in object. 96 | expect_error(suppressWarnings(addPlottingFactor(overlay, 97 | annots$segment[1:4], 98 | "test")), 99 | regexp = "Length of annots does not match samples in overlay") 100 | 101 | #Spec 8. The function only matches vectors if they are named, otherwise 102 | # assumed in correct order. 103 | #Spec 9. The function works with character vectors. 104 | expect_warning(overlay <- addPlottingFactor(overlay, 105 | as.character(annots$segment), 106 | "segmentNonNamed"), 107 | regexp = "No names on vector") 108 | annot <- as.character(annots$segment) 109 | names(annot) <- annots$Sample_ID 110 | expect_warning(overlay <- addPlottingFactor(overlay, annot, "segmentNamed"), 111 | NA) 112 | 113 | expect_true(class(plotFactors(overlay)$segmentNonNamed) == "factor") 114 | expect_true(class(plotFactors(overlay)$segmentNamed) == "factor") 115 | expect_false(all(plotFactors(overlay)$segmentNonNamed == plotFactors(overlay)$segmentNamed)) 116 | expect_identical(as.character(plotFactors(overlay)$segmentNamed), 117 | annots$segment[match(rownames(plotFactors(overlay)), 118 | annots$Sample_ID, nomatch = 0)]) 119 | 120 | #Spec 14. The function can handle NULL inputs. 121 | expect_error(addPlottingFactor(overlay, 122 | as.character(annots$segment), 123 | NULL), 124 | regexp = "Please provide valid plottingFactor") 125 | 126 | #Spec 8. The function only matches vectors if they are named, otherwise 127 | # assumed in correct order. 128 | #Spec 10. The function works with factor vectors. 129 | expect_warning(overlay <- addPlottingFactor(overlay, 130 | as.factor(annots$segment), 131 | "segmentNonNamedFactor"), 132 | regexp = "No names on vector") 133 | annot <- as.factor(annots$segment) 134 | names(annot) <- annots$Sample_ID 135 | expect_warning(overlay <- addPlottingFactor(overlay, annot, "segmentNamedFactor"), NA) 136 | 137 | expect_true(class(plotFactors(overlay)$segmentNonNamedFactor) == "factor") 138 | expect_true(class(plotFactors(overlay)$segmentNamedFactor) == "factor") 139 | expect_false(all(plotFactors(overlay)$segmentNonNamedFactor == plotFactors(overlay)$segmentNamedFactor)) 140 | expect_true(all(plotFactors(overlay)$segmentNonNamed == plotFactors(overlay)$segmentNonNamedFactor)) 141 | expect_true(all(plotFactors(overlay)$segmentNamed == plotFactors(overlay)$segmentNamedFactor)) 142 | expect_identical(as.character(plotFactors(overlay)$segmentNamedFactor), 143 | annots$segment[match(rownames(plotFactors(overlay)), 144 | annots$Sample_ID, nomatch = 0)]) 145 | 146 | #Spec 14. The function can handle NULL inputs. 147 | expect_error(addPlottingFactor(overlay, 148 | as.factor(annots$segment), 149 | NULL), 150 | regexp = "Please provide valid plottingFactor") 151 | 152 | #Spec 8. The function only matches vectors if they are named, otherwise 153 | # assumed in correct order. 154 | #Spec 11. The function works with numeric vectors. 155 | expect_warning(overlay <- addPlottingFactor(overlay, 156 | as.numeric(annots$area), 157 | "areaNonNamed"), 158 | regexp = "No names on vector") 159 | annot <- as.numeric(annots$area) 160 | names(annot) <- annots$Sample_ID 161 | expect_warning(overlay <- addPlottingFactor(overlay, annot, "areaNamed"), NA) 162 | 163 | expect_true(class(plotFactors(overlay)$areaNonNamed) == "numeric") 164 | expect_true(class(plotFactors(overlay)$areaNamed) == "numeric") 165 | 166 | expect_false(all(plotFactors(overlay)$areaNonNamed == plotFactors(overlay)$areaNamed)) 167 | expect_identical(plotFactors(overlay)$areaNamed, 168 | annots$area[match(rownames(plotFactors(overlay)), 169 | annots$Sample_ID, nomatch = 0)]) 170 | 171 | #Spec 14. The function can handle NULL inputs. 172 | expect_error(addPlottingFactor(overlay, 173 | as.numeric(annots$area), 174 | NULL), 175 | regexp = "Please provide valid plottingFactor") 176 | }) 177 | 178 | library(GeomxTools) 179 | 180 | GxT <- readRDS(unzip(system.file("extdata", "muBrain_GxT.zip", 181 | package = "SpatialOmicsOverlay"))) 182 | 183 | testthat::test_that("annotation GeoMxSet object can be added as plotting Factor",{ 184 | #Spec 12. The function works with a NanostringGeomxSet input, column name 185 | # plotting factor. 186 | overlay <- addPlottingFactor(overlay, GxT, "Group") 187 | 188 | expect_true(class(plotFactors(overlay)$Group) == "factor") 189 | expect_identical(as.character(plotFactors(overlay)$Group), 190 | sData(GxT)$Group[match(rownames(plotFactors(overlay)), 191 | sData(GxT)$SampleID, nomatch = 0)]) 192 | 193 | #Spec 13. The function works with a NanostringGeomxSet input, row name 194 | # plotting factor. 195 | overlay <- addPlottingFactor(overlay, GxT, "Cryab") 196 | 197 | expect_true(class(plotFactors(overlay)$Cryab) == "numeric") 198 | expect_true(all(plotFactors(overlay)$Cryab == 199 | exprs(GxT)["Cryab", match(rownames(plotFactors(overlay)), 200 | sData(GxT)$SampleID, nomatch = 0)])) 201 | 202 | #Spec 14. The function can handle NULL inputs. 203 | expect_error(addPlottingFactor(overlay, GxT, NULL), 204 | regexp = "Please provide valid plottingFactor") 205 | }) 206 | -------------------------------------------------------------------------------- /longtests/testthat/test_coordinateGeneration.R: -------------------------------------------------------------------------------- 1 | unzip(system.file("extdata", "testData", "kidney.zip", 2 | package = "SpatialOmicsOverlay"), 3 | exdir = "testData") 4 | 5 | kidneyXML <- readRDS("testData/kidneyXML.RDS") 6 | kidneyAnnots <- read.table("testData/kidney_annotations_allROIs.txt", 7 | header = T, sep = "\t") 8 | 9 | scanMetadataKidney <- parseScanMetadata(kidneyXML) 10 | 11 | kidneyAOIattrs <- parseOverlayAttrs(kidneyXML, kidneyAnnots, labworksheet = FALSE) 12 | 13 | AOImeta <- meta(kidneyAOIattrs)[meta(kidneyAOIattrs)$Sample_ID == 14 | "normal3_scan | 002 | neg",] 15 | AOIposition <- position(kidneyAOIattrs)[meta(kidneyAOIattrs)$Sample_ID == 16 | "normal3_scan | 002 | neg"] 17 | 18 | testthat::test_that("decodeB64 is correct",{ 19 | #Spec 1. The function produces same values as python truth. 20 | pythonTruth <- readRDS("testData/kidneyDecodedTruth.RDS") 21 | expect_true(all(as.numeric(decodeB64(b64string = AOIposition, width = AOImeta$Width, 22 | height = AOImeta$Height)) == pythonTruth)) 23 | }) 24 | 25 | pythonTruth <- readRDS("testData/kidneyMaskTruth.RDS") 26 | 27 | mask <- createMask(b64string = AOIposition, metadata = AOImeta, 28 | outline = FALSE) 29 | 30 | testthat::test_that("createMask is correct - all coordinates",{ 31 | #Spec 1. The function creates mask in correct dimension. 32 | expect_true(all(dim(mask) == c(AOImeta$Height,AOImeta$Width))) 33 | #Spec 2. The function produces same values as python truth. 34 | expect_true(all(mask == pythonTruth)) 35 | #Spec 3. The function produces mask of only 0 & 1. 36 | expect_true(all(mask %in% c(0,1))) 37 | #Spec 4. The function creates matrix. 38 | expect_true(class(mask)[1] == "matrix") 39 | }) 40 | 41 | testthat::test_that("coordsFromMask is correct - all coordinates",{ 42 | #Spec 1. The function creates coordinates for mask = 1 points. Coordinates 43 | # are put into full image range and changed from base1 to base0. 44 | coords <- coordsFromMask(mask = mask, metadata = AOImeta, 45 | outline = FALSE) 46 | 47 | expectedCoords <- as.data.frame(which(mask == 1, arr.ind = T)) 48 | colnames(expectedCoords) <- c("Y", "X") 49 | expectedCoords[["X"]] <- expectedCoords[["X"]] + AOImeta$X - 1 50 | expectedCoords[["Y"]] <- expectedCoords[["Y"]] + AOImeta$Y - 1 51 | 52 | expect_true(all(expectedCoords == coords)) 53 | }) 54 | 55 | outlineMask <- createMask(b64string = AOIposition, metadata = AOImeta, 56 | outline = TRUE) 57 | 58 | testthat::test_that("createMask is correct - outline coordinates",{ 59 | #Spec 1. The function creates mask in correct dimension. 60 | expect_true(all(dim(outlineMask) == c(AOImeta$Height,AOImeta$Width))) 61 | #Spec 2. The function has fewer matches with the python truth 62 | propTrue <- table(outlineMask == pythonTruth) 63 | expect_true(propTrue["TRUE"] < propTrue["FALSE"]) 64 | #Spec 3. The function produces mask of only 0 & 1. 65 | expect_true(all(outlineMask %in% c(0,1))) 66 | #Spec 4. The function creates matrix. 67 | expect_true(class(outlineMask)[1] == "matrix") 68 | 69 | #Spec 5. The function create mask with < 0.1% of points with 7 or more neighbors. 70 | expect_true(length(which(boundary(outlineMask) >= 7)) < length(outlineMask)*0.001) 71 | }) 72 | 73 | testthat::test_that("coordsFromMask is correct - outline coordinates",{ 74 | #Spec 1. The function creates coordinates for mask = 1 points. Coordinates 75 | # are put into full image range and changed from base1 to base0. 76 | coords <- coordsFromMask(outlineMask, AOImeta, outline = F) 77 | 78 | expectedCoords <- as.data.frame(which(outlineMask == 1, arr.ind = T)) 79 | colnames(expectedCoords) <- c("Y", "X") 80 | expectedCoords[["X"]] <- expectedCoords[["X"]] + AOImeta$X - 1 81 | expectedCoords[["Y"]] <- expectedCoords[["Y"]] + AOImeta$Y - 1 82 | 83 | expect_true(all(expectedCoords == coords)) 84 | }) 85 | 86 | testthat::test_that("Pencil Sorting works as expected",{ 87 | sortedCoords <- coordsFromMask(outlineMask, AOImeta, outline = T) 88 | 89 | sortedCoords$dif <- NA 90 | 91 | for(i in 1:nrow(sortedCoords)){ 92 | if(i == nrow(sortedCoords)){ 93 | sortedCoords$dif[i] <- abs(sortedCoords$ycoor[i] - sortedCoords$ycoor[1]) + 94 | abs(sortedCoords$xcoor[i] - sortedCoords$xcoor[1]) 95 | }else{ 96 | sortedCoords$dif[i] <- abs(sortedCoords$ycoor[i] - sortedCoords$ycoor[i+1]) + 97 | abs(sortedCoords$xcoor[i] - sortedCoords$xcoor[i+1]) 98 | } 99 | } 100 | 101 | #Spec 1. The function sorts outline coordinates by proximity. >99% of 102 | # differences between adjacent coordinates is 1. 103 | expect_true(length(which(sortedCoords == 1)) > nrow(sortedCoords)*0.99) 104 | #Spec 2. The function sorts outline coordinates by proximity. The max 105 | # difference is <100. 106 | expect_true(max(sortedCoords$dif) < 100) 107 | }) 108 | 109 | scanMetadataKidney[["Segmentation"]] <- ifelse(all(meta(kidneyAOIattrs)$Segmentation == "Geometric"), 110 | yes = "Geometric", no = "Segmented") 111 | 112 | overlay <- createCoordFile(SpatialOverlay(slideName = "normal3", 113 | scanMetadata = scanMetadataKidney, 114 | overlayData = kidneyAOIattrs), 115 | outline = FALSE) 116 | 117 | testthat::test_that("createCoordFile expects SpatialOverlay object",{ 118 | #Spec 4. The function must have SpatialOverlay object input. 119 | expect_error(createCoordFile("overlay"), 120 | regexp = "Overlay must be a SpatialOverlay object") 121 | }) 122 | 123 | testthat::test_that("createCoordFile puts data in correct spot",{ 124 | #Spec 1. The function places coordinates in correct location. 125 | expect_true(!is.null(coords(overlay))) 126 | }) 127 | 128 | coords <- coords(overlay) 129 | 130 | testthat::test_that("createCoordFile is correct",{ 131 | #Spec 2. The function produces same values as python truth. 132 | pythonTruth <- readRDS("testData/kidneyCoordsTruth.RDS") 133 | pythonTruth <- pythonTruth[,c("ROILabel","AOI","ycoor","xcoor")] 134 | pythonTruth <- pythonTruth[order(pythonTruth$ROILabel, 135 | pythonTruth$AOI, 136 | pythonTruth$xcoor),] 137 | 138 | # decreased test data size 139 | expect_true(all(coords[1:nrow(pythonTruth),c("ycoor", "xcoor")] == 140 | pythonTruth[,c("ycoor","xcoor")])) 141 | }) 142 | 143 | testthat::test_that("Outline points on segemented data - warning",{ 144 | #Spec 3. The function only returns outline coordinates on Geometric data. 145 | expect_warning(createCoordFile(SpatialOverlay(slideName = "normal3", 146 | scanMetadata = scanMetadataKidney, 147 | overlayData = kidneyAOIattrs), 148 | outline = TRUE), 149 | regexp = "Outline coordinates do not work in segmented data") 150 | }) 151 | 152 | 153 | testthat::test_that("Boundary is behaving as expected",{ 154 | #Spec 1. The function returns expected number of neighbors. 155 | testBound <- matrix(1, ncol = 3, nrow = 3) 156 | expect_equal(matrix(boundary(testBound), ncol = 3, nrow = 3), 157 | matrix(c(3,5,3,5,8,5,3,5,3), ncol = 3, nrow = 3)) 158 | 159 | testBound <- matrix(0, ncol = 3, nrow = 3) 160 | expect_equal(matrix(boundary(testBound), ncol = 3, nrow = 3), 161 | matrix(0, ncol = 3, nrow = 3)) 162 | 163 | testBound <- matrix(c(1,1,1,0,0,0,1,1,1), ncol = 3, nrow = 3) 164 | expect_equal(matrix(boundary(testBound), ncol = 3, nrow = 3), 165 | matrix(c(1,2,1,4,6,4,1,2,1), ncol = 3, nrow = 3)) 166 | 167 | testBound <- matrix(c(0,0,0,1,1,1,0,0,0), ncol = 3, nrow = 3) 168 | expect_equal(matrix(boundary(testBound), ncol = 3, nrow = 3), 169 | matrix(c(2,3,2,1,2,1,2,3,2), ncol = 3, nrow = 3)) 170 | 171 | testBound <- matrix(c(0,0,0,0,1,0,0,0,0), ncol = 3, nrow = 3) 172 | expect_equal(matrix(boundary(testBound), ncol = 3, nrow = 3), 173 | matrix(c(1,1,1,1,0,1,1,1,1), ncol = 3, nrow = 3)) 174 | }) 175 | 176 | testthat::test_that("moveCoords works as expected",{ 177 | #Spec 1. The function moves only expected coordinate by 1. 178 | expect_identical(coords$xcoor, coords(moveCoords(overlay, "up"))$xcoor) 179 | expect_identical(coords$ycoor+1, coords(moveCoords(overlay, "up"))$ycoor) 180 | 181 | expect_identical(coords$xcoor, coords(moveCoords(overlay, "down"))$xcoor) 182 | expect_identical(coords$ycoor-1, coords(moveCoords(overlay, "down"))$ycoor) 183 | 184 | expect_identical(coords$xcoor-1, coords(moveCoords(overlay, "left"))$xcoor) 185 | expect_identical(coords$ycoor, coords(moveCoords(overlay, "left"))$ycoor) 186 | 187 | expect_identical(coords$xcoor+1, coords(moveCoords(overlay, "right"))$xcoor) 188 | expect_identical(coords$ycoor, coords(moveCoords(overlay, "right"))$ycoor) 189 | }) 190 | -------------------------------------------------------------------------------- /longtests/testthat/test_extraction.R: -------------------------------------------------------------------------------- 1 | tifFile <- downloadMouseBrainImage() 2 | 3 | testthat::test_that("Error when xml path doesn't exist",{ 4 | #Spec 1. The function only works with valid ometiff file. 5 | expect_error(xmlExtraction("fakeFilePath.ome.tiff"), 6 | regexp = "ometiff file does not exist") 7 | }) 8 | 9 | xml <- xmlExtraction(ometiff = tifFile, saveFile = TRUE) 10 | xmlFile <- gsub(tifFile, pattern = "tiff", replacement = "xml") 11 | 12 | testthat::test_that("returned list is correct",{ 13 | #Spec 2. The function returns a valid list with the expected names. 14 | expect_true(class(xml) == "list") 15 | expect_true(length(xml) > 0) 16 | expect_true(all(names(xml) %in% c("Plate", "Screen", "Instrument", "Image", 17 | "StructuredAnnotations", "ROI", ".attrs"))) 18 | expect_true(length(which(names(xml) == "ROI")) > 1) 19 | 20 | #Spec 3. The function saves xml file in expected location, if desired. 21 | expect_true(file.exists(xmlFile)) 22 | }) 23 | 24 | unlink(xmlFile) 25 | 26 | xml <- xmlExtraction(ometiff = tifFile, saveFile = FALSE) 27 | 28 | testthat::test_that("no file saved",{ 29 | #Spec 4. The function doesn't save file when not asked. 30 | expect_false(file.exists(xmlFile)) 31 | }) 32 | 33 | fullSizeX <- 32768 34 | fullSizeY <- 32768 35 | 36 | scanMeta <- parseScanMetadata(xml) 37 | 38 | testthat::test_that("correct image gets extracted", { 39 | #Spec 1. The function only extracts valid res layers. 40 | expect_error(imageExtraction(ometiff = tifFile, res = 9), 41 | regexp = "valid res integers for this image must be between") 42 | #Spec 2. The function extracts expected res layer. 43 | for(i in 5:8){ 44 | image <- imageExtraction(ometiff = tifFile, res = i, scanMeta = scanMeta) 45 | expect_true(class(image) == "magick-image") 46 | expect_true(image_info(image)$width == fullSizeX/2^(i-1)) 47 | expect_true(image_info(image)$height == fullSizeY/2^(i-1)) 48 | } 49 | }) 50 | 51 | testthat::test_that("saved images are as expected",{ 52 | #Spec 3. The function saves file in expected location and in correct & 53 | # valid fileType. 54 | #tiff 55 | image <- imageExtraction(ometiff = tifFile, res = 8, scanMeta = scanMeta, 56 | saveFile = T, fileType = "tiff") 57 | imageFile <- gsub(".ome.tiff", ".tiff", tifFile) 58 | expect_true(file.exists(imageFile)) 59 | unlink(imageFile) 60 | 61 | #png 62 | image <- imageExtraction(ometiff = tifFile, res = 8, scanMeta = scanMeta, 63 | saveFile = T, fileType = "png") 64 | imageFile <- gsub(".ome.tiff", ".png", tifFile) 65 | expect_true(file.exists(imageFile)) 66 | unlink(imageFile) 67 | 68 | #jpg 69 | image <- imageExtraction(ometiff = tifFile, res = 8, scanMeta = scanMeta, 70 | saveFile = T, fileType = "jpg") 71 | imageFile <- gsub(".ome.tiff", ".jpeg", tifFile) 72 | expect_true(file.exists(imageFile)) 73 | unlink(imageFile) 74 | 75 | #jpeg 76 | image <- imageExtraction(ometiff = tifFile, res = 8, scanMeta = scanMeta, 77 | saveFile = T, fileType = "jpeg") 78 | imageFile <- gsub(".ome.tiff", ".jpeg", tifFile) 79 | expect_true(file.exists(imageFile)) 80 | unlink(imageFile) 81 | 82 | expect_error(imageExtraction(ometiff = tifFile, res = 8, scanMeta = scanMeta, 83 | saveFile = T, fileType = "fakeFile"), 84 | regexp = "fileType not valid") 85 | }) 86 | 87 | testthat::test_that("checkValidRes is correct",{ 88 | #Spec 1. The function returns expected value. 89 | expect_true(checkValidRes(tifFile) == 8) 90 | }) 91 | -------------------------------------------------------------------------------- /longtests/testthat/test_imageManipulation.R: -------------------------------------------------------------------------------- 1 | tiff <- downloadMouseBrainImage() 2 | 3 | if(!file.exists("muBrain.RDS")){ 4 | tifFile <- downloadMouseBrainImage() 5 | annots <- system.file("extdata", "muBrain_LabWorksheet.txt", 6 | package = "SpatialOmicsOverlay") 7 | 8 | overlay <- suppressWarnings(readSpatialOverlay(ometiff = tifFile, annots = annots, 9 | slideName = "D5761 (3)", outline = FALSE)) 10 | 11 | saveRDS(overlay, "muBrain.RDS") 12 | }else{ 13 | overlay <- readRDS( "muBrain.RDS") 14 | } 15 | 16 | overlayImage <- addImageOmeTiff(overlay, tiff, res = 8) 17 | overlay4Chan <- add4ChannelImage(overlay, tiff, res = 8) 18 | 19 | testthat::test_that("cropTissue works",{ 20 | #Spec 4. The function requires valid input. 21 | expect_error(cropTissue("overlay"), 22 | regexp = "Overlay must be a SpatialOverlay object") 23 | expect_error(cropTissue(overlay), regexp = "No image found") 24 | 25 | tissue <- cropTissue(overlayImage) 26 | 27 | #Spec 1. The function returns smaller image. 28 | expect_true(image_info(showImage(overlayImage))$width > 29 | image_info(showImage(tissue))$width) 30 | expect_true(image_info(showImage(overlayImage))$height > 31 | image_info(showImage(tissue))$height) 32 | 33 | #Spec 2. The function returns all original coordinates. 34 | expect_true(nrow(coords(overlayImage)) == nrow(coords(tissue))) 35 | 36 | #Spec 3. The function produces reproducible results. 37 | vdiffr::expect_doppelganger("cropTissue", showImage(tissue)) 38 | 39 | tissue4chan <- cropTissue(overlay4Chan) 40 | 41 | expect_true(dim(imageData(showImage(overlay4Chan)))[2] > 42 | image_info(showImage(tissue4chan))$width) 43 | expect_true(dim(imageData(showImage(overlay4Chan)))[1] > 44 | image_info(showImage(tissue4chan))$height) 45 | 46 | vdiffr::expect_doppelganger("cropTissue4Chan", showImage(tissue4chan)) 47 | }) 48 | 49 | testthat::test_that("cropSamples works",{ 50 | #Spec 1. The function requires valid input. 51 | expect_error(cropSamples("overlay"), 52 | regexp = "Overlay must be a SpatialOverlay object") 53 | 54 | samps <- sampNames(overlayImage)[sample(x = 1:length(sampNames(overlayImage)), 55 | size = 2, replace = FALSE)] 56 | 57 | expect_error(cropSamples(overlay, samps), regexp = "No image found") 58 | 59 | sampOnlyImage <- cropSamples(overlayImage, sampleIDs = samps, sampsOnly = TRUE) 60 | 61 | #Spec 1. The function returns smaller image. 62 | expect_true(image_info(showImage(overlayImage))$width > 63 | image_info(showImage(sampOnlyImage))$width) 64 | expect_true(image_info(showImage(overlayImage))$height > 65 | image_info(showImage(sampOnlyImage))$height) 66 | 67 | #Spec 2. The function returns all coordinates of only the given samples. 68 | expect_true(nrow(coords(overlayImage)) > nrow(coords(sampOnlyImage))) 69 | expect_true(nrow(coords(overlayImage)[coords(overlayImage)$sampleID %in% samps,]) == 70 | nrow(coords(sampOnlyImage))) 71 | 72 | #Spec 3. The function produces reproducible results. 73 | vdiffr::expect_doppelganger("cropSamples sampsOnly", showImage(sampOnlyImage)) 74 | 75 | sampImage <- cropSamples(overlayImage, sampleIDs = samps, sampsOnly = FALSE) 76 | 77 | #Spec 1. The function returns smaller image. 78 | expect_true(image_info(showImage(overlayImage))$width > 79 | image_info(showImage(sampImage))$width) 80 | expect_true(image_info(showImage(overlayImage))$height > 81 | image_info(showImage(sampImage))$height) 82 | 83 | #Spec 2. The function returns all coordinates of the given samples. 84 | expect_true(nrow(coords(overlayImage)) > nrow(coords(sampImage))) 85 | expect_true(nrow(coords(overlayImage)[coords(overlayImage)$sampleID %in% samps,]) < 86 | nrow(coords(sampImage))) 87 | 88 | #Spec 3. The function returns coordinates within dimensions of cropped image. 89 | expect_true(all(coords(sampOnlyImage)$xcoor < 90 | image_info(showImage(sampOnlyImage))$width)) 91 | expect_true(all(coords(sampOnlyImage)$ycoor < 92 | image_info(showImage(sampOnlyImage))$height)) 93 | 94 | expect_true(all(coords(sampImage)$xcoor < 95 | image_info(showImage(sampImage))$width + 1)) 96 | expect_true(all(coords(sampImage)$ycoor < 97 | image_info(showImage(sampImage))$height + 1)) 98 | 99 | #Spec 4. The function produces reproducible results. 100 | vdiffr::expect_doppelganger("cropSamples all ROIs", showImage(sampImage)) 101 | 102 | #Spec 5. The function only works with valid sampleIDs. 103 | expect_error(expect_warning(cropSamples(overlayImage, 104 | sampleIDs = "fakeID", 105 | sampsOnly = TRUE), 106 | regexp = "invalid sampleIDs given"), 107 | regexp = "No valid sampleIDs") 108 | 109 | expect_error(cropSamples(overlayImage, sampleIDs = NULL, sampsOnly = TRUE), 110 | regexp = "No valid sampleIDs") 111 | 112 | expect_warning(cropSamples(overlayImage, 113 | sampleIDs = c(samps,"fakeID"), 114 | sampsOnly = TRUE), 115 | regexp = "invalid sampleIDs given") 116 | }) 117 | 118 | testthat::test_that("flipX works",{ 119 | #Spec 3. The function requires valid input. 120 | expect_error(flipX("overlay"), 121 | regexp = "Overlay must be a SpatialOverlay object") 122 | expect_error(flipX(overlay), regexp = "No image is attached") 123 | 124 | #Spec 1. The function returns expected coordinates. 125 | expect_true(all(abs(image_info(showImage(overlayImage))$width - 126 | coords(overlayImage)$xcoor) == 127 | coords(flipX(overlayImage))$xcoor)) 128 | 129 | #Spec 2. The function produces reproducible results. 130 | vdiffr::expect_doppelganger("flipX", showImage(flipX(overlayImage))) 131 | }) 132 | 133 | testthat::test_that("flipY works",{ 134 | #Spec 3. The function requires valid input. 135 | expect_error(flipX("overlay"), 136 | regexp = "Overlay must be a SpatialOverlay object") 137 | expect_error(flipX(overlay), regexp = "No image is attached") 138 | 139 | #Spec 1. The function returns expected coordinates. 140 | expect_true(all(abs(image_info(showImage(overlayImage))$height - 141 | coords(overlayImage)$ycoor) == 142 | coords(flipY(overlayImage))$ycoor)) 143 | 144 | #Spec 2. The function produces reproducible results. 145 | vdiffr::expect_doppelganger("flipY", showImage(flipY(overlayImage))) 146 | }) 147 | 148 | testthat::test_that("coloring changes need 4 channel image",{ 149 | #Spec 1. The function only works on 4-channel images. 150 | expect_error(changeColoringIntensity(overlay, minInten = 0, 151 | maxInten = 100000, dye = "Cy3"), 152 | regexp = "Image in overlay must be the raw 4-channel image") 153 | #Spec 1. The function only works on 4-channel images. 154 | expect_error(changeImageColoring(overlay, "orange", "Cy3"), 155 | regexp = "Image in overlay must be the raw 4-channel image") 156 | }) 157 | 158 | overlay <- add4ChannelImage(overlay, tiff, res = 8) 159 | 160 | testthat::test_that("changeColorIntensity works",{ 161 | #Spec 2. The function changes min/max intensity values of only correct fluor. 162 | fluorChange <- changeColoringIntensity(overlay, minInten = 0, 163 | maxInten = 100000, dye = "Cy3") 164 | fluorChange <- changeColoringIntensity(fluorChange, minInten = 0, 165 | maxInten = 100, dye = "Alexa 647") 166 | 167 | cy3 <- which(fluor(overlay)$DisplayName == "Cy3") 168 | alexa647 <- which(fluor(overlay)$Dye == "Alexa 647") 169 | 170 | expect_true(all(fluor(overlay)$MinIntensity[-c(cy3,alexa647)] == 171 | fluor(fluorChange)$MinIntensity[-c(cy3,alexa647)])) 172 | expect_true(all(fluor(overlay)$MaxIntensity[-c(cy3,alexa647)] == 173 | fluor(fluorChange)$MaxIntensity[-c(cy3,alexa647)])) 174 | 175 | expect_true(fluor(fluorChange)$MinIntensity[cy3] == 0) 176 | expect_true(fluor(fluorChange)$MaxIntensity[cy3] == 100000) 177 | 178 | expect_true(fluor(fluorChange)$MinIntensity[alexa647] == 0) 179 | expect_true(fluor(fluorChange)$MaxIntensity[alexa647] == 100) 180 | }) 181 | 182 | testthat::test_that("changeImageColoring works",{ 183 | #Spec 2. The function changes ColorCode values of only correct fluor. 184 | fluorChange <- changeImageColoring(overlay, "orange", dye = "Cy3") 185 | fluorChange <- changeImageColoring(fluorChange, "#03fcf8", dye = "Alexa 647") 186 | fluorChange <- changeImageColoring(fluorChange, "#03c6fc", dye = "FITC") 187 | 188 | expect_false(all(fluor(overlay)$ColorCode == fluor(fluorChange)$ColorCode)) 189 | 190 | cy3 <- which(fluor(overlay)$DisplayName == "Cy3") 191 | alexa647 <- which(fluor(overlay)$Dye == "Alexa 647") 192 | fitc <- which(fluor(overlay)$DisplayName == "FITC") 193 | 194 | expect_true(all(fluor(overlay)$ColorCode[-c(cy3,alexa647,fitc)] == 195 | fluor(fluorChange)$ColorCode[-c(cy3,alexa647,fitc)])) 196 | 197 | expect_true(fluor(fluorChange)$ColorCode[cy3] == "orange") 198 | expect_true(fluor(fluorChange)$ColorCode[alexa647] == "#03fcf8") 199 | expect_true(fluor(fluorChange)$ColorCode[fitc] == "#03c6fc") 200 | 201 | expect_true(fluor(fluorChange)$Color[cy3] == "Orange") 202 | expect_true(fluor(fluorChange)$Color[alexa647] == "Cyan") 203 | expect_true(fluor(fluorChange)$Color[fitc] == "Deepskyblue") 204 | }) 205 | 206 | # need help writing a test that isn't just a copy of the function 207 | testthat::test_that("imageColoring works",{ 208 | #Spec 1. The function creates RGB image arrays. 209 | overlayRGB <- imageColoring(showImage(overlay), scanMeta(overlay)) 210 | 211 | expect_true(dim(imageData(overlayRGB))[3] == 3) 212 | 213 | #Spec 2. The function produces reproducible results. 214 | vdiffr::expect_doppelganger("imageColoring", image_read(overlayRGB)) 215 | }) 216 | 217 | testthat::test_that("recoloring works",{ 218 | #Spec 4. The function requires valid input. 219 | expect_error(recolor(overlayImage), 220 | regexp = "Image in overlay must be the raw 4-channel image") 221 | 222 | fluorChange <- changeImageColoring(overlay, "orange", dye = "Cy3") 223 | overlayRGB <- recolor(fluorChange) 224 | 225 | #Spec 1. The function scales coordinates. 226 | expect_true(overlay@workflow$scaled) 227 | 228 | expect_true(image_info(showImage(overlayImage))$width > 229 | image_info(showImage(overlayRGB))$width) 230 | expect_true(image_info(showImage(overlayImage))$height > 231 | image_info(showImage(overlayRGB))$height) 232 | 233 | #Spec 2. The function creates RGB image arrays. 234 | expect_false(all(imageData(as_EBImage(showImage(overlayRGB))) == 235 | imageData(as_EBImage(showImage(cropTissue(overlayImage)))))) 236 | 237 | expect_true(dim(imageData(as_EBImage(showImage(overlayRGB))))[3] == 3) 238 | 239 | #Spec 3. The function produces reproducible results. 240 | vdiffr::expect_doppelganger("recolor", showImage(overlayRGB)) 241 | }) 242 | -------------------------------------------------------------------------------- /longtests/testthat/test_parsing.R: -------------------------------------------------------------------------------- 1 | tifFile <- downloadMouseBrainImage() 2 | annots <- system.file("extdata", "muBrain_LabWorksheet.txt", 3 | package = "SpatialOmicsOverlay") 4 | 5 | annots <- readLabWorksheet(lw = annots, slideName = "D5761 (3)") 6 | 7 | extracted <- xmlExtraction(ometiff = tifFile, saveFile = T) 8 | 9 | scanMetadata <- parseScanMetadata(omexml = extracted) 10 | 11 | testthat::test_that("scanMetadata works on non expected variables",{ 12 | #Spec 1. The function works on ometiff variable instead of expected xml. 13 | expect_identical(scanMetadata, 14 | parseScanMetadata(omexml = tifFile)) 15 | }) 16 | 17 | testthat::test_that("scanMetadata is formatted correctly",{ 18 | #Spec 2. The function returns a list with all of the expected names. 19 | expect_true(class(scanMetadata) == "list") 20 | # expect_identical(scanMetadata, scan_metadata) 21 | expect_true(all(names(scanMetadata) == c("Panels", "PhysicalSizes", 22 | "Fluorescence"))) 23 | expect_true(all(names(scanMetadata$PhysicalSizes) == c("X", "Y"))) 24 | expect_true(all(names(scanMetadata$Fluorescence) == c("Dye","DisplayName", 25 | "Color","WaveLength", 26 | "Target", 27 | "ExposureTime", 28 | "MinIntensity", 29 | "MaxIntensity", 30 | "ColorCode"))) 31 | }) 32 | 33 | unzip(system.file("extdata", "testData", "kidney.zip", 34 | package = "SpatialOmicsOverlay"), 35 | exdir = "testData") 36 | 37 | kidneyXML <- readRDS("testData/kidneyXML.RDS") 38 | kidneyAnnots <- read.table("testData/kidney_annotations_allROIs.txt", 39 | header = T, sep = "\t") 40 | 41 | scanMetadataKidney <- parseScanMetadata(kidneyXML) 42 | 43 | testthat::test_that("fluorData works with 1 or 2 annotations in xml",{ 44 | #Spec 1. The function works on xmls where fluor data takes up 1 or 2 lines. 45 | 46 | #E11 data, each fluor takes up 2 annotations 47 | #kidney data, each fluor takes only 1 annotation 48 | 49 | expect_true(nrow(scanMetadata$Fluorescence) == 50 | nrow(scanMetadataKidney$Fluorescence)) 51 | 52 | expect_true(length(unique(scanMetadata$Fluorescence$Dye)) == 53 | nrow(scanMetadata$Fluorescence)) 54 | expect_true(length(unique(scanMetadata$Fluorescence$DisplayName)) == 55 | nrow(scanMetadata$Fluorescence)) 56 | expect_true(length(unique(scanMetadata$Fluorescence$Color)) == 57 | nrow(scanMetadata$Fluorescence)) 58 | expect_true(length(unique(scanMetadata$Fluorescence$WaveLength)) == 59 | nrow(scanMetadata$Fluorescence)) 60 | 61 | expect_true(length(unique(scanMetadataKidney$Fluorescence$Dye)) == 62 | nrow(scanMetadataKidney$Fluorescence)) 63 | expect_true(length(unique(scanMetadataKidney$Fluorescence$DisplayName)) == 64 | nrow(scanMetadataKidney$Fluorescence)) 65 | expect_true(length(unique(scanMetadataKidney$Fluorescence$Color)) == 66 | nrow(scanMetadataKidney$Fluorescence)) 67 | expect_true(length(unique(scanMetadataKidney$Fluorescence$WaveLength)) == 68 | nrow(scanMetadataKidney$Fluorescence)) 69 | }) 70 | 71 | testthat::test_that("fluorData works",{ 72 | #Spec 2. The function returns a data.frame with all of the expected values 73 | Dye <- c("Alexa 488", "SYTO 83", "Alexa 594", "Alexa 647") 74 | DisplayName <- c("FITC", "Cy3", "Texas Red", "Cy5") 75 | Color <- c("Blue", "Green", "Yellow", "Red") 76 | WaveLength <- c("525nm", "568nm", "615nm", "666nm") 77 | Target <- c("GFAP", "DNA", "Iba-1", "NeuN") 78 | ExposureTime <- c("200.0 µs", "50.0 µs", "300.0 µs", "100.0 µs") 79 | ColorCode <- c("#0000feff", "#00fe00ff", "#fefe00ff", "#fe0000ff") 80 | MinIntensity <- c(50, 4, 33, 88) 81 | MaxIntensity <- c(18509, 805, 3174, 30000) 82 | 83 | trueDF <- as.data.frame(cbind(Dye, DisplayName, Color, WaveLength, 84 | Target, ExposureTime, MinIntensity, 85 | MaxIntensity, ColorCode)) 86 | 87 | expect_identical(scanMetadata$Fluorescence, trueDF) 88 | }) 89 | 90 | testthat::test_that("Physical Sizes returns correctly",{ 91 | #Spec 1. The function works returns list with expected names & values. 92 | ps <- physicalSizes(extracted) 93 | expect_true(all(names(ps) == c("X", "Y"))) 94 | expect_true(class(ps) == "list") 95 | expect_true(class(ps$X) == "numeric") 96 | expect_true(class(ps$Y) == "numeric") 97 | expect_true(names(ps$X) == "µm/pixel") 98 | expect_true(names(ps$Y) == "µm/pixel") 99 | 100 | expect_equal(ps$X, c("µm/pixel"=0.3993132), tolerance = 1e-6) 101 | expect_equal(ps$Y, c("µm/pixel"=0.4003363), tolerance = 1e-6) 102 | }) 103 | 104 | testthat::test_that("Errors with invalid inputs",{ 105 | #Spec 1. The function requires correct inputs. 106 | expect_error(parseOverlayAttrs(omexml = extracted, annots = annots, 107 | labworksheet = FALSE), 108 | regexp = "Please change labWorksheet") 109 | 110 | expect_error(parseOverlayAttrs(omexml = extracted, annots = "annots", 111 | labworksheet = TRUE), 112 | regexp = "File must be read into R and passed as a dataframe") 113 | }) 114 | 115 | testthat::test_that("Warnings occur when AOIs are missing or mislabeled",{ 116 | #Spec 2. The function only works with valid sample names. 117 | expect_warning(AOIattrs <- parseOverlayAttrs(omexml = extracted, 118 | annots = rbind(annots, 119 | c(rep("FAKE", 9), 120 | 100)), 121 | labworksheet = TRUE), 122 | regexp = "Some AOIs do not match annotation file") 123 | }) 124 | 125 | AOIattrs <- suppressWarnings(parseOverlayAttrs(omexml = extracted, annots = annots, 126 | labworksheet = TRUE)) 127 | 128 | testthat::test_that("AOIattrs are correct",{ 129 | #Spec 3. The function returns SpatialPosition with correct column names. 130 | expect_true(class(AOIattrs) == "SpatialPosition") 131 | expect_true(class(meta(AOIattrs)) == "data.frame") 132 | expect_true(all(c("ROILabel","Sample_ID","Height","Width", 133 | "X","Y","Segmentation") %in% colnames(meta(AOIattrs)))) 134 | expect_true(class(position(AOIattrs)) == "character") 135 | expect_true(length(position(AOIattrs)) == nrow(meta(AOIattrs))) 136 | expect_true(all(position(AOIattrs) == AOIattrs@position$Position)) 137 | }) 138 | 139 | kidneyAOIattrs <- parseOverlayAttrs(kidneyXML, kidneyAnnots, 140 | labworksheet = FALSE) 141 | #number of pixels used as proxy for AOI size 142 | #for segmented ROIs compared order of #pixels and area 143 | #for geometric ROIs matched on ROILabel 144 | testthat::test_that("annotMatching is correct",{ 145 | #Spec 1. The function matches sampleIDs correctly between xml and annots. 146 | for(i in unique(meta(kidneyAOIattrs)$ROILabel)){ 147 | ROI <- meta(kidneyAOIattrs)[meta(kidneyAOIattrs)$ROILabel == i,] 148 | 149 | if(nrow(ROI) > 1){ 150 | totalPixels <- NULL 151 | for(j in ROI$Sample_ID){ 152 | pixels <- nrow(coordsFromMask(createMask(b64string = position(kidneyAOIattrs)[meta(kidneyAOIattrs)$Sample_ID == j], 153 | metadata = ROI[ROI$Sample_ID == j,], 154 | outline = FALSE), 155 | metadata = ROI[ROI$Sample_ID == j,], 156 | outline = FALSE)) 157 | totalPixels[j] <- pixels/scanMetadataKidney$PhysicalSizes$X 158 | } 159 | 160 | subsetAnnots <- kidneyAnnots[kidneyAnnots$SegmentDisplayName %in% ROI$Sample_ID,] 161 | 162 | expect_true(all(names(sort(totalPixels)) == subsetAnnots$SegmentDisplayName[order(subsetAnnots$AOISurfaceArea)])) 163 | }else{ 164 | expect_true(ROI$Sample_ID == kidneyAnnots$SegmentDisplayName[kidneyAnnots$ROILabel == as.numeric(i)]) 165 | } 166 | } 167 | }) 168 | 169 | -------------------------------------------------------------------------------- /longtests/testthat/test_readSpatialOverlay.R: -------------------------------------------------------------------------------- 1 | tifFile <- downloadMouseBrainImage() 2 | annots <- system.file("extdata", "muBrain_LabWorksheet.txt", 3 | package = "SpatialOmicsOverlay") 4 | 5 | annotsGxT <- readRDS(unzip(system.file("extdata", "muBrain_GxT.zip", 6 | package = "SpatialOmicsOverlay"))) 7 | annotsGxT <- annotsGxT[,sData(annotsGxT)$Updated_SegLabels == "Full ROI"] 8 | 9 | colnames(annotsGxT@protocolData@data)[which(colnames(annotsGxT@protocolData@data) == "ScanLabel")] <- "slide name" 10 | colnames(annotsGxT@phenoData@data)[which(colnames(annotsGxT@phenoData@data) == "SegmentLabel")] <- "segment" 11 | 12 | overlay <- suppressWarnings(readSpatialOverlay(ometiff = tifFile, annots = annots, 13 | slideName = "D5761 (3)", outline = FALSE)) 14 | 15 | testthat::test_that("annotation input types",{ 16 | #Spec 1. The function works with either a labworksheet or a geomxset object 17 | # as annotation. 18 | expect_error(overlay <- suppressWarnings(readSpatialOverlay(ometiff = tifFile, 19 | annots = annots, 20 | slideName = "D5761 (3)", 21 | outline = FALSE)), NA) 22 | 23 | expect_error(overlayBound <- readSpatialOverlay(ometiff = tifFile, 24 | annots = annotsGxT, 25 | slideName = "D5761 (3)", 26 | outline = TRUE), NA) 27 | 28 | #Spec 2. The function only returns samples in both xml and annotation 29 | expect_true(all(sampNames(overlayBound) %in% sampNames(overlay))) 30 | expect_false(all(sampNames(overlay) %in% sampNames(overlayBound))) 31 | }) 32 | 33 | 34 | testthat::test_that("readSpatialOverlay works as expected - all points",{ 35 | #Spec 1. The function returns a SpatialOverlay object. 36 | expect_true(class(overlay) == "SpatialOverlay") 37 | 38 | #Spec 2. The function returns a SpatialOverlay object with the expected 39 | # values in the correct locations. 40 | expect_true(labWork(overlay) == TRUE) 41 | expect_true(seg(overlay) == "Segmented") 42 | expect_true(outline(overlay) == FALSE) 43 | expect_true(is.null(plotFactors(overlay))) 44 | expect_true(slideName(overlay) == "D5761 (3)") 45 | 46 | annots <- readLabWorksheet(lw = annots, slideName = "D5761 (3)") 47 | labWorksheet <- TRUE 48 | xml <- xmlExtraction(ometiff = tifFile, saveFile = FALSE) 49 | 50 | expect_identical(scanMeta(overlay)[1:3], parseScanMetadata(omexml = xml)) 51 | expect_identical(overlay(overlay), suppressWarnings(parseOverlayAttrs(omexml = xml, 52 | annots = annots, 53 | labworksheet = TRUE))) 54 | expect_identical(coords(overlay), coords(createCoordFile(overlay, 55 | outline = FALSE))) 56 | }) 57 | 58 | overlayImage <- suppressWarnings(readSpatialOverlay(ometiff = tifFile, 59 | annots = annots, 60 | slideName = "D5761 (3)", 61 | outline = FALSE, 62 | image = TRUE, res = 8)) 63 | 64 | testthat::test_that("readSpatialOverlay works as expected - with image",{ 65 | #Spec 1. The function returns a SpatialOverlay object. 66 | expect_true(class(overlayImage) == "SpatialOverlay") 67 | 68 | #Spec 2. The function returns a SpatialOverlay object with the expected 69 | # values in the correct locations. 70 | expect_true(labWork(overlayImage) == TRUE) 71 | expect_true(seg(overlayImage) == "Segmented") 72 | expect_true(outline(overlayImage) == FALSE) 73 | expect_true(is.null(plotFactors(overlayImage))) 74 | expect_true(slideName(overlayImage) == "D5761 (3)") 75 | 76 | annots <- readLabWorksheet(lw = annots, slideName = "D5761 (3)") 77 | labWorksheet <- TRUE 78 | xml <- xmlExtraction(ometiff = tifFile, saveFile = FALSE) 79 | 80 | expect_identical(scanMeta(overlayImage)[1:3], parseScanMetadata(omexml = xml)) 81 | expect_identical(overlay(overlayImage), suppressWarnings(parseOverlayAttrs(omexml = xml, 82 | annots = annots, 83 | labworksheet = TRUE))) 84 | 85 | #Spec 3. The function returns a SpatialOverlay object with image in expected 86 | # location. 87 | expect_true(overlayImage@image$filePath == tifFile) 88 | expect_true(class(showImage(overlayImage)) == "magick-image") 89 | expect_true(overlayImage@image$resolution == 8) 90 | 91 | #Spec 4. The function returns a SpatialOverlay object with scaled 92 | # coordinates to image. 93 | expect_true(nrow(coords(overlayImage)) < nrow(coords(overlay))) 94 | }) 95 | 96 | overlayBound <- readSpatialOverlay(ometiff = tifFile, annots = annotsGxT, 97 | slideName = "D5761 (3)", outline = TRUE) 98 | 99 | testthat::test_that("readSpatialOverlay works as expected - boundary points",{ 100 | #Spec 1. The function returns a SpatialOverlay object. 101 | expect_true(class(overlayBound) == "SpatialOverlay") 102 | 103 | #Spec 2. The function returns a SpatialOverlay object with the expected 104 | # values in the correct locations. 105 | expect_true(labWork(overlayBound) == TRUE) 106 | expect_true(seg(overlayBound) == "Geometric") 107 | expect_true(outline(overlayBound) == TRUE) 108 | expect_true(is.null(plotFactors(overlayBound))) 109 | expect_true(slideName(overlayBound) == "D5761 (3)") 110 | 111 | annots <- sData(annotsGxT) 112 | annots <- annots[annots$`slide name` == "D5761 (3)",] 113 | annots$Sample_ID <- gsub(".dcc", "", rownames(annots)) 114 | colnames(annots)[colnames(annots) == "roi"] <- "ROILabel" 115 | 116 | xml <- xmlExtraction(ometiff = tifFile, saveFile = FALSE) 117 | 118 | expect_identical(scanMeta(overlayBound)[1:3], parseScanMetadata(omexml = xml)) 119 | expect_identical(overlay(overlayBound), suppressWarnings(parseOverlayAttrs(omexml = xml, 120 | annots = annots, 121 | labworksheet = TRUE))) 122 | expect_identical(coords(overlayBound), coords(createCoordFile(overlayBound, 123 | outline = TRUE))) 124 | }) 125 | -------------------------------------------------------------------------------- /longtests/testthat/test_removeSamples.R: -------------------------------------------------------------------------------- 1 | unzip(system.file("extdata", "testData", "kidney.zip", 2 | package = "SpatialOmicsOverlay"), 3 | exdir = "testData") 4 | 5 | kidneyXML <- readRDS("testData/kidneyXML.RDS") 6 | kidneyAnnots <- read.table("testData/kidney_annotations_allROIs.txt", 7 | header = T, sep = "\t") 8 | 9 | scanMetadataKidney <- parseScanMetadata(kidneyXML) 10 | 11 | kidneyAOIattrs <- parseOverlayAttrs(kidneyXML, kidneyAnnots, labworksheet = FALSE) 12 | 13 | scanMetadataKidney[["Segmentation"]] <- ifelse(all(meta(kidneyAOIattrs)$Segmentation == "Geometric"), 14 | yes = "Geometric",no = "Segmented") 15 | 16 | overlay <- SpatialOverlay(slideName = "normal3", 17 | scanMetadata = scanMetadataKidney, 18 | overlayData = kidneyAOIattrs) 19 | 20 | segmentedROIs <- meta(overlay(overlay))$Sample_ID[which(meta(overlay(overlay))$Segmentation == "Segmented")] 21 | 22 | geometricOverlay <- removeSample(overlay, segmentedROIs) 23 | 24 | testthat::test_that("removeSamples only removes valid sample names", { 25 | #Spec 1. The function only works on valid sample names. 26 | expect_warning(temp <- removeSample(overlay = overlay, remove = "fakeSample"), 27 | regexp = "No valid sample names") 28 | expect_identical(overlay, temp) 29 | }) 30 | 31 | testthat::test_that("removeSamples works as intended before coords and plotFactors", { 32 | #Spec 2. The function works before adding coordinates and plotting factors. 33 | expect_false(length(sampNames(overlay)) == length(sampNames(geometricOverlay))) 34 | expect_true(all(sampNames(geometricOverlay) %in% sampNames(overlay))) 35 | expect_false(all(sampNames(overlay) %in% sampNames(geometricOverlay))) 36 | expect_false(any(segmentedROIs %in% sampNames(geometricOverlay))) 37 | expect_true(length(sampNames(overlay))-length(segmentedROIs) == length(sampNames(geometricOverlay))) 38 | expect_false(seg(overlay) == seg(geometricOverlay)) 39 | expect_null(coords(geometricOverlay)) 40 | expect_null(coords(overlay)) 41 | expect_null(plotFactors(geometricOverlay)) 42 | expect_null(plotFactors(overlay)) 43 | }) 44 | 45 | overlay <- createCoordFile(overlay, outline = FALSE) 46 | 47 | geometricOverlay <- removeSample(overlay, segmentedROIs) 48 | 49 | testthat::test_that("removeSamples works as intended afer coords and before plotFactors", { 50 | #Spec 3. The function works after adding coordinates and before plotting 51 | # factors. 52 | expect_false(length(sampNames(overlay)) == length(sampNames(geometricOverlay))) 53 | expect_true(all(sampNames(geometricOverlay) %in% sampNames(overlay))) 54 | expect_false(all(sampNames(overlay) %in% sampNames(geometricOverlay))) 55 | expect_false(any(segmentedROIs %in% sampNames(geometricOverlay))) 56 | expect_true(length(sampNames(overlay))-length(segmentedROIs) == length(sampNames(geometricOverlay))) 57 | expect_false(seg(overlay) == seg(geometricOverlay)) 58 | expect_null(plotFactors(geometricOverlay)) 59 | expect_null(plotFactors(overlay)) 60 | expect_false(any(segmentedROIs %in% coords(geometricOverlay)$sampleID)) 61 | }) 62 | 63 | overlay <- addPlottingFactor(overlay, kidneyAnnots, "Segment_type") 64 | 65 | geometricOverlay <- removeSample(overlay, segmentedROIs) 66 | 67 | testthat::test_that("removeSamples works as intended after coords and plotFactors", { 68 | #Spec 4. The function works after adding coordinates and plotting factors. 69 | expect_false(length(sampNames(overlay)) == length(sampNames(geometricOverlay))) 70 | expect_true(all(sampNames(geometricOverlay) %in% sampNames(overlay))) 71 | expect_false(all(sampNames(overlay) %in% sampNames(geometricOverlay))) 72 | expect_false(any(segmentedROIs %in% sampNames(geometricOverlay))) 73 | expect_true(length(sampNames(overlay))-length(segmentedROIs) == length(sampNames(geometricOverlay))) 74 | expect_false(seg(overlay) == seg(geometricOverlay)) 75 | expect_false(nrow(plotFactors(geometricOverlay)) == nrow(plotFactors(overlay))) 76 | expect_false(any(segmentedROIs %in% rownames(plotFactors(geometricOverlay)))) 77 | expect_false(any(segmentedROIs %in% coords(geometricOverlay)$sampleID)) 78 | }) 79 | 80 | -------------------------------------------------------------------------------- /longtests/testthat/test_utils.R: -------------------------------------------------------------------------------- 1 | 2 | testthat::test_that("bookendStr prints correctly",{ 3 | #Spec 1. The function returns a string in the expected format. 4 | start_string <- stringi::stri_rand_strings(n = 1, length = 25) 5 | reps <- 10 6 | string <- paste(rep(start_string, reps), collapse = "") 7 | for(i in 1:(nchar(start_string)-1)){ 8 | tester <- bookendStr(string, bookend = i) 9 | tester <- stringr::str_split(tester, pattern = "\\(|\\.\\.\\.", 10 | simplify = T) 11 | expect_identical(tester[,1], paste0(substr(start_string, 1, i), " ")) 12 | expect_identical(tester[,2], paste0(" ", substr(start_string, 13 | nchar(start_string)-(i-1), 14 | nchar(start_string)), " ")) 15 | expect_identical(tester[,3], paste(nchar(start_string)*reps, 16 | "total char)")) 17 | } 18 | }) 19 | 20 | lw <- system.file("extdata", "testData", "test_LabWorksheet.txt", 21 | package = "SpatialOmicsOverlay") 22 | 23 | testthat::test_that("read labworksheet works",{ 24 | #Spec 1. The function only works on correct file paths. 25 | expect_error(readLabWorksheet(lw, "fake_slide"), 26 | regexp = "No ROIs match given slideName") 27 | #Spec 2. The function only works on correct slide names. 28 | expect_error(readLabWorksheet("fake/file/path", "hu_brain_004b"), 29 | regexp = "Lab worksheet path is invalid") 30 | 31 | #Spec 3. The function only returns annotations from the specified slide. 32 | annots4b <- readLabWorksheet(lw, "hu_brain_004b") 33 | annots4a <- readLabWorksheet(lw, "hu_brain_004a") 34 | 35 | expect_true(all(colnames(annots4b) == c("Sample_ID", "slide.name", "scan.name", 36 | "panel", "roi", "segment", "aoi", 37 | "area", "tags", "ROILabel"))) 38 | expect_true(all(colnames(annots4a) == c("Sample_ID", "slide.name", "scan.name", 39 | "panel", "roi", "segment", "aoi", 40 | "area", "tags", "ROILabel"))) 41 | 42 | expect_true(all(annots4a$slide.name == "hu_brain_004a")) 43 | expect_true(all(annots4b$slide.name == "hu_brain_004b")) 44 | 45 | expect_false(nrow(annots4b) == nrow(annots4a)) 46 | expect_false(any(annots4b$Sample_ID %in% annots4a$Sample_ID)) 47 | expect_false(any(annots4b$Sample_ID %in% annots4a$Sample_ID)) 48 | }) 49 | 50 | testthat::test_that("mouse brain tiff can be downloaded",{ 51 | #Spec 1. The function downloads the mouse brain tiff and returns a valid 52 | # file path. 53 | tifFile <- downloadMouseBrainImage() 54 | 55 | expect_true(endsWith(tifFile, "mu_brain_004.ome.tiff")) 56 | expect_true(file.exists(tifFile)) 57 | }) 58 | 59 | -------------------------------------------------------------------------------- /man/SpatialOverlay-class.Rd: -------------------------------------------------------------------------------- 1 | \name{SpatialOverlay-class} 2 | \docType{class} 3 | 4 | \alias{class:SpatialOverlay} 5 | \alias{SpatialOverlay-class} 6 | 7 | % constructors 8 | \alias{SpatialOverlay} 9 | \alias{SpatialOverlay,character-method} 10 | 11 | % show 12 | \alias{show,SpatialOverlay-method} 13 | 14 | % accessing 15 | \alias{slideName} 16 | \alias{slideName,SpatialOverlay-method} 17 | \alias{overlay} 18 | \alias{overlay,SpatialOverlay-method} 19 | \alias{scanMeta} 20 | \alias{scanMeta,SpatialOverlay-method} 21 | \alias{coords} 22 | \alias{coords,SpatialOverlay-method} 23 | \alias{plotFactors} 24 | \alias{plotFactors,SpatialOverlay-method} 25 | \alias{labWork} 26 | \alias{labWork,SpatialOverlay-method} 27 | \alias{outline} 28 | \alias{outline,SpatialOverlay-method} 29 | \alias{seg} 30 | \alias{seg,SpatialOverlay-method} 31 | \alias{scaleBarRatio} 32 | \alias{scaleBarRatio,SpatialOverlay-method} 33 | \alias{fluor} 34 | \alias{fluor,SpatialOverlay-method} 35 | \alias{sampNames} 36 | \alias{sampNames,SpatialOverlay-method} 37 | \alias{showImage} 38 | \alias{showImage,SpatialOverlay-method} 39 | \alias{res} 40 | \alias{res,SpatialOverlay-method} 41 | \alias{workflow} 42 | \alias{workflow,SpatialOverlay-method} 43 | \alias{scaled} 44 | \alias{scaled,SpatialOverlay-method} 45 | \alias{imageInfo} 46 | \alias{imageInfo,SpatialOverlay-method} 47 | 48 | 49 | \title{Class to Contain NanoString Spatial Overlay Images and Data} 50 | 51 | \description{ 52 | The \code{SpatialOverlay} class organizes the pertinant information from the 53 | OME-TIFFs allowing for plotting on top of or beside the image 54 | } 55 | 56 | \usage{ 57 | SpatialOverlay(slideName, 58 | scanMetadata, 59 | overlayData, 60 | coords = NULL, 61 | plottingFactors = NULL, 62 | workflow = list(outline=FALSE, 63 | labWorksheet=TRUE, 64 | scaled=FALSE), 65 | image = list(filePath = NULL, 66 | imagePointer = NULL, 67 | resolution = NULL)) 68 | } 69 | 70 | \arguments{ 71 | \item{slideName}{The name of the slide in the \code{SpatialOverlay} object} 72 | \item{scanMetadata}{A \code{list} containing the scan metadata: panel(s) used, 73 | Physical sizes (x,y) for scale bar, fluorescence data, and segmentation info} 74 | \item{overlayData}{An \code{\link{SpatialPosition}} containing individiual sample 75 | info: SampleID, Height, Width, X&Y coordinates in overall scan, 76 | segmentation, and base64 encoded position} 77 | \item{coords}{An optional \code{data.frame} with coordinates derived from the encoded position.} 78 | \item{plottingFactors}{An optional \code{data.frame} with annotations to plot on. 79 | These can be added using \code{\link{addPlottingFactor}}} 80 | \item{workflow}{A \code{list} containing meta-data on the processing workflow including 81 | \code{"outline"}, \code{"labWorksheet"}, & \code{"scaled"}. These booleans are kept 82 | automatically in \code{\link{readSpatialOverlay}} and are used 83 | for logic gates in downstream processing} 84 | \item{image}{A \code{list} containing location of and pointer to the image: 85 | \code{"filePath"}, \code{"imagePointer"}, & \code{"resolution"}} 86 | } 87 | 88 | \section{Accessing}{ 89 | \code{SpatialOverlay} objects have the following accessor methods: 90 | \describe{ 91 | \item{sampNames(object)}{ 92 | extracts the sample names of each ROI in the slide. 93 | } 94 | \item{slideName(object)}{ 95 | extracts the slide name. 96 | } 97 | \item{overlay(object)}{ 98 | extracts the \code{SpatialPosition} information for each ROI. 99 | } 100 | \item{scanMeta(object)}{ 101 | extracts the scan metadata. 102 | } 103 | \item{scanMeta(object)}{ 104 | \code{coords(object)}: extracts the coordinates for the entire scan. 105 | } 106 | \item{plotFactors(object)}{ 107 | extracts avaliable plotting factors. 108 | } 109 | \item{labWork(object)}{ 110 | extracts the boolean if a lab worksheet was used. 111 | } 112 | \item{outline(object)}{ 113 | extracts the boolena if only the outline points 114 | were generated. 115 | } 116 | \item{seg(object)}{ 117 | extracts if there are any segmented ROIs in the slide. 118 | } 119 | \item{scaleBarRatio(object)}{ 120 | extracts the scale bar ratio from \code{scanMeta} for the X axis 121 | } 122 | \item{fluor(object)}{ 123 | extracts fluorenscence information for the scan. 124 | } 125 | \item{showImage(object)}{ 126 | prints image. 127 | } 128 | \item{res(object)}{ 129 | extracts resolution of image. 130 | } 131 | \item{workflow(object)}{ 132 | extracts workflow data. 133 | } 134 | \item{scaled(object)}{ 135 | extracts if coordinates have been scaled. 136 | } 137 | \item{imageInfo(object)}{ 138 | extracts image data. 139 | } 140 | } 141 | } 142 | 143 | \value{ 144 | An S4 class containing image data from a NanoString GeoMx experiment 145 | } 146 | 147 | \seealso{ 148 | \code{\link{readSpatialOverlay}} 149 | } 150 | 151 | \keyword{classes} 152 | \keyword{methods} -------------------------------------------------------------------------------- /man/SpatialPosition-class.Rd: -------------------------------------------------------------------------------- 1 | \name{SpatialPosition-class} 2 | \docType{class} 3 | 4 | \alias{class:SpatialPosition} 5 | \alias{SpatialPosition-class} 6 | 7 | % constructors 8 | \alias{SpatialPosition} 9 | \alias{SpatialPosition,environment-method} 10 | \alias{SpatialPosition,data.frame-method} 11 | \alias{SpatialPosition,matrix-method} 12 | \alias{SpatialPosition,missing-method} 13 | 14 | % show 15 | \alias{show,SpatialPosition-method} 16 | 17 | % accessing 18 | \alias{meta} 19 | \alias{meta,SpatialPosition-method} 20 | \alias{position} 21 | \alias{position,SpatialPosition-method} 22 | \alias{spatialPos} 23 | \alias{spatialPos,SpatialPosition-method} 24 | 25 | \title{Class to Contain NanoString Spatial Overlay ROI information} 26 | 27 | \description{ 28 | The \code{SpatialPosition} class organizes the pertinant ROI specific information 29 | from the OME-TIFFs 30 | } 31 | 32 | \usage{ 33 | SpatialPosition(position) 34 | } 35 | 36 | \arguments{ 37 | \item{position}{\code{data.frame} containing information from the OME-TIFF: 38 | 39 | \code{"ROILabel"} order of ROIs 40 | 41 | \code{"Sample_ID"} unique identifier 42 | 43 | \code{"Height"} total height of ROI 44 | 45 | \code{"Width"} total width of ROI 46 | 47 | \code{"X"} top left corner (x coordinate) of ROI in total scan 48 | 49 | \code{"Y"} top left corner (y coordinate) of ROI in total scan 50 | 51 | \code{"Segmentation"} part of segmented ROI 52 | 53 | \code{"Position"} base64 encoding of coordinates} 54 | } 55 | 56 | \section{Accessing}{ 57 | \code{SpatialPosition} objects have the following accessor methods: 58 | \describe{ 59 | \item{spatialPos(object)}{returns SpatialPosition object} 60 | \item{meta(object)}{ 61 | extracts the metadata for each ROI, does not include the base64 encoding. 62 | } 63 | \item{position(object)}{ 64 | extracts the base64 encoding for each ROI, CAUTION: very long strings. 65 | } 66 | } 67 | } 68 | 69 | \value{ 70 | An S4 class containing image data from a NanoString GeoMx experiment 71 | } 72 | 73 | \seealso{ 74 | \code{\link{SpatialOverlay-class}} 75 | } 76 | 77 | \keyword{classes} 78 | \keyword{methods} -------------------------------------------------------------------------------- /man/add4ChannelImage.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/addImage.R 3 | \name{add4ChannelImage} 4 | \alias{add4ChannelImage} 5 | \title{Add 4-channel image to SpatialOverlay from OME-TIFF. Allows for recoloring 6 | of image} 7 | \usage{ 8 | add4ChannelImage(overlay, ometiff = NULL, res = NULL, ...) 9 | } 10 | \arguments{ 11 | \item{overlay}{SpatialOverlay object} 12 | 13 | \item{ometiff}{File path to OME-TIFF. NULL indicates pull info from overlay} 14 | 15 | \item{res}{resolution layer, 1 = largest & higher values = smaller. The 16 | images increase in resolution and memory. The largest image your 17 | environment can hold is recommended. NULL indicates pull info 18 | from overlay} 19 | 20 | \item{...}{Extra variables} 21 | } 22 | \value{ 23 | SpatialOverlay object with image 24 | } 25 | \description{ 26 | Add 4-channel image to SpatialOverlay from OME-TIFF. Allows for recoloring 27 | of image 28 | } 29 | \examples{ 30 | 31 | muBrain <- readRDS(unzip(system.file("extdata", "muBrainSubset_SpatialOverlay.zip", 32 | package = "SpatialOmicsOverlay"))) 33 | 34 | image <- downloadMouseBrainImage() 35 | 36 | muBrain <- add4ChannelImage(overlay = muBrain, 37 | ometiff = image, res = 8) 38 | 39 | dim(EBImage::imageData(showImage(muBrain))) 40 | 41 | } 42 | -------------------------------------------------------------------------------- /man/addImageFile.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/addImage.R 3 | \name{addImageFile} 4 | \alias{addImageFile} 5 | \title{Add image to SpatialOverlay from disk} 6 | \usage{ 7 | addImageFile(overlay, imageFile = NULL, res = NULL) 8 | } 9 | \arguments{ 10 | \item{overlay}{SpatialOverlay object} 11 | 12 | \item{imageFile}{path to image} 13 | 14 | \item{res}{what resolution is the image given? 15 | 1 = largest, higher number = smaller 16 | This value will affect the coordinates of the overlays. 17 | res = 2, resolution is 1/2 the size as the raw image 18 | res = 3, resolution is 1/4 the size as the raw image 19 | res = 4, resolution is 1/8 the size as the raw image 20 | resolution = 1/2^(res-1)} 21 | } 22 | \value{ 23 | SpatialOverlay object with image 24 | } 25 | \description{ 26 | Add image to SpatialOverlay from disk 27 | } 28 | -------------------------------------------------------------------------------- /man/addImageOmeTiff.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/addImage.R 3 | \name{addImageOmeTiff} 4 | \alias{addImageOmeTiff} 5 | \title{Add image to SpatialOverlay from OME-TIFF} 6 | \usage{ 7 | addImageOmeTiff(overlay, ometiff = NULL, res = NULL, ...) 8 | } 9 | \arguments{ 10 | \item{overlay}{SpatialOverlay object} 11 | 12 | \item{ometiff}{File path to OME-TIFF. NULL indicates pull info from overlay} 13 | 14 | \item{res}{resolution layer, 1 = largest & higher values = smaller. The 15 | images increase in resolution and memory. The largest image your 16 | environment can hold is recommended. NULL indicates pull info 17 | from overlay} 18 | 19 | \item{...}{Extra variables} 20 | } 21 | \value{ 22 | SpatialOverlay object with image 23 | } 24 | \description{ 25 | Add image to SpatialOverlay from OME-TIFF 26 | } 27 | \examples{ 28 | 29 | muBrain <- readRDS(unzip(system.file("extdata", "muBrainSubset_SpatialOverlay.zip", 30 | package = "SpatialOmicsOverlay"))) 31 | 32 | image <- downloadMouseBrainImage() 33 | 34 | muBrain <- addImageOmeTiff(overlay = muBrain, 35 | ometiff = image, res = 8) 36 | showImage(muBrain) 37 | 38 | } 39 | -------------------------------------------------------------------------------- /man/addPlottingFactor.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/addPlottingFactor.R 3 | \name{addPlottingFactor} 4 | \alias{addPlottingFactor} 5 | \alias{addPlottingFactor,NanoStringGeoMxSet-method} 6 | \alias{addPlottingFactor,matrix-method} 7 | \alias{addPlottingFactor,tbl_df-method} 8 | \alias{addPlottingFactor,tbl-method} 9 | \alias{addPlottingFactor,data.frame-method} 10 | \alias{addPlottingFactor,character-method} 11 | \alias{addPlottingFactor,numeric-method} 12 | \alias{addPlottingFactor,factor-method} 13 | \title{Add plotting factor to \code{\link{SpatialOverlay}} object} 14 | \usage{ 15 | addPlottingFactor(overlay, annots, plottingFactor, ...) 16 | 17 | \S4method{addPlottingFactor}{NanoStringGeoMxSet}(overlay, annots, plottingFactor, countMatrix = "exprs") 18 | 19 | \S4method{addPlottingFactor}{matrix}(overlay, annots, plottingFactor) 20 | 21 | \S4method{addPlottingFactor}{tbl_df}(overlay, annots, plottingFactor) 22 | 23 | \S4method{addPlottingFactor}{tbl}(overlay, annots, plottingFactor) 24 | 25 | \S4method{addPlottingFactor}{data.frame}(overlay, annots, plottingFactor) 26 | 27 | \S4method{addPlottingFactor}{character}(overlay, annots, plottingFactor) 28 | 29 | \S4method{addPlottingFactor}{numeric}(overlay, annots, plottingFactor) 30 | 31 | \S4method{addPlottingFactor}{factor}(overlay, annots, plottingFactor) 32 | } 33 | \arguments{ 34 | \item{overlay}{\code{\link{SpatialOverlay}} object} 35 | 36 | \item{annots}{factor vector with the plottingFactor. if names match sample 37 | names in overlay vector will be matched on those, 38 | otherwise assumed in the correct order} 39 | 40 | \item{plottingFactor}{name of the new plotting factor} 41 | 42 | \item{...}{if using \code{NanoStringGeoMxSet}, name of count matrix to pull 43 | counts from} 44 | 45 | \item{countMatrix}{name of count matrix to pull counts from} 46 | } 47 | \value{ 48 | \code{\link{SpatialOverlay}} object with new plotting factor 49 | } 50 | \description{ 51 | Add plotting factor to \code{\link{SpatialOverlay}} object 52 | } 53 | \examples{ 54 | muBrain <- readRDS(unzip(system.file("extdata", "muBrainSubset_SpatialOverlay.zip", 55 | package = "SpatialOmicsOverlay"))) 56 | 57 | muBrainLW <- system.file("extdata", "muBrain_LabWorksheet.txt", 58 | package = "SpatialOmicsOverlay") 59 | 60 | muBrainLW <- readLabWorksheet(muBrainLW, slideName = "D5761 (3)") 61 | 62 | muBrain <- addPlottingFactor(overlay = muBrain, 63 | annots = muBrainLW, 64 | plottingFactor = "segment") 65 | 66 | muBrainGxT <- readRDS(unzip(system.file("extdata", "muBrain_GxT.zip", 67 | package = "SpatialOmicsOverlay"))) 68 | 69 | muBrain <- addPlottingFactor(overlay = muBrain, 70 | annots = muBrainGxT, 71 | plottingFactor = "Calm1", 72 | countMatrix = "exprs") 73 | 74 | muBrain <- addPlottingFactor(overlay = muBrain, 75 | annots = seq_len(length(sampNames(muBrain))), 76 | plottingFactor = "ROINum") 77 | 78 | head(plotFactors(muBrain)) 79 | 80 | muBrain <- readRDS(unzip(system.file("extdata", "muBrainSubset_SpatialOverlay.zip", 81 | package = "SpatialOmicsOverlay"))) 82 | 83 | muBrain <- addPlottingFactor(overlay = muBrain, 84 | annots = as.factor(seq_len(length(sampNames(muBrain)))), 85 | plottingFactor = "ROINum") 86 | 87 | head(plotFactors(muBrain)) 88 | } 89 | -------------------------------------------------------------------------------- /man/annotMatching.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/xmlParsing.R 3 | \name{annotMatching} 4 | \alias{annotMatching} 5 | \title{Match ROIs in annotation file to xml} 6 | \usage{ 7 | annotMatching(annots, ROInum, maskNum, maskText, segCol = NULL) 8 | } 9 | \arguments{ 10 | \item{annots}{df of annotations} 11 | 12 | \item{ROInum}{ROI number from xml file} 13 | 14 | \item{maskNum}{number of masks for ROI, used for AOI matching in software 15 | <= v2.4} 16 | 17 | \item{maskText}{segment name, used for AOI matching in software v2.4+} 18 | 19 | \item{segCol}{column containing segment name, if NULL function will determine automatically} 20 | } 21 | \value{ 22 | df with ROI unique identifiers 23 | } 24 | \description{ 25 | Match ROIs in annotation file to xml 26 | } 27 | -------------------------------------------------------------------------------- /man/bookendStr.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/utils.R 3 | \name{bookendStr} 4 | \alias{bookendStr} 5 | \title{Print long string in more managable fashion} 6 | \usage{ 7 | bookendStr(x, bookend = 8) 8 | } 9 | \arguments{ 10 | \item{x}{long string} 11 | 12 | \item{bookend}{number of characters on either side to print} 13 | } 14 | \value{ 15 | reformatted string 16 | } 17 | \description{ 18 | Print first and last n characters of string in this format: 19 | "### ... ### (x total char)" 20 | } 21 | \examples{ 22 | 23 | start_string <- stringi::stri_rand_strings(n = 1, length = 250) 24 | bookendStr(start_string, bookend = 6) 25 | 26 | } 27 | -------------------------------------------------------------------------------- /man/changeColoringIntensity.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/imageManipulation.R 3 | \name{changeColoringIntensity} 4 | \alias{changeColoringIntensity} 5 | \title{Update color intensities for changing to RGB image} 6 | \usage{ 7 | changeColoringIntensity(overlay, minInten = NULL, maxInten = NULL, dye) 8 | } 9 | \arguments{ 10 | \item{overlay}{SpatialOverlay object} 11 | 12 | \item{minInten}{value to change MinIntensity to; NULL indicates no change} 13 | 14 | \item{maxInten}{value to change MaxIntensity to; NULL indicates no change} 15 | 16 | \item{dye}{which dye to change color, can be from Dye or DisplayName column 17 | from fluor(overlay)} 18 | } 19 | \value{ 20 | SpatialOverlay object with updated fluor data 21 | } 22 | \description{ 23 | Update color intensities for changing to RGB image 24 | } 25 | \examples{ 26 | 27 | muBrain <- readRDS(unzip(system.file("extdata", "muBrainSubset_SpatialOverlay.zip", 28 | package = "SpatialOmicsOverlay"))) 29 | 30 | image <- downloadMouseBrainImage() 31 | 32 | muBrain <- add4ChannelImage(overlay = muBrain, 33 | ometiff = image, res = 8) 34 | 35 | fluor(muBrain) 36 | 37 | muBrain <- changeColoringIntensity(overlay = muBrain, 38 | minInten = 500, 39 | maxInten = 10000, 40 | dye = "Cy5") 41 | 42 | fluor(muBrain) 43 | 44 | } 45 | -------------------------------------------------------------------------------- /man/changeImageColoring.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/imageManipulation.R 3 | \name{changeImageColoring} 4 | \alias{changeImageColoring} 5 | \title{Update color scheme for changing to RGB image} 6 | \usage{ 7 | changeImageColoring(overlay, color, dye) 8 | } 9 | \arguments{ 10 | \item{overlay}{SpatialOverlay object, with 4channel image} 11 | 12 | \item{color}{color to change dye to, hex or color name} 13 | 14 | \item{dye}{which dye to change color, can be from Dye or DisplayName column 15 | from fluor(overlay)} 16 | } 17 | \value{ 18 | SpatialOverlay object with updated fluor data 19 | } 20 | \description{ 21 | Update color scheme for changing to RGB image 22 | } 23 | \examples{ 24 | 25 | muBrain <- readRDS(unzip(system.file("extdata", "muBrainSubset_SpatialOverlay.zip", 26 | package = "SpatialOmicsOverlay"))) 27 | 28 | muBrain <- add4ChannelImage(overlay = muBrain, 29 | ometiff = downloadMouseBrainImage(), res = 8) 30 | 31 | fluor(muBrain) 32 | 33 | muBrain <- changeImageColoring(overlay = muBrain, color = "magenta", 34 | dye = "Cy5") 35 | muBrain <- changeImageColoring(overlay = muBrain, color = "#42f5ef", 36 | dye = "Alexa 488") 37 | 38 | fluor(muBrain) 39 | 40 | } 41 | -------------------------------------------------------------------------------- /man/checkValidRes.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/omeExtraction.R 3 | \name{checkValidRes} 4 | \alias{checkValidRes} 5 | \title{Determine lowest resolution image in OME-TIFF} 6 | \usage{ 7 | checkValidRes(ometiff) 8 | } 9 | \arguments{ 10 | \item{ometiff}{path to OME-TIFF} 11 | } 12 | \value{ 13 | value of lowest res image 14 | } 15 | \description{ 16 | Determine lowest resolution image in OME-TIFF 17 | } 18 | \examples{ 19 | 20 | image <- downloadMouseBrainImage() 21 | checkValidRes(ometiff = image) 22 | 23 | } 24 | -------------------------------------------------------------------------------- /man/createCoordFile.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/coordinateGeneration.R 3 | \name{createCoordFile} 4 | \alias{createCoordFile} 5 | \title{Create coordinate file for entire scan} 6 | \usage{ 7 | createCoordFile(overlay, outline = TRUE) 8 | } 9 | \arguments{ 10 | \item{overlay}{SpatialOverlay object} 11 | 12 | \item{outline}{returned coordinates only contain boundaries, 13 | will not work for segmented ROIs} 14 | } 15 | \value{ 16 | df of coordinates for every AOI in the scan 17 | } 18 | \description{ 19 | Create coordinate file for entire scan 20 | } 21 | \examples{ 22 | 23 | muBrain <- readRDS(unzip(system.file("extdata", "muBrainSubset_SpatialOverlay.zip", 24 | package = "SpatialOmicsOverlay"))) 25 | 26 | muBrain <- createCoordFile(muBrain, outline = FALSE) 27 | 28 | head(coords(muBrain)) 29 | 30 | } 31 | -------------------------------------------------------------------------------- /man/createMask.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/coordinateGeneration.R 3 | \name{createMask} 4 | \alias{createMask} 5 | \title{Create a binary mask from a base 64 string} 6 | \usage{ 7 | createMask(b64string, metadata, outline = TRUE) 8 | } 9 | \arguments{ 10 | \item{b64string}{base 64 string} 11 | 12 | \item{metadata}{metadata of AOI including: Height, Width of AOI} 13 | 14 | \item{outline}{only the outline points should be returned} 15 | } 16 | \value{ 17 | binary mask image 18 | } 19 | \description{ 20 | Create a binary mask from a base 64 string 21 | } 22 | \examples{ 23 | 24 | muBrain <- readRDS(unzip(system.file("extdata", "muBrainSubset_SpatialOverlay.zip", 25 | package = "SpatialOmicsOverlay"))) 26 | 27 | samp <- which(sampNames(muBrain) == "DSP-1012999073013-A-F12") 28 | 29 | ROIMask <- createMask(b64string = position(overlay(muBrain))[samp], 30 | metadata = meta(overlay(muBrain))[samp,], 31 | outline = TRUE) 32 | 33 | pheatmap::pheatmap(ROIMask, cluster_rows = FALSE, cluster_cols = FALSE) 34 | 35 | } 36 | -------------------------------------------------------------------------------- /man/cropSamples.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/imageManipulation.R 3 | \name{cropSamples} 4 | \alias{cropSamples} 5 | \title{Crop to zoom in on given ROIs} 6 | \usage{ 7 | cropSamples(overlay, sampleIDs, buffer = 0.1, sampsOnly = TRUE) 8 | } 9 | \arguments{ 10 | \item{overlay}{SpatialOverlay object} 11 | 12 | \item{sampleIDs}{sampleIDs of ROIs to keep in image} 13 | 14 | \item{buffer}{percent of new image size to add to each edge as a buffer} 15 | 16 | \item{sampsOnly}{should only ROIs with given sampleIDs be in image} 17 | } 18 | \value{ 19 | SpatialOverlay object 20 | } 21 | \description{ 22 | Crop to zoom in on given ROIs 23 | } 24 | \examples{ 25 | 26 | muBrain <- readRDS(unzip(system.file("extdata", "muBrainSubset_SpatialOverlay.zip", 27 | package = "SpatialOmicsOverlay"))) 28 | 29 | image <- downloadMouseBrainImage() 30 | 31 | muBrain <- addImageOmeTiff(overlay = muBrain, 32 | ometiff = image, res = 8) 33 | 34 | samps <- sampNames(muBrain) 35 | 36 | muBrainCrop <- suppressWarnings(cropSamples(overlay = muBrain, 37 | sampleIDs = samps, 38 | sampsOnly = TRUE)) 39 | 40 | plotSpatialOverlay(overlay = muBrainCrop, scaleBar = FALSE, 41 | hiRes = TRUE, legend = FALSE) 42 | 43 | } 44 | -------------------------------------------------------------------------------- /man/cropTissue.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/imageManipulation.R 3 | \name{cropTissue} 4 | \alias{cropTissue} 5 | \title{Crop to remove black boundary around tissue.} 6 | \usage{ 7 | cropTissue(overlay, buffer = 0.05) 8 | } 9 | \arguments{ 10 | \item{overlay}{SpatialOverlay object} 11 | 12 | \item{buffer}{percent of new image size to add to each edge as a buffer} 13 | } 14 | \value{ 15 | SpatialOverlay object 16 | } 17 | \description{ 18 | Crop to remove black boundary around tissue. 19 | } 20 | \examples{ 21 | 22 | muBrain <- readRDS(unzip(system.file("extdata", "muBrainSubset_SpatialOverlay.zip", 23 | package = "SpatialOmicsOverlay"))) 24 | 25 | image <- downloadMouseBrainImage() 26 | 27 | muBrain <- addImageOmeTiff(overlay = muBrain, 28 | ometiff = image, res = 8) 29 | 30 | muBrainCrop <- cropTissue(overlay = muBrain) 31 | 32 | plotSpatialOverlay(overlay = muBrainCrop, legend = FALSE, 33 | hiRes = FALSE, scaleBar = FALSE) 34 | 35 | } 36 | -------------------------------------------------------------------------------- /man/downloadMouseBrainImage.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/utils.R 3 | \name{downloadMouseBrainImage} 4 | \alias{downloadMouseBrainImage} 5 | \title{Download Mouse Brain OME-TIFF from NanoString's Spatial Organ Atlas} 6 | \usage{ 7 | downloadMouseBrainImage() 8 | } 9 | \value{ 10 | mouse brain OME-TIFF 11 | } 12 | \description{ 13 | Download Mouse Brain OME-TIFF from NanoString's Spatial Organ Atlas 14 | } 15 | \details{ 16 | https://nanostring.com/products/geomx-digital-spatial-profiler/spatial-organ-atlas/mouse-brain/ 17 | } 18 | \examples{ 19 | 20 | image <- downloadMouseBrainImage() 21 | 22 | } 23 | -------------------------------------------------------------------------------- /man/flipX.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/imageManipulation.R 3 | \name{flipX} 4 | \alias{flipX} 5 | \title{Flip x axis in image and overlay points} 6 | \usage{ 7 | flipX(overlay) 8 | } 9 | \arguments{ 10 | \item{overlay}{SpatialOverlay object} 11 | } 12 | \value{ 13 | SpatialOverlay object with x axis flipped 14 | } 15 | \description{ 16 | Flip x axis in image and overlay points 17 | } 18 | \examples{ 19 | 20 | muBrain <- readRDS(unzip(system.file("extdata", "muBrainSubset_SpatialOverlay.zip", 21 | package = "SpatialOmicsOverlay"))) 22 | 23 | image <- downloadMouseBrainImage() 24 | 25 | muBrain <- addImageOmeTiff(overlay = muBrain, 26 | ometiff = image, res = 8) 27 | 28 | showImage(flipX(muBrain)) 29 | 30 | } 31 | -------------------------------------------------------------------------------- /man/flipY.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/imageManipulation.R 3 | \name{flipY} 4 | \alias{flipY} 5 | \title{Flip y axis in image and overlay points} 6 | \usage{ 7 | flipY(overlay) 8 | } 9 | \arguments{ 10 | \item{overlay}{SpatialOverlay object} 11 | } 12 | \value{ 13 | SpatialOverlay object with y axis flipped 14 | } 15 | \description{ 16 | Flip y axis in image and overlay points 17 | } 18 | \examples{ 19 | muBrain <- readRDS(unzip(system.file("extdata", "muBrainSubset_SpatialOverlay.zip", 20 | package = "SpatialOmicsOverlay"))) 21 | 22 | image <- downloadMouseBrainImage() 23 | 24 | muBrain <- addImageOmeTiff(overlay = muBrain, 25 | ometiff = image, res = 8) 26 | 27 | showImage(flipY(muBrain)) 28 | 29 | } 30 | -------------------------------------------------------------------------------- /man/fluorLegend.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/plottingBasics.R 3 | \name{fluorLegend} 4 | \alias{fluorLegend} 5 | \title{Add legend of fluorescence targets that make up image} 6 | \usage{ 7 | fluorLegend(overlay, nrow = 4, textSize = 10, boxColor = "grey", alpha = 0.25) 8 | } 9 | \arguments{ 10 | \item{overlay}{SpatialOverlay} 11 | 12 | \item{nrow}{number of rows in the legend. Most studies have 4 which is 13 | where the values came from: 14 | 1 = horizontal legend, 4 = vertical legend, 2 = box legend} 15 | 16 | \item{textSize}{font size} 17 | 18 | \item{boxColor}{color of box behind legend} 19 | 20 | \item{alpha}{alpha value of box behind legend} 21 | } 22 | \value{ 23 | gp of fluorescence legend 24 | } 25 | \description{ 26 | Creates legend that can be overlayed on image using \code{cowplot}. 27 | } 28 | \examples{ 29 | 30 | muBrain <- readRDS(unzip(system.file("extdata", "muBrainSubset_SpatialOverlay.zip", 31 | package = "SpatialOmicsOverlay"))) 32 | 33 | # image <- downloadMouseBrainImage() 34 | 35 | # muBrain <- addImageOmeTiff(overlay = muBrain, 36 | # ometiff = image, res = 8) 37 | 38 | gp <- plotSpatialOverlay(overlay = muBrain, 39 | hiRes = FALSE, scaleBar = FALSE) 40 | 41 | legend <- fluorLegend(muBrain, nrow = 2, textSize = 3, boxColor = "red") 42 | 43 | cowplot::ggdraw() + 44 | cowplot::draw_plot(gp) + 45 | cowplot::draw_plot(legend, scale = 0.12, x = -0.3, y = -0.25) 46 | 47 | } 48 | -------------------------------------------------------------------------------- /man/moveCoords.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/coordinateGeneration.R 3 | \name{moveCoords} 4 | \alias{moveCoords} 5 | \title{Move coordinates if they don't match image} 6 | \usage{ 7 | moveCoords(overlay, direction = "right") 8 | } 9 | \arguments{ 10 | \item{overlay}{SpatialOverlay object} 11 | 12 | \item{direction}{which direction should coordinates move: left, right, up, down} 13 | } 14 | \value{ 15 | SpatialOverlay object 16 | } 17 | \description{ 18 | If generated coordinates do not match the image use this 19 | function to move coordinates. Coordinates are only changed 1 pixel at a time. 20 | } 21 | \examples{ 22 | 23 | muBrain <- readRDS(unzip(system.file("extdata", "muBrainSubset_SpatialOverlay.zip", 24 | package = "SpatialOmicsOverlay"))) 25 | head(coords(muBrain), 3) 26 | head(coords(moveCoords(muBrain, direction = "up")), 3) 27 | 28 | } 29 | -------------------------------------------------------------------------------- /man/parseOverlayAttrs.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/xmlParsing.R 3 | \name{parseOverlayAttrs} 4 | \alias{parseOverlayAttrs} 5 | \title{Parse the xml file for AOI attributes in GeoMx images} 6 | \usage{ 7 | parseOverlayAttrs(omexml, annots, labworksheet, ...) 8 | } 9 | \arguments{ 10 | \item{omexml}{xml file from OME-TIFF, can provide path to OME-TIFF and xml 11 | will automatically be extracted} 12 | 13 | \item{annots}{df of annotations} 14 | 15 | \item{labworksheet}{annots are from lab worksheet file} 16 | 17 | \item{...}{segCol in annotMatching, if auto detection doesn't work.} 18 | } 19 | \value{ 20 | SpatialPosition of AOIs containing metadata and base64encoded positions 21 | } 22 | \description{ 23 | Parse the xml file for AOI attributes in GeoMx images 24 | } 25 | \examples{ 26 | 27 | image <- downloadMouseBrainImage() 28 | 29 | xml <- xmlExtraction(ometiff = image) 30 | 31 | muBrainLW <- system.file("extdata", "muBrain_LabWorksheet.txt", 32 | package = "SpatialOmicsOverlay") 33 | 34 | muBrainLW <- readLabWorksheet(muBrainLW, slideName = "D5761 (3)") 35 | 36 | overlay <- parseOverlayAttrs(omexml = xml, 37 | annots = muBrainLW, 38 | labworksheet = TRUE) 39 | 40 | } 41 | -------------------------------------------------------------------------------- /man/parseScanMetadata.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/xmlParsing.R 3 | \name{parseScanMetadata} 4 | \alias{parseScanMetadata} 5 | \title{Parse the xml file for the scan metadata of GeoMx images} 6 | \usage{ 7 | parseScanMetadata(omexml) 8 | } 9 | \arguments{ 10 | \item{omexml}{xml file from OME-TIFF, can provide path to OME-TIFF and 11 | xml will automatically be extracted} 12 | } 13 | \value{ 14 | metadata for entire scan 15 | } 16 | \description{ 17 | Parse the xml file for the scan metadata of GeoMx images 18 | } 19 | \examples{ 20 | 21 | image <- downloadMouseBrainImage() 22 | 23 | xml <- xmlExtraction(ometiff = image) 24 | 25 | scan_metadata <- parseScanMetadata(omexml = xml) 26 | 27 | } 28 | -------------------------------------------------------------------------------- /man/plotSpatialOverlay.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/plottingBasics.R 3 | \name{plotSpatialOverlay} 4 | \alias{plotSpatialOverlay} 5 | \title{overlay plots} 6 | \usage{ 7 | plotSpatialOverlay( 8 | overlay, 9 | colorBy = "sampleID", 10 | hiRes = TRUE, 11 | alpha = 1, 12 | legend = TRUE, 13 | scaleBar = TRUE, 14 | image = TRUE, 15 | fluorLegend = FALSE, 16 | ..., 17 | corner = "bottomright", 18 | scaleBarWidth = 0.2, 19 | scaleBarMicrons = NULL, 20 | scaleBarColor = NULL, 21 | scaleBarFontSize = 6, 22 | scaleBarLineSize = 1.5, 23 | textDistance = 2 24 | ) 25 | } 26 | \arguments{ 27 | \item{overlay}{SpatialOverlay object} 28 | 29 | \item{colorBy}{annotation to color by} 30 | 31 | \item{hiRes}{generated figures are either high resolution or print quickly. 32 | Note: hiRes and outline ggplots use fill, lowRes uses color} 33 | 34 | \item{alpha}{opacity of overlays} 35 | 36 | \item{legend}{should legend be plotted} 37 | 38 | \item{scaleBar}{should scale bar be plotted} 39 | 40 | \item{image}{should image be plotted, image must be added to SpatialOverlay 41 | object} 42 | 43 | \item{fluorLegend}{should viz marker on the image be added to legend} 44 | 45 | \item{...}{additional parameters for scale bar line & text, will affect both} 46 | 47 | \item{corner}{where in the figure should the scale bar be printed. 48 | Options: "bottomright" "topright" 49 | "bottomleft" "topleft" 50 | "bottomcenter" "topcenter"} 51 | 52 | \item{scaleBarWidth}{percent of total figure the scale bar should take up} 53 | 54 | \item{scaleBarMicrons}{specific microns to set scale bar at, overrides scaleBarWidth if set} 55 | 56 | \item{scaleBarColor}{scale bar & text color} 57 | 58 | \item{scaleBarFontSize}{font size} 59 | 60 | \item{scaleBarLineSize}{width of line} 61 | 62 | \item{textDistance}{text's distance from scale bar.} 63 | } 64 | \value{ 65 | gp 66 | } 67 | \description{ 68 | overlay plots 69 | } 70 | \note{ 71 | hiRes and outline ggplots use fill, lowRes uses color 72 | } 73 | \examples{ 74 | 75 | muBrain <- readRDS(unzip(system.file("extdata", "muBrainSubset_SpatialOverlay.zip", 76 | package = "SpatialOmicsOverlay"))) 77 | 78 | plotSpatialOverlay(overlay = muBrain, legend = FALSE, 79 | hiRes = FALSE, scaleBar = FALSE) 80 | 81 | } 82 | -------------------------------------------------------------------------------- /man/readLabWorksheet.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/utils.R 3 | \name{readLabWorksheet} 4 | \alias{readLabWorksheet} 5 | \title{Read lab worksheet into dataframe of annotations} 6 | \usage{ 7 | readLabWorksheet(lw, slideName, roiCol = NULL, slideCol = NULL) 8 | } 9 | \arguments{ 10 | \item{lw}{lab worksheet file path} 11 | 12 | \item{slideName}{name of slide} 13 | 14 | \item{roiCol}{column containing ROI information, if NULL function will determine automatically} 15 | 16 | \item{slideCol}{column containing slide name, if NULL function will determine automatically} 17 | } 18 | \value{ 19 | df of ROI annotations 20 | } 21 | \description{ 22 | Read lab worksheet into dataframe of annotations 23 | } 24 | \examples{ 25 | 26 | muBrainLW <- system.file("extdata", "muBrain_LabWorksheet.txt", 27 | package = "SpatialOmicsOverlay") 28 | 29 | muBrainLW <- readLabWorksheet(muBrainLW, slideName = "D5761 (3)") 30 | 31 | } 32 | -------------------------------------------------------------------------------- /man/readSpatialOverlay.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/readSpatialOverlay.R 3 | \name{readSpatialOverlay} 4 | \alias{readSpatialOverlay} 5 | \title{Read in \code{\linkS4class{SpatialOverlay}} from tiff file and annotations} 6 | \usage{ 7 | readSpatialOverlay( 8 | ometiff, 9 | annots, 10 | slideName, 11 | image = FALSE, 12 | res = NULL, 13 | saveFile = FALSE, 14 | outline = TRUE, 15 | ..., 16 | segCol = NULL 17 | ) 18 | } 19 | \arguments{ 20 | \item{ometiff}{path to OME-TIFF} 21 | 22 | \item{annots}{path to annotation file: can be labWorksheet, DA excel file, or 23 | delimted file} 24 | 25 | \item{slideName}{name of slide} 26 | 27 | \item{image}{should image be extracted from OME-TIFF} 28 | 29 | \item{res}{resolution of image 30 | 1 = largest, higher number = smaller 31 | This value will affect the coordinates of the overlays. 32 | res = 2, resolution is 1/2 the size as the raw image 33 | res = 3, resolution is 1/4 the size as the raw image 34 | res = 4, resolution is 1/8 the size as the raw image 35 | resolution = 1/2^(res-1)} 36 | 37 | \item{saveFile}{should xml & image be saved, file is saved in working 38 | directory with same name as OME-TIFF} 39 | 40 | \item{outline}{returned coordinates only contain outlinearies, 41 | will not work for segmented ROIs} 42 | 43 | \item{...}{additional parameters for `readLabWorksheet` like `roiCol` and `slideCol`} 44 | 45 | \item{segCol}{additional parameter for `annotMatching` if default search doesn't work. 46 | For default search, set to NULL} 47 | } 48 | \value{ 49 | \code{\linkS4class{SpatialOverlay}} of slide 50 | } 51 | \description{ 52 | Create an instance of class \code{\linkS4class{SpatialOverlay}} 53 | by reading data from OME-TIFF and annotation sheet. 54 | } 55 | \examples{ 56 | 57 | muBrain_GxT <- readRDS(unzip(system.file("extdata", "muBrain_GxT.zip", 58 | package = "SpatialOmicsOverlay"))) 59 | 60 | image <- downloadMouseBrainImage() 61 | 62 | muBrain <- readSpatialOverlay(ometiff = image, annots = muBrain_GxT[,1:5], 63 | slideName = "D5761 (3)", image = TRUE, res = 8, 64 | saveFile = FALSE, outline = FALSE) 65 | 66 | } 67 | \seealso{ 68 | \code{\link{SpatialOverlay-class}} 69 | } 70 | -------------------------------------------------------------------------------- /man/recolor.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/imageManipulation.R 3 | \name{recolor} 4 | \alias{recolor} 5 | \title{recolor images after changing colors and/or color intensities} 6 | \usage{ 7 | recolor(overlay) 8 | } 9 | \arguments{ 10 | \item{overlay}{SpatialOverlay object} 11 | } 12 | \value{ 13 | SpatialOverlay object with RGB image 14 | } 15 | \description{ 16 | recolor images after changing colors and/or color intensities 17 | } 18 | \examples{ 19 | 20 | muBrain <- readRDS(unzip(system.file("extdata", "muBrainSubset_SpatialOverlay.zip", 21 | package = "SpatialOmicsOverlay"))) 22 | 23 | image <- downloadMouseBrainImage() 24 | 25 | muBrain <- add4ChannelImage(overlay = muBrain, 26 | ometiff = image, res = 8) 27 | 28 | muBrain <- changeImageColoring(overlay = muBrain, color = "magenta", 29 | dye = "Cy5") 30 | showImage(recolor(muBrain)) 31 | 32 | } 33 | -------------------------------------------------------------------------------- /man/removeSample.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/removeSamples.R 3 | \name{removeSample} 4 | \alias{removeSample} 5 | \title{Remove sample(s) from SpatialOverlay} 6 | \usage{ 7 | removeSample(overlay, remove) 8 | } 9 | \arguments{ 10 | \item{overlay}{SpatialOverlay object} 11 | 12 | \item{remove}{sampNames of overlay to remove} 13 | } 14 | \value{ 15 | SpatialOverlay object without samples in remove 16 | } 17 | \description{ 18 | Remove sample(s) from SpatialOverlay 19 | } 20 | \examples{ 21 | 22 | muBrain <- readRDS(unzip(system.file("extdata", "muBrainSubset_SpatialOverlay.zip", 23 | package = "SpatialOmicsOverlay"))) 24 | 25 | muBrainLW <- system.file("extdata", "muBrain_LabWorksheet.txt", 26 | package = "SpatialOmicsOverlay") 27 | 28 | muBrainLW <- readLabWorksheet(muBrainLW, slideName = "D5761 (3)") 29 | 30 | samps <- muBrainLW$Sample_ID[muBrainLW$segment != "Full ROI"] 31 | 32 | muBrainSub <- removeSample(overlay = muBrain, remove = samps) 33 | 34 | muBrain 35 | muBrainSub 36 | 37 | } 38 | -------------------------------------------------------------------------------- /man/xmlExtraction.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/omeExtraction.R 3 | \name{xmlExtraction} 4 | \alias{xmlExtraction} 5 | \title{Extract xml from OME-TIFF} 6 | \usage{ 7 | xmlExtraction(ometiff, saveFile = FALSE, outdir = NULL) 8 | } 9 | \arguments{ 10 | \item{ometiff}{path to OME-TIFF} 11 | 12 | \item{saveFile}{should xml be saved, file is saved in working directory with 13 | same name as OME-TIFF} 14 | 15 | \item{outdir}{output directory for saved xml. If NULL, saved in same directory as OME-TIFF} 16 | } 17 | \value{ 18 | list of xml data 19 | } 20 | \description{ 21 | Extract xml from OME-TIFF 22 | } 23 | \examples{ 24 | 25 | image <- downloadMouseBrainImage() 26 | xml <- xmlExtraction(ometiff = image) 27 | 28 | } 29 | -------------------------------------------------------------------------------- /tests/testthat.R: -------------------------------------------------------------------------------- 1 | library(testthat) 2 | library(vdiffr) 3 | 4 | options( java.parameters = "-Xmx4g" ) 5 | library( "RBioFormats" ) 6 | 7 | library(SpatialOmicsOverlay) 8 | 9 | # #run tests 10 | test_check("SpatialOmicsOverlay") 11 | 12 | 13 | -------------------------------------------------------------------------------- /vignettes/images/pyramidalTIFF.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Nanostring-Biostats/SpatialOmicsOverlay/fa91a50f1b6b668920697ed685b16717f2fb0454/vignettes/images/pyramidalTIFF.png --------------------------------------------------------------------------------