Commit 04601824 authored by Bertjan Broeksema's avatar Bertjan Broeksema

Remove all files from gh-pages branch to add documentation

parent f9ef00c0
^.*\.Rproj$
^\.Rproj\.user$
^.*\.Rproj$
^\.Rproj\.user$
.Rproj.user
.Rhistory
.RData
*.swp
data.raw/*
data/*
.idea/*
inst/www/node_modules
cstr.db
/rScratch
Package: ICoVeR
Type: Package
Title: An application for interactive binning of contigs and bin refinement
Version: 0.1.0
Date: 2015-06-11
Author: Bertjan Broeksema <research@broeksemaatjes.nl>
Maintainer: Bertjan Broeksema <research@broeksemaatjes.nl>
Description: An application for interactive binning of contigs and bin refinement.
License: GPLv3
LazyData: true
Depends: FactoMineR, RSQLite, Hmisc, ca
Version: 1.0
RestoreWorkspace: No
SaveWorkspace: No
AlwaysSaveHistory: Yes
EnableCodeIndexing: Yes
UseSpacesForTab: Yes
NumSpacesForTab: 2
Encoding: UTF-8
RnwWeave: Sweave
LaTeX: pdfLaTeX
AutoAppendNewline: Yes
StripTrailingWhitespace: Yes
BuildType: Package
PackageUseDevtools: Yes
PackageInstallArgs: --no-multiarch --with-keep.source
This diff is collapsed.
NPM := $(shell which npm)
JSLINT := $(shell which jslint)
SRC_DIR := inst/www
JS_MODULES := js js/controllers js/services js/templates
JS_SRC_DIR := $(addprefix $(SRC_DIR)/, $(JS_MODULES))
JS_SRC := $(foreach srcdir, $(JS_SRC_DIR), $(wildcard $(srcdir)/*.js))
# All must be the first target so that it is run automatically when you run make
# without a target specified.
all: init
npm:
ifdef NPM
@which npm > /dev/null
else
@echo "* Please install npm before continuing..."
@which npm > /dev/null
endif
jslint: npm
ifdef JSLINT
@which jslint > /dev/null
else
@echo "* Please install jslint before continuing..."
@echo " - e.g. try npm install jslint -g"
@which jslint > /dev/null
endif
.git/hooks/pre-commit: git-hooks/pre-commit
@echo " - pre-commit"
@cp git-hooks/pre-commit .git/hooks
@chmod +x .git/hooks/pre-commit
githooks: .git/hooks/pre-commit
init: jslint githooks
check: $(JS_SRC)
@jslint --edition=2014-07-08 $^
.PHONY: githooks init check
exportPattern("^data\\.[[:alpha:]]*")
exportPattern("^cluster\\.[[:alpha:]]*")
exportPattern("^dimred\\.[[:alpha:]]*")
exportPattern("^color\\.[[:alpha:]]*")
exportPattern("^db\\.[[:alpha:]]*")
export("app.init")
# ICoVeR - Interactive Contig-bin Verification and Refinement
#
# Copyright 2015 Luxembourg Institute of Science and technology. All rights reserved.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# cluster.kmeans(vars=c("M4", "M20", "M28", "M36", "M40", "M44", "M48"), identifier="kmeans_30_7", centers=30)
cluster.kmeans <- function(rows = c(), vars, identifier, centers = NA, iter.max=10) {
clusterData <- data.get(rows, vars)
clusterRows <- clusterData$row
clusterData$row <- NULL
if (is.na(centers)) centers <- floor(sqrt(nrow(clusterData)))
clusters <- as.factor(stats::kmeans(clusterData, centers, iter.max)$cluster)
clusters <- data.frame(row = clusterRows, cluster = clusters)
p.db.extend.schema(name = identifier, type = "factor", group = "Analytics",
group_type = "Clusterings")
p.db.add.column(column.name = identifier, type = "integer")
lapply(levels(clusters$cluster), function(level) {
level <- as.numeric(level)
rows <- clusters$row[clusters$cluster==level]
p.db.store(column.name = identifier, rows = rows, value = level)
})
}
cluster.correlation <- function(rows = c(), vars, identifier,
pearsonThreshold = 0.9, minClusterSize=2) {
# Get the data to cluster and keep track of row numbers.
clusterData <- data.get(rows, vars)
rownames(clusterData) <- clusterData$row
# Make sure that the row number is not included in the clustering process
clusterData$row <- NULL
Corrclusters <- as.data.frame(correlationCluster(clusterData))
Corrclusters$cluster <- as.factor(Corrclusters$cluster)
# Add a new column to the schema and the data table to store the new
# clustering variable into.
p.db.extend.schema(name = identifier, type = "factor", group = "Analytics",
group_type = "Clusterings")
p.db.add.column(column.name = identifier, type = "integer")
# Now, store the clustering levels for each row in the data base per level
lapply(levels(Corrclusters$cluster), function(level) {
rows <- Corrclusters$row[Corrclusters$cluster == level]
p.db.store(column.name = identifier, rows = rows, value = level)
})
TRUE
}
p.cluster.methods <- function() {
list("kmeans" = list(
"man" = "/ocpu/library/stats/man/kmeans/text",
"args" = list(
"identifier" = list("type" = "character", "required" = T),
"vars" = list("type"="schema.numeric", "required"=T),
"centers" = list("type"="numeric", "required"=F),
"iter.max" = list("type"="numeric", "required"=F, "default"=10),
"nstart" = list("type"="numeric", "required"=F, default=1),
"algorithm" = list("type"="character", "required"=F,
"values"=c("Hartigan-Wong", "Lloyd", "Forgy", "MacQueen"))
)
),
"correlation" = list(
"man" = "/ocpu/library/stats/man/kmeans/text",
"args" = list(
"identifier" = list("type" = "character", "required" = T),
"vars" = list("type"="schema.numeric", "required"=T),
"pearsonThreshold" = list("type"="numeric", "required"=F),
"minClusterSize" = list("type"="numeric", "required"=F, "default"=2)
)
)
)
}
# ICoVeR - Interactive Contig-bin Verification and Refinement
#
# Copyright 2015 Luxembourg Institute of Science and technology. All rights reserved.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
library(Hmisc)
# This function takes a row profile (abundance change over time) x and a pearson
# correlation coefficient (PCC) threshold, and returns a function that can be
# applied to the full data set in order to find other contigs that are within
# the given PCC threshold.
hasStrongCorrelation <- function(x, pearson) {
function (y) {
above <- Hmisc::rcorr(as.double(x), as.double(y))$r[1,2] > pearson
if (is.na(above)) {
above <- FALSE
}
above
}
}
# This function takes a contig data set X and returns a boolean vector, which
# contains TRUE for each contig is within the given pearsonThreshold.
withinDistance <- function(X, pearsonThreshold) {
test <- hasStrongCorrelation(X[1, ], pearsonThreshold)
apply(X, 1, test)
}
clusterProfiles <- function(X, pearsonThreshold = .9, minClusterSize = 2) {
clustered <- NULL
clusterId <- 1
repeat {
correlates <- withinDistance(X, pearsonThreshold)
nextcluster <- X[correlates, ]
if (sum(correlates) > minClusterSize) {
nextcluster$cacId <- rep(clusterId, nrow(nextcluster))
clusterId <- clusterId + 1
} else {
nextcluster$cacId <- rep(-1, nrow(nextcluster))
}
clustered <- rbind(clustered, nextcluster)
if (sum(!correlates) < nrow(X)) {
X <- X[!correlates,]
} else { # None of the remaining rows correlates with one another.
X$cacId <- rep(-1, nrow(X))
clustered <- rbind(clustered, X)
break
}
if (nrow(X) == 0) {
break # None remaining rows left
}
}
clustered
}
correlationCluster <- function(X, pearsonThreshold = .9, minClusterSize = 2) {
# First step, cluster profiles based on pearsonThreshold
clustered <- clusterProfiles(X, pearsonThreshold, minClusterSize)
# Deal with the case that no items where clustered together, because no two
# items had a correlatation >= pearsonThreshold
if (sum(clustered$cacId) == nrow(clustered) * -1) {
clustering <- cbind(as.integer(rownames(clustered)), -1)
colnames(clustering) <- c("row", "cluster")
return(clustering)
}
# Next step: merge clusters based on average profiles and PCC.
# For this we only look at the data that have a cluster ID != -1, because -1
# represents data with no strong correlations among each other.
repeat {
clusterMeans <- clustered[clustered$cacId != -1, ]
clusterMeans <- aggregate(clusterMeans, list(cacId = clusterMeans$cacId), mean)
clusterId <- 1
mergeCount <- 0 # Incremented when 2 or more clusters are merged
repeat {
correlates <- withinDistance(clusterMeans, .97) # .97 From Nielsen et al.
clusterIds <- clusterMeans[correlates, ]$cacId
#print(clusterIds)
# Reassign cluster ids
clustered[clustered$cacId %in% clusterIds, ]$cacId <- clusterId
clusterId <- clusterId + 1
if (length(clusterIds) > 1) {
mergeCount <- mergeCount + 1
}
clusterMeans <- clusterMeans[!correlates,]
if (nrow(clusterMeans) == 0) break
}
if (mergeCount == 0) break
}
clustering <- cbind(as.integer(rownames(clustered)), clustered$cacId)
colnames(clustering) <- c("row", "cluster")
clustering
}
# ICoVeR - Interactive Contig-bin Verification and Refinement
#
# Copyright 2015 Luxembourg Institute of Science and technology. All rights reserved.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
data.schema <- function(timestamp = Sys.time()) {
p.db.select(table="schema")
}
# data.get(rows = c(1,2,3,5,10), variables = c("gc_content"))
# data.get(variables = c("gc_content"))
data.get <- function(rows = c(), variables, addRows=T) {
if (addRows) variables <- c("row", variables)
data <- p.db.select(table="data", vars=variables, rows=rows)
factorVariables <- p.db.types(variables)
factorVariables <- factorVariables[factorVariables$type == "factor", c('name')]
Map(function(variable) {
data[variable] <<- as.factor(unlist(data[variable]))
}, factorVariables);
data
}
data.addTag <- function(timestamp, name, data) {
p.db.extend.schema(name = name, type = "boolean", group = "Tags", group_type = "Tags")
p.db.add.column(column.name = name, type = "integer")
p.db.store(column.name = name, rows = which(data==0), value = 0)
p.db.store(column.name = name, rows = which(data==1), value = 1)
}
data.removeTag <- function(timestamp, name) {
p.db.truncate.schema(name = name)
p.db.remove.column(column.name = name)
}
# ICoVeR - Interactive Contig-bin Verification and Refinement
#
# Copyright 2015 Luxembourg Institute of Science and technology. All rights reserved.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
p.dimred.methods <- function() {
list(
"pca" = list(
"restrict" = list("type"="schema.numeric", "group_type"="!Frequencies")
),
"ca" = list(
"restrict" = list("type"="schema.numeric", "group_type"="Frequencies")
),
"mca" = list(
"restrict" = list("type"="schema.factor", "group_type"="Characteristics")
)
)
}
p.dataAndLabels <- function(rows, vars) {
# Make sure to also retrieve the names of the individuals
ids <- subset(data.schema(), group_type == "Id");
idName <- NULL
if (nrow(ids) > 0) {
idName <- ids[1,]$name
vars <- c(vars, idName)
}
# Get the actual data
data <- data.get(rows, vars, addRows=T)
# Remove the labels from the data as we do not want them analysed
if (!is.null(idName)) {
labels <- data[[idName]]
data[[idName]] <- NULL
} else {
labels <- NULL
}
# The database calls the column with row names "row" instead of R's "row.names"
rownames(data) <- data$row
data$row <- NULL
return(list(data = data, labels = labels))
}
p.projections <- function(dim.red.res, column.results) {
# marge.row and marge.col are respectively the masses for the rows and the columns
weightName <- "marge.row"
if (column.results == "var" || column.results == "col") {
weightName <- "marge.col"
}
factors <- 1:(ncol(dim.red.res[[column.results]]$coord))
projections <- data.frame(matrix(NA, nrow=nrow(dim.red.res[[column.results]]$coord), ncol=4))
projections$id <- rownames(dim.red.res[[column.results]]$coord)
projections$mass <- dim.red.res$call[[weightName]]
projections$coord <- dim.red.res[[column.results]]$coord[, factors]
projections$contrib <- dim.red.res[[column.results]]$contrib[, factors]
# We do not use the official rownames as the label tag is a bit friendlier
rownames(projections) <- NULL
projections
}
p.generate.structure <- function(processedData, individualProjections, variableProjections, explainedVariance, method) {
# We send processedData as a matrix, to make the JSON smaller and computations in the front-end faster
processedList <- list(
rowNames = rownames(processedData),
columnNames = colnames(processedData),
data = data.matrix(processedData)
)
list(
processedData = processedList,
individualProjections = individualProjections,
variableProjections = variableProjections,
explainedVariance = explainedVariance,
method = method
)
}
p.plotdata <- function(dim.red.res, labels, processedData, type) {
varName <- "var"
indName <- "ind"
if (type == "ca") {
varName <- "col"
indName <- "row"
}
# If we have a large number of individuals the JSON will be too big and the visualisation will fail.
# TODO: fine-tune the 2500 individuals threshold
individualProjections <- NULL
includeIndividuals <- nrow(dim.red.res[[indName]]$coord) < 2500
if (includeIndividuals) {
individualProjections <- p.projections(dim.red.res, column.results = indName)
if (!is.null(labels)) {
individualProjections$label <- labels
}
}
# TODO: optimise processedData storage, currently it is a data.frame,
# which means that every column name is present in every row
analysis <- p.generate.structure(
processedData = processedData,
individualProjections = individualProjections,
variableProjections = p.projections(dim.red.res, column.results = varName),
explainedVariance = dim.red.res$eig$"percentage of variance",
method = type
)
if (!includeIndividuals) {
analysis$individualProjections <- NULL
}
analysis
}
# dimred.pca(vars = c("M4", "M20", "M28", "M36", "M40", "M44", "M48"))
dimred.pca <- function(rows=c(), vars) {
res <- p.dataAndLabels(rows, vars)
data <- res$data
# Create a dataframe with normalised data, to be used for the calculation of influence
columnNorms <- apply(data, 2, function(x){sqrt(sum(x^2))})
processedData <- as.data.frame(t(t(data)/columnNorms))
colnames(processedData) <- colnames(data)
rownames(processedData) <- rownames(data)
p.plotdata(FactoMineR::PCA(data, ncp=length(vars), graph=F), labels = res$labels, processedData = processedData, type = "pca")
}
# dimred.ca(vars=c("aaaa","aaac","aaag","aaat","aaca","aacc","aacg","aact","aaga","aagc","aagg","aagt","aata","aatc","aatg","aatt","acaa","acac","acag","acat","acca","accc","accg","acct","acga","acgc","acgg","acgt","acta","actc","actg","actt","agaa","agac","agag","agat","agca","agcc","agcg","agct","agga","aggc","aggg","aggt","agta","agtc","agtg","agtt","ataa","atac","atag","atat","atca","atcc","atcg","atct","atga","atgc","atgg","atgt","atta","attc","attg","attt","caaa","caac","caag","caat","caca","cacc","cacg","cact","caga","cagc","cagg","cagt","cata","catc","catg","catt","ccaa","ccac","ccag","ccat","ccca","cccc","cccg","ccct","ccga","ccgc","ccgg","ccgt","ccta","cctc","cctg","cctt","cgaa","cgac","cgag","cgat","cgca","cgcc","cgcg","cgct","cgga","cggc","cggg","cggt","cgta","cgtc","cgtg","cgtt","ctaa","ctac","ctag","ctat","ctca","ctcc","ctcg","ctct","ctga","ctgc","ctgg","ctgt","ctta","cttc","cttg","cttt"))
# dimred.ca(rows=c(19, 33, 36, 75, 81, 118, 169, 203, 218, 234, 236, 299, 380, 449, 457, 570, 572, 575, 579, 594, 595, 647, 679, 724, 736, 763, 764, 820, 833, 837, 1000, 1043, 1119, 1170, 1306, 1492, 1564, 1729, 1832, 1895, 2329, 2369, 2629, 2853, 3006, 3010, 3309, 3513, 3833, 5691, 6382, 6905, 7890, 10252, 13658), vars=c("aaaa","aaac","aaag","aaat","aaca","aacc","aacg","aact","aaga","aagc","aagg","aagt","aata","aatc","aatg","aatt","acaa","acac","acag","acat","acca","accc","accg","acct","acga","acgc","acgg","acgt","acta","actc","actg","actt","agaa","agac","agag","agat","agca","agcc","agcg","agct","agga","aggc","aggg","aggt","agta","agtc","agtg","agtt","ataa","atac","atag","atat","atca","atcc","atcg","atct","atga","atgc","atgg","atgt","atta","attc","attg","attt","caaa","caac","caag","caat","caca","cacc","cacg","cact","caga","cagc","cagg","cagt","cata","catc","catg","catt","ccaa","ccac","ccag","ccat","ccca","cccc","cccg","ccct","ccga","ccgc","ccgg","ccgt","ccta","cctc","cctg","cctt","cgaa","cgac","cgag","cgat","cgca","cgcc","cgcg","cgct","cgga","cggc","cggg","cggt","cgta","cgtc","cgtg","cgtt","ctaa","ctac","ctag","ctat","ctca","ctcc","ctcg","ctct","ctga","ctgc","ctgg","ctgt","ctta","cttc","cttg","cttt"))
dimred.ca <- function(rows=c(), vars) {
# TODO: Instead of this matrix use the burt matrix where rows represent
# columns as well. It must be something ling: data x data^T. Its size
# is number of cols X number of cols. It should make the operation.
res <- p.dataAndLabels(rows, vars)
data <- res$data
CAres <- FactoMineR::CA(data, ncp=length(vars), graph=F)
# CAres$call$X contains the normalised data
processedData <- CAres$call$X
p.plotdata(CAres, labels = res$labels, processedData = processedData, type = "ca")
}
# Processes the result of a ca::mjca analysis, we pass nd along because mjca ignores
# the parameter and gives us too many dimensions
p.mca.plotdata <- function(dim.red.res, labels, processedData, nd) {
variableProjections <- data.frame(matrix(NA, nrow=nrow(dim.red.res$colcoord), ncol=4))
variableProjections$id <- dim.red.res$levelnames
variableProjections$mass <- dim.red.res$colmass
variableProjections$coord <- dim.red.res$colcoord[,1:nd]
variableProjections$contrib <- dim.red.res$colctr[,1:nd]
individualProjections <- data.frame(matrix(NA, nrow=nrow(dim.red.res$rowcoord), ncol=4))
individualProjections$id <- rownames(processedData)
individualProjections$mass <- rep(1 / nrow(processedData), nrow(processedData))
individualProjections$coord <- dim.red.res$rowcoord[,1:nd]
individualProjections$contrib <- dim.red.res$rowcoord[,1:nd]^2
if (!is.null(labels)) {
individualProjections$label <- labels
}
# If we have a large number of individuals the JSON will be too big and the visualisation will fail.
# TODO: fine-tune the 2500 individuals threshold
includeIndividuals <- nrow(processedData) < 2500
if (!includeIndividuals) {
individualProjections <- NULL
}
# TODO: optimise processedData storage, currently it is a data.frame,
# which means that every column name is present in every row
analysis <- p.generate.structure(
processedData = processedData,
variableProjections = variableProjections,
individualProjections = individualProjections,
explainedVariance = dim.red.res$inertia.e[1:nd] * 100,
method = "mca"
)
if (!includeIndividuals) {
analysis$individualProjections <- NULL
}
analysis
}
#dimred.mca(vars=c("Exposition", "Max_Lithol", "Max_Permea", "Max_Zumste", "climatic_class", "Geologie", "Soil", "Bodenzustand", "GrAndigkeit", "Lage_im_Relief", "Durchwurzelung", "WAlbung", "Tiefe_cm_A", "Horizont_A", "Bodenart_A", "Bodenfarbe_A", "Zeilung", "Bodenpflegesystem", "Art_der_Begrunung", "Unterstockbodenpflege", "Festigkeit_A", "Tiefe_cm_B", "Horizont_B", "Bodenart_B", "Bodenfarbe_B", "Festigkeit_B", "Unterlage", "Klon", "Bodenart"))
dimred.mca <- function(rows=c(), vars) {
res <- p.dataAndLabels(rows, vars)
data <- res$data
# MJCA is used because it produces much nicer names for the generated variables
MCAres <- ca::mjca(data, nd = NA, lambda = "indicator", reti=TRUE)
# Prepare the binary matrix as processedData
MCAres$indmat <- as.data.frame(MCAres$indmat)
colnames(MCAres$indmat) <- MCAres$levelnames
rownames(MCAres$indmat) <- rownames(data)
# For some reason MJCA gives a lot of very small PC's, here we indicate how many we really want.
nd <- length(which(MCAres$inertia.e > 0.01))
p.mca.plotdata(MCAres, res$labels, MCAres$indmat, nd = nd)
}
# dimred.summarize(variableWeights=list(aaaa=c(6.0151, 7.0562), aaat=c(4.7641, 2.7563), aata=c(4.175, 0.851), aatt=c(4.4429, 2.0970), ataa=c(4.1547, 0.8407), atat=c(3.1881, 0.1051), atta=c(4.1958, 0.7357), attt=c(4.7248, 2.7704)))
dimred.summarize <- function(rows=c(), variableWeights, identifier) {
data <- data.get(rows, names(variableWeights), addRows=T)
vars <- names(variableWeights)
summary <- rep(0, nrow(data))
sapply(vars, function(variable) {
weights <- variableWeights[[variable]]
col <- data[variable]
summary <<- summary + weights[1] * col + weights[2] * col
})
# FIXME: apperently summary is a one-itme list. The item is equal to a column
# name (the first one?), the value of this item is a vector with the summary
# values. There must be more R-like ways to prevent this from happening.
summary <- as.list(summary[[1]])
#list items names are used as row identifiers
names(summary) <- data$row
p.db.extend.schema(name = identifier, type = "numeric", group = "Analytics",
group_type = "Summaries")
p.db.add.column(column.name = identifier, type = "REAL")
p.db.storeList(column.name = identifier, values = summary)
#summary
}
# ICoVeR - Interactive Contig-bin Verification and Refinement
#
# Copyright 2015 Luxembourg Institute of Science and technology. All rights reserved.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
app.init <- function(timestamp = Sys.time()) {
# Makes sure that the database is initialized and returns the schema of the
# data, and all the required UI configuration bits.
db.init()
schema <- data.schema(timestamp = timestamp)
# The Essential Single Copy gene information is stored in ${p.db.dataset}.rda
data(list=list(paste(p.db.dataset, ".escg", sep="")))
escg <- .GlobalEnv[[paste(p.db.dataset, ".escg", sep="")]]
data = list(
schema = schema,
dimensions = list(rows = p.db.rowcount(table = "data"), cols = nrow(schema))
)
cluster <- p.cluster.methods()
dimred <- p.dimred.methods()
list(data = data, cluster = cluster, dimred = dimred, escg = escg)
}
# ICoVeR - Interactive Contig-bin Verification and Refinement
#
# Copyright 2015 Luxembourg Institute of Science and technology. All rights reserved.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
library(DBI)
library(RSQLite)
# Some private helper functions and variables (starting with p.db.)
# Change this variable to switch data sets. It is expected that the data
# directory contains the files:
# - ${p.db.dataset}.rda
# - ${p.db.dataset}.schema.rda
p.db.dataset <- "cstr"
# NOTE: The "cache" databse will be created as: /tmp/RParcoords/cache.db under
# linux. In order to make this work with the opencpu service a couple of
# things need to be done on linux:
# 1) Some apparmor rules need to be set enable the RParcoords plugin to
# create a cache. The file: /etc/apparmor.d/opencpu.d/custom needs the
# following lines:
#
# /tmp/ICoVeR/ rw,
# /tmp/ICoVeR/** rwkmix,
#
# 2) The OpenCPU cache service must be disabled. Rationale: opencpu
# assumes each function to be pure (which is a reasonable assumption).
# However, we update the schema table in the sqlite database, and as
# such two calls to data.schema() can yield different results. This
# doesn't happen when the opencpu cache is enabled, as it will cache
# results of a function for given parameter configuration.
#
# 3) Make sure that OpenCPU can write large enough files from R. To
# achieve this edit /etc/opencpu/server.conf:
#
# "rlimit.fsize": 1e9,
#
p.db.file.path <- paste(.Platform$file.sep, paste("tmp", "ICoVeR", sep=.Platform$file.sep), sep="")
p.db.file.name <- paste(p.db.file.path, paste(p.db.dataset, "cache.db", sep="-"), sep=.Platform$file.sep)
db.init <- function() {
if (!file.exists(p.db.file.name)) {
if (!file.exists(p.db.file.path)) {
dir.create(p.db.file.path, recursive = T)
}
data(list=list(p.db.dataset, paste(p.db.dataset, ".schema", sep="")))
mSchema <- .GlobalEnv[[paste(p.db.dataset, ".schema", sep="")]]
mData <- .GlobalEnv[[p.db.dataset]]
mData$row <- as.integer(1:nrow(mData))
con <- DBI::dbConnect(RSQLite::SQLite(), p.db.file.name)
stopifnot(DBI::dbWriteTable(con, "data", mData, row.names=F))
stopifnot(DBI::dbWriteTable(con, "schema", mSchema, row.names=F))
#create index by row to allow for faster lookup / updates
res <- DBI::dbSendQuery(con,"CREATE INDEX row_index ON data (row ASC);")
DBI::dbClearResult(res)
DBI::dbDisconnect(con)
}
}
# This function makes sure column names are suitable for sqlite. It also prevents SQL injection.
p.db.escape.name <- function (name) {
name <- paste("\"", name, "\"", sep="")
}
p.db.connection <-function() {
DBI::dbConnect(RSQLite::SQLite(), p.db.file.name)
}
p.db.rowcount <- function(table) {
q <- paste("SELECT COUNT(*) FROM", table, sep=" ")
con <- p.db.connection()
rowcount <- DBI::dbGetQuery(con, q)
DBI::dbDisconnect(con)
as.vector(unlist(rowcount))
}
p.db.check.column.type <- function(type) {
type <- toupper(type)
if (!(type %in% c("INTEGER", "REAL", "TEXT"))) {
stop(paste("db.check.column.type - Invalid column type:", type))
}
type
}
# p.db.add.column(column.name="kmeans_35_M4", type="integer")
p.db.add.column <- function(table="data", column.name, type) {
type <- p.db.check.column.type(type)
con <- p.db.connection()
if (!(column.name %in% DBI::dbListFields(con, table))) {
column.name <- p.db.escape.name(column.name)
q <- paste("ALTER TABLE", table, "ADD COLUMN", column.name, type, sep=" ")
res <- DBI::dbSendQuery(con, q)
DBI::dbClearResult(res)
}
DBI::dbDisconnect(con)
}
# ALTER TABLE DROP COLUMN is not supported by sqlite
p.db.remove.column <- function(table="data", column.name) {
# con <- p.db.connection()
# if (column.name %in% DBI::dbListFields(con, table)) {
# column.name <- p.db.escape.name(column.name)
# q <- paste("ALTER TABLE", table, "DROP COLUMN", column.name, sep=" ")
# res <- DBI::dbSendQuery(con, q)
# DBI::dbClearResult(res)
# }
#
# DBI::dbDisconnect(con)
}
# p.db.extend.schema("kmeans_30_7", "integer", "Analytics", "Clusterings")
p.db.extend.schema <- function(name, type, group, group_type) {
con <- p.db.connection()
q <- paste("SELECT count(*) FROM schema WHERE name='", name, "'", sep="")
count <- unlist(DBI::dbGetQuery(con, q))
if (count == 0) {
values <- paste("'", c(name, type, group, group_type), "'", sep="", collapse=", ")
q <- paste("INSERT INTO schema (name, type, \"group\", group_type) VALUES(", values , ")", sep="")
res <- DBI::dbSendQuery(con, q)
DBI::dbClearResult(res)
}
DBI::dbDisconnect(con)
}
p.db.truncate.schema <- function(name) {
con <- p.db.connection()
q <- paste("SELECT count(*) FROM schema WHERE name='", name, "'", sep="")
count <- unlist(DBI::dbGetQuery(con, q))
if (count == 1) {
q <- paste("DELETE FROM schema WHERE name='", name, "'", sep="")
res <- DBI::dbSendQuery(con, q)
DBI::dbClearResult(res)
}
DBI::dbDisconnect(con)
}
# p.db.store(column.name="kmeans_30_7", 1:10, 8)
p.db.store <- function(column.name, rows = c(), value) {
column.name <- p.db.escape.name(column.name)
# NOTE: for now value is expected to be a numeric value.
con <- p.db.connection()
q <- paste("UPDATE data SET ", column.name, " = ", value, sep="")
if (length(rows) > 0) {
rows <- paste(as.character(rows), collapse=", ")
q <- paste(q, " WHERE row in (", rows, ")", sep="")
}
res <- DBI::dbSendQuery(con, q)
DBI::dbClearResult(res)
DBI::dbDisconnect(con)
}
p.db.storeList <- function(column.name, values) {
column.name <- p.db.escape.name(column.name)
#Note: list must have the row ids as the item names
#connect to DB
con <- p.db.connection()
#start TXN
dbBegin(con)
#build update statement for each item in the list,
# using the item name as a row id
print(paste("Query Build Start",Sys.time(),sep = " "))
queries<-paste("UPDATE data SET ", column.name, " = ", values, " WHERE row =", names(values),sep="")
#pass queries to DB
for(q in queries) {
DBI::dbSendQuery(con, q)
}
#commit changes
dbCommit(con)
DBI::dbDisconnect(con)
}
p.db.types <- function(variables) {
variables <- lapply(variables, p.db.escape.name)
# NOTE: for now value is expected to be a numeric value.
con <- p.db.connection()
q <- paste("SELECT name, type FROM schema WHERE name in ("
, paste(variables, collapse=", "), ")", sep="")
data <- DBI::dbGetQuery(con, q)
DBI::dbDisconnect(con)
data
}
# API exposed to the front-end
db.reset <- function() {
if (file.exists(p.db.file.name)) {
file.remove(p.db.file.name)
}
p.db.init()
}
# p.db.select(vars=c("M4", "M20"), rows=c(1,2,100,2300))
p.db.select <- function(table="data", vars=c(), rows=c()) {
vars <- lapply(vars, p.db.escape.name)
vars <- ifelse(length(vars) == 0,
"*",
paste(unlist(vars), collapse=", "))
q <- paste("SELECT ", vars, " FROM ", table, sep="")
if (length(rows) > 0) {
rows <- paste(as.character(rows), collapse=", ")
q <- paste(q, " WHERE row in (", rows, ")", sep="")
}
con <- p.db.connection()
data <- DBI::dbGetQuery(con, q)
DBI::dbDisconnect(con)
data
}
#!/bin/bash
sudo rm -rf /tmp/ocpu*
sudo rm -rf /tmp/opencpu*
sudo rm -rf /tmp/RParcoords
sudo service opencpu restart
sudo service opencpu-cache stop
#!/bin/sh
# We're only interested in checking files that are in the js directory. The js
# files in inst/www/lib/* are considered to be external libraries over which we
# have no control or that fall outside the responsibility of this project.
files=$(git diff --cached --name-only --diff-filter=ACM | grep "^inst/www/js/.*.js$")
if [ "$files" = "" ]; then
exit 0
fi
pass=true
echo "\nValidating JavaScript:\n"
for file in ${files}; do
result=$(jslint --edition=2014-07-08 ${file} | grep "${file} is OK")
if [ "$result" != "" ]; then
echo "\t\033[32mJSLint Passed: ${file}\033[0m"
else
echo "\t\033[31mJSLint Failed: ${file}\033[0m"
pass=false
fi
done
echo "\nJavaScript validation complete\n"
if ! $pass; then
echo "\033[41mCOMMIT FAILED\033[0m"
echo "Your commit contains files that should pass JSLint but do not."
echo "Please fix the JSLint errors and try again.\n"
exit 1
else
echo "\033[42mCOMMIT SUCCEEDED\033[0m\n"
fi
This diff is collapsed.
{
"title":"Test Data: columns only",
"x_axis_label": "Dim 1",
"y_axis_label": "Dim 2" ,
"dataExtents": [[-2.0,-2.0],[2.0,2.0]],
"dataItems":[
{"type":"column", "name":"CGGC.GCCG" , "x": 1.0, "y": -1.0},
{"type":"column", "name":"CGGC.GCCG" , "x": -1.0, "y": -1.0},
{"type":"column", "name":"CGGC.GCCG" , "x": -1.0, "y": 1.0},
{"type":"column", "name":"CGGC.GCCG" , "x": 1.0, "y": 1.0},
{"type":"column", "name":"CGGC.GCCG" , "x": 0.0, "y": 0.0},
{"type":"column", "name":"CGGC.GCCG" , "x": 0.5, "y": -0.5},
{"type":"column", "name":"CGGC.GCCG" , "x": -0.5, "y": -0.5},
{"type":"column", "name":"CGGC.GCCG" , "x": -0.5, "y": 0.5},
{"type":"column", "name":"CGGC.GCCG" , "x": 0.5, "y": 0.5}
]
}
@import url("../libs/bootstrap/css/bootstrap-slate.min.css");
@import url("main.css");
.progress-bar-brushed {
background-color: #aeb9c2;
}
.parcoords .axis line, .parcoords .axis path {
fill: none;
stroke: #c8c8c8;
shape-rendering: crispEdges;
}
.parcoords text {
fill: #c8c8c8;
}
.dimredplot .individual.scatterplot .selected {
fill: white;
stroke: white;
}
.dimredplot .colormap .text {
fill: black;
}
\ No newline at end of file
@import url("../libs/bootstrap/css/bootstrap.min.css");
@import url("main.css");
.progress-bar-brushed {
background-color: #5ec6ff;
}
html, body {
height: calc(100% - 35px);
}
.form-control.ng-invalid {
border: 2px solid red;
}
.navbar {
margin-bottom: 0px;
}
.navbar .progress {
margin-bottom: 0px;
margin-right: 1em;
width: 150px;
}
.tab-content {
padding-top: 5px;
}
.adjusted-right-padding {
padding-right: 5px !important;
margin-right: 0 !important;
}
.adjusted-left-padding {
padding-left: 9px !important;
margin-left: 0 !important;
}
.no-left-padding {
padding-left: 0 !important;
margin-left: 0 !important;
}
.no-right-padding {
padding-right: 0 !important;
margin-right: 0 !important;
}
.form-group {
margin-bottom: 5px;
}
.modal-body select[multiple] {
min-height: 200px;
}
.modal-footer {
padding: 10px 15px;
}
.colorpatch {
display: block;
vertical-align: middle;
width: 37px;
height: 22px;
}
#SwitchOptions {
float: right;
}
#main {
height: 100%;
width: 100%;
margin: 50px auto 0px;
}
#top {
height: 60%;
margin-bottom: 10px;
}
#bottom {
height: 40%;
}
#options {
float: left;
position: absolute;
z-index: 3;
}
.parcoords {
background-color: transparent
}
#parcoords,
#colourmap,
#parcoords div,
#colourmap div {
height: 100%;
}
#charts {
height: 100%;
}
.tab-content {
height: calc(100% - 40px);
}
.tab-pane, .ng-isolate-scope, #dimRedPlots {
height: 100%;
}
#dimRedPlot {
height: 100%;
}
#twodmap {
height: 100%;
padding-left: 0px;
padding-right: 0px;
}
import gulp from 'gulp';
import runSequence from 'run-sequence';
import gulpLoadPlugins from 'gulp-load-plugins';
const $ = gulpLoadPlugins();
gulp.task('scripts', () =>
gulp.src([
// Note: Since we are not using useref in the scripts build pipeline,
// you need to explicitly list your scripts here in the right order
// to be correctly concatenated
'libs/lodash/lodash-3.9.0.min.js',
'libs/jquery/jquery-1.11.1.min.js',
'libs/opencpu/opencpu-0.5.js',
'libs/d3/d3.min.js',
'libs/d3/d3.svg.multibrush.js',
'libs/d3/colorbrewer.js',
'libs/parcoords/d3.parcoords.js',
'libs/angularjs/angular-1.2.21.min.js',
'libs/ui-bootstrap/ui-bootstrap-tpls-0.12.1.min.js',
'libs/dimredplot/dimredplot.js',
'libs/dimredplot/scatterplot.js',
'libs/dimredplot/barplot.js',
'libs/dimredplot/variancepercentageplot.js',
'libs/dimredplot/colourmap.js',
'js/app.js',
'js/controllers/chartsctrl.js',
'js/controllers/clusterconfigctrl.js',
'js/controllers/clusterctrl.js',
'js/controllers/colorctrl.js',
'js/controllers/colourmapctrl.js',
'js/controllers/dataindicatorctrl.js',
'js/controllers/dimredctrl.js',
'js/controllers/dimreddisplayctrl.js',
'js/controllers/dimredplotctrl.js',
'js/controllers/escgctrl.js',
'js/controllers/exportctrl.js',
'js/controllers/filterctrl.js',
'js/controllers/manualcoloringctrl.js',
'js/controllers/namehighlightctrl.js',
'js/controllers/nameselectionctrl.js',
'js/controllers/parcoordsctrl.js',
'js/controllers/parcoordsvarsctrl.js',
'js/controllers/plotctrl.js',
'js/controllers/tagctrl.js',
'js/controllers/themectrl.js',
'js/controllers/variableselectionctrl.js',
'js/services/analytics.js',
'js/services/assert.js',
'js/services/color.js',
'js/services/dataset.js',
'js/services/dimredplot.js',
'js/services/opencpu.js',
'js/services/parcoords.js',
'js/services/r.js',
'js/services/tag.js'
])
.pipe($.concat('app.min.js'))
.pipe($.uglify({preserveComments: 'some', mangle: false}))
// Output files
.pipe(gulp.dest('.'))
.pipe($.size({title: 'scripts'}))
);
// Scan your HTML for assets & optimize them
gulp.task('html', () => {
const assets = $.useref.assets({searchPath: '{., ./css}'});
return gulp.src('index-raw.html')
.pipe($.rename('index.html'))
.pipe(assets)
// Remove any unused CSS
.pipe($.if('css/*.css', $.uncss({
html: ['index-raw.html']
})))
// Concatenate and minify styles
// In case you are still using useref build blocks
.pipe($.if('**/*.css', $.minifyCss()))
.pipe(assets.restore())
.pipe($.useref())
// Minify any HTML
.pipe($.if('*.html', $.minifyHtml()))
// Output files
.pipe(gulp.dest('.'))
.pipe($.size({title: 'html'}));
});
gulp.task('default', [], cb =>
runSequence(
['scripts', 'html'],
cb
)
);
<!DOCTYPE html>
<html lang="en" ng-app="contigBinningApp">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title></title>
<link href="libs/fontawesome/css/font-awesome.css" rel="stylesheet">
<link href="libs/parcoords/d3.parcoords.css" rel="stylesheet">
<link href="libs/dimredplot/dimredplot.css" rel="stylesheet">
<link href="css/light.css" rel="stylesheet" id="maincss">
</head>
<body>
<nav class="navbar navbar-default navbar-fixed-top" role="navigation">
<div class="container-fluid">
<div class="navbar-header">
<a class="navbar-brand">
<span style="color: #337ab7">ICoVeR</span> -
<span style="color: #337ab7">I</span>nteractive <span style="color: #337ab7">Co</span>ntig-bin
<span style="color: #337ab7">Ve</span>rification and <span style="color: #337ab7">R</span>efinement</a>
</div>
<form class="navbar-form navbar-right form-inline">
<div class="btn-group" ng-controller="ManualColoringCtrl" ng-show="manualColoringEnabled" dropdown>
<button type="button" class="btn btn-default" ng-disabled="!itemsBrushed" ng-style="{'background-color': colors[0]}">Apply color to selection</button>
<button type="button" class="btn btn-default dropdown-toggle" ng-disabled="!itemsBrushed" dropdown-toggle>
<span class="caret"></span>
<span class="sr-only">Toggle Dropdown</span>
</button>
<ul class="dropdown-menu brush-color" role="menu" id="brush-color-menu">
<li ng-repeat="color in colors">
<a href="#" ng-style="{'background-color': color}" ng-click="colorSelection(color)">
<span class="colorpatch"></span>
</a>
</li>
</ul>
</div>
<div class="form-group" ng-controller="NameHighlightCtrl" ng-hide="noHighlightAvailable">
<label class="control-label col-lg-4" for="rowNameHighlight">Highlight</label>
<input type="text" id="rowNameHighlight" class = "col-lg-5 input-sm" ng-model="rowName" ng-change="highlightRow()">
</div>
<div class="form-group" ng-controller="DataIndicatorCtrl">
<progress ng-click="changeScale()" max="1" animate="false">
<bar ng-repeat="bar in counts track by $index"
value="bar.rows / rowCount"
type="{{bar.type}}">
<b ng-hide="(bar.rows / rowCount) < 0.15">{{bar.rows}}</b>
</bar>
</progress>
</div>
<div class="form-group" ng-controller="ThemeCtrl">
<label class="control-label">Theme:</label>
<div class="btn-group">
<label class="btn btn-default" ng-model="theme" btn-radio="'light'">Light</label>
<label class="btn btn-default" ng-model="theme" btn-radio="'dark'">Dark</label>
</div>
</div>
</form>
</div>
</nav>
<div id="main" class="container-fluid">
<!-- Top half of the sceen -->
<div id="top" class="row">
<!--<div id="colourmap" class="col-lg-1">
<div class="colourmap" ng-controller="ColourmapCtrl">
</div>
</div>-->
<div id="parcoords" class="col-lg-12">
<div class="parcoords" ng-controller="ParcoordsCtrl">
</div>
</div>
</div>
<!-- Bottom half of the sceen -->
<div id="bottom" class="row" ng-controller="PlotCtrl">
<div id="options" ng-style="sliding">
<ng-include src="'js/templates/options.html'"></ng-include>
</div>
<div class="col-lg-1">
</div>
<!-- Scatterplot -->
<div id="charts" class="col-lg-11" ng-controller="ChartsCtrl">
<div class="row" id="dimRedPlots">
<div id="dimRedPlot" class="tab-pane container-fluid active" ng-class="dimredplotWidth" ng-repeat="analysis in analyses" ng-controller="DimRedPlotCtrl">
</div>
</div>
</div>
</div>
</div>
<!-- build:js(app) app.min.js -->
<script src="libs/lodash/lodash-3.9.0.min.js"></script>
<script src="libs/jquery/jquery-1.11.1.min.js"></script>
<script src="libs/opencpu/opencpu-0.5.js"></script>
<script src="libs/d3/d3.min.js"></script>
<script src="libs/d3/d3.svg.multibrush.js"></script>
<script src="libs/d3/colorbrewer.js"></script>
<script src="libs/parcoords/d3.parcoords.js"></script>
<script src="libs/dimredplot/dimredplot.js"></script>
<script src="libs/dimredplot/scatterplot.js"></script>
<script src="libs/dimredplot/barplot.js"></script>
<script src="libs/dimredplot/variancepercentageplot.js"></script>
<script src="libs/dimredplot/colourmap.js"></script>
<script src="libs/angularjs/angular-1.2.21.min.js"></script>
<script src="libs/ui-bootstrap/ui-bootstrap-tpls-0.12.1.min.js"></script>
<script src="js/app.js"></script>
<script src="js/services/dataset.js"></script>
<script src="js/controllers/namehighlightctrl.js"></script>
<script src="js/controllers/chartsctrl.js"></script>
<script src="js/controllers/clusterctrl.js"></script>
<script src="js/controllers/clusterconfigctrl.js"></script>
<script src="js/controllers/dataindicatorctrl.js"></script>
<script src="js/controllers/escgctrl.js"></script>
<script src="js/controllers/exportctrl.js"></script>
<script src="js/controllers/parcoordsctrl.js"></script>
<script src="js/controllers/parcoordsvarsctrl.js"></script>
<script src="js/controllers/filterctrl.js"></script>
<script src="js/controllers/dimredctrl.js"></script>
<script src="js/controllers/dimredplotctrl.js"></script>
<script src="js/controllers/colorctrl.js"></script>
<script src="js/controllers/manualcoloringctrl.js"></script>
<script src="js/controllers/themectrl.js"></script>
<script src="js/controllers/plotctrl.js"></script>
<script src="js/controllers/variableselectionctrl.js"></script>
<script src="js/controllers/dimreddisplayctrl.js"></script>
<script src="js/controllers/colourmapctrl.js"></script>
<script src="js/controllers/tagctrl.js"></script>
<script src="js/controllers/nameselectionctrl.js"></script>
<script src="js/services/analytics.js"></script>
<script src="js/services/assert.js"></script>
<script src="js/services/color.js"></script>
<script src="js/services/opencpu.js"></script>
<script src="js/services/parcoords.js"></script>
<script src="js/services/dimredplot.js"></script>
<script src="js/services/tag.js"></script>
<script src="js/services/r.js"></script>
<!-- endbuild -->
</body>
</html>
<!DOCTYPE html><html lang=en ng-app=contigBinningApp><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><meta name=viewport content="width=device-width, initial-scale=1"><title></title><link href=libs/fontawesome/css/font-awesome.css rel=stylesheet><link href=libs/parcoords/d3.parcoords.css rel=stylesheet><link href=libs/dimredplot/dimredplot.css rel=stylesheet><link href=css/light.css rel=stylesheet id=maincss></head><body><nav class="navbar navbar-default navbar-fixed-top" role=navigation><div class=container-fluid><div class=navbar-header><a class=navbar-brand><span style="color: #337ab7">ICoVeR</span> - <span style="color: #337ab7">I</span>nteractive <span style="color: #337ab7">Co</span>ntig-bin <span style="color: #337ab7">Ve</span>rification and <span style="color: #337ab7">R</span>efinement</a></div><form class="navbar-form navbar-right form-inline"><div class=btn-group ng-controller=ManualColoringCtrl ng-show=manualColoringEnabled><button type=button class="btn btn-default" ng-disabled=!itemsBrushed ng-style="{'background-color': colors[0]}">Apply color to selection</button><button type=button class="btn btn-default dropdown-toggle" ng-disabled=!itemsBrushed><span class=caret></span> <span class=sr-only>Toggle Dropdown</span></button><ul class="dropdown-menu brush-color" role=menu id=brush-color-menu><li ng-repeat="color in colors"><a href=# ng-style="{'background-color': color}" ng-click=colorSelection(color)><span class=colorpatch></span></a></li></ul></div><div class=form-group ng-controller=NameHighlightCtrl ng-hide=noHighlightAvailable><label class="control-label col-lg-4" for=rowNameHighlight>Highlight</label><input type=text id=rowNameHighlight class="col-lg-5 input-sm" ng-model=rowName ng-change=highlightRow()></div><div class=form-group ng-controller=DataIndicatorCtrl><progress ng-click=changeScale() max=1 animate=false><bar ng-repeat="bar in counts track by $index" value="bar.rows / rowCount" type={{bar.type}}><b ng-hide="(bar.rows / rowCount) < 0.15">{{bar.rows}}</b></bar></progress></div><div class=form-group ng-controller=ThemeCtrl><label class=control-label>Theme:</label><div class=btn-group><label class="btn btn-default" ng-model=theme btn-radio="'light'">Light</label><label class="btn btn-default" ng-model=theme btn-radio="'dark'">Dark</label></div></div></form></div></nav><div id=main class=container-fluid><div id=top class=row><div id=parcoords class=col-lg-12><div class=parcoords ng-controller=ParcoordsCtrl></div></div></div><div id=bottom class=row ng-controller=PlotCtrl><div id=options ng-style=sliding><ng-include src="'js/templates/options.html'"></ng-include></div><div class=col-lg-1></div><div id=charts class=col-lg-11 ng-controller=ChartsCtrl><div class=row id=dimRedPlots><div id=dimRedPlot class="tab-pane container-fluid active" ng-class=dimredplotWidth ng-repeat="analysis in analyses" ng-controller=DimRedPlotCtrl></div></div></div></div></div><script src=app.min.js></script></body></html>
\ No newline at end of file
/*jslint indent: 2 */
/*global angular */
/*
ICoVeR - Interactive Contig-bin Verification and Refinement
Copyright 2015 Luxembourg Institute of Science and technology. All rights reserved.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
//ocpu.seturl("/ocpu/library/RParcoords/R");
// Create empty modules, which will be populated once the deps are loaded.
angular.module('contigBinningApp.controllers', ['ui.bootstrap']);
angular.module('contigBinningApp.services', []);
// Create a module for the application with the dependencies specified.
angular.module('contigBinningApp', [
'contigBinningApp.controllers',
'contigBinningApp.services'
]);
/*jslint browser: true, todo:true, nomen: true, indent: 2 */
/*global angular, crpgl, d3, ocpu, _, $*/
/*
ICoVeR - Interactive Contig-bin Verification and Refinement
Copyright 2015 Luxembourg Institute of Science and technology. All rights reserved.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
angular.module('contigBinningApp.controllers')
.controller('ChartsCtrl', function ($scope) {
'use strict';
$scope.location = false;
/*jslint unparam: true */
$scope.$on('DataSet::schemaLoaded', function (e, schema) {
// FIXME: we make a lot of assumptions in this function. For now this is
// just a quick hack to make things work (tm) for some initial
// testing with datasets that have spatial information.
// For this widget to work, the schema must have a group with the type
// Location.*, which must in turn have an x and y variable.
function selector(v) {
return v.group_type === 'Location.Dense' || v.group_type === 'Location.Sparse';
}
var location = _.groupBy(_.select(schema, selector), 'group');
// For now we only support one location, so let's get the first one.
if (_.keys(location).length > 0) {
$scope.location = _.groupBy(location[_.first(_.keys(location))], 'name');
}
});
/*jslint unparam: false */
});
/*jslint indent: 2 */
/*global angular */
/*
ICoVeR - Interactive Contig-bin Verification and Refinement
Copyright 2015 Luxembourg Institute of Science and technology. All rights reserved.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
angular.module('contigBinningApp.controllers')
.controller('ClusterConfigCtrl', function ($scope, $modalInstance, options, DataSet) {
'use strict';
// It is possible that there are less than 30 individuals, in which case we can not use 30 clusters.
// The default number of clusters in this case is less than the number of rows as it would otherwise,
// make no sense.
var previousCentersCount = Math.min(30, Math.floor(Math.sqrt(DataSet.data().length)));
function updateControllerState() {
$scope.specified.identifier = $scope.specified.method.name
+ ($scope.specified.centers !== -1 ? '_' + $scope.specified.centers : "")
+ '_' + ($scope.specified.variables.length || 0);
$scope.configurationInvalid =
($scope.specified.centers < 2 && $scope.specified.centers !== -1)
|| $scope.specified.variables.length < 1;
}
$scope.options = options;
$scope.configurationInvalid = true;
$scope.specified = {
method: $scope.options.methods[0],
identifier: $scope.options.methods[0].name + '_' + previousCentersCount + '_0',
centers: previousCentersCount, // NOTE: The naming is kmeans specific
variables: []
};
$scope.$watch('specified.centers', updateControllerState);
$scope.$watch('specified.variables', updateControllerState);
$scope.$watch('specified.method', updateControllerState);
$scope.ok = function () {
$modalInstance.close($scope.specified);
};
$scope.hideCenters = function () {
if ($scope.specified.method.name !== "kmeans") {
previousCentersCount = $scope.specified.centers;
$scope.specified.centers = -1;
return true;
}
if ($scope.specified.centers === -1) {
$scope.specified.centers = previousCentersCount;
}
return false;
};
$scope.cancel = function () {
$modalInstance.dismiss();
};
});
/*jslint indent: 2, nomen: true */
/*global angular, _ */
/*
ICoVeR - Interactive Contig-bin Verification and Refinement
Copyright 2015 Luxembourg Institute of Science and technology. All rights reserved.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
angular.module('contigBinningApp.controllers')
.controller('ClusterCtrl', function ($scope, $modal, Analytics, R) {
'use strict';
var d = {
schema: undefined
};
function setVariables() {
$scope.options.variables = _.filter(d.schema, function (variable) {
return R.is.numeric(variable.type) && variable.analysable;
});
}
function performClustering(config) {
var args = {};
// FIXME: Generalize this code, we don't want to change this code for
// every clustering method we add.
if (config.method.name === "kmeans") {
args.centers = config.centers;
} else if (config.method.name !== "correlation") {
//FIXME get rid of this hard coded value, change it to a simple else
throw "Unknown clustering method: " + config.method.name;
}
Analytics.cluster(
config.method.name,
_.map(config.variables,
function (variable) { return variable.name; }),
args,
config.identifier
);
}
// Available clustering options.
$scope.options = {
methods: [],
variables: [],
valid: function () {
return $scope.options.methods.length > 0
&& $scope.options.variables.length > 2;
}
};
$scope.canCluster = false;
/*jslint unparam: true */
$scope.$on('DataSet::schemaLoaded', function (e, schema) {
d.schema = schema;
setVariables();
$scope.canCluster = $scope.options.valid();
});
/*jslint unparam: false */
/*jslint unparam: true */
$scope.$on('Analytics::clusterMethodsAvailable', function (e, methods) {
$scope.options.methods = methods;
$scope.canCluster = $scope.options.valid();
});
/*jslint unparam: false */
$scope.openSelectionDialog = function () {
var dialog = $modal.open({
templateUrl: 'js/templates/clusterconfig.html',
size: 'md',
controller: 'ClusterConfigCtrl',
resolve: {
options: function () {
return $scope.options;
}
}
});
dialog.result.then(performClustering);
};
});
/*jslint indent: 2, nomen: true */
/*global angular, _*/
/*
ICoVeR - Interactive Contig-bin Verification and Refinement
Copyright 2015 Luxembourg Institute of Science and technology. All rights reserved.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
angular.module('contigBinningApp.controllers')
.controller('ColorCtrl', function ($scope, R, Color) {
'use strict';
var d = {
methods: undefined,
initialSchemaLoad: true
};
function onMethodChange() {
if (d.methods === undefined) {
$scope.colorSchemes = [];
$scope.colorScheme = undefined;
return;
}
$scope.colorSchemes = d.methods[$scope.colorMethod];
if ($scope.colorSchemes === undefined) {
$scope.colorSchemes = [];
} else if (!_.isArray($scope.colorSchemes)) {
$scope.colorSchemes = [$scope.colorSchemes];
}
if ($scope.colorScheme === undefined
|| !_.contains($scope.colorSchemes, $scope.colorScheme)) {
$scope.colorScheme = $scope.colorSchemes[0];
}
}
function onVariableChange() {
if ($scope.colorVariable && R.is.numeric($scope.colorVariable.type)) {
d.methods = Color.configuration().numeric;
} else if ($scope.colorVariable && R.is.factor($scope.colorVariable.type)) {
d.methods = Color.configuration().factor;
} else {
d.methods = undefined;
$scope.colorMethod = undefined;
}
$scope.colorMethods = _.keys(d.methods);
if ($scope.colorMethod === undefined
|| !_.contains($scope.colorMethods, $scope.colorMethod)) {
$scope.colorMethod = $scope.colorMethods[0];
} else {
onMethodChange();
}
}
function onOpacityChange() {
Color.opacity($scope.opacity);
}
$scope.variables = [];
$scope.colorMethods = [];
$scope.colorSchemes = [];
$scope.colorVariable = undefined;
$scope.colorMethod = undefined;
$scope.colorScheme = undefined;
$scope.opacity = 0.05;
$scope.applyColoring = function () {
if ($scope.colorVariable !== undefined) {
Color.color($scope.colorVariable.name, $scope.colorMethod, $scope.colorScheme);
}
};
function updateVariables(schema) {
$scope.dataAvailable = true;
$scope.variables = _.filter(schema, function (variable) {
return R.is.numeric(variable.type) || R.is.factor(variable.type);
});
// Make sure that the manual selection option is on top
var manualIndex = _.findIndex($scope.variables, "name", "Manual selection"),
manualSelectionVar,
colorVariable;
if (manualIndex !== -1) {
manualSelectionVar = $scope.variables[manualIndex];
$scope.variables.splice(manualIndex, 1);
$scope.variables.splice(0, 0, manualSelectionVar);
}
if ($scope.colorVariable !== undefined) {
colorVariable = _.find($scope.variables, "name", $scope.colorVariable.name);
$scope.colorVariable = colorVariable;
}
}
$scope.$on('Colors::changed', function () {
$scope.colorVariable = _.find($scope.variables, "name", Color.colorVariable());
$scope.colorMethod = Color.colorMethod();
$scope.colorScheme = Color.colorSchemeName();
});
$scope.$on('DataSet::schemaLoaded', function (e, schema) {
/*jslint unparam: true */
updateVariables(schema);
if (d.initialSchemaLoad) {
// We only want to change the color scheme implicitly the first time we
// recieve data. Afterwards it's up to the user to change the color
// scheme to his or her likening.
d.initialSchemaLoad = false;
$scope.colorVariable = _.find(schema, { 'name': 'GC_CONTENT' });
$scope.colorMethod = "Decile";
$scope.colorScheme = "yellow_to_red";
$scope.applyColoring();
$scope.$watch('colorVariable', onVariableChange);
$scope.$watch('colorMethod', onMethodChange);
$scope.$watch('opacity', onOpacityChange);
}
});
});
/*jslint browser:true, unparam: true, indent: 2, nomen: true */
/*global angular, d3, $, _, list*/
/*
ICoVeR - Interactive Contig-bin Verification and Refinement
Copyright 2015 Luxembourg Institute of Science and technology. All rights reserved.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
angular.module('contigBinningApp.controllers')
.controller('ColourmapCtrl', function ($scope, $window, $element, DataSet, ParCoords, Color) {
'use strict';
//$scope.renderColourmap = false;
d3.select($element[0]).style("display", "none");
/// private Controller vars
var d = {
colourMap: list.ColourMap(),
colourMapScale: d3.scale.linear(),
colourMapGroup: null,
title: null
};
/// private controller functions
function render() {
d.colourMapGroup
.select("g")
.call(d.colourMap);
}
function resize() {
d.colourMapScale.range([$element[0].clientHeight - 15, 22]);
d.colourMap
.scale(d.colourMapScale);
d.colourMapGroup.attr("height", $element[0].clientHeight);
d.title
.attr("y", d.title.node().clientHeight)
.attr("x", -d.title.node().clientWidth + 20);
render();
}
/// Initialization
d.colourMapScale
.domain([0, 1])
.range([$element[0].clientHeight, 0]);
d.colourMap
.width(20)
.axisSide("left")
.extent([0, 0])
.scale(d.colourMapScale);
/*.on("brush", function () {
});*/
d.colourMapGroup = d3.select($element[0]).selectAll("svg.colourmap").data([true]);
d.colourMapGroup.enter()
.append("svg")
.attr("class", "colourmap")
.append("g")
.attr("transform", "translate(" + 60 + ", 4)")
.append("text")
.attr("class", "label");
d.title = d.colourMapGroup.select("text.label")
.text("influence");
angular.element($window).bind('resize', resize);
$(document).ready(resize);
/// Scope extensions
$scope.$on("Colors::changed", function (e, rowColors) {
/*jslint unparam:true todo:true*/
//$scope.renderColourmap = true;
//TODO fix this so it actualles uses ng-show
d3.select($element[0]).style("display", "block");
//d.colourMapScale.domain(domain);
d.colourMap.scale(d.colourMapScale);
d.colourMap.colourFunction(Color.colorFn());
d.title.text(Color.colorVariable());
resize();
});
});
/*jslint indent: 2 */
/*global angular */
/*
ICoVeR - Interactive Contig-bin Verification and Refinement
Copyright 2015 Luxembourg Institute of Science and technology. All rights reserved.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
angular.module('contigBinningApp.controllers')
.controller('DataIndicatorCtrl', function ($scope) {
'use strict';
var overallRowCount = 0, // The total number of rows in the dataset
currentRowCount = 0, // The current number of rows in the views
brushedRowCount = 0; // The current number of rows which are brushed
$scope.rowCount = 0;
$scope.counts = [];
/*jslint unparam: true */
$scope.$on("DataSet::brushed", function (ev, rows) {
brushedRowCount = rows.length;
if (rows.length > 0) {
$scope.counts = [
{ rows: brushedRowCount, type: "brushed" },
{ rows: currentRowCount - brushedRowCount, type: "" }
];
} else {
$scope.counts = [{ rows: currentRowCount, type: "" }];
}
});
/*jslint unparam: false */
/*jslint unparam: true */
$scope.$on("DataSet::filtered", function (ev, rows) {
currentRowCount = rows.length;
brushedRowCount = 0;
if ($scope.rowCount === overallRowCount) {
$scope.counts = [{ rows: currentRowCount, type: "" }];
} else {
$scope.rowCount = currentRowCount;
$scope.counts = [{ rows: currentRowCount, type: "" }];
}
});
/*jslint unparam: false */
$scope.changeScale = function () {
if ($scope.rowCount === overallRowCount) {
$scope.rowCount = currentRowCount;
} else {
$scope.rowCount = overallRowCount;
}
};
/*jslint unparam: true */
$scope.$on("App::configurationLoaded", function (ev, cfg) {
overallRowCount = currentRowCount = cfg.data.dimensions.rows;
brushedRowCount = 0;
$scope.rowCount = currentRowCount;
$scope.counts = [{ rows: currentRowCount, type: "" }];
});
/*jslint unparam: false */
});
/*jslint indent: 2, nomen: true */
/*global angular, _, list */
/*
ICoVeR - Interactive Contig-bin Verification and Refinement
Copyright 2015 Luxembourg Institute of Science and technology. All rights reserved.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
angular.module('contigBinningApp.controllers')
.controller('DimRedCtrl', function ($scope, $modal, Analytics, R, DimRedPlot, DataSet) {
'use strict';
var d = {
schema: undefined
};
function createGroupTypeRestrictionTest(restriction) {
var groupType = restriction,
test = function (gt) { return gt === groupType; };
if (restriction[0] === '!') {
groupType = restriction.substr(1);
test = function (gt) { return gt !== groupType; };
}
return function (variable) {
return test(variable.group_type);
};
}
function createTypeRestrictionTest(restriction) {
if (restriction === 'schema.numeric') {
return function (variable) {
return R.is.numeric(variable.type);
};
}
if (restriction === 'schema.factor') {
return function (variable) {
return R.is.factor(variable.type);
};
}
throw ('Unsupported type restriction');
}
function updateSelectedVariables(variables) {
if (variables.length === 0) {
$scope.selectionText = "Select variables...";
$scope.selectionTextLong = "No variables selected";
} else {
var text = _.reduce(variables, function (str, variable) {
return str === "" ? variable.name : str + ", " + variable.name;
}, "");
if (text.length > "Select variables...".length) {
$scope.selectionTextLong = text;
text = "Selected " + variables.length + " variables";
}
$scope.selectionText = text;
$scope.selectedVariables = variables;
}
$scope.configurationInvalid = $scope.selectedVariables.length === 0;
}
function setVariables() {
if ($scope.selectedDimRedMethod === undefined || d.schema === undefined) {
$scope.variables = [];
} else {
// FIXME: This is a sloppy implementation as I didn't think this out
// very well. Actually, it should allow for multiple types for
// group restriction.
var restrictions = $scope.selectedDimRedMethod.restrict,
matchesGroupRestriction = createGroupTypeRestrictionTest(restrictions.group_type),
matchesTypeRestriction = createTypeRestrictionTest(restrictions.type);
$scope.variables = _.filter(d.schema, matchesGroupRestriction);
$scope.variables = _.filter($scope.variables, matchesTypeRestriction);
$scope.variables = _.filter($scope.variables, function (variable) {
return variable.analysable;
});
}
}
$scope.selectionText = "Select variables...";
$scope.selectionTextLong = "No variables selected";
$scope.variables = [];
$scope.dimRedMethods = [];
$scope.configurationInvalid = true;
$scope.selectedDimRedMethod = $scope.dimRedMethods[0];
$scope.selectedVariables = [];
$scope.$watch('selectedDimRedMethod', function (newMethod) {
if (newMethod === undefined) { return; }
setVariables();
});
$scope.$on('DimRedPlot::variablesSelected', function (e, dimRedMethod) {
/*jslint unparam: true*/
$scope.dimRedMethods.some(function (method) {
if (method.name === dimRedMethod) {
$scope.selectedDimRedMethod = method;
return true;
}
return false;
});
setVariables();
var variables = [],
selectedVariables = DimRedPlot.selectedVariables();
_.forEach(selectedVariables, function (variable) {
$scope.variables.some(function (schemaVariable) {
if (schemaVariable.name === variable) {
variables.push(schemaVariable);
return true;
}
return false;
});
});
updateSelectedVariables(variables);
});
function updateCaOnTnf() {
$scope.selectedVariables = _.filter($scope.variables, function (variable) {
return variable.group === "Tetra nucleotide frequencies";
});
updateSelectedVariables($scope.selectedVariables);
if ($scope.selectedVariables.length > 2) {
$scope.reduceDimensionality();
}
}
/*jslint unparam: true */
$scope.$on('DataSet::schemaLoaded', function (e, schema) {
$scope.dataAvailable = true;
d.schema = schema;
setVariables();
});
/*jslint unparam: false */
$scope.$on('DataSet::filtered', updateCaOnTnf);
/*jslint unparam: true */
$scope.$on('Analytics::dimRedMethodsAvailable', function (e, methods) {
// ICoVeR: For now we only suppor CA on (T|P)NF, so we filter out all
// other dim. red. methods.
$scope.dimRedMethods = _.filter(methods, function (m) { return m.name === "ca"; });
$scope.selectedDimRedMethod = $scope.dimRedMethods[0];
setVariables();
});
/*jslint unparam: false */
$scope.$on('Analytics::dimensionalityReduced', function () {
$scope.configurationInvalid =
$scope.selectedVariables.length === 0
|| $scope.selectedDimRedMethod === undefined;
});
$scope.openSelectionDialog = function () {
var dialog = $modal.open({
templateUrl: 'js/templates/selectvars.html',
size: 'sm',
controller: 'VariableSelectionCtrl',
resolve: {
variables: function () {
return $scope.variables;
},
selected: function () {
return $scope.selectedVariables;
}
}
});
dialog.result.then(updateSelectedVariables);
};
$scope.reduceDimensionality = function () {
var drMethod = $scope.selectedDimRedMethod.name,
vars = _.pluck($scope.selectedVariables, 'name');
// For quick loading purposes we are making sure here that all variables requested are loaded
DataSet.get(vars, function () { return; });
$scope.configurationInvalid = true;
Analytics.reduce(drMethod, vars);
};
});
/*jslint indent: 2, todo:true, nomen:true */
/*global angular, d3, _ */
/*
ICoVeR - Interactive Contig-bin Verification and Refinement
Copyright 2015 Luxembourg Institute of Science and technology. All rights reserved.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
angular.module('contigBinningApp.controllers')
.controller('DimRedDisplayCtrl', function ($scope, $rootScope) {
'use strict';
$scope.clusters = [];
$scope.cluster = undefined;
function updateState(dimRedData) {
// NOTE: The backend calculates up to 12 clustering levels (at most).
var maxClusterCount = Math.min(dimRedData.projections.length, 13);
$scope.clusters = _.map(_.range(2, maxClusterCount),
function (val) {
return { count: val, label: String(val) };
});
$scope.clusters.unshift({ count: 0, label: "No clustering" });
$scope.cluster = $scope.clusters[0];
}
/*jslint unparam: true */
$scope.$on("Analytics::dimensionalityReduced", function (ev, method, session) {
session.getObject(updateState);
});
/*jslint unparam: false */
$scope.$watch('cluster', function (newCount) {
if (newCount !== undefined) {
$rootScope.$broadcast("DimRedDisplay::cluster", newCount.count);
}
});
});
/*jslint browser: true, todo:true, nomen: true, indent: 2 */
/*global angular, crpgl, list, d3, ocpu, _, $*/
/*
ICoVeR - Interactive Contig-bin Verification and Refinement
Copyright 2015 Luxembourg Institute of Science and technology. All rights reserved.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
angular.module('contigBinningApp.controllers')
.controller('DimRedPlotCtrl', function ($scope, $element, $window, DimRedPlot, DataSet, Color) {
'use strict';
var dimredplot = list.DimRedPlot();
function changeSelection() {
d3.select($element[0]).selectAll("div.dimredplot").call(dimredplot);
}
function resize() {
var div = d3.select($element[0]).selectAll("div.dimredplot").data([$scope.analysis]);
div.enter()
.append("div")
.attr("class", "dimredplot")
.style("height", "100%")
.style("width", "100%");
dimredplot
.width(div.node().clientWidth)
.height(div.node().clientHeight);
}
$scope.$on("DimRedPlot::resize", function (e, numOfPlots) {
/*jslint unparam:true*/
dimredplot.automaticResize(numOfPlots === 1);
dimredplot.invertPlotOrder(numOfPlots === 2 && $scope.analysis.plotIdx === 0);
resize();
changeSelection();
});
angular.element($window).bind('resize', resize);
$(document).ready(resize);
$scope.$on("DimRedPlot::selectionUpdated", function (ev, method) {
/*jslint unparam:true*/
if (method !== $scope.analysis.method[0]) {
dimredplot.individualSelections(DimRedPlot.selections.individual);
}
dimredplot.variableInfluences(DimRedPlot.influences.variable);
changeSelection();
});
$scope.$on("DimRedPlot::variablesSelected", function (ev, method) {
/*jslint unparam:true*/
if (method !== $scope.analysis.method[0]) {
dimredplot.variableSelections(DimRedPlot.selections.variable);
}
dimredplot.individualInfluences(DimRedPlot.influences.individual);
changeSelection();
});
function setColor() {
/*jslint todo:true*/
var variable = Color.colorVariable(),
schema;
if (variable !== undefined) {
schema = _.find(DataSet.schema(), "name", variable);
}
// TODO: Currently there is no support for colour mapping categorical variables,
// so for now we will just ignore these. In the future we may just want to upgrade
// the colourmap chart or not show a colour map, just colour the points.
if (schema === undefined) {
return;
}
DataSet.get([variable], function (rows) {
var variableValues = {};
_.each(rows, function (row) {
variableValues[row.row] = row[variable];
});
dimredplot
.colorFunction(Color.colorFn())
.colorVariableName(variable)
.colorVariableValues(variableValues);
});
}
function updatePlot() {
$scope.analysis.flags = {pointsChanged: true};
function calculateContribution(axesIdx) {
if ($scope.analysis.individualProjections === undefined) {
return;
}
var xyContributions = {},
xVariance = $scope.analysis.explainedVariance[axesIdx[0]],
yVariance = $scope.analysis.explainedVariance[axesIdx[1]];
_.forEach($scope.analysis.individualProjections, function (projection) {
xyContributions[projection.id] = (projection.contrib[axesIdx[0]] * xVariance +
projection.contrib[axesIdx[1]] * yVariance) /
(xVariance + yVariance);
});
DataSet.addVariable($scope.analysis.method[0].toUpperCase() + " x+y contribution", xyContributions, "numeric", "Analytics");
}
dimredplot
.originSize(30)
.originVisible(true)
.on("changeVariableSelection", function (drp) {
$scope.$apply(function () {
DimRedPlot.changeVariableSelection($scope.analysis.method[0], drp.variableSelections());
});
})
.on("changeIndividualSelection", function (drp) {
$scope.$apply(function () {
DimRedPlot.changeIndividualSelection($scope.analysis.method[0], drp.individualSelections());
});
})
.on("changeAxes", function (drp, axesIdx) {
/*jslint unparam:true*/
calculateContribution(axesIdx);
})
.individualSelections(DimRedPlot.selections.individual)
.variableSelections(DimRedPlot.selections.variable)
.individualInfluences(DimRedPlot.influences.individual)
.variableInfluences(DimRedPlot.influences.variable);
resize();
calculateContribution([0, 1]);
setColor();
changeSelection();
}
$scope.$on("Colors::changed", function () {
setColor();
changeSelection();
});
updatePlot();
});
/*jslint indent: 2, nomen: true */
/*global angular, _*/
/*
ICoVeR - Interactive Contig-bin Verification and Refinement
Copyright 2015 Luxembourg Institute of Science and technology. All rights reserved.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
angular.module('contigBinningApp.controllers')
.controller('ESCGCtrl', function ($rootScope, $scope, DataSet) {
'use strict';
var d = {};
$scope.uniqueGenes = 0;
$scope.multiCopyGenes = '0 / 0';
$scope.missingGenes = 0;
$scope.totalGenes = 0;
function updateGeneCounts(data) {
var contigs = d.contigs,
escg = {},
multiCopyGenes = 0,
additionalCopies = 0;
_.forEach(data, function (datum) {
var contig = datum.CONTIG,
asseccesions;
if (contigs.hasOwnProperty(contig)) {
asseccesions = _.isArray(contigs[contig]) ? contigs[contig] : [contigs[contig]];
_.forEach(asseccesions, function (a) {
escg[a] = escg[a] === undefined ? 1 : escg[a] + 1;
});
}
});
_.forEach(Object.getOwnPropertyNames(escg), function (asseccion) {
if (escg[asseccion] > 1) {
multiCopyGenes = multiCopyGenes + 1;
additionalCopies = additionalCopies + escg[asseccion] - 1;
}
});
$scope.uniqueGenes = Object.getOwnPropertyNames(escg).length;
$scope.multiCopyGenes = multiCopyGenes + ' / ' + additionalCopies;
$scope.missingGenes = d.asseccesions.length - $scope.uniqueGenes;
$scope.totalGenes = $scope.uniqueGenes + additionalCopies;
}
/*jslint unparam: true */
$rootScope.$on('App::configurationLoaded', function (e, cfg) {
d.asseccesions = cfg.escg.asseccion;
d.contigs = cfg.escg.contigs;
DataSet.get('CONTIG', updateGeneCounts);
});
$rootScope.$on('DataSet::brushed', function (e, data) {
if (data.length > 0) {
updateGeneCounts(data);
} else {
updateGeneCounts(DataSet.data());
}
});
$rootScope.$on('DataSet::filtered', function (e, data) {
updateGeneCounts(data);
});
/*jslint unparam: false */
});
/*jslint indent: 2, nomen: true */
/*global angular, _*/
/*
ICoVeR - Interactive Contig-bin Verification and Refinement
Copyright 2015 Luxembourg Institute of Science and technology. All rights reserved.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
angular.module('contigBinningApp.controllers')
.controller('ExportCtrl', function ($rootScope, $scope, DataSet) {
'use strict';
var d = {
all: [],
rows: []
};
$scope.url = undefined;
$scope.idStrings = "";
$scope.exportMethods = ["all"];
$scope.exportMethod = $scope.exportMethods[0];
/*jslint unparam: true */
$rootScope.$on("DataSet::brushed", function (ev, rows) {
d.rows = rows;
// Reset the url on brush change to avoid confusion of what is being
// exported when clicking the url.
$scope.url = undefined;
if (rows.length > 0) {
$scope.exportMethods = ["all", "brushed"];
$scope.exportMethod = $scope.exportMethods[1];
} else {
$scope.exportMethods = ["all"];
$scope.exportMethod = $scope.exportMethods[0];
}
});
/*jslint unparam: false */
/*jslint unparam: true */
$scope.$on('DataSet::schemaLoaded', function (e, schema) {
DataSet.get(["CONTIG"], function (data) {
d.all = data;
});
});
/*jslint unparam: false */
$scope.export = function () {
var data = d.rows.length > 0 ? d.rows : d.all,
rows = _.map(data, function (row) { return row.CONTIG; });
$scope.idStrings = _.reduce(rows, function (str, id) {
return str + (str.length > 0 ? "\n" : "") + id;
}, "");
};
});
/*jslint indent: 2 */
/*global angular */
/*
ICoVeR - Interactive Contig-bin Verification and Refinement
Copyright 2015 Luxembourg Institute of Science and technology. All rights reserved.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
angular.module('contigBinningApp.controllers')
.controller('FilterCtrl', function ($scope, DataSet) {
'use strict';
$scope.itemsBrushed = false;
$scope.dataFiltered = false;
$scope.filteringInProgress = false;
$scope.keepSelected = function () {
$scope.filteringInProgress = true;
DataSet.filter(DataSet.FilterMethod.KEEP);
};
$scope.removeSelected = function () {
$scope.filteringInProgress = true;
DataSet.filter(DataSet.FilterMethod.REMOVE);
};
$scope.reloadData = function () {
DataSet.filter(DataSet.FilterMethod.RESET);
};
$scope.$on('DataSet::loaded', function () { $scope.dataFiltered = false; });
$scope.$on('DataSet::filtered', function () {
$scope.filteringInProgress = false;
$scope.dataFiltered = DataSet.filtered();
});
/*jslint unparam: true */
$scope.$on('DataSet::brushed', function (e, rows) {
$scope.itemsBrushed = rows.length > 0;
});
/*jslint unparam: false */
});
/*jslint indent: 2, nomen: true */
/*global angular, _*/
/*
ICoVeR - Interactive Contig-bin Verification and Refinement
Copyright 2015 Luxembourg Institute of Science and technology. All rights reserved.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
angular.module('contigBinningApp.controllers')
.controller('ManualColoringCtrl', function ($scope, Color) {
'use strict';
$scope.colors = [];
$scope.manualColoringEnabled = false;
$scope.itemsBrushed = false;
$scope.$on("Colors::changed", function () {
if (Color.colorVariable() === "Manual selection") {
if (!$scope.manualColoringEnabled || $scope.colors !== Color.colorScheme()) { // Manual selection is already on
$scope.manualColoringEnabled = true;
$scope.colors = Color.colorScheme();
}
} else {
$scope.manualColoringEnabled = false;
}
});
$scope.colorSelection = function (color) {
Color.colorBrushed(color);
};
$scope.$on("DataSet::brushed", function (e, rows) {
/*jslint unparam:true*/
$scope.itemsBrushed = rows.length > 0;
});
});
/*jslint indent: 2 */
/*global angular */
/*
ICoVeR - Interactive Contig-bin Verification and Refinement
Copyright 2015 Luxembourg Institute of Science and technology. All rights reserved.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
angular.module('contigBinningApp.controllers')
.controller('NameHighlightCtrl', function ($scope, DataSet, ParCoords) {
'use strict';
var nameHash = {},
variables = [];
function buildNameHash(data) {
nameHash = {};
data.forEach(function (d, dataIndex) {
variables.forEach(function (v) {
nameHash[d[v]] = dataIndex;
});
});
$scope.noHighlightAvailable = false;
// if a row is highlighted before the event that caused the rebuild
// we still want it to be highlighted after
$scope.highlightRow();
}
/*jslint unparam: true */
$scope.$on('DataSet::schemaLoaded', function (e, schema) {
variables = [];
schema.forEach(function (d) {
if (d.group === "Id") {
variables.push(d.name);
}
});
if (variables.length > 0) {
DataSet.get(variables, buildNameHash);
}
});
/*jslint unparam: false */
/*jslint unparam: true */
$scope.$on('DataSet::filtered', function (e, filteredData) {
// remove highlight... it will be reapplied once the filter returns
ParCoords.highlightRow(-1);
if (variables.length > 0) {
buildNameHash(filteredData);
}
});
/*jslint unparam: false */
$scope.noHighlightAvailable = true;
$scope.highlightRow = function () {
// called by ng_change directive on the rowName input in the UI
var highlightIndex = -1;
if (nameHash.hasOwnProperty($scope.rowName)) {
highlightIndex = nameHash[$scope.rowName];
}
ParCoords.highlightRow(highlightIndex);
};
});
/*jslint indent: 2 */
/*global angular */
/*
ICoVeR - Interactive Contig-bin Verification and Refinement
Copyright 2015 Luxembourg Institute of Science and technology. All rights reserved.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
angular.module('contigBinningApp.controllers')
.controller('NameSelectionCtrl', function ($scope, $modalInstance, selectedName) {
'use strict';
// https://stackoverflow.com
// /questions/21379173/angularjs-ui-modal-and-select-doesnt-update-the-scope-values
$scope.data = {
selectedName: "",
placeholderName: selectedName
};
$scope.ok = function () {
if ($scope.data.selectedName === "") {
$scope.data.selectedName = $scope.data.placeholderName;
}
$modalInstance.close($scope.data.selectedName);
};
$scope.cancel = function () {
$modalInstance.dismiss();
};
});
/*jslint browser:true, unparam: true, indent: 2, nomen: true */
/*global angular, d3, $, _*/
/*
ICoVeR - Interactive Contig-bin Verification and Refinement
Copyright 2015 Luxembourg Institute of Science and technology. All rights reserved.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
angular.module('contigBinningApp.controllers')
.controller('ParcoordsCtrl', function ($scope, $window, $element, DataSet, ParCoords) {
'use strict';
/// private Controller vars
var d = {
parcoords: d3.parcoords()($element[0]),
currentHighlightRow: -1,
orderedVariables: []
};
/// private controller functions
function render() {
if ($scope.brushed === undefined || $scope.brushed.length !== 0) {
$scope.brushed = [];
DataSet.brush($scope.brushed, "parcoords");
}
d.parcoords
.brushReset()
.autoscale()
.updateAxes()
.render();
}
function resize() {
d.parcoords
.width($element[0].clientWidth)
.height($element[0].clientHeight)
.resize();
render();
}
/*
function transformBrushExtents() {
var brushData = {extents: {}, categories: {}},
b = null,
getDomain = function (item, index) {
if (item >= d.parcoords.brushExtents()[b][0] && item <= d.parcoords.brushExtents()[b][1]) {
brushData.categories[b].push(d.parcoords.yscale[b].domain()[index]);
}
};
for (b in d.parcoords.brushExtents()) {
if (d.parcoords.brushExtents().hasOwnProperty(b)) {
if (d.parcoords.types()[b] === "string") {
brushData.categories[b] = [];
d.parcoords.yscale[b].range().forEach(getDomain);
} else {
brushData.extents[b] = d.parcoords.brushExtents()[b];
}
}
}
return brushData;
}
*/
function setDimensions() {
var dims = _.pluck(ParCoords.selectedVariables, "name"),
types = {},
averages = {},
brushedData = d.parcoords.brushed(),
dimensionsChanged;
d.orderedVariables = _.filter(d.orderedVariables, function (variable) {
return _.contains(dims, variable);
});
_.each(dims, function (variable) {
if (!_.contains(d.orderedVariables, variable)) {
d.orderedVariables.push(variable);
}
});
_.each(ParCoords.selectedVariables, function (dim) {
if (dim.type === "factor") {
types[dim.name] = "string";
} else {
types[dim.name] = "number";
}
});
// We need to make sure that the scales for the dimensions we want are calculated,
// since we need those scales in the next block of code.
dimensionsChanged = d.orderedVariables.length !== d.parcoords.dimensions().length || d.orderedVariables.some(function (dimension) {
return d.parcoords.dimensions().indexOf(dimension) === -1;
});
d.parcoords.dimensions(d.orderedVariables);
if (dimensionsChanged) {
d.parcoords
.types(types)
.autoscale()
.updateAxes();
}
if (ParCoords.variableSorting !== "none") {
if (brushedData === false) {
brushedData = d.parcoords.data();
}
_.each(d.orderedVariables, function (variable) {
var catCounts = {},
maxCategory,
maxCount = 0;
if (types[variable] === "string") {
_.each(brushedData, function (row) {
var category = row[variable];
if (catCounts[category] === undefined) {
catCounts[category] = 1;
} else {
catCounts[category] += 1;
}
if (catCounts[category] > maxCount) {
maxCategory = category;
}
});
averages[variable] = maxCategory;
} else {
averages[variable] = _.sum(brushedData, variable) / brushedData.length;
}
});
d.parcoords.reorder(averages);
}
}
/// Initialization
d.parcoords
.mode("queue")
.brushedColor("black")
.alphaOnBrushed(0.5)
.rate(250)
.alpha(0.05)
.render()
.createAxes()
.brushMode("1D-axes-multi")
.reorderable()
.dimensionTitleRotation(-25)
.on("brushend", function () {
// NOTE: the brushend event from parcoords is "outside" angular, so we
// have to wrap it in $scope.$apply to make sure that other
// controllers are updated appropriately.
$scope.$apply(function () {
var brushed = d.parcoords.brushed();
// d3.parcoords.js returns the full data set when no brush is set.
// This can't be changed in the component for legacy reasons. However,
// when no brushes are set, no data is brushed, so let's work around
// this issue here.
brushed = brushed.length === d.parcoords.data().length ? [] : brushed;
DataSet.brush(brushed, "parcoords");
if (ParCoords.variableSorting !== "none") {
setDimensions();
d.parcoords.render();
}
});
})
.on("axesreorder", function (variables) {
d.orderedVariables = variables;
});
function updateSharedAxes() {
var dims = _.pluck(ParCoords.sharedScaleVariables, "name"),
domain;
// First we determine the min/max required extents of the domain
domain = _.reduce(dims, function (widest, variable) {
var current = d.parcoords.yscale[variable].domain();
return [
Math.min(widest[0], current[0]),
Math.max(widest[1], current[1])
];
}, [Infinity, -Infinity]);
// Next, we change the domain of the variables that have to share scale.
_.each(dims, function (dim) {
d.parcoords.scale(dim, domain);
});
d.parcoords
.brushReset()
.updateAxes()
.render();
}
// function to be used as callback when data is requested
function loadData(data) {
setDimensions();
d.parcoords.data(data);
render();
if (ParCoords.sharedScaleVariables.length > 0) {
updateSharedAxes();
}
// if there is a row currently highlighted and it exists in the new dataset
// we want to ensure it is still highlighted
if (d.currentHighlightRow > -1) {
d.parcoords.highlight([d.parcoords.data()[d.currentHighlightRow]]);
}
}
// function to be used as callback when new varaibles
// are requested to be added on to existing data
function loadAdditionalData(data) {
setDimensions();
d.parcoords.data().forEach(function (d, i) {
_.forEach(data[i], function (val, key) {
d[key] = val;
});
});
render();
}
function highlightRow(itemIndex) {
d.currentHighlightRow = itemIndex;
if (d.currentHighlightRow > -1) {
d.parcoords.highlight([d.parcoords.data()[d.currentHighlightRow]]);
} else {
d.parcoords.unhighlight();
}
}
angular.element($window).bind('resize', resize);
$(document).ready(resize);
/// Scope extensions
// For some reason $scope.$watch(ParCoords.selectedVariables), doesn't
// work. So for now, I'll fall back to the more reliable broadcast
//meganism.
$scope.$on("ParCoords::selectedVariablesChanged", function () {
var dims = _.pluck(ParCoords.selectedVariables, "name"),
newVariables = _.difference(dims, d.parcoords.dimensions()),
missingVariables = _.difference(d.parcoords.dimensions(), dims),
existingVariables = _.intersection(d.parcoords.dimensions(), dims);
// Comparing variable names to existing variables and only requesting new ones
if (existingVariables.length === 0) {
DataSet.get(dims, loadData);
} else {
if (newVariables.length > 0) {
DataSet.get(newVariables, loadAdditionalData);
} else if (missingVariables.length > 0 || ParCoords.variablesToUpdate.length !== 0) {
if (ParCoords.variablesToUpdate.length !== 0) {
DataSet.get(ParCoords.variablesToUpdate, loadAdditionalData);
}
setDimensions();
render();
ParCoords.variablesToUpdate = [];
}
}
});
$scope.$on("ParCoords::brushedColorChanged", function (e, color) {
/*jslint unparam:true*/
d.parcoords.brushedColor(color);
d.parcoords.renderBrushed();
});
$scope.$on("DataSet::brushed", function (ev, brushed, method) {
if (method === "parcoords") {
return;
}
d.parcoords.brushReset();
if (brushed.length === 0) {
brushed = d.parcoords.data();
}
d.parcoords.brushed(brushed);
if (ParCoords.variableSorting !== "none") {
setDimensions();
d.parcoords.render();
}
d.parcoords.renderBrushed();
});
$scope.$on("ParCoords::variableSortingChanged", function () {
setDimensions();
d.parcoords.render();
});
$scope.$on("ParCoords::scaleSharingVariablesChanged", function () {
if (ParCoords.sharedScaleVariables.length > 0) {
updateSharedAxes();
} else {
d.parcoords
.autoscale()
.updateAxes()
.render();
}
});
$scope.$on("ParCoords::brushPredicateChanged", function () {
d.parcoords.brushPredicate(ParCoords.brushPredicate).renderBrushed();
});
$scope.$on("DataSet::dataLoaded", function (ev, data) {
d.parcoords.data(data);
render();
});
$scope.$on("DataSet::filtered", function (ev, filteredData) {
loadData(filteredData);
});
$scope.$on("Colors::changed", function (e, colors) {
function colorfn(d, i) {
return colors.hasOwnProperty(d.row) ? colors[d.row] : "#000";
}
d.parcoords.color(colorfn);
render();
});
$scope.$on("Opacity::changed", function (e, opacity) {
d.parcoords.alpha(opacity).render();
});
ParCoords.setHighlightFunction(highlightRow);
});
/*jslint indent: 2*/
/*global angular */
/*
ICoVeR - Interactive Contig-bin Verification and Refinement
Copyright 2015 Luxembourg Institute of Science and technology. All rights reserved.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
angular.module('contigBinningApp.controllers')
.controller('ParCoordsVarsCtrl', function ($modal, $scope, ParCoords) {
'use strict';
$scope.parcoords = ParCoords;
$scope.brushPredicate = $scope.parcoords.brushPredicates[0];
$scope.variableSorting = "none";
$scope.noSharedScales = true;
$scope.openSelectionDialog = function () {
var dialog = $modal.open({
templateUrl: 'js/templates/selectvars.html',
size: 'sm',
controller: 'VariableSelectionCtrl',
resolve: {
variables: function () {
return $scope.parcoords.variables;
},
selected: function () {
return $scope.parcoords.selectedVariables;
}
}
});
dialog.result.then($scope.parcoords.updateSelectedVariables);
};
$scope.$watch('variableSorting', function (sortingMethod) {
$scope.parcoords.updateSortingMethod(sortingMethod);
});
$scope.openScaleBindDialog = function () {
var dialog = $modal.open({
templateUrl: 'js/templates/selectvars.html',
size: 'sm',
controller: 'VariableSelectionCtrl',
resolve: {
variables: function () {
return $scope.parcoords.selectedVariables;
},
selected: function () {
return $scope.parcoords.sharedScaleVariables;
}
}
});
dialog.result.then(function (variables) {
$scope.parcoords.shareScales(variables);
$scope.noSharedScales = variables.length === 0;
});
};
$scope.resetScales = function () {
$scope.parcoords.resetScales();
$scope.noSharedScales = true;
};
$scope.$watch("brushPredicate", function (newPredicate) {
$scope.parcoords.updateBrushPredicate(newPredicate);
});
});
/*jslint indent: 2, nomen: true */
/*global angular, _, d3 */
/*
ICoVeR - Interactive Contig-bin Verification and Refinement
Copyright 2015 Luxembourg Institute of Science and technology. All rights reserved.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
angular.module('contigBinningApp.controllers')
.controller('PlotCtrl', function ($scope, DimRedPlot) {
'use strict';
$scope.analyses = [];
$scope.dimredplotWidth = "col-lg-12";
$scope.hideOptions = false;
$scope.sliding = {"left": 0};
function switchOptions() {
if ($scope.hideOptions) {
$scope.sliding = {"transform": "translate(0,0)"};
$scope.hideOptions = false;
} else {
$scope.sliding = {"transform": "translate(-90%, 0)"};
$scope.hideOptions = true;
}
}
$scope.switchOptions = function () {
switchOptions();
};
// Makes sure that the labels of points are no longer than 80px
function createWrappedLabels(points) {
var testText = d3.select("body").append("div").style("float", "left");
testText.style("font-size", "8px");
function wrap(d, i) {
/*jslint unparam:true*/
var textLength,
string,
desiredStringLength,
label = d.id;
if (d.label !== undefined) {
label = d.label;
}
testText.text(label);
textLength = testText.node().offsetWidth;
string = label;
desiredStringLength = Math.ceil(80 / textLength * string.length);
string = string.slice(0, desiredStringLength);
testText.text(string);
textLength = testText.node().clientWidth;
while (textLength > 80 && string.length > 0) {
string = string.slice(0, -1);
testText.text(string);
textLength = testText.node().clientWidth;
}
d.wrappedLabel = string;
}
points.forEach(wrap);
testText.remove();
}
function updatePlot(data) {
$scope.$apply(function () {
var index;
DimRedPlot.addProcessedData(data.method[0], data.processedData);
if (data.variableProjections !== undefined) {
createWrappedLabels(data.variableProjections);
}
if (data.individualProjections !== undefined) {
createWrappedLabels(data.individualProjections);
}
index = _.findIndex($scope.analyses, {'method': data.method});
if (index === -1) {
data.plotIdx = $scope.analyses.length;
$scope.analyses.push(data);
} else {
data.plotIdx = index;
$scope.analyses[index] = data;
}
$scope.dimredplotWidth = "col-lg-" + (12 / $scope.analyses.length);
if ($scope.analyses.length > 1) {
if (!$scope.hideOptions) {
switchOptions();
}
}
});
$scope.$broadcast("DimRedPlot::resize", $scope.analyses.length);
}
$scope.$on("Analytics::dimensionalityReduced", function (ev, method, session) {
/*jslint unparam: true */
session.getObject(updatePlot);
});
});
/*jslint indent: 2, nomen: true */
/*global angular, _ */
/*
ICoVeR - Interactive Contig-bin Verification and Refinement
Copyright 2015 Luxembourg Institute of Science and technology. All rights reserved.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
angular.module('contigBinningApp.controllers')
.controller('TagCtrl', function ($scope, DataSet, Tag) {
'use strict';
// modify tag:
$scope.tags = [];
$scope.itemsBrushed = false;
$scope.modifyTag = "";
$scope.modifyTagExists = false;
$scope.placeholder = "selection1";
function checkIfMofidyTagExists() {
$scope.modifyTagExists = _.some($scope.tags, function (tag) {
return tag === $scope.modifyTag;
});
}
$scope.$on("Tag::tagsLoaded", function () {
$scope.tags = Tag.tags();
$scope.selectedTags = _.filter($scope.selectedTags, function (selectedTag) {
return _.some($scope.tags, function (tag) {
return selectedTag === tag;
});
});
checkIfMofidyTagExists();
});
$scope.$watch("modifyTag", function () {
checkIfMofidyTagExists();
});
$scope.createTag = function () {
Tag.storeTag($scope.modifyTag);
};
$scope.addToTag = function () {
Tag.appendToTag($scope.modifyTag);
};
// select tags:
$scope.dataFiltered = false;
$scope.filteringInProgress = false;
$scope.selectedTags = [];
$scope.enableDeselect = false;
$scope.removeTags = function () {
Tag.removeTags($scope.selectedTags);
};
$scope.selectTagged = function () {
Tag.selectTagged($scope.selectedTags);
};
$scope.deselectTags = function () {
Tag.selectTagged([]);
$scope.enableDeselect = false;
};
$scope.keepSelected = function () {
$scope.selectTagged();
$scope.filteringInProgress = true;
DataSet.filter(DataSet.FilterMethod.KEEP);
};
$scope.removeSelected = function () {
$scope.selectTagged();
$scope.filteringInProgress = true;
DataSet.filter(DataSet.FilterMethod.REMOVE);
};
$scope.reloadData = function () {
DataSet.filter(DataSet.FilterMethod.RESET);
};
$scope.$on('DataSet::loaded', function () {
$scope.dataFiltered = false;
$scope.tags = Tag.tags();
});
$scope.$on('DataSet::filtered', function () {
$scope.filteringInProgress = false;
$scope.dataFiltered = DataSet.filtered();
Tag.removeNonPresentTags();
});
$scope.$on('DataSet::brushed', function (e, rows, method) {
/*jslint unparam: true*/
$scope.enableDeselect = method === "tag";
$scope.itemsBrushed = rows.length > 0;
});
});
/*jslint indent: 2 */
/*global angular, $ */
/*
ICoVeR - Interactive Contig-bin Verification and Refinement
Copyright 2015 Luxembourg Institute of Science and technology. All rights reserved.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
angular.module('contigBinningApp.controllers')
.controller('ThemeCtrl', function ($scope, ParCoords) {
'use strict';
var link = $('#maincss');
$scope.theme = 'light';
$scope.$watch('theme', function (newTheme) {
var url = 'css/' + newTheme + '.css';
if (link.attr('href') !== url) {
link.attr('href', url);
}
ParCoords.changeTheme(newTheme);
});
});
/*jslint indent: 2 */
/*global angular */
/*
ICoVeR - Interactive Contig-bin Verification and Refinement
Copyright 2015 Luxembourg Institute of Science and technology. All rights reserved.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
angular.module('contigBinningApp.controllers')
.controller('VariableSelectionCtrl', function ($scope, $modalInstance, variables, selected) {
'use strict';
$scope.variables = variables;
// https://stackoverflow.com
// /questions/21379173/angularjs-ui-modal-and-select-doesnt-update-the-scope-values
$scope.selected = {
variables: selected
};
$scope.ok = function () {
$modalInstance.close($scope.selected.variables);
};
$scope.cancel = function () {
$modalInstance.dismiss();
};
});
/*jslint todo:true, nomen: true, indent: 2 */
/*global angular, ocpu, _ */
/*
ICoVeR - Interactive Contig-bin Verification and Refinement
Copyright 2015 Luxembourg Institute of Science and technology. All rights reserved.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
angular.module('contigBinningApp.services')
.service('Analytics', function ($rootScope, DataSet) {
'use strict';
var d = {
clusterMethods: [],
dimRedMethods: []
};
/*jslint unparam: true */
$rootScope.$on("App::configurationLoaded", function (ev, appConfig) {
d.clusterMethods = _.reduce(_.keys(appConfig.cluster), function (methods, method) {
methods.push({ name: method, args: appConfig.cluster[method] });
return methods;
}, []);
$rootScope.$broadcast("Analytics::clusterMethodsAvailable", d.clusterMethods);
d.dimRedMethods = _.reduce(_.keys(appConfig.dimred), function (methods, method) {
var cfg = appConfig.dimred[method];
cfg.name = method;
methods.push(cfg);
return methods;
}, []);
$rootScope.$broadcast("Analytics::dimRedMethodsAvailable", d.dimRedMethods);
});
/*jslint unparam: false */
return {
clusterMethods: function () {
return d.clusterMethods;
},
dimRedMethods: function () {
return d.dimRedMethods;
},
cluster: function (method, variables, args, id) {
var fnArgs = {
vars: variables,
identifier: id
};
if (DataSet.rows()) {
fnArgs.rows = DataSet.rows();
}
_.each(_.keys(args), function (key) {
fnArgs[key] = args[key];
});
ocpu.call("cluster." + method, fnArgs, function () {
$rootScope.$broadcast("Analytics::dataUpdated", id);
});
},
reduce: function (method, variables) {
var fnArgs = {
vars: variables
};
if (DataSet.rows()) {
fnArgs.rows = DataSet.rows();
}
ocpu.call("dimred." + method, fnArgs, function (session) {
$rootScope.$broadcast("Analytics::dimensionalityReduced", method, session);
});
}
};
});
/*jslint todo:true, unparam: true, nomen: true, indent: 2 */
/*global angular */
/*
ICoVeR - Interactive Contig-bin Verification and Refinement
Copyright 2015 Luxembourg Institute of Science and technology. All rights reserved.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
angular.module('contigBinningApp.services')
.service('assert', function () {
'use strict';
return {
strictEqual: function (actual, expected, message) {
var sEqual = (actual === expected),
msg = "Expected strict equality";
msg += (message !== undefined) ? ": " + message : "";
if (!sEqual) { throw new Error(msg); }
},
notStrictEqual: function (actual, expected, message) {
var sNotEqual = (actual !== expected),
msg = "Expected strict unequality";
msg += (message !== undefined) ? ": " + message : "";
if (!sNotEqual) { throw new Error(msg); }
}
};
});
/*jslint indent: 2, white: false, nomen: true */
/*global angular, _, d3 */
/*
ICoVeR - Interactive Contig-bin Verification and Refinement
Copyright 2015 Luxembourg Institute of Science and technology. All rights reserved.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
angular.module('contigBinningApp.services')
.service('Color', function ($rootScope, DataSet, R) {
'use strict';
var d = {
dataSchema: undefined,
coloring: {
schemeName: undefined,
scheme: undefined,
method: undefined,
colorFn: undefined,
variable: undefined
},
schemes: {
numeric: {
value: {
blue_to_brown: ["steelblue", "brown"],
blue_to_yellow: ["blue", "yellow"],
cool: ["#00FFFF", "magenta"]
},
decile: {
yellow_to_red: d3.colorbrewer.YlOrRd[10],
yellow_to_green: d3.colorbrewer.YlGn[10],
blue_to_green: d3.colorbrewer.BuGn[10],
blue_to_purple: d3.colorbrewer.BuPu[10],
blues: d3.colorbrewer.Blues[10]
}
},
factor: {
value: {
"paired (12 colors)": d3.colorbrewer.Paired[12],
"set3 (12 colors)": d3.colorbrewer.Set3[12],
"category A (20 colors)": d3.scale.category20().range(),
"category B (20 colors)": d3.scale.category20b().range(),
"category C (20 colors)": d3.scale.category20c().range(),
"red_yellow_blue (11 colors)": d3.colorbrewer.RdYlBu[11]
// the qualitiative set will calulate the number of clusters before application
// qualitative_set: [] //rainbow_hcl(30, c = 50, l = 70, start = 0, end = 360*(30-1)/30)
}
}
}
},
cfg = {
numeric: {
Value: _.keys(d.schemes.numeric.value),
Decile: _.keys(d.schemes.numeric.decile)
//"Z-score" = c("RedToBlue", "Spectral")
},
factor: {
Value: _.keys(d.schemes.factor.value)
}
};
function variableType(variable) {
return _.result(_.find(d.dataSchema, { name: variable }), 'type');
}
function colorFactorValue(colorVariable, colorScheme) {
DataSet.get([colorVariable], function (data) {
var domain = _.pluck(_.uniq(data, colorVariable), colorVariable),
colored = {};
d.coloring.colorFn = d3.scale.ordinal();
d.coloring.colorFn
.domain(domain)
.range(d.schemes.factor.value[colorScheme]);
_.each(data, function (datum) {
colored[datum.row] = d.coloring.colorFn(datum[colorVariable]);
});
d.coloring.scheme = d.schemes.factor.value[colorScheme];
$rootScope.$broadcast("Colors::changed", colored);
});
}
function colorNumericValue(colorVariable, colorScheme) {
DataSet.get([colorVariable], function (data) {
var domain = d3.extent(data, function (datum) { return datum[colorVariable]; }),
colored = {};
d.coloring.colorFn = d3.scale.linear();
d.coloring.colorFn
.domain(domain)
.range(d.schemes.numeric.value[colorScheme])
.interpolate(d3.interpolateLab);
_.each(data, function (datum) {
colored[datum.row] = d.coloring.colorFn(datum[colorVariable]);
});
d.coloring.scheme = d.schemes.numeric.value[colorScheme];
$rootScope.$broadcast("Colors::changed", colored);
});
}
// Puts 10 percent of the data items, ordered by color variabel in the same
// bin.
function colorNumericDecile(colorVariable, colorScheme) {
DataSet.get([colorVariable], function (data) {
var colored = {},
binSize = Math.round(data.length / 10),
currentBin = 0,
currentBinSize = 0,
lastValue,
colorStepValues = [];
data.sort(function (a, b) {
return +a[colorVariable] - +b[colorVariable];
});
colorScheme = d.schemes.numeric.decile[colorScheme];
_.each(data, function (row) {
var value = row[colorVariable];
if (currentBinSize >= binSize && currentBin < 9 && value !== lastValue) {
currentBin = currentBin + 1;
currentBinSize = 0;
colorStepValues.push((value + lastValue) / 2);
}
currentBinSize = currentBinSize + 1;
lastValue = value;
colored[row.row] = colorScheme[currentBin];
});
d.coloring.colorFn = function (value) {
var bin = 0;
_.each(colorStepValues, function (stepValue) {
if (value > stepValue) {
bin += 1;
} else {
return;
}
});
return colorScheme[bin];
};
d.coloring.scheme = d.schemes.numeric.decile[colorScheme];
$rootScope.$broadcast("Colors::changed", colored);
});
}
function colorNumeric(colorVariable, colorMethod, colorScheme) {
switch (colorMethod) {
case "Value":
colorNumericValue(colorVariable, colorScheme);
break;
case "Decile":
colorNumericDecile(colorVariable, colorScheme);
break;
case "Z-score":
break;
default:
throw "Unsupported color method:" + colorMethod;
}
}
function colorFactor(colorVariable, colorMethod, colorScheme) {
switch (colorMethod) {
case "Value":
colorFactorValue(colorVariable, colorScheme);
break;
default:
throw "Unsupported color method:" + colorMethod;
}
}
function colorManual(colorScheme) {
var data = DataSet.data(),
rowColors = {};
d.coloring.colorFn = function () {
return "steelblue";
};
_.forEach(data, function (row) {
rowColors[row.row] = "steelblue";
});
d.coloring.scheme = d.schemes.factor.value[colorScheme];
DataSet.addVariable("Manual selection", rowColors, "factor", "Colors", "steelblue");
$rootScope.$broadcast("Colors::changed", rowColors);
}
function color(variable, colorMethod, colorScheme) {
var type = variableType(variable);
d.coloring.variable = variable;
d.coloring.method = colorMethod;
d.coloring.schemeName = colorScheme;
if (R.is.factor(type)) {
if (variable === "Manual selection") {
colorManual(colorScheme);
} else {
colorFactor(variable, colorMethod, colorScheme);
}
} else if (R.is.numeric(type)) {
colorNumeric(variable, colorMethod, colorScheme);
} else {
throw type + " is an unsupported data type";
}
}
/*jslint unparam: true */
$rootScope.$on("DataSet::schemaLoaded", function (ev, schema) {
d.dataSchema = schema;
});
/*jslint unparam: false */
$rootScope.$on('DataSet::analyticsUpdated', function (e, analyticsSchema) {
/*jslint unparam:true*/
if (analyticsSchema.type !== "numeric" && d.coloring.variable === undefined) {
return; // We do not want automatic colouring on clustering
}
if (d.coloring.variable === undefined) {
d.coloring.method = "Value";
d.coloring.schemeName = "blue_to_brown";
}
if (d.coloring.variable === undefined || d.coloring.variable === analyticsSchema.name) {
color(analyticsSchema.name, d.coloring.method, d.coloring.schemeName);
}
});
$rootScope.$on("DataSet::initialDataLoaded", function () {
DataSet.addVariable("Manual selection", {}, "factor", "Colors", "steelblue");
});
return {
configuration: function () {
return cfg;
},
color: color,
colorScheme: function () {
return d.coloring.scheme;
},
colorSchemeName: function () {
return d.coloring.schemeName;
},
colorMethod: function () {
return d.coloring.method;
},
colorFn: function () {
return d.coloring.colorFn;
},
colorVariable: function () {
return d.coloring.variable;
},
colorBrushed: function (color) {
var rowColors = {};
DataSet.get(["Manual selection"], function (rows) {
_.forEach(rows, function (row) {
rowColors[row.row] = row["Manual selection"];
});
});
_.forEach(DataSet.brushed(), function (row) {
rowColors[row.row] = color;
});
d.coloring.variable = "Manual selection";
d.coloring.colorFn = function (colorVal) {
return colorVal; // The values of this variable are actually colors
};
DataSet.addVariable("Manual selection", rowColors, "factor", "Colors", "steelblue");
$rootScope.$broadcast("Colors::changed", rowColors);
},
opacity: function (value) {
$rootScope.$broadcast("Opacity::changed", value);
}
};
});
/*jslint todo:true, nomen: true, white: false, indent: 2, unparam: true */
/*global angular, _, ocpu*/
/*
ICoVeR - Interactive Contig-bin Verification and Refinement
Copyright 2015 Luxembourg Institute of Science and technology. All rights reserved.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
angular.module('contigBinningApp.services')
.service('DataSet', function ($rootScope, $http, assert, OpenCPU) {
'use strict';
var d = {
id: undefined,
data: undefined,
brushed: [],
backend: {
schema: undefined,
schemaIndex: undefined,
rows: undefined,
analytics: {
clusterings: {},
summaries: {}
}
}
};
function updateSchema(schema) {
d.backend.schema = schema;
// This adds a property that determines whether the variable is analysable in the R backend. This is necessary
// because some variables are only calculated in the Javascript.
_.forEach(d.backend.schema, function (variable) {
variable.analysable = true;
});
d.backend.schemaIndex = _.indexBy(schema, 'name');
$rootScope.$broadcast("DataSet::schemaLoaded", schema);
}
// Initialize the application as soon as the Dataset service is initialized and receive
// the required information to configure and further bootstrap the front end.
OpenCPU.json("app.init", {timestamp: Date.now()}, function (session, cfg) {
d.data = cfg.data;
updateSchema(cfg.data.schema);
$rootScope.$broadcast("App::configurationLoaded", cfg);
});
$rootScope.$on("ParCoords::brushPredicateChanged", function (ev, predicate) {
d.brushPredicate = predicate;
});
function addVariable(name, rows, type, group, missingReplacement) {
var variableSchema = {name: name, type: type, group: group, group_type: group, analysable: false},
rowArray = [],
value,
newVariable = false;
if (d.backend.schemaIndex[name] === undefined) {
d.backend.schema.push(variableSchema);
d.backend.schemaIndex[name] = variableSchema;
newVariable = true;
}
d.data.full.forEach(function (datum, idx) {
d.data.full[idx][name] = rows[datum.row];
});
if (d.data.filtered !== undefined) {
d.data.filtered.forEach(function (datum, idx) {
d.data.filtered[idx][name] = rows[datum.row];
});
}
if (newVariable) {
$rootScope.$broadcast('DataSet::schemaLoaded', d.backend.schema);
}
if (group === "Analytics") {
$rootScope.$broadcast('DataSet::analyticsUpdated', variableSchema);
}
// Tags need to be added to the actual database
// Preferably, R should get a function addVariable and the DataSet should not have to care what
// the group is of the variable we want to add. This would however require some extra work in R.
if (group === "Tags") {
_.each(d.data.full, function (row) {
value = rows[row.row];
if (value === undefined) {
value = missingReplacement;
}
rowArray.push(value);
});
OpenCPU.call("data.addTag", {timestamp: Date.now(), name: name, data: rowArray});
}
return variableSchema;
}
function removeVariable(name) {
var variableIdx = _.findIndex(d.backend.schema, "name", name),
group;
if (variableIdx === -1) {
return;
}
group = d.backend.schema[variableIdx].group;
d.backend.schema.splice(variableIdx, 1);
delete d.backend.schemaIndex[name];
$rootScope.$broadcast('DataSet::schemaLoaded', d.backend.schema);
if (group === "Tags") {
OpenCPU.call("data.removeTag", {timestamp: Date.now(), name: name});
}
}
// Listen to the analytics service to store the results of various
// analytical actions.
$rootScope.$on("Analytics::dataUpdated", function (ev, identifier) {
if (!d.backend.schemaIndex.hasOwnProperty(identifier)) {
// We send the current timestamp as arg to avoid caching to happen here
OpenCPU.json("data.schema", {timestamp: Date.now()}, function (session, schema) {
updateSchema(schema);
$rootScope.$broadcast("DataSet::analyticsUpdated", d.backend.schemaIndex[identifier]);
});
} else {
$rootScope.$broadcast("DataSet::analyticsUpdated", d.backend.schemaIndex[identifier]);
}
});
function processReceivedData(data) {
d.data.filtered = undefined; // Reset filtered data.
if (d.data.full === undefined) {
d.data.full = data;
d.data.full.index = {};
_.each(data, function (datum, i) {
d.data.full.index[datum.row] = i;
});
$rootScope.$broadcast("DataSet::initialDataLoaded");
} else {
// For each item we retrieved
_.each(data, function (datum) {
// If the item doesn't exist yet in the full data set, we'll have to
// add it.
if (d.data.full.index[datum.row] === undefined) {
d.data.full.index[datum.row] = d.data.full.length;
d.data.full.push(datum);
}
// Update the item in the full data set.
var index = d.data.full.index[datum.row],
dataItem = d.data.full[index],
keys = _.keys(datum);
_.each(keys, function (key) {
dataItem[key] = datum[key];
});
d.data.full[index] = dataItem; // Not sure if this is required
});
}
}
function dataFiltered() {
return d.backend.rows !== undefined && d.backend.rows.length > 0;
}
function filterData() {
if (!dataFiltered) { throw "Trying to filter unfiltered data."; }
var filtered = d.data.filtered || [];
// Recreate the filtered set of rows
_.each(d.backend.rows, function (row) {
var index = d.data.full.index[row];
filtered.push(d.data.full[index]);
});
return filtered;
}
function currentDataSet() {
if (dataFiltered()) {
if (!d.data.filtered) { d.data.filtered = filterData(); }
return d.data.filtered.slice();
}
if (d.data !== undefined && d.data.full !== undefined) {
return d.data.full.slice();
}
return [];
}
function changeBrushed(rows, method) {
d.brushed = rows;
$rootScope.$broadcast("DataSet::brushed", rows, method);
}
return {
FilterMethod: { KEEP: 'KEEP', REMOVE: 'REMOVE', RESET: 'RESET' },
/**
* Returns the row ids of the currently filtered rows or undefined if no
* filtering was applied (meaning all rows will loaded when using get).
*/
rows: function () {
return d.backend.rows;
},
/**
* Returns the full data set as it is currently loaded, this takes filtering into account.
*/
data: currentDataSet,
schema: function () {
return d.backend.schema.slice();
},
brushed: function () {
if (d.brushed === undefined) {
return [];
}
return d.brushed;
},
addVariable: addVariable,
removeVariable: removeVariable,
// Returns the data values for given variables.
// @param variables - a list of strings, containing the names of the
// variables to be loaded.
// @param callback - a function to be executed once data has been successfully loaded
get: function (variables, callback) {
var args = {},
availableVariables;
// TODO: Create a unique id for each requests. When a new request comes
// in, check if there is an ongoing requests which encompasses all
// variables in the new request. If so, add the callback to the
// list of callbacks for this request. Otherwise, remove already
// requested variables from the list (they will come in with the
// ongoing request) and place a new request with the remaining
// variables. The callback is called only when the remaining
// variables are loaded.
// @see _.uniqueId
if (d.data.full !== undefined && d.data.full.length > 0) {
availableVariables = _.keys(d.data.full[0]);
variables = _.difference(variables, availableVariables);
}
if (variables.length > 0) {
args.variables = variables;
// Always get the full column to avoid synchronization problems
// related to filtering
//args.rows = d.backend.rows;
OpenCPU.json("data.get", args, function (session, data) {
processReceivedData(data);
callback(currentDataSet());
});
} else {
// All variables are alread there, just directly return the data.
callback(currentDataSet());
}
},
filter: function (filterMethod) {
if (filterMethod === this.FilterMethod.RESET) {
d.backend.rows = undefined;
$rootScope.$broadcast("DataSet::filtered", currentDataSet());
return;
}
if (d.brushed.length === 0) { throw "ERROR, filtering while nothing is brushed"; }
if (filterMethod === this.FilterMethod.KEEP) {
d.backend.rows = _.pluck(d.brushed, "row");
} else {
var toRemove = _.indexBy(_.pluck(d.brushed, "row"));
d.backend.rows = d.backend.rows || _.pluck(d.data.full, "row");
d.backend.rows = _.filter(d.backend.rows, function (d) {
return toRemove[d] === undefined;
});
}
changeBrushed([], "filter");
d.data.filtered = undefined;
$rootScope.$broadcast("DataSet::filtered", currentDataSet());
},
filtered: function () {
return d.backend.rows && d.backend.rows.length > 0;
},
brush: changeBrushed
};
});
This diff is collapsed.
/*jslint white: false, indent: 2, nomen: true */
/*global angular, ocpu, _ */
/*
ICoVeR - Interactive Contig-bin Verification and Refinement
Copyright 2015 Luxembourg Institute of Science and technology. All rights reserved.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
angular.module('contigBinningApp.services')
.service('OpenCPU', function ($http) {
'use strict';
// For testing without having to re-install the R-plugin over and over again
// enable the following line, adjust the path, and run:
// rparcoords/inst/www $ python -m SimpleHTTPServer
//
// NOTE: Make sure that this line is disabled when you run gulp to generate
// the minimized version!
//ocpu.seturl("//localhost/ocpu/user/bertjan/library/ICoVeR/R", false);
function asJson(callback) {
return function (session) {
$http({method: 'GET', url: session.loc + "R/.val/json?auto_unbox=true"})
.success(_.partial(callback, session));
};
}
return {
call: function (fn, args, cb) {
ocpu.call(fn, args, cb);
},
json: function (fn, args, cb) {
ocpu.call(fn, args, asJson(cb));
}
};
});
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
<form role="form" class="form-horizontal" ng-controller="DimRedDisplayCtrl">
<div class="form-group">
<label class="col-sm-3 control-label adjusted-right-padding text-right">Cluster count:</label>
<div class="col-sm-9 no-left-padding">
<select class="form-control input-sm"
ng-model="cluster"
ng-options="cluster.label for cluster in clusters">
</select>
</div>
</div>
</form>
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment