From 2b13af49cf57b26ce1c9736fa9d55817f62c9496 Mon Sep 17 00:00:00 2001 From: Anders Pitman Date: Thu, 22 Dec 2016 18:09:14 -0700 Subject: [PATCH 1/7] Basic functionality for generating visualization Invokes Rscript pedigree_and_layout.R to compute the layout (depends on R kinship2 package), and bundles the output into an html template. The final output is an html file which contains all the visualization data except for some 3rd party libraries like JQuery, d3, and Bootstrap, which are currently being pulled from the web by the user's browser at runtime. Note: this functionality depends on pedigree_and_layout.R and the index.html template, which are not included in this commit, since they are part of the dng-vis repo. I'll probably add them in a separate commit. --- src/CMakeLists.txt | 1 + src/mutmap/CMakeLists.txt | 23 ++++++++++++++++++ src/mutmap/mutmap.py.in | 51 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 75 insertions(+) create mode 100644 src/mutmap/CMakeLists.txt create mode 100644 src/mutmap/mutmap.py.in diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 9dc84179..3cb804e1 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -4,6 +4,7 @@ include(CheckLibraryExists) add_subdirectory(lib) add_subdirectory(treecall) +add_subdirectory(mutmap) include_directories(BEFORE "${CMAKE_CURRENT_BINARY_DIR}") diff --git a/src/mutmap/CMakeLists.txt b/src/mutmap/CMakeLists.txt new file mode 100644 index 00000000..5aeb5b33 --- /dev/null +++ b/src/mutmap/CMakeLists.txt @@ -0,0 +1,23 @@ +find_package(PythonLibs 2.7) + +set(MUTMAP_DIR ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBEXECDIR}/mutmap) + +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/mutmap.py.in" + "${CMAKE_CURRENT_BINARY_DIR}/mutmap.py" @ONLY) + +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/pedigree_and_layout.R" + "${CMAKE_CURRENT_BINARY_DIR}/pedigree_and_layout.R" @ONLY) + +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/index.html" + "${CMAKE_CURRENT_BINARY_DIR}/index.html" @ONLY) + +install (DIRECTORY DESTINATION ${MUTMAP_DIR}) + +install (PROGRAMS "${CMAKE_CURRENT_BINARY_DIR}/mutmap.py" + DESTINATION ${CMAKE_INSTALL_LIBEXECDIR} RENAME dng-mutmap) + +install (FILES "${CMAKE_CURRENT_BINARY_DIR}/pedigree_and_layout.R" + DESTINATION ${MUTMAP_DIR}) + +install (FILES "${CMAKE_CURRENT_BINARY_DIR}/index.html" + DESTINATION ${MUTMAP_DIR}) diff --git a/src/mutmap/mutmap.py.in b/src/mutmap/mutmap.py.in new file mode 100644 index 00000000..c3a9215d --- /dev/null +++ b/src/mutmap/mutmap.py.in @@ -0,0 +1,51 @@ +#!/usr/bin/env python2.7 + +import sys +import os +from subprocess import Popen, PIPE + +def escapeForJavaScript(string): + return string.replace('"', '\\x22').replace('\n', '\\x0A') + + +if __name__ == '__main__': + if len(sys.argv) != 4: + print("mutmap requires 3 arguments") + sys.exit(1) + + pedFilename = sys.argv[1] + with open(pedFilename, 'r') as pedFile: + pedFileData = pedFile.read() + + dngOutputFilePath = sys.argv[2] + with open(dngOutputFilePath, 'r') as dngOutputFile: + # Need to escape quotes and newlines for JavaScript + #dngOutputData = dngOutputFile.read().replace('"', '\\x22') + #dngOutputData = dngOutputData.replace('\n', '\\x0A') + dngOutputData = escapeForJavaScript(dngOutputFile.read()) + + templateFilePath = os.path.join('@MUTMAP_DIR@', 'index.html') + with open(templateFilePath, 'r') as templateFile: + templateFileData = templateFile.read() + + layoutScriptPath = os.path.join('@MUTMAP_DIR@', 'pedigree_and_layout.R') + rProc = Popen(['Rscript', layoutScriptPath], stdout=PIPE, + stdin=PIPE, stderr=PIPE) + layoutData = rProc.communicate(input=pedFileData)[0] + + outFileData = templateFileData + + pedFileData = escapeForJavaScript(pedFileData) + outFileData = outFileData.replace( + '/*PEDIGREE_FILE_TEXT_PLACEHOLDER*/', + "var pedigreeFileText = \"" + pedFileData + "\";") + outFileData = outFileData.replace( + '/*LAYOUT_DATA_PLACEHOLDER*/', + "var layoutData = " + layoutData + ";") + outFileData = outFileData.replace( + '/*DNG_VCF_DATA_PLACEHOLDER*/', + "var dngOutputFileText = \"" + dngOutputData + "\";") + + outFileName = sys.argv[3] + with open(outFileName, 'w') as outFile: + outFile.write(outFileData) From f606005d11cc94bcf7490f13f7501fb6b234211e Mon Sep 17 00:00:00 2001 From: Anders Pitman Date: Thu, 22 Dec 2016 18:13:07 -0700 Subject: [PATCH 2/7] Add support files for visualization --- src/mutmap/index.html | 3200 ++++++++++++++++++++++++++++++ src/mutmap/pedigree_and_layout.R | 23 + 2 files changed, 3223 insertions(+) create mode 100644 src/mutmap/index.html create mode 100644 src/mutmap/pedigree_and_layout.R diff --git a/src/mutmap/index.html b/src/mutmap/index.html new file mode 100644 index 00000000..63f1b758 --- /dev/null +++ b/src/mutmap/index.html @@ -0,0 +1,3200 @@ + + + + + + + + + + + + + + +
+
+
+
+
ID:
+ +
+
+ +
+ + + + + + + + + + diff --git a/src/mutmap/pedigree_and_layout.R b/src/mutmap/pedigree_and_layout.R new file mode 100644 index 00000000..7a051ac0 --- /dev/null +++ b/src/mutmap/pedigree_and_layout.R @@ -0,0 +1,23 @@ +#!/usr/bin/env Rscript + +library(kinship2) +library(jsonlite) + +f <- file("stdin") +data <- read.table(f, header=FALSE) +ped <- pedigree(id=data[,2], dadid=data[,3], momid=data[,4], sex=data[,5], + famid=data[,1]) + +ped1 <- ped['1'] +outData <- list() +outData$layout <- align.pedigree(ped1) +pedigree <- list() +pedigree$id <- ped1$id +pedigree$famid <- ped1$famid +pedigree$sex <- ped1$sex +pedigree$findex <- ped1$findex +pedigree$mindex <- ped1$mindex +outData$pedigree <- pedigree + +jsonOut <- (toJSON(outData, pretty=TRUE, digits=NA)) +cat(jsonOut) From c53ba5443b098f99cca2ee511be8b87519e06070 Mon Sep 17 00:00:00 2001 From: Anders Pitman Date: Thu, 22 Dec 2016 20:24:00 -0700 Subject: [PATCH 3/7] Basic checking for Rscript dependency Also checks that kinship2 and jsonlite R packages are installed and issues a warning if not. --- Modules/FindRscript.cmake | 5 +++++ src/mutmap/CMakeLists.txt | 1 + src/mutmap/mutmap.py.in | 22 ++++++++++++++++------ 3 files changed, 22 insertions(+), 6 deletions(-) create mode 100644 Modules/FindRscript.cmake diff --git a/Modules/FindRscript.cmake b/Modules/FindRscript.cmake new file mode 100644 index 00000000..65c3dd36 --- /dev/null +++ b/Modules/FindRscript.cmake @@ -0,0 +1,5 @@ +find_program(RSCRIPT_COMMAND Rscript DOC "Rscript executable.") + +if (NOT RSCRIPT_COMMAND) + message(STATUS "Rscript not found. It is required if you want to generate a visualization via dng mutmap. Please install R with Rscript") +endif() diff --git a/src/mutmap/CMakeLists.txt b/src/mutmap/CMakeLists.txt index 5aeb5b33..560f7271 100644 --- a/src/mutmap/CMakeLists.txt +++ b/src/mutmap/CMakeLists.txt @@ -1,4 +1,5 @@ find_package(PythonLibs 2.7) +find_package(Rscript) set(MUTMAP_DIR ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBEXECDIR}/mutmap) diff --git a/src/mutmap/mutmap.py.in b/src/mutmap/mutmap.py.in index c3a9215d..01e6adae 100644 --- a/src/mutmap/mutmap.py.in +++ b/src/mutmap/mutmap.py.in @@ -2,26 +2,36 @@ import sys import os -from subprocess import Popen, PIPE +from subprocess import Popen, PIPE, call def escapeForJavaScript(string): + # Need to escape quotes and newlines for JavaScript return string.replace('"', '\\x22').replace('\n', '\\x0A') +def checkRscriptDependencies(): + for dep in ['kinship2', 'jsonlite']: + proc = Popen(['@RSCRIPT_COMMAND@', '-'], stdout=PIPE, stdin=PIPE, + stderr=PIPE) + proc.communicate(input="library({})".format(dep)) + + if proc.returncode != 0: + print("mutmap requires {} library for R. Please install".format(dep)) + exit(1) + if __name__ == '__main__': if len(sys.argv) != 4: print("mutmap requires 3 arguments") sys.exit(1) + checkRscriptDependencies() + pedFilename = sys.argv[1] with open(pedFilename, 'r') as pedFile: pedFileData = pedFile.read() dngOutputFilePath = sys.argv[2] with open(dngOutputFilePath, 'r') as dngOutputFile: - # Need to escape quotes and newlines for JavaScript - #dngOutputData = dngOutputFile.read().replace('"', '\\x22') - #dngOutputData = dngOutputData.replace('\n', '\\x0A') dngOutputData = escapeForJavaScript(dngOutputFile.read()) templateFilePath = os.path.join('@MUTMAP_DIR@', 'index.html') @@ -29,8 +39,8 @@ if __name__ == '__main__': templateFileData = templateFile.read() layoutScriptPath = os.path.join('@MUTMAP_DIR@', 'pedigree_and_layout.R') - rProc = Popen(['Rscript', layoutScriptPath], stdout=PIPE, - stdin=PIPE, stderr=PIPE) + rProc = Popen(['@RSCRIPT_COMMAND@', layoutScriptPath], stdout=PIPE, + stdin=PIPE, stderr=PIPE) layoutData = rProc.communicate(input=pedFileData)[0] outFileData = templateFileData From 0562cf24f2a8548d583d6ec46e667aa32b2a0e66 Mon Sep 17 00:00:00 2001 From: Anders Pitman Date: Thu, 22 Dec 2016 20:35:27 -0700 Subject: [PATCH 4/7] Improve Rscript cmake discovery Use find_package_handle_standard_args to get standard messages. --- Modules/FindRscript.cmake | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Modules/FindRscript.cmake b/Modules/FindRscript.cmake index 65c3dd36..988d797d 100644 --- a/Modules/FindRscript.cmake +++ b/Modules/FindRscript.cmake @@ -1,5 +1,3 @@ find_program(RSCRIPT_COMMAND Rscript DOC "Rscript executable.") -if (NOT RSCRIPT_COMMAND) - message(STATUS "Rscript not found. It is required if you want to generate a visualization via dng mutmap. Please install R with Rscript") -endif() +find_package_handle_standard_args(Rscript DEFAULT_MSG RSCRIPT_COMMAND) From 93fcbbdc37d652c0ba0d808b26fc7aebff097c02 Mon Sep 17 00:00:00 2001 From: Anders Pitman Date: Thu, 22 Dec 2016 20:42:40 -0700 Subject: [PATCH 5/7] Use shebangs from cmake --- src/mutmap/CMakeLists.txt | 4 ++-- src/mutmap/{index.html => index.html.in} | 0 src/mutmap/mutmap.py.in | 2 +- .../{pedigree_and_layout.R => pedigree_and_layout.R.in} | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) rename src/mutmap/{index.html => index.html.in} (100%) rename src/mutmap/{pedigree_and_layout.R => pedigree_and_layout.R.in} (95%) diff --git a/src/mutmap/CMakeLists.txt b/src/mutmap/CMakeLists.txt index 560f7271..85ef269f 100644 --- a/src/mutmap/CMakeLists.txt +++ b/src/mutmap/CMakeLists.txt @@ -6,10 +6,10 @@ set(MUTMAP_DIR ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBEXECDIR}/mutmap) configure_file("${CMAKE_CURRENT_SOURCE_DIR}/mutmap.py.in" "${CMAKE_CURRENT_BINARY_DIR}/mutmap.py" @ONLY) -configure_file("${CMAKE_CURRENT_SOURCE_DIR}/pedigree_and_layout.R" +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/pedigree_and_layout.R.in" "${CMAKE_CURRENT_BINARY_DIR}/pedigree_and_layout.R" @ONLY) -configure_file("${CMAKE_CURRENT_SOURCE_DIR}/index.html" +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/index.html.in" "${CMAKE_CURRENT_BINARY_DIR}/index.html" @ONLY) install (DIRECTORY DESTINATION ${MUTMAP_DIR}) diff --git a/src/mutmap/index.html b/src/mutmap/index.html.in similarity index 100% rename from src/mutmap/index.html rename to src/mutmap/index.html.in diff --git a/src/mutmap/mutmap.py.in b/src/mutmap/mutmap.py.in index 01e6adae..329b4144 100644 --- a/src/mutmap/mutmap.py.in +++ b/src/mutmap/mutmap.py.in @@ -1,4 +1,4 @@ -#!/usr/bin/env python2.7 +#!@PYTHON_EXECUTABLE@ import sys import os diff --git a/src/mutmap/pedigree_and_layout.R b/src/mutmap/pedigree_and_layout.R.in similarity index 95% rename from src/mutmap/pedigree_and_layout.R rename to src/mutmap/pedigree_and_layout.R.in index 7a051ac0..d1f02c1d 100644 --- a/src/mutmap/pedigree_and_layout.R +++ b/src/mutmap/pedigree_and_layout.R.in @@ -1,4 +1,4 @@ -#!/usr/bin/env Rscript +#!@RSCRIPT_COMMAND@ library(kinship2) library(jsonlite) From 295945696ac29a1978aad13b8bf2da6055e1d33c Mon Sep 17 00:00:00 2001 From: Anders Pitman Date: Fri, 23 Dec 2016 12:25:12 -0700 Subject: [PATCH 6/7] Improve development pipeline for visualization Made the development and deployment pipelines much closer. The same scripts are now used for both for the most part. Also added argument parsing to dng mutmap --- src/mutmap/CMakeLists.txt | 27 +++-- src/mutmap/build.py | 98 +++++++++++++++++++ src/mutmap/{index.html.in => bundle.js} | 53 ---------- src/mutmap/index.html | 53 ++++++++++ src/mutmap/mutmap.py.in | 61 ------------ src/mutmap/mutmap.sh.in | 5 + ..._and_layout.R.in => pedigree_and_layout.R} | 2 +- 7 files changed, 177 insertions(+), 122 deletions(-) create mode 100755 src/mutmap/build.py rename src/mutmap/{index.html.in => bundle.js} (98%) create mode 100644 src/mutmap/index.html delete mode 100644 src/mutmap/mutmap.py.in create mode 100644 src/mutmap/mutmap.sh.in rename src/mutmap/{pedigree_and_layout.R.in => pedigree_and_layout.R} (95%) diff --git a/src/mutmap/CMakeLists.txt b/src/mutmap/CMakeLists.txt index 85ef269f..40cb683b 100644 --- a/src/mutmap/CMakeLists.txt +++ b/src/mutmap/CMakeLists.txt @@ -3,22 +3,35 @@ find_package(Rscript) set(MUTMAP_DIR ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBEXECDIR}/mutmap) -configure_file("${CMAKE_CURRENT_SOURCE_DIR}/mutmap.py.in" - "${CMAKE_CURRENT_BINARY_DIR}/mutmap.py" @ONLY) +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/mutmap.sh.in" + "${CMAKE_CURRENT_BINARY_DIR}/mutmap.sh" @ONLY) -configure_file("${CMAKE_CURRENT_SOURCE_DIR}/pedigree_and_layout.R.in" - "${CMAKE_CURRENT_BINARY_DIR}/pedigree_and_layout.R" @ONLY) +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/build.py" + "${CMAKE_CURRENT_BINARY_DIR}/build.py" @ONLY) + +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/bundle.js" + "${CMAKE_CURRENT_BINARY_DIR}/bundle.js" @ONLY) -configure_file("${CMAKE_CURRENT_SOURCE_DIR}/index.html.in" +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/index.html" "${CMAKE_CURRENT_BINARY_DIR}/index.html" @ONLY) +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/pedigree_and_layout.R" + "${CMAKE_CURRENT_BINARY_DIR}/pedigree_and_layout.R" @ONLY) + install (DIRECTORY DESTINATION ${MUTMAP_DIR}) -install (PROGRAMS "${CMAKE_CURRENT_BINARY_DIR}/mutmap.py" +install (PROGRAMS "${CMAKE_CURRENT_BINARY_DIR}/mutmap.sh" DESTINATION ${CMAKE_INSTALL_LIBEXECDIR} RENAME dng-mutmap) -install (FILES "${CMAKE_CURRENT_BINARY_DIR}/pedigree_and_layout.R" +install (FILES "${CMAKE_CURRENT_BINARY_DIR}/build.py" + DESTINATION ${MUTMAP_DIR}) + +install (FILES "${CMAKE_CURRENT_BINARY_DIR}/bundle.js" DESTINATION ${MUTMAP_DIR}) install (FILES "${CMAKE_CURRENT_BINARY_DIR}/index.html" DESTINATION ${MUTMAP_DIR}) + +install (FILES "${CMAKE_CURRENT_BINARY_DIR}/pedigree_and_layout.R" + DESTINATION ${MUTMAP_DIR}) + diff --git a/src/mutmap/build.py b/src/mutmap/build.py new file mode 100755 index 00000000..cfd6e704 --- /dev/null +++ b/src/mutmap/build.py @@ -0,0 +1,98 @@ +#!/usr/bin/env python2.7 + +import sys +import os +import argparse +from subprocess import Popen, PIPE, call + +def escapeAsciiForJavaScript(string): + # Need to escape quotes and newlines for JavaScript + return string.replace('"', '\\x22').replace('\n', '\\x0A') + +def checkRscriptDependencies(rscript): + for dep in ['kinship2', 'jsonlite']: + proc = Popen([rscript, '-'], stdout=PIPE, stdin=PIPE, + stderr=PIPE) + proc.communicate(input="library({})".format(dep)) + + if proc.returncode != 0: + print("mutmap requires {} library for R. Please install".format(dep)) + exit(1) + +def computeLayout(rscript, sourceDir, pedFileData): + + checkRscriptDependencies(rscript) + + layoutScriptPath = os.path.join(sourceDir, 'pedigree_and_layout.R') + rProc = Popen([rscript, layoutScriptPath], stdout=PIPE, + stdin=PIPE, stderr=PIPE) + layoutData = rProc.communicate(input=pedFileData)[0] + return layoutData + +def createFileReader(directory): + def fileReader(filename): + path = os.path.join(directory, filename) + with open(path, 'r') as f: + return f.read() + return fileReader + + +if __name__ == '__main__': + + argParser = argparse.ArgumentParser(description="Visualization for denovogear") + argParser.add_argument("--rscript_location", type=str, + required=True, + help="Location of Rscript executable") + argParser.add_argument('-p', "--ped_file", type=str, required=True, + help="Pedigree file in ped format") + argParser.add_argument("--source_dir", type=str, required=True, + help="Source directory for input files") + argParser.add_argument('-i', "--dng_output_file_path", type=str, required=True, + help="denovogear output VCF") + argParser.add_argument('-o', "--output_file_path", type=str, required=True, + help="Output file path") + args = argParser.parse_args() + + readFile = createFileReader(args.source_dir) + + rscript = args.rscript_location + + pedFilePath = args.ped_file + + # Store ped file and compute layout + with open(pedFilePath, 'r') as pedFile: + pedFileData = pedFile.read() + layoutData = computeLayout(rscript, args.source_dir, pedFileData) + pedFileData = escapeAsciiForJavaScript(pedFileData) + + # Store dng output file + dngOutputFilePath = args.dng_output_file_path + with open(dngOutputFilePath, 'r') as dngOutputFile: + dngOutputData = escapeAsciiForJavaScript(dngOutputFile.read()) + + # Load javascript bundle file (from browserify build) + bundleFileData = readFile('bundle.js') + + # Load template file + templateFilePath = os.path.join(args.source_dir, 'index.html') + with open(templateFilePath, 'r') as templateFile: + templateFileData = templateFile.read() + outFileData = templateFileData + + # Replace template placeholders with actual data + outFileData = outFileData.replace( + '', + bundleFileData) + outFileData = outFileData.replace( + '/*PEDIGREE_FILE_TEXT_PLACEHOLDER*/', + "var pedigreeFileText = \"" + pedFileData + "\";") + outFileData = outFileData.replace( + '/*LAYOUT_DATA_PLACEHOLDER*/', + "var layoutData = " + layoutData + ";") + outFileData = outFileData.replace( + '/*DNG_VCF_DATA_PLACEHOLDER*/', + "var dngOutputFileText = \"" + dngOutputData + "\";") + + outFileName = args.output_file_path + with open(outFileName, 'w') as outFile: + outFile.write(outFileData) diff --git a/src/mutmap/index.html.in b/src/mutmap/bundle.js similarity index 98% rename from src/mutmap/index.html.in rename to src/mutmap/bundle.js index 63f1b758..308a11e5 100644 --- a/src/mutmap/index.html.in +++ b/src/mutmap/bundle.js @@ -1,50 +1,3 @@ - - - - - - - - - - - - - - -
-
-
-
-
ID:
- -
-
- -
- - - - - - - - - - diff --git a/src/mutmap/index.html b/src/mutmap/index.html new file mode 100644 index 00000000..2c948a50 --- /dev/null +++ b/src/mutmap/index.html @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + +
+
+
+
+
ID:
+ +
+
+ +
+ + + + + + + + + + diff --git a/src/mutmap/mutmap.py.in b/src/mutmap/mutmap.py.in deleted file mode 100644 index 329b4144..00000000 --- a/src/mutmap/mutmap.py.in +++ /dev/null @@ -1,61 +0,0 @@ -#!@PYTHON_EXECUTABLE@ - -import sys -import os -from subprocess import Popen, PIPE, call - -def escapeForJavaScript(string): - # Need to escape quotes and newlines for JavaScript - return string.replace('"', '\\x22').replace('\n', '\\x0A') - -def checkRscriptDependencies(): - for dep in ['kinship2', 'jsonlite']: - proc = Popen(['@RSCRIPT_COMMAND@', '-'], stdout=PIPE, stdin=PIPE, - stderr=PIPE) - proc.communicate(input="library({})".format(dep)) - - if proc.returncode != 0: - print("mutmap requires {} library for R. Please install".format(dep)) - exit(1) - - -if __name__ == '__main__': - if len(sys.argv) != 4: - print("mutmap requires 3 arguments") - sys.exit(1) - - checkRscriptDependencies() - - pedFilename = sys.argv[1] - with open(pedFilename, 'r') as pedFile: - pedFileData = pedFile.read() - - dngOutputFilePath = sys.argv[2] - with open(dngOutputFilePath, 'r') as dngOutputFile: - dngOutputData = escapeForJavaScript(dngOutputFile.read()) - - templateFilePath = os.path.join('@MUTMAP_DIR@', 'index.html') - with open(templateFilePath, 'r') as templateFile: - templateFileData = templateFile.read() - - layoutScriptPath = os.path.join('@MUTMAP_DIR@', 'pedigree_and_layout.R') - rProc = Popen(['@RSCRIPT_COMMAND@', layoutScriptPath], stdout=PIPE, - stdin=PIPE, stderr=PIPE) - layoutData = rProc.communicate(input=pedFileData)[0] - - outFileData = templateFileData - - pedFileData = escapeForJavaScript(pedFileData) - outFileData = outFileData.replace( - '/*PEDIGREE_FILE_TEXT_PLACEHOLDER*/', - "var pedigreeFileText = \"" + pedFileData + "\";") - outFileData = outFileData.replace( - '/*LAYOUT_DATA_PLACEHOLDER*/', - "var layoutData = " + layoutData + ";") - outFileData = outFileData.replace( - '/*DNG_VCF_DATA_PLACEHOLDER*/', - "var dngOutputFileText = \"" + dngOutputData + "\";") - - outFileName = sys.argv[3] - with open(outFileName, 'w') as outFile: - outFile.write(outFileData) diff --git a/src/mutmap/mutmap.sh.in b/src/mutmap/mutmap.sh.in new file mode 100644 index 00000000..3e3934f9 --- /dev/null +++ b/src/mutmap/mutmap.sh.in @@ -0,0 +1,5 @@ +#!/bin/bash + +@PYTHON_EXECUTABLE@ @MUTMAP_DIR@/build.py \ + --rscript_location @RSCRIPT_COMMAND@ \ + --source_dir @MUTMAP_DIR@ $@ diff --git a/src/mutmap/pedigree_and_layout.R.in b/src/mutmap/pedigree_and_layout.R similarity index 95% rename from src/mutmap/pedigree_and_layout.R.in rename to src/mutmap/pedigree_and_layout.R index d1f02c1d..7a051ac0 100644 --- a/src/mutmap/pedigree_and_layout.R.in +++ b/src/mutmap/pedigree_and_layout.R @@ -1,4 +1,4 @@ -#!@RSCRIPT_COMMAND@ +#!/usr/bin/env Rscript library(kinship2) library(jsonlite) From c5cd7960e11987007888c2b75a2ea14ab6451dc4 Mon Sep 17 00:00:00 2001 From: Anders Pitman Date: Fri, 23 Dec 2016 18:51:26 -0700 Subject: [PATCH 7/7] Port visualization from python to R --- src/mutmap/CMakeLists.txt | 7 ++- src/mutmap/build.R | 108 ++++++++++++++++++++++++++++++++++++++ src/mutmap/build.py | 98 ---------------------------------- src/mutmap/bundle.js | 4 +- src/mutmap/mutmap.sh.in | 4 +- 5 files changed, 113 insertions(+), 108 deletions(-) create mode 100755 src/mutmap/build.R delete mode 100755 src/mutmap/build.py diff --git a/src/mutmap/CMakeLists.txt b/src/mutmap/CMakeLists.txt index 40cb683b..9cc406dc 100644 --- a/src/mutmap/CMakeLists.txt +++ b/src/mutmap/CMakeLists.txt @@ -1,4 +1,3 @@ -find_package(PythonLibs 2.7) find_package(Rscript) set(MUTMAP_DIR ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBEXECDIR}/mutmap) @@ -6,8 +5,8 @@ set(MUTMAP_DIR ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBEXECDIR}/mutmap) configure_file("${CMAKE_CURRENT_SOURCE_DIR}/mutmap.sh.in" "${CMAKE_CURRENT_BINARY_DIR}/mutmap.sh" @ONLY) -configure_file("${CMAKE_CURRENT_SOURCE_DIR}/build.py" - "${CMAKE_CURRENT_BINARY_DIR}/build.py" @ONLY) +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/build.R" + "${CMAKE_CURRENT_BINARY_DIR}/build.R" @ONLY) configure_file("${CMAKE_CURRENT_SOURCE_DIR}/bundle.js" "${CMAKE_CURRENT_BINARY_DIR}/bundle.js" @ONLY) @@ -23,7 +22,7 @@ install (DIRECTORY DESTINATION ${MUTMAP_DIR}) install (PROGRAMS "${CMAKE_CURRENT_BINARY_DIR}/mutmap.sh" DESTINATION ${CMAKE_INSTALL_LIBEXECDIR} RENAME dng-mutmap) -install (FILES "${CMAKE_CURRENT_BINARY_DIR}/build.py" +install (FILES "${CMAKE_CURRENT_BINARY_DIR}/build.R" DESTINATION ${MUTMAP_DIR}) install (FILES "${CMAKE_CURRENT_BINARY_DIR}/bundle.js" diff --git a/src/mutmap/build.R b/src/mutmap/build.R new file mode 100755 index 00000000..4a1799c2 --- /dev/null +++ b/src/mutmap/build.R @@ -0,0 +1,108 @@ +#!/usr/bin/env Rscript + +parseArguments <- function() { + + library(argparser, quietly=TRUE) + + argParser <- arg_parser("Visualization for DeNovoGear") + argParser <- add_argument(argParser, "sourceDirectory", + help="Source directory for input files", + type="character") + argParser <- add_argument(argParser, "pedFilePath", + help="Path to pedigree file", type="character") + argParser <- add_argument(argParser, "dngOutputFilePath", + help="DeNovoGear output VCF", type="character") + argParser <- add_argument(argParser, "outputFilePath", + help="Where to write the output", + type="character") + argv <- parse_args(argParser) + return(argv) +} + +computeLayout <- function(pedFilePath) { + + library(kinship2, quietly=TRUE) + library(jsonlite, quietly=TRUE) + + data <- read.table(pedFilePath, header=FALSE) + + ped <- pedigree(id=data[,2], dadid=data[,3], momid=data[,4], sex=data[,5], + famid=data[,1]) + + ped1 <- ped['1'] + outData <- list() + outData$layout <- align.pedigree(ped1) + pedigree <- list() + pedigree$id <- ped1$id + pedigree$famid <- ped1$famid + pedigree$sex <- ped1$sex + pedigree$findex <- ped1$findex + pedigree$mindex <- ped1$mindex + outData$pedigree <- pedigree + + jsonOut <- (toJSON(outData, pretty=TRUE, digits=NA)) + return(jsonOut) +} + +readFile <- function(filePath) { + return(readChar(filePath, file.info(filePath)$size)) +} + +escapeAsciiForJavaScript <- function(string) { + return(gsub('\n', '\\\\x0A', gsub('"', '\\\\x22', string))) +} + +build <- function(sourceDirectory, pedFilePath, dngOutputFilePath, + outputFilePath) { + + pedFileText <- escapeAsciiForJavaScript(readFile(pedFilePath)) + bundleFilePath <- file.path(sourceDirectory, 'bundle.js') + bundleFileText <- readFile(bundleFilePath) + + templateFilePath <- file.path(sourceDirectory, 'index.html') + templateFileText <- readFile(templateFilePath) + outputText <- sub("", bundleFileText, + templateFileText, fixed=TRUE) + + outputText <- sub("/*PEDIGREE_FILE_TEXT_PLACEHOLDER*/", + paste("var pedigreeFileText = \"", pedFileText, "\";", + sep=""), + outputText, fixed=TRUE) + + layoutData <- computeLayout(pedFilePath) + outputText <- sub("/*LAYOUT_DATA_PLACEHOLDER*/", + paste("var layoutData = ", layoutData, ";", sep=""), + outputText, fixed=TRUE) + + dngOutputFileText <- escapeAsciiForJavaScript(readFile(dngOutputFilePath)) + outputText <- sub("/*DNG_VCF_DATA_PLACEHOLDER*/", + paste("var dngOutputFileText = \"", dngOutputFileText, + "\";", sep=""), + outputText, fixed=TRUE) + + write(outputText, outputFilePath) +} + +test <- function() { + sourceDirectory <- file.path('dist') + pedFilePath <- file.path('test', 'data', 'test.ped') + dngOutputFilePath <- file.path('test', 'data', 'dng_test_output.vcf') + outputFilePath <- file.path('mutmap.html') + + build(sourceDirectory, pedFilePath, dngOutputFilePath, outputFilePath) +} + +main <- function() { + argv <- parseArguments() + sourceDirectory <- argv$sourceDirectory + pedFilePath <- argv$pedFilePath + dngOutputFilePath <- argv$dngOutputFilePath + outputFilePath <- argv$outputFilePath + + build(sourceDirectory, pedFilePath, dngOutputFilePath, outputFilePath) +} + +if (!interactive()) { + main() +} + diff --git a/src/mutmap/build.py b/src/mutmap/build.py deleted file mode 100755 index cfd6e704..00000000 --- a/src/mutmap/build.py +++ /dev/null @@ -1,98 +0,0 @@ -#!/usr/bin/env python2.7 - -import sys -import os -import argparse -from subprocess import Popen, PIPE, call - -def escapeAsciiForJavaScript(string): - # Need to escape quotes and newlines for JavaScript - return string.replace('"', '\\x22').replace('\n', '\\x0A') - -def checkRscriptDependencies(rscript): - for dep in ['kinship2', 'jsonlite']: - proc = Popen([rscript, '-'], stdout=PIPE, stdin=PIPE, - stderr=PIPE) - proc.communicate(input="library({})".format(dep)) - - if proc.returncode != 0: - print("mutmap requires {} library for R. Please install".format(dep)) - exit(1) - -def computeLayout(rscript, sourceDir, pedFileData): - - checkRscriptDependencies(rscript) - - layoutScriptPath = os.path.join(sourceDir, 'pedigree_and_layout.R') - rProc = Popen([rscript, layoutScriptPath], stdout=PIPE, - stdin=PIPE, stderr=PIPE) - layoutData = rProc.communicate(input=pedFileData)[0] - return layoutData - -def createFileReader(directory): - def fileReader(filename): - path = os.path.join(directory, filename) - with open(path, 'r') as f: - return f.read() - return fileReader - - -if __name__ == '__main__': - - argParser = argparse.ArgumentParser(description="Visualization for denovogear") - argParser.add_argument("--rscript_location", type=str, - required=True, - help="Location of Rscript executable") - argParser.add_argument('-p', "--ped_file", type=str, required=True, - help="Pedigree file in ped format") - argParser.add_argument("--source_dir", type=str, required=True, - help="Source directory for input files") - argParser.add_argument('-i', "--dng_output_file_path", type=str, required=True, - help="denovogear output VCF") - argParser.add_argument('-o', "--output_file_path", type=str, required=True, - help="Output file path") - args = argParser.parse_args() - - readFile = createFileReader(args.source_dir) - - rscript = args.rscript_location - - pedFilePath = args.ped_file - - # Store ped file and compute layout - with open(pedFilePath, 'r') as pedFile: - pedFileData = pedFile.read() - layoutData = computeLayout(rscript, args.source_dir, pedFileData) - pedFileData = escapeAsciiForJavaScript(pedFileData) - - # Store dng output file - dngOutputFilePath = args.dng_output_file_path - with open(dngOutputFilePath, 'r') as dngOutputFile: - dngOutputData = escapeAsciiForJavaScript(dngOutputFile.read()) - - # Load javascript bundle file (from browserify build) - bundleFileData = readFile('bundle.js') - - # Load template file - templateFilePath = os.path.join(args.source_dir, 'index.html') - with open(templateFilePath, 'r') as templateFile: - templateFileData = templateFile.read() - outFileData = templateFileData - - # Replace template placeholders with actual data - outFileData = outFileData.replace( - '', - bundleFileData) - outFileData = outFileData.replace( - '/*PEDIGREE_FILE_TEXT_PLACEHOLDER*/', - "var pedigreeFileText = \"" + pedFileData + "\";") - outFileData = outFileData.replace( - '/*LAYOUT_DATA_PLACEHOLDER*/', - "var layoutData = " + layoutData + ";") - outFileData = outFileData.replace( - '/*DNG_VCF_DATA_PLACEHOLDER*/', - "var dngOutputFileText = \"" + dngOutputData + "\";") - - outFileName = args.output_file_path - with open(outFileName, 'w') as outFile: - outFile.write(outFileData) diff --git a/src/mutmap/bundle.js b/src/mutmap/bundle.js index 308a11e5..840e8a8b 100644 --- a/src/mutmap/bundle.js +++ b/src/mutmap/bundle.js @@ -3142,6 +3142,4 @@ function main() { }()); -},{}],10:[function(require,module,exports){ -arguments[4][5][0].apply(exports,arguments) -},{"dup":5,"underscore":4}]},{},[6,7,9,8,10]); +},{}]},{},[6,7,9,8]); diff --git a/src/mutmap/mutmap.sh.in b/src/mutmap/mutmap.sh.in index 3e3934f9..90a99789 100644 --- a/src/mutmap/mutmap.sh.in +++ b/src/mutmap/mutmap.sh.in @@ -1,5 +1,3 @@ #!/bin/bash -@PYTHON_EXECUTABLE@ @MUTMAP_DIR@/build.py \ - --rscript_location @RSCRIPT_COMMAND@ \ - --source_dir @MUTMAP_DIR@ $@ +@RSCRIPT_COMMAND@ --vanilla @MUTMAP_DIR@/build.R @MUTMAP_DIR@ $@