Skip to content
Snippets Groups Projects
Unverified Commit 80f85878 authored by Todor Kondic's avatar Todor Kondic
Browse files

Merge 0.9.3 from decouple

parents 59a92e80 61c8ee65
No related branches found
Tags v0.9.3
No related merge requests found
Package: shinyscreen
Title: Pre-screening of Mass Spectrometry Data
Version: 0.9.0
Version: 0.9.3
Author: Todor Kondić
Maintainer: Todor Kondić <todor.kondic@uni.lu>
Authors@R:
......@@ -20,19 +20,19 @@ Authors@R:
person(given = "Hiba Mohammed",
family = "Taha",
role = c("ctb"),
email = "hiba.mohammed-taha@ext.uni.lu"),
email = "hiba.mohammed-taha@uni.lu"),
person(given = "Jessy",
family = "Krier",
role = c("ctb"),
email = "jessy.krier@ext.uni.lu"),
email = "jessy.krier@uni.lu"),
person(given = "Mira",
family = "Narayanan",
role = c("ctb"),
email = "mira.narayanan@ext.uni.lu"),
email = "mira.narayanan@uni.lu"),
person(given = "Anjana",
family = "Elapavalore",
role = c("ctb"),
email = "anjana.elapavalore@ext.uni.lu"),
email = "anjana.elapavalore@uni.lu"),
person(given = "Marc",
family = "Warmoes",
role = c("ctb"),
......@@ -41,31 +41,34 @@ Description: Pre-screening of Mass Spectrometry Data.
License: Apache License (>= 2.0)
Encoding: UTF-8
LazyData: true
RoxygenNote: 6.1.1
RoxygenNote: 7.1.1
Roxygen: list(markdown = TRUE)
Collate:
'resources.R'
'base.R'
'resources.R'
'mix.R'
'extraction.R'
'run.R'
'shinyUI.R'
'api.R'
'shiny-ui-base.R'
Depends:
RMassBank,
RChemMass
Imports:
tools,
scales,
parallel,
future,
yaml,
mzR,
MSnbase,
data.table,
assertthat,
withr,
ggplot2,
cowplot,
RColorBrewer,
grid,
curl,
shiny,
shinydashboard,
shinyFiles,
rhandsontable
rhandsontable,
DT,
tcltk
# Generated by roxygen2: do not edit by hand
export(launch)
export(app)
export(concurrency)
export(conf_trans)
export(create_plots)
export(extr_data)
export(extract)
export(gen_key_plot_tab)
export(gen_struct_plots)
export(get_fn_comp)
export(get_fn_conf)
export(get_fn_extr)
export(get_fn_ftab)
export(get_fn_summ)
export(grab_unit)
export(list2rev)
export(load_compound_input)
export(load_data_input)
export(load_inputs)
export(merge2rev)
export(mk_comp_tab)
export(mk_tol_funcs)
export(mz_input)
export(new_rv_state)
export(new_state)
export(new_state_fn_conf)
export(plot_ms1_chr)
export(plot_ms2_chr)
export(plot_ms2_spec)
export(plot_struct)
export(plot_struct_nowrap)
export(prescreen)
export(report)
export(rev2list)
export(rt_input)
export(run)
export(run_in_dir)
export(save_plots)
export(setup_phase)
export(sort_spectra)
export(subset_summary)
export(tk_save_file)
import(data.table)
importFrom(shiny,validate)
R/api.R 0 → 100644
This diff is collapsed.
......@@ -12,16 +12,18 @@
## See the License for the specific language governing permissions and
## limitations under the License.
##' @import data.table
## Redirections
the_ifelse <- data.table::fifelse
dtable <- data.table::data.table
tab2file<-function(tab,file,...) {
write.csv(x=tab,file=file,row.names=F,...)
data.table::fwrite(x=tab,file=file,...)
}
file2tab<-function(file,stringsAsFactors=F,comment.char='',sep=',',...) {
read.csv(file=file,
header=T,
stringsAsFactors=stringsAsFactors,
comment.char=comment.char,
na.strings=c("","NA"),...)
file2tab<-function(file,na.strings=c("","NA","\"\""),...) {
data.table::fread(file=file,na.strings = na.strings, ...)
}
isThingFile<-function(fn) {
......@@ -35,3 +37,19 @@ split_path <- function(path) {
if (dirname(path) %in% c(".", path)) return(basename(path))
return(c(basename(path), split_path(dirname(path))))
}
print_table <- function (df) {
paste(apply(df,1,function (row) paste(row,collapse=',')),collapse = "\n")
}
assert <- function(expr,msg) shiny::validate(shiny::need(expr,message=msg))
gen_uniq_lab <- function(prev,pref='',suff='') {
l <- length(prev)
gen <- function() paste0(pref,as.integer(runif(1,min=l,max=2L*l+1L)),suff)
cand <- gen()
while (cand %in% prev) cand <- gen()
c(prev,cand)
}
......@@ -19,6 +19,30 @@ load_raw_data<-function(fn,mode="inMemory") {
}
centroided1 <- function(ms) {
if (all(MSnbase::centroided(ms)) == T)
return(T) else {
state <- MSnbase::isCentroided(ms)
N <- length(state)
fls <-length(which(state == F))
if (fls/(1.*N) < 0.01) T else F
}
}
centroided <- function(msvec) {
if (is.vector(msvec)) {
f <- list()
for (i in 1:length(msvec)) {
f[[i]] <- future::future(centroided1(msvec[[i]]))
}
lapply(f, FUN = future::value)
} else {
centroided1(msvec)
}
}
acq_mz<-function(tabFn) {
df<-read.csv(tabFn,
stringsAsFactors=F,
......@@ -33,17 +57,15 @@ id2name<-function(id) {paste("ID:",id,sep='')}
ppm2dev<-function(m,ppm) 1e-6*ppm*m
gen_mz_range<-function(mz,err) {
mat<-matrix(data=numeric(1),nrow=length(mz),ncol=2,dimnames=list(as.character(names(mz))))
mat<-matrix(data=numeric(1),nrow=length(mz),ncol=2)
mat[,1]<-mz - err
mat[,2]<-mz + err
mat
}
gen_rt_range<-function(rt,err) {
mat<-matrix(data=numeric(1),nrow=length(rt),ncol=2,dimnames=list(as.character(names(rt))))
mat<-matrix(data=numeric(1),nrow=length(rt),ncol=2)
rV<-which(!is.na(rt))
rNA<-which(is.na(rt))
mat[rV,1]<-(rt[rV] - err)*60
......@@ -53,10 +75,7 @@ gen_rt_range<-function(rt,err) {
mat
}
filt_ms2_by_prcs <- function(ms2,mz,errCoarse) {
mzRng<-gen_mz_range(mz,err=errCoarse)
ids<-rownames(mzRng)
filt_ms2_by_prcs <- function(ms2,mzrng,ids,adduct) {
pre<-MSnbase::precursorMz(ms2)
psn<-MSnbase::precScanNum(ms2)
acN<-MSnbase::acquisitionNum(ms2)
......@@ -64,37 +83,41 @@ filt_ms2_by_prcs <- function(ms2,mz,errCoarse) {
inRange<-function(i) {
mp<-pre[[i]]
x<-mzRng[,1]<mp & mp<mzRng[,2]
mRows<-which(x)
sids<-ids[mRows]
sids
x<-mzrng[,1]<mp & mp<mzrng[,2]
ind<-which(x)
sids <- ids[ind]
add <- adduct[ind]
dtable(ID=sids,adduct=add)
}
lst<-lapply(1:nR,function(i) list(n=i,prec_scan=psn[[i]],aN=acN[[i]],ids=inRange(i)))
lst<-lapply(1:nR,function(i) {
dt <- inRange(i)
list(n=i,prec_scan=psn[[i]],aN=acN[[i]],ids=dt$ID,adduct=dt$adduct)
})
nemp<-sapply(lst,function(m) length(m$ids)>0)
wrk<-lst[nemp]
dfL<-sum(sapply(wrk,function(w) length(w$ids)))
df<-data.frame(ID=character(dfL),
prec_scan=integer(dfL),
aN=integer(dfL),
OK=logical(dfL),
stringsAsFactors=F)
df<-dtable(ID=character(dfL),
adduct=character(dfL),
prec_scan=integer(dfL),
aN=integer(dfL),
OK=logical(dfL))
df$OK<-T #TODO Introduced for testing, be careful.
offD<-0
for (m in wrk) {
l<-length(m$ids)
rng<-(offD+1):(offD+l)
df[rng,"ID"]<-m$ids
df[rng,"prec_scan"]=m$prec_scan
df[rng,"aN"]<-m$aN
df[rng,"ID"] <- m$ids
df[rng,"prec_scan"] <- m$prec_scan
df[rng,"aN"] <- m$aN
df[rng,"adduct"] <- m$adduct
offD<-offD+l
}
df[order(df$aN),]
}
filt_ms2_by_prcs_ht<-function(ms2,mz,errCoarse) {
lgnd<-filt_ms2_by_prcs(ms2,mz,errCoarse)
filt_ms2_by_prcs_ht<-function(ms2,mzrng,ids,adduct) {
lgnd<-filt_ms2_by_prcs(ms2,mzrng=mzrng,ids=ids,adduct=adduct)
scans<-unique(lgnd$aN)
ns<-which(MSnbase::acquisitionNum(ms2) %in% scans)
sms2<-ms2[ns]
......@@ -105,29 +128,37 @@ filt_ms2_by_prcs_ht<-function(ms2,mz,errCoarse) {
pick_unique_precScans<-function(idx) {
ps<-unique(idx$prec_scan)
mind<-match(ps,idx$prec_scan)
ids<-idx$ID[mind]
data.frame(prec_scan=idx$prec_scan[mind],ID=ids,stringsAsFactors=F)
data.frame(prec_scan=idx$prec_scan[mind],
ID=idx$ID[mind],
adduct=idx$adduct[mind],
stringsAsFactors=F)
}
pick_uniq_pscan<-function(leg) {
ids<-unique(leg$ID)
x<-lapply(ids,function(id) {ups<-unique(leg[id==leg$ID,"prec_scan"]);data.frame(ID=rep(id,length(ups)),prec_scan=ups,stringsAsFactors = F)})
res<-do.call(rbind,c(x,list(stringsAsFactors=F)))
res[order(res$prec_scan),]
res <- leg[,.(prec_scan=unique(prec_scan)),by=c("ID","adduct")]
res[order(prec_scan),]
## ids<-unique(leg$ID)
## x<-lapply(ids,function(id) {ups<-unique(leg[id==leg$ID,"prec_scan"]);data.frame(ID=rep(id,length(ups)),prec_scan=ups,stringsAsFactors = F)})
## res<-do.call(rbind,c(x,list(stringsAsFactors=F)))
## res[order(res$prec_scan),]
}
verif_prec_fine_ht<-function(preLeg,ms1,mz,errFinePPM) {
mzRng<-gen_mz_range(mz,err=ppm2dev(mz,errFinePPM))
verif_prec_fine_ht<-function(preLeg,ms1,mz,mzrng,ids,adduct) {
## TODO FIXME TESTPHASE Something goes wrong here, all mapply results are
## not OK. More testing needed.
df<-preLeg
df$mz<-mz[df$ID]
mz1<-mzRng[df$ID,1]
mz2<-mzRng[df$ID,2]
ipns<-match(df$prec_scan,MSnbase::acquisitionNum(ms1))
rms1<-ms1[ipns]
mzsp<-MSnbase::mz(rms1)
df$OK<-mapply(function(m1,sp,m2) any((m1<sp) & (sp<m2)),mz1,mzsp,mz2)
df[df$OK,]
xx <- dtable(adduct=adduct,ID=ids,mz=mz,mz1=mzrng[,1],mz2=mzrng[,2])
df <- preLeg[xx,on=c("ID","adduct")]
df$ipns<-match(df$prec_scan,MSnbase::acquisitionNum(ms1))
df[, ("mzsp") := .(lapply(ipns,function (ip) if (!is.na(ip)) MSnbase::mz(ms1[[ip]]) else NA_real_))]
df$OK<-mapply(function(m1,sp,m2) any((m1<sp) & (sp<m2)),df$mz1,df$mzsp,df$mz2)
res<-df[df$OK,]
res$ipns<-NULL
res$mz1<-NULL
res$mz2<-NULL
res$mzsp<-NULL
res
}
filt_ms2<-function(ms1,ms2,mz,errCoarse,errFinePPM) {
......@@ -150,6 +181,60 @@ filt_ms2<-function(ms1,ms2,mz,errCoarse,errFinePPM) {
names(res)<-uids
res
}
filt_ms2_fine <- function(ms1,ms2,mz,ids,adduct,err_coarse_fun,err_fine_fun) {
## This function is supposed to extract only those MS2 spectra for
## which it is proven that the precursor exists within the fine
## error range.
mzrng_c <- gen_mz_range(mz,err_coarse_fun(mz))
mzrng_f <- gen_mz_range(mz,err_fine_fun(mz))
tmp<-filt_ms2_by_prcs_ht(ms2,mzrng=mzrng_c,ids=ids,adduct=adduct)
legMS2<-tmp$leg
legPcs<-pick_uniq_pscan(legMS2)
legPcs<-verif_prec_fine_ht(legPcs,ms1=ms1,mz=mz,mzrng=mzrng_f,ids=ids,adduct=adduct)
## x<-Map(function (id,psn,a) {legMS2[id==legMS2$ID & a==legMS2$adduct & psn==legMS2$prec_scan,]},legPcs[,"ID"],legPcs[,"prec_scan"],legPcs[,"adduct"])
## x <- data.table::rbindlist(x)[,.(ID,adduct,aN)]
x <- legMS2[legPcs[,.(ID,adduct,prec_scan)],on=c("ID","adduct","prec_scan")]
## x<-do.call(rbind,c(x,list(make.row.names=F,stringsAsFactors=F)))[c("ID","aN")]
## rownames(x)<-NULL
x<-x[order(x$aN),]
x
}
extr_ms2<-function(ms1,ms2,ids,mz,adduct,err_coarse_fun, err_fine_fun) {
## Extraction of MS2 EICs and spectra.
x <- filt_ms2_fine(ms1=ms1,
ms2=ms2,
mz=mz,
ids=ids,
adduct=adduct,
err_coarse_fun=err_coarse_fun,
err_fine_fun=err_fine_fun)
## This was here before and obviously wrong when multiple adducts
## correspond to the same ID:
##
## uids <- unique(x$ID)
## uadds <- unique(x$adduct)
idadd <- x[,unique(.SD),.SDcols=c("ID","adduct")]
acN<-MSnbase::acquisitionNum(ms2)
chunks <- Map(function(id,ad) {
ans <- x[id==x$ID & ad==x$adduct,]$aN
sp<-ms2[which(acN %in% ans)]
message("id:",id,"ad:",ad)
res <- gen_ms2_spec_blk(sp)
res$ID <- id
res$adduct <- ad
res
},
idadd$ID,idadd$adduct)
data.table::rbindlist(chunks,fill = T)
}
add_ms2_prcs_scans<-function(ms2,idx) {
......@@ -167,11 +252,6 @@ add_ms2_prcs_scans<-function(ms2,idx) {
df
}
refn_ms2_by_prec<-function(idxMS2,preFine) {
pf<-preFine[preFine$OK,]
pf$ID<-as.character(pf$ID)
......@@ -214,7 +294,7 @@ grab_ms2_spec<-function(idx,raw) {
names(res)<-IDs
res
}
gen_ms2_chrom<-function(ms2Spec) {
lapply(ms2Spec, function(sp)
......@@ -241,19 +321,18 @@ gen_ms2_chrom<-function(ms2Spec) {
}
gen_ms1_chrom<-function(raw,mz,errEIC,rt=NULL,errRT=NULL) {
mzRng<-gen_mz_range(mz,err=errEIC)
rtRng<-gen_rt_range(rt,err=errRT)
ids<-dimnames(mzRng)[[1]]
gen_ms1_chrom <- function(raw,mz,errEIC,id,rt=NULL,errRT=NULL) {
mzRng<-gen_mz_range(mz,err = errEIC)
rtRng<-gen_rt_range(rt,err = errRT)
x<-MSnbase::chromatogram(raw,mz=mzRng,msLevel=1,missing=0.0,rt=rtRng)
res<-lapply(x,function (xx) {
rt<-MSnbase::rtime(xx)/60.
ints<-MSnbase::intensity(xx)
df<-data.frame(rt=rt,intensity=ints,stringsAsFactors=F)
df<-dtable(rt=rt,intensity=ints)
df
})
names(res)<-ids
names(res)<-id
res
}
......@@ -267,20 +346,6 @@ gen_ms1_chrom_ht<-function(raw,mz,errEIC,rt=NULL,errRT=NULL) {
res
}
tab2file<-function(tab,file,...) {
write.csv(x=tab,file=file,row.names=F,...)
}
file2tab<-function(file,stringsAsFactors=F,comment.char='',...) {
read.csv(file=file,
header=T,
stringsAsFactors=stringsAsFactors,
comment.char=comment.char,
na.strings=c("","NA"),...)
}
get_ext_width <- function(maxid) {as.integer(log10(maxid)+1)}
id_fn_ext<-function(width,id) {
formatC(as.numeric(id),width=width,flag=0)
......@@ -351,7 +416,7 @@ extr_msnb <-function(file,wd,mz,errEIC, errFinePPM,errCoarse=0.5,rt=NULL,errRT=N
message("Extracting MS2 spectra.")
idxMS2<-filt_ms2_by_prcs(ms2=ms2,mz=mz,errCoarse=errCoarse)
message("Resampling MS2 spectra.")
# idxMS2<-add_ms2_prcs_scans(ms2,idxMS2)
# idxMS2<-add_ms2_prcs_scans(ms2,idxMS2)
prsc<-pick_unique_precScans(idxMS2)
vprsc<-verif_prec_fine(preSc=prsc,ms1=ms1,mz=mz,errFinePPM = errFinePPM)
idxMS2<-refn_ms2_by_prec(idxMS2=idxMS2,preFine=vprsc)
......@@ -411,39 +476,114 @@ extr_msnb_ht <-function(file,wd,mz,errEIC, errFinePPM,errCoarse,fnSpec,rt=NULL,e
x
}
##' Extracts data from mzML files.
##'
##' @title Data Extraction from mzML Files
##' @param fTab File table with Files,ID,wd,Name,mz and RT
##' columns. Column Files, as well as wd must have all rows
##' identical.
##' @param extr_fun Extraction function from the backend.
##' @param errEIC Absolute mz tolerance used to extract precursor EICs.
##' @param errFinePPM Tolerance given in PPM used to associate input
##' masses with what the instrument assigned as precursors to MS2.
##' @param errCoarse Absolute tolerance for preliminary association of
##' precursors (from precursorMZ), to MS2 spectra.
##' @param errRT The half-width of the retention time window.
##' @param fnSpec Output file specification.
##' @return Nothing useful.
##' @author Todor Kondić
extract<-function(fTab,extr_fun,errEIC,errFinePPM,errCoarse,fnSpec,errRT) {
fnData<-fTab$Files[[1]]
wd<-fTab$wd[[1]]
ID<-fTab$ID
mz<-fTab$mz
rt<-fTab$rt
names(mz)<-id2name(ID)
if (!is.null(rt)) names(rt)<-ID
dir.create(wd,showWarnings=F)
extr_fun(file=fnData,
wd=wd,
mz=mz,
rt=rt,
errRT=errRT,
errEIC=errEIC,
errFinePPM=errFinePPM,
errCoarse=errCoarse,
fnSpec=fnSpec)
extr_eic_ms1 <- function(tab,err) {
## Asynchronous extraction of ms1 spectra. The result is a list of
## running futures.
file <- unique(tab$file)
res <-lapply(file,function (fn) future::futur(extr_fn(fn), lazy=T))
names(res) <- file
res
}
##' @export
extract <- function(fn,tag,tab,err_ms1_eic.,err_coarse,err_fine,err_rt.) {
## Extracts MS1 and MS2 EICs, as well as MS2 spectra, subject to
## tolerance specifications.
## TODO: Still detecting external references ... but which?
## However, the results check out, compared to sequential access.
err_coarse_fun <- gen_mz_err_f(err_coarse,
"ms1 coarse error: Only ppm, or Da units allowed.")
err_fine_fun <- gen_mz_err_f(err_fine,
"ms1 fine error: Only ppm, or Da units allowed.")
err_ms1_eic <- gen_mz_err_f(err_ms1_eic.,
"eic error: Only ppm, or Da units allowed.")
err_rt <- gen_rt_err(err_rt.,
"rt error: Only s(econds), or min(utes) allowed.")
tab <- data.table::as.data.table(tab)
## chunk <- tab[file==fn]
mz <- tab$mz
rt <- tab$rt
id <- tab$ID
adduct <- tab$adduct
names(mz) <- id
names(rt) <- id
mzerr <- err_coarse_fun(mz)
mzrng <- gen_mz_range(mz=mz,err=mzerr)
rtrng <- gen_rt_range(rt=rt,err=err_rt)
mzmin <- min(mzrng)
mzmax <- max(mzrng)
read_ms1 <- function() {
ms1 <- MSnbase::readMSData(file=fn,msLevel=1,mode="onDisk")
ms1 <- MSnbase::filterMz(ms1,c(mzmin,mzmax))
ms1
}
read_ms2 <- function() {
ms2 <- MSnbase::readMSData(file=fn,msLevel=2,mode="onDisk")
ms2
}
extr_ms1_eic <- function(ms1) {
eic <- MSnbase::chromatogram(ms1,mz=mzrng,msLevel=1,missing=0.0,rt=rtrng)
bits <- dtable(N=sapply(eic,NROW))
bigN <- bits[,sum(N)]
bits[,idx:=paste0('I',.I)]
bits$ID <- id
bits$adduct <- adduct
bits$tag <- tag
res<-dtable(rt=numeric(bigN),
intensity=numeric(bigN),
tag=tag,
adduct=bits[,rep(adduct,N)],
ID=bits[,rep(ID,N)],
idx=bits[,rep(idx,N)])
data.table::setkey(res,idx)
names(eic)<-bits$idx
res[,c("rt","intensity") :=
.(MSnbase::rtime(eic[[idx]])/60.,
MSnbase::intensity(eic[[idx]])),
by=idx]
data.table::setkeyv(res,BASE_KEY)
res
}
ms1 <- read_ms1()
ms2 <- read_ms2()
res_ms1 <- extr_ms1_eic(ms1)
res_ms2 <- extr_ms2(ms1=ms1,
ms2=ms2,
ids=id,
mz=mz,
adduct=adduct,
err_coarse_fun=err_coarse_fun,
err_fine_fun=err_fine_fun)
res_ms2[,"tag":=tag]
res <- list(ms1=res_ms1,
ms2=res_ms2)
res
}
gen_ms2_spec_blk <- function(spectra) {
dt <- dtable(mz=MSnbase::mz(spectra),
intensity=MSnbase::intensity(spectra),
rt = lapply(MSnbase::rtime(spectra),function (z) z/60.),
CE = MSnbase::collisionEnergy(spectra),
an = MSnbase::acquisitionNum(spectra))
dt[,maspI:=sapply(intensity,function (zz) max(zz))]
data.table::rbindlist(apply(dt,1,function(row) dtable(intensity=row[["intensity"]],
rt = row[["rt"]],
mz = row[["mz"]],
CE = row[["CE"]],
an = row[["an"]])))
}
This diff is collapsed.
......@@ -14,28 +14,52 @@
## Config defaults
CONF <- list(data=NA_character_,
project=getwd(),
compounds=list(lists=list(),
sets=NA_character_))
## Constants
FN_FTAB_BASE<-"ftable.base.csv"
FN_FTAB_PP<-"ftable.pp.csv"
FN_SUMM_BASE<-"summ.base.csv"
FN_SUMM_PP<-"summ.pp.csv"
FN_PP_OUT_PREF<-"PP.filetable"
FN_FTAB_STATE<-"ftable_state.csv"
FN_FTAB_DEF_OUT<-"ftable.csv"
FN_SUMM_STATE<-"summ_state.csv"
FN_SUMM <- "summ.csv"
FN_SUMM_DEF_OUT <- FN_SUMM
FN_CMP_L<-"compounds.csv"
FN_LOC_SETID <-"setid.csv"
FN_COMP_TAB<-"comprehensive.csv"
FN_SPEC<-"specdata.rds"
MODEMAP<-list(pH="MpHp_mass",
mH="MmHm_mass",
pNH4="MpNH4_mass",
pNa="MpNa_mass")
TAG_DEF <- "unspecified"
FN_CONF <- "conf-state.yaml"
FN_EXTR_STATE <- "state_after_extraction.rds"
.envp <- new.env(parent = emptyenv())
data(adducts,package = "enviPat", envir = .envp)
data(isotopes,package = "enviPat", envir = .envp)
ADDUCTS <- dtable(.envp$adducts)
ISOTOPES <- dtable(.envp$isotopes)
.envp <- NULL
ADDUCTMAP <- ADDUCTS$Name
ADDUCTS$Name <- the_ifelse(ADDUCTS$Charge>0,paste0("[",ADDUCTS$Name,"]+"),paste0("[",ADDUCTS$Name,"]-"))
## names(ADDUCTMAP) <- apply(ADDUCTS,1,function(row) {
## nm <- row[["Name"]]
## sgn <- row[["Charge"]]
## suff <- if (sgn > 0) "+" else if (sgn < 0) "-" else ""
## paste0("[",nm,"]",suff)
## })
## ADDUCTS$Name <- names(ADDUCTMAP)
DISP_ADDUCTS <- ADDUCTS$Name
TAG_NA <- "::UNSET::"
SET_NA <- "::UNSET::"
TAG_DEF <- TAG_NA
TAG_DEF_DESC<-"Case"
DEFAULT_RT_RANGE=c(NA,NA)
DEFAULT_INT_RANGE=c(NA,NA)
DEFAULT_MZ_RANGE=c(NA,NA)
QANAMES <- c("MS1","MS2","Alignment","AboveNoise")
## QANAMES <- c("MS1","MS2","Alignment","AboveNoise")
PLOT_DEF_TAGS<-NA
PLOT_DEF_SET<-NA
......@@ -44,11 +68,6 @@ RT_DIGITS=2
M_DIGITS=4
PAL="Dark2"
REST_TXT_INP<-c("fnKnownL",
"fnUnkL",
"fnSetId",
"tagsInp")
REST_TAB<-c("mzml")
......@@ -76,11 +95,11 @@ EXTR_MS2_DIR<-"MS2"
EXTR_MS2_FLAG<-file.path(EXTR_MS2_DIR,'.ms2.DONE')
FTAB_CHK_NONE<-'NONE'
SUMM_CHK_NONE<-'NONE'
FTAB_CHK_AUTO<-'AUTO'
SUMM_CHK_AUTO<-'AUTO'
FTAB_CHK_MANL<-'MANUAL'
SUMM_CHK_MANL<-'MANUAL'
MS1_ERR_COARSE<-0.5 # Da
......@@ -97,4 +116,161 @@ MS1_SN_FAC <- 3.0
## Shiny objects
NUM_INP_WIDTH="15%"
NUM_INP_WIDTH=40
NUM_INP_HEIGHT="5%"
## Possible compound list fields
EMPTY_CMPD_LIST <- dtable(ID=character(),
SMILES=character(),
Name=character(),
Formula=character(),
RT=numeric(),
mz=numeric(),
known=character(),
ORIG=character())
COMP_LIST_COLS <- c("ID","Name","SMILES","Formula","RT","mz")
## Comprehensive table properties
COMP_NAME_MAP <- list(RT="rt")
COMP_NAME_FIRST <- c("ID","mz","rt","adduct","tag","set","Name","known","SMILES","Formula","file")
## Trivial data table
EMPTY_MZML <- dtable(file=character(0),
tag=character(0),
adduct=character(0),
set=character(0))
FN_DATA_TAB <- "data-files.csv"
## Default number of concurrent workers
NO_WORKERS <- 2
## Input parameters for prescreening.
CONF_PRES_NUM <- c("ms1_int_thresh","ms2_int_thresh","s2n")
CONF_PRES_TU <- c("ret_time_shift_tol")
## Prescreening columns
QA_FLAGS <- c("qa_pass",
"qa_ms1_exists",
"qa_ms2_exists",
"qa_ms1_good_int",
"qa_ms1_above_noise",
"qa_ms2_near",
"qa_ms2_good_int")
QA_NUM_REAL <- c("ms1_int","ms1_rt","ms1_mean")
QA_NUM_INT <- c("ms2_sel","ms1_rt_ind")
QA_COLS <- c(QA_FLAGS,QA_NUM_REAL,QA_NUM_INT)
## MS2 spectral table columns
MS2_SPEC_COLS <- c("adduct","tag","ID","CE","rt","file","spec","ms2_max_int")
## MS1 spectral table columns
MS1_SPEC_COLS <- c("adduct","tag","ID","eicMS1","ms1_int","ms1_rt","ms1_mean")
## Default secondary indexing in the summary table
DEF_INDEX_SUMM <- c("set", "-qa_pass", "-ms1_int", "adduct","-mz")
## Top-level directory to store the figures
FIG_TOPDIR <- "figures"
## Figure filter
FIG_DEF_FILTER <- ""
FIG_DEF_SUBSET <- c("set","adduct","ID")
REPORT_AUTHOR <- "Anonymous"
REPORT_TITLE <- "Plots of EICs and MS2 Spectra"
## Select the most fundamental group of entries. Within this group,
## each ID is unique.
BASE_KEY <- c("adduct","tag","ID")
BASE_KEY_MS2 <- c(BASE_KEY,"CE")
FIG_DEF_CONF <-list(grouping=list(group="adduct",
plot="ID",
label="tag"))
## File table properties
SUMM_COLS=c("set",BASE_KEY_MS2,"an","mz","ms1_rt", "ms1_int", "ms2_rt", "ms2_int",
"ms1_mean","ms2_sel",QA_FLAGS,"Name", "SMILES", "Formula", "known","Comments","file")
PLOT_FEATURES <- c("adduct",
"tag",
"ID")
## Empty summary table.
EMPTY_SUMM <- data.table::data.table(set=character(0),
adduct=character(0),
tag=character(0),
ID=character(0),
CE=character(0),
an=integer(0),
mz=numeric(0),
ms1_rt=numeric(0),
ms1_int=numeric(0),
ms2_rt=numeric(0),
ms2_int=numeric(0),
ms1_mean=numeric(0),
ms2_sel=logical(0),
qa_pass=logical(0),
qa_ms1_exists=logical(0),
qa_ms2_exists=logical(0),
qa_ms1_good_int=logical(0),
qa_ms1_above_noise=logical(0),
qa_ms2_near=logical(0),
qa_ms2_good_int=logical(0),
Name=character(0),
SMILES=character(0),
Formula=character(0),
known=character(0),
Comments=character(0),
file=character(0))
## Default sorting keys of spectra in the summary table
DEF_KEY_SUMM <- c(BASE_KEY_MS2,"an")
SUBSET_VALS <- c(IGNORE="ignore",
GOOD="select good",
BAD="select bad")
## Empty plotting tables.
EMPTY_MS1_PLOT_TAB <- dtable(ID=character(),
SMILES=character(),
tag=character(),
fig_eic=list(),
fig_struct=list())
EMPTY_MS2_PLOT_TAB <- dtable(tag=character(),
ID=character(),
fig_eic=list(),
fig_spec=list(),
fig_leg=list())
## Empty comprehensive table.
EMPTY_COMP_TAB <- dtable(ID=character(),
mz=numeric(),
rt=numeric(),
adduct=character(),
tag=character(),
set=character(),
Name=character(),
known=character(),
SMILES=character(),
Formula=character(),
file=character())
## Copyright (C) 2020 by University of Luxembourg
## Licensed under the Apache License, Version 2.0 (the "License");
## you may not use this file except in compliance with the License.
## You may obtain a copy of the License at
## http://www.apache.org/licenses/LICENSE-2.0
## Unless required by applicable law or agreed to in writing, software
## distributed under the License is distributed on an "AS IS" BASIS,
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
## See the License for the specific language governing permissions and
## limitations under the License.
is_gen_done<-function(dest) {
fnFlag<-file.path(dest,".gen.DONE")
file.exists(fnFlag)
}
is_ms2_done<-function(set,dest) {
fnFlag<-file.path(dest,paste('.',set,'.DONE',sep=''))
file.exists(fnFlag)
}
set_ms2_done<-function(set,dest) {
fnFlag<-file.path(dest,paste('.',set,'.DONE',sep=''))
file.create(fnFlag)
}
set_gen_done<-function(dest) {
fnFlag<-file.path(dest,".gen.DONE")
file.create(fnFlag)
}
unset_gen_done<-function(dest) {
fnFlag<-file.path(dest,".gen.DONE")
if (is_gen_done(dest)) unlink(fnFlag,force=T)
}
##' Paste with no separator.
##'
##'
##' @title Paste With No Separator
##' @param ... Strings to paste together.
##' @return Pasted string.
##' @author Todor Kondić
attch<-function(...) paste(...,sep='')
##' Do the prescreening.
##'
##' @title Prescreening on bunch of files.
##' @param fTab File table with Files,ID,wd,Name and mz
##' columns. Column Files, as well as wd must have all rows
##' identical.
##' @param extr_fun Extraction function from the backend.
##' @param errEIC Absolute mz tolerance used to extract precursor EICs.
##' @param errFinePPM Tolerance given in PPM used to associate input
##' masses with what the instrument assigned as precutsors to MS2.
##' @param proc Amount of processors, or FALSE.
##' @param fnLog For parallel execution, dump messages there.
##' @return Nothing useful.
##' @author Todor Kondić
##' @export
gen<-function(fTab,
errEIC,
errFinePPM,
errCoarse,
errRT,
proc=F,fnLog='prescreen.log',extr_fun=extr_msnb_ht) {
message("*** Started to generate prescreen data ...")
unlink(fnLog)
fread<-function(fTab) {
extract(fTab=fTab,
extr_fun=extr_fun,
errEIC=errEIC,
errFinePPM=errFinePPM,
errRT=errRT,
errCoarse=errCoarse,
fnSpec=FN_SPEC)
return(T)
}
fns<-unique(fTab$Files)
fTabs<-lapply(fns,function(fn) fTab[fTab$Files==fn,])
if (proc>1) {
cl<-parallel::makeCluster(spec=proc,type='PSOCK',outfile=fnLog)
parallel::clusterEvalQ(cl,library(shinyscreen))
## parallel::clusterExport(cl,c("extract"),envir=environment())
res<-parallel::parLapply(cl,fTabs,fread)
parallel::stopCluster(cl)
res
} else {
lapply(fTabs,fread)
}
message("*** ... done generating prescreen data.")
}
## Copyright (C) 2020 by University of Luxembourg
## Licensed under the Apache License, Version 2.0 (the "License");
## you may not use this file except in compliance with the License.
## You may obtain a copy of the License at
## http://www.apache.org/licenses/LICENSE-2.0
## Unless required by applicable law or agreed to in writing, software
## distributed under the License is distributed on an "AS IS" BASIS,
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
## See the License for the specific language governing permissions and
## limitations under the License.
##' @importFrom shiny validate
react_v <- shiny::reactiveValues
react_f <- shiny::reactive
react_e <- shiny::eventReactive
obsrv <- shiny::observe
obsrv_e <- shiny::observeEvent
isol <- shiny::isolate
# volumes <- function() c(wd=getwd(), shinyFiles::getVolumes()())
validate1 <- function(expr,msg) shiny::validate(shiny::need(expr,msg))
path2vol <- function(path) {
## This function returns shinyFiles compatible volumes.
splits <- split_path(path)
file.path(tail(splits,1),'')
}
prim_box<-function(...) {shinydashboard::box(...,
status="primary",
solidHeader=T)}
good_box<-function(...) {shinydashboard::box(...,
status="success",
solidHeader=T)}
err_box<-function(...) {shinydashboard::box(...,
status="danger",
solidHeader=T)}
inact_box<-function(...) {shinydashboard::box(...,
status="danger",
solidHeader=T)}
html<-function(...) {shiny::tags$div(shiny::HTML(...))}
## num_input<-function(...,width=NUM_INP_WIDTH) {shiny::tags$div(id="inline",shiny::textInput(...,width=width))}
num_input <- function(inputId,label,...,width=NUM_INP_WIDTH) {
shiny::tags$div(style="display:inline-block",
shiny::tags$label(label, `for` = inputId),
shiny::tags$input(id = inputId, type = "text",style=paste("width:",width,sep = ""),...))
}
num_input_unit <- function(inputId,l1,l2,width=NUM_INP_WIDTH,...) {
shiny::tags$div(style="display:inline-block",
shiny::tags$label(l1, `for` = inputId),
shiny::tags$input(id = inputId, type = "text",style=paste("width:",width,sep = ""),...),
shiny::tags$label(paste(" ",l2,sep=""), `for` = inputId))
}
txt_file_input <- function(inputId,input,fileB,label,volumes,default = "") {
fnobj<-shinyFiles::parseFilePaths(roots = volumes,
selection = input[[fileB]])
fn <- fnobj[['datapath']]
if (isThingFile(fn)) {
shiny::textInput(inputId = inputId,
label = label,
value = fn)
} else {
shiny::isolate(currFn <- input[[inputId]])
if (!isThingFile(currFn)) {
shiny::textInput(inputId = inputId,
label = label,
value = default)
} else {
shiny::textInput(inputId = inputId,
label = label,
value = currFn)
}
}
}
##' @export
mz_input <- function(input_mz,input_unit,width=NUM_INP_WIDTH,height=NUM_INP_HEIGHT,def_mz=0,def_unit="Da",pref="+/-") {
style <- "display: inline-block; vertical-align:top; width: "
stylel <- "display: inline-block; vertical-align:top;"
style=paste0(style,width,"; ")
shiny::div(shiny::div(style=stylel,
shiny::tags$label(pref,`for`=input_mz)),
shiny::div(style=style,
shiny::numericInput(input_mz,
label=NULL,
value = def_mz)),
shiny::div(style=style,
shiny::selectInput(input_unit,
label=NULL,
c("ppm","Da"),
selected=def_unit)))
}
##' @export
rt_input <- function(input_rt,input_unit,width=NUM_INP_WIDTH,width_u=1-NUM_INP_WIDTH,height=NUM_INP_HEIGHT,def_rt=0,def_unit="min",pref="+/-") {
width=paste0(as.character(width), "%")
width_u=paste0(as.character(width_u), "%")
style="display: inline-block; vertical-align:top; width: "
style=paste0(style,width,"; ")
stylel <- "display: inline-block; vertical-align:top;"
styleu <- paste0("display: inline-block; vertical-align:top; color: black; width: ",width_u,";")
shiny::div(shiny::div(style=stylel,
shiny::tags$label(pref,`for`=input_rt)),
shiny::div(style=style,
shiny::numericInput(input_rt,
label=NULL,
value = def_rt)),
shiny::div(style=styleu,
shiny::selectInput(input_unit,
label=NULL,
c("min","s"),
selected=def_unit)))
}
##'@export
rev2list <- function(rv) {
## Take reactive values structure and convert them to nested
## lists.
if (class(rv)[[1]] != "reactivevalues")
rv else lapply(shiny::reactiveValuesToList(rv),rev2list)
}
##' @export
list2rev <- function(lst) {
## Take nested named list and create reactive values from it.
if (class(lst)[[1]] != "list")
lst else do.call(react_v,lapply(lst,list2rev))
}
mk_roots <- function(wd) local({
addons <- c("project"=normalizePath(wd,winslash = '/'))
def_vol <- function() {
path <- addons[['project']]
svols <- shinyFiles::getVolumes()()
vol <- path2vol(path)
sel <- match(vol,svols)
res <- names(svols)[[sel]]
res
}
list(set=function (rts) {addons <<- rts},
get=function () c(addons,shinyFiles::getVolumes()()),
def_vol=def_vol,
def_path=function() {
vol <- def_vol()
svols <- shinyFiles::getVolumes()()
pref <- svols[[vol]]
res <- sub(paste0(pref,'(.*)'),'\\1',addons[["project"]])
message('Relative path: ',res)
res
})
})
#' @export
merge2rev <- function(rev,lst) {
crawllist <- function(lst,currname=""){
cls <- class(lst)
if (cls[[1]]=="list" && length(names(lst)) > 0)
invisible(lapply(names(lst),
function (nm)
crawllist(lst[[nm]],
currname=paste0(currname,'[["',nm,'"]]'))))
else {
currname
}
}
vars <- unlist(crawllist(lst),recursive = T)
vars
pref_r <- deparse(substitute(rev))
pref_l <- deparse(substitute(lst))
lhs <- paste0(pref_r,vars)
rhs <- paste0(pref_l,vars)
exprs <- Map(function (a,b) call("<-",
parse(text=a)[[1]],
parse(text=b)[[1]]),
lhs,
rhs)
code <- quote({})
for (n in 1:length(exprs)) {
code[[n+1]] <- exprs[[n]]
}
code
}
......@@ -237,20 +237,20 @@
| 999 | mixC | |
*** Data Files
*** Data files
These should be in mzML format.
** Sets, Tags, Modes, Files and IDs
Each file is labelled by a tag, mode and set. Sets are defined in
** Sets, Tags, Adducts, Files and IDs
Each file is labelled by a tag, adduct and set. Sets are defined in
the compound set CSV file and group compounds according to their
IDs. Modes correspond to the adducts. Tags label files in the
IDs. Adducts correspond to the adducts. Tags label files in the
plots.
For known compounds, each set can contain multiple modes. Sets of
unknowns can only contain a single mode. Any files belonging to the
same set that have been acquired in a single mode, must carry
For known compounds, each set can contain multiple adducts. Sets of
unknowns can only contain a single adduct. Any files belonging to the
same set that have been acquired in a single adduct, must carry
unique tags.
In addition, the IDs of compounds belonging to the same set/mode
In addition, the IDs of compounds belonging to the same set/adduct
combination must be unique. Different ID sets may overlap.
Essentially, sets serve the purpouse of visually grouping files in
......@@ -260,7 +260,7 @@
** Config Screen
This is the start tab. Import the compound and set lists first,
then proceed to import the mzML files. Provide tags in the tag text
box and then assign the sets, modes and tags to the imported mzML
box and then assign the sets, adducts and tags to the imported mzML
files using table widget. Once this is done, move on to the
~Spectra Extraction~ tab.
......
This diff is collapsed.
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/mix.R
\name{RMB_EIC_prescreen_df}
\alias{RMB_EIC_prescreen_df}
\title{Prescreen}
\usage{
RMB_EIC_prescreen_df(wd, RMB_mode, FileList, cmpd_list,
ppm_limit_fine = 10, EIC_limit = 0.001)
}
\arguments{
\item{wd}{Absolute path to the directory that will contain the
resulting data frame.}
\item{RMB_mode}{...}
\item{FileList}{...}
\item{cmpd_list}{...}
\item{ppm_limit_fine}{...}
\item{EIC_limit}{...}
}
\description{
Prescreens. Writes data out. Adapted from ReSOLUTION
}
\author{
Emma Schymanski, Todor Kondić
}
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/run.R
\name{attch}
\alias{attch}
\title{Paste With No Separator}
\usage{
attch(...)
}
\arguments{
\item{...}{Strings to paste together.}
}
\value{
Pasted string.
}
\description{
Paste with no separator.
}
\author{
Todor Kondić
}
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/mix.R
\name{gen_cmpd_l}
\alias{gen_cmpd_l}
\title{Generate Compound List File}
\usage{
gen_cmpd_l(src_fn, dest_fn)
}
\arguments{
\item{src_fn}{The input compound list CSV filename.}
\item{dest_fn}{The resulting compound list CSV filename.}
}
\value{
Number of compounds.
}
\description{
Generate the RMassBank compound list from the input compound list
in CSV file src_fn. The input compound list format is either a
Chemical Dashboard csv file with, at least, PREFERRED_ SMILES
columns \emph{filled} out, or just an ordinary CSV file with columns
SMILES and Names filled. Argument dest_fn is the destination
filename. Returns the number of compounds.
}
\author{
Todor Kondić
}
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/mix.R
\name{gen_cmpdl_and_load}
\alias{gen_cmpdl_and_load}
\title{Generate and Load the RMassBank Compound List}
\usage{
gen_cmpdl_and_load(wd, fn_cmpdl)
}
\arguments{
\item{wd}{Directory under which results are archived.}
\item{fn_cmpdl}{The input compound list filename.}
}
\value{
Named list. The key \code{fn_cmpdl} is the path of the
generated compound list and the key \code{n} the number of
compounds.
}
\description{
Generates the RMassBank compound list and loads it.
}
\author{
Todor Kondić
}
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/mix.R
\name{gen_ftable}
\alias{gen_ftable}
\title{Generate and Load the RMassBank Settings File}
\usage{
gen_ftable(fn_data, wd, n_cmpd)
}
\arguments{
\item{fn_data}{The mzML filename.}
\item{wd}{Directory under which results are archived.}
\item{n_cmpd}{Number of compounds.}
}
\value{
File path of the file table.
}
\description{
Generates file table.
}
\author{
Todor Kondić
}
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/mix.R
\name{gen_stgs_and_load}
\alias{gen_stgs_and_load}
\title{Generate and Load the RMassBank Settings File}
\usage{
gen_stgs_and_load(stgs, wd)
}
\arguments{
\item{stgs}{Settings named list, or a settings filename.}
\item{wd}{Directory under which results are archived.}
}
\value{
result of RMassBank::loadRmbSettings
}
\description{
Generates settings file and loads it.
}
\author{
Todor Kondić
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment