Mercurial > repos > yating-l > jbrowsehubtoapollo
changeset 0:bc00f5c4c59e draft
planemo upload for repository https://github.com/Yating-L/jbrowse-archive-creator.git
author | yating-l |
---|---|
date | Tue, 17 Oct 2017 17:28:05 -0400 |
parents | |
children | 2ae1e96a8380 |
files | apollo/ApolloInstance.py apollo/ApolloInstance.pyc apollo/ApolloUser.py apollo/ApolloUser.pyc apollo/__init__.py apollo/__init__.pyc jbrowsehubToApollo.py jbrowsehubToApollo.xml templates/__init__.py templates/apollo-arrow.yml templates/custom_track_styles.css tool_dependencies.xml util/Reader.py util/Reader.pyc util/__init__.py util/__init__.pyc util/santitizer.py util/santitizer.pyc util/subtools.py util/subtools.pyc |
diffstat | 17 files changed, 825 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/apollo/ApolloInstance.py Tue Oct 17 17:28:05 2017 -0400 @@ -0,0 +1,71 @@ +#!/usr/bin/env python +import os +import json +import shutil +import tempfile +import logging +from util import subtools +from mako.lookup import TemplateLookup + + +class ApolloInstance(object): + def __init__(self, apollo_host, tool_directory, user_email): + self.apollo_host = apollo_host + self.tool_directory = tool_directory + self.default_user = user_email + self.logger = logging.getLogger(__name__) + self.apolloTemplate = self._getApolloTemplate() + self._arrow_init() + + #TODO: Encode password + def _arrow_init(self): + arrow_config = tempfile.NamedTemporaryFile(bufsize=0) + with open(arrow_config.name, 'w') as conf: + htmlMakoRendered = self.apolloTemplate.render( + apollo_host = self.apollo_host, + admin_user = self.default_user, + admin_pw = '1234' + ) + conf.write(htmlMakoRendered) + + home_dir = os.path.expanduser('~') + arrow_config_dir = os.path.join(home_dir, '.apollo-arrow.yml') + shutil.copyfile(arrow_config.name, arrow_config_dir) + self.logger.debug("Initated arrow: apollo-arrow.yml= %s", arrow_config_dir) + + + def _getApolloTemplate(self): + mylookup = TemplateLookup(directories=[os.path.join(self.tool_directory, 'templates')], + output_encoding='utf-8', encoding_errors='replace') + apolloTemplate = mylookup.get_template("apollo-arrow.yml") + return apolloTemplate + + def getHost(self): + return self.apollo_host + + def createApolloUser(self, apollo_user, admin=None): + p = subtools.arrow_create_user(apollo_user.user_email, apollo_user.firstname, apollo_user.lastname, apollo_user.password, admin) + user_info = json.loads(p) + user_id = user_info.get('userId') + if not user_id: + self.logger.debug("Cannot create new user: %s; The user may already exist", apollo_user.user_email) + user_id = subtools.arrow_get_users(apollo_user.user_email) + self.logger.debug("Got user_id for new or existing user: user_id = %s", str(user_id)) + return user_id + + def grantPermission(self, user_id, organism_id, **user_permissions): + subtools.arrow_update_organism_permissions(user_id, organism_id, **user_permissions) + self.logger.debug("Grant user %s permissions to organism %s, permissions = %s", str(user_id), str(organism_id), ','.join(user_permissions)) + + def addOrganism(self, organism_name, organism_dir): + p = subtools.arrow_add_organism(organism_name, organism_dir) + organism = json.loads(p) + organism_id = organism['id'] + self.logger.debug("Added new organism to Apollo instance, %s", p) + return organism_id + + def loadHubToApollo(self, apollo_user, organism_name, organism_dir, admin_user=False, **user_permissions): + user_id = self.createApolloUser(apollo_user, admin_user) + organism_id = self.addOrganism(organism_name, organism_dir) + self.grantPermission(user_id, organism_id, **user_permissions) + self.logger.debug("Successfully load the hub to Apollo") \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/apollo/ApolloUser.py Tue Oct 17 17:28:05 2017 -0400 @@ -0,0 +1,10 @@ +#!/usr/bin/python + +import os + +class ApolloUser(object): + def __init__(self, user_email, firstname, lastname, password): + self.user_email = user_email + self.firstname = firstname + self.lastname = lastname + self.password = password
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jbrowsehubToApollo.py Tue Oct 17 17:28:05 2017 -0400 @@ -0,0 +1,65 @@ +#!/usr/bin/env python +import os +import sys +import argparse +import json +import logging +import collections +from apollo.ApolloInstance import ApolloInstance +from util.Reader import Reader + + +def main(argv): + parser = argparse.ArgumentParser(description='Upload a hub to display on Apollo.') + parser.add_argument('-j', '--data_json', help='JSON file containing the metadata of the inputs') + parser.add_argument('-o', '--output', help='HTML output') + + #parser.add_argument('-e', '--extra_file_path', help='Extra file path for generated jbrowse hub') + #parser.add_argument('-d', '--jbrowsehub', help='Name of the HTML summarizing the content of the JBrowse Hub Archive') + + # Get the args passed in parameter + args = parser.parse_args() + json_inputs_data = args.data_json + outputFile = args.output + #outputFile = args.jbrowsehub + + + ##Parse JSON file with Reader + reader = Reader(json_inputs_data) + + # Begin init variables + extra_files_path = reader.getExtFilesPath() + user_email = reader.getUserEmail() + genome_name = reader.getGenomeName() + species_name = reader.getSpeciesName() + apollo_host = reader.getApolloHost() + apollo_user = reader.getApolloUser() + toolDirectory = reader.getToolDir() + jbrowse_hub = reader.getJBrowseHubDir() + + logging.info("#### JBrowseArchiveCreator: Start to upload JBrowse Hub to Apollo instance: %s #### ", apollo_host) + + # Set up apollo + apollo = ApolloInstance(apollo_host, toolDirectory, user_email) + jbrowse_hub_dir = _getHubDir(jbrowse_hub, extra_files_path, genome_name) + apollo.loadHubToApollo(apollo_user, species_name, jbrowse_hub_dir, admin=True) + outHtml(outputFile, apollo_host, species_name) + + logging.info('#### JBrowseArchiveCreator: Congratulation! JBrowse Hub is uploaded! ####\n') + +def _getHubDir(outputFile, extra_files_path, genome_name): + file_dir = os.path.abspath(outputFile) + source_dir = os.path.dirname(file_dir) + output_folder_name = os.path.basename(extra_files_path) + jbrowse_hub_dir = os.path.join(source_dir, output_folder_name, 'myHub', genome_name) + return jbrowse_hub_dir + +def outHtml(outputFile, host_name, species_name): + with open(outputFile, 'w') as htmlfile: + htmlstr = 'The new Organism "%s" is created on Apollo: <br>' % species_name + jbrowse_hub = '<li><a href = "%s" target="_blank">View JBrowse Hub on Apollo</a></li>' % host_name + htmlstr += jbrowse_hub + htmlfile.write(htmlstr) + +if __name__ == "__main__": + main(sys.argv) \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jbrowsehubToApollo.xml Tue Oct 17 17:28:05 2017 -0400 @@ -0,0 +1,93 @@ +<tool id="jbrowsehubtoapollo" name="JBrowseHub To Apollo" version="1.0.0"> + <description> + This Galaxy tool is used to prepare your files to be ready for displaying on JBrowse with Apollo plugin + </description> + + <requirements> + <requirement type="package" version="3.0.3">apollo_api</requirement> + </requirements> + + <stdio> + </stdio> + + <command detect_errors="exit_code"><![CDATA[ + #import json + #set global data_parameter_dict = {} + #silent $data_parameter_dict.update({"jbrowse_hub": str($jbrowse_hub)}) + #silent $data_parameter_dict.update({"genome_name": str($genome_name)}) + #silent $data_parameter_dict.update({"apollo_host": str($apollo_host)}) + #silent $data_parameter_dict.update({"user_email": str($__user_email__)}) + #silent $data_parameter_dict.update({"tool_directory": str($__tool_directory__)}) + #silent $data_parameter_dict.update({"extra_files_path": str($jbrowsehub.extra_files_path)}) + #if $apollo_users_settings.apollo_users_selector == "yes": + #set apollo_user = {"firstname": str($apollo_users_settings.firstname), "lastname": str($apollo_users_settings.lastname), "password": str($apollo_users_settings.password), "user_email": str($apollo_users_settings.user_email)} + $data_parameter_dict.update({"apollo_user": $apollo_user}) + #end if + #set input_data = json.dumps($data_parameter_dict) + python $__tool_directory__/jbrowsehubToApollo.py --data_json $input_data -o $output + ]]></command> + + <inputs> + <param + format="jbrowsehub" + type="data" + name="jbrowse_hub" + label="JBrowse Hub created by JBrowse Archive Creator" + /> + <param + name="genome_name" + type="text" + size="30" + value="unknown" + label="Species name" + /> + <param + name="apollo_host" + type="text" + label="Apollo host" + /> + <conditional name="apollo_users_settings"> + <param name="apollo_users_selector" type="select" label="Create or specify your Apollo account"> + <option value="no" selected="true">Use exist demo user account (will use your galaxy email address for apollo, password: gonramp) </option> + <option value="yes">Create or use your own Apollo account</option> + </param> + <!-- TODO: Avoid redundancy here --> + <when value="yes"> + <param + name="firstname" + type="text" + label="First Name" + /> + <param + name="lastname" + type="text" + label="Last Name" + /> + <param + name="user_email" + type="text" + label="Email Address" + /> + <param + name="password" + type="text" + label="Password" + /> + </when> + <when value="no"> + <param name="default_user" type="hidden" + value="false"> + </param> + </when> + </conditional> + </inputs> + <outputs> + <data format="html" name="output" label="${tool.name}" /> + </outputs> + + <help> + This Galaxy tool will load a jbrowse hub to Apollo instance for visualization and interactive annotation. + </help> + <citations> + </citations> +</tool> \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/templates/apollo-arrow.yml Tue Oct 17 17:28:05 2017 -0400 @@ -0,0 +1,10 @@ +## Apollo's Arrow: Global Configuration File. +# Each stanza should contian a single galaxy server to control. +# +# You can set the key __default to the name of a default instance +__default: local + +local: + url: ${apollo_host} + username: ${admin_user} + password: ${admin_pw}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/templates/custom_track_styles.css Tue Oct 17 17:28:05 2017 -0400 @@ -0,0 +1,9 @@ +.${label}, +.plus-${label}, +.minus-${label} +{ + background-color: ${color}; + height: 90%; + top: 5%; +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tool_dependencies.xml Tue Oct 17 17:28:05 2017 -0400 @@ -0,0 +1,23 @@ +<?xml version="1.0"?> +<tool_dependency> + + <package name="apollo_api" version="3.0.3"> + <install version="1.0"> + <actions> + <action type="download_by_url">https://github.com/galaxy-genome-annotation/python-apollo/archive/3.0.3.tar.gz</action> + <action type="make_directory">$INSTALL_DIR/apollo</action> + <action type="shell_command"> + export PYTHONPATH=$PYTHONPATH:$INSTALL_DIR/apollo && + python setup.py install --install-lib $INSTALL_DIR/apollo + </action> + <action type="set_environment"> + <environment_variable action="append_to" name="PYTHONPATH">$INSTALL_DIR/apollo</environment_variable> + <environment_variable action="append_to" name="PATH">$INSTALL_DIR/apollo</environment_variable> + </action> + </actions> + </install> + </package> + + + +</tool_dependency>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/util/Reader.py Tue Oct 17 17:28:05 2017 -0400 @@ -0,0 +1,95 @@ +import json +import re +import logging +import codecs +from apollo.ApolloUser import ApolloUser +from util import santitizer + +class Reader(object): + + def __init__(self, input_json_file): + self.inputFile = input_json_file + self.args = self.loadJson() + + + def loadJson(self): + try: + data_file = codecs.open(self.inputFile, 'r', 'utf-8') + return json.load(data_file) + except IOError: + print "Cannot find JSON file\n" + exit(1) + + def getJBrowseHubDir(self): + try: + return self.args["jbrowse_hub"] + except KeyError: + print ("jbrowse_hub is not defined in the input file!") + exit(1) + + def getToolDir(self): + try: + return self.args["tool_directory"] + except KeyError: + print ("tool_directory is not defined in the input file!") + exit(1) + + def getExtFilesPath(self): + try: + return self.args["extra_files_path"] + except KeyError: + print ("extra_files_path is not defined in the input file!") + exit(1) + + def getUserEmail(self): + try: + return self.args["user_email"] + except KeyError: + print ("user_email is not defined in the input file!") + exit(1) + + def getDebugMode(self): + try: + return self.args["debug_mode"] + except KeyError: + print ("debug_mode is not defined in the input file!") + exit(1) + + def getApolloHost(self): + apollo_host = self.args.get("apollo_host") + return apollo_host + + + def getSpeciesName(self): + species_name = santitizer.sanitize_name_input(self.args["species_name"]) + return species_name + + def getGenomeName(self): + jbrowse_hub = self.getJBrowseHubDir() + with open(jbrowse_hub, 'r') as f: + html = f.read() + m = re.search('The new Organism "(.+?)" is created on Apollo', html) + if m: + genome_name = m.group(1) + else: + print("Cannot find genome name in the jbrowse hub file!") + exit(1) + return genome_name + + + def getApolloUser(self): + user_info = self.args.get("apollo_user") + if not user_info: + firstname = "demo" + lastname = "user" + password = "gonramp" + user_email = self.getUserEmail() + else: + firstname = user_info['firstname'] + lastname = user_info['lastname'] + user_email = user_info['user_email'] + password = user_info['password'] + apollo_user = ApolloUser(user_email, firstname, lastname, password) + return apollo_user + + \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/util/santitizer.py Tue Oct 17 17:28:05 2017 -0400 @@ -0,0 +1,70 @@ +#!/usr/bin/python +# -*- coding: utf8 -*- + +""" +This class handles the subprocess calls of the different tools used +in HubArchiveCreator +""" + +import logging +import os +import subprocess +import sys +import string +import tempfile + + +def prefixTrackName(filename): + """ + santitize trackName. Because track name must begin with a letter and + contain only the following chars: [a-zA-Z0-9_]. + See the "track" Common settings at: + https://genome.ucsc.edu/goldenpath/help/trackDb/trackDbHub.html#bigPsl_-_Pairwise_Alignments + skip the santitization for cytoBandIdeo track + """ + if filename == 'cytoBandIdeo': + return filename + valid_chars = "_%s%s" % (string.ascii_letters, string.digits) + sanitize_name = ''.join([c if c in valid_chars else '_' for c in filename]) + sanitize_name = "gonramp_" + sanitize_name + return sanitize_name + +def sanitize_name_input(string_to_sanitize): + """ + Sanitize the string passed in parameter by replacing '/' and ' ' by '_' + + :param string_to_sanitize: + :return : + + :Example: + + >>> sanitize_name_input('this/is an//example') + this_is_an__example + """ + return string_to_sanitize \ + .replace("/", "_") \ + .replace(" ", "_") + +def sanitize_name_inputs(inputs_data): + """ + Sanitize value of the keys "name" of the dictionary passed in parameter. + + Because sometimes output from Galaxy, or even just file name, from user inputs, have spaces. + Also, it can contain '/' character and could break the use of os.path function. + + :param inputs_data: dict[string, dict[string, string]] + """ + for key in inputs_data: + inputs_data[key]["name"] = sanitize_name_input(inputs_data[key]["name"]) + +def sanitize_group_name(group_name): + return group_name.lower().replace(' ', '_') + +def sanitize_name(input_name): + """ + Galaxy will name all the files and dirs as *.dat, + the function can replace '.' to '_' for the dirs + """ + validChars = "_-%s%s" % (string.ascii_letters, string.digits) + sanitized_name = ''.join([c if c in validChars else '_' for c in input_name]) + return "gonramp_" + sanitized_name
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/util/subtools.py Tue Oct 17 17:28:05 2017 -0400 @@ -0,0 +1,379 @@ +#!/usr/bin/env python + +""" +This file include common used functions for converting file format to gff3 +""" +from collections import OrderedDict +import json +import subprocess +import os +import sys +import tempfile +import string +import logging + +class PopenError(Exception): + def __init__(self, cmd, error, return_code): + self.cmd = cmd + self.error = error + self.return_code = return_code + + def __str__(self): + message = "The subprocess {0} has returned the error: {1}.".format( + self.cmd, self.return_code) + message = ','.join( + (message, "Its error message is: {0}".format(self.error))) + return repr(message) + + +def _handleExceptionAndCheckCall(array_call, **kwargs): + """ + This class handle exceptions and call the tool. + It maps the signature of subprocess.check_call: + See https://docs.python.org/2/library/subprocess.html#subprocess.check_call + """ + stdout = kwargs.get('stdout', subprocess.PIPE) + stderr = kwargs.get('stderr', subprocess.PIPE) + shell = kwargs.get('shell', False) + stdin = kwargs.get('stdin', None) + + cmd = array_call[0] + + output = None + error = None + + # TODO: Check the value of array_call and <=[0] + logging.debug("Calling {0}:".format(cmd)) + logging.debug("%s", array_call) + logging.debug("---------") + + # TODO: Use universal_newlines option from Popen? + try: + p = subprocess.Popen(array_call, stdout=stdout, + stderr=stderr, shell=shell, stdin=stdin) + + # TODO: Change this because of possible memory issues => https://docs.python.org/2/library/subprocess.html#subprocess.Popen.communicate + + output, error = p.communicate() + + if stdout == subprocess.PIPE: + logging.debug("\t{0}".format(output)) + else: + logging.debug("\tOutput in file {0}".format(stdout.name)) + # If we detect an error from the subprocess, then we raise an exception + # TODO: Manage if we raise an exception for everything, or use CRITICAL etc... but not stop process + # TODO: The responsability of returning a sys.exit() should not be there, but up in the app. + if p.returncode: + if stderr == subprocess.PIPE: + raise PopenError(cmd, error, p.returncode) + else: + # TODO: To Handle properly with a design behind, if we received a option as a file for the error + raise Exception("Error when calling {0}. Error as been logged in your file {1}. Error code: {2}" + .format(cmd, stderr.name, p.returncode)) + + except OSError as e: + message = "The subprocess {0} has encountered an OSError: {1}".format( + cmd, e.strerror) + if e.filename: + message = '\n'.join( + (message, ", against this file: {0}".format(e.filename))) + logging.error(message) + sys.exit(-1) + except PopenError as p: + message = "The subprocess {0} has returned the error: {1}.".format( + p.cmd, p.return_code) + message = '\n'.join( + (message, "Its error message is: {0}".format(p.error))) + + logging.exception(message) + + sys.exit(p.return_code) + except Exception as e: + message = "The subprocess {0} has encountered an unknown error: {1}".format( + cmd, e) + logging.exception(message) + + sys.exit(-1) + return p + + +def write_features(field, attribute, gff3): + """ + The function write the features to gff3 format (defined in https://github.com/The-Sequence-Ontology/Specifications/blob/master/gff3.md) + field, attribute are ordered dictionary + gff3 is the file handler + """ + attr = [] + for v in field.values(): + gff3.write(str(v) + '\t') + for k, v in attribute.items(): + s = str(k) + '=' + str(v) + attr.append(s) + gff3.write(';'.join(attr)) + gff3.write('\n') + +def twoBitInfo(two_bit_file_name, two_bit_info_file): + """ + Call twoBitInfo and write the result into twoBit_info_file + :param two_bit_file_name: + :param two_bit_info_file: + :return the subprocess.check_call return object: + """ + array_call = ['twoBitInfo', two_bit_file_name, two_bit_info_file] + p = _handleExceptionAndCheckCall(array_call) + return p + + +def faToTwoBit(fasta_file_name, twoBitFile): + """ + This function call faToTwoBit UCSC tool, and return the twoBitFile + :param fasta_file_name: + :param mySpecieFolder: + :return: + """ + + array_call = ['faToTwoBit', fasta_file_name, twoBitFile] + _handleExceptionAndCheckCall(array_call) + + return twoBitFile + +def sortChromSizes(two_bit_info_file_name, chrom_sizes_file_name): + """ + Call sort with -k2rn on two_bit_info_file_name and write the result into chrom_sizes_file_name + :param two_bit_info_file_name: + :param chrom_sizes_file_name: + :return: + """ + array_call = ['sort', '-k2rn', two_bit_info_file_name, + '-o', chrom_sizes_file_name] + p = _handleExceptionAndCheckCall(array_call) + return p + +def getChromSizes(reference, tool_dir): + #TODO: find a better way instead of shipping the two exec files with the tool + faToTwoBit = os.path.join(tool_dir, 'faToTwoBit') + twoBitInfo = os.path.join(tool_dir, 'twoBitInfo') + try: + twoBitFile = tempfile.NamedTemporaryFile(bufsize=0) + chrom_sizes = tempfile.NamedTemporaryFile(bufsize=0, suffix='.chrom.sizes', delete=False) + except IOError as err: + print "Cannot create tempfile err({0}): {1}".format(err.errno, err.strerror) + try: + subprocess.call(['faToTwoBit', reference, twoBitFile.name]) + except OSError as err: + print "Cannot generate twoBitFile from faToTwoBit err({0}): {1}".format(err.errno, err.strerror) + try: + subprocess.call(['twoBitInfo', twoBitFile.name, chrom_sizes.name]) + except OSError as err: + print "Cannot generate chrom_sizes from twoBitInfo err({0}): {1}".format(err.errno, err.strerror) + return chrom_sizes + +def sequence_region(chrom_sizes): + """ + This function read from a chromatin size file generated by twoBitInfo and write the information to dict + return a dict + """ + f = open(chrom_sizes, 'r') + sizes = f.readlines() + sizes_dict = {} + for line in sizes: + chrom_info = line.rstrip().split('\t') + sizes_dict[chrom_info[0]] = chrom_info[1] + return sizes_dict + +def child_blocks(parent_field, parent_attr, gff3, child_type): + num = 0 + blockcount = int(parent_attr['blockcount']) + chromstart = parent_attr['chromstarts'].split(',') + blocksize = parent_attr['blocksizes'].split(',') + parent_start = parent_field['start'] + while num < blockcount: + child_attr = OrderedDict() + child_field = parent_field + child_field['type'] = child_type + child_field['start'] = int(chromstart[num]) + int(parent_start) + child_field['end'] = int(child_field['start']) + int(blocksize[num]) - 1 + child_attr['ID'] = parent_attr['ID'] + '_part_' + str(num+1) + child_attr['Parent'] = parent_attr['ID'] + write_features(child_field, child_attr, gff3) + num = num + 1 + +def add_tracks_to_json(trackList_json, new_tracks, modify_type): + """ + Add to track configuration (trackList.json) + # modify_type = 'add_tracks': add a new track like bam or bigwig, new_track = dict() + # modify_type = 'add_attr': add configuration to the existing track, new_track = dict(track_name: dict()) + """ + with open(trackList_json, 'r+') as f: + data = json.load(f) + if modify_type == 'add_tracks': + data['tracks'].append(new_tracks) + elif modify_type == 'add_attr': + for k in new_tracks: + for track in data['tracks']: + if k.lower() in track['urlTemplate'].lower(): + attr = new_tracks[k] + for k, v in attr.items(): + track[k] = v + f.seek(0, 0) + f.write(json.dumps(data, separators=(',' , ':'), indent=4)) + f.truncate() + f.close() + + +def createBamIndex(bamfile): + subprocess.call(['samtools', 'index', bamfile]) + filename = bamfile + '.bai' + if os.path.exists(filename): + return filename + else: + raise ValueError('Did not find bai file') + +def flatfile_to_json(inputFile, dataType, trackType, trackLabel, outputFolder, options=None, compress=False): + if "bed" in dataType: + fileType = "--bed" + elif "gff" in dataType: + fileType = "--gff" + else: + raise ValueError("%s is not a valid filetype for flatfile_to_json" % dataType) + + + array_call = ['flatfile-to-json.pl', + fileType, inputFile, + '--trackType', trackType, + '--trackLabel', trackLabel, + '--out', outputFolder] + if compress: + array_call.append('--compress') + if options: + config = options.get("config") + clientConfig = options.get("clientConfig") + renderClassName = options.get('renderClassName') + subfeatureClasses = options.get('subfeatureClasses') + load_type = options.get("type") + if clientConfig: + array_call.append('--clientConfig') + array_call.append(clientConfig) + if config: + array_call.append('--config') + array_call.append(config) + if load_type: + array_call.append('--type') + array_call.append(load_type) + if renderClassName: + array_call.append('--renderClassName') + array_call.append(renderClassName) + if subfeatureClasses: + array_call.append('--subfeatureClasses') + array_call.append(json.dumps(subfeatureClasses)) + + p = _handleExceptionAndCheckCall(array_call) + return p + +def bam_to_json(inputFile, trackLabel, outputFolder, options=None, compress=False): + + array_call = ['bam-to-json.pl', + '--bam', inputFile, + '--trackLabel', trackLabel, + '--out', outputFolder] + if compress: + array_call.append('--compress') + if options: + config = options.get('config') + clientConfig = options.get('clientConfig') + if clientConfig: + array_call.append('--clientConfig') + array_call.append(clientConfig) + if config: + array_call.append('--config') + array_call.append(config) + + p = _handleExceptionAndCheckCall(array_call) + return p + +def add_track_json(trackList, track_json): + track_json = json.dumps(track_json) + new_track = subprocess.Popen(['echo', track_json], stdout=subprocess.PIPE) + p = subprocess.call(['add-track-json.pl', trackList], stdin=new_track.stdout) + return p + +def prepare_refseqs(fasta_file_name, outputFolder): + array_call = ['prepare-refseqs.pl', '--fasta', fasta_file_name, '--out', outputFolder] + p = _handleExceptionAndCheckCall(array_call) + return p + +def generate_names(outputFolder): + array_call = ['generate-names.pl', '-v', '--out', outputFolder] + p = _handleExceptionAndCheckCall(array_call) + return p + +def validateFiles(input_file, chrom_sizes_file_name, file_type, options=None): + """ + Call validateFiles on input_file, using chrom_sizes_file_name and file_type + :param input_file: + :param chrom_sizes_file_name: + :param file_type: + :return: + """ + + array_call = ['validateFiles', '-chromInfo=' + chrom_sizes_file_name, '-type='+ file_type, input_file] + if options: + tab = options.get("tab") + autoSql = options.get("autoSql") + logging.debug("tab: {0}".format(tab)) + logging.debug("autoSql: {0}".format(autoSql)) + if autoSql: + autoSql = ''.join(['-as=', autoSql]) + array_call.append(autoSql) + if tab: + array_call.append('-tab') + p = _handleExceptionAndCheckCall(array_call) + return p + +def arrow_add_organism(organism_name, organism_dir, public=False): + array_call = ['arrow', 'organisms', 'add_organism', organism_name, organism_dir] + if public: + array_call.append('--public') + print array_call + p = subprocess.check_output(array_call) + return p + +def arrow_create_user(user_email, firstname, lastname, password, admin=False): + """ Create a new user of Apollo, the default user_role is "user" """ + array_call = ['arrow', 'users', 'create_user', user_email, firstname, lastname, password] + if admin: + array_call += ['--role', 'admin'] + logging.debug("%s", array_call) + print array_call + p = subprocess.check_output(array_call) + print ("p = %s", p) + return p + +def arrow_update_organism_permissions(user_id, organism, **user_permissions): + array_call = ['arrow', 'users', 'update_organism_permissions', str(user_id), str(organism)] + admin = user_permissions.get("admin", False) + write = user_permissions.get("write", False) + read = user_permissions.get("read", False) + export = user_permissions.get("export", False) + if admin: + array_call.append('--administrate') + if write: + array_call.append('--write') + if read: + array_call.append('--read') + if export: + array_call.append('--export') + p = subprocess.check_output(array_call) + return p + +def arrow_get_users(user_email): + array_call = ['arrow', 'users', 'get_users'] + logging.debug("%s", array_call) + print array_call + p = subprocess.check_output(array_call) + all_users = json.loads(p) + for d in all_users: + if d['username'] == user_email: + return d['userId'] + logging.error("Cannot find user %s", user_email) +