From faafc762bf92e753af85d09913df2e6b29e8a172 Mon Sep 17 00:00:00 2001 From: Jeremy Goecks Date: Wed, 4 May 2011 10:20:54 -0400 Subject: [PATCH] Trackster: enable a tool to be run on complete dataset or a visible region. --- lib/galaxy/web/controllers/tracks.py | 111 +++++++++++++-------------- static/scripts/packed/trackster.js | 2 +- static/scripts/trackster.js | 86 +++++++++++++++------ 3 files changed, 118 insertions(+), 81 deletions(-) diff --git a/lib/galaxy/web/controllers/tracks.py b/lib/galaxy/web/controllers/tracks.py index ddefb749f68..a0839f94cbc 100644 --- a/lib/galaxy/web/controllers/tracks.py +++ b/lib/galaxy/web/controllers/tracks.py @@ -645,16 +645,17 @@ class TracksController( BaseController, UsesVisualization, UsesHistoryDatasetAss return self.tracks_grid( trans, **kwargs ) @web.expose - def run_tool( self, trans, dataset_id, chrom, low, high, tool_id, **kwargs ): + def run_tool( self, trans, dataset_id, tool_id, chrom=None, low=None, high=None, **kwargs ): """ Run a tool on a subset of input data to produce a new output dataset that corresponds to a dataset that a user is currently viewing. """ - # Parameter checks. - if not chrom or not low or not high: - return messages.NO_DATA - low, high = int( low ), int( high ) + # Run tool on region if region is specificied. + run_on_region = False + if chrom and low and high: + run_on_region = True + low, high = int( low ), int( high ) # Dataset check. original_dataset = self.get_dataset( trans, dataset_id, check_ownership=False, check_accessible=True ) @@ -678,27 +679,23 @@ class TracksController( BaseController, UsesVisualization, UsesHistoryDatasetAss tool_params = tool.params_from_strings( tool_params, self.app ) # - # Convert input datasets so that region of dataset can be quickly - # extracted. - # TODO: Is it useful/necessary to create data subsets for all input - # datasets or only the original dataset (aka the dataset that the user - # is viewing)? Currently we create data subsets for all input datasets - # because this provides the best performance as the tool runs on small - # datasets. + # If running tool on region, convert input datasets (create indices) so + # that can regions of data can be quickly extracted. # messages_list = [] - for jida in original_job.input_datasets: - input_dataset = jida.dataset - # TODO: put together more robust way to determine if a dataset can be indexed. - if hasattr( input_dataset, 'get_track_type' ): - # Can index dataset. - track_type, data_sources = input_dataset.datatype.get_track_type() - # Convert to datasource that provides 'data' because we need to - # extract the original data. - data_source = data_sources[ 'data' ] - msg = self._convert_dataset( trans, input_dataset, data_source ) - if msg is not None: - messages_list.append( msg ) + if run_on_region: + for jida in original_job.input_datasets: + input_dataset = jida.dataset + # TODO: put together more robust way to determine if a dataset can be indexed. + if hasattr( input_dataset, 'get_track_type' ): + # Can index dataset. + track_type, data_sources = input_dataset.datatype.get_track_type() + # Convert to datasource that provides 'data' because we need to + # extract the original data. + data_source = data_sources[ 'data' ] + msg = self._convert_dataset( trans, input_dataset, data_source ) + if msg is not None: + messages_list.append( msg ) # Return any messages generated during conversions. return_message = _get_highest_priority_msg( messages_list ) @@ -706,41 +703,40 @@ class TracksController( BaseController, UsesVisualization, UsesHistoryDatasetAss return return_message # - # Set input datasets for tool. Input datasets are subsets of full - # datasets and are based on chrom, low, high. + # Set target history (the history that tool will use for inputs/outputs). + # If user owns dataset, put new data in original dataset's history; if + # user does not own dataset (and hence is accessing dataset via sharing), + # put new data in user's current history. # - - # If user is rerunning own tool, put new data in original dataset's - # history. If another user is running tool, put new data in current - # history. if original_dataset.history.user == trans.user: - working_history = original_dataset.history + target_history = original_dataset.history else: - working_history = trans.get_history( create=True ) - hda_permissions = trans.app.security_agent.history_get_default_permissions( working_history ) - messages_list = [] + target_history = trans.get_history( create=True ) + hda_permissions = trans.app.security_agent.history_get_default_permissions( target_history ) + + # + # Set input datasets for tool. If running on region, extract and use subset + # when possible. + # for jida in original_job.input_datasets: input_dataset = jida.dataset - if hasattr( input_dataset.datatype, 'get_track_type' ): - # - # Dataset can be indexed and hence a subset can be extracted. - # + if run_on_region and hasattr( input_dataset.datatype, 'get_track_type' ): + # Dataset is indexed and hence a subset can be extracted and used + # as input. track_type, data_sources = input_dataset.datatype.get_track_type() data_source = data_sources[ 'data' ] converted_dataset = input_dataset.get_converted_dataset( trans, data_source ) deps = input_dataset.get_converted_dataset_deps( trans, data_source ) - # # Create new HDA for input dataset's subset. - # new_dataset = trans.app.model.HistoryDatasetAssociation( extension=input_dataset.ext, \ - dbkey=input_dataset.dbkey, \ - create_dataset=True, \ - sa_session=trans.sa_session, - name="Subset [%s:%i-%i] of data %i" % \ - ( chrom, low, high, input_dataset.hid ), - visible=False ) - working_history.add_dataset( new_dataset ) + dbkey=input_dataset.dbkey, \ + create_dataset=True, \ + sa_session=trans.sa_session, + name="Subset [%s:%i-%i] of data %i" % \ + ( chrom, low, high, input_dataset.hid ), + visible=False ) + target_history.add_dataset( new_dataset ) trans.sa_session.add( new_dataset ) trans.app.security_agent.set_all_dataset_permissions( new_dataset.dataset, hda_permissions ) @@ -751,7 +747,7 @@ class TracksController( BaseController, UsesVisualization, UsesHistoryDatasetAss dependencies=deps ) data_provider.write_data_to_file( chrom, low, high, new_dataset.file_name ) - # TODO: size not working. + # TODO: (a) size not working; (b) need to set peek. new_dataset.set_size() new_dataset.info = "Data subset for trackster" new_dataset.set_dataset_state( trans.app.model.Dataset.states.OK ) @@ -761,18 +757,21 @@ class TracksController( BaseController, UsesVisualization, UsesHistoryDatasetAss tool_params[ jida.name ] = new_dataset # - # Start tool and handle outputs. + # Execute tool and handle outputs. # try: - subset_job, subset_job_outputs = tool.execute( trans, incoming=tool_params, history=working_history ) + subset_job, subset_job_outputs = tool.execute( trans, incoming=tool_params, history=target_history ) except Exception, e: # Lots of things can go wrong when trying to execute tool. return to_json_string( { "error" : True, "message" : e.__class__.__name__ + ": " + str(e) } ) - for output in subset_job_outputs.values(): - output.visible = False - trans.sa_session.flush() - + if run_on_region: + for output in subset_job_outputs.values(): + output.visible = False + trans.sa_session.flush() + + # # Return new track that corresponds to the original dataset. + # output_name = None for joda in original_job.output_datasets: if joda.dataset == original_dataset: @@ -784,9 +783,9 @@ class TracksController( BaseController, UsesVisualization, UsesHistoryDatasetAss return self.add_track_async( trans, output_dataset.id ) - # + # ----------------- # Helper methods. - # + # ----------------- def _check_dataset_state( self, trans, dataset ): """ diff --git a/static/scripts/packed/trackster.js b/static/scripts/packed/trackster.js index 68ea939176f..8dd61ce467e 100644 --- a/static/scripts/packed/trackster.js +++ b/static/scripts/packed/trackster.js @@ -1 +1 @@ -var class_module=function(b,a){var c=function(){var f=arguments[0];for(var e=1;ec){a=AFTER}else{if(f<=c){a=CONTAINED_BY}else{a=OVERLAP_END}}}return a};var is_overlap=function(c,b){var a=compute_overlap(c,b);return(a!==BEFORE&&a!==AFTER)};var trackster_module=function(f,T){var o=f("class").extend,q=f("slotting"),I=f("painters");var Z=function(aa,ab){this.document=aa;this.default_font=ab!==undefined?ab:"9px Monaco, Lucida Console, monospace";this.dummy_canvas=this.new_canvas();this.dummy_context=this.dummy_canvas.getContext("2d");this.dummy_context.font=this.default_font;this.char_width_px=this.dummy_context.measureText("A").width;this.patterns={};this.load_pattern("right_strand","/visualization/strand_right.png");this.load_pattern("left_strand","/visualization/strand_left.png");this.load_pattern("right_strand_inv","/visualization/strand_right_inv.png");this.load_pattern("left_strand_inv","/visualization/strand_left_inv.png")};o(Z.prototype,{load_pattern:function(aa,ae){var ab=this.patterns,ac=this.dummy_context,ad=new Image();ad.src=image_path+ae;ad.onload=function(){ab[aa]=ac.createPattern(ad,"repeat")}},get_pattern:function(aa){return this.patterns[aa]},new_canvas:function(){var aa=this.document.createElement("canvas");if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(aa)}aa.manager=this;return aa}});var C=function(aa,ab){aa.bind("drag",{handle:ab,relative:true},function(af,ag){var ae=$(this).parent();var ad=ae.children();var ac;for(ac=0;ac=this.num_elements){var aa=this.key_ary.shift();delete this.obj_cache[aa]}this.key_ary.push(ab)}this.obj_cache[ab]=ac;return ac},move_key_to_end:function(ab,aa){this.key_ary.splice(aa,1);this.key_ary.push(ab)},clear:function(){this.obj_cache={};this.key_ary=[]},size:function(){return this.key_ary.length}});var N=function(ab,aa,ac){c.call(this,ab);this.track=aa;this.subset=(ac!==undefined?ac:true)};o(N.prototype,c.prototype,{load_data:function(ai,aj,ae,ah,ab,ag){var ad={chrom:ai,low:aj,high:ae,mode:ah,resolution:ab,dataset_id:this.track.dataset_id,hda_ldda:this.track.hda_ldda};$.extend(ad,ag);if(this.track.filters_manager){var ak=[];var aa=this.track.filters_manager.filters;for(var af=0;af1){return}return N.prototype.load_data.call(this,ac,aa,ae,af,ab,ad)}});var Y=function(aa,ad,ac,ab,ae){this.container=aa;this.chrom=null;this.vis_id=ac;this.dbkey=ab;this.title=ad;this.tracks=[];this.label_tracks=[];this.max_low=0;this.max_high=0;this.num_tracks=0;this.track_id_counter=0;this.zoom_factor=3;this.min_separation=30;this.has_changes=false;this.init(ae);this.canvas_manager=new Z(aa.get(0).ownerDocument);this.reset()};o(Y.prototype,{init:function(ad){var ac=this.container,aa=this;this.top_container=$("
").addClass("top-container").appendTo(ac);this.content_div=$("
").addClass("content").css("position","relative").appendTo(ac);this.bottom_container=$("
").addClass("bottom-container").appendTo(ac);this.top_labeltrack=$("
").addClass("top-labeltrack").appendTo(this.top_container);this.viewport_container=$("
").addClass("viewport-container").addClass("viewport-container").appendTo(this.content_div);this.intro_div=$("
").addClass("intro").text("Select a chrom from the dropdown below").hide();this.nav_labeltrack=$("
").addClass("nav-labeltrack").appendTo(this.bottom_container);this.nav_container=$("
").addClass("nav-container").prependTo(this.top_container);this.nav=$("
").addClass("nav").appendTo(this.nav_container);this.overview=$("
").addClass("overview").appendTo(this.bottom_container);this.overview_viewport=$("
").addClass("overview-viewport").appendTo(this.overview);this.overview_close=$("Close Overview").addClass("overview-close").hide().appendTo(this.overview_viewport);this.overview_highlight=$("
").addClass("overview-highlight").hide().appendTo(this.overview_viewport);this.overview_box_background=$("
").addClass("overview-boxback").appendTo(this.overview_viewport);this.overview_box=$("
").addClass("overview-box").appendTo(this.overview_viewport);this.default_overview_height=this.overview_box.height();this.nav_controls=$("
").addClass("nav-controls").appendTo(this.nav);this.chrom_select=$("").addClass("nav-input").hide().bind("keyup focusout",ab).appendTo(this.nav_controls);this.location_span=$("").addClass("location").appendTo(this.nav_controls);this.location_span.bind("click",function(){aa.location_span.hide();aa.chrom_select.hide();aa.nav_input.val(aa.chrom+":"+aa.low+"-"+aa.high);aa.nav_input.css("display","inline-block");aa.nav_input.select();aa.nav_input.focus()});if(this.vis_id!==undefined){this.hidden_input=$("").attr("type","hidden").val(this.vis_id).appendTo(this.nav_controls)}this.zo_link=$("").click(function(){aa.zoom_out();aa.redraw()}).appendTo(this.nav_controls);this.zi_link=$("").click(function(){aa.zoom_in();aa.redraw()}).appendTo(this.nav_controls);this.load_chroms({low:0},ad);this.chrom_select.bind("change",function(){aa.change_chrom(aa.chrom_select.val())});this.intro_div.show();this.content_div.bind("click",function(ae){$(this).find("input").trigger("blur")});this.content_div.bind("dblclick",function(ae){aa.zoom_in(ae.pageX,this.viewport_container)});this.overview_box.bind("dragstart",function(ae,af){this.current_x=af.offsetX}).bind("drag",function(ae,ag){var ah=ag.offsetX-this.current_x;this.current_x=ag.offsetX;var af=Math.round(ah/aa.viewport_container.width()*(aa.max_high-aa.max_low));aa.move_delta(-af)});this.overview_close.bind("click",function(){for(var af=0,ae=aa.tracks.length;afaa.viewport_container.width()-16){return false}}).bind("dragstart",function(ae,af){af.original_low=aa.low;af.current_height=ae.clientY;af.current_x=af.offsetX}).bind("drag",function(ag,ai){var ae=$(this);var aj=ai.offsetX-ai.current_x;var af=ae.scrollTop()-(ag.clientY-ai.current_height);ae.scrollTop(af);ai.current_height=ag.clientY;ai.current_x=ai.offsetX;var ah=Math.round(aj/aa.viewport_container.width()*(aa.high-aa.low));aa.move_delta(ah)}).bind("mousewheel",function(ag,ai,af,ae){if(af){var ah=Math.round(-af/aa.viewport_container.width()*(aa.high-aa.low));aa.move_delta(ah)}});this.top_labeltrack.bind("dragstart",function(ae,af){return $("
").css({height:aa.content_div.height()+aa.top_labeltrack.height()+aa.nav_labeltrack.height()+1,top:"0px",position:"absolute","background-color":"#ccf",opacity:0.5,"z-index":1000}).appendTo($(this))}).bind("drag",function(ai,aj){$(aj.proxy).css({left:Math.min(ai.pageX,aj.startX),width:Math.abs(ai.pageX-aj.startX)});var af=Math.min(ai.pageX,aj.startX)-aa.container.offset().left,ae=Math.max(ai.pageX,aj.startX)-aa.container.offset().left,ah=(aa.high-aa.low),ag=aa.viewport_container.width();aa.update_location(Math.round(af/ag*ah)+aa.low,Math.round(ae/ag*ah)+aa.low)}).bind("dragend",function(aj,ak){var af=Math.min(aj.pageX,ak.startX),ae=Math.max(aj.pageX,ak.startX),ah=(aa.high-aa.low),ag=aa.viewport_container.width(),ai=aa.low;aa.low=Math.round(af/ag*ah)+ai;aa.high=Math.round(ae/ag*ah)+ai;$(ak.proxy).remove();aa.redraw()});this.add_label_track(new X(this,this.top_labeltrack));this.add_label_track(new X(this,this.nav_labeltrack));$(window).bind("resize",function(){aa.resize_window()});$(document).bind("redraw",function(){aa.redraw()});this.reset();$(window).trigger("resize")},update_location:function(aa,ab){this.location_span.text(commatize(aa)+" - "+commatize(ab));this.nav_input.val(this.chrom+":"+commatize(aa)+"-"+commatize(ab))},load_chroms:function(ab,ac){ab.num=u;$.extend(ab,(this.vis_id!==undefined?{vis_id:this.vis_id}:{dbkey:this.dbkey}));var aa=this;$.ajax({url:chrom_url,data:ab,dataType:"json",success:function(ae){if(ae.chrom_info.length===0){alert("Invalid chromosome: "+ab.chrom);return}if(ae.reference){aa.add_label_track(new y(aa))}aa.chrom_data=ae.chrom_info;var ah='';for(var ag=0,ad=aa.chrom_data.length;ag'+af+""}if(ae.prev_chroms){ah+='"}if(ae.next_chroms){ah+='"}aa.chrom_select.html(ah);if(ac){ac()}aa.chrom_start_index=ae.start_index},error:function(){alert("Could not load chroms for this dbkey:",aa.dbkey)}})},change_chrom:function(ae,ab,ag){if(!ae||ae==="None"){return}var ad=this;if(ae==="previous"){ad.load_chroms({low:this.chrom_start_index-u});return}if(ae==="next"){ad.load_chroms({low:this.chrom_start_index+u});return}var af=$.grep(ad.chrom_data,function(ai,aj){return ai.chrom===ae})[0];if(af===undefined){ad.load_chroms({chrom:ae},function(){ad.change_chrom(ae,ab,ag)});return}else{if(ae!==ad.chrom){ad.chrom=ae;if(!ad.chrom){ad.intro_div.show()}else{ad.intro_div.hide()}ad.chrom_select.val(ad.chrom);ad.max_high=af.len-1;ad.reset();ad.redraw(true);for(var ah=0,aa=ad.tracks.length;ahaa.max_high){aa.high=aa.max_high;aa.low=aa.max_high-ab}else{aa.high-=ac;aa.low-=ac}}aa.redraw()},add_track:function(aa){aa.view=this;aa.track_id=this.track_id_counter;this.tracks.push(aa);if(aa.init){aa.init()}aa.container_div.attr("id","track_"+aa.track_id);C(aa.container_div,".draghandle");this.track_id_counter+=1;this.num_tracks+=1},add_label_track:function(aa){aa.view=this;this.label_tracks.push(aa)},remove_track:function(aa){this.has_changes=true;aa.container_div.fadeOut("slow",function(){$(this).remove()});delete this.tracks[this.tracks.indexOf(aa)];this.num_tracks-=1},reset:function(){this.low=this.max_low;this.high=this.max_high;this.viewport_container.find(".yaxislabel").remove()},redraw:function(ah){var ag=this.high-this.low,af=this.low,ab=this.high;if(afthis.max_high){ab=this.max_high}if(this.high!==0&&ag").addClass("dynamic-tool").hide();this.parent_div.bind("drag",function(ao){ao.stopPropagation()}).bind("click",function(ao){ao.stopPropagation()}).bind("dblclick",function(ao){ao.stopPropagation()});var ak=$("
").appendTo(this.parent_div).text(this.name);var ai=this.params;var af=this;$.each(this.params,function(ap,at){var ar=$("
").addClass("param-row").appendTo(af.parent_div);var ao=$("
").addClass("param-label").text(at.label).appendTo(ar);var aq=$("
").addClass("slider").html(at.html).appendTo(ar);$("
").appendTo(ar)});this.parent_div.find("input").click(function(){$(this).select()});var an=$("
").addClass("slider-row").appendTo(this.parent_div);var ag=$("").attr("value","Run").appendTo(an);var af=this;ag.click(function(){af.run()})};o(p.prototype,{get_param_values_dict:function(){var aa={};this.parent_div.find(":input").each(function(){var ab=$(this).attr("name"),ac=$(this).val();aa[ab]=JSON.stringify(ac)});return aa},get_param_values:function(){var ab=[];var aa={};this.parent_div.find(":input").each(function(){var ac=$(this).attr("name"),ad=$(this).val();if(ac){ab[ab.length]=ad}});return ab},run:function(){var ab={dataset_id:this.track.original_dataset_id,chrom:this.track.view.chrom,low:this.track.view.low,high:this.track.view.high,tool_id:this.name};$.extend(ab,this.get_param_values_dict());var ad=this.track,ac=ab.tool_id+ad.tool_region_and_parameters_str(ab.chrom,ab.low,ab.high),ae;if(ad.track_type==="FeatureTrack"){ae=new Q(ac,view,ad.hda_ldda,undefined,{},{},ad)}this.track.add_track(ae);ae.content_div.text("Starting job.");var aa=function(){$.getJSON(run_tool_url,ab,function(af){if(af==="no converter"){ae.container_div.addClass("error");ae.content_div.text(G)}else{if(af.error){ae.container_div.addClass("error");ae.content_div.text(w+af.message)}else{if(af==="pending"){ae.container_div.addClass("pending");ae.content_div.text("Converting input data so that it can be easily reused.");setTimeout(aa,2000)}else{ae.dataset_id=af.dataset_id;ae.content_div.text("Running job.");ae.init()}}}})};aa()}});var K=function(ab,aa,ac){this.name=ab;this.label=aa;this.html=ac};var g=function(ac,ab,ae,ad,aa){K.call(this,ac,ab,ae);this.min=ad;this.max=aa};var j=function(ab,aa,ac){this.name=ab;this.index=aa;this.value=ac};var R=function(ab,aa){this.name=ab;this.index=aa;this.low=-Number.MAX_VALUE;this.high=Number.MAX_VALUE;this.min=Number.MAX_VALUE;this.max=-Number.MAX_VALUE;this.slider=null;this.slider_label=null};o(R.prototype,{applies_to:function(aa){if(aa.length>this.index){return true}return false},keep:function(aa){if(!this.applies_to(aa)){return true}var ab=parseInt(aa[this.index]);return(isNaN(ab)||(ab>=this.low&&ab<=this.high))},update_attrs:function(ab){var aa=false;if(!this.applies_to(ab)){return aa}if(ab[this.index]this.max){this.max=Math.ceil(ab[this.index]);aa=true}return aa},update_ui_elt:function(){var ab=this.slider.slider("option","min"),aa=this.slider.slider("option","max");if(this.minaa){this.slider.slider("option","min",this.min);this.slider.slider("option","max",this.max);this.slider.slider("option","step",h(this.min,this.max));this.slider.slider("option","values",[this.min,this.max])}}});var W=function(ac,ai){this.track=ac;this.filters=[];for(var ae=0;ae").attr("size",input_size).attr("maxlength",input_size).attr("value",am).appendTo(ak).focus().select().click(function(an){an.stopPropagation()}).blur(function(){$(this).remove();ak.text(am)}).keyup(function(ar){if(ar.keyCode===27){$(this).trigger("blur")}else{if(ar.keyCode===13){var ap=al.slider("option","min"),an=al.slider("option","max"),aq=function(at){return(isNaN(at)||at>an||at").addClass("filters").hide();this.parent_div.bind("drag",function(aj){aj.stopPropagation()}).bind("click",function(aj){aj.stopPropagation()}).bind("dblclick",function(aj){aj.stopPropagation()});var ad=this;$.each(this.filters,function(ap,ak){var am=$("
").addClass("slider-row").appendTo(ad.parent_div);var aj=$("
").addClass("slider-label").appendTo(am);var ar=$("").addClass("slider-name").text(ak.name+" ").appendTo(aj);var al=$("");var an=$("").addClass("slider-value").appendTo(aj).append("[").append(al).append("]");var aq=$("
").addClass("slider").appendTo(am);ak.control_element=$("
").attr("id",ak.name+"-filter-control").appendTo(aq);var ao=[0,0];ak.control_element.slider({range:true,min:Number.MAX_VALUE,max:-Number.MIN_VALUE,values:[0,0],slide:function(at,au){ao=au.values;al.text(au.values[0]+"-"+au.values[1]);setTimeout(function(){if(au.values[0]==ao[0]&&au.values[1]==ao[1]){var av=au.values;al.text(av[0]+"-"+av[1]);ak.low=av[0];ak.high=av[1];ad.track.draw(true,true)}},50)},change:function(at,au){ak.control_element.slider("option","slide").call(ak.control_element,at,au)}});ak.slider=ak.control_element;ak.slider_label=al;ag(an,al,ak.control_element);$("
").appendTo(am)})};var V=function(aa){this.track=aa.track;this.params=aa.params;this.values={};if(aa.saved_values){this.restore_values(aa.saved_values)}this.onchange=aa.onchange};o(V.prototype,{restore_values:function(aa){var ab=this;$.each(this.params,function(ac,ad){if(aa[ad.key]!==undefined){ab.values[ad.key]=aa[ad.key]}else{ab.values[ad.key]=ad.default_value}})},build_form:function(){var ab=this;var aa=$("
");$.each(this.params,function(af,ad){if(!ad.hidden){var ac="param_"+af;var ak=$("
").appendTo(aa);ak.append($("
").hide();var ae=$("
").appendTo(ai);var aj=$("
").appendTo(ae).farbtastic({width:100,height:100,callback:ag,color:ah});$("
").append(ag).append(ai).appendTo(ak).bind("click",function(al){ai.css({left:$(this).position().left+($(ag).width()/2)-60,top:$(this).position().top+$(this.height)}).show();$(document).bind("click.color-picker",function(){ai.hide();$(document).unbind("click.color-picker")});al.stopPropagation()})}else{ak.append($("").attr("id",ac).attr("name",ac).val(ab.values[ad.key]))}}}});return aa},update_from_form:function(aa){var ac=this;var ab=false;$.each(this.params,function(ad,af){if(!af.hidden){var ag="param_"+ad;var ae=aa.find("#"+ag).val();if(af.type==="float"){ae=parseFloat(ae)}else{if(af.type==="int"){ae=parseInt(ae)}else{if(af.type==="bool"){ae=aa.find("#"+ag).is(":checked")}}}if(ae!==ac.values[af.key]){ac.values[af.key]=ae;ab=true}}});if(ab){this.onchange()}}});var b=function(ac,ab,aa){this.index=ac;this.resolution=ab;this.canvas=$("
").append(aa)};var m=function(ac,ab,aa,ad){b.call(this,ac,ab,aa);this.max_val=ad};var L=function(ac,ab,aa){b.call(this,ac,ab,aa)};var k=function(ab,aa,ae,ac,ad){this.name=ab;this.view=aa;this.parent_element=ae;this.data_url=(ac?ac:default_data_url);this.data_url_extra_params={};this.data_query_wait=(ad?ad:H);this.dataset_check_url=converted_datasets_state_url;this.container_div=$("
").addClass("track").css("position","relative");if(!this.hidden){this.header_div=$("
").appendTo(this.container_div);if(this.view.editor){this.drag_div=$("
").appendTo(this.header_div)}this.name_div=$("