diff --git a/deep_sequencing_unit/source/html/downloader/openbis-dendrogram.html b/deep_sequencing_unit/source/html/downloader/openbis-dendrogram.html index b3e7d67a3e4bc7b38466ad5bab8a808f0d3397cd..80b2085581a9cde30f82444b016923cee43181b7 100644 --- a/deep_sequencing_unit/source/html/downloader/openbis-dendrogram.html +++ b/deep_sequencing_unit/source/html/downloader/openbis-dendrogram.html @@ -97,6 +97,19 @@ function addSequencingSamplesToProject(project, bissamps) if (samples.length > 0) project.children = groupedSamples; + + // Get the flow lanes for each sequencing sample + var deferrer = + new actionDeferrer( + function() { updateDiagram(500) }, + samples.map(function(samp) { return samp.bis.code; })); + + samples.forEach(function(sample) { + dsu.retrieveFlowLanesForSequencingSample(sample, function(data) { + if (data.result) sample.flowlanes = data.result.map(function(flowlane) { return { bis : flowlane }}); + deferrer.dependencyCompleted(sample.bis.code); + }) + }); } @@ -221,13 +234,16 @@ function updateDiagram(duration) node.exit().transition() .duration(duration) - .attr("transform", translateDst) + .attr("transform", translateSrc) .remove(); } function classForNode(d) { + // Use whether the node has open children or not to compute the class var cssClass = hasChildren(d) ? "node withchildren" : "node leaf"; if (d.inspected) cssClass = cssClass + " inspected"; + if (d.flowlanes && d.flowlanes.length > 0) cssClass = cssClass + " sequenced"; + return cssClass; } @@ -259,6 +275,11 @@ function hasChildren(d) return d.children != null || d._children != null; } +function hasOpenChildren(d) +{ + return d.children != null; +} + // Toggle children on click. function toggle_open(d) { if (!hasChildren(d)) { @@ -303,6 +324,23 @@ function updateInspectors(duration) .text(function(d) { return d }) .transition() .style("opacity", "1"); + + var downloadTable = + box.append("table") + .attr("width", "100%") + .attr("class", "downloads") + .style("color", "steelblue"); + downloadTable.append("caption").text("Files"); + var downloadTableRow = downloadTable.append("tr"); + downloadTableRow + .append("td") + .style("text-align", "left") + .text("metadata.tsv"); + downloadTableRow + .append("td") + .style("border-right", "0px") + .style("text-align", "right") + .text("fastq.gz"); inspector.exit().transition() .duration(duration) @@ -316,15 +354,23 @@ function toggle_inspected(d) { var index = inspected.indexOf(d) if (index > -1) inspected.splice(index, 1); d.inspected = false; - d3.select(d.svgNode).attr("class", "node leaf") + d3.select(d.svgNode).attr("class", classForNode(d)) } else { d.inspected = true; inspected.push(d); - d3.select(d.svgNode).attr("class", "node leaf inspected") + d3.select(d.svgNode).attr("class", classForNode(d)) + retrieveFilesForSequencingSample(d); } updateInspectors(500); } +function retrieveFilesForSequencingSample(sequencing) +{ + // dsu.retrieveFastqGzDataSetsForFlowLane(sequencing, function(data) { + // sequencing.files = data.result; + // }); +} + /** * Convert properties to pairs */ diff --git a/deep_sequencing_unit/source/html/downloader/openbis-dsu.js b/deep_sequencing_unit/source/html/downloader/openbis-dsu.js index e5acbfa2fe0ce77329911583dbc727794ad23fa1..80f02391801d389dfde6e4823d6218baf41fa86d 100644 --- a/deep_sequencing_unit/source/html/downloader/openbis-dsu.js +++ b/deep_sequencing_unit/source/html/downloader/openbis-dsu.js @@ -106,6 +106,19 @@ openbis_dsu.prototype.retrieveSequencingSamplesForExperiment = function(experime */ openbis_dsu.prototype.retrieveFlowLanesForSequencingSample = function(sample, action) { + var experimentCriteria = + { + targetEntityKind : "EXPERIMENT", + criteria : { + matchClauses : + [ {"@type":"AttributeMatchClause", + "attribute":"PROJECT", + "fieldType":"ATTRIBUTE", + "desiredValue": sample.project.bis.code + } ] + } + }; + var parentCriteria = { targetEntityKind : "SAMPLE_PARENT", @@ -121,7 +134,7 @@ openbis_dsu.prototype.retrieveFlowLanesForSequencingSample = function(sample, ac var sampleCriteria = { - subCriterias : [ parentCriteria ], + subCriterias : [ experimentCriteria, parentCriteria ], matchClauses : [ {"@type":"AttributeMatchClause", attribute : "TYPE", @@ -137,24 +150,36 @@ openbis_dsu.prototype.retrieveFlowLanesForSequencingSample = function(sample, ac /** * Request the replicas for the grid */ -openbis_dsu.prototype.retrieveDataSetsForFlowLane = function(flowlane, action) +openbis_dsu.prototype.retrieveFastqGzDataSetsForFlowLane = function(flowlane, action) { var flowLaneCriteria = { targetEntityKind : "SAMPLE", criteria : { - matchClauses : - [ {"@type":"AttributeMatchClause", - "attribute":"CODE", - "fieldType":"ATTRIBUTE", - "desiredValue": flowlane.code - } ] + matchClauses : [ + {"@type":"AttributeMatchClause", + "attribute":"CODE", + "fieldType":"ATTRIBUTE", + "desiredValue": flowlane.bis.code + }, {"@type":"AttributeMatchClause", + "attribute":"SPACE", + "fieldType":"ATTRIBUTE", + "desiredValue": flowlane.project.bis.spaceCode + } + ] } }; var dataSetCriteria = { subCriterias : [ flowLaneCriteria ], + matchClauses : [ + {"@type":"AttributeMatchClause", + attribute : "TYPE", + fieldType : "ATTRIBUTE", + desiredValue : "FASTQ_GZ" + } + ], operator : "MATCH_ALL_CLAUSES" }; diff --git a/deep_sequencing_unit/source/html/downloader/openbis.js b/deep_sequencing_unit/source/html/downloader/openbis.js index 7e1d4131e3b1419a8953e80c90d23983b345aaef..8daf9bdee3376d61bda7b45850a2ff42df6e28e7 100644 --- a/deep_sequencing_unit/source/html/downloader/openbis.js +++ b/deep_sequencing_unit/source/html/downloader/openbis.js @@ -197,3 +197,34 @@ openbis.prototype.executeQuery = function(queryId, parameterBindings, action) { success: action }); } + +/** + * A utility class for deferring an action until all of some kind of action has completed + * + * @argument dependencies An array of the keys for the dependencies. + */ +function actionDeferrer(pendingAction, dependencies) { + this.pendingAction = pendingAction; + this.dependencies = {}; + var newme = this; + dependencies.forEach(function(key) { + newme.dependencies[key] = false; + }); +} + +/** + * Note that a dependency completed. Execute the pending action if appropriate. + */ +actionDeferrer.prototype.dependencyCompleted = function(key) { + this.dependencies[key] = true; + var shouldExecute = true; + for (prop in this.dependencies) { + if (false == this.dependencies[prop]) { + shouldExecute = false; + break; + } + } + if (shouldExecute) { + this.pendingAction(); + } +} diff --git a/deep_sequencing_unit/source/html/downloader/tree.css b/deep_sequencing_unit/source/html/downloader/tree.css index 2eda3c8c67aec20de9c23f67732a24c6f27526cd..cfb774fe829a7b1128291da2eeac5a8fd43c7ba6 100644 --- a/deep_sequencing_unit/source/html/downloader/tree.css +++ b/deep_sequencing_unit/source/html/downloader/tree.css @@ -1,26 +1,37 @@ .node circle { - fill: #fff; - stroke: steelblue; - stroke-width: 1.5px; + fill: #fff; + stroke: steelblue; + stroke-width: 1.5px; } .node { - font: 12px "Verdana", sans-serif; + font: 12px "Verdana", sans-serif; + z-index: 1; + cursor: pointer; } .link { - fill: none; - stroke: #ccc; - stroke-width: 1.5px; + fill: none; + stroke: #ccc; + stroke-width: 1.5px; + z-index: -1; } g.withchildren:hover { opacity: 0.5; - color: #AAA; + font-weight: bold; +} + +.leaf text { + fill: #999; +} + +.sequenced text{ + fill: black; } g.leaf:hover { - font-weight: bold + font-weight: bold; } .inspected { @@ -28,10 +39,6 @@ g.leaf:hover { } /* Inspector */ -.inspector { - font-family: "Trebuchet MS", sans-serif; - font-size: 12px; -} div.inspector { font: 12px "Verdana", sans-serif; @@ -52,4 +59,33 @@ div.inspector { .close:hover { opacity: 0.5; color: #AAA; + cursor: pointer; +} + +.downloads { + color: steelblue; + background-color: #E3E3E3; +} + +table.downloads { + font-family: "Trebuchet MS", sans-serif; + font-size: 18px; + font-variant: small-caps; + table-layout: fixed; +} + +/* +.downloads caption { + text-align: left; +} +*/ + +.downloads td { + width: 50%; + border-right: 2px solid #FFFFFF; +} + +.downloads td:hover { + cursor: pointer; + font-weight: bold; } \ No newline at end of file