# #' @title an empty file to import necessary libraries
# #' @import limma MASS
# #' @name _empty
# NULL
# <======the above section is for importing libraries. change it whenever necessary by uncommenting
#roxygen2 comments below
#' @title S4 class definition of SensorgramData
#'
#' @description \code{SensorgramData} define the S4 class of SensorgramData
#'
#' @details defining the S4 class of the SensorgrameData.
#' This is the data structure to hold the sensor grame Data.
#' It contains different slots for holding both association and
#' dissociation phase data.It also defines
#' the steady state window if there is one. Analyte concentrations
#' also included. Sometimes the data could
#' only have either association or dissociation phase alone.
#'
#' @concept SPR
#'
#' @param associationData Dataframe holding the association phase data.
#' It has a fixed format/template.
#' See \code{\link{ReadSensorgramData}} for details.
#' @param dissociationData Dataframe holding the dissociation phase data.
#' It has a fixed format/template.
#' See \code{\link{ReadSensorgramData}} for details.
#' @param analyteConcentrations, numeric vector for analyteConcentrations
#' of unit molar concentration (M/L)
#' @param steadyStateStart numeric indicating the starting time of
#' steady state (optional).
#' @param steadyStateEnd numeric indicating the ending time of
#' steady state (optional).
#' @param offset numeric indicating the RU levels shift at the
#' begining of dissociation phase. Not used for now.
#' will implement in the future release. (optional)
#' @slot associationData data.frame
#' @slot dissociationData data.frame
#' @slot analyteConcentrations numeric vector
#' @slot steadyStateStart numeric
#' @slot steadyStateEnd numeric
#' @slot offset numeric
#' @seealso \code{\link{ReadSensorgramData}} \code{\link{GetObservedRUs}} \code{\link{SaveSPRData}}
#' @examples
#' dt<-new("SensorgramData",
#' dissociationData=data.frame(time=1:5,RU=1:5, time2=1:5, RU=1:5))
#' dt@associationData
#'
#' dataFile<-list.files(system.file("extdata", package="SPRATS"),
#' pattern = "CBSInhibitor_raw.txt", full.names=TRUE)
#' rawData<-ReadSensorgramData(dataFile, skip=4,
#' header=T, sep="\t", associationPhaseEnd=80, dissociationPhaseEnd=150)
#'
#' plot(rawData)
#' @export
setClass( "SensorgramData",
representation(associationData="data.frame",
dissociationData="data.frame",
analyteConcentrations="numeric",
steadyStateStart="numeric", #optional, but necessary for fitting two state
steadyStateEnd="numeric",#optional, but necessary for fitting two state
offset="numeric" ###optional, might be used in the future
),
prototype(associationData=data.frame(),
dissociationData=data.frame(),
analyteConcentrations=numeric(),
steadyStateStart=-1,
steadyStateEnd=-1,
offset=0.0
)
)
setValidity("SensorgramData", function(object){
#first check for association data
if(!is.null(object@associationData)&&length(object@associationData)!=0){
#the columns must be pairs of Time and RUs
if(dim(object@associationData)[2]%%2!=0)
{
cat("AssociationData is not in correct format!!\n")
cat("dimension of association data:",dim(object@associationData)[2], "\n");
}
else if (!is.null(object@dissociationData)&&length(object@dissociationData)!=0){
if(dim(object@dissociationData)[2]%%2!=0)
"DissociationData is not in correct format!!"
else if(dim(object@associationData)[2]!=dim(object@dissociationData)[2]){
"AssociationData and DissociationData are not consistent with each other!"
}
else {
#cat("we are here\n")
TRUE
}
}
else
TRUE
}
#now check for dissociation data
else if(!is.null(object@dissociationData)&&length(object@dissociationData)!=0){
if(dim(object@dissociationData)[2]%%2!=0){
"dissociationData is not in correct format!!"
}
else
TRUE
}
#all the data is null or empty, go ahead
else
TRUE
#in this checking, we did not check for the number of concentration elements. leave it to the future
}
)
#' @title S3 method to read in the data
#'
#' @description It read in data as a txt file according to
#' exported SPR file from SensiQ
#' @details
#' Data file has the following format\cr
#' \tabular{llllllll}{
#' Curve\tab 1\tab 2\tab 3\tab 4\cr
#' Analyte\tab CBS\tab CBS\tab CBS\tab CBS\cr
#' Ligand\tab Ch 1\tab Ch 1\tab Ch 1\tab Ch 1\cr
#' Conc\tab 0.00E+00\tab 5.00E-05\tab 0.00E+00\tab 0.00E+00\cr
#' Time1\tab Data1\tab Time2\tab Data2\tab Time3\tab Data3\tab Time4\tab Data4\cr
#' -2.6\tab 0\tab -2.6\tab 0.2839\tab -2.6\tab 0\tab -2.6\tab 0\cr
#' -2.4\tab 0\tab -2.4\tab 0.3632\tab -2.4\tab 0\tab -2.4\tab 0\cr
#' -2.2\tab 0\tab -2.2\tab 0.6978\tab -2.2\tab 0\tab -2.2\tab 0\cr
#' }
#' Each file contains the header about the information of the data
#' Data colums for the raw sensorgram data with header for each column
#' each "curve" has two column, one time and the other RUs.
#' The number of curves are variable. Please check the example
#' data file in the example/ folder.
#' Note: after reading the dissociation phase is rescaled to
#' start at time zero.!!! relative to the
#' dissociationPhaseStart/associationPhaseEnd
#'
#' @param file the directory path to the input file with the
#' correct format as mentioned above
#' @param associationPhaseStart numeric indiciation the starting
#' time for associationPhase
#' @param associationPhaseEnd numeric indiciation the starting
#' time for associationPhase. This is actually the starting
#' time for dissociationPhase
#' @param dissociationPhaseEnd numeric indiciation the starting
#' time for dissociationPhase
#' @param steadyStateStart numeric indicating the starting time of
#' steady state (optional).
#' @param steadyStateEnd numeric indicating the ending time of
#' steady state (optional).
#' @param analyteConcentrations numeric vector for analyte concentrations
#' @param skip numeric the options for control the text reading. indicating
#' number of line to skip
#' @param header boolean header for the table reading (T/F)
#' @param sep character for the delimiter of the text
#'
#' @return a sensorgram data object
#'
#' @seealso \code{\link{SensorgramData-class}} \code{\link{plot}} \code{\link{SaveSPRData}}
#' @examples
#'
#' dataFile<-list.files(system.file("extdata", package="SPRATS"),
#' pattern = "CBSInhibitor_raw.txt", full.names=TRUE)
#' rawData<-ReadSensorgramData(dataFile, skip=4,
#' header=T, sep="\t", associationPhaseEnd=80, dissociationPhaseEnd=150)
#'
#' plot(rawData)
#' @export
ReadSensorgramData<-function(file, associationPhaseStart=0, associationPhaseEnd=-1,
dissociationPhaseEnd=-1, steadyStateStart=-1, steadyStateEnd=-1,
analyteConcentrations=numeric(0),
skip=0, header=TRUE, sep="\t")
{
#first we need to check for validity of the input
if(associationPhaseEnd<0 ||associationPhaseEnd< associationPhaseStart)
cat("Warning: the associationPhase window is not correctly (?) set......\n")
if(dissociationPhaseEnd<0||dissociationPhaseEnd<associationPhaseEnd)
cat("Warning: the dissociationPhase window is not correctly (?) set......\n")
cat("Start reading the data files.......\n")
x_rawData<-read.table(file,skip=skip, header=header,sep=sep)
cat("Done with reading the raw text file....\n")
cat("Start parsing.....\n");
x_sgdata<-new("SensorgramData")
x_sgdata@analyteConcentrations<-analyteConcentrations
#assuming formation is Time1 RU1 Time2 RU2....
x_Ass<-data.frame();
x_Dis<-data.frame();
for(i in seq(1,dim(x_rawData)[2], by=2))
{
#cat("i:",i,"....\n")
if(i+1>dim(x_rawData)[2])
break;
x_temp<-x_rawData[,c(i,i+1)]
x_tempAss<-x_temp[x_temp[,1]>=associationPhaseStart&x_temp[,1]<=associationPhaseEnd,]
x_tempDis<-x_temp[x_temp[,1]>=associationPhaseEnd&x_temp[,1]<=dissociationPhaseEnd,]
x_tempDis[,1]<-x_tempDis[,1]-associationPhaseEnd
if(i==1){
x_Ass<-x_tempAss
x_Dis<-x_tempDis
}
else
{
x_Ass<-cbind(x_Ass, x_tempAss)
x_Dis<-cbind(x_Dis, x_tempDis)
}
}
#now we have the data,
cat("Setting sensorgram data......\n")
x_sgdata@associationData<-x_Ass
x_sgdata@dissociationData<-x_Dis
x_sgdata@steadyStateStart<-steadyStateStart
x_sgdata@steadyStateEnd<-steadyStateEnd
cat("Done......\n")
return(x_sgdata)
}
#' @title Generic plot function for SensorgramData
#'
#' @description \code{plot} plot the sensorgram
#' @details Generic function to plot the sensorgram of SPR.
#' Both the dissociation and association phase as well
#' the steady state window.
#'
#' @param SensorgramData the SensorgramData object to be plotted
#'
#' @seealso \code{\link{ReadSensorgramData}} \code{\link{SensorgramData-class}} \code{\link{SaveSPRData}}
#' @export
setMethod("plot", "SensorgramData",
function(x, col=1, lty=1, lwd=1, main="",xlab="time (sec)", ylab="RUs" )
{
#cat("times:",ceiling(length(x@associationData)/2/col))
col<-rep(col,ceiling(length(x@associationData)/2/length(col)))
lty<-rep(lty,ceiling(length(x@associationData)/2/length(lty)))
lwd<-rep(lwd,ceiling(length(x@associationData)/2/length(lwd)))
#cat("lty:",lty,"\n")
max_x1<-0;
max_x2<-0;
max_y1<-0
max_y2<-0;
meanRUs<-rep(0, length(x@associationData)/2)
for(i in 1:(length(x@associationData)/2))
{
if(max_x1>min(x@associationData[,i*2-1]))
{
max_x1<-min(x@associationData[,i*2-1])
}
if(max_x2<max(x@associationData[,i*2-1]))
{
max_x2<-max(x@associationData[,i*2-1])
}
if(max_y1>min(x@associationData[,i*2]))
{
max_y1<-min(x@associationData[,i*2])
}
if(max_y2<max(x@associationData[,i*2]))
{
max_y2<-max(x@associationData[,i*2])
}
#meanRUs[i]<-
}
for(i in 1:(length(x@dissociationData)/2))
{
if(max_x1>min(max(x@associationData[,i*2-1])+x@dissociationData[,i*2-1]))
{
max_x1<-min(max(x@associationData[,i*2-1])+x@dissociationData[,i*2-1])
}
if(max_x2<max(max(x@associationData[,i*2-1])+x@dissociationData[,i*2-1]))
{
max_x2<-max(max(x@associationData[,i*2-1])+x@dissociationData[,i*2-1])
}
if(max_y1>min(x@dissociationData[,i*2]))
{
max_y1<-min(x@dissociationData[,i*2])
}
if(max_y2<max(x@dissociationData[,i*2]))
{
max_y2<-max(x@dissociationData[,i*2])
}
#meanRUs[i]<-
}
plot(c(max_x1, max_x2), c(max_y1, max_y2), type="n",main=main, xlab=xlab, ylab=ylab)
for(i in 1:(length(x@associationData)/2))
{
#cat("plotting i:",i,"lty[i]:",lty[i],"\n")
lines(x@associationData[,i*2-1], x@associationData[,i*2],col=col[i], lty=lty[i], lwd=lwd[i])
lines(max(x@associationData[,i*2-1])+x@dissociationData[,i*2-1], x@dissociationData[,i*2],col=col[i],lty=lty[i],lwd=lwd[i])
}
}
)
#'@title S3 function to combine/add two SensorgramData
#'
#'@description Combine two SensorgramData object to simulate
#' the real readout on a SPR machine.
#'
#'@details The idea is to combine the RUs from two different source
#' e.g. from two complexes with different comfirmations, as
#' an real readout on the SPR machine. It adds up the RUs at
#' the same time points to get the sum. Do this through the
#' association and dissociation. Don't try to modify any other
#' slots for the object.
#'
#'@param DATA1 SensorgramData
#'@param DATA2 SensorgramData
#'@return a SensorgramData object with the sum of the two input objects
#' on both association and dissociation data. It takes other slot
#' values from DATA1 assuming DATA2 has the identical values on
#' these other slots.
#'@seealso \code{\link{ReadSensorgramData}} \code{\link{SensorgramData-class}} \code{\link{plot}} \code{\link{SaveSPRData}}
#' @examples
#'
#' dataFile<-list.files(system.file("extdata", package="SPRATS"),
#' pattern = "CBSInhibitor_raw.txt", full.names=TRUE)
#' rawData<-ReadSensorgramData(dataFile, skip=4,
#' header=T, sep="\t", associationPhaseEnd=80, dissociationPhaseEnd=150)
#' rawData2<-GetObservedRUs(rawData,rawData)
#' plot(rawData)
#' @export
GetObservedRUs<-function(DATA1, DATA2)
{
if(class(DATA1)!="SensorgramData"||class(DATA2)!="SensorgramData")
{
cat("*******ERROR:SensorgramData are expected for both input")
return(FALSE)
}
if(length(DATA1@associationData)!=length(DATA2@associationData))
{
cat("********ERROR:input data are not consistent with each other\n")
return(FALSE);
}
if(length(DATA1@associationData[,1])!=length(DATA2@associationData[,1]))
{
cat("********ERROR:input data are not consistent with each other\n")
return(FALSE);
}
#add all the AB together to get RU observed
dt_RUs<-DATA1
#new to decide the dimension of association and dissociation data
#assuming they are of each dimension
#
lenData<-dim(DATA1@associationData)[2]
lenData<-lenData/2
if(lenData<1)
return(dt_RUs)
for(i in 1:lenData)
{
dt_RUs@associationData[,i*2]<-DATA1@associationData[,i*2]+DATA2@associationData[,i*2]
dt_RUs@dissociationData[,i*2]<-DATA1@dissociationData[,i*2]+DATA2@dissociationData[,i*2]
}
dt_RUs
}
#'@title S3 function to sum SensorgramData
#'
#'@description sum all SensorgramData objects to simulate
#' the real readout on a SPR machine.
#'
#'@details The idea is to combine the RUs from many different sources
#' in the multi-liganded system as
#' an real readout on the SPR machine. It adds up the RUs at
#' the same time points to get the sum. Do this through the
#' association and dissociation. Don't try to modify any other
#' slots for the object.
#'
#'@param DATA List of SensorgramData
#'
#'@return a SensorgramData object with the sum of the all input objects
#' in the list on both association and dissociation data. It takes other slot
#' values from DATA[[1]] assuming DATA objects all have the identical values on
#' these other slots.
#'@seealso \code{\link{ReadSensorgramData}} \code{\link{SensorgramData-class}} \code{\link{plot}} \code{\link{SaveSPRData}}
#' @examples
#'
#' dataFile<-list.files(system.file("extdata", package="SPRATS"),
#' pattern = "CBSInhibitor_raw.txt", full.names=TRUE)
#' rawData<-ReadSensorgramData(dataFile, skip=4,
#' header=T, sep="\t", associationPhaseEnd=80, dissociationPhaseEnd=150)
#'
#' rawDataSum<-sumRUs(list(rawData,rawData,rawData))
#' plot(rawData)
#' @export
sumRUs<-function(DATA)
{
#check data integrity
if(missing(DATA))
{
stop("DATA field has not been specified!");
}
if(class(DATA)!="list"&&class(DATA)!="SensorgramData")
{
stop("unexpected object class for DATA!");
}
#in this case, we can only have one input object
if(class(DATA)=="SensorgramData")
{
return(DATA)
}
#now could be many of them, check for sure
if(length(DATA)==0)
{
return(NULL)
}
if(length(DATA)==1)
{
return(DATA[[1]])
}
#now more than 2 element
lenList<-length(DATA)
#lenData<-length(DATA[[1]])
origDimAssData<-c(0,0)
origDimDisData<-c(0,0)
for(i in c(1:lenList))
{
if(class(DATA[[i]])!="SensorgramData")
{
stop("SensorgramData is expected for input list");
}
dimAssData<-dim(DATA[[i]]@associationData)
dimDisData<-dim(DATA[[i]]@dissociationData)
if(i==1)#first one, set original
{
origDimAssData<-dim(DATA[[i]]@associationData)
origDimDisData<-dim(DATA[[i]]@dissociationData)
}else
{
if((dimAssData[1]!=origDimAssData[1])||(dimAssData[2]!=origDimAssData[2])||(dimDisData[1]!=origDimDisData[1])||(dimDisData[2]!=origDimDisData[2]))
{
cat("********ERROR:input data are not consistent with each other (at ",i,"th element\n")
return(NULL)
}
origDimAssData<-dimAssData
origDimDisData<-dimDisData
}
}
#add all the AB together to get RU observed
dt_RUs<-DATA[[1]]
#new to decide the dimension of association and dissociation data
#assuming they are of each dimension
#
lenData<-dim(dt_RUs@associationData)[2]
lenData<-lenData/2
if(lenData<1)
return(dt_RUs)
for(j in 2:lenList)
{
for(i in 1:lenData)
{
dt_RUs@associationData[,i*2]<-dt_RUs@associationData[,i*2]+DATA[[j]]@associationData[,i*2]
dt_RUs@dissociationData[,i*2]<-dt_RUs@dissociationData[,i*2]+DATA[[j]]@dissociationData[,i*2]
}
}
dt_RUs
}
#'@title S3 function to save SensorgramData data
#'
#'@description save SensorgramData object data to the disk.
#'
#'@details It save the object data to the disk in a text format,
#' following the SensiQ format. See the detail \code{\link{ReadSensorgramData}}
#' Note: it will issue a warning to complain about appending the table.
#' There is nothing wrong with it. Simple ignore this warning.
#'
#'@param DATA SensorgramData to be saved
#'@param file the directory path to the file
#'@param sep character to delimit the text fields
#'
#'@seealso \code{\link{ReadSensorgramData}} \code{\link{SensorgramData-class}} \code{\link{plot}}
#' @export
SaveSPRData<-function(DATA, file, sep="\t")
{
if(class(DATA)!="SensorgramData")
{
cat("***ERROR***:sensorgramData is expected for the input\n")
return(FALSE)
}
dtfm_RUs_a<-DATA@associationData
dtfm_RUs_d<-DATA@dissociationData
#check the dissociation data first, if the first row is zero for time, we need to combine this one
#with the last one of the association data to make it consistent
if(dtfm_RUs_d[1,1]==0)
{
#get the mean of both values
dtfm_RUs_a[length(dtfm_RUs_a[,1]),seq(2,length(dtfm_RUs_a),2)]<-
(dtfm_RUs_a[length(dtfm_RUs_a[,1]),seq(2,length(dtfm_RUs_a),2)]+
dtfm_RUs_d[1,seq(2,length(dtfm_RUs_d),2)])/2;
#also remove the first one of the dissociation data
dtfm_RUs_d<-dtfm_RUs_d[c(-1),]
}
#also need to add the time together for dissociation data
for(i in 1:length(DATA@analyteConcentrations))
{
dtfm_RUs_d[,i*2-1]<-max(dtfm_RUs_a[,i*2-1])+dtfm_RUs_d[,i*2-1]
}
dtfm_RUs_a<-rbind(dtfm_RUs_a, dtfm_RUs_d)
#now save it to the disk
write(DATA@analyteConcentrations,file=file, sep=sep)
write.table(dtfm_RUs_a, file=file, sep=sep,append=TRUE, row.names=FALSE, quote=FALSE)
#TRUE
}
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.