mirror of
https://github.com/galaxyproject/galaxy.git
synced 2026-09-24 16:30:27 +08:00
merge; add temporary template to commit
This commit is contained in:
@@ -0,0 +1,93 @@
|
||||
import urllib, pkg_resources, os
|
||||
pkg_resources.require( 'elementtree' )
|
||||
from elementtree import ElementTree, ElementInclude
|
||||
from xml.parsers.expat import ExpatError as XMLParseErrorThing
|
||||
import sys
|
||||
|
||||
import pkg_resources
|
||||
|
||||
class GetListing:
|
||||
def __init__( self, data ):
|
||||
self.tree = ElementTree.parse( data )
|
||||
self.root = self.tree.getroot()
|
||||
ElementInclude.include(self.root)
|
||||
|
||||
def xml_text(self, name=None):
|
||||
"""Returns the text inside an element"""
|
||||
root = self.root
|
||||
if name is not None:
|
||||
# Try attribute first
|
||||
val = root.get(name)
|
||||
if val:
|
||||
return val
|
||||
# Then try as element
|
||||
elem = root.find(name)
|
||||
else:
|
||||
elem = root
|
||||
if elem is not None and elem.text:
|
||||
text = ''.join(elem.text.splitlines())
|
||||
return text.strip()
|
||||
# No luck, return empty string
|
||||
return ''
|
||||
|
||||
def dlcachefile( webenv, querykey, i, results ):
|
||||
url = 'http://eutils.ncbi.nlm.nih.gov/entrez/eutils/esearch.fcgi?db=nuccore&usehistory=y&term=nuccore_assembly[filter]%20AND%20refseq[filter]'
|
||||
fp = urllib.urlopen( url )
|
||||
search = GetListing( fp )
|
||||
fp.close()
|
||||
webenv = search.xml_text( 'WebEnv' )
|
||||
querykey = search.xml_text( 'QueryKey' )
|
||||
url = 'http://eutils.ncbi.nlm.nih.gov/entrez/eutils/esummary.fcgi?db=nuccore&WebEnv=%s&query_key=%s&retstart=%d&retmax=%d' % ( webenv, querykey, i, results )
|
||||
fp = urllib.urlopen( url )
|
||||
cachefile = os.tmpfile()
|
||||
for line in fp:
|
||||
cachefile.write( line )
|
||||
fp.close()
|
||||
cachefile.flush()
|
||||
cachefile.seek(0)
|
||||
return cachefile
|
||||
|
||||
|
||||
url = 'http://eutils.ncbi.nlm.nih.gov/entrez/eutils/esearch.fcgi?db=nuccore&usehistory=y&term=nuccore_assembly[filter]%20AND%20refseq[filter]'
|
||||
fp = urllib.urlopen( url )
|
||||
results = GetListing( fp )
|
||||
fp.close()
|
||||
|
||||
webenv = results.xml_text( 'WebEnv' )
|
||||
querykey = results.xml_text( 'QueryKey' )
|
||||
counts = int( results.xml_text( 'Count' ) )
|
||||
results = 10000
|
||||
found = 0
|
||||
|
||||
for i in range(0, counts + results, results):
|
||||
rets = dict()
|
||||
cache = dlcachefile( webenv, querykey, i, results )
|
||||
try:
|
||||
xmldoc = GetListing( cache )
|
||||
except (IOError, XMLParseErrorThing):
|
||||
cache = dlcachefile( webenv, querykey, i, results )
|
||||
try:
|
||||
xmldoc = GetListing( cache )
|
||||
except (IOError, XMLParseErrorThing):
|
||||
cache.close()
|
||||
exit()
|
||||
pass
|
||||
finally:
|
||||
cache.close()
|
||||
entries = xmldoc.root.findall( 'DocSum' )
|
||||
for entry in entries:
|
||||
dbkey = None
|
||||
children = entry.findall('Item')
|
||||
for item in children:
|
||||
rets[ item.get('Name') ] = item.text
|
||||
if not rets['Caption'].startswith('NC_'):
|
||||
continue
|
||||
|
||||
for ret in rets['Extra'].split('|'):
|
||||
if not ret.startswith('NC_'):
|
||||
continue
|
||||
else:
|
||||
dbkey = ret
|
||||
break
|
||||
if dbkey is not None:
|
||||
print '\t'.join( [ dbkey, rets['Title'] ] )
|
||||
@@ -0,0 +1,42 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Script to update NCBI shared data tables. The idea is to update, but if
|
||||
# the update fails, not replace current data/tables with error
|
||||
# messages.
|
||||
|
||||
# Edit this line to refer to galaxy's path:
|
||||
GALAXY=/path/to/galaxy
|
||||
PYTHONPATH=${GALAXY}/lib
|
||||
export PYTHONPATH
|
||||
|
||||
# setup directories
|
||||
echo "Creating required directories."
|
||||
DIRS="
|
||||
${GALAXY}/tool-data/shared/ncbi
|
||||
${GALAXY}/tool-data/shared/ncbi/new
|
||||
"
|
||||
for dir in $DIRS; do
|
||||
if [ ! -d $dir ]; then
|
||||
echo "Creating $dir"
|
||||
mkdir $dir
|
||||
else
|
||||
echo "$dir already exists, continuing."
|
||||
fi
|
||||
done
|
||||
|
||||
date
|
||||
echo "Updating NCBI shared data tables."
|
||||
|
||||
# Try to build "builds.txt"
|
||||
echo "Updating builds.txt"
|
||||
python ${GALAXY}/cron/get_ncbi.py > ${GALAXY}/tool-data/shared/ncbi/new/builds.txt
|
||||
if [ $? -eq 0 ]
|
||||
then
|
||||
diff ${GALAXY}/tool-data/shared/ncbi/new/builds.txt ${GALAXY}/tool-data/shared/ncbi/builds.txt > /dev/null 2>&1
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
cp -f ${GALAXY}/tool-data/shared/ncbi/new/builds.txt ${GALAXY}/tool-data/shared/ncbi/builds.txt
|
||||
fi
|
||||
else
|
||||
echo "Failed to update builds.txt" >&2
|
||||
fi
|
||||
@@ -4,6 +4,7 @@
|
||||
<datatype extension="ab1" type="galaxy.datatypes.binary:Ab1" mimetype="application/octet-stream" display_in_upload="true"/>
|
||||
<datatype extension="afg" type="galaxy.datatypes.assembly:Amos" display_in_upload="false"/>
|
||||
<datatype extension="axt" type="galaxy.datatypes.sequence:Axt" display_in_upload="true"/>
|
||||
<datatype extension="fli" type="galaxy.datatypes.tabular:FeatureLocationIndex" display_in_upload="false"/>
|
||||
<datatype extension="bam" type="galaxy.datatypes.binary:Bam" mimetype="application/octet-stream" display_in_upload="true">
|
||||
<converter file="bam_to_bai.xml" target_datatype="bai"/>
|
||||
<converter file="bam_to_summary_tree_converter.xml" target_datatype="summary_tree" depends_on="bai"/>
|
||||
@@ -22,7 +23,9 @@
|
||||
<display file="genetrack.xml" />
|
||||
<display file="igb/bed.xml" />
|
||||
</datatype>
|
||||
<datatype extension="bedgraph" type="galaxy.datatypes.interval:BedGraph" display_in_upload="true" />
|
||||
<datatype extension="bedgraph" type="galaxy.datatypes.interval:BedGraph" display_in_upload="true">
|
||||
<converter file="bedgraph_to_bigwig_converter.xml" target_datatype="bigwig"/>
|
||||
</datatype>
|
||||
<datatype extension="bedstrict" type="galaxy.datatypes.interval:BedStrict" />
|
||||
<datatype extension="bed6" type="galaxy.datatypes.interval:Bed6">
|
||||
<converter file="bed_to_genetrack_converter.xml" target_datatype="genetrack"/>
|
||||
@@ -79,6 +82,7 @@
|
||||
<converter file="gff_to_bed_converter.xml" target_datatype="bed"/>
|
||||
<converter file="gff_to_interval_index_converter.xml" target_datatype="interval_index"/>
|
||||
<converter file="gff_to_summary_tree_converter.xml" target_datatype="summary_tree"/>
|
||||
<converter file="gff_to_fli_converter.xml" target_datatype="fli"/>
|
||||
<display file="ensembl/ensembl_gff.xml" inherit="True"/>
|
||||
<!-- <display file="gbrowse/gbrowse_gff.xml" inherit="True" /> -->
|
||||
</datatype>
|
||||
@@ -167,7 +171,6 @@
|
||||
<datatype extension="linecount" type="galaxy.datatypes.data:LineCount" display_in_upload="false"/>
|
||||
<datatype extension="memexml" type="galaxy.datatypes.xml:MEMEXml" mimetype="application/xml" display_in_upload="true"/>
|
||||
<datatype extension="cisml" type="galaxy.datatypes.xml:CisML" mimetype="application/xml" display_in_upload="true"/>
|
||||
<datatype extension="blastxml" type="galaxy.datatypes.xml:BlastXml" mimetype="application/xml" display_in_upload="true"/>
|
||||
<datatype extension="xml" type="galaxy.datatypes.xml:GenericXml" mimetype="application/xml" display_in_upload="true"/>
|
||||
<datatype extension="vcf" type="galaxy.datatypes.tabular:Vcf" display_in_upload="true">
|
||||
<converter file="vcf_to_bgzip_converter.xml" target_datatype="bgzip"/>
|
||||
@@ -244,7 +247,6 @@
|
||||
<sniffer type="galaxy.datatypes.binary:TwoBit"/>
|
||||
<sniffer type="galaxy.datatypes.binary:Bam"/>
|
||||
<sniffer type="galaxy.datatypes.binary:Sff"/>
|
||||
<sniffer type="galaxy.datatypes.xml:BlastXml"/>
|
||||
<sniffer type="galaxy.datatypes.xml:GenericXml"/>
|
||||
<sniffer type="galaxy.datatypes.sequence:Maf"/>
|
||||
<sniffer type="galaxy.datatypes.sequence:Lav"/>
|
||||
|
||||
@@ -1,16 +1,24 @@
|
||||
<display id="gbrowse_gff" version="1.0.0" name="display at GBrowse">
|
||||
<!-- Load links from file: one line to one link -->
|
||||
<dynamic_links from_file="tool-data/shared/gbrowse/gbrowse_build_sites.txt" skip_startswith="#" id="0" name="0">
|
||||
<dynamic_links from_file="tool-data/shared/gbrowse/gbrowse_build_sites.txt" skip_startswith="#" id="0" name="1">
|
||||
|
||||
<!-- Define parameters by column from file, allow splitting on builds -->
|
||||
<dynamic_param name="site_id" value="0"/>
|
||||
<dynamic_param name="gbrowse_link" value="1"/>
|
||||
<dynamic_param name="builds" value="2" split="True" separator="," />
|
||||
<dynamic_param name="site_name" value="1"/>
|
||||
<dynamic_param name="site_link" value="2"/>
|
||||
<dynamic_param name="site_dbkeys" value="3" split="True" separator="," />
|
||||
<dynamic_param name="site_organisms" value="4" split="True" separator="," />
|
||||
|
||||
<!-- Filter out some of the links based upon matching site_id to a Galaxy application configuration parameter and by dataset dbkey -->
|
||||
<filter>${site_id in $APP.config.gbrowse_display_sites}</filter>
|
||||
<filter>${dataset.dbkey in $builds}</filter>
|
||||
<filter>${dataset.dbkey in $site_dbkeys}</filter>
|
||||
|
||||
<!-- We define url and params as normal, but values defined in dynamic_param are available by specified name -->
|
||||
<url>${gbrowse_link}/?${position}eurl=${gff_file.qp}</url>
|
||||
<url>${site_link}${site_organism}/?${position}eurl=${gff_file.qp}</url>
|
||||
<param type="data" name="gff_file" url="galaxy_${DATASET_HASH}.gff" />
|
||||
<param type="template" name="site_organism" strip="True" >
|
||||
$site_organisms[ $site_dbkeys.index( $gff_file.dbkey ) ]
|
||||
</param>
|
||||
<param type="template" name="position" strip="True" >
|
||||
#set chrom, start, end = $gff_file.datatype.get_estimated_display_viewport( $gff_file )
|
||||
#if $chrom is not None:
|
||||
|
||||
@@ -1,16 +1,24 @@
|
||||
<display id="gbrowse_interval_as_bed" version="1.0.0" name="display at GBrowse">
|
||||
<!-- Load links from file: one line to one link -->
|
||||
<dynamic_links from_file="tool-data/shared/gbrowse/gbrowse_build_sites.txt" skip_startswith="#" id="0" name="0">
|
||||
<dynamic_links from_file="tool-data/shared/gbrowse/gbrowse_build_sites.txt" skip_startswith="#" id="0" name="1">
|
||||
|
||||
<!-- Define parameters by column from file, allow splitting on builds -->
|
||||
<dynamic_param name="site_id" value="0"/>
|
||||
<dynamic_param name="gbrowse_link" value="1"/>
|
||||
<dynamic_param name="builds" value="2" split="True" separator="," />
|
||||
<dynamic_param name="site_name" value="1"/>
|
||||
<dynamic_param name="site_link" value="2"/>
|
||||
<dynamic_param name="site_dbkeys" value="3" split="True" separator="," />
|
||||
<dynamic_param name="site_organisms" value="4" split="True" separator="," />
|
||||
|
||||
<!-- Filter out some of the links based upon matching site_id to a Galaxy application configuration parameter and by dataset dbkey -->
|
||||
<filter>${site_id in $APP.config.gbrowse_display_sites}</filter>
|
||||
<filter>${dataset.dbkey in $builds}</filter>
|
||||
<filter>${dataset.dbkey in $site_dbkeys}</filter>
|
||||
|
||||
<!-- We define url and params as normal, but values defined in dynamic_param are available by specified name -->
|
||||
<url>${gbrowse_link}/?${position}eurl=${bed_file.qp}</url>
|
||||
<url>${site_link}${site_organism}/?${position}eurl=${bed_file.qp}</url>
|
||||
<param type="data" name="bed_file" url="galaxy_${DATASET_HASH}.bed" format="bedstrict"/> <!-- Galaxy allows BED files to contain non-standard fields beyond the first 3 columns, gbrowse does not(?): force use of converter which will make strict BED6+ file -->
|
||||
<param type="template" name="site_organism" strip="True" >
|
||||
$site_organisms[ $site_dbkeys.index( $bed_file.dbkey ) ]
|
||||
</param>
|
||||
<param type="template" name="position" strip="True" >
|
||||
#set chrom, start, end = $bed_file.datatype.get_estimated_display_viewport( $bed_file )
|
||||
#if $chrom is not None:
|
||||
|
||||
@@ -1,16 +1,24 @@
|
||||
<display id="gbrowse_wig" version="1.0.0" name="display at GBrowse">
|
||||
<!-- Load links from file: one line to one link -->
|
||||
<dynamic_links from_file="tool-data/shared/gbrowse/gbrowse_build_sites.txt" skip_startswith="#" id="0" name="0">
|
||||
<dynamic_links from_file="tool-data/shared/gbrowse/gbrowse_build_sites.txt" skip_startswith="#" id="0" name="1">
|
||||
|
||||
<!-- Define parameters by column from file, allow splitting on builds -->
|
||||
<dynamic_param name="site_id" value="0"/>
|
||||
<dynamic_param name="gbrowse_link" value="1"/>
|
||||
<dynamic_param name="builds" value="2" split="True" separator="," />
|
||||
<dynamic_param name="site_name" value="1"/>
|
||||
<dynamic_param name="site_link" value="2"/>
|
||||
<dynamic_param name="site_dbkeys" value="3" split="True" separator="," />
|
||||
<dynamic_param name="site_organisms" value="4" split="True" separator="," />
|
||||
|
||||
<!-- Filter out some of the links based upon matching site_id to a Galaxy application configuration parameter and by dataset dbkey -->
|
||||
<filter>${site_id in $APP.config.gbrowse_display_sites}</filter>
|
||||
<filter>${dataset.dbkey in $builds}</filter>
|
||||
<filter>${dataset.dbkey in $site_dbkeys}</filter>
|
||||
|
||||
<!-- We define url and params as normal, but values defined in dynamic_param are available by specified name -->
|
||||
<url>${gbrowse_link}/?${position}eurl=${wig_file.qp}</url>
|
||||
<url>${site_link}${site_organism}/?${position}eurl=${wig_file.qp}</url>
|
||||
<param type="data" name="wig_file" url="galaxy_${DATASET_HASH}.wig" format="wig"/>
|
||||
<param type="template" name="site_organism" strip="True" >
|
||||
$site_organisms[ $site_dbkeys.index( $wig_file.dbkey ) ]
|
||||
</param>
|
||||
<param type="template" name="position" strip="True" >
|
||||
#set chrom, start, end = $wig_file.datatype.get_estimated_display_viewport( $wig_file )
|
||||
#if $chrom is not None:
|
||||
|
||||
@@ -17,7 +17,7 @@ Cheetah = 2.2.2
|
||||
ctypes = 1.0.2
|
||||
DRMAA_python = 0.2
|
||||
MarkupSafe = 0.12
|
||||
mercurial = 2.1.2
|
||||
mercurial = 2.2.3
|
||||
MySQL_python = 1.2.3c1
|
||||
numpy = 1.6.0
|
||||
pbs_python = 4.1.0
|
||||
|
||||
+16
-5
@@ -132,7 +132,7 @@ class Configuration( object ):
|
||||
self.log_events = string_as_bool( kwargs.get( 'log_events', 'False' ) )
|
||||
self.sanitize_all_html = string_as_bool( kwargs.get( 'sanitize_all_html', True ) )
|
||||
self.ucsc_display_sites = kwargs.get( 'ucsc_display_sites', "main,test,archaea,ucla" ).lower().split(",")
|
||||
self.gbrowse_display_sites = kwargs.get( 'gbrowse_display_sites', "wormbase,tair,modencode_worm,modencode_fly,sgd_yeast" ).lower().split(",")
|
||||
self.gbrowse_display_sites = kwargs.get( 'gbrowse_display_sites', "modencode,sgd_yeast,tair,wormbase,wormbase_ws120,wormbase_ws140,wormbase_ws170,wormbase_ws180,wormbase_ws190,wormbase_ws200,wormbase_ws204,wormbase_ws210,wormbase_ws220,wormbase_ws225" ).lower().split(",")
|
||||
self.genetrack_display_sites = kwargs.get( 'genetrack_display_sites', "main,test" ).lower().split(",")
|
||||
self.brand = kwargs.get( 'brand', None )
|
||||
self.support_url = kwargs.get( 'support_url', 'http://wiki.g2.bx.psu.edu/Support' )
|
||||
@@ -169,10 +169,21 @@ class Configuration( object ):
|
||||
if self.nginx_upload_store:
|
||||
self.nginx_upload_store = os.path.abspath( self.nginx_upload_store )
|
||||
self.object_store = kwargs.get( 'object_store', 'disk' )
|
||||
self.aws_access_key = kwargs.get( 'aws_access_key', None )
|
||||
self.aws_secret_key = kwargs.get( 'aws_secret_key', None )
|
||||
self.s3_bucket = kwargs.get( 's3_bucket', None)
|
||||
self.use_reduced_redundancy = kwargs.get( 'use_reduced_redundancy', False )
|
||||
# Handle AWS-specific config options for backward compatibility
|
||||
if kwargs.get( 'aws_access_key', None) is not None:
|
||||
self.os_access_key= kwargs.get( 'aws_access_key', None )
|
||||
self.os_secret_key= kwargs.get( 'aws_secret_key', None )
|
||||
self.os_bucket_name= kwargs.get( 's3_bucket', None )
|
||||
self.os_use_reduced_redundancy = kwargs.get( 'use_reduced_redundancy', False )
|
||||
else:
|
||||
self.os_access_key = kwargs.get( 'os_access_key', None )
|
||||
self.os_secret_key = kwargs.get( 'os_secret_key', None )
|
||||
self.os_bucket_name = kwargs.get( 'os_bucket_name', None )
|
||||
self.os_use_reduced_redundancy = kwargs.get( 'os_use_reduced_redundancy', False )
|
||||
self.os_host = kwargs.get( 'os_host', None )
|
||||
self.os_port = kwargs.get( 'os_port', None )
|
||||
self.os_is_secure = string_as_bool( kwargs.get( 'os_is_secure', True ) )
|
||||
self.os_conn_path = kwargs.get( 'os_conn_path', '/' )
|
||||
self.object_store_cache_size = float(kwargs.get( 'object_store_cache_size', -1 ))
|
||||
self.distributed_object_store_config_file = kwargs.get( 'distributed_object_store_config_file', None )
|
||||
# Parse global_conf and save the parser
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
<tool id="CONVERTER_bedgraph_to_bigwig" name="Convert BedGraph to BigWig" hidden="true">
|
||||
<!-- Used internally to generate track indexes -->
|
||||
<command>grep -v "^track" $input | wigToBigWig -clip stdin $chromInfo $output</command>
|
||||
<inputs>
|
||||
<page>
|
||||
<param format="bedgraph" name="input" type="data" label="Choose wiggle"/>
|
||||
</page>
|
||||
</inputs>
|
||||
<outputs>
|
||||
<data format="bigwig" name="output"/>
|
||||
</outputs>
|
||||
<help>
|
||||
</help>
|
||||
</tool>
|
||||
@@ -0,0 +1,57 @@
|
||||
'''
|
||||
Creates a feature location index for a given GFF file.
|
||||
'''
|
||||
|
||||
import sys
|
||||
from galaxy import eggs
|
||||
from galaxy.datatypes.util.gff_util import read_unordered_gtf, convert_gff_coords_to_bed
|
||||
|
||||
def main():
|
||||
# Process arguments.
|
||||
in_fname = sys.argv[1]
|
||||
out_fname = sys.argv[2]
|
||||
|
||||
# Create dict of name-location pairings.
|
||||
name_loc_dict = {}
|
||||
for feature in read_unordered_gtf( open( in_fname, 'r' ) ):
|
||||
for name in feature.attributes:
|
||||
val = feature.attributes[ name ]
|
||||
try:
|
||||
float( val )
|
||||
continue
|
||||
except:
|
||||
convert_gff_coords_to_bed( feature )
|
||||
# Value is not a number, so it can be indexed.
|
||||
if val not in name_loc_dict:
|
||||
# Value is not in dictionary.
|
||||
name_loc_dict[ val ] = {
|
||||
'contig': feature.chrom,
|
||||
'start': feature.start,
|
||||
'end': feature.end
|
||||
}
|
||||
else:
|
||||
# Value already in dictionary, so update dictionary.
|
||||
loc = name_loc_dict[ val ]
|
||||
if feature.start < loc[ 'start' ]:
|
||||
loc[ 'start' ] = feature.start
|
||||
if feature.end > loc[ 'end' ]:
|
||||
loc[ 'end' ] = feature.end
|
||||
|
||||
# Print name, loc in sorted order.
|
||||
out = open( out_fname, 'w' )
|
||||
max_len = 0
|
||||
entries = []
|
||||
for name in sorted( name_loc_dict.iterkeys() ):
|
||||
loc = name_loc_dict[ name ]
|
||||
entry = '%s\t%s' % ( name, '%s:%i-%i' % ( loc[ 'contig' ], loc[ 'start' ], loc[ 'end' ] ) )
|
||||
if len( entry ) > max_len:
|
||||
max_len = len( entry )
|
||||
entries.append( entry )
|
||||
|
||||
out.write( str( max_len + 1 ).ljust( max_len ) + '\n' )
|
||||
for entry in entries:
|
||||
out.write( entry.ljust( max_len ) + '\n' )
|
||||
out.close()
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -0,0 +1,13 @@
|
||||
<tool id="CONVERTER_gff_to_fli_0" name="Convert GFF to Feature Location Index">
|
||||
<!-- <description>__NOT_USED_CURRENTLY_FOR_CONVERTERS__</description> -->
|
||||
<!-- Used on the metadata edit page. -->
|
||||
<command interpreter="python">gff_to_fli.py $input1 $output1</command>
|
||||
<inputs>
|
||||
<param format="gff" name="input1" type="data" label="Choose GFF file"/>
|
||||
</inputs>
|
||||
<outputs>
|
||||
<data format="fli" name="output1"/>
|
||||
</outputs>
|
||||
<help>
|
||||
</help>
|
||||
</tool>
|
||||
@@ -1,79 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
Convert from interval file to interval index file. Default input file format is BED (0-based, half-open intervals).
|
||||
|
||||
usage: %prog in_file out_file
|
||||
-G, --gff: input is GFF format, meaning start and end coordinates are 1-based, closed interval
|
||||
"""
|
||||
|
||||
from __future__ import division
|
||||
|
||||
import sys, fileinput
|
||||
from galaxy import eggs
|
||||
import pkg_resources; pkg_resources.require( "bx-python" )
|
||||
from galaxy.visualization.tracks.summary import *
|
||||
from bx.cookbook import doc_optparse
|
||||
from galaxy.tools.util.gff_util import convert_gff_coords_to_bed
|
||||
from bx.interval_index_file import Indexes
|
||||
from galaxy.tools.util.gff_util import parse_gff_attributes
|
||||
|
||||
def main():
|
||||
|
||||
# Read options, args.
|
||||
options, args = doc_optparse.parse( __doc__ )
|
||||
try:
|
||||
gff_format = bool( options.gff )
|
||||
input_fname, out_fname = args
|
||||
except:
|
||||
doc_optparse.exception()
|
||||
|
||||
# Do conversion.
|
||||
# TODO: take column numbers from command line.
|
||||
if gff_format:
|
||||
chr_col, start_col, end_col = ( 0, 3, 4 )
|
||||
else:
|
||||
chr_col, start_col, end_col = ( 0, 1, 2 )
|
||||
index = Indexes()
|
||||
offset = 0
|
||||
# Need to keep track of last gene, transcript id for indexing GTF files.
|
||||
last_gene_id = None
|
||||
last_transcript_id = None
|
||||
for line in open(input_fname, "r"):
|
||||
feature = line.strip().split('\t')
|
||||
if not feature or feature[0].startswith("track") or feature[0].startswith("#"):
|
||||
offset += len(line)
|
||||
continue
|
||||
chrom = feature[ chr_col ]
|
||||
chrom_start = int( feature[ start_col ] )
|
||||
chrom_end = int( feature[ end_col ] )
|
||||
if gff_format:
|
||||
chrom_start, chrom_end = convert_gff_coords_to_bed( [chrom_start, chrom_end ] )
|
||||
|
||||
# Only add feature if gene_id, transcript_id are different from last
|
||||
# values.
|
||||
if len( feature ) == 9:
|
||||
attributes = parse_gff_attributes( feature[8] )
|
||||
gene_id = attributes.get( 'gene_id', None )
|
||||
transcript_id = attributes.get( 'transcript_id', None )
|
||||
if gene_id and transcript_id and gene_id == last_gene_id and \
|
||||
transcript_id == last_transcript_id:
|
||||
# Feature has same gene_id, transcript as last feature, so
|
||||
# do not add.
|
||||
offset += len(line)
|
||||
continue
|
||||
else:
|
||||
# gene_id, transcript_id set and are different from last
|
||||
# values.
|
||||
last_gene_id = gene_id
|
||||
last_transcript_id = transcript_id
|
||||
|
||||
#print "%s %s %s %s %i %i %i" % (feature[2], last_gene_id, last_transcript_id, chrom, chrom_start, chrom_end, offset)
|
||||
index.add( chrom, chrom_start, chrom_end, offset )
|
||||
offset += len(line)
|
||||
|
||||
index.write( open(out_fname, "w") )
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<tool id="CONVERTER_wig_to_bigwig" name="Convert Wiggle to BigWig" hidden="true">
|
||||
<!-- Used internally to generate track indexes -->
|
||||
<command>wigToBigWig $input $chromInfo $output</command>
|
||||
<command>grep -v "^track" $input | wigToBigWig -clip stdin $chromInfo $output</command>
|
||||
<inputs>
|
||||
<page>
|
||||
<param format="wig" name="input" type="data" label="Choose wiggle"/>
|
||||
|
||||
@@ -719,7 +719,49 @@ class LineCount( Text ):
|
||||
pass
|
||||
|
||||
class Newick( Text ):
|
||||
pass
|
||||
"""New Hampshire/Newick Format"""
|
||||
file_ext = "nhx"
|
||||
|
||||
MetadataElement( name="columns", default=3, desc="Number of columns", readonly=True )
|
||||
|
||||
def __init__(self, **kwd):
|
||||
"""Initialize foobar datatype"""
|
||||
Text.__init__(self, **kwd)
|
||||
|
||||
def init_meta( self, dataset, copy_from=None ):
|
||||
Text.init_meta( self, dataset, copy_from=copy_from )
|
||||
|
||||
|
||||
def sniff( self, filename ):
|
||||
""" Returning false as the newick format is too general and cannot be sniffed."""
|
||||
return False
|
||||
|
||||
|
||||
class Nexus( Text ):
|
||||
"""Nexus format as used By Paup, Mr Bayes, etc"""
|
||||
file_ext = "nex"
|
||||
|
||||
MetadataElement( name="columns", default=3, desc="Number of columns", readonly=True )
|
||||
|
||||
def __init__(self, **kwd):
|
||||
"""Initialize foobar datatype"""
|
||||
Text.__init__(self, **kwd)
|
||||
|
||||
def init_meta( self, dataset, copy_from=None ):
|
||||
Text.init_meta( self, dataset, copy_from=copy_from )
|
||||
|
||||
|
||||
def sniff( self, filename ):
|
||||
"""All Nexus Files Simply puts a '#NEXUS' in its first line"""
|
||||
f = open(filename, "r")
|
||||
firstline = f.readline().upper()
|
||||
f.close()
|
||||
|
||||
if "#NEXUS" in firstline:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
# ------------- Utility methods --------------
|
||||
|
||||
|
||||
@@ -98,8 +98,10 @@ class DynamicDisplayApplicationBuilder( object ):
|
||||
for line in open( filename ):
|
||||
if not skip_startswith or not line.startswith( skip_startswith ):
|
||||
line = line.rstrip( '\n\r' )
|
||||
if not line:
|
||||
continue
|
||||
fields = line.split( separator )
|
||||
if len( fields ) >= max_col:
|
||||
if len( fields ) > max_col:
|
||||
new_elem = deepcopy( elem )
|
||||
new_elem.set( 'id', fields[id_col] )
|
||||
new_elem.set( 'name', fields[name_col] )
|
||||
@@ -111,6 +113,8 @@ class DynamicDisplayApplicationBuilder( object ):
|
||||
dynamic_values[key] = value
|
||||
#now populate
|
||||
rval.append( DisplayApplicationLink.from_elem( new_elem, display_application, other_values = dynamic_values ) )
|
||||
else:
|
||||
log.warning( 'Invalid dynamic display application link specified in %s: "%s"' % ( filename, line ) )
|
||||
self.links = rval
|
||||
def __iter__( self ):
|
||||
return iter( self.links )
|
||||
|
||||
@@ -338,7 +338,7 @@ class BedGraph( Interval ):
|
||||
file_ext = "bedgraph"
|
||||
|
||||
def get_track_type( self ):
|
||||
return "LineTrack", {"data": "array_tree"}
|
||||
return "LineTrack", { "data": "bigwig", "index": "bigwig" }
|
||||
|
||||
def as_ucsc_display_file( self, dataset, **kwd ):
|
||||
"""
|
||||
@@ -1141,8 +1141,9 @@ class Wiggle( Tabular, _RemoteCallMixin ):
|
||||
resolution = min( resolution, 100000 )
|
||||
resolution = max( resolution, 1 )
|
||||
return resolution
|
||||
|
||||
def get_track_type( self ):
|
||||
return "LineTrack", {"data": "bigwig", "index": "bigwig"}
|
||||
return "LineTrack", { "data": "bigwig", "index": "bigwig" }
|
||||
|
||||
class CustomTrack ( Tabular ):
|
||||
"""UCSC CustomTrack"""
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"""
|
||||
Provides mapping between extensions and datatypes, mime-types, etc.
|
||||
"""
|
||||
import os, sys, tempfile, threading, logging
|
||||
import os, sys, tempfile, threading, logging, imp
|
||||
import data, tabular, interval, images, sequence, qualityscore, genetics, xml, coverage, tracks, chrominfo, binary, assembly, ngsindex
|
||||
import galaxy.util
|
||||
from galaxy.util.odict import odict
|
||||
@@ -55,10 +55,9 @@ class Registry( object ):
|
||||
being installed. Since installation is occurring after the datatypes registry has been initialized, its
|
||||
contents cannot be overridden by new introduced conflicting data types.
|
||||
"""
|
||||
def __import_module( full_path, datatype_module ):
|
||||
sys.path.insert( 0, full_path )
|
||||
imported_module = __import__( datatype_module )
|
||||
sys.path.pop( 0 )
|
||||
def __import_module( full_path, datatype_module, datatype_class_name ):
|
||||
open_file_obj, file_name, description = imp.find_module( datatype_module, [ full_path ] )
|
||||
imported_module = imp.load_module( datatype_class_name, open_file_obj, file_name, description )
|
||||
return imported_module
|
||||
if root_dir and config:
|
||||
handling_proprietary_datatypes = False
|
||||
@@ -130,12 +129,12 @@ class Registry( object ):
|
||||
datatype_module = fields[0]
|
||||
datatype_class_name = fields[1]
|
||||
datatype_class = None
|
||||
if proprietary_path and proprietary_datatype_module:
|
||||
if proprietary_path and proprietary_datatype_module and datatype_class_name:
|
||||
# We need to change the value of sys.path, so do it in a way that is thread-safe.
|
||||
lock = threading.Lock()
|
||||
lock.acquire( True )
|
||||
try:
|
||||
imported_module = __import_module( proprietary_path, proprietary_datatype_module )
|
||||
imported_module = __import_module( proprietary_path, proprietary_datatype_module, datatype_class_name )
|
||||
if imported_module not in self.imported_modules:
|
||||
self.imported_modules.append( imported_module )
|
||||
if hasattr( imported_module, datatype_class_name ):
|
||||
@@ -276,7 +275,6 @@ class Registry( object ):
|
||||
'axt' : sequence.Axt(),
|
||||
'bam' : binary.Bam(),
|
||||
'bed' : interval.Bed(),
|
||||
'blastxml' : xml.BlastXml(),
|
||||
'coverage' : coverage.LastzCoverage(),
|
||||
'customtrack' : interval.CustomTrack(),
|
||||
'csfasta' : sequence.csFasta(),
|
||||
@@ -310,7 +308,6 @@ class Registry( object ):
|
||||
'axt' : 'text/plain',
|
||||
'bam' : 'application/octet-stream',
|
||||
'bed' : 'text/plain',
|
||||
'blastxml' : 'application/xml',
|
||||
'customtrack' : 'text/plain',
|
||||
'csfasta' : 'text/plain',
|
||||
'eland' : 'application/octet-stream',
|
||||
@@ -348,7 +345,6 @@ class Registry( object ):
|
||||
self.sniff_order = [
|
||||
binary.Bam(),
|
||||
binary.Sff(),
|
||||
xml.BlastXml(),
|
||||
xml.GenericXml(),
|
||||
sequence.Maf(),
|
||||
sequence.Lav(),
|
||||
|
||||
@@ -6,6 +6,7 @@ import registry
|
||||
from galaxy import util
|
||||
from galaxy.datatypes.checkers import *
|
||||
from galaxy.datatypes.binary import unsniffable_binary_formats
|
||||
from encodings import search_function as encodings_search_function
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
@@ -15,7 +16,7 @@ def get_test_fname(fname):
|
||||
full_path = os.path.join(path, 'test', fname)
|
||||
return full_path
|
||||
|
||||
def stream_to_open_named_file( stream, fd, filename ):
|
||||
def stream_to_open_named_file( stream, fd, filename, source_encoding=None, source_error='strict', target_encoding=None, target_error='strict' ):
|
||||
"""Writes a stream to the provided file descriptor, returns the file's name and bool( is_multi_byte ). Closes file descriptor"""
|
||||
#signature and behavor is somewhat odd, due to backwards compatibility, but this can/should be done better
|
||||
CHUNK_SIZE = 1048576
|
||||
@@ -23,6 +24,10 @@ def stream_to_open_named_file( stream, fd, filename ):
|
||||
is_compressed = False
|
||||
is_binary = False
|
||||
is_multi_byte = False
|
||||
if not target_encoding or not encodings_search_function( target_encoding ):
|
||||
target_encoding = util.DEFAULT_ENCODING #utf-8
|
||||
if not source_encoding:
|
||||
source_encoding = util.DEFAULT_ENCODING #sys.getdefaultencoding() would mimic old behavior (defaults to ascii)
|
||||
while 1:
|
||||
chunk = stream.read( CHUNK_SIZE )
|
||||
if not chunk:
|
||||
@@ -42,13 +47,12 @@ def stream_to_open_named_file( stream, fd, filename ):
|
||||
chars = chunk[:100]
|
||||
is_multi_byte = util.is_multi_byte( chars )
|
||||
if not is_multi_byte:
|
||||
for char in chars:
|
||||
if ord( char ) > 128:
|
||||
is_binary = True
|
||||
break
|
||||
is_binary = util.is_binary( chunk )
|
||||
data_checked = True
|
||||
if not is_compressed and not is_binary:
|
||||
os.write( fd, chunk.encode( "utf-8" ) )
|
||||
if not isinstance( chunk, unicode ):
|
||||
chunk = chunk.decode( source_encoding, source_error )
|
||||
os.write( fd, chunk.encode( target_encoding, target_error ) )
|
||||
else:
|
||||
# Compressed files must be encoded after they are uncompressed in the upload utility,
|
||||
# while binary files should not be encoded at all.
|
||||
@@ -56,10 +60,10 @@ def stream_to_open_named_file( stream, fd, filename ):
|
||||
os.close( fd )
|
||||
return filename, is_multi_byte
|
||||
|
||||
def stream_to_file( stream, suffix='', prefix='', dir=None, text=False ):
|
||||
def stream_to_file( stream, suffix='', prefix='', dir=None, text=False, **kwd ):
|
||||
"""Writes a stream to a temporary file, returns the temporary file's name"""
|
||||
fd, temp_name = tempfile.mkstemp( suffix=suffix, prefix=prefix, dir=dir, text=text )
|
||||
return stream_to_open_named_file( stream, fd, temp_name )
|
||||
return stream_to_open_named_file( stream, fd, temp_name, **kwd )
|
||||
|
||||
def check_newlines( fname, bytes_to_read=52428800 ):
|
||||
"""
|
||||
@@ -305,14 +309,9 @@ def guess_ext( fname, sniff_order=None, is_multi_byte=False ):
|
||||
else:
|
||||
for hdr in headers:
|
||||
for char in hdr:
|
||||
if len( char ) > 1:
|
||||
for c in char:
|
||||
if ord( c ) > 128:
|
||||
is_binary = True
|
||||
break
|
||||
elif ord( char ) > 128:
|
||||
is_binary = True
|
||||
break
|
||||
#old behavior had 'char' possibly having length > 1,
|
||||
#need to determine when/if this occurs
|
||||
is_binary = util.is_binary( char )
|
||||
if is_binary:
|
||||
break
|
||||
if is_binary:
|
||||
|
||||
@@ -264,10 +264,10 @@ class Tabular( data.Text ):
|
||||
|
||||
def display_data(self, trans, dataset, preview=False, filename=None, to_ext=None, chunk=None):
|
||||
#TODO Prevent failure when displaying extremely long > 50kb lines.
|
||||
if to_ext or not preview:
|
||||
return self._serve_raw(trans, dataset, to_ext)
|
||||
if chunk:
|
||||
return self.get_chunk(trans, dataset, chunk)
|
||||
if to_ext or not preview:
|
||||
return self._serve_raw(trans, dataset, to_ext)
|
||||
else:
|
||||
column_names = 'null'
|
||||
if dataset.metadata.column_names:
|
||||
@@ -638,3 +638,11 @@ class Eland( Tabular ):
|
||||
dataset.metadata.reads = reads.keys()
|
||||
|
||||
|
||||
class FeatureLocationIndex( Tabular ):
|
||||
"""
|
||||
An index that stores feature locations in tabular format.
|
||||
"""
|
||||
file_ext='fli'
|
||||
MetadataElement( name="columns", default=2, desc="Number of columns", readonly=True, visible=False )
|
||||
MetadataElement( name="column_types", default=['str', 'str'], param=metadata.ColumnTypesParameter, desc="Column types", readonly=True, visible=False, no_value=[] )
|
||||
|
||||
|
||||
@@ -1,722 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE BlastOutput PUBLIC "-//NCBI//NCBI BlastOutput/EN" "NCBI_BlastOutput.dtd">
|
||||
<BlastOutput>
|
||||
<BlastOutput_program>tblastn</BlastOutput_program>
|
||||
<BlastOutput_version>TBLASTN 2.2.25+</BlastOutput_version>
|
||||
<BlastOutput_reference>Stephen F. Altschul, Thomas L. Madden, Alejandro A. Sch&auml;ffer, Jinghui Zhang, Zheng Zhang, Webb Miller, and David J. Lipman (1997), "Gapped BLAST and PSI-BLAST: a new generation of protein database search programs", Nucleic Acids Res. 25:3389-3402.</BlastOutput_reference>
|
||||
<BlastOutput_db></BlastOutput_db>
|
||||
<BlastOutput_query-ID>Query_1</BlastOutput_query-ID>
|
||||
<BlastOutput_query-def>sp|Q9BS26|ERP44_HUMAN Endoplasmic reticulum resident protein 44 OS=Homo sapiens GN=ERP44 PE=1 SV=1</BlastOutput_query-def>
|
||||
<BlastOutput_query-len>406</BlastOutput_query-len>
|
||||
<BlastOutput_param>
|
||||
<Parameters>
|
||||
<Parameters_matrix>BLOSUM80</Parameters_matrix>
|
||||
<Parameters_expect>1e-10</Parameters_expect>
|
||||
<Parameters_gap-open>10</Parameters_gap-open>
|
||||
<Parameters_gap-extend>1</Parameters_gap-extend>
|
||||
<Parameters_filter>F</Parameters_filter>
|
||||
</Parameters>
|
||||
</BlastOutput_param>
|
||||
<BlastOutput_iterations>
|
||||
<Iteration>
|
||||
<Iteration_iter-num>1</Iteration_iter-num>
|
||||
<Iteration_query-ID>Query_1</Iteration_query-ID>
|
||||
<Iteration_query-def>sp|Q9BS26|ERP44_HUMAN Endoplasmic reticulum resident protein 44 OS=Homo sapiens GN=ERP44 PE=1 SV=1</Iteration_query-def>
|
||||
<Iteration_query-len>406</Iteration_query-len>
|
||||
<Iteration_hits></Iteration_hits>
|
||||
<Iteration_stat>
|
||||
<Statistics>
|
||||
<Statistics_db-num>0</Statistics_db-num>
|
||||
<Statistics_db-len>0</Statistics_db-len>
|
||||
<Statistics_hsp-len>19</Statistics_hsp-len>
|
||||
<Statistics_eff-space>127710</Statistics_eff-space>
|
||||
<Statistics_kappa>0.071</Statistics_kappa>
|
||||
<Statistics_lambda>0.299</Statistics_lambda>
|
||||
<Statistics_entropy>0.27</Statistics_entropy>
|
||||
</Statistics>
|
||||
</Iteration_stat>
|
||||
<Iteration_message>No hits found</Iteration_message>
|
||||
</Iteration>
|
||||
<Iteration>
|
||||
<Iteration_iter-num>2</Iteration_iter-num>
|
||||
<Iteration_query-ID>Query_1</Iteration_query-ID>
|
||||
<Iteration_query-def>sp|Q9BS26|ERP44_HUMAN Endoplasmic reticulum resident protein 44 OS=Homo sapiens GN=ERP44 PE=1 SV=1</Iteration_query-def>
|
||||
<Iteration_query-len>406</Iteration_query-len>
|
||||
<Iteration_hits></Iteration_hits>
|
||||
<Iteration_stat>
|
||||
<Statistics>
|
||||
<Statistics_db-num>0</Statistics_db-num>
|
||||
<Statistics_db-len>0</Statistics_db-len>
|
||||
<Statistics_hsp-len>19</Statistics_hsp-len>
|
||||
<Statistics_eff-space>127710</Statistics_eff-space>
|
||||
<Statistics_kappa>0.071</Statistics_kappa>
|
||||
<Statistics_lambda>0.299</Statistics_lambda>
|
||||
<Statistics_entropy>0.27</Statistics_entropy>
|
||||
</Statistics>
|
||||
</Iteration_stat>
|
||||
<Iteration_message>No hits found</Iteration_message>
|
||||
</Iteration>
|
||||
<Iteration>
|
||||
<Iteration_iter-num>3</Iteration_iter-num>
|
||||
<Iteration_query-ID>Query_1</Iteration_query-ID>
|
||||
<Iteration_query-def>sp|Q9BS26|ERP44_HUMAN Endoplasmic reticulum resident protein 44 OS=Homo sapiens GN=ERP44 PE=1 SV=1</Iteration_query-def>
|
||||
<Iteration_query-len>406</Iteration_query-len>
|
||||
<Iteration_hits></Iteration_hits>
|
||||
<Iteration_stat>
|
||||
<Statistics>
|
||||
<Statistics_db-num>0</Statistics_db-num>
|
||||
<Statistics_db-len>0</Statistics_db-len>
|
||||
<Statistics_hsp-len>19</Statistics_hsp-len>
|
||||
<Statistics_eff-space>127710</Statistics_eff-space>
|
||||
<Statistics_kappa>0.071</Statistics_kappa>
|
||||
<Statistics_lambda>0.299</Statistics_lambda>
|
||||
<Statistics_entropy>0.27</Statistics_entropy>
|
||||
</Statistics>
|
||||
</Iteration_stat>
|
||||
<Iteration_message>No hits found</Iteration_message>
|
||||
</Iteration>
|
||||
<Iteration>
|
||||
<Iteration_iter-num>4</Iteration_iter-num>
|
||||
<Iteration_query-ID>Query_1</Iteration_query-ID>
|
||||
<Iteration_query-def>sp|Q9BS26|ERP44_HUMAN Endoplasmic reticulum resident protein 44 OS=Homo sapiens GN=ERP44 PE=1 SV=1</Iteration_query-def>
|
||||
<Iteration_query-len>406</Iteration_query-len>
|
||||
<Iteration_hits></Iteration_hits>
|
||||
<Iteration_stat>
|
||||
<Statistics>
|
||||
<Statistics_db-num>0</Statistics_db-num>
|
||||
<Statistics_db-len>0</Statistics_db-len>
|
||||
<Statistics_hsp-len>19</Statistics_hsp-len>
|
||||
<Statistics_eff-space>127710</Statistics_eff-space>
|
||||
<Statistics_kappa>0.071</Statistics_kappa>
|
||||
<Statistics_lambda>0.299</Statistics_lambda>
|
||||
<Statistics_entropy>0.27</Statistics_entropy>
|
||||
</Statistics>
|
||||
</Iteration_stat>
|
||||
<Iteration_message>No hits found</Iteration_message>
|
||||
</Iteration>
|
||||
<Iteration>
|
||||
<Iteration_iter-num>5</Iteration_iter-num>
|
||||
<Iteration_query-ID>Query_1</Iteration_query-ID>
|
||||
<Iteration_query-def>sp|Q9BS26|ERP44_HUMAN Endoplasmic reticulum resident protein 44 OS=Homo sapiens GN=ERP44 PE=1 SV=1</Iteration_query-def>
|
||||
<Iteration_query-len>406</Iteration_query-len>
|
||||
<Iteration_hits></Iteration_hits>
|
||||
<Iteration_stat>
|
||||
<Statistics>
|
||||
<Statistics_db-num>0</Statistics_db-num>
|
||||
<Statistics_db-len>0</Statistics_db-len>
|
||||
<Statistics_hsp-len>19</Statistics_hsp-len>
|
||||
<Statistics_eff-space>127710</Statistics_eff-space>
|
||||
<Statistics_kappa>0.071</Statistics_kappa>
|
||||
<Statistics_lambda>0.299</Statistics_lambda>
|
||||
<Statistics_entropy>0.27</Statistics_entropy>
|
||||
</Statistics>
|
||||
</Iteration_stat>
|
||||
<Iteration_message>No hits found</Iteration_message>
|
||||
</Iteration>
|
||||
<Iteration>
|
||||
<Iteration_iter-num>6</Iteration_iter-num>
|
||||
<Iteration_query-ID>Query_1</Iteration_query-ID>
|
||||
<Iteration_query-def>sp|Q9BS26|ERP44_HUMAN Endoplasmic reticulum resident protein 44 OS=Homo sapiens GN=ERP44 PE=1 SV=1</Iteration_query-def>
|
||||
<Iteration_query-len>406</Iteration_query-len>
|
||||
<Iteration_hits></Iteration_hits>
|
||||
<Iteration_stat>
|
||||
<Statistics>
|
||||
<Statistics_db-num>0</Statistics_db-num>
|
||||
<Statistics_db-len>0</Statistics_db-len>
|
||||
<Statistics_hsp-len>19</Statistics_hsp-len>
|
||||
<Statistics_eff-space>127710</Statistics_eff-space>
|
||||
<Statistics_kappa>0.071</Statistics_kappa>
|
||||
<Statistics_lambda>0.299</Statistics_lambda>
|
||||
<Statistics_entropy>0.27</Statistics_entropy>
|
||||
</Statistics>
|
||||
</Iteration_stat>
|
||||
<Iteration_message>No hits found</Iteration_message>
|
||||
</Iteration>
|
||||
<Iteration>
|
||||
<Iteration_iter-num>7</Iteration_iter-num>
|
||||
<Iteration_query-ID>Query_2</Iteration_query-ID>
|
||||
<Iteration_query-def>sp|Q9NSY1|BMP2K_HUMAN BMP-2-inducible protein kinase OS=Homo sapiens GN=BMP2K PE=1 SV=2</Iteration_query-def>
|
||||
<Iteration_query-len>1161</Iteration_query-len>
|
||||
<Iteration_hits></Iteration_hits>
|
||||
<Iteration_stat>
|
||||
<Statistics>
|
||||
<Statistics_db-num>0</Statistics_db-num>
|
||||
<Statistics_db-len>0</Statistics_db-len>
|
||||
<Statistics_hsp-len>23</Statistics_hsp-len>
|
||||
<Statistics_eff-space>370988</Statistics_eff-space>
|
||||
<Statistics_kappa>0.071</Statistics_kappa>
|
||||
<Statistics_lambda>0.299</Statistics_lambda>
|
||||
<Statistics_entropy>0.27</Statistics_entropy>
|
||||
</Statistics>
|
||||
</Iteration_stat>
|
||||
<Iteration_message>No hits found</Iteration_message>
|
||||
</Iteration>
|
||||
<Iteration>
|
||||
<Iteration_iter-num>8</Iteration_iter-num>
|
||||
<Iteration_query-ID>Query_2</Iteration_query-ID>
|
||||
<Iteration_query-def>sp|Q9NSY1|BMP2K_HUMAN BMP-2-inducible protein kinase OS=Homo sapiens GN=BMP2K PE=1 SV=2</Iteration_query-def>
|
||||
<Iteration_query-len>1161</Iteration_query-len>
|
||||
<Iteration_hits></Iteration_hits>
|
||||
<Iteration_stat>
|
||||
<Statistics>
|
||||
<Statistics_db-num>0</Statistics_db-num>
|
||||
<Statistics_db-len>0</Statistics_db-len>
|
||||
<Statistics_hsp-len>23</Statistics_hsp-len>
|
||||
<Statistics_eff-space>370988</Statistics_eff-space>
|
||||
<Statistics_kappa>0.071</Statistics_kappa>
|
||||
<Statistics_lambda>0.299</Statistics_lambda>
|
||||
<Statistics_entropy>0.27</Statistics_entropy>
|
||||
</Statistics>
|
||||
</Iteration_stat>
|
||||
<Iteration_message>No hits found</Iteration_message>
|
||||
</Iteration>
|
||||
<Iteration>
|
||||
<Iteration_iter-num>9</Iteration_iter-num>
|
||||
<Iteration_query-ID>Query_2</Iteration_query-ID>
|
||||
<Iteration_query-def>sp|Q9NSY1|BMP2K_HUMAN BMP-2-inducible protein kinase OS=Homo sapiens GN=BMP2K PE=1 SV=2</Iteration_query-def>
|
||||
<Iteration_query-len>1161</Iteration_query-len>
|
||||
<Iteration_hits></Iteration_hits>
|
||||
<Iteration_stat>
|
||||
<Statistics>
|
||||
<Statistics_db-num>0</Statistics_db-num>
|
||||
<Statistics_db-len>0</Statistics_db-len>
|
||||
<Statistics_hsp-len>23</Statistics_hsp-len>
|
||||
<Statistics_eff-space>370988</Statistics_eff-space>
|
||||
<Statistics_kappa>0.071</Statistics_kappa>
|
||||
<Statistics_lambda>0.299</Statistics_lambda>
|
||||
<Statistics_entropy>0.27</Statistics_entropy>
|
||||
</Statistics>
|
||||
</Iteration_stat>
|
||||
<Iteration_message>No hits found</Iteration_message>
|
||||
</Iteration>
|
||||
<Iteration>
|
||||
<Iteration_iter-num>10</Iteration_iter-num>
|
||||
<Iteration_query-ID>Query_2</Iteration_query-ID>
|
||||
<Iteration_query-def>sp|Q9NSY1|BMP2K_HUMAN BMP-2-inducible protein kinase OS=Homo sapiens GN=BMP2K PE=1 SV=2</Iteration_query-def>
|
||||
<Iteration_query-len>1161</Iteration_query-len>
|
||||
<Iteration_hits></Iteration_hits>
|
||||
<Iteration_stat>
|
||||
<Statistics>
|
||||
<Statistics_db-num>0</Statistics_db-num>
|
||||
<Statistics_db-len>0</Statistics_db-len>
|
||||
<Statistics_hsp-len>23</Statistics_hsp-len>
|
||||
<Statistics_eff-space>370988</Statistics_eff-space>
|
||||
<Statistics_kappa>0.071</Statistics_kappa>
|
||||
<Statistics_lambda>0.299</Statistics_lambda>
|
||||
<Statistics_entropy>0.27</Statistics_entropy>
|
||||
</Statistics>
|
||||
</Iteration_stat>
|
||||
<Iteration_message>No hits found</Iteration_message>
|
||||
</Iteration>
|
||||
<Iteration>
|
||||
<Iteration_iter-num>11</Iteration_iter-num>
|
||||
<Iteration_query-ID>Query_2</Iteration_query-ID>
|
||||
<Iteration_query-def>sp|Q9NSY1|BMP2K_HUMAN BMP-2-inducible protein kinase OS=Homo sapiens GN=BMP2K PE=1 SV=2</Iteration_query-def>
|
||||
<Iteration_query-len>1161</Iteration_query-len>
|
||||
<Iteration_hits></Iteration_hits>
|
||||
<Iteration_stat>
|
||||
<Statistics>
|
||||
<Statistics_db-num>0</Statistics_db-num>
|
||||
<Statistics_db-len>0</Statistics_db-len>
|
||||
<Statistics_hsp-len>23</Statistics_hsp-len>
|
||||
<Statistics_eff-space>370988</Statistics_eff-space>
|
||||
<Statistics_kappa>0.071</Statistics_kappa>
|
||||
<Statistics_lambda>0.299</Statistics_lambda>
|
||||
<Statistics_entropy>0.27</Statistics_entropy>
|
||||
</Statistics>
|
||||
</Iteration_stat>
|
||||
<Iteration_message>No hits found</Iteration_message>
|
||||
</Iteration>
|
||||
<Iteration>
|
||||
<Iteration_iter-num>12</Iteration_iter-num>
|
||||
<Iteration_query-ID>Query_2</Iteration_query-ID>
|
||||
<Iteration_query-def>sp|Q9NSY1|BMP2K_HUMAN BMP-2-inducible protein kinase OS=Homo sapiens GN=BMP2K PE=1 SV=2</Iteration_query-def>
|
||||
<Iteration_query-len>1161</Iteration_query-len>
|
||||
<Iteration_hits></Iteration_hits>
|
||||
<Iteration_stat>
|
||||
<Statistics>
|
||||
<Statistics_db-num>0</Statistics_db-num>
|
||||
<Statistics_db-len>0</Statistics_db-len>
|
||||
<Statistics_hsp-len>23</Statistics_hsp-len>
|
||||
<Statistics_eff-space>370988</Statistics_eff-space>
|
||||
<Statistics_kappa>0.071</Statistics_kappa>
|
||||
<Statistics_lambda>0.299</Statistics_lambda>
|
||||
<Statistics_entropy>0.27</Statistics_entropy>
|
||||
</Statistics>
|
||||
</Iteration_stat>
|
||||
<Iteration_message>No hits found</Iteration_message>
|
||||
</Iteration>
|
||||
<Iteration>
|
||||
<Iteration_iter-num>13</Iteration_iter-num>
|
||||
<Iteration_query-ID>Query_3</Iteration_query-ID>
|
||||
<Iteration_query-def>sp|P06213|INSR_HUMAN Insulin receptor OS=Homo sapiens GN=INSR PE=1 SV=4</Iteration_query-def>
|
||||
<Iteration_query-len>1382</Iteration_query-len>
|
||||
<Iteration_hits></Iteration_hits>
|
||||
<Iteration_stat>
|
||||
<Statistics>
|
||||
<Statistics_db-num>0</Statistics_db-num>
|
||||
<Statistics_db-len>0</Statistics_db-len>
|
||||
<Statistics_hsp-len>24</Statistics_hsp-len>
|
||||
<Statistics_eff-space>441350</Statistics_eff-space>
|
||||
<Statistics_kappa>0.071</Statistics_kappa>
|
||||
<Statistics_lambda>0.299</Statistics_lambda>
|
||||
<Statistics_entropy>0.27</Statistics_entropy>
|
||||
</Statistics>
|
||||
</Iteration_stat>
|
||||
<Iteration_message>No hits found</Iteration_message>
|
||||
</Iteration>
|
||||
<Iteration>
|
||||
<Iteration_iter-num>14</Iteration_iter-num>
|
||||
<Iteration_query-ID>Query_3</Iteration_query-ID>
|
||||
<Iteration_query-def>sp|P06213|INSR_HUMAN Insulin receptor OS=Homo sapiens GN=INSR PE=1 SV=4</Iteration_query-def>
|
||||
<Iteration_query-len>1382</Iteration_query-len>
|
||||
<Iteration_hits></Iteration_hits>
|
||||
<Iteration_stat>
|
||||
<Statistics>
|
||||
<Statistics_db-num>0</Statistics_db-num>
|
||||
<Statistics_db-len>0</Statistics_db-len>
|
||||
<Statistics_hsp-len>24</Statistics_hsp-len>
|
||||
<Statistics_eff-space>441350</Statistics_eff-space>
|
||||
<Statistics_kappa>0.071</Statistics_kappa>
|
||||
<Statistics_lambda>0.299</Statistics_lambda>
|
||||
<Statistics_entropy>0.27</Statistics_entropy>
|
||||
</Statistics>
|
||||
</Iteration_stat>
|
||||
<Iteration_message>No hits found</Iteration_message>
|
||||
</Iteration>
|
||||
<Iteration>
|
||||
<Iteration_iter-num>15</Iteration_iter-num>
|
||||
<Iteration_query-ID>Query_3</Iteration_query-ID>
|
||||
<Iteration_query-def>sp|P06213|INSR_HUMAN Insulin receptor OS=Homo sapiens GN=INSR PE=1 SV=4</Iteration_query-def>
|
||||
<Iteration_query-len>1382</Iteration_query-len>
|
||||
<Iteration_hits></Iteration_hits>
|
||||
<Iteration_stat>
|
||||
<Statistics>
|
||||
<Statistics_db-num>0</Statistics_db-num>
|
||||
<Statistics_db-len>0</Statistics_db-len>
|
||||
<Statistics_hsp-len>24</Statistics_hsp-len>
|
||||
<Statistics_eff-space>441350</Statistics_eff-space>
|
||||
<Statistics_kappa>0.071</Statistics_kappa>
|
||||
<Statistics_lambda>0.299</Statistics_lambda>
|
||||
<Statistics_entropy>0.27</Statistics_entropy>
|
||||
</Statistics>
|
||||
</Iteration_stat>
|
||||
<Iteration_message>No hits found</Iteration_message>
|
||||
</Iteration>
|
||||
<Iteration>
|
||||
<Iteration_iter-num>16</Iteration_iter-num>
|
||||
<Iteration_query-ID>Query_3</Iteration_query-ID>
|
||||
<Iteration_query-def>sp|P06213|INSR_HUMAN Insulin receptor OS=Homo sapiens GN=INSR PE=1 SV=4</Iteration_query-def>
|
||||
<Iteration_query-len>1382</Iteration_query-len>
|
||||
<Iteration_hits></Iteration_hits>
|
||||
<Iteration_stat>
|
||||
<Statistics>
|
||||
<Statistics_db-num>0</Statistics_db-num>
|
||||
<Statistics_db-len>0</Statistics_db-len>
|
||||
<Statistics_hsp-len>24</Statistics_hsp-len>
|
||||
<Statistics_eff-space>441350</Statistics_eff-space>
|
||||
<Statistics_kappa>0.071</Statistics_kappa>
|
||||
<Statistics_lambda>0.299</Statistics_lambda>
|
||||
<Statistics_entropy>0.27</Statistics_entropy>
|
||||
</Statistics>
|
||||
</Iteration_stat>
|
||||
<Iteration_message>No hits found</Iteration_message>
|
||||
</Iteration>
|
||||
<Iteration>
|
||||
<Iteration_iter-num>17</Iteration_iter-num>
|
||||
<Iteration_query-ID>Query_3</Iteration_query-ID>
|
||||
<Iteration_query-def>sp|P06213|INSR_HUMAN Insulin receptor OS=Homo sapiens GN=INSR PE=1 SV=4</Iteration_query-def>
|
||||
<Iteration_query-len>1382</Iteration_query-len>
|
||||
<Iteration_hits></Iteration_hits>
|
||||
<Iteration_stat>
|
||||
<Statistics>
|
||||
<Statistics_db-num>0</Statistics_db-num>
|
||||
<Statistics_db-len>0</Statistics_db-len>
|
||||
<Statistics_hsp-len>24</Statistics_hsp-len>
|
||||
<Statistics_eff-space>441350</Statistics_eff-space>
|
||||
<Statistics_kappa>0.071</Statistics_kappa>
|
||||
<Statistics_lambda>0.299</Statistics_lambda>
|
||||
<Statistics_entropy>0.27</Statistics_entropy>
|
||||
</Statistics>
|
||||
</Iteration_stat>
|
||||
<Iteration_message>No hits found</Iteration_message>
|
||||
</Iteration>
|
||||
<Iteration>
|
||||
<Iteration_iter-num>18</Iteration_iter-num>
|
||||
<Iteration_query-ID>Query_3</Iteration_query-ID>
|
||||
<Iteration_query-def>sp|P06213|INSR_HUMAN Insulin receptor OS=Homo sapiens GN=INSR PE=1 SV=4</Iteration_query-def>
|
||||
<Iteration_query-len>1382</Iteration_query-len>
|
||||
<Iteration_hits></Iteration_hits>
|
||||
<Iteration_stat>
|
||||
<Statistics>
|
||||
<Statistics_db-num>0</Statistics_db-num>
|
||||
<Statistics_db-len>0</Statistics_db-len>
|
||||
<Statistics_hsp-len>24</Statistics_hsp-len>
|
||||
<Statistics_eff-space>441350</Statistics_eff-space>
|
||||
<Statistics_kappa>0.071</Statistics_kappa>
|
||||
<Statistics_lambda>0.299</Statistics_lambda>
|
||||
<Statistics_entropy>0.27</Statistics_entropy>
|
||||
</Statistics>
|
||||
</Iteration_stat>
|
||||
<Iteration_message>No hits found</Iteration_message>
|
||||
</Iteration>
|
||||
<Iteration>
|
||||
<Iteration_iter-num>19</Iteration_iter-num>
|
||||
<Iteration_query-ID>Query_4</Iteration_query-ID>
|
||||
<Iteration_query-def>sp|P08100|OPSD_HUMAN Rhodopsin OS=Homo sapiens GN=RHO PE=1 SV=1</Iteration_query-def>
|
||||
<Iteration_query-len>348</Iteration_query-len>
|
||||
<Iteration_hits>
|
||||
<Hit>
|
||||
<Hit_num>1</Hit_num>
|
||||
<Hit_id>Subject_1</Hit_id>
|
||||
<Hit_def>gi|57163782|ref|NM_001009242.1| Felis catus rhodopsin (RHO), mRNA</Hit_def>
|
||||
<Hit_accession>Subject_1</Hit_accession>
|
||||
<Hit_len>1047</Hit_len>
|
||||
<Hit_hsps>
|
||||
<Hsp>
|
||||
<Hsp_num>1</Hsp_num>
|
||||
<Hsp_bit-score>732.392902459534</Hsp_bit-score>
|
||||
<Hsp_score>1689</Hsp_score>
|
||||
<Hsp_evalue>0</Hsp_evalue>
|
||||
<Hsp_query-from>1</Hsp_query-from>
|
||||
<Hsp_query-to>348</Hsp_query-to>
|
||||
<Hsp_hit-from>1</Hsp_hit-from>
|
||||
<Hsp_hit-to>1044</Hsp_hit-to>
|
||||
<Hsp_query-frame>0</Hsp_query-frame>
|
||||
<Hsp_hit-frame>1</Hsp_hit-frame>
|
||||
<Hsp_identity>336</Hsp_identity>
|
||||
<Hsp_positive>343</Hsp_positive>
|
||||
<Hsp_gaps>0</Hsp_gaps>
|
||||
<Hsp_align-len>348</Hsp_align-len>
|
||||
<Hsp_qseq>MNGTEGPNFYVPFSNATGVVRSPFEYPQYYLAEPWQFSMLAAYMFLLIVLGFPINFLTLYVTVQHKKLRTPLNYILLNLAVADLFMVLGGFTSTLYTSLHGYFVFGPTGCNLEGFFATLGGEIALWSLVVLAIERYVVVCKPMSNFRFGENHAIMGVAFTWVMALACAAPPLAGWSRYIPEGLQCSCGIDYYTLKPEVNNESFVIYMFVVHFTIPMIIIFFCYGQLVFTVKEAAAQQQESATTQKAEKEVTRMVIIMVIAFLICWVPYASVAFYIFTHQGSNFGPIFMTIPAFFAKSAAIYNPVIYIMMNKQFRNCMLTTICCGKNPLGDDEASATVSKTETSQVAPA</Hsp_qseq>
|
||||
<Hsp_hseq>MNGTEGPNFYVPFSNKTGVVRSPFEYPQYYLAEPWQFSMLAAYMFLLIVLGFPINFLTLYVTVQHKKLRTPLNYILLNLAVADLFMVFGGFTTTLYTSLHGYFVFGPTGCNLEGFFATLGGEIALWSLVVLAIERYVVVCKPMSNFRFGENHAIMGVAFTWVMALACAAPPLVGWSRYIPEGMQCSCGIDYYTLKPEVNNESFVIYMFVVHFTIPMIVIFFCYGQLVFTVKEAAAQQQESATTQKAEKEVTRMVIIMVIAFLICWVPYASVAFYIFTHQGSNFGPIFMTLPAFFAKSSSIYNPVIYIMMNKQFRNCMLTTLCCGKNPLGDDEASTTGSKTETSQVAPA</Hsp_hseq>
|
||||
<Hsp_midline>MNGTEGPNFYVPFSN TGVVRSPFEYPQYYLAEPWQFSMLAAYMFLLIVLGFPINFLTLYVTVQHKKLRTPLNYILLNLAVADLFMV GGFT+TLYTSLHGYFVFGPTGCNLEGFFATLGGEIALWSLVVLAIERYVVVCKPMSNFRFGENHAIMGVAFTWVMALACAAPPL GWSRYIPEG+QCSCGIDYYTLKPEVNNESFVIYMFVVHFTIPMI+IFFCYGQLVFTVKEAAAQQQESATTQKAEKEVTRMVIIMVIAFLICWVPYASVAFYIFTHQGSNFGPIFMT+PAFFAKS++IYNPVIYIMMNKQFRNCMLTT+CCGKNPLGDDEAS T SKTETSQVAPA</Hsp_midline>
|
||||
</Hsp>
|
||||
</Hit_hsps>
|
||||
</Hit>
|
||||
</Iteration_hits>
|
||||
<Iteration_stat>
|
||||
<Statistics>
|
||||
<Statistics_db-num>0</Statistics_db-num>
|
||||
<Statistics_db-len>0</Statistics_db-len>
|
||||
<Statistics_hsp-len>18</Statistics_hsp-len>
|
||||
<Statistics_eff-space>109230</Statistics_eff-space>
|
||||
<Statistics_kappa>0.071</Statistics_kappa>
|
||||
<Statistics_lambda>0.299</Statistics_lambda>
|
||||
<Statistics_entropy>0.27</Statistics_entropy>
|
||||
</Statistics>
|
||||
</Iteration_stat>
|
||||
</Iteration>
|
||||
<Iteration>
|
||||
<Iteration_iter-num>20</Iteration_iter-num>
|
||||
<Iteration_query-ID>Query_4</Iteration_query-ID>
|
||||
<Iteration_query-def>sp|P08100|OPSD_HUMAN Rhodopsin OS=Homo sapiens GN=RHO PE=1 SV=1</Iteration_query-def>
|
||||
<Iteration_query-len>348</Iteration_query-len>
|
||||
<Iteration_hits>
|
||||
<Hit>
|
||||
<Hit_num>1</Hit_num>
|
||||
<Hit_id>Subject_2</Hit_id>
|
||||
<Hit_def>gi|2734705|gb|U59921.1|BBU59921 Bufo bufo rhodopsin mRNA, complete cds</Hit_def>
|
||||
<Hit_accession>Subject_2</Hit_accession>
|
||||
<Hit_len>1574</Hit_len>
|
||||
<Hit_hsps>
|
||||
<Hsp>
|
||||
<Hsp_num>1</Hsp_num>
|
||||
<Hsp_bit-score>646.119739014374</Hsp_bit-score>
|
||||
<Hsp_score>1489</Hsp_score>
|
||||
<Hsp_evalue>0</Hsp_evalue>
|
||||
<Hsp_query-from>1</Hsp_query-from>
|
||||
<Hsp_query-to>341</Hsp_query-to>
|
||||
<Hsp_hit-from>42</Hsp_hit-from>
|
||||
<Hsp_hit-to>1067</Hsp_hit-to>
|
||||
<Hsp_query-frame>0</Hsp_query-frame>
|
||||
<Hsp_hit-frame>3</Hsp_hit-frame>
|
||||
<Hsp_identity>290</Hsp_identity>
|
||||
<Hsp_positive>320</Hsp_positive>
|
||||
<Hsp_gaps>1</Hsp_gaps>
|
||||
<Hsp_align-len>342</Hsp_align-len>
|
||||
<Hsp_qseq>MNGTEGPNFYVPFSNATGVVRSPFEYPQYYLAEPWQFSMLAAYMFLLIVLGFPINFLTLYVTVQHKKLRTPLNYILLNLAVADLFMVLGGFTSTLYTSLHGYFVFGPTGCNLEGFFATLGGEIALWSLVVLAIERYVVVCKPMSNFRFGENHAIMGVAFTWVMALACAAPPLAGWSRYIPEGLQCSCGIDYYTLKPEVNNESFVIYMFVVHFTIPMIIIFFCYGQLVFTVKEAAAQQQESATTQKAEKEVTRMVIIMVIAFLICWVPYASVAFYIFTHQGSNFGPIFMTIPAFFAKSAAIYNPVIYIMMNKQFRNCMLTTICCGKNPLGDDEA-SATVSKTE</Hsp_qseq>
|
||||
<Hsp_hseq>MNGTEGPNFYIPMSNKTGVVRSPFEYPQYYLAEPWQYSILCAYMFLLILLGFPINFMTLYVTIQHKKLRTPLNYILLNLAFANHFMVLCGFTVTMYSSMNGYFILGATGCYVEGFFATLGGEIALWSLVVLAIERYVVVCKPMSNFRFSENHAVMGVAFTWIMALSCAVPPLLGWSRYIPEGMQCSCGVDYYTLKPEVNNESFVIYMFVVHFTIPLIIIFFCYGRLVCTVKEAAAQQQESATTQKAEKEVTRMVIIMVVFFLICWVPYASVAFFIFSNQGSEFGPIFMTVPAFFAKSSSIYNPVIYIMLNKQFRNCMITTLCCGKNPFGEDDASSAATSKTE</Hsp_hseq>
|
||||
<Hsp_midline>MNGTEGPNFY+P SN TGVVRSPFEYPQYYLAEPWQ+S+L AYMFLLI+LGFPINF+TLYVT+QHKKLRTPLNYILLNLA A+ FMVL GFT T+Y+S+ GYF+ G TGC +EGFFATLGGEIALWSLVVLAIERYVVVCKPMSNFRF ENHA+MGVAFTW+MAL+CA PPL GWSRYIPEG+QCSCG+DYYTLKPEVNNESFVIYMFVVHFTIP+IIIFFCYG+LV TVKEAAAQQQESATTQKAEKEVTRMVIIMV+ FLICWVPYASVAF+IF+ QGS FGPIFMT+PAFFAKS++IYNPVIYIM+NKQFRNCM+TT+CCGKNP G+D+A SA SKTE</Hsp_midline>
|
||||
</Hsp>
|
||||
</Hit_hsps>
|
||||
</Hit>
|
||||
</Iteration_hits>
|
||||
<Iteration_stat>
|
||||
<Statistics>
|
||||
<Statistics_db-num>0</Statistics_db-num>
|
||||
<Statistics_db-len>0</Statistics_db-len>
|
||||
<Statistics_hsp-len>18</Statistics_hsp-len>
|
||||
<Statistics_eff-space>109230</Statistics_eff-space>
|
||||
<Statistics_kappa>0.071</Statistics_kappa>
|
||||
<Statistics_lambda>0.299</Statistics_lambda>
|
||||
<Statistics_entropy>0.27</Statistics_entropy>
|
||||
</Statistics>
|
||||
</Iteration_stat>
|
||||
</Iteration>
|
||||
<Iteration>
|
||||
<Iteration_iter-num>21</Iteration_iter-num>
|
||||
<Iteration_query-ID>Query_4</Iteration_query-ID>
|
||||
<Iteration_query-def>sp|P08100|OPSD_HUMAN Rhodopsin OS=Homo sapiens GN=RHO PE=1 SV=1</Iteration_query-def>
|
||||
<Iteration_query-len>348</Iteration_query-len>
|
||||
<Iteration_hits>
|
||||
<Hit>
|
||||
<Hit_num>1</Hit_num>
|
||||
<Hit_id>Subject_3</Hit_id>
|
||||
<Hit_def>gi|283855845|gb|GQ290303.1| Cynopterus brachyotis voucher 20020434 rhodopsin (RHO) gene, exons 1 through 5 and partial cds</Hit_def>
|
||||
<Hit_accession>Subject_3</Hit_accession>
|
||||
<Hit_len>4301</Hit_len>
|
||||
<Hit_hsps>
|
||||
<Hsp>
|
||||
<Hsp_num>1</Hsp_num>
|
||||
<Hsp_bit-score>151.343146656381</Hsp_bit-score>
|
||||
<Hsp_score>342</Hsp_score>
|
||||
<Hsp_evalue>1.39566684546685e-72</Hsp_evalue>
|
||||
<Hsp_query-from>239</Hsp_query-from>
|
||||
<Hsp_query-to>312</Hsp_query-to>
|
||||
<Hsp_hit-from>3147</Hsp_hit-from>
|
||||
<Hsp_hit-to>3368</Hsp_hit-to>
|
||||
<Hsp_query-frame>0</Hsp_query-frame>
|
||||
<Hsp_hit-frame>3</Hsp_hit-frame>
|
||||
<Hsp_identity>69</Hsp_identity>
|
||||
<Hsp_positive>73</Hsp_positive>
|
||||
<Hsp_gaps>0</Hsp_gaps>
|
||||
<Hsp_align-len>74</Hsp_align-len>
|
||||
<Hsp_qseq>ESATTQKAEKEVTRMVIIMVIAFLICWVPYASVAFYIFTHQGSNFGPIFMTIPAFFAKSAAIYNPVIYIMMNKQ</Hsp_qseq>
|
||||
<Hsp_hseq>ESATTQKAEKEVTRMVIIMVIAFLICWLPYAGVAFYIFTHQGSNFGPIFMTLPAFFAKSSSIYNPVIYIMMNKQ</Hsp_hseq>
|
||||
<Hsp_midline>ESATTQKAEKEVTRMVIIMVIAFLICW+PYA VAFYIFTHQGSNFGPIFMT+PAFFAKS++IYNPVIYIMMNKQ</Hsp_midline>
|
||||
</Hsp>
|
||||
<Hsp>
|
||||
<Hsp_num>2</Hsp_num>
|
||||
<Hsp_bit-score>126.323929257285</Hsp_bit-score>
|
||||
<Hsp_score>284</Hsp_score>
|
||||
<Hsp_evalue>1.39566684546685e-72</Hsp_evalue>
|
||||
<Hsp_query-from>177</Hsp_query-from>
|
||||
<Hsp_query-to>235</Hsp_query-to>
|
||||
<Hsp_hit-from>2855</Hsp_hit-from>
|
||||
<Hsp_hit-to>3031</Hsp_hit-to>
|
||||
<Hsp_query-frame>0</Hsp_query-frame>
|
||||
<Hsp_hit-frame>2</Hsp_hit-frame>
|
||||
<Hsp_identity>54</Hsp_identity>
|
||||
<Hsp_positive>57</Hsp_positive>
|
||||
<Hsp_gaps>0</Hsp_gaps>
|
||||
<Hsp_align-len>59</Hsp_align-len>
|
||||
<Hsp_qseq>RYIPEGLQCSCGIDYYTLKPEVNNESFVIYMFVVHFTIPMIIIFFCYGQLVFTVKEAAA</Hsp_qseq>
|
||||
<Hsp_hseq>RYIPEGMQCSCGIDYYTLKPEVNNESFVIYMFVVHFTIPMIVIFFCYGQLVFTVKEVRS</Hsp_hseq>
|
||||
<Hsp_midline>RYIPEG+QCSCGIDYYTLKPEVNNESFVIYMFVVHFTIPMI+IFFCYGQLVFTVKE +</Hsp_midline>
|
||||
</Hsp>
|
||||
<Hsp>
|
||||
<Hsp_num>3</Hsp_num>
|
||||
<Hsp_bit-score>229.420359574251</Hsp_bit-score>
|
||||
<Hsp_score>523</Hsp_score>
|
||||
<Hsp_evalue>9.84654801241353e-65</Hsp_evalue>
|
||||
<Hsp_query-from>11</Hsp_query-from>
|
||||
<Hsp_query-to>121</Hsp_query-to>
|
||||
<Hsp_hit-from>1</Hsp_hit-from>
|
||||
<Hsp_hit-to>333</Hsp_hit-to>
|
||||
<Hsp_query-frame>0</Hsp_query-frame>
|
||||
<Hsp_hit-frame>1</Hsp_hit-frame>
|
||||
<Hsp_identity>107</Hsp_identity>
|
||||
<Hsp_positive>109</Hsp_positive>
|
||||
<Hsp_gaps>0</Hsp_gaps>
|
||||
<Hsp_align-len>111</Hsp_align-len>
|
||||
<Hsp_qseq>VPFSNATGVVRSPFEYPQYYLAEPWQFSMLAAYMFLLIVLGFPINFLTLYVTVQHKKLRTPLNYILLNLAVADLFMVLGGFTSTLYTSLHGYFVFGPTGCNLEGFFATLGG</Hsp_qseq>
|
||||
<Hsp_hseq>VPFSNKTGVVRSPFEHPQYYLAEPWQFSMLAAYMFLLIVLGFPINFLTLYVTVQHKKLRTPLNYILLNLAVADLFMVFGGFTTTLYTSLHGYFVFGPTGCNLEGFFATLGG</Hsp_hseq>
|
||||
<Hsp_midline>VPFSN TGVVRSPFE+PQYYLAEPWQFSMLAAYMFLLIVLGFPINFLTLYVTVQHKKLRTPLNYILLNLAVADLFMV GGFT+TLYTSLHGYFVFGPTGCNLEGFFATLGG</Hsp_midline>
|
||||
</Hsp>
|
||||
<Hsp>
|
||||
<Hsp_num>4</Hsp_num>
|
||||
<Hsp_bit-score>122.873002719478</Hsp_bit-score>
|
||||
<Hsp_score>276</Hsp_score>
|
||||
<Hsp_evalue>1.40732096096596e-32</Hsp_evalue>
|
||||
<Hsp_query-from>119</Hsp_query-from>
|
||||
<Hsp_query-to>177</Hsp_query-to>
|
||||
<Hsp_hit-from>1404</Hsp_hit-from>
|
||||
<Hsp_hit-to>1580</Hsp_hit-to>
|
||||
<Hsp_query-frame>0</Hsp_query-frame>
|
||||
<Hsp_hit-frame>3</Hsp_hit-frame>
|
||||
<Hsp_identity>55</Hsp_identity>
|
||||
<Hsp_positive>56</Hsp_positive>
|
||||
<Hsp_gaps>0</Hsp_gaps>
|
||||
<Hsp_align-len>59</Hsp_align-len>
|
||||
<Hsp_qseq>LGGEIALWSLVVLAIERYVVVCKPMSNFRFGENHAIMGVAFTWVMALACAAPPLAGWSR</Hsp_qseq>
|
||||
<Hsp_hseq>LAGEIALWSLVVLAIERYVVVCKPMSNFRFGENHAIMGLALTWVMALACAAPPLVGWSR</Hsp_hseq>
|
||||
<Hsp_midline>L GEIALWSLVVLAIERYVVVCKPMSNFRFGENHAIMG+A TWVMALACAAPPL GWSR</Hsp_midline>
|
||||
</Hsp>
|
||||
<Hsp>
|
||||
<Hsp_num>5</Hsp_num>
|
||||
<Hsp_bit-score>57.7367643183824</Hsp_bit-score>
|
||||
<Hsp_score>125</Hsp_score>
|
||||
<Hsp_evalue>5.60065526485586e-13</Hsp_evalue>
|
||||
<Hsp_query-from>312</Hsp_query-from>
|
||||
<Hsp_query-to>337</Hsp_query-to>
|
||||
<Hsp_hit-from>4222</Hsp_hit-from>
|
||||
<Hsp_hit-to>4299</Hsp_hit-to>
|
||||
<Hsp_query-frame>0</Hsp_query-frame>
|
||||
<Hsp_hit-frame>1</Hsp_hit-frame>
|
||||
<Hsp_identity>23</Hsp_identity>
|
||||
<Hsp_positive>24</Hsp_positive>
|
||||
<Hsp_gaps>0</Hsp_gaps>
|
||||
<Hsp_align-len>26</Hsp_align-len>
|
||||
<Hsp_qseq>QFRNCMLTTICCGKNPLGDDEASATV</Hsp_qseq>
|
||||
<Hsp_hseq>QFRNCMLTTLCCGKNPLGDDEASTTA</Hsp_hseq>
|
||||
<Hsp_midline>QFRNCMLTT+CCGKNPLGDDEAS T </Hsp_midline>
|
||||
</Hsp>
|
||||
</Hit_hsps>
|
||||
</Hit>
|
||||
</Iteration_hits>
|
||||
<Iteration_stat>
|
||||
<Statistics>
|
||||
<Statistics_db-num>0</Statistics_db-num>
|
||||
<Statistics_db-len>0</Statistics_db-len>
|
||||
<Statistics_hsp-len>18</Statistics_hsp-len>
|
||||
<Statistics_eff-space>109230</Statistics_eff-space>
|
||||
<Statistics_kappa>0.071</Statistics_kappa>
|
||||
<Statistics_lambda>0.299</Statistics_lambda>
|
||||
<Statistics_entropy>0.27</Statistics_entropy>
|
||||
</Statistics>
|
||||
</Iteration_stat>
|
||||
</Iteration>
|
||||
<Iteration>
|
||||
<Iteration_iter-num>22</Iteration_iter-num>
|
||||
<Iteration_query-ID>Query_4</Iteration_query-ID>
|
||||
<Iteration_query-def>sp|P08100|OPSD_HUMAN Rhodopsin OS=Homo sapiens GN=RHO PE=1 SV=1</Iteration_query-def>
|
||||
<Iteration_query-len>348</Iteration_query-len>
|
||||
<Iteration_hits>
|
||||
<Hit>
|
||||
<Hit_num>1</Hit_num>
|
||||
<Hit_id>Subject_4</Hit_id>
|
||||
<Hit_def>gi|283855822|gb|GQ290312.1| Myotis ricketti voucher GQX10 rhodopsin (RHO) mRNA, partial cds</Hit_def>
|
||||
<Hit_accession>Subject_4</Hit_accession>
|
||||
<Hit_len>983</Hit_len>
|
||||
<Hit_hsps>
|
||||
<Hsp>
|
||||
<Hsp_num>1</Hsp_num>
|
||||
<Hsp_bit-score>658.197981896696</Hsp_bit-score>
|
||||
<Hsp_score>1517</Hsp_score>
|
||||
<Hsp_evalue>0</Hsp_evalue>
|
||||
<Hsp_query-from>11</Hsp_query-from>
|
||||
<Hsp_query-to>336</Hsp_query-to>
|
||||
<Hsp_hit-from>1</Hsp_hit-from>
|
||||
<Hsp_hit-to>978</Hsp_hit-to>
|
||||
<Hsp_query-frame>0</Hsp_query-frame>
|
||||
<Hsp_hit-frame>1</Hsp_hit-frame>
|
||||
<Hsp_identity>310</Hsp_identity>
|
||||
<Hsp_positive>322</Hsp_positive>
|
||||
<Hsp_gaps>0</Hsp_gaps>
|
||||
<Hsp_align-len>326</Hsp_align-len>
|
||||
<Hsp_qseq>VPFSNATGVVRSPFEYPQYYLAEPWQFSMLAAYMFLLIVLGFPINFLTLYVTVQHKKLRTPLNYILLNLAVADLFMVLGGFTSTLYTSLHGYFVFGPTGCNLEGFFATLGGEIALWSLVVLAIERYVVVCKPMSNFRFGENHAIMGVAFTWVMALACAAPPLAGWSRYIPEGLQCSCGIDYYTLKPEVNNESFVIYMFVVHFTIPMIIIFFCYGQLVFTVKEAAAQQQESATTQKAEKEVTRMVIIMVIAFLICWVPYASVAFYIFTHQGSNFGPIFMTIPAFFAKSAAIYNPVIYIMMNKQFRNCMLTTICCGKNPLGDDEASAT</Hsp_qseq>
|
||||
<Hsp_hseq>VPFSNKTGVVRSPFEYPQYYLAEPWQFSMLAAYMFLLIVLGFPINFLTLYVTVQHKKLRTPLNYILLNLAVANLFMVFGGFTTTLYTSMHGYFVFGATGCNLEGFFATLGGEIALWSLVVLAIERYVVVCKPMSNFRFGENHAIMGLAFTWVMALACAAPPLAGWSRYIPEGMQCSCGIDYYTLKPEVNNESFVIYMFVVHFTIPMIVIFFCYGQLVFTVKEAAAQQQESATTQKAEKEVTRMVIIMVVAFLICWLPYASVAFYIFTHQGSNFGPVFMTIPAFFAKSSSIYNPVIYIMMNKQFRNCMLTTLCCGKNPLGDDEASTT</Hsp_hseq>
|
||||
<Hsp_midline>VPFSN TGVVRSPFEYPQYYLAEPWQFSMLAAYMFLLIVLGFPINFLTLYVTVQHKKLRTPLNYILLNLAVA+LFMV GGFT+TLYTS+HGYFVFG TGCNLEGFFATLGGEIALWSLVVLAIERYVVVCKPMSNFRFGENHAIMG+AFTWVMALACAAPPLAGWSRYIPEG+QCSCGIDYYTLKPEVNNESFVIYMFVVHFTIPMI+IFFCYGQLVFTVKEAAAQQQESATTQKAEKEVTRMVIIMV+AFLICW+PYASVAFYIFTHQGSNFGP+FMTIPAFFAKS++IYNPVIYIMMNKQFRNCMLTT+CCGKNPLGDDEAS T</Hsp_midline>
|
||||
</Hsp>
|
||||
</Hit_hsps>
|
||||
</Hit>
|
||||
</Iteration_hits>
|
||||
<Iteration_stat>
|
||||
<Statistics>
|
||||
<Statistics_db-num>0</Statistics_db-num>
|
||||
<Statistics_db-len>0</Statistics_db-len>
|
||||
<Statistics_hsp-len>18</Statistics_hsp-len>
|
||||
<Statistics_eff-space>109230</Statistics_eff-space>
|
||||
<Statistics_kappa>0.071</Statistics_kappa>
|
||||
<Statistics_lambda>0.299</Statistics_lambda>
|
||||
<Statistics_entropy>0.27</Statistics_entropy>
|
||||
</Statistics>
|
||||
</Iteration_stat>
|
||||
</Iteration>
|
||||
<Iteration>
|
||||
<Iteration_iter-num>23</Iteration_iter-num>
|
||||
<Iteration_query-ID>Query_4</Iteration_query-ID>
|
||||
<Iteration_query-def>sp|P08100|OPSD_HUMAN Rhodopsin OS=Homo sapiens GN=RHO PE=1 SV=1</Iteration_query-def>
|
||||
<Iteration_query-len>348</Iteration_query-len>
|
||||
<Iteration_hits>
|
||||
<Hit>
|
||||
<Hit_num>1</Hit_num>
|
||||
<Hit_id>Subject_5</Hit_id>
|
||||
<Hit_def>gi|18148870|dbj|AB062417.1| Synthetic construct Bos taurus gene for rhodopsin, complete cds</Hit_def>
|
||||
<Hit_accession>Subject_5</Hit_accession>
|
||||
<Hit_len>1047</Hit_len>
|
||||
<Hit_hsps>
|
||||
<Hsp>
|
||||
<Hsp_num>1</Hsp_num>
|
||||
<Hsp_bit-score>711.255977415469</Hsp_bit-score>
|
||||
<Hsp_score>1640</Hsp_score>
|
||||
<Hsp_evalue>0</Hsp_evalue>
|
||||
<Hsp_query-from>1</Hsp_query-from>
|
||||
<Hsp_query-to>348</Hsp_query-to>
|
||||
<Hsp_hit-from>1</Hsp_hit-from>
|
||||
<Hsp_hit-to>1044</Hsp_hit-to>
|
||||
<Hsp_query-frame>0</Hsp_query-frame>
|
||||
<Hsp_hit-frame>1</Hsp_hit-frame>
|
||||
<Hsp_identity>325</Hsp_identity>
|
||||
<Hsp_positive>337</Hsp_positive>
|
||||
<Hsp_gaps>0</Hsp_gaps>
|
||||
<Hsp_align-len>348</Hsp_align-len>
|
||||
<Hsp_qseq>MNGTEGPNFYVPFSNATGVVRSPFEYPQYYLAEPWQFSMLAAYMFLLIVLGFPINFLTLYVTVQHKKLRTPLNYILLNLAVADLFMVLGGFTSTLYTSLHGYFVFGPTGCNLEGFFATLGGEIALWSLVVLAIERYVVVCKPMSNFRFGENHAIMGVAFTWVMALACAAPPLAGWSRYIPEGLQCSCGIDYYTLKPEVNNESFVIYMFVVHFTIPMIIIFFCYGQLVFTVKEAAAQQQESATTQKAEKEVTRMVIIMVIAFLICWVPYASVAFYIFTHQGSNFGPIFMTIPAFFAKSAAIYNPVIYIMMNKQFRNCMLTTICCGKNPLGDDEASATVSKTETSQVAPA</Hsp_qseq>
|
||||
<Hsp_hseq>MNGTEGPNFYVPFSNKTGVVRSPFEAPQYYLAEPWQFSMLAAYMFLLIMLGFPINFLTLYVTVQHKKLRTPLNYILLNLAVADLFMVFGGFTTTLYTSLHGYFVFGPTGCNLEGFFATLGGEIALWSLVVLAIERYVVVCKPMSNFRFGENHAIMGVAFTWVMALACAAPPLVGWSRYIPEGMQCSCGIDYYTPHEETNNESFVIYMFVVHFIIPLIVIFFCYGQLVFTVKEAAAQQQESATTQKAEKEVTRMVIIMVIAFLICWLPYAGVAFYIFTHQGSDFGPIFMTIPAFFAKTSAVYNPVIYIMMNKQFRNCMVTTLCCGKNPLGDDEASTTVSKTETSQVAPA</Hsp_hseq>
|
||||
<Hsp_midline>MNGTEGPNFYVPFSN TGVVRSPFE PQYYLAEPWQFSMLAAYMFLLI+LGFPINFLTLYVTVQHKKLRTPLNYILLNLAVADLFMV GGFT+TLYTSLHGYFVFGPTGCNLEGFFATLGGEIALWSLVVLAIERYVVVCKPMSNFRFGENHAIMGVAFTWVMALACAAPPL GWSRYIPEG+QCSCGIDYYT E NNESFVIYMFVVHF IP+I+IFFCYGQLVFTVKEAAAQQQESATTQKAEKEVTRMVIIMVIAFLICW+PYA VAFYIFTHQGS+FGPIFMTIPAFFAK++A+YNPVIYIMMNKQFRNCM+TT+CCGKNPLGDDEAS TVSKTETSQVAPA</Hsp_midline>
|
||||
</Hsp>
|
||||
</Hit_hsps>
|
||||
</Hit>
|
||||
</Iteration_hits>
|
||||
<Iteration_stat>
|
||||
<Statistics>
|
||||
<Statistics_db-num>0</Statistics_db-num>
|
||||
<Statistics_db-len>0</Statistics_db-len>
|
||||
<Statistics_hsp-len>18</Statistics_hsp-len>
|
||||
<Statistics_eff-space>109230</Statistics_eff-space>
|
||||
<Statistics_kappa>0.071</Statistics_kappa>
|
||||
<Statistics_lambda>0.299</Statistics_lambda>
|
||||
<Statistics_entropy>0.27</Statistics_entropy>
|
||||
</Statistics>
|
||||
</Iteration_stat>
|
||||
</Iteration>
|
||||
<Iteration>
|
||||
<Iteration_iter-num>24</Iteration_iter-num>
|
||||
<Iteration_query-ID>Query_4</Iteration_query-ID>
|
||||
<Iteration_query-def>sp|P08100|OPSD_HUMAN Rhodopsin OS=Homo sapiens GN=RHO PE=1 SV=1</Iteration_query-def>
|
||||
<Iteration_query-len>348</Iteration_query-len>
|
||||
<Iteration_hits>
|
||||
<Hit>
|
||||
<Hit_num>1</Hit_num>
|
||||
<Hit_id>Subject_6</Hit_id>
|
||||
<Hit_def>gi|12583664|dbj|AB043817.1| Conger myriaster conf gene for fresh water form rod opsin, complete cds</Hit_def>
|
||||
<Hit_accession>Subject_6</Hit_accession>
|
||||
<Hit_len>1344</Hit_len>
|
||||
<Hit_hsps>
|
||||
<Hsp>
|
||||
<Hsp_num>1</Hsp_num>
|
||||
<Hsp_bit-score>626.708277239213</Hsp_bit-score>
|
||||
<Hsp_score>1444</Hsp_score>
|
||||
<Hsp_evalue>0</Hsp_evalue>
|
||||
<Hsp_query-from>1</Hsp_query-from>
|
||||
<Hsp_query-to>341</Hsp_query-to>
|
||||
<Hsp_hit-from>23</Hsp_hit-from>
|
||||
<Hsp_hit-to>1048</Hsp_hit-to>
|
||||
<Hsp_query-frame>0</Hsp_query-frame>
|
||||
<Hsp_hit-frame>2</Hsp_hit-frame>
|
||||
<Hsp_identity>281</Hsp_identity>
|
||||
<Hsp_positive>311</Hsp_positive>
|
||||
<Hsp_gaps>1</Hsp_gaps>
|
||||
<Hsp_align-len>342</Hsp_align-len>
|
||||
<Hsp_qseq>MNGTEGPNFYVPFSNATGVVRSPFEYPQYYLAEPWQFSMLAAYMFLLIVLGFPINFLTLYVTVQHKKLRTPLNYILLNLAVADLFMVLGGFTSTLYTSLHGYFVFGPTGCNLEGFFATLGGEIALWSLVVLAIERYVVVCKPMSNFRFGENHAIMGVAFTWVMALACAAPPLAGWSRYIPEGLQCSCGIDYYTLKPEVNNESFVIYMFVVHFTIPMIIIFFCYGQLVFTVKEAAAQQQESATTQKAEKEVTRMVIIMVIAFLICWVPYASVAFYIFTHQGSNFGPIFMTIPAFFAKSAAIYNPVIYIMMNKQFRNCMLTTICCGKNPL-GDDEASATVSKTE</Hsp_qseq>
|
||||
<Hsp_hseq>MNGTEGPNFYIPMSNATGVVRSPFEYPQYYLAEPWAFSALSAYMFFLIIAGFPINFLTLYVTIEHKKLRTPLNYILLNLAVADLFMVFGGFTTTMYTSMHGYFVFGPTGCNIEGFFATLGGEIALWCLVVLAIERWMVVCKPVTNFRFGESHAIMGVMVTWTMALACALPPLFGWSRYIPEGLQCSCGIDYYTRAPGINNESFVIYMFTCHFSIPLAVISFCYGRLVCTVKEAAAQQQESETTQRAEREVTRMVVIMVISFLVCWVPYASVAWYIFTHQGSTFGPIFMTIPSFFAKSSALYNPMIYICMNKQFRHCMITTLCCGKNPFEEEDGASATSSKTE</Hsp_hseq>
|
||||
<Hsp_midline>MNGTEGPNFY+P SNATGVVRSPFEYPQYYLAEPW FS L+AYMF LI+ GFPINFLTLYVT++HKKLRTPLNYILLNLAVADLFMV GGFT+T+YTS+HGYFVFGPTGCN+EGFFATLGGEIALW LVVLAIER++VVCKP++NFRFGE HAIMGV TW MALACA PPL GWSRYIPEGLQCSCGIDYYT P +NNESFVIYMF HF+IP+ +I FCYG+LV TVKEAAAQQQES TTQ+AE+EVTRMV+IMVI+FL+CWVPYASVA YIFTHQGS FGPIFMTIP+FFAKS+A+YNP+IYI MNKQFR CM+TT+CCGKNP +D ASAT SKTE</Hsp_midline>
|
||||
</Hsp>
|
||||
</Hit_hsps>
|
||||
</Hit>
|
||||
</Iteration_hits>
|
||||
<Iteration_stat>
|
||||
<Statistics>
|
||||
<Statistics_db-num>0</Statistics_db-num>
|
||||
<Statistics_db-len>0</Statistics_db-len>
|
||||
<Statistics_hsp-len>18</Statistics_hsp-len>
|
||||
<Statistics_eff-space>109230</Statistics_eff-space>
|
||||
<Statistics_kappa>0.071</Statistics_kappa>
|
||||
<Statistics_lambda>0.299</Statistics_lambda>
|
||||
<Statistics_entropy>0.27</Statistics_entropy>
|
||||
</Statistics>
|
||||
</Iteration_stat>
|
||||
</Iteration>
|
||||
</BlastOutput_iterations>
|
||||
</BlastOutput>
|
||||
+21
-120
@@ -27,9 +27,6 @@ class GenericXml( data.Text ):
|
||||
>>> fname = get_test_fname( 'megablast_xml_parser_test1.blastxml' )
|
||||
>>> GenericXml().sniff( fname )
|
||||
True
|
||||
>>> fname = get_test_fname( 'tblastn_four_human_vs_rhodopsin.xml' )
|
||||
>>> BlastXml().sniff( fname )
|
||||
True
|
||||
>>> fname = get_test_fname( 'interval.interval' )
|
||||
>>> GenericXml().sniff( fname )
|
||||
False
|
||||
@@ -50,123 +47,6 @@ class GenericXml( data.Text ):
|
||||
data.Text.merge(split_files, output_file)
|
||||
merge = staticmethod(merge)
|
||||
|
||||
class BlastXml( GenericXml ):
|
||||
"""NCBI Blast XML Output data"""
|
||||
file_ext = "blastxml"
|
||||
|
||||
def set_peek( self, dataset, is_multi_byte=False ):
|
||||
"""Set the peek and blurb text"""
|
||||
if not dataset.dataset.purged:
|
||||
dataset.peek = data.get_file_peek( dataset.file_name, is_multi_byte=is_multi_byte )
|
||||
dataset.blurb = 'NCBI Blast XML data'
|
||||
else:
|
||||
dataset.peek = 'file does not exist'
|
||||
dataset.blurb = 'file purged from disk'
|
||||
def sniff( self, filename ):
|
||||
"""
|
||||
Determines whether the file is blastxml
|
||||
|
||||
>>> fname = get_test_fname( 'megablast_xml_parser_test1.blastxml' )
|
||||
>>> BlastXml().sniff( fname )
|
||||
True
|
||||
>>> fname = get_test_fname( 'tblastn_four_human_vs_rhodopsin.xml' )
|
||||
>>> BlastXml().sniff( fname )
|
||||
True
|
||||
>>> fname = get_test_fname( 'interval.interval' )
|
||||
>>> BlastXml().sniff( fname )
|
||||
False
|
||||
"""
|
||||
#TODO - Use a context manager on Python 2.5+ to close handle
|
||||
handle = open(filename)
|
||||
line = handle.readline()
|
||||
if line.strip() != '<?xml version="1.0"?>':
|
||||
handle.close()
|
||||
return False
|
||||
line = handle.readline()
|
||||
if line.strip() not in ['<!DOCTYPE BlastOutput PUBLIC "-//NCBI//NCBI BlastOutput/EN" "http://www.ncbi.nlm.nih.gov/dtd/NCBI_BlastOutput.dtd">',
|
||||
'<!DOCTYPE BlastOutput PUBLIC "-//NCBI//NCBI BlastOutput/EN" "NCBI_BlastOutput.dtd">']:
|
||||
handle.close()
|
||||
return False
|
||||
line = handle.readline()
|
||||
if line.strip() != '<BlastOutput>':
|
||||
handle.close()
|
||||
return False
|
||||
handle.close()
|
||||
return True
|
||||
|
||||
def merge(split_files, output_file):
|
||||
"""Merging multiple XML files is non-trivial and must be done in subclasses."""
|
||||
if len(split_files) == 1:
|
||||
#For one file only, use base class method (move/copy)
|
||||
return data.Text.merge(split_files, output_file)
|
||||
out = open(output_file, "w")
|
||||
h = None
|
||||
for f in split_files:
|
||||
h = open(f)
|
||||
body = False
|
||||
header = h.readline()
|
||||
if not header:
|
||||
out.close()
|
||||
h.close()
|
||||
raise ValueError("BLAST XML file %s was empty" % f)
|
||||
if header.strip() != '<?xml version="1.0"?>':
|
||||
out.write(header) #for diagnosis
|
||||
out.close()
|
||||
h.close()
|
||||
raise ValueError("%s is not an XML file!" % f)
|
||||
line = h.readline()
|
||||
header += line
|
||||
if line.strip() not in ['<!DOCTYPE BlastOutput PUBLIC "-//NCBI//NCBI BlastOutput/EN" "http://www.ncbi.nlm.nih.gov/dtd/NCBI_BlastOutput.dtd">',
|
||||
'<!DOCTYPE BlastOutput PUBLIC "-//NCBI//NCBI BlastOutput/EN" "NCBI_BlastOutput.dtd">']:
|
||||
out.write(header) #for diagnosis
|
||||
out.close()
|
||||
h.close()
|
||||
raise ValueError("%s is not a BLAST XML file!" % f)
|
||||
while True:
|
||||
line = h.readline()
|
||||
if not line:
|
||||
out.write(header) #for diagnosis
|
||||
out.close()
|
||||
h.close()
|
||||
raise ValueError("BLAST XML file %s ended prematurely" % f)
|
||||
header += line
|
||||
if "<Iteration>" in line:
|
||||
break
|
||||
if len(header) > 10000:
|
||||
#Something has gone wrong, don't load too much into memory!
|
||||
#Write what we have to the merged file for diagnostics
|
||||
out.write(header)
|
||||
out.close()
|
||||
h.close()
|
||||
raise ValueError("BLAST XML file %s has too long a header!" % f)
|
||||
if "<BlastOutput>" not in header:
|
||||
out.close()
|
||||
h.close()
|
||||
raise ValueError("%s is not a BLAST XML file:\n%s\n..." % (f, header))
|
||||
if f == split_files[0]:
|
||||
out.write(header)
|
||||
old_header = header
|
||||
elif old_header[:300] != header[:300]:
|
||||
#Enough to check <BlastOutput_program> and <BlastOutput_version> match
|
||||
out.close()
|
||||
h.close()
|
||||
raise ValueError("BLAST XML headers don't match for %s and %s - have:\n%s\n...\n\nAnd:\n%s\n...\n" \
|
||||
% (split_files[0], f, old_header[:300], header[:300]))
|
||||
else:
|
||||
out.write(" <Iteration>\n")
|
||||
for line in h:
|
||||
if "</BlastOutput_iterations>" in line:
|
||||
break
|
||||
#TODO - Increment <Iteration_iter-num> and if required automatic query names
|
||||
#like <Iteration_query-ID>Query_3</Iteration_query-ID> to be increasing?
|
||||
out.write(line)
|
||||
h.close()
|
||||
out.write(" </BlastOutput_iterations>\n")
|
||||
out.write("</BlastOutput>\n")
|
||||
out.close()
|
||||
merge = staticmethod(merge)
|
||||
|
||||
|
||||
class MEMEXml( GenericXml ):
|
||||
"""MEME XML Output data"""
|
||||
file_ext = "memexml"
|
||||
@@ -196,3 +76,24 @@ class CisML( GenericXml ):
|
||||
dataset.blurb = 'file purged from disk'
|
||||
def sniff( self, filename ):
|
||||
return False
|
||||
|
||||
class Phyloxml( GenericXml ):
|
||||
"""Format for defining phyloxml data http://www.phyloxml.org/"""
|
||||
file_ext = "phyloxml"
|
||||
def set_peek( self, dataset, is_multi_byte=False ):
|
||||
"""Set the peek and blurb text"""
|
||||
if not dataset.dataset.purged:
|
||||
dataset.peek = data.get_file_peek( dataset.file_name, is_multi_byte=is_multi_byte )
|
||||
dataset.blurb = 'Phyloxml data'
|
||||
else:
|
||||
dataset.peek = 'file does not exist'
|
||||
dataset.blurb = 'file purged from disk'
|
||||
|
||||
def sniff( self, filename ):
|
||||
""""Checking for keyword - 'phyloxml' always in lowercase in the first few lines"""
|
||||
f = open(filename, "r")
|
||||
firstlines = "".join(f.readlines(5))
|
||||
f.close()
|
||||
if "phyloxml" in firstlines:
|
||||
return True
|
||||
return False
|
||||
+16
-16
@@ -471,7 +471,7 @@ class JobWrapper( object ):
|
||||
job.user.total_disk_usage += bytes
|
||||
|
||||
# fix permissions
|
||||
for path in [ dp.real_path for dp in self.get_output_fnames() ]:
|
||||
for path in [ dp.real_path for dp in self.get_mutable_output_fnames() ]:
|
||||
util.umask_fix_perms( path, self.app.config.umask, 0666, self.app.config.gid )
|
||||
self.sa_session.flush()
|
||||
log.debug( 'job %d ended' % self.job_id )
|
||||
@@ -490,7 +490,6 @@ class JobWrapper( object ):
|
||||
if stderr contains anything, then False is returned.
|
||||
Note that the job id is just for messages.
|
||||
"""
|
||||
err_msg = ""
|
||||
# By default, the tool succeeded. This covers the case where the code
|
||||
# has a bug but the tool was ok, and it lets a workflow continue.
|
||||
success = True
|
||||
@@ -507,7 +506,7 @@ class JobWrapper( object ):
|
||||
# Check the exit code ranges in the order in which
|
||||
# they were specified. Each exit_code is a StdioExitCode
|
||||
# that includes an applicable range. If the exit code was in
|
||||
# that range, then apply the error level and add in a message.
|
||||
# that range, then apply the error level and add a message.
|
||||
# If we've reached a fatal error rule, then stop.
|
||||
max_error_level = galaxy.tools.StdioErrorLevel.NO_ERROR
|
||||
for stdio_exit_code in self.tool.stdio_exit_codes:
|
||||
@@ -515,20 +514,16 @@ class JobWrapper( object ):
|
||||
tool_exit_code <= stdio_exit_code.range_end ):
|
||||
# Tack on a generic description of the code
|
||||
# plus a specific code description. For example,
|
||||
# this might append "Job 42: Warning: Out of Memory\n".
|
||||
# TODO: Find somewhere to stick the err_msg -
|
||||
# possibly to the source (stderr/stdout), possibly
|
||||
# in a new db column.
|
||||
# this might prepend "Job 42: Warning: Out of Memory\n".
|
||||
code_desc = stdio_exit_code.desc
|
||||
if ( None == code_desc ):
|
||||
code_desc = ""
|
||||
tool_msg = ( "Job %s: %s: Exit code %d: %s" % (
|
||||
job.get_id_tag(),
|
||||
galaxy.tools.StdioErrorLevel.desc( tool_exit_code ),
|
||||
tool_msg = ( "%s: Exit code %d: %s" % (
|
||||
galaxy.tools.StdioErrorLevel.desc( stdio_exit_code.error_level ),
|
||||
tool_exit_code,
|
||||
code_desc ) )
|
||||
log.info( tool_msg )
|
||||
stderr = err_msg + stderr
|
||||
log.info( "Job %s: %s" % (job.get_id_tag(), tool_msg) )
|
||||
stderr = tool_msg + "\n" + stderr
|
||||
max_error_level = max( max_error_level,
|
||||
stdio_exit_code.error_level )
|
||||
if ( max_error_level >=
|
||||
@@ -571,7 +566,6 @@ class JobWrapper( object ):
|
||||
re.IGNORECASE )
|
||||
if ( regex_match ):
|
||||
rexmsg = self.regex_err_msg( regex_match, regex)
|
||||
# DELETEME
|
||||
log.info( "Job %s: %s"
|
||||
% ( job.get_id_tag(), rexmsg ) )
|
||||
stderr = rexmsg + "\n" + stderr
|
||||
@@ -685,6 +679,11 @@ class JobWrapper( object ):
|
||||
self.compute_outputs()
|
||||
return self.output_paths
|
||||
|
||||
def get_mutable_output_fnames( self ):
|
||||
if self.output_paths is None:
|
||||
self.compute_outputs()
|
||||
return filter( lambda dsp: dsp.mutable, self.output_paths )
|
||||
|
||||
def get_output_hdas_and_fnames( self ):
|
||||
if self.output_hdas_and_paths is None:
|
||||
self.compute_outputs()
|
||||
@@ -692,10 +691,11 @@ class JobWrapper( object ):
|
||||
|
||||
def compute_outputs( self ) :
|
||||
class DatasetPath( object ):
|
||||
def __init__( self, dataset_id, real_path, false_path = None ):
|
||||
def __init__( self, dataset_id, real_path, false_path = None, mutable = True ):
|
||||
self.dataset_id = dataset_id
|
||||
self.real_path = real_path
|
||||
self.false_path = false_path
|
||||
self.mutable = mutable
|
||||
def __str__( self ):
|
||||
if self.false_path is None:
|
||||
return self.real_path
|
||||
@@ -712,13 +712,13 @@ class JobWrapper( object ):
|
||||
self.output_hdas_and_paths = {}
|
||||
for name, hda in [ ( da.name, da.dataset ) for da in job.output_datasets + job.output_library_datasets ]:
|
||||
false_path = os.path.abspath( os.path.join( self.working_directory, "galaxy_dataset_%d.dat" % hda.dataset.id ) )
|
||||
dsp = DatasetPath( hda.dataset.id, hda.dataset.file_name, false_path )
|
||||
dsp = DatasetPath( hda.dataset.id, hda.dataset.file_name, false_path, mutable = hda.dataset.external_filename is None )
|
||||
self.output_paths.append( dsp )
|
||||
self.output_hdas_and_paths[name] = hda, dsp
|
||||
if special:
|
||||
false_path = os.path.abspath( os.path.join( self.working_directory, "galaxy_dataset_%d.dat" % special.dataset.id ) )
|
||||
else:
|
||||
results = [ ( da.name, da.dataset, DatasetPath( da.dataset.dataset.id, da.dataset.file_name ) ) for da in job.output_datasets + job.output_library_datasets ]
|
||||
results = [ ( da.name, da.dataset, DatasetPath( da.dataset.dataset.id, da.dataset.file_name, mutable = da.dataset.dataset.external_filename is None ) ) for da in job.output_datasets + job.output_library_datasets ]
|
||||
self.output_paths = [t[2] for t in results]
|
||||
self.output_hdas_and_paths = dict([(t[0], t[1:]) for t in results])
|
||||
if special:
|
||||
|
||||
@@ -115,15 +115,16 @@ class GenomeTransferPlugin( DataTransfer ):
|
||||
files = tar.getmembers()
|
||||
for filename in files:
|
||||
z = tar.extractfile(filename)
|
||||
try:
|
||||
chunk = z.read( CHUNK_SIZE )
|
||||
except IOError:
|
||||
os.close( fd )
|
||||
log.error( 'Problem decompressing compressed data' )
|
||||
exit()
|
||||
if not chunk:
|
||||
break
|
||||
os.write( fd, chunk )
|
||||
while 1:
|
||||
try:
|
||||
chunk = z.read( CHUNK_SIZE )
|
||||
except IOError:
|
||||
os.close( fd )
|
||||
log.error( 'Problem decompressing compressed data' )
|
||||
exit()
|
||||
if not chunk:
|
||||
break
|
||||
os.write( fd, chunk )
|
||||
os.write( fd, '\n' )
|
||||
os.close( fd )
|
||||
tar.close()
|
||||
|
||||
@@ -360,7 +360,7 @@ class DefaultJobDispatcher( object ):
|
||||
def __init__( self, app ):
|
||||
self.app = app
|
||||
self.job_runners = {}
|
||||
start_job_runners = ["local", "lwr", "dynamic"]
|
||||
start_job_runners = ["local", "lwr"]
|
||||
if app.config.start_job_runners is not None:
|
||||
start_job_runners.extend( [ x.strip() for x in util.listify( app.config.start_job_runners ) ] )
|
||||
if app.config.use_tasked_jobs:
|
||||
|
||||
@@ -111,7 +111,7 @@ class JobRunnerMapper( object ):
|
||||
expand_function = self.__get_expand_function( expand_function_name )
|
||||
return self.__invoke_expand_function( expand_function )
|
||||
else:
|
||||
raise Exception( "Unhandled dynamic job runner type specified - %s" % calculation_type )
|
||||
raise Exception( "Unhandled dynamic job runner type specified - %s" % expand_type )
|
||||
|
||||
def __cache_job_runner_url( self, params ):
|
||||
raw_job_runner_url = self.job_wrapper.tool.get_job_runner_url( params )
|
||||
|
||||
@@ -95,7 +95,7 @@ class UsesAnnotations:
|
||||
""" Returns a user's annotation string for an item. """
|
||||
annotation_obj = self.get_item_annotation_obj( db_session, user, item )
|
||||
if annotation_obj:
|
||||
return annotation_obj.annotation
|
||||
return galaxy.util.unicodify( annotation_obj.annotation )
|
||||
return None
|
||||
|
||||
def get_item_annotation_obj( self, db_session, user, item ):
|
||||
|
||||
@@ -25,6 +25,7 @@ from sqlalchemy.orm import object_session
|
||||
if sys.version_info >= (2, 6):
|
||||
import multiprocessing
|
||||
from galaxy.objectstore.s3_multipart_upload import multipart_upload
|
||||
import boto
|
||||
from boto.s3.key import Key
|
||||
from boto.s3.connection import S3Connection
|
||||
from boto.exception import S3ResponseError
|
||||
@@ -377,9 +378,9 @@ class S3ObjectStore(ObjectStore):
|
||||
super(S3ObjectStore, self).__init__()
|
||||
self.config = config
|
||||
self.staging_path = self.config.file_path
|
||||
self.s3_conn = S3Connection()
|
||||
self.bucket = self._get_bucket(self.config.s3_bucket)
|
||||
self.use_rr = self.config.use_reduced_redundancy
|
||||
self.s3_conn = get_OS_connection(self.config)
|
||||
self.bucket = self._get_bucket(self.config.os_bucket_name)
|
||||
self.use_rr = self.config.os_use_reduced_redundancy
|
||||
self.cache_size = self.config.object_store_cache_size
|
||||
self.transfer_progress = 0
|
||||
# Clean cache only if value is set in universe_wsgi.ini
|
||||
@@ -468,7 +469,7 @@ class S3ObjectStore(ObjectStore):
|
||||
for i in range(5):
|
||||
try:
|
||||
bucket = self.s3_conn.get_bucket(bucket_name)
|
||||
log.debug("Using S3 object store; got bucket '%s'" % bucket.name)
|
||||
log.debug("Using cloud object store with bucket '%s'" % bucket.name)
|
||||
return bucket
|
||||
except S3ResponseError:
|
||||
log.debug("Could not get bucket '%s', attempt %s/5" % (bucket_name, i+1))
|
||||
@@ -607,13 +608,13 @@ class S3ObjectStore(ObjectStore):
|
||||
log.error("Problem downloading key '%s' from S3 bucket '%s': %s" % (rel_path, self.bucket.name, ex))
|
||||
return False
|
||||
|
||||
def _push_to_s3(self, rel_path, source_file=None, from_string=None):
|
||||
def _push_to_os(self, rel_path, source_file=None, from_string=None):
|
||||
"""
|
||||
Push the file pointed to by `rel_path` to S3 naming the key `rel_path`.
|
||||
If `source_file` is provided, push that file instead while still using
|
||||
`rel_path` as the key name.
|
||||
If `from_string` is provided, set contents of the file to the value of
|
||||
the string
|
||||
Push the file pointed to by ``rel_path`` to the object store naming the key
|
||||
``rel_path``. If ``source_file`` is provided, push that file instead while
|
||||
still using ``rel_path`` as the key name.
|
||||
If ``from_string`` is provided, set contents of the file to the value of
|
||||
the string.
|
||||
"""
|
||||
try:
|
||||
source_file = source_file if source_file else self._get_cache_path(rel_path)
|
||||
@@ -630,7 +631,7 @@ class S3ObjectStore(ObjectStore):
|
||||
# print "Pushing cache file '%s' of size %s bytes to key '%s'" % (source_file, os.path.getsize(source_file), rel_path)
|
||||
# print "+ Push started at '%s'" % start_time
|
||||
mb_size = os.path.getsize(source_file) / 1e6
|
||||
if mb_size < 60:
|
||||
if mb_size < 60 or self.config.object_store == 'swift':
|
||||
self.transfer_progress = 0 # Reset transfer progress counter
|
||||
key.set_contents_from_filename(source_file, reduced_redundancy=self.use_rr,
|
||||
cb=self._transfer_cb, num_cb=10)
|
||||
@@ -648,12 +649,17 @@ class S3ObjectStore(ObjectStore):
|
||||
return False
|
||||
|
||||
def file_ready(self, obj, **kwargs):
|
||||
""" A helper method that checks if a file corresponding to a dataset
|
||||
is ready and available to be used. Return True if so, False otherwise."""
|
||||
"""
|
||||
A helper method that checks if a file corresponding to a dataset is
|
||||
ready and available to be used. Return ``True`` if so, ``False`` otherwise.
|
||||
"""
|
||||
rel_path = self._construct_path(obj, **kwargs)
|
||||
# Make sure the size in cache is available in its entirety
|
||||
if self._in_cache(rel_path) and os.path.getsize(self._get_cache_path(rel_path)) == self._get_size_in_s3(rel_path):
|
||||
return True
|
||||
if self._in_cache(rel_path):
|
||||
if os.path.getsize(self._get_cache_path(rel_path)) == self._get_size_in_s3(rel_path):
|
||||
return True
|
||||
log.debug("Waiting for dataset {0} to transfer from OS: {1}/{2}".format(rel_path,
|
||||
os.path.getsize(self._get_cache_path(rel_path)), self._get_size_in_s3(rel_path)))
|
||||
return False
|
||||
|
||||
def exists(self, obj, **kwargs):
|
||||
@@ -674,7 +680,7 @@ class S3ObjectStore(ObjectStore):
|
||||
return False
|
||||
# TODO: Sync should probably not be done here. Add this to an async upload stack?
|
||||
if in_cache and not in_s3:
|
||||
self._push_to_s3(rel_path, source_file=self._get_cache_path(rel_path))
|
||||
self._push_to_os(rel_path, source_file=self._get_cache_path(rel_path))
|
||||
return True
|
||||
elif in_s3:
|
||||
return True
|
||||
@@ -707,12 +713,12 @@ class S3ObjectStore(ObjectStore):
|
||||
# flat namespace), do so for consistency with the regular file system
|
||||
# S3 folders are marked by having trailing '/' so add it now
|
||||
# s3_dir = '%s/' % rel_path
|
||||
# self._push_to_s3(s3_dir, from_string='')
|
||||
# self._push_to_os(s3_dir, from_string='')
|
||||
# If instructed, create the dataset in cache & in S3
|
||||
if not dir_only:
|
||||
rel_path = os.path.join(rel_path, alt_name if alt_name else "dataset_%s.dat" % obj.id)
|
||||
open(os.path.join(self.staging_path, rel_path), 'w').close()
|
||||
self._push_to_s3(rel_path, from_string='')
|
||||
self._push_to_os(rel_path, from_string='')
|
||||
|
||||
def empty(self, obj, **kwargs):
|
||||
if self.exists(obj, **kwargs):
|
||||
@@ -826,7 +832,7 @@ class S3ObjectStore(ObjectStore):
|
||||
else:
|
||||
source_file = self._get_cache_path(rel_path)
|
||||
# Update the file on S3
|
||||
self._push_to_s3(rel_path, source_file)
|
||||
self._push_to_os(rel_path, source_file)
|
||||
else:
|
||||
raise ObjectNotFound()
|
||||
|
||||
@@ -843,7 +849,6 @@ class S3ObjectStore(ObjectStore):
|
||||
def get_store_usage_percent(self):
|
||||
return 0.0
|
||||
|
||||
|
||||
class DistributedObjectStore(ObjectStore):
|
||||
"""
|
||||
ObjectStore that defers to a list of backends, for getting objects the
|
||||
@@ -1009,14 +1014,14 @@ def build_object_store_from_config(config):
|
||||
store = config.object_store
|
||||
if store == 'disk':
|
||||
return DiskObjectStore(config=config)
|
||||
elif store == 's3':
|
||||
os.environ['AWS_ACCESS_KEY_ID'] = config.aws_access_key
|
||||
os.environ['AWS_SECRET_ACCESS_KEY'] = config.aws_secret_key
|
||||
elif store == 's3' or store == 'swift':
|
||||
return S3ObjectStore(config=config)
|
||||
elif store == 'distributed':
|
||||
return DistributedObjectStore(config=config)
|
||||
elif store == 'hierarchical':
|
||||
return HierarchicalObjectStore()
|
||||
else:
|
||||
log.error("Unrecognized object store definition: {0}".format(store))
|
||||
|
||||
def convert_bytes(bytes):
|
||||
""" A helper function used for pretty printing disk usage """
|
||||
@@ -1039,3 +1044,26 @@ def convert_bytes(bytes):
|
||||
else:
|
||||
size = '%.2fb' % bytes
|
||||
return size
|
||||
|
||||
def get_OS_connection(config):
|
||||
"""
|
||||
Get a connection object for a cloud Object Store specified in the config.
|
||||
Currently, this is a ``boto`` connection object.
|
||||
"""
|
||||
log.debug("Getting a connection object for '{0}' object store".format(config.object_store))
|
||||
a_key = config.os_access_key
|
||||
s_key = config.os_secret_key
|
||||
if config.object_store == 's3':
|
||||
return S3Connection(a_key, s_key)
|
||||
else:
|
||||
# Establish the connection now
|
||||
calling_format = boto.s3.connection.OrdinaryCallingFormat()
|
||||
s3_conn = boto.connect_s3(aws_access_key_id=a_key,
|
||||
aws_secret_access_key=s_key,
|
||||
is_secure=config.os_is_secure,
|
||||
host=config.os_host,
|
||||
port=int(config.os_port),
|
||||
calling_format=calling_format,
|
||||
path=config.os_conn_path)
|
||||
return s3_conn
|
||||
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
"""
|
||||
The NCBI BLAST+ tools have been eliminated from the distribution. The tools and
|
||||
datatypes are are now available in repositories named ncbi_blast_plus and
|
||||
blast_datatypes, respectively, from the main Galaxy tool shed at
|
||||
http://toolshed.g2.bx.psu.edu will be installed into your local Galaxy instance
|
||||
at the location discussed above by running the following command.
|
||||
"""
|
||||
|
||||
import sys
|
||||
|
||||
def upgrade():
|
||||
print __doc__
|
||||
def downgrade():
|
||||
pass
|
||||
@@ -187,7 +187,9 @@ class ToolBox( object ):
|
||||
section.elems[ section_key ] = workflow
|
||||
log.debug( "Loaded workflow: %s %s" % ( workflow_id, workflow.name ) )
|
||||
elif section_key.startswith( 'label_' ):
|
||||
section.elems[ section_key ] = section_val
|
||||
if section_val:
|
||||
section.elems[ section_key ] = section_val
|
||||
log.debug( "Loaded label: %s" % ( section_val.text ) )
|
||||
self.tool_panel[ key ] = section
|
||||
def load_integrated_tool_panel_keys( self ):
|
||||
"""
|
||||
@@ -215,12 +217,12 @@ class ToolBox( object ):
|
||||
section.elems[ key ] = None
|
||||
elif section_elem.tag == 'label':
|
||||
key = 'label_%s' % section_elem.get( 'id' )
|
||||
section.elems[ key ] = ToolSectionLabel( section_elem )
|
||||
section.elems[ key ] = None
|
||||
key = 'section_%s' % elem.get( 'id' )
|
||||
self.integrated_tool_panel[ key ] = section
|
||||
elif elem.tag == 'label':
|
||||
key = 'label_%s' % elem.get( 'id' )
|
||||
self.integrated_tool_panel[ key ] = ToolSectionLabel( elem )
|
||||
self.integrated_tool_panel[ key ] = None
|
||||
def write_integrated_tool_panel_config_file( self ):
|
||||
"""
|
||||
Write the current in-memory version of the integrated_tool_panel.xml file to disk. Since Galaxy administrators
|
||||
@@ -254,10 +256,11 @@ class ToolBox( object ):
|
||||
if section_item:
|
||||
os.write( fd, ' <workflow id="%s" />\n' % section_item.id )
|
||||
elif section_key.startswith( 'label_' ):
|
||||
label_id = section_item.id or ''
|
||||
label_text = section_item.text or ''
|
||||
label_version = section_item.version or ''
|
||||
os.write( fd, ' <label id="%s" text="%s" version="%s" />\n' % ( label_id, label_text, label_version ) )
|
||||
if section_item:
|
||||
label_id = section_item.id or ''
|
||||
label_text = section_item.text or ''
|
||||
label_version = section_item.version or ''
|
||||
os.write( fd, ' <label id="%s" text="%s" version="%s" />\n' % ( label_id, label_text, label_version ) )
|
||||
os.write( fd, ' </section>\n' )
|
||||
os.write( fd, '</toolbox>\n' )
|
||||
os.close( fd )
|
||||
@@ -2631,7 +2634,7 @@ class Tool:
|
||||
if for_link:
|
||||
# Create tool link.
|
||||
if not self.tool_type.startswith( 'data_source' ):
|
||||
link = url_for( controller='tool_runner', tool_id=self.id )
|
||||
link = url_for( '/tool_runner', tool_id=self.id )
|
||||
else:
|
||||
link = url_for( self.action, **self.get_static_param_values( trans ) )
|
||||
|
||||
|
||||
@@ -18,13 +18,16 @@ def load_genome_index_tools( toolbox ):
|
||||
<tool id="__GENOME_INDEX__" name="Index Genome" version="0.1" tool_type="genome_index">
|
||||
<type class="GenomeIndexTool" module="galaxy.tools"/>
|
||||
<action module="galaxy.tools.actions.index_genome" class="GenomeIndexToolAction"/>
|
||||
<command>$__GENOME_INDEX_COMMAND__ $output_file $output_file.files_path $__app__.config.rsync_url "$__app__.config.tool_data_path"</command>
|
||||
<command>$__GENOME_INDEX_COMMAND__ $output_file $output_file.files_path "$__app__.config.rsync_url" "$__app__.config.tool_data_path"</command>
|
||||
<inputs>
|
||||
<param name="__GENOME_INDEX_COMMAND__" type="hidden"/>
|
||||
</inputs>
|
||||
<outputs>
|
||||
<data format="txt" name="output_file"/>
|
||||
</outputs>
|
||||
<stdio>
|
||||
<exit_code range="1:" err_level="fatal" />
|
||||
</stdio>
|
||||
</tool>
|
||||
"""
|
||||
|
||||
@@ -64,6 +67,18 @@ class GenomeIndexToolWrapper( object ):
|
||||
|
||||
|
||||
if gitd:
|
||||
fp = open( gitd.dataset.get_file_name(), 'r' )
|
||||
deferred = sa_session.query( model.DeferredJob ).filter_by( id=gitd.deferred_job_id ).first()
|
||||
try:
|
||||
logloc = json.load( fp )
|
||||
except ValueError:
|
||||
deferred.state = app.model.DeferredJob.states.ERROR
|
||||
sa_session.add( deferred )
|
||||
sa_session.flush()
|
||||
log.debug( 'Indexing job failed, setting deferred job state to error.' )
|
||||
return False
|
||||
finally:
|
||||
fp.close()
|
||||
destination = None
|
||||
tdtman = ToolDataTableManager( app.config.tool_data_path )
|
||||
xmltree = tdtman.load_from_config_file( app.config.tool_data_table_config_path, app.config.tool_data_path )
|
||||
@@ -72,16 +87,12 @@ class GenomeIndexToolWrapper( object ):
|
||||
location = node.findall('file')[0].get('path')
|
||||
self.locations[table] = os.path.abspath( location )
|
||||
locbase = os.path.abspath( os.path.split( self.locations['all_fasta'] )[0] )
|
||||
deferred = sa_session.query( model.DeferredJob ).filter_by( id=gitd.deferred_job_id ).first()
|
||||
params = deferred.params
|
||||
dbkey = params[ 'dbkey' ]
|
||||
basepath = os.path.join( os.path.abspath( app.config.genome_data_path ), dbkey )
|
||||
intname = params[ 'intname' ]
|
||||
indexer = gitd.indexer
|
||||
workingdir = os.path.abspath( gitd.dataset.extra_files_path )
|
||||
fp = open( gitd.dataset.get_file_name(), 'r' )
|
||||
logloc = json.load( fp )
|
||||
fp.close()
|
||||
location = []
|
||||
indexdata = gitd.dataset.extra_files_path
|
||||
if indexer == '2bit':
|
||||
|
||||
@@ -40,19 +40,21 @@ class ManagedIndexer():
|
||||
self.genome = os.path.splitext( self.fafile )[0]
|
||||
with WithChDir( self.basedir ):
|
||||
if indexer not in self.indexers:
|
||||
raise KeyError, 'The requested indexing function does not exist'
|
||||
sys.stderr.write( 'The requested indexing function does not exist' )
|
||||
exit(127)
|
||||
else:
|
||||
with WithChDir( self.workingdir ):
|
||||
self._log( 'Running indexer %s.' % indexer )
|
||||
result = getattr( self, self.indexers[ indexer ] )()
|
||||
if result in [ None, False ]:
|
||||
self._log( 'Error running indexer %s, %s' % ( indexer, result ) )
|
||||
sys.stderr.write( 'Error running indexer %s, %s' % ( indexer, result ) )
|
||||
self._flush_files()
|
||||
return True
|
||||
exit(1)
|
||||
else:
|
||||
self._log( self.locations )
|
||||
self._log( 'Indexer %s completed successfully.' % indexer )
|
||||
self._flush_files()
|
||||
exit(0)
|
||||
|
||||
def _check_link( self ):
|
||||
self._log( 'Checking symlink to %s' % self.fafile )
|
||||
@@ -309,5 +311,7 @@ if __name__ == "__main__":
|
||||
|
||||
# Create archive.
|
||||
idxobj = ManagedIndexer( outfile, infile, working_dir, rsync_url, tooldata )
|
||||
idxobj.run_indexer( indexer )
|
||||
|
||||
returncode = idxobj.run_indexer( indexer )
|
||||
if not returncode:
|
||||
exit(1)
|
||||
exit(0)
|
||||
@@ -34,6 +34,9 @@ _lock = threading.RLock()
|
||||
|
||||
gzip_magic = '\037\213'
|
||||
bz2_magic = 'BZh'
|
||||
DEFAULT_ENCODING = 'utf-8'
|
||||
NULL_CHAR = '\000'
|
||||
BINARY_CHARS = [ NULL_CHAR ]
|
||||
|
||||
from inflection import Inflector, English
|
||||
inflector = Inflector(English)
|
||||
@@ -57,6 +60,32 @@ def is_multi_byte( chars ):
|
||||
return True
|
||||
return False
|
||||
|
||||
def is_binary( value, binary_chars=None ):
|
||||
"""
|
||||
File is binary if it contains a null-byte by default (e.g. behavior of grep, etc.).
|
||||
This may fail for utf-16 files, but so would ASCII encoding.
|
||||
>>> is_binary( string.printable )
|
||||
False
|
||||
>>> is_binary( '\\xce\\x94' )
|
||||
False
|
||||
>>> is_binary( '\\000' )
|
||||
True
|
||||
"""
|
||||
if binary_chars is None:
|
||||
binary_chars = BINARY_CHARS
|
||||
for binary_char in binary_chars:
|
||||
if binary_char in value:
|
||||
return True
|
||||
return False
|
||||
|
||||
def get_charset_from_http_headers( headers, default=None ):
|
||||
rval = headers.get('content-type', None )
|
||||
if rval and 'charset=' in rval:
|
||||
rval = rval.split('charset=')[-1].split(';')[0].strip()
|
||||
if rval:
|
||||
return rval
|
||||
return default
|
||||
|
||||
def synchronized(func):
|
||||
"""This wrapper will serialize access to 'func' to a single thread. Use it as a decorator."""
|
||||
def caller(*params, **kparams):
|
||||
@@ -333,6 +362,17 @@ def roundify(amount, sfs = 2):
|
||||
else:
|
||||
return amount[0:sfs] + '0'*(len(amount) - sfs)
|
||||
|
||||
def unicodify( value, encoding=DEFAULT_ENCODING, error='replace', default=None ):
|
||||
"""
|
||||
Returns a unicode string or None
|
||||
"""
|
||||
if isinstance( value, unicode ):
|
||||
return value
|
||||
try:
|
||||
return unicode( value, encoding, error )
|
||||
except:
|
||||
return default
|
||||
|
||||
def object_to_string( obj ):
|
||||
return binascii.hexlify( pickle.dumps( obj, 2 ) )
|
||||
|
||||
@@ -502,7 +542,7 @@ def stringify_dictionary_keys( in_dict ):
|
||||
|
||||
def recursively_stringify_dictionary_keys( d ):
|
||||
if isinstance(d, dict):
|
||||
return dict([(k.encode('utf-8'), recursively_stringify_dictionary_keys(v)) for k,v in d.iteritems()])
|
||||
return dict([(k.encode( DEFAULT_ENCODING ), recursively_stringify_dictionary_keys(v)) for k,v in d.iteritems()])
|
||||
elif isinstance(d, list):
|
||||
return [recursively_stringify_dictionary_keys(x) for x in d]
|
||||
else:
|
||||
@@ -622,7 +662,7 @@ def send_mail( frm, to, subject, body, config ):
|
||||
Sends an email.
|
||||
"""
|
||||
to = listify( to )
|
||||
msg = MIMEText( body )
|
||||
msg = MIMEText( body.encode( 'ascii', 'replace' ) )
|
||||
msg[ 'To' ] = ', '.join( to )
|
||||
msg[ 'From' ] = frm
|
||||
msg[ 'Subject' ] = subject
|
||||
|
||||
@@ -334,7 +334,7 @@ def clone_repository( repository_clone_url, repository_file_dir, ctx_rev ):
|
||||
noupdate=False,
|
||||
rev=util.listify( str( ctx_rev ) ) )
|
||||
def copy_sample_file( app, filename, dest_path=None ):
|
||||
"""Copy xxx.loc.sample to dest_path/xxx.loc.sample and dest_path/xxx.loc. The default value for dest_path is ~/tool-data."""
|
||||
"""Copy xxx.sample to dest_path/xxx.sample and dest_path/xxx. The default value for dest_path is ~/tool-data."""
|
||||
if dest_path is None:
|
||||
dest_path = os.path.abspath( app.config.tool_data_path )
|
||||
sample_file_name = strip_path( filename )
|
||||
@@ -454,7 +454,7 @@ def create_tool_dependency_objects( app, tool_shed_repository, relative_install_
|
||||
def generate_clone_url( trans, repository ):
|
||||
"""Generate the URL for cloning a repository."""
|
||||
tool_shed_url = get_url_from_repository_tool_shed( trans.app, repository )
|
||||
return '%s/repos/%s/%s' % ( tool_shed_url, repository.owner, repository.name )
|
||||
return url_join( tool_shed_url, 'repos', repository.owner, repository.name )
|
||||
def generate_datatypes_metadata( datatypes_config, metadata_dict ):
|
||||
"""Update the received metadata_dict with information from the parsed datatypes_config."""
|
||||
tree = ElementTree.parse( datatypes_config )
|
||||
@@ -533,7 +533,7 @@ def can_generate_tool_dependency_metadata( root, metadata_dict ):
|
||||
if req_name==tool_dependency_name and req_version==tool_dependency_version and req_type==tool_dependency_type:
|
||||
can_generate_dependency_metadata = True
|
||||
break
|
||||
if not can_generate_dependency_metadata:
|
||||
if requirements and not can_generate_dependency_metadata:
|
||||
# We've discovered at least 1 combination of name, version and type that is not defined in the <requirement>
|
||||
# tag for any tool in the repository.
|
||||
break
|
||||
@@ -573,13 +573,13 @@ def generate_metadata_for_changeset_revision( app, repository_clone_url, relativ
|
||||
if datatypes_config:
|
||||
metadata_dict = generate_datatypes_metadata( datatypes_config, metadata_dict )
|
||||
# Get the relative path to all sample files included in the repository for storage in the repository's metadata.
|
||||
sample_files = get_sample_files_from_disk( repository_files_dir=files_dir,
|
||||
relative_install_dir=relative_install_dir,
|
||||
resetting_all_metadata_on_repository=resetting_all_metadata_on_repository )
|
||||
if sample_files:
|
||||
metadata_dict[ 'sample_files' ] = sample_files
|
||||
sample_file_metadata_paths, sample_file_copy_paths = get_sample_files_from_disk( repository_files_dir=files_dir,
|
||||
relative_install_dir=relative_install_dir,
|
||||
resetting_all_metadata_on_repository=resetting_all_metadata_on_repository )
|
||||
if sample_file_metadata_paths:
|
||||
metadata_dict[ 'sample_files' ] = sample_file_metadata_paths
|
||||
# Copy all sample files included in the repository to a single directory location so we can load tools that depend on them.
|
||||
for sample_file in sample_files:
|
||||
for sample_file in sample_file_copy_paths:
|
||||
copy_sample_file( app, sample_file, dest_path=work_dir )
|
||||
# If the list of sample files includes a tool_data_table_conf.xml.sample file, laad it's table elements into memory.
|
||||
relative_path, filename = os.path.split( sample_file )
|
||||
@@ -608,21 +608,9 @@ def generate_metadata_for_changeset_revision( app, repository_clone_url, relativ
|
||||
print "Error parsing %s", full_path, ", exception: ", str( e )
|
||||
is_tool = False
|
||||
if is_tool:
|
||||
try:
|
||||
tool = app.toolbox.load_tool( full_path )
|
||||
except KeyError, e:
|
||||
tool = None
|
||||
invalid_tool_configs.append( name )
|
||||
error_message = 'This file requires an entry for "%s" in the tool_data_table_conf.xml file. Upload a file ' % str( e )
|
||||
error_message += 'named tool_data_table_conf.xml.sample to the repository that includes the required entry to correct '
|
||||
error_message += 'this error. '
|
||||
invalid_file_tups.append( ( name, error_message ) )
|
||||
except Exception, e:
|
||||
tool = None
|
||||
invalid_tool_configs.append( name )
|
||||
invalid_file_tups.append( ( name, str( e ) ) )
|
||||
tool, valid, error_message = load_tool_from_config( app, full_path )
|
||||
if tool is not None:
|
||||
invalid_files_and_errors_tups = check_tool_input_params( app, files_dir, name, tool, sample_files, webapp=webapp )
|
||||
invalid_files_and_errors_tups = check_tool_input_params( app, files_dir, name, tool, sample_file_metadata_paths, webapp=webapp )
|
||||
can_set_metadata = True
|
||||
for tup in invalid_files_and_errors_tups:
|
||||
if name in tup:
|
||||
@@ -993,7 +981,7 @@ def get_converter_and_display_paths( registration_elem, relative_install_dir ):
|
||||
break
|
||||
return converter_path, display_path
|
||||
def get_ctx_rev( tool_shed_url, name, owner, changeset_revision ):
|
||||
url = '%s/repository/get_ctx_rev?name=%s&owner=%s&changeset_revision=%s&webapp=galaxy' % ( tool_shed_url, name, owner, changeset_revision )
|
||||
url = url_join( tool_shed_url, 'repository/get_ctx_rev?name=%s&owner=%s&changeset_revision=%s&webapp=galaxy' % ( name, owner, changeset_revision ) )
|
||||
response = urllib2.urlopen( url )
|
||||
ctx_rev = response.read()
|
||||
response.close()
|
||||
@@ -1077,7 +1065,8 @@ def get_sample_files_from_disk( repository_files_dir, relative_install_dir=None,
|
||||
if resetting_all_metadata_on_repository:
|
||||
# Keep track of the location where the repository is temporarily cloned so that we can strip it when setting metadata.
|
||||
work_dir = repository_files_dir
|
||||
sample_files = []
|
||||
sample_file_metadata_paths = []
|
||||
sample_file_copy_paths = []
|
||||
for root, dirs, files in os.walk( repository_files_dir ):
|
||||
if root.find( '.hg' ) < 0:
|
||||
for name in files:
|
||||
@@ -1088,10 +1077,15 @@ def get_sample_files_from_disk( repository_files_dir, relative_install_dir=None,
|
||||
if stripped_path_to_sample_file.startswith( '/' ):
|
||||
stripped_path_to_sample_file = stripped_path_to_sample_file[ 1: ]
|
||||
relative_path_to_sample_file = os.path.join( relative_install_dir, stripped_path_to_sample_file )
|
||||
if os.path.exists( relative_path_to_sample_file ):
|
||||
sample_file_copy_paths.append( relative_path_to_sample_file )
|
||||
else:
|
||||
sample_file_copy_paths.append( full_path_to_sample_file )
|
||||
else:
|
||||
relative_path_to_sample_file = os.path.join( root, name )
|
||||
sample_files.append( relative_path_to_sample_file )
|
||||
return sample_files
|
||||
sample_file_copy_paths.append( relative_path_to_sample_file )
|
||||
sample_file_metadata_paths.append( relative_path_to_sample_file )
|
||||
return sample_file_metadata_paths, sample_file_copy_paths
|
||||
def get_shed_tool_conf_dict( app, shed_tool_conf ):
|
||||
"""
|
||||
Return the in-memory version of the shed_tool_conf file, which is stored in the config_elems entry
|
||||
@@ -1221,8 +1215,8 @@ def get_tool_version_association( app, parent_tool_version, tool_version ):
|
||||
def get_update_to_changeset_revision_and_ctx_rev( trans, repository ):
|
||||
"""Return the changeset revision hash to which the repository can be updated."""
|
||||
tool_shed_url = get_url_from_repository_tool_shed( trans.app, repository )
|
||||
url = '%s/repository/get_changeset_revision_and_ctx_rev?name=%s&owner=%s&changeset_revision=%s' % \
|
||||
( tool_shed_url, repository.name, repository.owner, repository.installed_changeset_revision )
|
||||
url = url_join( tool_shed_url, 'repository/get_changeset_revision_and_ctx_rev?name=%s&owner=%s&changeset_revision=%s' % \
|
||||
( repository.name, repository.owner, repository.installed_changeset_revision ) )
|
||||
try:
|
||||
response = urllib2.urlopen( url )
|
||||
encoded_update_dict = response.read()
|
||||
@@ -1404,6 +1398,22 @@ def load_installed_datatypes( app, repository, relative_install_dir, deactivate=
|
||||
def load_installed_display_applications( app, installed_repository_dict, deactivate=False ):
|
||||
# Load or deactivate proprietary datatype display applications
|
||||
app.datatypes_registry.load_display_applications( installed_repository_dict=installed_repository_dict, deactivate=deactivate )
|
||||
def load_tool_from_config( app, full_path ):
|
||||
try:
|
||||
tool = app.toolbox.load_tool( full_path )
|
||||
valid = True
|
||||
error_message = None
|
||||
except KeyError, e:
|
||||
tool = None
|
||||
valid = False
|
||||
error_message = 'This file requires an entry for "%s" in the tool_data_table_conf.xml file. Upload a file ' % str( e )
|
||||
error_message += 'named tool_data_table_conf.xml.sample to the repository that includes the required entry to correct '
|
||||
error_message += 'this error. '
|
||||
except Exception, e:
|
||||
tool = None
|
||||
valid = False
|
||||
error_message = str( e )
|
||||
return tool, valid, error_message
|
||||
def open_repository_files_folder( trans, folder_path ):
|
||||
try:
|
||||
files_list = get_repository_files( trans, folder_path )
|
||||
@@ -1645,3 +1655,8 @@ def update_tool_shed_repository_status( app, tool_shed_repository, status ):
|
||||
tool_shed_repository.status = status
|
||||
sa_session.add( tool_shed_repository )
|
||||
sa_session.flush()
|
||||
def url_join( *args ):
|
||||
parts = []
|
||||
for arg in args:
|
||||
parts.append( arg.strip( '/' ) )
|
||||
return '/'.join( parts )
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
__author__ = 'Tomithy'
|
||||
@@ -0,0 +1,125 @@
|
||||
import json
|
||||
|
||||
class Node(object):
|
||||
"""Node class of PhyloTree, which represents a CLAUDE in a phylogenetic tree"""
|
||||
def __init__(self, nodeName, **kwargs):
|
||||
"""Creates a node and adds in the typical annotations"""
|
||||
self.name, self.id = nodeName, kwargs.get("id", 0)
|
||||
self.depth = kwargs.get("depth", 0)
|
||||
self.children = []
|
||||
|
||||
self.isInternal = kwargs.get("isInternal", 0)
|
||||
self.length, self.bootstrap = kwargs.get("length", 0), kwargs.get("bootstrap", None)
|
||||
self.events = kwargs.get("events", "")
|
||||
|
||||
# clean up boot strap values
|
||||
if self.bootstrap == -1:
|
||||
self.bootstrap = None
|
||||
|
||||
def addChildNode(self, child):
|
||||
"""Adds a child node to the current node"""
|
||||
if isinstance(child, Node):
|
||||
self.children.append(child)
|
||||
else:
|
||||
self.children += child
|
||||
|
||||
|
||||
def __str__(self):
|
||||
return self.name + " id:" + str(self.id) + ", depth: " + str(self.depth)
|
||||
|
||||
|
||||
def toJson(self):
|
||||
"""Converts the data in the node to a dict representation of json"""
|
||||
thisJson = {
|
||||
"name" : self.name,
|
||||
"id" : self.id,
|
||||
"depth" : self.depth,
|
||||
"dist" : self.length
|
||||
}
|
||||
thisJson = self.addChildrenToJson(thisJson)
|
||||
thisJson = self.addMiscToJson(thisJson)
|
||||
return thisJson
|
||||
|
||||
def addChildrenToJson(self, jsonDict):
|
||||
"""Needs a special method to addChildren, such that the key does not appear in the Jsondict when the children is empty
|
||||
this requirement is due to the layout algorithm used by d3 layout for hiding subtree """
|
||||
if len(self.children) > 0:
|
||||
children = [ node.toJson() for node in self.children]
|
||||
jsonDict["children"] = children
|
||||
return jsonDict
|
||||
|
||||
|
||||
def addMiscToJson(self, jsonDict):
|
||||
"""Adds other misc attributes to json if they are present"""
|
||||
if not self.events == "":
|
||||
jsonDict["events"] = self.events
|
||||
if not self.bootstrap == None:
|
||||
jsonDict["bootstrap"] = self.bootstrap
|
||||
return jsonDict
|
||||
|
||||
|
||||
|
||||
class PhyloTree(object):
|
||||
"""Standardized python based class to represent the phylogenetic tree parsed from different
|
||||
phylogenetic file formats."""
|
||||
|
||||
def __init__(self):
|
||||
self.root, self.rootAttr = None, {}
|
||||
self.nodes = {}
|
||||
self.title = None
|
||||
self.id = 1
|
||||
|
||||
def addAttributesToRoot(self, attrDict):
|
||||
"""Adds attributes to root, but first we put it in a temp store and bind it with root when .toJson is called"""
|
||||
for key, value in attrDict.items():
|
||||
self.rootAttr[key] = value
|
||||
|
||||
def makeNode(self, nodeName, **kwargs):
|
||||
"""Called to make a node within PhyloTree, arbitrary kwargs can be passed to annotate nodes
|
||||
Tracks the number of nodes via internally incremented id"""
|
||||
kwargs["id"] = self.id
|
||||
self.id += 1
|
||||
return Node(nodeName, **kwargs)
|
||||
|
||||
def addRoot(self, root):
|
||||
"""Creates a root for phyloTree"""
|
||||
assert isinstance(root, Node)
|
||||
root.parent = None
|
||||
self.root = root
|
||||
|
||||
def generateJsonableDict(self):
|
||||
"""Changes itself into a dictonary by recurssively calling the tojson on all its nodes. Think of it
|
||||
as a dict in an array of dict in an array of dict and so on..."""
|
||||
jsonTree = ""
|
||||
if self.root:
|
||||
assert isinstance(self.root, Node)
|
||||
jsonTree = self.root.toJson()
|
||||
for key, value in self.rootAttr.items():
|
||||
# transfer temporary stored attr to root
|
||||
jsonTree[key] = value
|
||||
else:
|
||||
raise Exception("Root is not assigned!")
|
||||
return jsonTree
|
||||
|
||||
|
||||
|
||||
class Base_Parser(object):
|
||||
"""Base parsers contain all the methods to handle phylogeny tree creation and
|
||||
converting the data to json that all parsers should have"""
|
||||
|
||||
def __init__(self):
|
||||
self.phyloTrees = []
|
||||
|
||||
def parseFile(self, filePath):
|
||||
"""Base method that all phylogeny file parser should have"""
|
||||
raise Exception("Base method for phylogeny file parsers is not implemented")
|
||||
|
||||
def toJson(self, jsonDict):
|
||||
"""Convenience method to get a json string from a python json dict"""
|
||||
return json.dumps(jsonDict)
|
||||
|
||||
def _writeJsonToFile(self, filepath, json):
|
||||
"""Writes the file out to the system"""
|
||||
f = open(filepath, "w")
|
||||
f.writelines(json)
|
||||
f.close()
|
||||
@@ -0,0 +1,185 @@
|
||||
from baseparser import Base_Parser, PhyloTree
|
||||
import re
|
||||
|
||||
class Newick_Parser(Base_Parser):
|
||||
"""For parsing trees stored in the newick format (.nhx)
|
||||
It is necessarily more complex because this parser is later extended by Nexus for parsing newick as well.."""
|
||||
|
||||
|
||||
def __init__(self):
|
||||
super(Newick_Parser, self).__init__()
|
||||
|
||||
|
||||
def parseFile(self, filePath):
|
||||
"""Parses a newick file to obtain the string inside. Returns: jsonableDict"""
|
||||
with open(filePath, "r") as newickFile:
|
||||
newickString = newickFile.read()
|
||||
newickString = newickString.replace("\n", "").replace("\r", "")
|
||||
return [self.parseData(newickString)], "Success"
|
||||
|
||||
|
||||
def parseData(self, newickString):
|
||||
"""To be called on a newickString directly to parse it. Returns: jsonableDict"""
|
||||
return self._parseNewickToJson(newickString)
|
||||
|
||||
|
||||
def _parseNewickToJson(self, newickString, treeName=None, nameMap=None):
|
||||
"""parses a newick representation of a tree into a PhyloTree data structure,
|
||||
which can be easily converted to json"""
|
||||
self.phyloTree = PhyloTree()
|
||||
newickString = self.cleanNewickString(newickString)
|
||||
if nameMap:
|
||||
newickString = self._mapName(newickString, nameMap)
|
||||
|
||||
self.phyloTree.root = self.parseNode(newickString, 0)
|
||||
if nameMap:
|
||||
self.phyloTree.addAttributesToRoot({"treeName": treeName})
|
||||
|
||||
return self.phyloTree.generateJsonableDict()
|
||||
|
||||
|
||||
def cleanNewickString(self, rawNewick):
|
||||
"""removing semi colon, and illegal json characters (\,',") and white spaces"""
|
||||
return re.sub(r'\s|;|\"|\'|\\', '', rawNewick)
|
||||
|
||||
|
||||
def _makeNodesFromString(self, string, depth):
|
||||
"""elements separated by comma could be empty"""
|
||||
|
||||
if string.find("(") != -1:
|
||||
raise Exception("Tree is not well form, location: " + string)
|
||||
|
||||
childrenString = string.split(",")
|
||||
childrenNodes = []
|
||||
|
||||
for childString in childrenString:
|
||||
if len(childString) == 0:
|
||||
continue
|
||||
nodeInfo = childString.split(":")
|
||||
name, length, bootstrap = "", None, -1
|
||||
if len(nodeInfo) == 2: # has length info
|
||||
length = nodeInfo[1]
|
||||
# checking for bootstap values
|
||||
name = nodeInfo[0]
|
||||
try: # Nexus may bootstrap in names position
|
||||
name = float(name)
|
||||
if 0<= name <= 1:
|
||||
bootstrap = name
|
||||
elif 1 <= name <= 100:
|
||||
bootstrap = name / 100
|
||||
name = ""
|
||||
except ValueError:
|
||||
name = nodeInfo[0]
|
||||
else:
|
||||
name = nodeInfo[0] # string only contains name
|
||||
node = self.phyloTree.makeNode(name, length=length, depth=depth, bootstrap= bootstrap)
|
||||
childrenNodes += [node]
|
||||
return childrenNodes
|
||||
|
||||
|
||||
|
||||
def _mapName(self, newickString, nameMap):
|
||||
"""
|
||||
Necessary to replace names of terms inside nexus representation
|
||||
Also, its here because Mailaud's doesnt deal with id_strings outside of quotes(" ")
|
||||
"""
|
||||
newString = ""
|
||||
start = 0
|
||||
end = 0
|
||||
|
||||
for i in xrange(len(newickString)):
|
||||
if newickString[i] == "(" or newickString[i] == ",":
|
||||
if re.match(r"[,(]", newickString[i+1:]):
|
||||
continue
|
||||
else:
|
||||
end = i + 1
|
||||
# i now refers to the starting position of the term to be replaced,
|
||||
# we will next find j which is the ending pos of the term
|
||||
for j in xrange(i+1, len(newickString)):
|
||||
enclosingSymbol = newickString[j] # the immediate symbol after a common or left bracket which denotes the end of a term
|
||||
if enclosingSymbol == ")" or enclosingSymbol == ":" or enclosingSymbol == ",":
|
||||
termToReplace = newickString[end:j]
|
||||
|
||||
newString += newickString[start : end] + nameMap[termToReplace] #+ "'" "'" +
|
||||
start = j
|
||||
break
|
||||
|
||||
newString += newickString[start:]
|
||||
return newString
|
||||
|
||||
|
||||
def parseNode(self, string, depth):
|
||||
""" Recursive method for parsing newick string, works by stripping down the string into substring
|
||||
of newick contained with brackers, which is used to call itself.
|
||||
Eg ... ( A, B, (D, E)C, F, G ) ...
|
||||
We will make the preceeding nodes first A, B, then the internal node C, its children D, E,
|
||||
and finally the succeeding nodes F, G"""
|
||||
|
||||
# Base case where there is only an empty string
|
||||
if string == "":
|
||||
return
|
||||
# Base case there its only an internal claude
|
||||
if string.find("(") == -1:
|
||||
return self._makeNodesFromString(string, depth)
|
||||
|
||||
nodes, children = [], [] # nodes refer to the nodes on this level, children refers to the child of the
|
||||
start = 0
|
||||
lenOfPreceedingInternalNodeString = 0
|
||||
bracketStack = []
|
||||
|
||||
for j in xrange(len(string)):
|
||||
if string[j] == "(": #finding the positions of all the open brackets
|
||||
bracketStack.append(j)
|
||||
continue
|
||||
if string[j] == ")": #finding the positions of all the closed brackets to extract claude
|
||||
i = bracketStack.pop()
|
||||
|
||||
if len(bracketStack) == 0: # is child of current node
|
||||
|
||||
InternalNode = None
|
||||
|
||||
#First flat call to make nodes of the same depth but from the preceeding string.
|
||||
startSubstring = string[start + lenOfPreceedingInternalNodeString: i]
|
||||
preceedingNodes = self._makeNodesFromString(startSubstring, depth)
|
||||
nodes += preceedingNodes
|
||||
|
||||
# Then We will try to see if the substring has any internal nodes first, make it then make nodes preceeding it and succeeding it.
|
||||
if j + 1 < len(string):
|
||||
stringRightOfBracket = string[j+1:] # Eg. '(b:0.4,a:0.3)c:0.3, stringRightOfBracket = c:0.3
|
||||
match = re.search(r"[\)\,\(]", stringRightOfBracket)
|
||||
if match:
|
||||
indexOfNextSymbol = match.start()
|
||||
stringRepOfInternalNode = stringRightOfBracket[:indexOfNextSymbol]
|
||||
internalNodes = self._makeNodesFromString( stringRepOfInternalNode, depth)
|
||||
if len(internalNodes) > 0:
|
||||
InternalNode = internalNodes[0]
|
||||
lenOfPreceedingInternalNodeString = len(stringRepOfInternalNode)
|
||||
else: # sometimes the node can be the last element of a string
|
||||
InternalNode = self._makeNodesFromString(string[j+1:], depth)[0]
|
||||
lenOfPreceedingInternalNodeString = len(string) - j
|
||||
if InternalNode == None: #creating a generic node if it is unnamed
|
||||
InternalNode = self.phyloTree.makeNode( "", depth=depth, isInternal=True ) #"internal-" + str(depth)
|
||||
lenOfPreceedingInternalNodeString = 0
|
||||
|
||||
# recussive call to make the internal claude
|
||||
childSubString = string[ i + 1 : j ]
|
||||
InternalNode.addChildNode(self.parseNode(childSubString, depth + 1))
|
||||
|
||||
nodes.append(InternalNode) # we append the internal node later to preserve order
|
||||
|
||||
start = j + 1
|
||||
continue
|
||||
|
||||
if depth == 0: # if its the root node, we do nothing about it and return
|
||||
return nodes[0]
|
||||
|
||||
# Adding last most set of children
|
||||
endString = string[start:]
|
||||
if string[start-1] == ")": # if the symbol belongs to an internal node which is created previously, then we remove it from the string left to parse
|
||||
match = re.search(r"[\)\,\(]", endString)
|
||||
if match:
|
||||
endOfNodeName = start + match.start() + 1
|
||||
endString = string[endOfNodeName:]
|
||||
nodes += self._makeNodesFromString(endString, depth)
|
||||
|
||||
return nodes
|
||||
@@ -0,0 +1,107 @@
|
||||
from newickparser import Newick_Parser
|
||||
import re
|
||||
|
||||
MAX_READLINES = 200000
|
||||
|
||||
|
||||
class Nexus_Parser(Newick_Parser):
|
||||
|
||||
def __init__(self):
|
||||
super(Nexus_Parser, self).__init__()
|
||||
|
||||
def parseFile(self, filePath):
|
||||
"""passes a file and extracts its Nexus content."""
|
||||
return self.parseNexus(filePath)
|
||||
|
||||
|
||||
def parseNexus(self, filename):
|
||||
""" Nexus data is stored in blocks between a line starting with begin and another line starting with end;
|
||||
Commends inside square brackets are to be ignored,
|
||||
For more information: http://wiki.christophchamp.com/index.php/NEXUS_file_format
|
||||
Nexus can store multiple trees
|
||||
"""
|
||||
|
||||
with open( filename, "rt") as nex_file:
|
||||
nexlines = nex_file.readlines()
|
||||
|
||||
rowCount = 0
|
||||
inTreeBlock = False # sentinel to check if we are in a tree block
|
||||
intranslateBlock = False # sentinel to check if we are in the translate region of the tree. Stores synonyms of the labellings
|
||||
self.inCommentBlock = False
|
||||
self.nameMapping = None # stores mapping representation used in nexus format
|
||||
treeNames = []
|
||||
|
||||
for line in nexlines:
|
||||
line = line.replace(";\n", "")
|
||||
lline = line.lower()
|
||||
|
||||
if rowCount > MAX_READLINES or (not nex_file) :
|
||||
break
|
||||
rowCount +=1
|
||||
# We are only interested in the tree block.
|
||||
if "begin" in lline and "tree" in lline and not inTreeBlock:
|
||||
inTreeBlock = True
|
||||
continue
|
||||
if inTreeBlock and "end" in lline[:3]:
|
||||
inTreeBlock, currPhyloTree = False, None
|
||||
continue
|
||||
|
||||
if inTreeBlock:
|
||||
|
||||
if "title" in lline: # Adding title to the tree
|
||||
titleLoc = lline.find("title")
|
||||
title = line[titleLoc + 5:].replace(" ", "")
|
||||
|
||||
continue
|
||||
|
||||
if "translate" in lline:
|
||||
intranslateBlock = True
|
||||
self.nameMapping = {}
|
||||
continue
|
||||
|
||||
if intranslateBlock:
|
||||
mappingLine = self.splitLinebyWhitespaces(line)
|
||||
key, value = mappingLine[1], mappingLine[2].replace(",", "").replace("'","") #replacing illegal json characters
|
||||
self.nameMapping[key] = value
|
||||
|
||||
# Extracting newick Trees
|
||||
if "tree" in lline:
|
||||
intranslateBlock = False
|
||||
|
||||
treeLineCols = self.splitLinebyWhitespaces(line)
|
||||
treeName, newick = treeLineCols[2], treeLineCols[-1]
|
||||
|
||||
if newick == "": # Empty lines can be found in tree blocks
|
||||
continue
|
||||
|
||||
currPhyloTree = self._parseNewickToJson(newick, treeName, nameMap=self.nameMapping)
|
||||
|
||||
self.phyloTrees.append(currPhyloTree)
|
||||
treeIndex = len(self.phyloTrees) - 1
|
||||
treeNames.append( (treeName, treeIndex) ) # appending name of tree, and its index
|
||||
continue
|
||||
|
||||
return self.phyloTrees, treeNames
|
||||
|
||||
|
||||
def splitLinebyWhitespaces(self, line):
|
||||
"""replace tabs and write spaces to a single write space, so we can properly split it."""
|
||||
return re.split(r"\s+", line)
|
||||
|
||||
|
||||
def checkComments(self, line):
|
||||
"""Check to see if the line/lines is a comment."""
|
||||
if not self.inCommentBlock:
|
||||
if "[" in line:
|
||||
if "]" not in line:
|
||||
self.inCommentBlock = True
|
||||
else:
|
||||
return "Nextline" # need to move on to the nextline after getting out of comment
|
||||
else :
|
||||
if "]" in line:
|
||||
if line.rfind("[") > line.rfind("]"):
|
||||
pass # a comment block is closed but another is open.
|
||||
else:
|
||||
self.inCommentBlock = False
|
||||
return "Nextline" # need to move on to the nextline after getting out of comment
|
||||
return ""
|
||||
@@ -0,0 +1,35 @@
|
||||
from newickparser import Newick_Parser
|
||||
from nexusparser import Nexus_Parser
|
||||
from phyloxmlparser import Phyloxml_Parser
|
||||
|
||||
class Phyloviz_DataProvider(object):
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def parseFile(self, filepath, fileExt):
|
||||
"""returns [trees], meta
|
||||
Trees are actually an array of JsonDicts. It's usually one tree, except in the case of Nexus
|
||||
"""
|
||||
jsonDicts, meta = [], {}
|
||||
try:
|
||||
if fileExt == "nhx": # parses newick files
|
||||
newickParser = Newick_Parser()
|
||||
jsonDicts, parseMsg = newickParser.parseFile(filepath)
|
||||
elif fileExt == "phyloxml": # parses phyloXML files
|
||||
phyloxmlParser = Phyloxml_Parser()
|
||||
jsonDicts, parseMsg = phyloxmlParser.parseFile(filepath)
|
||||
elif fileExt == "nex": # parses nexus files
|
||||
nexusParser = Nexus_Parser()
|
||||
jsonDicts, parseMsg = nexusParser.parseFile(filepath)
|
||||
meta["trees"] = parseMsg
|
||||
else:
|
||||
raise Exception("File type is not supported")
|
||||
|
||||
meta["msg"] = parseMsg
|
||||
|
||||
except Exception:
|
||||
jsonDicts, meta["msg"] = [], "Parse failed"
|
||||
|
||||
return jsonDicts, meta
|
||||
|
||||
@@ -0,0 +1,134 @@
|
||||
from baseparser import Base_Parser, PhyloTree, Node
|
||||
from xml.etree import ElementTree
|
||||
|
||||
class Phyloxml_Parser(Base_Parser):
|
||||
"""Parses a phyloxml file into a json file that will be passed to PhyloViz for display"""
|
||||
|
||||
def __init__(self):
|
||||
super(Phyloxml_Parser, self).__init__()
|
||||
self.phyloTree = PhyloTree()
|
||||
self.tagsOfInterest = {
|
||||
"clade": "",
|
||||
"name" : "name",
|
||||
"branch_length" : "length",
|
||||
"confidence" : "bootstrap",
|
||||
"events" : "events"
|
||||
}
|
||||
|
||||
def parseFile(self, filePath):
|
||||
"""passes a file and extracts its Phylogeny Tree content."""
|
||||
phyloXmlFile = open(filePath, "r")
|
||||
|
||||
xmlTree = ElementTree.parse(phyloXmlFile)
|
||||
xmlRoot = xmlTree.getroot()[0]
|
||||
self.nameSpaceIndex = xmlRoot.tag.rfind("}") + 1 # used later by the clean tag method to remove the name space in every element.tag
|
||||
|
||||
phyloRoot = None
|
||||
for child in xmlRoot:
|
||||
childTag = self.cleanTag(child.tag)
|
||||
if childTag == "clade":
|
||||
phyloRoot = child
|
||||
elif childTag == "name":
|
||||
self.phyloTree.title = child.text
|
||||
|
||||
self.phyloTree.root = self.parseNode(phyloRoot, 0)
|
||||
jsonDict = self.phyloTree.generateJsonableDict()
|
||||
return [jsonDict], "Success"
|
||||
|
||||
|
||||
def parseNode(self, node, depth):
|
||||
"""Parses any node within a phyloxml tree and looks out for claude, which signals the creation of
|
||||
nodes - internal OR leaf"""
|
||||
assert isinstance(node, etree._Element)
|
||||
|
||||
tag = self.cleanTag(node.tag)
|
||||
if not tag == "clade":
|
||||
return None
|
||||
hasInnerClade = False
|
||||
|
||||
# peeking once for parent and once for child to check if the node is internal
|
||||
for child in node:
|
||||
childTag = self.cleanTag(child.tag)
|
||||
if childTag == "clade":
|
||||
hasInnerClade = True
|
||||
break
|
||||
|
||||
if hasInnerClade: # this node is an internal node
|
||||
currentNode = self._makeInternalNode(node, depth= depth)
|
||||
for child in node:
|
||||
child = self.parseNode(child, depth + 1)
|
||||
if isinstance(child, Node):
|
||||
currentNode.addChildNode(child)
|
||||
|
||||
else: # this node is a leaf node
|
||||
currentNode = self._makeLeafNode(node, depth=depth+1)
|
||||
|
||||
return currentNode
|
||||
|
||||
|
||||
def _makeLeafNode(self, leafNode, depth = 0 ):
|
||||
"""Makes leaf nodes by calling Phylotree methods"""
|
||||
node = {}
|
||||
for child in leafNode:
|
||||
childTag = self.cleanTag(child.tag)
|
||||
if childTag in self.tagsOfInterest:
|
||||
key = self.tagsOfInterest[childTag] # need to map phyloxml terms to ours
|
||||
node[key] = child.text
|
||||
|
||||
node["depth"] = depth
|
||||
return self.phyloTree.makeNode(self._getNodeName(leafNode), **node)
|
||||
|
||||
def _getNodeName(self, node, depth=-1):
|
||||
"""Gets the name of a claude. It handles the case where a taxonomy node is involved"""
|
||||
|
||||
def getTagFromTaxonomyNode(node):
|
||||
"""Returns the name of a taxonomy node. A taxonomy node have to be treated differently as the name
|
||||
is embedded one level deeper"""
|
||||
phyloxmlTaxoNames = {
|
||||
"common_name" : "",
|
||||
"scientific_name" : "",
|
||||
"code" : ""
|
||||
}
|
||||
for child in node:
|
||||
childTag = self.cleanTag(child.tag)
|
||||
if childTag in phyloxmlTaxoNames:
|
||||
return child.text
|
||||
return ""
|
||||
|
||||
nodeName = ""
|
||||
for child in node:
|
||||
childTag = self.cleanTag(child.tag)
|
||||
if childTag == "name" :
|
||||
nodeName = child.text
|
||||
break
|
||||
elif childTag == "taxonomy":
|
||||
nodeName = getTagFromTaxonomyNode(child)
|
||||
break
|
||||
|
||||
return nodeName
|
||||
|
||||
|
||||
def _makeInternalNode(self, internalNode, depth=0):
|
||||
""" Makes an internal node from an element object that is guranteed to be a parent node.
|
||||
Gets the value of interests like events and appends it to a custom node object that will be passed to PhyloTree to make nodes
|
||||
"""
|
||||
node = {}
|
||||
for child in internalNode:
|
||||
childTag = self.cleanTag(child.tag)
|
||||
if childTag == "clade":
|
||||
continue
|
||||
elif childTag in self.tagsOfInterest:
|
||||
if childTag == "events": # events is nested 1 more level deeper than others
|
||||
key, text = "events", self.cleanTag(child[0].tag)
|
||||
else:
|
||||
key = self.tagsOfInterest[childTag]
|
||||
text = child.text
|
||||
node[key] = text
|
||||
|
||||
|
||||
return self.phyloTree.makeNode(self._getNodeName(internalNode, depth), **node)
|
||||
|
||||
|
||||
def cleanTag(self, tagString):
|
||||
return tagString[self.nameSpaceIndex:]
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
Data providers for tracks visualizations.
|
||||
"""
|
||||
|
||||
import sys
|
||||
import os, sys
|
||||
from math import ceil, log
|
||||
import pkg_resources
|
||||
pkg_resources.require( "bx-python" )
|
||||
@@ -59,6 +59,51 @@ def _convert_between_ucsc_and_ensemble_naming( chrom ):
|
||||
|
||||
def _chrom_naming_matches( chrom1, chrom2 ):
|
||||
return ( chrom1.startswith( 'chr' ) and chrom2.startswith( 'chr' ) ) or ( not chrom1.startswith( 'chr' ) and not chrom2.startswith( 'chr' ) )
|
||||
|
||||
class FeatureLocationIndexDataProvider( object ):
|
||||
'''
|
||||
|
||||
'''
|
||||
|
||||
def __init__( self, converted_dataset ):
|
||||
self.converted_dataset = converted_dataset
|
||||
|
||||
def get_data( self, query ):
|
||||
# Init.
|
||||
textloc_file = open( self.converted_dataset.file_name, 'r' )
|
||||
line_len = int( textloc_file.readline() )
|
||||
file_len = os.path.getsize( self.converted_dataset.file_name )
|
||||
|
||||
# Find query in file using binary search.
|
||||
low = 0
|
||||
high = file_len / line_len
|
||||
while low < high:
|
||||
mid = ( low + high ) // 2
|
||||
position = mid * line_len
|
||||
textloc_file.seek( position )
|
||||
|
||||
# Compare line with query and update low, high.
|
||||
line = textloc_file.readline()
|
||||
print '--', mid, line
|
||||
if line < query:
|
||||
low = mid + 1
|
||||
else:
|
||||
high = mid
|
||||
|
||||
position = low * line_len
|
||||
|
||||
# At right point in file, generate hits.
|
||||
result = [ ]
|
||||
while True:
|
||||
line = textloc_file.readline()
|
||||
if not line.startswith( query ):
|
||||
break
|
||||
if line[ -1: ] == '\n':
|
||||
line = line[ :-1 ]
|
||||
result.append( line.split() )
|
||||
|
||||
textloc_file.close()
|
||||
return result
|
||||
|
||||
class TracksDataProvider( object ):
|
||||
""" Base class for tracks data providers. """
|
||||
@@ -439,6 +484,11 @@ class BedDataProvider( TracksDataProvider ):
|
||||
|
||||
# Score (filter data)
|
||||
if length >= 5 and filter_cols and filter_cols[0] == "Score":
|
||||
# If dataset doesn't have name/strand/thick start/thick end/blocks,
|
||||
# add placeholders. There should be 8 entries if all attributes
|
||||
# are present.
|
||||
payload.extend( [ None for i in range( 8 - len( payload ) ) ] )
|
||||
|
||||
try:
|
||||
payload.append( float( feature[4] ) )
|
||||
except:
|
||||
@@ -575,7 +625,8 @@ class VcfDataProvider( TracksDataProvider ):
|
||||
end = start + len( new_seq )
|
||||
|
||||
# Pack line.
|
||||
payload = [ hash( line ),
|
||||
payload = [
|
||||
hash( line ),
|
||||
start,
|
||||
end,
|
||||
# ID:
|
||||
@@ -584,7 +635,8 @@ class VcfDataProvider( TracksDataProvider ):
|
||||
# TODO? VCF does not have strand, so default to positive.
|
||||
"+",
|
||||
new_seq,
|
||||
float( feature[5] ) ]
|
||||
None if feature[5] == '.' else float( feature[5] )
|
||||
]
|
||||
rval.append(payload)
|
||||
|
||||
return { 'data': rval, 'message': message }
|
||||
@@ -923,79 +975,99 @@ class BBIDataProvider( TracksDataProvider ):
|
||||
# which we use converted_dataset
|
||||
f, bbi = self._get_dataset()
|
||||
|
||||
# If the stats kwarg was provide, we compute overall summary data for the
|
||||
# range defined by start and end but no reduced data. This is currently
|
||||
# used by client to determine the default range.
|
||||
# If stats requested, compute overall summary data for the range
|
||||
# start:endbut no reduced data. This is currently used by client
|
||||
# to determine the default range.
|
||||
if 'stats' in kwargs:
|
||||
summary = bbi.summarize( chrom, start, end, 1 )
|
||||
f.close()
|
||||
if summary is None:
|
||||
return None
|
||||
else:
|
||||
|
||||
min = 0
|
||||
max = 0
|
||||
mean = 0
|
||||
sd = 0
|
||||
if summary is not None:
|
||||
# Does the summary contain any defined values?
|
||||
valid_count = summary.valid_count[0]
|
||||
if summary.valid_count < 1:
|
||||
return None
|
||||
if summary.valid_count > 0:
|
||||
# Compute $\mu \pm 2\sigma$ to provide an estimate for upper and lower
|
||||
# bounds that contain ~95% of the data.
|
||||
mean = summary.sum_data[0] / valid_count
|
||||
var = summary.sum_squares[0] - mean
|
||||
if valid_count > 1:
|
||||
var /= valid_count - 1
|
||||
sd = numpy.sqrt( var )
|
||||
min = summary.min_val[0]
|
||||
max = summary.max_val[0]
|
||||
|
||||
# Compute $\mu \pm 2\sigma$ to provide an estimate for upper and lower
|
||||
# bounds that contain ~95% of the data.
|
||||
mean = summary.sum_data[0] / valid_count
|
||||
var = summary.sum_squares[0] - mean
|
||||
if valid_count > 1:
|
||||
var /= valid_count - 1
|
||||
sd = numpy.sqrt( var )
|
||||
return dict( data=dict( min=min, max=max, mean=mean, sd=sd ) )
|
||||
|
||||
return dict( data=dict( min=summary.min_val[0], max=summary.max_val[0], mean=mean, sd=sd ) )
|
||||
# Sample from region using approximately this many samples.
|
||||
N = 1000
|
||||
|
||||
# The following seems not to work very well, for example it will only return one
|
||||
# data point if the tile is 1280px wide. Not sure what the intent is.
|
||||
def summarize_region( bbi, chrom, start, end, num_points ):
|
||||
'''
|
||||
Returns results from summarizing a region using num_points.
|
||||
NOTE: num_points cannot be greater than end - start or BBI
|
||||
will return None for all positions.s
|
||||
'''
|
||||
result = []
|
||||
|
||||
# The first zoom level for BBI files is 640. If too much is requested, it will look at each block instead
|
||||
# of summaries. The calculation done is: zoom <> (end-start)/num_points/2.
|
||||
# Thus, the optimal number of points is (end-start)/num_points/2 = 640
|
||||
# num_points = (end-start) / 1280
|
||||
#num_points = (end-start) / 1280
|
||||
#if num_points < 1:
|
||||
# num_points = end - start
|
||||
#else:
|
||||
# num_points = min(num_points, 500)
|
||||
|
||||
# For now, we'll do 1000 data points by default. However, the summaries
|
||||
# don't seem to work when a summary pixel corresponds to less than one
|
||||
# datapoint, so we prevent that.
|
||||
|
||||
# FIXME: need to choose the number of points to maximize coverage of the area.
|
||||
# It appears that BBI calculates points using intervals of
|
||||
# floor( num_points / end - start )
|
||||
# In some cases, this prevents sampling near the end of the interval,
|
||||
# especially when (a) the total interval is small ( < 20-30Kb) and (b) the
|
||||
# computed interval size has a large fraction, e.g. 14.7 or 35.8
|
||||
num_points = min( 1000, end - start )
|
||||
|
||||
# HACK to address the FIXME above; should generalize.
|
||||
if end - start <= 2000:
|
||||
num_points = end - start
|
||||
|
||||
summary = bbi.summarize( chrom, start, end, num_points )
|
||||
f.close()
|
||||
|
||||
result = []
|
||||
|
||||
if summary:
|
||||
#mean = summary.sum_data / summary.valid_count
|
||||
# Get summary; this samples at intervals of length
|
||||
# (end - start)/num_points -- i.e. drops any fractional component
|
||||
# of interval length.
|
||||
summary = bbi.summarize( chrom, start, end, num_points )
|
||||
if summary:
|
||||
#mean = summary.sum_data / summary.valid_count
|
||||
|
||||
## Standard deviation by bin, not yet used
|
||||
## var = summary.sum_squares - mean
|
||||
## var /= minimum( valid_count - 1, 1 )
|
||||
## sd = sqrt( var )
|
||||
|
||||
## Standard deviation by bin, not yet used
|
||||
## var = summary.sum_squares - mean
|
||||
## var /= minimum( valid_count - 1, 1 )
|
||||
## sd = sqrt( var )
|
||||
|
||||
pos = start
|
||||
step_size = (end - start) / num_points
|
||||
pos = start
|
||||
step_size = (end - start) / num_points
|
||||
|
||||
for i in range( num_points ):
|
||||
result.append( (pos, float_nan( summary.sum_data[i] / summary.valid_count[i] ) ) )
|
||||
pos += step_size
|
||||
for i in range( num_points ):
|
||||
result.append( (pos, float_nan( summary.sum_data[i] / summary.valid_count[i] ) ) )
|
||||
pos += step_size
|
||||
|
||||
return result
|
||||
|
||||
# Approach is different depending on region size.
|
||||
if end - start < N:
|
||||
# Get values for individual bases in region, including start and end.
|
||||
# To do this, need to increase end to next base and request number of points.
|
||||
num_points = end - start + 1
|
||||
end += 1
|
||||
else:
|
||||
#
|
||||
# The goal is to sample the region between start and end uniformly
|
||||
# using ~N data points. The challenge is that the size of sampled
|
||||
# intervals rarely is full bases, so sampling using N points will
|
||||
# leave the end of the region unsampled due to remainders for each
|
||||
# interval. To recitify this, a new N is calculated based on the
|
||||
# step size that covers as much of the region as possible.
|
||||
#
|
||||
# However, this still leaves some of the region unsampled. This
|
||||
# could be addressed by repeatedly sampling remainder using a
|
||||
# smaller and smaller step_size, but that would require iteratively
|
||||
# going to BBI, which could be time consuming.
|
||||
#
|
||||
|
||||
# Start with N samples.
|
||||
num_points = N
|
||||
step_size = ( end - start ) / num_points
|
||||
# Add additional points to sample in the remainder not covered by
|
||||
# the initial N samples.
|
||||
remainder_start = start + step_size * num_points
|
||||
additional_points = ( end - remainder_start ) / step_size
|
||||
num_points += additional_points
|
||||
|
||||
result = summarize_region( bbi, chrom, start, end, num_points )
|
||||
|
||||
# Cleanup and return.
|
||||
f.close()
|
||||
return { 'data': result }
|
||||
|
||||
class BigBedDataProvider( BBIDataProvider ):
|
||||
|
||||
@@ -109,6 +109,7 @@ class HistoriesController( BaseAPIController, UsesHistoryMixin ):
|
||||
trans.sa_session.add( new_history )
|
||||
trans.sa_session.flush()
|
||||
item = new_history.get_api_value(view='element', value_mapper={'id':trans.security.encode_id})
|
||||
item['url'] = url_for( 'history', id=item['id'] )
|
||||
return item
|
||||
|
||||
@web.expose_api
|
||||
|
||||
@@ -98,7 +98,7 @@ class LibrariesController( BaseAPIController ):
|
||||
rval['url'] = url_for( 'library', id=encoded_id )
|
||||
rval['name'] = name
|
||||
rval['id'] = encoded_id
|
||||
return [ rval ]
|
||||
return rval
|
||||
|
||||
@web.expose_api
|
||||
def delete( self, trans, id, **kwd ):
|
||||
|
||||
@@ -40,10 +40,10 @@ class PermissionsController( BaseAPIController ):
|
||||
role_params = params.get( k + '_in', [] )
|
||||
in_roles = [ trans.sa_session.query( trans.app.model.Role ).get( trans.security.decode_id( x ) ) for x in util.listify( role_params ) ]
|
||||
permissions[ trans.app.security_agent.get_action( v.action ) ] = in_roles
|
||||
trans.app.security_agent.set_all_library_permissions( library, permissions )
|
||||
trans.app.security_agent.set_all_library_permissions( trans, library, permissions )
|
||||
trans.sa_session.refresh( library )
|
||||
# Copy the permissions to the root folder
|
||||
trans.app.security_agent.copy_library_permissions( library, library.root_folder )
|
||||
trans.app.security_agent.copy_library_permissions( trans, library, library.root_folder )
|
||||
message = "Permissions updated for library '%s'." % library.name
|
||||
|
||||
item = library.get_api_value( view='element' )
|
||||
|
||||
@@ -17,7 +17,7 @@ class RoleAPIController( BaseAPIController ):
|
||||
"""
|
||||
rval = []
|
||||
for role in trans.sa_session.query( trans.app.model.Role ).filter( trans.app.model.Role.table.c.deleted == False ):
|
||||
if trans.app.security_agent.ok_to_display( trans.user, role ):
|
||||
if trans.user_is_admin() or trans.app.security_agent.ok_to_display( trans.user, role ):
|
||||
item = role.get_api_value( value_mapper={ 'id': trans.security.encode_id } )
|
||||
encoded_id = trans.security.encode_id( role.id )
|
||||
item['url'] = url_for( 'role', id=encoded_id )
|
||||
@@ -32,7 +32,7 @@ class RoleAPIController( BaseAPIController ):
|
||||
"""
|
||||
role_id = id
|
||||
try:
|
||||
role_id = trans.security.decode_id( role_id )
|
||||
decoded_role_id = trans.security.decode_id( role_id )
|
||||
except TypeError:
|
||||
trans.response.status = 400
|
||||
return "Malformed role id ( %s ) specified, unable to decode." % str( role_id )
|
||||
@@ -40,7 +40,7 @@ class RoleAPIController( BaseAPIController ):
|
||||
role = trans.sa_session.query( trans.app.model.Role ).get( decoded_role_id )
|
||||
except:
|
||||
role = None
|
||||
if not role or not trans.app.security_agent.ok_to_display( trans.user, role ):
|
||||
if not role or not (trans.user_is_admin() or trans.app.security_agent.ok_to_display( trans.user, role )):
|
||||
trans.response.status = 400
|
||||
return "Invalid role id ( %s ) specified." % str( role_id )
|
||||
item = role.get_api_value( view='element', value_mapper={ 'id': trans.security.encode_id } )
|
||||
|
||||
@@ -10,10 +10,12 @@ from galaxy.tools.parameters import visit_input_values, DataToolParameter
|
||||
from galaxy.web.base.controller import BaseAPIController, url_for
|
||||
from galaxy.workflow.modules import module_factory
|
||||
from galaxy.jobs.actions.post import ActionBox
|
||||
from galaxy.model.item_attrs import UsesAnnotations
|
||||
from galaxy.web.controllers.workflow import attach_ordered_steps
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
class WorkflowsAPIController(BaseAPIController):
|
||||
class WorkflowsAPIController(BaseAPIController, UsesAnnotations):
|
||||
@web.expose_api
|
||||
def index(self, trans, **kwd):
|
||||
"""
|
||||
@@ -73,6 +75,16 @@ class WorkflowsAPIController(BaseAPIController):
|
||||
# Eventually, allow regular tool parameters to be inserted and modified at runtime.
|
||||
# p = step.get_required_parameters()
|
||||
item['inputs'] = inputs
|
||||
steps = {}
|
||||
for step in latest_workflow.steps:
|
||||
steps[step.id] = {'id': step.id,
|
||||
'type': step.type,
|
||||
'tool_id': step.tool_id,
|
||||
'input_steps': {}}
|
||||
for conn in step.input_connections:
|
||||
steps[step.id]['input_steps'][conn.input_name] = {'source_step': conn.output_step_id,
|
||||
'step_output': conn.output_name}
|
||||
item['steps'] = steps
|
||||
return item
|
||||
|
||||
@web.expose_api
|
||||
@@ -84,6 +96,17 @@ class WorkflowsAPIController(BaseAPIController):
|
||||
|
||||
However, we will import them if installed_repository_file is specified
|
||||
"""
|
||||
|
||||
# ------------------------------------------------------------------------------- #
|
||||
### RPARK: dictionary containing which workflows to change and edit ###
|
||||
param_map = {};
|
||||
if (payload.has_key('parameters') ):
|
||||
param_map = payload['parameters'];
|
||||
# ------------------------------------------------------------------------------- #
|
||||
|
||||
|
||||
|
||||
|
||||
if 'workflow_id' not in payload:
|
||||
# create new
|
||||
if 'installed_repository_file' in payload:
|
||||
@@ -168,6 +191,17 @@ class WorkflowsAPIController(BaseAPIController):
|
||||
# are not persisted so we need to do it every time)
|
||||
step.module.add_dummy_datasets( connections=step.input_connections )
|
||||
step.state = step.module.state
|
||||
|
||||
####################################################
|
||||
####################################################
|
||||
# RPARK: IF TOOL_NAME IN PARAMETER MAP #
|
||||
if step.tool_id in param_map:
|
||||
change_param = param_map[step.tool_id]['param'];
|
||||
change_value = param_map[step.tool_id]['value'];
|
||||
step.state.inputs[change_param] = change_value;
|
||||
####################################################
|
||||
####################################################
|
||||
|
||||
if step.tool_errors:
|
||||
trans.response.status = 400
|
||||
return "Workflow cannot be run because of validation errors in some steps: %s" % step_errors
|
||||
@@ -220,3 +254,299 @@ class WorkflowsAPIController(BaseAPIController):
|
||||
trans.sa_session.flush()
|
||||
return rval
|
||||
|
||||
# ---------------------------------------------------------------------------------------------- #
|
||||
# ---------------------------------------------------------------------------------------------- #
|
||||
# ---- RPARK EDITS ---- #
|
||||
# ---------------------------------------------------------------------------------------------- #
|
||||
# ---------------------------------------------------------------------------------------------- #
|
||||
@web.expose_api
|
||||
#@web.json
|
||||
def workflow_dict( self, trans, workflow_id, **kwd ):
|
||||
"""
|
||||
GET /api/workflows/{encoded_workflow_id}/download
|
||||
Returns a selected workflow as a json dictionary.
|
||||
"""
|
||||
|
||||
try:
|
||||
stored_workflow = trans.sa_session.query(self.app.model.StoredWorkflow).get(trans.security.decode_id(workflow_id))
|
||||
except Exception,e:
|
||||
return ("Workflow with ID='%s' can not be found\n Exception: %s") % (workflow_id, str( e ))
|
||||
|
||||
# check to see if user has permissions to selected workflow
|
||||
if stored_workflow.user != trans.user and not trans.user_is_admin():
|
||||
if trans.sa_session.query(trans.app.model.StoredWorkflowUserShareAssociation).filter_by(user=trans.user, stored_workflow=stored_workflow).count() == 0:
|
||||
trans.response.status = 400
|
||||
return("Workflow is not owned by or shared with current user")
|
||||
|
||||
ret_dict = self._workflow_to_dict( trans, stored_workflow );
|
||||
return ret_dict
|
||||
|
||||
@web.expose_api
|
||||
def delete( self, trans, id, **kwd ):
|
||||
"""
|
||||
DELETE /api/workflows/{encoded_workflow_id}
|
||||
Deletes a specified workflow
|
||||
Author: rpark
|
||||
|
||||
copied from galaxy.web.controllers.workflows.py (delete)
|
||||
"""
|
||||
workflow_id = id;
|
||||
|
||||
try:
|
||||
stored_workflow = trans.sa_session.query(self.app.model.StoredWorkflow).get(trans.security.decode_id(workflow_id))
|
||||
except Exception,e:
|
||||
return ("Workflow with ID='%s' can not be found\n Exception: %s") % (workflow_id, str( e ))
|
||||
|
||||
# check to see if user has permissions to selected workflow
|
||||
if stored_workflow.user != trans.user and not trans.user_is_admin():
|
||||
if trans.sa_session.query(trans.app.model.StoredWorkflowUserShareAssociation).filter_by(user=trans.user, stored_workflow=stored_workflow).count() == 0:
|
||||
trans.response.status = 400
|
||||
return("Workflow is not owned by or shared with current user")
|
||||
|
||||
#Mark a workflow as deleted
|
||||
stored_workflow.deleted = True
|
||||
trans.sa_session.flush()
|
||||
|
||||
# TODO: Unsure of response message to let api know that a workflow was successfully deleted
|
||||
#return 'OK'
|
||||
return ( "Workflow '%s' successfully deleted" % stored_workflow.name )
|
||||
|
||||
@web.expose_api
|
||||
def import_new_workflow(self, trans, payload, **kwd):
|
||||
"""
|
||||
POST /api/workflows/upload
|
||||
Importing dynamic workflows from the api. Return newly generated workflow id.
|
||||
Author: rpark
|
||||
|
||||
# currently assumes payload['workflow'] is a json representation of a workflow to be inserted into the database
|
||||
"""
|
||||
|
||||
data = payload['workflow'];
|
||||
workflow, missing_tool_tups = self._workflow_from_dict( trans, data, source="API" )
|
||||
|
||||
# galaxy workflow newly created id
|
||||
workflow_id = workflow.id;
|
||||
# api encoded, id
|
||||
encoded_id = trans.security.encode_id(workflow_id);
|
||||
|
||||
# return list
|
||||
rval= [];
|
||||
|
||||
item = workflow.get_api_value(value_mapper={'id':trans.security.encode_id})
|
||||
item['url'] = url_for('workflow', id=encoded_id)
|
||||
|
||||
rval.append(item);
|
||||
|
||||
return item;
|
||||
|
||||
def _workflow_from_dict( self, trans, data, source=None ):
|
||||
"""
|
||||
RPARK: copied from galaxy.web.controllers.workflows.py
|
||||
Creates a workflow from a dict. Created workflow is stored in the database and returned.
|
||||
"""
|
||||
# Put parameters in workflow mode
|
||||
trans.workflow_building_mode = True
|
||||
# Create new workflow from incoming dict
|
||||
workflow = model.Workflow()
|
||||
# If there's a source, put it in the workflow name.
|
||||
if source:
|
||||
name = "%s (imported from %s)" % ( data['name'], source )
|
||||
else:
|
||||
name = data['name']
|
||||
workflow.name = name
|
||||
# Assume no errors until we find a step that has some
|
||||
workflow.has_errors = False
|
||||
# Create each step
|
||||
steps = []
|
||||
# The editor will provide ids for each step that we don't need to save,
|
||||
# but do need to use to make connections
|
||||
steps_by_external_id = {}
|
||||
# Keep track of tools required by the workflow that are not available in
|
||||
# the local Galaxy instance. Each tuple in the list of missing_tool_tups
|
||||
# will be ( tool_id, tool_name, tool_version ).
|
||||
missing_tool_tups = []
|
||||
# First pass to build step objects and populate basic values
|
||||
for key, step_dict in data[ 'steps' ].iteritems():
|
||||
# Create the model class for the step
|
||||
step = model.WorkflowStep()
|
||||
steps.append( step )
|
||||
steps_by_external_id[ step_dict['id' ] ] = step
|
||||
# FIXME: Position should be handled inside module
|
||||
step.position = step_dict['position']
|
||||
module = module_factory.from_dict( trans, step_dict, secure=False )
|
||||
if module.type == 'tool' and module.tool is None:
|
||||
# A required tool is not available in the local Galaxy instance.
|
||||
missing_tool_tup = ( step_dict[ 'tool_id' ], step_dict[ 'name' ], step_dict[ 'tool_version' ] )
|
||||
if missing_tool_tup not in missing_tool_tups:
|
||||
missing_tool_tups.append( missing_tool_tup )
|
||||
module.save_to_step( step )
|
||||
if step.tool_errors:
|
||||
workflow.has_errors = True
|
||||
# Stick this in the step temporarily
|
||||
step.temp_input_connections = step_dict['input_connections']
|
||||
# Save step annotation.
|
||||
annotation = step_dict[ 'annotation' ]
|
||||
#if annotation:
|
||||
#annotation = sanitize_html( annotation, 'utf-8', 'text/html' )
|
||||
# ------------------------------------------ #
|
||||
# RPARK REMOVING: user annotation b/c of API
|
||||
#self.add_item_annotation( trans.sa_session, trans.get_user(), step, annotation )
|
||||
# ------------------------------------------ #
|
||||
# Unpack and add post-job actions.
|
||||
post_job_actions = step_dict.get( 'post_job_actions', {} )
|
||||
for name, pja_dict in post_job_actions.items():
|
||||
pja = PostJobAction( pja_dict[ 'action_type' ],
|
||||
step, pja_dict[ 'output_name' ],
|
||||
pja_dict[ 'action_arguments' ] )
|
||||
# Second pass to deal with connections between steps
|
||||
for step in steps:
|
||||
# Input connections
|
||||
for input_name, conn_dict in step.temp_input_connections.iteritems():
|
||||
if conn_dict:
|
||||
conn = model.WorkflowStepConnection()
|
||||
conn.input_step = step
|
||||
conn.input_name = input_name
|
||||
conn.output_name = conn_dict['output_name']
|
||||
conn.output_step = steps_by_external_id[ conn_dict['id'] ]
|
||||
del step.temp_input_connections
|
||||
# Order the steps if possible
|
||||
attach_ordered_steps( workflow, steps )
|
||||
# Connect up
|
||||
stored = model.StoredWorkflow()
|
||||
stored.name = workflow.name
|
||||
workflow.stored_workflow = stored
|
||||
stored.latest_workflow = workflow
|
||||
stored.user = trans.user
|
||||
# Persist
|
||||
trans.sa_session.add( stored )
|
||||
trans.sa_session.flush()
|
||||
return stored, missing_tool_tups
|
||||
|
||||
def _workflow_to_dict( self, trans, stored ):
|
||||
"""
|
||||
RPARK: copied from galaxy.web.controllers.workflows.py
|
||||
Converts a workflow to a dict of attributes suitable for exporting.
|
||||
"""
|
||||
workflow = stored.latest_workflow
|
||||
|
||||
### ----------------------------------- ###
|
||||
## RPARK EDIT ##
|
||||
workflow_annotation = self.get_item_annotation_obj( trans.sa_session, trans.user, stored )
|
||||
annotation_str = ""
|
||||
if workflow_annotation:
|
||||
annotation_str = workflow_annotation.annotation
|
||||
### ----------------------------------- ###
|
||||
|
||||
|
||||
# Pack workflow data into a dictionary and return
|
||||
data = {}
|
||||
data['a_galaxy_workflow'] = 'true' # Placeholder for identifying galaxy workflow
|
||||
data['format-version'] = "0.1"
|
||||
data['name'] = workflow.name
|
||||
### ----------------------------------- ###
|
||||
## RPARK EDIT ##
|
||||
data['annotation'] = annotation_str
|
||||
### ----------------------------------- ###
|
||||
|
||||
data['steps'] = {}
|
||||
# For each step, rebuild the form and encode the state
|
||||
for step in workflow.steps:
|
||||
# Load from database representation
|
||||
module = module_factory.from_workflow_step( trans, step )
|
||||
|
||||
### ----------------------------------- ###
|
||||
## RPARK EDIT ##
|
||||
# Get user annotation.
|
||||
step_annotation = self.get_item_annotation_obj(trans.sa_session, trans.user, step )
|
||||
annotation_str = ""
|
||||
if step_annotation:
|
||||
annotation_str = step_annotation.annotation
|
||||
### ----------------------------------- ###
|
||||
|
||||
# Step info
|
||||
step_dict = {
|
||||
'id': step.order_index,
|
||||
'type': module.type,
|
||||
'tool_id': module.get_tool_id(),
|
||||
'tool_version' : step.tool_version,
|
||||
'name': module.get_name(),
|
||||
'tool_state': module.get_state( secure=False ),
|
||||
'tool_errors': module.get_errors(),
|
||||
## 'data_inputs': module.get_data_inputs(),
|
||||
## 'data_outputs': module.get_data_outputs(),
|
||||
|
||||
### ----------------------------------- ###
|
||||
## RPARK EDIT ##
|
||||
'annotation' : annotation_str
|
||||
### ----------------------------------- ###
|
||||
|
||||
}
|
||||
# Add post-job actions to step dict.
|
||||
if module.type == 'tool':
|
||||
pja_dict = {}
|
||||
for pja in step.post_job_actions:
|
||||
pja_dict[pja.action_type+pja.output_name] = dict( action_type = pja.action_type,
|
||||
output_name = pja.output_name,
|
||||
action_arguments = pja.action_arguments )
|
||||
step_dict[ 'post_job_actions' ] = pja_dict
|
||||
# Data inputs
|
||||
step_dict['inputs'] = []
|
||||
if module.type == "data_input":
|
||||
# Get input dataset name; default to 'Input Dataset'
|
||||
name = module.state.get( 'name', 'Input Dataset')
|
||||
step_dict['inputs'].append( { "name" : name, "description" : annotation_str } )
|
||||
else:
|
||||
# Step is a tool and may have runtime inputs.
|
||||
for name, val in module.state.inputs.items():
|
||||
input_type = type( val )
|
||||
if input_type == RuntimeValue:
|
||||
step_dict['inputs'].append( { "name" : name, "description" : "runtime parameter for tool %s" % module.get_name() } )
|
||||
elif input_type == dict:
|
||||
# Input type is described by a dict, e.g. indexed parameters.
|
||||
for partname, partval in val.items():
|
||||
if type( partval ) == RuntimeValue:
|
||||
step_dict['inputs'].append( { "name" : name, "description" : "runtime parameter for tool %s" % module.get_name() } )
|
||||
# User outputs
|
||||
step_dict['user_outputs'] = []
|
||||
"""
|
||||
module_outputs = module.get_data_outputs()
|
||||
step_outputs = trans.sa_session.query( WorkflowOutput ).filter( step=step )
|
||||
for output in step_outputs:
|
||||
name = output.output_name
|
||||
annotation = ""
|
||||
for module_output in module_outputs:
|
||||
if module_output.get( 'name', None ) == name:
|
||||
output_type = module_output.get( 'extension', '' )
|
||||
break
|
||||
data['outputs'][name] = { 'name' : name, 'annotation' : annotation, 'type' : output_type }
|
||||
"""
|
||||
|
||||
# All step outputs
|
||||
step_dict['outputs'] = []
|
||||
if type( module ) is ToolModule:
|
||||
for output in module.get_data_outputs():
|
||||
step_dict['outputs'].append( { 'name' : output['name'], 'type' : output['extensions'][0] } )
|
||||
# Connections
|
||||
input_connections = step.input_connections
|
||||
if step.type is None or step.type == 'tool':
|
||||
# Determine full (prefixed) names of valid input datasets
|
||||
data_input_names = {}
|
||||
def callback( input, value, prefixed_name, prefixed_label ):
|
||||
if isinstance( input, DataToolParameter ):
|
||||
data_input_names[ prefixed_name ] = True
|
||||
visit_input_values( module.tool.inputs, module.state.inputs, callback )
|
||||
# Filter
|
||||
# FIXME: this removes connection without displaying a message currently!
|
||||
input_connections = [ conn for conn in input_connections if conn.input_name in data_input_names ]
|
||||
# Encode input connections as dictionary
|
||||
input_conn_dict = {}
|
||||
for conn in input_connections:
|
||||
input_conn_dict[ conn.input_name ] = \
|
||||
dict( id=conn.output_step.order_index, output_name=conn.output_name )
|
||||
step_dict['input_connections'] = input_conn_dict
|
||||
# Position
|
||||
step_dict['position'] = step.position
|
||||
# Add to return value
|
||||
data['steps'][step.order_index] = step_dict
|
||||
return data
|
||||
|
||||
|
||||
@@ -151,6 +151,11 @@ def app_factory( global_conf, **kwargs ):
|
||||
webapp.api_mapper.resource_with_deleted( 'history', 'histories', path_prefix='/api' )
|
||||
#webapp.api_mapper.connect( 'run_workflow', '/api/workflow/{workflow_id}/library/{library_id}', controller='workflows', action='run', workflow_id=None, library_id=None, conditions=dict(method=["GET"]) )
|
||||
|
||||
# "POST /api/workflows/import" => ``workflows.import_workflow()``.
|
||||
# Defines a named route "import_workflow".
|
||||
webapp.api_mapper.connect("import_workflow", "/api/workflows/upload", controller="workflows", action="import_new_workflow", conditions=dict(method=["POST"]))
|
||||
webapp.api_mapper.connect("workflow_dict", '/api/workflows/download/{workflow_id}', controller='workflows', action='workflow_dict', conditions=dict(method=['GET']))
|
||||
|
||||
webapp.finalize_config()
|
||||
# Wrap the webapp in some useful middleware
|
||||
if kwargs.get( 'middleware', True ):
|
||||
|
||||
@@ -374,7 +374,7 @@ class AdminToolshed( AdminGalaxy ):
|
||||
def browse_tool_shed( self, trans, **kwd ):
|
||||
tool_shed_url = kwd[ 'tool_shed_url' ]
|
||||
galaxy_url = url_for( '/', qualified=True )
|
||||
url = '%srepository/browse_valid_categories?galaxy_url=%s&webapp=galaxy' % ( tool_shed_url, galaxy_url )
|
||||
url = url_join( tool_shed_url, 'repository/browse_valid_categories?galaxy_url=%s&webapp=galaxy' % ( galaxy_url ) )
|
||||
return trans.response.send_redirect( url )
|
||||
@web.expose
|
||||
@web.require_admin
|
||||
@@ -392,8 +392,9 @@ class AdminToolshed( AdminGalaxy ):
|
||||
# Send a request to the relevant tool shed to see if there are any updates.
|
||||
repository = get_repository( trans, kwd[ 'id' ] )
|
||||
tool_shed_url = get_url_from_repository_tool_shed( trans.app, repository )
|
||||
url = '%s/repository/check_for_updates?galaxy_url=%s&name=%s&owner=%s&changeset_revision=%s&webapp=galaxy' % \
|
||||
( tool_shed_url, url_for( '/', qualified=True ), repository.name, repository.owner, repository.changeset_revision )
|
||||
url = url_join( tool_shed_url,
|
||||
'repository/check_for_updates?galaxy_url=%s&name=%s&owner=%s&changeset_revision=%s&webapp=galaxy' % \
|
||||
( url_for( '/', qualified=True ), repository.name, repository.owner, repository.changeset_revision ) )
|
||||
return trans.response.send_redirect( url )
|
||||
@web.expose
|
||||
@web.require_admin
|
||||
@@ -467,14 +468,14 @@ class AdminToolshed( AdminGalaxy ):
|
||||
def find_tools_in_tool_shed( self, trans, **kwd ):
|
||||
tool_shed_url = kwd[ 'tool_shed_url' ]
|
||||
galaxy_url = url_for( '/', qualified=True )
|
||||
url = '%srepository/find_tools?galaxy_url=%s&webapp=galaxy' % ( tool_shed_url, galaxy_url )
|
||||
url = url_join( tool_shed_url, 'repository/find_tools?galaxy_url=%s&webapp=galaxy' % galaxy_url )
|
||||
return trans.response.send_redirect( url )
|
||||
@web.expose
|
||||
@web.require_admin
|
||||
def find_workflows_in_tool_shed( self, trans, **kwd ):
|
||||
tool_shed_url = kwd[ 'tool_shed_url' ]
|
||||
galaxy_url = url_for( '/', qualified=True )
|
||||
url = '%srepository/find_workflows?galaxy_url=%s&webapp=galaxy' % ( tool_shed_url, galaxy_url )
|
||||
url = url_join( tool_shed_url, 'repository/find_workflows?galaxy_url=%s&webapp=galaxy' % galaxy_url )
|
||||
return trans.response.send_redirect( url )
|
||||
def generate_tool_path( self, repository_clone_url, changeset_revision ):
|
||||
"""
|
||||
@@ -489,7 +490,7 @@ class AdminToolshed( AdminGalaxy ):
|
||||
tool_shed_url = items[ 0 ]
|
||||
repo_path = items[ 1 ]
|
||||
tool_shed_url = clean_tool_shed_url( tool_shed_url )
|
||||
return '%s/repos%s/%s' % ( tool_shed_url, repo_path, changeset_revision )
|
||||
return url_join( tool_shed_url, 'repos', repo_path, changeset_revision )
|
||||
@web.json
|
||||
@web.require_admin
|
||||
def get_file_contents( self, trans, file_path ):
|
||||
@@ -634,8 +635,9 @@ class AdminToolshed( AdminGalaxy ):
|
||||
tool_shed_repository,
|
||||
trans.model.ToolShedRepository.installation_status.SETTING_TOOL_VERSIONS )
|
||||
tool_shed_url = get_url_from_repository_tool_shed( trans.app, tool_shed_repository )
|
||||
url = '%s/repository/get_tool_versions?name=%s&owner=%s&changeset_revision=%s&webapp=galaxy' % \
|
||||
( tool_shed_url, tool_shed_repository.name, tool_shed_repository.owner, tool_shed_repository.changeset_revision )
|
||||
url = url_join( tool_shed_url,
|
||||
'/repository/get_tool_versions?name=%s&owner=%s&changeset_revision=%s&webapp=galaxy' % \
|
||||
( tool_shed_repository.name, tool_shed_repository.owner, tool_shed_repository.changeset_revision ) )
|
||||
response = urllib2.urlopen( url )
|
||||
text = response.read()
|
||||
response.close()
|
||||
@@ -954,7 +956,9 @@ class AdminToolshed( AdminGalaxy ):
|
||||
repository_ids = kwd.get( 'repository_ids', None )
|
||||
changeset_revisions = kwd.get( 'changeset_revisions', None )
|
||||
# Get the information necessary to install each repository.
|
||||
url = '%srepository/get_repository_information?repository_ids=%s&changeset_revisions=%s&webapp=galaxy' % ( tool_shed_url, repository_ids, changeset_revisions )
|
||||
url = url_join( tool_shed_url,
|
||||
'repository/get_repository_information?repository_ids=%s&changeset_revisions=%s&webapp=galaxy' % \
|
||||
( repository_ids, changeset_revisions ) )
|
||||
response = urllib2.urlopen( url )
|
||||
raw_text = response.read()
|
||||
response.close()
|
||||
@@ -1097,8 +1101,9 @@ class AdminToolshed( AdminGalaxy ):
|
||||
name = repo_info_dict.keys()[ 0 ]
|
||||
repo_info_tuple = repo_info_dict[ name ]
|
||||
description, repository_clone_url, changeset_revision, ctx_rev, repository_owner, tool_dependencies = repo_info_tuple
|
||||
url = '%srepository/get_readme?name=%s&owner=%s&changeset_revision=%s&webapp=galaxy' % \
|
||||
( tool_shed_url, name, repository_owner, changeset_revision )
|
||||
url = url_join( tool_shed_url,
|
||||
'repository/get_readme?name=%s&owner=%s&changeset_revision=%s&webapp=galaxy' % \
|
||||
( name, repository_owner, changeset_revision ) )
|
||||
response = urllib2.urlopen( url )
|
||||
raw_text = response.read()
|
||||
response.close()
|
||||
@@ -1273,8 +1278,9 @@ class AdminToolshed( AdminGalaxy ):
|
||||
tool_shed = get_tool_shed_from_clone_url( repository_clone_url )
|
||||
# Get all previous change set revisions from the tool shed for the repository back to, but excluding, the previous valid changeset
|
||||
# revision to see if it was previously installed using one of them.
|
||||
url = '%s/repository/previous_changeset_revisions?galaxy_url=%s&name=%s&owner=%s&changeset_revision=%s&webapp=galaxy' % \
|
||||
( tool_shed_url, url_for( '/', qualified=True ), repository_name, repository_owner, changeset_revision )
|
||||
url = url_join( tool_shed_url,
|
||||
'repository/previous_changeset_revisions?galaxy_url=%s&name=%s&owner=%s&changeset_revision=%s&webapp=galaxy' % \
|
||||
( url_for( '/', qualified=True ), repository_name, repository_owner, changeset_revision ) )
|
||||
response = urllib2.urlopen( url )
|
||||
text = response.read()
|
||||
response.close()
|
||||
@@ -1350,8 +1356,9 @@ class AdminToolshed( AdminGalaxy ):
|
||||
# Get the tool_versions from the tool shed for each tool in the installed change set.
|
||||
repository = get_repository( trans, kwd[ 'id' ] )
|
||||
tool_shed_url = get_url_from_repository_tool_shed( trans.app, repository )
|
||||
url = '%s/repository/get_tool_versions?name=%s&owner=%s&changeset_revision=%s&webapp=galaxy' % \
|
||||
( tool_shed_url, repository.name, repository.owner, repository.changeset_revision )
|
||||
url = url_join( tool_shed_url,
|
||||
'repository/get_tool_versions?name=%s&owner=%s&changeset_revision=%s&webapp=galaxy' % \
|
||||
( repository.name, repository.owner, repository.changeset_revision ) )
|
||||
response = urllib2.urlopen( url )
|
||||
text = response.read()
|
||||
response.close()
|
||||
@@ -1522,7 +1529,7 @@ class AdminToolshed( AdminGalaxy ):
|
||||
def __generate_clone_url( self, trans, repository ):
|
||||
"""Generate the URL for cloning a repository."""
|
||||
tool_shed_url = get_url_from_repository_tool_shed( trans.app, repository )
|
||||
return '%s/repos/%s/%s' % ( tool_shed_url, repository.owner, repository.name )
|
||||
return url_join( tool_shed_url, 'repos', repository.owner, repository.name )
|
||||
|
||||
## ---- Utility methods -------------------------------------------------------
|
||||
|
||||
|
||||
@@ -75,7 +75,7 @@ class DataAdmin( BaseUIController ):
|
||||
@web.require_admin
|
||||
def add_genome( self, trans, **kwd ):
|
||||
if trans.app.config.get_bool( 'enable_beta_job_managers', False ) == False:
|
||||
return trans.fill_template( '/admin/data_admin/betajob.mako' )
|
||||
return trans.fill_template( '/admin/data_admin/generic_error.mako', message='This feature requires that enable_beta_job_managers be set to True in your Galaxy configuration.' )
|
||||
dbkeys = trans.ucsc_builds
|
||||
ensemblkeys = trans.ensembl_builds
|
||||
ncbikeys = trans.ncbi_builds
|
||||
@@ -137,9 +137,10 @@ class DataAdmin( BaseUIController ):
|
||||
dbkey = build.split( ': ' )[0]
|
||||
longname = build.split( ': ' )[-1]
|
||||
url = 'http://togows.dbcls.jp/entry/ncbi-nucleotide/%s.fasta' % dbkey
|
||||
elif source == 'Broad':
|
||||
dbkey = params.get('broad_dbkey', '')[0]
|
||||
url = 'ftp://ftp.broadinstitute.org/pub/seq/references/%s.fasta' % dbkey
|
||||
elif source == 'URL':
|
||||
dbkey = params.get( 'url_dbkey', '' )
|
||||
url = params.get( 'url', None )
|
||||
longname = params.get( 'longname', None )
|
||||
elif source == 'UCSC':
|
||||
longname = None
|
||||
for build in trans.ucsc_builds:
|
||||
@@ -147,7 +148,8 @@ class DataAdmin( BaseUIController ):
|
||||
dbkey = build[0]
|
||||
longname = build[1]
|
||||
break
|
||||
assert dbkey is not '?', 'That build was not found'
|
||||
if dbkey == '?':
|
||||
return trans.fill_template( '/admin/data_admin/generic_error.mako', message='An invalid build was specified.' )
|
||||
ftp = ftplib.FTP('hgdownload.cse.ucsc.edu')
|
||||
ftp.login('anonymous', trans.get_user().email)
|
||||
checker = []
|
||||
@@ -188,7 +190,8 @@ class DataAdmin( BaseUIController ):
|
||||
dbkeys=trans.ucsc_builds )
|
||||
elif source == 'Ensembl':
|
||||
dbkey = params.get( 'ensembl_dbkey', None )
|
||||
assert dbkey is not '?', 'That build was not found'
|
||||
if dbkey == '?':
|
||||
return trans.fill_template( '/admin/data_admin/generic_error.mako', message='An invalid build was specified.' )
|
||||
for build in trans.ensembl_builds:
|
||||
if build[ 'dbkey' ] == dbkey:
|
||||
dbkey = build[ 'dbkey' ]
|
||||
@@ -198,7 +201,9 @@ class DataAdmin( BaseUIController ):
|
||||
break
|
||||
url = 'ftp://ftp.ensembl.org/pub/release-%s/fasta/%s/dna/%s.%s.%s.dna.toplevel.fa.gz' % ( release, pathname.lower(), pathname, dbkey, release )
|
||||
else:
|
||||
raise ValueError, 'Somehow an invalid data source was specified.'
|
||||
return trans.fill_template( '/admin/data_admin/generic_error.mako', message='An invalid data source was specified.' )
|
||||
if url is None:
|
||||
return trans.fill_template( '/admin/data_admin/generic_error.mako', message='Unable to generate a valid URL with the specified parameters.' )
|
||||
params = dict( protocol='http', name=dbkey, datatype='fasta', url=url, user=trans.user.id )
|
||||
jobid = trans.app.job_manager.deferred_job_queue.plugins['GenomeTransferPlugin'].create_job( trans, url, dbkey, longname, indexers )
|
||||
chainjob = []
|
||||
@@ -245,7 +250,8 @@ class DataAdmin( BaseUIController ):
|
||||
sa = trans.app.model.context.current
|
||||
if jobtype == 'liftover':
|
||||
job = sa.query( model.TransferJob ).filter_by( id=jobid ).first()
|
||||
joblabel = 'Download liftOver'
|
||||
liftover = trans.app.job_manager.deferred_job_queue.plugins['LiftOverTransferPlugin'].get_job_status( jobid )
|
||||
joblabel = 'Download liftOver (%s to %s)' % ( liftover.params[ 'from_genome' ], liftover.params[ 'to_genome' ] )
|
||||
elif jobtype == 'transfer':
|
||||
job = sa.query( model.TransferJob ).filter_by( id=jobid ).first()
|
||||
joblabel = 'Download Genome'
|
||||
|
||||
@@ -203,12 +203,12 @@ class DatasetInterface( BaseUIController, UsesAnnotations, UsesHistoryMixin, Use
|
||||
job_id=job.id,
|
||||
job_tool_id=job.tool_id,
|
||||
job_command_line=job.command_line,
|
||||
job_stderr=job.stderr,
|
||||
job_stdout=job.stdout,
|
||||
job_info=job.info,
|
||||
job_traceback=job.traceback,
|
||||
job_stderr=util.unicodify( job.stderr ),
|
||||
job_stdout=util.unicodify( job.stdout ),
|
||||
job_info=util.unicodify( job.info ),
|
||||
job_traceback=util.unicodify( job.traceback ),
|
||||
email=email,
|
||||
message=message )
|
||||
message=util.unicodify( message ) )
|
||||
frm = to_address
|
||||
# Check email a bit
|
||||
email = email.strip()
|
||||
@@ -644,7 +644,10 @@ class DatasetInterface( BaseUIController, UsesAnnotations, UsesHistoryMixin, Use
|
||||
dataset = self.get_dataset( trans, id, False, True )
|
||||
if not dataset:
|
||||
web.httpexceptions.HTTPNotFound()
|
||||
return self.get_item_annotation_str( trans.sa_session, trans.user, dataset )
|
||||
annotation = self.get_item_annotation_str( trans.sa_session, trans.user, dataset )
|
||||
if annotation and isinstance( annotation, unicode ):
|
||||
annotation = annotation.encode( 'ascii', 'replace' ) #paste needs ascii here
|
||||
return annotation
|
||||
|
||||
@web.expose
|
||||
def display_at( self, trans, dataset_id, filename=None, **kwd ):
|
||||
|
||||
@@ -1752,6 +1752,7 @@ class LibraryCommon( BaseUIController, UsesFormDefinitionsMixin ):
|
||||
if action == 'zip':
|
||||
# Can't use mkstemp - the file must not exist first
|
||||
tmpd = tempfile.mkdtemp()
|
||||
util.umask_fix_perms( tmpd, trans.app.config.umask, 0777, self.app.config.gid )
|
||||
tmpf = os.path.join( tmpd, 'library_download.' + action )
|
||||
if ziptype == '64' and trans.app.config.upstream_gzip:
|
||||
archive = zipfile.ZipFile( tmpf, 'w', zipfile.ZIP_STORED, True )
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
import pkg_resources
|
||||
pkg_resources.require( "bx-python" )
|
||||
|
||||
from galaxy.util.json import to_json_string, from_json_string
|
||||
from galaxy.web.base.controller import *
|
||||
from galaxy.visualization.phyloviz.phyloviz_dataprovider import Phyloviz_DataProvider
|
||||
|
||||
|
||||
class PhyloVizController( BaseUIController, UsesVisualizationMixin, UsesHistoryDatasetAssociationMixin, SharableMixin ):
|
||||
"""
|
||||
Controller for phyloViz browser interface.
|
||||
"""
|
||||
def __init__(self, app ):
|
||||
BaseUIController.__init__( self, app )
|
||||
|
||||
@web.expose
|
||||
@web.require_login()
|
||||
def index( self, trans, dataset_id = None, **kwargs ):
|
||||
"""
|
||||
The index method is called using phyloviz/ with a dataset id passed in.
|
||||
The relevant data set is then retrieved via get_json_from_datasetId which interfaces with the parser
|
||||
The json representation of the phylogenetic tree along with the config is then written in the .mako template and passed back to the user
|
||||
"""
|
||||
json, config = self.get_json_from_datasetId(trans, dataset_id)
|
||||
config["saved_visualization"] = False
|
||||
return trans.fill_template( "visualization/phyloviz.mako", data = json, config=config)
|
||||
|
||||
|
||||
@web.expose
|
||||
def visualization(self, trans, id):
|
||||
"""
|
||||
Called using a viz_id (id) to retrieved stored visualization data (in json format) and all the viz_config
|
||||
"""
|
||||
viz = self.get_visualization(trans, id)
|
||||
config = self.get_visualization_config(trans, viz)
|
||||
config["saved_visualization"] = True
|
||||
data = config["root"]
|
||||
|
||||
return trans.fill_template( "visualization/phyloviz.mako", data = data, config=config)
|
||||
|
||||
|
||||
@web.expose
|
||||
@web.json
|
||||
def load_visualization_json(self, trans, viz_id):
|
||||
"""
|
||||
Though not used in current implementation, this provides user with a convenient method to retrieve the viz_data & viz_config via json.
|
||||
"""
|
||||
viz = self.get_visualization(trans, viz_id)
|
||||
viz_config = self.get_visualization_config(trans, viz)
|
||||
viz_config["saved_visualization"] = True
|
||||
return {
|
||||
"data" : viz_config["root"],
|
||||
"config" : viz_config
|
||||
}
|
||||
|
||||
|
||||
@web.expose
|
||||
@web.json
|
||||
def getJsonData(self, trans, dataset_id, treeIndex=0):
|
||||
"""
|
||||
Method to retrieve data asynchronously via json format. Retriving from here rather than
|
||||
making a direct datasets/ call allows for some processing and event capturing
|
||||
"""
|
||||
treeIndex = int(treeIndex)
|
||||
json, config = self.get_json_from_datasetId(trans, dataset_id, treeIndex)
|
||||
packedJson = {
|
||||
"data" : json,
|
||||
"config" : config
|
||||
}
|
||||
|
||||
return packedJson
|
||||
|
||||
|
||||
def get_json_from_datasetId(self, trans, dataset_id, treeIndex=0):
|
||||
"""
|
||||
For interfacing phyloviz controllers with phyloviz visualization data provider (parsers)
|
||||
"""
|
||||
dataset = self.get_dataset(trans, dataset_id)
|
||||
fileExt, filepath = dataset.ext, dataset.file_name # .name stores the name of the dataset from the orginal upload
|
||||
json, config = "", {} # config contains properties of the tree and file
|
||||
|
||||
if fileExt == "json":
|
||||
something, json = self.get_data(dataset)
|
||||
else:
|
||||
try:
|
||||
pd = Phyloviz_DataProvider()
|
||||
json, config = pd.parseFile(filepath, fileExt)
|
||||
json = json[treeIndex]
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
config["title"] = dataset.display_name()
|
||||
config["ext"] = fileExt
|
||||
config["dataset_id"] = dataset_id
|
||||
config["treeIndex"] = treeIndex
|
||||
|
||||
return json, config
|
||||
@@ -345,6 +345,20 @@ class TracksController( BaseUIController, UsesVisualizationMixin, UsesHistoryDat
|
||||
|
||||
# Have data if we get here
|
||||
return { "status": messages.DATA, "valid_chroms": valid_chroms }
|
||||
|
||||
@web.json
|
||||
def feature_loc( self, trans, hda_ldda, dataset_id, query ):
|
||||
"""
|
||||
Returns features, locations in dataset that match query. Format is a
|
||||
list of features; each feature is a list itself: [name, location]
|
||||
"""
|
||||
dataset = self.get_hda_or_ldda( trans, hda_ldda, dataset_id )
|
||||
converted_dataset = dataset.get_converted_dataset( trans, "fli" )
|
||||
data_provider = FeatureLocationIndexDataProvider( converted_dataset=converted_dataset )
|
||||
if data_provider:
|
||||
return data_provider.get_data( query )
|
||||
else:
|
||||
return 'None'
|
||||
|
||||
@web.json
|
||||
def data( self, trans, hda_ldda, dataset_id, chrom, low, high, start_val=0, max_vals=None, **kwargs ):
|
||||
@@ -373,7 +387,21 @@ class TracksController( BaseUIController, UsesVisualizationMixin, UsesHistoryDat
|
||||
return return_message
|
||||
|
||||
extra_info = None
|
||||
if 'index' in data_sources and data_sources['index']['name'] == "summary_tree" and kwargs.get("mode", "Auto") == "Auto":
|
||||
mode = kwargs.get( "mode", "Auto" )
|
||||
# Handle histogram mode uniquely for now:
|
||||
if mode == "Coverage":
|
||||
# Get summary using minimal cutoffs.
|
||||
tracks_dataset_type = data_sources['index']['name']
|
||||
converted_dataset = dataset.get_converted_dataset( trans, tracks_dataset_type )
|
||||
indexer = get_data_provider( tracks_dataset_type )( converted_dataset, dataset )
|
||||
summary = indexer.get_data( chrom, low, high, resolution=kwargs[ 'resolution' ], detail_cutoff=0, draw_cutoff=0 )
|
||||
if summary == "detail":
|
||||
# Use maximum level of detail--2--to get summary data no matter the resolution.
|
||||
summary = indexer.get_data( chrom, low, high, resolution=kwargs[ 'resolution' ], level=2, detail_cutoff=0, draw_cutoff=0 )
|
||||
frequencies, max_v, avg_v, delta = summary
|
||||
return { 'dataset_type': tracks_dataset_type, 'data': frequencies, 'max': max_v, 'avg': avg_v, 'delta': delta }
|
||||
|
||||
if 'index' in data_sources and data_sources['index']['name'] == "summary_tree" and mode == "Auto":
|
||||
# Only check for summary_tree if it's Auto mode (which is the default)
|
||||
#
|
||||
# Have to choose between indexer and data provider
|
||||
|
||||
@@ -5,7 +5,7 @@ from galaxy.web.framework.helpers import time_ago, grids, iff
|
||||
from galaxy.util.sanitize_html import sanitize_html
|
||||
|
||||
class VisualizationListGrid( grids.Grid ):
|
||||
def get_link( item ):
|
||||
def get_url_args( item ):
|
||||
"""
|
||||
Returns dictionary used to create item link.
|
||||
"""
|
||||
@@ -16,6 +16,10 @@ class VisualizationListGrid( grids.Grid ):
|
||||
action = "paramamonster"
|
||||
elif item.type == "circster":
|
||||
action = "circster"
|
||||
elif item.type == "phyloviz":
|
||||
# Support phyloviz
|
||||
controller = "phyloviz"
|
||||
action = "visualization"
|
||||
return dict( controller=controller, action=action, id=item.id )
|
||||
|
||||
# Grid definition
|
||||
@@ -24,7 +28,7 @@ class VisualizationListGrid( grids.Grid ):
|
||||
default_sort_key = "-update_time"
|
||||
default_filter = dict( title="All", deleted="False", tags="All", sharing="All" )
|
||||
columns = [
|
||||
grids.TextColumn( "Title", key="title", attach_popup=True, link=get_link ),
|
||||
grids.TextColumn( "Title", key="title", attach_popup=True, link=get_url_args ),
|
||||
grids.TextColumn( "Type", key="type" ),
|
||||
grids.TextColumn( "Dbkey", key="dbkey" ),
|
||||
grids.IndividualTagsColumn( "Tags", key="tags", model_tag_association_class=model.VisualizationTagAssociation, filterable="advanced", grid_name="VisualizationListGrid" ),
|
||||
@@ -42,7 +46,7 @@ class VisualizationListGrid( grids.Grid ):
|
||||
grids.GridAction( "Create new visualization", dict( action='create' ) )
|
||||
]
|
||||
operations = [
|
||||
grids.GridOperation( "View/Edit", allow_multiple=False, url_args=dict( controller='tracks', action='browser' ) ),
|
||||
grids.GridOperation( "View/Edit", allow_multiple=False, url_args=get_url_args ),
|
||||
grids.GridOperation( "Edit Attributes", allow_multiple=False, url_args=dict( action='edit') ),
|
||||
grids.GridOperation( "Copy", allow_multiple=False, condition=( lambda item: not item.deleted ), async_compatible=False, url_args=dict( action='clone') ),
|
||||
grids.GridOperation( "Share or Publish", allow_multiple=False, condition=( lambda item: not item.deleted ), async_compatible=False ),
|
||||
|
||||
@@ -4,7 +4,7 @@ Classes for generating HTML forms
|
||||
|
||||
import logging, sys, os, time
|
||||
from cgi import escape
|
||||
from galaxy.util import restore_text, relpath, nice_size
|
||||
from galaxy.util import restore_text, relpath, nice_size, unicodify
|
||||
from galaxy.web import url_for
|
||||
from binascii import hexlify
|
||||
|
||||
@@ -34,8 +34,8 @@ class TextField(BaseField):
|
||||
self.size = int( size or 10 )
|
||||
self.value = value or ""
|
||||
def get_html( self, prefix="", disabled=False ):
|
||||
return '<input type="text" name="%s%s" size="%d" value="%s"%s>' \
|
||||
% ( prefix, self.name, self.size, escape( str( self.value ), quote=True ), self.get_disabled_str( disabled ) )
|
||||
return unicodify( '<input type="text" name="%s%s" size="%d" value="%s"%s>' \
|
||||
% ( prefix, self.name, self.size, escape( str( self.value ), quote=True ), self.get_disabled_str( disabled ) ) )
|
||||
def set_size(self, size):
|
||||
self.size = int( size )
|
||||
|
||||
@@ -53,8 +53,8 @@ class PasswordField(BaseField):
|
||||
self.size = int( size or 10 )
|
||||
self.value = value or ""
|
||||
def get_html( self, prefix="", disabled=False ):
|
||||
return '<input type="password" name="%s%s" size="%d" value="%s"%s>' \
|
||||
% ( prefix, self.name, self.size, escape( str( self.value ), quote=True ), self.get_disabled_str( disabled ) )
|
||||
return unicodify( '<input type="password" name="%s%s" size="%d" value="%s"%s>' \
|
||||
% ( prefix, self.name, self.size, escape( str( self.value ), quote=True ), self.get_disabled_str( disabled ) ) )
|
||||
def set_size(self, size):
|
||||
self.size = int( size )
|
||||
|
||||
@@ -74,8 +74,8 @@ class TextArea(BaseField):
|
||||
self.cols = int(self.size[-1])
|
||||
self.value = value or ""
|
||||
def get_html( self, prefix="", disabled=False ):
|
||||
return '<textarea name="%s%s" rows="%d" cols="%d"%s>%s</textarea>' \
|
||||
% ( prefix, self.name, self.rows, self.cols, self.get_disabled_str( disabled ), escape( str( self.value ), quote=True ) )
|
||||
return unicodify( '<textarea name="%s%s" rows="%d" cols="%d"%s>%s</textarea>' \
|
||||
% ( prefix, self.name, self.rows, self.cols, self.get_disabled_str( disabled ), escape( str( self.value ), quote=True ) ) )
|
||||
def set_size(self, rows, cols):
|
||||
self.rows = rows
|
||||
self.cols = cols
|
||||
@@ -111,8 +111,8 @@ class CheckboxField(BaseField):
|
||||
# parsing the request, the value 'true' in the hidden field actually means it is NOT checked.
|
||||
# See the is_checked() method below. The prefix is necessary in each case to ensure functional
|
||||
# correctness when the param is inside a conditional.
|
||||
return '<input type="checkbox" id="%s" name="%s" value="true"%s%s%s><input type="hidden" name="%s%s" value="true"%s>' \
|
||||
% ( id_name, id_name, checked_text, self.get_disabled_str( disabled ), self.refresh_on_change_text, prefix, self.name, self.get_disabled_str( disabled ) )
|
||||
return unicodify( '<input type="checkbox" id="%s" name="%s" value="true"%s%s%s><input type="hidden" name="%s%s" value="true"%s>' \
|
||||
% ( id_name, id_name, checked_text, self.get_disabled_str( disabled ), self.refresh_on_change_text, prefix, self.name, self.get_disabled_str( disabled ) ) )
|
||||
@staticmethod
|
||||
def is_checked( value ):
|
||||
if value == True:
|
||||
@@ -148,7 +148,7 @@ class FileField(BaseField):
|
||||
ajax_text = ""
|
||||
if self.ajax:
|
||||
ajax_text = ' galaxy-ajax-upload="true"'
|
||||
return '<input type="file" name="%s%s"%s%s>' % ( prefix, self.name, ajax_text, value_text )
|
||||
return unicodify( '<input type="file" name="%s%s"%s%s>' % ( prefix, self.name, ajax_text, value_text ) )
|
||||
|
||||
class FTPFileField(BaseField):
|
||||
"""
|
||||
@@ -223,7 +223,7 @@ class HiddenField(BaseField):
|
||||
self.name = name
|
||||
self.value = value or ""
|
||||
def get_html( self, prefix="" ):
|
||||
return '<input type="hidden" name="%s%s" value="%s">' % ( prefix, self.name, escape( str( self.value ), quote=True ) )
|
||||
return unicodify( '<input type="hidden" name="%s%s" value="%s">' % ( prefix, self.name, escape( str( self.value ), quote=True ) ) )
|
||||
|
||||
class SelectField(BaseField):
|
||||
"""
|
||||
@@ -308,7 +308,7 @@ class SelectField(BaseField):
|
||||
rval.append( '<div%s><input type="checkbox" name="%s%s" value="%s" id="%s"%s%s><label class="inline" for="%s">%s</label></div>' % \
|
||||
( style, prefix, self.name, escaped_value, uniq_id, selected_text, self.get_disabled_str( disabled ), uniq_id, escape( str( text ), quote=True ) ) )
|
||||
ctr += 1
|
||||
return "\n".join( rval )
|
||||
return unicodify( "\n".join( rval ) )
|
||||
def get_html_radio( self, prefix="", disabled=False ):
|
||||
rval = []
|
||||
ctr = 0
|
||||
@@ -333,7 +333,7 @@ class SelectField(BaseField):
|
||||
uniq_id,
|
||||
text ) )
|
||||
ctr += 1
|
||||
return "\n".join( rval )
|
||||
return unicodify( "\n".join( rval ) )
|
||||
def get_html_default( self, prefix="", disabled=False ):
|
||||
if self.multiple:
|
||||
multiple = " multiple"
|
||||
@@ -357,7 +357,7 @@ class SelectField(BaseField):
|
||||
rval.insert( 0, '<select name="%s%s"%s%s%s%s%s>' % \
|
||||
( prefix, self.name, multiple, size, self.refresh_on_change_text, last_selected_value, self.get_disabled_str( disabled ) ) )
|
||||
rval.append( '</select>' )
|
||||
return "\n".join( rval )
|
||||
return unicodify( "\n".join( rval ) )
|
||||
def get_selected( self, return_label=False, return_value=False, multi=False ):
|
||||
'''
|
||||
Return the currently selected option's label, value or both as a tuple. For
|
||||
@@ -513,7 +513,7 @@ class DrillDownField( BaseField ):
|
||||
find_expanded_options( expanded_options, self.options )
|
||||
recurse_options( rval, self.options, drilldown_id, expanded_options )
|
||||
rval.append( '</div>' )
|
||||
return '\n'.join( rval )
|
||||
return unicodify( '\n'.join( rval ) )
|
||||
|
||||
class AddressField(BaseField):
|
||||
@staticmethod
|
||||
@@ -688,8 +688,8 @@ class LibraryField( BaseField ):
|
||||
else:
|
||||
ldda_ids = "||".join( [ self.trans.security.encode_id( ldda.id ) for ldda in self.lddas ] )
|
||||
text = "<br />".join( [ "%s. %s" % (i+1, ldda.name) for i, ldda in enumerate(self.lddas)] )
|
||||
return '<a href="javascript:void(0);" class="add-librarydataset">%s</a> \
|
||||
<input type="hidden" name="%s%s" value="%s">' % ( text, prefix, self.name, escape( str(ldda_ids), quote=True ) )
|
||||
return unicodify( '<a href="javascript:void(0);" class="add-librarydataset">%s</a> \
|
||||
<input type="hidden" name="%s%s" value="%s">' % ( text, prefix, self.name, escape( str(ldda_ids), quote=True ) ) )
|
||||
|
||||
def get_display_text(self):
|
||||
if self.ldda:
|
||||
|
||||
@@ -728,9 +728,12 @@ class GridOperation( object ):
|
||||
self.global_operation = global_operation
|
||||
def get_url_args( self, item ):
|
||||
if self.url_args:
|
||||
temp = dict( self.url_args )
|
||||
temp['id'] = item.id
|
||||
return temp
|
||||
if hasattr( self.url_args, '__call__' ):
|
||||
url_args = self.url_args( item )
|
||||
else:
|
||||
url_args = dict( self.url_args )
|
||||
url_args['id'] = item.id
|
||||
return url_args
|
||||
else:
|
||||
return dict( operation=self.label, id=item.id )
|
||||
def allowed( self, item ):
|
||||
|
||||
@@ -87,6 +87,7 @@ class Configuration( object ):
|
||||
self.server_name = ''
|
||||
self.job_manager = ''
|
||||
self.default_job_handlers = []
|
||||
self.default_cluster_job_runner = 'local:///'
|
||||
self.job_handlers = []
|
||||
self.tool_handlers = []
|
||||
self.tool_runners = []
|
||||
|
||||
@@ -696,9 +696,14 @@ class AdminController( BaseUIController, Admin ):
|
||||
owner = repository_name_owner_list[ 1 ]
|
||||
repository = get_repository_by_name_and_owner( trans, name, owner )
|
||||
try:
|
||||
reset_all_metadata_on_repository( trans, trans.security.encode_id( repository.id ) )
|
||||
log.debug( "Successfully reset metadata on repository %s" % repository.name )
|
||||
successful_count += 1
|
||||
invalid_file_tups = reset_all_metadata_on_repository( trans, trans.security.encode_id( repository.id ) )
|
||||
if invalid_file_tups:
|
||||
message = generate_message_for_invalid_tools( invalid_file_tups, repository, None, as_html=False )
|
||||
log.debug( message )
|
||||
unsuccessful_count += 1
|
||||
else:
|
||||
log.debug( "Successfully reset metadata on repository %s" % repository.name )
|
||||
successful_count += 1
|
||||
except Exception, e:
|
||||
log.debug( "Error attempting to reset metadata on repository '%s': %s" % ( repository.name, str( e ) ) )
|
||||
unsuccessful_count += 1
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
import os, string, socket, logging, simplejson, binascii, tempfile
|
||||
import os, string, socket, logging, simplejson, binascii, tempfile, filecmp
|
||||
from time import strftime
|
||||
from datetime import *
|
||||
from galaxy.datatypes.checkers import *
|
||||
from galaxy.tools import *
|
||||
from galaxy.util.json import from_json_string, to_json_string
|
||||
from galaxy.util.hash_util import *
|
||||
from galaxy.util.shed_util import clone_repository, generate_metadata_for_changeset_revision, get_changectx_for_changeset, get_config_from_disk
|
||||
from galaxy.util.shed_util import get_configured_ui, get_named_tmpfile_from_ctx, handle_sample_tool_data_table_conf_file, INITIAL_CHANGELOG_HASH
|
||||
from galaxy.util.shed_util import reset_tool_data_tables, reversed_upper_bounded_changelog, strip_path
|
||||
from galaxy.util.shed_util import check_tool_input_params, clone_repository, copy_sample_file, generate_metadata_for_changeset_revision
|
||||
from galaxy.util.shed_util import get_changectx_for_changeset, get_config_from_disk, get_configured_ui, get_named_tmpfile_from_ctx
|
||||
from galaxy.util.shed_util import handle_sample_tool_data_table_conf_file, INITIAL_CHANGELOG_HASH, load_tool_from_config, reset_tool_data_tables
|
||||
from galaxy.util.shed_util import reversed_upper_bounded_changelog, strip_path
|
||||
from galaxy.web.base.controller import *
|
||||
from galaxy.webapps.community import model
|
||||
from galaxy.model.orm import *
|
||||
@@ -105,6 +106,42 @@ class ItemRatings( UsesItemRatings ):
|
||||
trans.sa_session.flush()
|
||||
return item_rating
|
||||
|
||||
def add_tool_versions( trans, id, repository_metadata, changeset_revisions ):
|
||||
# Build a dictionary of { 'tool id' : 'parent tool id' } pairs for each tool in repository_metadata.
|
||||
metadata = repository_metadata.metadata
|
||||
tool_versions_dict = {}
|
||||
for tool_dict in metadata.get( 'tools', [] ):
|
||||
# We have at least 2 changeset revisions to compare tool guids and tool ids.
|
||||
parent_id = get_parent_id( trans,
|
||||
id,
|
||||
tool_dict[ 'id' ],
|
||||
tool_dict[ 'version' ],
|
||||
tool_dict[ 'guid' ],
|
||||
changeset_revisions )
|
||||
tool_versions_dict[ tool_dict[ 'guid' ] ] = parent_id
|
||||
if tool_versions_dict:
|
||||
repository_metadata.tool_versions = tool_versions_dict
|
||||
trans.sa_session.add( repository_metadata )
|
||||
trans.sa_session.flush()
|
||||
def can_use_tool_config_disk_file( trans, repository, repo, file_path, changeset_revision ):
|
||||
"""
|
||||
Determine if repository's tool config file on disk can be used. This method is restricted to tool config files since, with the
|
||||
exception of tool config files, multiple files with the same name will likely be in various directories in the repository and we're
|
||||
comparing file names only (not relative paths).
|
||||
"""
|
||||
if not file_path or not os.path.exists( file_path ):
|
||||
# The file no longer exists on disk, so it must have been deleted at some previous point in the change log.
|
||||
return False
|
||||
if changeset_revision == repository.tip:
|
||||
return True
|
||||
file_name = strip_path( file_path )
|
||||
latest_version_of_file = get_latest_tool_config_revision_from_repository_manifest( repo, file_name, changeset_revision )
|
||||
can_use_disk_file = filecmp.cmp( file_path, latest_version_of_file )
|
||||
try:
|
||||
os.unlink( latest_version_of_file )
|
||||
except:
|
||||
pass
|
||||
return can_use_disk_file
|
||||
def changeset_is_malicious( trans, id, changeset_revision, **kwd ):
|
||||
"""Check the malicious flag in repository metadata for a specified change set"""
|
||||
repository_metadata = get_repository_metadata_by_changeset_revision( trans, id, changeset_revision )
|
||||
@@ -221,6 +258,16 @@ def compare_workflows( ancestor_workflows, current_workflows ):
|
||||
else:
|
||||
return 'subset'
|
||||
return 'not equal and not subset'
|
||||
def copy_disk_sample_files_to_dir( trans, repo_files_dir, dest_path ):
|
||||
sample_files = []
|
||||
for root, dirs, files in os.walk( repo_files_dir ):
|
||||
if root.find( '.hg' ) < 0:
|
||||
for name in files:
|
||||
if name.endswith( '.sample' ):
|
||||
relative_path = os.path.join( root, name )
|
||||
copy_sample_file( trans.app, relative_path, dest_path=dest_path )
|
||||
sample_files_copied.append( name )
|
||||
return sample_files
|
||||
def copy_file_from_disk( filename, repo_dir, dir ):
|
||||
file_path = None
|
||||
found = False
|
||||
@@ -240,9 +287,7 @@ def copy_file_from_disk( filename, repo_dir, dir ):
|
||||
tmp_filename = None
|
||||
return tmp_filename
|
||||
def copy_file_from_manifest( repo, ctx, filename, dir ):
|
||||
"""
|
||||
Copy the latest version of the file named filename from the repository manifest to the directory to which dir refers.
|
||||
"""
|
||||
"""Copy the latest version of the file named filename from the repository manifest to the directory to which dir refers."""
|
||||
for changeset in reversed_upper_bounded_changelog( repo, ctx ):
|
||||
changeset_ctx = repo.changectx( changeset )
|
||||
fctx = get_file_context_from_ctx( changeset_ctx, filename )
|
||||
@@ -277,6 +322,42 @@ def generate_clone_url( trans, repository_id ):
|
||||
return '%s://%s%s/repos/%s/%s' % ( protocol, username, base, repository.user.username, repository.name )
|
||||
else:
|
||||
return '%s/repos/%s/%s' % ( base_url, repository.user.username, repository.name )
|
||||
def generate_message_for_invalid_tools( invalid_file_tups, repository, metadata_dict, as_html=True, displaying_invalid_tool=False ):
|
||||
if as_html:
|
||||
new_line = '<br/>'
|
||||
bold_start = '<b>'
|
||||
bold_end = '</b>'
|
||||
else:
|
||||
new_line = '\n'
|
||||
bold_start = ''
|
||||
bold_end = ''
|
||||
message = ''
|
||||
if not displaying_invalid_tool:
|
||||
if metadata_dict:
|
||||
message += "Metadata was defined for some items in revision '%s'. " % str( repository.tip )
|
||||
message += "Correct the following problems if necessary and reset metadata.%s" % new_line
|
||||
else:
|
||||
message += "Metadata cannot be defined for revision '%s' so this revision cannot be automatically " % str( repository.tip )
|
||||
message += "installed into a local Galaxy instance. Correct the following problems and reset metadata.%s" % new_line
|
||||
for itc_tup in invalid_file_tups:
|
||||
tool_file, exception_msg = itc_tup
|
||||
if exception_msg.find( 'No such file or directory' ) >= 0:
|
||||
exception_items = exception_msg.split()
|
||||
missing_file_items = exception_items[ 7 ].split( '/' )
|
||||
missing_file = missing_file_items[ -1 ].rstrip( '\'' )
|
||||
if missing_file.endswith( '.loc' ):
|
||||
sample_ext = '%s.sample' % missing_file
|
||||
else:
|
||||
sample_ext = missing_file
|
||||
correction_msg = "This file refers to a missing file %s%s%s. " % ( bold_start, str( missing_file ), bold_end )
|
||||
correction_msg += "Upload a file named %s%s%s to the repository to correct this error." % ( bold_start, sample_ext, bold_end )
|
||||
else:
|
||||
if as_html:
|
||||
correction_msg = exception_msg
|
||||
else:
|
||||
correction_msg = exception_msg.replace( '<br/>', new_line ).replace( '<b>', bold_start ).replace( '</b>', bold_end )
|
||||
message += "%s%s%s - %s%s" % ( bold_start, tool_file, bold_end, correction_msg, new_line )
|
||||
return message
|
||||
def generate_tool_guid( trans, repository, tool ):
|
||||
"""
|
||||
Generate a guid for the received tool. The form of the guid is
|
||||
@@ -287,6 +368,19 @@ def generate_tool_guid( trans, repository, tool ):
|
||||
repository.name,
|
||||
tool.id,
|
||||
tool.version )
|
||||
def get_absolute_path_to_file_in_repository( repo_files_dir, file_name ):
|
||||
file_path = None
|
||||
found = False
|
||||
for root, dirs, files in os.walk( repo_files_dir ):
|
||||
if root.find( '.hg' ) < 0:
|
||||
for name in files:
|
||||
if name == file_name:
|
||||
file_path = os.path.abspath( os.path.join( root, name ) )
|
||||
found = True
|
||||
break
|
||||
if found:
|
||||
break
|
||||
return file_path
|
||||
def get_category( trans, id ):
|
||||
"""Get a category from the database"""
|
||||
return trans.sa_session.query( trans.model.Category ).get( trans.security.decode_id( id ) )
|
||||
@@ -318,12 +412,44 @@ def get_file_context_from_ctx( ctx, filename ):
|
||||
if deleted:
|
||||
return 'DELETED'
|
||||
return None
|
||||
def get_ctx_file_path_from_manifest( filename, repo, changeset_revision ):
|
||||
"""Get the ctx file path for the latest revision of filename from the repository manifest up to the value of changeset_revision."""
|
||||
stripped_filename = strip_path( filename )
|
||||
for changeset in reversed_upper_bounded_changelog( repo, changeset_revision ):
|
||||
manifest_changeset_revision = str( repo.changectx( changeset ) )
|
||||
manifest_ctx = repo.changectx( changeset )
|
||||
for ctx_file in manifest_ctx.files():
|
||||
ctx_file_name = strip_path( ctx_file )
|
||||
if ctx_file_name == stripped_filename:
|
||||
return manifest_ctx, ctx_file
|
||||
return None, None
|
||||
def get_latest_repository_metadata( trans, decoded_repository_id ):
|
||||
"""Get last metadata defined for a specified repository from the database"""
|
||||
return trans.sa_session.query( trans.model.RepositoryMetadata ) \
|
||||
.filter( trans.model.RepositoryMetadata.table.c.repository_id == decoded_repository_id ) \
|
||||
.order_by( trans.model.RepositoryMetadata.table.c.id.desc() ) \
|
||||
.first()
|
||||
def get_latest_tool_config_revision_from_repository_manifest( repo, filename, changeset_revision ):
|
||||
"""
|
||||
Get the latest revision of a tool config file named filename from the repository manifest up to the value of changeset_revision.
|
||||
This method is restricted to tool_config files rather than any file since it is likely that, with the exception of tool config files,
|
||||
multiple files will have the same name in various directories within the repository.
|
||||
"""
|
||||
stripped_filename = strip_path( filename )
|
||||
for changeset in reversed_upper_bounded_changelog( repo, changeset_revision ):
|
||||
manifest_ctx = repo.changectx( changeset )
|
||||
for ctx_file in manifest_ctx.files():
|
||||
ctx_file_name = strip_path( ctx_file )
|
||||
if ctx_file_name == stripped_filename:
|
||||
fctx = manifest_ctx[ ctx_file ]
|
||||
fh = tempfile.NamedTemporaryFile( 'wb' )
|
||||
tmp_filename = fh.name
|
||||
fh.close()
|
||||
fh = open( tmp_filename, 'wb' )
|
||||
fh.write( fctx.data() )
|
||||
fh.close()
|
||||
return tmp_filename
|
||||
return None
|
||||
def get_list_of_copied_sample_files( repo, ctx, dir ):
|
||||
"""
|
||||
Find all sample files (files in the repository with the special .sample extension) in the reversed repository manifest up to ctx. Copy
|
||||
@@ -416,8 +542,8 @@ def get_repository_by_name_and_owner( trans, name, owner ):
|
||||
def get_repository_metadata_by_changeset_revision( trans, id, changeset_revision ):
|
||||
"""Get metadata for a specified repository change set from the database"""
|
||||
# Make sure there are no duplicate records, and return the single unique record for the changeset_revision. Duplicate records were somehow
|
||||
# creatd in the past. This may or may not be resolved, so when it is confirmed that the cause of duplicate records has been corrected, tweak
|
||||
# this method accordingly.
|
||||
# created in the past. The cause of this issue has been resolved, but we'll leave this method as is for a while longer to ensure all duplicate
|
||||
# records are removed.
|
||||
all_metadata_records = trans.sa_session.query( trans.model.RepositoryMetadata ) \
|
||||
.filter( and_( trans.model.RepositoryMetadata.table.c.repository_id == trans.security.decode_id( id ),
|
||||
trans.model.RepositoryMetadata.table.c.changeset_revision == changeset_revision ) ) \
|
||||
@@ -542,90 +668,61 @@ def handle_email_alerts( trans, repository, content_alert_str='', new_repo_alert
|
||||
log.exception( "An error occurred sending a tool shed repository update alert by email." )
|
||||
def is_downloadable( metadata_dict ):
|
||||
return 'datatypes' in metadata_dict or 'tools' in metadata_dict or 'workflows' in metadata_dict
|
||||
def load_tool( trans, config_file ):
|
||||
"""Load a single tool from the file named by `config_file` and return an instance of `Tool`."""
|
||||
# Parse XML configuration file and get the root element
|
||||
tree = util.parse_xml( config_file )
|
||||
root = tree.getroot()
|
||||
if root.tag == 'tool':
|
||||
# Allow specifying a different tool subclass to instantiate
|
||||
if root.find( "type" ) is not None:
|
||||
type_elem = root.find( "type" )
|
||||
module = type_elem.get( 'module', 'galaxy.tools' )
|
||||
cls = type_elem.get( 'class' )
|
||||
mod = __import__( module, globals(), locals(), [cls] )
|
||||
ToolClass = getattr( mod, cls )
|
||||
elif root.get( 'tool_type', None ) is not None:
|
||||
ToolClass = tool_types.get( root.get( 'tool_type' ) )
|
||||
else:
|
||||
ToolClass = Tool
|
||||
return ToolClass( config_file, root, trans.app )
|
||||
return None
|
||||
def load_tool_from_changeset_revision( trans, repository_id, changeset_revision, tool_config_filename ):
|
||||
"""
|
||||
Return a loaded tool whose tool config file name (e.g., filtering.xml) is the value of tool_config_filename. The value of changeset_revision
|
||||
is a valid (downloadable) changset revision. The tool config will be located in the repository manifest between the received valid changeset
|
||||
revision and the first changeset revision in the repository, searching backwards.
|
||||
"""
|
||||
def load_from_tmp_config( toolbox, ctx, ctx_file, work_dir ):
|
||||
tool = None
|
||||
message = ''
|
||||
tmp_tool_config = get_named_tmpfile_from_ctx( ctx, ctx_file, work_dir )
|
||||
if tmp_tool_config:
|
||||
element_tree = util.parse_xml( tmp_tool_config )
|
||||
element_tree_root = element_tree.getroot()
|
||||
# Look for code files required by the tool config.
|
||||
tmp_code_files = []
|
||||
for code_elem in element_tree_root.findall( 'code' ):
|
||||
code_file_name = code_elem.get( 'file' )
|
||||
tmp_code_file_name = copy_file_from_manifest( repo, ctx, code_file_name, work_dir )
|
||||
if tmp_code_file_name:
|
||||
tmp_code_files.append( tmp_code_file_name )
|
||||
try:
|
||||
tool = toolbox.load_tool( tmp_tool_config )
|
||||
except KeyError, e:
|
||||
message = '<b>%s</b> - This file requires an entry for %s in the tool_data_table_conf.xml file. ' % ( tool_config_filename, str( e ) )
|
||||
message += 'Upload a file named tool_data_table_conf.xml.sample to the repository that includes the required entry to correct this error. '
|
||||
except Exception, e:
|
||||
message = 'Error loading tool: %s. ' % str( e )
|
||||
for tmp_code_file in tmp_code_files:
|
||||
try:
|
||||
os.unlink( tmp_code_file )
|
||||
except:
|
||||
pass
|
||||
try:
|
||||
os.unlink( tmp_tool_config )
|
||||
except:
|
||||
pass
|
||||
return tool, message
|
||||
original_tool_data_path = trans.app.config.tool_data_path
|
||||
tool_config_filename = strip_path( tool_config_filename )
|
||||
repository = get_repository( trans, repository_id )
|
||||
repo_files_dir = repository.repo_path
|
||||
repo = hg.repository( get_configured_ui(), repo_files_dir )
|
||||
ctx = get_changectx_for_changeset( repo, changeset_revision )
|
||||
message = ''
|
||||
tool = None
|
||||
can_use_disk_file = False
|
||||
tool_config_filepath = get_absolute_path_to_file_in_repository( repo_files_dir, tool_config_filename )
|
||||
work_dir = tempfile.mkdtemp()
|
||||
sample_files, deleted_sample_files = get_list_of_copied_sample_files( repo, ctx, dir=work_dir )
|
||||
if sample_files:
|
||||
trans.app.config.tool_data_path = work_dir
|
||||
if 'tool_data_table_conf.xml.sample' in sample_files:
|
||||
# Load entries into the tool_data_tables if the tool requires them.
|
||||
tool_data_table_config = os.path.join( work_dir, 'tool_data_table_conf.xml' )
|
||||
error, correction_msg = handle_sample_tool_data_table_conf_file( trans.app, tool_data_table_config )
|
||||
found = False
|
||||
# Get the latest revision of the tool config from the repository manifest up to the value of changeset_revision.
|
||||
for changeset in reversed_upper_bounded_changelog( repo, changeset_revision ):
|
||||
manifest_changeset_revision = str( repo.changectx( changeset ) )
|
||||
manifest_ctx = repo.changectx( changeset )
|
||||
for ctx_file in manifest_ctx.files():
|
||||
ctx_file_name = strip_path( ctx_file )
|
||||
if ctx_file_name == tool_config_filename:
|
||||
found = True
|
||||
break
|
||||
if found:
|
||||
tool, message = load_from_tmp_config( trans.app.toolbox, manifest_ctx, ctx_file, work_dir )
|
||||
break
|
||||
can_use_disk_file = can_use_tool_config_disk_file( trans, repository, repo, tool_config_filepath, changeset_revision )
|
||||
if can_use_disk_file:
|
||||
# Copy all sample files from disk to a temporary directory since the sample files may be in multiple directories.
|
||||
sample_files = copy_disk_sample_files_to_dir( trans, repo_files_dir, work_dir )
|
||||
if sample_files:
|
||||
trans.app.config.tool_data_path = work_dir
|
||||
if 'tool_data_table_conf.xml.sample' in sample_files:
|
||||
# Load entries into the tool_data_tables if the tool requires them.
|
||||
tool_data_table_config = os.path.join( work_dir, 'tool_data_table_conf.xml' )
|
||||
error, correction_msg = handle_sample_tool_data_table_conf_file( trans.app, tool_data_table_config )
|
||||
tool, valid, message = load_tool_from_config( trans.app, tool_config_filepath )
|
||||
if tool is not None:
|
||||
invalid_files_and_errors_tups = check_tool_input_params( trans.app,
|
||||
repo_files_dir,
|
||||
tool_config_filename,
|
||||
tool,
|
||||
sample_files,
|
||||
webapp='community' )
|
||||
if invalid_files_and_errors_tups:
|
||||
message = generate_message_for_invalid_tools( invalid_files_and_errors_tups,
|
||||
repository,
|
||||
metadata_dict=None,
|
||||
as_html=True,
|
||||
displaying_invalid_tool=True )
|
||||
status = 'error'
|
||||
else:
|
||||
# The desired version of the tool config is no longer on disk, so create a temporary work environment and copy the tool config and dependent files.
|
||||
ctx = get_changectx_for_changeset( repo, changeset_revision )
|
||||
# We're not currently doing anything with the returned list of deleted_sample_files here. It is intended to help handle sample files that are in
|
||||
# the manifest, but have been deleted from disk.
|
||||
sample_files, deleted_sample_files = get_list_of_copied_sample_files( repo, ctx, dir=work_dir )
|
||||
if sample_files:
|
||||
trans.app.config.tool_data_path = work_dir
|
||||
if 'tool_data_table_conf.xml.sample' in sample_files:
|
||||
# Load entries into the tool_data_tables if the tool requires them.
|
||||
tool_data_table_config = os.path.join( work_dir, 'tool_data_table_conf.xml' )
|
||||
error, correction_msg = handle_sample_tool_data_table_conf_file( trans.app, tool_data_table_config )
|
||||
manifest_ctx, ctx_file = get_ctx_file_path_from_manifest( tool_config_filename, repo, changeset_revision )
|
||||
if manifest_ctx and ctx_file:
|
||||
tool, message = load_tool_from_tmp_config( trans, repo, manifest_ctx, ctx_file, work_dir )
|
||||
try:
|
||||
shutil.rmtree( work_dir )
|
||||
except:
|
||||
@@ -634,50 +731,32 @@ def load_tool_from_changeset_revision( trans, repository_id, changeset_revision,
|
||||
trans.app.config.tool_data_path = original_tool_data_path
|
||||
# Reset the tool_data_tables by loading the empty tool_data_table_conf.xml file.
|
||||
reset_tool_data_tables( trans.app )
|
||||
return tool, message
|
||||
def load_tool_from_tmp_directory( trans, repo, repo_dir, ctx, filename, dir ):
|
||||
is_tool_config = False
|
||||
return repository, tool, message
|
||||
def load_tool_from_tmp_config( trans, repo, ctx, ctx_file, work_dir ):
|
||||
tool = None
|
||||
valid = False
|
||||
error_message = ''
|
||||
tmp_config = get_named_tmpfile_from_ctx( ctx, filename, dir )
|
||||
if tmp_config:
|
||||
if not ( check_binary( tmp_config ) or check_image( tmp_config ) or check_gzip( tmp_config )[ 0 ]
|
||||
or check_bz2( tmp_config )[ 0 ] or check_zip( tmp_config ) ):
|
||||
message = ''
|
||||
tmp_tool_config = get_named_tmpfile_from_ctx( ctx, ctx_file, work_dir )
|
||||
if tmp_tool_config:
|
||||
element_tree = util.parse_xml( tmp_tool_config )
|
||||
element_tree_root = element_tree.getroot()
|
||||
# Look for code files required by the tool config.
|
||||
tmp_code_files = []
|
||||
for code_elem in element_tree_root.findall( 'code' ):
|
||||
code_file_name = code_elem.get( 'file' )
|
||||
tmp_code_file_name = copy_file_from_manifest( repo, ctx, code_file_name, work_dir )
|
||||
if tmp_code_file_name:
|
||||
tmp_code_files.append( tmp_code_file_name )
|
||||
tool, valid, message = load_tool_from_config( trans.app, tmp_tool_config )
|
||||
for tmp_code_file in tmp_code_files:
|
||||
try:
|
||||
# Make sure we're looking at a tool config and not a display application config or something else.
|
||||
element_tree = util.parse_xml( tmp_config )
|
||||
element_tree_root = element_tree.getroot()
|
||||
is_tool_config = element_tree_root.tag == 'tool'
|
||||
except Exception, e:
|
||||
log.debug( "Error parsing %s, exception: %s" % ( tmp_config, str( e ) ) )
|
||||
is_tool_config = False
|
||||
if is_tool_config:
|
||||
# Load entries into the tool_data_tables if the tool requires them.
|
||||
tool_data_table_config = copy_file_from_manifest( repo, ctx, 'tool_data_table_conf.xml.sample', dir )
|
||||
if tool_data_table_config:
|
||||
error, correction_msg = handle_sample_tool_data_table_conf_file( trans.app, tool_data_table_config )
|
||||
# Look for code files required by the tool config. The directory to which dir refers should be removed by the caller.
|
||||
for code_elem in element_tree_root.findall( 'code' ):
|
||||
code_file_name = code_elem.get( 'file' )
|
||||
if not os.path.exists( os.path.join( dir, code_file_name ) ):
|
||||
tmp_code_file_name = copy_file_from_disk( code_file_name, repo_dir, dir )
|
||||
if tmp_code_file_name is None:
|
||||
tmp_code_file_name = copy_file_from_manifest( repo, ctx, code_file_name, dir )
|
||||
try:
|
||||
tool = load_tool( trans, tmp_config )
|
||||
valid = True
|
||||
except KeyError, e:
|
||||
valid = False
|
||||
error_message = 'This file requires an entry for "%s" in the tool_data_table_conf.xml file. Upload a file ' % str( e )
|
||||
error_message += 'named tool_data_table_conf.xml.sample to the repository that includes the required entry to correct '
|
||||
error_message += 'this error. '
|
||||
except Exception, e:
|
||||
valid = False
|
||||
error_message = str( e )
|
||||
# Reset the tool_data_tables by loading the empty tool_data_table_conf.xml file.
|
||||
reset_tool_data_tables( trans.app )
|
||||
return is_tool_config, valid, tool, error_message
|
||||
os.unlink( tmp_code_file )
|
||||
except:
|
||||
pass
|
||||
try:
|
||||
os.unlink( tmp_tool_config )
|
||||
except:
|
||||
pass
|
||||
return tool, message
|
||||
def new_tool_metadata_required( trans, repository, metadata_dict ):
|
||||
"""
|
||||
Compare the last saved metadata for each tool in the repository with the new metadata in metadata_dict to determine if a new repository_metadata
|
||||
@@ -854,28 +933,12 @@ def reset_all_metadata_on_repository( trans, id, **kwd ):
|
||||
clean_repository_metadata( trans, id, changeset_revisions )
|
||||
# Set tool version information for all downloadable changeset revisions. Get the list of changeset revisions from the changelog.
|
||||
reset_all_tool_versions( trans, id, repo )
|
||||
return invalid_file_tups
|
||||
def set_repository_metadata( trans, repository, content_alert_str='', **kwd ):
|
||||
"""
|
||||
Set metadata using the repository's current disk files, returning specific error messages (if any) to alert the repository owner that the changeset
|
||||
has problems.
|
||||
"""
|
||||
def add_tool_versions( trans, id, repository_metadata, changeset_revisions ):
|
||||
# Build a dictionary of { 'tool id' : 'parent tool id' } pairs for each tool in repository_metadata.
|
||||
metadata = repository_metadata.metadata
|
||||
tool_versions_dict = {}
|
||||
for tool_dict in metadata.get( 'tools', [] ):
|
||||
# We have at least 2 changeset revisions to compare tool guids and tool ids.
|
||||
parent_id = get_parent_id( trans,
|
||||
id,
|
||||
tool_dict[ 'id' ],
|
||||
tool_dict[ 'version' ],
|
||||
tool_dict[ 'guid' ],
|
||||
changeset_revisions )
|
||||
tool_versions_dict[ tool_dict[ 'guid' ] ] = parent_id
|
||||
if tool_versions_dict:
|
||||
repository_metadata.tool_versions = tool_versions_dict
|
||||
trans.sa_session.add( repository_metadata )
|
||||
trans.sa_session.flush()
|
||||
message = ''
|
||||
status = 'done'
|
||||
encoded_id = trans.security.encode_id( repository.id )
|
||||
@@ -931,27 +994,7 @@ def set_repository_metadata( trans, repository, content_alert_str='', **kwd ):
|
||||
message += "be defined so this revision cannot be automatically installed into a local Galaxy instance."
|
||||
status = "error"
|
||||
if invalid_file_tups:
|
||||
if metadata_dict:
|
||||
message += "Metadata was defined for some items in revision '%s'. " % str( repository.tip )
|
||||
message += "Correct the following problems if necessary and reset metadata.<br/>"
|
||||
else:
|
||||
message += "Metadata cannot be defined for revision '%s' so this revision cannot be automatically " % str( repository.tip )
|
||||
message += "installed into a local Galaxy instance. Correct the following problems and reset metadata.<br/>"
|
||||
for itc_tup in invalid_file_tups:
|
||||
tool_file, exception_msg = itc_tup
|
||||
if exception_msg.find( 'No such file or directory' ) >= 0:
|
||||
exception_items = exception_msg.split()
|
||||
missing_file_items = exception_items[ 7 ].split( '/' )
|
||||
missing_file = missing_file_items[ -1 ].rstrip( '\'' )
|
||||
if missing_file.endswith( '.loc' ):
|
||||
sample_ext = '%s.sample' % missing_file
|
||||
else:
|
||||
sample_ext = missing_file
|
||||
correction_msg = "This file refers to a missing file <b>%s</b>. " % str( missing_file )
|
||||
correction_msg += "Upload a file named <b>%s</b> to the repository to correct this error." % sample_ext
|
||||
else:
|
||||
correction_msg = exception_msg
|
||||
message += "<b>%s</b> - %s<br/>" % ( tool_file, correction_msg )
|
||||
message = generate_message_for_invalid_tools( invalid_file_tups, repository, metadata_dict )
|
||||
status = 'error'
|
||||
return message, status
|
||||
def set_repository_metadata_due_to_new_tip( trans, repository, content_alert_str=None, **kwd ):
|
||||
|
||||
@@ -9,9 +9,9 @@ from galaxy.webapps.community.model import directory_hash_id
|
||||
from galaxy.web.framework.helpers import time_ago, iff, grids
|
||||
from galaxy.util.json import from_json_string, to_json_string
|
||||
from galaxy.model.orm import *
|
||||
from galaxy.util.shed_util import create_repo_info_dict, get_changectx_for_changeset, get_configured_ui, get_repository_file_contents, NOT_TOOL_CONFIGS
|
||||
from galaxy.util.shed_util import open_repository_files_folder, reversed_lower_upper_bounded_changelog, reversed_upper_bounded_changelog, strip_path
|
||||
from galaxy.util.shed_util import to_html_escaped, update_repository
|
||||
from galaxy.util.shed_util import create_repo_info_dict, get_changectx_for_changeset, get_configured_ui, get_repository_file_contents, load_tool_from_config
|
||||
from galaxy.util.shed_util import NOT_TOOL_CONFIGS, open_repository_files_folder, reversed_lower_upper_bounded_changelog, reversed_upper_bounded_changelog
|
||||
from galaxy.util.shed_util import strip_path, to_html_escaped, update_repository, url_join
|
||||
from galaxy.tool_shed.encoding_util import *
|
||||
from common import *
|
||||
|
||||
@@ -246,6 +246,28 @@ class EmailAlertsRepositoryListGrid( RepositoryListGrid ):
|
||||
grids.GridAction( "User preferences", dict( controller='user', action='index', cntrller='repository', webapp='community' ) )
|
||||
]
|
||||
|
||||
class WritableRepositoryListGrid( RepositoryListGrid ):
|
||||
def build_initial_query( self, trans, **kwd ):
|
||||
# TODO: improve performance by adding a db table associating users with repositories for which they have write access.
|
||||
username = kwd[ 'username' ]
|
||||
clause_list = []
|
||||
for repository in trans.sa_session.query( self.model_class ) \
|
||||
.filter( self.model_class.table.c.deleted == False ):
|
||||
allow_push = repository.allow_push
|
||||
if allow_push:
|
||||
allow_push_usernames = allow_push.split( ',' )
|
||||
if username in allow_push_usernames:
|
||||
clause_list.append( self.model_class.table.c.id == repository.id )
|
||||
if clause_list:
|
||||
return trans.sa_session.query( self.model_class ) \
|
||||
.filter( or_( *clause_list ) ) \
|
||||
.join( model.User.table ) \
|
||||
.outerjoin( model.RepositoryCategoryAssociation.table ) \
|
||||
.outerjoin( model.Category.table )
|
||||
# Return an empty query.
|
||||
return trans.sa_session.query( self.model_class ) \
|
||||
.filter( self.model_class.table.c.id < 0 )
|
||||
|
||||
class ValidRepositoryListGrid( RepositoryListGrid ):
|
||||
class CategoryColumn( grids.TextColumn ):
|
||||
def get_value( self, trans, grid, repository ):
|
||||
@@ -393,6 +415,7 @@ class RepositoryController( BaseUIController, ItemRatings ):
|
||||
email_alerts_repository_list_grid = EmailAlertsRepositoryListGrid()
|
||||
category_list_grid = CategoryListGrid()
|
||||
valid_category_list_grid = ValidCategoryListGrid()
|
||||
writable_repository_list_grid = WritableRepositoryListGrid()
|
||||
|
||||
def __add_hgweb_config_entry( self, trans, repository, repository_path ):
|
||||
# Add an entry in the hgweb.config file for a new repository. An entry looks something like:
|
||||
@@ -458,7 +481,10 @@ class RepositoryController( BaseUIController, ItemRatings ):
|
||||
metadata = downloadable_revision.metadata
|
||||
invalid_tools = metadata.get( 'invalid_tools', [] )
|
||||
for invalid_tool_config in invalid_tools:
|
||||
invalid_tools_dict[ invalid_tool_config ] = ( repository.id, repository.name, downloadable_revision.changeset_revision )
|
||||
invalid_tools_dict[ invalid_tool_config ] = ( repository.id,
|
||||
repository.name,
|
||||
repository.user.username,
|
||||
downloadable_revision.changeset_revision )
|
||||
else:
|
||||
for repository in trans.sa_session.query( trans.model.Repository ) \
|
||||
.filter( and_( trans.model.Repository.table.c.deleted == False,
|
||||
@@ -468,7 +494,10 @@ class RepositoryController( BaseUIController, ItemRatings ):
|
||||
metadata = downloadable_revision.metadata
|
||||
invalid_tools = metadata.get( 'invalid_tools', [] )
|
||||
for invalid_tool_config in invalid_tools:
|
||||
invalid_tools_dict[ invalid_tool_config ] = ( repository.id, repository.name, downloadable_revision.changeset_revision )
|
||||
invalid_tools_dict[ invalid_tool_config ] = ( repository.id,
|
||||
repository.name,
|
||||
repository.user.username,
|
||||
downloadable_revision.changeset_revision )
|
||||
return trans.fill_template( '/webapps/community/repository/browse_invalid_tools.mako',
|
||||
cntrller=cntrller,
|
||||
invalid_tools_dict=invalid_tools_dict,
|
||||
@@ -513,12 +542,15 @@ class RepositoryController( BaseUIController, ItemRatings ):
|
||||
repository_id = kwd.get( 'id', None )
|
||||
repository = get_repository( trans, repository_id )
|
||||
kwd[ 'f-email' ] = repository.user.email
|
||||
elif operation == "my_repositories":
|
||||
elif operation == "repositories_i_own":
|
||||
# Eliminate the current filters if any exist.
|
||||
for k, v in kwd.items():
|
||||
if k.startswith( 'f-' ):
|
||||
del kwd[ k ]
|
||||
kwd[ 'f-email' ] = trans.user.email
|
||||
elif operation == "writable_repositories":
|
||||
kwd[ 'username' ] = trans.user.username
|
||||
return self.writable_repository_list_grid( trans, **kwd )
|
||||
elif operation == "repositories_by_category":
|
||||
# Eliminate the current filters if any exist.
|
||||
for k, v in kwd.items():
|
||||
@@ -720,9 +752,10 @@ class RepositoryController( BaseUIController, ItemRatings ):
|
||||
update = 'true'
|
||||
no_update = 'false'
|
||||
else:
|
||||
# Start building up the url to redirect back to the calling Galaxy instance.
|
||||
url = '%sadmin_toolshed/update_to_changeset_revision?tool_shed_url=%s' % ( galaxy_url, url_for( '/', qualified=True ) )
|
||||
url += '&name=%s&owner=%s&changeset_revision=%s&latest_changeset_revision=' % ( repository.name, repository.user.username, changeset_revision )
|
||||
# Start building up the url to redirect back to the calling Galaxy instance.
|
||||
url = url_join( galaxy_url,
|
||||
'admin_toolshed/update_to_changeset_revision?tool_shed_url=%s&name=%s&owner=%s&changeset_revision=%s&latest_changeset_revision=' % \
|
||||
( url_for( '/', qualified=True ), repository.name, repository.user.username, changeset_revision ) )
|
||||
if changeset_revision == repository.tip:
|
||||
# If changeset_revision is the repository tip, there are no additional updates.
|
||||
if from_update_manager:
|
||||
@@ -882,8 +915,7 @@ class RepositoryController( BaseUIController, ItemRatings ):
|
||||
message = util.restore_text( params.get( 'message', '' ) )
|
||||
status = params.get( 'status', 'done' )
|
||||
webapp = get_webapp( trans, **kwd )
|
||||
repository = get_repository( trans, repository_id )
|
||||
tool, message = load_tool_from_changeset_revision( trans, repository_id, changeset_revision, tool_config )
|
||||
repository, tool, message = load_tool_from_changeset_revision( trans, repository_id, changeset_revision, tool_config )
|
||||
tool_state = self.__new_state( trans )
|
||||
is_malicious = changeset_is_malicious( trans, repository_id, repository.tip )
|
||||
try:
|
||||
@@ -1366,10 +1398,9 @@ class RepositoryController( BaseUIController, ItemRatings ):
|
||||
"""Send the list of repository_ids and changeset_revisions to Galaxy so it can begin the installation process."""
|
||||
galaxy_url = trans.get_cookie( name='toolshedgalaxyurl' )
|
||||
# Redirect back to local Galaxy to perform install.
|
||||
url = '%sadmin_toolshed/prepare_for_install' % galaxy_url
|
||||
url += '?tool_shed_url=%s' % url_for( '/', qualified=True )
|
||||
url += '&repository_ids=%s' % ','.join( util.listify( repository_ids ) )
|
||||
url += '&changeset_revisions=%s' % ','.join( util.listify( changeset_revisions ) )
|
||||
url = url_join( galaxy_url,
|
||||
'admin_toolshed/prepare_for_install?tool_shed_url=%s&repository_ids=%s&changeset_revisions=%s' % \
|
||||
( url_for( '/', qualified=True ), ','.join( util.listify( repository_ids ) ), ','.join( util.listify( changeset_revisions ) ) ) )
|
||||
return trans.response.send_redirect( url )
|
||||
@web.expose
|
||||
def load_invalid_tool( self, trans, repository_id, tool_config, changeset_revision, **kwd ):
|
||||
@@ -1378,8 +1409,7 @@ class RepositoryController( BaseUIController, ItemRatings ):
|
||||
status = params.get( 'status', 'error' )
|
||||
webapp = get_webapp( trans, **kwd )
|
||||
repository_clone_url = generate_clone_url( trans, repository_id )
|
||||
repository = get_repository( trans, repository_id )
|
||||
tool, error_message = load_tool_from_changeset_revision( trans, repository_id, changeset_revision, tool_config )
|
||||
repository, tool, error_message = load_tool_from_changeset_revision( trans, repository_id, changeset_revision, tool_config )
|
||||
tool_state = self.__new_state( trans )
|
||||
is_malicious = changeset_is_malicious( trans, repository_id, repository.tip )
|
||||
try:
|
||||
@@ -1752,9 +1782,14 @@ class RepositoryController( BaseUIController, ItemRatings ):
|
||||
status=status )
|
||||
@web.expose
|
||||
def reset_all_metadata( self, trans, id, **kwd ):
|
||||
reset_all_metadata_on_repository( trans, id, **kwd )
|
||||
message = "All repository metadata has been reset."
|
||||
status = 'done'
|
||||
invalid_file_tups = reset_all_metadata_on_repository( trans, id, **kwd )
|
||||
if invalid_file_tups:
|
||||
repository = get_repository( trans, id )
|
||||
message = generate_message_for_invalid_tools( invalid_file_tups, repository, None )
|
||||
status = 'error'
|
||||
else:
|
||||
message = "All repository metadata has been reset."
|
||||
status = 'done'
|
||||
return trans.response.send_redirect( web.url_for( controller='repository',
|
||||
action='manage_repository',
|
||||
id=id,
|
||||
@@ -2185,6 +2220,8 @@ class RepositoryController( BaseUIController, ItemRatings ):
|
||||
status = params.get( 'status', 'done' )
|
||||
webapp = get_webapp( trans, **kwd )
|
||||
repository = get_repository( trans, repository_id )
|
||||
repo_files_dir = repository.repo_path
|
||||
repo = hg.repository( get_configured_ui(), repo_files_dir )
|
||||
tool_metadata_dict = {}
|
||||
tool_lineage = []
|
||||
tool = None
|
||||
@@ -2195,12 +2232,18 @@ class RepositoryController( BaseUIController, ItemRatings ):
|
||||
if 'tools' in metadata:
|
||||
for tool_metadata_dict in metadata[ 'tools' ]:
|
||||
if tool_metadata_dict[ 'id' ] == tool_id:
|
||||
relative_path_to_tool_config = tool_metadata_dict[ 'tool_config' ]
|
||||
guid = tool_metadata_dict[ 'guid' ]
|
||||
try:
|
||||
# We may be attempting to load a tool that no longer exists in the repository tip.
|
||||
tool = load_tool( trans, os.path.abspath( tool_metadata_dict[ 'tool_config' ] ) )
|
||||
except:
|
||||
tool = None
|
||||
full_path = os.path.abspath( relative_path_to_tool_config )
|
||||
can_use_disk_file = can_use_tool_config_disk_file( trans, repository, repo, full_path, changeset_revision )
|
||||
if can_use_disk_file:
|
||||
tool, valid, message = load_tool_from_config( trans.app, full_path )
|
||||
else:
|
||||
# We're attempting to load a tool using a config that no longer exists on disk.
|
||||
work_dir = tempfile.mkdtemp()
|
||||
manifest_ctx, ctx_file = get_ctx_file_path_from_manifest( relative_path_to_tool_config, repo, changeset_revision )
|
||||
if manifest_ctx and ctx_file:
|
||||
tool, message = load_tool_from_tmp_config( trans, repo, manifest_ctx, ctx_file, work_dir )
|
||||
break
|
||||
if guid:
|
||||
tool_lineage = self.get_versions_of_tool( trans, repository, repository_metadata, guid )
|
||||
|
||||
@@ -48,7 +48,7 @@ class RepoToolModule( ToolModule ):
|
||||
self.errors = None
|
||||
for tool_dict in tools_metadata:
|
||||
if self.tool_id in [ tool_dict[ 'id' ], tool_dict[ 'guid' ] ]:
|
||||
self.tool, message = load_tool_from_changeset_revision( trans, repository_id, changeset_revision, tool_dict[ 'tool_config' ] )
|
||||
repository, self.tool, message = load_tool_from_changeset_revision( trans, repository_id, changeset_revision, tool_dict[ 'tool_config' ] )
|
||||
if message and self.tool is None:
|
||||
self.errors = 'unavailable'
|
||||
break
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
#!/usr/bin/env python
|
||||
"""
|
||||
# ---------------------------------------------- #
|
||||
# PARKLAB, Author: RPARK
|
||||
API example script for deleting workflows
|
||||
# ---------------------------------------------- #
|
||||
|
||||
Example calls:
|
||||
python workflow_delete.py <api_key> <galaxy_url>/api/workflows/<workflow id> True
|
||||
"""
|
||||
|
||||
import os, sys
|
||||
sys.path.insert( 0, os.path.dirname( __file__ ) )
|
||||
from common import delete
|
||||
|
||||
try:
|
||||
assert sys.argv[2]
|
||||
except IndexError:
|
||||
print 'usage: %s key url [purge (true/false)] ' % os.path.basename( sys.argv[0] )
|
||||
sys.exit( 1 )
|
||||
try:
|
||||
data = {}
|
||||
data[ 'purge' ] = sys.argv[3]
|
||||
except IndexError:
|
||||
pass
|
||||
|
||||
delete( sys.argv[1], sys.argv[2], data )
|
||||
@@ -0,0 +1,55 @@
|
||||
#!/usr/bin/env python
|
||||
"""
|
||||
# ---------------------------------------------- #
|
||||
# PARKLAB, Author: RPARK
|
||||
# ---------------------------------------------- #
|
||||
|
||||
Execute workflows from the command line.
|
||||
Example calls:
|
||||
python workflow_execute.py <api_key> <galaxy_url>/api/workflows <workflow_id> 'hist_id=<history_id>' '38=hda=<file_id>' 'param=tool=name=value'
|
||||
python workflow_execute_parameters.py <api_key> http://localhost:8080/api/workflows 1cd8e2f6b131e891 'Test API' '69=ld=a799d38679e985db' '70=ld=33b43b4e7093c91f' 'param=peakcalling_spp=aligner=bowtie' 'param=bowtie_wrapper=suppressHeader=True' 'param=peakcalling_spp=window_size=1000'
|
||||
"""
|
||||
|
||||
import os, sys
|
||||
sys.path.insert( 0, os.path.dirname( __file__ ) )
|
||||
from common import submit
|
||||
|
||||
|
||||
def main():
|
||||
try:
|
||||
print("workflow_execute:py:");
|
||||
data = {}
|
||||
data['workflow_id'] = sys.argv[3]
|
||||
data['history'] = sys.argv[4]
|
||||
data['ds_map'] = {}
|
||||
|
||||
#########################################################
|
||||
### Trying to pass in parameter for my own dictionary ###
|
||||
data['parameters'] = {};
|
||||
|
||||
# DBTODO If only one input is given, don't require a step
|
||||
# mapping, just use it for everything?
|
||||
for v in sys.argv[5:]:
|
||||
print("Multiple arguments ");
|
||||
print(v);
|
||||
|
||||
try:
|
||||
step, src, ds_id = v.split('=');
|
||||
data['ds_map'][step] = {'src':src, 'id':ds_id};
|
||||
|
||||
except ValueError:
|
||||
print("VALUE ERROR:");
|
||||
wtype, wtool, wparam, wvalue = v.split('=');
|
||||
try:
|
||||
data['parameters'][wtool] = {'param':wparam, 'value':wvalue}
|
||||
except ValueError:
|
||||
print("TOOL ID ERROR:");
|
||||
|
||||
except IndexError:
|
||||
print 'usage: %s key url workflow_id history step=src=dataset_id' % os.path.basename(sys.argv[0])
|
||||
sys.exit(1)
|
||||
submit( sys.argv[1], sys.argv[2], data )
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
|
||||
python rpark_import_workflow_from_file.py 35a24ae2643785ff3d046c98ea362c7f http://localhost:8080/api/workflows/import 'spp_submodule.ga'
|
||||
python rpark_import_workflow_from_file.py 35a24ae2643785ff3d046c98ea362c7f http://localhost:8080/api/workflows/import 'spp_submodule.ga'
|
||||
"""
|
||||
|
||||
import os, sys
|
||||
sys.path.insert( 0, os.path.dirname( __file__ ) )
|
||||
from common import submit
|
||||
|
||||
### Rpark edit ###
|
||||
import simplejson
|
||||
|
||||
def openWorkflow(in_file):
|
||||
with open(in_file) as f:
|
||||
temp_data = simplejson.load(f)
|
||||
return temp_data;
|
||||
|
||||
|
||||
|
||||
try:
|
||||
assert sys.argv[2]
|
||||
except IndexError:
|
||||
print 'usage: %s key url [name] ' % os.path.basename( sys.argv[0] )
|
||||
sys.exit( 1 )
|
||||
try:
|
||||
#data = {}
|
||||
#data[ 'name' ] = sys.argv[3]
|
||||
data = {};
|
||||
workflow_dict = openWorkflow(sys.argv[3]);
|
||||
data ['workflow'] = workflow_dict;
|
||||
|
||||
|
||||
except IndexError:
|
||||
pass
|
||||
|
||||
submit( sys.argv[1], sys.argv[2], data )
|
||||
@@ -0,0 +1,4 @@
|
||||
#!/bin/sh
|
||||
|
||||
cd `dirname $0`/../..
|
||||
python ./scripts/migrate_tools/migrate_tools.py 0004_tools.xml $@
|
||||
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0"?>
|
||||
<toolshed name="toolshed.g2.bx.psu.edu">
|
||||
<repository name="blast_datatypes" description="Datatypes for BLAST" changeset_revision="e1c29f302301" />
|
||||
<repository name="ncbi_blast_plus" description="Galaxy wrappers for NCBI BLAST+" changeset_revision="d375502056f1">
|
||||
<tool id="blastxml_to_tabular" version="0.0.8" file="blastxml_to_tabular.xml"/>
|
||||
<tool id="ncbi_blastn_wrapper" version="0.0.11" file="ncbi_blastn_wrapper.xml"/>
|
||||
<tool id="ncbi_blastp_wrapper" version="0.0.11" file="ncbi_blastp_wrapper.xml"/>
|
||||
<tool id="ncbi_blastx_wrapper" version="0.0.11" file="ncbi_blastx_wrapper.xml"/>
|
||||
<tool id="ncbi_tblastn_wrapper" version="0.0.11" file="ncbi_tblastn_wrapper.xml"/>
|
||||
<tool id="ncbi_tblastx_wrapper" version="0.0.11" file="ncbi_tblastx_wrapper.xml"/>
|
||||
</repository>
|
||||
</toolshed>
|
||||
@@ -55,6 +55,7 @@ history_queued_bg=#EEEEEE
|
||||
peek_table_header=#023858
|
||||
# Masthead
|
||||
masthead_bg=#2C3143
|
||||
masthead_bg_highlight=#333
|
||||
masthead_text=#eeeeee
|
||||
masthead_bg_hatch=-
|
||||
masthead_link=#eeeeee
|
||||
|
||||
@@ -144,7 +144,7 @@
|
||||
// -------------------------
|
||||
@navbarHeight: 32px;
|
||||
@navbarBackground: @masthead_bg;
|
||||
@navbarBackgroundHighlight: @grayDark;
|
||||
@navbarBackgroundHighlight: @masthead_bg_highlight;
|
||||
|
||||
@navbarText: @grayLight;
|
||||
@navbarLinkColor: @grayLight;
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
96c96
|
||||
< if ( drag.dragging ){
|
||||
---
|
||||
> if ( drag.dragging ) {
|
||||
99c99,101
|
||||
< }
|
||||
---
|
||||
> } else {
|
||||
> hijack( event, "dragclickonly", elem );
|
||||
> }
|
||||
|
Before Width: | Height: | Size: 48 B After Width: | Height: | Size: 48 B |
Binary file not shown.
|
Before Width: | Height: | Size: 48 B |
Vendored
-1
File diff suppressed because one or more lines are too long
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user