changeset 11:9340099a8605 draft

Deleted selected files
author mzeidler
date Sun, 22 Sep 2013 19:13:07 -0400
parents 4d9f6da1e04f
children 70a2ed3fe672
files jalview/JGoogleAnalytics_0.3.jar jalview/Jmol-12.2.4.jar jalview/VARNAv3-9-dev.jar jalview/activation.jar jalview/apache-mime4j-0.6.jar jalview/axis.jar jalview/castor-1.1-cycle-xml.jar jalview/commons-codec-1.3.jar jalview/commons-discovery.jar jalview/commons-logging-1.1.1.jar jalview/datatypes_conf.xml jalview/fasta_to_bwa_index_converter.xml jalview/fasta_to_star_index_converter.xml jalview/groovy-all-1.8.2.jar jalview/httpclient-4.0.3.jar jalview/httpcore-4.0.1.jar jalview/httpmime-4.0.3.jar jalview/jalview.jar jalview/jalview/JGoogleAnalytics_0.3.jar jalview/jalview/Jmol-12.2.4.jar jalview/jalview/VARNAv3-9-dev.jar jalview/jalview/activation.jar jalview/jalview/apache-mime4j-0.6.jar jalview/jalview/axis.jar jalview/jalview/castor-1.1-cycle-xml.jar jalview/jalview/commons-codec-1.3.jar jalview/jalview/commons-discovery.jar jalview/jalview/commons-logging-1.1.1.jar jalview/jalview/groovy-all-1.8.2.jar jalview/jalview/httpclient-4.0.3.jar jalview/jalview/httpcore-4.0.1.jar jalview/jalview/httpmime-4.0.3.jar jalview/jalview/jalview.jar jalview/jalview/jaxrpc.jar jalview/jalview/jdas-1.0.4.jar jalview/jalview/jhall.jar jalview/jalview/jswingreader-0.3.jar jalview/jalview/log4j-1.2.8.jar jalview/jalview/mail.jar jalview/jalview/miglayout-4.0-swing.jar jalview/jalview/min-jaba-client-2.0.jar jalview/jalview/regex.jar jalview/jalview/saaj.jar jalview/jalview/spring-core-3.0.5.RELEASE.jar jalview/jalview/spring-web-3.0.5.RELEASE.jar jalview/jalview/vamsas-client.jar jalview/jalview/wsdl4j.jar jalview/jalview/xercesImpl.jar jalview/jalview/xml-apis.jar jalview/jaxrpc.jar jalview/jdas-1.0.4.jar jalview/jhall.jar jalview/jqBarGraph.1.1.min.js jalview/jqBarGraph.2.1.js jalview/jqBarGraph.2.1.min.js jalview/jquery-1.10.2.min.js jalview/jswingreader-0.3.jar jalview/log4j-1.2.8.jar jalview/mail.jar jalview/miglayout-4.0-swing.jar jalview/min-jaba-client-2.0.jar jalview/regex.jar jalview/saaj.jar jalview/spring-core-3.0.5.RELEASE.jar jalview/spring-web-3.0.5.RELEASE.jar jalview/tool_dependencies.xml jalview/vamsas-client.jar jalview/vhom.py jalview/vhom_region.xml jalview/vhom_regionplot.py jalview/vhom_regions.py jalview/vmap.py jalview/vmap_dnaindex.py jalview/vmap_dnamap.xml jalview/vmap_rnaindex.py jalview/vmap_rnamap.xml jalview/vref.py jalview/vref_blast.xml jalview/vref_fasta.xml jalview/wsdl4j.jar jalview/xercesImpl.jar jalview/xml-apis.jar
diffstat 82 files changed, 4951 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
Binary file jalview/JGoogleAnalytics_0.3.jar has changed
Binary file jalview/Jmol-12.2.4.jar has changed
Binary file jalview/VARNAv3-9-dev.jar has changed
Binary file jalview/activation.jar has changed
Binary file jalview/apache-mime4j-0.6.jar has changed
Binary file jalview/axis.jar has changed
Binary file jalview/castor-1.1-cycle-xml.jar has changed
Binary file jalview/commons-codec-1.3.jar has changed
Binary file jalview/commons-discovery.jar has changed
Binary file jalview/commons-logging-1.1.1.jar has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jalview/datatypes_conf.xml	Sun Sep 22 19:13:07 2013 -0400
@@ -0,0 +1,19 @@
+<?xml version="1.0"?>
+      <datatypes>
+          <registration>
+              <datatype extension="hit" type="galaxy.datatypes.sequence:Fasta" display_in_upload="true" subclass="True"/>
+              <datatype extension="hit_bz2" type="galaxy.datatypes.binary:Binary" display_in_upload="true" subclass="True"/>
+      
+              <datatype extension="qual" type="galaxy.datatypes.tabular:Tabular" display_in_upload="true" subclass="True"/>
+              <datatype extension="tax" type="galaxy.datatypes.tabular:Tabular" display_in_upload="true" subclass="True"/>
+              <datatype extension="bwa_index" type="galaxy.datatypes.images:Html" mimetype="text/html" display_in_upload="False" subclass="True"/>
+              <datatype extension="star_index" type="galaxy.datatypes.images:Html" mimetype="text/html" display_in_upload="False" subclass="True"/>
+              <datatype extension="fasta" type="galaxy.datatypes.sequence:Fasta" display_in_upload="true">
+                <converter file="fasta_to_bwa_index_converter.xml" target_datatype="bwa_index"/>
+                <converter file="fasta_to_star_index_converter.xml" target_datatype="star_index"/>
+              </datatype>
+              <datatype extension="reg_stats" type="galaxy.datatypes.tabular:Tabular" display_in_upload="true" subclass="True"/>
+              <datatype extension="hom_reg" type="galaxy.datatypes.images:Html" mimetype="text/html" display_in_upload="False" subclass="True"/>
+             
+          </registration>
+     </datatypes>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jalview/fasta_to_bwa_index_converter.xml	Sun Sep 22 19:13:07 2013 -0400
@@ -0,0 +1,18 @@
+<tool id="CONVERTER_fasta_to_bwa_index" name="Convert FASTA to BWA Index" version="1.0.0">
+
+    <requirements>
+        <requirement type="package" version="0.7.4">bwa</requirement>
+        <requirement type="package" version="0.1.19">samtools</requirement>
+        <requirement type="package" version="1.0">vmap_python</requirement>
+    </requirements>
+    <command interpreter="python">vmap_dnaindex.py --html_file $output --index_dir ${output.files_path} --dir ${output.files_path}  --reference_file $input 2&gt;&amp;1 </command>
+    
+    <inputs>
+        <param name="input" format="fasta" type="data" label="Fasta file"/>
+    </inputs>
+    
+    <outputs>
+        <data name="output" format="bwa_index"/>
+    </outputs>
+
+</tool>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jalview/fasta_to_star_index_converter.xml	Sun Sep 22 19:13:07 2013 -0400
@@ -0,0 +1,18 @@
+<tool id="CONVERTER_fasta_to_STAR_index" name="Convert FASTA to STAR Index" version="1.0.0">
+
+    <requirements>
+        <requirement type="package" version="2.3.0">STAR</requirement>
+        <requirement type="package" version="0.1.19">samtools</requirement>
+        <requirement type="package" version="1.0">vmap_python</requirement>
+    </requirements>
+    <command interpreter="python">vmap_rnaindex.py --html_file $output --dir ${output.files_path} --index_dir ${output.files_path} --reference_file $input 2&gt;&amp;1 </command>
+    
+    <inputs>
+        <param name="input" format="fasta" type="data" label="Fasta file"/>
+    </inputs>
+    
+    <outputs>
+        <data name="output" format="star_index"/>
+    </outputs>
+
+</tool>
\ No newline at end of file
Binary file jalview/groovy-all-1.8.2.jar has changed
Binary file jalview/httpclient-4.0.3.jar has changed
Binary file jalview/httpcore-4.0.1.jar has changed
Binary file jalview/httpmime-4.0.3.jar has changed
Binary file jalview/jalview.jar has changed
Binary file jalview/jalview/JGoogleAnalytics_0.3.jar has changed
Binary file jalview/jalview/Jmol-12.2.4.jar has changed
Binary file jalview/jalview/VARNAv3-9-dev.jar has changed
Binary file jalview/jalview/activation.jar has changed
Binary file jalview/jalview/apache-mime4j-0.6.jar has changed
Binary file jalview/jalview/axis.jar has changed
Binary file jalview/jalview/castor-1.1-cycle-xml.jar has changed
Binary file jalview/jalview/commons-codec-1.3.jar has changed
Binary file jalview/jalview/commons-discovery.jar has changed
Binary file jalview/jalview/commons-logging-1.1.1.jar has changed
Binary file jalview/jalview/groovy-all-1.8.2.jar has changed
Binary file jalview/jalview/httpclient-4.0.3.jar has changed
Binary file jalview/jalview/httpcore-4.0.1.jar has changed
Binary file jalview/jalview/httpmime-4.0.3.jar has changed
Binary file jalview/jalview/jalview.jar has changed
Binary file jalview/jalview/jaxrpc.jar has changed
Binary file jalview/jalview/jdas-1.0.4.jar has changed
Binary file jalview/jalview/jhall.jar has changed
Binary file jalview/jalview/jswingreader-0.3.jar has changed
Binary file jalview/jalview/log4j-1.2.8.jar has changed
Binary file jalview/jalview/mail.jar has changed
Binary file jalview/jalview/miglayout-4.0-swing.jar has changed
Binary file jalview/jalview/min-jaba-client-2.0.jar has changed
Binary file jalview/jalview/regex.jar has changed
Binary file jalview/jalview/saaj.jar has changed
Binary file jalview/jalview/spring-core-3.0.5.RELEASE.jar has changed
Binary file jalview/jalview/spring-web-3.0.5.RELEASE.jar has changed
Binary file jalview/jalview/vamsas-client.jar has changed
Binary file jalview/jalview/wsdl4j.jar has changed
Binary file jalview/jalview/xercesImpl.jar has changed
Binary file jalview/jalview/xml-apis.jar has changed
Binary file jalview/jaxrpc.jar has changed
Binary file jalview/jdas-1.0.4.jar has changed
Binary file jalview/jhall.jar has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jalview/jqBarGraph.1.1.min.js	Sun Sep 22 19:13:07 2013 -0400
@@ -0,0 +1,34 @@
+/**
+ * jqBarGraph - jQuery plugin
+ * @version: 1.1 (2011/04/03)
+ * @requires jQuery v1.2.2 or later 
+ * @author Ivan Lazarevic
+ * Examples and documentation at: http://www.workshop.rs/jqbargraph/
+ * 
+ * Dual licensed under the MIT and GPL licenses:
+ *   http://www.opensource.org/licenses/mit-license.php
+ *   http://www.gnu.org/licenses/gpl.html
+ * 
+ */
+
+(function($){var opts=new Array;var level=new Array;$.fn.jqBarGraph=$.fn.jqbargraph=function(options){init=function(el){opts[el.id]=$.extend({},$.fn.jqBarGraph.defaults,options);$(el).css({'width':opts[el.id].width,'height':opts[el.id].height,'position':'relative','text-align':'center'});doGraph(el);};sum=function(ar){total=0;for(val in ar){total+=ar[val];}
+return total.toFixed(2);};max=function(ar){maxvalue=0;for(var val in ar){value=ar[val][0];if(value instanceof Array)value=sum(value);if(parseFloat(value)>parseFloat(maxvalue))maxvalue=value;}
+return maxvalue;};maxMulti=function(ar){maxvalue=0;maxvalue2=0;for(var val in ar){ar2=ar[val][0];for(var val2 in ar2){if(ar2[val2]>maxvalue2)maxvalue2=ar2[val2];}
+if(maxvalue2>maxvalue)maxvalue=maxvalue2;}
+return maxvalue;};doGraph=function(el){arr=opts[el.id];data=arr.data;if(data==undefined){$(el).html('There is not enought data for graph');return;}
+if(arr.sort=='asc')data.sort(sortNumberAsc);if(arr.sort=='desc')data.sort(sortNumberDesc);legend='';prefix=arr.prefix;postfix=arr.postfix;space=arr.barSpace;legendWidth=arr.legend?arr.legendWidth:0;fieldWidth=($(el).width()-legendWidth)/data.length;totalHeight=$(el).height();var leg=new Array();max=max(data);colPosition=0;for(var val in data){valueData=data[val][0];if(valueData instanceof Array)
+value=sum(valueData);else
+value=valueData;lbl=data[val][1];color=data[val][2];unique=val+el.id;if(color==undefined&&arr.colors==false)
+color=arr.color;if(arr.colors&&!color){colorsCounter=arr.colors.length;if(colorsCounter==colPosition)colPosition=0;color=arr.colors[colPosition];colPosition++;}
+if(arr.type=='multi')color='none';if(lbl==undefined)lbl=arr.lbl;out="<div class='graphField"+el.id+"' id='graphField"+unique+"' style='position: absolute'>";out+="<div class='graphValue"+el.id+"' id='graphValue"+unique+"'>"+prefix+value+postfix+"</div>";out+="<div class='graphBar"+el.id+"' id='graphFieldBar"+unique+"' style='background-color:"+color+";position: relative; overflow: hidden;'></div>";if(!arr.legend||arr.legends)
+out+="<div class='graphLabel"+el.id+"' id='graphLabel"+unique+"'>"+lbl+"</div>";out+="</div>";$(el).append(out);totalHeightBar=totalHeight-$('.graphLabel'+el.id).height()-$('.graphValue'+el.id).height();fieldHeight=(totalHeightBar*value)/max;$('#graphField'+unique).css({'left':(fieldWidth)*val,'width':fieldWidth-space,'margin-left':space});if(valueData instanceof Array){if(arr.type=="multi"){maxe=maxMulti(data);totalHeightBar=fieldHeight=totalHeight-$('.graphLabel'+el.id).height();$('.graphValue'+el.id).remove();}else{maxe=max;}
+for(i in valueData){heig=totalHeightBar*valueData[i]/maxe;wid=parseInt((fieldWidth-space)/valueData.length);sv='';fs=0;if(arr.showValues){sv=arr.prefix+valueData[i]+arr.postfix;fs=12;}
+o="<div class='subBars"+el.id+"' style='height:"+heig+"px; background-color: "+arr.colors[i]+"; left:"+wid*i+"px; color:"+arr.showValuesColor+"; font-size:"+fs+"px' >"+sv+"</div>";$('#graphFieldBar'+unique).prepend(o);}}
+if(arr.type=='multi')
+$('.subBars'+el.id).css({'width':wid,'position':'absolute','bottom':0});if(arr.position=='bottom')$('.graphField'+el.id).css('bottom',0);if(!arr.legends)
+leg.push([color,lbl,el.id,unique]);if(arr.animate){$('#graphFieldBar'+unique).css({'height':0});$('#graphFieldBar'+unique).animate({'height':fieldHeight},arr.speed*1000);}else{$('#graphFieldBar'+unique).css({'height':fieldHeight});}}
+for(var l in arr.legends){leg.push([arr.colors[l],arr.legends[l],el.id,l]);}
+createLegend(leg);if(arr.legend){$(el).append("<div id='legendHolder"+unique+"'></div>");$('#legendHolder'+unique).css({'width':legendWidth,'float':'right','text-align':'left'});$('#legendHolder'+unique).append(legend);$('.legendBar'+el.id).css({'float':'left','margin':3,'height':12,'width':20,'font-size':0});}
+if(arr.title){$(el).wrap("<div id='graphHolder"+unique+"'></div>");$('#graphHolder'+unique).prepend(arr.title).css({'width':arr.width+'px','text-align':'center'});}};createLegend=function(legendArr){legend='';for(var val in legendArr){legend+="<div id='legend"+legendArr[val][3]+"' style='overflow: hidden; zoom: 1;'>";legend+="<div class='legendBar"+legendArr[val][2]+"' id='legendColor"+legendArr[val][3]+"' style='background-color:"+legendArr[val][0]+"'></div>";legend+="<div class='legendLabel"+legendArr[val][2]+"' id='graphLabel"+unique+"'>"+legendArr[val][1]+"</div>";legend+="</div>";}};this.each(function()
+{init(this);})};$.fn.jqBarGraph.defaults={barSpace:10,width:400,height:300,color:'#000000',colors:false,lbl:'',sort:false,position:'bottom',prefix:'',postfix:'',animate:true,speed:1.5,legendWidth:100,legend:false,legends:false,type:false,showValues:true,showValuesColor:'#fff',title:false};function sortNumberAsc(a,b){if(a[0]<b[0])return-1;if(a[0]>b[0])return 1;return 0;}
+function sortNumberDesc(a,b){if(a[0]>b[0])return-1;if(a[0]<b[0])return 1;return 0;}})(jQuery);
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jalview/jqBarGraph.2.1.js	Sun Sep 22 19:13:07 2013 -0400
@@ -0,0 +1,566 @@
+/**
+ * jqBarGraph - jQuery plugin
+ * @version: 1.1 (2011/04/03)
+ * @requires jQuery v1.2.2 or later 
+ * @author Ivan Lazarevic
+ * Examples and documentation at: http://www.workshop.rs/jqbargraph/
+ * 
+ * Dual licensed under the MIT and GPL licenses:
+ *   http://www.opensource.org/licenses/mit-license.php
+ *   http://www.gnu.org/licenses/gpl.html
+ * 
+ * @param data: arrayOfData // array of data for your graph
+ * @param title: false // title of your graph, accept HTML
+ * @param barSpace: 10 // this is default space between bars in pixels
+ * @param width: 400 // default width of your graph ghhjgjhg
+ * @param height: 200 //default height of your graph
+ * @param color: '#000000' // if you don't send colors for your data this will be default bars color
+ * @param colors: false // array of colors that will be used for your bars and legends
+ * @param lbl: '' // if there is no label in your array
+ * @param sort: false // sort your data before displaying graph, you can sort as 'asc' or 'desc'
+ * @param position: 'bottom' // position of your bars, can be 'bottom' or 'top'. 'top' doesn't work for multi type
+ * @param prefix: '' // text that will be shown before every label
+ * @param postfix: '' // text that will be shown after every label
+ * @param animate: true // if you don't need animated appereance change to false
+ * @param speed: 2 // speed of animation in seconds
+ * @param legendWidth: 100 // width of your legend box
+ * @param legend: false // if you want legend change to true
+ * @param legends: false // array for legend. for simple graph type legend will be extracted from labels if you don't set this
+ * @param type: false // for multi array data default graph type is stacked, you can change to 'multi' for multi bar type
+ * @param showValues: true // you can use this for multi and stacked type and it will show values of every bar part
+ * @param showValuesColor: '#fff' // color of font for values 
+
+ * @example  $('#divForGraph').jqBarGraph({ data: arrayOfData });  
+  
+**/
+
+(function($) {
+	var opts = new Array;
+	var level = new Array;
+	
+	$.fn.jqBarGraph = $.fn.jqbargraph = function(options){
+	
+	init = function(el){
+
+		opts[el.id] = $.extend({}, $.fn.jqBarGraph.defaults, options);
+		$(el).css({ 'width': opts[el.id].width, 'height': opts[el.id].height, 'position':'relative', 'text-align':'center' });
+		
+
+		doGraph(el);
+		$("a").css({'color':'black'});
+
+	};
+	
+	// sum of array elements
+	sum = function(ar){
+		total = 0;
+		for(val in ar){
+			total += ar[val][0];
+		}
+		return total.toFixed(2);
+	};
+	
+	// count max value of array
+	max = function(ar){
+		maxvalue = 0;
+		for(var val in ar){
+			value = ar[val][0];
+			if(value instanceof Array) value = sum(value);	
+			if (parseFloat(value) > parseFloat(maxvalue)) maxvalue=value;
+		}	
+		return maxvalue;	
+	};
+
+	// max value of multi array
+	maxMulti = function(ar){
+		maxvalue = 0;
+		maxvalue2 = 0;
+		
+		for(var val in ar){
+			ar2 = ar[val][0];
+			
+			for(var val2 in ar2){
+				if(ar2[val2][0]>maxvalue2) maxvalue2 = ar2[val2][0];
+			}
+
+			if (maxvalue2>maxvalue) maxvalue=maxvalue2;
+		}	
+		return maxvalue;		
+	};
+	
+		
+	doGraph = function(el){
+		
+		arr = opts[el.id];
+		data = arr.data;
+		
+		//check if array is bad or empty
+		if(data == undefined) {
+			$(el).html('There is not enought data for graph');
+			return;
+		}
+		//sorting ascending or descending
+		if(arr.sort == 'asc') data.sort(sortNumberAsc);
+		if(arr.sort == 'desc') data.sort(sortNumberDesc);
+		if(arr.sortBar == 'asc') sortBars(data, barAsc);
+		if(arr.sortBar == 'desc')sortBars(data,barDesc);
+
+		
+		legend = '';
+		prefix = arr.prefix;
+		postfix = arr.postfix;
+		space = arr.barSpace; //space between bars
+		legendWidth = arr.legend ? arr.legendWidth : 0; //width of legend box
+		fieldWidth = ($(el).width()-legendWidth)/data.length; //width of bar
+		totalHeight =  $(el).height(); //total height of graph box
+		var leg = new Array(); //legends array
+		
+		//max value in data, I use this to calculate height of bar
+		max = max(data);
+	
+		color_map={};
+		color_map["pathogen"]=arr.colors[0];
+		color_map["ambiguous"]=arr.colors[1];
+		color_map["human"]=arr.colors[2];
+		
+		val_index=0;
+
+ 		for(var val in data){
+ 			
+ 			valueData = data[val][0];
+ 			if (valueData instanceof Array) 
+ 				value = sum(valueData);
+ 			else
+ 				value = valueData;
+ 			
+ 			lbl = data[val][1];
+			unique = val+el.id; //unique identifier
+			divid=""+el.id;
+ 			
+ 			if(arr.type == 'multi') color = 'none';
+ 				
+ 			if (lbl == undefined) lbl = arr.lbl;
+ 			
+ 			margin_top=14/(data.length);
+
+ 		
+ 			out  = "<div class='graphField"+el.id+"' id='graphField"+unique+"' style='position: absolute'>";
+ 			out += "<div class='graphValue"+el.id+"' id='graphValue"+unique+"'>"+prefix+value+postfix+"</div>";
+ 			
+ 			out += "<div class='graphBar"+el.id+"' id='graphFieldBar"+unique+"' style='background-color:#fff;position: relative; overflow: hidden;'></div>";
+            //console.log(color)
+			// if there is no legend or exist legends display lbl at the bottom
+ 			
+ 				out += "<a class='graphLabelLink' href=#files"+el.id+" onclick=fillDiv('"+el.id+"','"+valueData[0][3]+"_"+lbl+"')><div class='graphLabel"+el.id+"' id='graphLabel"+unique+"'style='margin-top:"+margin_top+"px;'>"+lbl+"</div></a>";
+ 			out += "</div>";
+ 			
+ 			
+ 			 			
+			$(el).append(out);
+			$(".graphLabel"+el.id).css({'-webkit-transform': 'rotate(30deg)', '-moz-transform': 'rotate(30deg)','-o-transform': 'rotate(30deg)', '-ms-transform': 'rotate(30deg)','transform': 'rotate(30deg)', 'height':'100'});
+ 			$('a.graphLabel').css({
+ 			    'text-decoration': 'none',
+ 			    'color':'black'    
+ 			});
+ 			
+ 			//$('#graphLabel'+el.id).rotateLeft();
+ 			
+ 			//size of bar
+ 			totalHeightBar = totalHeight - $('.graphLabel'+el.id).height() - $('.graphValue'+el.id).height()-margin_top; 
+ 			fieldHeight = (totalHeightBar*value)/max;	
+ 			$('#graphField'+unique).css({ 
+ 				'left': (fieldWidth)*val, 
+ 				'width': fieldWidth-space, 
+ 				'margin-left': space});
+ 	
+ 			// multi array
+ 			if(valueData instanceof Array){
+ 				
+				if(arr.type=="multi"){
+					maxe = maxMulti(data);
+					totalHeightBar = fieldHeight = totalHeight - $('.graphLabel'+el.id).height()-margin_top;
+					$('.graphValue'+el.id).remove();
+				} else {
+					maxe = max;
+				}
+				
+ 				for (i in valueData){
+ 					heig = (totalHeightBar*valueData[i][val_index]/maxe);
+                    if(navigator.userAgent.match('Safari') && !navigator.userAgent.match('Chrom')){
+                        
+                        heig = heig + (arr.borderSize/1.85);
+                    } 
+                    
+ 					wid = parseInt((fieldWidth-space)/valueData.length);
+
+ 					sv = ''; // show values
+ 					fs = 0; // font size
+ 					if (arr.showValues){
+ 						sv = arr.prefix+valueData[i][0]+arr.postfix;
+ 						fs = 12; // font-size is 0 if showValues = false
+ 					}
+ 					o = "<a class='subBarLink' href=#files"+el.id+" onclick=fillDiv('"+el.id+"','"+valueData[i][3]+"_"+lbl+"','"+valueData[i][5]+"')><div class='subBars"+el.id+"' style=' box-sizing:border-box; -moz-box-sizing:border-box; -ms-box-sizing:border-box; -webkit-box-sizing:border-box; height:"+heig+"px;  border-top:"+arr.borderSize+"px solid; border-color: "+arr.showValuesColor+"; background-color: "+color_map[valueData[i][2]]+"; left:"+wid*i+"px; color:"+arr.showValuesColor+"; font-size:"+fs+"px' >"+sv+"</div></a>";
+ 					$('#graphFieldBar'+unique).prepend(o);
+ 				}
+ 			}
+ 			
+ 			if(arr.type=='multi')
+ 				$('.subBars'+el.id).css({ 'width': wid, 'position': 'absolute', 'bottom': 0 });
+ 
+ 			//position of bars
+ 			if(arr.position == 'bottom') $('.graphField'+el.id).css('bottom',0);
+            
+            
+			
+ 			
+ 			
+ 			// animated apearing
+ 			if(arr.animate){
+ 				$('#graphFieldBar'+unique).css({ 'height' : 0 });
+ 				$('#graphFieldBar'+unique).animate({'height': fieldHeight},arr.speed*1000);
+ 			} else {
+ 				$('#graphFieldBar'+unique).css({'height': fieldHeight});
+ 			}
+ 			
+ 		}
+ 			
+ 		
+ 		
+ 		createLegend(color_map,el.id); // create legend from array
+ 		createLinks(el.id);
+ 		//position of legend
+ 		
+			$(el).append("<div id='legendHolder"+unique+"'></div>");
+	 		$('#legendHolder'+unique).css({ 'width': legendWidth, 'float': 'right', 'margin-left':'100px','text-align' : 'left'});
+	 		$('#legendHolder'+unique).append(legend);
+	 		$('#legendHolder'+unique).append(links);
+	 		$('.legendBar'+el.id).css({ 'float':'left', 'margin': 3, 'margin-left':'10','height': 12, 'width': 20, 'font-size': 0});
+	 		$('.linkBar'+el.id).css({'margin-left':'10'});
+	 		
+	 		$("#sortAsc"+el.id).click(function(){
+	           if(opts[el.id].sort!='asc'){
+	               opts[el.id].sort='asc';
+	               $('#graphHolder'+el.id).html('');
+	               $('#graphHolder'+el.id).jqbargraph(opts[el.id]);
+	           }
+    
+	        });
+	        $("#sortDesc"+el.id).click(function(){
+	           if(opts[el.id].sort!='desc'){
+	               opts[el.id].sort='desc';
+	               $('#graphHolder'+el.id).html('');
+	               $('#graphHolder'+el.id).jqbargraph(opts[el.id]);
+	           }
+    
+	        });
+	        $("#sortBarAsc"+el.id).click(function(){
+	           if(opts[el.id].sortBar!='asc'){
+	               opts[el.id].sortBar='asc';
+	               $('#graphHolder'+el.id).html('');
+	               $('#graphHolder'+el.id).jqbargraph(opts[el.id]);
+	           }
+    
+	        });
+	 		$("#sortBarDesc"+el.id).click(function(){
+	           if(opts[el.id].sortBar!='desc'){
+	               opts[el.id].sortBar='desc';
+	               $('#graphHolder'+el.id).html('');
+	               $('#graphHolder'+el.id).jqbargraph(opts[el.id]);
+	           }
+    
+	        });
+ 		    
+ 		    
+
+ 		//position of title
+ 		if(arr.title){
+ 			$(el).wrap("<div id='graphHolder"+el.id+"'></div>");
+ 			$('#graphHolder'+el.id).prepend("<a href='javascript:void(0);' class=>Reads</a> <a href='javascript:void(0);'>Basepairs</a>");
+ 			$('#graphHolder'+el.id).prepend("<a href=#files"+el.id+" onclick=fillDiv('"+el.id+"')>"+arr.title+"</a>").css({ 'width' : arr.width+'px', 'text-align' : 'center' });
+ 		}
+ 		    $("#graphHolder"+el.id).append("<div class='files"+el.id+"' id='files"+el.id+"' ></div><p/>");
+ 		    $('.files'+el.id).css({'width' : arr.width+'px','background-color':'silver', 'border':'2px solid gray', 'display':'none'})
+ 		    
+ 		     $("#graphHolder"+el.id).append("<div class='image"+el.id+"' id='image"+el.id+"' ></div>");
+ 		    $('.image'+el.id).css({'width' : arr.width+'px','background-color':'silver', 'border':'2px solid gray', 'display':'none'})
+ 		
+	};
+
+
+	//creating legend from array
+	createLegend = function(color_map,id){
+		legend = '';
+		for(var val in color_map){
+	 			legend += "<div id='legend"+val+"' style='overflow: hidden; zoom: 1;'>";
+	 			legend += "<div class='legendBar"+id+"' id='legendColor"+val+"' style='background-color:"+color_map[val]+"'></div>";
+	 			legend += "<div class='legendLabel"+id+"' id='graphLabel"+unique+"'>"+val+"</div>";
+	 			legend += "</div>";			
+		}
+	};
+	
+	createLinks = function(id){
+	   links="<div class='linkBar"+id+"'>";
+	   links+="<div ><a href='javascript:void(0);' id='sortAsc"+id+"' >sort  asceding</a></div>"
+	   links+="<div ><a href='javascript:void(0);' id='sortDesc"+id+"'>sort  desceding</a></div>"
+	   links+="<div ><a href='javascript:void(0);' id='sortBarAsc"+id+"'>sort bars asceding</a></div>"
+	   links+="<div ><a href='javascript:void(0);' id='sortBarDesc"+id+"'>sort bars desceding</a></div>"
+	   links+="</div>"
+	   
+	     
+	};
+	
+	fillDiv = function (elid, dir, region) {
+	   
+	        
+	   
+	        arr=opts[elid];
+	        
+	        dict=arr.files;
+	        
+	        generateDownloadLink = function(family,region,filetype){
+	           out="no file";
+	           if(searchArray("region_"+region+"_"+filetype,dict[family][region])!=-1){
+	               out="<a href="+family+"/region_"+region+"_"+filetype+">download</a>";
+	           }
+	           return out;
+	           
+	        };
+	        generateShowLink = function(family,region){
+	           out="no image";
+
+	           if(searchArray("region_"+region+"_consensus.png",dict[family][region])!=-1){
+	               out="<a href=#image"+elid+" onclick=showImage('"+elid+"','"+region+"','"+ family +"/"+dict[family][region][3]+"')>show</a>";
+	           }
+	           return out;
+	           
+	        };
+
+	        
+	        data = arr.data
+	        for(var val in data){
+	           for(var element in data[val][0]){     
+	                   dict[data[val][0][0][3]+"_"+data[val][1]][data[val][0][element][5]].push(data[val][0][element][0],data[val][0][element][1],data[val][0][element][4]);
+	               
+	           }      
+	        }
+            var div = document.getElementById("files" + elid);
+            div.innerHTML="";
+            out = "<div><b>Files for Sample "+arr.sample+"</b></div><p/>";
+            
+            out += "<div class='" + elid + "_files' id='" + elid + "_files'><table id='"+elid+"table' class='"+elid+"table' border=1 cellpadding=3 cellspacing=0 style=' border: 1pt solid #000000; border-Collapse: collapse'>";
+            out += "<tr><th>family</th><th>region</th><th>#reads</th><th>#basepairs</th><th>region length</th><th>unaligned fasta</th><th>bam alignment</th><th>consensus fasta</th><th>consensus diagram</th></tr>"
+            if (!dir) {
+                for (var directory in dict) {
+                    //out += "<b>"+directory+"</b>";
+                    //out += "<div class='dirlist' id='" + directory + "_files'";
+                    for (var region in dict[directory]) {
+                        if(dict[directory][region][5]){
+                            out += "<tr><td>"+directory+"</td><td>"+region+"</td><td>"+dict[directory][region][5]+"</td><td>"+dict[directory][region][6]+"</td><td>"+dict[directory][region][7]+"</td><td>"+generateDownloadLink(directory,region,"unaligned.fa.bzip2")+"</td><td>"+generateDownloadLink(directory,region,"alignment.bam")+"</td><td>"+generateDownloadLink(directory,region,"consensus.fa")+"</td><td>"+generateShowLink(directory,region)+" "+generateDownloadLink(directory,region,"consensus.png")+"</td></tr>";
+                        }
+                    }
+                    out += "</div>";
+                }
+            } else {
+                out += "<b>"+ dir+"</b>" ;
+                
+                if (!region) {
+                    for (var region in dict[dir]) {
+                        if(dict[dir][region][5]){
+                            out += "<tr><td>"+dir+"</td><td>"+region+"</td><td>"+dict[dir][region][5]+"</td><td>"+dict[dir][region][6]+"</td><td>"+dict[dir][region][7]+"</td><td>"+generateDownloadLink(dir,region,"unaligned.fa.bzip2")+"</td><td>"+generateDownloadLink(dir,region,"alignment.bam")+"</td><td>"+generateDownloadLink(dir,region,"consensus.fa")+"</td><td>"+generateShowLink(dir,region)+" "+generateDownloadLink(dir,region,"consensus.png")+"</td></tr>";
+                        }
+                    }
+                } else {
+
+                    if(dict[dir][region][5]){
+                        out += "<tr><td>"+dir+"</td><td>"+region+"</td><td>"+dict[dir][region][5]+"</td><td>"+dict[dir][region][6]+"</td><td>"+dict[dir][region][7]+"</td><td>"+generateDownloadLink(dir,region,"unaligned.fa.bzip2")+"</td><td>"+generateDownloadLink(dir,region,"alignment.bam")+"</td><td>"+generateDownloadLink(dir,region,"consensus.fa")+"</td><td>"+generateShowLink(dir,region)+"     "+generateDownloadLink(dir,region,"consensus.png")+"</td></tr>";
+                    }
+                }
+            }
+            out += "</div>";
+            
+            $(div).append(out);
+            $("a").css({'color':'black'});
+            $("table").css({'border':'collapse'});
+            $(div).append("<div class='close_files"+elid+"'style='cursor:pointer;'>x</div>");
+            $(".close_files"+elid).click(function(){
+                $('.files'+elid).animate({'height':'0px'},1000,'',function(){
+                    $('.files'+elid).css({'display':'none'});
+                    $('.files'+elid).removeClass("selected");
+                });
+                
+                
+            });
+            $("div.close_files"+elid).css({'color':'white','position':'absolute','top':5,'left':5,'background-color':arr.colors[1],'border':'1px solid white','border-radius':'20px','height':'20px','width':'20px','text-align': 'center'});
+            $("a.close_files"+elid).css({'color':'white', 'text-decoration': 'none'});
+            $('.files'+elid).css({'width': 'auto','display':'none'});
+            wi=$('.files'+elid).width()+15;
+
+           
+            if(!$('.files'+elid).hasClass("selected")){
+                $('.files'+elid).css({'height': 'auto','display':'none'});
+                hei=$('.files'+elid).height();
+                hei=parseInt(hei)+10;
+                hei=hei>400? hei=400 : hei;
+                $('.files'+elid).css({'width':wi+'px','position':'relative','height':'0px', 'overflow' : 'auto','background-color':'#D0D0D0', 'border':'2px solid silver','border-radius':'10px','display':'block' });
+                $('.files'+elid).animate({'height':hei+'px'}, 1000,'',function(){
+                   
+                    $('.files'+elid).addClass("selected");
+                });
+            }
+            else{
+                
+                curr_hei=$('.files'+elid).height();
+                $('.files'+elid).css({'height': 'auto','display':'none'});
+                hei=$('.files'+elid).height();
+                hei=parseInt(hei)+10;
+                hei=hei>400? hei=400 : hei;
+                $('.files'+elid).css({'height': curr_hei+'px', 'width':'915px','position':'relative', 'overflow' : 'auto','background-color':'#D0D0D0', 'border':'2px solid silver','border-radius':'10px','display':'block' }).animate({'height':hei+'px'}, 1000);	           
+            }
+	};
+	 searchArray = function(str, strArray){
+	       for (var j=0; j<strArray.length; j++) {
+                if (strArray[j].indexOf(str)!=-1) return j;
+            }
+            return -1;
+	 };
+	 
+	 showImage = function (elid,region, consensus_image,wi) {
+            var div = document.getElementById("image" + elid);
+            div.innerHTML="";
+            this.img = new Image();
+            this.img.src = consensus_image;
+            hei=this.img.height;
+            out="<img src="+consensus_image+" alt="+consensus_image+">";
+            $(div).append(out)
+     
+     
+     
+            $(div).append("<div class='close_image"+elid+"'style='cursor:pointer;'>x</div>");
+            $(".close_image"+elid).click(function(){
+                $('.image'+elid).animate({'height':'0px'},1000,'',function(){
+                    $('.image'+elid).css({'display':'none'});
+                    $('.image'+elid).removeClass("selected");
+                });
+                
+                
+            });
+            $("div.close_image"+elid).css({'color':'white','position':'absolute','bottom':5,'left':5,'background-color':arr.colors[1],'border':'1px solid white','border-radius':'20px','height':'20px','width':'20px','text-align': 'center'});
+            $("a.close_image"+elid).css({'color':'white', 'text-decoration': 'none'});
+            
+            wi=$('.files'+elid).width();
+            
+            
+            if(!$('.image'+elid).hasClass("selected")){
+                $('.image'+elid).css({'width':wi+'px','position':'relative','height':'0px', 'overflow' : 'auto','background-color':'#D0D0D0', 'border':'2px solid silver','border-radius':'10px','display':'block' });
+                $('.image'+elid).animate({'height':hei}, 1000,'',function(){
+                   
+                    $('.image'+elid).addClass("selected");
+                });
+            }
+       
+	 };
+
+
+	this.each (
+		function()
+		{ init(this); }
+	)
+	
+};
+
+	// default values
+	$.fn.jqBarGraph.defaults = {	
+		sample: 'no_sample_id',
+		barSpace: 10,
+		width: 400,
+		height: 600,
+		color: '#000000',
+		colors: false,
+		lbl: '',
+		sort: false, // 'asc' or 'desc'
+		sortBar: false,
+		position: 'bottom', // or 'top' doesn't work for multi type
+		prefix: '',
+		postfix: '',
+		animate: true,
+		speed: 3.0,
+		legendWidth: 150,
+		legend: false,
+		type: false, // or 'multi'
+		showValues: false,
+		borderSize: 1,
+		showValuesColor: '#fff',
+		title: false
+	};
+	
+	
+	//sorting functions
+	function sortNumberAsc(a,b){
+	    sum_a=0
+	    for(var values in a){
+	       if(a[values] instanceof Array){
+	           for(var val in a[values]){
+	               sum_a+=a[values][val][0];
+	           }
+	       }
+	    }
+	    sum_b=0
+	    for(var values in b){
+	       if(b[values] instanceof Array){
+	           for(var val in b[values]){
+	               sum_b+=b[values][val][0];
+	           }
+	       }
+	    }
+	    
+		if (sum_a<sum_b) return -1;
+		if (sum_a>sum_b) return 1;
+		return 0;
+	}
+	
+	function sortNumberDesc(a,b){
+		sum_a=0
+	    for(var values in a){
+	       if(a[values] instanceof Array){
+	           for(var val in a[values]){
+	               sum_a+=a[values][val][0];
+	           }
+	       }
+	    }
+	    sum_b=0
+	    for(var values in b){
+	       if(b[values] instanceof Array){
+	           for(var val in b[values]){
+	               sum_b+=b[values][val][0];
+	           }
+	       }
+	    }
+	    
+		if (sum_a<sum_b) return 1;
+		if (sum_a>sum_b) return -1;
+		return 0;
+	}
+	
+    function sortBars(data,fun){
+        for(var values in data){
+                last = data[values].pop();
+                for(var val in data[values]){
+                    data[values][val].sort(fun);
+                }
+                data[values].push(last);       
+        }           
+    }
+    
+    function barAsc(a,b){
+        if(a[0]<b[0]) return -1;
+        if(a[0]>b[0]) return 1;
+        return 0;   
+    }
+	
+	function barDesc(a,b){
+	    if(a[0]<b[0]) return 1;
+        if(a[0]>b[0]) return -1;
+	    return 0;  
+	}
+
+})(jQuery);
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jalview/jqBarGraph.2.1.min.js	Sun Sep 22 19:13:07 2013 -0400
@@ -0,0 +1,1 @@
+(function(e){function r(e,t){sum_a=0;for(var n in e){if(e[n]instanceof Array){for(var r in e[n]){sum_a+=e[n][r][0]}}}sum_b=0;for(var n in t){if(t[n]instanceof Array){for(var r in t[n]){sum_b+=t[n][r][0]}}}if(sum_a<sum_b)return-1;if(sum_a>sum_b)return 1;return 0}function s(e,t){sum_a=0;for(var n in e){if(e[n]instanceof Array){for(var r in e[n]){sum_a+=e[n][r][0]}}}sum_b=0;for(var n in t){if(t[n]instanceof Array){for(var r in t[n]){sum_b+=t[n][r][0]}}}if(sum_a<sum_b)return 1;if(sum_a>sum_b)return-1;return 0}function u(e,t){for(var n in e){last=e[n].pop();for(var r in e[n]){e[n][r].sort(t)}e[n].push(last)}}function a(e,t){if(e[0]<t[0])return-1;if(e[0]>t[0])return 1;return 0}function f(e,t){if(e[0]<t[0])return 1;if(e[0]>t[0])return-1;return 0}var t=new Array;var n=new Array;e.fn.jqBarGraph=e.fn.jqbargraph=function(n){init=function(r){t[r.id]=e.extend({},e.fn.jqBarGraph.defaults,n);e(r).css({width:t[r.id].width,height:t[r.id].height,position:"relative","text-align":"center"});doGraph(r);e("a").css({color:"black"})};sum=function(e){total=0;for(val in e){total+=e[val][0]}return total.toFixed(2)};max=function(e){maxvalue=0;for(var t in e){value=e[t][0];if(value instanceof Array)value=sum(value);if(parseFloat(value)>parseFloat(maxvalue))maxvalue=value}return maxvalue};maxMulti=function(e){maxvalue=0;maxvalue2=0;for(var t in e){ar2=e[t][0];for(var n in ar2){if(ar2[n][0]>maxvalue2)maxvalue2=ar2[n][0]}if(maxvalue2>maxvalue)maxvalue=maxvalue2}return maxvalue};doGraph=function(n){arr=t[n.id];data=arr.data;if(data==undefined){e(n).html("There is not enought data for graph");return}if(arr.sort=="asc")data.sort(r);if(arr.sort=="desc")data.sort(s);if(arr.sortBar=="asc")u(data,a);if(arr.sortBar=="desc")u(data,f);legend="";prefix=arr.prefix;postfix=arr.postfix;space=arr.barSpace;legendWidth=arr.legend?arr.legendWidth:0;fieldWidth=(e(n).width()-legendWidth)/data.length;totalHeight=e(n).height();var l=new Array;max=max(data);color_map={};color_map["pathogen"]=arr.colors[0];color_map["ambiguous"]=arr.colors[1];color_map["human"]=arr.colors[2];val_index=0;for(var c in data){valueData=data[c][0];if(valueData instanceof Array)value=sum(valueData);else value=valueData;lbl=data[c][1];unique=c+n.id;divid=""+n.id;if(arr.type=="multi")color="none";if(lbl==undefined)lbl=arr.lbl;margin_top=14/data.length;out="<div class='graphField"+n.id+"' id='graphField"+unique+"' style='position: absolute'>";out+="<div class='graphValue"+n.id+"' id='graphValue"+unique+"'>"+prefix+value+postfix+"</div>";out+="<div class='graphBar"+n.id+"' id='graphFieldBar"+unique+"' style='background-color:#fff;position: relative; overflow: hidden;'></div>";out+="<a class='graphLabelLink' href=#files"+n.id+" onclick=fillDiv('"+n.id+"','"+valueData[0][3]+"_"+lbl+"')><div class='graphLabel"+n.id+"' id='graphLabel"+unique+"'style='margin-top:"+margin_top+"px;'>"+lbl+"</div></a>";out+="</div>";e(n).append(out);e(".graphLabel"+n.id).css({"-webkit-transform":"rotate(30deg)","-moz-transform":"rotate(30deg)","-o-transform":"rotate(30deg)","-ms-transform":"rotate(30deg)",transform:"rotate(30deg)",height:"100"});e("a.graphLabel").css({"text-decoration":"none",color:"black"});totalHeightBar=totalHeight-e(".graphLabel"+n.id).height()-e(".graphValue"+n.id).height()-margin_top;fieldHeight=totalHeightBar*value/max;e("#graphField"+unique).css({left:fieldWidth*c,width:fieldWidth-space,"margin-left":space});if(valueData instanceof Array){if(arr.type=="multi"){maxe=maxMulti(data);totalHeightBar=fieldHeight=totalHeight-e(".graphLabel"+n.id).height()-margin_top;e(".graphValue"+n.id).remove()}else{maxe=max}for(i in valueData){heig=totalHeightBar*valueData[i][val_index]/maxe;if(navigator.userAgent.match("Safari")&&!navigator.userAgent.match("Chrom")){heig=heig+arr.borderSize/1.85}wid=parseInt((fieldWidth-space)/valueData.length);sv="";fs=0;if(arr.showValues){sv=arr.prefix+valueData[i][0]+arr.postfix;fs=12}o="<a class='subBarLink' href=#files"+n.id+" onclick=fillDiv('"+n.id+"','"+valueData[i][3]+"_"+lbl+"','"+valueData[i][5]+"')><div class='subBars"+n.id+"' style=' box-sizing:border-box; -moz-box-sizing:border-box; -ms-box-sizing:border-box; -webkit-box-sizing:border-box; height:"+heig+"px;  border-top:"+arr.borderSize+"px solid; border-color: "+arr.showValuesColor+"; background-color: "+color_map[valueData[i][2]]+"; left:"+wid*i+"px; color:"+arr.showValuesColor+"; font-size:"+fs+"px' >"+sv+"</div></a>";e("#graphFieldBar"+unique).prepend(o)}}if(arr.type=="multi")e(".subBars"+n.id).css({width:wid,position:"absolute",bottom:0});if(arr.position=="bottom")e(".graphField"+n.id).css("bottom",0);if(arr.animate){e("#graphFieldBar"+unique).css({height:0});e("#graphFieldBar"+unique).animate({height:fieldHeight},arr.speed*1e3)}else{e("#graphFieldBar"+unique).css({height:fieldHeight})}}createLegend(color_map,n.id);createLinks(n.id);e(n).append("<div id='legendHolder"+unique+"'></div>");e("#legendHolder"+unique).css({width:legendWidth,"float":"right","margin-left":"100px","text-align":"left"});e("#legendHolder"+unique).append(legend);e("#legendHolder"+unique).append(links);e(".legendBar"+n.id).css({"float":"left",margin:3,"margin-left":"10",height:12,width:20,"font-size":0});e(".linkBar"+n.id).css({"margin-left":"10"});e("#sortAsc"+n.id).click(function(){if(t[n.id].sort!="asc"){t[n.id].sort="asc";e("#graphHolder"+n.id).html("");e("#graphHolder"+n.id).jqbargraph(t[n.id])}});e("#sortDesc"+n.id).click(function(){if(t[n.id].sort!="desc"){t[n.id].sort="desc";e("#graphHolder"+n.id).html("");e("#graphHolder"+n.id).jqbargraph(t[n.id])}});e("#sortBarAsc"+n.id).click(function(){if(t[n.id].sortBar!="asc"){t[n.id].sortBar="asc";e("#graphHolder"+n.id).html("");e("#graphHolder"+n.id).jqbargraph(t[n.id])}});e("#sortBarDesc"+n.id).click(function(){if(t[n.id].sortBar!="desc"){t[n.id].sortBar="desc";e("#graphHolder"+n.id).html("");e("#graphHolder"+n.id).jqbargraph(t[n.id])}});if(arr.title){e(n).wrap("<div id='graphHolder"+n.id+"'></div>");e("#graphHolder"+n.id).prepend("<a href='javascript:void(0);' class=>Reads</a> <a href='javascript:void(0);'>Basepairs</a>");e("#graphHolder"+n.id).prepend("<a href=#files"+n.id+" onclick=fillDiv('"+n.id+"')>"+arr.title+"</a>").css({width:arr.width+"px","text-align":"center"})}e("#graphHolder"+n.id).append("<div class='files"+n.id+"' id='files"+n.id+"' ></div><p/>");e(".files"+n.id).css({width:arr.width+"px","background-color":"silver",border:"2px solid gray",display:"none"});e("#graphHolder"+n.id).append("<div class='image"+n.id+"' id='image"+n.id+"' ></div>");e(".image"+n.id).css({width:arr.width+"px","background-color":"silver",border:"2px solid gray",display:"none"})};createLegend=function(e,t){legend="";for(var n in e){legend+="<div id='legend"+n+"' style='overflow: hidden; zoom: 1;'>";legend+="<div class='legendBar"+t+"' id='legendColor"+n+"' style='background-color:"+e[n]+"'></div>";legend+="<div class='legendLabel"+t+"' id='graphLabel"+unique+"'>"+n+"</div>";legend+="</div>"}};createLinks=function(e){links="<div class='linkBar"+e+"'>";links+="<div ><a href='javascript:void(0);' id='sortAsc"+e+"' >sort  asceding</a></div>";links+="<div ><a href='javascript:void(0);' id='sortDesc"+e+"'>sort  desceding</a></div>";links+="<div ><a href='javascript:void(0);' id='sortBarAsc"+e+"'>sort bars asceding</a></div>";links+="<div ><a href='javascript:void(0);' id='sortBarDesc"+e+"'>sort bars desceding</a></div>";links+="</div>"};fillDiv=function(n,r,i){arr=t[n];dict=arr.files;generateDownloadLink=function(e,t,n){out="no file";if(searchArray("region_"+t+"_"+n,dict[e][t])!=-1){out="<a href="+e+"/region_"+t+"_"+n+">download</a>"}return out};generateShowLink=function(e,t){out="no image";if(searchArray("region_"+t+"_consensus.png",dict[e][t])!=-1){out="<a href=#image"+n+" onclick=showImage('"+n+"','"+t+"','"+e+"/"+dict[e][t][3]+"')>show</a>"}return out};data=arr.data;for(var s in data){for(var o in data[s][0]){dict[data[s][0][0][3]+"_"+data[s][1]][data[s][0][o][5]].push(data[s][0][o][0],data[s][0][o][1],data[s][0][o][4])}}var u=document.getElementById("files"+n);u.innerHTML="";out="<div><b>Files for Sample "+arr.sample+"</b></div><p/>";out+="<div class='"+n+"_files' id='"+n+"_files'><table id='"+n+"table' class='"+n+"table' border=1 cellpadding=3 cellspacing=0 style=' border: 1pt solid #000000; border-Collapse: collapse'>";out+="<tr><th>family</th><th>region</th><th>#reads</th><th>#basepairs</th><th>region length</th><th>unaligned fasta</th><th>bam alignment</th><th>consensus fasta</th><th>consensus diagram</th></tr>";if(!r){for(var a in dict){for(var i in dict[a]){if(dict[a][i][5]){out+="<tr><td>"+a+"</td><td>"+i+"</td><td>"+dict[a][i][5]+"</td><td>"+dict[a][i][6]+"</td><td>"+dict[a][i][7]+"</td><td>"+generateDownloadLink(a,i,"unaligned.fa.bzip2")+"</td><td>"+generateDownloadLink(a,i,"alignment.bam")+"</td><td>"+generateDownloadLink(a,i,"consensus.fa")+"</td><td>"+generateShowLink(a,i)+" "+generateDownloadLink(a,i,"consensus.png")+"</td></tr>"}}out+="</div>"}}else{out+="<b>"+r+"</b>";if(!i){for(var i in dict[r]){if(dict[r][i][5]){out+="<tr><td>"+r+"</td><td>"+i+"</td><td>"+dict[r][i][5]+"</td><td>"+dict[r][i][6]+"</td><td>"+dict[r][i][7]+"</td><td>"+generateDownloadLink(r,i,"unaligned.fa.bzip2")+"</td><td>"+generateDownloadLink(r,i,"alignment.bam")+"</td><td>"+generateDownloadLink(r,i,"consensus.fa")+"</td><td>"+generateShowLink(r,i)+" "+generateDownloadLink(r,i,"consensus.png")+"</td></tr>"}}}else{if(dict[r][i][5]){out+="<tr><td>"+r+"</td><td>"+i+"</td><td>"+dict[r][i][5]+"</td><td>"+dict[r][i][6]+"</td><td>"+dict[r][i][7]+"</td><td>"+generateDownloadLink(r,i,"unaligned.fa.bzip2")+"</td><td>"+generateDownloadLink(r,i,"alignment.bam")+"</td><td>"+generateDownloadLink(r,i,"consensus.fa")+"</td><td>"+generateShowLink(r,i)+"     "+generateDownloadLink(r,i,"consensus.png")+"</td></tr>"}}}out+="</div>";e(u).append(out);e("a").css({color:"black"});e("table").css({border:"collapse"});e(u).append("<div class='close_files"+n+"'style='cursor:pointer;'>x</div>");e(".close_files"+n).click(function(){e(".files"+n).animate({height:"0px"},1e3,"",function(){e(".files"+n).css({display:"none"});e(".files"+n).removeClass("selected")})});e("div.close_files"+n).css({color:"white",position:"absolute",top:5,left:5,"background-color":arr.colors[1],border:"1px solid white","border-radius":"20px",height:"20px",width:"20px","text-align":"center"});e("a.close_files"+n).css({color:"white","text-decoration":"none"});e(".files"+n).css({width:"auto",display:"none"});wi=e(".files"+n).width()+15;if(!e(".files"+n).hasClass("selected")){e(".files"+n).css({height:"auto",display:"none"});hei=e(".files"+n).height();hei=parseInt(hei)+10;hei=hei>400?hei=400:hei;e(".files"+n).css({width:wi+"px",position:"relative",height:"0px",overflow:"auto","background-color":"#D0D0D0",border:"2px solid silver","border-radius":"10px",display:"block"});e(".files"+n).animate({height:hei+"px"},1e3,"",function(){e(".files"+n).addClass("selected")})}else{curr_hei=e(".files"+n).height();e(".files"+n).css({height:"auto",display:"none"});hei=e(".files"+n).height();hei=parseInt(hei)+10;hei=hei>400?hei=400:hei;e(".files"+n).css({height:curr_hei+"px",width:"915px",position:"relative",overflow:"auto","background-color":"#D0D0D0",border:"2px solid silver","border-radius":"10px",display:"block"}).animate({height:hei+"px"},1e3)}};searchArray=function(e,t){for(var n=0;n<t.length;n++){if(t[n].indexOf(e)!=-1)return n}return-1};showImage=function(t,n,r,i){var s=document.getElementById("image"+t);s.innerHTML="";this.img=new Image;this.img.src=r;hei=this.img.height;out="<img src="+r+" alt="+r+">";e(s).append(out);e(s).append("<div class='close_image"+t+"'style='cursor:pointer;'>x</div>");e(".close_image"+t).click(function(){e(".image"+t).animate({height:"0px"},1e3,"",function(){e(".image"+t).css({display:"none"});e(".image"+t).removeClass("selected")})});e("div.close_image"+t).css({color:"white",position:"absolute",bottom:5,left:5,"background-color":arr.colors[1],border:"1px solid white","border-radius":"20px",height:"20px",width:"20px","text-align":"center"});e("a.close_image"+t).css({color:"white","text-decoration":"none"});i=e(".files"+t).width();if(!e(".image"+t).hasClass("selected")){e(".image"+t).css({width:i+"px",position:"relative",height:"0px",overflow:"auto","background-color":"#D0D0D0",border:"2px solid silver","border-radius":"10px",display:"block"});e(".image"+t).animate({height:hei},1e3,"",function(){e(".image"+t).addClass("selected")})}};this.each(function(){init(this)})};e.fn.jqBarGraph.defaults={sample:"no_sample_id",barSpace:10,width:400,height:600,color:"#000000",colors:false,lbl:"",sort:false,sortBar:false,position:"bottom",prefix:"",postfix:"",animate:true,speed:3,legendWidth:150,legend:false,type:false,showValues:false,borderSize:1,showValuesColor:"#fff",title:false}})(jQuery)
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jalview/jquery-1.10.2.min.js	Sun Sep 22 19:13:07 2013 -0400
@@ -0,0 +1,6 @@
+/*! jQuery v1.10.2 | (c) 2005, 2013 jQuery Foundation, Inc. | jquery.org/license
+//@ sourceMappingURL=jquery-1.10.2.min.map
+*/
+(function(e,t){var n,r,i=typeof t,o=e.location,a=e.document,s=a.documentElement,l=e.jQuery,u=e.$,c={},p=[],f="1.10.2",d=p.concat,h=p.push,g=p.slice,m=p.indexOf,y=c.toString,v=c.hasOwnProperty,b=f.trim,x=function(e,t){return new x.fn.init(e,t,r)},w=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,T=/\S+/g,C=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,N=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,k=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,E=/^[\],:{}\s]*$/,S=/(?:^|:|,)(?:\s*\[)+/g,A=/\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,j=/"[^"\\\r\n]*"|true|false|null|-?(?:\d+\.|)\d+(?:[eE][+-]?\d+|)/g,D=/^-ms-/,L=/-([\da-z])/gi,H=function(e,t){return t.toUpperCase()},q=function(e){(a.addEventListener||"load"===e.type||"complete"===a.readyState)&&(_(),x.ready())},_=function(){a.addEventListener?(a.removeEventListener("DOMContentLoaded",q,!1),e.removeEventListener("load",q,!1)):(a.detachEvent("onreadystatechange",q),e.detachEvent("onload",q))};x.fn=x.prototype={jquery:f,constructor:x,init:function(e,n,r){var i,o;if(!e)return this;if("string"==typeof e){if(i="<"===e.charAt(0)&&">"===e.charAt(e.length-1)&&e.length>=3?[null,e,null]:N.exec(e),!i||!i[1]&&n)return!n||n.jquery?(n||r).find(e):this.constructor(n).find(e);if(i[1]){if(n=n instanceof x?n[0]:n,x.merge(this,x.parseHTML(i[1],n&&n.nodeType?n.ownerDocument||n:a,!0)),k.test(i[1])&&x.isPlainObject(n))for(i in n)x.isFunction(this[i])?this[i](n[i]):this.attr(i,n[i]);return this}if(o=a.getElementById(i[2]),o&&o.parentNode){if(o.id!==i[2])return r.find(e);this.length=1,this[0]=o}return this.context=a,this.selector=e,this}return e.nodeType?(this.context=this[0]=e,this.length=1,this):x.isFunction(e)?r.ready(e):(e.selector!==t&&(this.selector=e.selector,this.context=e.context),x.makeArray(e,this))},selector:"",length:0,toArray:function(){return g.call(this)},get:function(e){return null==e?this.toArray():0>e?this[this.length+e]:this[e]},pushStack:function(e){var t=x.merge(this.constructor(),e);return t.prevObject=this,t.context=this.context,t},each:function(e,t){return x.each(this,e,t)},ready:function(e){return x.ready.promise().done(e),this},slice:function(){return this.pushStack(g.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(e){var t=this.length,n=+e+(0>e?t:0);return this.pushStack(n>=0&&t>n?[this[n]]:[])},map:function(e){return this.pushStack(x.map(this,function(t,n){return e.call(t,n,t)}))},end:function(){return this.prevObject||this.constructor(null)},push:h,sort:[].sort,splice:[].splice},x.fn.init.prototype=x.fn,x.extend=x.fn.extend=function(){var e,n,r,i,o,a,s=arguments[0]||{},l=1,u=arguments.length,c=!1;for("boolean"==typeof s&&(c=s,s=arguments[1]||{},l=2),"object"==typeof s||x.isFunction(s)||(s={}),u===l&&(s=this,--l);u>l;l++)if(null!=(o=arguments[l]))for(i in o)e=s[i],r=o[i],s!==r&&(c&&r&&(x.isPlainObject(r)||(n=x.isArray(r)))?(n?(n=!1,a=e&&x.isArray(e)?e:[]):a=e&&x.isPlainObject(e)?e:{},s[i]=x.extend(c,a,r)):r!==t&&(s[i]=r));return s},x.extend({expando:"jQuery"+(f+Math.random()).replace(/\D/g,""),noConflict:function(t){return e.$===x&&(e.$=u),t&&e.jQuery===x&&(e.jQuery=l),x},isReady:!1,readyWait:1,holdReady:function(e){e?x.readyWait++:x.ready(!0)},ready:function(e){if(e===!0?!--x.readyWait:!x.isReady){if(!a.body)return setTimeout(x.ready);x.isReady=!0,e!==!0&&--x.readyWait>0||(n.resolveWith(a,[x]),x.fn.trigger&&x(a).trigger("ready").off("ready"))}},isFunction:function(e){return"function"===x.type(e)},isArray:Array.isArray||function(e){return"array"===x.type(e)},isWindow:function(e){return null!=e&&e==e.window},isNumeric:function(e){return!isNaN(parseFloat(e))&&isFinite(e)},type:function(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?c[y.call(e)]||"object":typeof e},isPlainObject:function(e){var n;if(!e||"object"!==x.type(e)||e.nodeType||x.isWindow(e))return!1;try{if(e.constructor&&!v.call(e,"constructor")&&!v.call(e.constructor.prototype,"isPrototypeOf"))return!1}catch(r){return!1}if(x.support.ownLast)for(n in e)return v.call(e,n);for(n in e);return n===t||v.call(e,n)},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},error:function(e){throw Error(e)},parseHTML:function(e,t,n){if(!e||"string"!=typeof e)return null;"boolean"==typeof t&&(n=t,t=!1),t=t||a;var r=k.exec(e),i=!n&&[];return r?[t.createElement(r[1])]:(r=x.buildFragment([e],t,i),i&&x(i).remove(),x.merge([],r.childNodes))},parseJSON:function(n){return e.JSON&&e.JSON.parse?e.JSON.parse(n):null===n?n:"string"==typeof n&&(n=x.trim(n),n&&E.test(n.replace(A,"@").replace(j,"]").replace(S,"")))?Function("return "+n)():(x.error("Invalid JSON: "+n),t)},parseXML:function(n){var r,i;if(!n||"string"!=typeof n)return null;try{e.DOMParser?(i=new DOMParser,r=i.parseFromString(n,"text/xml")):(r=new ActiveXObject("Microsoft.XMLDOM"),r.async="false",r.loadXML(n))}catch(o){r=t}return r&&r.documentElement&&!r.getElementsByTagName("parsererror").length||x.error("Invalid XML: "+n),r},noop:function(){},globalEval:function(t){t&&x.trim(t)&&(e.execScript||function(t){e.eval.call(e,t)})(t)},camelCase:function(e){return e.replace(D,"ms-").replace(L,H)},nodeName:function(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()},each:function(e,t,n){var r,i=0,o=e.length,a=M(e);if(n){if(a){for(;o>i;i++)if(r=t.apply(e[i],n),r===!1)break}else for(i in e)if(r=t.apply(e[i],n),r===!1)break}else if(a){for(;o>i;i++)if(r=t.call(e[i],i,e[i]),r===!1)break}else for(i in e)if(r=t.call(e[i],i,e[i]),r===!1)break;return e},trim:b&&!b.call("\ufeff\u00a0")?function(e){return null==e?"":b.call(e)}:function(e){return null==e?"":(e+"").replace(C,"")},makeArray:function(e,t){var n=t||[];return null!=e&&(M(Object(e))?x.merge(n,"string"==typeof e?[e]:e):h.call(n,e)),n},inArray:function(e,t,n){var r;if(t){if(m)return m.call(t,e,n);for(r=t.length,n=n?0>n?Math.max(0,r+n):n:0;r>n;n++)if(n in t&&t[n]===e)return n}return-1},merge:function(e,n){var r=n.length,i=e.length,o=0;if("number"==typeof r)for(;r>o;o++)e[i++]=n[o];else while(n[o]!==t)e[i++]=n[o++];return e.length=i,e},grep:function(e,t,n){var r,i=[],o=0,a=e.length;for(n=!!n;a>o;o++)r=!!t(e[o],o),n!==r&&i.push(e[o]);return i},map:function(e,t,n){var r,i=0,o=e.length,a=M(e),s=[];if(a)for(;o>i;i++)r=t(e[i],i,n),null!=r&&(s[s.length]=r);else for(i in e)r=t(e[i],i,n),null!=r&&(s[s.length]=r);return d.apply([],s)},guid:1,proxy:function(e,n){var r,i,o;return"string"==typeof n&&(o=e[n],n=e,e=o),x.isFunction(e)?(r=g.call(arguments,2),i=function(){return e.apply(n||this,r.concat(g.call(arguments)))},i.guid=e.guid=e.guid||x.guid++,i):t},access:function(e,n,r,i,o,a,s){var l=0,u=e.length,c=null==r;if("object"===x.type(r)){o=!0;for(l in r)x.access(e,n,l,r[l],!0,a,s)}else if(i!==t&&(o=!0,x.isFunction(i)||(s=!0),c&&(s?(n.call(e,i),n=null):(c=n,n=function(e,t,n){return c.call(x(e),n)})),n))for(;u>l;l++)n(e[l],r,s?i:i.call(e[l],l,n(e[l],r)));return o?e:c?n.call(e):u?n(e[0],r):a},now:function(){return(new Date).getTime()},swap:function(e,t,n,r){var i,o,a={};for(o in t)a[o]=e.style[o],e.style[o]=t[o];i=n.apply(e,r||[]);for(o in t)e.style[o]=a[o];return i}}),x.ready.promise=function(t){if(!n)if(n=x.Deferred(),"complete"===a.readyState)setTimeout(x.ready);else if(a.addEventListener)a.addEventListener("DOMContentLoaded",q,!1),e.addEventListener("load",q,!1);else{a.attachEvent("onreadystatechange",q),e.attachEvent("onload",q);var r=!1;try{r=null==e.frameElement&&a.documentElement}catch(i){}r&&r.doScroll&&function o(){if(!x.isReady){try{r.doScroll("left")}catch(e){return setTimeout(o,50)}_(),x.ready()}}()}return n.promise(t)},x.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(e,t){c["[object "+t+"]"]=t.toLowerCase()});function M(e){var t=e.length,n=x.type(e);return x.isWindow(e)?!1:1===e.nodeType&&t?!0:"array"===n||"function"!==n&&(0===t||"number"==typeof t&&t>0&&t-1 in e)}r=x(a),function(e,t){var n,r,i,o,a,s,l,u,c,p,f,d,h,g,m,y,v,b="sizzle"+-new Date,w=e.document,T=0,C=0,N=st(),k=st(),E=st(),S=!1,A=function(e,t){return e===t?(S=!0,0):0},j=typeof t,D=1<<31,L={}.hasOwnProperty,H=[],q=H.pop,_=H.push,M=H.push,O=H.slice,F=H.indexOf||function(e){var t=0,n=this.length;for(;n>t;t++)if(this[t]===e)return t;return-1},B="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",P="[\\x20\\t\\r\\n\\f]",R="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",W=R.replace("w","w#"),$="\\["+P+"*("+R+")"+P+"*(?:([*^$|!~]?=)"+P+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+W+")|)|)"+P+"*\\]",I=":("+R+")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|"+$.replace(3,8)+")*)|.*)\\)|)",z=RegExp("^"+P+"+|((?:^|[^\\\\])(?:\\\\.)*)"+P+"+$","g"),X=RegExp("^"+P+"*,"+P+"*"),U=RegExp("^"+P+"*([>+~]|"+P+")"+P+"*"),V=RegExp(P+"*[+~]"),Y=RegExp("="+P+"*([^\\]'\"]*)"+P+"*\\]","g"),J=RegExp(I),G=RegExp("^"+W+"$"),Q={ID:RegExp("^#("+R+")"),CLASS:RegExp("^\\.("+R+")"),TAG:RegExp("^("+R.replace("w","w*")+")"),ATTR:RegExp("^"+$),PSEUDO:RegExp("^"+I),CHILD:RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+P+"*(even|odd|(([+-]|)(\\d*)n|)"+P+"*(?:([+-]|)"+P+"*(\\d+)|))"+P+"*\\)|)","i"),bool:RegExp("^(?:"+B+")$","i"),needsContext:RegExp("^"+P+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+P+"*((?:-\\d)?\\d*)"+P+"*\\)|)(?=[^-]|$)","i")},K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,et=/^(?:input|select|textarea|button)$/i,tt=/^h\d$/i,nt=/'|\\/g,rt=RegExp("\\\\([\\da-f]{1,6}"+P+"?|("+P+")|.)","ig"),it=function(e,t,n){var r="0x"+t-65536;return r!==r||n?t:0>r?String.fromCharCode(r+65536):String.fromCharCode(55296|r>>10,56320|1023&r)};try{M.apply(H=O.call(w.childNodes),w.childNodes),H[w.childNodes.length].nodeType}catch(ot){M={apply:H.length?function(e,t){_.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function at(e,t,n,i){var o,a,s,l,u,c,d,m,y,x;if((t?t.ownerDocument||t:w)!==f&&p(t),t=t||f,n=n||[],!e||"string"!=typeof e)return n;if(1!==(l=t.nodeType)&&9!==l)return[];if(h&&!i){if(o=Z.exec(e))if(s=o[1]){if(9===l){if(a=t.getElementById(s),!a||!a.parentNode)return n;if(a.id===s)return n.push(a),n}else if(t.ownerDocument&&(a=t.ownerDocument.getElementById(s))&&v(t,a)&&a.id===s)return n.push(a),n}else{if(o[2])return M.apply(n,t.getElementsByTagName(e)),n;if((s=o[3])&&r.getElementsByClassName&&t.getElementsByClassName)return M.apply(n,t.getElementsByClassName(s)),n}if(r.qsa&&(!g||!g.test(e))){if(m=d=b,y=t,x=9===l&&e,1===l&&"object"!==t.nodeName.toLowerCase()){c=mt(e),(d=t.getAttribute("id"))?m=d.replace(nt,"\\$&"):t.setAttribute("id",m),m="[id='"+m+"'] ",u=c.length;while(u--)c[u]=m+yt(c[u]);y=V.test(e)&&t.parentNode||t,x=c.join(",")}if(x)try{return M.apply(n,y.querySelectorAll(x)),n}catch(T){}finally{d||t.removeAttribute("id")}}}return kt(e.replace(z,"$1"),t,n,i)}function st(){var e=[];function t(n,r){return e.push(n+=" ")>o.cacheLength&&delete t[e.shift()],t[n]=r}return t}function lt(e){return e[b]=!0,e}function ut(e){var t=f.createElement("div");try{return!!e(t)}catch(n){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function ct(e,t){var n=e.split("|"),r=e.length;while(r--)o.attrHandle[n[r]]=t}function pt(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&(~t.sourceIndex||D)-(~e.sourceIndex||D);if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function ft(e){return function(t){var n=t.nodeName.toLowerCase();return"input"===n&&t.type===e}}function dt(e){return function(t){var n=t.nodeName.toLowerCase();return("input"===n||"button"===n)&&t.type===e}}function ht(e){return lt(function(t){return t=+t,lt(function(n,r){var i,o=e([],n.length,t),a=o.length;while(a--)n[i=o[a]]&&(n[i]=!(r[i]=n[i]))})})}s=at.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return t?"HTML"!==t.nodeName:!1},r=at.support={},p=at.setDocument=function(e){var n=e?e.ownerDocument||e:w,i=n.defaultView;return n!==f&&9===n.nodeType&&n.documentElement?(f=n,d=n.documentElement,h=!s(n),i&&i.attachEvent&&i!==i.top&&i.attachEvent("onbeforeunload",function(){p()}),r.attributes=ut(function(e){return e.className="i",!e.getAttribute("className")}),r.getElementsByTagName=ut(function(e){return e.appendChild(n.createComment("")),!e.getElementsByTagName("*").length}),r.getElementsByClassName=ut(function(e){return e.innerHTML="<div class='a'></div><div class='a i'></div>",e.firstChild.className="i",2===e.getElementsByClassName("i").length}),r.getById=ut(function(e){return d.appendChild(e).id=b,!n.getElementsByName||!n.getElementsByName(b).length}),r.getById?(o.find.ID=function(e,t){if(typeof t.getElementById!==j&&h){var n=t.getElementById(e);return n&&n.parentNode?[n]:[]}},o.filter.ID=function(e){var t=e.replace(rt,it);return function(e){return e.getAttribute("id")===t}}):(delete o.find.ID,o.filter.ID=function(e){var t=e.replace(rt,it);return function(e){var n=typeof e.getAttributeNode!==j&&e.getAttributeNode("id");return n&&n.value===t}}),o.find.TAG=r.getElementsByTagName?function(e,n){return typeof n.getElementsByTagName!==j?n.getElementsByTagName(e):t}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},o.find.CLASS=r.getElementsByClassName&&function(e,n){return typeof n.getElementsByClassName!==j&&h?n.getElementsByClassName(e):t},m=[],g=[],(r.qsa=K.test(n.querySelectorAll))&&(ut(function(e){e.innerHTML="<select><option selected=''></option></select>",e.querySelectorAll("[selected]").length||g.push("\\["+P+"*(?:value|"+B+")"),e.querySelectorAll(":checked").length||g.push(":checked")}),ut(function(e){var t=n.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("t",""),e.querySelectorAll("[t^='']").length&&g.push("[*^$]="+P+"*(?:''|\"\")"),e.querySelectorAll(":enabled").length||g.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),g.push(",.*:")})),(r.matchesSelector=K.test(y=d.webkitMatchesSelector||d.mozMatchesSelector||d.oMatchesSelector||d.msMatchesSelector))&&ut(function(e){r.disconnectedMatch=y.call(e,"div"),y.call(e,"[s!='']:x"),m.push("!=",I)}),g=g.length&&RegExp(g.join("|")),m=m.length&&RegExp(m.join("|")),v=K.test(d.contains)||d.compareDocumentPosition?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},A=d.compareDocumentPosition?function(e,t){if(e===t)return S=!0,0;var i=t.compareDocumentPosition&&e.compareDocumentPosition&&e.compareDocumentPosition(t);return i?1&i||!r.sortDetached&&t.compareDocumentPosition(e)===i?e===n||v(w,e)?-1:t===n||v(w,t)?1:c?F.call(c,e)-F.call(c,t):0:4&i?-1:1:e.compareDocumentPosition?-1:1}:function(e,t){var r,i=0,o=e.parentNode,a=t.parentNode,s=[e],l=[t];if(e===t)return S=!0,0;if(!o||!a)return e===n?-1:t===n?1:o?-1:a?1:c?F.call(c,e)-F.call(c,t):0;if(o===a)return pt(e,t);r=e;while(r=r.parentNode)s.unshift(r);r=t;while(r=r.parentNode)l.unshift(r);while(s[i]===l[i])i++;return i?pt(s[i],l[i]):s[i]===w?-1:l[i]===w?1:0},n):f},at.matches=function(e,t){return at(e,null,null,t)},at.matchesSelector=function(e,t){if((e.ownerDocument||e)!==f&&p(e),t=t.replace(Y,"='$1']"),!(!r.matchesSelector||!h||m&&m.test(t)||g&&g.test(t)))try{var n=y.call(e,t);if(n||r.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(i){}return at(t,f,null,[e]).length>0},at.contains=function(e,t){return(e.ownerDocument||e)!==f&&p(e),v(e,t)},at.attr=function(e,n){(e.ownerDocument||e)!==f&&p(e);var i=o.attrHandle[n.toLowerCase()],a=i&&L.call(o.attrHandle,n.toLowerCase())?i(e,n,!h):t;return a===t?r.attributes||!h?e.getAttribute(n):(a=e.getAttributeNode(n))&&a.specified?a.value:null:a},at.error=function(e){throw Error("Syntax error, unrecognized expression: "+e)},at.uniqueSort=function(e){var t,n=[],i=0,o=0;if(S=!r.detectDuplicates,c=!r.sortStable&&e.slice(0),e.sort(A),S){while(t=e[o++])t===e[o]&&(i=n.push(o));while(i--)e.splice(n[i],1)}return e},a=at.getText=function(e){var t,n="",r=0,i=e.nodeType;if(i){if(1===i||9===i||11===i){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=a(e)}else if(3===i||4===i)return e.nodeValue}else for(;t=e[r];r++)n+=a(t);return n},o=at.selectors={cacheLength:50,createPseudo:lt,match:Q,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(rt,it),e[3]=(e[4]||e[5]||"").replace(rt,it),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||at.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&at.error(e[0]),e},PSEUDO:function(e){var n,r=!e[5]&&e[2];return Q.CHILD.test(e[0])?null:(e[3]&&e[4]!==t?e[2]=e[4]:r&&J.test(r)&&(n=mt(r,!0))&&(n=r.indexOf(")",r.length-n)-r.length)&&(e[0]=e[0].slice(0,n),e[2]=r.slice(0,n)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(rt,it).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=N[e+" "];return t||(t=RegExp("(^|"+P+")"+e+"("+P+"|$)"))&&N(e,function(e){return t.test("string"==typeof e.className&&e.className||typeof e.getAttribute!==j&&e.getAttribute("class")||"")})},ATTR:function(e,t,n){return function(r){var i=at.attr(r,e);return null==i?"!="===t:t?(i+="","="===t?i===n:"!="===t?i!==n:"^="===t?n&&0===i.indexOf(n):"*="===t?n&&i.indexOf(n)>-1:"$="===t?n&&i.slice(-n.length)===n:"~="===t?(" "+i+" ").indexOf(n)>-1:"|="===t?i===n||i.slice(0,n.length+1)===n+"-":!1):!0}},CHILD:function(e,t,n,r,i){var o="nth"!==e.slice(0,3),a="last"!==e.slice(-4),s="of-type"===t;return 1===r&&0===i?function(e){return!!e.parentNode}:function(t,n,l){var u,c,p,f,d,h,g=o!==a?"nextSibling":"previousSibling",m=t.parentNode,y=s&&t.nodeName.toLowerCase(),v=!l&&!s;if(m){if(o){while(g){p=t;while(p=p[g])if(s?p.nodeName.toLowerCase()===y:1===p.nodeType)return!1;h=g="only"===e&&!h&&"nextSibling"}return!0}if(h=[a?m.firstChild:m.lastChild],a&&v){c=m[b]||(m[b]={}),u=c[e]||[],d=u[0]===T&&u[1],f=u[0]===T&&u[2],p=d&&m.childNodes[d];while(p=++d&&p&&p[g]||(f=d=0)||h.pop())if(1===p.nodeType&&++f&&p===t){c[e]=[T,d,f];break}}else if(v&&(u=(t[b]||(t[b]={}))[e])&&u[0]===T)f=u[1];else while(p=++d&&p&&p[g]||(f=d=0)||h.pop())if((s?p.nodeName.toLowerCase()===y:1===p.nodeType)&&++f&&(v&&((p[b]||(p[b]={}))[e]=[T,f]),p===t))break;return f-=i,f===r||0===f%r&&f/r>=0}}},PSEUDO:function(e,t){var n,r=o.pseudos[e]||o.setFilters[e.toLowerCase()]||at.error("unsupported pseudo: "+e);return r[b]?r(t):r.length>1?(n=[e,e,"",t],o.setFilters.hasOwnProperty(e.toLowerCase())?lt(function(e,n){var i,o=r(e,t),a=o.length;while(a--)i=F.call(e,o[a]),e[i]=!(n[i]=o[a])}):function(e){return r(e,0,n)}):r}},pseudos:{not:lt(function(e){var t=[],n=[],r=l(e.replace(z,"$1"));return r[b]?lt(function(e,t,n,i){var o,a=r(e,null,i,[]),s=e.length;while(s--)(o=a[s])&&(e[s]=!(t[s]=o))}):function(e,i,o){return t[0]=e,r(t,null,o,n),!n.pop()}}),has:lt(function(e){return function(t){return at(e,t).length>0}}),contains:lt(function(e){return function(t){return(t.textContent||t.innerText||a(t)).indexOf(e)>-1}}),lang:lt(function(e){return G.test(e||"")||at.error("unsupported lang: "+e),e=e.replace(rt,it).toLowerCase(),function(t){var n;do if(n=h?t.lang:t.getAttribute("xml:lang")||t.getAttribute("lang"))return n=n.toLowerCase(),n===e||0===n.indexOf(e+"-");while((t=t.parentNode)&&1===t.nodeType);return!1}}),target:function(t){var n=e.location&&e.location.hash;return n&&n.slice(1)===t.id},root:function(e){return e===d},focus:function(e){return e===f.activeElement&&(!f.hasFocus||f.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:function(e){return e.disabled===!1},disabled:function(e){return e.disabled===!0},checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,e.selected===!0},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeName>"@"||3===e.nodeType||4===e.nodeType)return!1;return!0},parent:function(e){return!o.pseudos.empty(e)},header:function(e){return tt.test(e.nodeName)},input:function(e){return et.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||t.toLowerCase()===e.type)},first:ht(function(){return[0]}),last:ht(function(e,t){return[t-1]}),eq:ht(function(e,t,n){return[0>n?n+t:n]}),even:ht(function(e,t){var n=0;for(;t>n;n+=2)e.push(n);return e}),odd:ht(function(e,t){var n=1;for(;t>n;n+=2)e.push(n);return e}),lt:ht(function(e,t,n){var r=0>n?n+t:n;for(;--r>=0;)e.push(r);return e}),gt:ht(function(e,t,n){var r=0>n?n+t:n;for(;t>++r;)e.push(r);return e})}},o.pseudos.nth=o.pseudos.eq;for(n in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})o.pseudos[n]=ft(n);for(n in{submit:!0,reset:!0})o.pseudos[n]=dt(n);function gt(){}gt.prototype=o.filters=o.pseudos,o.setFilters=new gt;function mt(e,t){var n,r,i,a,s,l,u,c=k[e+" "];if(c)return t?0:c.slice(0);s=e,l=[],u=o.preFilter;while(s){(!n||(r=X.exec(s)))&&(r&&(s=s.slice(r[0].length)||s),l.push(i=[])),n=!1,(r=U.exec(s))&&(n=r.shift(),i.push({value:n,type:r[0].replace(z," ")}),s=s.slice(n.length));for(a in o.filter)!(r=Q[a].exec(s))||u[a]&&!(r=u[a](r))||(n=r.shift(),i.push({value:n,type:a,matches:r}),s=s.slice(n.length));if(!n)break}return t?s.length:s?at.error(e):k(e,l).slice(0)}function yt(e){var t=0,n=e.length,r="";for(;n>t;t++)r+=e[t].value;return r}function vt(e,t,n){var r=t.dir,o=n&&"parentNode"===r,a=C++;return t.first?function(t,n,i){while(t=t[r])if(1===t.nodeType||o)return e(t,n,i)}:function(t,n,s){var l,u,c,p=T+" "+a;if(s){while(t=t[r])if((1===t.nodeType||o)&&e(t,n,s))return!0}else while(t=t[r])if(1===t.nodeType||o)if(c=t[b]||(t[b]={}),(u=c[r])&&u[0]===p){if((l=u[1])===!0||l===i)return l===!0}else if(u=c[r]=[p],u[1]=e(t,n,s)||i,u[1]===!0)return!0}}function bt(e){return e.length>1?function(t,n,r){var i=e.length;while(i--)if(!e[i](t,n,r))return!1;return!0}:e[0]}function xt(e,t,n,r,i){var o,a=[],s=0,l=e.length,u=null!=t;for(;l>s;s++)(o=e[s])&&(!n||n(o,r,i))&&(a.push(o),u&&t.push(s));return a}function wt(e,t,n,r,i,o){return r&&!r[b]&&(r=wt(r)),i&&!i[b]&&(i=wt(i,o)),lt(function(o,a,s,l){var u,c,p,f=[],d=[],h=a.length,g=o||Nt(t||"*",s.nodeType?[s]:s,[]),m=!e||!o&&t?g:xt(g,f,e,s,l),y=n?i||(o?e:h||r)?[]:a:m;if(n&&n(m,y,s,l),r){u=xt(y,d),r(u,[],s,l),c=u.length;while(c--)(p=u[c])&&(y[d[c]]=!(m[d[c]]=p))}if(o){if(i||e){if(i){u=[],c=y.length;while(c--)(p=y[c])&&u.push(m[c]=p);i(null,y=[],u,l)}c=y.length;while(c--)(p=y[c])&&(u=i?F.call(o,p):f[c])>-1&&(o[u]=!(a[u]=p))}}else y=xt(y===a?y.splice(h,y.length):y),i?i(null,a,y,l):M.apply(a,y)})}function Tt(e){var t,n,r,i=e.length,a=o.relative[e[0].type],s=a||o.relative[" "],l=a?1:0,c=vt(function(e){return e===t},s,!0),p=vt(function(e){return F.call(t,e)>-1},s,!0),f=[function(e,n,r){return!a&&(r||n!==u)||((t=n).nodeType?c(e,n,r):p(e,n,r))}];for(;i>l;l++)if(n=o.relative[e[l].type])f=[vt(bt(f),n)];else{if(n=o.filter[e[l].type].apply(null,e[l].matches),n[b]){for(r=++l;i>r;r++)if(o.relative[e[r].type])break;return wt(l>1&&bt(f),l>1&&yt(e.slice(0,l-1).concat({value:" "===e[l-2].type?"*":""})).replace(z,"$1"),n,r>l&&Tt(e.slice(l,r)),i>r&&Tt(e=e.slice(r)),i>r&&yt(e))}f.push(n)}return bt(f)}function Ct(e,t){var n=0,r=t.length>0,a=e.length>0,s=function(s,l,c,p,d){var h,g,m,y=[],v=0,b="0",x=s&&[],w=null!=d,C=u,N=s||a&&o.find.TAG("*",d&&l.parentNode||l),k=T+=null==C?1:Math.random()||.1;for(w&&(u=l!==f&&l,i=n);null!=(h=N[b]);b++){if(a&&h){g=0;while(m=e[g++])if(m(h,l,c)){p.push(h);break}w&&(T=k,i=++n)}r&&((h=!m&&h)&&v--,s&&x.push(h))}if(v+=b,r&&b!==v){g=0;while(m=t[g++])m(x,y,l,c);if(s){if(v>0)while(b--)x[b]||y[b]||(y[b]=q.call(p));y=xt(y)}M.apply(p,y),w&&!s&&y.length>0&&v+t.length>1&&at.uniqueSort(p)}return w&&(T=k,u=C),x};return r?lt(s):s}l=at.compile=function(e,t){var n,r=[],i=[],o=E[e+" "];if(!o){t||(t=mt(e)),n=t.length;while(n--)o=Tt(t[n]),o[b]?r.push(o):i.push(o);o=E(e,Ct(i,r))}return o};function Nt(e,t,n){var r=0,i=t.length;for(;i>r;r++)at(e,t[r],n);return n}function kt(e,t,n,i){var a,s,u,c,p,f=mt(e);if(!i&&1===f.length){if(s=f[0]=f[0].slice(0),s.length>2&&"ID"===(u=s[0]).type&&r.getById&&9===t.nodeType&&h&&o.relative[s[1].type]){if(t=(o.find.ID(u.matches[0].replace(rt,it),t)||[])[0],!t)return n;e=e.slice(s.shift().value.length)}a=Q.needsContext.test(e)?0:s.length;while(a--){if(u=s[a],o.relative[c=u.type])break;if((p=o.find[c])&&(i=p(u.matches[0].replace(rt,it),V.test(s[0].type)&&t.parentNode||t))){if(s.splice(a,1),e=i.length&&yt(s),!e)return M.apply(n,i),n;break}}}return l(e,f)(i,t,!h,n,V.test(e)),n}r.sortStable=b.split("").sort(A).join("")===b,r.detectDuplicates=S,p(),r.sortDetached=ut(function(e){return 1&e.compareDocumentPosition(f.createElement("div"))}),ut(function(e){return e.innerHTML="<a href='#'></a>","#"===e.firstChild.getAttribute("href")})||ct("type|href|height|width",function(e,n,r){return r?t:e.getAttribute(n,"type"===n.toLowerCase()?1:2)}),r.attributes&&ut(function(e){return e.innerHTML="<input/>",e.firstChild.setAttribute("value",""),""===e.firstChild.getAttribute("value")})||ct("value",function(e,n,r){return r||"input"!==e.nodeName.toLowerCase()?t:e.defaultValue}),ut(function(e){return null==e.getAttribute("disabled")})||ct(B,function(e,n,r){var i;return r?t:(i=e.getAttributeNode(n))&&i.specified?i.value:e[n]===!0?n.toLowerCase():null}),x.find=at,x.expr=at.selectors,x.expr[":"]=x.expr.pseudos,x.unique=at.uniqueSort,x.text=at.getText,x.isXMLDoc=at.isXML,x.contains=at.contains}(e);var O={};function F(e){var t=O[e]={};return x.each(e.match(T)||[],function(e,n){t[n]=!0}),t}x.Callbacks=function(e){e="string"==typeof e?O[e]||F(e):x.extend({},e);var n,r,i,o,a,s,l=[],u=!e.once&&[],c=function(t){for(r=e.memory&&t,i=!0,a=s||0,s=0,o=l.length,n=!0;l&&o>a;a++)if(l[a].apply(t[0],t[1])===!1&&e.stopOnFalse){r=!1;break}n=!1,l&&(u?u.length&&c(u.shift()):r?l=[]:p.disable())},p={add:function(){if(l){var t=l.length;(function i(t){x.each(t,function(t,n){var r=x.type(n);"function"===r?e.unique&&p.has(n)||l.push(n):n&&n.length&&"string"!==r&&i(n)})})(arguments),n?o=l.length:r&&(s=t,c(r))}return this},remove:function(){return l&&x.each(arguments,function(e,t){var r;while((r=x.inArray(t,l,r))>-1)l.splice(r,1),n&&(o>=r&&o--,a>=r&&a--)}),this},has:function(e){return e?x.inArray(e,l)>-1:!(!l||!l.length)},empty:function(){return l=[],o=0,this},disable:function(){return l=u=r=t,this},disabled:function(){return!l},lock:function(){return u=t,r||p.disable(),this},locked:function(){return!u},fireWith:function(e,t){return!l||i&&!u||(t=t||[],t=[e,t.slice?t.slice():t],n?u.push(t):c(t)),this},fire:function(){return p.fireWith(this,arguments),this},fired:function(){return!!i}};return p},x.extend({Deferred:function(e){var t=[["resolve","done",x.Callbacks("once memory"),"resolved"],["reject","fail",x.Callbacks("once memory"),"rejected"],["notify","progress",x.Callbacks("memory")]],n="pending",r={state:function(){return n},always:function(){return i.done(arguments).fail(arguments),this},then:function(){var e=arguments;return x.Deferred(function(n){x.each(t,function(t,o){var a=o[0],s=x.isFunction(e[t])&&e[t];i[o[1]](function(){var e=s&&s.apply(this,arguments);e&&x.isFunction(e.promise)?e.promise().done(n.resolve).fail(n.reject).progress(n.notify):n[a+"With"](this===r?n.promise():this,s?[e]:arguments)})}),e=null}).promise()},promise:function(e){return null!=e?x.extend(e,r):r}},i={};return r.pipe=r.then,x.each(t,function(e,o){var a=o[2],s=o[3];r[o[1]]=a.add,s&&a.add(function(){n=s},t[1^e][2].disable,t[2][2].lock),i[o[0]]=function(){return i[o[0]+"With"](this===i?r:this,arguments),this},i[o[0]+"With"]=a.fireWith}),r.promise(i),e&&e.call(i,i),i},when:function(e){var t=0,n=g.call(arguments),r=n.length,i=1!==r||e&&x.isFunction(e.promise)?r:0,o=1===i?e:x.Deferred(),a=function(e,t,n){return function(r){t[e]=this,n[e]=arguments.length>1?g.call(arguments):r,n===s?o.notifyWith(t,n):--i||o.resolveWith(t,n)}},s,l,u;if(r>1)for(s=Array(r),l=Array(r),u=Array(r);r>t;t++)n[t]&&x.isFunction(n[t].promise)?n[t].promise().done(a(t,u,n)).fail(o.reject).progress(a(t,l,s)):--i;return i||o.resolveWith(u,n),o.promise()}}),x.support=function(t){var n,r,o,s,l,u,c,p,f,d=a.createElement("div");if(d.setAttribute("className","t"),d.innerHTML="  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",n=d.getElementsByTagName("*")||[],r=d.getElementsByTagName("a")[0],!r||!r.style||!n.length)return t;s=a.createElement("select"),u=s.appendChild(a.createElement("option")),o=d.getElementsByTagName("input")[0],r.style.cssText="top:1px;float:left;opacity:.5",t.getSetAttribute="t"!==d.className,t.leadingWhitespace=3===d.firstChild.nodeType,t.tbody=!d.getElementsByTagName("tbody").length,t.htmlSerialize=!!d.getElementsByTagName("link").length,t.style=/top/.test(r.getAttribute("style")),t.hrefNormalized="/a"===r.getAttribute("href"),t.opacity=/^0.5/.test(r.style.opacity),t.cssFloat=!!r.style.cssFloat,t.checkOn=!!o.value,t.optSelected=u.selected,t.enctype=!!a.createElement("form").enctype,t.html5Clone="<:nav></:nav>"!==a.createElement("nav").cloneNode(!0).outerHTML,t.inlineBlockNeedsLayout=!1,t.shrinkWrapBlocks=!1,t.pixelPosition=!1,t.deleteExpando=!0,t.noCloneEvent=!0,t.reliableMarginRight=!0,t.boxSizingReliable=!0,o.checked=!0,t.noCloneChecked=o.cloneNode(!0).checked,s.disabled=!0,t.optDisabled=!u.disabled;try{delete d.test}catch(h){t.deleteExpando=!1}o=a.createElement("input"),o.setAttribute("value",""),t.input=""===o.getAttribute("value"),o.value="t",o.setAttribute("type","radio"),t.radioValue="t"===o.value,o.setAttribute("checked","t"),o.setAttribute("name","t"),l=a.createDocumentFragment(),l.appendChild(o),t.appendChecked=o.checked,t.checkClone=l.cloneNode(!0).cloneNode(!0).lastChild.checked,d.attachEvent&&(d.attachEvent("onclick",function(){t.noCloneEvent=!1}),d.cloneNode(!0).click());for(f in{submit:!0,change:!0,focusin:!0})d.setAttribute(c="on"+f,"t"),t[f+"Bubbles"]=c in e||d.attributes[c].expando===!1;d.style.backgroundClip="content-box",d.cloneNode(!0).style.backgroundClip="",t.clearCloneStyle="content-box"===d.style.backgroundClip;for(f in x(t))break;return t.ownLast="0"!==f,x(function(){var n,r,o,s="padding:0;margin:0;border:0;display:block;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;",l=a.getElementsByTagName("body")[0];l&&(n=a.createElement("div"),n.style.cssText="border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px",l.appendChild(n).appendChild(d),d.innerHTML="<table><tr><td></td><td>t</td></tr></table>",o=d.getElementsByTagName("td"),o[0].style.cssText="padding:0;margin:0;border:0;display:none",p=0===o[0].offsetHeight,o[0].style.display="",o[1].style.display="none",t.reliableHiddenOffsets=p&&0===o[0].offsetHeight,d.innerHTML="",d.style.cssText="box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;",x.swap(l,null!=l.style.zoom?{zoom:1}:{},function(){t.boxSizing=4===d.offsetWidth}),e.getComputedStyle&&(t.pixelPosition="1%"!==(e.getComputedStyle(d,null)||{}).top,t.boxSizingReliable="4px"===(e.getComputedStyle(d,null)||{width:"4px"}).width,r=d.appendChild(a.createElement("div")),r.style.cssText=d.style.cssText=s,r.style.marginRight=r.style.width="0",d.style.width="1px",t.reliableMarginRight=!parseFloat((e.getComputedStyle(r,null)||{}).marginRight)),typeof d.style.zoom!==i&&(d.innerHTML="",d.style.cssText=s+"width:1px;padding:1px;display:inline;zoom:1",t.inlineBlockNeedsLayout=3===d.offsetWidth,d.style.display="block",d.innerHTML="<div></div>",d.firstChild.style.width="5px",t.shrinkWrapBlocks=3!==d.offsetWidth,t.inlineBlockNeedsLayout&&(l.style.zoom=1)),l.removeChild(n),n=d=o=r=null)}),n=s=l=u=r=o=null,t
+}({});var B=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,P=/([A-Z])/g;function R(e,n,r,i){if(x.acceptData(e)){var o,a,s=x.expando,l=e.nodeType,u=l?x.cache:e,c=l?e[s]:e[s]&&s;if(c&&u[c]&&(i||u[c].data)||r!==t||"string"!=typeof n)return c||(c=l?e[s]=p.pop()||x.guid++:s),u[c]||(u[c]=l?{}:{toJSON:x.noop}),("object"==typeof n||"function"==typeof n)&&(i?u[c]=x.extend(u[c],n):u[c].data=x.extend(u[c].data,n)),a=u[c],i||(a.data||(a.data={}),a=a.data),r!==t&&(a[x.camelCase(n)]=r),"string"==typeof n?(o=a[n],null==o&&(o=a[x.camelCase(n)])):o=a,o}}function W(e,t,n){if(x.acceptData(e)){var r,i,o=e.nodeType,a=o?x.cache:e,s=o?e[x.expando]:x.expando;if(a[s]){if(t&&(r=n?a[s]:a[s].data)){x.isArray(t)?t=t.concat(x.map(t,x.camelCase)):t in r?t=[t]:(t=x.camelCase(t),t=t in r?[t]:t.split(" ")),i=t.length;while(i--)delete r[t[i]];if(n?!I(r):!x.isEmptyObject(r))return}(n||(delete a[s].data,I(a[s])))&&(o?x.cleanData([e],!0):x.support.deleteExpando||a!=a.window?delete a[s]:a[s]=null)}}}x.extend({cache:{},noData:{applet:!0,embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"},hasData:function(e){return e=e.nodeType?x.cache[e[x.expando]]:e[x.expando],!!e&&!I(e)},data:function(e,t,n){return R(e,t,n)},removeData:function(e,t){return W(e,t)},_data:function(e,t,n){return R(e,t,n,!0)},_removeData:function(e,t){return W(e,t,!0)},acceptData:function(e){if(e.nodeType&&1!==e.nodeType&&9!==e.nodeType)return!1;var t=e.nodeName&&x.noData[e.nodeName.toLowerCase()];return!t||t!==!0&&e.getAttribute("classid")===t}}),x.fn.extend({data:function(e,n){var r,i,o=null,a=0,s=this[0];if(e===t){if(this.length&&(o=x.data(s),1===s.nodeType&&!x._data(s,"parsedAttrs"))){for(r=s.attributes;r.length>a;a++)i=r[a].name,0===i.indexOf("data-")&&(i=x.camelCase(i.slice(5)),$(s,i,o[i]));x._data(s,"parsedAttrs",!0)}return o}return"object"==typeof e?this.each(function(){x.data(this,e)}):arguments.length>1?this.each(function(){x.data(this,e,n)}):s?$(s,e,x.data(s,e)):null},removeData:function(e){return this.each(function(){x.removeData(this,e)})}});function $(e,n,r){if(r===t&&1===e.nodeType){var i="data-"+n.replace(P,"-$1").toLowerCase();if(r=e.getAttribute(i),"string"==typeof r){try{r="true"===r?!0:"false"===r?!1:"null"===r?null:+r+""===r?+r:B.test(r)?x.parseJSON(r):r}catch(o){}x.data(e,n,r)}else r=t}return r}function I(e){var t;for(t in e)if(("data"!==t||!x.isEmptyObject(e[t]))&&"toJSON"!==t)return!1;return!0}x.extend({queue:function(e,n,r){var i;return e?(n=(n||"fx")+"queue",i=x._data(e,n),r&&(!i||x.isArray(r)?i=x._data(e,n,x.makeArray(r)):i.push(r)),i||[]):t},dequeue:function(e,t){t=t||"fx";var n=x.queue(e,t),r=n.length,i=n.shift(),o=x._queueHooks(e,t),a=function(){x.dequeue(e,t)};"inprogress"===i&&(i=n.shift(),r--),i&&("fx"===t&&n.unshift("inprogress"),delete o.stop,i.call(e,a,o)),!r&&o&&o.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return x._data(e,n)||x._data(e,n,{empty:x.Callbacks("once memory").add(function(){x._removeData(e,t+"queue"),x._removeData(e,n)})})}}),x.fn.extend({queue:function(e,n){var r=2;return"string"!=typeof e&&(n=e,e="fx",r--),r>arguments.length?x.queue(this[0],e):n===t?this:this.each(function(){var t=x.queue(this,e,n);x._queueHooks(this,e),"fx"===e&&"inprogress"!==t[0]&&x.dequeue(this,e)})},dequeue:function(e){return this.each(function(){x.dequeue(this,e)})},delay:function(e,t){return e=x.fx?x.fx.speeds[e]||e:e,t=t||"fx",this.queue(t,function(t,n){var r=setTimeout(t,e);n.stop=function(){clearTimeout(r)}})},clearQueue:function(e){return this.queue(e||"fx",[])},promise:function(e,n){var r,i=1,o=x.Deferred(),a=this,s=this.length,l=function(){--i||o.resolveWith(a,[a])};"string"!=typeof e&&(n=e,e=t),e=e||"fx";while(s--)r=x._data(a[s],e+"queueHooks"),r&&r.empty&&(i++,r.empty.add(l));return l(),o.promise(n)}});var z,X,U=/[\t\r\n\f]/g,V=/\r/g,Y=/^(?:input|select|textarea|button|object)$/i,J=/^(?:a|area)$/i,G=/^(?:checked|selected)$/i,Q=x.support.getSetAttribute,K=x.support.input;x.fn.extend({attr:function(e,t){return x.access(this,x.attr,e,t,arguments.length>1)},removeAttr:function(e){return this.each(function(){x.removeAttr(this,e)})},prop:function(e,t){return x.access(this,x.prop,e,t,arguments.length>1)},removeProp:function(e){return e=x.propFix[e]||e,this.each(function(){try{this[e]=t,delete this[e]}catch(n){}})},addClass:function(e){var t,n,r,i,o,a=0,s=this.length,l="string"==typeof e&&e;if(x.isFunction(e))return this.each(function(t){x(this).addClass(e.call(this,t,this.className))});if(l)for(t=(e||"").match(T)||[];s>a;a++)if(n=this[a],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(U," "):" ")){o=0;while(i=t[o++])0>r.indexOf(" "+i+" ")&&(r+=i+" ");n.className=x.trim(r)}return this},removeClass:function(e){var t,n,r,i,o,a=0,s=this.length,l=0===arguments.length||"string"==typeof e&&e;if(x.isFunction(e))return this.each(function(t){x(this).removeClass(e.call(this,t,this.className))});if(l)for(t=(e||"").match(T)||[];s>a;a++)if(n=this[a],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(U," "):"")){o=0;while(i=t[o++])while(r.indexOf(" "+i+" ")>=0)r=r.replace(" "+i+" "," ");n.className=e?x.trim(r):""}return this},toggleClass:function(e,t){var n=typeof e;return"boolean"==typeof t&&"string"===n?t?this.addClass(e):this.removeClass(e):x.isFunction(e)?this.each(function(n){x(this).toggleClass(e.call(this,n,this.className,t),t)}):this.each(function(){if("string"===n){var t,r=0,o=x(this),a=e.match(T)||[];while(t=a[r++])o.hasClass(t)?o.removeClass(t):o.addClass(t)}else(n===i||"boolean"===n)&&(this.className&&x._data(this,"__className__",this.className),this.className=this.className||e===!1?"":x._data(this,"__className__")||"")})},hasClass:function(e){var t=" "+e+" ",n=0,r=this.length;for(;r>n;n++)if(1===this[n].nodeType&&(" "+this[n].className+" ").replace(U," ").indexOf(t)>=0)return!0;return!1},val:function(e){var n,r,i,o=this[0];{if(arguments.length)return i=x.isFunction(e),this.each(function(n){var o;1===this.nodeType&&(o=i?e.call(this,n,x(this).val()):e,null==o?o="":"number"==typeof o?o+="":x.isArray(o)&&(o=x.map(o,function(e){return null==e?"":e+""})),r=x.valHooks[this.type]||x.valHooks[this.nodeName.toLowerCase()],r&&"set"in r&&r.set(this,o,"value")!==t||(this.value=o))});if(o)return r=x.valHooks[o.type]||x.valHooks[o.nodeName.toLowerCase()],r&&"get"in r&&(n=r.get(o,"value"))!==t?n:(n=o.value,"string"==typeof n?n.replace(V,""):null==n?"":n)}}}),x.extend({valHooks:{option:{get:function(e){var t=x.find.attr(e,"value");return null!=t?t:e.text}},select:{get:function(e){var t,n,r=e.options,i=e.selectedIndex,o="select-one"===e.type||0>i,a=o?null:[],s=o?i+1:r.length,l=0>i?s:o?i:0;for(;s>l;l++)if(n=r[l],!(!n.selected&&l!==i||(x.support.optDisabled?n.disabled:null!==n.getAttribute("disabled"))||n.parentNode.disabled&&x.nodeName(n.parentNode,"optgroup"))){if(t=x(n).val(),o)return t;a.push(t)}return a},set:function(e,t){var n,r,i=e.options,o=x.makeArray(t),a=i.length;while(a--)r=i[a],(r.selected=x.inArray(x(r).val(),o)>=0)&&(n=!0);return n||(e.selectedIndex=-1),o}}},attr:function(e,n,r){var o,a,s=e.nodeType;if(e&&3!==s&&8!==s&&2!==s)return typeof e.getAttribute===i?x.prop(e,n,r):(1===s&&x.isXMLDoc(e)||(n=n.toLowerCase(),o=x.attrHooks[n]||(x.expr.match.bool.test(n)?X:z)),r===t?o&&"get"in o&&null!==(a=o.get(e,n))?a:(a=x.find.attr(e,n),null==a?t:a):null!==r?o&&"set"in o&&(a=o.set(e,r,n))!==t?a:(e.setAttribute(n,r+""),r):(x.removeAttr(e,n),t))},removeAttr:function(e,t){var n,r,i=0,o=t&&t.match(T);if(o&&1===e.nodeType)while(n=o[i++])r=x.propFix[n]||n,x.expr.match.bool.test(n)?K&&Q||!G.test(n)?e[r]=!1:e[x.camelCase("default-"+n)]=e[r]=!1:x.attr(e,n,""),e.removeAttribute(Q?n:r)},attrHooks:{type:{set:function(e,t){if(!x.support.radioValue&&"radio"===t&&x.nodeName(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}}},propFix:{"for":"htmlFor","class":"className"},prop:function(e,n,r){var i,o,a,s=e.nodeType;if(e&&3!==s&&8!==s&&2!==s)return a=1!==s||!x.isXMLDoc(e),a&&(n=x.propFix[n]||n,o=x.propHooks[n]),r!==t?o&&"set"in o&&(i=o.set(e,r,n))!==t?i:e[n]=r:o&&"get"in o&&null!==(i=o.get(e,n))?i:e[n]},propHooks:{tabIndex:{get:function(e){var t=x.find.attr(e,"tabindex");return t?parseInt(t,10):Y.test(e.nodeName)||J.test(e.nodeName)&&e.href?0:-1}}}}),X={set:function(e,t,n){return t===!1?x.removeAttr(e,n):K&&Q||!G.test(n)?e.setAttribute(!Q&&x.propFix[n]||n,n):e[x.camelCase("default-"+n)]=e[n]=!0,n}},x.each(x.expr.match.bool.source.match(/\w+/g),function(e,n){var r=x.expr.attrHandle[n]||x.find.attr;x.expr.attrHandle[n]=K&&Q||!G.test(n)?function(e,n,i){var o=x.expr.attrHandle[n],a=i?t:(x.expr.attrHandle[n]=t)!=r(e,n,i)?n.toLowerCase():null;return x.expr.attrHandle[n]=o,a}:function(e,n,r){return r?t:e[x.camelCase("default-"+n)]?n.toLowerCase():null}}),K&&Q||(x.attrHooks.value={set:function(e,n,r){return x.nodeName(e,"input")?(e.defaultValue=n,t):z&&z.set(e,n,r)}}),Q||(z={set:function(e,n,r){var i=e.getAttributeNode(r);return i||e.setAttributeNode(i=e.ownerDocument.createAttribute(r)),i.value=n+="","value"===r||n===e.getAttribute(r)?n:t}},x.expr.attrHandle.id=x.expr.attrHandle.name=x.expr.attrHandle.coords=function(e,n,r){var i;return r?t:(i=e.getAttributeNode(n))&&""!==i.value?i.value:null},x.valHooks.button={get:function(e,n){var r=e.getAttributeNode(n);return r&&r.specified?r.value:t},set:z.set},x.attrHooks.contenteditable={set:function(e,t,n){z.set(e,""===t?!1:t,n)}},x.each(["width","height"],function(e,n){x.attrHooks[n]={set:function(e,r){return""===r?(e.setAttribute(n,"auto"),r):t}}})),x.support.hrefNormalized||x.each(["href","src"],function(e,t){x.propHooks[t]={get:function(e){return e.getAttribute(t,4)}}}),x.support.style||(x.attrHooks.style={get:function(e){return e.style.cssText||t},set:function(e,t){return e.style.cssText=t+""}}),x.support.optSelected||(x.propHooks.selected={get:function(e){var t=e.parentNode;return t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex),null}}),x.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){x.propFix[this.toLowerCase()]=this}),x.support.enctype||(x.propFix.enctype="encoding"),x.each(["radio","checkbox"],function(){x.valHooks[this]={set:function(e,n){return x.isArray(n)?e.checked=x.inArray(x(e).val(),n)>=0:t}},x.support.checkOn||(x.valHooks[this].get=function(e){return null===e.getAttribute("value")?"on":e.value})});var Z=/^(?:input|select|textarea)$/i,et=/^key/,tt=/^(?:mouse|contextmenu)|click/,nt=/^(?:focusinfocus|focusoutblur)$/,rt=/^([^.]*)(?:\.(.+)|)$/;function it(){return!0}function ot(){return!1}function at(){try{return a.activeElement}catch(e){}}x.event={global:{},add:function(e,n,r,o,a){var s,l,u,c,p,f,d,h,g,m,y,v=x._data(e);if(v){r.handler&&(c=r,r=c.handler,a=c.selector),r.guid||(r.guid=x.guid++),(l=v.events)||(l=v.events={}),(f=v.handle)||(f=v.handle=function(e){return typeof x===i||e&&x.event.triggered===e.type?t:x.event.dispatch.apply(f.elem,arguments)},f.elem=e),n=(n||"").match(T)||[""],u=n.length;while(u--)s=rt.exec(n[u])||[],g=y=s[1],m=(s[2]||"").split(".").sort(),g&&(p=x.event.special[g]||{},g=(a?p.delegateType:p.bindType)||g,p=x.event.special[g]||{},d=x.extend({type:g,origType:y,data:o,handler:r,guid:r.guid,selector:a,needsContext:a&&x.expr.match.needsContext.test(a),namespace:m.join(".")},c),(h=l[g])||(h=l[g]=[],h.delegateCount=0,p.setup&&p.setup.call(e,o,m,f)!==!1||(e.addEventListener?e.addEventListener(g,f,!1):e.attachEvent&&e.attachEvent("on"+g,f))),p.add&&(p.add.call(e,d),d.handler.guid||(d.handler.guid=r.guid)),a?h.splice(h.delegateCount++,0,d):h.push(d),x.event.global[g]=!0);e=null}},remove:function(e,t,n,r,i){var o,a,s,l,u,c,p,f,d,h,g,m=x.hasData(e)&&x._data(e);if(m&&(c=m.events)){t=(t||"").match(T)||[""],u=t.length;while(u--)if(s=rt.exec(t[u])||[],d=g=s[1],h=(s[2]||"").split(".").sort(),d){p=x.event.special[d]||{},d=(r?p.delegateType:p.bindType)||d,f=c[d]||[],s=s[2]&&RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"),l=o=f.length;while(o--)a=f[o],!i&&g!==a.origType||n&&n.guid!==a.guid||s&&!s.test(a.namespace)||r&&r!==a.selector&&("**"!==r||!a.selector)||(f.splice(o,1),a.selector&&f.delegateCount--,p.remove&&p.remove.call(e,a));l&&!f.length&&(p.teardown&&p.teardown.call(e,h,m.handle)!==!1||x.removeEvent(e,d,m.handle),delete c[d])}else for(d in c)x.event.remove(e,d+t[u],n,r,!0);x.isEmptyObject(c)&&(delete m.handle,x._removeData(e,"events"))}},trigger:function(n,r,i,o){var s,l,u,c,p,f,d,h=[i||a],g=v.call(n,"type")?n.type:n,m=v.call(n,"namespace")?n.namespace.split("."):[];if(u=f=i=i||a,3!==i.nodeType&&8!==i.nodeType&&!nt.test(g+x.event.triggered)&&(g.indexOf(".")>=0&&(m=g.split("."),g=m.shift(),m.sort()),l=0>g.indexOf(":")&&"on"+g,n=n[x.expando]?n:new x.Event(g,"object"==typeof n&&n),n.isTrigger=o?2:3,n.namespace=m.join("."),n.namespace_re=n.namespace?RegExp("(^|\\.)"+m.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,n.result=t,n.target||(n.target=i),r=null==r?[n]:x.makeArray(r,[n]),p=x.event.special[g]||{},o||!p.trigger||p.trigger.apply(i,r)!==!1)){if(!o&&!p.noBubble&&!x.isWindow(i)){for(c=p.delegateType||g,nt.test(c+g)||(u=u.parentNode);u;u=u.parentNode)h.push(u),f=u;f===(i.ownerDocument||a)&&h.push(f.defaultView||f.parentWindow||e)}d=0;while((u=h[d++])&&!n.isPropagationStopped())n.type=d>1?c:p.bindType||g,s=(x._data(u,"events")||{})[n.type]&&x._data(u,"handle"),s&&s.apply(u,r),s=l&&u[l],s&&x.acceptData(u)&&s.apply&&s.apply(u,r)===!1&&n.preventDefault();if(n.type=g,!o&&!n.isDefaultPrevented()&&(!p._default||p._default.apply(h.pop(),r)===!1)&&x.acceptData(i)&&l&&i[g]&&!x.isWindow(i)){f=i[l],f&&(i[l]=null),x.event.triggered=g;try{i[g]()}catch(y){}x.event.triggered=t,f&&(i[l]=f)}return n.result}},dispatch:function(e){e=x.event.fix(e);var n,r,i,o,a,s=[],l=g.call(arguments),u=(x._data(this,"events")||{})[e.type]||[],c=x.event.special[e.type]||{};if(l[0]=e,e.delegateTarget=this,!c.preDispatch||c.preDispatch.call(this,e)!==!1){s=x.event.handlers.call(this,e,u),n=0;while((o=s[n++])&&!e.isPropagationStopped()){e.currentTarget=o.elem,a=0;while((i=o.handlers[a++])&&!e.isImmediatePropagationStopped())(!e.namespace_re||e.namespace_re.test(i.namespace))&&(e.handleObj=i,e.data=i.data,r=((x.event.special[i.origType]||{}).handle||i.handler).apply(o.elem,l),r!==t&&(e.result=r)===!1&&(e.preventDefault(),e.stopPropagation()))}return c.postDispatch&&c.postDispatch.call(this,e),e.result}},handlers:function(e,n){var r,i,o,a,s=[],l=n.delegateCount,u=e.target;if(l&&u.nodeType&&(!e.button||"click"!==e.type))for(;u!=this;u=u.parentNode||this)if(1===u.nodeType&&(u.disabled!==!0||"click"!==e.type)){for(o=[],a=0;l>a;a++)i=n[a],r=i.selector+" ",o[r]===t&&(o[r]=i.needsContext?x(r,this).index(u)>=0:x.find(r,this,null,[u]).length),o[r]&&o.push(i);o.length&&s.push({elem:u,handlers:o})}return n.length>l&&s.push({elem:this,handlers:n.slice(l)}),s},fix:function(e){if(e[x.expando])return e;var t,n,r,i=e.type,o=e,s=this.fixHooks[i];s||(this.fixHooks[i]=s=tt.test(i)?this.mouseHooks:et.test(i)?this.keyHooks:{}),r=s.props?this.props.concat(s.props):this.props,e=new x.Event(o),t=r.length;while(t--)n=r[t],e[n]=o[n];return e.target||(e.target=o.srcElement||a),3===e.target.nodeType&&(e.target=e.target.parentNode),e.metaKey=!!e.metaKey,s.filter?s.filter(e,o):e},props:"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(e,t){return null==e.which&&(e.which=null!=t.charCode?t.charCode:t.keyCode),e}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(e,n){var r,i,o,s=n.button,l=n.fromElement;return null==e.pageX&&null!=n.clientX&&(i=e.target.ownerDocument||a,o=i.documentElement,r=i.body,e.pageX=n.clientX+(o&&o.scrollLeft||r&&r.scrollLeft||0)-(o&&o.clientLeft||r&&r.clientLeft||0),e.pageY=n.clientY+(o&&o.scrollTop||r&&r.scrollTop||0)-(o&&o.clientTop||r&&r.clientTop||0)),!e.relatedTarget&&l&&(e.relatedTarget=l===e.target?n.toElement:l),e.which||s===t||(e.which=1&s?1:2&s?3:4&s?2:0),e}},special:{load:{noBubble:!0},focus:{trigger:function(){if(this!==at()&&this.focus)try{return this.focus(),!1}catch(e){}},delegateType:"focusin"},blur:{trigger:function(){return this===at()&&this.blur?(this.blur(),!1):t},delegateType:"focusout"},click:{trigger:function(){return x.nodeName(this,"input")&&"checkbox"===this.type&&this.click?(this.click(),!1):t},_default:function(e){return x.nodeName(e.target,"a")}},beforeunload:{postDispatch:function(e){e.result!==t&&(e.originalEvent.returnValue=e.result)}}},simulate:function(e,t,n,r){var i=x.extend(new x.Event,n,{type:e,isSimulated:!0,originalEvent:{}});r?x.event.trigger(i,null,t):x.event.dispatch.call(t,i),i.isDefaultPrevented()&&n.preventDefault()}},x.removeEvent=a.removeEventListener?function(e,t,n){e.removeEventListener&&e.removeEventListener(t,n,!1)}:function(e,t,n){var r="on"+t;e.detachEvent&&(typeof e[r]===i&&(e[r]=null),e.detachEvent(r,n))},x.Event=function(e,n){return this instanceof x.Event?(e&&e.type?(this.originalEvent=e,this.type=e.type,this.isDefaultPrevented=e.defaultPrevented||e.returnValue===!1||e.getPreventDefault&&e.getPreventDefault()?it:ot):this.type=e,n&&x.extend(this,n),this.timeStamp=e&&e.timeStamp||x.now(),this[x.expando]=!0,t):new x.Event(e,n)},x.Event.prototype={isDefaultPrevented:ot,isPropagationStopped:ot,isImmediatePropagationStopped:ot,preventDefault:function(){var e=this.originalEvent;this.isDefaultPrevented=it,e&&(e.preventDefault?e.preventDefault():e.returnValue=!1)},stopPropagation:function(){var e=this.originalEvent;this.isPropagationStopped=it,e&&(e.stopPropagation&&e.stopPropagation(),e.cancelBubble=!0)},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=it,this.stopPropagation()}},x.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(e,t){x.event.special[e]={delegateType:t,bindType:t,handle:function(e){var n,r=this,i=e.relatedTarget,o=e.handleObj;return(!i||i!==r&&!x.contains(r,i))&&(e.type=o.origType,n=o.handler.apply(this,arguments),e.type=t),n}}}),x.support.submitBubbles||(x.event.special.submit={setup:function(){return x.nodeName(this,"form")?!1:(x.event.add(this,"click._submit keypress._submit",function(e){var n=e.target,r=x.nodeName(n,"input")||x.nodeName(n,"button")?n.form:t;r&&!x._data(r,"submitBubbles")&&(x.event.add(r,"submit._submit",function(e){e._submit_bubble=!0}),x._data(r,"submitBubbles",!0))}),t)},postDispatch:function(e){e._submit_bubble&&(delete e._submit_bubble,this.parentNode&&!e.isTrigger&&x.event.simulate("submit",this.parentNode,e,!0))},teardown:function(){return x.nodeName(this,"form")?!1:(x.event.remove(this,"._submit"),t)}}),x.support.changeBubbles||(x.event.special.change={setup:function(){return Z.test(this.nodeName)?(("checkbox"===this.type||"radio"===this.type)&&(x.event.add(this,"propertychange._change",function(e){"checked"===e.originalEvent.propertyName&&(this._just_changed=!0)}),x.event.add(this,"click._change",function(e){this._just_changed&&!e.isTrigger&&(this._just_changed=!1),x.event.simulate("change",this,e,!0)})),!1):(x.event.add(this,"beforeactivate._change",function(e){var t=e.target;Z.test(t.nodeName)&&!x._data(t,"changeBubbles")&&(x.event.add(t,"change._change",function(e){!this.parentNode||e.isSimulated||e.isTrigger||x.event.simulate("change",this.parentNode,e,!0)}),x._data(t,"changeBubbles",!0))}),t)},handle:function(e){var n=e.target;return this!==n||e.isSimulated||e.isTrigger||"radio"!==n.type&&"checkbox"!==n.type?e.handleObj.handler.apply(this,arguments):t},teardown:function(){return x.event.remove(this,"._change"),!Z.test(this.nodeName)}}),x.support.focusinBubbles||x.each({focus:"focusin",blur:"focusout"},function(e,t){var n=0,r=function(e){x.event.simulate(t,e.target,x.event.fix(e),!0)};x.event.special[t]={setup:function(){0===n++&&a.addEventListener(e,r,!0)},teardown:function(){0===--n&&a.removeEventListener(e,r,!0)}}}),x.fn.extend({on:function(e,n,r,i,o){var a,s;if("object"==typeof e){"string"!=typeof n&&(r=r||n,n=t);for(a in e)this.on(a,n,r,e[a],o);return this}if(null==r&&null==i?(i=n,r=n=t):null==i&&("string"==typeof n?(i=r,r=t):(i=r,r=n,n=t)),i===!1)i=ot;else if(!i)return this;return 1===o&&(s=i,i=function(e){return x().off(e),s.apply(this,arguments)},i.guid=s.guid||(s.guid=x.guid++)),this.each(function(){x.event.add(this,e,i,r,n)})},one:function(e,t,n,r){return this.on(e,t,n,r,1)},off:function(e,n,r){var i,o;if(e&&e.preventDefault&&e.handleObj)return i=e.handleObj,x(e.delegateTarget).off(i.namespace?i.origType+"."+i.namespace:i.origType,i.selector,i.handler),this;if("object"==typeof e){for(o in e)this.off(o,n,e[o]);return this}return(n===!1||"function"==typeof n)&&(r=n,n=t),r===!1&&(r=ot),this.each(function(){x.event.remove(this,e,r,n)})},trigger:function(e,t){return this.each(function(){x.event.trigger(e,t,this)})},triggerHandler:function(e,n){var r=this[0];return r?x.event.trigger(e,n,r,!0):t}});var st=/^.[^:#\[\.,]*$/,lt=/^(?:parents|prev(?:Until|All))/,ut=x.expr.match.needsContext,ct={children:!0,contents:!0,next:!0,prev:!0};x.fn.extend({find:function(e){var t,n=[],r=this,i=r.length;if("string"!=typeof e)return this.pushStack(x(e).filter(function(){for(t=0;i>t;t++)if(x.contains(r[t],this))return!0}));for(t=0;i>t;t++)x.find(e,r[t],n);return n=this.pushStack(i>1?x.unique(n):n),n.selector=this.selector?this.selector+" "+e:e,n},has:function(e){var t,n=x(e,this),r=n.length;return this.filter(function(){for(t=0;r>t;t++)if(x.contains(this,n[t]))return!0})},not:function(e){return this.pushStack(ft(this,e||[],!0))},filter:function(e){return this.pushStack(ft(this,e||[],!1))},is:function(e){return!!ft(this,"string"==typeof e&&ut.test(e)?x(e):e||[],!1).length},closest:function(e,t){var n,r=0,i=this.length,o=[],a=ut.test(e)||"string"!=typeof e?x(e,t||this.context):0;for(;i>r;r++)for(n=this[r];n&&n!==t;n=n.parentNode)if(11>n.nodeType&&(a?a.index(n)>-1:1===n.nodeType&&x.find.matchesSelector(n,e))){n=o.push(n);break}return this.pushStack(o.length>1?x.unique(o):o)},index:function(e){return e?"string"==typeof e?x.inArray(this[0],x(e)):x.inArray(e.jquery?e[0]:e,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){var n="string"==typeof e?x(e,t):x.makeArray(e&&e.nodeType?[e]:e),r=x.merge(this.get(),n);return this.pushStack(x.unique(r))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}});function pt(e,t){do e=e[t];while(e&&1!==e.nodeType);return e}x.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return x.dir(e,"parentNode")},parentsUntil:function(e,t,n){return x.dir(e,"parentNode",n)},next:function(e){return pt(e,"nextSibling")},prev:function(e){return pt(e,"previousSibling")},nextAll:function(e){return x.dir(e,"nextSibling")},prevAll:function(e){return x.dir(e,"previousSibling")},nextUntil:function(e,t,n){return x.dir(e,"nextSibling",n)},prevUntil:function(e,t,n){return x.dir(e,"previousSibling",n)},siblings:function(e){return x.sibling((e.parentNode||{}).firstChild,e)},children:function(e){return x.sibling(e.firstChild)},contents:function(e){return x.nodeName(e,"iframe")?e.contentDocument||e.contentWindow.document:x.merge([],e.childNodes)}},function(e,t){x.fn[e]=function(n,r){var i=x.map(this,t,n);return"Until"!==e.slice(-5)&&(r=n),r&&"string"==typeof r&&(i=x.filter(r,i)),this.length>1&&(ct[e]||(i=x.unique(i)),lt.test(e)&&(i=i.reverse())),this.pushStack(i)}}),x.extend({filter:function(e,t,n){var r=t[0];return n&&(e=":not("+e+")"),1===t.length&&1===r.nodeType?x.find.matchesSelector(r,e)?[r]:[]:x.find.matches(e,x.grep(t,function(e){return 1===e.nodeType}))},dir:function(e,n,r){var i=[],o=e[n];while(o&&9!==o.nodeType&&(r===t||1!==o.nodeType||!x(o).is(r)))1===o.nodeType&&i.push(o),o=o[n];return i},sibling:function(e,t){var n=[];for(;e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n}});function ft(e,t,n){if(x.isFunction(t))return x.grep(e,function(e,r){return!!t.call(e,r,e)!==n});if(t.nodeType)return x.grep(e,function(e){return e===t!==n});if("string"==typeof t){if(st.test(t))return x.filter(t,e,n);t=x.filter(t,e)}return x.grep(e,function(e){return x.inArray(e,t)>=0!==n})}function dt(e){var t=ht.split("|"),n=e.createDocumentFragment();if(n.createElement)while(t.length)n.createElement(t.pop());return n}var ht="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",gt=/ jQuery\d+="(?:null|\d+)"/g,mt=RegExp("<(?:"+ht+")[\\s/>]","i"),yt=/^\s+/,vt=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,bt=/<([\w:]+)/,xt=/<tbody/i,wt=/<|&#?\w+;/,Tt=/<(?:script|style|link)/i,Ct=/^(?:checkbox|radio)$/i,Nt=/checked\s*(?:[^=]|=\s*.checked.)/i,kt=/^$|\/(?:java|ecma)script/i,Et=/^true\/(.*)/,St=/^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,At={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],area:[1,"<map>","</map>"],param:[1,"<object>","</object>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:x.support.htmlSerialize?[0,"",""]:[1,"X<div>","</div>"]},jt=dt(a),Dt=jt.appendChild(a.createElement("div"));At.optgroup=At.option,At.tbody=At.tfoot=At.colgroup=At.caption=At.thead,At.th=At.td,x.fn.extend({text:function(e){return x.access(this,function(e){return e===t?x.text(this):this.empty().append((this[0]&&this[0].ownerDocument||a).createTextNode(e))},null,e,arguments.length)},append:function(){return this.domManip(arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=Lt(this,e);t.appendChild(e)}})},prepend:function(){return this.domManip(arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=Lt(this,e);t.insertBefore(e,t.firstChild)}})},before:function(){return this.domManip(arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return this.domManip(arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},remove:function(e,t){var n,r=e?x.filter(e,this):this,i=0;for(;null!=(n=r[i]);i++)t||1!==n.nodeType||x.cleanData(Ft(n)),n.parentNode&&(t&&x.contains(n.ownerDocument,n)&&_t(Ft(n,"script")),n.parentNode.removeChild(n));return this},empty:function(){var e,t=0;for(;null!=(e=this[t]);t++){1===e.nodeType&&x.cleanData(Ft(e,!1));while(e.firstChild)e.removeChild(e.firstChild);e.options&&x.nodeName(e,"select")&&(e.options.length=0)}return this},clone:function(e,t){return e=null==e?!1:e,t=null==t?e:t,this.map(function(){return x.clone(this,e,t)})},html:function(e){return x.access(this,function(e){var n=this[0]||{},r=0,i=this.length;if(e===t)return 1===n.nodeType?n.innerHTML.replace(gt,""):t;if(!("string"!=typeof e||Tt.test(e)||!x.support.htmlSerialize&&mt.test(e)||!x.support.leadingWhitespace&&yt.test(e)||At[(bt.exec(e)||["",""])[1].toLowerCase()])){e=e.replace(vt,"<$1></$2>");try{for(;i>r;r++)n=this[r]||{},1===n.nodeType&&(x.cleanData(Ft(n,!1)),n.innerHTML=e);n=0}catch(o){}}n&&this.empty().append(e)},null,e,arguments.length)},replaceWith:function(){var e=x.map(this,function(e){return[e.nextSibling,e.parentNode]}),t=0;return this.domManip(arguments,function(n){var r=e[t++],i=e[t++];i&&(r&&r.parentNode!==i&&(r=this.nextSibling),x(this).remove(),i.insertBefore(n,r))},!0),t?this:this.remove()},detach:function(e){return this.remove(e,!0)},domManip:function(e,t,n){e=d.apply([],e);var r,i,o,a,s,l,u=0,c=this.length,p=this,f=c-1,h=e[0],g=x.isFunction(h);if(g||!(1>=c||"string"!=typeof h||x.support.checkClone)&&Nt.test(h))return this.each(function(r){var i=p.eq(r);g&&(e[0]=h.call(this,r,i.html())),i.domManip(e,t,n)});if(c&&(l=x.buildFragment(e,this[0].ownerDocument,!1,!n&&this),r=l.firstChild,1===l.childNodes.length&&(l=r),r)){for(a=x.map(Ft(l,"script"),Ht),o=a.length;c>u;u++)i=l,u!==f&&(i=x.clone(i,!0,!0),o&&x.merge(a,Ft(i,"script"))),t.call(this[u],i,u);if(o)for(s=a[a.length-1].ownerDocument,x.map(a,qt),u=0;o>u;u++)i=a[u],kt.test(i.type||"")&&!x._data(i,"globalEval")&&x.contains(s,i)&&(i.src?x._evalUrl(i.src):x.globalEval((i.text||i.textContent||i.innerHTML||"").replace(St,"")));l=r=null}return this}});function Lt(e,t){return x.nodeName(e,"table")&&x.nodeName(1===t.nodeType?t:t.firstChild,"tr")?e.getElementsByTagName("tbody")[0]||e.appendChild(e.ownerDocument.createElement("tbody")):e}function Ht(e){return e.type=(null!==x.find.attr(e,"type"))+"/"+e.type,e}function qt(e){var t=Et.exec(e.type);return t?e.type=t[1]:e.removeAttribute("type"),e}function _t(e,t){var n,r=0;for(;null!=(n=e[r]);r++)x._data(n,"globalEval",!t||x._data(t[r],"globalEval"))}function Mt(e,t){if(1===t.nodeType&&x.hasData(e)){var n,r,i,o=x._data(e),a=x._data(t,o),s=o.events;if(s){delete a.handle,a.events={};for(n in s)for(r=0,i=s[n].length;i>r;r++)x.event.add(t,n,s[n][r])}a.data&&(a.data=x.extend({},a.data))}}function Ot(e,t){var n,r,i;if(1===t.nodeType){if(n=t.nodeName.toLowerCase(),!x.support.noCloneEvent&&t[x.expando]){i=x._data(t);for(r in i.events)x.removeEvent(t,r,i.handle);t.removeAttribute(x.expando)}"script"===n&&t.text!==e.text?(Ht(t).text=e.text,qt(t)):"object"===n?(t.parentNode&&(t.outerHTML=e.outerHTML),x.support.html5Clone&&e.innerHTML&&!x.trim(t.innerHTML)&&(t.innerHTML=e.innerHTML)):"input"===n&&Ct.test(e.type)?(t.defaultChecked=t.checked=e.checked,t.value!==e.value&&(t.value=e.value)):"option"===n?t.defaultSelected=t.selected=e.defaultSelected:("input"===n||"textarea"===n)&&(t.defaultValue=e.defaultValue)}}x.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(e,t){x.fn[e]=function(e){var n,r=0,i=[],o=x(e),a=o.length-1;for(;a>=r;r++)n=r===a?this:this.clone(!0),x(o[r])[t](n),h.apply(i,n.get());return this.pushStack(i)}});function Ft(e,n){var r,o,a=0,s=typeof e.getElementsByTagName!==i?e.getElementsByTagName(n||"*"):typeof e.querySelectorAll!==i?e.querySelectorAll(n||"*"):t;if(!s)for(s=[],r=e.childNodes||e;null!=(o=r[a]);a++)!n||x.nodeName(o,n)?s.push(o):x.merge(s,Ft(o,n));return n===t||n&&x.nodeName(e,n)?x.merge([e],s):s}function Bt(e){Ct.test(e.type)&&(e.defaultChecked=e.checked)}x.extend({clone:function(e,t,n){var r,i,o,a,s,l=x.contains(e.ownerDocument,e);if(x.support.html5Clone||x.isXMLDoc(e)||!mt.test("<"+e.nodeName+">")?o=e.cloneNode(!0):(Dt.innerHTML=e.outerHTML,Dt.removeChild(o=Dt.firstChild)),!(x.support.noCloneEvent&&x.support.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||x.isXMLDoc(e)))for(r=Ft(o),s=Ft(e),a=0;null!=(i=s[a]);++a)r[a]&&Ot(i,r[a]);if(t)if(n)for(s=s||Ft(e),r=r||Ft(o),a=0;null!=(i=s[a]);a++)Mt(i,r[a]);else Mt(e,o);return r=Ft(o,"script"),r.length>0&&_t(r,!l&&Ft(e,"script")),r=s=i=null,o},buildFragment:function(e,t,n,r){var i,o,a,s,l,u,c,p=e.length,f=dt(t),d=[],h=0;for(;p>h;h++)if(o=e[h],o||0===o)if("object"===x.type(o))x.merge(d,o.nodeType?[o]:o);else if(wt.test(o)){s=s||f.appendChild(t.createElement("div")),l=(bt.exec(o)||["",""])[1].toLowerCase(),c=At[l]||At._default,s.innerHTML=c[1]+o.replace(vt,"<$1></$2>")+c[2],i=c[0];while(i--)s=s.lastChild;if(!x.support.leadingWhitespace&&yt.test(o)&&d.push(t.createTextNode(yt.exec(o)[0])),!x.support.tbody){o="table"!==l||xt.test(o)?"<table>"!==c[1]||xt.test(o)?0:s:s.firstChild,i=o&&o.childNodes.length;while(i--)x.nodeName(u=o.childNodes[i],"tbody")&&!u.childNodes.length&&o.removeChild(u)}x.merge(d,s.childNodes),s.textContent="";while(s.firstChild)s.removeChild(s.firstChild);s=f.lastChild}else d.push(t.createTextNode(o));s&&f.removeChild(s),x.support.appendChecked||x.grep(Ft(d,"input"),Bt),h=0;while(o=d[h++])if((!r||-1===x.inArray(o,r))&&(a=x.contains(o.ownerDocument,o),s=Ft(f.appendChild(o),"script"),a&&_t(s),n)){i=0;while(o=s[i++])kt.test(o.type||"")&&n.push(o)}return s=null,f},cleanData:function(e,t){var n,r,o,a,s=0,l=x.expando,u=x.cache,c=x.support.deleteExpando,f=x.event.special;for(;null!=(n=e[s]);s++)if((t||x.acceptData(n))&&(o=n[l],a=o&&u[o])){if(a.events)for(r in a.events)f[r]?x.event.remove(n,r):x.removeEvent(n,r,a.handle);
+u[o]&&(delete u[o],c?delete n[l]:typeof n.removeAttribute!==i?n.removeAttribute(l):n[l]=null,p.push(o))}},_evalUrl:function(e){return x.ajax({url:e,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0})}}),x.fn.extend({wrapAll:function(e){if(x.isFunction(e))return this.each(function(t){x(this).wrapAll(e.call(this,t))});if(this[0]){var t=x(e,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstChild&&1===e.firstChild.nodeType)e=e.firstChild;return e}).append(this)}return this},wrapInner:function(e){return x.isFunction(e)?this.each(function(t){x(this).wrapInner(e.call(this,t))}):this.each(function(){var t=x(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=x.isFunction(e);return this.each(function(n){x(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(){return this.parent().each(function(){x.nodeName(this,"body")||x(this).replaceWith(this.childNodes)}).end()}});var Pt,Rt,Wt,$t=/alpha\([^)]*\)/i,It=/opacity\s*=\s*([^)]*)/,zt=/^(top|right|bottom|left)$/,Xt=/^(none|table(?!-c[ea]).+)/,Ut=/^margin/,Vt=RegExp("^("+w+")(.*)$","i"),Yt=RegExp("^("+w+")(?!px)[a-z%]+$","i"),Jt=RegExp("^([+-])=("+w+")","i"),Gt={BODY:"block"},Qt={position:"absolute",visibility:"hidden",display:"block"},Kt={letterSpacing:0,fontWeight:400},Zt=["Top","Right","Bottom","Left"],en=["Webkit","O","Moz","ms"];function tn(e,t){if(t in e)return t;var n=t.charAt(0).toUpperCase()+t.slice(1),r=t,i=en.length;while(i--)if(t=en[i]+n,t in e)return t;return r}function nn(e,t){return e=t||e,"none"===x.css(e,"display")||!x.contains(e.ownerDocument,e)}function rn(e,t){var n,r,i,o=[],a=0,s=e.length;for(;s>a;a++)r=e[a],r.style&&(o[a]=x._data(r,"olddisplay"),n=r.style.display,t?(o[a]||"none"!==n||(r.style.display=""),""===r.style.display&&nn(r)&&(o[a]=x._data(r,"olddisplay",ln(r.nodeName)))):o[a]||(i=nn(r),(n&&"none"!==n||!i)&&x._data(r,"olddisplay",i?n:x.css(r,"display"))));for(a=0;s>a;a++)r=e[a],r.style&&(t&&"none"!==r.style.display&&""!==r.style.display||(r.style.display=t?o[a]||"":"none"));return e}x.fn.extend({css:function(e,n){return x.access(this,function(e,n,r){var i,o,a={},s=0;if(x.isArray(n)){for(o=Rt(e),i=n.length;i>s;s++)a[n[s]]=x.css(e,n[s],!1,o);return a}return r!==t?x.style(e,n,r):x.css(e,n)},e,n,arguments.length>1)},show:function(){return rn(this,!0)},hide:function(){return rn(this)},toggle:function(e){return"boolean"==typeof e?e?this.show():this.hide():this.each(function(){nn(this)?x(this).show():x(this).hide()})}}),x.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=Wt(e,"opacity");return""===n?"1":n}}}},cssNumber:{columnCount:!0,fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":x.support.cssFloat?"cssFloat":"styleFloat"},style:function(e,n,r,i){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var o,a,s,l=x.camelCase(n),u=e.style;if(n=x.cssProps[l]||(x.cssProps[l]=tn(u,l)),s=x.cssHooks[n]||x.cssHooks[l],r===t)return s&&"get"in s&&(o=s.get(e,!1,i))!==t?o:u[n];if(a=typeof r,"string"===a&&(o=Jt.exec(r))&&(r=(o[1]+1)*o[2]+parseFloat(x.css(e,n)),a="number"),!(null==r||"number"===a&&isNaN(r)||("number"!==a||x.cssNumber[l]||(r+="px"),x.support.clearCloneStyle||""!==r||0!==n.indexOf("background")||(u[n]="inherit"),s&&"set"in s&&(r=s.set(e,r,i))===t)))try{u[n]=r}catch(c){}}},css:function(e,n,r,i){var o,a,s,l=x.camelCase(n);return n=x.cssProps[l]||(x.cssProps[l]=tn(e.style,l)),s=x.cssHooks[n]||x.cssHooks[l],s&&"get"in s&&(a=s.get(e,!0,r)),a===t&&(a=Wt(e,n,i)),"normal"===a&&n in Kt&&(a=Kt[n]),""===r||r?(o=parseFloat(a),r===!0||x.isNumeric(o)?o||0:a):a}}),e.getComputedStyle?(Rt=function(t){return e.getComputedStyle(t,null)},Wt=function(e,n,r){var i,o,a,s=r||Rt(e),l=s?s.getPropertyValue(n)||s[n]:t,u=e.style;return s&&(""!==l||x.contains(e.ownerDocument,e)||(l=x.style(e,n)),Yt.test(l)&&Ut.test(n)&&(i=u.width,o=u.minWidth,a=u.maxWidth,u.minWidth=u.maxWidth=u.width=l,l=s.width,u.width=i,u.minWidth=o,u.maxWidth=a)),l}):a.documentElement.currentStyle&&(Rt=function(e){return e.currentStyle},Wt=function(e,n,r){var i,o,a,s=r||Rt(e),l=s?s[n]:t,u=e.style;return null==l&&u&&u[n]&&(l=u[n]),Yt.test(l)&&!zt.test(n)&&(i=u.left,o=e.runtimeStyle,a=o&&o.left,a&&(o.left=e.currentStyle.left),u.left="fontSize"===n?"1em":l,l=u.pixelLeft+"px",u.left=i,a&&(o.left=a)),""===l?"auto":l});function on(e,t,n){var r=Vt.exec(t);return r?Math.max(0,r[1]-(n||0))+(r[2]||"px"):t}function an(e,t,n,r,i){var o=n===(r?"border":"content")?4:"width"===t?1:0,a=0;for(;4>o;o+=2)"margin"===n&&(a+=x.css(e,n+Zt[o],!0,i)),r?("content"===n&&(a-=x.css(e,"padding"+Zt[o],!0,i)),"margin"!==n&&(a-=x.css(e,"border"+Zt[o]+"Width",!0,i))):(a+=x.css(e,"padding"+Zt[o],!0,i),"padding"!==n&&(a+=x.css(e,"border"+Zt[o]+"Width",!0,i)));return a}function sn(e,t,n){var r=!0,i="width"===t?e.offsetWidth:e.offsetHeight,o=Rt(e),a=x.support.boxSizing&&"border-box"===x.css(e,"boxSizing",!1,o);if(0>=i||null==i){if(i=Wt(e,t,o),(0>i||null==i)&&(i=e.style[t]),Yt.test(i))return i;r=a&&(x.support.boxSizingReliable||i===e.style[t]),i=parseFloat(i)||0}return i+an(e,t,n||(a?"border":"content"),r,o)+"px"}function ln(e){var t=a,n=Gt[e];return n||(n=un(e,t),"none"!==n&&n||(Pt=(Pt||x("<iframe frameborder='0' width='0' height='0'/>").css("cssText","display:block !important")).appendTo(t.documentElement),t=(Pt[0].contentWindow||Pt[0].contentDocument).document,t.write("<!doctype html><html><body>"),t.close(),n=un(e,t),Pt.detach()),Gt[e]=n),n}function un(e,t){var n=x(t.createElement(e)).appendTo(t.body),r=x.css(n[0],"display");return n.remove(),r}x.each(["height","width"],function(e,n){x.cssHooks[n]={get:function(e,r,i){return r?0===e.offsetWidth&&Xt.test(x.css(e,"display"))?x.swap(e,Qt,function(){return sn(e,n,i)}):sn(e,n,i):t},set:function(e,t,r){var i=r&&Rt(e);return on(e,t,r?an(e,n,r,x.support.boxSizing&&"border-box"===x.css(e,"boxSizing",!1,i),i):0)}}}),x.support.opacity||(x.cssHooks.opacity={get:function(e,t){return It.test((t&&e.currentStyle?e.currentStyle.filter:e.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":t?"1":""},set:function(e,t){var n=e.style,r=e.currentStyle,i=x.isNumeric(t)?"alpha(opacity="+100*t+")":"",o=r&&r.filter||n.filter||"";n.zoom=1,(t>=1||""===t)&&""===x.trim(o.replace($t,""))&&n.removeAttribute&&(n.removeAttribute("filter"),""===t||r&&!r.filter)||(n.filter=$t.test(o)?o.replace($t,i):o+" "+i)}}),x(function(){x.support.reliableMarginRight||(x.cssHooks.marginRight={get:function(e,n){return n?x.swap(e,{display:"inline-block"},Wt,[e,"marginRight"]):t}}),!x.support.pixelPosition&&x.fn.position&&x.each(["top","left"],function(e,n){x.cssHooks[n]={get:function(e,r){return r?(r=Wt(e,n),Yt.test(r)?x(e).position()[n]+"px":r):t}}})}),x.expr&&x.expr.filters&&(x.expr.filters.hidden=function(e){return 0>=e.offsetWidth&&0>=e.offsetHeight||!x.support.reliableHiddenOffsets&&"none"===(e.style&&e.style.display||x.css(e,"display"))},x.expr.filters.visible=function(e){return!x.expr.filters.hidden(e)}),x.each({margin:"",padding:"",border:"Width"},function(e,t){x.cssHooks[e+t]={expand:function(n){var r=0,i={},o="string"==typeof n?n.split(" "):[n];for(;4>r;r++)i[e+Zt[r]+t]=o[r]||o[r-2]||o[0];return i}},Ut.test(e)||(x.cssHooks[e+t].set=on)});var cn=/%20/g,pn=/\[\]$/,fn=/\r?\n/g,dn=/^(?:submit|button|image|reset|file)$/i,hn=/^(?:input|select|textarea|keygen)/i;x.fn.extend({serialize:function(){return x.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var e=x.prop(this,"elements");return e?x.makeArray(e):this}).filter(function(){var e=this.type;return this.name&&!x(this).is(":disabled")&&hn.test(this.nodeName)&&!dn.test(e)&&(this.checked||!Ct.test(e))}).map(function(e,t){var n=x(this).val();return null==n?null:x.isArray(n)?x.map(n,function(e){return{name:t.name,value:e.replace(fn,"\r\n")}}):{name:t.name,value:n.replace(fn,"\r\n")}}).get()}}),x.param=function(e,n){var r,i=[],o=function(e,t){t=x.isFunction(t)?t():null==t?"":t,i[i.length]=encodeURIComponent(e)+"="+encodeURIComponent(t)};if(n===t&&(n=x.ajaxSettings&&x.ajaxSettings.traditional),x.isArray(e)||e.jquery&&!x.isPlainObject(e))x.each(e,function(){o(this.name,this.value)});else for(r in e)gn(r,e[r],n,o);return i.join("&").replace(cn,"+")};function gn(e,t,n,r){var i;if(x.isArray(t))x.each(t,function(t,i){n||pn.test(e)?r(e,i):gn(e+"["+("object"==typeof i?t:"")+"]",i,n,r)});else if(n||"object"!==x.type(t))r(e,t);else for(i in t)gn(e+"["+i+"]",t[i],n,r)}x.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(e,t){x.fn[t]=function(e,n){return arguments.length>0?this.on(t,null,e,n):this.trigger(t)}}),x.fn.extend({hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)},bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)}});var mn,yn,vn=x.now(),bn=/\?/,xn=/#.*$/,wn=/([?&])_=[^&]*/,Tn=/^(.*?):[ \t]*([^\r\n]*)\r?$/gm,Cn=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Nn=/^(?:GET|HEAD)$/,kn=/^\/\//,En=/^([\w.+-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,Sn=x.fn.load,An={},jn={},Dn="*/".concat("*");try{yn=o.href}catch(Ln){yn=a.createElement("a"),yn.href="",yn=yn.href}mn=En.exec(yn.toLowerCase())||[];function Hn(e){return function(t,n){"string"!=typeof t&&(n=t,t="*");var r,i=0,o=t.toLowerCase().match(T)||[];if(x.isFunction(n))while(r=o[i++])"+"===r[0]?(r=r.slice(1)||"*",(e[r]=e[r]||[]).unshift(n)):(e[r]=e[r]||[]).push(n)}}function qn(e,n,r,i){var o={},a=e===jn;function s(l){var u;return o[l]=!0,x.each(e[l]||[],function(e,l){var c=l(n,r,i);return"string"!=typeof c||a||o[c]?a?!(u=c):t:(n.dataTypes.unshift(c),s(c),!1)}),u}return s(n.dataTypes[0])||!o["*"]&&s("*")}function _n(e,n){var r,i,o=x.ajaxSettings.flatOptions||{};for(i in n)n[i]!==t&&((o[i]?e:r||(r={}))[i]=n[i]);return r&&x.extend(!0,e,r),e}x.fn.load=function(e,n,r){if("string"!=typeof e&&Sn)return Sn.apply(this,arguments);var i,o,a,s=this,l=e.indexOf(" ");return l>=0&&(i=e.slice(l,e.length),e=e.slice(0,l)),x.isFunction(n)?(r=n,n=t):n&&"object"==typeof n&&(a="POST"),s.length>0&&x.ajax({url:e,type:a,dataType:"html",data:n}).done(function(e){o=arguments,s.html(i?x("<div>").append(x.parseHTML(e)).find(i):e)}).complete(r&&function(e,t){s.each(r,o||[e.responseText,t,e])}),this},x.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){x.fn[t]=function(e){return this.on(t,e)}}),x.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:yn,type:"GET",isLocal:Cn.test(mn[1]),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":Dn,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":x.parseJSON,"text xml":x.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(e,t){return t?_n(_n(e,x.ajaxSettings),t):_n(x.ajaxSettings,e)},ajaxPrefilter:Hn(An),ajaxTransport:Hn(jn),ajax:function(e,n){"object"==typeof e&&(n=e,e=t),n=n||{};var r,i,o,a,s,l,u,c,p=x.ajaxSetup({},n),f=p.context||p,d=p.context&&(f.nodeType||f.jquery)?x(f):x.event,h=x.Deferred(),g=x.Callbacks("once memory"),m=p.statusCode||{},y={},v={},b=0,w="canceled",C={readyState:0,getResponseHeader:function(e){var t;if(2===b){if(!c){c={};while(t=Tn.exec(a))c[t[1].toLowerCase()]=t[2]}t=c[e.toLowerCase()]}return null==t?null:t},getAllResponseHeaders:function(){return 2===b?a:null},setRequestHeader:function(e,t){var n=e.toLowerCase();return b||(e=v[n]=v[n]||e,y[e]=t),this},overrideMimeType:function(e){return b||(p.mimeType=e),this},statusCode:function(e){var t;if(e)if(2>b)for(t in e)m[t]=[m[t],e[t]];else C.always(e[C.status]);return this},abort:function(e){var t=e||w;return u&&u.abort(t),k(0,t),this}};if(h.promise(C).complete=g.add,C.success=C.done,C.error=C.fail,p.url=((e||p.url||yn)+"").replace(xn,"").replace(kn,mn[1]+"//"),p.type=n.method||n.type||p.method||p.type,p.dataTypes=x.trim(p.dataType||"*").toLowerCase().match(T)||[""],null==p.crossDomain&&(r=En.exec(p.url.toLowerCase()),p.crossDomain=!(!r||r[1]===mn[1]&&r[2]===mn[2]&&(r[3]||("http:"===r[1]?"80":"443"))===(mn[3]||("http:"===mn[1]?"80":"443")))),p.data&&p.processData&&"string"!=typeof p.data&&(p.data=x.param(p.data,p.traditional)),qn(An,p,n,C),2===b)return C;l=p.global,l&&0===x.active++&&x.event.trigger("ajaxStart"),p.type=p.type.toUpperCase(),p.hasContent=!Nn.test(p.type),o=p.url,p.hasContent||(p.data&&(o=p.url+=(bn.test(o)?"&":"?")+p.data,delete p.data),p.cache===!1&&(p.url=wn.test(o)?o.replace(wn,"$1_="+vn++):o+(bn.test(o)?"&":"?")+"_="+vn++)),p.ifModified&&(x.lastModified[o]&&C.setRequestHeader("If-Modified-Since",x.lastModified[o]),x.etag[o]&&C.setRequestHeader("If-None-Match",x.etag[o])),(p.data&&p.hasContent&&p.contentType!==!1||n.contentType)&&C.setRequestHeader("Content-Type",p.contentType),C.setRequestHeader("Accept",p.dataTypes[0]&&p.accepts[p.dataTypes[0]]?p.accepts[p.dataTypes[0]]+("*"!==p.dataTypes[0]?", "+Dn+"; q=0.01":""):p.accepts["*"]);for(i in p.headers)C.setRequestHeader(i,p.headers[i]);if(p.beforeSend&&(p.beforeSend.call(f,C,p)===!1||2===b))return C.abort();w="abort";for(i in{success:1,error:1,complete:1})C[i](p[i]);if(u=qn(jn,p,n,C)){C.readyState=1,l&&d.trigger("ajaxSend",[C,p]),p.async&&p.timeout>0&&(s=setTimeout(function(){C.abort("timeout")},p.timeout));try{b=1,u.send(y,k)}catch(N){if(!(2>b))throw N;k(-1,N)}}else k(-1,"No Transport");function k(e,n,r,i){var c,y,v,w,T,N=n;2!==b&&(b=2,s&&clearTimeout(s),u=t,a=i||"",C.readyState=e>0?4:0,c=e>=200&&300>e||304===e,r&&(w=Mn(p,C,r)),w=On(p,w,C,c),c?(p.ifModified&&(T=C.getResponseHeader("Last-Modified"),T&&(x.lastModified[o]=T),T=C.getResponseHeader("etag"),T&&(x.etag[o]=T)),204===e||"HEAD"===p.type?N="nocontent":304===e?N="notmodified":(N=w.state,y=w.data,v=w.error,c=!v)):(v=N,(e||!N)&&(N="error",0>e&&(e=0))),C.status=e,C.statusText=(n||N)+"",c?h.resolveWith(f,[y,N,C]):h.rejectWith(f,[C,N,v]),C.statusCode(m),m=t,l&&d.trigger(c?"ajaxSuccess":"ajaxError",[C,p,c?y:v]),g.fireWith(f,[C,N]),l&&(d.trigger("ajaxComplete",[C,p]),--x.active||x.event.trigger("ajaxStop")))}return C},getJSON:function(e,t,n){return x.get(e,t,n,"json")},getScript:function(e,n){return x.get(e,t,n,"script")}}),x.each(["get","post"],function(e,n){x[n]=function(e,r,i,o){return x.isFunction(r)&&(o=o||i,i=r,r=t),x.ajax({url:e,type:n,dataType:o,data:r,success:i})}});function Mn(e,n,r){var i,o,a,s,l=e.contents,u=e.dataTypes;while("*"===u[0])u.shift(),o===t&&(o=e.mimeType||n.getResponseHeader("Content-Type"));if(o)for(s in l)if(l[s]&&l[s].test(o)){u.unshift(s);break}if(u[0]in r)a=u[0];else{for(s in r){if(!u[0]||e.converters[s+" "+u[0]]){a=s;break}i||(i=s)}a=a||i}return a?(a!==u[0]&&u.unshift(a),r[a]):t}function On(e,t,n,r){var i,o,a,s,l,u={},c=e.dataTypes.slice();if(c[1])for(a in e.converters)u[a.toLowerCase()]=e.converters[a];o=c.shift();while(o)if(e.responseFields[o]&&(n[e.responseFields[o]]=t),!l&&r&&e.dataFilter&&(t=e.dataFilter(t,e.dataType)),l=o,o=c.shift())if("*"===o)o=l;else if("*"!==l&&l!==o){if(a=u[l+" "+o]||u["* "+o],!a)for(i in u)if(s=i.split(" "),s[1]===o&&(a=u[l+" "+s[0]]||u["* "+s[0]])){a===!0?a=u[i]:u[i]!==!0&&(o=s[0],c.unshift(s[1]));break}if(a!==!0)if(a&&e["throws"])t=a(t);else try{t=a(t)}catch(p){return{state:"parsererror",error:a?p:"No conversion from "+l+" to "+o}}}return{state:"success",data:t}}x.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/(?:java|ecma)script/},converters:{"text script":function(e){return x.globalEval(e),e}}}),x.ajaxPrefilter("script",function(e){e.cache===t&&(e.cache=!1),e.crossDomain&&(e.type="GET",e.global=!1)}),x.ajaxTransport("script",function(e){if(e.crossDomain){var n,r=a.head||x("head")[0]||a.documentElement;return{send:function(t,i){n=a.createElement("script"),n.async=!0,e.scriptCharset&&(n.charset=e.scriptCharset),n.src=e.url,n.onload=n.onreadystatechange=function(e,t){(t||!n.readyState||/loaded|complete/.test(n.readyState))&&(n.onload=n.onreadystatechange=null,n.parentNode&&n.parentNode.removeChild(n),n=null,t||i(200,"success"))},r.insertBefore(n,r.firstChild)},abort:function(){n&&n.onload(t,!0)}}}});var Fn=[],Bn=/(=)\?(?=&|$)|\?\?/;x.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Fn.pop()||x.expando+"_"+vn++;return this[e]=!0,e}}),x.ajaxPrefilter("json jsonp",function(n,r,i){var o,a,s,l=n.jsonp!==!1&&(Bn.test(n.url)?"url":"string"==typeof n.data&&!(n.contentType||"").indexOf("application/x-www-form-urlencoded")&&Bn.test(n.data)&&"data");return l||"jsonp"===n.dataTypes[0]?(o=n.jsonpCallback=x.isFunction(n.jsonpCallback)?n.jsonpCallback():n.jsonpCallback,l?n[l]=n[l].replace(Bn,"$1"+o):n.jsonp!==!1&&(n.url+=(bn.test(n.url)?"&":"?")+n.jsonp+"="+o),n.converters["script json"]=function(){return s||x.error(o+" was not called"),s[0]},n.dataTypes[0]="json",a=e[o],e[o]=function(){s=arguments},i.always(function(){e[o]=a,n[o]&&(n.jsonpCallback=r.jsonpCallback,Fn.push(o)),s&&x.isFunction(a)&&a(s[0]),s=a=t}),"script"):t});var Pn,Rn,Wn=0,$n=e.ActiveXObject&&function(){var e;for(e in Pn)Pn[e](t,!0)};function In(){try{return new e.XMLHttpRequest}catch(t){}}function zn(){try{return new e.ActiveXObject("Microsoft.XMLHTTP")}catch(t){}}x.ajaxSettings.xhr=e.ActiveXObject?function(){return!this.isLocal&&In()||zn()}:In,Rn=x.ajaxSettings.xhr(),x.support.cors=!!Rn&&"withCredentials"in Rn,Rn=x.support.ajax=!!Rn,Rn&&x.ajaxTransport(function(n){if(!n.crossDomain||x.support.cors){var r;return{send:function(i,o){var a,s,l=n.xhr();if(n.username?l.open(n.type,n.url,n.async,n.username,n.password):l.open(n.type,n.url,n.async),n.xhrFields)for(s in n.xhrFields)l[s]=n.xhrFields[s];n.mimeType&&l.overrideMimeType&&l.overrideMimeType(n.mimeType),n.crossDomain||i["X-Requested-With"]||(i["X-Requested-With"]="XMLHttpRequest");try{for(s in i)l.setRequestHeader(s,i[s])}catch(u){}l.send(n.hasContent&&n.data||null),r=function(e,i){var s,u,c,p;try{if(r&&(i||4===l.readyState))if(r=t,a&&(l.onreadystatechange=x.noop,$n&&delete Pn[a]),i)4!==l.readyState&&l.abort();else{p={},s=l.status,u=l.getAllResponseHeaders(),"string"==typeof l.responseText&&(p.text=l.responseText);try{c=l.statusText}catch(f){c=""}s||!n.isLocal||n.crossDomain?1223===s&&(s=204):s=p.text?200:404}}catch(d){i||o(-1,d)}p&&o(s,c,p,u)},n.async?4===l.readyState?setTimeout(r):(a=++Wn,$n&&(Pn||(Pn={},x(e).unload($n)),Pn[a]=r),l.onreadystatechange=r):r()},abort:function(){r&&r(t,!0)}}}});var Xn,Un,Vn=/^(?:toggle|show|hide)$/,Yn=RegExp("^(?:([+-])=|)("+w+")([a-z%]*)$","i"),Jn=/queueHooks$/,Gn=[nr],Qn={"*":[function(e,t){var n=this.createTween(e,t),r=n.cur(),i=Yn.exec(t),o=i&&i[3]||(x.cssNumber[e]?"":"px"),a=(x.cssNumber[e]||"px"!==o&&+r)&&Yn.exec(x.css(n.elem,e)),s=1,l=20;if(a&&a[3]!==o){o=o||a[3],i=i||[],a=+r||1;do s=s||".5",a/=s,x.style(n.elem,e,a+o);while(s!==(s=n.cur()/r)&&1!==s&&--l)}return i&&(a=n.start=+a||+r||0,n.unit=o,n.end=i[1]?a+(i[1]+1)*i[2]:+i[2]),n}]};function Kn(){return setTimeout(function(){Xn=t}),Xn=x.now()}function Zn(e,t,n){var r,i=(Qn[t]||[]).concat(Qn["*"]),o=0,a=i.length;for(;a>o;o++)if(r=i[o].call(n,t,e))return r}function er(e,t,n){var r,i,o=0,a=Gn.length,s=x.Deferred().always(function(){delete l.elem}),l=function(){if(i)return!1;var t=Xn||Kn(),n=Math.max(0,u.startTime+u.duration-t),r=n/u.duration||0,o=1-r,a=0,l=u.tweens.length;for(;l>a;a++)u.tweens[a].run(o);return s.notifyWith(e,[u,o,n]),1>o&&l?n:(s.resolveWith(e,[u]),!1)},u=s.promise({elem:e,props:x.extend({},t),opts:x.extend(!0,{specialEasing:{}},n),originalProperties:t,originalOptions:n,startTime:Xn||Kn(),duration:n.duration,tweens:[],createTween:function(t,n){var r=x.Tween(e,u.opts,t,n,u.opts.specialEasing[t]||u.opts.easing);return u.tweens.push(r),r},stop:function(t){var n=0,r=t?u.tweens.length:0;if(i)return this;for(i=!0;r>n;n++)u.tweens[n].run(1);return t?s.resolveWith(e,[u,t]):s.rejectWith(e,[u,t]),this}}),c=u.props;for(tr(c,u.opts.specialEasing);a>o;o++)if(r=Gn[o].call(u,e,c,u.opts))return r;return x.map(c,Zn,u),x.isFunction(u.opts.start)&&u.opts.start.call(e,u),x.fx.timer(x.extend(l,{elem:e,anim:u,queue:u.opts.queue})),u.progress(u.opts.progress).done(u.opts.done,u.opts.complete).fail(u.opts.fail).always(u.opts.always)}function tr(e,t){var n,r,i,o,a;for(n in e)if(r=x.camelCase(n),i=t[r],o=e[n],x.isArray(o)&&(i=o[1],o=e[n]=o[0]),n!==r&&(e[r]=o,delete e[n]),a=x.cssHooks[r],a&&"expand"in a){o=a.expand(o),delete e[r];for(n in o)n in e||(e[n]=o[n],t[n]=i)}else t[r]=i}x.Animation=x.extend(er,{tweener:function(e,t){x.isFunction(e)?(t=e,e=["*"]):e=e.split(" ");var n,r=0,i=e.length;for(;i>r;r++)n=e[r],Qn[n]=Qn[n]||[],Qn[n].unshift(t)},prefilter:function(e,t){t?Gn.unshift(e):Gn.push(e)}});function nr(e,t,n){var r,i,o,a,s,l,u=this,c={},p=e.style,f=e.nodeType&&nn(e),d=x._data(e,"fxshow");n.queue||(s=x._queueHooks(e,"fx"),null==s.unqueued&&(s.unqueued=0,l=s.empty.fire,s.empty.fire=function(){s.unqueued||l()}),s.unqueued++,u.always(function(){u.always(function(){s.unqueued--,x.queue(e,"fx").length||s.empty.fire()})})),1===e.nodeType&&("height"in t||"width"in t)&&(n.overflow=[p.overflow,p.overflowX,p.overflowY],"inline"===x.css(e,"display")&&"none"===x.css(e,"float")&&(x.support.inlineBlockNeedsLayout&&"inline"!==ln(e.nodeName)?p.zoom=1:p.display="inline-block")),n.overflow&&(p.overflow="hidden",x.support.shrinkWrapBlocks||u.always(function(){p.overflow=n.overflow[0],p.overflowX=n.overflow[1],p.overflowY=n.overflow[2]}));for(r in t)if(i=t[r],Vn.exec(i)){if(delete t[r],o=o||"toggle"===i,i===(f?"hide":"show"))continue;c[r]=d&&d[r]||x.style(e,r)}if(!x.isEmptyObject(c)){d?"hidden"in d&&(f=d.hidden):d=x._data(e,"fxshow",{}),o&&(d.hidden=!f),f?x(e).show():u.done(function(){x(e).hide()}),u.done(function(){var t;x._removeData(e,"fxshow");for(t in c)x.style(e,t,c[t])});for(r in c)a=Zn(f?d[r]:0,r,u),r in d||(d[r]=a.start,f&&(a.end=a.start,a.start="width"===r||"height"===r?1:0))}}function rr(e,t,n,r,i){return new rr.prototype.init(e,t,n,r,i)}x.Tween=rr,rr.prototype={constructor:rr,init:function(e,t,n,r,i,o){this.elem=e,this.prop=n,this.easing=i||"swing",this.options=t,this.start=this.now=this.cur(),this.end=r,this.unit=o||(x.cssNumber[n]?"":"px")},cur:function(){var e=rr.propHooks[this.prop];return e&&e.get?e.get(this):rr.propHooks._default.get(this)},run:function(e){var t,n=rr.propHooks[this.prop];return this.pos=t=this.options.duration?x.easing[this.easing](e,this.options.duration*e,0,1,this.options.duration):e,this.now=(this.end-this.start)*t+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),n&&n.set?n.set(this):rr.propHooks._default.set(this),this}},rr.prototype.init.prototype=rr.prototype,rr.propHooks={_default:{get:function(e){var t;return null==e.elem[e.prop]||e.elem.style&&null!=e.elem.style[e.prop]?(t=x.css(e.elem,e.prop,""),t&&"auto"!==t?t:0):e.elem[e.prop]},set:function(e){x.fx.step[e.prop]?x.fx.step[e.prop](e):e.elem.style&&(null!=e.elem.style[x.cssProps[e.prop]]||x.cssHooks[e.prop])?x.style(e.elem,e.prop,e.now+e.unit):e.elem[e.prop]=e.now}}},rr.propHooks.scrollTop=rr.propHooks.scrollLeft={set:function(e){e.elem.nodeType&&e.elem.parentNode&&(e.elem[e.prop]=e.now)}},x.each(["toggle","show","hide"],function(e,t){var n=x.fn[t];x.fn[t]=function(e,r,i){return null==e||"boolean"==typeof e?n.apply(this,arguments):this.animate(ir(t,!0),e,r,i)}}),x.fn.extend({fadeTo:function(e,t,n,r){return this.filter(nn).css("opacity",0).show().end().animate({opacity:t},e,n,r)},animate:function(e,t,n,r){var i=x.isEmptyObject(e),o=x.speed(t,n,r),a=function(){var t=er(this,x.extend({},e),o);(i||x._data(this,"finish"))&&t.stop(!0)};return a.finish=a,i||o.queue===!1?this.each(a):this.queue(o.queue,a)},stop:function(e,n,r){var i=function(e){var t=e.stop;delete e.stop,t(r)};return"string"!=typeof e&&(r=n,n=e,e=t),n&&e!==!1&&this.queue(e||"fx",[]),this.each(function(){var t=!0,n=null!=e&&e+"queueHooks",o=x.timers,a=x._data(this);if(n)a[n]&&a[n].stop&&i(a[n]);else for(n in a)a[n]&&a[n].stop&&Jn.test(n)&&i(a[n]);for(n=o.length;n--;)o[n].elem!==this||null!=e&&o[n].queue!==e||(o[n].anim.stop(r),t=!1,o.splice(n,1));(t||!r)&&x.dequeue(this,e)})},finish:function(e){return e!==!1&&(e=e||"fx"),this.each(function(){var t,n=x._data(this),r=n[e+"queue"],i=n[e+"queueHooks"],o=x.timers,a=r?r.length:0;for(n.finish=!0,x.queue(this,e,[]),i&&i.stop&&i.stop.call(this,!0),t=o.length;t--;)o[t].elem===this&&o[t].queue===e&&(o[t].anim.stop(!0),o.splice(t,1));for(t=0;a>t;t++)r[t]&&r[t].finish&&r[t].finish.call(this);delete n.finish})}});function ir(e,t){var n,r={height:e},i=0;for(t=t?1:0;4>i;i+=2-t)n=Zt[i],r["margin"+n]=r["padding"+n]=e;return t&&(r.opacity=r.width=e),r}x.each({slideDown:ir("show"),slideUp:ir("hide"),slideToggle:ir("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(e,t){x.fn[e]=function(e,n,r){return this.animate(t,e,n,r)}}),x.speed=function(e,t,n){var r=e&&"object"==typeof e?x.extend({},e):{complete:n||!n&&t||x.isFunction(e)&&e,duration:e,easing:n&&t||t&&!x.isFunction(t)&&t};return r.duration=x.fx.off?0:"number"==typeof r.duration?r.duration:r.duration in x.fx.speeds?x.fx.speeds[r.duration]:x.fx.speeds._default,(null==r.queue||r.queue===!0)&&(r.queue="fx"),r.old=r.complete,r.complete=function(){x.isFunction(r.old)&&r.old.call(this),r.queue&&x.dequeue(this,r.queue)},r},x.easing={linear:function(e){return e},swing:function(e){return.5-Math.cos(e*Math.PI)/2}},x.timers=[],x.fx=rr.prototype.init,x.fx.tick=function(){var e,n=x.timers,r=0;for(Xn=x.now();n.length>r;r++)e=n[r],e()||n[r]!==e||n.splice(r--,1);n.length||x.fx.stop(),Xn=t},x.fx.timer=function(e){e()&&x.timers.push(e)&&x.fx.start()},x.fx.interval=13,x.fx.start=function(){Un||(Un=setInterval(x.fx.tick,x.fx.interval))},x.fx.stop=function(){clearInterval(Un),Un=null},x.fx.speeds={slow:600,fast:200,_default:400},x.fx.step={},x.expr&&x.expr.filters&&(x.expr.filters.animated=function(e){return x.grep(x.timers,function(t){return e===t.elem}).length}),x.fn.offset=function(e){if(arguments.length)return e===t?this:this.each(function(t){x.offset.setOffset(this,e,t)});var n,r,o={top:0,left:0},a=this[0],s=a&&a.ownerDocument;if(s)return n=s.documentElement,x.contains(n,a)?(typeof a.getBoundingClientRect!==i&&(o=a.getBoundingClientRect()),r=or(s),{top:o.top+(r.pageYOffset||n.scrollTop)-(n.clientTop||0),left:o.left+(r.pageXOffset||n.scrollLeft)-(n.clientLeft||0)}):o},x.offset={setOffset:function(e,t,n){var r=x.css(e,"position");"static"===r&&(e.style.position="relative");var i=x(e),o=i.offset(),a=x.css(e,"top"),s=x.css(e,"left"),l=("absolute"===r||"fixed"===r)&&x.inArray("auto",[a,s])>-1,u={},c={},p,f;l?(c=i.position(),p=c.top,f=c.left):(p=parseFloat(a)||0,f=parseFloat(s)||0),x.isFunction(t)&&(t=t.call(e,n,o)),null!=t.top&&(u.top=t.top-o.top+p),null!=t.left&&(u.left=t.left-o.left+f),"using"in t?t.using.call(e,u):i.css(u)}},x.fn.extend({position:function(){if(this[0]){var e,t,n={top:0,left:0},r=this[0];return"fixed"===x.css(r,"position")?t=r.getBoundingClientRect():(e=this.offsetParent(),t=this.offset(),x.nodeName(e[0],"html")||(n=e.offset()),n.top+=x.css(e[0],"borderTopWidth",!0),n.left+=x.css(e[0],"borderLeftWidth",!0)),{top:t.top-n.top-x.css(r,"marginTop",!0),left:t.left-n.left-x.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent||s;while(e&&!x.nodeName(e,"html")&&"static"===x.css(e,"position"))e=e.offsetParent;return e||s})}}),x.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(e,n){var r=/Y/.test(n);x.fn[e]=function(i){return x.access(this,function(e,i,o){var a=or(e);return o===t?a?n in a?a[n]:a.document.documentElement[i]:e[i]:(a?a.scrollTo(r?x(a).scrollLeft():o,r?o:x(a).scrollTop()):e[i]=o,t)},e,i,arguments.length,null)}});function or(e){return x.isWindow(e)?e:9===e.nodeType?e.defaultView||e.parentWindow:!1}x.each({Height:"height",Width:"width"},function(e,n){x.each({padding:"inner"+e,content:n,"":"outer"+e},function(r,i){x.fn[i]=function(i,o){var a=arguments.length&&(r||"boolean"!=typeof i),s=r||(i===!0||o===!0?"margin":"border");return x.access(this,function(n,r,i){var o;return x.isWindow(n)?n.document.documentElement["client"+e]:9===n.nodeType?(o=n.documentElement,Math.max(n.body["scroll"+e],o["scroll"+e],n.body["offset"+e],o["offset"+e],o["client"+e])):i===t?x.css(n,r,s):x.style(n,r,i,s)},n,a?i:t,a,null)}})}),x.fn.size=function(){return this.length},x.fn.andSelf=x.fn.addBack,"object"==typeof module&&module&&"object"==typeof module.exports?module.exports=x:(e.jQuery=e.$=x,"function"==typeof define&&define.amd&&define("jquery",[],function(){return x}))})(window);
Binary file jalview/jswingreader-0.3.jar has changed
Binary file jalview/log4j-1.2.8.jar has changed
Binary file jalview/mail.jar has changed
Binary file jalview/miglayout-4.0-swing.jar has changed
Binary file jalview/min-jaba-client-2.0.jar has changed
Binary file jalview/regex.jar has changed
Binary file jalview/saaj.jar has changed
Binary file jalview/spring-core-3.0.5.RELEASE.jar has changed
Binary file jalview/spring-web-3.0.5.RELEASE.jar has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jalview/tool_dependencies.xml	Sun Sep 22 19:13:07 2013 -0400
@@ -0,0 +1,98 @@
+<tool_dependency>
+    <package name="vref_python" version="1.0">
+        <install version="1.0">
+            <actions>
+                <action type="setup_virtualenv"> plumbum==1.3.0
+                                                 numpy==1.7.1
+                                                 biopython==1.61
+                                                 HTSeq==0.5.4
+                                                 pysam==0.7.5
+                                                 matplotlib==1.3.0
+                                                 ftputil==2.2.3</action>
+            </actions>
+        </install>
+    </package>
+    <package name="samtools" version="0.1.19">
+        <install>
+            <actions>
+                <action type="download_by_url">http://sourceforge.net/projects/samtools/files/samtools/0.1.19/samtools-0.1.19.tar.bz2</action>
+                <action type="shell_command">make</action>
+                <action type="move_file">
+                    <source>samtools</source>
+                    <destination>$INSTALL_DIR/bin</destination>
+                </action>
+                <action type="set_environment">
+                    <environment_variable name="PATH" action="prepend_to">$INSTALL_DIR/bin</environment_variable>
+                </action>
+            </actions>
+        </install>
+    </package>
+    <package name="bwa" version="0.7.4">
+        <install version="1.0">
+            <actions>
+                <action type="download_by_url">http://sourceforge.net/projects/bio-bwa/files/bwa-0.7.4.tar.bz2 </action>
+                <action type="shell_command">make</action>
+                <action type="move_file">
+                    <source>bwa</source>
+                    <destination>$INSTALL_DIR/bin</destination>
+                </action>
+                <action type="set_environment">
+                    <environment_variable name="PATH" action="prepend_to">$INSTALL_DIR/bin</environment_variable>
+                </action>
+            </actions>
+        </install>
+    </package>
+    
+    <package name="STAR" version="2.3.0" >
+        <install version="1.0">
+            <actions>
+                <action type="download_by_url">https://rna-star.googlecode.com/files/STAR_2.3.0e.tgz</action>
+                <action type="move_file">
+                    <source>STAR</source>
+                    <destination>$INSTALL_DIR/bin</destination>
+                </action>
+                <action type="set_environment">
+                    <environment_variable name="PATH" action="prepend_to">$INSTALL_DIR/bin</environment_variable>
+                </action>
+            </actions>
+        </install>
+    
+    </package>
+    <package name="lastz" version="1.02.00" >
+        <install version="1.0">
+            <actions>
+                <action type="download_by_url" target_filename="lastz-distrib-1.02.00.tar.gz">http://www.bx.psu.edu/miller_lab/dist/lastz-1.02.00.tar.gz</action>
+                <action type="shell_command">make</action>
+                <action type="move_file">
+                         <source>src/lastz</source>
+                         <destination>$INSTALL_DIR/bin</destination>
+                     </action>
+                     <action type="move_file">
+                         <source>src/lastz_D</source>
+                         <destination>$INSTALL_DIR/bin</destination>
+                     </action>
+                <action type="set_environment">
+                    <environment_variable name="PATH" action="prepend_to">$INSTALL_DIR/bin</environment_variable>
+                </action>
+            </actions>
+        </install>
+    </package>
+    <package name="jalview" version="2.8" >
+        <install version="1.0">
+            <actions>
+                <action type="move_file">
+                         <source>jalview/jalview.jar</source>
+                         <destination>$INSTALL_DIR</destination>
+                </action>
+                <action type="move_directory_files">
+                        <source_directory>jalview</source_directory>
+                        <destination_directory>$INSTALL_DIR/lib</destination_directory>
+                </action>
+                <action type="set_environment">
+                    <environment_variable name="JALVIEW_DIR" action="prepend_to">$INSTALL_DIR</environment_variable>
+                </action>
+            </actions>
+        </install>
+    </package>
+   
+</tool_dependency>
\ No newline at end of file
Binary file jalview/vamsas-client.jar has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jalview/vhom.py	Sun Sep 22 19:13:07 2013 -0400
@@ -0,0 +1,1315 @@
+#!/usr/bin/env python
+
+import sys
+import os
+import logging
+import tempfile
+import shutil
+
+import subprocess
+import bz2
+import re
+import glob
+
+from shutil import rmtree
+from subprocess import PIPE
+from collections import defaultdict, Counter
+
+try:
+    import pysam
+except ImportError:
+    message = 'This script requires the pysam python package\n'
+    sys.stderr.write(message)
+    sys.exit(1)
+
+try:
+    from plumbum import cli
+except ImportError:
+    message = 'This script requires the plumbum python package\n'
+    sys.stderr.write(message)
+    sys.exit(1)
+
+try:
+    from Bio.SeqRecord import SeqRecord
+    from Bio import SeqIO
+    from Bio.Seq import Seq
+    from Bio.Alphabet import IUPAC, Gapped
+except ImportError:
+    message = 'This script requires the BioPython python package\n'
+    sys.stderr.write(message)
+    sys.exit(1)
+
+try:
+    import HTSeq
+except ImportError:
+    message = 'This script requires the HTSeq python package\n'
+    sys.stderr.write(message)
+    sys.exit(1)
+
+logging.basicConfig(level=logging.INFO, format='%(message)s')
+
+
+class CLI(cli.Application):
+
+    """ Homologous region analysis of hit files"""
+    PROGNAME = "vmap"
+    VERSION = "1.0.0"
+    DESCRIPTION = """"""
+    USAGE = """"""
+
+    def main(self, *args):
+
+        if args:
+            print("Unknown command %r" % (args[0]))
+            print self.USAGE
+            return 1
+
+        if not self.nested_command:
+            print("No command given")
+            print self.USAGE
+            return 1
+
+class SequenceProxy:
+
+    def __init__(self, references_path, human_transcripts_path=None):
+
+        self.references_path = references_path
+        self.human_transcripts_path = human_transcripts_path
+
+        self.human_transcript_records = None
+        self.reference_records = None
+        self.hit_records = []
+
+        self.transcript_ranges = None
+
+    def add_hit_file(self, hit_file_path):
+
+        logging.debug('SequenceProxy: adding new hit file %s' % hit_file_path)
+
+        hit_handle = bz2.BZ2File(hit_file_path, 'rb')
+        try:
+            hit_handle.read(10)
+        except IOError:
+            hit_handle = open(hit_file_path, 'rb')
+
+        hit_dict = SeqIO.to_dict(SeqIO.parse(hit_handle, "fasta"))
+
+        logging.debug('SequenceProxy: hit file has %i entries' % len(hit_dict))
+
+        self.hit_records.append(hit_dict)
+
+    def get_read_record(self, read_id):
+
+        for record_dict in self.hit_records:
+            if read_id in record_dict:
+                record = record_dict[read_id]
+                return SeqRecord(record.seq, record.id, '', '')
+
+        return None
+
+    def get_reference_record(self, identifier):
+
+        if not self.reference_records:
+            logging.debug('SequenceProxy: indexing reference records')
+            self.reference_records = SeqIO.index(self.references_path, 'fasta')
+
+        try:
+            record = self.reference_records[identifier]
+            return SeqRecord(record.seq, record.id, '', '')
+        except KeyError:
+            return None
+
+    def get_transcript_record(self, identifier):
+
+        if not self.human_transcripts_path:
+            return None
+
+        if not self.human_transcript_records:
+            logging.debug('SequenceProxy: indexing human transcripts')
+            self.human_transcript_records = SeqIO.index(
+                self.human_transcripts_path, 'fasta')
+
+        try:
+            record = self.human_transcript_records[identifier]
+            return SeqRecord(record.seq, record.id, '', '')
+
+        except KeyError:
+            return None
+
+    def get_overlapping_human_transcript_identifiers(self, chromosome, start, end):
+
+        if not self.human_transcripts_path:
+            return set()
+
+        if not self.transcript_ranges:
+            self._set_transcript_ranges()
+
+        interval = HTSeq.GenomicInterval(chromosome, start, end, '.')
+        all_transcript_ids = set()
+        for interval, transcript_ids in self.transcript_ranges[interval].steps():
+            all_transcript_ids = all_transcript_ids.union(transcript_ids)
+
+        return all_transcript_ids
+
+    def _set_transcript_ranges(self):
+
+        logging.debug(
+            'SequenceProxy: Preparing transcript ranges, please wait...')
+
+        self.transcript_ranges = HTSeq.GenomicArrayOfSets(
+            'auto', stranded=False)
+
+        for record in SeqIO.parse(self.human_transcripts_path, 'fasta'):
+            transcript_id = record.id
+            for exon in record.description.strip().split(' ')[1].split('|'):
+                chromosome, start, end = exon.split(';')
+                start, end = sorted((int(start), int(end)))
+                if start == end:
+                    continue
+                interval = HTSeq.GenomicInterval(chromosome, start, end, ".")
+                self.transcript_ranges[interval] += transcript_id
+
+
+class JalviewRunner:
+
+    def __init__(self, jalview_jar_dir, tmp_dir=None):
+
+        self.jalview_jar_dir = jalview_jar_dir
+
+        if tmp_dir:
+            self.tmp_dir = tempfile.mkdtemp(
+                dir=os.path.abspath(os.path.expandvars(tmp_dir)))
+        else:
+            self.tmp_dir = tempfile.mkdtemp()
+
+        self.config = ['#---JalviewX Properties File---',
+                       '#Fri Nov 04 14:23:53 CET 2011',
+                       'FIGURE_AUTOIDWIDTH=true',
+                       'ID_ITALICS=false',
+                       'SORT_ALIGNMENT=No sort',
+                       'SHOW_IDENTITY=true',
+                       'FONT_NAME=SansSerif',
+                       'GAP_SYMBOL=.',
+                       'SHOW_QUALITY=false',
+                       'SHOW_GROUP_CONSERVATION=false',
+                       'FONT_STYLE=plain',
+                       'ANTI_ALIAS=false',
+                       'SORT_BY_TREE=false',
+                       'SHOW_CONSENSUS_HISTOGRAM=false',
+                       'SHOW_OVERVIEW=false',
+                       'DEFAULT_COLOUR=Nucleotide',
+                       'SHOW_CONSENSUS_LOGO=false',
+                       'SHOW_ANNOTATIONS=true',
+                       'SHOW_UNCONSERVED=true',
+                       'AUTO_CALC_CONSENSUS=true',
+                       'PAD_GAPS=true',
+                       'FONT_SIZE=10',
+                       'RIGHT_ALIGN_IDS=false',
+                       'WRAP_ALIGNMENT=false',
+                       'FASTA_JVSUFFIX=false',
+                       'PILEUP_JVSUFFIX=false',
+                       'SHOW_JVSUFFIX=false']
+
+    def _make_configuration(self, sub_tmp_dir):
+
+        config_path = os.path.join(sub_tmp_dir, 'config.txt')
+        logging.debug(
+            'JalviewRunner: writing configuration file %s' % config_path)
+        with open(config_path, 'w') as config_file:
+            for c in self.config:
+                config_file.write(c + '\n')
+
+        return config_path
+
+    def _delete_tmp_dir(self):
+
+        try:
+            rmtree(self.tmp_dir)
+        except OSError:
+            pass
+
+    def _delete_sub_tmp_dir(self, sub_tmp_dir):
+
+        try:
+            rmtree(sub_tmp_dir)
+        except OSError:
+            pass
+
+    def run(self, fasta_path, png_output_path):
+
+        fasta_path = os.path.abspath(os.path.expandvars(fasta_path))
+
+        png_output_path = os.path.abspath(os.path.expandvars(png_output_path))
+
+        sub_tmp_dir = tempfile.mkdtemp(dir=self.tmp_dir)
+        config_path = self._make_configuration(sub_tmp_dir)
+
+        logging.debug(
+            'JalviewRunner: running Jalview on fasta %s with temp dir %s' %
+            (fasta_path, sub_tmp_dir))
+
+        cline = ['java', '-Djava.ext.dirs=%s/lib' % self.jalview_jar_dir,
+                 '-cp %s/jalview.jar' % self.jalview_jar_dir, 'jalview.bin.Jalview',
+                 '-open', fasta_path, '-nodisplay', '-png', png_output_path,
+                 '-colour', 'nucleotide', '-props', config_path]
+
+        # Run sibelia process
+        java_process = subprocess.Popen(
+            ' '.join(cline), shell=True, stdout=PIPE, stderr=PIPE)
+
+        # Block until streams are closed by the process
+        stdout, stderr = java_process.communicate()
+
+        if stderr:
+            sys.stderr.write('JalviewRunner: ' + stderr.replace('\n', ' '))
+
+        self._delete_sub_tmp_dir(sub_tmp_dir)
+
+        return png_output_path
+
+    def __del__(self):
+
+        self._delete_tmp_dir()
+
+
+class LastzRunner:
+
+    def __init__(self, lastz_path=None, word_length=7):
+
+        self.lastz_path = lastz_path
+        self.word_length = word_length
+
+    def align_to_bam_file(self, reference_fasta_path, query_fasta_path, output_bam_path, multiple=False, assert_record=None):
+
+        logging.debug('LastzRunner: running on reference %s and query %s' %
+                     (reference_fasta_path, query_fasta_path))
+        output_sam_path = os.path.abspath(
+            os.path.expandvars(output_bam_path.replace('.bam', '.sam')))
+        output_bam_unsorted_path = os.path.abspath(
+            os.path.expandvars(output_bam_path + '.unsorted'))
+
+        logging.debug(
+            'LastzRunner: aligning with output in temporary sam file %s' %
+            output_sam_path)
+        with open(output_sam_path, 'w') as output_sam_handler:
+            for line in self._align(reference_fasta_path, query_fasta_path, multiple):
+                output_sam_handler.write(line)
+
+        logging.debug(
+            'LastzRunner: transforming sam into unsorted bam file %s' %
+            output_bam_unsorted_path)
+        input_sam_handler = pysam.Samfile(output_sam_path, "r")
+        output_bam_file = pysam.Samfile(
+            output_bam_unsorted_path, "wb", template=input_sam_handler)
+
+        logging.debug(
+            'LastzRunner: copying from sam file to bam file')
+        for s in input_sam_handler:
+            output_bam_file.write(s)
+        output_bam_file.close()
+
+        logging.debug('LastzRunner: sorting and indexing bam file %s' %
+                      output_bam_path)
+        pysam.sort(output_bam_unsorted_path,
+                   output_bam_path.replace('.bam', ''))
+
+        pysam.index(output_bam_path)
+
+    def align_to_samlines(self, reference_fasta_path, query_fasta_path, multiple=False):
+
+        logging.debug('LastzRunner: running on reference %s and query %s' %
+                      (reference_fasta_path, query_fasta_path))
+
+        for line in self._align(reference_fasta_path, query_fasta_path, multiple):
+            yield line
+
+    def _align(self, reference_fasta_path, query_fasta_path, multiple):
+
+        reference_fasta_path = os.path.abspath(
+            os.path.expandvars(reference_fasta_path))
+        query_fasta_path = os.path.abspath(
+            os.path.expandvars(query_fasta_path))
+
+        lastz = [self.lastz_path and self.lastz_path or 'lastz']
+        if multiple:
+            cline = lastz + [
+                reference_fasta_path +
+                '[multiple]', query_fasta_path + '[nameparse=darkspace]',
+                '--format=sam', '--strand=both', '--gapped', '--chain',
+                '--nogfextend', '--seed=match%i' % self.word_length]
+
+        else:
+            cline = lastz + [
+                reference_fasta_path, query_fasta_path +
+                '[nameparse=darkspace]',
+                '--format=sam', '--strand=both', '--gapped',
+                '--chain', '--nogfextend', '--seed=match%i' % self.word_length]
+
+        # Run lastz process
+        lastz_process = subprocess.Popen(
+            ' '.join(cline), shell=True, stdout=PIPE, stderr=PIPE)
+
+        # Filter multiple read mappings (one to each strand) by only keeping
+        # the one with the most matches
+        alignments = []
+        for i, line in enumerate(iter(lastz_process.stdout.readline, '')):
+            if line.startswith('@'):
+                yield line
+            elif line.lower().startswith('read'):
+
+                fields = line.split('\t')
+                read_name = fields[0]
+                read_cigar = fields[5]
+                if not alignments:
+                    alignments = [read_name, line, read_cigar]
+                    continue
+                else:
+                    if alignments[0] == read_name:
+                        this_mapping = sum(
+                            [int(c[:-1]) for c in re.findall('[0-9]*M', read_cigar)])
+                        other_mapping = sum(
+                            [int(c[:-1]) for c in re.findall('[0-9]*M', alignments[2])])
+
+                        if other_mapping > this_mapping:
+                            yield alignments[1]
+                        else:
+                            yield line
+                    else:
+                        yield line
+                    alignments = []
+            else:
+                yield line
+
+
+class ConsensusRunner:
+
+    def __init__(self, ambiguity_cutoff=0.3):
+
+        self.ambiguity_cutoff = ambiguity_cutoff
+        self.ambiguity = {
+            'GT': 'K', 'AC': 'M', 'AG': 'R', 'CT': 'Y', 'CG': 'S',
+            'AT': 'W', 'CGT': 'B', 'ACG': 'V', 'ACT': 'H', 'AGT': 'D',
+            'ACGT': 'N'}
+
+        self.alphabet = Gapped(IUPAC.unambiguous_dna, "-")
+
+    def run(self, input_sam_path, output_fasta_path):
+
+        samfile = pysam.Samfile(input_sam_path, "rb")
+        references = samfile.references
+
+        logging.debug(
+            'ConsensusRunner: writing consensus of bam file %s' % input_sam_path)
+
+        assert len(references) == 1
+
+        consensus = defaultdict(list)
+        conditions = {}
+
+        base_mapper = {'A': 0, 'C': 1, 'G': 2, 'T': 3, 'N': 4, '-': 5}
+        ambiguity = self.ambiguity
+
+        alphabet = Gapped(IUPAC.ambiguous_dna)
+        frequency_cutoff = self.ambiguity_cutoff
+
+        # Get all conditions of aligned reads
+        for alignedread in samfile.fetch(references[0]):
+
+            name = alignedread.qname
+            length = len(alignedread.seq)
+            condition = None
+
+            if name.lower().startswith('read'):
+                condition = ';'.join(name.split(';')[:2])
+            else:
+                condition = ';'.join(name.split(';')[:-1])
+
+            if condition in conditions:
+                if name not in conditions[condition][0]:
+                    conditions[condition][0].add(name)
+                    conditions[condition][1] += 1
+                    conditions[condition][2] += length
+            else:
+                conditions[condition] = [set([name]), 1, length]
+
+        # Prepare count dictionaries
+        consensus = defaultdict(list)
+
+        for i, pileupcolumn in enumerate(samfile.pileup(references[0], max_depth=100000)):
+
+            if i % 1000 == 0:
+                logging.debug(
+                    'ConsensusRunner: making consensus at position %i' % i)
+
+            counters = {}
+            for condition in conditions:
+                counters[condition] = [0, 0, 0, 0, 0, 0]  # ACGTN-
+
+            for pileupread in pileupcolumn.pileups:
+
+                alignment = pileupread.alignment
+                name = alignment.qname
+
+                if pileupread.is_del:
+                    base = '-'
+                else:
+                    base = alignment.seq[pileupread.qpos].upper()
+
+                if name.lower().startswith('read'):
+                    condition = ';'.join(name.split(';')[:2])
+                    counters[condition][base_mapper[base]] += 1
+                else:
+                    condition = ';'.join(name.split(';')[:-1])
+                    counters[condition][base_mapper[base]] += 1
+
+            for condition, counts in counters.iteritems():
+                depth = float(sum(counts))
+                bases = []
+                a, c, g, t, n, gap = counts
+
+                if depth > 0:
+                    if (n / depth) >= frequency_cutoff:
+                        consensus[condition].append('N')
+                    else:
+                        if (a / depth) >= frequency_cutoff:
+                            bases.append('A')
+                        if (c / depth) >= frequency_cutoff:
+                            bases.append('C')
+                        if (g / depth) >= frequency_cutoff:
+                            bases.append('G')
+                        if (t / depth) >= frequency_cutoff:
+                            bases.append('T')
+
+                if len(bases) > 1:
+                    consensus[condition].append(
+                        ambiguity[''.join(sorted(bases))])
+                elif len(bases) == 1:
+                    consensus[condition].append(bases[0])
+                else:
+                    consensus[condition].append('-')
+
+        # Split consensuses by type
+        reference_consensuses = []
+        read_consensuses = []
+        for condition, sequence_list in consensus.iteritems():
+            if condition.lower().startswith('read'):
+                read_consensuses.append((''.join(sequence_list), condition))
+            else:
+                reference_consensuses.append(
+                    (''.join(sequence_list), condition))
+
+        reference_consensuses.sort(reverse=True)
+        read_consensuses.sort(reverse=True)
+
+        # Get start and end of reads (remove fully gapped positions)
+        start = None
+        end = None
+        for read_consensus, condition in read_consensuses:
+
+            # Forward direction
+            for i, char in enumerate(read_consensus):
+                if char != '-':
+                    if start is None:
+                        start = i
+                    else:
+                        start = min(start, i)
+                    break
+
+            # Reverse direction
+            for i, char in enumerate(read_consensus[::-1]):
+                if char != '-':
+                    if end is None:
+                        end = i
+                    else:
+                        end = min(end, i)
+                    break
+
+        if end == 0 or end is None:
+            end = None
+        else:
+            end = -end
+
+        # Filter all records by start and end of reads
+        reference_consensuses =\
+            [(r[start:end], c) for r, c in reference_consensuses]
+
+        read_consensuses =\
+            [(r[start:end], c) for r, c in read_consensuses]
+
+        # Write consensus records to file
+        with open(output_fasta_path, 'w',  buffering=100 * 1024 * 1024) as output_handler:
+            for consensus, condition in read_consensuses + reference_consensuses:
+                stats = ';'.join(map(str, conditions[condition][1:]))
+                record = SeqRecord(
+                    Seq(consensus, alphabet=alphabet), id=condition + ';' + stats, name='', description='')
+                SeqIO.write([record], output_handler, "fasta")
+
+
+class Group:
+
+    def __init__(self, family_name, qualified_family_name, sequence_proxy, tmp_dir=None):
+
+        self.family_name = family_name
+        self.qualified_family_name = qualified_family_name
+        self.sequence_proxy = sequence_proxy
+
+        self.regions = []
+        self.fasta_path = None
+
+        if tmp_dir:
+            self.tmp_dir = tempfile.mkdtemp(
+                dir=os.path.abspath(os.path.expandvars(tmp_dir)))
+        else:
+            self.tmp_dir = tempfile.mkdtemp()
+
+    def add_region(self, read_id, pathogen_mapping_locations, human_mapping_locations):
+
+        region = Region(self.sequence_proxy, self.tmp_dir)
+
+        region.add_read(read_id)
+
+        for mapping_location in list(pathogen_mapping_locations) + list(human_mapping_locations):
+            reference = ';'.join(mapping_location[:-2])
+            region.add_reference(
+                reference, int(mapping_location[-2]), int(mapping_location[-1]))
+
+        self.regions.append(region)
+
+    def write_outputs(self, output_dir, lastz_runner, consensus_builder, jalview_runner):
+
+        if not self.regions:
+            logging.debug('Group %s: no regions for family' % self.family_name)
+            return
+
+        made_output_dir = False
+        for i, region in enumerate(self.regions):
+
+            if not made_output_dir:
+                output_dir = os.path.abspath(
+                    os.path.expandvars(os.path.join(output_dir, self.qualified_family_name)))
+                logging.debug('Group %s: writing output files to %s' %
+                              (self.family_name, output_dir))
+                try:
+                    os.makedirs(output_dir)
+                except OSError:
+                    pass
+                made_output_dir = True
+
+            logging.debug('Group %s: writing region number %i files to %s' %
+                          (self.family_name, i + 1, output_dir))
+
+            unaligned_path = os.path.join(
+                output_dir, 'region_%i_unaligned.fa.bzip2' % (i + 1))
+            compressed_unaligned = bz2.BZ2File(unaligned_path, 'wb')
+            with open(region.get_unaligned_fasta_path()) as unaligned_fasta:
+                for line in unaligned_fasta:
+                    compressed_unaligned.write(line)
+
+            bam_path = os.path.join(
+                output_dir, 'region_%i_alignment.bam' % (i + 1))
+            temporary_alignment_bam_path = region.get_alignment_bam_path(
+                lastz_runner, assert_record='Read')
+            shutil.copy(temporary_alignment_bam_path, bam_path)
+
+            shutil.copy(
+                temporary_alignment_bam_path + '.bai', bam_path + '.bai')
+
+            consensus_path = os.path.join(
+                output_dir, 'region_%i_consensus.fa' % (i + 1))
+            temporary_consensus_path = region.get_consensus_fasta_path(
+                consensus_builder, temporary_alignment_bam_path)
+            shutil.copy(temporary_consensus_path, consensus_path)
+
+            if jalview_runner:
+
+                jalview_path = os.path.join(
+                    output_dir, 'region_%i_consensus.png' % (i + 1))
+                temporary_jalview_path = region.get_consensus_figure_path(
+                    jalview_runner, temporary_consensus_path)
+                shutil.copy(temporary_jalview_path, jalview_path)
+
+    def _delete_temporary_dir(self):
+
+        self.fasta_path = None
+        try:
+            rmtree(self.tmp_dir)
+        except OSError:
+            pass
+
+    def filter_regions(self, min_region_length=50, min_read_number=5):
+
+        logging.debug('Group %s: filtering %i candidate regions' %
+                      (self.family_name, len(self.regions)))
+
+        filtered = [r for r in self.regions if len(
+            r) >= min_read_number and r.get_longest_reference_length() >= min_region_length]
+
+        ordered = sorted(filtered, reverse=True)
+
+        if ordered:
+            length = ordered[0].length
+        else:
+            length = 0
+
+        logging.debug(
+            'Group %s: %i candidate regions remained after filtering, the longest is %i bp long' %
+            (self.family_name, len(ordered), length))
+
+        self.regions = ordered
+
+        return ordered
+
+    def merge_regions(self, max_gap_length):
+        """ Merges candidate regions into homologous regions. """
+
+        logging.debug('Group %s: merging %i candidate regions' %
+                      (self.family_name, len(self.regions)))
+
+        if len(self.regions) > 1:
+
+            potentially_mergable = self.regions
+            not_mergable = []
+
+            while len(potentially_mergable) > 1:
+
+                merged = False
+                current = potentially_mergable[0]
+                compared_to = potentially_mergable[1:]
+
+                for region in compared_to:
+                    if region.overlaps(current, max_gap_length):
+                        region.merge(current)
+                        region.clean_references(max_gap_length)
+                        #logging.debug('Group %s: merged a region. %i potentially mergable candidate regions remaining' % (self.family_name, len(potentially_mergable)))
+                        potentially_mergable = compared_to
+                        merged = True
+                        break
+
+                if not merged:
+                    not_mergable.append(current)
+                    potentially_mergable = compared_to
+                    #logging.debug('Group %s: not merged a region. %i potentially mergable candidate regions remaining' % (self.family_name, len(potentially_mergable)))
+
+            results = not_mergable + potentially_mergable
+
+            logging.debug('Group %s: merged into %i regions' %
+                          (self.family_name, len(results)))
+
+            self.regions = results
+
+        else:
+            logging.debug(
+                'Group %s: found only 1 region, no mergin necessary' % self.family_name)
+
+    def add_transcripts_to_regions(self):
+
+        logging.debug('Group %s: enriching %i regions with human transcript information'
+                      % (self.family_name, len(self.regions)))
+
+        for region in self.regions:
+
+            added_transcripts = 0
+
+            for identifier, locations in region.references.iteritems():
+                chromosome = identifier.split(';')[-1]
+
+                for start, end in locations:
+                    transcript_identifiers = self.sequence_proxy.get_overlapping_human_transcript_identifiers(
+                        chromosome, start, end)
+
+                    for transcript_identifier in transcript_identifiers:
+                        region.add_transcript(transcript_identifier)
+                        added_transcripts += 1
+
+            logging.debug('Group %s: added %i transcripts to a region' %
+                          (self.family_name, added_transcripts))
+
+    def __str__(self):
+
+        s = "Group %s with %i regions" % (self.family_name, len(self.regions))
+
+        return s
+
+
+class GroupGenerator:
+
+    """ Produces Groups from Hitfiles. Reads are assigned to groups based on
+        taxonomic families. Transcripts overlapping human read mappings as well
+        as genome sequences of pathogens the reads map to are added to the
+        Groups.
+    """
+
+    def __init__(self, sequence_proxy, reference_database_filter=None, pathogen_family_filter=None, tmp_dir=None):
+
+        self.sequence_proxy = sequence_proxy
+
+        self.tmp_path = tmp_dir
+        self.reference_database_filter = reference_database_filter
+        self.pathogen_family_filter = pathogen_family_filter
+
+        self.groups = {}
+
+        if tmp_dir:
+            self.tmp_dir = tempfile.mkdtemp(
+                dir=os.path.abspath(os.path.expandvars(tmp_dir)))
+        else:
+            self.tmp_dir = tempfile.mkdtemp()
+
+    def get_groups(self, min_read_number=5):
+
+        logging.debug(
+            'GroupGenerator: generating groups from %i hit files, please wait...' %
+            len(self.sequence_proxy.hit_records))
+
+        for hit_index in self.sequence_proxy.hit_records:
+            for read_id, record in hit_index.iteritems():
+
+                # Extract mapping locations to human DNA, human transcript, and
+                # pathogen genomes
+                mapping_locations = record.description.strip().split(
+                    ' ')[1].split('|')
+
+                pathogen_families = defaultdict(set)
+                human_mapping_locations = set()
+
+                for mapping_location in mapping_locations:
+                    fields = mapping_location.split(';')
+
+                    # Convert start and end to integers
+                    fields[-2] = int(fields[-2])  # start
+                    fields[-1] = int(fields[-1])  # end
+
+                    # Add mapping locations to human cDNA or human DNA
+                    if fields[2] == 'Homo_sapiens':
+                        human_mapping_locations.add(tuple(fields))
+
+                    # Add mapping locations to non-human references
+                    else:
+                        reference_database, family = fields[:2]
+                        if self.reference_database_filter and reference_database\
+                                not in self.reference_database_filter:
+                            continue
+                        if self.pathogen_family_filter and family\
+                                not in self.pathogen_family_filter:
+                            continue
+                        pathogen_families[
+                            (reference_database, family)].add(tuple(fields))
+
+                if not pathogen_families:
+                    continue
+
+                # Process the hits to different pathogen families
+                for (reference_database, family), pathogen_locations in pathogen_families.iteritems():
+
+                    qualified_family_name = reference_database + '_' + family
+
+                    # Obtain existing group or make new group
+                    if qualified_family_name in self.groups:
+                        group = self.groups[qualified_family_name]
+                    else:
+                        group = Group(family, qualified_family_name,
+                                      self.sequence_proxy, self.tmp_dir)
+                        self.groups[qualified_family_name] = group
+
+                    group.add_region(
+                        read_id, pathogen_locations, human_mapping_locations)
+
+        # Exclude groups that have collected to few reads
+        for qualified_family_name, group in self.groups.items():
+            if len(group.regions) < min_read_number:
+                del self.groups[qualified_family_name]
+            else:
+                logging.debug(
+                    'GroupGenerator: made new group for family %s' % qualified_family_name)
+
+        return self.groups
+
+
+class Region:
+
+    def __init__(self, sequence_proxy, tmp_dir=None):
+
+        self.sequence_proxy = sequence_proxy
+
+        self.references = defaultdict(set)
+        self.reads = set()
+        self.transcripts = set()
+        self.length = None
+
+        self.sorted_reference_positions = None
+
+        self.master_tmp = tmp_dir
+        self.tmp_dir = None
+
+        self.unaligned_fasta_path = None
+        self.alignment_sam_path = None
+        self.consensus_fasta_path = None
+
+    def add_reference(self, name, start, end):
+
+        assert start < end
+        self.length = None
+        self.longest_reference_id = None
+        self.references[name].add((start, end))
+
+    def add_read(self, name):
+
+        self.reads.add(name)
+
+    def add_transcript(self, name):
+
+        self.transcripts.add(name)
+
+    def get_tmp_path(self):
+
+        if self.tmp_dir:
+            return self.tmp_dir
+
+        if self.master_tmp:
+            self.tmp_dir = tempfile.mkdtemp(
+                dir=os.path.abspath(os.path.expandvars(self.master_tmp)))
+        else:
+            self.tmp_dir = tempfile.mkdtemp()
+
+        return self.tmp_dir
+
+    def _distance(self, range1, range2):
+
+        first, second = sorted((range1, range2))
+
+        if first[0] <= first[1] < second[0]:
+            return (second[0] - first[1])
+        else:
+            return 0
+
+    def _delete_temporary_dir(self):
+
+        self.unaligned_fasta_path = None
+        if self.tmp_dir:
+            try:
+                rmtree(self.tmp_dir)
+            except OSError:
+                pass
+
+    def _get_unaligned_fasta_path(self):
+
+        output_path = os.path.join(self.get_tmp_path(), 'unaligned_region.fa')
+        logging.debug('Region: writing unaligned fasta to %s' % output_path)
+
+        assert self.reads
+
+        with open(output_path, 'w',  buffering=100 * 1024 * 1024) as output_handler:
+
+            # Cut and write references
+            human_positions = []
+            pathogen_positions = []
+            for length, identifier, start, end in self.get_sorted_reference_positions():
+                if ';Homo_sapiens;' in identifier:
+                    human_positions.append((identifier, start, end))
+                else:
+                    pathogen_positions.append((identifier, start, end))
+
+            for identifier, start, end in pathogen_positions + human_positions:
+                record = self.sequence_proxy.get_reference_record(identifier)
+                if record:
+                    record = SeqRecord(record.seq, record.id, '', '')
+                    #record.id += ';%i-%i' % (start, end)
+                    SeqIO.write(
+                        [record[start - 1:end]], output_handler, "fasta")
+                else:
+                    pass
+                    #logging.debug('Region: could not retrieve reference %s' % identifier)
+
+            # Write full-length transcripts
+            for identifier in self.transcripts:
+                record = self.sequence_proxy.get_transcript_record(identifier)
+                if record:
+                    record = SeqRecord(record.seq, record.id, '', '')
+                    SeqIO.write([record], output_handler, "fasta")
+                else:
+                    logging.debug(
+                        'Region: could not retrieve reference %s' % identifier)
+
+            # Write reads
+            for read_id in sorted(self.reads):
+                record = self.sequence_proxy.get_read_record(read_id)
+                if record:
+                    # Transform read ID so that LASTZ can work with it (it
+                    # makes nicknames based on some characters )
+                    identifier = record.id.replace(
+                        ':', '_').replace('|', '_').replace('/', '_')
+                    record = SeqRecord(record.seq, identifier, '', '')
+                    SeqIO.write([record], output_handler, "fasta")
+                else:
+                    logging.debug(
+                        'Region: could not retrieve read %s' % read_id)
+
+            self.unaligned_fasta_path = output_path
+
+        return self.unaligned_fasta_path
+
+    def get_unaligned_fasta_path(self):
+
+        if not self.unaligned_fasta_path:
+            self._get_unaligned_fasta_path()
+
+        return self.unaligned_fasta_path
+
+    def _align_fastas(self, aligner, assert_record=None):
+
+        # Write reference fasta
+        queries_path = self.get_unaligned_fasta_path()
+        first_record = SeqIO.parse(open(queries_path, "rU"), "fasta").next()
+        reference_path = os.path.join(self.get_tmp_path(), 'reference.fa')
+
+        logging.debug(
+            'Region: writing longest reference to %s' % reference_path)
+
+        SeqIO.write([first_record], reference_path, "fasta")
+
+        # Do alignment
+        bam_path = os.path.join(self.get_tmp_path(), 'aligned.bam')
+        logging.debug(
+            'Region: starting alignment using queries %s to sam path %s' %
+            (queries_path, bam_path))
+
+        aligner.align_to_bam_file(
+            reference_path, queries_path, bam_path, assert_record=assert_record)
+
+        return bam_path
+
+    def _build_alignment_consensus(self, consensus_builder, alignment_bam_path):
+
+        consensus_path = os.path.join(self.get_tmp_path(), 'consensus.fa')
+        logging.debug('Region: writing consensus to %s' % consensus_path)
+
+        consensus_builder.run(alignment_bam_path, consensus_path)
+
+        return consensus_path
+
+    def get_alignment_bam_path(self, aligner, assert_record=None):
+
+        return self._align_fastas(aligner, assert_record)
+
+    def get_consensus_fasta_path(self, consensus_builder, alignment_bam_path):
+
+        return self._build_alignment_consensus(consensus_builder, alignment_bam_path)
+
+    def get_consensus_figure_path(self, jalview_runner, consensus_fasta_path):
+
+        png_path = os.path.join(self.get_tmp_path(), 'consensus_figure.png')
+
+        return jalview_runner.run(consensus_fasta_path, png_path)
+
+    def overlaps(self, other, max_gap_length):
+
+        overlap = (set(self.references) & set(other.references))
+
+        # Overlap is solely based on non-human references
+        overlap = [ref for ref in overlap if not ';Homo_sapiens;' in ref]
+
+        if not overlap:
+            return False
+
+        for reference in overlap:
+            reflist = self.references[reference]
+            for start, end in reflist:
+                for other_start, other_end in other.references[reference]:
+                    distance = self._distance((start, end),
+                                             (other_start, other_end))
+                    if distance <= max_gap_length:
+                        return True
+        return False
+
+    def merge(self, other):
+
+        for reference, reflist in other.references.iteritems():
+            for (start, end) in reflist:
+                self.add_reference(reference, start, end)
+
+        for read in other.reads:
+            self.add_read(read)
+
+    def clean_references(self, max_gap_length):
+
+        for reference, reflist in self.references.iteritems():
+
+            start_list = sorted(reflist)
+            saved = list(start_list[0])
+            result = set()
+
+            for item in start_list:
+                if self._distance(saved, item) <= max_gap_length:
+                    saved[1] = max(saved[1], item[1])
+                else:
+                    result.add(tuple(saved))
+                    saved[0] = item[0]
+                    saved[1] = item[1]
+            result.add(tuple(saved))
+            self.references[reference] = result
+
+    def to_sorted_record_ids(self):
+
+        references = []
+        for name, locations in self.references.iteritems():
+            for start, end in locations:
+                references.append(end - start, name)
+
+        reads = defaultdict(list)
+        for name, locations in self.references.iteritems():
+            condition = name.split(';')[1]
+            for start, end in locations:
+                reads[condition].append(end - start, name)
+
+        all_record_ids = sorted(references, reverse=True)
+        for condition, the_reads in reads.iteritems():
+            all_record_ids += sorted(the_reads, reverse=True)
+
+        for length, record_id in all_record_ids:
+            yield record_id
+
+    def __len__(self):
+
+        return len(self.reads)
+
+    def __cmp__(self, other):
+
+        if self.get_longest_reference_length() <\
+                other.get_longest_reference_length():
+            return -1
+        elif self.get_longest_reference_length() ==\
+                other.get_longest_reference_length():
+            return 0
+        return 1
+
+    def get_longest_reference_length(self):
+
+        if self.length is not None:
+            return self.length
+
+        positions = self.get_sorted_reference_positions()
+        if positions:
+            self.length = self.get_sorted_reference_positions()[0][0]
+        else:
+            self.length = 0
+
+        return self.length
+
+    def get_sorted_reference_positions(self):
+
+        if self.sorted_reference_positions is not None:
+            return self.sorted_reference_positions
+
+        lengths = []
+        for reference, the_set in self.references.iteritems():
+            for start, end in the_set:
+                lengths.append([end - start, reference, start, end])
+
+        self.sorted_reference_positions = sorted(lengths, reverse=True)
+
+        return self.sorted_reference_positions
+
+    def __str__(self):
+        return '<Region> of length %10i with %10i reads and %5i references' %\
+            (self.get_longest_reference_length(),
+             len(self.reads), len(self.references))
+
+
+class RegionStatistics:
+
+    def __init__(self, input_dir):
+
+        self.input_dir = input_dir
+        self.stats = []
+
+    def _add_sequence(self, qualified_name, region_id,
+                      longest_human_reference, longest_pathogen_reference, record):
+
+        state = 'pathogen'
+        if longest_human_reference:
+            state = 'ambiguous'
+
+        reference_type = qualified_name.split('_')[0]
+        family_name = '_'.join(qualified_name.split('_')[1:])
+
+        read_type, sample_id, number_reads, basepairs = record.id.split(';')
+
+        coverage = int(basepairs) / float(len(longest_pathogen_reference))
+
+        self.stats.append(
+            [reference_type, family_name, region_id, sample_id, state,
+             number_reads, str(len(longest_pathogen_reference)), basepairs, '%.5f' % coverage])
+
+    def run(self, output_file):
+
+        for qualified_family_name in os.listdir(self.input_dir):
+
+            family_dir = os.path.join(self.input_dir, qualified_family_name)
+
+            if not os.path.isdir(family_dir):
+                continue
+
+            consensus_regions = glob.glob(os.path.join(
+                family_dir, 'region_*_consensus.fa'))
+
+            for consensus_region in consensus_regions:
+
+                base_bame = os.path.basename(consensus_region)
+
+                region_id = base_bame.split('_')[1]
+
+                reads = []
+                longest_human_reference = None
+                longest_pathogen_reference = None
+
+                for consensus_record in SeqIO.parse(consensus_region, 'fasta'):
+                    if consensus_record.id.lower().startswith('read'):
+                        # ends with read number; cumulative bases
+                        reads.append(consensus_record)
+                    elif ';Homo_sapiens;' in consensus_record.id:
+                        if longest_human_reference is None or\
+                                len(consensus_record) > longest_human_reference:
+                            longest_human_reference = consensus_record
+                    else:
+                        if longest_pathogen_reference is None or\
+                                len(consensus_record) > longest_pathogen_reference:
+                            longest_pathogen_reference = consensus_record
+
+                for read in reads:
+                    self._add_sequence(qualified_family_name, region_id,
+                                       longest_human_reference, longest_pathogen_reference, read)
+
+        with open(os.path.abspath(os.path.expandvars(output_file)), 'w') as output_handler:
+            output_handler.write(
+                '\t'.join(['reference_type', 'family_name', 'region_id',
+                        'sample_id', 'taxonomic_origin', 'number_reads',
+                        'region_length', 'basepairs', 'coverage']) + '\n')
+            for entries in sorted(self.stats):
+                line = '\t'.join(entries) + '\n'
+                output_handler.write(line)
+
+
+@CLI.subcommand("regions")
+class RegionRunner(cli.Application):
+
+    """ Derive homologous groups and regions from hit files """
+
+    hit_files = cli.SwitchAttr(
+        ['-v', '--virana_hits'], str, list=True, mandatory=True,
+        help="Add hit file for analysis. May be supplied multiple times.")
+
+    lastz_path = cli.SwitchAttr(['-z', '--lastz_path'], str, mandatory=False,
+                                help="Path to lastz executable",
+                                default='')
+
+    jalview_jar_dir = cli.SwitchAttr(
+        ['-j', '--jalview_jar_dir'], str, mandatory=False,
+        help="Directory containing the jalview.jar file",
+        default=None)
+
+    references_path = cli.SwitchAttr(
+        ['-r', '--references'], str, mandatory=True,
+        help="Input fasta file containing genomic references of pathogens and possibly of human chromosomes as well (the latter is experimental)",
+        default='')
+
+    cdna_path = cli.SwitchAttr(['-c', '--cdna'], str, mandatory=False,
+                               help="Input fasta file containing human cDNA records.",
+                               default=None)
+
+    output_dir = cli.SwitchAttr(['-o', '--output_dir'], str, mandatory=True,
+                                help="Output directory that will be filled with subdirectories corresponding to homologous regions. The directory will be generated if it is not existing.",
+                                default='')
+
+    tmp_dir = cli.SwitchAttr(['-t', '--tmp_dir'], str, mandatory=False,
+                             help="Directory in which temorary files are stored. Temporary files will be stored in subdirectories of the provided directory and will be deleted after completion.",
+                             default=None)
+
+    stat_path = cli.SwitchAttr(['-s', '--region_stats'], str, mandatory=False,
+                               help="Path to output statistics tab-delimited text file.",
+                               default='')
+
+    reference_database_filter = cli.SwitchAttr(
+        ['-b', '--reference_database_filter'], str, list=True, mandatory=False,
+        help="Specifies which kind of reference databases are consisdered when extracting hits from hit files. May be specified multiple times. If any are specified, all reference databases not specified are filtered out. By default, this parameter is empty.",
+        default=[])
+
+    pathogen_family_filter = cli.SwitchAttr(
+        ['-f', '--pathogen_family_filter'], str, list=True, mandatory=False,
+        help="Specifies which kind of pathogen families are consisdered when extracting hits from hit files. May be specified multiple times. If any are specified, all families not specified are filtered out. By default, this parameter is empty.",
+        default=[])
+
+    min_read_number = cli.SwitchAttr(
+        ['-m', '--min_read_number'], cli.Range(1, 1000), mandatory=False,
+        help="Minimum number of reads that are required to be present in homologous region. Regions with fewer reads will be omitted from the results.",
+        default=5)
+
+    max_gap_length = cli.SwitchAttr(
+        ['-l', '--max_gap_length'], cli.Range(1, 1000), mandatory=False,
+        help="Maximum number bases that two candidate homologous regions are distant from each other with regard to their positions on a common reference sequence in order for being eligable for merging.",
+        default=25)
+
+    min_region_length = cli.SwitchAttr(
+        ['-x', '--min_region_length'], cli.Range(1, 1000), mandatory=False,
+        help="Minimum number bases of the longest reference sequence of each homologous region that is generated. Shoer regions will be omitted from the results.",
+        default=50)
+
+    word_length = cli.SwitchAttr(
+        ['-w', '--word_length'], cli.Range(1, 21), mandatory=False,
+        help="Word length of the lastz alignment process. Shorter word lengths allow more sensitive but less specific alignments.",
+        default=7)
+
+    ambiguity_cutoff = cli.SwitchAttr(
+        ['-a', '--ambiguity_cutoff'], float, mandatory=False,
+        help="Ratio of variant positions within a column of the homologous region sequence alignment so that the corresponding consensus sequence at this positions show a ambiguous base instead of the majority base.",
+        default=0.3)
+
+    debug = cli.Flag(
+        ["-d", "--debug"], help="Enable debug information")
+
+    def main(self):
+
+        if self.debug:
+            logging.getLogger().setLevel(logging.DEBUG)
+
+        # Make sequence proxy for managing hit files, references, and cdna
+        proxy = SequenceProxy(self.references_path, self.cdna_path)
+        for hit_file in self.hit_files:
+            proxy.add_hit_file(hit_file)
+
+        # Generate homologous groups
+        generator = GroupGenerator(proxy,
+                                   reference_database_filter=self.reference_database_filter,
+                                   pathogen_family_filter=self.pathogen_family_filter,
+                                   tmp_dir=self.tmp_dir)
+        groups = generator.get_groups(min_read_number=self.min_read_number)
+
+        # Prepare analysis modules ('runners') for postprocessing homologous
+        # regions
+        consensus = ConsensusRunner(ambiguity_cutoff=self.ambiguity_cutoff)
+        lastz = LastzRunner(word_length=self.word_length)
+
+        if self.jalview_jar_dir:
+            jalview = JalviewRunner(
+                jalview_jar_dir=self.jalview_jar_dir, tmp_dir=self.tmp_dir)
+        else:
+            jalview = None
+
+        # Make homologous regions within each homologous group
+        for name, group in groups.iteritems():
+            group.merge_regions(max_gap_length=self.max_gap_length)
+            group.filter_regions(
+                min_region_length=self.min_region_length, min_read_number=self.min_read_number)
+
+            if self.cdna_path:
+                group.add_transcripts_to_regions()
+
+            group.write_outputs(self.output_dir, lastz, consensus, jalview)
+            group._delete_temporary_dir()
+
+        # Run statistics on all homologous regions
+        if self.stat_path:
+            statistics = RegionStatistics(self.output_dir)
+            statistics.run(self.stat_path)
+
+if __name__ == "__main__":
+    CLI.run()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jalview/vhom_region.xml	Sun Sep 22 19:13:07 2013 -0400
@@ -0,0 +1,87 @@
+<tool id="vhom_region" name="Virana Homologous Groups">
+
+<description>Derive homologous groups and regions from hit files. </description>
+
+	<requirements>
+        
+        <requirement type="package" version="2.8">jalview</requirement>
+        <requirement type="package" version="1.02.00">lastz</requirement>
+        <requirement type="package" version="1.0">vhom_python</requirement>
+    </requirements>
+
+    <command interpreter="python">vhom_regions.py --html_file $hom_output --directory ${hom_output.files_path}
+    
+    --virana_hits $virana_hits
+    
+    #if $cdna
+        --cdna $cdna
+    #end if
+    
+    --references $references
+    
+    --ambiguity_cutoff $ambiguity_cutoff
+    
+    --max_gap_length $max_gap_length
+    
+    --min_read_number $min_read_number
+    
+    --word_length $word_length
+    
+    --min_region_length $min_region_length
+    
+    #if $reference_database_filter
+        #set $groups = str($reference_database_filter).split(",")
+        
+        #for $ref in $groups
+            --reference_database_filter $ref
+        #end for
+    #end if
+    
+    #for $i, $s in enumerate( $filter )
+        
+        --pathogen_family_filter $s
+        
+    #end for
+    
+    --output_dir ${hom_output.files_path}
+    
+    --region_stats $stat_output
+    </command>
+    
+    
+    <inputs>
+        
+        <param name="virana_hits" type="data" format="hit_bz2" label="Add hit file for analysis" />
+        
+        <param name="cdna" type="data" format="fasta" optional="True" label="Input fasta file containing human cDNA records" />
+        
+        <param name="references" type="data" format="fasta" label="Input fasta file containing genomic references of pathogens" />
+        
+        <param name="ambiguity_cutoff" type="float" min="0" max="1" value="0.3" label="Ambiguity Cutoff" />
+        
+        <param name="max_gap_length" type="integer" min="1" max="1000" value="25" label="Max Gap Length" />
+        
+        <param name="min_read_number" type="integer" min="1" max="1000" value="5" label="Min Read Number" />
+        
+        <param name="word_length" type="integer" min="1" max="21" value="7" label="Word length" />
+        
+        <param name="min_region_length" type="integer" min="1" max="1000" value="50" label="Min Region length" />
+        
+        <param name="reference_database_filter" type="select" optional="true" multiple="true" display="checkboxes" label="Specify Reference Database to use">
+            <option value="nr">nr</option>
+            <option value="nt">nt</option>
+        </param>
+        
+        <repeat name="filter" title="Pathogen Family Filter">
+            <param name="pathogen_family_filter" type="text" size="20" optional="true" label="Specifies which kind of pathogen families are consisdered when extracting hits"/>
+        </repeat>
+    
+    </inputs>
+    
+    
+    <outputs>
+        <data format="hom_reg" name="hom_output" label="" />
+        <data format="reg_stats" name="stat_output" label="" /> 
+    </outputs>
+ 
+</tool>    
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jalview/vhom_regionplot.py	Sun Sep 22 19:13:07 2013 -0400
@@ -0,0 +1,251 @@
+import matplotlib.pyplot as plt
+
+from matplotlib import rcParams
+from matplotlib import colors
+from matplotlib import cm
+
+from argparse import ArgumentParser
+from matplotlib.backends.backend_pdf import PdfPages
+
+import os
+
+import colorsys
+
+
+
+
+rcParams['figure.figsize'] = (6, 6)
+rcParams['figure.dpi'] = 100
+rcParams['axes.facecolor'] = 'white'
+rcParams['font.size'] = 10
+rcParams['patch.edgecolor'] = 'white'
+rcParams['patch.linewidth']=0.5
+rcParams['patch.facecolor'] = 'black'
+rcParams['font.family'] = 'StixGeneral'
+
+
+def color_variants(r,g,b):
+    h,l2,s= colorsys.rgb_to_hls(r,g,b)
+    l=[l2-0.4,l2-0.1,l2+0.2]
+    hexs=[]
+    for i in l:
+        hexs.append(colors.rgb2hex(colorsys.hls_to_rgb(h,i,s)))
+    return hexs
+    
+def rgb_color_variants(r,g,b):
+    h,l2,s= colorsys.rgb_to_hls(r,g,b)
+    l=[l2-0.4,l2-0.1,l2+0.2]
+    rgbs={}
+    rgbs["pathogen"]=colorsys.hls_to_rgb(h,l[0],s)
+    rgbs["ambiguous"]=colorsys.hls_to_rgb(h,l[1],s)
+    rgbs["human"]=colorsys.hls_to_rgb(h,l[2],s)
+    return rgbs
+
+                
+     
+
+def remove_border(axes=None, top=False, right=False, left=True, bottom=True):
+    """
+    Minimize chartjunk by stripping out unnecesasry plot borders and axis ticks
+    
+    The top/right/left/bottom keywords toggle whether the corresponding plot border is drawn
+    """
+    ax = axes or plt.gca()
+    ax.spines['top'].set_visible(top)
+    ax.spines['right'].set_visible(right)
+    ax.spines['left'].set_visible(left)
+    ax.spines['bottom'].set_visible(bottom)
+    
+    #turn off all ticks
+    ax.yaxis.set_ticks_position('none')
+    ax.xaxis.set_ticks_position('none')
+    
+    #now re-enable visibles
+    if top:
+        ax.xaxis.tick_top()
+    if bottom:
+        ax.xaxis.tick_bottom()
+    if left:
+        ax.yaxis.tick_left()
+    if right:
+        ax.yaxis.tick_right()
+        
+        
+def generateHTML(stat_dict,file,directory):
+    rval=["<html><head><title>Homologous groups and regions derived from hit files </title></head><body><p/>\n"]
+    rval.append("<a href='plot.pdf'>Download Plot</a>")
+    n_samples=0
+    for sample in stat_dict.iterkeys():
+        n_samples+=1
+        rval.append("<div id=%s_graph></div><p/>"%(sample))
+    rval.append("<script src='jquery-1.10.2.min.js'></script>")
+    rval.append("<script src='jqBarGraph.2.1.js'></script>")
+    rval.append('<script>')
+    i=0
+    for sample in stat_dict.iterkeys():
+        i+=1
+        rval.append("%s_array = new Array(" %sample)
+        for family in stat_dict[sample].iterkeys():
+            values=[]
+            for region,data in stat_dict[sample][family].iteritems():
+                  values.append([int(data[0][1]),int(data[0][2]), data[0][0], data[0][3],int(data[0][4]),int(region)])
+            rval.append(str([values,family])+",")
+        rval[-1]=rval[-1][:-1]
+        rval.append(");")
+        rval.append("%s_files=%s;"%(sample,str(getFiles(directory))))	
+        rval.append("$('#%s_graph').jqBarGraph({"%sample)
+        rval.append("sample: '%s',"%sample)
+        rval.append("data: %s_array,"%sample)
+        rval.append("files: %s_files,"%sample)
+        r,g,b,a=cm.hsv(1.*i/n_samples)
+        rval.append("colors: %s," %color_variants(r,g,b))
+        rval.append("legend: true,")
+        rval.append("title: '<H3>Visualisation of Sample %s</H3>',"%sample)
+        rval.append("width: %d"%((len(stat_dict[sample])*50)+150))
+        rval.append("});")
+#        rval.append("jQuery.get('test.py', function(data) {")
+#        rval.append("alert(data)")
+#        rval.append("})")
+    rval.append("</script>")
+    
+    rval.append( '</body></html>' )
+    with open(file,'w') as file:
+        file.write("\n".join( rval ))
+    
+def generatePyPlot(stat_dict,output_file):
+    pp = PdfPages(output_file)
+    fig = plt.figure()
+    
+    n_samples=len(stat_dict)
+    dict={}
+    position={}
+    dict_label={}
+    for sample in stat_dict.iterkeys():
+        dict[sample]=[{},{}]
+        position[sample]={}
+        dict_label[sample]={}
+        j=0
+        for family in stat_dict[sample].iterkeys():
+         
+            i=0
+            for region,values in stat_dict[sample][family].iteritems():
+                
+                if i not in dict[sample][0]:
+                    dict[sample][0][i]=[]
+                    dict[sample][1][i]=[]
+                    position[sample][i]=[]
+                    dict_label[sample][i]=[]
+                dict[sample][0][i].append(int(values[0][1]))
+                dict[sample][1][i].append(int(values[0][2]))
+                position[sample][i].append(j)
+                dict_label[sample][i].append(values[0][0])
+                i+=1
+            j+=1
+                
+    i=0    
+    for sample in dict.iterkeys():
+        fig = plt.figure()
+        fig.subplots_adjust(bottom=0.25,hspace=0.5)
+        r,g,b,a=cm.hsv(1.*i/n_samples)
+        color_map=rgb_color_variants(r,g,b)
+        for sub in [0,1]:
+          plt.subplot(1,2,sub+1)
+          bottom={}
+          for level,values in dict[sample][sub].iteritems():
+              colors=[color_map[r] for r in dict_label[sample][level]]
+              if level==0:
+                  print level, values, position[sample][level],bottom
+                  plt.bar(position[sample][level],values,bottom=0, width=0.8 ,color=colors)
+              else:
+                  lastvalues=[]
+                  for oldpos in range(len(values)):
+                      lastvalues.append(bottom[position[sample][level][oldpos]])         
+                  print level, values, position[sample][level], lastvalues
+                  plt.bar(position[sample][level],values, width=0.8,bottom=lastvalues ,color=colors)
+              for pos in range(len(values)):
+                  bottom[position[sample][level][pos]]=values[pos]
+          pos=[x+0.4 for x in range(len(stat_dict[sample]))]    
+          plt.xticks(pos, stat_dict[sample].keys(), rotation='vertical')
+          if(sub==0):
+            plt.ylabel("Reads")
+          else:
+            plt.ylabel("Basepairs")
+          plt.xlabel("")
+          fig.subplots_adjust(bottom=0.25,wspace=0.5)
+          remove_border()
+        plt.suptitle(sample)
+        pp.savefig(fig)
+        i+=1
+    pp.close()
+    
+
+
+def parseStatFile(filename):
+
+    with open(filename,'r') as file:     
+        values=[ map(str,line.split('\t')) for line in file ]
+
+        dict={}
+        for line in values[1:]:
+            if line[3] not in dict:
+                dict[line[3]]={}
+                dict[line[3]][line[1]]={}
+                dict[line[3]][line[1]][line[2]]=[[line[4],line[5],line[7],line[0],line[6]]]
+            else:
+                if line[1] not in dict[line[3]]:
+                    dict[line[3]][line[1]]={}
+                    dict[line[3]][line[1]][line[2]]=[[line[4],line[5],line[7],line[0],line[6]]]
+                else:
+                    if line[2] not in dict[line[3]][line[1]]:
+                        dict[line[3]][line[1]][line[2]]=[[line[4],line[5],line[7],line[0],line[6]]]
+                    else:
+                         dict[line[3]][line[1]][line[2]].append([line[4],line[5],line[7],line[0],line[6]])        
+#        for key in dict.iterkeys():
+#            for family_key,values in dict[key].iteritems():
+#                for line in values:
+#                    print key,family_key,line
+        return dict
+def getFiles(directory):
+    rval={}
+    dlist = os.listdir(directory)
+    for dire in dlist:
+        if(os.path.isdir(os.path.join(directory,dire))):
+             rval[dire]={}
+             flist = os.listdir(os.path.join(directory,dire))
+             for file in flist:
+                split=file.split("_")
+                region=split[1]
+                if region not in rval[dire]:
+                    rval[dire][region]=[file]
+                else:
+                    rval[dire][region].append(file)
+                         
+    return rval
+
+        
+
+if __name__ == "__main__":
+    
+    
+    parser = ArgumentParser()
+    
+    a = parser.add_argument
+    a("--html_file",dest="html_file")
+    a("--directory",dest="directory")
+    a("--stats",dest="stat_file")
+      
+    (options,args)= parser.parse_known_args()
+    
+#    args.insert(0,"dummy")
+#    try:
+#        RegionRunner.run(argv=args)
+#    except SystemExit:
+
+    stat_dict=parseStatFile(options.stat_file)
+    generatePyPlot(stat_dict,os.path.join(options.directory,"plot.pdf"))
+    generateHTML(stat_dict,options.html_file,options.directory)
+    
+        
+                        
+ 
+ 
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jalview/vhom_regions.py	Sun Sep 22 19:13:07 2013 -0400
@@ -0,0 +1,45 @@
+from argparse import ArgumentParser
+import os
+from vhom import RegionRunner
+
+
+def printDir(directory):
+    rval=["<ul>"]
+    flist = os.listdir(directory)
+    
+    for entry in flist:
+        if(os.path.isdir(os.path.join(directory,entry))):
+             rval.append('<li>%s</li>'%entry)
+             rval.extend(printDir(os.path.join(directory,entry)))
+        else:
+            rval.append( '<li><a href="%s">%s</a></li>' % ( os.path.join(directory,entry), entry) )     
+    rval.append("</ul>")
+    return rval
+
+
+
+if __name__ == "__main__":
+    
+    
+    parser = ArgumentParser()
+    
+    a = parser.add_argument
+    a("-o","--html_file",dest="html_file")
+    a("-d","--directory",dest="directory")
+      
+    (options,args)= parser.parse_known_args()
+    
+    args.insert(0,"dummy")
+    try:
+        RegionRunner.run(argv=args)
+    except SystemExit:
+        f = open(options.html_file,'w')
+        rval = ["<html><head><title>Homologous groups and regions derived from hit files </title></head><body><p/>\n"]
+        rval.append('<div>This composite dataset is composed of the following files:<p/>')
+        directory= options.directory
+        rval.extend(printDir(directory))
+        
+        rval.append( '</body></html>' )
+    
+        f.write("\n".join( rval ))
+        f.close() 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jalview/vmap.py	Sun Sep 22 19:13:07 2013 -0400
@@ -0,0 +1,1425 @@
+#!/usr/bin/env python
+#from __future__ import print_function
+
+import cProfile
+
+import sys
+import re
+
+import tempfile
+import subprocess
+import shutil
+import os
+import os.path
+import logging
+import bz2
+import zlib
+
+import math
+import string
+
+from collections import defaultdict, Counter
+
+from subprocess import PIPE
+
+NON_ID = ''.join(c for c in map(chr, range(256)) if not c.isalnum())
+NON_ID = NON_ID.replace('_', '').replace('-', '')
+
+try:
+    from Bio.SeqRecord import SeqRecord
+    from Bio import SeqIO
+    from Bio.Seq import Seq
+except ImportError:
+    message = 'This script requires the BioPython python package\n'
+    sys.stderr.write(message)
+    sys.exit(1)
+
+try:
+    from plumbum import cli
+except ImportError:
+    message = 'This script requires the plumbum python package\n'
+    sys.stderr.write(message)
+    sys.exit(1)
+
+
+try:
+    import HTSeq
+except ImportError:
+    message = 'This script requires the HTSeq python package\n'
+    sys.stderr.write(message)
+    sys.exit(1)
+
+KHMER_AVAILABLE = True
+try:
+    import khmer
+except ImportError:
+    KHMER_AVAILABLE = False
+
+#from io import BufferedRandom
+
+logging.basicConfig(level=logging.INFO, format='%(message)s')
+
+
+def profile_this(fn):
+    def profiled_fn(*args, **kwargs):
+        fpath = fn.__name__ + ".profile"
+        prof = cProfile.Profile()
+        ret = prof.runcall(fn, *args, **kwargs)
+        prof.dump_stats(fpath)
+        return ret
+    return profiled_fn
+
+
+class CLI(cli.Application):
+    """RNA-Seq and DNA-Seq short read analysis by mapping to known reference sequences"""
+    PROGNAME = "vmap"
+    VERSION = "1.0.0"
+    DESCRIPTION = """Virana vmap is an interface to the NCBI and ensembl reference databases that can
+                     generate reference indexes for the short read mappers STAR (RNA-Seq) and
+                     BWA-MEM (DNA-Seq). Short reads can be mapped to arbitrary combinations of
+                     reference databases and the results can be summarized by taxonomic family
+                     as well as stored as SAM file, unsorted BAM file, or as a HIT file that
+                     models multimapping reads between specific reference databases."""
+    USAGE = """The program has four modes that can be accessed by `vmap rnaindex`, `vmap dnaindex`, `vmap rnamap`, and `vmap dnamap.`"""
+
+    def main(self, *args):
+
+        if args:
+            print("Unknown command %r" % (args[0]))
+            print self.USAGE
+            return 1
+
+        if not self.nested_command:
+            print("No command given")
+            print self.USAGE
+            return 1
+
+
+@CLI.subcommand("rnaindex")
+class RNAIndex(cli.Application):
+    """ Creates a STAR index from a FASTA genome reference """
+
+    reference_files = cli.SwitchAttr(
+        ['-r', '--reference_file'], str, list=True, mandatory=True,
+        help="Sets the reference genome(s) FASTA file." +
+        " Multiple occurrences of this parameter are allowed.")
+    index_dir = cli.SwitchAttr(['-i', '--index_dir'], str, mandatory=True,
+                               help="Sets the index output directory." +
+                               " Directory will be generated if not existing." +
+                               " Directory will be filled with several index files.")
+    threads = cli.SwitchAttr(
+        ['-t', '--threads'], cli.Range(1, 512), mandatory=False,
+        help="Sets the number of threads to use",
+        default=1)
+    max_ram = cli.SwitchAttr(
+        ['-m'], cli.Range(1, 400000000000), mandatory=False,
+        help="Sets the maximum amount of memory (RAM) to use (in bytes)",
+        default=400000000000)
+    path = cli.SwitchAttr(['-p', '--path'], str, mandatory=False,
+                          help="Path to STAR executable",
+                          default='')
+    sparse = cli.Flag(
+        ["-s", "--sparse"], help="If given, a sparse index that requires less " +
+        " RAM in the mapping phase will be constructed")
+
+    debug = cli.Flag(["-d", "--debug"], help="Enable debug output")
+
+    def main(self):
+
+        if self.debug:
+            logging.getLogger().setLevel(logging.DEBUG)
+
+        # Obtain star executable
+        star = [self.path and self.path or 'STAR']
+
+        # Check if genome directory is existing
+        for reference_file in self.reference_files:
+            if not os.path.exists(reference_file):
+                sys.stdout.write(
+                    'Reference file %s nor existing, exiting' % reference_file)
+                sys.exit(1)
+
+        # Check if output directory is existing
+        if not os.path.exists(self.index_dir):
+            logging.debug(
+                'Making output directory for index at %s' % self.index_dir)
+            os.makedirs(self.index_dir)
+
+        # # Make named pipe to extract genomes
+        # pipe_path = os.path.abspath(os.path.join(self.genome_dir, 'pipe.fa'))
+        # if os.path.exists(pipe_path):
+        #     os.unlink(pipe_path)
+        # os.mkfifo(pipe_path)
+
+        # Make star command line
+        cline = star + ['--runMode', 'genomeGenerate',
+                        '--genomeDir', self.index_dir,
+                        '--limitGenomeGenerateRAM', str(self.max_ram),
+                        '--runThreadN', str(self.threads),
+                        '--genomeFastaFiles'] + self.reference_files
+
+        # Add parameters for sparse (memory-saving) index generation
+        if self.sparse:
+            cline += ['--genomeSAsparseD', '2',
+                      '--genomeChrBinNbits', '12',
+                      '--genomeSAindexNbases', '13']
+
+        else:
+            cline += ['--genomeSAsparseD', '1',
+                      '--genomeChrBinNbits', '18',
+                      '--genomeSAindexNbases', '15']
+
+        if self.debug:
+            print ' '.join(cline)
+
+        # Run STAR reference generation process
+        star_process = subprocess.Popen(' '.join(cline), shell=True, stdout=PIPE, stderr=PIPE)
+
+        # Block until streams are closed by the process
+        stdout, stderr = star_process.communicate()
+
+        if stderr:
+            sys.stderr.write(stderr)
+
+        if self.debug and stdout:
+            print stdout
+
+
+@CLI.subcommand("dnaindex")
+class DNAIndex(cli.Application):
+    """ Creates a BWA index from a FASTA reference file """
+
+    reference_file  = cli.SwitchAttr(['-r', '--reference_file'], str, mandatory=True,
+                                 help="Sets the input reference FASTA file.")
+    index_dir   = cli.SwitchAttr(['-i', '--index_dir'], str, mandatory=True,
+                                 help="Sets the index output directory." +
+                                 " Directory will be generated if not existing." +
+                                 " Directory will be filled with several index files.")
+    path        = cli.SwitchAttr(['-p', '--path'], str, mandatory=False,
+                                 help="Path to BWA executable",
+                                 default='')
+    debug       = cli.Flag(["-d", "--debug"], help="Enable debug output")
+
+    if debug:
+        logging.getLogger().setLevel(logging.DEBUG)
+
+    def main(self):
+
+        # Obtain star executable
+        bwa = [self.path and self.path or 'bwa']
+
+        # Check if genome directory is existing
+        if not os.path.exists(self.reference_file):
+            sys.stdout.write('Genome file %s nor existing, exiting' % self.reference_file)
+            sys.exit(1)
+
+        # Check if output directory is existing
+        if not os.path.exists(self.index_dir):
+            logging.debug('Making output directory %s' % self.index_dir)
+            os.makedirs(self.index_dir)
+
+        # Make star command line
+        cline = bwa + ['index', '-a', 'bwtsw', '-p', os.path.join(self.index_dir, 'index'), self.reference_file]
+
+        if self.debug:
+            print ' '.join(cline)
+
+        # Run BWA index generation process
+        bwa_process = subprocess.Popen(' '.join(cline), shell=True, stdout=PIPE, stderr=PIPE)
+        stdout, stderr = bwa_process.communicate()
+
+        if stderr:
+            sys.stderr.write(stderr)
+
+        if self.debug and stdout:
+            print stdout
+
+
+
+
+
+class SAMHits:
+    """ Converts SAM output of mappers into bzipped HIT files. """
+
+    def __init__(self, output_file, sample_id, refseq_filter=None, min_mapping_score=None,\
+                     min_alignment_score=None, max_mismatches=None,\
+                     max_relative_mismatches=None, min_continiously_matching=None,\
+                     filter_complexity=False):
+
+        self.output_file                = bz2.BZ2File(output_file, 'wb', buffering=100 * 1024 * 1024)
+        self.sample_id                  = sample_id.translate(None, NON_ID)
+        self.refseq_filter              = refseq_filter
+        self.max_mismatches             = max_mismatches
+        self.max_relative_mismatches    = max_relative_mismatches
+        self.current_group              = []
+        self.min_mapping_score          = min_mapping_score
+        self.min_alignment_score        = min_alignment_score
+        self.min_continiously_matching  = min_continiously_matching
+        self.filter_complexity          = filter_complexity
+
+        self.re_matches = re.compile(r'(\d+)M')
+        self.re_dels    = re.compile(r'(\d+)D')
+
+    def count(self, parsed_line):
+
+        if parsed_line is None:
+            return
+
+        read_key, read_name, flag, ref_name, ref_position, mapping_score,\
+                    cigar, mate_ref_name, mate_ref_position, insert_size, seq, qual,\
+                    is_end1, is_end2, number_mismatches, alignment_score,\
+                    number_hits, is_reverse, is_primary, is_mapped, is_mate_mapped,\
+                    is_paired, number_matches, read_end_pos, max_match = parsed_line
+
+        if not is_mapped:
+            return
+
+        if self.filter_complexity:
+
+            avg_compression = float(len(zlib.compress(seq)))/len(seq)
+
+            if avg_compression < 0.5:
+                return
+
+            # length = len(seq)
+            # counts = [seq.count(nuc) for nuc in 'ACGT']
+            # min_count = length * 0.10
+            # max_count = length * 0.50
+            # for count in counts:
+            #     if count < min_count or count > max_count:
+            #         return None
+
+            # counter = Counter()
+            # for i in range(length - 2):
+            #     counter[seq[i: i + 3]] += 1
+            # maximal = length - 4
+
+            # highest = sum([v for k, v in counter.most_common(2)])
+            # if highest > (maximal / 3.0):
+            #     return None
+
+            # self.passed.append(avg_compression)
+
+        pair_id = ''
+        if is_end1:
+            pair_id = '/1'
+
+        elif is_end2:
+            pair_id = '/2'
+
+        read_name = self.sample_id + ';' + read_name + pair_id
+
+        # Initialize new current group
+        if len(self.current_group) == 0:
+            self.current_group = [read_name, seq, []]
+
+        # Write old current group to file
+        if read_name != self.current_group[0]:
+            self._write_group()
+            self.current_group = [read_name, seq, []]
+
+        try:
+            refseq_group, family, organism, identifier = ref_name.split(';')[:4]
+        except ValueError:
+            sys.stderr.write('Read mapped to malformed reference sequence %s, skipping\n' % ref_name)
+            return
+
+        if self.min_continiously_matching:
+
+            if self.min_continiously_matching > max_match:
+                return
+
+        if self.max_mismatches\
+            and int(number_mismatches) > self.max_mismatches:
+            return
+
+        if self.max_relative_mismatches\
+            and int(number_mismatches) / float(len(seq))\
+            > self.max_relative_mismatches:
+            return
+
+        if self.min_mapping_score\
+            and self.min_mapping_score > mapping_score:
+            return
+
+        if self.min_alignment_score\
+            and self.min_alignment_score > alignment_score:
+            return
+
+        start = int(ref_position) + 1
+
+        self.current_group[2].append([refseq_group, family, organism, identifier, str(start), str(read_end_pos)])
+
+    def _write_group(self):
+        passed = True
+
+        if self.refseq_filter:
+            passed = False
+            for refseq_group, family, organism, identifier, start, end in self.current_group[2]:
+                if passed:
+                    break
+                for f in self.refseq_filter:
+                    if refseq_group == f:
+                        passed = True
+                        break
+        if passed:
+            description = []
+            for identifier in self.current_group[2]:
+                description.append(';'.join(identifier))
+            description = '|'.join(description)
+
+            record = SeqRecord(Seq(self.current_group[1]))
+            record.id = 'Read;' + self.current_group[0]
+            record.description = description
+
+            SeqIO.write([record], self.output_file, "fasta")
+
+    def write(self):
+
+        self._write_group()
+        self.output_file.close()
+
+class SAMParser:
+
+    def parse(self, line):
+
+        if line[0] == '@':
+            return None
+
+        alignment   = HTSeq._HTSeq.SAM_Alignment.from_SAM_line(line)
+        read_name   = alignment.read.name
+        seq         = alignment.read.seq
+        qual        = alignment.read.qual
+        flag        = alignment.flag
+        cigar       = None
+
+        is_paired       = (flag & 1)
+        is_mapped       = not (flag & 4)
+        is_mate_mapped  = alignment.mate_aligned is not None #not (flag & 8)
+        is_reverse      = (flag & 16)
+        is_end1         = (flag & 64)
+        is_end2         = (flag & 128)
+        is_primary      = not (flag & 256)
+
+        read_key = (read_name, is_end1)
+
+        ref_name            = None
+        ref_position        = None
+        mapping_score       = 0
+        mate_ref_name       = None
+        mate_ref_position   = None
+        insert_size         = None
+        alignment_score     = 0
+        read_end_pos        = None
+
+        if is_mate_mapped and alignment.mate_start:
+            mate_ref_name       = alignment.mate_start.chrom
+            mate_ref_position   = alignment.mate_start.start
+
+        number_hits         = 0
+        alignment_score     = 0
+        number_mismatches   = 0
+
+        number_matches      = 0
+        max_match           = 0
+
+        if is_mapped:
+
+            ref_name            = alignment.iv.chrom
+            ref_position        = alignment.iv.start
+            read_end_pos        = alignment.iv.end
+            alignment_score     = alignment.aQual
+            cigar               = alignment.cigar
+
+            if is_mate_mapped:
+                insert_size         = alignment.inferred_insert_size
+
+            for c in cigar:
+                if c.type == 'M':
+                    number_matches += c.size
+                    max_match = max(max_match, c.size)
+
+            for tag, value in alignment.optional_fields:
+                if tag == 'NM':
+                    number_hits = value
+                elif tag == 'AS':
+                    alignment_score = value
+                elif tag == 'NH':
+                    number_mismatches = value
+
+        return read_key, read_name, flag, ref_name, ref_position, mapping_score,\
+            cigar, mate_ref_name, mate_ref_position, insert_size, seq, qual,\
+            is_end1, is_end2, number_mismatches, alignment_score,\
+            number_hits, is_reverse, is_primary, is_mapped, is_mate_mapped,\
+            is_paired, number_matches, read_end_pos, max_match
+
+
+class SAMQuality:
+
+    def __init__(self, file_path):
+
+        self.file_path          = file_path
+
+        self.stored             = defaultdict(Counter)
+        self.all_references     = defaultdict(int)
+        self.primary_references = defaultdict(int)
+        self.complement         = string.maketrans('ATCGN', 'TAGCN')
+
+        if KHMER_AVAILABLE:
+            self.ktable = khmer.new_ktable(10)
+
+    def _get_complement(self, sequence):
+
+        return sequence.translate(self.complement)[::-1]
+
+    def _get_summary(self, counter):
+        """"Returns five numbers (sum, extrema, mean, and std)
+            for a max_frequency counter """
+
+        maximum  = 0
+        minimum  = sys.maxint
+        thesum   = 0
+        allcount = 0
+        mode     = [0, None]
+
+        items       = 0.0
+        mean        = 0.0
+        m2          = 0.0
+        variance    = 0.0
+
+        for item in counter:
+
+            count   = counter[item]
+            if count > mode[0]:
+                mode = [count, item]
+
+            allcount += count
+            maximum = max(maximum, item)
+            minimum = min(minimum, item)
+            thesum  += (count * item)
+
+            x = 1
+            while x <= count:
+                items       += 1
+                delta       = item - mean
+                mean        = mean + delta / items
+                m2          = m2 + delta * (item - mean)
+                variance    = m2 / items
+                x += 1
+
+        std = math.sqrt(variance)
+
+        return allcount, thesum, minimum, maximum, mode[1], mean, std
+
+
+    def _to_unit(self, item, is_percentage=False):
+        """ Convert a numeric to a string with metric units """
+
+        if is_percentage:
+            return ('%-.3f' % (item * 100)) + '%'
+        converted = None
+        try:
+            item = float(item)
+            if item > 10**12:
+                converted = str(round(item / 10**9,3))+'P'
+            elif item > 10**9:
+                converted = str(round(item / 10**9,3))+'G'
+            elif item > 10**6:
+                converted = str(round(item / 10**6,3))+'M'
+            elif item > 10**3:
+                converted = str(round(item / 10**3,3))+'K'
+            else:
+                converted = str(round(item,3))
+        except:
+            converted = str(item)
+
+        return converted
+
+    def _str_metrics(self, data):
+
+        str_metrics = []
+
+        for (item, metric) in sorted(data.keys()):
+            counter = data[(item, metric)]
+            if not hasattr(counter.iterkeys().next(), 'real'):
+                for element, count in counter.most_common():
+                    str_metrics.append(self._str_metric(item, metric, element, count, no_units=True))
+            else:
+                summary = self._get_summary(counter)
+                str_metrics.append(self._str_metric(item, metric, *summary))
+
+        return str_metrics
+
+    def _str_metric(self, item, metric, count, thesum='', minimum='',\
+                        maximum='', mode='', mean='', std='', no_units=False):
+
+        counters = [count, thesum, minimum, maximum, mode, mean, std]
+        counters = map(str, counters)
+
+        if no_units:
+            items = [item, metric] +  counters
+        else:
+            units = map(self._to_unit, counters)
+            items = [item, metric] + units
+
+        return '%-15s\t%-60s\t%12s\t%12s\t%12s\t%12s\t%12s\t%12s\t%12s\n' \
+                    % tuple(items)
+
+
+    def _count_read(self, metric, data, sample):
+
+        item = 'read'
+
+        (insert_size, alignment_score, mapping_score, length,\
+            q20_length, avg_phred_quality, number_hits, is_reverse) = data
+
+        self.stored[(item, metric + ' mappings')][number_hits] += sample
+        self.stored[(item, metric + ' insert')][insert_size] += sample
+
+
+    def _count_segment(self, metric, data, sample):
+
+        item = 'segment'
+
+        (insert_size, alignment_score, mapping_score, length,\
+            q20_length, avg_phred_quality, number_hits, is_reverse) = data
+
+        self.stored[(item, metric + ' algq')][alignment_score] += sample
+        self.stored[(item, metric + ' mapq')][mapping_score] += sample
+        self.stored[(item, metric + ' length')][length] += sample
+        self.stored[(item, metric + ' q20length')][q20_length] += sample
+        self.stored[(item, metric + ' meanbasequal')][avg_phred_quality] += sample
+        self.stored[(item, metric + ' reverse')][is_reverse] += sample
+
+    def count(self, parsed_line):
+
+        if parsed_line is None:
+            return
+
+        #print_metric('Item' , 'Metric', 'Count', 'Sum', 'Min', 'Max', 'Mode', 'Mean', 'STD')
+
+        read_key, read_name, flag, ref_name, ref_position, mapping_score,\
+                    cigar, mate_ref_name, mate_ref_position, insert_size, seq, qual,\
+                    is_end1, is_end2, number_mismatches, alignment_score,\
+                    number_hits, is_reverse, is_primary, is_mapped, is_mate_mapped,\
+                    is_paired, number_matches, read_end_pos, max_match = parsed_line
+
+        phred_quality       = [q - 33 for q in qual]
+        avg_phred_quality   = sum(phred_quality) / float(len(phred_quality))
+        length              = len(seq)
+        mate_reference_id   = mate_ref_name
+        reference_id        = ref_name
+        reference           = reference_id is not None and reference_id != '*'
+        insert_size         = insert_size and abs(insert_size) or insert_size
+        is_segment1         = not is_paired or (is_paired and is_end1)
+        is_reverse          = is_reverse
+        is_unique           = is_primary and number_hits == 1
+        is_translocation    = is_paired and is_mapped and is_mate_mapped\
+                                    and (mate_reference_id != '=' and reference_id != mate_reference_id)
+        is_part_of_doublemap    = is_paired and is_mapped and is_mate_mapped
+        is_part_of_halfmap      = is_paired and (is_mapped != is_mate_mapped)
+        is_part_of_nomap        = is_paired and not is_mapped and not is_mate_mapped
+
+
+        # Count length until first low quality base call
+        q20_length = 0
+        for q in phred_quality:
+            if q < 20:
+                break
+            q20_length += 1
+
+        # Count kmers
+        if KHMER_AVAILABLE:
+            if not is_reverse:
+                self.ktable.consume(seq)
+            else:
+                self.ktable.consume(self._get_complement(seq))
+
+        if reference:
+
+            self.all_references[reference_id] += 1
+
+            if is_primary:
+                self.primary_references[reference_id] += 1
+
+
+        data   = (insert_size, alignment_score, mapping_score, length,\
+                        q20_length, avg_phred_quality, number_hits, is_reverse)
+
+        sample = 1
+
+        self._count_segment('sequenced', data, sample)
+        if is_mapped:
+            self._count_segment('sequenced mapped multi', data, sample)
+            if is_primary:
+                self._count_segment('sequenced mapped primary', data, sample)
+                if number_hits and is_unique:
+                    self._count_segment('sequenced mapped primary unique', data, sample)
+
+            if is_segment1:
+                self._count_read('sequenced mapped multi', data, sample)
+                if is_primary:
+                    self._count_read('sequenced mapped primary', data, sample)
+
+        if is_paired:
+            self._count_segment('sequenced paired', data, sample)
+
+            if is_part_of_doublemap:
+                self._count_segment('sequenced paired doublemap', data, sample)
+
+                if is_primary:
+                    self._count_segment('sequenced paired doublemap primary', data, sample)
+
+                if is_segment1:
+                    self._count_read('sequenced paired doublemap multi', data, sample)
+
+                    if is_primary:
+                        self._count_read('sequenced paired doublemap primary', data, sample)
+
+                        if number_hits and is_unique:
+                            self._count_read('sequenced paired doublemap primary unique', data, sample)
+
+                            if is_translocation:
+                                self._count_read('sequenced paired doublemap primary unique translocation', data, sample)
+
+            elif is_part_of_halfmap:
+
+                self._count_segment('sequenced paired halfmap', data, sample)
+
+                # The mapped segment
+                if is_mapped:
+
+                    self._count_segment('sequenced paired halfmap mapped', data, sample)
+
+                    if is_primary:
+
+                        self._count_read('sequenced paired halfmap mapped primary', data, sample)
+
+                        if number_hits and is_unique:
+                            self._count_read('sequenced paired halfmap mapped primary unique', data, sample)
+
+                    elif not is_primary:
+
+                        self._count_read('sequenced unpaired mapped multi', data, sample)
+
+                # The unmapped segment
+                elif not is_mapped:
+                    self._count_segment('sequenced paired halfmap unmapped', data, sample)
+
+            elif is_part_of_nomap:
+
+                self._count_segment('sequenced paired nomap', data, sample)
+
+                if is_segment1:
+
+                    self._count_read('sequenced paired nomap', data, sample)
+
+        elif not is_paired:
+
+            self._count_segment('sequenced unpaired', data, sample)
+
+            if is_mapped:
+
+                self._count_segment('sequenced unpaired mapped', data, sample)
+
+                if is_primary:
+
+                        self._count_read('sequenced unpaired mapped primary', data, sample)
+
+                        if number_hits and is_unique:
+
+                            self._count_read('sequenced paired unpaired mapped primary unique', data, sample)
+
+                elif not is_primary:
+
+                    self._count_read('sequenced unpaired mapped multi', data, sample)
+
+
+            elif not is_mapped:
+
+                self._count_segment('sequenced unpaired unmapped', data, sample)
+
+                if is_segment1:
+                    self._count_read('sequenced unpaired unmapped', data, sample)
+
+    def write(self):
+
+        with open(self.file_path, 'w') as output_file:
+
+            all_references = sorted([(count, reference) for reference, count\
+                                    in self.all_references.iteritems()], reverse=True)
+
+            for j, (count, reference) in enumerate(all_references[:30]):
+                self.stored[('segment', 'multireference_' + str(j+1))][reference] = count
+
+            primary_references = sorted([(count, reference) for reference, count\
+                                            in self.primary_references.iteritems()], reverse=True)
+
+            for j, (count, reference) in enumerate(primary_references[:30]):
+                self.stored[('segment', 'primaryreference_' + str(j+1))][reference] = count
+
+            # Extract top-ranking kmers
+            if KHMER_AVAILABLE:
+                kmer_frequencies = []
+                for i in range(0, self.ktable.n_entries()):
+                    n = self.ktable.get(i)
+                    if n > 0:
+                        kmer_frequencies.append((n, self.ktable.reverse_hash(i)))
+                kmer_frequencies = sorted(kmer_frequencies, reverse=True)
+                for j, (frequency, kmer) in enumerate(kmer_frequencies[:10]):
+                    self.stored[('segment', 'kmer_' + str(j+1))][kmer] = frequency
+
+            output_file.writelines(self._str_metrics(self.stored))
+
+
+class SAMTaxonomy:
+    """ Provides taxonomic summary information from a SAM file stream. """
+
+    def __init__(self, file_path):
+
+        self.file_path = file_path
+
+        self.count_primaries = Counter()
+        self.detailed_information = {}
+
+        self._last_read                 = (None, None)
+        self._last_read_human_prim      = 0
+        self._last_read_human_sec       = 0
+        self._last_organisms            = set()
+
+    def count(self, parsed_line):
+
+        if parsed_line is None:
+            return
+
+        read_key, read_name, flag, ref_name, ref_position, mapping_score,\
+                    cigar, mate_ref_name, mate_ref_position, insert_size, seq, qual,\
+                    is_end1, is_end2, number_mismatches, alignment_score,\
+                    number_hits, is_reverse, is_primary, is_mapped, is_mate_mapped,\
+                    is_paired, number_matches, read_end_pos, max_match = parsed_line
+
+        if is_mapped:
+
+            refseq_group, family, organism, gi = ref_name.split(';')[:4]
+
+            if is_primary:
+                self.count_primaries[organism] += 1
+
+            if organism not in self.detailed_information:
+                # refseq_group. family, gis, avg_mapping_score,
+                # avg_seq_length, avg_number_hits, avg_alignment_score, avg_nr_mismatches
+                initial = [refseq_group,
+                           family,
+                           set([gi]),
+                           [int(mapping_score), 1],
+                           [len(seq), 1],
+                           [0, 0],
+                           [alignment_score, 1],
+                           [number_mismatches, 1],
+                           0,
+                           0]
+
+                self.detailed_information[organism] = initial
+
+            else:
+                entry = self.detailed_information[organism]
+                entry[2].add(gi)
+                entry[3][0] += int(mapping_score)
+                entry[3][1] += 1
+                entry[4][0] += len(seq)
+                entry[4][1] += 1
+                entry[6][0] += alignment_score
+                entry[6][1] += 1
+                entry[7][0] += number_mismatches
+                entry[7][1] += 1
+
+            if is_primary:
+                entry = self.detailed_information[organism]
+                entry[5][0] += number_hits
+                entry[5][1] += 1
+
+            if self._last_read == (None, None):
+                self._last_read = read_key
+
+            if self._last_read != read_key:
+
+                for last_organism in self._last_organisms:
+
+                    self.detailed_information[last_organism][8]\
+                        += self._last_read_human_prim
+
+                    self.detailed_information[last_organism][9]\
+                        += self._last_read_human_sec
+
+                self._last_read = read_key
+                self._last_organisms = set()
+                self._last_read_human_prim  = 0
+                self._last_read_human_sec   = 0
+
+            self._last_organisms.add(organism)
+
+            if organism == 'Homo_sapiens':
+                if is_primary:
+                    self._last_read_human_prim += 1
+                else:
+                    self._last_read_human_sec += 1
+
+    def get_summary(self, top=100):
+
+        lines = []
+
+        lines.append('%10s\t%20s\t%20s\t%-20s\t%10s\t%10s\t%10s\t%5s\t%5s\t%5s\t%10s\t%10s\n'\
+            % ('Count', 'Group', 'Family', 'Organism', 'Targets', 'ReadLen', 'Hits', 'Map', 'Algn', 'Mism', 'HuP', 'HuS'))
+
+        top_organisms = self.count_primaries.most_common(top)
+
+        for organism, count in top_organisms:
+
+            refseq_group, family, identifiers,\
+                avg_mapping_score, avg_seq_length, avg_number_hits,\
+                avg_alignment_score, avg_nr_mismatches, human_prim, human_sec\
+                = self.detailed_information[organism]
+
+            avg_len = int(avg_seq_length[0] / float(avg_seq_length[1]))
+            if avg_number_hits[1] == 0:
+                avg_hits = 0
+            else:
+                avg_hits = int(avg_number_hits[
+                               0] / float(avg_number_hits[1]))
+
+            avg_mapping_score = int(avg_mapping_score[
+                                    0] / float(avg_mapping_score[1]))
+
+            avg_alignment_score = int(avg_alignment_score[
+                                      0] / float(avg_alignment_score[1]))
+
+            avg_nr_mismatches = int(avg_nr_mismatches[
+                                    0] / float(avg_nr_mismatches[1]))
+
+            nr_ids = len(identifiers)
+
+            if count > 10**6:
+                count = str(round(count / float(10**6), 3)) + 'M'
+            if human_prim > 10**6:
+                human_prim = str(round(human_prim / float(10**6), 3)) + 'M'
+            if human_sec > 10**6:
+                human_sec = str(round(human_sec / float(10**6), 3)) + 'M'
+            if nr_ids > 10**6:
+                nr_ids = str(round(nr_ids / float(10**6), 3)) + 'M'
+
+            lines.append('%10s\t%20s\t%20s\t%-20s\t%10s\t%10i\t%10i\t%5i\t%5i\t%5i\t%10s\t%10s\n'\
+                % (str(count), refseq_group[:20], family[:20], organism[:20],\
+                    str(nr_ids), avg_len, avg_hits, avg_mapping_score,\
+                    avg_alignment_score, avg_nr_mismatches, str(human_prim),\
+                    str(human_sec)))
+
+        return lines
+
+    def write(self):
+
+        with open(self.file_path, 'w') as output_file:
+            output_file.writelines(self.get_summary())
+
+@CLI.subcommand("rnamap")
+class RNAmap(cli.Application):
+    """ Map input reads against a STAR index """
+
+    index_dir = cli.SwitchAttr(['-i', '--index_dir'], str, mandatory=True,
+                               help="Sets the index output directory")
+
+    threads = cli.SwitchAttr(
+        ['-t', '--threads'], cli.Range(1, 512), mandatory=False,
+        help="Sets the number of threads to use",
+        default=1)
+
+    taxonomy = cli.SwitchAttr(
+        ['-x', '--taxonomy'], str, mandatory=False,
+        help="Output path for the taxonomy file; setting this option will also enable regular taxonomy output to stdout during mapping",
+        default='')
+
+    star_path = cli.SwitchAttr(['--star_path'], str, mandatory=False,
+                          help="Path to STAR executable",
+                          default='')
+
+    samtools_path = cli.SwitchAttr(['--samtools_path'], str, mandatory=False,
+                          help="Path to samtools executable",
+                          default='')
+
+    temp_path = cli.SwitchAttr(['--temporary_path'], str, mandatory=False,
+                          help="Path to temporary directory in which to generate temp files. All temp files with be automatically deleted after execution is complete.",
+                          default='')
+
+    min_mapping_score = cli.SwitchAttr(['--min_mapping_score'], cli.Range(1, 255), mandatory=False,
+                          help="Mimimum mapping score for saved hits (only applied to -v/--virana_hits)",
+                          default=None)
+
+    min_alignment_score = cli.SwitchAttr(['--min_alignment_score'], cli.Range(1, 255), mandatory=False,
+                          help="Mimimum alignment score for saved hits (only applied to -v/--virana_hits)",
+                          default=None)
+
+    max_mismatches = cli.SwitchAttr(['--max_mismatches'],  cli.Range(0, 10000000), mandatory=False,
+                          help="Maximum number of mismatches for saved hits (only applied to -v/--virana_hits)",
+                          default=None)
+
+    max_relative_mismatches = cli.SwitchAttr(['--max_relative_mismatches'], float, mandatory=False,
+                          help="Maximum number of mismatches relative to read length for saved hits (only applied to -v/--virana_hits)",
+                          default=None)
+
+    min_continiously_matching = cli.SwitchAttr(['--min_continiously_matching'], cli.Range(0, 10000000), mandatory=False,
+                          help="Minimum number of continious matches for saved hits (only applied to -v/--virana_hits)",
+                          default=None)
+
+    filter_complexity = cli.Flag(['--filter_complexity'],
+                          help="Discard low-complexity reads (only applied to -v/--virana_hits). Adds some extra processing load to the mapping and may discard important information. Applies to all output files, including quality files (!)",
+                          default=False)
+
+    bam = cli.SwitchAttr(['-b', '--bam'], str, mandatory=False,
+                         help="Path to unsorted, unindexed output BAM file",
+                         default='')
+
+    sam = cli.SwitchAttr(['-s', '--sam'], str, mandatory=False,
+                         help="Path to output SAM file",
+                         default='')
+
+    qual = cli.SwitchAttr(['-q', '--qual'], str, mandatory=False,
+                         help="Path to output quality file",
+                         default='')
+
+    hits = cli.SwitchAttr(['-v', '--virana_hits'], str, mandatory=False,
+                          help="Path to bzip2-compressed tab-delimited output hit file",
+                          default='')
+
+    sample_id = cli.SwitchAttr(['--sample_id'], str, mandatory=False,
+                          help="Alphanumeric string ([0-9a-zA-Z_-]*) used to designate sample information within the hit file",
+                          default='no_sample_id')
+
+    unmapped1 = cli.SwitchAttr(['--unmapped_end_1'], str, mandatory=False,
+                         help="Output path to uncompressed fastq file containing unmapped reads, first ends only for paired ends.",
+                         default='')
+
+    unmapped2 = cli.SwitchAttr(['--unmapped_end_2'], str, mandatory=False,
+                         help="Output path to uncompressed fastq file containing unmapped reads, second ends only for paired ends.",
+                         default='')
+
+    splice_junctions = cli.SwitchAttr(['--splice_junctions'], str, mandatory=False,
+                         help="Input path to splice junction file (currently not implemented)",
+                         default='')
+
+    chimeric_mappings = cli.SwitchAttr(['--chimeric_mappings'], str, mandatory=False,
+                         help="Ouput path to SAM file containing chimeric mappings",
+                         default='')
+
+    hit_filter = cli.SwitchAttr(
+        ['-f', '--virana_hit_filter'], str, list=True, mandatory=False,
+        help="Only generate hit groups that include at last one read mapping to a reference of this reference group.",
+        default=[])
+
+    debug = cli.Flag(["-d", "--debug"], help="Enable debug information")
+
+    reads = cli.SwitchAttr(
+        ['-r', '--reads'], str, list=True, mandatory=True,
+        help="Sets the input reads. Add this parameter twice for paired end reads.")
+
+    zipped = cli.Flag(["-z", "--zipped"], help="Input reads are zipped")
+
+    sensitive = cli.Flag(
+        ["--sensitive"], help="If given, mapping will process slower and more sensitive")
+
+    def main(self):
+
+        if self.debug:
+            logging.getLogger().setLevel(logging.DEBUG)
+
+        # Obtain star executable
+        star        = [self.star_path and self.star_path or 'STAR']
+        samtools    = [self.samtools_path and self.samtools_path or 'samtools']
+
+        # Check if genome directory is existing
+        if not os.path.exists(self.index_dir):
+            sys.stdout.write('Index directory %s not existing, exiting' % self.genome_dir)
+            sys.exit(1)
+
+        if self.temp_path:
+            temp_path = tempfile.mkdtemp(dir=self.temp_path)
+        else:
+            temp_path = tempfile.mkdtemp()
+
+        first_ends      = []
+        second_ends     = []
+        single_ends     = []
+
+        if len(self.reads) == 2:
+            first, second = self.reads
+            first_ends.append(first)
+            second_ends.append(second)
+
+        elif len(self.reads) == 1:
+            single_ends.append(self.reads[0])
+
+        else:
+            sys.stdout.write('Invalid number of fastq files; provide either one (single end) or two (paired end)')
+            sys.exit(1)
+
+        if single_ends and not first_ends and not second_ends:
+            reads = [','.join(single_ends)]
+
+        elif first_ends and second_ends:
+            reads = [','.join(first_ends), ','.join(second_ends)]
+
+
+        star_cline = star + ['--runMode', 'alignReads',
+                        '--genomeDir', self.index_dir,
+                        '--runThreadN', str(self.threads),
+                        '--readMatesLengthsIn', 'NotEqual',
+                        '--outFileNamePrefix', os.path.join(
+                            temp_path, 'out'),
+                        '--outSAMmode', 'Full',
+                        '--outSAMstrandField', 'None',
+                        '--outSAMattributes', 'Standard',
+                        '--outSAMunmapped', 'Within',
+                        '--outStd', 'SAM',
+                        '--outFilterMultimapNmax', '1000',
+                        '--outSAMprimaryFlag', 'AllBestScore',
+                        '--outSAMorder', 'PairedKeepInputOrder']
+
+        if self.unmapped1 or self.unmapped2:
+            star_cline += ['--outReadsUnmapped', 'Fastx']
+        else:
+            star_cline += ['--outReadsUnmapped', 'None']
+
+
+        if self.zipped:
+            star_cline += ['--readFilesCommand', 'zcat']
+
+        if self.sensitive:
+            star_cline += ['--outFilterMultimapScoreRange', '10',
+                          '--outFilterMismatchNmax', '60',
+                          '--outFilterMismatchNoverLmax', '0.3',
+                          '--outFilterScoreMin', '0',
+                          '--outFilterScoreMinOverLread', '0.3',
+                          '--outFilterMatchNmin', '0',
+                          '--outFilterMatchNminOverLread', '0.66',
+                          '--seedSearchStartLmax', '12',
+                          '--winAnchorMultimapNmax', '50']
+
+        star_cline += ['--readFilesIn'] + reads
+
+        if self.debug:
+            print ' '.join(star_cline)
+
+        # Try if we can make the relevant files
+        touch_files = [self.unmapped1, self.unmapped2, self.taxonomy, self.qual, self.hits, self.sam, self.bam]
+        for file_path in touch_files:
+            if file_path is None or file_path == '':
+                continue
+            try:
+                with file(file_path, 'a'):
+                    os.utime(file_path, None)
+            except IOError:
+                sys.stderr.write('Could not write output file %s\n' % file_path)
+                sys.exit(1)
+
+        star_process = subprocess.Popen(' '.join(
+                                        star_cline), shell=True, stdout=PIPE)
+
+        parser      = SAMParser()
+
+        if self.taxonomy:
+            taxonomy    = SAMTaxonomy(self.taxonomy)
+
+        if self.qual:
+            quality     = SAMQuality(self.qual)
+
+        if self.hits:
+            hits        = SAMHits(self.hits, self.sample_id, self.hit_filter,
+                        self.min_mapping_score,
+                        self.min_alignment_score,
+                        self.max_mismatches,
+                        self.max_relative_mismatches,
+                        self.min_continiously_matching,
+                        self.filter_complexity)
+
+        if self.sam:
+            sam_file = open(self.sam, 'w')
+
+        if self.bam:
+            with open(self.bam, 'wb', buffering=100 * 1024 * 1024) as bam_file:
+                samtools_cline = samtools + [
+                    'view', '-b', '-1', '-S', '-@', '4', '/dev/stdin']
+                if self.debug:
+                    print ' '.join(samtools_cline)
+                samtools_process = subprocess.Popen(' '.join(samtools_cline), shell=True, stdout=bam_file, stdin=PIPE)
+
+
+        do_sam = self.sam
+        do_bam = self.bam
+        do_taxonomy = self.taxonomy
+        do_qual = self.qual
+        do_hits = self.hits
+        do_parse = do_taxonomy or do_qual or do_hits
+
+        for i, line in enumerate(iter(star_process.stdout.readline, '')):
+
+            if do_sam:
+                sam_file.write(line)
+
+            if do_bam:
+                samtools_process.stdin.write(line)
+
+            if line[0] == '@':
+                continue
+
+            if do_parse:
+                parsed_line = parser.parse(line)
+
+            if  do_taxonomy:
+                taxonomy.count(parsed_line)
+                if i > 0 and (i % 50000) == 0:
+                    print ''.join(taxonomy.get_summary(10))
+
+            if do_qual:
+                quality.count(parsed_line)
+
+            if do_hits:
+                hits.count(parsed_line)
+
+        if do_bam:
+            samtools_process.stdin.close()
+
+        if do_sam:
+            sam_file.close()
+
+        if do_hits:
+            hits.write()
+
+        if do_taxonomy:
+            print ''.join(taxonomy.get_summary(10))
+            taxonomy.write()
+
+        if do_qual:
+            quality.write()
+
+        try:
+            if self.unmapped1:
+                shutil.move(os.path.join(temp_path, 'out' + 'Unmapped.out.mate1'),\
+                self.unmapped1)
+        except IOError:
+            pass
+
+        try:
+            if self.unmapped2:
+                shutil.move(os.path.join(temp_path, 'out' + 'Unmapped.out.mate2'),\
+                 self.unmapped2)
+        except IOError:
+            pass
+
+        try:
+            if self.chimeric_mappings:
+                shutil.move(os.path.join(temp_path, 'out' + 'Chimeric.out.sam'),\
+                 self.chimeric_mappings)
+        except IOError:
+            pass
+
+        shutil.rmtree(temp_path)
+
+@CLI.subcommand("dnamap")
+class DNAmap(cli.Application):
+    """ Map input reads against a BWA index """
+
+    index_dir = cli.SwitchAttr(['-i', '--index_dir'], str, mandatory=True,
+                               help="Sets the index output directory")
+
+    threads = cli.SwitchAttr(
+        ['-t', '--threads'], cli.Range(1, 512), mandatory=False,
+        help="Sets the number of threads to use",
+        default=1)
+
+    taxonomy = cli.SwitchAttr(
+        ['-x', '--taxonomy'], str, mandatory=False,
+        help="Output path for the taxonomy file; setting this option will also enable regular taxonomy output to stdout during mapping",
+        default='')
+
+    samtools_path = cli.SwitchAttr(['--samtools_path'], str, mandatory=False,
+                          help="Path to samtools executable",
+                          default='')
+
+    temp_path = cli.SwitchAttr(['--temporary_path'], str, mandatory=False,
+                          help="Path to temporary directory in which to generate temp files. All temp files with be automatically deleted after execution is complete.",
+                          default='')
+
+    min_mapping_score = cli.SwitchAttr(['--min_mapping_score'], cli.Range(1, 255), mandatory=False,
+                          help="Mimimum mapping score for saved hits (only applied to -v/--virana_hits)",
+                          default=None)
+
+    min_alignment_score = cli.SwitchAttr(['--min_alignment_score'], cli.Range(1, 255), mandatory=False,
+                          help="Mimimum alignment score for saved hits (only applied to -v/--virana_hits)",
+                          default=None)
+
+    max_mismatches = cli.SwitchAttr(['--max_mismatches'],  cli.Range(0, 10000000), mandatory=False,
+                          help="Maximum number of mismatches for saved hits (only applied to -v/--virana_hits)",
+                          default=None)
+
+    max_relative_mismatches = cli.SwitchAttr(['--max_relative_mismatches'], float, mandatory=False,
+                          help="Maximum number of mismatches relative to read length for saved hits (only applied to -v/--virana_hits)",
+                          default=None)
+
+    min_continiously_matching = cli.SwitchAttr(['--min_continiously_matching'], cli.Range(0, 10000000), mandatory=False,
+                          help="Minimum number of continious matches for saved hits (only applied to -v/--virana_hits)",
+                          default=None)
+
+    filter_complexity = cli.Flag(['--filter_complexity'],
+                          help="Discard low-complexity reads (only applied to -v/--virana_hits). Adds some extra processing load to the mapping and may discard important information. Applies to all output files, including quality files (!)",
+                          default=False)
+
+    sample_id = cli.SwitchAttr(['--sample_id'], str, mandatory=False,
+                          help="Alphanumeric string ([0-9a-zA-Z_-]*) used to designate sample information within the hit file",
+                          default='no_sample_id')
+
+    bam = cli.SwitchAttr(['-b', '--bam'], str, mandatory=False,
+                         help="Path to unsorted, unindexed output BAM file",
+                         default='')
+
+    sam = cli.SwitchAttr(['-s', '--sam'], str, mandatory=False,
+                         help="Path to output SAM file",
+                         default='')
+
+    qual = cli.SwitchAttr(['-q', '--qual'], str, mandatory=False,
+                         help="Path to output quality file",
+                         default='')
+
+    hits = cli.SwitchAttr(['-v', '--virana_hits'], str, mandatory=False,
+                          help="Path to bzip2-compressed tab-delimited output virana hit file",
+                          default='')
+
+    hit_filter = cli.SwitchAttr(
+        ['-f', '--virana_hit_filter'], str, list=True, mandatory=False,
+        help="Only generate hit groups that include at last one read mapping to a reference of this reference group.",
+        default=[])
+
+    debug = cli.Flag(["-d", "--debug"], help="Enable debug information")
+
+    zipped = cli.Flag(["-z", "--zipped"], help="Input reads are zipped")
+
+    sensitive = cli.Flag(
+        ["--sensitive"], help="If given, mapping will process slower and more sensitive")
+
+
+    bwa_path = cli.SwitchAttr(['--bwa_path'], str, mandatory=False,
+                          help="Path to BWA executable",
+                          default='')
+
+    debug = cli.Flag(["-d", "--debug"], help="Enable debug information")
+
+    if debug:
+        logging.getLogger().setLevel(logging.DEBUG)
+
+    reads = cli.SwitchAttr(
+        ['-r', '--reads'], str, list=True, mandatory=True,
+        help="Sets the input reads. Add this parameter twice for paired end reads.")
+
+    def main(self):
+
+        if self.debug:
+            logging.getLogger().setLevel(logging.DEBUG)
+
+        # Obtain star executable
+        bwa         = [self.bwa_path and self.bwa_path or 'bwa']
+        samtools    = [self.samtools_path and self.samtools_path or 'samtools']
+
+        # Check if genome directory is existing
+        if not os.path.exists(self.index_dir):
+            sys.stdout.write('Index directory %s not existing, exiting'\
+                % self.genome_dir)
+            sys.exit(1)
+
+        if len(self.reads) not in (1, 2):
+            message = 'Invalid number of FASTQ files; supply either one (single end) or two (paired end)\n'
+            sys.stderr.write(message)
+            sys.exit(1)
+
+        bwa_cline = bwa + ['mem', '-t', str(self.threads), '-M', os.path.join(self.index_dir, 'index')]
+
+        bwa_cline += self.reads
+
+        if self.debug:
+            print ' '.join(bwa_cline)
+
+        bwa_process = subprocess.Popen(' '.join(bwa_cline), shell=True, stdout=PIPE)
+
+        parser      = SAMParser()
+
+        if self.taxonomy:
+            taxonomy    = SAMTaxonomy(self.taxonomy)
+
+        if self.qual:
+            quality     = SAMQuality(self.qual)
+
+        if self.hits:
+            hits        = SAMHits(self.hits, self.sample_id, self.hit_filter,
+                        self.min_mapping_score,
+                        self.min_alignment_score,
+                        self.max_mismatches,
+                        self.max_relative_mismatches,
+                        self.min_continiously_matching,
+                        self.filter_complexity)
+
+        if self.sam:
+            sam_file = open(self.sam, 'w', buffering=100 * 1024 * 1024)
+
+        if self.bam:
+            with open(self.bam, 'wb', buffering=100 * 1024 * 1024) as bam_file:
+                samtools_cline = samtools + [
+                    'view', '-b', '-1', '-S', '-@', '4', '/dev/stdin']
+                if self.debug:
+                    print ' '.join(samtools_cline)
+                samtools_process = subprocess.Popen(' '.join(samtools_cline), shell=True, stdout=bam_file, stdin=PIPE)
+
+        do_sam = self.sam
+        do_bam = self.bam
+        do_taxonomy = self.taxonomy
+        do_qual = self.qual
+        do_hits = self.hits
+        do_parse = do_taxonomy or do_qual or do_hits
+
+        for i, line in enumerate(iter(bwa_process.stdout.readline, '')):
+
+            if do_sam:
+                sam_file.write(line)
+
+            if do_bam:
+                samtools_process.stdin.write(line)
+
+            if do_parse:
+                parsed_line = parser.parse(line)
+
+            if do_taxonomy:
+                taxonomy.count(parsed_line)
+
+                if i > 0 and (i % 10000) == 0:
+                    print ''.join(taxonomy.get_summary(10))
+
+            if do_qual:
+                quality.count(parsed_line)
+
+            if do_hits:
+                hits.count(parsed_line)
+
+        if do_bam:
+            samtools_process.stdin.close()
+
+        if do_sam:
+            sam_file.close()
+
+        if do_hits:
+            hits.write()
+
+        if do_taxonomy:
+            print ''.join(taxonomy.get_summary(10))
+            taxonomy.write()
+
+        if do_qual:
+            quality.write()
+
+
+if __name__ == "__main__":
+    CLI.run()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jalview/vmap_dnaindex.py	Sun Sep 22 19:13:07 2013 -0400
@@ -0,0 +1,30 @@
+from argparse import ArgumentParser
+import os
+from vmap import DNAIndex
+
+if __name__ == "__main__":
+    
+    
+    parser = ArgumentParser()
+    
+    a = parser.add_argument
+    a("-o","--html_file",dest="html_file")
+    a("-d","--dir",dest="directory")
+      
+    (options,args)= parser.parse_known_args()
+    
+    args.insert(0,"dummy")
+    try:
+        DNAIndex.run(argv=args)
+    except SystemExit:
+        f = open(options.html_file,'w')
+        rval = ["<html><head><title>BWA Index Galaxy Composite Dataset </title></head><body><p/>\n"]
+        rval.append('<div>This composite dataset is composed of the following files:<p/><ul>')
+        flist = os.listdir(options.directory)
+
+        for file in flist:
+            rval.append( '<li><a href="%s">%s</a></li>' % ( file, file) )
+        rval.append( '</ul></body></html>' )
+    
+        f.write("\n".join( rval ))
+        f.close() 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jalview/vmap_dnamap.xml	Sun Sep 22 19:13:07 2013 -0400
@@ -0,0 +1,161 @@
+<tool id="vmap_dnamap" name="Virana DNAMap">
+
+<description>Map input reads against a BWA index. </description>
+
+	<requirements>
+        
+        <requirement type="package" version="0.1.19">samtools</requirement>
+        <requirement type="package" version="0.7.4">bwa</requirement>
+        <requirement type="package" version="1.0">vmap_python</requirement>
+    </requirements>
+
+    <command interpreter="python">vmap.py dnamap
+    
+    
+    
+    --reads $reads
+    
+    #if $paired.select_paired == "paired"
+        --reads $paired.paired_read
+    #end if
+    
+    #if $refseq
+        #set $groups = str($refseq).split(",")
+        #for $ref in $groups:
+            --virana_hit_filter $ref
+        #end for
+    #end if
+        
+
+        #if $bam
+            --bam $bam_output
+        #end if
+        
+        #if $sam
+            --sam $sam_output
+        #end if
+        
+        #if $output_type.hit
+            --virana_hits $hit_output
+            
+            #if $output_type.filter_complexity
+                --filter_complexity
+            #end if
+            
+            #if $output_type.max_mismatches
+                --max_mismatches $output_type.max_mismatches
+            #end if
+            
+            #if $output_type.max_relative_mismatches
+                --max_relative_mismatches $output_type.max_relative_mismatches
+            #end if
+            
+            #if $output_type.min_alignment_score
+                --min_alignment_score $output_type.min_alignment_score
+            #end if
+            
+            #if $output_type.min_continiously_matching
+                --min_continiously_matching $output_type.min_continiously_matching
+            #end if
+            
+            #if $output_type.min_mapping_score
+                --min_mapping_score $output_type.min_mapping_score
+            #end if
+       #end if
+       #if $qual
+            --qual $qual_output 
+       #end if
+        #if $tax
+            --taxonomy $tax_output  
+        #end if
+    
+    
+    #if $sample_id:
+        --sample_id $sample_id
+    #end if 
+    
+    --index_dir $index.extra_files_path
+    
+    $sensitive
+    
+    2&gt;&amp;1
+        
+    </command>
+    
+    <inputs>
+        <param name="reads" type="data" format="fastq" label="Read file"/>
+        
+        <conditional name="paired">
+            <param name="select_paired" type="select" label="Paired end reads?" >
+                <option value="single">single end</option>
+                <option value="paired">paired end</option>
+            </param>
+            
+           <when value="paired">
+                <param name="paired_read" type="data" format="fastq" label="Paired end read file" />
+           </when>
+        
+        </conditional>
+        <conditional name="output_type">
+            <param name="hit" type="boolean" label="Hit Output"/>
+                           
+            <when value="true">
+                <param name="max_mismatches" type="integer" min="0" max="10000000"  optional="true" label="Maximum number of mismatches for saved hits"/>
+                <param name="max_relative_mismatches" type="float" min="0" max="1" optional="true" label="Maximum number of mismatches relative to read length for saved hits " />
+                <param name="min_continiously_matching" type="integer" min="0" max="10000000" optional="true" label="Minimum number of continious matches for saved hits"  />
+                <param name="min_mapping_score" type="integer" min="1" max="255"  optional="true" label="Mimimum mapping score for saved hit"  />        
+                <param name="filter_complexity" type="boolean"  label="Discard low-complexity reads"/>
+                <param name="min_alignment_score" type="integer" min="0" max="255" optional="true" label="Mimimum alignment score for reported hits"/>
+
+            </when>
+        
+        </conditional>
+        
+        <param name="bam" type="boolean" label="BAM Output"/>
+        <param name="sam" type="boolean" label="SAM Output"/>
+        <param name="qual" type="boolean"  label="Quality Output"/>
+        <param name="tax" type="boolean"  label="Taxonomy Output"/>
+        
+        <param name="refseq" type="select" label="Set RefSeq taxonomic groups" multiple="true" display="checkboxes" optional="true">
+            <option value="UniVec">UniVec</option>
+            <option value="rRNA">rRNA</option>
+            <option value="Homo_sapiens">Homo sapiens</option>
+            <option value="Fungi">Fungi</option>
+            <option value="Plasmids">Plasmids</option>
+            <option value="Protozoa">Protozoa</option>
+            <option value="Viruses">Viruses</option>
+            <option value="Homo_sapiens_cDNA">Homo sapiens cDNA</option>
+            <option value="Fungi_DRAFT">Fungi DRAFT</option>
+            <option value="Bacteria">Bacteria</option>
+            <option value="Bacteria_DRAFT">Bacteria DRAFT</option>
+        </param>
+        
+        <param name="index" type="data" format="bwa_index" label="BWA Index files"/>
+        
+        <param name="sample_id" type="text" optional="true" label="String used to designate sample information within the hit file"/>
+        
+        
+        
+        <param name="sensitive" type="boolean" truevalue="--sensitive" falsevalue="" label="If given, mapping will process slower and more sensitive"/>
+
+    </inputs>
+    
+    
+    <outputs>
+        <data format="hit_bz2" name="hit_output" label="">
+            <filter>output_type['hit']</filter>
+        </data>
+        <data format="bam" name="bam_output" label="" >
+            <filter>bam</filter>
+        </data>
+        <data format="sam" name="sam_output" label="">
+            <filter>sam</filter>
+        </data>
+        <data format="qual" name="qual_output" label="" >
+            <filter>qual</filter>
+        </data>
+        <data format="tax" name="tax_output" label="" >
+            <filter>tax'</filter>
+        </data>
+    </outputs>
+</tool>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jalview/vmap_rnaindex.py	Sun Sep 22 19:13:07 2013 -0400
@@ -0,0 +1,29 @@
+from argparse import ArgumentParser
+import os
+from vmap import RNAIndex
+
+if __name__ == "__main__":
+    
+    
+    parser = ArgumentParser()
+    
+    a = parser.add_argument
+    a("-o","--html_file",dest="html_file")
+    a("-d","--dir",dest="directory")
+      
+    (options,args)= parser.parse_known_args()
+    
+    args.insert(0,"dummy")
+    try:
+        RNAIndex.run(argv=args)
+    except SystemExit:
+        f = open(options.html_file,'w')
+        rval = ["<html><head><title>STAR Index Galaxy Composite Dataset </title></head><body><p/>\n"]
+        rval.append('<div>This composite dataset is composed of the following files:<p/><ul>')
+        flist = os.listdir(options.directory)
+        for file in flist:
+           rval.append( '<li><a href="%s">%s</a></li>' % ( file, file) )
+        rval.append( '</ul></body></html>' )
+    
+        f.write("\n".join( rval ))
+        f.close() 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jalview/vmap_rnamap.xml	Sun Sep 22 19:13:07 2013 -0400
@@ -0,0 +1,183 @@
+<tool id="vmap_rnamap" name="Virana RNAMap">
+
+<description>Map input reads against a STAR index. </description>
+
+	<requirements>
+        <requirement type="package" version="2.3.0">STAR</requirement>
+        <requirement type="package" version="0.1.19">samtools</requirement>
+        <requirement type="package" version="1.0">vmap_python</requirement>
+    </requirements>
+
+    <command interpreter="python">vmap.py rnamap
+    
+    
+    
+    --reads $reads
+    
+    #if $paired.select_paired == "paired"
+        --reads $paired.paired_read
+    #end if
+    
+    #if $refseq
+        #set $groups = str($refseq).split(",")
+        #for $ref in $groups:
+            --virana_hit_filter $ref
+        #end for
+    #end if
+        
+
+        #if $bam
+            --bam $bam_output
+        #end if
+        
+        #if $sam
+            --sam $sam_output
+        #end if
+        
+        #if $output_type.hit
+            --virana_hits $hit_output
+            
+            $output_type.filter_complexity
+            
+            #if $output_type.max_mismatches
+                --max_mismatches $output_type.max_mismatches
+            #end if
+            
+            #if $output_type.max_relative_mismatches
+                --max_relative_mismatches $output_type.max_relative_mismatches
+            #end if
+            
+            #if $output_type.min_alignment_score
+                --min_alignment_score $output_type.min_alignment_score
+            #end if
+            
+            #if $output_type.min_continiously_matching
+                --min_continiously_matching $output_type.min_continiously_matching
+            #end if
+            
+            #if $output_type.min_mapping_score
+                --min_mapping_score $output_type.min_mapping_score
+            #end if
+       #end if
+       #if $qual
+            --qual $qual_output
+       #end if
+        
+       #if $tax
+            --taxonomy $tax_output
+       #end if
+        #if $chimeric
+            --chimeric_mappings $chimeric_output
+        #end if
+        #if $unmapped
+            --unmapped_end_1 $unmapped1_output
+            #if $paired.select_paired == "paired"
+                --unmapped_end_2 $unmapped2_output
+            #end if
+        #end if
+    
+    #if $sample_id:
+        --sample_id $sample_id
+    #end if 
+        
+    #if $splice_junctions:
+        --splice_junctions $splice_junctions
+    #end if
+    
+    --index_dir $index.extra_files_path
+    
+    $sensitive
+    
+    2&gt;&amp;1
+        
+    </command>
+    
+    <inputs>
+        <param name="reads" type="data" format="fastq" label="Read file"/>
+        
+        <conditional name="paired">
+            <param name="select_paired" type="select" label="Paired end reads?" >
+                <option value="single">single end</option>
+                <option value="paired">paired end</option>
+            </param>
+            
+           <when value="paired">
+                <param name="paired_read" type="data" format="fastq" label="Paired end read file" />
+           </when>
+        
+        </conditional>
+        <conditional name="output_type">
+            <param name="hit" type="boolean" label="Hit Output"/>
+                           
+            <when value="hit">
+                <param name="max_mismatches" type="integer" min="0" max="10000000"  optional="true" label="Maximum number of mismatches for saved hits"/>
+                <param name="max_relative_mismatches" type="float" min="0" max="1" optional="true" label="Maximum number of mismatches relative to read length for saved hits " />
+                <param name="min_continiously_matching" type="integer" min="0" max="10000000" optional="true" label="Minimum number of continious matches for saved hits"  />
+                <param name="min_mapping_score" type="integer" min="1" max="255"  optional="true" label="Mimimum mapping score for saved hit"  />        
+                <param name="filter_complexity" type="boolean" truevalue="--filter_complexity" falsevalue="" label="Discard low-complexity reads"/>
+                <param name="min_alignment_score" type="integer" min="0" max="255" optional="true" label="Mimimum alignment score for reported hits"/>
+
+            </when>
+        
+        </conditional>
+        
+        <param name="bam" type="boolean" label="BAM Output"/>
+        <param name="sam" type="boolean" label="SAM Output"/>
+        <param name="qual" type="boolean"  label="Quality Output"/>
+        <param name="tax" type="boolean"  label="Taxonomy Output"/>
+        <param name="chimeric" type="boolean" label="Chimeric Mapping Ouput" />
+        <param name="unmapped" type="boolean" label="Unmapped Reads Output" />
+        
+        <param name="refseq" type="select" label="Set RefSeq taxonomic groups" multiple="true" display="checkboxes" optional="true">
+            <option value="UniVec">UniVec</option>
+            <option value="rRNA">rRNA</option>
+            <option value="Homo_sapiens">Homo sapiens</option>
+            <option value="Fungi">Fungi</option>
+            <option value="Plasmids">Plasmids</option>
+            <option value="Protozoa">Protozoa</option>
+            <option value="Viruses">Viruses</option>
+            <option value="Homo_sapiens_cDNA">Homo sapiens cDNA</option>
+            <option value="Fungi_DRAFT">Fungi DRAFT</option>
+            <option value="Bacteria">Bacteria</option>
+            <option value="Bacteria_DRAFT">Bacteria DRAFT</option>
+        </param>
+        
+        <param name="splice_junctions" type="data" format="txt" optional="true" label="splice junction file"/>
+        
+        <param name="index" type="data" format="star_index" label="STAR Index files"/>
+        
+        <param name="sample_id" type="text" optional="true" label="String used to designate sample information within the hit file"/>
+        
+        <param name="sensitive" type="boolean" truevalue="--sensitive" falsevalue="" label="If given, mapping will process slower and more sensitive"/>
+
+    </inputs>
+    
+    
+    <outputs>
+        <data format="hit" name="hit_output" label="">
+            <filter>output_type['hit']</filter>
+        </data>
+        <data format="bam" name="bam_output" label="" >
+            <filter>bam</filter>
+        </data>
+        <data format="sam" name="sam_output" label="">
+            <filter>sam</filter>
+        </data>
+        <data format="txt" name="qual_output" label="" >
+            <filter>qual</filter>
+        </data>
+        <data format="txt" name="tax_output" label="" >
+            <filter>tax</filter>
+        </data>
+        <data format="sam" name="chimeric_output" label="" >
+            <filter>chimeric</filter>
+        </data>
+        <data format="fastq" name="unmapped1_output" label="" >
+            <filter>unmapped</filter>
+        </data>
+        <data format="fastq" name="unmapped2_output" label="" >
+            <filter>unmapped</filter>
+            <filter> paired['select_paired'] == 'paired'</filter>
+        </data>
+    </outputs>
+</tool>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jalview/vref.py	Sun Sep 22 19:13:07 2013 -0400
@@ -0,0 +1,582 @@
+#!/usr/bin/env python
+
+import sys
+import logging
+import gzip
+import string
+import os
+import tarfile
+
+from io import BytesIO
+from collections import defaultdict
+
+try:
+    from Bio.SeqRecord import SeqRecord
+    from Bio import SeqIO
+except ImportError:
+    message = 'This script requires the BioPython python package\n'
+    sys.stderr.write(message)
+    sys.exit(1)
+
+try:
+    from plumbum import cli
+except ImportError:
+    message = 'This script requires the plumbum python package\n'
+    sys.stderr.write(message)
+    sys.exit(1)
+
+try:
+    import ftputil
+except ImportError:
+    message = 'This script requires the ftputil python package\n'
+    sys.stderr.write(message)
+    sys.exit(1)
+
+
+NON_ID = ''.join(c for c in map(chr, range(256)) if not c.isalnum())
+NON_ID = NON_ID.replace('_', '').replace('-', '')
+NUC_TRANS = string.maketrans('uryswkmbdhvURYSWKMBDHV', 'tnnnnnnnnnnTNNNNNNNNNN')
+
+logging.basicConfig(level=logging.INFO, format='%(message)s')
+
+
+class DataDownloader(object):
+    """ Generic class for downloading fasta records via FTP. """
+
+    def __init__(self, host_name, base_path, user='anonymous', password='anonymous'):
+
+        self.group     = 'NoGroup'
+        self.host_name = host_name
+        self.base_path = base_path
+
+        self.host = ftputil.FTPHost(host_name, user, password)
+        self.host.chdir(base_path)
+
+    @classmethod
+    def _get_fasta_record(self, record, group, family, organism, identifier, sub_identifier=None, description=''):
+
+        record.seq._data = record.seq._data.translate(NUC_TRANS)
+
+        group       = group.translate(None, NON_ID)
+        family      = family.translate(None, NON_ID)
+        organism    = organism.translate(None, NON_ID)
+        identifier  = identifier.translate(None, NON_ID)
+
+        if sub_identifier:
+            sub_identifier = sub_identifier.translate(None, NON_ID)
+            record.id  = ';'.join([group, family, organism, identifier, sub_identifier])
+        else:
+            record.id           = ';'.join([group, family, organism, identifier])
+
+        record.description  = description
+        record.name         = ''
+
+        return record
+
+    def get_fasta_records(self):
+
+        raise NotImplementedError
+
+class SilvaDownlaoder(DataDownloader):
+    """ Downlaods rRNA transcripts from the Silva database. """
+
+    def __init__(self, silva_release='111'):
+
+        self.silva_release      = silva_release
+        self.silva_host_name    = 'ftp.arb-silva.de'
+        self.base_path          = '/release_%s/Exports/' % self.silva_release
+
+        super(SilvaDownlaoder, self).__init__(self.silva_host_name, self.base_path)
+
+        self.group = 'rRNA'
+
+    def get_fasta_records(self):
+
+        remote_path = self.base_path + 'SSURef_%s_NR_tax_silva_trunc.fasta.tgz' % self.silva_release
+        if self.host.path.isfile(remote_path):
+
+            with self.host.file(remote_path, 'rb') as remote_handle:
+                remote_content = BytesIO(remote_handle.read())
+
+                with tarfile.open(fileobj=remote_content) as tar:
+
+                    for subentry in tar.getnames():
+                        if subentry.endswith('.fasta'):
+                            logging.debug('Processing rRNA file %s' % subentry)
+                            subhandle = tar.extractfile(subentry)
+
+                            for record in SeqIO.parse(subhandle, "fasta"):
+                                identifier  = record.id.split('.')[0]
+                                description = '_'.join(record.description.split(' ')[1:])
+                                taxonomy    = description.split(';')
+                                organism    = taxonomy[-1]
+                                family      = 'Unassigned'
+
+                                for level in taxonomy:
+                                    if level.endswith('eae'):
+                                        family = level
+                                        break
+
+                                yield self._get_fasta_record(record, self.group, family, organism, identifier)
+
+class HumanTranscriptDownloader(DataDownloader):
+    """ Downloads human transcripts fasta records that contain the locations
+        of their exons on the human genome within their description line.
+    """
+
+    def __init__(self):
+
+        self.ensemble_host_name  = 'ftp.ensembl.org'
+        self.gtf_path            = '/pub/current_gtf/homo_sapiens'
+        self.cdna_path           = '/pub/current_fasta/homo_sapiens/cdna'
+        self.ncrna_path          = '/pub/current_fasta/homo_sapiens/ncrna'
+
+        super(HumanTranscriptDownloader, self).__init__(self.ensemble_host_name, self.gtf_path)
+
+        self.chromosomes    = set()
+        self.genes          = defaultdict(set)
+        self.regions        = defaultdict(set)
+        self.group          = 'Homo_sapiens_cDNA'
+
+    def _cache_annotations(self):
+        """ Obtains gtf annotations for human transcripts from ensemble and
+            caches them in memory.
+        """
+
+        self.host.chdir(self.gtf_path)
+
+        entries = self.host.listdir(self.host.curdir)
+
+        for entry in entries:
+
+            if self.host.path.isfile(entry):
+                if entry.startswith('Homo_sapiens.') and entry.endswith('.gtf.gz'):
+                    logging.debug('Processing cDNA annotations %s' % entry)
+
+                    with self.host.file(self.gtf_path + '/' + entry, 'rb') as zipped_handle:
+                        remote_content = BytesIO(zipped_handle.read())
+
+                        with gzip.GzipFile(fileobj=remote_content) as gzipfile:
+                            for i, gtf_line in enumerate(gzipfile):
+                                if i % 100000 == 0:
+                                    logging.debug('Cached %i human transcript annotations' % i)
+
+                                self._add_annotation(gtf_line)
+
+    def _get_raw_transcripts(self):
+        """ Obtains coding and noncoding human transcripts from ensemble and
+            yields them as fasta records if they have exons that have a known location
+            on the human genome. Fasta records contain the exon locations in their header
+            lines.
+        """
+
+        for subpath in [self.cdna_path, self.ncrna_path]:
+
+            self.host.chdir(subpath)
+
+            entries = self.host.listdir(self.host.curdir)
+
+            for entry in entries:
+                if self.host.path.isfile(entry):
+                    if entry.endswith('cdna.all.fa.gz') or entry.endswith('ncrna.fa.gz'):
+
+                        logging.debug('Processing human transcript file %s' % entry)
+
+                        with self.host.file(subpath + '/' + entry, 'rb') as zipped_handle:
+                            remote_content = BytesIO(zipped_handle.read())
+
+                            with gzip.GzipFile(fileobj=remote_content) as gzipfile:
+                                for i, record in enumerate(SeqIO.parse(gzipfile, "fasta")):
+
+                                    if record.id.startswith('ENST'):
+
+                                        if i % 100000 == 0:
+                                            logging.debug('Retrieved %i human transcripts' % i)
+
+                                        record.description = ''
+
+                                        yield record
+
+    def _add_annotation(self, gtf_line):
+        """ Parses gtf annotations and stores them in memory. """
+
+        if gtf_line[0] == '#':
+            return
+
+        fields = gtf_line.strip().split('\t')
+        chromosome, source, feature, start, end, score, strands, frame, attributes\
+                                                                    = fields
+
+        start, end = sorted([int(start), int(end)])
+
+        if feature != 'exon':
+            return
+
+        attributes = attributes.replace(' ', '').split(';')
+        transcript_ids = [identifier.split('"')[1] for identifier in attributes\
+                                if identifier.startswith('transcript_id')]
+
+        gene_names = [identifier.split('"')[1] for identifier in attributes\
+                                if identifier.startswith('gene_name')]
+
+        for transcript_id in transcript_ids:
+            self.genes[transcript_id] = self.genes[transcript_id].union(gene_names)
+            self.regions[transcript_id].add((chromosome, start, end))
+
+    def get_fasta_records(self):
+        """ Yields annotated fasta records of human transcripts. """
+
+        logging.debug('Caching annotations')
+        self._cache_annotations()
+
+        logging.debug('Downloading and annotating transcripts')
+        for record in self._get_raw_transcripts():
+            transcript_id   = record.id
+
+            if transcript_id in self.regions:
+
+                mapping_locations = self.regions[transcript_id]
+
+                description = '|'.join([';'.join(map(str, location))\
+                        for location in mapping_locations])
+
+                # Obtain gene name for transcript
+                gene_names = self.genes[transcript_id]
+                if gene_names:
+                    gene_name = list(gene_names)[0]
+                else:
+                    gene_name = transcript_id
+
+                yield self._get_fasta_record(record, self.group , 'Hominidae', 'Homo_sapiens', gene_name, sub_identifier=transcript_id, description=description)
+
+class RefSeqDownloader(DataDownloader):
+    """ Generic downloader that known how to interpret and parse genbank records """
+
+    def __init__(self, group):
+
+        self.refseq_host_name  = 'ftp.ncbi.nih.gov'
+        self.base_path         = '/genomes/' + group
+
+        super(RefSeqDownloader, self).__init__(self.refseq_host_name, self.base_path)
+
+        self.group              = group
+
+
+    @classmethod
+    def _get_project_from_genbank(self, gb_record):
+        """ Parses genbank project identifier from genbank record. """
+
+        project = ''
+        for dbxref in gb_record.dbxrefs:
+            for entry in dbxref.split(' '):
+                if entry.startswith('BioProject'):
+                    project = entry.split(':')[1]
+                    return project
+
+        if not project:
+            for dbxref in gb_record.dbxrefs:
+                for entry in dbxref.split(' '):
+                    if entry.startswith('Project'):
+                        project = entry.split(':')[1]
+                        return project
+
+        return project
+
+    @classmethod
+    def _get_annotations_from_genbank(self, gb_record):
+        """ Parses taxonomic annotation from genbank record. """
+
+        accession   = gb_record.annotations['accessions'][0]
+        organism    = gb_record.annotations['organism'].replace(' ', '_')
+        organism    = '_'.join(organism.split('_')[:2])
+        taxonomy    = ("; ").join(gb_record.annotations['taxonomy'])
+        gi          = gb_record.annotations['gi']
+
+        family      = 'Unassigned'
+        if len(gb_record.annotations['taxonomy']) > 0:
+            for level in gb_record.annotations['taxonomy']:
+                if level.endswith('dae') or level.endswith('aceae'):
+                    family = level
+                    break
+
+        if family == 'Unassigned':
+            logging.debug('Unassigned family found based on %s' % taxonomy)
+
+        return organism, accession, gi, taxonomy, family
+
+    @classmethod
+    def _get_record_from_genbank(self, gb_record):
+        """ Parses sequence from genbank record. """
+
+        return SeqRecord(gb_record.seq)
+
+    @classmethod
+    def _parse_genbank_records(self, file_handle):
+
+        for gb_record in SeqIO.parse(file_handle, 'genbank'):
+
+            project = self._get_project_from_genbank(gb_record)
+            organism, accession, gi, taxonomy, family =\
+                self._get_annotations_from_genbank(gb_record)
+            record = self._get_record_from_genbank(gb_record)
+
+            if len(record) > 0:
+                yield record, project, taxonomy, family, organism, gi
+
+    def _get_nc(self, entry_path):
+
+        if self.host.path.isfile(entry_path):
+            logging.debug('Processing refseq entry %s' % entry_path)
+            remote_handle = self.host.file(entry_path)
+            
+
+            for record, project, taxonomy, family, organism, gi\
+                in self._parse_genbank_records(remote_handle):
+
+                cleaned = self._get_fasta_record(record, self.group , family, organism, gi)
+
+                yield cleaned
+
+    def _get_nz(self, entry_path):
+
+        scaffold_path = entry_path.replace('.gbk', '.scaffold.gbk.tgz')
+        if self.host.path.isfile(scaffold_path):
+            logging.debug('Processing refseq entry %s' % scaffold_path)
+            with self.host.file(scaffold_path, 'rb') as remote_handle:
+                remote_content = BytesIO(remote_handle.read())
+                with tarfile.open(fileobj=remote_content) as tar:
+                    for subentry in tar.getnames():
+                        if subentry.endswith('.gbk'):
+                            logging.debug('Processing subaccession %s' % subentry)
+                            subhandle = tar.extractfile(subentry)
+                            for record, project, taxonomy, family, organism, gi in self._parse_genbank_records(subhandle):
+                                yield self._get_fasta_record(record, self.group , family, organism, gi)
+
+
+    def get_fasta_records(self):
+
+        species_dirs = self.host.listdir(self.host.curdir)
+
+        for species_dir in species_dirs:
+
+            species_path = self.base_path + '/' + species_dir
+
+            if self.host.path.isdir(species_path):
+
+                self.host.chdir(species_path)
+
+                logging.debug('Processing species directory %s' % species_path)
+
+                if self.host.path.isdir(species_path):
+
+                    self.host.chdir(species_path)
+
+                    entries = self.host.listdir(self.host.curdir)
+
+                    for entry in entries:
+
+                        if self.host.path.isfile(self.host.curdir + '/' + entry):
+
+                            if entry.endswith('.gbk') or entry.endswith('.gbk.gz'):
+
+                                logging.debug('Processing entry %s' % entry)
+
+                                entry_path = species_path + '/' + entry
+
+                                if entry.startswith('NC_'):
+                                    for record in self._get_nc(entry_path):
+                                        yield record
+
+                                elif entry.startswith('NZ_'):
+                                    for record in self._get_nz(entry_path):
+                                        yield record
+
+class HumanGenomeDownloader(DataDownloader):
+
+    def __init__(self):
+
+        self.ensemble_host_name  = 'ftp.ensembl.org'
+        self.base_path           = '/pub/current_fasta/homo_sapiens/dna'
+
+        super(HumanGenomeDownloader, self).__init__(self.ensemble_host_name, self.base_path)
+
+        self.group          = 'Homo_sapiens'
+
+    def get_fasta_records(self):
+
+        entries = self.host.listdir(self.host.curdir)
+        for entry in entries:
+
+            if self.host.path.isfile(entry):
+
+                # You may want to change your filtering criteria here if you would like to include patches and haplotypes
+                if entry.endswith('fa.gz') and 'dna_sm.primary_assembly' in entry:
+
+                    logging.debug('Processing human entry %s' % entry)
+
+                    with self.host.file(self.host.getcwd() + '/' + entry, 'rb') as zipped_handle:
+                        remote_content = BytesIO(zipped_handle.read())
+
+                        with gzip.GzipFile(fileobj=remote_content) as gzipfile:
+
+                            for record in SeqIO.parse(gzipfile, "fasta"):
+
+                                identifier      = record.id
+                                organism        = 'Homo_sapiens'
+                                family          = 'Hominidae'
+
+                                yield self._get_fasta_record(record, self.group, family, organism, identifier)
+
+class UniVecDownloader(DataDownloader):
+
+    def __init__(self):
+
+        self.univec_host_name  = 'ftp.ncbi.nih.gov'
+        self.base_path         = '/pub/UniVec'
+
+        super(UniVecDownloader, self).__init__(self.univec_host_name, self.base_path)
+
+        self.group          = 'UniVec'
+
+    def get_fasta_records(self):
+
+        logging.debug('Processing Univec entries')
+
+        with self.host.file(self.host.getcwd() + '/' + 'UniVec') as remote_handle:
+            for record in SeqIO.parse(remote_handle, "fasta"):
+                organism    = '_'.join(record.description.split(' ')[1:])
+                family      = 'Unassigned'
+                identifier  = '000000000'
+
+                yield self._get_fasta_record(record, self.group, family, organism, identifier)
+
+class CLI(cli.Application):
+    """"""
+    PROGNAME = "metamap"
+    VERSION = "1.0.0"
+    DESCRIPTION = """"""
+
+    def main(self, *args):
+
+        if args:
+            print("Unknown command %r" % (args[0]))
+            print self.USAGE
+            return 1
+
+        if not self.nested_command:
+            print("No command given")
+            print self.USAGE
+            return 1
+
+@CLI.subcommand("fasta")
+class References(cli.Application):
+    """ Obtains NCBI RefSeq and Ensembl reference genomes and transcripts"""
+
+    valid_references = ['Fungi', 'Fungi_DRAFT', 'Bacteria',
+              'Bacteria_DRAFT', 'Homo_sapiens',
+              'Viruses', 'UniVec', 'Plasmids',
+              'Protozoa', 'rRNA', 'Homo_sapiens_cDNA']
+
+    references = cli.SwitchAttr(['-r', '--reference'],
+                                   cli.Set(*valid_references, case_sensitive=True),
+                                   list=True, default=valid_references,
+                                   mandatory=False,
+                                   help="Sets the kind of references to obtain")
+
+    fasta_path  = cli.SwitchAttr(['-o', '--output_file'], str, mandatory=True,
+                                 help="Sets the fasta output file")
+
+    zipped      = cli.Flag(["-z", "--zipped"], help="Write gzipped output")
+    debug       = cli.Flag(["-d", "--debug"], help="Enable debug messages")
+
+
+    def main(self):
+        """ Downloads genome fasta files from reference databases"""
+
+        if self.debug:
+            logging.getLogger().setLevel(logging.DEBUG)
+
+        if os.path.dirname(self.fasta_path) and not os.path.exists(os.path.dirname(self.fasta_path)):
+            logging.debug('Making directories for output file %s' % self.fasta_path)
+            os.makedirs(os.path.dirname(self.fasta_path))
+
+        if self.zipped:
+            logging.debug('Making zipped output file %s' % self.fasta_path)
+            output_file = gzip.open(self.fasta_path, 'wb')
+
+        else:
+            logging.debug('Making regular output file %s' % self.fasta_path)
+            output_file = open(self.fasta_path, 'w', buffering=100 * 1024 * 1024)
+
+
+        for reference in self.references:
+
+            if reference == 'UniVec':
+                downloader = UniVecDownloader()
+            elif reference == 'Homo_sapiens':
+                downloader = HumanGenomeDownloader()
+            elif reference == 'rRNA':
+                downloader = SilvaDownlaoder()
+            elif reference == 'Homo_sapiens_cDNA':
+                downloader = HumanTranscriptDownloader()
+            else:
+                downloader = RefSeqDownloader(group=reference)
+
+            for record in downloader.get_fasta_records():
+                SeqIO.write([record], output_file, "fasta")
+
+        output_file.close()
+
+@CLI.subcommand("blast")
+class Blast(cli.Application):
+    """ Obtains blast databases """
+
+    valid_references = ['nt', 'nr']
+
+    references = cli.SwitchAttr(['-r', '--reference_database'],
+                                   cli.Set(*valid_references, case_sensitive=True),
+                                   list=True, default=valid_references,
+                                   mandatory=False,
+                                   help="Sets the kind of database to obtain")
+
+    database_path  = cli.SwitchAttr(['-o', '--output_path'], str, mandatory=True,
+                                 help="Sets the fasta output file")
+
+    debug       = cli.Flag(["-d", "--debug"], help="Enable debug messages")
+
+    def main(self):
+        """ Downloads blast database files """
+
+        if self.debug:
+            logging.getLogger().setLevel(logging.DEBUG)
+
+        if not os.path.exists(self.database_path):
+            logging.debug('Making output directory %s' % self.database_path)
+            os.makedirs(self.database_path)
+
+        host_name = 'ftp.ncbi.nih.gov'
+        host = ftputil.FTPHost(host_name, 'anonymous', 'anonymous')
+
+        for reference in self.references:
+
+            path = '/blast/db'
+            host.chdir(path)
+
+            entries = host.listdir(host.curdir)
+
+            for entry in entries:
+
+                if host.path.isfile(entry):
+
+                    if entry.startswith(reference) and entry.endswith('.tar.gz'):
+                        logging.debug('Downloading %s' % entry)
+                        local_path = os.path.join(self.database_path, entry)
+                        host.download(entry, local_path, 'b')
+                        logging.debug('Unpacking %s' % entry)
+                        tfile = tarfile.open(local_path, 'r:gz')
+                        tfile.extractall(self.database_path)
+                        os.remove(local_path)
+
+if __name__ == "__main__":
+    CLI.run()
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jalview/vref_blast.xml	Sun Sep 22 19:13:07 2013 -0400
@@ -0,0 +1,36 @@
+<tool id="vref_blast" name="Virana Blast References">
+
+<description>Obtains blast databases. </description>
+
+	<requirements>
+        <requirement type="package" version="1.0">vref_python</requirement>
+    </requirements>
+
+    <command interpreter="python">vref.py blast --output_path $output 
+    
+    #if $database
+        #set $groups = str($database).split(",")
+        #for $ref in $groups:
+            --reference_database $ref
+        #end for
+    #end if
+    
+    
+    </command>
+    
+    
+    <inputs>
+        <param name="database" type="select" label="choose BLAST databases" multiple="true" display="checkboxes">
+            <option value="nr">nr</option>
+            <option value="nt">nt</option>
+        </param>
+
+    
+    </inputs>
+    
+        
+    <outputs>
+        <data format="blastdb" name="output" label="blast_ref.blastdb"/>
+    </outputs>
+
+</tool>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jalview/vref_fasta.xml	Sun Sep 22 19:13:07 2013 -0400
@@ -0,0 +1,47 @@
+<tool id="vref_fasta" name="Virana References">
+
+<description>Obtains NCBI RefSeq and Ensembl reference genomes. </description>
+
+	<requirements>
+        <requirement type="package" version="1.0">vref_python</requirement>
+    </requirements>
+
+    <command interpreter="python">vref.py fasta --output_file $output 
+        
+    #if $refseq
+        #set $groups = str($refseq).split(",")
+        #for $ref in $groups:
+            --reference $ref
+        #end for
+    #end if
+    
+    
+    $zipped
+       
+    2&gt;&amp;1
+    </command>
+    
+    <inputs>
+        <param name="refseq" type="select" label="Set RefSeq taxonomic groups" multiple="true" display="checkboxes">
+            <option value="UniVec">UniVec</option>
+            <option value="rRNA">rRNA</option>
+            <option value="Homo_sapiens">Homo sapiens</option>
+            <option value="Fungi">Fungi</option>
+            <option value="Plasmids">Plasmids</option>
+            <option value="Protozoa">Protozoa</option>
+            <option value="Viruses">Viruses</option>
+            <option value="Homo_sapiens_cDNA">Homo sapiens cDNA</option>
+            <option value="Fungi_DRAFT">Fungi DRAFT</option>
+            <option value="Bacteria">Bacteria</option>
+            <option value="Bacteria_DRAFT">Bacteria DRAFT</option>
+        </param>
+        
+        <param name="zipped" type="boolean" label="check for zipped output?" truevalue="--zipped" falsevalue=""/>
+
+    </inputs>
+    
+    
+    <outputs>
+        <data format="fasta" name="output" label="references.fasta"/>
+    </outputs>
+</tool>
\ No newline at end of file
Binary file jalview/wsdl4j.jar has changed
Binary file jalview/xercesImpl.jar has changed
Binary file jalview/xml-apis.jar has changed