Nothing
################
## New S4 class to represent 5C or HiC data
## This class is mainly based on the GRanges class
## The interaction matrix is added to the object
################
## class definition
setClass("HTCexp",
representation = representation(
"intdata"="Matrix",
"xgi"="GRanges",
"ygi"="GRanges")
)
setValidity("HTCexp",
function(object){
fails <- character(0L)
## Format
if(!inherits(object@intdata,"Matrix")) {
fails <- c(fails, "Expected Matrix for the data slot!\n")
}
if(!inherits(object@ygi,"GRanges") || !inherits(object@xgi,"GRanges")) {
fails <- c(fails, "Intervals 'xgi' and 'ygi' objects must be two GRanges objects!\n")
}
if (dim(object@intdata)[1] != length(object@ygi)){
fails <- c(fails, "The 'ygi' GRanges object must have exactly the same length as the number of rows of the data matrix")
}
if (dim(object@intdata)[2] != length(object@xgi)){
fails <- c(fails, "The 'xgi' GRanges object must have exactly the same length as the number of column of the data matrix")
}
if (is.null(colnames(object@intdata)) || is.null(id(object@xgi))){
fails <- c(fails,"No ids for 'xgi' intervals")
}
if (is.null(rownames(object@intdata)) || is.null(id(object@ygi))){
fails <- c(fails,"No ids for 'ygi' intervals")
}
## Content
if (length(object@xgi) == 0L || length(object@ygi) == 0L){
fails <- c(fails, "Inervals xgi or ygi are of size 0")
}
if (length(seqlevels(object@xgi)) > 1L || length(seqlevels(object@ygi)) > 1L){
fails <- c(fails, "Multiple chromosome found in xgi or ygi object")
}
if (length(setdiff(rownames(object@intdata), id(object@ygi)))>0L){
fails <- c(fails, "The 'ygi' intervals from the interaction matrix are different from those defined in the GRanges object")
}
if (length(setdiff(colnames(object@intdata), id(object@xgi)))>0L){
fails <- c(fails, "The 'xgi' intervals from the interaction matrix are different from those defined in the GRanges object")
}
if (length(fails) > 0L) return(fails)
return(TRUE)
}
)
## constructor
HTCexp <- function(intdata, xgi, ygi, lazyload=FALSE)
{
## check xgi/ygi length
stopifnot(inherits(ygi,"GRanges"))
stopifnot(inherits(xgi,"GRanges"))
if (length(xgi)==0L || length(ygi)==0L)
stop("Cannot create HTCexp object of size 0")
if(length(ygi) != nrow(intdata))
stop("Length 'ygi' is not equal to number of rows in 'intdata'")
if(length(xgi) != ncol(intdata))
stop("Length 'xgi' is not equal to number of columns in 'intdata'")
## sort xgi and ygi data
xgi <- sort(xgi)
ygi <- sort(ygi)
## Check matrix format
if (!inherits(intdata, "Matrix")){
intdata <- as(as.matrix(intdata), "Matrix")
}
## Check matrix names
colnames(intdata) <- id(xgi)
rownames(intdata) <- id(ygi)
## Create HTCexp
obj <- new("HTCexp", intdata, xgi, ygi)
if (lazyload & seqlevels(xgi)==seqlevels(ygi)){
obj <- forceSymmetric(obj)
obj <- forceTriangular(obj)
}
obj
}
################
##
## Functions
##
################
removeIntervals <- function(x, ids)
{
stopifnot(inherits(x, "HTCexp"))
xgi <- x_intervals(x)
ygi <- y_intervals(x)
xgi.id <- id(xgi)
ygi.id <- id(ygi)
stopifnot(!is.null(xgi.id) | !is.null(ygi.id))
xgi.id.n <- setdiff(xgi.id, ids)
if (length(xgi.id.n) != length(xgi.id)){
message("Discard ",(length(xgi.id)-length(xgi.id.n)), " 'x' intervals")
x_intervals(x) <- xgi[which(id(xgi)%in%xgi.id.n),]
}
ygi.id.n <- setdiff(ygi.id, ids)
if (length(ygi.id.n) != length(ygi.id)){
message("Discard ",(length(ygi.id)-length(ygi.id.n)), " 'y' intervals")
y_intervals(x) <- ygi[which(id(ygi)%in%ygi.id.n),]
}
x
}
extractRegion <- function(x, MARGIN=c(1,2), chr, from, to, exact=FALSE)
{
stopifnot(inherits(x, "HTCexp"))
stopifnot(is.element(MARGIN, c(1,2)))
fromto <- GRanges(seqnames = chr, ranges = IRanges(start=from, end=to))
xgi <- x_intervals(x)
ygi <- y_intervals(x)
data <- x@intdata
## Force exact overlap by adding flanking regions
if (exact){
## if no interval with from, add NA values
## else force overlapping coordinates
## x_intervals
if (is.element(c(1), MARGIN)){
xgi <- subsetByOverlaps(xgi, fromto, ignore.strand=TRUE)
if (min(start(xgi))>from){
##flank(xgi[which.min(start(xgi))], width=min(start(xgi))-from, start=TRUE, ignore.strand=TRUE)
ir <- IRanges(start=from, end=min(start(xgi))-1)
edata <- elementMetadata(xgi)[1,]
if (is.element("score",colnames(edata)))
edata$score <- 0L
if (is.element("name",colnames(edata)))
edata$name <- paste(chr,":",from,"-",min(start(xgi))-1, sep="")
if (is.element("thick",colnames(edata)))
edata$thick <- ir
ngr <- GRanges(seqnames = chr, ranges = ir, strand = "*", edata)
xgi <- c(ngr,xgi)
data <- cbind(rep(NA, nrow(data)), data)
}else if (min(start(xgi))<=from){
maxind <- max(which(start(xgi)<=from & end(xgi)>=from))
start(xgi[maxind,]) <- from
data <- data[,maxind:length(xgi)]
xgi <- xgi[maxind:length(xgi),]
}
if (max(end(xgi))<to){
ir <- IRanges(start=max(end(xgi))+1, end=to)
edata <- elementMetadata(xgi)[length(xgi),]
if (is.element("score",colnames(edata)))
edata$score <- 0L
if (is.element("name",colnames(edata)))
edata$name <- paste(chr,":",max(end(xgi))+1,"-",to, sep="")
if (is.element("thick",colnames(edata)))
edata$thick <- ir
ngr <- GRanges(seqnames = chr, ranges = ir, strand = "*", edata)
xgi <- c(xgi, ngr)
data <- cbind(data, rep(NA, nrow(data)))
}else if (max(end(xgi))>=to){
maxind <- min(which(start(xgi)<=to & end(xgi)>=to))
end(xgi[maxind,]) <- to
data <- data[,1:maxind]
xgi <- xgi[1:maxind,]
}
}
## y_intervals
if (is.element(c(2), MARGIN)){
ygi <- subsetByOverlaps(ygi, fromto, ignore.strand=TRUE)
if (min(start(ygi))>from){
ir <- IRanges(start=from, end=min(start(ygi))-1)
edata <- elementMetadata(ygi)[1,]
if (is.element("score",colnames(edata)))
edata$score <- 0L
if (is.element("name",colnames(edata)))
edata$name <- paste(chr,":",from,"-",min(start(ygi))-1, sep="")
if (is.element("thick",colnames(edata)))
edata$thick <- ir
ngr <- GRanges(seqnames = chr, ranges = ir, strand = "*", edata)
ygi <- c(ngr,ygi)
data <- rbind(rep(NA, ncol(data)), data)
}else if (min(start(ygi))<=from){
maxind <- max(which(start(ygi)<=from & end(ygi)>=from))
start(ygi[maxind,]) <- from
data <- data[maxind:length(ygi),]
ygi <- ygi[maxind:length(ygi),]
}
if (max(end(ygi))<to){
ir <- IRanges(start=max(end(ygi))+1, end=to)
edata <- elementMetadata(ygi)[length(ygi),]
if (is.element("score",colnames(edata)))
edata$score <- 0L
if (is.element("name",colnames(edata)))
edata$name <- paste(chr,":",max(end(ygi))+1,"-",to, sep="")
if (is.element("thick",colnames(edata)))
edata$thick <- ir
ngr <- GRanges(seqnames = chr, ranges = ir, strand = "*", edata)
ygi <- c(ygi, ngr)
data <- rbind(data, rep(NA, ncol(data)))
}else if (max(end(ygi))>=to){
maxind <- min(which(start(ygi)<=to & end(ygi)>=to))
end(ygi[maxind,]) <- to
data <- data[1:maxind,]
ygi <- ygi[1:maxind,]
}
}
data <- x@intdata[id(ygi), id(xgi)]
colnames(data) <- id(xgi)
rownames(data) <- id(ygi)
HTCexp(data, xgi, ygi)
}else{
## Full overlap
if (is.element(c(1), MARGIN))
xgi <- subsetByOverlaps(xgi, fromto, type="within", ignore.strand=TRUE)
if (is.element(c(2), MARGIN))
ygi <- subsetByOverlaps(ygi, fromto, type="within", ignore.strand=TRUE)
data <- x@intdata[id(ygi), id(xgi)]
HTCexp(data, xgi, ygi)
}
}##extractRegion
################
##
## Methods
##
################
setMethod("c", "HTCexp", function(x, ...){
if (missing(x))
args <- unname(list(...))
else
args <- unname(list(x, ...))
HTClist(args)
})
setMethod("detail",signature(x="HTCexp"),
function(x){
stopifnot(validObject(x))
cat("HTC object\n")
r <- range(x)
if (length(r)==1){
cat("Focus on genomic region [", seqlevels(r), ":",
start(r),"-",end(r),"]\n", sep="")
}else{
cat("Focus on genomic regions [",
seqlevels(r)[1], ":", start(r)[1], "-", end(r)[1],"] vs [",
seqlevels(r)[2], ":", start(r)[2], "-", end(r)[2],"]\n", sep="")
}
if(isIntraChrom(x)){
cat("CIS Interaction Map\n")
}else{
cat("TRANS Interaction Map\n")
}
cat("Matrix of Interaction data: [", dim(x@intdata)[1],"-",dim(x@intdata)[2], "]\n", sep="")
if (isBinned(x)){
cat("Binned data - window size =", width(x_intervals(x))[1],"\n")
cat(length(x_intervals(x)),"genome intervals\n")
}
else{
cat(length(x_intervals(x))," genomic ranges from 'xgi' object\n")
cat(length(y_intervals(x))," genomic ranges from 'ygi' object\n")
}
xdata <- x@intdata
cat("Total Reads = ",sum(xdata, na.rm=TRUE),"\n")
cat("Number of Interactions = ",nnzero(xdata),"\n")
cat("Median Frequency = ",median(xdata@x[xdata@x>0L]),"\n")
#cat("Sparsity = ",round((length(xdata)-nnzero(xdata))/length(xdata),3),"\n")
cat("Sparsity = ",round(length(xdata@x)/length(xdata),3),"\n")
invisible(NULL)
}
)
## Divide method
setMethod("divide", signature=c("HTCexp","HTCexp"),
function(x,y){
xgi.ov <- findOverlaps(x@xgi, y@xgi, type="equal")
ygi.ov <- findOverlaps(x@ygi, y@ygi, type="equal")
##xgi <- subsetByOverlaps(x@xgi, y@xgi, type="equal")
##ygi <- subsetByOverlaps(x@ygi, y@ygi, type="equal")
if (length(queryHits(xgi.ov)) == 0L || length(queryHits(ygi.ov)) == 0L){
stop("No equal intervals found in x and y objects")
}
x.xgi <- x@xgi[queryHits(xgi.ov)]
x.ygi <- x@ygi[queryHits(ygi.ov)]
y.xgi <- y@xgi[subjectHits(xgi.ov)]
y.ygi <- y@ygi[subjectHits(ygi.ov)]
a <- x@intdata[id(x.ygi), id(x.xgi)]
b <- y@intdata[id(y.ygi), id(y.xgi)]
##a <- x@intdata[id(ygi), id(xgi)]
##b <- y@intdata[id(ygi), id(xgi)]
a[Matrix::which(a==0L | b==0L)]<-NA
b[Matrix::which(a==0L | b==0L)]<-NA
## Use x as reference for intervals description
colnames(b) <- colnames(a)
rownames(b) <- rownames(a)
data <- a/b
HTCexp(data, x.xgi , x.ygi)
}
)
## forceSymmetric
setMethod(f="forceSymmetric", signature(x="HTCexp", uplo="missing"),
function(x, uplo){forceSymmetric(x, uplo="U")})
setMethod(f="forceSymmetric", signature(x="HTCexp", uplo="character"),
function(x, uplo){
stopifnot(uplo=="U" || uplo=="L")# || uplo=="S")
idata <- x@intdata
#if (uplo == "U" || uplo == "L"){
# idata <- forceSymmetric(idata, uplo)
#}else if (uplo== "S"){
# idata <- idata + t(idata)
# diag(idata) <- diag(idata)/2
# idata <- as(idata, "symmetricMatrix")
#}
#intdata(x) <- idata
intdata(x) <- forceSymmetric(idata, uplo)
x
}
)
setMethod(f="forceTriangular", signature(x="HTCexp"),
function(x){
stopifnot(isSymmetric(x))
idata <- intdata(x)
idata[lower.tri(idata)] <- 0
intdata(x)<-as(idata, "sparseMatrix")
x
})
#setMethod(f="forcePairwise", signature(x="HTCexp"),
# function(x){
# idata <- intdata(x)
# idata <- idata + t(idata)
# diag(idata) <- diag(idata)/2
# idata <- as(idata, "sparseMatrix")
# intdata(x) <- idata
# x
# })
## Interaction Data
setMethod(f="intdata", signature(x="HTCexp"),
function(x){
#if (isTriangular(x) && isIntraChrom(x)){
# x <- forceSymmetric(x)
#}
x@intdata
}
)
setReplaceMethod(f="intdata", signature(x="HTCexp",value="Matrix"),
function(x, value){
x@intdata <- value
stopifnot(validObject(x))
return(x)
}
)
## Symetric interaction maps
setMethod("isSymmetric", signature(object="HTCexp"),
function(object){
ret <- FALSE
idata <- object@intdata
if (Matrix::isSymmetric(idata))
ret <- TRUE
else if (isTriangular(idata))
ret <- TRUE
else if (seqlevels(object@xgi)==seqlevels(object@ygi)){
if (ncol(idata)==nrow(idata))
ret <- suppressWarnings(all(idata-t(idata)==0, na.rm=TRUE))
}
ret
}
)
## is Triangular Matrix
setMethod("isTriangular", signature(object="HTCexp"),
function(object){
object@intdata[which(is.na(object@intdata))] <- 0
Matrix::isTriangular(object@intdata)
}
)
## Initialize method
setMethod("initialize",signature=c("HTCexp"),
function(.Object, interaction.data, xgi, ygi){
if (!missing(interaction.data) && !missing(ygi) && !missing(xgi)){
.Object@intdata<-interaction.data
.Object@ygi <-ygi
.Object@xgi <-xgi
}
return(.Object)
}
)
## Binned data
setMethod("isBinned", signature(x="HTCexp"),
function(x){
stopifnot(validObject(x))
ret <- TRUE
## Same bins for intra chromosomal
##if(isIntraChrom(x) && !all.equal(x@xgi, x@ygi)){
if (isIntraChrom(x) && sum(countMatches(x@xgi, x@ygi)) != length(x@xgi)){
ret <- FALSE
}
## Same width (exept for last bins - checked in 95% of bins)
x.excl <- round(length(x@xgi)*.95)
y.excl <- round(length(x@ygi)*.95)
if (length(duplicated(width(x@xgi)))< x.excl || length(duplicated(width(x@ygi)))< y.excl)
ret <- FALSE
## no gaps
##if (isDisjoint(x@xgi) || isDisjoint(x@ygi))
if (length(reduce(x@xgi)) != 1 || length(reduce(x@ygi)) != 1)
ret <- FALSE
ret
}
)
## Inter/Intra chromosomal interaction
setMethod("isIntraChrom", signature(x="HTCexp"),
function(x){
stopifnot(validObject(x))
ret <- FALSE
if (seqlevels(x@xgi) == seqlevels(x@ygi))
ret <- TRUE
ret
}
)
## Intervals names
setMethod(f="id", signature(x="GRanges"),
function(x){
ret <- NULL
if (!is.null(names(x)))
ret <- names(x)
else if (!is.null(elementMetadata(x)$name))
ret <- elementMetadata(x)$name
as.character(ret)
}
)
## Range
setMethod(f="range", signature(x="HTCexp"),
function(x){
suppressWarnings(range(c(x@ygi, x@xgi), ignore.strand=TRUE))
}
)
## Seqlevels
setMethod(f="seqlevels", signature(x="HTCexp"),
function(x){
unique(c(seqlevels(x@ygi), seqlevels(x@xgi)))
}
)
## Show method
setMethod("show",signature="HTCexp",
function(object){
stopifnot(validObject(object))
cat("HTCexp object\n")
r <- range(object)
if (length(r)==1){
cat("Focus on genomic region [", seqlevels(r), ":",
start(r),"-",end(r),"]\n", sep="")
}else{
cat("Focus on genomic regions [",
seqlevels(r)[1], ":", start(r)[1], "-", end(r)[1],"] vs [",
seqlevels(r)[2], ":", start(r)[2], "-", end(r)[2],"]\n", sep="")
}
cat("Matrix of Interaction data: [", dim(object@intdata)[1],"-",dim(object@intdata)[2], "]\n", sep="")
gf <- union(names(elementMetadata(object@xgi)), names(elementMetadata(object@ygi)))
if (length(gf)>0)
cat("Genomic Features : ", paste(gf, collapse="-"),"\n")
invisible(NULL)
}
)
## Substraction
setMethod("substract", signature(x="HTCexp",y="HTCexp"),
function(x,y){
xov <- findOverlaps(x@xgi, y@xgi, type="equal")
yov <- findOverlaps(x@ygi, y@ygi, type="equal")
a <- x@intdata[id(x@ygi)[queryHits(yov)],
id(x@xgi)[queryHits(xov)]]
b <- y@intdata[id(y@ygi)[subjectHits(yov)],
id(y@xgi)[subjectHits(xov)]]
#a <- x@intdata[id(x@ygi),id(x@xgi)]
#b <- y@intdata[id(y@ygi),id(y@xgi)]
#a[which(a==0L | b==0L)]<-NA
#b[which(a==0L | b==0L)]<-NA
data <- a-b
xgi <- x@xgi[queryHits(xov)]
ygi <- x@ygi[queryHits(yov)]
HTCexp(data, xgi , ygi)
}
)
## Summary
setMethod("summary", signature=c(object="HTCexp"),
function(object){
interactors <- seqlevels(object)
if (isIntraChrom(object))
interactors <- rep(seqlevels(object),2)
else
interactors <- seqlevels(object)
if(max(object@intdata, na.rm=TRUE)==0){
dstat <- c(interactors, 0, 0, 0, 0, 1)
}else{
## Force cohersion to dgTMatrix to have @x equal of non zero values
xdata <- as(as(object@intdata, "sparseMatrix"),"dgTMatrix")
mx <- round(mean(xdata@x, na.rm=TRUE),4)
mdx <- round(median(xdata@x, na.rm=TRUE),4)
dstat <- c(interactors, sum(xdata@x, na.rm=TRUE), nnzero(xdata, na.counted=TRUE), mx, mdx, round((length(xdata)-length(xdata@x))/length(xdata),4))
}
names(dstat) <- c("seq1", "seq2", "nbreads","nbinteraction","averagefreq","medfreq","sparsity")
data.frame(summary=dstat, stringsAsFactors=FALSE)
})
## X Intervals
setMethod(f="x_intervals", signature(x="HTCexp"),
function(x){x@xgi})
setReplaceMethod(f="x_intervals", signature(x="HTCexp",value="GRanges"),
function(x, value){
x@xgi <- value
intdata <- as(as.matrix(x@intdata[,as.vector(id(x@xgi))]), "Matrix")
colnames(intdata) <-as.vector(id(x@xgi))
rownames(intdata) <- rownames(x@intdata)
x@intdata <- intdata
x
}
)
## Y Intervals
setMethod(f="y_intervals", signature(x="HTCexp"),
function(x){x@ygi})
setReplaceMethod(f="y_intervals", signature(x="HTCexp",value="GRanges"),
function(x, value){
x@ygi <- value
intdata <- as(as.matrix(x@intdata[as.vector(id(x@ygi)),]), "Matrix")
rownames(intdata) <-as.vector(id(x@ygi))
colnames(intdata) <- colnames(x@intdata)
x@intdata <- intdata
x
}
)
## X and Y Intervals
setMethod(f="xy_intervals", signature(x="HTCexp"),
function(x){
GRangesList(xgi=x@xgi, ygi=x@ygi)
}
)
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.