() => { var settings_leaf = param_tree.get_leaf(pm_track.get("settings").get("values")); var connected_node_ids = _.pluck(param_tree.get_connected_nodes(settings_leaf), "id"); // TODO: can do faster with enter? d3.select(self.tool_param_tree_view.$el[0]) .selectAll("g.node") .filter(d => _.find(connected_node_ids, id => id === d.id) !== undefined) .style("fill", "#f00"); },
handle_node_clicks: function() { // When node clicked in tree, run tool and add tracks to model. var self = this; var param_tree = this.model.get("parameter_tree"); var regions = this.model.get("regions"); var node = d3.select(this.tool_param_tree_view.$el[0]).selectAll("g.node"); node.on("click", (d, i) => { // Get all settings corresponding to node. var tool = self.model.get("tool"); var dataset = self.model.get("dataset"); var all_settings = param_tree.get_node_settings(d); var run_jobs_deferred = $.Deferred(); // Do not allow 10+ jobs to be run. if (all_settings.length >= 10) { show_modal( "Whoa there cowboy!", `You clicked on a node to try ${self.model.get("tool").get("name")} with ${ all_settings.length } different combinations of settings. You can only run 10 jobs at a time.`, { Ok: function() { hide_modal(); run_jobs_deferred.resolve(false); } } ); } else { run_jobs_deferred.resolve(true); } // Take action when deferred resolves. $.when(run_jobs_deferred).then(run_jobs => { if (!run_jobs) { return; } // Create and add tracks for each settings group. var new_tracks = _.map(all_settings, settings => { var pm_track = new SweepsterTrack({ settings: settings, regions: regions, mode: self.model.get("default_mode") }); self.add_track(pm_track); return pm_track; }); // For each track, run tool using track's settings and update track. _.each(new_tracks, (pm_track, index) => { setTimeout(() => { // Set inputs and run tool. tool.set_input_values(pm_track.get("settings").get("values")); $.when(tool.rerun(dataset, regions)).then(output => { // HACKish: output is an HDA with track config attribute. To create a track // that works correctly with Backbone relational, it is necessary to // use a modified version of the track config. var dataset = output.first(); var track_config = dataset.get("track_config"); // Set dataset to be the tool's output. track_config.dataset = dataset; // Set tool to null so that it is not unpacked; unpacking it messes with // the tool parameters and parameter tree. track_config.tool = null; track_config.prefs = self.config.to_key_value_dict(); // Create and add track for output dataset. var track_obj = tracks.object_from_template(track_config, self, null); track_obj.init_for_tool_data(); pm_track.set("track", track_obj); }); }, index * 10000); }); }); }); }
() => { d3.select(self.tool_param_tree_view.$el[0]) .selectAll("g.node") .style("fill", "#000"); }
render: function() { // Start fresh. this.$el.children().remove(); var tree_params = this.model.get_tree_params(); if (!tree_params.length) { return; } // Set width, height based on params and samples. this.width = 100 * (2 + tree_params.length); this.height = 15 * this.model.get_num_leaves(); var self = this; // Layout tree. var cluster = d3.layout.cluster().size([this.height, this.width - 160]); var diagonal = d3.svg.diagonal().projection(d => [d.y, d.x]); // Layout nodes. var nodes = cluster.nodes(this.model.get("tree_data")); // Setup and add labels for tree levels. var param_depths = _.uniq(_.pluck(nodes, "y")); _.each(tree_params, (param, index) => { var x = param_depths[index + 1]; var center_left = $("#center").position().left; self.$el.append( $("<div>") .addClass("label") .text(param.get("label")) .css("left", x + center_left) ); }); // Set up vis element. var vis = d3 .select(this.$el[0]) .append("svg") .attr("width", this.width) .attr("height", this.height + 30) .append("g") .attr("transform", "translate(40, 20)"); // Draw links. var link = vis .selectAll("path.link") .data(cluster.links(nodes)) .enter() .append("path") .attr("class", "link") .attr("d", diagonal); // Draw nodes. var node = vis .selectAll("g.node") .data(nodes) .enter() .append("g") .attr("class", "node") .attr("transform", d => `translate(${d.y},${d.x})`) .on("mouseover", a_node => { var connected_node_ids = _.pluck(self.model.get_connected_nodes(a_node), "id"); // TODO: probably can use enter() to do this more easily. node.filter(d => _.find(connected_node_ids, id => id === d.id) !== undefined).style("fill", "#f00"); }) .on("mouseout", () => { node.style("fill", "#000"); }); node.append("circle").attr("r", 9); node.append("text") .attr("dx", d => (d.children ? -12 : 12)) .attr("dy", 3) .attr("text-anchor", d => (d.children ? "end" : "start")) .text(d => d.name); }