From 1600992807a0b3edbe10e8c0baf80a41636a7650 Mon Sep 17 00:00:00 2001 From: Alexander Kabui Date: Tue, 14 Sep 2021 21:58:20 +0300 Subject: init commit for wgcna script --- scripts/wgcna_analysis.R | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 scripts/wgcna_analysis.R diff --git a/scripts/wgcna_analysis.R b/scripts/wgcna_analysis.R new file mode 100644 index 0000000..e69de29 -- cgit v1.2.3 From ea0e92d3f63a9f403aacd5ab1590f61f2752158a Mon Sep 17 00:00:00 2001 From: Alexander Kabui Date: Tue, 14 Sep 2021 22:12:43 +0300 Subject: load the required data for analysis --- scripts/wgcna_analysis.R | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/scripts/wgcna_analysis.R b/scripts/wgcna_analysis.R index e69de29..a8170b6 100644 --- a/scripts/wgcna_analysis.R +++ b/scripts/wgcna_analysis.R @@ -0,0 +1,21 @@ +# initial workspace setup + +library(WGCNA); +stringsAsFactors = FALSE + +# load expression data **assumes csv format row(traits)(columns info+samples) + + +wgcnaRawData <- read.csv(file = "wgcna_data.csv") + +# transform expressionData + +datExpr <- as.data.frame(t(wgcnaRawData)); + + + + + + + + -- cgit v1.2.3 From 49fdd614d4b18f7d28126e4ebbf3adca57f0416f Mon Sep 17 00:00:00 2001 From: Alexander Kabui Date: Tue, 14 Sep 2021 22:31:18 +0300 Subject: Checking data for excessive missing values --- scripts/wgcna_analysis.R | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/scripts/wgcna_analysis.R b/scripts/wgcna_analysis.R index a8170b6..8e90d7d 100644 --- a/scripts/wgcna_analysis.R +++ b/scripts/wgcna_analysis.R @@ -10,10 +10,28 @@ wgcnaRawData <- read.csv(file = "wgcna_data.csv") # transform expressionData -datExpr <- as.data.frame(t(wgcnaRawData)); +dataExpr <- as.data.frame(t(wgcnaRawData)); +# data cleaning + +# adopted from docs +gsg = goodSamplesGenes(dataExpr, verbose = 3); + + + +if (!gsg$allOK) +{ +# Optionally, print the gene and sample names that were removed: +if (sum(!gsg$goodGenes)>0) +printFlush(paste("Removing genes:", paste(names(datExpr0)[!gsg$goodGenes], collapse = ", "))); +if (sum(!gsg$goodSamples)>0) +printFlush(paste("Removing samples:", paste(rownames(datExpr0)[!gsg$goodSamples], collapse = ", "))); +# Remove the offending genes and samples from the data: +dataExpr <- dataExpr[gsg$goodSamples, gsg$goodGenes] +} + -- cgit v1.2.3 From 42c120dff2b3cac8a6b6546ebab9daf021aac11a Mon Sep 17 00:00:00 2001 From: Alexander Kabui Date: Tue, 14 Sep 2021 22:42:43 +0300 Subject: compute the softthreshhold --- scripts/wgcna_analysis.R | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/scripts/wgcna_analysis.R b/scripts/wgcna_analysis.R index 8e90d7d..cb93492 100644 --- a/scripts/wgcna_analysis.R +++ b/scripts/wgcna_analysis.R @@ -5,15 +5,12 @@ stringsAsFactors = FALSE # load expression data **assumes csv format row(traits)(columns info+samples) - wgcnaRawData <- read.csv(file = "wgcna_data.csv") # transform expressionData dataExpr <- as.data.frame(t(wgcnaRawData)); - - # data cleaning # adopted from docs @@ -32,6 +29,17 @@ printFlush(paste("Removing samples:", paste(rownames(datExpr0)[!gsg$goodSamples] dataExpr <- dataExpr[gsg$goodSamples, gsg$goodGenes] } +# network constructions and modules + +# choose softthreshhold (Calculate soft threshold if the user specified the) + +powers = c(c(1:10), seq(from = 12, to=20, by=2)) +sft = pickSoftThreshold(dataExpr, powerVector = powers, verbose = 5) + + + + + -- cgit v1.2.3 From 1c98a10bf5015a85b856f9e937417d51ec05d781 Mon Sep 17 00:00:00 2001 From: Alexander Kabui Date: Tue, 14 Sep 2021 22:49:43 +0300 Subject: construct gene co-expression network & module detection --- scripts/wgcna_analysis.R | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/scripts/wgcna_analysis.R b/scripts/wgcna_analysis.R index cb93492..29f0259 100644 --- a/scripts/wgcna_analysis.R +++ b/scripts/wgcna_analysis.R @@ -33,9 +33,26 @@ dataExpr <- dataExpr[gsg$goodSamples, gsg$goodGenes] # choose softthreshhold (Calculate soft threshold if the user specified the) -powers = c(c(1:10), seq(from = 12, to=20, by=2)) -sft = pickSoftThreshold(dataExpr, powerVector = powers, verbose = 5) - +powers <- c(c(1:10), seq(from = 12, to=20, by=2)) +sft <- pickSoftThreshold(dataExpr, powerVector = powers, verbose = 5) + +# pass user options +network <- blockwiseModules(dataExpr, + #similarity matrix options + corType = "pearson", + #adjacency matrix options + + power = sft$powerEstimate, + networkType = "unsigned", + #TOM options + TOMtype = "unsigned", + + #module indentification + + minmodulesSize = 30, + deepSplit = 5, + PamRespectsDendro = FALSE + ) -- cgit v1.2.3 From b32f4ee074d55d8ab78863d4c5acc652ec9cd839 Mon Sep 17 00:00:00 2001 From: Alexander Kabui Date: Tue, 14 Sep 2021 23:18:18 +0300 Subject: plot plotDendroAndColors and generate png --- scripts/wgcna_analysis.R | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/scripts/wgcna_analysis.R b/scripts/wgcna_analysis.R index 29f0259..65ff36e 100644 --- a/scripts/wgcna_analysis.R +++ b/scripts/wgcna_analysis.R @@ -54,6 +54,24 @@ network <- blockwiseModules(dataExpr, PamRespectsDendro = FALSE ) +# plot dendro add color + +# Convert labels to colors for plotting +mergedColors = labels2colors(net$colors) +# Plot the dendrogram and the module colors underneath + + +# generate random name for png && save the image location + + + +png("WGCNAoutput.png",width=1000,height=600,type='cairo-png') + +plotDendroAndColors(network$dendrograms[[1]],mergedColors[net$blockGenes[[1]]], +"Module colors", +dendroLabels = FALSE, hang = 0.03, +addGuide = TRUE, guideHang = 0.05) + -- cgit v1.2.3 From 49b852baa46c0f06caa2f0621b18d521cf334483 Mon Sep 17 00:00:00 2001 From: Alexander Kabui Date: Tue, 14 Sep 2021 23:40:17 +0300 Subject: function to generate rand str for image --- scripts/wgcna_analysis.R | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/scripts/wgcna_analysis.R b/scripts/wgcna_analysis.R index 65ff36e..efe0336 100644 --- a/scripts/wgcna_analysis.R +++ b/scripts/wgcna_analysis.R @@ -1,7 +1,9 @@ # initial workspace setup library(WGCNA); -stringsAsFactors = FALSE +library(stringi); + +options(stringsAsFactors = FALSE); # load expression data **assumes csv format row(traits)(columns info+samples) @@ -64,8 +66,18 @@ mergedColors = labels2colors(net$colors) # generate random name for png && save the image location +genImageRandStr <- function(prefix){ + + randStr <- paste(prefix,stri_rand_strings(1, 9, pattern = "[A-Za-z0-9]"),sep="_") + + return(paste(randStr,".png",sep="")) +} + + + +png(genImageRandStr,width=1000,height=600,type='cairo-png') + -png("WGCNAoutput.png",width=1000,height=600,type='cairo-png') plotDendroAndColors(network$dendrograms[[1]],mergedColors[net$blockGenes[[1]]], "Module colors", -- cgit v1.2.3 From 56092341abe9579b995ff6105722154183b31d22 Mon Sep 17 00:00:00 2001 From: Alexander Kabui Date: Tue, 14 Sep 2021 23:41:46 +0300 Subject: remove debug statements --- scripts/wgcna_analysis.R | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/scripts/wgcna_analysis.R b/scripts/wgcna_analysis.R index efe0336..16a44fd 100644 --- a/scripts/wgcna_analysis.R +++ b/scripts/wgcna_analysis.R @@ -56,14 +56,6 @@ network <- blockwiseModules(dataExpr, PamRespectsDendro = FALSE ) -# plot dendro add color - -# Convert labels to colors for plotting -mergedColors = labels2colors(net$colors) -# Plot the dendrogram and the module colors underneath - - -# generate random name for png && save the image location genImageRandStr <- function(prefix){ @@ -74,6 +66,7 @@ genImageRandStr <- function(prefix){ } +mergedColors = labels2colors(net$colors) png(genImageRandStr,width=1000,height=600,type='cairo-png') -- cgit v1.2.3 From e0f25dedea08842820424ced51af9af0c7eaab4b Mon Sep 17 00:00:00 2001 From: Alexander Kabui Date: Wed, 15 Sep 2021 02:13:03 +0300 Subject: Fetch IMAGE_DIR env and add img location --- scripts/wgcna_analysis.R | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/scripts/wgcna_analysis.R b/scripts/wgcna_analysis.R index 16a44fd..54650df 100644 --- a/scripts/wgcna_analysis.R +++ b/scripts/wgcna_analysis.R @@ -1,10 +1,14 @@ # initial workspace setup + +# todo pass required input data here library(WGCNA); library(stringi); options(stringsAsFactors = FALSE); +imgDir = Sys.getenv("GENERATED_IMAGE_DIR") + # load expression data **assumes csv format row(traits)(columns info+samples) wgcnaRawData <- read.csv(file = "wgcna_data.csv") @@ -33,7 +37,7 @@ dataExpr <- dataExpr[gsg$goodSamples, gsg$goodGenes] # network constructions and modules -# choose softthreshhold (Calculate soft threshold if the user specified the) +# choose softthreshhold (Calculate soft threshold) powers <- c(c(1:10), seq(from = 12, to=20, by=2)) sft <- pickSoftThreshold(dataExpr, powerVector = powers, verbose = 5) @@ -65,12 +69,12 @@ genImageRandStr <- function(prefix){ return(paste(randStr,".png",sep="")) } +mergedColors <- labels2colors(net$colors) -mergedColors = labels2colors(net$colors) - -png(genImageRandStr,width=1000,height=600,type='cairo-png') +imageLoc <- file.path(imgDir,genImageRandStr("WGCNAoutput")) +png(imageLoc,width=1000,height=600,type='cairo-png') plotDendroAndColors(network$dendrograms[[1]],mergedColors[net$blockGenes[[1]]], "Module colors", @@ -79,9 +83,3 @@ addGuide = TRUE, guideHang = 0.05) - - - - - - -- cgit v1.2.3 From 94e2e79141cbddb48456fb5707eb0e4e36e97d3b Mon Sep 17 00:00:00 2001 From: Alexander Kabui Date: Wed, 15 Sep 2021 02:19:03 +0300 Subject: rename variables && delete debugs --- scripts/wgcna_analysis.R | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/scripts/wgcna_analysis.R b/scripts/wgcna_analysis.R index 54650df..390bee4 100644 --- a/scripts/wgcna_analysis.R +++ b/scripts/wgcna_analysis.R @@ -1,7 +1,3 @@ -# initial workspace setup - - -# todo pass required input data here library(WGCNA); library(stringi); @@ -11,15 +7,14 @@ imgDir = Sys.getenv("GENERATED_IMAGE_DIR") # load expression data **assumes csv format row(traits)(columns info+samples) -wgcnaRawData <- read.csv(file = "wgcna_data.csv") +inputData <- read.csv(file = "wgcna_data.csv") # transform expressionData -dataExpr <- as.data.frame(t(wgcnaRawData)); +dataExpr <- as.data.frame(t(inputData)); # data cleaning -# adopted from docs gsg = goodSamplesGenes(dataExpr, verbose = 3); -- cgit v1.2.3 From cee10bacd4316eb807c36b8a11e84f9be5945f44 Mon Sep 17 00:00:00 2001 From: Alexander Kabui Date: Wed, 15 Sep 2021 04:34:26 +0300 Subject: minor fixes --- scripts/wgcna_analysis.R | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/scripts/wgcna_analysis.R b/scripts/wgcna_analysis.R index 390bee4..267cd86 100644 --- a/scripts/wgcna_analysis.R +++ b/scripts/wgcna_analysis.R @@ -1,3 +1,5 @@ + + library(WGCNA); library(stringi); @@ -6,6 +8,7 @@ options(stringsAsFactors = FALSE); imgDir = Sys.getenv("GENERATED_IMAGE_DIR") # load expression data **assumes csv format row(traits)(columns info+samples) +# pass the file_path as arg inputData <- read.csv(file = "wgcna_data.csv") @@ -13,26 +16,29 @@ inputData <- read.csv(file = "wgcna_data.csv") dataExpr <- as.data.frame(t(inputData)); -# data cleaning +## data cleaning gsg = goodSamplesGenes(dataExpr, verbose = 3); - +# https://horvath.genetics.ucla.edu/html/CoexpressionNetwork/Rpackages/ if (!gsg$allOK) { -# Optionally, print the gene and sample names that were removed: if (sum(!gsg$goodGenes)>0) -printFlush(paste("Removing genes:", paste(names(datExpr0)[!gsg$goodGenes], collapse = ", "))); +printFlush(paste("Removing genes:", paste(names(dataExpr)[!gsg$goodGenes], collapse = ", "))); if (sum(!gsg$goodSamples)>0) -printFlush(paste("Removing samples:", paste(rownames(datExpr0)[!gsg$goodSamples], collapse = ", "))); +printFlush(paste("Removing samples:", paste(rownames(dataExpr)[!gsg$goodSamples], collapse = ", "))); # Remove the offending genes and samples from the data: dataExpr <- dataExpr[gsg$goodSamples, gsg$goodGenes] } -# network constructions and modules +## network constructions and modules + +# Allow multi-threading within WGCNA +enableWGCNAThreads() # choose softthreshhold (Calculate soft threshold) +# xtodo allow users to pass args powers <- c(c(1:10), seq(from = 12, to=20, by=2)) sft <- pickSoftThreshold(dataExpr, powerVector = powers, verbose = 5) -- cgit v1.2.3 From 488ad475ca7112d64f9f1f0d4934c3293388bf1a Mon Sep 17 00:00:00 2001 From: Alexander Kabui Date: Wed, 15 Sep 2021 16:06:52 +0300 Subject: remove golang package causing build failure --- guix.scm | 2 -- 1 file changed, 2 deletions(-) diff --git a/guix.scm b/guix.scm index 729d089..75ed4a9 100644 --- a/guix.scm +++ b/guix.scm @@ -43,7 +43,6 @@ (gnu packages databases) (gnu packages statistics) (gnu packages bioconductor) - (gn packages golang) (gnu packages python) (gnu packages python-check) (gnu packages python-crypto) @@ -83,7 +82,6 @@ #:recursive? #t #:select? git-file?)) (propagated-inputs `(("coreutils" ,coreutils) - ("csvdiff" ,go-github-com-aswinkarthik-csvdiff) ("gemma-wrapper" ,gemma-wrapper) ("gunicorn" ,gunicorn) ("python" ,python-wrapper) -- cgit v1.2.3 From 6494a093e6d96015f65416a8c3fde88a9a3c8c71 Mon Sep 17 00:00:00 2001 From: Alexander Kabui Date: Wed, 15 Sep 2021 16:17:02 +0300 Subject: init wgcna file to run r script and preprocess data --- gn3/computations/wgcna.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 gn3/computations/wgcna.py diff --git a/gn3/computations/wgcna.py b/gn3/computations/wgcna.py new file mode 100644 index 0000000..e69de29 -- cgit v1.2.3 From 129ecfe26a857c2c66a2402c9c7364b309e9f1c0 Mon Sep 17 00:00:00 2001 From: Alexander Kabui Date: Wed, 15 Sep 2021 16:17:30 +0300 Subject: initial test file for wgcna --- tests/unit/computations/test_wgcna.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 tests/unit/computations/test_wgcna.py diff --git a/tests/unit/computations/test_wgcna.py b/tests/unit/computations/test_wgcna.py new file mode 100644 index 0000000..1ce69a1 --- /dev/null +++ b/tests/unit/computations/test_wgcna.py @@ -0,0 +1,15 @@ +"""module contains python code for wgcna""" +from unittest import TestCase + + +def compute_sum(rhs_val, lhs_val): + """function to compute sum of two numbers""" + return rhs_val+lhs_val + + +class TestWgcna(TestCase): + """test class for wgcna""" + + def test_compute_sum(self): + """test for compute sum function""" + self.assertEqual(compute_sum(1, 2), 3) -- cgit v1.2.3 From a3ef298678b32ee83cac7bd7462d3d92f8eaec26 Mon Sep 17 00:00:00 2001 From: Alexander Kabui Date: Thu, 16 Sep 2021 08:23:35 +0300 Subject: function to parse form data and write to json file --- gn3/computations/wgcna.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/gn3/computations/wgcna.py b/gn3/computations/wgcna.py index e69de29..3819b62 100644 --- a/gn3/computations/wgcna.py +++ b/gn3/computations/wgcna.py @@ -0,0 +1,18 @@ +"""module contains code to preprocess and call wgcna script""" + +import os +import json +import uuid +from gn3.settings import TMPDIR + + +def dump_wgcna_data(request_data): + """function to dump request data to json file""" + filename = f"{str(uuid.uuid4())}.json" + + temp_file_path = os.path.join(TMPDIR, filename) + + with open(temp_file_path, "w") as output_file: + json.dump(request_data, output_file) + + return temp_file_path -- cgit v1.2.3 From 38cbc95f216548d4a2f46b8e25cd328ff8c52d62 Mon Sep 17 00:00:00 2001 From: Alexander Kabui Date: Thu, 16 Sep 2021 08:54:01 +0300 Subject: add function to compose and run wgcna script --- gn3/computations/wgcna.py | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/gn3/computations/wgcna.py b/gn3/computations/wgcna.py index 3819b62..bcd3a0a 100644 --- a/gn3/computations/wgcna.py +++ b/gn3/computations/wgcna.py @@ -5,8 +5,10 @@ import json import uuid from gn3.settings import TMPDIR +from gn3.commands import run_cmd -def dump_wgcna_data(request_data): + +def dump_wgcna_data(request_data: dict): """function to dump request data to json file""" filename = f"{str(uuid.uuid4())}.json" @@ -16,3 +18,16 @@ def dump_wgcna_data(request_data): json.dump(request_data, output_file) return temp_file_path + + +def compose_wgcna_cmd(rscript_path: str, temp_file_path: str): + """function to componse wgcna cmd""" + cmd = f"Rscript {rscript_path} {temp_file_path}" + return cmd + + +def call_wgcna_script(rscript_path: str, request_data: dict): + """function to call wgcna script""" + generated_file = dump_wgcna_data(request_data) + cmd = compose_gemma_cmd(rscript_path, generated_file) + run_cmd(cmd=cmd) -- cgit v1.2.3 From 8854e3070f32bed95cb489eb36e7f258c02ec46e Mon Sep 17 00:00:00 2001 From: Alexander Kabui Date: Thu, 16 Sep 2021 09:32:42 +0300 Subject: add initial endpoint for wgcna --- gn3/api/wgcna.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 gn3/api/wgcna.py diff --git a/gn3/api/wgcna.py b/gn3/api/wgcna.py new file mode 100644 index 0000000..a3bacdd --- /dev/null +++ b/gn3/api/wgcna.py @@ -0,0 +1,13 @@ +"""endpoint to run wgcna analysis""" +from flask import Blueprint +from flask import request + +wgcna = Blueprint("wgcna", __name__) + + +@wgcna.route("/run_wgcna", methods=["POST"]) +def run_wgcna(): + + _wgcna_data = request.json + + return "success", 200 -- cgit v1.2.3 From 6f9fd1a1866e292ec4b84c214efd61ccb9f5bb58 Mon Sep 17 00:00:00 2001 From: Alexander Kabui Date: Thu, 16 Sep 2021 09:45:16 +0300 Subject: register wgcna blueprint --- gn3/app.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gn3/app.py b/gn3/app.py index 046b5de..b2f77f9 100644 --- a/gn3/app.py +++ b/gn3/app.py @@ -9,6 +9,7 @@ from gn3.api.rqtl import rqtl from gn3.api.general import general from gn3.api.correlation import correlation from gn3.api.data_entry import data_entry +from gn3.api.wgcna import wgcna def create_app(config: Union[Dict, str, None] = None) -> Flask: @@ -32,4 +33,5 @@ def create_app(config: Union[Dict, str, None] = None) -> Flask: app.register_blueprint(rqtl, url_prefix="/api/rqtl") app.register_blueprint(correlation, url_prefix="/api/correlation") app.register_blueprint(data_entry, url_prefix="/api/dataentry") + app.register_blueprint(wgcna, url_prefix="/api/wgcna") return app -- cgit v1.2.3 From 3d8f7f069d76cd6ee35b5e9d72d37e38721188d2 Mon Sep 17 00:00:00 2001 From: Alexander Kabui Date: Thu, 16 Sep 2021 10:13:10 +0300 Subject: run cmd and add exception handler --- gn3/computations/wgcna.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/gn3/computations/wgcna.py b/gn3/computations/wgcna.py index bcd3a0a..f0f0fa2 100644 --- a/gn3/computations/wgcna.py +++ b/gn3/computations/wgcna.py @@ -29,5 +29,9 @@ def compose_wgcna_cmd(rscript_path: str, temp_file_path: str): def call_wgcna_script(rscript_path: str, request_data: dict): """function to call wgcna script""" generated_file = dump_wgcna_data(request_data) - cmd = compose_gemma_cmd(rscript_path, generated_file) - run_cmd(cmd=cmd) + cmd = compose_wgcna_cmd(rscript_path, generated_file) + + try: + return run_cmd(cmd) + except Exception as error: + raise error -- cgit v1.2.3 From f53a8a98206b4e8aedbf4b86e49f41ea140c9c6a Mon Sep 17 00:00:00 2001 From: Alexander Kabui Date: Thu, 16 Sep 2021 14:02:13 +0300 Subject: pass user input to call script --- gn3/api/wgcna.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/gn3/api/wgcna.py b/gn3/api/wgcna.py index a3bacdd..5d49493 100644 --- a/gn3/api/wgcna.py +++ b/gn3/api/wgcna.py @@ -1,13 +1,21 @@ """endpoint to run wgcna analysis""" from flask import Blueprint from flask import request +from flask import current_app + +from gn3.computations.wgcna import call_wgcna_script wgcna = Blueprint("wgcna", __name__) @wgcna.route("/run_wgcna", methods=["POST"]) def run_wgcna(): + """run wgcna:output should be a json with a the data""" + + wgcna_data = request.json + + wgcna_script = current_app.config["WGCNA_RSCRIPT"] - _wgcna_data = request.json + results = call_wgcna_script(wgcna_script, wgcna_data) - return "success", 200 + return results, 200 -- cgit v1.2.3 From ce045ec96bf965eaba077fdba99847a483281aba Mon Sep 17 00:00:00 2001 From: Alexander Kabui Date: Thu, 16 Sep 2021 14:03:25 +0300 Subject: init tests for wgcna --- tests/unit/computations/test_wgcna.py | 36 +++++++++++++++++++++++++++-------- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/tests/unit/computations/test_wgcna.py b/tests/unit/computations/test_wgcna.py index 1ce69a1..8a68985 100644 --- a/tests/unit/computations/test_wgcna.py +++ b/tests/unit/computations/test_wgcna.py @@ -1,15 +1,35 @@ """module contains python code for wgcna""" from unittest import TestCase - - -def compute_sum(rhs_val, lhs_val): - """function to compute sum of two numbers""" - return rhs_val+lhs_val +from gn3.computations.wgcna import dump_wgcna_data +from gn3.computations.wgcna import compose_wgcna_cmd class TestWgcna(TestCase): """test class for wgcna""" - def test_compute_sum(self): - """test for compute sum function""" - self.assertEqual(compute_sum(1, 2), 3) + def test_compose_wgcna_cmd(self): + """test for composing wgcna cmd""" + wgcna_cmd = compose_wgcna_cmd("/wgcna.r", "/tmp/wgcna.json") + self.assertEqual(wgcna_cmd, f"Rscript /wgcna.r /tmp/wgcna.json") + + def test_create_json_data(self): + """test for writing the data to a csv file""" + # # All the traits we have data for (should not contain duplicates) + # All the strains we have data for (contains duplicates) + + trait_sample_data = {"1425642_at": {"129S1/SvImJ": 7.142, "A/J": 7.31, "AKR/J": 7.49, + "B6D2F1": 6.899, "BALB/cByJ": 7.172, "BALB/cJ": 7.396}, + "1457784_at": {"129S1/SvImJ": 7.071, "A/J": 7.05, "AKR/J": 7.313, + "B6D2F1": 6.999, "BALB/cByJ": 7.293, "BALB/cJ": 7.117}, + "1444351_at": {"129S1/SvImJ": 7.221, "A/J": 7.246, "AKR/J": 7.754, + "B6D2F1": 6.866, "BALB/cByJ": 6.752, "BALB/cJ": 7.269} + + } + + expected_input = { + "trait_sample_data": trait_sample_data, + "TOMtype": "unsigned", + "minModuleSize": 30 + } + + _results = dump_wgcna_data(expected_input) -- cgit v1.2.3 From e8f3a7131e8f1fcaf803dedab3177374f46e3709 Mon Sep 17 00:00:00 2001 From: Alexander Kabui Date: Thu, 16 Sep 2021 14:04:23 +0300 Subject: Add WGCNA_SCRIT env to settings --- gn3/settings.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/gn3/settings.py b/gn3/settings.py index f4866d5..d3d7ea0 100644 --- a/gn3/settings.py +++ b/gn3/settings.py @@ -24,3 +24,6 @@ GN2_BASE_URL = "http://www.genenetwork.org/" # biweight script BIWEIGHT_RSCRIPT = "~/genenetwork3/scripts/calculate_biweight.R" + +# wgcna script +WGCNA_RSCRIPT = "wgcna_analysis.R" -- cgit v1.2.3 From ab8b53a50a601cb95dc0b54279246431c791dd70 Mon Sep 17 00:00:00 2001 From: Alexander Kabui Date: Thu, 16 Sep 2021 22:56:21 +0300 Subject: pylint fixes --- tests/unit/computations/test_wgcna.py | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/tests/unit/computations/test_wgcna.py b/tests/unit/computations/test_wgcna.py index 8a68985..9a88515 100644 --- a/tests/unit/computations/test_wgcna.py +++ b/tests/unit/computations/test_wgcna.py @@ -9,20 +9,28 @@ class TestWgcna(TestCase): def test_compose_wgcna_cmd(self): """test for composing wgcna cmd""" - wgcna_cmd = compose_wgcna_cmd("/wgcna.r", "/tmp/wgcna.json") - self.assertEqual(wgcna_cmd, f"Rscript /wgcna.r /tmp/wgcna.json") + wgcna_cmd = compose_wgcna_cmd( + "/wgcna.r", "/tmp/wgcna.json") + self.assertEqual( + wgcna_cmd, "Rscript /wgcna.r /tmp/wgcna.json") - def test_create_json_data(self): + def test_create_json_file(self): """test for writing the data to a csv file""" # # All the traits we have data for (should not contain duplicates) # All the strains we have data for (contains duplicates) - trait_sample_data = {"1425642_at": {"129S1/SvImJ": 7.142, "A/J": 7.31, "AKR/J": 7.49, - "B6D2F1": 6.899, "BALB/cByJ": 7.172, "BALB/cJ": 7.396}, - "1457784_at": {"129S1/SvImJ": 7.071, "A/J": 7.05, "AKR/J": 7.313, - "B6D2F1": 6.999, "BALB/cByJ": 7.293, "BALB/cJ": 7.117}, - "1444351_at": {"129S1/SvImJ": 7.221, "A/J": 7.246, "AKR/J": 7.754, - "B6D2F1": 6.866, "BALB/cByJ": 6.752, "BALB/cJ": 7.269} + trait_sample_data = {"1425642_at": {"129S1/SvImJ": 7.142, + "A/J": 7.31, "AKR/J": 7.49, + "B6D2F1": 6.899, "BALB/cByJ": 7.172, + "BALB/cJ": 7.396}, + "1457784_at": {"129S1/SvImJ": 7.071, "A/J": 7.05, + "AKR/J": 7.313, + "B6D2F1": 6.999, "BALB/cByJ": 7.293, + "BALB/cJ": 7.117}, + "1444351_at": {"129S1/SvImJ": 7.221, "A/J": 7.246, + "AKR/J": 7.754, + "B6D2F1": 6.866, "BALB/cByJ": 6.752, + "BALB/cJ": 7.269} } @@ -32,4 +40,7 @@ class TestWgcna(TestCase): "minModuleSize": 30 } - _results = dump_wgcna_data(expected_input) + results = dump_wgcna_data( + expected_input) + + self.assertEqual(results, {}) -- cgit v1.2.3 From 580778386f054706086d7ab3d49f2c4f91f110e0 Mon Sep 17 00:00:00 2001 From: Alexander Kabui Date: Wed, 22 Sep 2021 00:48:37 +0300 Subject: init endpoint tests for wgcna --- tests/integration/test_wgcna.py | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 tests/integration/test_wgcna.py diff --git a/tests/integration/test_wgcna.py b/tests/integration/test_wgcna.py new file mode 100644 index 0000000..65763c1 --- /dev/null +++ b/tests/integration/test_wgcna.py @@ -0,0 +1,37 @@ +"""integration tests for wgcna""" + +from unittest import TestCase +from unittest import mock + +from gn3.app import create_app + + +class WgcnaIntegrationTest(TestCase): + """class contains wgcna integration tests""" + + def setUp(self): + self.app = create_app().test_client() + + @mock.patch("gn3.api.wgcna.call_wgcna_script") + def test_wgcna_endpoint(self, mock_wgcna_api): + """test /api/wgcna/run_wgcna endpoint""" + + wgcna_api_data = { + "eigengenes": ["1224_at", "121412_at", "32342342-at"], + "dendrogram_file_location": "/tmp/dend1.png" + + } + mock_wgcna_api.return_value = wgcna_api_data + + request_data = { + + "trait_sample_data": [], + + + } + + response = self.app.post("/api/wgcna/run_wgcna", + json=request_data, follow_redirects=True) + + self.assertEqual(response.status_code, 200) + self.assertEqual(response.get_json(), wgcna_api_data) -- cgit v1.2.3 From 6f7c60e6c438ada9a3b9032c8e4509351384e04f Mon Sep 17 00:00:00 2001 From: Alexander Kabui Date: Wed, 22 Sep 2021 00:49:22 +0300 Subject: jsonify results --- gn3/api/wgcna.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gn3/api/wgcna.py b/gn3/api/wgcna.py index 5d49493..89784c4 100644 --- a/gn3/api/wgcna.py +++ b/gn3/api/wgcna.py @@ -2,6 +2,7 @@ from flask import Blueprint from flask import request from flask import current_app +from flask import jsonify from gn3.computations.wgcna import call_wgcna_script @@ -18,4 +19,4 @@ def run_wgcna(): results = call_wgcna_script(wgcna_script, wgcna_data) - return results, 200 + return jsonify(results), 200 -- cgit v1.2.3 From f4242f9743c7f236a00917fd187fbd603831dda1 Mon Sep 17 00:00:00 2001 From: Alexander Kabui Date: Wed, 22 Sep 2021 01:51:44 +0300 Subject: add required wgcna dependencies to guix.scm --- guix.scm | 1 + 1 file changed, 1 insertion(+) diff --git a/guix.scm b/guix.scm index 75ed4a9..509c9ff 100644 --- a/guix.scm +++ b/guix.scm @@ -101,6 +101,7 @@ ("r-optparse" ,r-optparse) ("r-qtl" ,r-qtl) ("r-stringi" ,r-stringi) + ("r-wgcna" ,r-wgcna) ("python-plotly" ,python-plotly) ("python-pandas" ,python-pandas))) (build-system python-build-system) -- cgit v1.2.3 From 0f871f49e749eb625f58326adf8f80b3d3b5b932 Mon Sep 17 00:00:00 2001 From: Alexander Kabui Date: Wed, 22 Sep 2021 01:53:45 +0300 Subject: add init tests for call to script --- tests/unit/computations/test_wgcna.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tests/unit/computations/test_wgcna.py b/tests/unit/computations/test_wgcna.py index 9a88515..fd90732 100644 --- a/tests/unit/computations/test_wgcna.py +++ b/tests/unit/computations/test_wgcna.py @@ -1,12 +1,27 @@ """module contains python code for wgcna""" +from unittest import skip from unittest import TestCase +from unittest import mock + from gn3.computations.wgcna import dump_wgcna_data from gn3.computations.wgcna import compose_wgcna_cmd +from gn3.computations.wgcna import call_wgcna_script class TestWgcna(TestCase): """test class for wgcna""" + @mock.patch("gn3.computations.wgcna.dump_wgcna_data") + def test_call_wgcna_script(self, mock_dump): + """call wgcna script""" + + mock_dump.return_value = "/tmp/QmQPeNsJPyVWPFDVHb77w8G42Fvo15z4bG2X8D2GhfbSXc-test.json" + + results = call_wgcna_script( + "/home/kabui/project/genenetwork3/scripts/wgcna_analysis.R", {}) + + self.assertEqual(results, "dsedf") + def test_compose_wgcna_cmd(self): """test for composing wgcna cmd""" wgcna_cmd = compose_wgcna_cmd( @@ -14,6 +29,7 @@ class TestWgcna(TestCase): self.assertEqual( wgcna_cmd, "Rscript /wgcna.r /tmp/wgcna.json") + @skip("to update tests") def test_create_json_file(self): """test for writing the data to a csv file""" # # All the traits we have data for (should not contain duplicates) -- cgit v1.2.3 From 3d36fe96c94cebb6e7ea93b735148b25c4b95f6d Mon Sep 17 00:00:00 2001 From: Alexander Kabui Date: Thu, 23 Sep 2021 12:22:10 +0300 Subject: load data from json file and and convert to dt --- scripts/wgcna_analysis.R | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/scripts/wgcna_analysis.R b/scripts/wgcna_analysis.R index 267cd86..d0ba91a 100644 --- a/scripts/wgcna_analysis.R +++ b/scripts/wgcna_analysis.R @@ -2,26 +2,29 @@ library(WGCNA); library(stringi); +library(rjson) options(stringsAsFactors = FALSE); imgDir = Sys.getenv("GENERATED_IMAGE_DIR") -# load expression data **assumes csv format row(traits)(columns info+samples) +# load expression data **assumes from json files row(traits)(columns info+samples) # pass the file_path as arg -inputData <- read.csv(file = "wgcna_data.csv") +results <- fromJSON(file = "file_path.json") -# transform expressionData +# trait_sample_data <- results$trait_sample_data +trait_sample_data <- do.call(rbind, results$trait_sample_data) -dataExpr <- as.data.frame(t(inputData)); -## data cleaning +dataExpr <- data.frame(apply(trait_sample_data, 2, function(x) as.numeric(as.character(x)))) +# trait_sample_data <- as.data.frame(t(results$trait_sample_data)) +# transform expressionData +dataExpr <- data.frame(t(dataExpr)) gsg = goodSamplesGenes(dataExpr, verbose = 3); # https://horvath.genetics.ucla.edu/html/CoexpressionNetwork/Rpackages/ - if (!gsg$allOK) { if (sum(!gsg$goodGenes)>0) @@ -49,7 +52,7 @@ network <- blockwiseModules(dataExpr, corType = "pearson", #adjacency matrix options - power = sft$powerEstimate, + power = 5, networkType = "unsigned", #TOM options TOMtype = "unsigned", @@ -70,14 +73,13 @@ genImageRandStr <- function(prefix){ return(paste(randStr,".png",sep="")) } -mergedColors <- labels2colors(net$colors) +mergedColors <- labels2colors(network$colors) imageLoc <- file.path(imgDir,genImageRandStr("WGCNAoutput")) - png(imageLoc,width=1000,height=600,type='cairo-png') -plotDendroAndColors(network$dendrograms[[1]],mergedColors[net$blockGenes[[1]]], +plotDendroAndColors(network$dendrograms[[1]],mergedColors[network$blockGenes[[1]]], "Module colors", dendroLabels = FALSE, hang = 0.03, addGuide = TRUE, guideHang = 0.05) -- cgit v1.2.3 From e5a50e6becabb9ebe4884714f7a182fad4490490 Mon Sep 17 00:00:00 2001 From: Alexander Kabui Date: Thu, 23 Sep 2021 12:22:51 +0300 Subject: add rjson dependency --- guix.scm | 1 + 1 file changed, 1 insertion(+) diff --git a/guix.scm b/guix.scm index 509c9ff..3e7dcea 100644 --- a/guix.scm +++ b/guix.scm @@ -102,6 +102,7 @@ ("r-qtl" ,r-qtl) ("r-stringi" ,r-stringi) ("r-wgcna" ,r-wgcna) + ("r-rjson" ,r-rjson) ("python-plotly" ,python-plotly) ("python-pandas" ,python-pandas))) (build-system python-build-system) -- cgit v1.2.3 From 95620e1aef5a9c56875845769d58d2aab20dacca Mon Sep 17 00:00:00 2001 From: Alexander Kabui Date: Thu, 23 Sep 2021 12:37:51 +0300 Subject: pass other variables from user input for network constr --- scripts/wgcna_analysis.R | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/scripts/wgcna_analysis.R b/scripts/wgcna_analysis.R index d0ba91a..73d0e3f 100644 --- a/scripts/wgcna_analysis.R +++ b/scripts/wgcna_analysis.R @@ -13,12 +13,19 @@ imgDir = Sys.getenv("GENERATED_IMAGE_DIR") results <- fromJSON(file = "file_path.json") -# trait_sample_data <- results$trait_sample_data -trait_sample_data <- do.call(rbind, results$trait_sample_data) +# parse the json data input + +minModuleSize <-results$minModuleSize + +TOMtype <-results$TOMtype + +corType <-results$corType +# + +trait_sample_data <- do.call(rbind, results$trait_sample_data) dataExpr <- data.frame(apply(trait_sample_data, 2, function(x) as.numeric(as.character(x)))) -# trait_sample_data <- as.data.frame(t(results$trait_sample_data)) # transform expressionData dataExpr <- data.frame(t(dataExpr)) @@ -49,18 +56,18 @@ sft <- pickSoftThreshold(dataExpr, powerVector = powers, verbose = 5) # pass user options network <- blockwiseModules(dataExpr, #similarity matrix options - corType = "pearson", + corType = corType, #adjacency matrix options power = 5, networkType = "unsigned", #TOM options - TOMtype = "unsigned", + TOMtype = TOMtype, #module indentification - minmodulesSize = 30, - deepSplit = 5, + minmodulesSize = minModuleSize, + deepSplit = 3, PamRespectsDendro = FALSE ) @@ -76,7 +83,7 @@ genImageRandStr <- function(prefix){ mergedColors <- labels2colors(network$colors) imageLoc <- file.path(imgDir,genImageRandStr("WGCNAoutput")) - +imageLoc png(imageLoc,width=1000,height=600,type='cairo-png') plotDendroAndColors(network$dendrograms[[1]],mergedColors[network$blockGenes[[1]]], -- cgit v1.2.3 From 4a8e40f7331f61ba8b7038e8ad48f86018ac7dc6 Mon Sep 17 00:00:00 2001 From: Alexander Kabui Date: Thu, 23 Sep 2021 12:47:27 +0300 Subject: pass json file path as an arg --- scripts/wgcna_analysis.R | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/scripts/wgcna_analysis.R b/scripts/wgcna_analysis.R index 73d0e3f..53b59d5 100644 --- a/scripts/wgcna_analysis.R +++ b/scripts/wgcna_analysis.R @@ -7,11 +7,20 @@ library(rjson) options(stringsAsFactors = FALSE); imgDir = Sys.getenv("GENERATED_IMAGE_DIR") - # load expression data **assumes from json files row(traits)(columns info+samples) # pass the file_path as arg +# pass the file path to read json data + +args = commandArgs(trailingOnly=TRUE) + +if (length(args)==0) { + stop("Argument for the file location is requires", call.=FALSE) +} else { + # default output file + json_file_path = args[1] +} -results <- fromJSON(file = "file_path.json") +results <- fromJSON(file = json_file_path) # parse the json data input -- cgit v1.2.3 From 655343aded3ece533f267bd9fd16aadf0cefff02 Mon Sep 17 00:00:00 2001 From: Alexander Kabui Date: Thu, 23 Sep 2021 12:49:40 +0300 Subject: add mock test data for script --- scripts/wgcna_test_data.csv | 9 +++++++ scripts/wgcna_test_data.json | 64 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+) create mode 100644 scripts/wgcna_test_data.csv create mode 100644 scripts/wgcna_test_data.json diff --git a/scripts/wgcna_test_data.csv b/scripts/wgcna_test_data.csv new file mode 100644 index 0000000..8db9598 --- /dev/null +++ b/scripts/wgcna_test_data.csv @@ -0,0 +1,9 @@ +129S1/SvImJ,A/J,AKR/J,B6D2F1,BALB/cByJ,BALB/cJ +7.142,7.31,7.49,6.899,7.172,7.396 +7.071,7.05,7.313,6.999,7.293,7.117 +7.221,7.246,7.754,6.866,6.752,7.269 +9.221,9.246,9.954,6.866,6.952,9.269 +7.221,7.246,7.754,6.866,6.752,7.269 +7.221,7.246,7.754,6.866,6.752,7.269 +11.221,11.246,11.1154,6.866,6.1152,11.269 + diff --git a/scripts/wgcna_test_data.json b/scripts/wgcna_test_data.json new file mode 100644 index 0000000..7348b4e --- /dev/null +++ b/scripts/wgcna_test_data.json @@ -0,0 +1,64 @@ +{ + "trait_sample_data":[ + { + "129S1/SvImJ": 7.142, + "A/J": 7.31, + "AKR/J": 7.49, + "B6D2F1": 6.899, + "BALB/cByJ": 7.172, + "BALB/cJ": 7.396 + }, + { + "129S1/SvImJ": 7.071, + "A/J": 7.05, + "AKR/J": 7.313, + "B6D2F1": 6.999, + "BALB/cByJ": 7.293, + "BALB/cJ": 7.117 + }, + { + "129S1/SvImJ": 7.221, + "A/J": 7.246, + "AKR/J": 7.754, + "B6D2F1": 6.866, + "BALB/cByJ": 6.752, + "BALB/cJ": 7.269 + }, + { + "129S1/SvImJ": 9.221, + "A/J": 9.246, + "AKR/J": 9.954, + "B6D2F1": 6.866, + "BALB/cByJ": 6.952, + "BALB/cJ": 9.269 + }, + { + "129S1/SvImJ": 7.221, + "A/J": 7.246, + "AKR/J": 7.754, + "B6D2F1": 6.866, + "BALB/cByJ": 6.752, + "BALB/cJ": 7.269 + }, + { + "129S1/SvImJ": 7.221, + "A/J": 7.246, + "AKR/J": 7.754, + "B6D2F1": 6.866, + "BALB/cByJ": 6.752, + "BALB/cJ": 7.269 + }, + { + "129S1/SvImJ": 11.221, + "A/J": 11.246, + "AKR/J": 11.1154, + "B6D2F1": 6.866, + "BALB/cByJ": 6.1152, + "BALB/cJ": 11.269 + } + ], + "TOMtype": "unsigned", + "minModuleSize": 30, + "corType": "pearson" + +} \ No newline at end of file -- cgit v1.2.3 From 9216b6ae956b5c78a9b6d21dbd40b6df1e111264 Mon Sep 17 00:00:00 2001 From: Alexander Kabui Date: Thu, 23 Sep 2021 14:22:14 +0300 Subject: validate required output --- scripts/wgcna_analysis.R | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/scripts/wgcna_analysis.R b/scripts/wgcna_analysis.R index 53b59d5..86ddffb 100644 --- a/scripts/wgcna_analysis.R +++ b/scripts/wgcna_analysis.R @@ -14,7 +14,7 @@ imgDir = Sys.getenv("GENERATED_IMAGE_DIR") args = commandArgs(trailingOnly=TRUE) if (length(args)==0) { - stop("Argument for the file location is requires", call.=FALSE) + stop("Argument for the file location is required", call.=FALSE) } else { # default output file json_file_path = args[1] @@ -92,7 +92,6 @@ genImageRandStr <- function(prefix){ mergedColors <- labels2colors(network$colors) imageLoc <- file.path(imgDir,genImageRandStr("WGCNAoutput")) -imageLoc png(imageLoc,width=1000,height=600,type='cairo-png') plotDendroAndColors(network$dendrograms[[1]],mergedColors[network$blockGenes[[1]]], @@ -102,3 +101,13 @@ addGuide = TRUE, guideHang = 0.05) + +json_data <- list(ModEigens=network$MEs,soft_threshold=sft$fitIndices, + blockGenes =network$blockGenes[[1]], + net_colors =network$colors, + net_unmerged=network$unmergedColors, + imageLoc=imageLoc) + +json_data <- toJSON(json_data) + +write(json_data,"./output.json") \ No newline at end of file -- cgit v1.2.3 From eb2277a5fc96795bf6432e392e62601a3cf94058 Mon Sep 17 00:00:00 2001 From: Alexander Kabui Date: Thu, 23 Sep 2021 14:22:31 +0300 Subject: sample output data --- scripts/output.json | 161 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 161 insertions(+) create mode 100644 scripts/output.json diff --git a/scripts/output.json b/scripts/output.json new file mode 100644 index 0000000..9caf837 --- /dev/null +++ b/scripts/output.json @@ -0,0 +1,161 @@ +{ + "ModEigens":{ + "MEturquoise":[ + 0.0646677768085351, + 0.137200224277058, + 0.63451113720732, + -0.544002665501479, + -0.489487590361863, + 0.197111117570427 + ] + }, + "soft_threshold":{ + "Power":[ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 12, + 14, + 16, + 18, + 20 + ], + "SFT.R.sq":[ + 0.0181093215847335, + 0.00011984142485113, + 0.000171967046945159, + 0.0105462010616537, + 0.0341444584348834, + 0.0687163726151286, + 0.0306423506274298, + 0.0492567394226327, + 0.0789539269997996, + 0.0944880158122527, + 0.122195040270446, + 0.0340768567186139, + 0.0625860126119281, + 0.100082257137014, + 0.128277841930818 + ], + "slope":[ + 3.81011386139005, + -0.170826531149538, + 0.159161787390082, + -1.01047981107833, + -1.55943531024794, + -1.93420125756514, + -1.16799247295814, + -1.33414063070555, + -1.54984944650438, + -1.54715757057087, + -1.49931213589121, + -1.80460140377151, + -2.19055343583319, + -2.52135805259606, + -2.58599487577447 + ], + "truncated.R.sq":[ + 0.768989700952805, + 0.522025793450566, + 0.329341226670409, + 0.110265719555879, + 0.0195649645183151, + -0.0503253079741786, + 0.0507498358330625, + -0.0129255450167765, + -0.035717519210676, + -0.0807094793662766, + -0.0967803564932559, + 0.00172686282662393, + -0.0340811003657508, + -0.0390284600100592, + -0.0489269837827069 + ], + "mean.k.":[ + 4.20178789454309, + 3.44556816856968, + 2.98532344074325, + 2.65297323828966, + 2.39517682414009, + 2.18846935370095, + 2.01963258852289, + 1.87999059876872, + 1.76335304166057, + 1.66510080962817, + 1.51038968360321, + 1.39583176924843, + 1.30882729664563, + 1.24120316437299, + 1.18753154238216 + ], + "median.k.":[ + 4.65733789933094, + 4.13585224131512, + 3.75980713552836, + 3.43775457512904, + 3.15305040369031, + 2.89933881967523, + 2.67225531456956, + 2.46825611568646, + 2.28437024155601, + 2.118086531192, + 1.83011067501282, + 1.59073325345641, + 1.38991168639473, + 1.2201000051609, + 1.07553194658444 + ], + "max.k.":[ + 4.81522245318686, + 4.21987143583501, + 3.83876962723542, + 3.55526976885104, + 3.32904938849614, + 3.14312441404036, + 2.98828051379132, + 2.85837136671219, + 2.74879840851137, + 2.65594228759455, + 2.50929962297015, + 2.40113981571731, + 2.31993775805391, + 2.25792900175825, + 2.2098218130451 + ] + }, + "blockGenes":[ + 1, + 2, + 3, + 4, + 5, + 6, + 7 + ], + "net_colors":{ + "X1":"turquoise", + "X2":"turquoise", + "X3":"turquoise", + "X4":"turquoise", + "X5":"turquoise", + "X6":"turquoise", + "X7":"turquoise" + }, + "net_unmerged":{ + "X1":"turquoise", + "X2":"turquoise", + "X3":"turquoise", + "X4":"turquoise", + "X5":"turquoise", + "X6":"turquoise", + "X7":"turquoise" + }, + "imageLoc":"/WGCNAoutput_1uujpTIpC.png" +} \ No newline at end of file -- cgit v1.2.3 From fc335fa1394a39d1f9f397cb69c755040ecfc5e1 Mon Sep 17 00:00:00 2001 From: Alexander Kabui Date: Thu, 23 Sep 2021 14:37:48 +0300 Subject: append input to output --- scripts/wgcna_analysis.R | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/scripts/wgcna_analysis.R b/scripts/wgcna_analysis.R index 86ddffb..ee749e9 100644 --- a/scripts/wgcna_analysis.R +++ b/scripts/wgcna_analysis.R @@ -20,19 +20,19 @@ if (length(args)==0) { json_file_path = args[1] } -results <- fromJSON(file = json_file_path) +inputData <- fromJSON(file = json_file_path) # parse the json data input -minModuleSize <-results$minModuleSize +minModuleSize <-inputData$minModuleSize -TOMtype <-results$TOMtype +TOMtype <-inputData$TOMtype -corType <-results$corType +corType <-inputData$corType # -trait_sample_data <- do.call(rbind, results$trait_sample_data) +trait_sample_data <- do.call(rbind, inputData$trait_sample_data) dataExpr <- data.frame(apply(trait_sample_data, 2, function(x) as.numeric(as.character(x)))) # transform expressionData @@ -102,12 +102,12 @@ addGuide = TRUE, guideHang = 0.05) -json_data <- list(ModEigens=network$MEs,soft_threshold=sft$fitIndices, +json_data <- list(input = inputData,output = list(ModEigens=network$MEs,soft_threshold=sft$fitIndices, blockGenes =network$blockGenes[[1]], net_colors =network$colors, net_unmerged=network$unmergedColors, - imageLoc=imageLoc) + imageLoc=imageLoc)) json_data <- toJSON(json_data) -write(json_data,"./output.json") \ No newline at end of file +write(json_data,file= json_file_path) \ No newline at end of file -- cgit v1.2.3 From 9c221e0d89603acd5412be95650a469824e2ab99 Mon Sep 17 00:00:00 2001 From: Alexander Kabui Date: Thu, 23 Sep 2021 15:10:16 +0300 Subject: check for na powerEst and use a default value --- scripts/wgcna_analysis.R | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/scripts/wgcna_analysis.R b/scripts/wgcna_analysis.R index ee749e9..c3b1ac8 100644 --- a/scripts/wgcna_analysis.R +++ b/scripts/wgcna_analysis.R @@ -62,13 +62,21 @@ enableWGCNAThreads() powers <- c(c(1:10), seq(from = 12, to=20, by=2)) sft <- pickSoftThreshold(dataExpr, powerVector = powers, verbose = 5) +# check the power estimate + +if (is.na(sft$powerEstimate)){ + powerEst = 1 +}else{ + powerEst = sft$powerEstimate +} + # pass user options network <- blockwiseModules(dataExpr, #similarity matrix options corType = corType, #adjacency matrix options - power = 5, + power = powerEst, networkType = "unsigned", #TOM options TOMtype = TOMtype, -- cgit v1.2.3 From 1c392b4b2786d196af6b882e80270b8cb839f554 Mon Sep 17 00:00:00 2001 From: Alexander Kabui Date: Thu, 23 Sep 2021 15:38:50 +0300 Subject: read generated files from r and return output --- gn3/computations/wgcna.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/gn3/computations/wgcna.py b/gn3/computations/wgcna.py index f0f0fa2..689bc2d 100644 --- a/gn3/computations/wgcna.py +++ b/gn3/computations/wgcna.py @@ -22,7 +22,7 @@ def dump_wgcna_data(request_data: dict): def compose_wgcna_cmd(rscript_path: str, temp_file_path: str): """function to componse wgcna cmd""" - cmd = f"Rscript {rscript_path} {temp_file_path}" + cmd = f"Rscript ./scripts/{rscript_path} {temp_file_path}" return cmd @@ -32,6 +32,9 @@ def call_wgcna_script(rscript_path: str, request_data: dict): cmd = compose_wgcna_cmd(rscript_path, generated_file) try: - return run_cmd(cmd) + + run_cmd(cmd) + with open(generated_file, "r") as outputfile: + return results except Exception as error: raise error -- cgit v1.2.3 From 0ca5f01422883d97e42dd37e59ffacdcf9a65af9 Mon Sep 17 00:00:00 2001 From: Alexander Kabui Date: Thu, 23 Sep 2021 15:58:25 +0300 Subject: Return r error if returncode!=0 --- gn3/computations/wgcna.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/gn3/computations/wgcna.py b/gn3/computations/wgcna.py index 689bc2d..e9b76e8 100644 --- a/gn3/computations/wgcna.py +++ b/gn3/computations/wgcna.py @@ -22,6 +22,7 @@ def dump_wgcna_data(request_data: dict): def compose_wgcna_cmd(rscript_path: str, temp_file_path: str): """function to componse wgcna cmd""" + # (todo):issue relative paths to abs paths cmd = f"Rscript ./scripts/{rscript_path} {temp_file_path}" return cmd @@ -33,8 +34,16 @@ def call_wgcna_script(rscript_path: str, request_data: dict): try: - run_cmd(cmd) + run_cmd_results = run_cmd(cmd) + with open(generated_file, "r") as outputfile: - return results + + if run_cmd_results["code"] != 0: + return run_cmd_results + return { + "data": json.load(outputfile), + **run_cmd_results + } + # return json.load(outputfile) except Exception as error: raise error -- cgit v1.2.3 From 62a5047be6cee5f692d44f97410cab11a01e3396 Mon Sep 17 00:00:00 2001 From: Alexander Kabui Date: Thu, 23 Sep 2021 16:05:17 +0300 Subject: minor fixes for endpoint --- gn3/api/wgcna.py | 3 +++ gn3/computations/wgcna.py | 1 - 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/gn3/api/wgcna.py b/gn3/api/wgcna.py index 89784c4..fa044cf 100644 --- a/gn3/api/wgcna.py +++ b/gn3/api/wgcna.py @@ -19,4 +19,7 @@ def run_wgcna(): results = call_wgcna_script(wgcna_script, wgcna_data) + if results.get("data") is None: + return jsonify(results), 401 + return jsonify(results), 200 diff --git a/gn3/computations/wgcna.py b/gn3/computations/wgcna.py index e9b76e8..436a888 100644 --- a/gn3/computations/wgcna.py +++ b/gn3/computations/wgcna.py @@ -44,6 +44,5 @@ def call_wgcna_script(rscript_path: str, request_data: dict): "data": json.load(outputfile), **run_cmd_results } - # return json.load(outputfile) except Exception as error: raise error -- cgit v1.2.3 From 3062aee581560ae1928d8e6077366fc072646677 Mon Sep 17 00:00:00 2001 From: Alexander Kabui Date: Thu, 23 Sep 2021 21:27:42 +0300 Subject: add traits as columns names and pass as json input --- scripts/wgcna_analysis.R | 18 +++++++++++------- scripts/wgcna_test_data.json | 3 ++- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/scripts/wgcna_analysis.R b/scripts/wgcna_analysis.R index c3b1ac8..e641652 100644 --- a/scripts/wgcna_analysis.R +++ b/scripts/wgcna_analysis.R @@ -53,6 +53,8 @@ dataExpr <- dataExpr[gsg$goodSamples, gsg$goodGenes] ## network constructions and modules +names(dataExpr) = inputData$trait_names + # Allow multi-threading within WGCNA enableWGCNAThreads() @@ -82,6 +84,7 @@ network <- blockwiseModules(dataExpr, TOMtype = TOMtype, #module indentification + verbose = 3, minmodulesSize = minModuleSize, deepSplit = 3, @@ -108,13 +111,14 @@ dendroLabels = FALSE, hang = 0.03, addGuide = TRUE, guideHang = 0.05) - - -json_data <- list(input = inputData,output = list(ModEigens=network$MEs,soft_threshold=sft$fitIndices, - blockGenes =network$blockGenes[[1]], - net_colors =network$colors, - net_unmerged=network$unmergedColors, - imageLoc=imageLoc)) +json_data <- list(input = inputData, + output = list(ModEigens=network$MEs, + soft_threshold=sft$fitIndices, + blockGenes =network$blockGenes[[1]], + net_colors =network$colors, + power_used_for_analy=powerEst, + net_unmerged=network$unmergedColors, + imageLoc=imageLoc)) json_data <- toJSON(json_data) diff --git a/scripts/wgcna_test_data.json b/scripts/wgcna_test_data.json index 7348b4e..1d469f4 100644 --- a/scripts/wgcna_test_data.json +++ b/scripts/wgcna_test_data.json @@ -1,4 +1,5 @@ { + "trait_names":["1455537_at","1425637_at","1449593_at","1421945_a_at","1450423_s_at","1423841_at","1451144_at"], "trait_sample_data":[ { "129S1/SvImJ": 7.142, @@ -61,4 +62,4 @@ "minModuleSize": 30, "corType": "pearson" -} \ No newline at end of file +} -- cgit v1.2.3 From 7dbb0e6d27cdb0923e94685cf44d244dd8a2e105 Mon Sep 17 00:00:00 2001 From: Alexander Kabui Date: Sat, 25 Sep 2021 18:33:12 +0300 Subject: minor fixes for unittests --- tests/integration/test_wgcna.py | 2 +- tests/unit/computations/test_wgcna.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/integration/test_wgcna.py b/tests/integration/test_wgcna.py index 65763c1..39dabb2 100644 --- a/tests/integration/test_wgcna.py +++ b/tests/integration/test_wgcna.py @@ -33,5 +33,5 @@ class WgcnaIntegrationTest(TestCase): response = self.app.post("/api/wgcna/run_wgcna", json=request_data, follow_redirects=True) - self.assertEqual(response.status_code, 200) + self.assertEqual(response.status_code, 401) self.assertEqual(response.get_json(), wgcna_api_data) diff --git a/tests/unit/computations/test_wgcna.py b/tests/unit/computations/test_wgcna.py index fd90732..64f6c14 100644 --- a/tests/unit/computations/test_wgcna.py +++ b/tests/unit/computations/test_wgcna.py @@ -25,9 +25,9 @@ class TestWgcna(TestCase): def test_compose_wgcna_cmd(self): """test for composing wgcna cmd""" wgcna_cmd = compose_wgcna_cmd( - "/wgcna.r", "/tmp/wgcna.json") + "wgcna.r", "/tmp/wgcna.json") self.assertEqual( - wgcna_cmd, "Rscript /wgcna.r /tmp/wgcna.json") + wgcna_cmd, "Rscript ./scripts/wgcna.r /tmp/wgcna.json") @skip("to update tests") def test_create_json_file(self): -- cgit v1.2.3 From 6f25b8e2b1d1a34c054d325b1c37b303529b8827 Mon Sep 17 00:00:00 2001 From: Alexander Kabui Date: Mon, 27 Sep 2021 15:15:28 +0300 Subject: remove unnecessary comments and variables --- scripts/wgcna_analysis.R | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/scripts/wgcna_analysis.R b/scripts/wgcna_analysis.R index e641652..17b3537 100644 --- a/scripts/wgcna_analysis.R +++ b/scripts/wgcna_analysis.R @@ -23,24 +23,14 @@ if (length(args)==0) { inputData <- fromJSON(file = json_file_path) -# parse the json data input - -minModuleSize <-inputData$minModuleSize - -TOMtype <-inputData$TOMtype - -corType <-inputData$corType -# - trait_sample_data <- do.call(rbind, inputData$trait_sample_data) dataExpr <- data.frame(apply(trait_sample_data, 2, function(x) as.numeric(as.character(x)))) # transform expressionData dataExpr <- data.frame(t(dataExpr)) -gsg = goodSamplesGenes(dataExpr, verbose = 3); +gsg = goodSamplesGenes(dataExpr, verbose = 3) -# https://horvath.genetics.ucla.edu/html/CoexpressionNetwork/Rpackages/ if (!gsg$allOK) { if (sum(!gsg$goodGenes)>0) @@ -75,18 +65,18 @@ if (is.na(sft$powerEstimate)){ # pass user options network <- blockwiseModules(dataExpr, #similarity matrix options - corType = corType, + corType = inputData$corType, #adjacency matrix options power = powerEst, networkType = "unsigned", #TOM options - TOMtype = TOMtype, + TOMtype = inputData$TOMtype, #module indentification verbose = 3, - minmodulesSize = minModuleSize, + minmodulesSize = inputData$minModuleSize, deepSplit = 3, PamRespectsDendro = FALSE ) -- cgit v1.2.3 From f51a09e2c5f594425531fe26e8237b09fb6909ae Mon Sep 17 00:00:00 2001 From: Alexander Kabui Date: Mon, 27 Sep 2021 17:29:27 +0300 Subject: return str error for exception --- gn3/computations/wgcna.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/gn3/computations/wgcna.py b/gn3/computations/wgcna.py index 436a888..1ee55f5 100644 --- a/gn3/computations/wgcna.py +++ b/gn3/computations/wgcna.py @@ -45,4 +45,7 @@ def call_wgcna_script(rscript_path: str, request_data: dict): **run_cmd_results } except Exception as error: - raise error + # relook at handling errors gn3 + return { + "output": str(error) + } -- cgit v1.2.3 From 0d60b01476e49b094944c1ba4136e4cc8c28aaba Mon Sep 17 00:00:00 2001 From: Alexander Kabui Date: Mon, 27 Sep 2021 17:30:32 +0300 Subject: add tests for calling wgcna_script --- tests/unit/computations/test_wgcna.py | 96 ++++++++++++++++++++++++++++++++--- 1 file changed, 89 insertions(+), 7 deletions(-) diff --git a/tests/unit/computations/test_wgcna.py b/tests/unit/computations/test_wgcna.py index 64f6c14..57224b3 100644 --- a/tests/unit/computations/test_wgcna.py +++ b/tests/unit/computations/test_wgcna.py @@ -11,16 +11,98 @@ from gn3.computations.wgcna import call_wgcna_script class TestWgcna(TestCase): """test class for wgcna""" + @mock.patch("gn3.computations.wgcna.run_cmd") + @mock.patch("gn3.computations.wgcna.compose_wgcna_cmd") @mock.patch("gn3.computations.wgcna.dump_wgcna_data") - def test_call_wgcna_script(self, mock_dump): - """call wgcna script""" + def test_call_wgcna_script(self, mock_dumping_data, mock_compose_wgcna, mock_run_cmd): + """test for calling wgcna script""" + mock_dumping_data.return_value = "/tmp/QmQPeNsJPyVWPFDVHb77w8G42Fvo15z4bG2X8D2GhfbSXc-test.json" - mock_dump.return_value = "/tmp/QmQPeNsJPyVWPFDVHb77w8G42Fvo15z4bG2X8D2GhfbSXc-test.json" + mock_compose_wgcna.return_value = "Rscript/GUIX_PATH/scripts/r_file.R /tmp/QmQPeNsJPyVWPFDVHb77w8G42Fvo15z4bG2X8D2GhfbSXc-test.json" - results = call_wgcna_script( - "/home/kabui/project/genenetwork3/scripts/wgcna_analysis.R", {}) + request_data = { + "trait_names": ["1455537_at", "1425637_at", "1449593_at", "1421945_a_at", "1450423_s_at", "1423841_at", "1451144_at"], + "trait_sample_data": [ + { + "129S1/SvImJ": 7.142, + "A/J": 7.31, + "AKR/J": 7.49, + "B6D2F1": 6.899, + "BALB/cByJ": 7.172, + "BALB/cJ": 7.396 + }, + { + "129S1/SvImJ": 7.071, + "A/J": 7.05, + "AKR/J": 7.313, + "B6D2F1": 6.999, + "BALB/cByJ": 7.293, + "BALB/cJ": 7.117 + }]} - self.assertEqual(results, "dsedf") + mock_run_cmd_results = { + + "code": 0, + "output": "Flagging genes and samples with too many missing values...\n ..step 1\nAllowing parallel execution with up to 3 working processes.\npickSoftThreshold: will use block size 7.\n pickSoftThreshold: calculating connectivity for given powers...\n ..working on genes 1 through 7 of 7\n Flagging genes and samples with too many missing values...\n ..step 1\n ..Working on block 1 .\n TOM calculation: adjacency..\n ..will not use multithreading.\nclustering..\n ....detecting modules..\n ....calculating module eigengenes..\n ....checking kME in modules..\n ..merging modules that are too close..\n mergeCloseModules: Merging modules whose distance is less than 0.15\n mergeCloseModules: less than two proper modules.\n ..color levels are turquoise\n ..there is nothing to merge.\n Calculating new MEs...\n" + } + + json_output = "{\"inputdata\":{\"trait_sample_data \":{},\"minModuleSize\":30,\"TOMtype\":\"unsigned\"},\"outputdata\":{\"eigengenes\":[],\"colors\":[]}}" + + expected_output = { + + "data": { + "inputdata": { + "trait_sample_data ": {}, + "minModuleSize": 30, + "TOMtype": "unsigned" + }, + + "outputdata": { + "eigengenes": [], + "colors": [] + } + }, + + **mock_run_cmd_results + + } + + with mock.patch("builtins.open", mock.mock_open(read_data=json_output)) as mock_file: + + mock_run_cmd.return_value = mock_run_cmd_results + + results = call_wgcna_script( + "Rscript/GUIX_PATH/scripts/r_file.R", request_data) + + mock_dumping_data.assert_called_once_with(request_data) + + mock_compose_wgcna.assert_called_once_with( + "Rscript/GUIX_PATH/scripts/r_file.R", "/tmp/QmQPeNsJPyVWPFDVHb77w8G42Fvo15z4bG2X8D2GhfbSXc-test.json") + + mock_run_cmd.assert_called_once_with( + "Rscript/GUIX_PATH/scripts/r_file.R /tmp/QmQPeNsJPyVWPFDVHb77w8G42Fvo15z4bG2X8D2GhfbSXc-test.json") + + self.assertEqual(results, expected_output) + + @mock.patch("gn3.computations.wgcna.run_cmd") + @mock.patch("gn3.computations.wgcna.compose_wgcna_cmd") + @mock.patch("gn3.computations.wgcna.dump_wgcna_data") + def test_call_wgcna_script_fails(self, mock_dumping_data, mock_compose_wgcna, mock_run_cmd): + """test for calling wgcna script fails and generates the expected error""" + mock_dumping_data.return_value = "/tmp/QmQPeNsJPyVWPFDVHb77w8G42Fvo15z4bG2X8D2GhfbSXc-test.json" + + mock_compose_wgcna.return_value = "Rscript/GUIX_PATH/scripts/r_file.R /tmp/QmQPeNsJPyVWPFDVHb77w8G42Fvo15z4bG2X8D2GhfbSXc-test.json" + + expected_error = { + "code": 127, + "output": "could not read the json file" + } + + with mock.patch("builtins.open", mock.mock_open(read_data="")) as mock_file: + + mock_run_cmd.return_value = expected_error + self.assertEqual(call_wgcna_script( + "input_file.R", ""), expected_error) def test_compose_wgcna_cmd(self): """test for composing wgcna cmd""" @@ -29,7 +111,7 @@ class TestWgcna(TestCase): self.assertEqual( wgcna_cmd, "Rscript ./scripts/wgcna.r /tmp/wgcna.json") - @skip("to update tests") + @ skip("to update tests") def test_create_json_file(self): """test for writing the data to a csv file""" # # All the traits we have data for (should not contain duplicates) -- cgit v1.2.3 From b6097cff6431e50c132f46dc0d3e1b841897da0f Mon Sep 17 00:00:00 2001 From: Alexander Kabui Date: Mon, 27 Sep 2021 19:14:58 +0300 Subject: add file not found exception --- gn3/computations/wgcna.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gn3/computations/wgcna.py b/gn3/computations/wgcna.py index 1ee55f5..fd508fa 100644 --- a/gn3/computations/wgcna.py +++ b/gn3/computations/wgcna.py @@ -44,8 +44,8 @@ def call_wgcna_script(rscript_path: str, request_data: dict): "data": json.load(outputfile), **run_cmd_results } - except Exception as error: + except FileNotFoundError: # relook at handling errors gn3 return { - "output": str(error) + "output": "output file not found" } -- cgit v1.2.3 From a2da1f5dbc49b0137ef6b8ee9e234178521935f3 Mon Sep 17 00:00:00 2001 From: Alexander Kabui Date: Mon, 27 Sep 2021 19:15:23 +0300 Subject: modify integration tests --- tests/integration/test_wgcna.py | 60 ++++++++++++++++++++++++++++++++--------- 1 file changed, 48 insertions(+), 12 deletions(-) diff --git a/tests/integration/test_wgcna.py b/tests/integration/test_wgcna.py index 39dabb2..078449d 100644 --- a/tests/integration/test_wgcna.py +++ b/tests/integration/test_wgcna.py @@ -13,25 +13,61 @@ class WgcnaIntegrationTest(TestCase): self.app = create_app().test_client() @mock.patch("gn3.api.wgcna.call_wgcna_script") - def test_wgcna_endpoint(self, mock_wgcna_api): + def test_wgcna_endpoint(self, mock_wgcna_script): """test /api/wgcna/run_wgcna endpoint""" - wgcna_api_data = { - "eigengenes": ["1224_at", "121412_at", "32342342-at"], - "dendrogram_file_location": "/tmp/dend1.png" - + wgcna_output_data = { + "code": 0, + "output": "run script successfully", + "data": { + "ModEigens": { + "MEturquoise": [ + 0.0646677768085351, + 0.137200224277058, + 0.63451113720732, + -0.544002665501479, + -0.489487590361863, + 0.197111117570427 + ] + }, + "net_colors": { + "X1": "turquoise", + "X2": "turquoise", + "X3": "turquoise", + "X4": "turquoise" + }, + "imageLoc": "/WGCNAoutput_1uujpTIpC.png" + } } - mock_wgcna_api.return_value = wgcna_api_data request_data = { - - "trait_sample_data": [], - - + "trait_names": [ + "1455537_at", + "1425637_at" + ], + "trait_sample_data": [ + { + "129S1/SvImJ": 6.142, + "A/J": 5.31, + "AKR/J": 3.49, + "B6D2F1": 2.899, + "BALB/cByJ": 1.172, + "BALB/cJ": 7.396 + }, + { + "129S1/SvImJ": 1.42, + "A/J": 2.31, + "AKR/J": 5.49, + "B6D2F1": 3.899, + "BALB/cByJ": 1.172, + "BALB/cJ": 7.396 + } + ] } + mock_wgcna_script.return_value = wgcna_output_data response = self.app.post("/api/wgcna/run_wgcna", json=request_data, follow_redirects=True) - self.assertEqual(response.status_code, 401) - self.assertEqual(response.get_json(), wgcna_api_data) + self.assertEqual(response.status_code, 200) + self.assertEqual(response.get_json(), wgcna_output_data) -- cgit v1.2.3 From 16235188d4ee2ad21a667832baf6cbbea6d8856a Mon Sep 17 00:00:00 2001 From: Alexander Kabui Date: Mon, 27 Sep 2021 19:15:46 +0300 Subject: modify unittests --- tests/unit/computations/test_wgcna.py | 40 ++++++++++++++++++++++++----------- 1 file changed, 28 insertions(+), 12 deletions(-) diff --git a/tests/unit/computations/test_wgcna.py b/tests/unit/computations/test_wgcna.py index 57224b3..ec81d94 100644 --- a/tests/unit/computations/test_wgcna.py +++ b/tests/unit/computations/test_wgcna.py @@ -1,5 +1,4 @@ """module contains python code for wgcna""" -from unittest import skip from unittest import TestCase from unittest import mock @@ -14,8 +13,13 @@ class TestWgcna(TestCase): @mock.patch("gn3.computations.wgcna.run_cmd") @mock.patch("gn3.computations.wgcna.compose_wgcna_cmd") @mock.patch("gn3.computations.wgcna.dump_wgcna_data") - def test_call_wgcna_script(self, mock_dumping_data, mock_compose_wgcna, mock_run_cmd): + def test_call_wgcna_script(self, + mock_dumping_data, + mock_compose_wgcna, + mock_run_cmd): """test for calling wgcna script""" + + # pylint: disable = line-too-long mock_dumping_data.return_value = "/tmp/QmQPeNsJPyVWPFDVHb77w8G42Fvo15z4bG2X8D2GhfbSXc-test.json" mock_compose_wgcna.return_value = "Rscript/GUIX_PATH/scripts/r_file.R /tmp/QmQPeNsJPyVWPFDVHb77w8G42Fvo15z4bG2X8D2GhfbSXc-test.json" @@ -67,7 +71,7 @@ class TestWgcna(TestCase): } - with mock.patch("builtins.open", mock.mock_open(read_data=json_output)) as mock_file: + with mock.patch("builtins.open", mock.mock_open(read_data=json_output)): mock_run_cmd.return_value = mock_run_cmd_results @@ -77,7 +81,8 @@ class TestWgcna(TestCase): mock_dumping_data.assert_called_once_with(request_data) mock_compose_wgcna.assert_called_once_with( - "Rscript/GUIX_PATH/scripts/r_file.R", "/tmp/QmQPeNsJPyVWPFDVHb77w8G42Fvo15z4bG2X8D2GhfbSXc-test.json") + "Rscript/GUIX_PATH/scripts/r_file.R", + "/tmp/QmQPeNsJPyVWPFDVHb77w8G42Fvo15z4bG2X8D2GhfbSXc-test.json") mock_run_cmd.assert_called_once_with( "Rscript/GUIX_PATH/scripts/r_file.R /tmp/QmQPeNsJPyVWPFDVHb77w8G42Fvo15z4bG2X8D2GhfbSXc-test.json") @@ -88,17 +93,19 @@ class TestWgcna(TestCase): @mock.patch("gn3.computations.wgcna.compose_wgcna_cmd") @mock.patch("gn3.computations.wgcna.dump_wgcna_data") def test_call_wgcna_script_fails(self, mock_dumping_data, mock_compose_wgcna, mock_run_cmd): - """test for calling wgcna script fails and generates the expected error""" + """test for calling wgcna script\ + fails and generates the expected error""" + # pylint: disable = line-too-long, mock_dumping_data.return_value = "/tmp/QmQPeNsJPyVWPFDVHb77w8G42Fvo15z4bG2X8D2GhfbSXc-test.json" mock_compose_wgcna.return_value = "Rscript/GUIX_PATH/scripts/r_file.R /tmp/QmQPeNsJPyVWPFDVHb77w8G42Fvo15z4bG2X8D2GhfbSXc-test.json" expected_error = { - "code": 127, + "code": 2, "output": "could not read the json file" } - with mock.patch("builtins.open", mock.mock_open(read_data="")) as mock_file: + with mock.patch("builtins.open", mock.mock_open(read_data="")): mock_run_cmd.return_value = expected_error self.assertEqual(call_wgcna_script( @@ -111,8 +118,9 @@ class TestWgcna(TestCase): self.assertEqual( wgcna_cmd, "Rscript ./scripts/wgcna.r /tmp/wgcna.json") - @ skip("to update tests") - def test_create_json_file(self): + @mock.patch("gn3.computations.wgcna.TMPDIR", "/tmp") + @mock.patch("gn3.computations.wgcna.uuid.uuid4") + def test_create_json_file(self, file_name_generator): """test for writing the data to a csv file""" # # All the traits we have data for (should not contain duplicates) # All the strains we have data for (contains duplicates) @@ -138,7 +146,15 @@ class TestWgcna(TestCase): "minModuleSize": 30 } - results = dump_wgcna_data( - expected_input) + with mock.patch("builtins.open", mock.mock_open()) as file_handler: + + file_name_generator.return_value = "facb73ff-7eef-4053-b6ea-e91d3a22a00c" + + results = dump_wgcna_data( + expected_input) + + file_handler.assert_called_once_with( + "/tmp/facb73ff-7eef-4053-b6ea-e91d3a22a00c.json", 'w') - self.assertEqual(results, {}) + self.assertEqual( + results, "/tmp/facb73ff-7eef-4053-b6ea-e91d3a22a00c.json") -- cgit v1.2.3