BlastHitsFinished.txt
BioMartReport.txt
OligosNotFound.txt
BlastReport.txt
if(FALSE){
# if it should be executed outside RShell
blastresultfile <- "BlastReport.txt"
biomartfile <- "BioMartReport.txt"
Classes <- "classes.txt"
Report <- "report.txt"
BarPlot <- "barplot.pdf"
printDevice <- pdf
} else{
printDevice <- png
}
##MODIFY THESE PARAMETERS###########################################################
eval_threshold = 1e-12;
span_threshold = 57;
debug = 0;
####################################################################################
result.table <- c("oligo", "gene", "class")
#classes
#1~single hit approved
#2~mulithit single transcript single gene approved on span only
#3~mulithit single transcript single gene approved on e-value for single stretch, possibly intron spanning
#4~mulithit single transcript single gene approved on e-value for single stretch, no intron spanning
#5~multihit multiple transcripts single gene approved on span only
#6~multihit multiple transcripts single gene approved on e-value for single stretch, possibly intron spanning
#7~multihit multiple transcripts single gene approved on e-value for single stretch, no intron spanning
#8~hit discarded
#9~mulithit single transcript single gene discarded, no intron spanning
#10~mulithit multiple transcript single gene discarded, no intron spanning
#11~multi gene hit discarded
#12~no transcript found but minimum e-value below threshold
#13~no transcript found and discard on e-value above threshold
#14~single hit below the e-value threshold + hit below the e-value threshold on assembly without transcript
classchart <- rep(0,14)
names(classchart)<-c("class 1", "class 2","class 3","class 4","class 5","class 6","class 7","class 8","class 9","class 10","class 11","class 12","class 13","class 14")
nms<-c("1 - single hit within specs"
,"2 - mulithit single transcript single gene approved on span only"
,"3 - mulithit single transcript single gene approved on e-value, possibly intron spanning"
,"4 - mulithit single transcript single gene approved on e-value for single stretch, no intron spanning"
,"5 - multihit multiple transcripts single gene approved on span only"
,"6 - multihit multiple transcripts single gene approved on e-value for single stretch, possibly intron spanning"
,"7 - multihit multiple transcripts single gene approved on e-value for single stretch, no intron spanning"
,"8 - hit outside specs"
,"9 - mulithit single transcript outside specs"
,"10 - mulithit multiple transcript outside specs"
,"11 - multi gene hit"
,"12 - no transcript found but hit found within specs"
,"13 - no transcript found, hits outside specs"
,"14 - single hit below the e-value threshold + hit below the e-value threshold on assembly without transcript"
)
classeleven<-matrix(0,ncol=2,nrow=1)
#oligo.res[,1]: "blasthitidx"
#oligo.res[,2] "oligoid.x"
#oligo.res[,3] "contig"
#oligo.res[,4] "percid"
#oligo.res[,5] "stretch"
#oligo.res[,6] "mm"
#oligo.res[,7] "gap"
#oligo.res[,8] "qstart"
#oligo.res[,9] "qstop"
#oligo.res[,10] "dstart"
#oligo.res[,11] "dstop"
#oligo.res[,12] "eval"
#oligo.res[,13] "bitscore"
#oligo.res[,14] "index"
#oligo.res[,15] "oligoid.y"
#oligo.res[,16] "gene"
#oligo.res[,17] "transcript"
#oligo.res[,18] "startT"
#oligo.res[,19] "stopT"
##FUNCTIONS#########################################################################
intronspanfunc <- function(oligo.res) {
span <- 0;
intronspan <- 0;
approv <- 0;
#for intron spanning it is required that oligo hits target whithout overlap
d <- c(oligo.res[1,10]:oligo.res[1,11]);
# print(paste("d:",d))
# print(paste("oligo:",as.character(oligo.res[1,2])))
a <- oligo.res[1,]
if(dim(oligo.res)[1] >1){
for (ii in 2:length(oligo.res[,1])) {
if (length(intersect(c(oligo.res[ii,10]:oligo.res[ii,11]),d)) == 0) {
a<- rbind(a,oligo.res[ii,])
#print(paste("intersect:",intersect(c(oligo.res[ii,10]:oligo.res[ii,11]),d)))
d<- c(d,c(oligo.res[ii,10]:oligo.res[ii,11]))
}
}
}
a<- oligo.res[order(a[,8]),]
overlap <- 0
span <- a[1,9]-a[1,8] +1 ;
# print(paste("span binnen a: ", span))
# print(a)
for (ii in 1:length(a[,1])) {
# print(paste("A:",a[ii,8:11]))
if (ii > 1 ) {
overlap <- a[ii,8] - a[ii-1,9] -1 ;
if (overlap >= 0) { #to avoid negative overlaps
span <- span + a[ii,9] - a[ii,8] + 1 - overlap;}
#print(paste("span binnen a: ", span))
}
}
# print(paste("SPAN: ", span));
ret <-c(span);
ret;
}
getresfunc <- function(oligo.res) {
#function to determine if there exist hits with a mapping below eval_threshold and if exist non-mapping hits below eval_threshold
transcript_complies <- 0;
non_transcript_compliance <- 0;
for (ii in 1 : length(oligo.res[,1])){
if (!is.na(oligo.res[ii, 17]) & oligo.res[ii,12] < eval_threshold){
transcript_complies <- 1;
}
if (oligo.res[ii,12] < eval_threshold & is.na(oligo.res[ii, 17])) {
non_transcript_compliance <- 1;
}
}
ret <-c(transcript_complies,non_transcript_compliance)
ret;
}
##MAIN##############################################################################
start <- as.numeric(Sys.time());
blast_result <- read.csv(file = blastresultfile, header = TRUE, sep ="\t", row.names=NULL, col.names=c("oligoid","contig","percid","stretch", "mm","gap","qstart","qstop","dstart","dstop","eval","bitscore","blasthitidx", "index"));
biomart_result <- read.csv(file = biomartfile, header = TRUE, sep = "\t", row.names=NULL, col.names=c("oligoid","blasthitidx","gene","transcript","startT","stopT"))
no.of.lines <- length(blast_result[,1])
ens_result <- merge(blast_result, biomart_result, by="blasthitidx",all.x = TRUE)
write.table(ens_result, file="ens_result.txt", sep = "\t", row.names=F)
lev <- levels(ens_result[,2])
no.of.levels <- length(lev)
for (i in 1 : (no.of.levels ) ){
oligo.res = subset(ens_result,ens_result[,2]==lev[i])
x <- dim(oligo.res);
curr <- as.numeric(Sys.time());
print(paste("Subset no. ", i, "/" ,no.of.levels, "from", blastresultfile , "oligo:", lev[i], "#hits:" , x[1], "idx:", oligo.res[1,1], round(((start-curr)/60),0), " - gene: ", oligo.res[,16], " - transcr.: ", oligo.res[,17]," - eval: ", oligo.res[,12] ));
tot.res <- NULL;
NoH <- length(na.omit(oligo.res[,17]));
NoTf <- length(unique(na.omit(oligo.res[,17])));
NoG <- length(unique(as.vector(na.omit(oligo.res[,16]))));
if (NoTf == 0) {
if ( min(as.numeric(oligo.res[,12])) <= eval_threshold) {
class <- 12;
classchart[12] <- classchart[12]+1
result.table <- rbind(result.table, c(as.vector(oligo.res[1,2]),"NA", class));
if (debug) {print(paste("QUESTIONABLE ", oligo.res[1,2], " - NO TRANSCRIPT FOUND BUT HIT BELOW e-VALUE THRESHOLD"));}
}
if ( min(as.numeric(oligo.res[,12])) > eval_threshold) {
class <- 13;
classchart[13] <- classchart[13]+1
result.table <- rbind(result.table, c(as.vector(oligo.res[1,2]),"NA", class));
if (debug) {print(paste("DISCARD ", oligo.res[1,2], " - NO TRANSCRIPT FOUND AND HIT(S) ABOVE e-VALUE THRESHOLD"));}
}
}
if(NoTf > 0) {
levels(oligo.res) <- factor(as.character(oligo.res[,17])) #per transcript
if (debug) {print(paste ("RESULT FOR ",oligo.res[1,2]));}
#Multi Gene Class:
if (NoG >1) {
glev <- levels(factor(as.character(oligo.res[,16]))) #gene level
no.of.glev <- length(glev)
res <- getresfunc(oligo.res)
gene.w.approv.tr <- 0;
#look at all genes in this set:
#each can be multihit multi transcripts, second loop is by transcript level on gene level
# if (debug) {print (paste(no.of.trlev, " levels " , trlev));}
for (y in 1 : ( no.of.glev ) ){
rsl <- 0;
isp <-0;
ispanmt <- 0;
ntc <- res[2]
hitspan <-0
hiteval <-0
hitspaneval <-0
g.sub = subset(oligo.res,oligo.res[,16]==glev[y])
#look if there is any non-transcript hit below e-value threshold
gres <- getresfunc(g.sub)
ntc <- gres[2]
trlev <- levels(factor(as.character(g.sub[,17])))
no.of.trlev <- length(trlev)
for (yy in 1 : (no.of.trlev ) ){
tr.sub = subset(g.sub,g.sub[,17]==trlev[yy])
#print(paste("Dimension tr.sub:",dim(tr.sub)[1]))
span<-intronspanfunc(tr.sub);
if (span > span_threshold) {isp =1}
res.lev <- getresfunc(tr.sub)
if (res.lev[1] == 1) {rsl <- 1} # transcript complient
if (debug) {print(paste("span, isp and rsl: ", span," ",isp," ",rsl))}
# hitspaneval <- 1
# break
if (hitspan ==0 & isp ==1 ) {hitspan <-1}
if (hiteval == 0 & rsl == 1 ) {hiteval <- 1}
}
if (hitspan ==1 | hiteval == 1 ) {
gene.w.approv.tr <- gene.w.approv.tr +1
}
}
if (debug) {print(paste(gene.w.approv.tr, "MULTI GENE BELOW THRESHOLDS"))}
if(gene.w.approv.tr > 1 ) {
print(paste(gene.w.approv.tr, "MULTI GENE BELOW THRESHOLDS - II"))
if (debug) {print(paste("DISCARD " , oligo.res[1,2], " ", NoG, " GENES FOUND"));}
class <- 11;
classchart[11] <- classchart[11]+1
result.table <- rbind(result.table, c(as.vector(oligo.res[1,2]),"NA", class));
}
if ( gene.w.approv.tr == 0 & ntc ==1 ) {
class <- 12;
classchart[12] <- classchart[12]+1
result.table <- rbind(result.table, c(as.vector(oligo.res[1,2]),as.vector(oligo.res[1,16]), class));
if (debug) {print (paste("Q " , oligo.res[1,2], " MULTIHIT MULTIPLE TRANSCRIPT - Multiple GENEs: probe only approved on e-value of hit without a transcript annotation"))}
}
if ( gene.w.approv.tr == 0 & ntc == 0 ) {
class <- 8;
classchart[8] <- classchart[8]+1
result.table <- rbind(result.table, c(as.vector(oligo.res[1,2]),"NA", class));
if (debug) {print (paste("DISCARD " , oligo.res[1,2], " MULTIHIT MULTIPLE TRANSCRIPT - Multiple GENEs: hit below specs"))}
}
if ( gene.w.approv.tr == 1 & ntc == 0 ) {
class <- 3;
classchart[3] <- classchart[3]+1
result.table <- rbind(result.table, c(as.vector(oligo.res[1,2]),"NA", class));
if (debug) {print (paste("APPROVE " , oligo.res[1,2], " MULTIHIT MULTIPLE TRANSCRIPT - Multiple GENEs: one gene with approved transcript"))}
}
if ( gene.w.approv.tr == 1 & ntc ==1 ) {
class <- 14;
classchart[14] <- classchart[14]+1
result.table <- rbind(result.table, c(as.vector(oligo.res[1,2]),as.vector(oligo.res[1,16]), class));
if (debug) {print (paste("Q " , oligo.res[1,2], " MULTIHIT MULTIPLE TRANSCRIPT - Multiple GENEs: probe hits at least one annotated transcript but also has of hit without a transcript annotation"))}
}
}
#Single Hit Class:
if (debug) {print(paste("Number of Different Hits found " , NoH));}
if (NoH == 1 ) {
res <- getresfunc(oligo.res)
transcript_complies <- res[1]
non_transcript_compliance <- res[2]
if (transcript_complies == 1 & non_transcript_compliance == 0) {
class <- 1;
classchart[1] <- classchart[1]+1
result.table <- rbind(result.table, c(as.vector(oligo.res[1,2]),as.vector(oligo.res[1,16]), class));
if (debug) {print(paste("APPROVE ", oligo.res[1,2], " - single hit below the e-value threshold", as.vector(oligo.res[1,16]), as.vector(oligo.res[1,17])));}
}
if (transcript_complies == 1 & non_transcript_compliance == 1) {
class <- 14;
classchart[14] <- classchart[14]+1
result.table <- rbind(result.table, c(as.vector(oligo.res[1,2]),as.vector(oligo.res[1,16]), class));
if (debug) {print(paste("Q ", oligo.res[1,2], " - single hit below the e-value threshold + hit on assembly without transcript"));}
}
if (transcript_complies == 0 & non_transcript_compliance == 1) {
class <- 12;
classchart[12] <- classchart[12]+1
result.table <- rbind(result.table, c(as.vector(oligo.res[1,2]),"NA", class));
if (debug) {print(paste("QUESTIONABLE ", oligo.res[1,2], " - NO TRANSCRIPT BELOW e-VALUES THRESHOLD FOUND BUT HIT BELOW e-VALUE THRESHOLD"));}
}
if (transcript_complies == 0 & non_transcript_compliance == 0) {
class <- 8;
classchart[8] <- classchart[8]+1
result.table <- rbind(result.table, c(as.vector(oligo.res[1,2]),as.vector(oligo.res[1,16]), class));
}
}
#Multiple hit, single transcript class
isp <- 0;
approv <- 0;
if (NoTf == 1 & NoH > 1 & NoG <= 1){
if (debug) {print ("MULTIHIT SINGLE TRANSCRIPT - SINGLE GENE");}
span <- intronspanfunc(oligo.res);
if (span > span_threshold) {isp =1}
res <- getresfunc(oligo.res)
transcript_complies <- res[1]
non_transcript_compliance <- res[2]
if ( isp ==1 & transcript_complies ==0 & non_transcript_compliance ==0) {
class <- 2;
classchart[2] <- classchart[2]+1
result.table <- rbind(result.table, c(as.vector(oligo.res[1,2]),as.vector(oligo.res[1,16]), class));
if (debug) {print (paste("APPROVE " , oligo.res[1,2], " MULTIHIT SINGLE TRANSCRIPT - SINGLE GENE: ON SPAN (POSSIBLY INTRON SPANNING) probe could not be approved on single e-value"))}
}
if ( isp == 1 & transcript_complies ==1 & non_transcript_compliance ==0 ) {
class <- 3;
classchart[3] <- classchart[3]+1
result.table <- rbind(result.table, c(as.vector(oligo.res[1,2]),as.vector(oligo.res[1,16]), class));
if (debug) {print (paste("APPROVE " , oligo.res[1,2], " MULTIHIT SINGLE TRANSCRIPT - SINGLE GENE: ON SINGLE e-VALUE - POSSIBLY INTRON SPANNING"));}
}
if ( isp == 0 & transcript_complies ==1 & non_transcript_compliance ==0 ) {
class <- 4;
classchart[4] <- classchart[4]+1
result.table <- rbind(result.table, c(as.vector(oligo.res[1,2]),as.vector(oligo.res[1,16]), class));
if (debug) {print (paste("APPROVE " , oligo.res[1,2], " MULTIHIT SINGLE TRANSCRIPT - SINGLE GENE: no intron spanning, single e-value below threshold"))}
}
if ( transcript_complies ==1 & non_transcript_compliance ==1 ) {
class <- 14;
classchart[14] <- classchart[14]+1
result.table <- rbind(result.table, c(as.vector(oligo.res[1,2]),as.vector(oligo.res[1,16]), class));
if (debug) {print (paste("APPROVE " , oligo.res[1,2], " MULTIHIT SINGLE TRANSCRIPT - SINGLE GENE: ON SINGLE e-VALUE - POSSIBLY INTRON SPANNING + hit on assembly without transcript"));}
}
if ( transcript_complies ==0 & non_transcript_compliance ==1 ) {
class <- 12;
classchart[12] <- classchart[12]+1
result.table <- rbind(result.table, c(as.vector(oligo.res[1,2]),as.vector(oligo.res[1,16]), class));
if (debug) {print (paste("APPROVE " , oligo.res[1,2], " MULTIHIT SINGLE TRANSCRIPT - SINGLE GENE: ON SINGLE e-VALUE hit on assembly without transcript"));}
}
if ( isp ==0 & transcript_complies ==0 & non_transcript_compliance ==0) {
class <- 9;
classchart[9] <- classchart[9]+1
result.table <- rbind(result.table, c(as.vector(oligo.res[1,2]),as.vector(oligo.res[1,16]), class));
if (debug) {print (paste("DISCARD " , oligo.res[1,2], " MULTIHIT SINGLE TRANSCRIPT - SINGLE GENE: NO INTRON SPANNING AND NO SINGLE e-VALUE BELOW THRESHOLD"))}
}
}
#Multiple hit, multiple transcript class
if (NoTf > 1 & NoH > 1 & NoG <= 1){
if (debug) {print ("MULTIHIT MULTIPLE TRANSCRIPTS - SINGLE GENE");}
trlev <- levels(factor(as.character(oligo.res[,17])))
no.of.trlev <- length(trlev)
rsl <- 0;
ispanmt <- 0;
#look if there is any non-transcript hit below e-value threshold
res <- getresfunc(oligo.res)
transcript_complies <- res[1]
ntc <- res[2]
hitspan <-0 # 1 if any of the transcript hit classes has span above span_threshold
hiteval <-0 # 1 if any of the transcript hit classes has eval below eval_threshold
hitspaneval <-0 # 1 if any of the transcript hit classes has span above span_threshold and eval below eval_threshold
if (debug) {print (paste(no.of.trlev, " levels " , trlev));}
for (y in 1 : (no.of.trlev ) ){
tr.sub = subset(oligo.res,oligo.res[,17]==trlev[y])
print ("SUBLEVEL:");
print(tr.sub);
print(paste("Dimension tr.sub:",dim(tr.sub)))
span<-intronspanfunc(tr.sub);
if (span > span_threshold) {isp =1}
res.lev <- getresfunc(tr.sub)
if (res.lev[1] == 1) {
rsl <- 1
if (debug) {print(paste("span, isp and approv: ", span," ",isp," ",rsl))}
#if there is any hit in this transcript class below e-value threshold, stop the loop
if (isp == 1) {
hitspaneval <- 1
break
}
}
if (hitspan ==0 & isp ==1 ) {hitspan <-1}
if (hiteval == 0 & rsl == 1 ) {hiteval <- 1}
}
if ( hitspan == 1 & hiteval == 0 & hitspaneval == 0 & ntc ==0 ) {
class <- 5;
classchart[5] <- classchart[5]+1
result.table <- rbind(result.table, c(as.vector(oligo.res[1,2]),as.vector(oligo.res[1,16]), class));
if (debug) {print (paste("APPROVE " , oligo.res[1,2], " MULTIHIT MULTIPLE TRANSCRIPT - SINGLE GENE: ON SPAN (POSSIBLY INTRON SPANNING) probe could not be approved on single e-value"))}
}
if ( hitspaneval == 1 & ntc ==0 ) {
class <- 6;
classchart[6] <- classchart[6]+1
result.table <- rbind(result.table, c(as.vector(oligo.res[1,2]),as.vector(oligo.res[1,16]), class));
if (debug) {print (paste("APPROVE " , oligo.res[1,2], " MULTIHIT MULTIPLE TRANSCRIPT - SINGLE GENE: INTRON SPANNING + probe approved on e-value"))}
}
if ( hitspan == 0 & hiteval == 1 & hitspaneval == 0 & ntc ==0 ) {
class <- 7;
classchart[7] <- classchart[7]+1
result.table <- rbind(result.table, c(as.vector(oligo.res[1,2]),as.vector(oligo.res[1,16]), class));
if (debug) {print (paste("APPROVE " , oligo.res[1,2], " MULTIHIT MULTIPLE TRANSCRIPT - SINGLE GENE: POSSIBLY INTRON SPANNING but probe only approved on e-value"))}
}
if ( hitspan == 0 & hiteval == 0 & hitspaneval == 0 & ntc ==1 ) {
class <- 12;
classchart[12] <- classchart[12]+1
result.table <- rbind(result.table, c(as.vector(oligo.res[1,2]),as.vector(oligo.res[1,16]), class));
if (debug) {print (paste("Q " , oligo.res[1,2], " MULTIHIT MULTIPLE TRANSCRIPT - SINGLE GENE: probe only approved on e-value of hit without a transcript annotation"))}
}
if ( (hitspan == 1 | hiteval == 1 | hitspaneval == 1 ) & ntc ==1 ) {
class <- 14;
classchart[14] <- classchart[14]+1
result.table <- rbind(result.table, c(as.vector(oligo.res[1,2]),as.vector(oligo.res[1,16]), class));
if (debug) {print (paste("Q " , oligo.res[1,2], " MULTIHIT MULTIPLE TRANSCRIPT - SINGLE GENE: probe hits at least one annotated transcript but also has of hit without a transcript annotation"))}
}
if ( hitspan == 0 & hiteval == 0 & hitspaneval == 0 & ntc == 0 ) {
class <- 10;
classchart[10] <- classchart[10]+1
result.table <- rbind(result.table, c(as.vector(oligo.res[1,2]),as.vector(oligo.res[1,16]), class));
if (debug) {print (paste("DISCARD " , oligo.res[1,2], " MULTIHIT MULTIPLE TRANSCRIPT - SINGLE GENE: probe hits not below thresholds"))}
}
}
}
print(paste("CLASS is: " ,class));
#print(paste("Number of genes: ",length(unique(as.vector(oligo.res[,14])))));
if (debug) {print("++++++++++++++++++++++++++++++++++++++++++++++++++++++++");}
}
write.table(result.table, file = Report, sep = "\t", row.names = FALSE, col.names = FALSE)
classchartTable <- cbind(as.data.frame(classchart), round(100*classchart/sum(classchart), digits=1))
write.table(classchartTable, file = Classes, sep = "\t", col.names = FALSE)
if(!exists("oligosnotfound")){
oligosnotfound <- c()
}
##Visualizations:
classchart_rel = c(length(oligosnotfound), as.vector(classchart)[1:14])
classchart_rel = 100*classchart_rel/sum(classchart_rel)
printDevice(BarPlot)
barplot(classchart_rel, names=c(1:length(classchart_rel))-1,
main="Relative distribution of probes among the classes",
xlab="Classes",
ylab="% of probes", col=rainbow(length(classchart_rel)))
dev.off()
print(paste("This run took " , round(((as.numeric(Sys.time()) - start)/60),0), " minutes"));
####################################################################################
oligosNotFound
blastresultfile
biomartfile
BarPlot
Classes
Report
net.sourceforge.taverna.scuflworkers.io.TextFileReader
Processor to add content to a (existing) file. The content is added to the end of the file.
The inputs:
Filename: the file name of a file, if the file does not exists, a new file is added
Content: the string to append
NewLine [default = true]: if true, a newline is added to the end of the line (useful if you want to add a record each time)
OligoId Contig Perc ID Stretch Kw1 Kw2 Qstart Qstop Dstart Dstop E-value Score BlastHitNr Index
import java.util.concurrent.Semaphore;
if(!Boolean.parseBoolean(Restart) && new File(Filename).exists()){
return;
}
if(bsh.shared.appendFileSemaphore == void){
bsh.shared.appendFileSemaphore = new Semaphore(1);
}
PrintStream stream;
try{
bsh.shared.appendFileSemaphore.acquire();
stream = new PrintStream(new FileOutputStream(Filename, false));
if(NewLine == void){
NewLine = "true";
}
if(Boolean.parseBoolean(NewLine)){
stream.println(Content);
} else{
stream.print(Content);
}
} finally{
if(stream != void){
stream.close();
}
bsh.shared.appendFileSemaphore.release();
}
Filename
Content
NewLine
Restart
import java.util.concurrent.Semaphore;
if(bsh.shared.appendFileSemaphore == void){
bsh.shared.appendFileSemaphore = new Semaphore(1);
}
net.sourceforge.taverna.scuflworkers.io.TextFileReader
250
Processor to add content to a (existing) file. The content is added to the end of the file.
The inputs:
Filename: the file name of a file, if the file does not exists, a new file is added
Content: the string to append
NewLine [default = true]: if true, a newline is added to the end of the line (useful if you want to add a record each time)
OligoId Index BlastHitNr GenId TranscriptId TranscriptStart TranscriptEnd
import java.util.concurrent.Semaphore;
if(!Boolean.parseBoolean(Restart) && new File(Filename).exists()){
return;
}
if(bsh.shared.appendFileSemaphore == void){
bsh.shared.appendFileSemaphore = new Semaphore(1);
}
PrintStream stream;
try{
bsh.shared.appendFileSemaphore.acquire();
stream = new PrintStream(new FileOutputStream(Filename, false));
if(NewLine == void){
NewLine = "true";
}
if(Boolean.parseBoolean(NewLine)){
stream.println(Content);
} else{
stream.print(Content);
}
} finally{
if(stream != void){
stream.close();
}
bsh.shared.appendFileSemaphore.release();
}
Filename
Content
NewLine
Restart
7
int size = Integer.parseInt(chunkSize);
List chunks = new ArrayList();
for(int index=0; index < sequences.size(); index += size){
Iterator iterator = sequences.subList(index, Math.min(sequences.size(), index+size)).iterator();
StringBuffer stringBuffer = new StringBuffer();
while(iterator.hasNext()){
stringBuffer.append(iterator.next()).append("\n");
}
chunks.add(stringBuffer.toString());
}
sequences
chunkSize
chunks
false
import java.util.concurrent.Semaphore;
if(!Boolean.parseBoolean(Restart) && new File(Filename).exists()){
return;
}
if(bsh.shared.appendFileSemaphore == void){
bsh.shared.appendFileSemaphore = new Semaphore(1);
}
PrintStream stream;
try{
bsh.shared.appendFileSemaphore.acquire();
stream = new PrintStream(new FileOutputStream(Filename, false));
if(NewLine == void){
NewLine = "true";
}
if(Boolean.parseBoolean(NewLine)){
stream.println(Content);
} else{
stream.print(Content);
}
} finally{
if(stream != void){
stream.close();
}
bsh.shared.appendFileSemaphore.release();
}
Filename
Content
NewLine
Restart
import java.io.BufferedReader;
import java.io.StringReader;
Map indexMap = new HashMap();
BufferedReader fileReader = new BufferedReader(new InputStreamReader(new FileInputStream(filename)));
fileReader.readLine();
while((lineInFile = fileReader.readLine()) != null){
String index = lineInFile.trim();
if(index.length() <= 0){
continue;
}
indexMap.put(index, new Integer(1));
}
fileReader.close();
BufferedReader reader = new BufferedReader(new StringReader(BlastReport));
Records = new ArrayList();
String line;
// skip first line
reader.readLine();
while((line = reader.readLine()) != null){
String[] entries = line.split("\t");
if(entries.length <= 1){
continue;
}
String index = entries[entries.length-1];
if(!indexMap.containsKey(index)){
Records.add(line);
}
}
BlastReport
filename
Records
net.sourceforge.taverna.scuflworkers.io.TextFileReader
Processor to add content to a (existing) file. The content is added to the end of the file.
The inputs:
Filename: the file name of a file, if the file does not exists, a new file is added
Content: the string to append
NewLine [default = true]: if true, a newline is added to the end of the line (useful if you want to add a record each time)
false
import java.util.concurrent.Semaphore;
if(bsh.shared.appendFileSemaphore == void){
bsh.shared.appendFileSemaphore = new Semaphore(1);
}
PrintStream stream;
try{
bsh.shared.appendFileSemaphore.acquire();
stream = new PrintStream(new FileOutputStream(Filename, false));
if(NewLine == void){
NewLine = "true";
}
if(Boolean.parseBoolean(NewLine)){
stream.println(Content);
} else{
stream.print(Content);
}
} finally{
if(stream != void){
stream.close();
}
bsh.shared.appendFileSemaphore.release();
}
Filename
Content
NewLine
import java.io.BufferedReader;
import java.io.StringReader;
Map idMap = new HashMap();
bsh.shared.blastReportIndex = 1;
BufferedReader fileReader = new BufferedReader(new InputStreamReader(new FileInputStream(filename)));
fileReader.readLine();
while((lineInFile = fileReader.readLine()) != null){
String[] fields = lineInFile.split("\t");
if(fields.length <= 1){
continue;
}
idMap.put(fields[0], new Integer(1));
bsh.shared.blastReportIndex = Math.max(bsh.shared.blastReportIndex, Integer.parseInt(fields[fields.length-1])+1);
}
fileReader.close();
BufferedReader reader = new BufferedReader(new StringReader(sequences));
StringBuffer sequencesToDoSB = new StringBuffer();
String line;
while((line = reader.readLine()) != null){
if(line.startsWith(">")){
String sequenceId = line.substring(1).trim();
if(!idMap.containsKey(sequenceId)){
sequencesToDoSB.append(line).append("\n")
.append(reader.readLine()).append("\n");
}
}
}
sequencesToDo = sequencesToDoSB.toString();
if(bsh.shared.blastReportIndex == void){
bsh.shared.blastReportIndex = 1;
}
sequences
filename
sequencesToDo
import java.io.BufferedReader;
import java.io.StringReader;
BufferedReader reader = new BufferedReader(new StringReader(sequenceText));
ArrayList sequences = new ArrayList();
String line;
while((line = reader.readLine()) != null){
if(line.trim().length() == 0){
continue;
}
if(line.startsWith(">")){
line += "\n" + reader.readLine();
}
sequences.add(line);
}
sequenceText
sequences
Processor to add content to a (existing) file. The content is added to the end of the file.
The inputs:
Filename: the file name of a file, if the file does not exists, a new file is added
Content: the string to append
NewLine [default = true]: if true, a newline is added to the end of the line (useful if you want to add a record each time)
import java.util.concurrent.Semaphore;
if(bsh.shared.appendFileSemaphore == void){
bsh.shared.appendFileSemaphore = new Semaphore(1);
}
PrintStream stream;
try{
bsh.shared.appendFileSemaphore.acquire();
stream = new PrintStream(new FileOutputStream(Filename, true));
if(NewLine == void){
NewLine = "true";
}
if(Boolean.parseBoolean(NewLine)){
stream.println(Content);
} else{
stream.print(Content);
}
} finally{
if(stream != void){
stream.close();
}
bsh.shared.appendFileSemaphore.release();
}
Filename
Content
NewLine
String[] elements = blastRecord.trim().split("\t");
oligoId = elements[0];
contig = elements[1];
dstart = Integer.parseInt(elements[8]);
dstop = Integer.parseInt(elements[9]);
blastIndex = elements[elements.length-1];
int strand;
if(dstart >= dstop){
strand = -1;
int tmp = dstart;
dstart = dstop;
dstop = tmp;
} else{
strand = 1;
}
chromosomeRegion = contig + ":" + dstart + ":" + dstop + ":" + strand;
blastRecord
oligoId
blastIndex
chromosomeRegion
dstart
dstop
FullRecord = new ArrayList();
for(String record : BioMartRecord){
FullRecord.add(OligoID + "\t" + BlastIndex + "\t" + record);
}
BioMartRecord
OligoID
BlastIndex
FullRecord
import java.util.concurrent.Semaphore;
if(bsh.shared.appendFileSemaphore == void){
bsh.shared.appendFileSemaphore = new Semaphore(1);
}
PrintStream stream;
try{
bsh.shared.appendFileSemaphore.acquire();
stream = new PrintStream(new FileOutputStream(Filename, true));
if(NewLine == void){
NewLine = "true";
}
if(Boolean.parseBoolean(NewLine)){
stream.println(Content);
} else{
stream.print(Content);
}
} finally{
if(stream != void){
stream.close();
}
bsh.shared.appendFileSemaphore.release();
}
Filename
Content
NewLine
org.embl.ebi.escience.scuflworkers.java.FlattenList
org.embl.ebi.escience.scuflworkers.java.FailIfFalse
record = new StringBuffer() .append(geneId).append("\t")
.append(transcriptId).append("\t")
.append(transcriptStart).append("\t")
.append(transcriptEnd).toString();
geneId
transcriptId
transcriptStart
transcriptEnd
record
org.embl.ebi.escience.scuflworkers.java.FailIfTrue
list = new ArrayList();
list
int dStart = Integer.parseInt(DStart);
int dStop = Integer.parseInt(DStop);
if(dStart > dStop){
int tmp = dStop;
dStop = dStart;
dStart = tmp;
}
eStart = Integer.parseInt(ExonStart);
eStop = Integer.parseInt(ExonStop);
boolean inExon;
if(eStart <= eStop){
inExon = eStart <= dStart && dStop <= eStop;
} else{
inExon = eStop <= dStart && dStop <= eStart;
}
isInExon = Boolean.toString(inExon);
DStart
DStop
ExonStart
ExonStop
isInExon
Completed
Fail_if_false
Create_BioMart_Record
Scheduled
Running
Completed
Fail_if_true
EmptyList
Scheduled
Running
Danio rerio genes (ZFISH7)
protein_coding
This workflow combines the blat and blast workflows. It takes as input a database name (Danio_rerio_Genome for Zebra Fish for example) and and a set of Fasta sequences. It first tries to perform a blat (at www.bioinformatics.nl). When this service returns nothing, a blast is done (also at www.bioinformatics.nl). The resulting reports are combined.
org.embl.ebi.escience.scuflworkers.java.FailIfFalse
isEmpty = new Boolean(string.length() == 0).toString();
string
isEmpty
org.embl.ebi.escience.scuflworkers.java.FailIfTrue
// create reader for sequence list
BufferedReader reader = new BufferedReader(new StringReader(Sequences));
// filter sequences
SequencesNotFound = new ArrayList();
String line;
while((line = reader.readLine()) != null){
if(line.startsWith(">")){
String sequenceId = line.substring(1).trim();
Iterator reportIterator = Report.iterator();
boolean found = false;
while(!found && reportIterator.hasNext()){
if(reportIterator.next().startsWith(sequenceId)){
found = true;
}
}
if(!found){
SequencesNotFound.add(sequenceId);
}
}
}
Report
Sequences
SequencesNotFound
// create reader for sequence list
BufferedReader reader = new BufferedReader(new StringReader(sequences));
StringBuffer blastSequences = new StringBuffer();
// filter sequences
String line;
while((line = reader.readLine()) != null){
if(line.startsWith(">")){
String sequenceId = line.substring(1).trim();
Iterator reportIterator = blatResult.iterator();
boolean found = false;
while(!found && reportIterator.hasNext()){
if(reportIterator.next().startsWith(sequenceId)){
found = true;
}
}
// if sequenceId is not in blat report, than it should be blasted
if(!found){
blastSequences.append(line).append("\n").append(reader.readLine()).append("\n");
}
}
}
sequencesForBlast = blastSequences.toString();
sequences
blatResult
sequencesForBlast
Processor to add content to a (existing) file. The content is added to the end of the file.
The inputs:
Filename: the file name of a file, if the file does not exists, a new file is added
Content: the string to append
NewLine [default = true]: if true, a newline is added to the end of the line (useful if you want to add a record each time)
import java.util.concurrent.Semaphore;
if(bsh.shared.appendFileSemaphore == void){
bsh.shared.appendFileSemaphore = new Semaphore(1);
}
PrintStream stream;
try{
bsh.shared.appendFileSemaphore.acquire();
stream = new PrintStream(new FileOutputStream(Filename, true));
if(NewLine == void){
NewLine = "true";
}
if(Boolean.parseBoolean(NewLine)){
stream.println(Content);
} else{
stream.print(Content);
}
} finally{
if(stream != void){
stream.close();
}
bsh.shared.appendFileSemaphore.release();
}
Filename
Content
NewLine
Processor to add content to a (existing) file. The content is added to the end of the file.
The inputs:
Filename: the file name of a file, if the file does not exists, a new file is added
Content: the string to append
NewLine [default = true]: if true, a newline is added to the end of the line (useful if you want to add a record each time)
import java.util.concurrent.Semaphore;
if(bsh.shared.appendFileSemaphore == void){
bsh.shared.appendFileSemaphore = new Semaphore(1);
}
PrintStream stream;
try{
bsh.shared.appendFileSemaphore.acquire();
stream = new PrintStream(new FileOutputStream(Filename, true));
if(NewLine == void){
NewLine = "true";
}
if(Boolean.parseBoolean(NewLine)){
stream.println(Content);
} else{
stream.print(Content);
}
} finally{
if(stream != void){
stream.close();
}
bsh.shared.appendFileSemaphore.release();
}
Filename
Content
NewLine
outputList = new ArrayList();
outputList.addAll(list1);
outputList.addAll(list2);
list1
list2
outputList
list = new ArrayList();
list
import java.util.concurrent.Semaphore;
if(bsh.shared.blastReportIndex == void){
bsh.shared.blastReportIndex = 1;
}
if(bsh.shared.addIndexSemaphore == void){
bsh.shared.addIndexSemaphore = new Semaphore(1);
}
try{
bsh.shared.addIndexSemaphore.acquire();
record_with_index = record + "\t" + bsh.shared.blastReportIndex++;
} finally{
bsh.shared.addIndexSemaphore.release();
}
record
record_with_index
This workflow invokes the blast service provided at www.bioinformatics.nl, written by Pieter Neerincx. The workflow takes as input a database name (Danio_rerio_Genome for Zebra Fish for example) and a set of sequences in fasta format.
The blast service is invoked (using polling) and the result is a tab separated blast report.
This workflow invokes the blast service provided at www.bioinformatics.nl, written by Pieter Neerincx. The workflow takes as input a database name (Danio_rerio_Genome for Zebra Fish for example) and a set of sequences in fasta format.
The blast service is invoked (using polling) and the result is a tab separated blast report.
This Beanshell downloads a file to disk. The standard download local Java widgets don't handle URLs with HTTP(S) Basic Authentication, but this Beanshell can. When a webserver uses BasicAuth, a login and password can be coded as part of the URL using the following syntax: http(s)://login:password@www.some.website/my/great/tool/result.xml. This beanshel extracts the login and password from the URL and supplies them automatically to the webserver. This prevents Taverna from showing popup dialogs requesting the login and password from the user as this will be problematic for large workflows.
Please note that the path where the downloaded file will be stored must be an absolute path to a folder ended with a slash. (Slash backward on Windows or a slash forward on Linux/Unix/Mac OS X.) The filename for the result is automatically extracted from the URL.
//
// Import modules;
//
import java.io.*;
import java.net.*;
import java.util.regex.*;
// Connect to URL.
URL oURL = new URL(theURL);
URLConnection oURLConnection = oURL.openConnection();
// Check if we are are dealing with a site
// that uses basic http(s) authentication.
oPattern = Pattern.compile("(\\w+://)??([^:]+):([^:@]+)@.*");
oMatcher = oPattern.matcher(oURL.toString());
vHit = oMatcher.matches();
if (vHit) {
//String vProtocol = oMatcher.group(1);
String vUser = oMatcher.group(2);
String vPass = oMatcher.group(3);
String vAuth = vUser + ":" + vPass;
String vEncodedUserPassword = new sun.misc.BASE64Encoder().encode(vAuth.getBytes());
oURLConnection.setRequestProperty ("Authorization", "Basic " + vEncodedUserPassword);
}
InputStream inputStream = oURLConnection.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
blastResults = new ArrayList();
String line;
while((line = reader.readLine()) != null){
blastResults.add(line);
}
reader.close();
theURL
blastResults
org.embl.ebi.escience.scuflworkers.java.StringListMerge
Processor to parse the datatype URL
http://moby.ucalgary.ca/moby/MOBY-Central.pl
URL
result
Processor to parse the datatype URL
A BLAST job.
http://moby.ucalgary.ca/moby/MOBY-Central.pl
BlastJob
//moby:Simple/*/@id
net.sourceforge.taverna.scuflworkers.xml.XPathTextWorker
org.embl.ebi.escience.scuflworkers.java.FailIfTrue
outputXML = inputXML.replace("<Object articleName=\"\"", "<Object articleName=\"job_id\"");
inputXML
outputXML
// if status is "r", than is running, "f" is finished
isRunning = new Boolean(status.equals("r")).toString();
status
isRunning
org.embl.ebi.escience.scuflworkers.java.StringListMerge
Processor to parse the datatype Object
http://moby.ucalgary.ca/moby/MOBY-Central.pl
Object
status
Processor to parse the datatype Object
Submit the result of the MobyBlast_submit service and obtain status info for the job.
http://moby.ucalgary.ca/moby/MOBY-Central.pl
MobyBlast_poll
www.bioinformatics.nl
an object
www.bioinformatics.nl
job_id
http://moby.ucalgary.ca/moby/MOBY-Central.pl
Object
a string
fasta
http://moby.ucalgary.ca/moby/MOBY-Central.pl
String
A generic user object.
www.bioinformatics.nl
client
user
http://moby.ucalgary.ca/moby/MOBY-Central.pl
User
Submit a BLAST Job and retrieve a Job ID. Use this Job ID with the MobyBlast_poll service from the same service provider to check the status of your job.Use this Job ID with the MobyBlast_retrieve service from the same service provider to fetch the results.
http://moby.ucalgary.ca/moby/MOBY-Central.pl
MobyBlast_submit
www.bioinformatics.nl
0
T
F
T
0
500
0.00015
0
1
-3
250
F
0
0
F
T
0
1
1
BLOSUM62
0
0
0
F
0
0
8
0
0
0
0
3
A generic program object.
blast
blastn
program
http://moby.ucalgary.ca/moby/MOBY-Central.pl
Program
An e-mail address object.
www.bioinformatics.nl
some.user@domain.nl
email
http://moby.ucalgary.ca/moby/MOBY-Central.pl
Email
A database object.
blast
database
http://moby.ucalgary.ca/moby/MOBY-Central.pl
DataBase
FASTA formatted sequence
1
http://moby.ucalgary.ca/moby/MOBY-Central.pl
FASTA
A generic password object.
www.bioinformatics.nl
testing
password
http://moby.ucalgary.ca/moby/MOBY-Central.pl
Password
Sequences in fasta format
Database name (Danio_rerio_Genome for Zebra Fish)
Completed
Poll_Job
DownloadURLWithBasicAuth
Scheduled
Running
The blat workflow invokes the blat services provided at www.bioinformatics.nl (author Pieter Neerincx).
As input, it takes a database name (for example, Danio_rerio_Genome for Zebra Fish) and one or more sequences in Fasta format. The output will be a tab separated output of the blat. An eValue string constant is added to filter on the e-Value.
Note, the e-Value is not exactly the same as the blast e-Value.
The blat workflow invokes the blat services provided at www.bioinformatics.nl (author Pieter Neerincx).
As input, it takes a database name (for example, Danio_rerio_Genome for Zebra Fish) and one or more sequences in Fasta format. The output will be a tab separated output of the blat. An eValue string constant is added to filter on the e-Value.
Note, the e-Value is not exactly the same as the blast e-Value.
This Beanshell downloads a file to disk. The standard download local Java widgets don't handle URLs with HTTP(S) Basic Authentication, but this Beanshell can. When a webserver uses BasicAuth, a login and password can be coded as part of the URL using the following syntax: http(s)://login:password@www.some.website/my/great/tool/result.xml. This beanshel extracts the login and password from the URL and supplies them automatically to the webserver. This prevents Taverna from showing popup dialogs requesting the login and password from the user as this will be problematic for large workflows.
Please note that the path where the downloaded file will be stored must be an absolute path to a folder ended with a slash. (Slash backward on Windows or a slash forward on Linux/Unix/Mac OS X.) The filename for the result is automatically extracted from the URL.
//
// Import modules;
//
import java.io.*;
import java.net.*;
import java.util.regex.*;
// Connect to URL.
URL oURL = new URL(URL);
URLConnection oURLConnection = oURL.openConnection();
// Check if we are are dealing with a site
// that uses basic http(s) authentication.
oPattern = Pattern.compile("(\\w+://)??([^:]+):([^:@]+)@.*");
oMatcher = oPattern.matcher(URL);
vHit = oMatcher.matches();
if (vHit) {
//String vProtocol = oMatcher.group(1);
String vUser = oMatcher.group(2);
String vPass = oMatcher.group(3);
String vAuth = vUser + ":" + vPass;
String vEncodedUserPassword = new sun.misc.BASE64Encoder().encode(vAuth.getBytes());
oURLConnection.setRequestProperty ("Authorization", "Basic " + vEncodedUserPassword);
}
// get input stream
InputStream inputStream = oURLConnection.getInputStream();
// download all results and filter
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
List blatResults = new ArrayList();
double ev = Double.parseDouble(eValue);
String line;
while((line = reader.readLine()) != null){
String[] values = line.split("\t");
double currentEValue = Double.parseDouble(values[values.length-2]);
if(currentEValue < ev){
blatResults.add(line);
}
}
reader.close();
URL
eValue
blatResults
0.00015
org.embl.ebi.escience.scuflworkers.java.StringListMerge
A generic password object.
www.bioinformatics.nl
testing
password
http://moby.ucalgary.ca/moby/MOBY-Central.pl
Password
A BLAT job.
http://moby.ucalgary.ca/moby/MOBY-Central.pl
BlatJob
Processor to parse the datatype URL
http://moby.ucalgary.ca/moby/MOBY-Central.pl
URL
result
Processor to parse the datatype URL
An e-mail address object.
www.bioinformatics.nl
some.user@domain.nl
email
http://moby.ucalgary.ca/moby/MOBY-Central.pl
Email
BioMOBY web service wrapper for the command line query tool 'BLAT'.
http://moby.ucalgary.ca/moby/MOBY-Central.pl
MobyBlat
www.bioinformatics.nl
blast8
dna
0
0
1000000
A generic user object.
www.bioinformatics.nl
client
user
http://moby.ucalgary.ca/moby/MOBY-Central.pl
User
A database object.
blat
dataBase
http://moby.ucalgary.ca/moby/MOBY-Central.pl
DataBase
a string
fasta
http://moby.ucalgary.ca/moby/MOBY-Central.pl
String
FASTA formatted sequence
1
http://moby.ucalgary.ca/moby/MOBY-Central.pl
FASTA
Database name (Danio_rerio_Genome for Zebra Fish)
Sequences in fasta format
The name of the database (Danio_rerio_Genome for Zebra Fish)
Fasta sequences
Completed
Fail_if_true
Blast
Scheduled
Running
Completed
Fail_if_false
EmptyList
Scheduled
Running
Database name (for example Danio_rerio_Genome)
Sequences in fasta format, for example
>ENSDART00000061775
TTGTTTCCTCATCAACACAGCAGATCGAATCATTCGAGTTTACGACGGTCGAGAGATCCT
>ENSDART00000100022
TGCTGTTCAGTGGTTATGTTGTTGTTTGAATAAATGTTAAGAGCCAGTGGATGGCACAAA
>OTTDART00000006800
ATCTCTTAGCACTCTGCTGACTCACAACTTCTTCAGAAATGACTTTTTGGATATCATGAA
>OTTDART00000002447
AAGACTGTACGACAAGACAGTGCAAATGGCACCATAGTAAATTCAACCGCTCACCAGGAA
>ENSDART00000047499
CTCTATGACGTATATTGCTATGTGGAGAACATTCATGGGGAGGTTTTTCATGGCTCAACC
>ENSDART00000093312
CAGAGGGTTGCAACCTCTTCATCTATCATCTACCACAAGAGTTTGGTGACAATGAGCTTA
>OTTDART00000002445
AATGTTGCTGGTATCAGTGACCCCTTTCTGCAGGTGCGCATTCTTAGATTGCTAAGGATT
>ENSDART00000093311
CGGGCCTTTCTGGAGAAACGCAAACCTGTGTGGAGCAACACAGACGACTGCATTCACTGA
>ENSDART00000085701
AGAATGACAATGACTGTGGAGCTTTTGTTTTGGAGTACTGTAAGTGCCTGGCCTTCATGA
>OTTDART00000002443
AAACCATCACGCTTTAATTAGTTTCCCCTGTTAACCATTGTCCCACAAGTCTTATGTGGA
>OTTDART00000002442
CTGAAAGGCACTTGAGTTAATCAAATCCGCTTCTATGTAAGTGTTTTGTAAGAGCAGGCT
Whether the workflow should start from scratch.
If false, the workflow will continue. This is useful if a crash has occured
in Taverna (and it does sometimes when the data set is large)
The blast hits
The biomart genes and transcripts
The sequences not found by blast and blat
A bar plot of the oligos per class
The classes, same as bar plot
The total R report
Completed
Create_Header_BlastReport
BlatOrBlast
Scheduled
Running
Completed
BlatOrBlast
Read_BlastReport
Scheduled
Running
Completed
BlatOrBlast
Read_OligosNotFound
Scheduled
Running
Completed
DoBioMart
Read_BioMartReport
Scheduled
Running
Completed
Create_Header_BioMartReport
DoBioMart
Scheduled
Running
Completed
Create_Header_BlastReport
Filter_Sequences_For_Blast
Scheduled
Running
Completed
Touch_OligosNotFound_File
BlatOrBlast
Scheduled
Running
Completed
Create_Semaphore
Create_Header_BlastReport
Scheduled
Running
Completed
Create_Semaphore
Touch_OligosNotFound_File
Scheduled
Running
Completed
Create_Semaphore
Create_Header_BioMartReport
Scheduled
Running
Completed
Create_Semaphore
Touch_BlastHitsFinished_File
Scheduled
Running