Diff of /R/assay.R [000000] .. [413088]

Switch to unified view

a b/R/assay.R
1
#' @include zzz.R
2
#' @importClassesFrom Matrix dgCMatrix dgRMatrix dgeMatrix
3
#' @importClassesFrom S4Arrays Array
4
NULL
5
6
####
7
# Objects and Classes ####
8
####
9
10
## vrAssay and vrAssayV2####
11
12
## UpdateAssay ####
13
14
updateAssayvrAssay <- function(object){
15
  
16
  # data matrix and feature data
17
  data_list <- list(main = object@rawdata, main_norm = object@normdata)
18
  featuredata_list <- list(main = object@featuredata)
19
  
20
  # create assay v2
21
  methods::new("vrAssayV2",
22
               data = data_list,
23
               featuredata = featuredata_list,
24
               embeddings = object@embeddings,
25
               image = object@image,
26
               params = object@params,
27
               type = object@type,
28
               name = object@name,
29
               main_image = object@main_image,
30
               main_featureset = "main")
31
}
32
33
#' @param object a vrAssay object to be converted to vrAssayV2
34
#' @rdname updateAssay
35
#' @method updateAssay vrAssay
36
#' @importFrom methods new
37
setMethod("updateAssay", "vrAssay", updateAssayvrAssay)
38
39
updateAssayvrAssayV2 <- function(object){
40
  message("The assay is of version 2, nothing to change!")
41
  return(object)
42
}
43
44
#' @param object a vrAssayV2 object to be converted to vrAssayV2
45
#' @rdname updateAssay
46
#' @method updateAssay vrAssayV2
47
setMethod("updateAssay", "vrAssayV2", updateAssayvrAssayV2)
48
49
####
50
# Methods ####
51
####
52
53
### Create vrAssay Object ####
54
55
#' formAssay
56
#'
57
#' Create a vrAssay (VoltRon assay) object
58
#'
59
#' @param data the feature matrix of spatialpoints
60
#' @param coords the coordinates of the spatial points
61
#' @param segments the list of segments each associated with a spatial point (optional)
62
#' @param image a singelton or list of images as magick-image objects
63
#' @param params additional parameters of the object
64
#' @param type the type of the assay (tile, molecule, cell, spot or ROI)
65
#' @param name the name of the assay
66
#' @param main_image the name of the main_image
67
#' @param main_featureset the name of the main_featureset
68
#' @param assay_version the assay version
69
#' @param ... additional arguements passed to \link{formImage}
70
#'
71
#' @importFrom methods new
72
#'
73
#' @export
74
#'
75
formAssay <- function(data = NULL, 
76
                      coords, 
77
                      segments = list(), 
78
                      image = NULL, 
79
                      params = list(), 
80
                      type = "ROI", 
81
                      name = "Assay1", 
82
                      main_image = "image_1", 
83
                      main_featureset = NULL, 
84
                      assay_version = "v2", 
85
                      ...){
86
87
  # get data
88
  if(is.null(data)){
89
    data <- matrix(nrow = 0, ncol = nrow(coords))
90
    colnames(data) <- rownames(coords)
91
  }
92
93
  # get image object
94
  image <- formImage(coords = coords, segments = segments, image = image, ...)
95
  image <- list(image)
96
  names(image) <- main_image
97
98
  # check feature
99
  if(is.null(main_featureset))
100
    main_featureset <- "main"
101
  
102
  # make vrAssay object
103
  data_list <- list(main = data, main_norm = data)
104
  names(data_list) <- c(main_featureset, paste0(main_featureset, "_norm"))
105
  if(assay_version == "v2"){
106
    object <-   methods::new("vrAssayV2", 
107
                             data = data_list,
108
                             image = image, params = params, type = type, name = name, 
109
                             main_image = main_image, main_featureset = main_featureset)
110
  } else {
111
    object <-   methods::new("vrAssay", 
112
                             rawdata = data, normdata = data,
113
                             image = image, params = params, type = type, name = name, 
114
                             main_image = main_image)
115
  }
116
  return(object)
117
}
118
119
### Subset vrAssay objects ####
120
121
subsetvrAssay <- function(x, subset, spatialpoints = NULL, features = NULL, image = NULL) {
122
  
123
  # start 
124
  object <- x
125
  
126
  if (!missing(x = subset)) {
127
    subset <- rlang::enquo(arg = subset)
128
  }
129
  
130
  # subseting on samples, layers and assays
131
  if(!is.null(features)){
132
    
133
    # select features
134
    nonmatching_features <- setdiff(features, vrFeatures(object))
135
    features <- intersect(vrFeatures(object), features)
136
    
137
    if(length(features) > 0){
138
      # object@rawdata <- object@rawdata[rownames(object@rawdata) %in% features,, drop = FALSE]
139
      # object@normdata <- object@normdata[rownames(object@normdata) %in% features,, drop = FALSE]
140
      object <- subsetData(object, features = features)
141
      object <- subsetData(object, features = features)
142
      
143
    } else {
144
      stop("none of the provided features are found in the assay")
145
    }
146
    
147
    if(length(nonmatching_features))
148
      message("the following features are not found in the assay: ", paste(nonmatching_features, collapse = ", "))
149
    
150
  } else {
151
    
152
    if(!is.null(spatialpoints)){
153
      
154
      # check if spatial points are here
155
      spatialpoints <- intersect(spatialpoints, vrSpatialPoints(object))
156
      if(length(spatialpoints) == 0){
157
        return(NULL)
158
      }
159
      
160
      # data
161
      # object@rawdata  <- object@rawdata[,spatialpoints, drop = FALSE]
162
      # object@normdata  <- object@normdata[,spatialpoints, drop = FALSE]
163
      object <- subsetData(object, spatialpoints = spatialpoints)
164
      object <- subsetData(object, spatialpoints = spatialpoints)
165
      
166
      # embeddings
167
      for(embed in vrEmbeddingNames(object)){
168
        embedding <- vrEmbeddings(object, type = embed)
169
        vrEmbeddings(object, type = embed) <- embedding[spatialpoints[spatialpoints %in% rownames(embedding)],, drop = FALSE]
170
      }
171
      
172
      # image
173
      # for(img in vrImageNames(object))
174
      for(img in vrSpatialNames(object))
175
        object@image[[img]] <- subsetvrImage(object@image[[img]], spatialpoints = spatialpoints)
176
        # object@image[[img]] <- subset.vrImage(object@image[[img]], spatialpoints = spatialpoints)
177
      
178
    } else if(!is.null(image)) {
179
      
180
      # images
181
      img <- vrMainSpatial(object)
182
      object@image <- object@image[img]
183
      object@image[[img]] <- subsetvrImage(object@image[[img]], image = image)
184
      # object@image[[img]] <- subset.vrImage(object@image[[img]], image = image)
185
      spatialpoints <- rownames(vrCoordinates(object@image[[img]]))
186
      
187
      # data
188
      # object@rawdata  <- object@rawdata[,colnames(object@rawdata) %in% spatialpoints, drop = FALSE]
189
      # object@normdata  <- object@normdata[,colnames(object@normdata) %in% spatialpoints, drop = FALSE]
190
      object <- subsetData(object, spatialpoints = spatialpoints)
191
      object <- subsetData(object, spatialpoints = spatialpoints)
192
      
193
      # embeddings
194
      for(embed in vrEmbeddingNames(object)){
195
        embedding <- vrEmbeddings(object, type = embed)
196
        vrEmbeddings(object, type = embed) <- embedding[rownames(embedding) %in% spatialpoints,, drop = FALSE]
197
      }
198
    } else {
199
      
200
      # else return empty
201
      return(NULL)
202
    }
203
  }
204
  
205
  # set VoltRon class
206
  return(object)
207
}
208
209
#' Subsetting vrAssay objects
210
#'
211
#' Given a vrAssay object, subset the object given one of the attributes
212
#'
213
#' @param x a vrAssay object
214
#' @param subset Logical statement for subsetting
215
#' @param spatialpoints the set of spatial points to subset the object
216
#' @param features the set of features to subset the object
217
#' @param image the subseting string passed to \link{image_crop}
218
#'
219
#' @method subset vrAssay
220
#' @order 4
221
#'
222
#' @importFrom rlang enquo
223
#'
224
#' @export
225
setMethod("subset", "vrAssay", subsetvrAssay)
226
227
#' Subsetting vrAssayV2 objects
228
#'
229
#' Given a vrAssayV2 object, subset the object given one of the attributes
230
#'
231
#' @param x a vrAssayV2 object
232
#' @param subset Logical statement for subsetting
233
#' @param spatialpoints the set of spatial points to subset the object
234
#' @param features the set of features to subset the object
235
#' @param image the subseting string passed to \link{image_crop}
236
#'
237
#' @method subset vrAssayV2
238
#' @order 4
239
#'
240
#' @export
241
setMethod("subset", "vrAssayV2", subsetvrAssay)
242
243
#' subsetCoordinates
244
#'
245
#' subsetting coordinates given cropping parameters of a magick image objects
246
#'
247
#' @param coords the coordinates of the spatial points
248
#' @param image the magick image associated with the coordinates
249
#' @param crop_info the subseting string passed to \link{image_crop}
250
#'
251
subsetCoordinates <- function(coords, image, crop_info){
252
253
  # image
254
  imageinfo <- image_info(image)
255
256
  # get crop information
257
  crop_info <- strsplit(crop_info, split = "\\+")[[1]]
258
  crop_info <- unlist(lapply(crop_info, function(x) strsplit(x, "x")))
259
  crop_info <- as.numeric(crop_info)
260
261
  # get uncropped spatial points
262
  xlim <- c(crop_info[3], crop_info[3]+crop_info[1])
263
  ylim <- c(crop_info[4], crop_info[4]+crop_info[2])
264
  ylim <- rev(imageinfo$height - ylim)
265
266
  # adjust for maximum res
267
  if(ylim[2] < 0){
268
    ylim[2] <- 0
269
    # ylim[1] <- ylim[2] - imageinfo$height + crop_info[2] # CHANGE THIS LATER ?
270
  }
271
  if(xlim[2] > imageinfo$width){
272
    xlim[2] <- imageinfo$width
273
    # xlim[1] <- xlim[2] - crop_info[1] # CHANGE THIS LATER ?
274
  }
275
276
  # get inside coords
277
  if(inherits(coords, "IterableMatrix")){
278
    # BPCells only accepts e1 > e2 ## S4 method for signature 'IterableMatrix,numeric'
279
    inside <- (!!as.vector(as(coords[,1] > xlim[1], "dgCMatrix")) & 
280
                 !!!as.vector(as(coords[,1] > xlim[2], "dgCMatrix"))) & 
281
      (!!as.vector(as(coords[,2] > ylim[1], "dgCMatrix")) & 
282
         !!!as.vector(as(coords[,2] > ylim[2], "dgCMatrix"))) 
283
  } else {
284
    inside <- (coords[,1] > xlim[1] & coords[,1] < xlim[2]) & (coords[,2] > ylim[1] & coords[,2] < ylim[2])
285
  }
286
  coords <- coords[inside,]
287
288
  if(nrow(coords) > 0){
289
    # adjust coordinates
290
    coords[,1] <- coords[,1] - xlim[1]
291
    coords[,2] <- coords[,2] - ylim[1]
292
293
    # return new coords
294
    return(coords)
295
  } else {
296
    stop("No spatial points remain after cropping!")
297
  }
298
}
299
300
#' subsetSegments
301
#'
302
#' subsetting segments given cropping parameters of a magick image objects
303
#'
304
#' @param segments the list of segments each associated with a spatial point
305
#' @param image the magick image associated with the coordinates
306
#' @param crop_info the subseting string passed to \link{image_crop}
307
#'
308
#' @importFrom dplyr bind_rows
309
subsetSegments <- function(segments, image, crop_info){
310
311
  # get segments
312
  segment_names <- names(segments)
313
  segments <- do.call(dplyr::bind_rows, segments)
314
  rownames(segments) <- seq_len(nrow(segments))
315
  segments <- data.frame(segments, row_id = rownames(segments))
316
  
317
  # subset
318
  cropped_segments <- subsetCoordinates(segments[,c("x","y")], image, crop_info)
319
  if(any(colnames(segments) %in% c("rx", "ry"))){
320
    cropped_segments_extra <- segments[rownames(cropped_segments), c("rx", "ry")]
321
    cropped_segments <- cbind(cropped_segments, cropped_segments_extra)
322
  }
323
  cropped_segments <- data.frame(cropped_segments, id = segments[rownames(cropped_segments),1], row_id = rownames(cropped_segments))
324
  cropped_segments <- cropped_segments %>% right_join(segments[,c(colnames(segments)[1], "row_id")], by = c("row_id" = "row_id"))
325
  if(any(colnames(segments) %in% c("rx", "ry"))){
326
    cropped_segments <- cropped_segments[,c(colnames(cropped_segments)[which(grepl(colnames(segments)[1], colnames(cropped_segments)))[1]], "x", "y", "rx", "ry")]
327
    colnames(cropped_segments) <- c("id", "x", "y", "rx", "ry")
328
    
329
  } else {
330
    cropped_segments <- cropped_segments[,c(colnames(cropped_segments)[which(grepl(colnames(segments)[1], colnames(cropped_segments)))[1]], "x", "y")]
331
    colnames(cropped_segments) <- c("id", "x", "y")
332
  }
333
  # split back to segments
334
  segments <- split(cropped_segments, cropped_segments[,1])
335
  segments <- lapply(segments, function(df){
336
    df[,colSums(is.na(df))<nrow(df), drop = FALSE]
337
  })
338
  names(segments) <- segment_names
339
  
340
  # return
341
  return(segments)
342
}
343
344
#' subsetData
345
#'
346
#' subsetting data matrices given spatialpoints, features etc.
347
#'
348
#' @param object a vrAssay object
349
#' @param spatialpoints the set of spatial points to subset the object
350
#' @param features the set of features to subset the object
351
#'
352
#' @noRd
353
subsetData <- function(object, spatialpoints = NULL, features = NULL){
354
  
355
  # features
356
  if(!is.null(features)){
357
    
358
    if(inherits(object, "vrAssay")){
359
      if(nrow(object@rawdata) > 0){
360
        object@rawdata <- object@rawdata[rownames(object@rawdata) %in% features,, drop = FALSE]
361
        object@normdata <- object@normdata[rownames(object@normdata) %in% features,, drop = FALSE]
362
      }
363
    } else {
364
      main <- vrMainFeatureType(object)
365
      if(nrow(object@data[[main]]) > 0){
366
        object@data[[main]] <- object@data[[main]][rownames(object@data[[main]]) %in% features,, drop = FALSE]
367
        object@data[[paste0(main, "_norm")]] <- object@data[[paste0(main, "_norm")]][rownames(object@data[[paste0(main, "_norm")]]) %in% features,, drop = FALSE]
368
      }
369
    }
370
  }
371
  
372
  # spatialpoints
373
  if(!is.null(spatialpoints)){
374
    
375
    if(inherits(object, "vrAssay")){
376
      # if(nrow(object@rawdata) > 0){
377
      if(ncol(object@rawdata) > 0){
378
        object@rawdata  <- object@rawdata[,colnames(object@rawdata) %in% spatialpoints, drop = FALSE]
379
        object@normdata  <- object@normdata[,colnames(object@normdata) %in% spatialpoints, drop = FALSE]
380
      }
381
    } else {
382
      for(nm in vrFeatureTypeNames(object)){
383
        # if(nrow(object@data[[nm]]) > 0){
384
        if(ncol(object@data[[nm]]) > 0){
385
          object@data[[nm]] <- object@data[[nm]][,colnames(object@data[[nm]]) %in% spatialpoints, drop = FALSE]
386
          object@data[[paste0(nm, "_norm")]] <- object@data[[paste0(nm, "_norm")]][,colnames(object@data[[paste0(nm, "_norm")]]) %in% spatialpoints, drop = FALSE]
387
        }
388
      }
389
    }
390
  }
391
  
392
  # return
393
  return(object)
394
}
395
396
#' getData
397
#'
398
#' get data matrix
399
#'
400
#' @param object a vrAssay object
401
#'
402
#' @noRd
403
getData <- function(object){
404
  
405
  if(inherits(object, "vrAssay")){
406
    data <- object@rawdata
407
  } else {
408
    data <- object@data[[vrMainFeatureType(object)]]
409
  }
410
  
411
  return(data)
412
}
413
414
#' updateData
415
#'
416
#' update data matrix
417
#'
418
#' @param object a vrAssay object
419
#' @param value the new column names
420
#'
421
#' @noRd
422
updateData <- function(object, value){
423
  
424
  if(inherits(object, "vrAssay")){
425
    if(ncol(object@rawdata) > 0){
426
      colnames(object@rawdata) <- value
427
      colnames(object@normdata) <- value 
428
    }
429
  } else {
430
    for(nm in vrFeatureTypeNames(object)){
431
      if(ncol(object@data[[nm]] > 0)){
432
        colnames(object@data[[nm]]) <- value
433
        colnames(object@data[[paste0(nm, "_norm")]]) <- value
434
      }
435
    }
436
  }
437
  
438
  return(object)
439
}
440
441
### Feature Methods ####
442
443
vrMainFeatureTypevrAssayV2 <- function(object){
444
  if(inherits(object, "vrAssayV2")){
445
    return(object@main_featureset)
446
  } else {
447
    return(NULL)
448
  }
449
}
450
451
#' @rdname vrMainFeatureType
452
#' @order 3
453
#' @export
454
setMethod("vrMainFeatureType", "vrAssayV2", vrMainFeatureTypevrAssayV2)
455
456
#' @rdname vrMainFeatureType
457
#' @order 3
458
#' @export
459
setMethod("vrMainFeatureType", "vrAssay", vrMainFeatureTypevrAssayV2)
460
461
vrMainFeatureTypeReplacevrAssayV2 <- function(object, ignore = FALSE, value){
462
  if(value %in% names(object@data)){
463
    object@main_featureset <- value
464
  } else {
465
    if(ignore){
466
      warning("The feature type '", value, "' is not found in '", vrAssayNames(object),"'. Main feature type is still set to '", vrMainFeatureType(object), "'")
467
    } else {
468
      stop("The feature type '", value, "' is not found in '", vrAssayNames(object),"'. Use ignore = TRUE for ignoring this message")
469
    }
470
  }
471
  
472
  return(object)
473
}
474
475
#' @param ignore ignore if some assays dont have the feature set name
476
#' 
477
#' @rdname vrMainFeatureType
478
#' @order 5
479
#' @export
480
setMethod("vrMainFeatureType<-", "vrAssayV2", vrMainFeatureTypeReplacevrAssayV2)
481
482
#' @param ignore ignore if some assays dont have the feature set name
483
#' 
484
#' @rdname vrMainFeatureType
485
#' @order 5
486
#' @export
487
setMethod("vrMainFeatureType<-", "vrAssay", function(object, ignore = FALSE, value){
488
  stop("vrAssay V1 objects do not have multiple feature types!")
489
})
490
491
vrFeatureTypeNamesvrAssayV2 <- function(object){
492
  names_data <- names(object@data)
493
  return(names_data[!grepl("_norm$", names_data)])
494
}
495
496
#' @rdname vrFeatureTypeNames
497
#'
498
#' @export
499
setMethod("vrFeatureTypeNames", "vrAssayV2", vrFeatureTypeNamesvrAssayV2)
500
501
#' @rdname vrFeatureTypeNames
502
#'
503
#' @export
504
setMethod("vrFeatureTypeNames", "vrAssay", function(object){
505
  stop("vrAssay V1 objects do not have multiple feature types!")
506
})
507
508
addFeaturevrAssayV2 <- function(object, data, feature_name){
509
  
510
  # get feature name
511
  featuresets <- vrFeatureTypeNames(object)
512
  if(feature_name %in% featuresets){
513
    stop("Feature type '", feature_name, "' already exists in the assay.")
514
  }
515
  
516
  # check spatial point names in the object
517
  colnames_data <- colnames(data)
518
  colnames_data <- stringr::str_remove(colnames_data, pattern = "_Assay[0-9]+$")
519
  colnames(data) <- paste0(colnames_data, "_", vrAssayNames(object))
520
  
521
  # check spatial points
522
  spatialpoints <- vrSpatialPoints(object)
523
  if(length(setdiff(colnames(data), vrSpatialPoints(object))) > 0){
524
    stop("The number of spatial points is not matching with number of points in the input data")
525
  } 
526
527
  # add new features
528
  feature_list_name <- names(object@data)
529
  feature_list_name <- c(feature_list_name, feature_name, paste0(feature_name, "_norm"))
530
  object@data <- c(object@data, list(data,data))
531
  names(object@data) <- feature_list_name
532
  
533
  # return
534
  return(object)
535
}
536
537
#' @rdname addFeature
538
#' @method addFeature vrAssayV2
539
#' 
540
#' @importFrom stringr str_remove
541
#' 
542
#' @export
543
setMethod("addFeature", "vrAssayV2", addFeaturevrAssayV2)
544
545
### Other Methods ####
546
547
#' @rdname vrSpatialPoints
548
#' @order 4
549
#' 
550
#' @export
551
setMethod("vrSpatialPoints", "vrAssay", function(object) {
552
  return(rownames(vrCoordinates(object)))
553
})
554
555
#' @rdname vrSpatialPoints
556
#' @order 4
557
#' 
558
#' @export
559
setMethod("vrSpatialPoints", "vrAssayV2", function(object) {
560
  return(rownames(vrCoordinates(object)))
561
})
562
563
vrSpatialPointsReplacevrAssayV2 <- function(object, value) {
564
  
565
  # spatial points 
566
  spatialpoints <- vrSpatialPoints(object)
567
  
568
  # data
569
  if(length(vrSpatialPoints(object)) != length(value)){
570
    stop("The number of spatial points is not matching with the input")
571
  } else {
572
    if(ncol(getData(object)) > 0){
573
      object <- updateData(object, value)
574
    }
575
  }
576
  
577
  # images
578
  for(img in vrSpatialNames(object)){
579
    vrSpatialPoints(object@image[[img]]) <- value
580
  }
581
  
582
  # embeddings
583
  embeddings <- object@embeddings
584
  embed_names <- names(embeddings)
585
  if(length(embed_names) > 0){
586
    for(type in embed_names){
587
      if(nrow(embeddings[[type]]) > 0){
588
        rownames(embeddings[[type]]) <- value[match(rownames(embeddings[[type]]), spatialpoints)]
589
        object@embeddings[[type]] <- embeddings[[type]]
590
      }
591
    }
592
  }
593
  
594
  # return
595
  return(object)
596
}
597
598
#' @rdname vrSpatialPoints
599
#' @order 8
600
#' @export
601
setMethod("vrSpatialPoints<-", "vrAssay", vrSpatialPointsReplacevrAssayV2)
602
603
#' @rdname vrSpatialPoints
604
#' @order 8
605
#' @export
606
setMethod("vrSpatialPoints<-", "vrAssayV2", vrSpatialPointsReplacevrAssayV2)
607
608
vrFeaturesvrAssay <- function(object) {
609
  return(rownames(getData(object)))
610
}
611
612
#' @rdname vrFeatures
613
#' @order 3
614
#' @export
615
setMethod("vrFeatures", signature = "vrAssay", definition = vrFeaturesvrAssay)
616
 
617
#' @rdname vrFeatures
618
#' @method vrFeatures vrAssayV2
619
#' @order 3
620
#' @export
621
setMethod("vrFeatures", "vrAssayV2", vrFeaturesvrAssay)
622
623
vrFeatureDatavrAssay <- function(object) {
624
  return(object@featuredata)
625
}
626
627
#' @rdname vrFeatureData
628
#' @order 3
629
#' @export
630
setMethod("vrFeatureData", "vrAssay", vrFeatureDatavrAssay)
631
632
vrFeatureDatavrAssayV2 <- function(object, feat_type = NULL){
633
  if(is.null(feat_type))
634
    feat_type <- vrMainFeatureType(object)
635
  return(object@featuredata[[feat_type]])
636
}
637
638
#' @param feat_type the feature set type
639
#'
640
#' @rdname vrFeatureData
641
#' @order 3
642
#' @export
643
setMethod("vrFeatureData", "vrAssayV2", vrFeatureDatavrAssayV2)
644
645
vrFeatureDataRreplacevrAssay <- function(object, value) {
646
  object@featuredata <- value
647
  return(object)
648
}
649
650
#' @rdname vrFeatureData
651
#' @order 5
652
#' @export
653
setMethod("vrFeatureData<-", "vrAssay", vrFeatureDataRreplacevrAssay)
654
655
vrFeatureDataReplacevrAssayV2 <- function(object, feat_type = NULL, value) {
656
  if(is.null(feat_type))
657
    feat_type <- vrMainFeatureType(object)
658
  object@featuredata[[feat_type]] <- value
659
  return(object)
660
}
661
662
#' @rdname vrFeatureData
663
#' @order 5
664
#' @export
665
setMethod("vrFeatureData<-", "vrAssayV2", vrFeatureDataReplacevrAssayV2)
666
667
vrAssayNamesvrAssay <- function(object) {
668
  
669
  if(.hasSlot(object, name = "name")){
670
    if(grep("Assay", object@name)){
671
      return(object@name)
672
    } else {
673
      assay_ids <- stringr::str_extract(vrSpatialPoints(object), "Assay[0-9]+$")
674
      assay_id <- unique(assay_ids)
675
      return(assay_id)
676
    }
677
  } else {
678
    assay_ids <- stringr::str_extract(vrSpatialPoints(object), "Assay[0-9]+$")
679
    assay_id <- unique(assay_ids)
680
    return(assay_id)
681
  }
682
}
683
684
#' @rdname vrAssayNames
685
#' @order 4
686
#' @export
687
setMethod("vrAssayNames", "vrAssay", vrAssayNamesvrAssay)
688
689
#' @rdname vrAssayNames
690
#' @order 4
691
#' @export
692
setMethod("vrAssayNames", "vrAssayV2", vrAssayNamesvrAssay)
693
694
vrAssayNamesReplacevrAssay <- function(object, value){
695
  
696
  # get original assay name
697
  assayname <- vrAssayNames(object)
698
  
699
  # change assay names
700
  spatialpoints <- stringr::str_replace(vrSpatialPoints(object), assayname, value)
701
  
702
  # add assay name if missing
703
  if(vrAssayTypes(object) %in% c("ROI", "cell", "spot")){
704
    ind <- !grepl("Assay[0-9]+$", spatialpoints)
705
    spatialpoints[ind] <- stringr::str_replace(spatialpoints[ind], "$", paste0("_", value))
706
  }
707
  
708
  # replace spatial point names
709
  vrSpatialPoints(object) <- spatialpoints
710
  object@name <- value
711
  
712
  # return
713
  return(object)
714
}
715
716
#' @param value assay name
717
#' 
718
#' @rdname vrAssayNames
719
#' @order 5
720
#' @importFrom stringr str_replace
721
setMethod("vrAssayNames<-", "vrAssay", vrAssayNamesReplacevrAssay)
722
723
vrAssayNamesReplacevrAssayV2 <- function(object, value){
724
  
725
  # get original assay name
726
  assayname <- vrAssayNames(object)
727
  
728
  # change assay names
729
  spatialpoints <- stringr::str_replace(vrSpatialPoints(object), assayname, value)
730
  
731
  # add assay name if missing
732
  if(vrAssayTypes(object) %in% c("ROI", "cell", "spot")){
733
    ind <- !grepl("Assay[0-9]+$", spatialpoints)
734
    spatialpoints[ind] <- stringr::str_replace(spatialpoints[ind], "$", paste0("_", value))
735
  }
736
  
737
  # replace spatial point names
738
  vrSpatialPoints(object) <- spatialpoints
739
  object@name <- value
740
  
741
  # return
742
  return(object)
743
}
744
745
#' @param value assay name
746
#' 
747
#' @rdname vrAssayNames
748
#' @order 5
749
#' @importFrom stringr str_replace
750
setMethod("vrAssayNames<-", "vrAssayV2", vrAssayNamesReplacevrAssayV2)
751
752
vrAssayTypesvrAssay <- function(object) {
753
  return(object@type)
754
}
755
756
#' @rdname vrAssayTypes
757
#' @order 3
758
#' @export
759
setMethod("vrAssayTypes", "vrAssay", vrAssayTypesvrAssay)
760
761
#' @rdname vrAssayTypes
762
#' @order 3
763
#' @export
764
setMethod("vrAssayTypes", "vrAssayV2", vrAssayTypesvrAssay)
765
766
#' Get assay parameters
767
#'
768
#' Given a vrAssay object, if there are any, get a list of parameters of the assay(s)
769
#'
770
#' @param object a vrAssay object
771
#' @param param the parameter value to return
772
#'
773
#' @rdname vrAssayParams
774
#'
775
#' @export
776
vrAssayParams <- function(object, param = NULL) {
777
  if(!is.null(param)){
778
    if(param %in% names(object@params)){
779
      return(object@params[[param]])
780
    } else {
781
      message(param, " not found in the param list")
782
      return(NULL)
783
    }
784
  } else {
785
    return(object@params)
786
  }
787
}
788
789
vrDatavrAssay <- function(object, features = NULL, feat_type = NULL, norm = FALSE, ...) {
790
  
791
  # get assay types
792
  assay.type <- vrAssayTypes(object)
793
  
794
  # for ROIs, cells and spots
795
  if(assay.type %in% c("ROI", "cell", "spot")){
796
    
797
    # check if there are features
798
    if(!is.null(features)){
799
      if(!all(features %in% vrFeatures(object))){
800
        stop("Some features are not available in the assay!")
801
      }
802
      
803
      if(inherits(object, "vrAssay")){
804
        if(norm){
805
          return(object@normdata[features,,drop = FALSE])
806
        } else {
807
          return(object@rawdata[features,,drop = FALSE])
808
        }
809
      } else {
810
        if(is.null(feat_type))
811
          feat_type <- vrMainFeatureType(object)
812
        if(norm){
813
          return(object@data[[paste0(feat_type, "_norm")]][features,,drop = FALSE])
814
        } else {
815
          return(object@data[[feat_type]][features,,drop = FALSE])
816
        }
817
      }
818
      
819
      # if there are no features requested, return the data
820
    } else {
821
      
822
      if(inherits(object, "vrAssay")){
823
        if(norm){
824
          return(object@normdata)
825
        } else {
826
          return(object@rawdata)
827
        }
828
      } else {
829
        if(is.null(feat_type))
830
          feat_type <- vrMainFeatureType(object)
831
        if(norm){
832
          return(object@data[[paste0(feat_type, "_norm")]])
833
        } else {
834
          return(object@data[[feat_type]])
835
        }
836
      }
837
    }
838
    
839
    # for tiles and molecules
840
  } else {
841
    
842
    # check if features are requested
843
    if(!is.null(features)){
844
      stop("No features are available for tile and molecule assays!")
845
    } else{
846
      
847
      if(inherits(object, "vrAssay")){
848
        if(norm){
849
          return(object@normdata)
850
        } else {
851
          return(object@rawdata)
852
        }
853
      } else {
854
        if(is.null(feat_type))
855
          feat_type <- vrMainFeatureType(object)
856
        if(norm){
857
          return(object@data[[paste0(feat_type, "_norm")]])
858
        } else {
859
          return(object@data[[feat_type]])
860
        }
861
      }
862
    }
863
  }
864
}
865
866
#' @rdname vrData
867
#' @order 3
868
#'
869
#' @importFrom magick image_raster
870
#'
871
#' @export
872
setMethod("vrData", "vrAssay", vrDatavrAssay)
873
874
#' @rdname vrData
875
#' @order 3
876
#'
877
#' @export
878
setMethod("vrData", "vrAssayV2", vrDatavrAssay)
879
880
generateTileDatavrAssay <- function(object, name = NULL, reg = FALSE, channel = NULL) {
881
  
882
  if(vrAssayTypes(object) != "tile"){
883
    stop("generateTileData can only be used for tile-based assays")
884
  } else {
885
    image_data <- as.numeric(vrImages(object, name = name, reg = reg, channel = channel, as.raster = TRUE))
886
    image_data <- (0.299 * image_data[,,1] + 0.587 * image_data[,,2] + 0.114 * image_data[,,3])
887
    image_data <- split_into_tiles(image_data, tile_size = vrAssayParams(object, param = "tile.size"))
888
    image_data <- sapply(image_data, function(x) return(as.vector(x)))
889
    image_data <- image_data*255
890
    rownames(image_data) <- paste0("pixel", seq_len(nrow(image_data)))
891
    colnames(image_data) <- vrSpatialPoints(object)
892
    feat_type <- vrMainFeatureType(object)
893
    
894
    if(inherits(object, "vrAssay")){
895
      object@rawdata <- object@normdata <- image_data
896
    } else{
897
      object@data[[feat_type]] <- image_data
898
      object@data[[paste0(feat_type, "_norm")]] <- image_data
899
    }
900
  }
901
  return(object)
902
}
903
904
#' @param name the name of the main spatial system
905
#' @param reg TRUE if registered coordinates of the main image (\link{vrMainSpatial}) is requested
906
#' @param channel the name of the channel associated with the image
907
#' 
908
#' @rdname generateTileData
909
#' @order 3
910
#'
911
#' @export
912
setMethod("generateTileData", "vrAssay", generateTileDatavrAssay)
913
914
#' @rdname generateTileData
915
#' @order 3
916
#'
917
#' @export
918
setMethod("generateTileData", "vrAssayV2", generateTileDatavrAssay)
919
920
vrCoordinatesvrAssay <- function(object, image_name = NULL, spatial_name = NULL, reg = FALSE) {
921
  
922
  # get spatial name
923
  if(!is.null(spatial_name)) 
924
    image_name <- spatial_name
925
  
926
  # check main image
927
  if(is.null(image_name)){
928
    image_name <- vrMainSpatial(object)
929
  }
930
  
931
  # check registered coordinates
932
  if(reg){
933
    if(!paste0(image_name, "_reg") %in% vrSpatialNames(object)){
934
      warning("There are no registered spatial systems with name ", image_name, "!")
935
    } else {
936
      image_name <- paste0(image_name, "_reg")
937
    }
938
  }
939
  
940
  # check coordinates
941
  if(!image_name %in% vrSpatialNames(object)){
942
    stop(image_name, " is not among any spatial system in this vrAssay object")
943
  }
944
  
945
  # return coordinates
946
  return(vrCoordinates(object@image[[image_name]]))
947
}
948
949
#' @rdname vrCoordinates
950
#' @order 3
951
#' @export
952
#'
953
setMethod("vrCoordinates", "vrAssay", vrCoordinatesvrAssay)
954
955
#' @rdname vrCoordinates
956
#' @order 3
957
#' @export
958
#'
959
setMethod("vrCoordinates", "vrAssayV2", vrCoordinatesvrAssay)
960
961
vrCoordinatesReplacevrAssay <- function(object, image_name = NULL, spatial_name = NULL, reg = FALSE, value) {
962
  
963
  # get spatial name
964
  if(!is.null(spatial_name)) 
965
    image_name <- spatial_name
966
  
967
  # check main image
968
  if(is.null(image_name)){
969
    image_name <- vrMainSpatial(object)
970
  }
971
  
972
  # check registered coordinates
973
  if(reg){
974
    image_name <- paste0(image_name, "_reg")
975
  }
976
  
977
  # check coordinates
978
  if(!image_name %in% vrSpatialNames(object)){
979
    stop(image_name, " is not among any spatial system in this vrAssay object")
980
  }
981
  
982
  vrCoordinates(object@image[[image_name]]) <- value
983
  return(object)
984
}
985
986
#' @rdname vrCoordinates
987
#' @order 5
988
#' @importFrom methods slot
989
#'
990
#' @export
991
setMethod("vrCoordinates<-", "vrAssay", vrCoordinatesReplacevrAssay)
992
993
#' @rdname vrCoordinates
994
#' @order 5
995
#' @importFrom methods slot
996
#'
997
#' @export
998
setMethod("vrCoordinates<-", "vrAssayV2", vrCoordinatesReplacevrAssay)
999
1000
flipCoordinatesvrAssay <- function(object, image_name = NULL, spatial_name = NULL, ...) {
1001
  
1002
  # get spatial name
1003
  if(!is.null(spatial_name)) 
1004
    image_name <- spatial_name
1005
  
1006
  # get coordinates
1007
  coords <- vrCoordinates(object, image_name = image_name, ...)
1008
  
1009
  # get image info
1010
  image <- vrImages(object, name = image_name)
1011
  if(!is.null(image)){
1012
    imageinfo <- magick::image_info(vrImages(object, name = image_name))
1013
    height <- imageinfo$height
1014
  } else{
1015
    height <- max(coords[,"y"])
1016
  }
1017
  
1018
  # flip coordinates
1019
  coords[,"y"] <- height - coords[,"y"]
1020
  vrCoordinates(object, image_name = image_name, ...) <- coords
1021
  
1022
  # flip segments
1023
  segments <- vrSegments(object, image_name = image_name, ...)
1024
  if(length(segments) > 0){
1025
    name_segments <- names(segments)
1026
    segments <- do.call("rbind", segments)
1027
    segments[,"y"] <- height - segments[,"y"]
1028
    segments <- split(segments, segments[,1])
1029
    names(segments) <- name_segments
1030
    vrSegments(object, image_name = image_name, ...) <- segments
1031
  }
1032
  
1033
  # return
1034
  return(object)
1035
}
1036
1037
#' @rdname flipCoordinates
1038
#' @order 3
1039
#'
1040
#' @importFrom magick image_info
1041
#'
1042
#' @export
1043
setMethod("flipCoordinates", "vrAssay", flipCoordinatesvrAssay)
1044
1045
#' @rdname flipCoordinates
1046
#' @order 3
1047
#'
1048
#' @export
1049
setMethod("flipCoordinates", "vrAssayV2", flipCoordinatesvrAssay)
1050
1051
vrSegmentsvrAssay <- function(object, image_name = NULL, spatial_name = NULL, reg = FALSE) {
1052
  
1053
  # get spatial name
1054
  if(!is.null(spatial_name)) 
1055
    image_name <- spatial_name
1056
  
1057
  # check main image
1058
  if(is.null(image_name)){
1059
    image_name <- vrMainSpatial(object)
1060
  }
1061
  
1062
  # check registered segments
1063
  if(reg){
1064
    if(!paste0(image_name, "_reg") %in% vrSpatialNames(object)){
1065
      warning("There are no registered spatial systems with name ", image_name, "!")
1066
    } else {
1067
      image_name <- paste0(image_name, "_reg")
1068
    }
1069
  }
1070
  
1071
  # check coordinates
1072
  if(!image_name %in% vrSpatialNames(object)){
1073
    stop(image_name, " is not among any spatial system in this vrAssay object")
1074
  }
1075
  
1076
  # return coordinates
1077
  return(vrSegments(object@image[[image_name]]))
1078
}
1079
1080
#' @rdname vrSegments
1081
#' @order 3
1082
#' @export
1083
setMethod("vrSegments", "vrAssay", vrSegmentsvrAssay)
1084
1085
#' @rdname vrSegments
1086
#' @order 3
1087
#' @export
1088
setMethod("vrSegments", "vrAssayV2", vrSegmentsvrAssay)
1089
1090
vrSegmentsReplacevrAssay <- function(object, image_name = NULL, spatial_name = NULL, reg = FALSE, value) {
1091
  
1092
  # get spatial name
1093
  if(!is.null(spatial_name)) 
1094
    image_name <- spatial_name
1095
  
1096
  # check main image
1097
  if(is.null(image_name)){
1098
    image_name <- vrMainSpatial(object)
1099
  }
1100
  
1101
  # check registered segments
1102
  if(reg){
1103
    image_name <- paste0(image_name, "_reg")
1104
  }
1105
  
1106
  # check coordinates
1107
  if(!image_name %in% vrSpatialNames(object)){
1108
    stop(image_name, " is not among any spatial system in this vrAssay object")
1109
  }
1110
  
1111
  vrSegments(object@image[[image_name]]) <- value
1112
  return(object)
1113
}
1114
1115
#' @rdname vrSegments
1116
#' @order 6
1117
#' @importFrom methods slot
1118
#' @export
1119
setMethod("vrSegments<-", "vrAssay", vrSegmentsReplacevrAssay)
1120
1121
#' @rdname vrSegments
1122
#' @order 6
1123
#' @importFrom methods slot
1124
#' @export
1125
setMethod("vrSegments<-", "vrAssayV2", vrSegmentsReplacevrAssay)
1126
1127
vrEmbeddingsvrAssay <- function(object, type = "pca", dims = seq_len(30)) {
1128
  
1129
  # embeddings
1130
  embeddings <- object@embeddings
1131
  embedding_names <- names(embeddings)
1132
  
1133
  # check embeddings and return
1134
  if(!type %in% embedding_names){
1135
    stop("Embedding type ", type, " is not found!")
1136
  } else{
1137
    embedding <- object@embeddings[[type]]
1138
    if(max(dims) > ncol(embedding)){
1139
      dims <- seq_len(ncol(embedding))
1140
    }
1141
    return(embedding[,dims, drop = FALSE])
1142
  }
1143
}
1144
1145
#' @rdname vrEmbeddings
1146
#' @order 3
1147
#' @export
1148
setMethod("vrEmbeddings", "vrAssay", vrEmbeddingsvrAssay)
1149
1150
#' @rdname vrEmbeddings
1151
#' @order 3
1152
#' @export
1153
#'
1154
setMethod("vrEmbeddings", "vrAssayV2", vrEmbeddingsvrAssay)
1155
1156
vrEmbeddingsReplacevrAssay <- function(object, type = "pca", value) {
1157
  object@embeddings[[type]] <- value
1158
  return(object)
1159
}
1160
1161
#' @rdname vrEmbeddings
1162
#' @order 4
1163
#' @export
1164
setMethod("vrEmbeddings<-", "vrAssay", vrEmbeddingsReplacevrAssay)
1165
1166
vrEmbeddingsReplacevrAssayV2 <- function(object, type = "pca", value) {
1167
  object@embeddings[[type]] <- value
1168
  return(object)
1169
}
1170
1171
#' @rdname vrEmbeddings
1172
#' @order 4
1173
#' @export
1174
setMethod("vrEmbeddings<-", "vrAssayV2", vrEmbeddingsReplacevrAssayV2)
1175
1176
vrEmbeddingNamesvrAssay <- function(object){
1177
  return(names(object@embeddings))
1178
}
1179
1180
#' @rdname vrEmbeddingNames
1181
#' @order 3
1182
#'
1183
#' @export
1184
setMethod("vrEmbeddingNames", "vrAssay", vrEmbeddingNamesvrAssay)
1185
1186
#' @rdname vrEmbeddingNames
1187
#' @order 3
1188
#'
1189
#' @export
1190
setMethod("vrEmbeddingNames", "vrAssayV2", vrEmbeddingNamesvrAssay)