Finally remerged changeset. Should be good now.

This commit is contained in:
Ian Schenck
2009-01-21 16:48:54 -05:00
parent 427bc02028
commit 82d09f5824
19 changed files with 1042 additions and 5 deletions
+3
View File
@@ -5,8 +5,10 @@
<datatype extension="axt" type="galaxy.datatypes.sequence:Axt" display_in_upload="true"/>
<datatype extension="bed" type="galaxy.datatypes.interval:Bed" display_in_upload="true">
<converter file="bed_to_gff_converter.xml" target_datatype="gff"/>
<converter file="interval_to_coverage.xml" target_datatype="coverage"/>
</datatype>
<datatype extension="binseq.zip" type="galaxy.datatypes.images:Binseq" mimetype="application/zip" display_in_upload="true"/>
<datatype extension="coverage" type="galaxy.datatypes.coverage:LastzCoverage" display_in_upload="true"/>
<datatype extension="customtrack" type="galaxy.datatypes.interval:CustomTrack"/>
<datatype extension="csfasta" type="galaxy.datatypes.sequence:csFasta" display_in_upload="true"/>
<datatype extension="data" type="galaxy.datatypes.data:Data" mimetype="application/octet-stream"/>
@@ -17,6 +19,7 @@
<converter file="fastqsolexa_to_fasta_converter.xml" target_datatype="fasta"/>
<converter file="fastqsolexa_to_qual_converter.xml" target_datatype="qual"/>
</datatype>
<datatype extension="genetrack" type="galaxy.datatypes.tracks:GeneTrack"/>
<datatype extension="gff" type="galaxy.datatypes.interval:Gff" display_in_upload="true">
<converter file="gff_to_bed_converter.xml" target_datatype="bed"/>
</datatype>
@@ -0,0 +1,80 @@
#!/usr/bin/env python
"""
Converter to generate 3 (or 4) column base-pair coverage from an interval file.
usage: %prog bed_file out_file
-1, --cols1=N,N,N,N: Columns for chrom, start, end, strand in interval file
-2, --cols2=N,N,N,N: Columns for chrom, start, end, strand in coverage file
"""
import sys
from galaxy import eggs
import pkg_resources; pkg_resources.require( "bx-python" )
from bx.intervals import io
from bx.cookbook import doc_optparse
INTERVAL_METADATA = ('chromCol',
'startCol',
'endCol',
'strandCol',)
COVERAGE_METADATA = ('chromCol',
'positionCol',
'forwardCol',
'reverseCol',)
def main( interval, coverage ):
chroms = dict()
for record in interval:
if not type( record ) is io.GenomicInterval: continue
chrom = chroms[record.chrom] = chroms.get(record.chrom, dict())
for position in xrange(record.start, record.end):
coverages = chrom[position] = chrom.get(position,[0,0])
if record.strand == "-": coverages[1] += 1
else: coverages[0] += 1
for chrom in sorted(chroms.iterkeys()):
positions = chroms[chrom]
for position in sorted(positions.iterkeys()):
coverage.write( chrom=chrom, position=position, forward=positions[position][0], reverse=positions[position][1] )
class CoverageWriter( object ):
def __init__( self, out_stream=None, chromCol=0, positionCol=1, forwardCol=2, reverseCol=3 ):
self.chromCol, self.positionCol, self.forwardCol, self.reverseCol = chromCol, positionCol, forwardCol, reverseCol
self.nfields = max( chromCol, positionCol, forwardCol, reverseCol )+1
self.out_stream = out_stream
self.nlines = 0
def write(self, chrom="chr", position=0, forward=0, reverse=0 ):
self.nlines += 1
if self.nlines % 64000: self.out_stream.flush()
outlist = [None] * self.nfields
outlist[self.chromCol] = str(chrom)
outlist[self.positionCol] = str(position)
if self.reverseCol == -1: outlist[self.forwardCol] = str(forward + reverse)
else:
outlist[self.forwardCol] = str(forward)
outlist[self.reverseCol] = str(reverse)
self.out_stream.write("%s\n" % "\t".join( outlist ))
def flush(self):
self.out_stream.flush()
if __name__ == "__main__":
options, args = doc_optparse.parse( __doc__ )
try:
chr_col_1, start_col_1, end_col_1, strand_col_1 = [int(x)-1 for x in options.cols1.split(',')]
chr_col_2, position_col_2, forward_col_2, reverse_col_2 = [int(x)-1 for x in options.cols2.split(',')]
in_fname, out_fname = args
except:
doc_optparse.exception()
coverage = CoverageWriter( out_stream = open(out_fname, "a"),
chromCol = chr_col_2, positionCol = position_col_2,
forwardCol = forward_col_2, reverseCol = reverse_col_2, )
interval = io.NiceReaderWrapper( open(in_fname, "r"),
chrom_col=chr_col_1,
start_col=start_col_1,
end_col=end_col_1,
strand_col=strand_col_1,
fix_strand=True )
main( interval, coverage )
coverage.flush()
@@ -0,0 +1,18 @@
<tool id="CONVERTER_interval_to_coverage_0" name="Convert Genomic Intervals To COVERAGE">
<!-- <description>__NOT_USED_CURRENTLY_FOR_CONVERTERS__</description> -->
<!-- Used on the metadata edit page. -->
<command interpreter="python">interval_to_coverage.py $input1 $output1
-1 ${input1.metadata.chromCol},${input1.metadata.startCol},${input1.metadata.endCol},${input1.metadata.strandCol}
-2 ${output1.metadata.chromCol},${output1.metadata.positionCol},${output1.metadata.forwardCol},${output1.metadata.reverseCol}
</command>
<inputs>
<page>
<param format="interval" name="input1" type="data" label="Choose intervals"/>
</page>
</inputs>
<outputs>
<data format="coverage" name="output1"/>
</outputs>
<help>
</help>
</tool>
+30
View File
@@ -0,0 +1,30 @@
"""
Coverage datatypes
"""
import pkg_resources
pkg_resources.require( "bx-python" )
import logging, os, sys, time, sets, tempfile, shutil
import data
from galaxy import util
from galaxy.datatypes.sniff import *
from galaxy.web import url_for
from cgi import escape
import urllib
from bx.intervals.io import *
from galaxy.datatypes import metadata
from galaxy.datatypes.metadata import MetadataElement
from galaxy.datatypes.tabular import Tabular
log = logging.getLogger(__name__)
class LastzCoverage( Tabular ):
file_ext = "coverage"
MetadataElement( name="chromCol", default=1, desc="Chrom column", param=metadata.ColumnParameter )
MetadataElement( name="positionCol", default=2, desc="Position column", param=metadata.ColumnParameter )
MetadataElement( name="forwardCol", default=3, desc="Forward or aggregate read column", param=metadata.ColumnParameter )
MetadataElement( name="reverseCol", desc="Optional reverse read column", param=metadata.ColumnParameter, optional=True, no_value=0 )
MetadataElement( name="columns", default=3, desc="Number of columns", readonly=True, visible=False )
+4 -2
View File
@@ -3,7 +3,7 @@ Provides mapping between extensions and datatypes, mime-types, etc.
"""
import os
import logging
import data, tabular, interval, images, sequence, qualityscore, genetics, xml
import data, tabular, interval, images, sequence, qualityscore, genetics, xml, coverage, tracks
import galaxy.util
from galaxy.util.odict import odict
@@ -94,12 +94,14 @@ class Registry( object ):
'bed' : interval.Bed(),
'binseq.zip' : images.Binseq(),
'blastxml' : xml.BlastXml(),
'coverage' : coverage.LastzCoverage(),
'customtrack' : interval.CustomTrack(),
'csfasta' : sequence.csFasta(),
'fasta' : sequence.Fasta(),
'fastqsolexa' : sequence.FastqSolexa(),
'gff' : interval.Gff(),
'gff3' : interval.Gff3(),
'gff3' : interval.Gff3(),
'genetrack' : tracks.GeneTrack(),
'interval' : interval.Interval(),
'laj' : images.Laj(),
'lav' : sequence.Lav(),
+30
View File
@@ -0,0 +1,30 @@
"""
Datatype classes for tracks/track views within galaxy.
"""
import data
import logging
import re
from cgi import escape
from galaxy.datatypes.metadata import MetadataElement
from galaxy.datatypes import metadata
import galaxy.model
from galaxy import util
from galaxy.web import url_for
from sniff import *
log = logging.getLogger(__name__)
class GeneTrack( data.Binary ):
file_ext = "genetrack"
MetadataElement( name="hdf", default="data.hdf", desc="HDF DB", readonly=True, visible=True, no_value=0 )
MetadataElement( name="sqlite", default="features.sqlite", desc="SQLite Features DB", readonly=True, visible=True, no_value=0 )
MetadataElement( name="label", default="Custom", desc="Track Label", readonly=True, visible=True, no_value="Custom" )
def __init__(self, **kwargs):
super(GeneTrack, self).__init__(**kwargs)
self.add_display_app( 'genetrack', 'View in ', '', 'genetrack_link' )
def genetrack_link( self, dataset, type, app, base_url ):
return [('GeneTrack', url_for(controller='genetrack', action='index', dataset_id=dataset.id ))]
+4 -1
View File
@@ -28,4 +28,7 @@ class BaseController( object ):
Root = BaseController
"""
Deprecated: `BaseController` used to be available under the name `Root`
"""
"""
class ControllerUnavailable( Exception ):
pass
+6 -1
View File
@@ -28,13 +28,18 @@ def add_controllers( webapp, app ):
them to the webapp.
"""
from galaxy.web.base.controller import BaseController
from galaxy.web.base.controller import ControllerUnavailable
import galaxy.web.controllers
controller_dir = galaxy.web.controllers.__path__[0]
for fname in os.listdir( controller_dir ):
if not( fname.startswith( "_" ) ) and fname.endswith( ".py" ):
name = fname[:-3]
module_name = "galaxy.web.controllers." + name
module = __import__( module_name )
try:
module = __import__( module_name )
except ControllerUnavailable, exc:
log.debug("%s could not be loaded: %s" % (module_name, str(exc)))
continue
for comp in module_name.split( "." )[1:]:
module = getattr( module, comp )
# Look for a controller inside the modules
+283
View File
@@ -0,0 +1,283 @@
import time, glob, os
from itertools import cycle
from mako import exceptions
from mako.template import Template
from mako.lookup import TemplateLookup
from galaxy.web.base.controller import *
try:
import pkg_resources
pkg_resources.require("GeneTrack")
import atlas
from atlas import sql
from atlas import hdf
from atlas import util as atlas_utils
from atlas.web import formlib, feature_query, feature_filter
from atlas.web import label_cache as atlas_label_cache
from atlas.plotting.const import *
from atlas.plotting.tracks import prefab
from atlas.plotting.tracks import chart
from atlas.plotting import tracks
except Exception, exc:
raise ControllerUnavailable("GeneTrack could not import a required dependency: %s" % str(exc))
pkg_resources.require( "Paste" )
import paste.httpexceptions
# Database helpers
SHOW_LABEL_LIMIT = 10000
color = cycle( [LIGHT, WHITE] )
def list_labels(session):
"""
Returns a list of labels that will be plotted in order.
"""
labels = sql.Label
query = session.query(labels).order_by("-id")
return query
def open_databases( conf ):
"""
A helper function that returns handles to the hdf and sql databases
"""
db = hdf.hdf_open( conf.HDF_DATABASE, mode='r' )
session = sql.get_session( conf.SQL_URI )
return db, session
def hdf_query(db, name, param, autosize=False ):
"""
Schema specific hdf query.
Note that returns data as columns not rows.
"""
if not hdf.has_node(db=db, name=name):
atlas.warn( 'missing label %s' % name )
return [], [], [], []
data = hdf.GroupData( db=db, name=name)
istart, iend = data.get_indices(label=param.chrom, start=param.start, stop=param.end)
table = data.get_table(label=param.chrom)
if autosize:
# attempts to reduce the number of points
size = len( table.cols.ix[istart:iend] )
step = max( [1, size/1200] )
else:
step = 1
ix = table.cols.ix[istart:iend:step].tolist()
wx = table.cols.wx[istart:iend:step].tolist()
cx = table.cols.cx[istart:iend:step].tolist()
ax = table.cols.ax[istart:iend:step].tolist()
return ix, wx, cx, ax
# Chart helpers
def build_tracks( param, conf, data_label, fit_label, pred_label, strand, show=False ):
"""
Builds tracks
"""
# gets all the labels for a fast lookup
label_cache = atlas_label_cache( conf )
# get database handles for hdf and sql
db, session = open_databases( conf )
# fetching x and y coordinates for bar and fit (line) for
# each strand plus (p), minus (m), all (a)
bix, bpy, bmy, bay = hdf_query( db=db, name=data_label, param=param )
fix, fpy, fmy, fay = hdf_query( db=db, name=fit_label, param=param )
# close the hdf database
db.close()
# get all features within the range
all = feature_query( session=session, param=param )
# draws the barchart and the nucleosome chart below it
if strand == 'composite':
bar = prefab.composite_bartrack( fix=fix, fay=fay, bix=bix, bay=bay, param=param)
else:
bar = prefab.twostrand_bartrack( fix=fix, fmy=fmy, fpy=fpy, bix=bix, bmy=bmy, bpy=bpy, param=param)
charts = list()
charts.append( bar )
return charts
def feature_chart(param=None, session=None, label=None, label_dict={}):
# draw the ORF tracks
all = feature_filter(feature_query(session=session, param=param), name=label, kdict=label_dict)
if len(all) == 0: return []
opts = track_options(
xscale=param.xscale, w=param.width, fgColor=PURPLE,
show_labels=param.show_labels, ylabel=str(label),
bgColor=color.next()
)
return [
tracks.split_tracks(features=all, options=opts, split=param.show_labels, track_type='vector')
]
def consolidate_charts( charts, param ):
# create the multiplot
opt = chart_options( w=param.width )
multi = chart.MultiChart(options=opt, charts=charts)
return multi
# SETUP Track Builders
import functools
def twostrand_tracks( param=None, conf=None ):
return build_tracks( data_label=conf.LABEL, fit_label=conf.FIT_LABEL, pred_label=conf.PRED_LABEL, param=param, conf=conf, strand='twostrand')
def composite_tracks( param=None, conf=None ):
return build_tracks( data_label=conf.LABEL, fit_label=conf.FIT_LABEL, pred_label=conf.PRED_LABEL, param=param, conf=conf, strand='composite')
class BaseConf( object ):
"""
Fake web_conf for atlas.
"""
IMAGE_DIR = "static/genetrack/plots/"
LEVELS = [str(x) for x in [ 50, 100, 250, 500, 1000, 2500, 5000, 10000, 20000, 50000, 100000, 200000 ]]
ZOOM_LEVELS = zip(LEVELS, LEVELS)
PLOT_SETUP = [
('comp-id', 'Composite' , 'genetrack/index.html', composite_tracks ),
('two-id' , 'Two Strand', 'genetrack/index.html', twostrand_tracks ),
]
PLOT_CHOICES = [ (id, name) for (id, name, page, func) in PLOT_SETUP ]
PLOT_MAPPER = dict( [ (id, (page, func)) for (id, name, page, func) in PLOT_SETUP ] )
def __init__(self, **kwds):
for key,value in kwds.items():
setattr( self, key, value)
class WebRoot(BaseController):
@web.expose
def search(self, trans, word='', dataset_id=None, submit=''):
"""
Default search page
"""
data = trans.app.model.HistoryDatasetAssociation.get( dataset_id )
if not data:
raise paste.httpexceptions.HTTPRequestRangeNotSatisfiable( "Invalid reference dataset id: %s." % str( dataset_id ) )
# the main configuration file
conf = BaseConf(
TITLE = "<i>%s</i>: %s" % (data.metadata.dbkey, data.metadata.label),
HDF_DATABASE = os.path.join( data.extra_files_path, data.metadata.hdf ),
SQL_URI = "sqlite:///%s" % os.path.join( data.extra_files_path, data.metadata.sqlite ),
LABEL = data.metadata.label,
FIT_LABEL = "%s-SIGMA-%d" % (data.metadata.label, 20),
PRED_LABEL = "PRED-%s-SIGMA-%d" % (data.metadata.label, 20),
)
from atlas import hdf
db = hdf.hdf_open( conf.HDF_DATABASE, mode='r' )
conf.CHROM_FIELDS = [(x,x) for x in hdf.GroupData(db=db, name=conf.LABEL).labels]
db.close()
param = atlas.Param( word=word )
# search with features based on param.feature
# search for a given
session = sql.get_session( conf.SQL_URI )
if param.word:
def search_query( word, text ):
query = session.query(sql.Feature).filter( "name LIKE :word or freetext LIKE :text" ).params(word=word, text=text)
query = list(query[:20])
return query
# a little heuristics to match most likely target
targets = [
(param.word+'%', 'No match'), # match beginning
('%'+param.word+'%', 'No match'), # match name anywhere
('%'+param.word+'%', '%'+param.word+'%'), # match json anywhere
]
for word, text in targets:
query = search_query( word=word, text=text)
if query:
break
else:
query = []
return trans.fill_template_mako('genetrack/search.html', param=param, query=query, dataset_id=dataset_id)
@web.expose
def index(self, trans, dataset_id=None, **kwds):
"""
Main request handler
"""
color = cycle( [LIGHT, WHITE] )
data = trans.app.model.HistoryDatasetAssociation.get( dataset_id )
if not data:
raise paste.httpexceptions.HTTPRequestRangeNotSatisfiable( "Invalid reference dataset id: %s." % str( dataset_id ) )
# the main configuration file
conf = BaseConf(
TITLE = "<i>%s</i>: %s" % (data.metadata.dbkey, data.metadata.label),
HDF_DATABASE = os.path.join( data.extra_files_path, data.metadata.hdf ),
SQL_URI = "sqlite:///%s" % os.path.join( data.extra_files_path, data.metadata.sqlite ),
LABEL = data.metadata.label,
FIT_LABEL = "%s-SIGMA-%d" % (data.metadata.label, 20),
PRED_LABEL = "PRED-%s-SIGMA-%d" % (data.metadata.label, 20),
)
session = sql.get_session( conf.SQL_URI )
if os.path.exists( conf.HDF_DATABASE ):
db = hdf.hdf_open( conf.HDF_DATABASE, mode='r' )
conf.CHROM_FIELDS = [(x,x) for x in hdf.GroupData(db=db, name=conf.LABEL).labels]
db.close()
else:
query = session.execute(sql.select([sql.feature_table.c.chrom]).distinct())
conf.CHROM_FIELDS = [(x.chrom,x.chrom) for x in query]
# generate a new form based on the configuration
form = formlib.main_form( conf )
# clear the tempdir every once in a while
atlas_utils.clear_tempdir( dir=conf.IMAGE_DIR, days=1, chance=10)
incoming = form.defaults()
incoming.update( kwds )
# manage the zoom and pan requests
incoming = formlib.zoom_change( kdict=incoming, levels=conf.LEVELS)
incoming = formlib.pan_view( kdict=incoming )
# process the form
param = atlas.Param( **incoming )
form.process( incoming )
if kwds and form.isSuccessful():
# adds the sucessfull parameters
param.update( form.values() )
# if it was a search word not a number go to search page
try:
center = int( param.feature )
except ValueError:
# go and search for these
return trans.response.send_redirect( web.url_for( controller='genetrack', action='search', word=param.feature, dataset_id=dataset_id ) )
# keep image at a sane size
param.width = min( [2000, int(param.img_size)] )
# get the template and the function used to generate the tracks
tmpl_name, track_maker = conf.PLOT_MAPPER[param.plot]
charts = []
fname, fpath = atlas_utils.make_tempfile( dir=conf.IMAGE_DIR, suffix='.png')
param.fname = fname
# set the scale of the plot
param.xscale = [ param.start, param.end ]
# when visualizing on wide scales labels are not useful
param.show_labels = ( param.end - param.start ) <= SHOW_LABEL_LIMIT
if track_maker is not None and os.path.exists( conf.HDF_DATABASE ):
# generate the fit track
charts = track_maker( param=param, conf=conf )
for label in list_labels( session ):
charts.extend( feature_chart(param=param, session=session, label=label.name, label_dict={label.name:label.id}) )
track_chart = consolidate_charts( charts, param )
track_chart.save(fname=fpath)
return trans.fill_template_mako(tmpl_name, conf=conf, form=form, param=param, dataset_id=dataset_id)
+78
View File
@@ -0,0 +1,78 @@
body {
font-family: "Trebuchet MS", Arial, tahoma, sans-serif;
font-size: 14px;
line-height: 1.6em;
margin: 0;
padding: 0;
border-top: 9px solid #CCD9FF;
}
/* Error message style */
.error{
background: #FFFF66;
}
/* Error message style */
.message{
background: #33FF66;
}
/* Odd data row in the table */
.selected {
background-color: #FFFFCC;
}
.nav_button{
background-color:#EEEEEE;
border:1px solid;
color: #000000;
}
.nav_button:hover{
background-color:#000000;
border:1px solid;
color: #FFFFFF;
}
.grey {
background-color: #EFEFEF;
}
.odd {
background-color: #ECECEC;
}
.even {
background-color: #FFFFFF;
}
/* Text table style */
.data_table {
border: 1px solid #CCCCCC;
background-color: white;
}
/* Footer is added to every page */
#footer {
background: #EFEFEF;
text-align:center;
padding:.2em;
border-top: 1px solid #CCD9FF;
border-bottom: 1px solid #CCD9FF;
clear: both;
}
#footer p {
font-size:.94em; line-height:2em; color:#cccccc; margin: 0;
}
#tag {
font-size:.80em; margin: 4px; padding: 2px;
}
#footer img {
vertical-align: middle; margin-left: 3px; padding-bottom: 2px;
}
+79
View File
@@ -0,0 +1,79 @@
var cookie_name = "genetrack_ui"
var now = new Date();
now.setTime(now.getTime() + 365 * 24 * 60 * 60 * 1000);
// this toggles between none and block
function toggle(name){
var elem = get(name)
if (elem) {
if (elem.style.display=="none"){
elem.style.display="block"
setCookie(cookie_name, name, now)
} else {
elem.style.display="none"
setCookie(cookie_name, '', now)
}
}
}
function main(){
//executed upon main body load
var value = getCookie(cookie_name);
toggle( value )
}
// this toggles between visible and hidden
function show(name){
var elem = get(name)
if (elem.style.visibility=="hidden"){
elem.style.visibility="visible";
} else {
elem.style.visibility="hidden";
}
}
// utility function to get the length of on object
function len(obj){
return obj.length;
}
// utility function to get an element by id
function get(name){
return document.getElementById(name);
}
// pops up a window
function pop_up(url) {
day = new Date();
id = day.getTime();
eval("page" + id + " = window.open(url, '" + id + "', 'toolbar=0,scrollbars=1,location=0,statusbar=1,menubar=0,resizable=1,width=500,height=300');");
}
//
// cookie management off the web
// http://www.webreference.com/js/column8/property.html
//
function setCookie(name, value, expires, path, domain, secure) {
var curCookie = name + "=" + escape(value) +
((expires) ? "; expires=" + expires.toGMTString() : "") +
((path) ? "; path=" + path : "") +
((domain) ? "; domain=" + domain : "") +
((secure) ? "; secure" : "");
document.cookie = curCookie;
}
function getCookie(name) {
var dc = document.cookie;
var prefix = name + "=";
var begin = dc.indexOf("; " + prefix);
if (begin == -1) {
begin = dc.indexOf(prefix);
if (begin != 0) return null;
} else
begin += 2;
var end = document.cookie.indexOf(";", begin);
if (end == -1)
end = dc.length;
return unescape(dc.substring(begin + prefix.length, end));
}
+29
View File
@@ -0,0 +1,29 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>${self.title()}</title>
<link rel="stylesheet" href="${h.url_for('/static/genetrack/genetrack.css')}" type="text/css" media="screen">
<script type="text/javascript" src="${h.url_for('/static/genetrack/genetrack.js')}">var dummy1=0;</script>
</head>
<%def name="title()">
Title
</%def>
<%def name="footer()">
<div align="center" id="footer">
<a href="/">Home</a>&nbsp;&nbsp;|&nbsp;&nbsp;<a href="${h.url_for(controller='genetrack',action='search',dataset_id=dataset_id)}">Search</a>
</div>
<div align="center" id="tag">
Powered by <a href="http://genetrack.googlecode.com">GeneTrack</a> |
<a href="http://atlas.bx.psu.edu/">Penn State Genome Cartography (2008)</a>
</div>
</%def>
<body>
${self.body()}
${self.footer()}
</body>
</html>
+75
View File
@@ -0,0 +1,75 @@
## index.html
<%inherit file="base.html"/>
<%def name="title()">
Index
</%def>
<h1 align="center">${conf.TITLE}</h1>
<form action="" method="get">
<table align="center" cellpadding="2" cellspacing="1" width="100%">
% if form.errors():
<tr class="error"><td align="center">
% for ekey, evalue in form.errors().items():
<b>ERROR:</b> &nbsp;&nbsp; ${ekey}: &nbsp;&nbsp; ${evalue}<br>
% endfor
</td></tr>
% endif
<tr class="grey">
<td colspan="4" align="center">
<a href="javascript:toggle('options')">More</a><img src="/static/images/thumbtack_icon.png" align="absmiddle" border="0">
Chromosome: ${form.chrom.tag()}&nbsp;&nbsp;
Feature: ${form.feature.tag()}&nbsp;&nbsp;
Width: ${form.zoom.tag()}&nbsp;&nbsp;
Plot: ${form.plot.tag()}&nbsp;&nbsp;
<input type="submit" name="submit" value="Display!">
<div id="options" style="display:none" class="selected">
<table cellpadding="3">
<tr>
<td>
<!-- Nucleosome:${form.nuc_track.tag()} &nbsp;&nbsp;
ORF:${form.orf_track.tag()} &nbsp;&nbsp;
-->
Fit threshold: ${form.min_fit.tag()} &nbsp;&nbsp;
Image width: ${form.img_size.tag()} &nbsp;&nbsp;
</td>
</tr>
</table>
</div>
</td>
</tr>
<tr>
<td align="center">
<input type="submit" name="move_left" value="<< Move Left">
&nbsp;&nbsp;&nbsp;
<input type="submit" name="zoom_out" value="Shrink -">
&nbsp;&nbsp;&nbsp;
<input type="submit" name="zoom_in" value="Magnify +">
&nbsp;&nbsp;&nbsp;
<input type="submit" name="move_right" value="Move Right >>">
</td>
</tr>
<tr>
<td align="center">
<img src="${h.url_for('/static/genetrack/plots/' + param.fname)}" align="center" border="0">
</td>
</tr>
<tr>
<td align="center">
<!-- <a href='/search'>Search</a> -->
</td>
</tr>
</table>
<input type="hidden" id="dataset_id" name="dataset_id" value="${dataset_id}" />
</form>
+55
View File
@@ -0,0 +1,55 @@
## search.html
<%!
from itertools import cycle
colors = cycle( [ 'even', 'odd' ] )
%>
<%inherit file="base.html"/>
<%def name="title()">
Search
</%def>
<h1 align="center">Search</h1>
<div align="center">
<form action="search" method="get">
Search terms <input type="text" name="word" value="${param.word}">
<input type="hidden" name="dataset_id" id="dataset_id" value="${dataset_id}" />
<input type="submit" name="submit" value="Search!">
</form>
</div>
% if param.word:
% if len(query)>0:
<h4 align="center">Showing the best ${len(query)} matches</h4>
<table align="center" class="data_table" cellpadding="6" cellspacing="0">
<tr align="center">
<th width="25%">Name</td>
<th width="25%">Chromosome</td>
<th width="25%">Start:End</td>
<th width="25%">Type</td>
</tr>
% for color, row in zip(colors, query):
${makerow(color, row)}
% endfor
</table>
% else:
<h4 align="center">No results found</h4>
% endif
%endif
<br>
<%def name="makerow(color, row)">
<tr class="${color}" align="center">
<td><a href="${h.url_for(controller='genetrack', action='index', chrom=row.chrom, feature=row.start, dataset_id=dataset_id)}">${row.name}</a></td>
<td>${row.chrom}</td>
<td>${row.start}:${row.end}</td>
<td>${row.label.name}</td>
</tr>
</%def>
</form>
+3
View File
@@ -303,4 +303,7 @@
<tool file="metag_tools/blat_wrapper.xml" />
<tool file="metag_tools/mapping_to_ucsc.xml" />
</section>
<section name="Tracks" id="tracks">
<tool file="visualization/genetrack.xml" />
</section>
</toolbox>
+1 -1
View File
@@ -82,7 +82,7 @@
<when input="out_format" value="maf" format="maf" />
</change_format>
</data>
<data format="tabular" name="output2" />
<data format="coverage" name="output2" />
</outputs>
<requirements>
<requirement type="binary">lastz</requirement>
+189
View File
@@ -0,0 +1,189 @@
#!/usr/bin/env python
"""
Run GeneTrack(atlas) with a faked conf file to generate GeneTrack data files.
usage: %prog
-l, --label=N: Data label for fit curve/peak plot
-1, --fits=N/N/N/N/N,...: Data files (interval format) for fit curve/peak plot
-2, --feats=N:M/N/N/N/N/N,...: Data files (interval format) for features.
-d, --data=N: Output path for hdf5 and sqlite databases.
-o, --output=N: Output path for export file.
"""
from galaxy import eggs
import pkg_resources
pkg_resources.require("GeneTrack")
pkg_resources.require("bx-python")
import commands as oscommands
from atlas import commands
from atlas import sql
from bx.cookbook import doc_optparse
from bx.intervals import io
import os
import tempfile
from functools import partial
SIGMA = 20
WIDTH = 5 * SIGMA
EXCLUSION_ZONE = 147
def main(label, fit, feats, data_dir, output):
os.mkdir(data_dir)
conf = DummyConf(
__name__=label,
CLOBBER = True,
DATA_SIZE = 3*10**6,
MINIMUM_PEAK_SIZE = 0.1,
LOADER_ENABLED = False,
FITTER_ENABLED = False,
PREDICTOR_ENABLED = False,
EXPORTER_ENABLED = False,
LOADER = loader,
FITTER = fitter,
PREDICTOR = predictor,
EXPORTER = partial( commands.exporter, formatter=commands.bed_formatter),
HDF_DATABASE = os.path.join( data_dir, "data.hdf" ),
SQL_URI = "sqlite:///%s" % os.path.join( data_dir, "features.sqlite" ),
SIGMA = SIGMA,
WIDTH = WIDTH,
DATA_LABEL = label,
FIT_LABEL = "%s-SIGMA-%d" % ( label,SIGMA ),
PEAK_LABEL = "PRED-%s-SIGMA-%d" % ( label,SIGMA ),
EXCLUSION_ZONE = EXCLUSION_ZONE,
LEFT_SHIFT = EXCLUSION_ZONE / 2,
RIGHT_SHIFT = EXCLUSION_ZONE / 2,
EXPORT_LABELS = [ "PRED-%s-SIGMA-%d" % ( label,SIGMA ) ],
EXPORT_DIR = os.path.join( data_dir ),
DATA_FILE=fit and fit[1] or None,
fit=fit,
feats=feats,
)
if fit:
# Turn on fit processing.
conf.LOADER_ENABLED = True,
conf.FITTER_ENABLED = True,
conf.PREDICTOR_ENABLED = True,
conf.EXPORTER_ENABLED = True,
for feat in feats:
load_feature_files(conf, feats)
commands.execute(conf)
outname = "%s.%s.txt" % (conf.__name__, conf.EXPORT_LABELS[0] )
if os.path.exists( os.path.join(data_dir, outname) ):
os.rename( os.path.join(data_dir, outname), output)
# mod454 seems to be a module without a package. The necessary funcitons are
# stubbed out here until I'm sure of their final home. INS
def loader( conf ):
from atlas import hdf
from mod454.schema import Mod454Schema as Schema
last_chrom = table = None
db = hdf.hdf_open( conf.HDF_DATABASE, mode='a', title='HDF database')
gp = hdf.create_group( db=db, name=conf.DATA_LABEL, desc='data group', clobber=conf.CLOBBER )
fit_meta = conf.fit[2]
# iterate over the file and insert into table
for line in open( conf.fit[1], "r" ):
if line.startswith("chrom"): continue #Skip possible header
if line.startswith("#"): continue
fields = line.rstrip('\r\n').split('\t')
chrom = fields[fit_meta.chromCol]
if chrom != last_chrom:
if table: table.flush()
table = hdf.create_table( db=db, name=chrom, where=gp, schema=Schema, clobber=False )
last_chrom = chrom
try:
position = int(fields[fit_meta.positionCol])
forward = float(fields[fit_meta.forwardCol])
reverse = fit_meta.reverseCol > -1 and float(fields[fit_meta.reverseCol]) or 0.0
row = ( position, forward, reverse, forward+reverse, )
table.append( [ row ] )
except ValueError:
# Ignore bad lines
pass
table.flush()
db.close()
def fitter( conf ):
from mod454.fitter import fitter as mod454_fitter
return mod454_fitter( conf )
def predictor( conf ):
from mod454.predictor import predictor as mod454_predictor
return mod454_predictor( conf )
def load_feature_files( conf, feats):
"""
Loads features from file names
"""
engine = sql.get_engine( conf.SQL_URI )
sql.drop_indices(engine)
conn = engine.connect()
for label, fname, col_spec in feats:
label_id = sql.make_label(engine, name=label, clobber=False)
reader = io.NiceReaderWrapper( open(fname,"r"),
chrom_col=col_spec.chromCol,
start_col=col_spec.startCol,
end_col=col_spec.endCol,
strand_col=col_spec.strandCol,
fix_strand=False )
values = list()
for interval in reader:
print interval
if not type( interval ) is io.GenomicInterval: continue
row = {'label_id':label_id,
'name':col_spec.nameCol == -1 and "%s-%s" % (str(interval.start), str(interval.end)) or interval.fields[col_spec.nameCol],
'altname':"",
'chrom':interval.chrom,
'start':interval.start,
'end':interval.end,
'strand':interval.strand,
'value':0,
'freetext':""}
values.append(row)
insert = sql.feature_table.insert()
conn.execute( insert, values)
conn.close()
sql.create_indices(engine)
class Bunch( object ):
def __init__(self, **kwargs):
for key,value in kwargs.items():
setattr( self, key, value )
class DummyConf( Bunch ):
"""
Fake conf module for genetrack/atlas.
"""
pass
if __name__ == "__main__":
options, args = doc_optparse.parse( __doc__ )
try:
label = options.label
if options.fits:
fit_name, fit_meta = options.fits.split(':')[0], [int(x)-1 for x in options.fits.split(':')[1:]]
fit_meta = Bunch(chromCol=fit_meta[0], positionCol=fit_meta[1], forwardCol=fit_meta[2], reverseCol=fit_meta[3])
fit = ( label, fit_name, fit_meta, )
else:
fit = []
# split apart the string into nested lists, preserves order
if options.feats:
feats = [ (
feat_label,
fname,
Bunch(chromCol=int(chromCol)-1, startCol=int(startCol)-1, endCol=int(endCol)-1,
strandCol=int(strandCol)-1, nameCol=int(nameCol)-1),
)
for feat_label, fname, chromCol, startCol, endCol, strandCol, nameCol
in ( feat.split(':') for feat in options.feats.split(',') if len(feat) > 0 )]
else:
feats = []
data_dir = options.data
output = options.output
except:
doc_optparse.exception()
main(label, fit, feats, data_dir, output)
+62
View File
@@ -0,0 +1,62 @@
<tool id="genetrack1" name="GeneTrack">
<description>Track creator/viewer</description>
<code file="genetrack_code.py">
<hook exec_after_process="exec_after_process" />
</code>
<command interpreter="python">
genetrack.py -l $data_label
#if not str($fit_data) == "None"
-1
${fit_data}:${fit_data.metadata.chromCol}:${fit_data.metadata.positionCol}:${fit_data.metadata.forwardCol}:${fit_data.metadata.reverseCol}
#end if
#if $feature_data
-2
#end if
#for $data in $feature_data
${data.name}:${data.input}:${data.input.metadata.chromCol}:${data.input.metadata.startCol}:${data.input.metadata.endCol}:${data.input.metadata.strandCol}:${data.input.metadata.nameCol},
#end for
-d ${genetrack.files_path}
-o ${bed_out}
</command>
<inputs>
<param name="data_label" type="text" label="Track Label" size="50">
<validator type="regex" message="Please name the track with only alphanumeric characters.">[a-zA-Z0-9]{0,25}</validator>
</param>
<param name="fit_data" type="data" format="coverage" label="Coverage Dataset" optional="true" />
<repeat name="feature_data" title="Features">
<param name="input" type="data" format="interval" label="Dataset" />
<param name="name" type="text" label="Feature Type (mRNA, ESTs, ORFs, etc.)" size="25">
<validator type="regex" message="Please name the feature with only alphanumeric characters.">[a-zA-Z0-9]{0,25}</validator>
</param>
</repeat>
</inputs>
<outputs>
<data format="genetrack" name="genetrack" />
<data format="bed" name="bed_out" />
</outputs>
<requirements>
<requirement type="python-module">tables</requirement>
<requirement type="python-module">atlas</requirement>
<requirement type="python-module">pychartdir</requirement>
<requirement type="python-module">numpy</requirement>
</requirements>
<help>
This tool takes the input Fit Data and creates a peak and curve plot showing
the reads and fitness on each basepair. Features can be plotted below as tracks.
-----
**Syntax**
- **Track Label** is the name of the generated track.
- **Fit Data** are the datasets to calculate coverage/reads across basepairs and generate a curve.
- **Features** are additional datasets (interval format) to be plotted below as tracks.
</help>
</tool>
+13
View File
@@ -0,0 +1,13 @@
import sets, os
from galaxy import eggs
from galaxy import jobs
from galaxy.tools.parameters import DataToolParameter
def exec_after_process(app, inp_data, out_data, param_dict, tool=None, stdout=None, stderr=None):
"""
Copy data_label to genetrack.metadata.label
"""
out_data['genetrack'].metadata.label = param_dict['data_label']
out_data['genetrack'].info = "Use the link below to view the custom track."
out_data['bed_out'].info = ""