galaxy-commits
Threads by month
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
August 2014
- 1 participants
- 159 discussions
2 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/96abe113c582/
Changeset: 96abe113c582
Branch: next-stable
User: greg
Date: 2014-08-05 16:09:20
Summary: Fix for writing entries to shed_tool_conf.xml so that sym linked files are handled correctly (thanks Bjoern), and making changes to this and data manager config files thread-safe.
Affected #: 2 files
diff -r 7cacfb33db90dee8c4e9ce78a3a735cd6cef8490 -r 96abe113c582eed53fcf143bd516ad9cf5152c26 lib/tool_shed/galaxy_install/tools/data_manager.py
--- a/lib/tool_shed/galaxy_install/tools/data_manager.py
+++ b/lib/tool_shed/galaxy_install/tools/data_manager.py
@@ -1,5 +1,6 @@
import logging
import os
+import threading
from tool_shed.galaxy_install.tools import tool_panel_manager
@@ -18,12 +19,19 @@
Persist the current in-memory list of config_elems to a file named by the value
of config_filename.
"""
- fh = open( config_filename, 'wb' )
- fh.write( '<?xml version="1.0"?>\n<data_managers>\n' )
- for elem in config_elems:
- fh.write( xml_util.xml_to_string( elem ) )
- fh.write( '</data_managers>\n' )
- fh.close()
+ lock = threading.Lock()
+ lock.acquire( True )
+ try:
+ fh = open( config_filename, 'wb' )
+ fh.write( '<?xml version="1.0"?>\n<data_managers>\n' )
+ for elem in config_elems:
+ fh.write( xml_util.xml_to_string( elem ) )
+ fh.write( '</data_managers>\n' )
+ fh.close()
+ except Exception, e:
+ log.exception( "Exception in DataManagerHandler.data_manager_config_elems_to_xml_file: %s" % str( e ) )
+ finally:
+ lock.release()
def install_data_managers( self, shed_data_manager_conf_filename, metadata_dict, shed_config_dict,
relative_install_dir, repository, repository_tools_tups ):
diff -r 7cacfb33db90dee8c4e9ce78a3a735cd6cef8490 -r 96abe113c582eed53fcf143bd516ad9cf5152c26 lib/tool_shed/galaxy_install/tools/tool_panel_manager.py
--- a/lib/tool_shed/galaxy_install/tools/tool_panel_manager.py
+++ b/lib/tool_shed/galaxy_install/tools/tool_panel_manager.py
@@ -1,7 +1,6 @@
import logging
import os
-import shutil
-import tempfile
+import threading
import galaxy.tools
from galaxy.tools.search import ToolBoxSearch
@@ -90,15 +89,19 @@
Persist the current in-memory list of config_elems to a file named by the
value of config_filename.
"""
- fd, filename = tempfile.mkstemp( prefix="tmp-toolshed-cetxf" )
- os.write( fd, '<?xml version="1.0"?>\n' )
- os.write( fd, '<toolbox tool_path="%s">\n' % str( tool_path ) )
- for elem in config_elems:
- os.write( fd, '%s' % xml_util.xml_to_string( elem, use_indent=True ) )
- os.write( fd, '</toolbox>\n' )
- os.close( fd )
- shutil.move( filename, os.path.abspath( config_filename ) )
- os.chmod( config_filename, 0644 )
+ lock = threading.Lock()
+ lock.acquire( True )
+ try:
+ fh = open( config_filename, 'wb' )
+ fh.write( '<?xml version="1.0"?>\n<toolbox tool_path="%s">\n' % str( tool_path ) )
+ for elem in config_elems:
+ fh.write( xml_util.xml_to_string( elem, use_indent=True ) )
+ fh.write( '</toolbox>\n' )
+ fh.close()
+ except Exception, e:
+ log.exception( "Exception in ToolPanelManager.config_elems_to_xml_file: %s" % str( e ) )
+ finally:
+ lock.release()
def generate_tool_elem( self, tool_shed, repository_name, changeset_revision, owner, tool_file_path,
tool, tool_section ):
https://bitbucket.org/galaxy/galaxy-central/commits/626c583781a1/
Changeset: 626c583781a1
User: greg
Date: 2014-08-05 16:09:56
Summary: Merged next-stable
Affected #: 2 files
diff -r 213a23e98fec2ad620483e36286ce4a35b3f7c1f -r 626c583781a1d6f2d550fb3c2c4b357f1f3d5273 lib/tool_shed/galaxy_install/tools/data_manager.py
--- a/lib/tool_shed/galaxy_install/tools/data_manager.py
+++ b/lib/tool_shed/galaxy_install/tools/data_manager.py
@@ -1,5 +1,6 @@
import logging
import os
+import threading
from tool_shed.galaxy_install.tools import tool_panel_manager
@@ -18,12 +19,19 @@
Persist the current in-memory list of config_elems to a file named by the value
of config_filename.
"""
- fh = open( config_filename, 'wb' )
- fh.write( '<?xml version="1.0"?>\n<data_managers>\n' )
- for elem in config_elems:
- fh.write( xml_util.xml_to_string( elem ) )
- fh.write( '</data_managers>\n' )
- fh.close()
+ lock = threading.Lock()
+ lock.acquire( True )
+ try:
+ fh = open( config_filename, 'wb' )
+ fh.write( '<?xml version="1.0"?>\n<data_managers>\n' )
+ for elem in config_elems:
+ fh.write( xml_util.xml_to_string( elem ) )
+ fh.write( '</data_managers>\n' )
+ fh.close()
+ except Exception, e:
+ log.exception( "Exception in DataManagerHandler.data_manager_config_elems_to_xml_file: %s" % str( e ) )
+ finally:
+ lock.release()
def install_data_managers( self, shed_data_manager_conf_filename, metadata_dict, shed_config_dict,
relative_install_dir, repository, repository_tools_tups ):
diff -r 213a23e98fec2ad620483e36286ce4a35b3f7c1f -r 626c583781a1d6f2d550fb3c2c4b357f1f3d5273 lib/tool_shed/galaxy_install/tools/tool_panel_manager.py
--- a/lib/tool_shed/galaxy_install/tools/tool_panel_manager.py
+++ b/lib/tool_shed/galaxy_install/tools/tool_panel_manager.py
@@ -1,7 +1,6 @@
import logging
import os
-import shutil
-import tempfile
+import threading
import galaxy.tools
from galaxy.tools.search import ToolBoxSearch
@@ -90,15 +89,19 @@
Persist the current in-memory list of config_elems to a file named by the
value of config_filename.
"""
- fd, filename = tempfile.mkstemp( prefix="tmp-toolshed-cetxf" )
- os.write( fd, '<?xml version="1.0"?>\n' )
- os.write( fd, '<toolbox tool_path="%s">\n' % str( tool_path ) )
- for elem in config_elems:
- os.write( fd, '%s' % xml_util.xml_to_string( elem, use_indent=True ) )
- os.write( fd, '</toolbox>\n' )
- os.close( fd )
- shutil.move( filename, os.path.abspath( config_filename ) )
- os.chmod( config_filename, 0644 )
+ lock = threading.Lock()
+ lock.acquire( True )
+ try:
+ fh = open( config_filename, 'wb' )
+ fh.write( '<?xml version="1.0"?>\n<toolbox tool_path="%s">\n' % str( tool_path ) )
+ for elem in config_elems:
+ fh.write( xml_util.xml_to_string( elem, use_indent=True ) )
+ fh.write( '</toolbox>\n' )
+ fh.close()
+ except Exception, e:
+ log.exception( "Exception in ToolPanelManager.config_elems_to_xml_file: %s" % str( e ) )
+ finally:
+ lock.release()
def generate_tool_elem( self, tool_shed, repository_name, changeset_revision, owner, tool_file_path,
tool, tool_section ):
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: dannon: Merged in iracooke/galaxy-central (pull request #446)
by commits-noreply@bitbucket.org 05 Aug '14
by commits-noreply@bitbucket.org 05 Aug '14
05 Aug '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/213a23e98fec/
Changeset: 213a23e98fec
User: dannon
Date: 2014-08-05 16:00:07
Summary: Merged in iracooke/galaxy-central (pull request #446)
Metadata detection for sqlite datatype
Affected #: 1 file
diff -r a714f168aa7ddb1dfd3142f49869992cd325456c -r 213a23e98fec2ad620483e36286ce4a35b3f7c1f lib/galaxy/datatypes/binary.py
--- a/lib/galaxy/datatypes/binary.py
+++ b/lib/galaxy/datatypes/binary.py
@@ -20,7 +20,7 @@
from bx.seq.twobit import TWOBIT_MAGIC_NUMBER, TWOBIT_MAGIC_NUMBER_SWAP, TWOBIT_MAGIC_SIZE
-from galaxy.datatypes.metadata import MetadataElement
+from galaxy.datatypes.metadata import MetadataElement,ListParameter,DictParameter
from galaxy.datatypes import metadata
from galaxy.datatypes.sniff import *
import dataproviders
@@ -550,8 +550,36 @@
@dataproviders.decorators.has_dataproviders
class SQlite ( Binary ):
+ """Class describing a Sqlite database """
+ MetadataElement( name="tables", default=[], param=ListParameter, desc="Database Tables", readonly=True, visible=True, no_value=[] )
+ MetadataElement( name="table_columns", default={}, param=DictParameter, desc="Database Table Columns", readonly=True, visible=True, no_value={} )
+ MetadataElement( name="table_row_count", default={}, param=DictParameter, desc="Database Table Row Count", readonly=True, visible=True, no_value={} )
file_ext = "sqlite"
+ def init_meta( self, dataset, copy_from=None ):
+ Binary.init_meta( self, dataset, copy_from=copy_from )
+
+ def set_meta( self, dataset, overwrite = True, **kwd ):
+ try:
+ tables = []
+ columns = dict()
+ rowcounts = dict()
+ conn = sqlite3.connect(dataset.file_name)
+ c = conn.cursor()
+ tables_query = "SELECT name,sql FROM sqlite_master WHERE type='table' ORDER BY name"
+ rslt = c.execute(tables_query).fetchall()
+ for table,sql in rslt:
+ tables.append(table)
+ columns[table] = re.sub('^.*\((.*)\)$','\\1',sql).split(',')
+ for table in tables:
+ row_query = "SELECT count(*) FROM %s" % table
+ rowcounts[table] = c.execute(row_query).fetchone()[0]
+ dataset.metadata.tables = tables
+ dataset.metadata.table_columns = columns
+ dataset.metadata.table_row_count = rowcounts
+ except Exception, exc:
+ pass
+
# Connects and runs a query that should work on any real database
# If the file is not sqlite, an exception will be thrown and the sniffer will return false
def sniff( self, filename ):
@@ -568,6 +596,14 @@
def set_peek( self, dataset, is_multi_byte=False ):
if not dataset.dataset.purged:
dataset.peek = "SQLite Database"
+ lines = ['SQLite Database']
+ if dataset.metadata.tables:
+ for table in dataset.metadata.tables:
+ try:
+ lines.append('%s [%s]' % (table,dataset.metadata.table_row_count[table]))
+ except:
+ continue
+ dataset.peek = '\n'.join(lines)
dataset.blurb = data.nice_size( dataset.get_size() )
else:
dataset.peek = 'file does not exist'
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
3 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/a0db2788e912/
Changeset: a0db2788e912
User: iracooke
Date: 2014-08-01 03:31:51
Summary: Added sqlite metadata detection (from JJ)
Affected #: 1 file
diff -r 19859e3e4b1c58217c31d2f3c472359c667c2a7f -r a0db2788e9125270aec5391e676d8a0b36691233 lib/galaxy/datatypes/binary.py
--- a/lib/galaxy/datatypes/binary.py
+++ b/lib/galaxy/datatypes/binary.py
@@ -20,7 +20,7 @@
from bx.seq.twobit import TWOBIT_MAGIC_NUMBER, TWOBIT_MAGIC_NUMBER_SWAP, TWOBIT_MAGIC_SIZE
-from galaxy.datatypes.metadata import MetadataElement
+from galaxy.datatypes.metadata import MetadataElement,ListParameter,DictParameter
from galaxy.datatypes import metadata
from galaxy.datatypes.sniff import *
import dataproviders
@@ -550,8 +550,36 @@
@dataproviders.decorators.has_dataproviders
class SQlite ( Binary ):
+ """Class describing a Sqlite database """
+ MetadataElement( name="tables", default=[], param=ListParameter, desc="Database Tables", readonly=True, visible=True, no_value=[] )
+ MetadataElement( name="table_columns", default={}, param=DictParameter, desc="Database Table Columns", readonly=True, visible=True, no_value={} )
+ MetadataElement( name="table_row_count", default={}, param=DictParameter, desc="Database Table Row Count", readonly=True, visible=True, no_value={} )
file_ext = "sqlite"
+ def init_meta( self, dataset, copy_from=None ):
+ Binary.init_meta( self, dataset, copy_from=copy_from )
+
+ def set_meta( self, dataset, overwrite = True, **kwd ):
+ try:
+ tables = []
+ columns = dict()
+ rowcounts = dict()
+ conn = sqlite3.connect(dataset.file_name)
+ c = conn.cursor()
+ tables_query = "SELECT name,sql FROM sqlite_master WHERE type='table' ORDER BY name"
+ rslt = c.execute(tables_query).fetchall()
+ for table,sql in rslt:
+ tables.append(table)
+ columns[table] = re.sub('^.*\((.*)\)$','\\1',sql).split(',')
+ for table in tables:
+ row_query = "SELECT count(*) FROM %s" % table
+ rowcounts[table] = c.execute(row_query).fetchone()[0]
+ dataset.metadata.tables = tables
+ dataset.metadata.table_columns = columns
+ dataset.metadata.table_row_count = rowcounts
+ except Exception, exc:
+ pass
+
# Connects and runs a query that should work on any real database
# If the file is not sqlite, an exception will be thrown and the sniffer will return false
def sniff( self, filename ):
@@ -568,6 +596,14 @@
def set_peek( self, dataset, is_multi_byte=False ):
if not dataset.dataset.purged:
dataset.peek = "SQLite Database"
+ lines = ['SQLite Database']
+ if dataset.metadata.tables:
+ for table in dataset.metadata.tables:
+ try:
+ lines.append('%s [%s]' % (table,dataset.metadata.table_row_count[table]))
+ except:
+ continue
+ dataset.peek = '\n'.join(lines)
dataset.blurb = data.nice_size( dataset.get_size() )
else:
dataset.peek = 'file does not exist'
https://bitbucket.org/galaxy/galaxy-central/commits/7dd390cfd674/
Changeset: 7dd390cfd674
User: iracooke
Date: 2014-08-01 03:33:22
Summary: Merged galaxy/galaxy-central into default
Affected #: 50 files
diff -r a0db2788e9125270aec5391e676d8a0b36691233 -r 7dd390cfd674cae4c2833fb36f9b4875576cb1c0 .hgtags
--- a/.hgtags
+++ b/.hgtags
@@ -7,6 +7,13 @@
26f58e05aa1068761660681583821e21e6cbf7ab release_2013.11.04
5e605ed6069fe4c5ca9875e95e91b2713499e8ca release_2014.02.10
9e53251b0b7e93b9563008a2b112f2e815a04bbc release_2014.04.14
-68a8b0397947c732b28207d465d3f3c4e2a7a8a0 latest_2014.04.14
7e257c7b10badb65772b1528cb61d58175a42e47 release_2014.06.02
-8a863a311a6c9f14b302799bffcf94df9186fef7 latest_2014.06.02
+8c30e91bc9ae19ee4dc7ec2c22fa825979497108 latest_2014.06.02
+9661b9d5d5b330483ae3ad2236410e0efaa7c500 latest_2014.04.14
+6b0bd93038a843b1585155f0d63f0eea2459c70b latest_2013.01.13
+3e62060b14b9afc46f8e0ec02e1a4500d77db9e1 latest_2013.02.08
+425009b3ff4d8b67d2812253b221f3c4f4a8d1e3 latest_2013.04.01
+9713d86392ef985ffcdc39ff0c8ddf51a1f9ce47 latest_2013.06.03
+9ed84cd208e07e8985ec917cb025fcbbb09edcfb latest_2013.08.12
+81fbe25bd02edcd53065e8e4476dd1dfb5a72cf2 latest_2013.11.04
+2a756ca2cb1826db7796018e77d12e2dd7b67603 latest_2014.02.10
diff -r a0db2788e9125270aec5391e676d8a0b36691233 -r 7dd390cfd674cae4c2833fb36f9b4875576cb1c0 lib/galaxy/util/__init__.py
--- a/lib/galaxy/util/__init__.py
+++ b/lib/galaxy/util/__init__.py
@@ -714,11 +714,11 @@
def object_to_string( obj ):
- return binascii.hexlify( pickle.dumps( obj, 2 ) )
+ return binascii.hexlify( obj )
def string_to_object( s ):
- return pickle.loads( binascii.unhexlify( s ) )
+ return binascii.unhexlify( s )
class ParamsWithSpecs( collections.defaultdict ):
diff -r a0db2788e9125270aec5391e676d8a0b36691233 -r 7dd390cfd674cae4c2833fb36f9b4875576cb1c0 lib/galaxy/webapps/galaxy/controllers/ucsc_proxy.py
--- a/lib/galaxy/webapps/galaxy/controllers/ucsc_proxy.py
+++ b/lib/galaxy/webapps/galaxy/controllers/ucsc_proxy.py
@@ -5,6 +5,7 @@
from galaxy.web.base.controller import *
import sys
+import json
from galaxy import web, util
import re, urllib, logging
@@ -33,7 +34,7 @@
try:
store = params.get("__GALAXY__", None)
if store:
- store = util.string_to_object(store)
+ store = json.loads(util.string_to_object(store))
else:
store = {}
UCSC_URL = 'UCSC_URL'
@@ -86,7 +87,7 @@
# Serialize store into a form element
store_text = "<INPUT TYPE=\"HIDDEN\" NAME=\"__GALAXY__\" ID=\"__GALAXY__\" VALUE=\"" \
- + util.object_to_string(store) + "\" \>"
+ + json.dumps(util.object_to_string(store)) + "\" \>"
# Remove text regions that should not be exposed
for key,value in altered_regions.items():
diff -r a0db2788e9125270aec5391e676d8a0b36691233 -r 7dd390cfd674cae4c2833fb36f9b4875576cb1c0 lib/galaxy/webapps/tool_shed/controllers/repository.py
--- a/lib/galaxy/webapps/tool_shed/controllers/repository.py
+++ b/lib/galaxy/webapps/tool_shed/controllers/repository.py
@@ -20,13 +20,13 @@
from tool_shed.galaxy_install import dependency_display
from tool_shed.metadata import repository_metadata_manager
+from tool_shed.utility_containers import ToolShedUtilityContainerManager
from tool_shed.tools import tool_validator
from tool_shed.tools import tool_version_manager
from tool_shed.util import basic_util
from tool_shed.util import common_util
-from tool_shed.util import container_util
from tool_shed.util import encoding_util
from tool_shed.util import hg_util
from tool_shed.util import metadata_util
@@ -1273,12 +1273,12 @@
# Only display repository dependencies if they exist.
exclude = [ 'datatypes', 'invalid_repository_dependencies', 'invalid_tool_dependencies', 'invalid_tools',
'readme_files', 'tool_dependencies', 'tools', 'tool_test_results', 'workflows', 'data_manager' ]
- containers_dict = container_util.build_repository_containers_for_tool_shed( trans.app,
- repository,
- changeset_revision,
- repository_dependencies,
- repository_metadata,
- exclude=exclude )
+ tsucm = ToolShedUtilityContainerManager( trans.app )
+ containers_dict = tsucm.build_repository_containers( repository,
+ changeset_revision,
+ repository_dependencies,
+ repository_metadata,
+ exclude=exclude )
export_repository_dependencies_check_box = CheckboxField( 'export_repository_dependencies', checked=True )
else:
containers_dict = None
@@ -2458,11 +2458,11 @@
skip_tool_tests_check_box = CheckboxField( 'skip_tool_tests', checked=skip_tool_tests_checked )
categories = suc.get_categories( trans.app )
selected_categories = [ rca.category_id for rca in repository.categories ]
- containers_dict = container_util.build_repository_containers_for_tool_shed( trans.app,
- repository,
- changeset_revision,
- repository_dependencies,
- repository_metadata )
+ tsucm = ToolShedUtilityContainerManager( trans.app )
+ containers_dict = tsucm.build_repository_containers( repository,
+ changeset_revision,
+ repository_dependencies,
+ repository_metadata )
heads = hg_util.get_repository_heads( repo )
deprecated_repository_dependency_tups = \
metadata_util.get_repository_dependency_tups_from_repository_metadata( trans.app,
@@ -2653,11 +2653,11 @@
selected_value=changeset_revision,
add_id_to_name=False,
downloadable=False )
- containers_dict = container_util.build_repository_containers_for_tool_shed( trans.app,
- repository,
- changeset_revision,
- repository_dependencies,
- repository_metadata )
+ tsucm = ToolShedUtilityContainerManager( trans.app )
+ containers_dict = tsucm.build_repository_containers( repository,
+ changeset_revision,
+ repository_dependencies,
+ repository_metadata )
return trans.fill_template( '/webapps/tool_shed/repository/preview_tools_in_changeset.mako',
repository=repository,
containers_dict=containers_dict,
@@ -3360,11 +3360,11 @@
else:
message += malicious_error
status = 'error'
- containers_dict = container_util.build_repository_containers_for_tool_shed( trans.app,
- repository,
- changeset_revision,
- repository_dependencies,
- repository_metadata )
+ tsucm = ToolShedUtilityContainerManager( trans.app )
+ containers_dict = tsucm.build_repository_containers( repository,
+ changeset_revision,
+ repository_dependencies,
+ repository_metadata )
repository_type_select_field = rt_util.build_repository_type_select_field( trans, repository=repository )
heads = hg_util.get_repository_heads( repo )
return trans.fill_template( '/webapps/tool_shed/repository/view_repository.mako',
diff -r a0db2788e9125270aec5391e676d8a0b36691233 -r 7dd390cfd674cae4c2833fb36f9b4875576cb1c0 lib/galaxy/webapps/tool_shed/controllers/repository_review.py
--- a/lib/galaxy/webapps/tool_shed/controllers/repository_review.py
+++ b/lib/galaxy/webapps/tool_shed/controllers/repository_review.py
@@ -1,17 +1,26 @@
-import os, logging
-from galaxy import web, util
+import logging
+import os
+
+from sqlalchemy.sql.expression import func
+
+from galaxy import util
+from galaxy import web
+
+from galaxy.model.orm import and_
+from galaxy.util.odict import odict
from galaxy.web.base.controller import BaseUIController
-from galaxy.web.form_builder import SelectField, CheckboxField
-from sqlalchemy.sql.expression import func
-from galaxy.model.orm import and_
+from galaxy.web.form_builder import CheckboxField
+from galaxy.web.form_builder import SelectField
+
from galaxy.webapps.tool_shed.util import ratings_util
+
+import tool_shed.grids.repository_review_grids as repository_review_grids
+import tool_shed.grids.util as grids_util
+
from tool_shed.util.container_util import STRSEP
-import tool_shed.util.shed_util_common as suc
from tool_shed.util import hg_util
from tool_shed.util import review_util
-from galaxy.util.odict import odict
-import tool_shed.grids.repository_review_grids as repository_review_grids
-import tool_shed.grids.util as grids_util
+from tool_shed.util import shed_util_common as suc
log = logging.getLogger( __name__ )
diff -r a0db2788e9125270aec5391e676d8a0b36691233 -r 7dd390cfd674cae4c2833fb36f9b4875576cb1c0 lib/tool_shed/dependencies/repository/relation_builder.py
--- a/lib/tool_shed/dependencies/repository/relation_builder.py
+++ b/lib/tool_shed/dependencies/repository/relation_builder.py
@@ -3,6 +3,7 @@
from galaxy.util import asbool
from galaxy.util import listify
+
from tool_shed.util import common_util
from tool_shed.util import container_util
from tool_shed.util import hg_util
diff -r a0db2788e9125270aec5391e676d8a0b36691233 -r 7dd390cfd674cae4c2833fb36f9b4875576cb1c0 lib/tool_shed/galaxy_install/dependency_display.py
--- a/lib/tool_shed/galaxy_install/dependency_display.py
+++ b/lib/tool_shed/galaxy_install/dependency_display.py
@@ -5,6 +5,9 @@
from galaxy import util
+from tool_shed.galaxy_install.utility_containers import GalaxyUtilityContainerManager
+from tool_shed.utility_containers import utility_container_manager
+
from tool_shed.util import common_util
from tool_shed.util import container_util
from tool_shed.util import readme_util
@@ -276,22 +279,23 @@
old_container_repository_dependencies_root = old_container_dict[ 'repository_dependencies' ]
if old_container_repository_dependencies_root:
if repository_dependencies_root_folder is None:
- repository_dependencies_root_folder = container_util.Folder( id=folder_id,
- key='root',
- label='root',
- parent=None )
+ repository_dependencies_root_folder = utility_container_manager.Folder( id=folder_id,
+ key='root',
+ label='root',
+ parent=None )
folder_id += 1
- repository_dependencies_folder = container_util.Folder( id=folder_id,
- key='merged',
- label='Repository dependencies',
- parent=repository_dependencies_root_folder )
+ repository_dependencies_folder = utility_container_manager.Folder( id=folder_id,
+ key='merged',
+ label='Repository dependencies',
+ parent=repository_dependencies_root_folder )
folder_id += 1
# The old_container_repository_dependencies_root will be a root folder containing a single sub_folder.
old_container_repository_dependencies_folder = old_container_repository_dependencies_root.folders[ 0 ]
# Change the folder id so it won't confict with others being merged.
old_container_repository_dependencies_folder.id = folder_id
folder_id += 1
- repository_components_tuple = container_util.get_components_from_key( old_container_repository_dependencies_folder.key )
+ repository_components_tuple = \
+ container_util.get_components_from_key( old_container_repository_dependencies_folder.key )
components_list = suc.extract_components_from_tuple( repository_components_tuple )
name = components_list[ 1 ]
# Generate the label by retrieving the repository name.
@@ -301,15 +305,15 @@
old_container_tool_dependencies_root = old_container_dict[ 'tool_dependencies' ]
if old_container_tool_dependencies_root:
if tool_dependencies_root_folder is None:
- tool_dependencies_root_folder = container_util.Folder( id=folder_id,
- key='root',
- label='root',
- parent=None )
+ tool_dependencies_root_folder = utility_container_manager.Folder( id=folder_id,
+ key='root',
+ label='root',
+ parent=None )
folder_id += 1
- tool_dependencies_folder = container_util.Folder( id=folder_id,
- key='merged',
- label='Tool dependencies',
- parent=tool_dependencies_root_folder )
+ tool_dependencies_folder = utility_container_manager.Folder( id=folder_id,
+ key='merged',
+ label='Tool dependencies',
+ parent=tool_dependencies_root_folder )
folder_id += 1
else:
td_list = [ td.listify for td in tool_dependencies_folder.tool_dependencies ]
@@ -410,23 +414,22 @@
repository_missing_tool_dependencies=missing_tool_dependencies,
required_repo_info_dicts=None )
# Most of the repository contents are set to None since we don't yet know what they are.
- containers_dict = \
- container_util.build_repository_containers_for_galaxy( app=self.app,
- repository=None,
- datatypes=None,
- invalid_tools=None,
- missing_repository_dependencies=missing_repository_dependencies,
- missing_tool_dependencies=missing_tool_dependencies,
- readme_files_dict=readme_files_dict,
- repository_dependencies=installed_repository_dependencies,
- tool_dependencies=installed_tool_dependencies,
- valid_tools=None,
- workflows=None,
- valid_data_managers=None,
- invalid_data_managers=None,
- data_managers_errors=None,
- new_install=True,
- reinstalling=False )
+ gucm = GalaxyUtilityContainerManager( self.app )
+ containers_dict = gucm.build_repository_containers( repository=None,
+ datatypes=None,
+ invalid_tools=None,
+ missing_repository_dependencies=missing_repository_dependencies,
+ missing_tool_dependencies=missing_tool_dependencies,
+ readme_files_dict=readme_files_dict,
+ repository_dependencies=installed_repository_dependencies,
+ tool_dependencies=installed_tool_dependencies,
+ valid_tools=None,
+ workflows=None,
+ valid_data_managers=None,
+ invalid_data_managers=None,
+ data_managers_errors=None,
+ new_install=True,
+ reinstalling=False )
if not updating:
# If we installing a new repository and not updaing an installed repository, we can merge
# the missing_repository_dependencies container contents to the installed_repository_dependencies
@@ -508,23 +511,22 @@
valid_data_managers = metadata['data_manager'].get( 'data_managers', None )
invalid_data_managers = metadata['data_manager'].get( 'invalid_data_managers', None )
data_managers_errors = metadata['data_manager'].get( 'messages', None )
- containers_dict = \
- container_util.build_repository_containers_for_galaxy( app=self.app,
- repository=repository,
- datatypes=datatypes,
- invalid_tools=invalid_tools,
- missing_repository_dependencies=missing_repository_dependencies,
- missing_tool_dependencies=missing_tool_dependencies,
- readme_files_dict=readme_files_dict,
- repository_dependencies=installed_repository_dependencies,
- tool_dependencies=installed_tool_dependencies,
- valid_tools=valid_tools,
- workflows=workflows,
- valid_data_managers=valid_data_managers,
- invalid_data_managers=invalid_data_managers,
- data_managers_errors=data_managers_errors,
- new_install=False,
- reinstalling=reinstalling )
+ gucm = GalaxyUtilityContainerManager( self.app )
+ containers_dict = gucm.build_repository_containers( repository=repository,
+ datatypes=datatypes,
+ invalid_tools=invalid_tools,
+ missing_repository_dependencies=missing_repository_dependencies,
+ missing_tool_dependencies=missing_tool_dependencies,
+ readme_files_dict=readme_files_dict,
+ repository_dependencies=installed_repository_dependencies,
+ tool_dependencies=installed_tool_dependencies,
+ valid_tools=valid_tools,
+ workflows=workflows,
+ valid_data_managers=valid_data_managers,
+ invalid_data_managers=invalid_data_managers,
+ data_managers_errors=data_managers_errors,
+ new_install=False,
+ reinstalling=reinstalling )
else:
containers_dict = dict( datatypes=None,
invalid_tools=None,
diff -r a0db2788e9125270aec5391e676d8a0b36691233 -r 7dd390cfd674cae4c2833fb36f9b4875576cb1c0 lib/tool_shed/galaxy_install/utility_containers/__init__.py
--- /dev/null
+++ b/lib/tool_shed/galaxy_install/utility_containers/__init__.py
@@ -0,0 +1,145 @@
+import logging
+import os
+import threading
+
+from tool_shed.utility_containers import utility_container_manager
+
+log = logging.getLogger( __name__ )
+
+
+class GalaxyUtilityContainerManager( utility_container_manager.UtilityContainerManager ):
+
+ def __init__( self, app ):
+ self.app = app
+
+ def build_repository_containers( self, repository, datatypes, invalid_tools, missing_repository_dependencies,
+ missing_tool_dependencies, readme_files_dict, repository_dependencies,
+ tool_dependencies, valid_tools, workflows, valid_data_managers,
+ invalid_data_managers, data_managers_errors, new_install=False,
+ reinstalling=False ):
+ """
+ Return a dictionary of containers for the received repository's dependencies and readme files for
+ display during installation to Galaxy.
+ """
+ containers_dict = dict( datatypes=None,
+ invalid_tools=None,
+ missing_tool_dependencies=None,
+ readme_files=None,
+ repository_dependencies=None,
+ missing_repository_dependencies=None,
+ tool_dependencies=None,
+ valid_tools=None,
+ workflows=None,
+ valid_data_managers=None,
+ invalid_data_managers=None )
+ # Some of the tool dependency folders will include links to display tool dependency information, and
+ # some of these links require the repository id. However we need to be careful because sometimes the
+ # repository object is None.
+ if repository:
+ repository_id = repository.id
+ changeset_revision = repository.changeset_revision
+ else:
+ repository_id = None
+ changeset_revision = None
+ lock = threading.Lock()
+ lock.acquire( True )
+ try:
+ folder_id = 0
+ # Datatypes container.
+ if datatypes:
+ folder_id, datatypes_root_folder = self.build_datatypes_folder( folder_id, datatypes )
+ containers_dict[ 'datatypes' ] = datatypes_root_folder
+ # Invalid tools container.
+ if invalid_tools:
+ folder_id, invalid_tools_root_folder = \
+ self.build_invalid_tools_folder( folder_id,
+ invalid_tools,
+ changeset_revision,
+ repository=repository,
+ label='Invalid tools' )
+ containers_dict[ 'invalid_tools' ] = invalid_tools_root_folder
+ # Readme files container.
+ if readme_files_dict:
+ folder_id, readme_files_root_folder = self.build_readme_files_folder( folder_id, readme_files_dict )
+ containers_dict[ 'readme_files' ] = readme_files_root_folder
+ # Installed repository dependencies container.
+ if repository_dependencies:
+ if new_install:
+ label = 'Repository dependencies'
+ else:
+ label = 'Installed repository dependencies'
+ folder_id, repository_dependencies_root_folder = \
+ self.build_repository_dependencies_folder( folder_id=folder_id,
+ repository_dependencies=repository_dependencies,
+ label=label,
+ installed=True )
+ containers_dict[ 'repository_dependencies' ] = repository_dependencies_root_folder
+ # Missing repository dependencies container.
+ if missing_repository_dependencies:
+ folder_id, missing_repository_dependencies_root_folder = \
+ self.build_repository_dependencies_folder( folder_id=folder_id,
+ repository_dependencies=missing_repository_dependencies,
+ label='Missing repository dependencies',
+ installed=False )
+ containers_dict[ 'missing_repository_dependencies' ] = missing_repository_dependencies_root_folder
+ # Installed tool dependencies container.
+ if tool_dependencies:
+ if new_install:
+ label = 'Tool dependencies'
+ else:
+ label = 'Installed tool dependencies'
+ # We only want to display the Status column if the tool_dependency is missing.
+ folder_id, tool_dependencies_root_folder = \
+ self.build_tool_dependencies_folder( folder_id,
+ tool_dependencies,
+ label=label,
+ missing=False,
+ new_install=new_install,
+ reinstalling=reinstalling )
+ containers_dict[ 'tool_dependencies' ] = tool_dependencies_root_folder
+ # Missing tool dependencies container.
+ if missing_tool_dependencies:
+ # We only want to display the Status column if the tool_dependency is missing.
+ folder_id, missing_tool_dependencies_root_folder = \
+ self.build_tool_dependencies_folder( folder_id,
+ missing_tool_dependencies,
+ label='Missing tool dependencies',
+ missing=True,
+ new_install=new_install,
+ reinstalling=reinstalling )
+ containers_dict[ 'missing_tool_dependencies' ] = missing_tool_dependencies_root_folder
+ # Valid tools container.
+ if valid_tools:
+ folder_id, valid_tools_root_folder = self.build_tools_folder( folder_id,
+ valid_tools,
+ repository,
+ changeset_revision,
+ label='Valid tools' )
+ containers_dict[ 'valid_tools' ] = valid_tools_root_folder
+ # Workflows container.
+ if workflows:
+ folder_id, workflows_root_folder = \
+ self.build_workflows_folder( folder_id=folder_id,
+ workflows=workflows,
+ repository_metadata_id=None,
+ repository_id=repository_id,
+ label='Workflows' )
+ containers_dict[ 'workflows' ] = workflows_root_folder
+ if valid_data_managers:
+ folder_id, valid_data_managers_root_folder = \
+ self.build_data_managers_folder( folder_id=folder_id,
+ data_managers=valid_data_managers,
+ label='Valid Data Managers' )
+ containers_dict[ 'valid_data_managers' ] = valid_data_managers_root_folder
+ if invalid_data_managers or data_managers_errors:
+ folder_id, invalid_data_managers_root_folder = \
+ self.build_invalid_data_managers_folder( folder_id=folder_id,
+ data_managers=invalid_data_managers,
+ error_messages=data_managers_errors,
+ label='Invalid Data Managers' )
+ containers_dict[ 'invalid_data_managers' ] = invalid_data_managers_root_folder
+ except Exception, e:
+ log.debug( "Exception in build_repository_containers: %s" % str( e ) )
+ finally:
+ lock.release()
+ return containers_dict
diff -r a0db2788e9125270aec5391e676d8a0b36691233 -r 7dd390cfd674cae4c2833fb36f9b4875576cb1c0 lib/tool_shed/grids/repository_grid_filter_manager.py
--- a/lib/tool_shed/grids/repository_grid_filter_manager.py
+++ b/lib/tool_shed/grids/repository_grid_filter_manager.py
@@ -27,7 +27,7 @@
return "Certified 2 Repository Suites %s" % trailing_string
if filter == self.filters.SUITES:
return "Repository Suites %s" % trailing_string
- return "%s" % default
+ return "%s %s" % ( default, trailing_string )
def get_filter( self, trans ):
filter = trans.get_cookie( name='toolshedrepogridfilter' )
This diff is so big that we needed to truncate the remainder.
https://bitbucket.org/galaxy/galaxy-central/commits/213a23e98fec/
Changeset: 213a23e98fec
User: dannon
Date: 2014-08-05 16:00:07
Summary: Merged in iracooke/galaxy-central (pull request #446)
Metadata detection for sqlite datatype
Affected #: 1 file
diff -r a714f168aa7ddb1dfd3142f49869992cd325456c -r 213a23e98fec2ad620483e36286ce4a35b3f7c1f lib/galaxy/datatypes/binary.py
--- a/lib/galaxy/datatypes/binary.py
+++ b/lib/galaxy/datatypes/binary.py
@@ -20,7 +20,7 @@
from bx.seq.twobit import TWOBIT_MAGIC_NUMBER, TWOBIT_MAGIC_NUMBER_SWAP, TWOBIT_MAGIC_SIZE
-from galaxy.datatypes.metadata import MetadataElement
+from galaxy.datatypes.metadata import MetadataElement,ListParameter,DictParameter
from galaxy.datatypes import metadata
from galaxy.datatypes.sniff import *
import dataproviders
@@ -550,8 +550,36 @@
@dataproviders.decorators.has_dataproviders
class SQlite ( Binary ):
+ """Class describing a Sqlite database """
+ MetadataElement( name="tables", default=[], param=ListParameter, desc="Database Tables", readonly=True, visible=True, no_value=[] )
+ MetadataElement( name="table_columns", default={}, param=DictParameter, desc="Database Table Columns", readonly=True, visible=True, no_value={} )
+ MetadataElement( name="table_row_count", default={}, param=DictParameter, desc="Database Table Row Count", readonly=True, visible=True, no_value={} )
file_ext = "sqlite"
+ def init_meta( self, dataset, copy_from=None ):
+ Binary.init_meta( self, dataset, copy_from=copy_from )
+
+ def set_meta( self, dataset, overwrite = True, **kwd ):
+ try:
+ tables = []
+ columns = dict()
+ rowcounts = dict()
+ conn = sqlite3.connect(dataset.file_name)
+ c = conn.cursor()
+ tables_query = "SELECT name,sql FROM sqlite_master WHERE type='table' ORDER BY name"
+ rslt = c.execute(tables_query).fetchall()
+ for table,sql in rslt:
+ tables.append(table)
+ columns[table] = re.sub('^.*\((.*)\)$','\\1',sql).split(',')
+ for table in tables:
+ row_query = "SELECT count(*) FROM %s" % table
+ rowcounts[table] = c.execute(row_query).fetchone()[0]
+ dataset.metadata.tables = tables
+ dataset.metadata.table_columns = columns
+ dataset.metadata.table_row_count = rowcounts
+ except Exception, exc:
+ pass
+
# Connects and runs a query that should work on any real database
# If the file is not sqlite, an exception will be thrown and the sniffer will return false
def sniff( self, filename ):
@@ -568,6 +596,14 @@
def set_peek( self, dataset, is_multi_byte=False ):
if not dataset.dataset.purged:
dataset.peek = "SQLite Database"
+ lines = ['SQLite Database']
+ if dataset.metadata.tables:
+ for table in dataset.metadata.tables:
+ try:
+ lines.append('%s [%s]' % (table,dataset.metadata.table_row_count[table]))
+ except:
+ continue
+ dataset.peek = '\n'.join(lines)
dataset.blurb = data.nice_size( dataset.get_size() )
else:
dataset.peek = 'file does not exist'
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
2 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/ea4f983c227e/
Changeset: ea4f983c227e
User: jmchilton
Date: 2014-08-05 03:45:02
Summary: API tests for authenticate and some of users endpoints.
Affected #: 4 files
diff -r d4070ec86d404eec61f78a60f23536080b04ab1f -r ea4f983c227e4cac4b331699e8b7a87f9383df06 test/api/test_authenticate.py
--- /dev/null
+++ b/test/api/test_authenticate.py
@@ -0,0 +1,29 @@
+import base64
+
+from base.interactor import get_request
+from base import api
+
+
+TEST_USER_EMAIL = "auth_user_test(a)bx.psu.edu"
+TEST_USER_PASSWORD = "testpassword1"
+
+
+class AuthenticationApiTestCase( api.ApiTestCase ):
+
+ def test_auth( self ):
+ self._setup_user( TEST_USER_EMAIL, TEST_USER_PASSWORD )
+ baseauth_url = self._api_url( "authenticate/baseauth", use_key=False )
+ unencoded_credentials = "%s:%s" % ( TEST_USER_EMAIL, TEST_USER_PASSWORD )
+ authorization = base64.b64encode(unencoded_credentials)
+ headers = {
+ "Authorization": authorization,
+ }
+ auth_response = get_request( baseauth_url, headers=headers )
+ self._assert_status_code_is( auth_response, 200 )
+ auth_dict = auth_response.json()
+ self._assert_has_keys( auth_dict, "api_key" )
+
+ # Verify key...
+ random_api_url = self._api_url( "users", use_key=False )
+ random_api_response = get_request( random_api_url, params=dict( key=auth_dict[ "api_key" ] ) )
+ self._assert_status_code_is( random_api_response, 200 )
diff -r d4070ec86d404eec61f78a60f23536080b04ab1f -r ea4f983c227e4cac4b331699e8b7a87f9383df06 test/api/test_users.py
--- /dev/null
+++ b/test/api/test_users.py
@@ -0,0 +1,24 @@
+from base import api
+
+TEST_USER_EMAIL = "user_for_users_index_test(a)bx.psu.edu"
+
+
+class UsersApiTestCase( api.ApiTestCase ):
+
+ def test_index( self ):
+ self._setup_user( TEST_USER_EMAIL )
+ all_users_response = self._get( "users", admin=True )
+ self._assert_status_code_is( all_users_response, 200 )
+ all_users = all_users_response.json()
+ # New user is in list
+ assert len( [ u for u in all_users if u[ "email" ] == TEST_USER_EMAIL ] ) == 1
+ # Request made from admin user, so should at least self and this
+ # new user.
+ assert len( all_users ) > 1
+
+ def test_index_only_self_for_nonadmins( self ):
+ self._setup_user( TEST_USER_EMAIL )
+ with self._different_user( ):
+ all_users_response = self._get( "users" )
+ # Non admin users can only see themselves
+ assert len( all_users_response.json() ) == 1
diff -r d4070ec86d404eec61f78a60f23536080b04ab1f -r ea4f983c227e4cac4b331699e8b7a87f9383df06 test/base/api.py
--- a/test/base/api.py
+++ b/test/base/api.py
@@ -41,8 +41,8 @@
url = "%s?%s" % ( url, query )
return url
- def _setup_user( self, email ):
- self.galaxy_interactor.ensure_user_with_email(email)
+ def _setup_user( self, email, password=None ):
+ self.galaxy_interactor.ensure_user_with_email( email, password=password )
users = self._get( "users", admin=True ).json()
user = [ user for user in users if user["email"] == email ][0]
return user
diff -r d4070ec86d404eec61f78a60f23536080b04ab1f -r ea4f983c227e4cac4b331699e8b7a87f9383df06 test/base/interactor.py
--- a/test/base/interactor.py
+++ b/test/base/interactor.py
@@ -325,16 +325,17 @@
)
return self._post( "tools", files=files, data=data )
- def ensure_user_with_email( self, email ):
+ def ensure_user_with_email( self, email, password=None ):
admin_key = self.master_api_key
all_users = self._get( 'users', key=admin_key ).json()
try:
test_user = [ user for user in all_users if user["email"] == email ][0]
except IndexError:
username = re.sub('[^a-z-]', '--', email.lower())
+ password = password or 'testpass'
data = dict(
email=email,
- password='testuser',
+ password=password,
username=username,
)
test_user = self._post( 'users', data, key=admin_key ).json()
https://bitbucket.org/galaxy/galaxy-central/commits/a714f168aa7d/
Changeset: a714f168aa7d
User: jmchilton
Date: 2014-08-05 03:45:02
Summary: Introduce ApiKeyManager to replace and expand upon CreatedApiKeysMixin.
Affected #: 3 files
diff -r ea4f983c227e4cac4b331699e8b7a87f9383df06 -r a714f168aa7ddb1dfd3142f49869992cd325456c lib/galaxy/managers/api_keys.py
--- /dev/null
+++ b/lib/galaxy/managers/api_keys.py
@@ -0,0 +1,26 @@
+
+
+class ApiKeyManager( object ):
+
+ def __init__( self, app ):
+ self.app = app
+
+ def create_api_key( self, user ):
+ guid = self.app.security.get_new_guid()
+ new_key = self.app.model.APIKeys()
+ new_key.user_id = user.id
+ new_key.key = guid
+ sa_session = self.app.model.context
+ sa_session.add( new_key )
+ sa_session.flush()
+ return guid
+
+ def get_or_create_api_key( self, user ):
+ # Logic Galaxy has always used - but it would appear to have a race
+ # condition. Worth fixing? Would kind of need a message queue to fix
+ # in multiple process mode.
+ if user.api_keys:
+ key = user.api_keys[0].key
+ else:
+ key = self.create_api_key( user )
+ return key
diff -r ea4f983c227e4cac4b331699e8b7a87f9383df06 -r a714f168aa7ddb1dfd3142f49869992cd325456c lib/galaxy/web/base/controller.py
--- a/lib/galaxy/web/base/controller.py
+++ b/lib/galaxy/web/base/controller.py
@@ -37,6 +37,7 @@
from galaxy.model import ExtendedMetadata, ExtendedMetadataIndex, LibraryDatasetDatasetAssociation, HistoryDatasetAssociation
+from galaxy.managers import api_keys
from galaxy.datatypes.metadata import FileParameter
from galaxy.tools.parameters import RuntimeValue, visit_input_values
from galaxy.tools.parameters.basic import DataToolParameter
@@ -286,16 +287,12 @@
class CreatesApiKeysMixin:
"""
Mixing centralizing logic for creating API keys for user objects.
+
+ Deprecated - please use api_keys.ApiKeyManager for new development.
"""
def create_api_key( self, trans, user ):
- guid = trans.app.security.get_new_guid()
- new_key = trans.app.model.APIKeys()
- new_key.user_id = user.id
- new_key.key = guid
- trans.sa_session.add( new_key )
- trans.sa_session.flush()
- return guid
+ return api_keys.ApiKeyManager( trans.app ).create_api_key( user )
class SharableItemSecurityMixin:
diff -r ea4f983c227e4cac4b331699e8b7a87f9383df06 -r a714f168aa7ddb1dfd3142f49869992cd325456c lib/galaxy/webapps/galaxy/api/authenticate.py
--- a/lib/galaxy/webapps/galaxy/api/authenticate.py
+++ b/lib/galaxy/webapps/galaxy/api/authenticate.py
@@ -15,14 +15,19 @@
from urllib import unquote
from galaxy.web import _future_expose_api_anonymous as expose_api_anonymous
+from galaxy.managers import api_keys
from galaxy import exceptions
-from galaxy.web.base.controller import BaseAPIController, CreatesApiKeysMixin
+from galaxy.web.base.controller import BaseAPIController
import logging
log = logging.getLogger( __name__ )
-class AuthenticationController( BaseAPIController, CreatesApiKeysMixin ):
+class AuthenticationController( BaseAPIController ):
+
+ def __init__( self, app ):
+ super( AuthenticationController, self ).__init__( app )
+ self.api_keys_manager = api_keys.ApiKeyManager( app )
@expose_api_anonymous
def get_api_key( self, trans, **kwd ):
@@ -47,10 +52,7 @@
user = user[0]
is_valid_user = user.check_password( password )
if ( is_valid_user ):
- if user.api_keys:
- key = user.api_keys[0].key
- else:
- key = self.create_api_key( trans, user )
+ key = self.api_keys_manager.get_or_create_api_key( user )
return dict( api_key=key )
else:
raise exceptions.AuthenticationFailed()
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
04 Aug '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/d4070ec86d40/
Changeset: d4070ec86d40
User: jmchilton
Date: 2014-08-04 21:02:01
Summary: Merge next-stable.
Affected #: 6 files
diff -r cd82587fb36ecbc802931edad29372f69cee7108 -r d4070ec86d404eec61f78a60f23536080b04ab1f lib/galaxy/tools/__init__.py
--- a/lib/galaxy/tools/__init__.py
+++ b/lib/galaxy/tools/__init__.py
@@ -69,7 +69,7 @@
from galaxy.model import Workflow
from tool_shed.util import common_util
from tool_shed.util import shed_util_common as suc
-from .loader import load_tool, template_macro_params
+from .loader import load_tool, template_macro_params, raw_tool_xml_tree, imported_macro_paths
from .execute import execute as execute_job
from .wrappers import (
ToolParameterValueWrapper,
@@ -2989,6 +2989,23 @@
def get_default_history_by_trans( self, trans, create=False ):
return trans.get_history( create=create )
+ @classmethod
+ def get_externally_referenced_paths( self, path ):
+ """ Return relative paths to externally referenced files by the tool
+ described by file at `path`. External components should not assume things
+ about the structure of tool xml files (this is the tool's responsibility).
+ """
+ tree = raw_tool_xml_tree(path)
+ root = tree.getroot()
+ external_paths = []
+ for code_elem in root.findall( 'code' ):
+ external_path = code_elem.get( 'file' )
+ if external_path:
+ external_paths.append( external_path )
+ external_paths.extend( imported_macro_paths( root ) )
+ # May also need to load external citation files as well at some point.
+ return external_paths
+
class OutputParameterJSONTool( Tool ):
"""
diff -r cd82587fb36ecbc802931edad29372f69cee7108 -r d4070ec86d404eec61f78a60f23536080b04ab1f lib/galaxy/tools/loader.py
--- a/lib/galaxy/tools/loader.py
+++ b/lib/galaxy/tools/loader.py
@@ -10,7 +10,7 @@
"""
Loads tool from file system and preprocesses tool macros.
"""
- tree = parse_xml(path)
+ tree = raw_tool_xml_tree(path)
root = tree.getroot()
_import_macros(root, path)
@@ -38,14 +38,31 @@
return param_dict
+def raw_tool_xml_tree(path):
+ """ Load raw (no macro expansion) tree representation of tool represented
+ at the specified path.
+ """
+ tree = parse_xml(path)
+ return tree
+
+
+def imported_macro_paths(root):
+ macros_el = _macros_el(root)
+ return _imported_macro_paths_from_el(macros_el)
+
+
def _import_macros(root, path):
tool_dir = os.path.dirname(path)
- macros_el = root.find('macros')
+ macros_el = _macros_el(root)
if macros_el:
macro_els = _load_macros(macros_el, tool_dir)
_xml_set_children(macros_el, macro_els)
+def _macros_el(root):
+ return root.find('macros')
+
+
def _macros_of_type(root, type, el_func):
macros_el = root.find('macros')
macro_dict = {}
@@ -159,6 +176,17 @@
def _load_imported_macros(macros_el, tool_dir):
macros = []
+ for tool_relative_import_path in _imported_macro_paths_from_el(macros_el):
+ import_path = \
+ os.path.join(tool_dir, tool_relative_import_path)
+ file_macros = _load_macro_file(import_path, tool_dir)
+ macros.extend(file_macros)
+
+ return macros
+
+
+def _imported_macro_paths_from_el(macros_el):
+ imported_macro_paths = []
macro_import_els = []
if macros_el:
macro_import_els = macros_el.findall("import")
@@ -166,12 +194,8 @@
raw_import_path = macro_import_el.text
tool_relative_import_path = \
os.path.basename(raw_import_path) # Sanitize this
- import_path = \
- os.path.join(tool_dir, tool_relative_import_path)
- file_macros = _load_macro_file(import_path, tool_dir)
- macros.extend(file_macros)
-
- return macros
+ imported_macro_paths.append( tool_relative_import_path )
+ return imported_macro_paths
def _load_macro_file(path, tool_dir):
diff -r cd82587fb36ecbc802931edad29372f69cee7108 -r d4070ec86d404eec61f78a60f23536080b04ab1f lib/tool_shed/tools/tool_validator.py
--- a/lib/tool_shed/tools/tool_validator.py
+++ b/lib/tool_shed/tools/tool_validator.py
@@ -3,6 +3,7 @@
import os
import tempfile
+from galaxy.tools import Tool
from galaxy.tools import parameters
from galaxy.tools.parameters import dynamic_options
@@ -311,15 +312,14 @@
message = ''
tmp_tool_config = hg_util.get_named_tmpfile_from_ctx( ctx, ctx_file, work_dir )
if tmp_tool_config:
- element_tree, error_message = xml_util.parse_xml( tmp_tool_config )
- if element_tree is None:
+ tool_element, error_message = xml_util.parse_xml( tmp_tool_config )
+ if tool_element is None:
return tool, message
- element_tree_root = element_tree.getroot()
- # Look for code files required by the tool config.
+ # Look for external 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 = hg_util.copy_file_from_manifest( repo, ctx, code_file_name, work_dir )
+ external_paths = Tool.get_externally_referenced_paths( tmp_tool_config )
+ for path in external_paths:
+ tmp_code_file_name = hg_util.copy_file_from_manifest( repo, ctx, path, work_dir )
if tmp_code_file_name:
tmp_code_files.append( tmp_code_file_name )
tool, valid, message = self.load_tool_from_config( repository_id, tmp_tool_config )
diff -r cd82587fb36ecbc802931edad29372f69cee7108 -r d4070ec86d404eec61f78a60f23536080b04ab1f static/scripts/packed/viz/trackster/painters.js
--- a/static/scripts/packed/viz/trackster/painters.js
+++ b/static/scripts/packed/viz/trackster/painters.js
@@ -1,1 +1,1 @@
-define(["libs/underscore"],function(_){var BEFORE=1001,CONTAINS=1002,OVERLAP_START=1003,OVERLAP_END=1004,CONTAINED_BY=1005,AFTER=1006;var compute_overlap=function(first_region,second_region){var first_start=first_region[0],first_end=first_region[1],second_start=second_region[0],second_end=second_region[1],overlap;if(first_start<second_start){if(first_end<=second_start){overlap=BEFORE}else{if(first_end<=second_end){overlap=OVERLAP_START}else{overlap=CONTAINS}}}else{if(first_start>second_end){overlap=AFTER}else{if(first_end<=second_end){overlap=CONTAINED_BY}else{overlap=OVERLAP_END}}}return overlap};var is_overlap=function(first_region,second_region){var overlap=compute_overlap(first_region,second_region);return(overlap!==BEFORE&&overlap!==AFTER)};var dashedLine=function(ctx,x1,y1,x2,y2,dashLen){if(dashLen===undefined){dashLen=4}var dX=x2-x1;var dY=y2-y1;var dashes=Math.floor(Math.sqrt(dX*dX+dY*dY)/dashLen);var dashX=dX/dashes;var dashY=dY/dashes;var q;for(q=0;q<dashes;q++,x1+=dashX,y1+=dashY){if(q%2!==0){continue}ctx.fillRect(x1,y1,dashLen,1)}};var drawDownwardEquilateralTriangle=function(ctx,down_vertex_x,down_vertex_y,side_len){var x1=down_vertex_x-side_len/2,x2=down_vertex_x+side_len/2,y=down_vertex_y-Math.sqrt(side_len*3/2);ctx.beginPath();ctx.moveTo(x1,y);ctx.lineTo(x2,y);ctx.lineTo(down_vertex_x,down_vertex_y);ctx.lineTo(x1,y);ctx.strokeStyle=this.fillStyle;ctx.fill();ctx.stroke();ctx.closePath()};var Scaler=function(default_val){this.default_val=(default_val?default_val:1)};Scaler.prototype.gen_val=function(input){return this.default_val};var DrawResults=function(options){this.incomplete_features=options.incomplete_features;this.feature_mapper=options.feature_mapper};var Painter=function(data,view_start,view_end,prefs,mode){this.data=data;this.view_start=view_start;this.view_end=view_end;this.prefs=_.extend({},this.default_prefs,prefs);this.mode=mode};Painter.prototype.default_prefs={};Painter.prototype.draw=function(ctx,width,height,w_scale){};var LinePainter=function(data,view_start,view_end,prefs,mode){Painter.call(this,data,view_start,view_end,prefs,mode);if(this.prefs.min_value===undefined){this.prefs.min_value=_.min(_.map(this.data,function(d){return d[1]}))||0}if(this.prefs.max_value===undefined){this.prefs.max_value=_.max(_.map(this.data,function(d){return d[1]}))||0}};LinePainter.prototype.default_prefs={min_value:undefined,max_value:undefined,mode:"Histogram",color:"#000",overflow_color:"#F66"};LinePainter.prototype.draw=function(ctx,width,height,w_scale){var in_path=false,min_value=this.prefs.min_value,max_value=this.prefs.max_value,vertical_range=max_value-min_value,height_px=height,view_start=this.view_start,mode=this.mode,data=this.data;ctx.save();var y_zero=Math.round(height+min_value/vertical_range*height);if(mode!=="Intensity"){ctx.fillStyle="#aaa";ctx.fillRect(0,y_zero,width,1)}ctx.beginPath();var x_scaled,y,delta_x_px;if(data.length>1){delta_x_px=Math.ceil((data[1][0]-data[0][0])*w_scale)}else{delta_x_px=10}var painter_color=this.prefs.block_color||this.prefs.color,pref_color=parseInt(painter_color.slice(1),16),pref_r=(pref_color&16711680)>>16,pref_g=(pref_color&65280)>>8,pref_b=pref_color&255,top_overflow=false,bot_overflow=false;for(var i=0,len=data.length;i<len;i++){ctx.fillStyle=ctx.strokeStyle=painter_color;top_overflow=bot_overflow=false;x_scaled=Math.round((data[i][0]-view_start)*w_scale);y=data[i][1];if(y===null){if(in_path&&mode==="Filled"){ctx.lineTo(x_scaled,height_px)}in_path=false;continue}if(y<min_value){bot_overflow=true;y=min_value}else{if(y>max_value){top_overflow=true;y=max_value}}if(mode==="Histogram"){y=Math.round(y/vertical_range*height_px);ctx.fillRect(x_scaled,y_zero,delta_x_px,-y)}else{if(mode==="Intensity"){var saturation=(y-min_value)/vertical_range,new_r=Math.round(pref_r+(255-pref_r)*(1-saturation)),new_g=Math.round(pref_g+(255-pref_g)*(1-saturation)),new_b=Math.round(pref_b+(255-pref_b)*(1-saturation));ctx.fillStyle="rgb("+new_r+","+new_g+","+new_b+")";ctx.fillRect(x_scaled,0,delta_x_px,height_px)}else{y=Math.round(height_px-(y-min_value)/vertical_range*height_px);if(in_path){ctx.lineTo(x_scaled,y)}else{in_path=true;if(mode==="Filled"){ctx.moveTo(x_scaled,height_px);ctx.lineTo(x_scaled,y)}else{ctx.moveTo(x_scaled,y)}}}}ctx.fillStyle=this.prefs.overflow_color;if(top_overflow||bot_overflow){var overflow_x;if(mode==="Histogram"||mode==="Intensity"){overflow_x=delta_x_px}else{x_scaled-=2;overflow_x=4}if(top_overflow){ctx.fillRect(x_scaled,0,overflow_x,3)}if(bot_overflow){ctx.fillRect(x_scaled,height_px-3,overflow_x,3)}}ctx.fillStyle=painter_color}if(mode==="Filled"){if(in_path){ctx.lineTo(x_scaled,y_zero);ctx.lineTo(0,y_zero)}ctx.fill()}else{ctx.stroke()}ctx.restore()};var FeaturePositionMapper=function(slot_height){this.feature_positions={};this.slot_height=slot_height;this.translation=0;this.y_translation=0};FeaturePositionMapper.prototype.map_feature_data=function(feature_data,slot,x_start,x_end){if(!this.feature_positions[slot]){this.feature_positions[slot]=[]}this.feature_positions[slot].push({data:feature_data,x_start:x_start,x_end:x_end})};FeaturePositionMapper.prototype.get_feature_data=function(x,y){var slot=Math.floor((y-this.y_translation)/this.slot_height),feature_dict;if(!this.feature_positions[slot]){return null}x+=this.translation;for(var i=0;i<this.feature_positions[slot].length;i++){feature_dict=this.feature_positions[slot][i];if(x>=feature_dict.x_start&&x<=feature_dict.x_end){return feature_dict.data}}};var FeaturePainter=function(data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler){Painter.call(this,data,view_start,view_end,prefs,mode);this.alpha_scaler=(alpha_scaler?alpha_scaler:new Scaler());this.height_scaler=(height_scaler?height_scaler:new Scaler());this.max_label_length=200};FeaturePainter.prototype.default_prefs={block_color:"#FFF",connector_color:"#FFF"};_.extend(FeaturePainter.prototype,{get_required_height:function(rows_required,width){var required_height=this.get_row_height(),y_scale=required_height,mode=this.mode;if(mode==="no_detail"||mode==="Squish"||mode==="Pack"){required_height=rows_required*y_scale}return required_height+this.get_top_padding(width)},get_top_padding:function(width){return 0},draw:function(ctx,width,height,w_scale,slots){var data=this.data,view_start=this.view_start,view_end=this.view_end;ctx.save();ctx.fillStyle=this.prefs.block_color;ctx.textAlign="right";var y_scale=this.get_row_height(),feature_mapper=new FeaturePositionMapper(y_scale),x_draw_coords,incomplete_features=[];for(var i=0,len=data.length;i<len;i++){var feature=data[i],feature_uid=feature[0],feature_start=feature[1],feature_end=feature[2],slot=(slots&&slots[feature_uid]!==undefined?slots[feature_uid]:null);if((this.mode==="Dense"||slot!==null)&&(feature_start<view_end&&feature_end>view_start)){x_draw_coords=this.draw_element(ctx,this.mode,feature,slot,view_start,view_end,w_scale,y_scale,width);feature_mapper.map_feature_data(feature,slot,x_draw_coords[0],x_draw_coords[1]);if(feature_start<view_start||feature_end>view_end){incomplete_features.push(feature)}}}ctx.restore();feature_mapper.y_translation=this.get_top_padding(width);return new DrawResults({incomplete_features:incomplete_features,feature_mapper:feature_mapper})},draw_element:function(ctx,mode,feature,slot,tile_low,tile_high,w_scale,y_scale,width){return[0,0]}});var DENSE_TRACK_HEIGHT=10,NO_DETAIL_TRACK_HEIGHT=3,SQUISH_TRACK_HEIGHT=5,PACK_TRACK_HEIGHT=10,NO_DETAIL_FEATURE_HEIGHT=1,DENSE_FEATURE_HEIGHT=9,SQUISH_FEATURE_HEIGHT=3,PACK_FEATURE_HEIGHT=9,LABEL_SPACING=2,CONNECTOR_COLOR="#ccc";var LinkedFeaturePainter=function(data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler){FeaturePainter.call(this,data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler);this.draw_background_connector=true;this.draw_individual_connectors=false};_.extend(LinkedFeaturePainter.prototype,FeaturePainter.prototype,{get_row_height:function(){var mode=this.mode,height;if(mode==="Dense"){height=DENSE_TRACK_HEIGHT}else{if(mode==="no_detail"){height=NO_DETAIL_TRACK_HEIGHT}else{if(mode==="Squish"){height=SQUISH_TRACK_HEIGHT}else{height=PACK_TRACK_HEIGHT}}}return height},draw_element:function(ctx,mode,feature,slot,tile_low,tile_high,w_scale,y_scale,width){var feature_uid=feature[0],feature_start=feature[1],feature_end=feature[2],feature_name=feature[3],feature_strand=feature[4],f_start=Math.floor(Math.max(0,(feature_start-tile_low-0.5)*w_scale)),f_end=Math.ceil(Math.min(width,Math.max(0,(feature_end-tile_low-0.5)*w_scale))),draw_start=f_start,draw_end=f_end,y_start=(mode==="Dense"?0:(0+slot))*y_scale+this.get_top_padding(width),thickness,y_start,thick_start=null,thick_end=null,block_color=(!feature_strand||feature_strand==="+"||feature_strand==="."?this.prefs.block_color:this.prefs.reverse_strand_color);label_color=this.prefs.label_color;ctx.globalAlpha=this.alpha_scaler.gen_val(feature);if(mode==="Dense"){slot=1}if(mode==="no_detail"){ctx.fillStyle=block_color;ctx.fillRect(f_start,y_start+5,f_end-f_start,NO_DETAIL_FEATURE_HEIGHT)}else{var feature_ts=feature[5],feature_te=feature[6],feature_blocks=feature[7],full_height=true;if(feature_ts&&feature_te){thick_start=Math.floor(Math.max(0,(feature_ts-tile_low)*w_scale));thick_end=Math.ceil(Math.min(width,Math.max(0,(feature_te-tile_low)*w_scale)))}var thin_height,thick_height;if(mode==="Squish"){thin_height=1;thick_height=SQUISH_FEATURE_HEIGHT;full_height=false}else{if(mode==="Dense"){thin_height=5;thick_height=DENSE_FEATURE_HEIGHT}else{thin_height=5;thick_height=PACK_FEATURE_HEIGHT}}if(!feature_blocks){ctx.fillStyle=block_color;ctx.fillRect(f_start,y_start+1,f_end-f_start,thick_height);if(feature_strand&&full_height){if(feature_strand==="+"){ctx.fillStyle=ctx.canvas.manager.get_pattern("right_strand_inv")}else{if(feature_strand==="-"){ctx.fillStyle=ctx.canvas.manager.get_pattern("left_strand_inv")}}ctx.fillRect(f_start,y_start+1,f_end-f_start,thick_height)}}else{var cur_y_start,cur_height;if(mode==="Squish"||mode==="Dense"){cur_y_start=y_start+Math.floor(SQUISH_FEATURE_HEIGHT/2)+1;cur_height=1}else{if(feature_strand){cur_y_start=y_start;cur_height=thick_height}else{cur_y_start+=(SQUISH_FEATURE_HEIGHT/2)+1;cur_height=1}}if(this.draw_background_connector){if(mode==="Squish"||mode==="Dense"){ctx.fillStyle=CONNECTOR_COLOR}else{if(feature_strand){if(feature_strand==="+"){ctx.fillStyle=ctx.canvas.manager.get_pattern("right_strand")}else{if(feature_strand==="-"){ctx.fillStyle=ctx.canvas.manager.get_pattern("left_strand")}}}else{ctx.fillStyle=CONNECTOR_COLOR}}ctx.fillRect(f_start,cur_y_start,f_end-f_start,cur_height)}var start_and_height;for(var k=0,k_len=feature_blocks.length;k<k_len;k++){var block=feature_blocks[k],block_start=Math.floor(Math.max(0,(block[0]-tile_low-0.5)*w_scale)),block_end=Math.ceil(Math.min(width,Math.max((block[1]-tile_low-0.5)*w_scale))),last_block_start,last_block_end;if(block_start>block_end){continue}ctx.fillStyle=block_color;ctx.fillRect(block_start,y_start+(thick_height-thin_height)/2+1,block_end-block_start,thin_height);if(thick_start!==undefined&&feature_te>feature_ts&&!(block_start>thick_end||block_end<thick_start)){var block_thick_start=Math.max(block_start,thick_start),block_thick_end=Math.min(block_end,thick_end);ctx.fillRect(block_thick_start,y_start+1,block_thick_end-block_thick_start,thick_height);if(feature_blocks.length===1&&mode==="Pack"){if(feature_strand==="+"){ctx.fillStyle=ctx.canvas.manager.get_pattern("right_strand_inv")}else{if(feature_strand==="-"){ctx.fillStyle=ctx.canvas.manager.get_pattern("left_strand_inv")}}if(block_thick_start+14<block_thick_end){block_thick_start+=2;block_thick_end-=2}ctx.fillRect(block_thick_start,y_start+1,block_thick_end-block_thick_start,thick_height)}}if(this.draw_individual_connectors&&last_block_start){this.draw_connector(ctx,last_block_start,last_block_end,block_start,block_end,y_start)}last_block_start=block_start;last_block_end=block_end}if(mode==="Pack"){ctx.globalAlpha=1;ctx.fillStyle="white";var hscale_factor=this.height_scaler.gen_val(feature),new_height=Math.ceil(thick_height*hscale_factor),ws_height=Math.round((thick_height-new_height)/2);if(hscale_factor!==1){ctx.fillRect(f_start,cur_y_start+1,f_end-f_start,ws_height);ctx.fillRect(f_start,cur_y_start+thick_height-ws_height+1,f_end-f_start,ws_height)}}}ctx.globalAlpha=1;if(feature_name&&mode==="Pack"&&feature_start>tile_low){ctx.fillStyle=label_color;if(tile_low===0&&f_start-ctx.measureText(feature_name).width<0){ctx.textAlign="left";ctx.fillText(feature_name,f_end+LABEL_SPACING,y_start+8,this.max_label_length);draw_end+=ctx.measureText(feature_name).width+LABEL_SPACING}else{ctx.textAlign="right";ctx.fillText(feature_name,f_start-LABEL_SPACING,y_start+8,this.max_label_length);draw_start-=ctx.measureText(feature_name).width+LABEL_SPACING}}}ctx.globalAlpha=1;return[draw_start,draw_end]}});var ReadPainter=function(data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler,ref_seq,base_color_fn){FeaturePainter.call(this,data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler);this.ref_seq=(ref_seq?ref_seq.data:null);this.base_color_fn=base_color_fn};_.extend(ReadPainter.prototype,FeaturePainter.prototype,{get_row_height:function(){var height,mode=this.mode;if(mode==="Dense"){height=DENSE_TRACK_HEIGHT}else{if(mode==="Squish"){height=SQUISH_TRACK_HEIGHT}else{height=PACK_TRACK_HEIGHT;if(this.prefs.show_insertions){height*=2}}}return height},_parse_cigar:function(cigar_str){var cigar_ops="MIDNSHP=X";var blocks=[[0,0]],cur_block=blocks[0],base_pos=0,parsed_cigar=_.map(cigar_str.match(/[0-9]+[MIDNSHP=X]/g),function(op){var op_len=parseInt(op.slice(0,-1),10),op_char=op.slice(-1);if(op_char==="N"){if(cur_block[1]!==0){cur_block=[base_pos+op_len,base_pos+op_len];blocks.push(cur_block)}}else{if("ISHP".indexOf(op_char)===-1){cur_block[1]+=op_len;base_pos+=op_len}}return[cigar_ops.indexOf(op_char),op_len]});return{blocks:blocks,cigar:parsed_cigar}},draw_read:function(ctx,mode,w_scale,y_start,tile_low,tile_high,feature_start,cigar,strand,read_seq){var update_base_offset=function(offset,cig_op,cig_len){if("M=NXD".indexOf(cig_op)!==-1){offset+=cig_len}return offset},update_seq_offset=function(offset,cig_op,cig_len){if("IX".indexOf(cig_op)!==-1){offset+=cig_len}return offset},get_draw_coord=function(sequence_coord){return Math.floor(Math.max(0,(sequence_coord-tile_low-0.5)*w_scale))};ctx.textAlign="center";var tile_region=[tile_low,tile_high],base_offset=0,seq_offset=0,gap=Math.round(w_scale/2),char_width_px=ctx.canvas.manager.char_width_px,block_color=(strand==="+"?this.prefs.detail_block_color:this.prefs.reverse_strand_color),pack_mode=(mode==="Pack"),draw_height=(pack_mode?PACK_FEATURE_HEIGHT:SQUISH_FEATURE_HEIGHT),rect_y=y_start+1,paint_utils=new ReadPainterUtils(ctx,draw_height,w_scale,mode),drawing_blocks=[],s_start,s_end;var draw_last=[];var t=this._parse_cigar(cigar);cigar=t.cigar;drawing_blocks=t.blocks;for(var i=0;i<drawing_blocks.length;i++){var block=drawing_blocks[i];if(is_overlap([feature_start+block[0],feature_start+block[1]],tile_region)){s_start=get_draw_coord(feature_start+block[0]);s_end=get_draw_coord(feature_start+block[1]);if(s_start===s_end){s_end+=1}ctx.fillStyle=block_color;ctx.fillRect(s_start,rect_y,s_end-s_start,draw_height)}}for(var cig_id=0,len=cigar.length;cig_id<len;cig_id++){var cig=cigar[cig_id],cig_op="MIDNSHP=X"[cig[0]],cig_len=cig[1];var seq_start=feature_start+base_offset;s_start=get_draw_coord(seq_start);s_end=get_draw_coord(seq_start+cig_len);if(!is_overlap([seq_start,seq_start+cig_len],tile_region)){base_offset=update_base_offset(base_offset,cig_op,cig_len);seq_offset=update_seq_offset(seq_offset,cig_op,cig_len);continue}if(s_start===s_end){s_end+=1}switch(cig_op){case"H":case"S":case"P":break;case"M":base_offset+=cig_len;break;case"=":case"X":var cur_seq="";if(cig_op==="X"){cur_seq=read_seq.slice(seq_offset,seq_offset+cig_len)}else{if(this.ref_seq){cur_seq=this.ref_seq.slice(Math.max(0,seq_start-tile_low),Math.min(seq_start-tile_low+cig_len,tile_high-tile_low))}}var start_pos=Math.max(seq_start,tile_low);for(var c=0;c<cur_seq.length;c++){if(cur_seq&&!this.prefs.show_differences||cig_op==="X"){var c_start=Math.floor(Math.max(0,(start_pos+c-tile_low)*w_scale));ctx.fillStyle=this.base_color_fn(cur_seq[c]);if(pack_mode&&w_scale>char_width_px){ctx.fillText(cur_seq[c],c_start,y_start+9)}else{if(w_scale>0.05){ctx.fillRect(c_start-gap,rect_y,Math.max(1,Math.round(w_scale)),draw_height)}}}}if(cig_op==="X"){seq_offset+=cig_len}base_offset+=cig_len;break;case"N":ctx.fillStyle=CONNECTOR_COLOR;ctx.fillRect(s_start,y_start+5,s_end-s_start,1);base_offset+=cig_len;break;case"D":paint_utils.draw_deletion(s_start,rect_y,cig_len);base_offset+=cig_len;break;case"I":var insert_x_coord=s_start-gap;if(is_overlap([seq_start,seq_start+cig_len],tile_region)){var seq=read_seq.slice(seq_offset,seq_offset+cig_len);if(this.prefs.show_insertions){var x_center=s_start-(s_end-s_start)/2;if((mode==="Pack"||this.mode==="Auto")&&read_seq!==undefined&&w_scale>char_width_px){ctx.fillStyle="yellow";ctx.fillRect(x_center-gap,y_start-9,s_end-s_start,9);draw_last[draw_last.length]={type:"triangle",data:[insert_x_coord,y_start+4,5]};ctx.fillStyle=CONNECTOR_COLOR;switch(compute_overlap([seq_start,seq_start+cig_len],tile_region)){case (OVERLAP_START):seq=seq.slice(tile_low-seq_start);break;case (OVERLAP_END):seq=seq.slice(0,seq_start-tile_high);break;case (CONTAINED_BY):break;case (CONTAINS):seq=seq.slice(tile_low-seq_start,seq_start-tile_high);break}for(var c=0,str_len=seq.length;c<str_len;c++){var c_start=Math.floor(Math.max(0,(seq_start+c-tile_low)*w_scale));ctx.fillText(seq[c],c_start-(s_end-s_start)/2,y_start)}}else{ctx.fillStyle="yellow";ctx.fillRect(x_center,y_start+(this.mode!=="Dense"?2:5),s_end-s_start,(mode!=="Dense"?SQUISH_FEATURE_HEIGHT:DENSE_FEATURE_HEIGHT))}}else{if((mode==="Pack"||this.mode==="Auto")&&read_seq!==undefined&&w_scale>char_width_px){draw_last.push({type:"text",data:[seq.length,insert_x_coord,y_start+9]})}else{}}}seq_offset+=cig_len;break}}ctx.fillStyle="yellow";var item,type,data;for(var i=0;i<draw_last.length;i++){item=draw_last[i];type=item.type;data=item.data;if(type==="text"){ctx.save();ctx.font="bold "+ctx.font;ctx.fillText(data[0],data[1],data[2]);ctx.restore()}else{if(type==="triangle"){drawDownwardEquilateralTriangle(ctx,data[0],data[1],data[2])}}}},draw_element:function(ctx,mode,feature,slot,tile_low,tile_high,w_scale,y_scale,width){var feature_uid=feature[0],feature_start=feature[1],feature_end=feature[2],feature_name=feature[3],f_start=Math.floor(Math.max(-0.5*w_scale,(feature_start-tile_low-0.5)*w_scale)),f_end=Math.ceil(Math.min(width,Math.max(0,(feature_end-tile_low-0.5)*w_scale))),y_start=(mode==="Dense"?0:(0+slot))*y_scale,label_color=this.prefs.label_color;if(feature[5] instanceof Array){var connector=true;if(feature[4][1]>=tile_low&&feature[4][0]<=tile_high&&feature[4][2]){this.draw_read(ctx,mode,w_scale,y_start,tile_low,tile_high,feature[4][0],feature[4][2],feature[4][3],feature[4][4])}else{connector=false}if(feature[5][1]>=tile_low&&feature[5][0]<=tile_high&&feature[5][2]){this.draw_read(ctx,mode,w_scale,y_start,tile_low,tile_high,feature[5][0],feature[5][2],feature[5][3],feature[5][4])}else{connector=false}var b1_end=Math.ceil(Math.min(width,Math.max(-0.5*w_scale,(feature[4][1]-tile_low-0.5)*w_scale))),b2_start=Math.floor(Math.max(-0.5*w_scale,(feature[5][0]-tile_low-0.5)*w_scale));if(connector&&b2_start>b1_end){ctx.fillStyle=CONNECTOR_COLOR;dashedLine(ctx,b1_end,y_start+5,b2_start,y_start+5)}}else{this.draw_read(ctx,mode,w_scale,y_start,tile_low,tile_high,feature_start,feature[4],feature[5],feature[6])}if(mode==="Pack"&&feature_start>=tile_low&&feature_name!=="."){ctx.fillStyle=this.prefs.label_color;if(tile_low===0&&f_start-ctx.measureText(feature_name).width<0){ctx.textAlign="left";ctx.fillText(feature_name,f_end+LABEL_SPACING,y_start+9,this.max_label_length)}else{ctx.textAlign="right";ctx.fillText(feature_name,f_start-LABEL_SPACING,y_start+9,this.max_label_length)}}return[0,0]}});var ArcLinkedFeaturePainter=function(data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler){LinkedFeaturePainter.call(this,data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler);this.longest_feature_length=this.calculate_longest_feature_length();this.draw_background_connector=false;this.draw_individual_connectors=true};_.extend(ArcLinkedFeaturePainter.prototype,FeaturePainter.prototype,LinkedFeaturePainter.prototype,{calculate_longest_feature_length:function(){var longest_feature_length=0;for(var i=0,len=this.data.length;i<len;i++){var feature=this.data[i],feature_start=feature[1],feature_end=feature[2];longest_feature_length=Math.max(longest_feature_length,feature_end-feature_start)}return longest_feature_length},get_top_padding:function(width){var view_range=this.view_end-this.view_start,w_scale=width/view_range;return Math.min(128,Math.ceil((this.longest_feature_length/2)*w_scale))},draw_connector:function(ctx,block1_start,block1_end,block2_start,block2_end,y_start){var x_center=(block1_end+block2_start)/2,radius=block2_start-x_center;var angle1=Math.PI,angle2=0;if(radius>0){ctx.beginPath();ctx.arc(x_center,y_start,block2_start-x_center,Math.PI,0);ctx.stroke()}}});var Color=function(rgb,a){if(Array.isArray(rgb)){this.rgb=rgb}else{if(rgb.length==6){this.rgb=rgb.match(/.{2}/g).map(function(c){return parseInt(c,16)})}else{if(rgb.length==7){this.rgb=rgb.substring(1,7).match(/.{2}/g).map(function(c){return parseInt(c,16)})}else{this.rgb=rgb.split("").map(function(c){return parseInt(c+c,16)})}}}this.alpha=typeof(a)==="number"?a:1};Color.prototype={eval:function(){return this},toCSS:function(){if(this.alpha<1){return"rgba("+this.rgb.map(function(c){return Math.round(c)}).concat(this.alpha).join(", ")+")"}else{return"#"+this.rgb.map(function(i){i=Math.round(i);i=(i>255?255:(i<0?0:i)).toString(16);return i.length===1?"0"+i:i}).join("")}},toHSL:function(){var r=this.rgb[0]/255,g=this.rgb[1]/255,b=this.rgb[2]/255,a=this.alpha;var max=Math.max(r,g,b),min=Math.min(r,g,b);var h,s,l=(max+min)/2,d=max-min;if(max===min){h=s=0}else{s=l>0.5?d/(2-max-min):d/(max+min);switch(max){case r:h=(g-b)/d+(g<b?6:0);break;case g:h=(b-r)/d+2;break;case b:h=(r-g)/d+4;break}h/=6}return{h:h*360,s:s,l:l,a:a}},toARGB:function(){var argb=[Math.round(this.alpha*255)].concat(this.rgb);return"#"+argb.map(function(i){i=Math.round(i);i=(i>255?255:(i<0?0:i)).toString(16);return i.length===1?"0"+i:i}).join("")},mix:function(color2,weight){color1=this;var p=weight;var w=p*2-1;var a=color1.toHSL().a-color2.toHSL().a;var w1=(((w*a==-1)?w:(w+a)/(1+w*a))+1)/2;var w2=1-w1;var rgb=[color1.rgb[0]*w1+color2.rgb[0]*w2,color1.rgb[1]*w1+color2.rgb[1]*w2,color1.rgb[2]*w1+color2.rgb[2]*w2];var alpha=color1.alpha*p+color2.alpha*(1-p);return new Color(rgb,alpha)}};var LinearRamp=function(start_color,end_color,start_value,end_value){this.start_color=new Color(start_color);this.end_color=new Color(end_color);this.start_value=start_value;this.end_value=end_value;this.value_range=end_value-start_value};LinearRamp.prototype.map_value=function(value){value=Math.max(value,this.start_value);value=Math.min(value,this.end_value);value=(value-this.start_value)/this.value_range;return this.start_color.mix(this.end_color,1-value).toCSS()};var SplitRamp=function(start_color,middle_color,end_color,start_value,end_value){this.positive_ramp=new LinearRamp(middle_color,end_color,0,end_value);this.negative_ramp=new LinearRamp(middle_color,start_color,0,-start_value);this.start_value=start_value;this.end_value=end_value};SplitRamp.prototype.map_value=function(value){value=Math.max(value,this.start_value);value=Math.min(value,this.end_value);if(value>=0){return this.positive_ramp.map_value(value)}else{return this.negative_ramp.map_value(-value)}};var DiagonalHeatmapPainter=function(data,view_start,view_end,prefs,mode){Painter.call(this,data,view_start,view_end,prefs,mode);var i,len;if(this.prefs.min_value===undefined){var min_value=Infinity;for(i=0,len=this.data.length;i<len;i++){min_value=Math.min(min_value,this.data[i][5])}this.prefs.min_value=min_value}if(this.prefs.max_value===undefined){var max_value=-Infinity;for(i=0,len=this.data.length;i<len;i++){max_value=Math.max(max_value,this.data[i][5])}this.prefs.max_value=max_value}};DiagonalHeatmapPainter.prototype.default_prefs={min_value:undefined,max_value:undefined,mode:"Heatmap",pos_color:"#FF8C00",neg_color:"#4169E1"};DiagonalHeatmapPainter.prototype.draw=function(ctx,width,height,w_scale){var min_value=this.prefs.min_value,max_value=this.prefs.max_value,value_range=max_value-min_value,height_px=height,view_start=this.view_start,mode=this.mode,data=this.data,invsqrt2=1/Math.sqrt(2);var ramp=(new SplitRamp(this.prefs.neg_color,"#FFFFFF",this.prefs.pos_color,min_value,max_value));var d,s1,e1,s2,e2,value;var scale=function(p){return(p-view_start)*w_scale};ctx.save();ctx.rotate(-45*Math.PI/180);ctx.scale(invsqrt2,invsqrt2);for(var i=0,len=data.length;i<len;i++){d=data[i];s1=scale(d[1]);e1=scale(d[2]);s2=scale(d[4]);e2=scale(d[5]);value=d[6];ctx.fillStyle=(ramp.map_value(value));ctx.fillRect(s1,s2,(e1-s1),(e2-s2))}ctx.restore()};var ReadPainterUtils=function(ctx,row_height,px_per_base,mode){this.ctx=ctx;this.row_height=row_height;this.px_per_base=px_per_base;this.draw_details=(mode==="Pack"||mode==="Auto")&&(px_per_base>=ctx.canvas.manager.char_width_px);this.delete_details_thickness=0.2};_.extend(ReadPainterUtils.prototype,{draw_deletion:function(x,y,len){this.ctx.fillStyle="black";var thickness=(this.draw_details?this.delete_details_thickness:1)*this.row_height;y+=0.5*(this.row_height-thickness);this.ctx.fillRect(x,y,len*this.px_per_base,thickness)}});var VariantPainter=function(data,view_start,view_end,prefs,mode,base_color_fn){Painter.call(this,data,view_start,view_end,prefs,mode);this.base_color_fn=base_color_fn;this.divider_height=1};_.extend(VariantPainter.prototype,Painter.prototype,{get_row_height:function(){var mode=this.mode,height;if(mode==="Dense"){height=DENSE_TRACK_HEIGHT}else{if(mode==="Squish"){height=SQUISH_TRACK_HEIGHT}else{height=PACK_TRACK_HEIGHT}}return height},get_required_height:function(num_samples){var height=this.prefs.summary_height;if(num_samples>1&&this.prefs.show_sample_data){height+=this.divider_height+num_samples*this.get_row_height()}return height},draw:function(ctx,width,height,w_scale){ctx.save();var get_deletion_info=function(ref,alt){var ref_len=ref.length,alt_len=alt.length,start=0,len=1,is_delete=false;if(alt==="-"){is_delete=true;len=ref.length}else{if(ref.indexOf(alt)===0&&ref_len>alt_len){is_delete=true;len=ref_len=alt_len;start+=alt_len}}return(is_delete?{start:start,len:len}:null)};var locus_data,pos,id,ref,alt,qual,filter,sample_gts,allele_counts,variant,draw_x_start,char_x_start,draw_y_start,genotype,base_px=Math.max(1,Math.floor(w_scale)),num_samples=(this.data.length?this.data[0][7].split(",").length:0),row_height=(this.mode==="Squish"?SQUISH_TRACK_HEIGHT:PACK_TRACK_HEIGHT),feature_height=(w_scale<0.1?row_height:(this.mode==="Squish"?SQUISH_FEATURE_HEIGHT:PACK_FEATURE_HEIGHT)),draw_summary=true,paint_utils=new ReadPainterUtils(ctx,row_height,w_scale,this.mode),j;if(num_samples===1){row_height=feature_height=(w_scale<ctx.canvas.manager.char_width_px?this.prefs.summary_height:row_height);paint_utils.row_height=row_height;draw_summary=false}if(this.prefs.show_sample_data&&draw_summary){ctx.fillStyle="#F3F3F3";ctx.globalAlpha=1;ctx.fillRect(0,this.prefs.summary_height-this.divider_height,width,this.divider_height)}ctx.textAlign="center";for(var i=0;i<this.data.length;i++){locus_data=this.data[i];pos=locus_data[1];ref=locus_data[3];alt=[locus_data[4].split(",")];sample_gts=locus_data[7].split(",");allele_counts=locus_data.slice(8);alt=_.map(_.flatten(alt),function(a){var type,alt_info={},delete_info=get_deletion_info(ref,a);if(delete_info){type="deletion";_.extend(alt_info,delete_info)}else{type="snp"}return _.extend(alt_info,{type:type,value:a,})});if(pos<this.view_start||pos>this.view_end){continue}draw_x_start=Math.floor(Math.max(-0.5*w_scale,(pos-this.view_start-0.5)*w_scale));char_x_start=Math.floor(Math.max(0,(pos-this.view_start)*w_scale));if(draw_summary){ctx.fillStyle="#999999";ctx.globalAlpha=1;ctx.fillRect(draw_x_start,0,base_px,this.prefs.summary_height);draw_y_start=this.prefs.summary_height;for(j=0;j<alt.length;j++){ctx.fillStyle=(alt[j].type==="deletion"?"black":this.base_color_fn(alt[j].value));allele_frac=allele_counts/sample_gts.length;draw_height=Math.ceil(this.prefs.summary_height*allele_frac);ctx.fillRect(draw_x_start,draw_y_start-draw_height,base_px,draw_height);draw_y_start-=draw_height}}if(!this.prefs.show_sample_data){continue}draw_y_start=(draw_summary?this.prefs.summary_height+this.divider_height:0);for(j=0;j<sample_gts.length;j++,draw_y_start+=row_height){genotype=(sample_gts[j]?sample_gts[j].split(/\/|\|/):["0","0"]);variant=null;if(genotype[0]===genotype[1]){if(genotype[0]==="."){}else{if(genotype[0]!=="0"){variant=alt[parseInt(genotype[0],10)-1];ctx.globalAlpha=1}}}else{variant=(genotype[0]!=="0"?genotype[0]:genotype[1]);variant=alt[parseInt(variant,10)-1];ctx.globalAlpha=0.5}if(variant){if(variant.type==="snp"){var snp=variant.value;ctx.fillStyle=this.base_color_fn(snp);if(paint_utils.draw_details){ctx.fillText(snp,char_x_start,draw_y_start+row_height)}else{ctx.fillRect(draw_x_start,draw_y_start+1,base_px,feature_height)}}else{if(variant.type==="deletion"){paint_utils.draw_deletion(draw_x_start+base_px*variant.start,draw_y_start+1,variant.len)}else{}}}}}ctx.restore()}});return{Scaler:Scaler,LinePainter:LinePainter,LinkedFeaturePainter:LinkedFeaturePainter,ReadPainter:ReadPainter,ArcLinkedFeaturePainter:ArcLinkedFeaturePainter,DiagonalHeatmapPainter:DiagonalHeatmapPainter,VariantPainter:VariantPainter}});
\ No newline at end of file
+define(["libs/underscore"],function(_){var BEFORE=1001,CONTAINS=1002,OVERLAP_START=1003,OVERLAP_END=1004,CONTAINED_BY=1005,AFTER=1006;var compute_overlap=function(first_region,second_region){var first_start=first_region[0],first_end=first_region[1],second_start=second_region[0],second_end=second_region[1],overlap;if(first_start<second_start){if(first_end<=second_start){overlap=BEFORE}else{if(first_end<=second_end){overlap=OVERLAP_START}else{overlap=CONTAINS}}}else{if(first_start>second_end){overlap=AFTER}else{if(first_end<=second_end){overlap=CONTAINED_BY}else{overlap=OVERLAP_END}}}return overlap};var is_overlap=function(first_region,second_region){var overlap=compute_overlap(first_region,second_region);return(overlap!==BEFORE&&overlap!==AFTER)};var dashedLine=function(ctx,x1,y1,x2,y2,dashLen){if(dashLen===undefined){dashLen=4}var dX=x2-x1;var dY=y2-y1;var dashes=Math.floor(Math.sqrt(dX*dX+dY*dY)/dashLen);var dashX=dX/dashes;var dashY=dY/dashes;var q;for(q=0;q<dashes;q++,x1+=dashX,y1+=dashY){if(q%2!==0){continue}ctx.fillRect(x1,y1,dashLen,1)}};var drawDownwardEquilateralTriangle=function(ctx,down_vertex_x,down_vertex_y,side_len){var x1=down_vertex_x-side_len/2,x2=down_vertex_x+side_len/2,y=down_vertex_y-Math.sqrt(side_len*3/2);ctx.beginPath();ctx.moveTo(x1,y);ctx.lineTo(x2,y);ctx.lineTo(down_vertex_x,down_vertex_y);ctx.lineTo(x1,y);ctx.strokeStyle=this.fillStyle;ctx.fill();ctx.stroke();ctx.closePath()};var Scaler=function(default_val){this.default_val=(default_val?default_val:1)};Scaler.prototype.gen_val=function(input){return this.default_val};var DrawResults=function(options){this.incomplete_features=options.incomplete_features;this.feature_mapper=options.feature_mapper};var Painter=function(data,view_start,view_end,prefs,mode){this.data=data;this.view_start=view_start;this.view_end=view_end;this.prefs=_.extend({},this.default_prefs,prefs);this.mode=mode};Painter.prototype.default_prefs={};Painter.prototype.draw=function(ctx,width,height,w_scale){};var LinePainter=function(data,view_start,view_end,prefs,mode){Painter.call(this,data,view_start,view_end,prefs,mode);if(this.prefs.min_value===undefined){this.prefs.min_value=_.min(_.map(this.data,function(d){return d[1]}))||0}if(this.prefs.max_value===undefined){this.prefs.max_value=_.max(_.map(this.data,function(d){return d[1]}))||0}};LinePainter.prototype.default_prefs={min_value:undefined,max_value:undefined,mode:"Histogram",color:"#000",overflow_color:"#F66"};LinePainter.prototype.draw=function(ctx,width,height,w_scale){var in_path=false,min_value=this.prefs.min_value,max_value=this.prefs.max_value,vertical_range=max_value-min_value,height_px=height,view_start=this.view_start,mode=this.mode,data=this.data;ctx.save();var y_zero=Math.round(height+min_value/vertical_range*height);if(mode!=="Intensity"){ctx.fillStyle="#aaa";ctx.fillRect(0,y_zero,width,1)}ctx.beginPath();var x_scaled,y,delta_x_px;if(data.length>1){delta_x_px=Math.ceil((data[1][0]-data[0][0])*w_scale)}else{delta_x_px=10}var painter_color=this.prefs.block_color||this.prefs.color,pref_color=parseInt(painter_color.slice(1),16),pref_r=(pref_color&16711680)>>16,pref_g=(pref_color&65280)>>8,pref_b=pref_color&255,top_overflow=false,bot_overflow=false;for(var i=0,len=data.length;i<len;i++){ctx.fillStyle=ctx.strokeStyle=painter_color;top_overflow=bot_overflow=false;x_scaled=Math.ceil((data[i][0]-view_start)*w_scale);y=data[i][1];if(y===null){if(in_path&&mode==="Filled"){ctx.lineTo(x_scaled,height_px)}in_path=false;continue}if(y<min_value){bot_overflow=true;y=min_value}else{if(y>max_value){top_overflow=true;y=max_value}}if(mode==="Histogram"){y=Math.round(y/vertical_range*height_px);ctx.fillRect(x_scaled,y_zero,delta_x_px,-y)}else{if(mode==="Intensity"){var saturation=(y-min_value)/vertical_range,new_r=Math.round(pref_r+(255-pref_r)*(1-saturation)),new_g=Math.round(pref_g+(255-pref_g)*(1-saturation)),new_b=Math.round(pref_b+(255-pref_b)*(1-saturation));ctx.fillStyle="rgb("+new_r+","+new_g+","+new_b+")";ctx.fillRect(x_scaled,0,delta_x_px,height_px)}else{y=Math.round(height_px-(y-min_value)/vertical_range*height_px);if(in_path){ctx.lineTo(x_scaled,y)}else{in_path=true;if(mode==="Filled"){ctx.moveTo(x_scaled,height_px);ctx.lineTo(x_scaled,y)}else{ctx.moveTo(x_scaled,y)}}}}ctx.fillStyle=this.prefs.overflow_color;if(top_overflow||bot_overflow){var overflow_x;if(mode==="Histogram"||mode==="Intensity"){overflow_x=delta_x_px}else{x_scaled-=2;overflow_x=4}if(top_overflow){ctx.fillRect(x_scaled,0,overflow_x,3)}if(bot_overflow){ctx.fillRect(x_scaled,height_px-3,overflow_x,3)}}ctx.fillStyle=painter_color}if(mode==="Filled"){if(in_path){ctx.lineTo(x_scaled,y_zero);ctx.lineTo(0,y_zero)}ctx.fill()}else{ctx.stroke()}ctx.restore()};var FeaturePositionMapper=function(slot_height){this.feature_positions={};this.slot_height=slot_height;this.translation=0;this.y_translation=0};FeaturePositionMapper.prototype.map_feature_data=function(feature_data,slot,x_start,x_end){if(!this.feature_positions[slot]){this.feature_positions[slot]=[]}this.feature_positions[slot].push({data:feature_data,x_start:x_start,x_end:x_end})};FeaturePositionMapper.prototype.get_feature_data=function(x,y){var slot=Math.floor((y-this.y_translation)/this.slot_height),feature_dict;if(!this.feature_positions[slot]){return null}x+=this.translation;for(var i=0;i<this.feature_positions[slot].length;i++){feature_dict=this.feature_positions[slot][i];if(x>=feature_dict.x_start&&x<=feature_dict.x_end){return feature_dict.data}}};var FeaturePainter=function(data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler){Painter.call(this,data,view_start,view_end,prefs,mode);this.alpha_scaler=(alpha_scaler?alpha_scaler:new Scaler());this.height_scaler=(height_scaler?height_scaler:new Scaler());this.max_label_length=200};FeaturePainter.prototype.default_prefs={block_color:"#FFF",connector_color:"#FFF"};_.extend(FeaturePainter.prototype,{get_required_height:function(rows_required,width){var required_height=this.get_row_height(),y_scale=required_height,mode=this.mode;if(mode==="no_detail"||mode==="Squish"||mode==="Pack"){required_height=rows_required*y_scale}return required_height+this.get_top_padding(width)},get_top_padding:function(width){return 0},draw:function(ctx,width,height,w_scale,slots){var data=this.data,view_start=this.view_start,view_end=this.view_end;ctx.save();ctx.fillStyle=this.prefs.block_color;ctx.textAlign="right";var y_scale=this.get_row_height(),feature_mapper=new FeaturePositionMapper(y_scale),x_draw_coords,incomplete_features=[];for(var i=0,len=data.length;i<len;i++){var feature=data[i],feature_uid=feature[0],feature_start=feature[1],feature_end=feature[2],slot=(slots&&slots[feature_uid]!==undefined?slots[feature_uid]:null);if((this.mode==="Dense"||slot!==null)&&(feature_start<view_end&&feature_end>view_start)){x_draw_coords=this.draw_element(ctx,this.mode,feature,slot,view_start,view_end,w_scale,y_scale,width);feature_mapper.map_feature_data(feature,slot,x_draw_coords[0],x_draw_coords[1]);if(feature_start<view_start||feature_end>view_end){incomplete_features.push(feature)}}}ctx.restore();feature_mapper.y_translation=this.get_top_padding(width);return new DrawResults({incomplete_features:incomplete_features,feature_mapper:feature_mapper})},draw_element:function(ctx,mode,feature,slot,tile_low,tile_high,w_scale,y_scale,width){return[0,0]}});var DENSE_TRACK_HEIGHT=10,NO_DETAIL_TRACK_HEIGHT=3,SQUISH_TRACK_HEIGHT=5,PACK_TRACK_HEIGHT=10,NO_DETAIL_FEATURE_HEIGHT=1,DENSE_FEATURE_HEIGHT=9,SQUISH_FEATURE_HEIGHT=3,PACK_FEATURE_HEIGHT=9,LABEL_SPACING=2,CONNECTOR_COLOR="#ccc";var LinkedFeaturePainter=function(data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler){FeaturePainter.call(this,data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler);this.draw_background_connector=true;this.draw_individual_connectors=false};_.extend(LinkedFeaturePainter.prototype,FeaturePainter.prototype,{get_row_height:function(){var mode=this.mode,height;if(mode==="Dense"){height=DENSE_TRACK_HEIGHT}else{if(mode==="no_detail"){height=NO_DETAIL_TRACK_HEIGHT}else{if(mode==="Squish"){height=SQUISH_TRACK_HEIGHT}else{height=PACK_TRACK_HEIGHT}}}return height},draw_element:function(ctx,mode,feature,slot,tile_low,tile_high,w_scale,y_scale,width){var feature_uid=feature[0],feature_start=feature[1],feature_end=feature[2],feature_name=feature[3],feature_strand=feature[4],f_start=Math.floor(Math.max(0,(feature_start-tile_low-0.5)*w_scale)),f_end=Math.ceil(Math.min(width,Math.max(0,(feature_end-tile_low-0.5)*w_scale))),draw_start=f_start,draw_end=f_end,y_start=(mode==="Dense"?0:(0+slot))*y_scale+this.get_top_padding(width),thickness,y_start,thick_start=null,thick_end=null,block_color=(!feature_strand||feature_strand==="+"||feature_strand==="."?this.prefs.block_color:this.prefs.reverse_strand_color);label_color=this.prefs.label_color;ctx.globalAlpha=this.alpha_scaler.gen_val(feature);if(mode==="Dense"){slot=1}if(mode==="no_detail"){ctx.fillStyle=block_color;ctx.fillRect(f_start,y_start+5,f_end-f_start,NO_DETAIL_FEATURE_HEIGHT)}else{var feature_ts=feature[5],feature_te=feature[6],feature_blocks=feature[7],full_height=true;if(feature_ts&&feature_te){thick_start=Math.floor(Math.max(0,(feature_ts-tile_low)*w_scale));thick_end=Math.ceil(Math.min(width,Math.max(0,(feature_te-tile_low)*w_scale)))}var thin_height,thick_height;if(mode==="Squish"){thin_height=1;thick_height=SQUISH_FEATURE_HEIGHT;full_height=false}else{if(mode==="Dense"){thin_height=5;thick_height=DENSE_FEATURE_HEIGHT}else{thin_height=5;thick_height=PACK_FEATURE_HEIGHT}}if(!feature_blocks){ctx.fillStyle=block_color;ctx.fillRect(f_start,y_start+1,f_end-f_start,thick_height);if(feature_strand&&full_height){if(feature_strand==="+"){ctx.fillStyle=ctx.canvas.manager.get_pattern("right_strand_inv")}else{if(feature_strand==="-"){ctx.fillStyle=ctx.canvas.manager.get_pattern("left_strand_inv")}}ctx.fillRect(f_start,y_start+1,f_end-f_start,thick_height)}}else{var cur_y_start,cur_height;if(mode==="Squish"||mode==="Dense"){cur_y_start=y_start+Math.floor(SQUISH_FEATURE_HEIGHT/2)+1;cur_height=1}else{if(feature_strand){cur_y_start=y_start;cur_height=thick_height}else{cur_y_start+=(SQUISH_FEATURE_HEIGHT/2)+1;cur_height=1}}if(this.draw_background_connector){if(mode==="Squish"||mode==="Dense"){ctx.fillStyle=CONNECTOR_COLOR}else{if(feature_strand){if(feature_strand==="+"){ctx.fillStyle=ctx.canvas.manager.get_pattern("right_strand")}else{if(feature_strand==="-"){ctx.fillStyle=ctx.canvas.manager.get_pattern("left_strand")}}}else{ctx.fillStyle=CONNECTOR_COLOR}}ctx.fillRect(f_start,cur_y_start,f_end-f_start,cur_height)}var start_and_height;for(var k=0,k_len=feature_blocks.length;k<k_len;k++){var block=feature_blocks[k],block_start=Math.floor(Math.max(0,(block[0]-tile_low-0.5)*w_scale)),block_end=Math.ceil(Math.min(width,Math.max((block[1]-tile_low-0.5)*w_scale))),last_block_start,last_block_end;if(block_start>block_end){continue}ctx.fillStyle=block_color;ctx.fillRect(block_start,y_start+(thick_height-thin_height)/2+1,block_end-block_start,thin_height);if(thick_start!==undefined&&feature_te>feature_ts&&!(block_start>thick_end||block_end<thick_start)){var block_thick_start=Math.max(block_start,thick_start),block_thick_end=Math.min(block_end,thick_end);ctx.fillRect(block_thick_start,y_start+1,block_thick_end-block_thick_start,thick_height);if(feature_blocks.length===1&&mode==="Pack"){if(feature_strand==="+"){ctx.fillStyle=ctx.canvas.manager.get_pattern("right_strand_inv")}else{if(feature_strand==="-"){ctx.fillStyle=ctx.canvas.manager.get_pattern("left_strand_inv")}}if(block_thick_start+14<block_thick_end){block_thick_start+=2;block_thick_end-=2}ctx.fillRect(block_thick_start,y_start+1,block_thick_end-block_thick_start,thick_height)}}if(this.draw_individual_connectors&&last_block_start){this.draw_connector(ctx,last_block_start,last_block_end,block_start,block_end,y_start)}last_block_start=block_start;last_block_end=block_end}if(mode==="Pack"){ctx.globalAlpha=1;ctx.fillStyle="white";var hscale_factor=this.height_scaler.gen_val(feature),new_height=Math.ceil(thick_height*hscale_factor),ws_height=Math.round((thick_height-new_height)/2);if(hscale_factor!==1){ctx.fillRect(f_start,cur_y_start+1,f_end-f_start,ws_height);ctx.fillRect(f_start,cur_y_start+thick_height-ws_height+1,f_end-f_start,ws_height)}}}ctx.globalAlpha=1;if(feature_name&&mode==="Pack"&&feature_start>tile_low){ctx.fillStyle=label_color;if(tile_low===0&&f_start-ctx.measureText(feature_name).width<0){ctx.textAlign="left";ctx.fillText(feature_name,f_end+LABEL_SPACING,y_start+8,this.max_label_length);draw_end+=ctx.measureText(feature_name).width+LABEL_SPACING}else{ctx.textAlign="right";ctx.fillText(feature_name,f_start-LABEL_SPACING,y_start+8,this.max_label_length);draw_start-=ctx.measureText(feature_name).width+LABEL_SPACING}}}ctx.globalAlpha=1;return[draw_start,draw_end]}});var ReadPainter=function(data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler,ref_seq,base_color_fn){FeaturePainter.call(this,data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler);this.ref_seq=(ref_seq?ref_seq.data:null);this.base_color_fn=base_color_fn};_.extend(ReadPainter.prototype,FeaturePainter.prototype,{get_row_height:function(){var height,mode=this.mode;if(mode==="Dense"){height=DENSE_TRACK_HEIGHT}else{if(mode==="Squish"){height=SQUISH_TRACK_HEIGHT}else{height=PACK_TRACK_HEIGHT;if(this.prefs.show_insertions){height*=2}}}return height},_parse_cigar:function(cigar_str){var cigar_ops="MIDNSHP=X";var blocks=[[0,0]],cur_block=blocks[0],base_pos=0,parsed_cigar=_.map(cigar_str.match(/[0-9]+[MIDNSHP=X]/g),function(op){var op_len=parseInt(op.slice(0,-1),10),op_char=op.slice(-1);if(op_char==="N"){if(cur_block[1]!==0){cur_block=[base_pos+op_len,base_pos+op_len];blocks.push(cur_block)}}else{if("ISHP".indexOf(op_char)===-1){cur_block[1]+=op_len;base_pos+=op_len}}return[cigar_ops.indexOf(op_char),op_len]});return{blocks:blocks,cigar:parsed_cigar}},draw_read:function(ctx,mode,w_scale,y_start,tile_low,tile_high,feature_start,cigar,strand,read_seq){var update_base_offset=function(offset,cig_op,cig_len){if("M=NXD".indexOf(cig_op)!==-1){offset+=cig_len}return offset},update_seq_offset=function(offset,cig_op,cig_len){if("IX".indexOf(cig_op)!==-1){offset+=cig_len}return offset},get_draw_coord=function(sequence_coord){return Math.floor(Math.max(0,(sequence_coord-tile_low-0.5)*w_scale))};ctx.textAlign="center";var tile_region=[tile_low,tile_high],base_offset=0,seq_offset=0,gap=Math.round(w_scale/2),char_width_px=ctx.canvas.manager.char_width_px,block_color=(strand==="+"?this.prefs.detail_block_color:this.prefs.reverse_strand_color),pack_mode=(mode==="Pack"),draw_height=(pack_mode?PACK_FEATURE_HEIGHT:SQUISH_FEATURE_HEIGHT),rect_y=y_start+1,paint_utils=new ReadPainterUtils(ctx,draw_height,w_scale,mode),drawing_blocks=[],s_start,s_end;var draw_last=[];var t=this._parse_cigar(cigar);cigar=t.cigar;drawing_blocks=t.blocks;for(var i=0;i<drawing_blocks.length;i++){var block=drawing_blocks[i];if(is_overlap([feature_start+block[0],feature_start+block[1]],tile_region)){s_start=get_draw_coord(feature_start+block[0]);s_end=get_draw_coord(feature_start+block[1]);if(s_start===s_end){s_end+=1}ctx.fillStyle=block_color;ctx.fillRect(s_start,rect_y,s_end-s_start,draw_height)}}for(var cig_id=0,len=cigar.length;cig_id<len;cig_id++){var cig=cigar[cig_id],cig_op="MIDNSHP=X"[cig[0]],cig_len=cig[1];var seq_start=feature_start+base_offset;s_start=get_draw_coord(seq_start);s_end=get_draw_coord(seq_start+cig_len);if(!is_overlap([seq_start,seq_start+cig_len],tile_region)){base_offset=update_base_offset(base_offset,cig_op,cig_len);seq_offset=update_seq_offset(seq_offset,cig_op,cig_len);continue}if(s_start===s_end){s_end+=1}switch(cig_op){case"H":case"S":case"P":break;case"M":base_offset+=cig_len;break;case"=":case"X":var cur_seq="";if(cig_op==="X"){cur_seq=read_seq.slice(seq_offset,seq_offset+cig_len)}else{if(this.ref_seq){cur_seq=this.ref_seq.slice(Math.max(0,seq_start-tile_low),Math.min(seq_start-tile_low+cig_len,tile_high-tile_low))}}var start_pos=Math.max(seq_start,tile_low);for(var c=0;c<cur_seq.length;c++){if(cur_seq&&!this.prefs.show_differences||cig_op==="X"){var c_start=Math.floor(Math.max(0,(start_pos+c-tile_low)*w_scale));ctx.fillStyle=this.base_color_fn(cur_seq[c]);if(pack_mode&&w_scale>char_width_px){ctx.fillText(cur_seq[c],c_start,y_start+9)}else{if(w_scale>0.05){ctx.fillRect(c_start-gap,rect_y,Math.max(1,Math.round(w_scale)),draw_height)}}}}if(cig_op==="X"){seq_offset+=cig_len}base_offset+=cig_len;break;case"N":ctx.fillStyle=CONNECTOR_COLOR;ctx.fillRect(s_start,y_start+5,s_end-s_start,1);base_offset+=cig_len;break;case"D":paint_utils.draw_deletion(s_start,rect_y,cig_len);base_offset+=cig_len;break;case"I":var insert_x_coord=s_start-gap;if(is_overlap([seq_start,seq_start+cig_len],tile_region)){var seq=read_seq.slice(seq_offset,seq_offset+cig_len);if(this.prefs.show_insertions){var x_center=s_start-(s_end-s_start)/2;if((mode==="Pack"||this.mode==="Auto")&&read_seq!==undefined&&w_scale>char_width_px){ctx.fillStyle="yellow";ctx.fillRect(x_center-gap,y_start-9,s_end-s_start,9);draw_last[draw_last.length]={type:"triangle",data:[insert_x_coord,y_start+4,5]};ctx.fillStyle=CONNECTOR_COLOR;switch(compute_overlap([seq_start,seq_start+cig_len],tile_region)){case (OVERLAP_START):seq=seq.slice(tile_low-seq_start);break;case (OVERLAP_END):seq=seq.slice(0,seq_start-tile_high);break;case (CONTAINED_BY):break;case (CONTAINS):seq=seq.slice(tile_low-seq_start,seq_start-tile_high);break}for(var c=0,str_len=seq.length;c<str_len;c++){var c_start=Math.floor(Math.max(0,(seq_start+c-tile_low)*w_scale));ctx.fillText(seq[c],c_start-(s_end-s_start)/2,y_start)}}else{ctx.fillStyle="yellow";ctx.fillRect(x_center,y_start+(this.mode!=="Dense"?2:5),s_end-s_start,(mode!=="Dense"?SQUISH_FEATURE_HEIGHT:DENSE_FEATURE_HEIGHT))}}else{if((mode==="Pack"||this.mode==="Auto")&&read_seq!==undefined&&w_scale>char_width_px){draw_last.push({type:"text",data:[seq.length,insert_x_coord,y_start+9]})}else{}}}seq_offset+=cig_len;break}}ctx.fillStyle="yellow";var item,type,data;for(var i=0;i<draw_last.length;i++){item=draw_last[i];type=item.type;data=item.data;if(type==="text"){ctx.save();ctx.font="bold "+ctx.font;ctx.fillText(data[0],data[1],data[2]);ctx.restore()}else{if(type==="triangle"){drawDownwardEquilateralTriangle(ctx,data[0],data[1],data[2])}}}},draw_element:function(ctx,mode,feature,slot,tile_low,tile_high,w_scale,y_scale,width){var feature_uid=feature[0],feature_start=feature[1],feature_end=feature[2],feature_name=feature[3],f_start=Math.floor(Math.max(-0.5*w_scale,(feature_start-tile_low-0.5)*w_scale)),f_end=Math.ceil(Math.min(width,Math.max(0,(feature_end-tile_low-0.5)*w_scale))),y_start=(mode==="Dense"?0:(0+slot))*y_scale,label_color=this.prefs.label_color;if(feature[5] instanceof Array){var connector=true;if(feature[4][1]>=tile_low&&feature[4][0]<=tile_high&&feature[4][2]){this.draw_read(ctx,mode,w_scale,y_start,tile_low,tile_high,feature[4][0],feature[4][2],feature[4][3],feature[4][4])}else{connector=false}if(feature[5][1]>=tile_low&&feature[5][0]<=tile_high&&feature[5][2]){this.draw_read(ctx,mode,w_scale,y_start,tile_low,tile_high,feature[5][0],feature[5][2],feature[5][3],feature[5][4])}else{connector=false}var b1_end=Math.ceil(Math.min(width,Math.max(-0.5*w_scale,(feature[4][1]-tile_low-0.5)*w_scale))),b2_start=Math.floor(Math.max(-0.5*w_scale,(feature[5][0]-tile_low-0.5)*w_scale));if(connector&&b2_start>b1_end){ctx.fillStyle=CONNECTOR_COLOR;dashedLine(ctx,b1_end,y_start+5,b2_start,y_start+5)}}else{this.draw_read(ctx,mode,w_scale,y_start,tile_low,tile_high,feature_start,feature[4],feature[5],feature[6])}if(mode==="Pack"&&feature_start>=tile_low&&feature_name!=="."){ctx.fillStyle=this.prefs.label_color;if(tile_low===0&&f_start-ctx.measureText(feature_name).width<0){ctx.textAlign="left";ctx.fillText(feature_name,f_end+LABEL_SPACING,y_start+9,this.max_label_length)}else{ctx.textAlign="right";ctx.fillText(feature_name,f_start-LABEL_SPACING,y_start+9,this.max_label_length)}}return[0,0]}});var ArcLinkedFeaturePainter=function(data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler){LinkedFeaturePainter.call(this,data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler);this.longest_feature_length=this.calculate_longest_feature_length();this.draw_background_connector=false;this.draw_individual_connectors=true};_.extend(ArcLinkedFeaturePainter.prototype,FeaturePainter.prototype,LinkedFeaturePainter.prototype,{calculate_longest_feature_length:function(){var longest_feature_length=0;for(var i=0,len=this.data.length;i<len;i++){var feature=this.data[i],feature_start=feature[1],feature_end=feature[2];longest_feature_length=Math.max(longest_feature_length,feature_end-feature_start)}return longest_feature_length},get_top_padding:function(width){var view_range=this.view_end-this.view_start,w_scale=width/view_range;return Math.min(128,Math.ceil((this.longest_feature_length/2)*w_scale))},draw_connector:function(ctx,block1_start,block1_end,block2_start,block2_end,y_start){var x_center=(block1_end+block2_start)/2,radius=block2_start-x_center;var angle1=Math.PI,angle2=0;if(radius>0){ctx.beginPath();ctx.arc(x_center,y_start,block2_start-x_center,Math.PI,0);ctx.stroke()}}});var Color=function(rgb,a){if(Array.isArray(rgb)){this.rgb=rgb}else{if(rgb.length==6){this.rgb=rgb.match(/.{2}/g).map(function(c){return parseInt(c,16)})}else{if(rgb.length==7){this.rgb=rgb.substring(1,7).match(/.{2}/g).map(function(c){return parseInt(c,16)})}else{this.rgb=rgb.split("").map(function(c){return parseInt(c+c,16)})}}}this.alpha=typeof(a)==="number"?a:1};Color.prototype={eval:function(){return this},toCSS:function(){if(this.alpha<1){return"rgba("+this.rgb.map(function(c){return Math.round(c)}).concat(this.alpha).join(", ")+")"}else{return"#"+this.rgb.map(function(i){i=Math.round(i);i=(i>255?255:(i<0?0:i)).toString(16);return i.length===1?"0"+i:i}).join("")}},toHSL:function(){var r=this.rgb[0]/255,g=this.rgb[1]/255,b=this.rgb[2]/255,a=this.alpha;var max=Math.max(r,g,b),min=Math.min(r,g,b);var h,s,l=(max+min)/2,d=max-min;if(max===min){h=s=0}else{s=l>0.5?d/(2-max-min):d/(max+min);switch(max){case r:h=(g-b)/d+(g<b?6:0);break;case g:h=(b-r)/d+2;break;case b:h=(r-g)/d+4;break}h/=6}return{h:h*360,s:s,l:l,a:a}},toARGB:function(){var argb=[Math.round(this.alpha*255)].concat(this.rgb);return"#"+argb.map(function(i){i=Math.round(i);i=(i>255?255:(i<0?0:i)).toString(16);return i.length===1?"0"+i:i}).join("")},mix:function(color2,weight){color1=this;var p=weight;var w=p*2-1;var a=color1.toHSL().a-color2.toHSL().a;var w1=(((w*a==-1)?w:(w+a)/(1+w*a))+1)/2;var w2=1-w1;var rgb=[color1.rgb[0]*w1+color2.rgb[0]*w2,color1.rgb[1]*w1+color2.rgb[1]*w2,color1.rgb[2]*w1+color2.rgb[2]*w2];var alpha=color1.alpha*p+color2.alpha*(1-p);return new Color(rgb,alpha)}};var LinearRamp=function(start_color,end_color,start_value,end_value){this.start_color=new Color(start_color);this.end_color=new Color(end_color);this.start_value=start_value;this.end_value=end_value;this.value_range=end_value-start_value};LinearRamp.prototype.map_value=function(value){value=Math.max(value,this.start_value);value=Math.min(value,this.end_value);value=(value-this.start_value)/this.value_range;return this.start_color.mix(this.end_color,1-value).toCSS()};var SplitRamp=function(start_color,middle_color,end_color,start_value,end_value){this.positive_ramp=new LinearRamp(middle_color,end_color,0,end_value);this.negative_ramp=new LinearRamp(middle_color,start_color,0,-start_value);this.start_value=start_value;this.end_value=end_value};SplitRamp.prototype.map_value=function(value){value=Math.max(value,this.start_value);value=Math.min(value,this.end_value);if(value>=0){return this.positive_ramp.map_value(value)}else{return this.negative_ramp.map_value(-value)}};var DiagonalHeatmapPainter=function(data,view_start,view_end,prefs,mode){Painter.call(this,data,view_start,view_end,prefs,mode);var i,len;if(this.prefs.min_value===undefined){var min_value=Infinity;for(i=0,len=this.data.length;i<len;i++){min_value=Math.min(min_value,this.data[i][5])}this.prefs.min_value=min_value}if(this.prefs.max_value===undefined){var max_value=-Infinity;for(i=0,len=this.data.length;i<len;i++){max_value=Math.max(max_value,this.data[i][5])}this.prefs.max_value=max_value}};DiagonalHeatmapPainter.prototype.default_prefs={min_value:undefined,max_value:undefined,mode:"Heatmap",pos_color:"#FF8C00",neg_color:"#4169E1"};DiagonalHeatmapPainter.prototype.draw=function(ctx,width,height,w_scale){var min_value=this.prefs.min_value,max_value=this.prefs.max_value,value_range=max_value-min_value,height_px=height,view_start=this.view_start,mode=this.mode,data=this.data,invsqrt2=1/Math.sqrt(2);var ramp=(new SplitRamp(this.prefs.neg_color,"#FFFFFF",this.prefs.pos_color,min_value,max_value));var d,s1,e1,s2,e2,value;var scale=function(p){return(p-view_start)*w_scale};ctx.save();ctx.rotate(-45*Math.PI/180);ctx.scale(invsqrt2,invsqrt2);for(var i=0,len=data.length;i<len;i++){d=data[i];s1=scale(d[1]);e1=scale(d[2]);s2=scale(d[4]);e2=scale(d[5]);value=d[6];ctx.fillStyle=(ramp.map_value(value));ctx.fillRect(s1,s2,(e1-s1),(e2-s2))}ctx.restore()};var ReadPainterUtils=function(ctx,row_height,px_per_base,mode){this.ctx=ctx;this.row_height=row_height;this.px_per_base=px_per_base;this.draw_details=(mode==="Pack"||mode==="Auto")&&(px_per_base>=ctx.canvas.manager.char_width_px);this.delete_details_thickness=0.2};_.extend(ReadPainterUtils.prototype,{draw_deletion:function(x,y,len){this.ctx.fillStyle="black";var thickness=(this.draw_details?this.delete_details_thickness:1)*this.row_height;y+=0.5*(this.row_height-thickness);this.ctx.fillRect(x,y,len*this.px_per_base,thickness)}});var VariantPainter=function(data,view_start,view_end,prefs,mode,base_color_fn){Painter.call(this,data,view_start,view_end,prefs,mode);this.base_color_fn=base_color_fn;this.divider_height=1};_.extend(VariantPainter.prototype,Painter.prototype,{get_row_height:function(){var mode=this.mode,height;if(mode==="Dense"){height=DENSE_TRACK_HEIGHT}else{if(mode==="Squish"){height=SQUISH_TRACK_HEIGHT}else{height=PACK_TRACK_HEIGHT}}return height},get_required_height:function(num_samples){var height=this.prefs.summary_height;if(num_samples>1&&this.prefs.show_sample_data){height+=this.divider_height+num_samples*this.get_row_height()}return height},draw:function(ctx,width,height,w_scale){ctx.save();var get_deletion_info=function(ref,alt){var ref_len=ref.length,alt_len=alt.length,start=0,len=1,is_delete=false;if(alt==="-"){is_delete=true;len=ref.length}else{if(ref.indexOf(alt)===0&&ref_len>alt_len){is_delete=true;len=ref_len=alt_len;start+=alt_len}}return(is_delete?{start:start,len:len}:null)};var locus_data,pos,id,ref,alt,qual,filter,sample_gts,allele_counts,variant,draw_x_start,char_x_start,draw_y_start,genotype,base_px=Math.max(1,Math.floor(w_scale)),num_samples=(this.data.length?this.data[0][7].split(",").length:0),row_height=(this.mode==="Squish"?SQUISH_TRACK_HEIGHT:PACK_TRACK_HEIGHT),feature_height=(w_scale<0.1?row_height:(this.mode==="Squish"?SQUISH_FEATURE_HEIGHT:PACK_FEATURE_HEIGHT)),draw_summary=true,paint_utils=new ReadPainterUtils(ctx,row_height,w_scale,this.mode),j;if(num_samples===1){row_height=feature_height=(w_scale<ctx.canvas.manager.char_width_px?this.prefs.summary_height:row_height);paint_utils.row_height=row_height;draw_summary=false}if(this.prefs.show_sample_data&&draw_summary){ctx.fillStyle="#F3F3F3";ctx.globalAlpha=1;ctx.fillRect(0,this.prefs.summary_height-this.divider_height,width,this.divider_height)}ctx.textAlign="center";for(var i=0;i<this.data.length;i++){locus_data=this.data[i];pos=locus_data[1];ref=locus_data[3];alt=[locus_data[4].split(",")];sample_gts=locus_data[7].split(",");allele_counts=locus_data.slice(8);alt=_.map(_.flatten(alt),function(a){var type,alt_info={},delete_info=get_deletion_info(ref,a);if(delete_info){type="deletion";_.extend(alt_info,delete_info)}else{type="snp"}return _.extend(alt_info,{type:type,value:a,})});if(pos<this.view_start||pos>this.view_end){continue}draw_x_start=Math.floor(Math.max(-0.5*w_scale,(pos-this.view_start-0.5)*w_scale));char_x_start=Math.floor(Math.max(0,(pos-this.view_start)*w_scale));if(draw_summary){ctx.fillStyle="#999999";ctx.globalAlpha=1;ctx.fillRect(draw_x_start,0,base_px,this.prefs.summary_height);draw_y_start=this.prefs.summary_height;for(j=0;j<alt.length;j++){ctx.fillStyle=(alt[j].type==="deletion"?"black":this.base_color_fn(alt[j].value));allele_frac=allele_counts/sample_gts.length;draw_height=Math.ceil(this.prefs.summary_height*allele_frac);ctx.fillRect(draw_x_start,draw_y_start-draw_height,base_px,draw_height);draw_y_start-=draw_height}}if(!this.prefs.show_sample_data){continue}draw_y_start=(draw_summary?this.prefs.summary_height+this.divider_height:0);for(j=0;j<sample_gts.length;j++,draw_y_start+=row_height){genotype=(sample_gts[j]?sample_gts[j].split(/\/|\|/):["0","0"]);variant=null;if(genotype[0]===genotype[1]){if(genotype[0]==="."){}else{if(genotype[0]!=="0"){variant=alt[parseInt(genotype[0],10)-1];ctx.globalAlpha=1}}}else{variant=(genotype[0]!=="0"?genotype[0]:genotype[1]);variant=alt[parseInt(variant,10)-1];ctx.globalAlpha=0.5}if(variant){if(variant.type==="snp"){var snp=variant.value;ctx.fillStyle=this.base_color_fn(snp);if(paint_utils.draw_details){ctx.fillText(snp,char_x_start,draw_y_start+row_height)}else{ctx.fillRect(draw_x_start,draw_y_start+1,base_px,feature_height)}}else{if(variant.type==="deletion"){paint_utils.draw_deletion(draw_x_start+base_px*variant.start,draw_y_start+1,variant.len)}else{}}}}}ctx.restore()}});return{Scaler:Scaler,LinePainter:LinePainter,LinkedFeaturePainter:LinkedFeaturePainter,ReadPainter:ReadPainter,ArcLinkedFeaturePainter:ArcLinkedFeaturePainter,DiagonalHeatmapPainter:DiagonalHeatmapPainter,VariantPainter:VariantPainter}});
\ No newline at end of file
diff -r cd82587fb36ecbc802931edad29372f69cee7108 -r d4070ec86d404eec61f78a60f23536080b04ab1f static/scripts/viz/trackster/painters.js
--- a/static/scripts/viz/trackster/painters.js
+++ b/static/scripts/viz/trackster/painters.js
@@ -196,7 +196,7 @@
ctx.fillStyle = ctx.strokeStyle = painter_color;
top_overflow = bot_overflow = false;
- x_scaled = Math.round((data[i][0] - view_start) * w_scale);
+ x_scaled = Math.ceil((data[i][0] - view_start) * w_scale);
y = data[i][1];
// Process Y (scaler) value.
diff -r cd82587fb36ecbc802931edad29372f69cee7108 -r d4070ec86d404eec61f78a60f23536080b04ab1f test/unit/tools/test_tool_external_files.py
--- /dev/null
+++ b/test/unit/tools/test_tool_external_files.py
@@ -0,0 +1,30 @@
+""" Unit test logic related to finding externally referenced files in tool
+descriptions.
+"""
+import tempfile
+import os
+import shutil
+from galaxy.tools import Tool
+
+
+def test_finds_external_code_file():
+ assert __external_files("""<tool><code file="foo.py" /></tool>""") == ["foo.py"]
+
+
+def test_finds_skips_empty_code_file_attribute():
+ assert __external_files("""<tool><code /></tool>""") == []
+
+
+def test_finds_external_macro_file():
+ assert __external_files("""<tool><macros><import>cool_macros.xml</import></macros></tool>""") == ["cool_macros.xml"]
+
+
+def __external_files(contents):
+ base_path = tempfile.mkdtemp()
+ try:
+ tool_path = os.path.join(base_path, "tool.xml")
+ with open(tool_path, "w") as f:
+ f.write(contents)
+ return Tool.get_externally_referenced_paths(tool_path)
+ finally:
+ shutil.rmtree(base_path)
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: jmchilton: Merged in jmchilton/galaxy-central-fork-1/next-stable (pull request #449)
by commits-noreply@bitbucket.org 04 Aug '14
by commits-noreply@bitbucket.org 04 Aug '14
04 Aug '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/7cacfb33db90/
Changeset: 7cacfb33db90
Branch: next-stable
User: jmchilton
Date: 2014-08-04 20:57:31
Summary: Merged in jmchilton/galaxy-central-fork-1/next-stable (pull request #449)
Fix tool shed's logic related to finding tool externally referenced files.
Affected #: 4 files
diff -r 7ac5a36c0ce7a6eb280d339de2107740552825ce -r 7cacfb33db90dee8c4e9ce78a3a735cd6cef8490 lib/galaxy/tools/__init__.py
--- a/lib/galaxy/tools/__init__.py
+++ b/lib/galaxy/tools/__init__.py
@@ -69,7 +69,7 @@
from galaxy.model import Workflow
from tool_shed.util import common_util
from tool_shed.util import shed_util_common as suc
-from .loader import load_tool, template_macro_params
+from .loader import load_tool, template_macro_params, raw_tool_xml_tree, imported_macro_paths
from .execute import execute as execute_job
from .wrappers import (
ToolParameterValueWrapper,
@@ -2989,6 +2989,23 @@
def get_default_history_by_trans( self, trans, create=False ):
return trans.get_history( create=create )
+ @classmethod
+ def get_externally_referenced_paths( self, path ):
+ """ Return relative paths to externally referenced files by the tool
+ described by file at `path`. External components should not assume things
+ about the structure of tool xml files (this is the tool's responsibility).
+ """
+ tree = raw_tool_xml_tree(path)
+ root = tree.getroot()
+ external_paths = []
+ for code_elem in root.findall( 'code' ):
+ external_path = code_elem.get( 'file' )
+ if external_path:
+ external_paths.append( external_path )
+ external_paths.extend( imported_macro_paths( root ) )
+ # May also need to load external citation files as well at some point.
+ return external_paths
+
class OutputParameterJSONTool( Tool ):
"""
diff -r 7ac5a36c0ce7a6eb280d339de2107740552825ce -r 7cacfb33db90dee8c4e9ce78a3a735cd6cef8490 lib/galaxy/tools/loader.py
--- a/lib/galaxy/tools/loader.py
+++ b/lib/galaxy/tools/loader.py
@@ -10,7 +10,7 @@
"""
Loads tool from file system and preprocesses tool macros.
"""
- tree = parse_xml(path)
+ tree = raw_tool_xml_tree(path)
root = tree.getroot()
_import_macros(root, path)
@@ -38,14 +38,31 @@
return param_dict
+def raw_tool_xml_tree(path):
+ """ Load raw (no macro expansion) tree representation of tool represented
+ at the specified path.
+ """
+ tree = parse_xml(path)
+ return tree
+
+
+def imported_macro_paths(root):
+ macros_el = _macros_el(root)
+ return _imported_macro_paths_from_el(macros_el)
+
+
def _import_macros(root, path):
tool_dir = os.path.dirname(path)
- macros_el = root.find('macros')
+ macros_el = _macros_el(root)
if macros_el:
macro_els = _load_macros(macros_el, tool_dir)
_xml_set_children(macros_el, macro_els)
+def _macros_el(root):
+ return root.find('macros')
+
+
def _macros_of_type(root, type, el_func):
macros_el = root.find('macros')
macro_dict = {}
@@ -159,6 +176,17 @@
def _load_imported_macros(macros_el, tool_dir):
macros = []
+ for tool_relative_import_path in _imported_macro_paths_from_el(macros_el):
+ import_path = \
+ os.path.join(tool_dir, tool_relative_import_path)
+ file_macros = _load_macro_file(import_path, tool_dir)
+ macros.extend(file_macros)
+
+ return macros
+
+
+def _imported_macro_paths_from_el(macros_el):
+ imported_macro_paths = []
macro_import_els = []
if macros_el:
macro_import_els = macros_el.findall("import")
@@ -166,12 +194,8 @@
raw_import_path = macro_import_el.text
tool_relative_import_path = \
os.path.basename(raw_import_path) # Sanitize this
- import_path = \
- os.path.join(tool_dir, tool_relative_import_path)
- file_macros = _load_macro_file(import_path, tool_dir)
- macros.extend(file_macros)
-
- return macros
+ imported_macro_paths.append( tool_relative_import_path )
+ return imported_macro_paths
def _load_macro_file(path, tool_dir):
diff -r 7ac5a36c0ce7a6eb280d339de2107740552825ce -r 7cacfb33db90dee8c4e9ce78a3a735cd6cef8490 lib/tool_shed/tools/tool_validator.py
--- a/lib/tool_shed/tools/tool_validator.py
+++ b/lib/tool_shed/tools/tool_validator.py
@@ -3,6 +3,7 @@
import os
import tempfile
+from galaxy.tools import Tool
from galaxy.tools import parameters
from galaxy.tools.parameters import dynamic_options
@@ -311,15 +312,14 @@
message = ''
tmp_tool_config = hg_util.get_named_tmpfile_from_ctx( ctx, ctx_file, work_dir )
if tmp_tool_config:
- element_tree, error_message = xml_util.parse_xml( tmp_tool_config )
- if element_tree is None:
+ tool_element, error_message = xml_util.parse_xml( tmp_tool_config )
+ if tool_element is None:
return tool, message
- element_tree_root = element_tree.getroot()
- # Look for code files required by the tool config.
+ # Look for external 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 = hg_util.copy_file_from_manifest( repo, ctx, code_file_name, work_dir )
+ external_paths = Tool.get_externally_referenced_paths( tmp_tool_config )
+ for path in external_paths:
+ tmp_code_file_name = hg_util.copy_file_from_manifest( repo, ctx, path, work_dir )
if tmp_code_file_name:
tmp_code_files.append( tmp_code_file_name )
tool, valid, message = self.load_tool_from_config( repository_id, tmp_tool_config )
diff -r 7ac5a36c0ce7a6eb280d339de2107740552825ce -r 7cacfb33db90dee8c4e9ce78a3a735cd6cef8490 test/unit/tools/test_tool_external_files.py
--- /dev/null
+++ b/test/unit/tools/test_tool_external_files.py
@@ -0,0 +1,30 @@
+""" Unit test logic related to finding externally referenced files in tool
+descriptions.
+"""
+import tempfile
+import os
+import shutil
+from galaxy.tools import Tool
+
+
+def test_finds_external_code_file():
+ assert __external_files("""<tool><code file="foo.py" /></tool>""") == ["foo.py"]
+
+
+def test_finds_skips_empty_code_file_attribute():
+ assert __external_files("""<tool><code /></tool>""") == []
+
+
+def test_finds_external_macro_file():
+ assert __external_files("""<tool><macros><import>cool_macros.xml</import></macros></tool>""") == ["cool_macros.xml"]
+
+
+def __external_files(contents):
+ base_path = tempfile.mkdtemp()
+ try:
+ tool_path = os.path.join(base_path, "tool.xml")
+ with open(tool_path, "w") as f:
+ f.write(contents)
+ return Tool.get_externally_referenced_paths(tool_path)
+ finally:
+ shutil.rmtree(base_path)
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
3 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/e90ee102ac65/
Changeset: e90ee102ac65
Branch: next-stable
User: jmchilton
Date: 2014-08-04 18:18:00
Summary: Restructure tool external file logic in load_tool_from_tmp_config in ToolValidator...
... so internals of tool XML description are only utilized in the galaxy.tools module (and submodules). Add some unit tests for this new method for finding externally referenced files.
Affected #: 4 files
diff -r 2438770e2cfbf804acc0d5c7b2f3d6e491f30695 -r e90ee102ac654cc88bc3cf156aa1319008412846 lib/galaxy/tools/__init__.py
--- a/lib/galaxy/tools/__init__.py
+++ b/lib/galaxy/tools/__init__.py
@@ -69,7 +69,7 @@
from galaxy.model import Workflow
from tool_shed.util import common_util
from tool_shed.util import shed_util_common as suc
-from .loader import load_tool, template_macro_params
+from .loader import load_tool, template_macro_params, raw_tool_xml_tree
from .execute import execute as execute_job
from .wrappers import (
ToolParameterValueWrapper,
@@ -2989,6 +2989,21 @@
def get_default_history_by_trans( self, trans, create=False ):
return trans.get_history( create=create )
+ @classmethod
+ def get_externally_referenced_paths( self, path ):
+ """ Return relative paths to externally referenced files by the tool
+ described by file at `path`. External components should not assume things
+ about the structure of tool xml files (this is the tool's responsibility).
+ """
+ tree = raw_tool_xml_tree(path)
+ root = tree.getroot()
+ external_paths = []
+ for code_elem in root.findall( 'code' ):
+ external_path = code_elem.get( 'file' )
+ if external_path:
+ external_paths.append( external_path )
+ return external_paths
+
class OutputParameterJSONTool( Tool ):
"""
diff -r 2438770e2cfbf804acc0d5c7b2f3d6e491f30695 -r e90ee102ac654cc88bc3cf156aa1319008412846 lib/galaxy/tools/loader.py
--- a/lib/galaxy/tools/loader.py
+++ b/lib/galaxy/tools/loader.py
@@ -10,7 +10,7 @@
"""
Loads tool from file system and preprocesses tool macros.
"""
- tree = parse_xml(path)
+ tree = raw_tool_xml_tree(path)
root = tree.getroot()
_import_macros(root, path)
@@ -38,6 +38,14 @@
return param_dict
+def raw_tool_xml_tree(path):
+ """ Load raw (no macro expansion) tree representation of tool represented
+ at the specified path.
+ """
+ tree = parse_xml(path)
+ return tree
+
+
def _import_macros(root, path):
tool_dir = os.path.dirname(path)
macros_el = root.find('macros')
diff -r 2438770e2cfbf804acc0d5c7b2f3d6e491f30695 -r e90ee102ac654cc88bc3cf156aa1319008412846 lib/tool_shed/tools/tool_validator.py
--- a/lib/tool_shed/tools/tool_validator.py
+++ b/lib/tool_shed/tools/tool_validator.py
@@ -3,6 +3,7 @@
import os
import tempfile
+from galaxy.tools import Tool
from galaxy.tools import parameters
from galaxy.tools.parameters import dynamic_options
@@ -311,15 +312,14 @@
message = ''
tmp_tool_config = hg_util.get_named_tmpfile_from_ctx( ctx, ctx_file, work_dir )
if tmp_tool_config:
- element_tree, error_message = xml_util.parse_xml( tmp_tool_config )
- if element_tree is None:
+ tool_element, error_message = xml_util.parse_xml( tmp_tool_config )
+ if tool_element is None:
return tool, message
- element_tree_root = element_tree.getroot()
- # Look for code files required by the tool config.
+ # Look for external 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 = hg_util.copy_file_from_manifest( repo, ctx, code_file_name, work_dir )
+ external_paths = Tool.get_externally_referenced_paths( tmp_tool_config )
+ for path in external_paths:
+ tmp_code_file_name = hg_util.copy_file_from_manifest( repo, ctx, path, work_dir )
if tmp_code_file_name:
tmp_code_files.append( tmp_code_file_name )
tool, valid, message = self.load_tool_from_config( repository_id, tmp_tool_config )
diff -r 2438770e2cfbf804acc0d5c7b2f3d6e491f30695 -r e90ee102ac654cc88bc3cf156aa1319008412846 test/unit/tools/test_tool_external_files.py
--- /dev/null
+++ b/test/unit/tools/test_tool_external_files.py
@@ -0,0 +1,26 @@
+""" Unit test logic related to finding externally referenced files in tool
+descriptions.
+"""
+import tempfile
+import os
+import shutil
+from galaxy.tools import Tool
+
+
+def test_finds_external_code_file():
+ assert __external_files("""<tool><code file="foo.py" /></tool>""") == ["foo.py"]
+
+
+def test_finds_skips_empty_code_file_attribute():
+ assert __external_files("""<tool><code /></tool>""") == []
+
+
+def __external_files(contents):
+ base_path = tempfile.mkdtemp()
+ try:
+ tool_path = os.path.join(base_path, "tool.xml")
+ with open(tool_path, "w") as f:
+ f.write(contents)
+ return Tool.get_externally_referenced_paths(tool_path)
+ finally:
+ shutil.rmtree(base_path)
https://bitbucket.org/galaxy/galaxy-central/commits/d026577e04ac/
Changeset: d026577e04ac
Branch: next-stable
User: jmchilton
Date: 2014-08-04 18:18:00
Summary: Fix new Tool.get_externally_referenced_paths to find imported macro files.
Should fix this bug https://trello.com/c/TeguDYSq discovered by Bjoern... on stage at the GCC.
Affected #: 3 files
diff -r e90ee102ac654cc88bc3cf156aa1319008412846 -r d026577e04ac9802249aeecb64d14292bf59e20d lib/galaxy/tools/__init__.py
--- a/lib/galaxy/tools/__init__.py
+++ b/lib/galaxy/tools/__init__.py
@@ -69,7 +69,7 @@
from galaxy.model import Workflow
from tool_shed.util import common_util
from tool_shed.util import shed_util_common as suc
-from .loader import load_tool, template_macro_params, raw_tool_xml_tree
+from .loader import load_tool, template_macro_params, raw_tool_xml_tree, imported_macro_paths
from .execute import execute as execute_job
from .wrappers import (
ToolParameterValueWrapper,
@@ -3002,6 +3002,8 @@
external_path = code_elem.get( 'file' )
if external_path:
external_paths.append( external_path )
+ external_paths.extend( imported_macro_paths( root ) )
+ # May also need to load external citation files as well at some point.
return external_paths
diff -r e90ee102ac654cc88bc3cf156aa1319008412846 -r d026577e04ac9802249aeecb64d14292bf59e20d lib/galaxy/tools/loader.py
--- a/lib/galaxy/tools/loader.py
+++ b/lib/galaxy/tools/loader.py
@@ -46,14 +46,23 @@
return tree
+def imported_macro_paths(root):
+ macros_el = _macros_el(root)
+ return _imported_macro_paths_from_el(macros_el)
+
+
def _import_macros(root, path):
tool_dir = os.path.dirname(path)
- macros_el = root.find('macros')
+ macros_el = _macros_el(root)
if macros_el:
macro_els = _load_macros(macros_el, tool_dir)
_xml_set_children(macros_el, macro_els)
+def _macros_el(root):
+ return root.find('macros')
+
+
def _macros_of_type(root, type, el_func):
macros_el = root.find('macros')
macro_dict = {}
@@ -167,6 +176,17 @@
def _load_imported_macros(macros_el, tool_dir):
macros = []
+ for tool_relative_import_path in _imported_macro_paths_from_el(macros_el):
+ import_path = \
+ os.path.join(tool_dir, tool_relative_import_path)
+ file_macros = _load_macro_file(import_path, tool_dir)
+ macros.extend(file_macros)
+
+ return macros
+
+
+def _imported_macro_paths_from_el(macros_el):
+ imported_macro_paths = []
macro_import_els = []
if macros_el:
macro_import_els = macros_el.findall("import")
@@ -174,12 +194,8 @@
raw_import_path = macro_import_el.text
tool_relative_import_path = \
os.path.basename(raw_import_path) # Sanitize this
- import_path = \
- os.path.join(tool_dir, tool_relative_import_path)
- file_macros = _load_macro_file(import_path, tool_dir)
- macros.extend(file_macros)
-
- return macros
+ imported_macro_paths.append( tool_relative_import_path )
+ return imported_macro_paths
def _load_macro_file(path, tool_dir):
diff -r e90ee102ac654cc88bc3cf156aa1319008412846 -r d026577e04ac9802249aeecb64d14292bf59e20d test/unit/tools/test_tool_external_files.py
--- a/test/unit/tools/test_tool_external_files.py
+++ b/test/unit/tools/test_tool_external_files.py
@@ -15,6 +15,10 @@
assert __external_files("""<tool><code /></tool>""") == []
+def test_finds_external_macro_file():
+ assert __external_files("""<tool><macros><import>cool_macros.xml</import></macros></tool>""") == ["cool_macros.xml"]
+
+
def __external_files(contents):
base_path = tempfile.mkdtemp()
try:
https://bitbucket.org/galaxy/galaxy-central/commits/7cacfb33db90/
Changeset: 7cacfb33db90
Branch: next-stable
User: jmchilton
Date: 2014-08-04 20:57:31
Summary: Merged in jmchilton/galaxy-central-fork-1/next-stable (pull request #449)
Fix tool shed's logic related to finding tool externally referenced files.
Affected #: 4 files
diff -r 7ac5a36c0ce7a6eb280d339de2107740552825ce -r 7cacfb33db90dee8c4e9ce78a3a735cd6cef8490 lib/galaxy/tools/__init__.py
--- a/lib/galaxy/tools/__init__.py
+++ b/lib/galaxy/tools/__init__.py
@@ -69,7 +69,7 @@
from galaxy.model import Workflow
from tool_shed.util import common_util
from tool_shed.util import shed_util_common as suc
-from .loader import load_tool, template_macro_params
+from .loader import load_tool, template_macro_params, raw_tool_xml_tree, imported_macro_paths
from .execute import execute as execute_job
from .wrappers import (
ToolParameterValueWrapper,
@@ -2989,6 +2989,23 @@
def get_default_history_by_trans( self, trans, create=False ):
return trans.get_history( create=create )
+ @classmethod
+ def get_externally_referenced_paths( self, path ):
+ """ Return relative paths to externally referenced files by the tool
+ described by file at `path`. External components should not assume things
+ about the structure of tool xml files (this is the tool's responsibility).
+ """
+ tree = raw_tool_xml_tree(path)
+ root = tree.getroot()
+ external_paths = []
+ for code_elem in root.findall( 'code' ):
+ external_path = code_elem.get( 'file' )
+ if external_path:
+ external_paths.append( external_path )
+ external_paths.extend( imported_macro_paths( root ) )
+ # May also need to load external citation files as well at some point.
+ return external_paths
+
class OutputParameterJSONTool( Tool ):
"""
diff -r 7ac5a36c0ce7a6eb280d339de2107740552825ce -r 7cacfb33db90dee8c4e9ce78a3a735cd6cef8490 lib/galaxy/tools/loader.py
--- a/lib/galaxy/tools/loader.py
+++ b/lib/galaxy/tools/loader.py
@@ -10,7 +10,7 @@
"""
Loads tool from file system and preprocesses tool macros.
"""
- tree = parse_xml(path)
+ tree = raw_tool_xml_tree(path)
root = tree.getroot()
_import_macros(root, path)
@@ -38,14 +38,31 @@
return param_dict
+def raw_tool_xml_tree(path):
+ """ Load raw (no macro expansion) tree representation of tool represented
+ at the specified path.
+ """
+ tree = parse_xml(path)
+ return tree
+
+
+def imported_macro_paths(root):
+ macros_el = _macros_el(root)
+ return _imported_macro_paths_from_el(macros_el)
+
+
def _import_macros(root, path):
tool_dir = os.path.dirname(path)
- macros_el = root.find('macros')
+ macros_el = _macros_el(root)
if macros_el:
macro_els = _load_macros(macros_el, tool_dir)
_xml_set_children(macros_el, macro_els)
+def _macros_el(root):
+ return root.find('macros')
+
+
def _macros_of_type(root, type, el_func):
macros_el = root.find('macros')
macro_dict = {}
@@ -159,6 +176,17 @@
def _load_imported_macros(macros_el, tool_dir):
macros = []
+ for tool_relative_import_path in _imported_macro_paths_from_el(macros_el):
+ import_path = \
+ os.path.join(tool_dir, tool_relative_import_path)
+ file_macros = _load_macro_file(import_path, tool_dir)
+ macros.extend(file_macros)
+
+ return macros
+
+
+def _imported_macro_paths_from_el(macros_el):
+ imported_macro_paths = []
macro_import_els = []
if macros_el:
macro_import_els = macros_el.findall("import")
@@ -166,12 +194,8 @@
raw_import_path = macro_import_el.text
tool_relative_import_path = \
os.path.basename(raw_import_path) # Sanitize this
- import_path = \
- os.path.join(tool_dir, tool_relative_import_path)
- file_macros = _load_macro_file(import_path, tool_dir)
- macros.extend(file_macros)
-
- return macros
+ imported_macro_paths.append( tool_relative_import_path )
+ return imported_macro_paths
def _load_macro_file(path, tool_dir):
diff -r 7ac5a36c0ce7a6eb280d339de2107740552825ce -r 7cacfb33db90dee8c4e9ce78a3a735cd6cef8490 lib/tool_shed/tools/tool_validator.py
--- a/lib/tool_shed/tools/tool_validator.py
+++ b/lib/tool_shed/tools/tool_validator.py
@@ -3,6 +3,7 @@
import os
import tempfile
+from galaxy.tools import Tool
from galaxy.tools import parameters
from galaxy.tools.parameters import dynamic_options
@@ -311,15 +312,14 @@
message = ''
tmp_tool_config = hg_util.get_named_tmpfile_from_ctx( ctx, ctx_file, work_dir )
if tmp_tool_config:
- element_tree, error_message = xml_util.parse_xml( tmp_tool_config )
- if element_tree is None:
+ tool_element, error_message = xml_util.parse_xml( tmp_tool_config )
+ if tool_element is None:
return tool, message
- element_tree_root = element_tree.getroot()
- # Look for code files required by the tool config.
+ # Look for external 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 = hg_util.copy_file_from_manifest( repo, ctx, code_file_name, work_dir )
+ external_paths = Tool.get_externally_referenced_paths( tmp_tool_config )
+ for path in external_paths:
+ tmp_code_file_name = hg_util.copy_file_from_manifest( repo, ctx, path, work_dir )
if tmp_code_file_name:
tmp_code_files.append( tmp_code_file_name )
tool, valid, message = self.load_tool_from_config( repository_id, tmp_tool_config )
diff -r 7ac5a36c0ce7a6eb280d339de2107740552825ce -r 7cacfb33db90dee8c4e9ce78a3a735cd6cef8490 test/unit/tools/test_tool_external_files.py
--- /dev/null
+++ b/test/unit/tools/test_tool_external_files.py
@@ -0,0 +1,30 @@
+""" Unit test logic related to finding externally referenced files in tool
+descriptions.
+"""
+import tempfile
+import os
+import shutil
+from galaxy.tools import Tool
+
+
+def test_finds_external_code_file():
+ assert __external_files("""<tool><code file="foo.py" /></tool>""") == ["foo.py"]
+
+
+def test_finds_skips_empty_code_file_attribute():
+ assert __external_files("""<tool><code /></tool>""") == []
+
+
+def test_finds_external_macro_file():
+ assert __external_files("""<tool><macros><import>cool_macros.xml</import></macros></tool>""") == ["cool_macros.xml"]
+
+
+def __external_files(contents):
+ base_path = tempfile.mkdtemp()
+ try:
+ tool_path = os.path.join(base_path, "tool.xml")
+ with open(tool_path, "w") as f:
+ f.write(contents)
+ return Tool.get_externally_referenced_paths(tool_path)
+ finally:
+ shutil.rmtree(base_path)
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: jgoecks: Trackster: fix single-pixel gap bug in quantitative track display.
by commits-noreply@bitbucket.org 04 Aug '14
by commits-noreply@bitbucket.org 04 Aug '14
04 Aug '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/7ac5a36c0ce7/
Changeset: 7ac5a36c0ce7
Branch: next-stable
User: jgoecks
Date: 2014-08-04 20:50:28
Summary: Trackster: fix single-pixel gap bug in quantitative track display.
Affected #: 2 files
diff -r 2438770e2cfbf804acc0d5c7b2f3d6e491f30695 -r 7ac5a36c0ce7a6eb280d339de2107740552825ce static/scripts/packed/viz/trackster/painters.js
--- a/static/scripts/packed/viz/trackster/painters.js
+++ b/static/scripts/packed/viz/trackster/painters.js
@@ -1,1 +1,1 @@
-define(["libs/underscore"],function(_){var BEFORE=1001,CONTAINS=1002,OVERLAP_START=1003,OVERLAP_END=1004,CONTAINED_BY=1005,AFTER=1006;var compute_overlap=function(first_region,second_region){var first_start=first_region[0],first_end=first_region[1],second_start=second_region[0],second_end=second_region[1],overlap;if(first_start<second_start){if(first_end<=second_start){overlap=BEFORE}else{if(first_end<=second_end){overlap=OVERLAP_START}else{overlap=CONTAINS}}}else{if(first_start>second_end){overlap=AFTER}else{if(first_end<=second_end){overlap=CONTAINED_BY}else{overlap=OVERLAP_END}}}return overlap};var is_overlap=function(first_region,second_region){var overlap=compute_overlap(first_region,second_region);return(overlap!==BEFORE&&overlap!==AFTER)};var dashedLine=function(ctx,x1,y1,x2,y2,dashLen){if(dashLen===undefined){dashLen=4}var dX=x2-x1;var dY=y2-y1;var dashes=Math.floor(Math.sqrt(dX*dX+dY*dY)/dashLen);var dashX=dX/dashes;var dashY=dY/dashes;var q;for(q=0;q<dashes;q++,x1+=dashX,y1+=dashY){if(q%2!==0){continue}ctx.fillRect(x1,y1,dashLen,1)}};var drawDownwardEquilateralTriangle=function(ctx,down_vertex_x,down_vertex_y,side_len){var x1=down_vertex_x-side_len/2,x2=down_vertex_x+side_len/2,y=down_vertex_y-Math.sqrt(side_len*3/2);ctx.beginPath();ctx.moveTo(x1,y);ctx.lineTo(x2,y);ctx.lineTo(down_vertex_x,down_vertex_y);ctx.lineTo(x1,y);ctx.strokeStyle=this.fillStyle;ctx.fill();ctx.stroke();ctx.closePath()};var Scaler=function(default_val){this.default_val=(default_val?default_val:1)};Scaler.prototype.gen_val=function(input){return this.default_val};var DrawResults=function(options){this.incomplete_features=options.incomplete_features;this.feature_mapper=options.feature_mapper};var Painter=function(data,view_start,view_end,prefs,mode){this.data=data;this.view_start=view_start;this.view_end=view_end;this.prefs=_.extend({},this.default_prefs,prefs);this.mode=mode};Painter.prototype.default_prefs={};Painter.prototype.draw=function(ctx,width,height,w_scale){};var LinePainter=function(data,view_start,view_end,prefs,mode){Painter.call(this,data,view_start,view_end,prefs,mode);if(this.prefs.min_value===undefined){this.prefs.min_value=_.min(_.map(this.data,function(d){return d[1]}))||0}if(this.prefs.max_value===undefined){this.prefs.max_value=_.max(_.map(this.data,function(d){return d[1]}))||0}};LinePainter.prototype.default_prefs={min_value:undefined,max_value:undefined,mode:"Histogram",color:"#000",overflow_color:"#F66"};LinePainter.prototype.draw=function(ctx,width,height,w_scale){var in_path=false,min_value=this.prefs.min_value,max_value=this.prefs.max_value,vertical_range=max_value-min_value,height_px=height,view_start=this.view_start,mode=this.mode,data=this.data;ctx.save();var y_zero=Math.round(height+min_value/vertical_range*height);if(mode!=="Intensity"){ctx.fillStyle="#aaa";ctx.fillRect(0,y_zero,width,1)}ctx.beginPath();var x_scaled,y,delta_x_px;if(data.length>1){delta_x_px=Math.ceil((data[1][0]-data[0][0])*w_scale)}else{delta_x_px=10}var painter_color=this.prefs.block_color||this.prefs.color,pref_color=parseInt(painter_color.slice(1),16),pref_r=(pref_color&16711680)>>16,pref_g=(pref_color&65280)>>8,pref_b=pref_color&255,top_overflow=false,bot_overflow=false;for(var i=0,len=data.length;i<len;i++){ctx.fillStyle=ctx.strokeStyle=painter_color;top_overflow=bot_overflow=false;x_scaled=Math.round((data[i][0]-view_start)*w_scale);y=data[i][1];if(y===null){if(in_path&&mode==="Filled"){ctx.lineTo(x_scaled,height_px)}in_path=false;continue}if(y<min_value){bot_overflow=true;y=min_value}else{if(y>max_value){top_overflow=true;y=max_value}}if(mode==="Histogram"){y=Math.round(y/vertical_range*height_px);ctx.fillRect(x_scaled,y_zero,delta_x_px,-y)}else{if(mode==="Intensity"){var saturation=(y-min_value)/vertical_range,new_r=Math.round(pref_r+(255-pref_r)*(1-saturation)),new_g=Math.round(pref_g+(255-pref_g)*(1-saturation)),new_b=Math.round(pref_b+(255-pref_b)*(1-saturation));ctx.fillStyle="rgb("+new_r+","+new_g+","+new_b+")";ctx.fillRect(x_scaled,0,delta_x_px,height_px)}else{y=Math.round(height_px-(y-min_value)/vertical_range*height_px);if(in_path){ctx.lineTo(x_scaled,y)}else{in_path=true;if(mode==="Filled"){ctx.moveTo(x_scaled,height_px);ctx.lineTo(x_scaled,y)}else{ctx.moveTo(x_scaled,y)}}}}ctx.fillStyle=this.prefs.overflow_color;if(top_overflow||bot_overflow){var overflow_x;if(mode==="Histogram"||mode==="Intensity"){overflow_x=delta_x_px}else{x_scaled-=2;overflow_x=4}if(top_overflow){ctx.fillRect(x_scaled,0,overflow_x,3)}if(bot_overflow){ctx.fillRect(x_scaled,height_px-3,overflow_x,3)}}ctx.fillStyle=painter_color}if(mode==="Filled"){if(in_path){ctx.lineTo(x_scaled,y_zero);ctx.lineTo(0,y_zero)}ctx.fill()}else{ctx.stroke()}ctx.restore()};var FeaturePositionMapper=function(slot_height){this.feature_positions={};this.slot_height=slot_height;this.translation=0;this.y_translation=0};FeaturePositionMapper.prototype.map_feature_data=function(feature_data,slot,x_start,x_end){if(!this.feature_positions[slot]){this.feature_positions[slot]=[]}this.feature_positions[slot].push({data:feature_data,x_start:x_start,x_end:x_end})};FeaturePositionMapper.prototype.get_feature_data=function(x,y){var slot=Math.floor((y-this.y_translation)/this.slot_height),feature_dict;if(!this.feature_positions[slot]){return null}x+=this.translation;for(var i=0;i<this.feature_positions[slot].length;i++){feature_dict=this.feature_positions[slot][i];if(x>=feature_dict.x_start&&x<=feature_dict.x_end){return feature_dict.data}}};var FeaturePainter=function(data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler){Painter.call(this,data,view_start,view_end,prefs,mode);this.alpha_scaler=(alpha_scaler?alpha_scaler:new Scaler());this.height_scaler=(height_scaler?height_scaler:new Scaler());this.max_label_length=200};FeaturePainter.prototype.default_prefs={block_color:"#FFF",connector_color:"#FFF"};_.extend(FeaturePainter.prototype,{get_required_height:function(rows_required,width){var required_height=this.get_row_height(),y_scale=required_height,mode=this.mode;if(mode==="no_detail"||mode==="Squish"||mode==="Pack"){required_height=rows_required*y_scale}return required_height+this.get_top_padding(width)},get_top_padding:function(width){return 0},draw:function(ctx,width,height,w_scale,slots){var data=this.data,view_start=this.view_start,view_end=this.view_end;ctx.save();ctx.fillStyle=this.prefs.block_color;ctx.textAlign="right";var y_scale=this.get_row_height(),feature_mapper=new FeaturePositionMapper(y_scale),x_draw_coords,incomplete_features=[];for(var i=0,len=data.length;i<len;i++){var feature=data[i],feature_uid=feature[0],feature_start=feature[1],feature_end=feature[2],slot=(slots&&slots[feature_uid]!==undefined?slots[feature_uid]:null);if((this.mode==="Dense"||slot!==null)&&(feature_start<view_end&&feature_end>view_start)){x_draw_coords=this.draw_element(ctx,this.mode,feature,slot,view_start,view_end,w_scale,y_scale,width);feature_mapper.map_feature_data(feature,slot,x_draw_coords[0],x_draw_coords[1]);if(feature_start<view_start||feature_end>view_end){incomplete_features.push(feature)}}}ctx.restore();feature_mapper.y_translation=this.get_top_padding(width);return new DrawResults({incomplete_features:incomplete_features,feature_mapper:feature_mapper})},draw_element:function(ctx,mode,feature,slot,tile_low,tile_high,w_scale,y_scale,width){return[0,0]}});var DENSE_TRACK_HEIGHT=10,NO_DETAIL_TRACK_HEIGHT=3,SQUISH_TRACK_HEIGHT=5,PACK_TRACK_HEIGHT=10,NO_DETAIL_FEATURE_HEIGHT=1,DENSE_FEATURE_HEIGHT=9,SQUISH_FEATURE_HEIGHT=3,PACK_FEATURE_HEIGHT=9,LABEL_SPACING=2,CONNECTOR_COLOR="#ccc";var LinkedFeaturePainter=function(data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler){FeaturePainter.call(this,data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler);this.draw_background_connector=true;this.draw_individual_connectors=false};_.extend(LinkedFeaturePainter.prototype,FeaturePainter.prototype,{get_row_height:function(){var mode=this.mode,height;if(mode==="Dense"){height=DENSE_TRACK_HEIGHT}else{if(mode==="no_detail"){height=NO_DETAIL_TRACK_HEIGHT}else{if(mode==="Squish"){height=SQUISH_TRACK_HEIGHT}else{height=PACK_TRACK_HEIGHT}}}return height},draw_element:function(ctx,mode,feature,slot,tile_low,tile_high,w_scale,y_scale,width){var feature_uid=feature[0],feature_start=feature[1],feature_end=feature[2],feature_name=feature[3],feature_strand=feature[4],f_start=Math.floor(Math.max(0,(feature_start-tile_low-0.5)*w_scale)),f_end=Math.ceil(Math.min(width,Math.max(0,(feature_end-tile_low-0.5)*w_scale))),draw_start=f_start,draw_end=f_end,y_start=(mode==="Dense"?0:(0+slot))*y_scale+this.get_top_padding(width),thickness,y_start,thick_start=null,thick_end=null,block_color=(!feature_strand||feature_strand==="+"||feature_strand==="."?this.prefs.block_color:this.prefs.reverse_strand_color);label_color=this.prefs.label_color;ctx.globalAlpha=this.alpha_scaler.gen_val(feature);if(mode==="Dense"){slot=1}if(mode==="no_detail"){ctx.fillStyle=block_color;ctx.fillRect(f_start,y_start+5,f_end-f_start,NO_DETAIL_FEATURE_HEIGHT)}else{var feature_ts=feature[5],feature_te=feature[6],feature_blocks=feature[7],full_height=true;if(feature_ts&&feature_te){thick_start=Math.floor(Math.max(0,(feature_ts-tile_low)*w_scale));thick_end=Math.ceil(Math.min(width,Math.max(0,(feature_te-tile_low)*w_scale)))}var thin_height,thick_height;if(mode==="Squish"){thin_height=1;thick_height=SQUISH_FEATURE_HEIGHT;full_height=false}else{if(mode==="Dense"){thin_height=5;thick_height=DENSE_FEATURE_HEIGHT}else{thin_height=5;thick_height=PACK_FEATURE_HEIGHT}}if(!feature_blocks){ctx.fillStyle=block_color;ctx.fillRect(f_start,y_start+1,f_end-f_start,thick_height);if(feature_strand&&full_height){if(feature_strand==="+"){ctx.fillStyle=ctx.canvas.manager.get_pattern("right_strand_inv")}else{if(feature_strand==="-"){ctx.fillStyle=ctx.canvas.manager.get_pattern("left_strand_inv")}}ctx.fillRect(f_start,y_start+1,f_end-f_start,thick_height)}}else{var cur_y_start,cur_height;if(mode==="Squish"||mode==="Dense"){cur_y_start=y_start+Math.floor(SQUISH_FEATURE_HEIGHT/2)+1;cur_height=1}else{if(feature_strand){cur_y_start=y_start;cur_height=thick_height}else{cur_y_start+=(SQUISH_FEATURE_HEIGHT/2)+1;cur_height=1}}if(this.draw_background_connector){if(mode==="Squish"||mode==="Dense"){ctx.fillStyle=CONNECTOR_COLOR}else{if(feature_strand){if(feature_strand==="+"){ctx.fillStyle=ctx.canvas.manager.get_pattern("right_strand")}else{if(feature_strand==="-"){ctx.fillStyle=ctx.canvas.manager.get_pattern("left_strand")}}}else{ctx.fillStyle=CONNECTOR_COLOR}}ctx.fillRect(f_start,cur_y_start,f_end-f_start,cur_height)}var start_and_height;for(var k=0,k_len=feature_blocks.length;k<k_len;k++){var block=feature_blocks[k],block_start=Math.floor(Math.max(0,(block[0]-tile_low-0.5)*w_scale)),block_end=Math.ceil(Math.min(width,Math.max((block[1]-tile_low-0.5)*w_scale))),last_block_start,last_block_end;if(block_start>block_end){continue}ctx.fillStyle=block_color;ctx.fillRect(block_start,y_start+(thick_height-thin_height)/2+1,block_end-block_start,thin_height);if(thick_start!==undefined&&feature_te>feature_ts&&!(block_start>thick_end||block_end<thick_start)){var block_thick_start=Math.max(block_start,thick_start),block_thick_end=Math.min(block_end,thick_end);ctx.fillRect(block_thick_start,y_start+1,block_thick_end-block_thick_start,thick_height);if(feature_blocks.length===1&&mode==="Pack"){if(feature_strand==="+"){ctx.fillStyle=ctx.canvas.manager.get_pattern("right_strand_inv")}else{if(feature_strand==="-"){ctx.fillStyle=ctx.canvas.manager.get_pattern("left_strand_inv")}}if(block_thick_start+14<block_thick_end){block_thick_start+=2;block_thick_end-=2}ctx.fillRect(block_thick_start,y_start+1,block_thick_end-block_thick_start,thick_height)}}if(this.draw_individual_connectors&&last_block_start){this.draw_connector(ctx,last_block_start,last_block_end,block_start,block_end,y_start)}last_block_start=block_start;last_block_end=block_end}if(mode==="Pack"){ctx.globalAlpha=1;ctx.fillStyle="white";var hscale_factor=this.height_scaler.gen_val(feature),new_height=Math.ceil(thick_height*hscale_factor),ws_height=Math.round((thick_height-new_height)/2);if(hscale_factor!==1){ctx.fillRect(f_start,cur_y_start+1,f_end-f_start,ws_height);ctx.fillRect(f_start,cur_y_start+thick_height-ws_height+1,f_end-f_start,ws_height)}}}ctx.globalAlpha=1;if(feature_name&&mode==="Pack"&&feature_start>tile_low){ctx.fillStyle=label_color;if(tile_low===0&&f_start-ctx.measureText(feature_name).width<0){ctx.textAlign="left";ctx.fillText(feature_name,f_end+LABEL_SPACING,y_start+8,this.max_label_length);draw_end+=ctx.measureText(feature_name).width+LABEL_SPACING}else{ctx.textAlign="right";ctx.fillText(feature_name,f_start-LABEL_SPACING,y_start+8,this.max_label_length);draw_start-=ctx.measureText(feature_name).width+LABEL_SPACING}}}ctx.globalAlpha=1;return[draw_start,draw_end]}});var ReadPainter=function(data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler,ref_seq,base_color_fn){FeaturePainter.call(this,data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler);this.ref_seq=(ref_seq?ref_seq.data:null);this.base_color_fn=base_color_fn};_.extend(ReadPainter.prototype,FeaturePainter.prototype,{get_row_height:function(){var height,mode=this.mode;if(mode==="Dense"){height=DENSE_TRACK_HEIGHT}else{if(mode==="Squish"){height=SQUISH_TRACK_HEIGHT}else{height=PACK_TRACK_HEIGHT;if(this.prefs.show_insertions){height*=2}}}return height},_parse_cigar:function(cigar_str){var cigar_ops="MIDNSHP=X";var blocks=[[0,0]],cur_block=blocks[0],base_pos=0,parsed_cigar=_.map(cigar_str.match(/[0-9]+[MIDNSHP=X]/g),function(op){var op_len=parseInt(op.slice(0,-1),10),op_char=op.slice(-1);if(op_char==="N"){if(cur_block[1]!==0){cur_block=[base_pos+op_len,base_pos+op_len];blocks.push(cur_block)}}else{if("ISHP".indexOf(op_char)===-1){cur_block[1]+=op_len;base_pos+=op_len}}return[cigar_ops.indexOf(op_char),op_len]});return{blocks:blocks,cigar:parsed_cigar}},draw_read:function(ctx,mode,w_scale,y_start,tile_low,tile_high,feature_start,cigar,strand,read_seq){var update_base_offset=function(offset,cig_op,cig_len){if("M=NXD".indexOf(cig_op)!==-1){offset+=cig_len}return offset},update_seq_offset=function(offset,cig_op,cig_len){if("IX".indexOf(cig_op)!==-1){offset+=cig_len}return offset},get_draw_coord=function(sequence_coord){return Math.floor(Math.max(0,(sequence_coord-tile_low-0.5)*w_scale))};ctx.textAlign="center";var tile_region=[tile_low,tile_high],base_offset=0,seq_offset=0,gap=Math.round(w_scale/2),char_width_px=ctx.canvas.manager.char_width_px,block_color=(strand==="+"?this.prefs.detail_block_color:this.prefs.reverse_strand_color),pack_mode=(mode==="Pack"),draw_height=(pack_mode?PACK_FEATURE_HEIGHT:SQUISH_FEATURE_HEIGHT),rect_y=y_start+1,paint_utils=new ReadPainterUtils(ctx,draw_height,w_scale,mode),drawing_blocks=[],s_start,s_end;var draw_last=[];var t=this._parse_cigar(cigar);cigar=t.cigar;drawing_blocks=t.blocks;for(var i=0;i<drawing_blocks.length;i++){var block=drawing_blocks[i];if(is_overlap([feature_start+block[0],feature_start+block[1]],tile_region)){s_start=get_draw_coord(feature_start+block[0]);s_end=get_draw_coord(feature_start+block[1]);if(s_start===s_end){s_end+=1}ctx.fillStyle=block_color;ctx.fillRect(s_start,rect_y,s_end-s_start,draw_height)}}for(var cig_id=0,len=cigar.length;cig_id<len;cig_id++){var cig=cigar[cig_id],cig_op="MIDNSHP=X"[cig[0]],cig_len=cig[1];var seq_start=feature_start+base_offset;s_start=get_draw_coord(seq_start);s_end=get_draw_coord(seq_start+cig_len);if(!is_overlap([seq_start,seq_start+cig_len],tile_region)){base_offset=update_base_offset(base_offset,cig_op,cig_len);seq_offset=update_seq_offset(seq_offset,cig_op,cig_len);continue}if(s_start===s_end){s_end+=1}switch(cig_op){case"H":case"S":case"P":break;case"M":base_offset+=cig_len;break;case"=":case"X":var cur_seq="";if(cig_op==="X"){cur_seq=read_seq.slice(seq_offset,seq_offset+cig_len)}else{if(this.ref_seq){cur_seq=this.ref_seq.slice(Math.max(0,seq_start-tile_low),Math.min(seq_start-tile_low+cig_len,tile_high-tile_low))}}var start_pos=Math.max(seq_start,tile_low);for(var c=0;c<cur_seq.length;c++){if(cur_seq&&!this.prefs.show_differences||cig_op==="X"){var c_start=Math.floor(Math.max(0,(start_pos+c-tile_low)*w_scale));ctx.fillStyle=this.base_color_fn(cur_seq[c]);if(pack_mode&&w_scale>char_width_px){ctx.fillText(cur_seq[c],c_start,y_start+9)}else{if(w_scale>0.05){ctx.fillRect(c_start-gap,rect_y,Math.max(1,Math.round(w_scale)),draw_height)}}}}if(cig_op==="X"){seq_offset+=cig_len}base_offset+=cig_len;break;case"N":ctx.fillStyle=CONNECTOR_COLOR;ctx.fillRect(s_start,y_start+5,s_end-s_start,1);base_offset+=cig_len;break;case"D":paint_utils.draw_deletion(s_start,rect_y,cig_len);base_offset+=cig_len;break;case"I":var insert_x_coord=s_start-gap;if(is_overlap([seq_start,seq_start+cig_len],tile_region)){var seq=read_seq.slice(seq_offset,seq_offset+cig_len);if(this.prefs.show_insertions){var x_center=s_start-(s_end-s_start)/2;if((mode==="Pack"||this.mode==="Auto")&&read_seq!==undefined&&w_scale>char_width_px){ctx.fillStyle="yellow";ctx.fillRect(x_center-gap,y_start-9,s_end-s_start,9);draw_last[draw_last.length]={type:"triangle",data:[insert_x_coord,y_start+4,5]};ctx.fillStyle=CONNECTOR_COLOR;switch(compute_overlap([seq_start,seq_start+cig_len],tile_region)){case (OVERLAP_START):seq=seq.slice(tile_low-seq_start);break;case (OVERLAP_END):seq=seq.slice(0,seq_start-tile_high);break;case (CONTAINED_BY):break;case (CONTAINS):seq=seq.slice(tile_low-seq_start,seq_start-tile_high);break}for(var c=0,str_len=seq.length;c<str_len;c++){var c_start=Math.floor(Math.max(0,(seq_start+c-tile_low)*w_scale));ctx.fillText(seq[c],c_start-(s_end-s_start)/2,y_start)}}else{ctx.fillStyle="yellow";ctx.fillRect(x_center,y_start+(this.mode!=="Dense"?2:5),s_end-s_start,(mode!=="Dense"?SQUISH_FEATURE_HEIGHT:DENSE_FEATURE_HEIGHT))}}else{if((mode==="Pack"||this.mode==="Auto")&&read_seq!==undefined&&w_scale>char_width_px){draw_last.push({type:"text",data:[seq.length,insert_x_coord,y_start+9]})}else{}}}seq_offset+=cig_len;break}}ctx.fillStyle="yellow";var item,type,data;for(var i=0;i<draw_last.length;i++){item=draw_last[i];type=item.type;data=item.data;if(type==="text"){ctx.save();ctx.font="bold "+ctx.font;ctx.fillText(data[0],data[1],data[2]);ctx.restore()}else{if(type==="triangle"){drawDownwardEquilateralTriangle(ctx,data[0],data[1],data[2])}}}},draw_element:function(ctx,mode,feature,slot,tile_low,tile_high,w_scale,y_scale,width){var feature_uid=feature[0],feature_start=feature[1],feature_end=feature[2],feature_name=feature[3],f_start=Math.floor(Math.max(-0.5*w_scale,(feature_start-tile_low-0.5)*w_scale)),f_end=Math.ceil(Math.min(width,Math.max(0,(feature_end-tile_low-0.5)*w_scale))),y_start=(mode==="Dense"?0:(0+slot))*y_scale,label_color=this.prefs.label_color;if(feature[5] instanceof Array){var connector=true;if(feature[4][1]>=tile_low&&feature[4][0]<=tile_high&&feature[4][2]){this.draw_read(ctx,mode,w_scale,y_start,tile_low,tile_high,feature[4][0],feature[4][2],feature[4][3],feature[4][4])}else{connector=false}if(feature[5][1]>=tile_low&&feature[5][0]<=tile_high&&feature[5][2]){this.draw_read(ctx,mode,w_scale,y_start,tile_low,tile_high,feature[5][0],feature[5][2],feature[5][3],feature[5][4])}else{connector=false}var b1_end=Math.ceil(Math.min(width,Math.max(-0.5*w_scale,(feature[4][1]-tile_low-0.5)*w_scale))),b2_start=Math.floor(Math.max(-0.5*w_scale,(feature[5][0]-tile_low-0.5)*w_scale));if(connector&&b2_start>b1_end){ctx.fillStyle=CONNECTOR_COLOR;dashedLine(ctx,b1_end,y_start+5,b2_start,y_start+5)}}else{this.draw_read(ctx,mode,w_scale,y_start,tile_low,tile_high,feature_start,feature[4],feature[5],feature[6])}if(mode==="Pack"&&feature_start>=tile_low&&feature_name!=="."){ctx.fillStyle=this.prefs.label_color;if(tile_low===0&&f_start-ctx.measureText(feature_name).width<0){ctx.textAlign="left";ctx.fillText(feature_name,f_end+LABEL_SPACING,y_start+9,this.max_label_length)}else{ctx.textAlign="right";ctx.fillText(feature_name,f_start-LABEL_SPACING,y_start+9,this.max_label_length)}}return[0,0]}});var ArcLinkedFeaturePainter=function(data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler){LinkedFeaturePainter.call(this,data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler);this.longest_feature_length=this.calculate_longest_feature_length();this.draw_background_connector=false;this.draw_individual_connectors=true};_.extend(ArcLinkedFeaturePainter.prototype,FeaturePainter.prototype,LinkedFeaturePainter.prototype,{calculate_longest_feature_length:function(){var longest_feature_length=0;for(var i=0,len=this.data.length;i<len;i++){var feature=this.data[i],feature_start=feature[1],feature_end=feature[2];longest_feature_length=Math.max(longest_feature_length,feature_end-feature_start)}return longest_feature_length},get_top_padding:function(width){var view_range=this.view_end-this.view_start,w_scale=width/view_range;return Math.min(128,Math.ceil((this.longest_feature_length/2)*w_scale))},draw_connector:function(ctx,block1_start,block1_end,block2_start,block2_end,y_start){var x_center=(block1_end+block2_start)/2,radius=block2_start-x_center;var angle1=Math.PI,angle2=0;if(radius>0){ctx.beginPath();ctx.arc(x_center,y_start,block2_start-x_center,Math.PI,0);ctx.stroke()}}});var Color=function(rgb,a){if(Array.isArray(rgb)){this.rgb=rgb}else{if(rgb.length==6){this.rgb=rgb.match(/.{2}/g).map(function(c){return parseInt(c,16)})}else{if(rgb.length==7){this.rgb=rgb.substring(1,7).match(/.{2}/g).map(function(c){return parseInt(c,16)})}else{this.rgb=rgb.split("").map(function(c){return parseInt(c+c,16)})}}}this.alpha=typeof(a)==="number"?a:1};Color.prototype={eval:function(){return this},toCSS:function(){if(this.alpha<1){return"rgba("+this.rgb.map(function(c){return Math.round(c)}).concat(this.alpha).join(", ")+")"}else{return"#"+this.rgb.map(function(i){i=Math.round(i);i=(i>255?255:(i<0?0:i)).toString(16);return i.length===1?"0"+i:i}).join("")}},toHSL:function(){var r=this.rgb[0]/255,g=this.rgb[1]/255,b=this.rgb[2]/255,a=this.alpha;var max=Math.max(r,g,b),min=Math.min(r,g,b);var h,s,l=(max+min)/2,d=max-min;if(max===min){h=s=0}else{s=l>0.5?d/(2-max-min):d/(max+min);switch(max){case r:h=(g-b)/d+(g<b?6:0);break;case g:h=(b-r)/d+2;break;case b:h=(r-g)/d+4;break}h/=6}return{h:h*360,s:s,l:l,a:a}},toARGB:function(){var argb=[Math.round(this.alpha*255)].concat(this.rgb);return"#"+argb.map(function(i){i=Math.round(i);i=(i>255?255:(i<0?0:i)).toString(16);return i.length===1?"0"+i:i}).join("")},mix:function(color2,weight){color1=this;var p=weight;var w=p*2-1;var a=color1.toHSL().a-color2.toHSL().a;var w1=(((w*a==-1)?w:(w+a)/(1+w*a))+1)/2;var w2=1-w1;var rgb=[color1.rgb[0]*w1+color2.rgb[0]*w2,color1.rgb[1]*w1+color2.rgb[1]*w2,color1.rgb[2]*w1+color2.rgb[2]*w2];var alpha=color1.alpha*p+color2.alpha*(1-p);return new Color(rgb,alpha)}};var LinearRamp=function(start_color,end_color,start_value,end_value){this.start_color=new Color(start_color);this.end_color=new Color(end_color);this.start_value=start_value;this.end_value=end_value;this.value_range=end_value-start_value};LinearRamp.prototype.map_value=function(value){value=Math.max(value,this.start_value);value=Math.min(value,this.end_value);value=(value-this.start_value)/this.value_range;return this.start_color.mix(this.end_color,1-value).toCSS()};var SplitRamp=function(start_color,middle_color,end_color,start_value,end_value){this.positive_ramp=new LinearRamp(middle_color,end_color,0,end_value);this.negative_ramp=new LinearRamp(middle_color,start_color,0,-start_value);this.start_value=start_value;this.end_value=end_value};SplitRamp.prototype.map_value=function(value){value=Math.max(value,this.start_value);value=Math.min(value,this.end_value);if(value>=0){return this.positive_ramp.map_value(value)}else{return this.negative_ramp.map_value(-value)}};var DiagonalHeatmapPainter=function(data,view_start,view_end,prefs,mode){Painter.call(this,data,view_start,view_end,prefs,mode);var i,len;if(this.prefs.min_value===undefined){var min_value=Infinity;for(i=0,len=this.data.length;i<len;i++){min_value=Math.min(min_value,this.data[i][5])}this.prefs.min_value=min_value}if(this.prefs.max_value===undefined){var max_value=-Infinity;for(i=0,len=this.data.length;i<len;i++){max_value=Math.max(max_value,this.data[i][5])}this.prefs.max_value=max_value}};DiagonalHeatmapPainter.prototype.default_prefs={min_value:undefined,max_value:undefined,mode:"Heatmap",pos_color:"#FF8C00",neg_color:"#4169E1"};DiagonalHeatmapPainter.prototype.draw=function(ctx,width,height,w_scale){var min_value=this.prefs.min_value,max_value=this.prefs.max_value,value_range=max_value-min_value,height_px=height,view_start=this.view_start,mode=this.mode,data=this.data,invsqrt2=1/Math.sqrt(2);var ramp=(new SplitRamp(this.prefs.neg_color,"#FFFFFF",this.prefs.pos_color,min_value,max_value));var d,s1,e1,s2,e2,value;var scale=function(p){return(p-view_start)*w_scale};ctx.save();ctx.rotate(-45*Math.PI/180);ctx.scale(invsqrt2,invsqrt2);for(var i=0,len=data.length;i<len;i++){d=data[i];s1=scale(d[1]);e1=scale(d[2]);s2=scale(d[4]);e2=scale(d[5]);value=d[6];ctx.fillStyle=(ramp.map_value(value));ctx.fillRect(s1,s2,(e1-s1),(e2-s2))}ctx.restore()};var ReadPainterUtils=function(ctx,row_height,px_per_base,mode){this.ctx=ctx;this.row_height=row_height;this.px_per_base=px_per_base;this.draw_details=(mode==="Pack"||mode==="Auto")&&(px_per_base>=ctx.canvas.manager.char_width_px);this.delete_details_thickness=0.2};_.extend(ReadPainterUtils.prototype,{draw_deletion:function(x,y,len){this.ctx.fillStyle="black";var thickness=(this.draw_details?this.delete_details_thickness:1)*this.row_height;y+=0.5*(this.row_height-thickness);this.ctx.fillRect(x,y,len*this.px_per_base,thickness)}});var VariantPainter=function(data,view_start,view_end,prefs,mode,base_color_fn){Painter.call(this,data,view_start,view_end,prefs,mode);this.base_color_fn=base_color_fn;this.divider_height=1};_.extend(VariantPainter.prototype,Painter.prototype,{get_row_height:function(){var mode=this.mode,height;if(mode==="Dense"){height=DENSE_TRACK_HEIGHT}else{if(mode==="Squish"){height=SQUISH_TRACK_HEIGHT}else{height=PACK_TRACK_HEIGHT}}return height},get_required_height:function(num_samples){var height=this.prefs.summary_height;if(num_samples>1&&this.prefs.show_sample_data){height+=this.divider_height+num_samples*this.get_row_height()}return height},draw:function(ctx,width,height,w_scale){ctx.save();var get_deletion_info=function(ref,alt){var ref_len=ref.length,alt_len=alt.length,start=0,len=1,is_delete=false;if(alt==="-"){is_delete=true;len=ref.length}else{if(ref.indexOf(alt)===0&&ref_len>alt_len){is_delete=true;len=ref_len=alt_len;start+=alt_len}}return(is_delete?{start:start,len:len}:null)};var locus_data,pos,id,ref,alt,qual,filter,sample_gts,allele_counts,variant,draw_x_start,char_x_start,draw_y_start,genotype,base_px=Math.max(1,Math.floor(w_scale)),num_samples=(this.data.length?this.data[0][7].split(",").length:0),row_height=(this.mode==="Squish"?SQUISH_TRACK_HEIGHT:PACK_TRACK_HEIGHT),feature_height=(w_scale<0.1?row_height:(this.mode==="Squish"?SQUISH_FEATURE_HEIGHT:PACK_FEATURE_HEIGHT)),draw_summary=true,paint_utils=new ReadPainterUtils(ctx,row_height,w_scale,this.mode),j;if(num_samples===1){row_height=feature_height=(w_scale<ctx.canvas.manager.char_width_px?this.prefs.summary_height:row_height);paint_utils.row_height=row_height;draw_summary=false}if(this.prefs.show_sample_data&&draw_summary){ctx.fillStyle="#F3F3F3";ctx.globalAlpha=1;ctx.fillRect(0,this.prefs.summary_height-this.divider_height,width,this.divider_height)}ctx.textAlign="center";for(var i=0;i<this.data.length;i++){locus_data=this.data[i];pos=locus_data[1];ref=locus_data[3];alt=[locus_data[4].split(",")];sample_gts=locus_data[7].split(",");allele_counts=locus_data.slice(8);alt=_.map(_.flatten(alt),function(a){var type,alt_info={},delete_info=get_deletion_info(ref,a);if(delete_info){type="deletion";_.extend(alt_info,delete_info)}else{type="snp"}return _.extend(alt_info,{type:type,value:a,})});if(pos<this.view_start||pos>this.view_end){continue}draw_x_start=Math.floor(Math.max(-0.5*w_scale,(pos-this.view_start-0.5)*w_scale));char_x_start=Math.floor(Math.max(0,(pos-this.view_start)*w_scale));if(draw_summary){ctx.fillStyle="#999999";ctx.globalAlpha=1;ctx.fillRect(draw_x_start,0,base_px,this.prefs.summary_height);draw_y_start=this.prefs.summary_height;for(j=0;j<alt.length;j++){ctx.fillStyle=(alt[j].type==="deletion"?"black":this.base_color_fn(alt[j].value));allele_frac=allele_counts/sample_gts.length;draw_height=Math.ceil(this.prefs.summary_height*allele_frac);ctx.fillRect(draw_x_start,draw_y_start-draw_height,base_px,draw_height);draw_y_start-=draw_height}}if(!this.prefs.show_sample_data){continue}draw_y_start=(draw_summary?this.prefs.summary_height+this.divider_height:0);for(j=0;j<sample_gts.length;j++,draw_y_start+=row_height){genotype=(sample_gts[j]?sample_gts[j].split(/\/|\|/):["0","0"]);variant=null;if(genotype[0]===genotype[1]){if(genotype[0]==="."){}else{if(genotype[0]!=="0"){variant=alt[parseInt(genotype[0],10)-1];ctx.globalAlpha=1}}}else{variant=(genotype[0]!=="0"?genotype[0]:genotype[1]);variant=alt[parseInt(variant,10)-1];ctx.globalAlpha=0.5}if(variant){if(variant.type==="snp"){var snp=variant.value;ctx.fillStyle=this.base_color_fn(snp);if(paint_utils.draw_details){ctx.fillText(snp,char_x_start,draw_y_start+row_height)}else{ctx.fillRect(draw_x_start,draw_y_start+1,base_px,feature_height)}}else{if(variant.type==="deletion"){paint_utils.draw_deletion(draw_x_start+base_px*variant.start,draw_y_start+1,variant.len)}else{}}}}}ctx.restore()}});return{Scaler:Scaler,LinePainter:LinePainter,LinkedFeaturePainter:LinkedFeaturePainter,ReadPainter:ReadPainter,ArcLinkedFeaturePainter:ArcLinkedFeaturePainter,DiagonalHeatmapPainter:DiagonalHeatmapPainter,VariantPainter:VariantPainter}});
\ No newline at end of file
+define(["libs/underscore"],function(_){var BEFORE=1001,CONTAINS=1002,OVERLAP_START=1003,OVERLAP_END=1004,CONTAINED_BY=1005,AFTER=1006;var compute_overlap=function(first_region,second_region){var first_start=first_region[0],first_end=first_region[1],second_start=second_region[0],second_end=second_region[1],overlap;if(first_start<second_start){if(first_end<=second_start){overlap=BEFORE}else{if(first_end<=second_end){overlap=OVERLAP_START}else{overlap=CONTAINS}}}else{if(first_start>second_end){overlap=AFTER}else{if(first_end<=second_end){overlap=CONTAINED_BY}else{overlap=OVERLAP_END}}}return overlap};var is_overlap=function(first_region,second_region){var overlap=compute_overlap(first_region,second_region);return(overlap!==BEFORE&&overlap!==AFTER)};var dashedLine=function(ctx,x1,y1,x2,y2,dashLen){if(dashLen===undefined){dashLen=4}var dX=x2-x1;var dY=y2-y1;var dashes=Math.floor(Math.sqrt(dX*dX+dY*dY)/dashLen);var dashX=dX/dashes;var dashY=dY/dashes;var q;for(q=0;q<dashes;q++,x1+=dashX,y1+=dashY){if(q%2!==0){continue}ctx.fillRect(x1,y1,dashLen,1)}};var drawDownwardEquilateralTriangle=function(ctx,down_vertex_x,down_vertex_y,side_len){var x1=down_vertex_x-side_len/2,x2=down_vertex_x+side_len/2,y=down_vertex_y-Math.sqrt(side_len*3/2);ctx.beginPath();ctx.moveTo(x1,y);ctx.lineTo(x2,y);ctx.lineTo(down_vertex_x,down_vertex_y);ctx.lineTo(x1,y);ctx.strokeStyle=this.fillStyle;ctx.fill();ctx.stroke();ctx.closePath()};var Scaler=function(default_val){this.default_val=(default_val?default_val:1)};Scaler.prototype.gen_val=function(input){return this.default_val};var DrawResults=function(options){this.incomplete_features=options.incomplete_features;this.feature_mapper=options.feature_mapper};var Painter=function(data,view_start,view_end,prefs,mode){this.data=data;this.view_start=view_start;this.view_end=view_end;this.prefs=_.extend({},this.default_prefs,prefs);this.mode=mode};Painter.prototype.default_prefs={};Painter.prototype.draw=function(ctx,width,height,w_scale){};var LinePainter=function(data,view_start,view_end,prefs,mode){Painter.call(this,data,view_start,view_end,prefs,mode);if(this.prefs.min_value===undefined){this.prefs.min_value=_.min(_.map(this.data,function(d){return d[1]}))||0}if(this.prefs.max_value===undefined){this.prefs.max_value=_.max(_.map(this.data,function(d){return d[1]}))||0}};LinePainter.prototype.default_prefs={min_value:undefined,max_value:undefined,mode:"Histogram",color:"#000",overflow_color:"#F66"};LinePainter.prototype.draw=function(ctx,width,height,w_scale){var in_path=false,min_value=this.prefs.min_value,max_value=this.prefs.max_value,vertical_range=max_value-min_value,height_px=height,view_start=this.view_start,mode=this.mode,data=this.data;ctx.save();var y_zero=Math.round(height+min_value/vertical_range*height);if(mode!=="Intensity"){ctx.fillStyle="#aaa";ctx.fillRect(0,y_zero,width,1)}ctx.beginPath();var x_scaled,y,delta_x_px;if(data.length>1){delta_x_px=Math.ceil((data[1][0]-data[0][0])*w_scale)}else{delta_x_px=10}var painter_color=this.prefs.block_color||this.prefs.color,pref_color=parseInt(painter_color.slice(1),16),pref_r=(pref_color&16711680)>>16,pref_g=(pref_color&65280)>>8,pref_b=pref_color&255,top_overflow=false,bot_overflow=false;for(var i=0,len=data.length;i<len;i++){ctx.fillStyle=ctx.strokeStyle=painter_color;top_overflow=bot_overflow=false;x_scaled=Math.ceil((data[i][0]-view_start)*w_scale);y=data[i][1];if(y===null){if(in_path&&mode==="Filled"){ctx.lineTo(x_scaled,height_px)}in_path=false;continue}if(y<min_value){bot_overflow=true;y=min_value}else{if(y>max_value){top_overflow=true;y=max_value}}if(mode==="Histogram"){y=Math.round(y/vertical_range*height_px);ctx.fillRect(x_scaled,y_zero,delta_x_px,-y)}else{if(mode==="Intensity"){var saturation=(y-min_value)/vertical_range,new_r=Math.round(pref_r+(255-pref_r)*(1-saturation)),new_g=Math.round(pref_g+(255-pref_g)*(1-saturation)),new_b=Math.round(pref_b+(255-pref_b)*(1-saturation));ctx.fillStyle="rgb("+new_r+","+new_g+","+new_b+")";ctx.fillRect(x_scaled,0,delta_x_px,height_px)}else{y=Math.round(height_px-(y-min_value)/vertical_range*height_px);if(in_path){ctx.lineTo(x_scaled,y)}else{in_path=true;if(mode==="Filled"){ctx.moveTo(x_scaled,height_px);ctx.lineTo(x_scaled,y)}else{ctx.moveTo(x_scaled,y)}}}}ctx.fillStyle=this.prefs.overflow_color;if(top_overflow||bot_overflow){var overflow_x;if(mode==="Histogram"||mode==="Intensity"){overflow_x=delta_x_px}else{x_scaled-=2;overflow_x=4}if(top_overflow){ctx.fillRect(x_scaled,0,overflow_x,3)}if(bot_overflow){ctx.fillRect(x_scaled,height_px-3,overflow_x,3)}}ctx.fillStyle=painter_color}if(mode==="Filled"){if(in_path){ctx.lineTo(x_scaled,y_zero);ctx.lineTo(0,y_zero)}ctx.fill()}else{ctx.stroke()}ctx.restore()};var FeaturePositionMapper=function(slot_height){this.feature_positions={};this.slot_height=slot_height;this.translation=0;this.y_translation=0};FeaturePositionMapper.prototype.map_feature_data=function(feature_data,slot,x_start,x_end){if(!this.feature_positions[slot]){this.feature_positions[slot]=[]}this.feature_positions[slot].push({data:feature_data,x_start:x_start,x_end:x_end})};FeaturePositionMapper.prototype.get_feature_data=function(x,y){var slot=Math.floor((y-this.y_translation)/this.slot_height),feature_dict;if(!this.feature_positions[slot]){return null}x+=this.translation;for(var i=0;i<this.feature_positions[slot].length;i++){feature_dict=this.feature_positions[slot][i];if(x>=feature_dict.x_start&&x<=feature_dict.x_end){return feature_dict.data}}};var FeaturePainter=function(data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler){Painter.call(this,data,view_start,view_end,prefs,mode);this.alpha_scaler=(alpha_scaler?alpha_scaler:new Scaler());this.height_scaler=(height_scaler?height_scaler:new Scaler());this.max_label_length=200};FeaturePainter.prototype.default_prefs={block_color:"#FFF",connector_color:"#FFF"};_.extend(FeaturePainter.prototype,{get_required_height:function(rows_required,width){var required_height=this.get_row_height(),y_scale=required_height,mode=this.mode;if(mode==="no_detail"||mode==="Squish"||mode==="Pack"){required_height=rows_required*y_scale}return required_height+this.get_top_padding(width)},get_top_padding:function(width){return 0},draw:function(ctx,width,height,w_scale,slots){var data=this.data,view_start=this.view_start,view_end=this.view_end;ctx.save();ctx.fillStyle=this.prefs.block_color;ctx.textAlign="right";var y_scale=this.get_row_height(),feature_mapper=new FeaturePositionMapper(y_scale),x_draw_coords,incomplete_features=[];for(var i=0,len=data.length;i<len;i++){var feature=data[i],feature_uid=feature[0],feature_start=feature[1],feature_end=feature[2],slot=(slots&&slots[feature_uid]!==undefined?slots[feature_uid]:null);if((this.mode==="Dense"||slot!==null)&&(feature_start<view_end&&feature_end>view_start)){x_draw_coords=this.draw_element(ctx,this.mode,feature,slot,view_start,view_end,w_scale,y_scale,width);feature_mapper.map_feature_data(feature,slot,x_draw_coords[0],x_draw_coords[1]);if(feature_start<view_start||feature_end>view_end){incomplete_features.push(feature)}}}ctx.restore();feature_mapper.y_translation=this.get_top_padding(width);return new DrawResults({incomplete_features:incomplete_features,feature_mapper:feature_mapper})},draw_element:function(ctx,mode,feature,slot,tile_low,tile_high,w_scale,y_scale,width){return[0,0]}});var DENSE_TRACK_HEIGHT=10,NO_DETAIL_TRACK_HEIGHT=3,SQUISH_TRACK_HEIGHT=5,PACK_TRACK_HEIGHT=10,NO_DETAIL_FEATURE_HEIGHT=1,DENSE_FEATURE_HEIGHT=9,SQUISH_FEATURE_HEIGHT=3,PACK_FEATURE_HEIGHT=9,LABEL_SPACING=2,CONNECTOR_COLOR="#ccc";var LinkedFeaturePainter=function(data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler){FeaturePainter.call(this,data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler);this.draw_background_connector=true;this.draw_individual_connectors=false};_.extend(LinkedFeaturePainter.prototype,FeaturePainter.prototype,{get_row_height:function(){var mode=this.mode,height;if(mode==="Dense"){height=DENSE_TRACK_HEIGHT}else{if(mode==="no_detail"){height=NO_DETAIL_TRACK_HEIGHT}else{if(mode==="Squish"){height=SQUISH_TRACK_HEIGHT}else{height=PACK_TRACK_HEIGHT}}}return height},draw_element:function(ctx,mode,feature,slot,tile_low,tile_high,w_scale,y_scale,width){var feature_uid=feature[0],feature_start=feature[1],feature_end=feature[2],feature_name=feature[3],feature_strand=feature[4],f_start=Math.floor(Math.max(0,(feature_start-tile_low-0.5)*w_scale)),f_end=Math.ceil(Math.min(width,Math.max(0,(feature_end-tile_low-0.5)*w_scale))),draw_start=f_start,draw_end=f_end,y_start=(mode==="Dense"?0:(0+slot))*y_scale+this.get_top_padding(width),thickness,y_start,thick_start=null,thick_end=null,block_color=(!feature_strand||feature_strand==="+"||feature_strand==="."?this.prefs.block_color:this.prefs.reverse_strand_color);label_color=this.prefs.label_color;ctx.globalAlpha=this.alpha_scaler.gen_val(feature);if(mode==="Dense"){slot=1}if(mode==="no_detail"){ctx.fillStyle=block_color;ctx.fillRect(f_start,y_start+5,f_end-f_start,NO_DETAIL_FEATURE_HEIGHT)}else{var feature_ts=feature[5],feature_te=feature[6],feature_blocks=feature[7],full_height=true;if(feature_ts&&feature_te){thick_start=Math.floor(Math.max(0,(feature_ts-tile_low)*w_scale));thick_end=Math.ceil(Math.min(width,Math.max(0,(feature_te-tile_low)*w_scale)))}var thin_height,thick_height;if(mode==="Squish"){thin_height=1;thick_height=SQUISH_FEATURE_HEIGHT;full_height=false}else{if(mode==="Dense"){thin_height=5;thick_height=DENSE_FEATURE_HEIGHT}else{thin_height=5;thick_height=PACK_FEATURE_HEIGHT}}if(!feature_blocks){ctx.fillStyle=block_color;ctx.fillRect(f_start,y_start+1,f_end-f_start,thick_height);if(feature_strand&&full_height){if(feature_strand==="+"){ctx.fillStyle=ctx.canvas.manager.get_pattern("right_strand_inv")}else{if(feature_strand==="-"){ctx.fillStyle=ctx.canvas.manager.get_pattern("left_strand_inv")}}ctx.fillRect(f_start,y_start+1,f_end-f_start,thick_height)}}else{var cur_y_start,cur_height;if(mode==="Squish"||mode==="Dense"){cur_y_start=y_start+Math.floor(SQUISH_FEATURE_HEIGHT/2)+1;cur_height=1}else{if(feature_strand){cur_y_start=y_start;cur_height=thick_height}else{cur_y_start+=(SQUISH_FEATURE_HEIGHT/2)+1;cur_height=1}}if(this.draw_background_connector){if(mode==="Squish"||mode==="Dense"){ctx.fillStyle=CONNECTOR_COLOR}else{if(feature_strand){if(feature_strand==="+"){ctx.fillStyle=ctx.canvas.manager.get_pattern("right_strand")}else{if(feature_strand==="-"){ctx.fillStyle=ctx.canvas.manager.get_pattern("left_strand")}}}else{ctx.fillStyle=CONNECTOR_COLOR}}ctx.fillRect(f_start,cur_y_start,f_end-f_start,cur_height)}var start_and_height;for(var k=0,k_len=feature_blocks.length;k<k_len;k++){var block=feature_blocks[k],block_start=Math.floor(Math.max(0,(block[0]-tile_low-0.5)*w_scale)),block_end=Math.ceil(Math.min(width,Math.max((block[1]-tile_low-0.5)*w_scale))),last_block_start,last_block_end;if(block_start>block_end){continue}ctx.fillStyle=block_color;ctx.fillRect(block_start,y_start+(thick_height-thin_height)/2+1,block_end-block_start,thin_height);if(thick_start!==undefined&&feature_te>feature_ts&&!(block_start>thick_end||block_end<thick_start)){var block_thick_start=Math.max(block_start,thick_start),block_thick_end=Math.min(block_end,thick_end);ctx.fillRect(block_thick_start,y_start+1,block_thick_end-block_thick_start,thick_height);if(feature_blocks.length===1&&mode==="Pack"){if(feature_strand==="+"){ctx.fillStyle=ctx.canvas.manager.get_pattern("right_strand_inv")}else{if(feature_strand==="-"){ctx.fillStyle=ctx.canvas.manager.get_pattern("left_strand_inv")}}if(block_thick_start+14<block_thick_end){block_thick_start+=2;block_thick_end-=2}ctx.fillRect(block_thick_start,y_start+1,block_thick_end-block_thick_start,thick_height)}}if(this.draw_individual_connectors&&last_block_start){this.draw_connector(ctx,last_block_start,last_block_end,block_start,block_end,y_start)}last_block_start=block_start;last_block_end=block_end}if(mode==="Pack"){ctx.globalAlpha=1;ctx.fillStyle="white";var hscale_factor=this.height_scaler.gen_val(feature),new_height=Math.ceil(thick_height*hscale_factor),ws_height=Math.round((thick_height-new_height)/2);if(hscale_factor!==1){ctx.fillRect(f_start,cur_y_start+1,f_end-f_start,ws_height);ctx.fillRect(f_start,cur_y_start+thick_height-ws_height+1,f_end-f_start,ws_height)}}}ctx.globalAlpha=1;if(feature_name&&mode==="Pack"&&feature_start>tile_low){ctx.fillStyle=label_color;if(tile_low===0&&f_start-ctx.measureText(feature_name).width<0){ctx.textAlign="left";ctx.fillText(feature_name,f_end+LABEL_SPACING,y_start+8,this.max_label_length);draw_end+=ctx.measureText(feature_name).width+LABEL_SPACING}else{ctx.textAlign="right";ctx.fillText(feature_name,f_start-LABEL_SPACING,y_start+8,this.max_label_length);draw_start-=ctx.measureText(feature_name).width+LABEL_SPACING}}}ctx.globalAlpha=1;return[draw_start,draw_end]}});var ReadPainter=function(data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler,ref_seq,base_color_fn){FeaturePainter.call(this,data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler);this.ref_seq=(ref_seq?ref_seq.data:null);this.base_color_fn=base_color_fn};_.extend(ReadPainter.prototype,FeaturePainter.prototype,{get_row_height:function(){var height,mode=this.mode;if(mode==="Dense"){height=DENSE_TRACK_HEIGHT}else{if(mode==="Squish"){height=SQUISH_TRACK_HEIGHT}else{height=PACK_TRACK_HEIGHT;if(this.prefs.show_insertions){height*=2}}}return height},_parse_cigar:function(cigar_str){var cigar_ops="MIDNSHP=X";var blocks=[[0,0]],cur_block=blocks[0],base_pos=0,parsed_cigar=_.map(cigar_str.match(/[0-9]+[MIDNSHP=X]/g),function(op){var op_len=parseInt(op.slice(0,-1),10),op_char=op.slice(-1);if(op_char==="N"){if(cur_block[1]!==0){cur_block=[base_pos+op_len,base_pos+op_len];blocks.push(cur_block)}}else{if("ISHP".indexOf(op_char)===-1){cur_block[1]+=op_len;base_pos+=op_len}}return[cigar_ops.indexOf(op_char),op_len]});return{blocks:blocks,cigar:parsed_cigar}},draw_read:function(ctx,mode,w_scale,y_start,tile_low,tile_high,feature_start,cigar,strand,read_seq){var update_base_offset=function(offset,cig_op,cig_len){if("M=NXD".indexOf(cig_op)!==-1){offset+=cig_len}return offset},update_seq_offset=function(offset,cig_op,cig_len){if("IX".indexOf(cig_op)!==-1){offset+=cig_len}return offset},get_draw_coord=function(sequence_coord){return Math.floor(Math.max(0,(sequence_coord-tile_low-0.5)*w_scale))};ctx.textAlign="center";var tile_region=[tile_low,tile_high],base_offset=0,seq_offset=0,gap=Math.round(w_scale/2),char_width_px=ctx.canvas.manager.char_width_px,block_color=(strand==="+"?this.prefs.detail_block_color:this.prefs.reverse_strand_color),pack_mode=(mode==="Pack"),draw_height=(pack_mode?PACK_FEATURE_HEIGHT:SQUISH_FEATURE_HEIGHT),rect_y=y_start+1,paint_utils=new ReadPainterUtils(ctx,draw_height,w_scale,mode),drawing_blocks=[],s_start,s_end;var draw_last=[];var t=this._parse_cigar(cigar);cigar=t.cigar;drawing_blocks=t.blocks;for(var i=0;i<drawing_blocks.length;i++){var block=drawing_blocks[i];if(is_overlap([feature_start+block[0],feature_start+block[1]],tile_region)){s_start=get_draw_coord(feature_start+block[0]);s_end=get_draw_coord(feature_start+block[1]);if(s_start===s_end){s_end+=1}ctx.fillStyle=block_color;ctx.fillRect(s_start,rect_y,s_end-s_start,draw_height)}}for(var cig_id=0,len=cigar.length;cig_id<len;cig_id++){var cig=cigar[cig_id],cig_op="MIDNSHP=X"[cig[0]],cig_len=cig[1];var seq_start=feature_start+base_offset;s_start=get_draw_coord(seq_start);s_end=get_draw_coord(seq_start+cig_len);if(!is_overlap([seq_start,seq_start+cig_len],tile_region)){base_offset=update_base_offset(base_offset,cig_op,cig_len);seq_offset=update_seq_offset(seq_offset,cig_op,cig_len);continue}if(s_start===s_end){s_end+=1}switch(cig_op){case"H":case"S":case"P":break;case"M":base_offset+=cig_len;break;case"=":case"X":var cur_seq="";if(cig_op==="X"){cur_seq=read_seq.slice(seq_offset,seq_offset+cig_len)}else{if(this.ref_seq){cur_seq=this.ref_seq.slice(Math.max(0,seq_start-tile_low),Math.min(seq_start-tile_low+cig_len,tile_high-tile_low))}}var start_pos=Math.max(seq_start,tile_low);for(var c=0;c<cur_seq.length;c++){if(cur_seq&&!this.prefs.show_differences||cig_op==="X"){var c_start=Math.floor(Math.max(0,(start_pos+c-tile_low)*w_scale));ctx.fillStyle=this.base_color_fn(cur_seq[c]);if(pack_mode&&w_scale>char_width_px){ctx.fillText(cur_seq[c],c_start,y_start+9)}else{if(w_scale>0.05){ctx.fillRect(c_start-gap,rect_y,Math.max(1,Math.round(w_scale)),draw_height)}}}}if(cig_op==="X"){seq_offset+=cig_len}base_offset+=cig_len;break;case"N":ctx.fillStyle=CONNECTOR_COLOR;ctx.fillRect(s_start,y_start+5,s_end-s_start,1);base_offset+=cig_len;break;case"D":paint_utils.draw_deletion(s_start,rect_y,cig_len);base_offset+=cig_len;break;case"I":var insert_x_coord=s_start-gap;if(is_overlap([seq_start,seq_start+cig_len],tile_region)){var seq=read_seq.slice(seq_offset,seq_offset+cig_len);if(this.prefs.show_insertions){var x_center=s_start-(s_end-s_start)/2;if((mode==="Pack"||this.mode==="Auto")&&read_seq!==undefined&&w_scale>char_width_px){ctx.fillStyle="yellow";ctx.fillRect(x_center-gap,y_start-9,s_end-s_start,9);draw_last[draw_last.length]={type:"triangle",data:[insert_x_coord,y_start+4,5]};ctx.fillStyle=CONNECTOR_COLOR;switch(compute_overlap([seq_start,seq_start+cig_len],tile_region)){case (OVERLAP_START):seq=seq.slice(tile_low-seq_start);break;case (OVERLAP_END):seq=seq.slice(0,seq_start-tile_high);break;case (CONTAINED_BY):break;case (CONTAINS):seq=seq.slice(tile_low-seq_start,seq_start-tile_high);break}for(var c=0,str_len=seq.length;c<str_len;c++){var c_start=Math.floor(Math.max(0,(seq_start+c-tile_low)*w_scale));ctx.fillText(seq[c],c_start-(s_end-s_start)/2,y_start)}}else{ctx.fillStyle="yellow";ctx.fillRect(x_center,y_start+(this.mode!=="Dense"?2:5),s_end-s_start,(mode!=="Dense"?SQUISH_FEATURE_HEIGHT:DENSE_FEATURE_HEIGHT))}}else{if((mode==="Pack"||this.mode==="Auto")&&read_seq!==undefined&&w_scale>char_width_px){draw_last.push({type:"text",data:[seq.length,insert_x_coord,y_start+9]})}else{}}}seq_offset+=cig_len;break}}ctx.fillStyle="yellow";var item,type,data;for(var i=0;i<draw_last.length;i++){item=draw_last[i];type=item.type;data=item.data;if(type==="text"){ctx.save();ctx.font="bold "+ctx.font;ctx.fillText(data[0],data[1],data[2]);ctx.restore()}else{if(type==="triangle"){drawDownwardEquilateralTriangle(ctx,data[0],data[1],data[2])}}}},draw_element:function(ctx,mode,feature,slot,tile_low,tile_high,w_scale,y_scale,width){var feature_uid=feature[0],feature_start=feature[1],feature_end=feature[2],feature_name=feature[3],f_start=Math.floor(Math.max(-0.5*w_scale,(feature_start-tile_low-0.5)*w_scale)),f_end=Math.ceil(Math.min(width,Math.max(0,(feature_end-tile_low-0.5)*w_scale))),y_start=(mode==="Dense"?0:(0+slot))*y_scale,label_color=this.prefs.label_color;if(feature[5] instanceof Array){var connector=true;if(feature[4][1]>=tile_low&&feature[4][0]<=tile_high&&feature[4][2]){this.draw_read(ctx,mode,w_scale,y_start,tile_low,tile_high,feature[4][0],feature[4][2],feature[4][3],feature[4][4])}else{connector=false}if(feature[5][1]>=tile_low&&feature[5][0]<=tile_high&&feature[5][2]){this.draw_read(ctx,mode,w_scale,y_start,tile_low,tile_high,feature[5][0],feature[5][2],feature[5][3],feature[5][4])}else{connector=false}var b1_end=Math.ceil(Math.min(width,Math.max(-0.5*w_scale,(feature[4][1]-tile_low-0.5)*w_scale))),b2_start=Math.floor(Math.max(-0.5*w_scale,(feature[5][0]-tile_low-0.5)*w_scale));if(connector&&b2_start>b1_end){ctx.fillStyle=CONNECTOR_COLOR;dashedLine(ctx,b1_end,y_start+5,b2_start,y_start+5)}}else{this.draw_read(ctx,mode,w_scale,y_start,tile_low,tile_high,feature_start,feature[4],feature[5],feature[6])}if(mode==="Pack"&&feature_start>=tile_low&&feature_name!=="."){ctx.fillStyle=this.prefs.label_color;if(tile_low===0&&f_start-ctx.measureText(feature_name).width<0){ctx.textAlign="left";ctx.fillText(feature_name,f_end+LABEL_SPACING,y_start+9,this.max_label_length)}else{ctx.textAlign="right";ctx.fillText(feature_name,f_start-LABEL_SPACING,y_start+9,this.max_label_length)}}return[0,0]}});var ArcLinkedFeaturePainter=function(data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler){LinkedFeaturePainter.call(this,data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler);this.longest_feature_length=this.calculate_longest_feature_length();this.draw_background_connector=false;this.draw_individual_connectors=true};_.extend(ArcLinkedFeaturePainter.prototype,FeaturePainter.prototype,LinkedFeaturePainter.prototype,{calculate_longest_feature_length:function(){var longest_feature_length=0;for(var i=0,len=this.data.length;i<len;i++){var feature=this.data[i],feature_start=feature[1],feature_end=feature[2];longest_feature_length=Math.max(longest_feature_length,feature_end-feature_start)}return longest_feature_length},get_top_padding:function(width){var view_range=this.view_end-this.view_start,w_scale=width/view_range;return Math.min(128,Math.ceil((this.longest_feature_length/2)*w_scale))},draw_connector:function(ctx,block1_start,block1_end,block2_start,block2_end,y_start){var x_center=(block1_end+block2_start)/2,radius=block2_start-x_center;var angle1=Math.PI,angle2=0;if(radius>0){ctx.beginPath();ctx.arc(x_center,y_start,block2_start-x_center,Math.PI,0);ctx.stroke()}}});var Color=function(rgb,a){if(Array.isArray(rgb)){this.rgb=rgb}else{if(rgb.length==6){this.rgb=rgb.match(/.{2}/g).map(function(c){return parseInt(c,16)})}else{if(rgb.length==7){this.rgb=rgb.substring(1,7).match(/.{2}/g).map(function(c){return parseInt(c,16)})}else{this.rgb=rgb.split("").map(function(c){return parseInt(c+c,16)})}}}this.alpha=typeof(a)==="number"?a:1};Color.prototype={eval:function(){return this},toCSS:function(){if(this.alpha<1){return"rgba("+this.rgb.map(function(c){return Math.round(c)}).concat(this.alpha).join(", ")+")"}else{return"#"+this.rgb.map(function(i){i=Math.round(i);i=(i>255?255:(i<0?0:i)).toString(16);return i.length===1?"0"+i:i}).join("")}},toHSL:function(){var r=this.rgb[0]/255,g=this.rgb[1]/255,b=this.rgb[2]/255,a=this.alpha;var max=Math.max(r,g,b),min=Math.min(r,g,b);var h,s,l=(max+min)/2,d=max-min;if(max===min){h=s=0}else{s=l>0.5?d/(2-max-min):d/(max+min);switch(max){case r:h=(g-b)/d+(g<b?6:0);break;case g:h=(b-r)/d+2;break;case b:h=(r-g)/d+4;break}h/=6}return{h:h*360,s:s,l:l,a:a}},toARGB:function(){var argb=[Math.round(this.alpha*255)].concat(this.rgb);return"#"+argb.map(function(i){i=Math.round(i);i=(i>255?255:(i<0?0:i)).toString(16);return i.length===1?"0"+i:i}).join("")},mix:function(color2,weight){color1=this;var p=weight;var w=p*2-1;var a=color1.toHSL().a-color2.toHSL().a;var w1=(((w*a==-1)?w:(w+a)/(1+w*a))+1)/2;var w2=1-w1;var rgb=[color1.rgb[0]*w1+color2.rgb[0]*w2,color1.rgb[1]*w1+color2.rgb[1]*w2,color1.rgb[2]*w1+color2.rgb[2]*w2];var alpha=color1.alpha*p+color2.alpha*(1-p);return new Color(rgb,alpha)}};var LinearRamp=function(start_color,end_color,start_value,end_value){this.start_color=new Color(start_color);this.end_color=new Color(end_color);this.start_value=start_value;this.end_value=end_value;this.value_range=end_value-start_value};LinearRamp.prototype.map_value=function(value){value=Math.max(value,this.start_value);value=Math.min(value,this.end_value);value=(value-this.start_value)/this.value_range;return this.start_color.mix(this.end_color,1-value).toCSS()};var SplitRamp=function(start_color,middle_color,end_color,start_value,end_value){this.positive_ramp=new LinearRamp(middle_color,end_color,0,end_value);this.negative_ramp=new LinearRamp(middle_color,start_color,0,-start_value);this.start_value=start_value;this.end_value=end_value};SplitRamp.prototype.map_value=function(value){value=Math.max(value,this.start_value);value=Math.min(value,this.end_value);if(value>=0){return this.positive_ramp.map_value(value)}else{return this.negative_ramp.map_value(-value)}};var DiagonalHeatmapPainter=function(data,view_start,view_end,prefs,mode){Painter.call(this,data,view_start,view_end,prefs,mode);var i,len;if(this.prefs.min_value===undefined){var min_value=Infinity;for(i=0,len=this.data.length;i<len;i++){min_value=Math.min(min_value,this.data[i][5])}this.prefs.min_value=min_value}if(this.prefs.max_value===undefined){var max_value=-Infinity;for(i=0,len=this.data.length;i<len;i++){max_value=Math.max(max_value,this.data[i][5])}this.prefs.max_value=max_value}};DiagonalHeatmapPainter.prototype.default_prefs={min_value:undefined,max_value:undefined,mode:"Heatmap",pos_color:"#FF8C00",neg_color:"#4169E1"};DiagonalHeatmapPainter.prototype.draw=function(ctx,width,height,w_scale){var min_value=this.prefs.min_value,max_value=this.prefs.max_value,value_range=max_value-min_value,height_px=height,view_start=this.view_start,mode=this.mode,data=this.data,invsqrt2=1/Math.sqrt(2);var ramp=(new SplitRamp(this.prefs.neg_color,"#FFFFFF",this.prefs.pos_color,min_value,max_value));var d,s1,e1,s2,e2,value;var scale=function(p){return(p-view_start)*w_scale};ctx.save();ctx.rotate(-45*Math.PI/180);ctx.scale(invsqrt2,invsqrt2);for(var i=0,len=data.length;i<len;i++){d=data[i];s1=scale(d[1]);e1=scale(d[2]);s2=scale(d[4]);e2=scale(d[5]);value=d[6];ctx.fillStyle=(ramp.map_value(value));ctx.fillRect(s1,s2,(e1-s1),(e2-s2))}ctx.restore()};var ReadPainterUtils=function(ctx,row_height,px_per_base,mode){this.ctx=ctx;this.row_height=row_height;this.px_per_base=px_per_base;this.draw_details=(mode==="Pack"||mode==="Auto")&&(px_per_base>=ctx.canvas.manager.char_width_px);this.delete_details_thickness=0.2};_.extend(ReadPainterUtils.prototype,{draw_deletion:function(x,y,len){this.ctx.fillStyle="black";var thickness=(this.draw_details?this.delete_details_thickness:1)*this.row_height;y+=0.5*(this.row_height-thickness);this.ctx.fillRect(x,y,len*this.px_per_base,thickness)}});var VariantPainter=function(data,view_start,view_end,prefs,mode,base_color_fn){Painter.call(this,data,view_start,view_end,prefs,mode);this.base_color_fn=base_color_fn;this.divider_height=1};_.extend(VariantPainter.prototype,Painter.prototype,{get_row_height:function(){var mode=this.mode,height;if(mode==="Dense"){height=DENSE_TRACK_HEIGHT}else{if(mode==="Squish"){height=SQUISH_TRACK_HEIGHT}else{height=PACK_TRACK_HEIGHT}}return height},get_required_height:function(num_samples){var height=this.prefs.summary_height;if(num_samples>1&&this.prefs.show_sample_data){height+=this.divider_height+num_samples*this.get_row_height()}return height},draw:function(ctx,width,height,w_scale){ctx.save();var get_deletion_info=function(ref,alt){var ref_len=ref.length,alt_len=alt.length,start=0,len=1,is_delete=false;if(alt==="-"){is_delete=true;len=ref.length}else{if(ref.indexOf(alt)===0&&ref_len>alt_len){is_delete=true;len=ref_len=alt_len;start+=alt_len}}return(is_delete?{start:start,len:len}:null)};var locus_data,pos,id,ref,alt,qual,filter,sample_gts,allele_counts,variant,draw_x_start,char_x_start,draw_y_start,genotype,base_px=Math.max(1,Math.floor(w_scale)),num_samples=(this.data.length?this.data[0][7].split(",").length:0),row_height=(this.mode==="Squish"?SQUISH_TRACK_HEIGHT:PACK_TRACK_HEIGHT),feature_height=(w_scale<0.1?row_height:(this.mode==="Squish"?SQUISH_FEATURE_HEIGHT:PACK_FEATURE_HEIGHT)),draw_summary=true,paint_utils=new ReadPainterUtils(ctx,row_height,w_scale,this.mode),j;if(num_samples===1){row_height=feature_height=(w_scale<ctx.canvas.manager.char_width_px?this.prefs.summary_height:row_height);paint_utils.row_height=row_height;draw_summary=false}if(this.prefs.show_sample_data&&draw_summary){ctx.fillStyle="#F3F3F3";ctx.globalAlpha=1;ctx.fillRect(0,this.prefs.summary_height-this.divider_height,width,this.divider_height)}ctx.textAlign="center";for(var i=0;i<this.data.length;i++){locus_data=this.data[i];pos=locus_data[1];ref=locus_data[3];alt=[locus_data[4].split(",")];sample_gts=locus_data[7].split(",");allele_counts=locus_data.slice(8);alt=_.map(_.flatten(alt),function(a){var type,alt_info={},delete_info=get_deletion_info(ref,a);if(delete_info){type="deletion";_.extend(alt_info,delete_info)}else{type="snp"}return _.extend(alt_info,{type:type,value:a,})});if(pos<this.view_start||pos>this.view_end){continue}draw_x_start=Math.floor(Math.max(-0.5*w_scale,(pos-this.view_start-0.5)*w_scale));char_x_start=Math.floor(Math.max(0,(pos-this.view_start)*w_scale));if(draw_summary){ctx.fillStyle="#999999";ctx.globalAlpha=1;ctx.fillRect(draw_x_start,0,base_px,this.prefs.summary_height);draw_y_start=this.prefs.summary_height;for(j=0;j<alt.length;j++){ctx.fillStyle=(alt[j].type==="deletion"?"black":this.base_color_fn(alt[j].value));allele_frac=allele_counts/sample_gts.length;draw_height=Math.ceil(this.prefs.summary_height*allele_frac);ctx.fillRect(draw_x_start,draw_y_start-draw_height,base_px,draw_height);draw_y_start-=draw_height}}if(!this.prefs.show_sample_data){continue}draw_y_start=(draw_summary?this.prefs.summary_height+this.divider_height:0);for(j=0;j<sample_gts.length;j++,draw_y_start+=row_height){genotype=(sample_gts[j]?sample_gts[j].split(/\/|\|/):["0","0"]);variant=null;if(genotype[0]===genotype[1]){if(genotype[0]==="."){}else{if(genotype[0]!=="0"){variant=alt[parseInt(genotype[0],10)-1];ctx.globalAlpha=1}}}else{variant=(genotype[0]!=="0"?genotype[0]:genotype[1]);variant=alt[parseInt(variant,10)-1];ctx.globalAlpha=0.5}if(variant){if(variant.type==="snp"){var snp=variant.value;ctx.fillStyle=this.base_color_fn(snp);if(paint_utils.draw_details){ctx.fillText(snp,char_x_start,draw_y_start+row_height)}else{ctx.fillRect(draw_x_start,draw_y_start+1,base_px,feature_height)}}else{if(variant.type==="deletion"){paint_utils.draw_deletion(draw_x_start+base_px*variant.start,draw_y_start+1,variant.len)}else{}}}}}ctx.restore()}});return{Scaler:Scaler,LinePainter:LinePainter,LinkedFeaturePainter:LinkedFeaturePainter,ReadPainter:ReadPainter,ArcLinkedFeaturePainter:ArcLinkedFeaturePainter,DiagonalHeatmapPainter:DiagonalHeatmapPainter,VariantPainter:VariantPainter}});
\ No newline at end of file
diff -r 2438770e2cfbf804acc0d5c7b2f3d6e491f30695 -r 7ac5a36c0ce7a6eb280d339de2107740552825ce static/scripts/viz/trackster/painters.js
--- a/static/scripts/viz/trackster/painters.js
+++ b/static/scripts/viz/trackster/painters.js
@@ -196,7 +196,7 @@
ctx.fillStyle = ctx.strokeStyle = painter_color;
top_overflow = bot_overflow = false;
- x_scaled = Math.round((data[i][0] - view_start) * w_scale);
+ x_scaled = Math.ceil((data[i][0] - view_start) * w_scale);
y = data[i][1];
// Process Y (scaler) value.
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
2 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/2438770e2cfb/
Changeset: 2438770e2cfb
Branch: next-stable
User: jmchilton
Date: 2014-08-04 16:15:57
Summary: Python 2.6 compat fix for 591f036.
Affected #: 1 file
diff -r 4aa37815f1fba179ac45c0a67eaffc319905cf0e -r 2438770e2cfbf804acc0d5c7b2f3d6e491f30695 lib/galaxy/util/topsort.py
--- a/lib/galaxy/util/topsort.py
+++ b/lib/galaxy/util/topsort.py
@@ -36,7 +36,7 @@
many methods to help analyze and break the cycles. This requires
a good deal more code than topsort itself!
"""
-from collections import OrderedDict
+from galaxy.util.odict import odict as OrderedDict
from exceptions import Exception
https://bitbucket.org/galaxy/galaxy-central/commits/cd82587fb36e/
Changeset: cd82587fb36e
User: jmchilton
Date: 2014-08-04 16:16:13
Summary: Merge next-stable.
Affected #: 1 file
diff -r 120b7b9c1c73e5577f874674e9773b17784c0d52 -r cd82587fb36ecbc802931edad29372f69cee7108 lib/galaxy/util/topsort.py
--- a/lib/galaxy/util/topsort.py
+++ b/lib/galaxy/util/topsort.py
@@ -36,7 +36,7 @@
many methods to help analyze and break the cycles. This requires
a good deal more code than topsort itself!
"""
-from collections import OrderedDict
+from galaxy.util.odict import odict as OrderedDict
from exceptions import Exception
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: jmchilton: Cleanup test case in e7ba2469bca0cb7a1d5a8d754885537dc683d490.
by commits-noreply@bitbucket.org 04 Aug '14
by commits-noreply@bitbucket.org 04 Aug '14
04 Aug '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/120b7b9c1c73/
Changeset: 120b7b9c1c73
User: jmchilton
Date: 2014-08-04 15:38:05
Summary: Cleanup test case in e7ba2469bca0cb7a1d5a8d754885537dc683d490.
Affected #: 1 file
diff -r cde36ab1fe9934579d1fc03c7538853b0f533708 -r 120b7b9c1c73e5577f874674e9773b17784c0d52 test/api/test_workflows.py
--- a/test/api/test_workflows.py
+++ b/test/api/test_workflows.py
@@ -109,11 +109,12 @@
# Run this index stability test with following command:
# ./run_tests.sh test/api/test_workflows.py:WorkflowsApiTestCase.test_workflow_stability
from pkg_resources import resource_string
+ num_tests = 1
for workflow_file in [ "test_workflow_topoambigouity.ga", "test_workflow_topoambigouity_auto_laidout.ga" ]:
workflow_str = resource_string( __name__, workflow_file )
workflow = self.workflow_populator.load_workflow( "test1", content=workflow_str )
last_step_map = self._step_map( workflow )
- for i in range(10):
+ for i in range(num_tests):
uploaded_workflow_id = self.workflow_populator.create_workflow( workflow )
download_response = self._get( "workflows/%s/download" % uploaded_workflow_id )
downloaded_workflow = download_response.json()
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0