From 059f451047eda61875ae89a53c71700368f22a79 Mon Sep 17 00:00:00 2001 From: Nick Booher Date: Tue, 16 Feb 2021 12:14:26 -0600 Subject: [PATCH] MacOS bundle (#2) * Try that * Get python path * Get python path * Get python path * That's not going to work * Compile scanfold with nuitka * Missing sed flag * Bundle rnastructure and viennarna * tar file * less verbose * i think thats everything * fix path * More fixes * Change multiprocessing method to work with nuitka * python2/python3 * Switch fork * Try using threads * Build macos for releases * Make run_me double clickable * Final tweaks * Switch submodule back --- .github/workflows/macos.yml | 16 +++++++++- README.md | 6 ++-- ScanFold | 2 +- macos/bundle_macos.sh | 62 +++++++++++++++++++++++++++++++++++-- macos/run_me.command | 10 ++++++ scripts/run_scanfold.py | 39 +++++++++++++++++------ 6 files changed, 119 insertions(+), 16 deletions(-) create mode 100755 macos/run_me.command diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index abd23b5..bb7dab5 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -4,6 +4,8 @@ name: MacOS package on: + release: + types: [published] workflow_dispatch: jobs: @@ -29,4 +31,16 @@ jobs: if: ${{ success() && github.event_name == 'workflow_dispatch' }} with: name: scanfoldigv-macos - path: ./scanfoldigv-macos.zip \ No newline at end of file + path: ./scanfoldigv-macos.zip + + - name: Upload Release Asset (automatically on release) + id: upload-release-asset + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ github.event.release.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps + asset_path: ./scanfoldigv-macos.zip + asset_name: scanfoldigv-macos-${{github.event.release.tag_name}}.zip + asset_content_type: application/zip + if: ${{ github.event_name == 'release' }} diff --git a/README.md b/README.md index c8e2be1..3678365 100644 --- a/README.md +++ b/README.md @@ -4,10 +4,10 @@ Patched version of IGV that integrates ScanFold functionality. ## Run -### Windows -A pre-built version for Windows is available on [releases](https://github.com/ResearchIT/scanfoldigv/releases). +### Windows and Mac +A pre-built version is available on [releases](https://github.com/ResearchIT/scanfoldigv/releases). -### Mac and Linux +### Linux Follow instructions to compile. Then diff --git a/ScanFold b/ScanFold index 01346c0..06208ea 160000 --- a/ScanFold +++ b/ScanFold @@ -1 +1 @@ -Subproject commit 01346c0a7fe44e650bc6a1b83a54a05ff4926aa9 +Subproject commit 06208eaa240e6baee84092e6937e0b7346de39b1 diff --git a/macos/bundle_macos.sh b/macos/bundle_macos.sh index 716f00b..d559f26 100755 --- a/macos/bundle_macos.sh +++ b/macos/bundle_macos.sh @@ -13,11 +13,69 @@ popd pushd igv ./gradlew clean ./gradlew createMacAppWithJavaDistZip -PjdkBundleMac=${TOPLEVEL}/lib/jdk-11.0.10+9-jre/Contents/Home -#unzip -d ${BUNDLE_PREFIX} distributions/IGV_MacApp_user_WithJava.zip -mv build ${BUNDLE_PREFIX}/IGV +unzip build/distributions/IGV_MacApp_user_WithJava.zip +mv IGV_User.app ${BUNDLE_PREFIX}/IGV.app +popd + + +# compile scanfold +pushd ScanFold +sed -i -e 's/#!\/usr\/local\/bin\/python.*//' ScanFold-Scan_IGV.py ScanFold-Fold_IGV.py +python3 -mvenv env +. env/bin/activate +pip install Nuitka biopython numpy +python -m nuitka --standalone --plugin-enable=numpy ScanFold-Scan_IGV.py +python -m nuitka --standalone --plugin-enable=numpy ScanFold-Fold_IGV.py +deactivate +popd + +# bundle scanfold +mkdir -p ${BUNDLE_PREFIX}/scanfold/ + +pushd ${BUNDLE_PREFIX}/scanfold +cp -R ${TOPLEVEL}/ScanFold/{ScanFold-Scan_IGV.dist,ScanFold-Fold_IGV.dist} . +cp ${TOPLEVEL}/scripts/run_scanfold.py . +popd + +# viennarna +pushd lib +curl -L -O https://github.com/ViennaRNA/ViennaRNA/releases/download/v2.4.16/ViennaRNA-2.4.16.tar.gz +tar -xzf ViennaRNA-2.4.16.tar.gz +pushd ViennaRNA-2.4.16 +mkdir target +#export ac_cv_func_realloc_0_nonnull=yes +#export ac_cv_func_malloc_0_nonnull=yes +CONFIGURE_OPTIONS=" --without-swig \ + --without-doc \ + --without-forester \ + --with-cluster \ + --with-kinwalker \ + --disable-mpfr \ + --disable-pthreads \ + --disable-tty-colors \ + --disable-lto" +./configure --prefix=${PWD}/target ${CONFIGURE_OPTIONS} +make +make install +mkdir -p ${BUNDLE_PREFIX}/ViennaRNA +mv target/bin/RNAfold ${BUNDLE_PREFIX}/ViennaRNA/ +cp license.txt ${BUNDLE_PREFIX}/ViennaRNA/ +popd +popd + +# rnastructure +pushd lib +curl -L -O http://rna.urmc.rochester.edu/Releases/current/RNAstructureTextInterfacesMac.tgz +tar -xzf RNAstructureTextInterfacesMac.tgz +mv RNAstructureTextInterfacesMac.tgz +mkdir ${BUNDLE_PREFIX}/RNAstructure +mv RNAstructure/exe/ct2dot ${BUNDLE_PREFIX}/RNAstructure/ +mv RNAstructure/gpl.txt ${BUNDLE_PREFIX}/RNAstructure/ +mv RNAstructure/data_tables ${BUNDLE_PREFIX}/RNAstructure/ popd # main pushd ${BUNDLE_PREFIX} +cp ${TOPLEVEL}/macos/run_me.command . zip -r ${TOPLEVEL}/scanfoldigv-macos.zip * popd diff --git a/macos/run_me.command b/macos/run_me.command new file mode 100755 index 0000000..0d1bcc9 --- /dev/null +++ b/macos/run_me.command @@ -0,0 +1,10 @@ +export SCANFOLDRUNDIR=$(cd `dirname $(readlink $0 || echo $0)` && pwd) +export SCANFOLDPYTHONINTERPRETER=$(which python) +export SCANFOLDRUNSCRIPT=${SCANFOLDRUNDIR}/scanfold/run_scanfold.py +export SCANFOLDISBUNDLED=TRUE +#switch to this if fork doesn't work +#export SCANFOLDMPUSETHREADS=TRUE +export SCANFOLDMPMETHOD=fork +cd "${SCANFOLDRUNDIR}" +xattr -r -d com.apple.quarantine . >/dev/null 2>&1 +open IGV.app \ No newline at end of file diff --git a/scripts/run_scanfold.py b/scripts/run_scanfold.py index c68c955..7f474b5 100755 --- a/scripts/run_scanfold.py +++ b/scripts/run_scanfold.py @@ -3,14 +3,15 @@ import tempfile import sys import os +import platform def run_me(script, workdir, args): proc_env = os.environ.copy() cwd = os.getcwd() - if os.name == 'nt': - script = os.path.join(cwd, 'scanfold', script) + if platform.system() == 'Windows': + script = os.path.join(cwd, 'scanfold', script + ".py") proc_env['DATAPATH'] = os.path.join(cwd, 'RNAstructure', 'data_tables') new_path = [ os.path.join(cwd, 'ViennaRNA'), @@ -19,8 +20,22 @@ def run_me(script, workdir, args): ] proc_env['PATH'] = ';'.join(new_path) python_interpreter = os.environ['SCANFOLDPYTHONINTERPRETER'] + command = [python_interpreter, '-u', script] + elif platform.system() == 'Darwin' and 'SCANFOLDISBUNDLED' in os.environ: + proc_env['DATAPATH'] = os.path.join(cwd, 'RNAstructure', 'data_tables') + new_path = [ + os.path.join(cwd, 'ViennaRNA'), + os.path.join(cwd, 'RNAstructure'), + proc_env['PATH'] + ] + proc_env['PATH'] = ':'.join(new_path) + python_interpreter = os.environ['SCANFOLDPYTHONINTERPRETER'] + if script == "ScanFold-Scan_IGV": + command = [os.path.join(cwd, 'scanfold', 'ScanFold-Scan_IGV.dist', 'ScanFold-Scan_IGV')] + else: + command = [os.path.join(cwd, 'scanfold', 'ScanFold-Fold_IGV.dist', 'ScanFold-Fold_IGV')] else: - script = os.path.join(cwd, 'ScanFold', script) + script = os.path.join(cwd, 'ScanFold', script + ".py") proc_env['DATAPATH'] = os.path.join(cwd, 'env', 'data_tables') proc_env['VIRTUAL_ENV'] = os.path.join(cwd, 'env') new_path = [ @@ -29,14 +44,20 @@ def run_me(script, workdir, args): ] proc_env['PATH'] = ':'.join(new_path) python_interpreter = 'python' - - command = [python_interpreter, '-u', script] + command = [python_interpreter, '-u', script] + command.extend(args) process = subprocess.Popen(command, stdout=subprocess.PIPE, env=proc_env, cwd=workdir, bufsize=0) for c in iter(lambda: process.stdout.read(1), b''): - sys.stdout.buffer.write(c) - sys.stdout.buffer.flush() + if hasattr(sys.stdout, 'buffer'): + # python 3 + sys.stdout.buffer.write(c) + sys.stdout.buffer.flush() + else: + # python 2 (macos) + sys.stdout.write(c) + sys.stdout.flush() def mktemp(directory, extension, name="output"): file_handle, file_path = tempfile.mkstemp(prefix=name, suffix=extension, dir=directory) @@ -72,7 +93,7 @@ def main(args): '--fasta_index', FASTAINDEX ] - run_me('ScanFold-Scan_IGV.py', args.WORKDIR, scan_params) + run_me('ScanFold-Scan_IGV', args.WORKDIR, scan_params) OUT1 = mktemp(args.WORKDIR, '.nofilter.ct') OUT2 = mktemp(args.WORKDIR, '.-1filter.ct') @@ -116,7 +137,7 @@ def main(args): if args.GLOBALREFOLD: fold_params.append('--global_refold') - run_me('ScanFold-Fold_IGV.py', args.WORKDIR, fold_params) + run_me('ScanFold-Fold_IGV', args.WORKDIR, fold_params) files_to_load = [ BPTRACK,