MediaWiki:LipoqualityChart.js: Difference between revisions
Jcblmaster (talk | contribs) (Created page with "// 定数 const DEFAULT_BAR_COLOR = "#7cb5ec"; const MARGIN = 30; var barColor = DEFAULT_BAR_COLOR; // バーチャート(バンドル)のX軸ラベル変更用 var leg...") |
Jcblmaster (talk | contribs) No edit summary |
||
(12 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
// Last-Update: 2020/03/23 | |||
// 定数 | // 定数 | ||
const DEFAULT_BAR_COLOR = "#7cb5ec"; | const DEFAULT_BAR_COLOR = "#7cb5ec"; | ||
const MARGIN = 30; | const MARGIN = 30; | ||
const RELATIVE_LABEL = 'Relative Value (%)'; | |||
var barColor = DEFAULT_BAR_COLOR; | var barColor = DEFAULT_BAR_COLOR; | ||
// バーチャート(バンドル)のX軸ラベル変更用 | // バーチャート(バンドル)のX軸ラベル変更用 | ||
var legendOptions = ["Sample name"," | var legendOptions = ["Sample name","Category","Tissue/Species","Genotype/Background","Perturbation","Diet/Culture"]; | ||
// グローバル変数 | // グローバル変数 | ||
Line 14: | Line 16: | ||
var defaultTickInterval = currentTickInterval = 5; | var defaultTickInterval = currentTickInterval = 5; | ||
var gHeatmapData; | var gHeatmapData; | ||
var gChainData; | |||
// 初期化 /////////////////////////////////////////////////////////////////////////////////////////////////////////////// | // 初期化 /////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
Line 44: | Line 47: | ||
if(document.getElementById("pieContainer").style.display == "none") | if(document.getElementById("pieContainer").style.display == "none") | ||
pieWidth = 0; | pieWidth = 0; | ||
var width = $(window).width() - $("#sortableList").width() - $("# | var width = $(window).width() - $("#sortableList").width() - $("#p-logo").width() - pieWidth - MARGIN; | ||
if(width < 300) | if(width < 300) | ||
width = 300; | width = 300; | ||
Line 55: | Line 58: | ||
// chain | // chain | ||
var height = 500; | var height = 500; | ||
var width = $(window).width() - $("#sortableList").width()- $("# | var width = $(window).width() - $("#sortableList").width()- $("#p-logo").width() - MARGIN; | ||
$("#container0").highcharts().setSize(width, height); | $("#container0").highcharts().setSize(width, height); | ||
Line 61: | Line 64: | ||
// heatmap or barchart(bundle) | // heatmap or barchart(bundle) | ||
var height = 400; | var height = 400; | ||
var width = $(window).width() - $("#sortableList").width() - $("# | var width = $(window).width() - $("#sortableList").width() - $("#p-logo").width() - MARGIN; | ||
for(var i = 0; i < chart.length; i ++) | for(var i = 0; i < chart.length; i ++) | ||
$("#container" + i).highcharts().setSize(width, height); | $("#container" + i).highcharts().setSize(width, height); | ||
Line 107: | Line 110: | ||
gChartType = chartType | gChartType = chartType | ||
var result = retrieveChartData(targets, chartType); | var result = retrieveChartData(targets, chartType, gDataType); | ||
document.getElementById('retrieving').style.display = "none"; | document.getElementById('retrieving').style.display = "none"; | ||
Line 118: | Line 121: | ||
cutoffText.id = "cutoffValue"; | cutoffText.id = "cutoffValue"; | ||
cutoffText.type = "text"; | cutoffText.type = "text"; | ||
cutoffText.value = | cutoffText.value = 0; // デフォルトは1%カット -> 初期表示は0%にしておく | ||
cutoffText.min = 0; | cutoffText.min = 0; | ||
cutoffText.max = 80; | cutoffText.max = 80; | ||
Line 150: | Line 153: | ||
} | } | ||
// バーチャート(バンドル) ///////////////////////////////////////////////////////////////////////////////////////////////////// | // バーチャート(バンドル) ///////////////////////////////////////////////////////////////////////////////////////////////////// | ||
// JCBLの構造ページへ飛ぶ | |||
function jumpToStructureOnBundleBar(seq, x) | |||
{ | |||
var chain = attrEscape(chart[0].xAxis[0].categories[x]); | |||
jumpToMassBank(gBarData[seq]["type"], chain, chart[0].adduct[seq][x]); | |||
//console.log(gBarData[seq]["type"] + " " + chain + " " + chart[0].adduct[seq][x]); | |||
} | |||
// データの切り替え(表示/非表示、0-intensity) /////////////////////////////////////////////////////////////////////////////////////////////////////////////// | // データの切り替え(表示/非表示、0-intensity) /////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
function setBarBundleData() | function setBarBundleData() | ||
Line 166: | Line 176: | ||
target[j] = not0; | target[j] = not0; | ||
} | } | ||
var adduct = []; | |||
for(var j = 0; j < chart[0].series.length; j ++){ | for(var j = 0; j < chart[0].series.length; j ++){ | ||
var i = 0; | var i = 0; | ||
var data = []; | var data = []; | ||
var xLabels = []; | var xLabels = []; | ||
adduct[j] = []; | |||
for(var k = 0; k < chart[0].srcdata[j].length; k ++){ | for(var k = 0; k < chart[0].srcdata[j].length; k ++){ | ||
if(target[k]){ // チェックボックスにチェックがついていれば表示対象 | if(target[k]){ // チェックボックスにチェックがついていれば表示対象 | ||
Line 177: | Line 189: | ||
else | else | ||
data[i] = [chart[0].xLabels[k], chart[0].srcdata[j][k]]; | data[i] = [chart[0].xLabels[k], chart[0].srcdata[j][k]]; | ||
xLabels[i | xLabels[i] = chart[0].xLabels[k]; | ||
adduct[j][i] = gBarData[j][k]; | |||
i ++; | |||
} | } | ||
} | } | ||
Line 183: | Line 197: | ||
// chart[0].yAxis[0].setExtremes(0, 100); | // chart[0].yAxis[0].setExtremes(0, 100); | ||
chart[0].yAxis[0].update({max: 100}); | chart[0].yAxis[0].update({max: 100}); | ||
chart[0].yAxis[0].axisTitle.attr({text: | chart[0].yAxis[0].axisTitle.attr({text: RELATIVE_LABEL}); | ||
chart[0].tooltip.options.formatter = | chart[0].tooltip.options.formatter = barchartTooltipPercent; | ||
} else { // 絶対値でのY軸タイトル | } else { // 絶対値でのY軸タイトル | ||
// chart[0].yAxis[0].setExtremes(0, chart[0].max); | // chart[0].yAxis[0].setExtremes(0, chart[0].max); | ||
chart[0].yAxis[0].update({max: chart.max}); | chart[0].yAxis[0].update({max: chart.max}); | ||
chart[0].yAxis[0].axisTitle.attr({text: | chart[0].yAxis[0].axisTitle.attr({text: chart[0].quantification}); | ||
chart[0].tooltip.options.formatter = | chart[0].tooltip.options.formatter = barchartTooltipValue; | ||
} | } | ||
chart[0].xAxis[0].categories = xLabels; | chart[0].xAxis[0].categories = xLabels; | ||
chart[0].series[j].setData(data, true); | chart[0].series[j].setData(data, true); | ||
} | } | ||
chart[0].adduct = adduct; | |||
unzoomBarCharts(); | unzoomBarCharts(); | ||
Line 233: | Line 248: | ||
line.appendChild(label); | line.appendChild(label); | ||
sortableList.appendChild(line); | sortableList.appendChild(line); | ||
}/* | } | ||
$('#sortableList').sortable(); | |||
$('#sortableList').sortable("disable"); | |||
/* | |||
$('#sortableList').sortable({ | $('#sortableList').sortable({ | ||
cursor: 'move', | cursor: 'move', | ||
Line 257: | Line 275: | ||
var option = document.createElement('option'); | var option = document.createElement('option'); | ||
option.setAttribute("value", legendOptions[i]); | option.setAttribute("value", legendOptions[i]); | ||
if(legendOptions[i] == " | if(legendOptions[i] == "Genotype/Background") | ||
option.setAttribute("selected", "true"); | option.setAttribute("selected", "true"); | ||
option.innerHTML = legendOptions[i]; | option.innerHTML = legendOptions[i]; | ||
Line 278: | Line 296: | ||
data = []; | data = []; | ||
srcdata = []; | srcdata = []; | ||
var meta | var meta = []; | ||
var root = document.getElementById('container'); | var root = document.getElementById('container'); | ||
var unifiedFlag = true; | var unifiedFlag = true; | ||
Line 301: | Line 319: | ||
data[i][j] = [attrEscape(result[0].x[j]), attrEscape(result[0].map[i].data[j][0] * 100 / result[0].maxOfAll)]; // 相対値を計算 | data[i][j] = [attrEscape(result[0].x[j]), attrEscape(result[0].map[i].data[j][0] * 100 / result[0].maxOfAll)]; // 相対値を計算 | ||
srcdata[i][j] = attrEscape(result[0].map[i].data[j][0]); // もともとの値を計算 | srcdata[i][j] = attrEscape(result[0].map[i].data[j][0]); // もともとの値を計算 | ||
xLabels[j] = attrEscape(result[0].x[j] | xLabels[j] = attrEscape(result[0].x[j] + " [" + result[0].map[i].data[j].meta["Internal standard"] + "]"); // X軸ラベル | ||
gBarData[i][j] = result[0].map[i].data[j].meta["Adduct"]; | |||
gBarData[i][j] = | |||
} | } | ||
// for link | |||
// var type = result[0].map[i].title.replace(/.*\//,"").replace("[","_").replace("]", ""); | |||
var type = result[0].map[i].title.split(" / ")[2]; | |||
var ionmode = ""; | |||
if(result[0].map[i].meta["Ion mode"] == "Positive") | |||
ionmode = "p"; | |||
else if(result[0].map[i].meta["Ion mode"] == "Negative") | |||
ionmode = "n"; | |||
gBarData[i]["type"] = type; | |||
gBarData[i]["ionmode"] = ionmode; | |||
//console.log(gBarData[i]); | |||
meta[i] = result[0].map[i].meta; | meta[i] = result[0].map[i].meta; | ||
seriesData[i] = { | seriesData[i] = { | ||
name: attrEscape(result[0].map[i].meta[" | name: attrEscape(result[0].map[i].meta["Genotype/Background"]), | ||
data: data[i], | data: data[i], | ||
events: { | events: { | ||
click: function(event) { | click: function(event) { | ||
//alert(event.point.name); | //alert(event.point.name); | ||
var index = event. | var index = event.point.series.columnIndex; | ||
jumpToStructureOnBundleBar(index, event.point.x); | |||
} | } | ||
} | } | ||
Line 340: | Line 369: | ||
style: { | style: { | ||
fontSize: '11px', | fontSize: '11px', | ||
fontWeight: 'bold', | |||
fontFamily: 'Verdana, sans-serif' | fontFamily: 'Verdana, sans-serif' | ||
}, | }, | ||
Line 352: | Line 382: | ||
max: 100, | max: 100, | ||
title: { | title: { | ||
text: | text: RELATIVE_LABEL | ||
} | } | ||
}, | }, | ||
Line 360: | Line 390: | ||
tooltip: { | tooltip: { | ||
pointFormat: '<b>{point.y:.1f} %</b>', | pointFormat: '<b>{point.y:.1f} %</b>', | ||
formatter: | formatter: barchartTooltipPercent | ||
}, | }, | ||
series: seriesData | series: seriesData | ||
Line 371: | Line 401: | ||
chart[0].quantification = unitType; | chart[0].quantification = unitType; | ||
chart[0].meta = meta; | chart[0].meta = meta; | ||
chart[0].adduct = gBarData; | |||
// 絶対量/相対量を切り替えるチェックボックス | // 絶対量/相対量を切り替えるチェックボックス | ||
Line 390: | Line 421: | ||
if(unifiedFlag == false) | if(unifiedFlag == false) | ||
alert("intensityの単位が統一されていません。"); | alert("intensityの単位が統一されていません。"); | ||
} | |||
// MassBankへ飛ぶ共通のメソッド | |||
function jumpToMassBank(lipidclass, chain, adduct) | |||
{ | |||
var PRECURSOR_TYPE_NAMES = { | |||
'[M]+': 'p', | |||
'[M+H]+': 'Hp', | |||
'[M+Na]+': 'Nap', | |||
'[M+NH4]+': 'NH4p', | |||
'[M-H]-': 'Hm', | |||
'[M+FA-H]-': 'FAm', | |||
'[M+Hac-H]-': 'Hacm' | |||
}; | |||
var type = PRECURSOR_TYPE_NAMES[adduct]; | |||
window.open("http://133.242.136.63/wiki/Volatile:" + lipidclass + "?my_1=" + chain + "&my_2=" + type); | |||
// window.open("http://133.242.136.63/wiki/?lc=" + lipidclass + "&c=" + chain + "&p" + adduct, "new"); | |||
console.log(lipidclass +" " + chain +" " + adduct); | |||
} | } | ||
Line 396: | Line 444: | ||
function jumpToStructureOnBar(seq, x) | function jumpToStructureOnBar(seq, x) | ||
{ | { | ||
// window.open("http://jcbl.jp/wiki/LBG" + gBarData[seq][x], "new"); | |||
// window.open("http://133.242.136.63/wiki/Category:CS:" + gBarData[seq][x], "new"); | |||
// console.log(seq + "/" + x + " => " + gBarData[seq][x]); | |||
var chain = attrEscape(chart[0].xAxis[0].categories[x]); | |||
console.log(gBarData[seq]); | |||
jumpToMassBank(gBarData[seq]["type"], chain, chart[seq].adduct[x]); | |||
//console.log(gBarData[seq]["type"] + " " + chain + " " + chart[seq].adduct[x]); | |||
/* if(chain.indexOf("/") >= 0) | |||
chain = "(" + chain + ")"; | |||
else | |||
chain = "_" + chain; | |||
var link = gBarData[seq]["type"] + chain + gBarData[seq]["ionmode"]; | |||
window.open("http://133.242.136.63/wiki/Category:CS:" + link, "new"); | |||
console.log(seq + "/" + x + " => " + link); | |||
*/ | |||
} | } | ||
// 全バーチャートのズーム解除 /////////////////////////////////////////////////////////////////////////////////////////////////////////////// | // 全バーチャートのズーム解除 /////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
Line 425: | Line 486: | ||
for(var j = 0; j < chart.length; j ++){ | for(var j = 0; j < chart.length; j ++){ | ||
var i = 0; | var i = 0; | ||
var data = []; | var data = []; | ||
var xLabels = []; | var xLabels = []; | ||
var adduct = []; | |||
for(var k = 0,l = 0; k < chart[j].data.length; k ++){ | for(var k = 0,l = 0; k < chart[j].data.length; k ++){ | ||
if(target[k]){ | if(target[k]){ | ||
Line 435: | Line 497: | ||
else | else | ||
data[i] = [chart[j].xLabels[k], chart[j].srcdata[k]]; | data[i] = [chart[j].xLabels[k], chart[j].srcdata[k]]; | ||
adduct[i] = gBarData[j].adduct[k]; | |||
xLabels[i++] = chart[j].xLabels[k]; | xLabels[i++] = chart[j].xLabels[k]; | ||
} | } | ||
Line 440: | Line 503: | ||
if(document.getElementById("ratio").checked){ | if(document.getElementById("ratio").checked){ | ||
chart[j].yAxis[0].setExtremes(0, 100); | chart[j].yAxis[0].setExtremes(0, 100); | ||
// chart[j].yAxis[0].axisTitle.attr({text: "Relative Intensity (%)"}); | |||
chart[j]. | chart[j].yAxis[0].axisTitle.attr({text: RELATIVE_LABEL}); | ||
chart[j].tooltip.options.formatter = barchartTooltipPercent; | |||
} else { | } else { | ||
chart[j].yAxis[0].setExtremes(0, chart[j].max); | chart[j].yAxis[0].setExtremes(0, chart[j].max); | ||
// chart[j].yAxis[0].axisTitle.attr({text: "Intensity (" + chart[j].quantification + ")"}); | |||
chart[j]. | chart[j].yAxis[0].axisTitle.attr({text: chart[j].quantification}); | ||
chart[j].tooltip.options.formatter = barchartTooltipValue; | |||
} | } | ||
chart[j].xAxis[0].categories = xLabels; | chart[j].xAxis[0].categories = xLabels; | ||
chart[j].series[0].setData(data, true); | chart[j].series[0].setData(data, true); | ||
chart[j].adduct = adduct; | |||
} | } | ||
Line 457: | Line 523: | ||
function showBarChart(result) | function showBarChart(result) | ||
{ | { | ||
console.log(result); | |||
function computeTickInterval(xMin, xMax) | function computeTickInterval(xMin, xMax) | ||
{ | { | ||
Line 498: | Line 565: | ||
var label = document.createElement("label"); | var label = document.createElement("label"); | ||
label.setAttribute("for", "item" + i); | label.setAttribute("for", "item" + i); | ||
label.innerHTML = (i+1) + "." + escape(result[0].map[i].title); | label.innerHTML = (i+1) + "." + escape(result[0].map[i].title); | ||
line.appendChild(label); | line.appendChild(label); | ||
Line 534: | Line 600: | ||
} | } | ||
}); | }); | ||
$('#sortableList').sortable("enable"); | |||
// パイチャートの表示/非表示の切り替え | // パイチャートの表示/非表示の切り替え | ||
var switchPieHidden = document.getElementById("optionHeader"); | var switchPieHidden = document.getElementById("optionHeader"); | ||
Line 565: | Line 632: | ||
var srcdata = []; | var srcdata = []; | ||
var xLabels = []; | var xLabels = []; | ||
gBarData[i].adduct = []; | |||
for(var j = 0; j < result[0].map[i].data.length; j ++){ | for(var j = 0; j < result[0].map[i].data.length; j ++){ | ||
// data[j] = [attrEscape(result[0].x[j]), attrEscape(result[0].map[i].data[j][0] * 100 / result[0].map[i].max)]; | // data[j] = [attrEscape(result[0].x[j]), attrEscape(result[0].map[i].data[j][0] * 100 / result[0].map[i].max)]; | ||
data[j] = [attrEscape(result[0].x[j]), attrEscape(result[0].map[i].data[j][0] * 100 / result[0].map[i].max)]; | data[j] = [attrEscape(result[0].x[j]), attrEscape(result[0].map[i].data[j][0] * 100 / result[0].map[i].max)]; | ||
srcdata[j] = attrEscape(result[0].map[i].data[j][0]); | srcdata[j] = attrEscape(result[0].map[i].data[j][0]); | ||
xLabels[j] = attrEscape(result[0].x[j]); | xLabels[j] = attrEscape(result[0].x[j] + " [" + result[0].map[i].data[j].meta["Internal standard"] + "]"); | ||
gBarData[i].adduct[j] = result[0].map[i].data[j].meta["Adduct"]; | |||
// gBarData[i][j] = inchiEscape(result[0].map[i].data[j][2]); // InChIキー | // gBarData[i][j] = inchiEscape(result[0].map[i].data[j][2]); // InChIキー | ||
gBarData[i][j] = type + attrEscape(result[0].x[j]).replace("/","-"); // InChIキー | /* var type = result[0].map[i].title.replace(/.*\//,""); | ||
gBarData[i][j] = type + attrEscape(result[0].x[j]).replace("/","-"); // InChIキー*/ | |||
} | } | ||
// for link | |||
// var type = result[0].map[i].title.replace(/.*\//,"").replace("[","_").replace("]", ""); | |||
var type = result[0].map[i].title.split(" / ")[2]; | |||
var ionmode = ""; | |||
if(result[0].map[i].meta["Ion mode"] == "Positive") | |||
ionmode = "p"; | |||
else if(result[0].map[i].meta["Ion mode"] == "Negative") | |||
ionmode = "n"; | |||
gBarData[i]["type"] = type; | |||
gBarData[i]["ionmode"] = ionmode; | |||
gBarData[i]["pieclass"] = []; | |||
for(var j = 0; j < result[0].map[i].pie.length; j ++) | |||
gBarData[i]["pieclass"][j] = result[0].map[i].pie[j].name; | |||
// barchartの追加 | // barchartの追加 | ||
Line 602: | Line 685: | ||
style: { | style: { | ||
fontSize: '11px', | fontSize: '11px', | ||
fontWeight: 'bold', | |||
fontFamily: 'Verdana, sans-serif' | fontFamily: 'Verdana, sans-serif' | ||
}, | }, | ||
Line 637: | Line 721: | ||
max: 100, | max: 100, | ||
title: { | title: { | ||
text: | text: RELATIVE_LABEL | ||
} | } | ||
}, | }, | ||
Line 645: | Line 729: | ||
tooltip: { | tooltip: { | ||
pointFormat: '<b>{point.y:.1f} %</b>', | pointFormat: '<b>{point.y:.1f} %</b>', | ||
formatter: | formatter: barchartTooltipPercent | ||
}, | }, | ||
series: [{ | series: [{ | ||
Line 666: | Line 750: | ||
chart[i].xLabels = xLabels; | chart[i].xLabels = xLabels; | ||
chart[i].quantification = result[0].map[i].meta.Quantification; | chart[i].quantification = result[0].map[i].meta.Quantification; | ||
chart[i].adduct = gBarData[i].adduct; | |||
// piechartの追加 | // piechartの追加 | ||
Line 682: | Line 767: | ||
}, | }, | ||
title: { | title: { | ||
text: (i+1) + '. | text: (i+1) + '.Value ratio' | ||
}, | }, | ||
tooltip: { | tooltip: { | ||
Line 710: | Line 795: | ||
var nextType = event.point.name; | var nextType = event.point.name; | ||
for(var i = 0; i < gBarData.length; i ++){ | |||
if(!(gBarData[i]["pieclass"].includes(nextType))){ | |||
alert("表示中の中に、" + nextType + "が含まれないデータがあるため、切り替えができません。"); | |||
return; | |||
} | |||
} | |||
var targets = []; | var targets = []; | ||
var sortableList = document.getElementById("sortableList"); | var sortableList = document.getElementById("sortableList"); | ||
for(var i = 0; i < sortableList.childNodes.length; i ++){ | for(var i = 0; i < sortableList.childNodes.length; i ++){ | ||
var w = sortableList.childNodes[i].childNodes[1].innerHTML.replace(/^[0-9]+./,"").split("/"); | var w = sortableList.childNodes[i].childNodes[1].innerHTML.replace(/^[0-9]+./,"").split(" / "); | ||
targets.push(w[0] + "/" + w[1] + "/" + nextType); | // targets.push(w[0] + " / " + w[1] + " / " + nextType + " / " + w[2]); | ||
targets.push(w[0] + " / " + w[1] + " / " + nextType + " / " + w[3]); | |||
} | } | ||
showChart(targets); | showChart(targets); | ||
Line 742: | Line 834: | ||
function jumpToStructureOnHeatmap(seq, x, y) | function jumpToStructureOnHeatmap(seq, x, y) | ||
{ | { | ||
// window.open("http://jcbl.jp/wiki/LBG" + gHeatmapData[seq].map[0].title.replace(/.*\//, "") + gHeatmapData[seq].x[x].replace("/","-"), "new"); | |||
// console.log(seq + "/" + y + "/" + x + " => " + | // window.open("http://133.242.136.63/wiki/Category:CS:" + gBarData[seq][x], "new"); | ||
// var type = gHeatmapData[0].map[0].title.replace(/.*\//,"").replace("[","_").replace("]", ""); | |||
var type = gHeatmapData[0].map[0].title.split(" / ")[2]; | |||
var chain = attrEscape(chart[0].xAxis[0].categories[x]); | |||
var adduct = gBarData[y].adduct[x]; | |||
jumpToMassBank(type, chain, adduct); | |||
//console.log(type + " " + chain + " " + adduct); | |||
/* if(chain.indexOf("/") >= 0) | |||
chain = "(" + chain + ")"; | |||
else | |||
chain = "_" + chain; | |||
var link = type + chain + gBarData[y]; | |||
window.open("http://133.242.136.63/wiki/Category:CS:" + link, "new"); | |||
console.log(seq + "/" + y + "/" + x + " => " + link); | |||
*/ | |||
// console.log(seq + "/" + y + "/" + x + " => " + gHeatmapData[seq].x[x]); | |||
} | } | ||
Line 772: | Line 878: | ||
xLabels[i++] = gHeatmapData[index].x[k]; | xLabels[i++] = gHeatmapData[index].x[k]; | ||
} | } | ||
// ジャンプ先の設定 | |||
gBarData = []; | |||
for(var j = 0; j < seq.length; j ++){ | |||
var ionmode = ""; | |||
if(gHeatmapData[index].map[seq[j]].meta["Ion mode"] == "Positive") | |||
ionmode = "p"; | |||
else if(gHeatmapData[index].map[seq[j]].meta["Ion mode"] == "Negative") | |||
ionmode = "n"; | |||
gBarData[j] = ionmode; // LBG + lipid class + chain | |||
} | |||
gBarData.reverse(); | |||
var data = []; | var data = []; | ||
Line 786: | Line 904: | ||
// データのセット | // データのセット | ||
for(var j = 0; j < seq.length && j < length; j ++){ | for(var j = 0; j < seq.length && j < length; j ++){ | ||
gBarData[j] = []; | |||
gBarData[j].adduct = []; | |||
if(document.getElementById("eachInRate").checked) | if(document.getElementById("eachInRate").checked) | ||
max = gHeatmapData[index].map[seq[j]].max; | max = gHeatmapData[index].map[seq[j]].max; | ||
Line 794: | Line 914: | ||
for(var k = 0,l = 0; k < gHeatmapData[index].map[seq[j]].data.length; k ++){ | for(var k = 0,l = 0; k < gHeatmapData[index].map[seq[j]].data.length; k ++){ | ||
if(target[k]){ | if(target[k]){ | ||
data[i] = [l | data[i] = [l, seq.length-j-1, attrEscape(gHeatmapData[index].map[seq[j]].data[k][0] * 100 / max)]; // 相対値の計算 | ||
chart[index].inchi[j][k] = inchiEscape(gHeatmapData[index].map[seq[j]].data[k].meta["InChIKey"]); // インチ―キー | chart[index].inchi[j][k] = inchiEscape(gHeatmapData[index].map[seq[j]].data[k].meta["InChIKey"]); // インチ―キー | ||
gBarData[j].adduct[l++] = gHeatmapData[index].map[seq[j]].data[k].meta["Adduct"]; | |||
i ++; | i ++; | ||
} | } | ||
} | } | ||
yLabels[j] = (parseInt(seq[j])+1) + "." + attrEscape(gHeatmapData[index].map[seq[j]].title.replace(/\/[^\/]+$/, "")); // Y軸ラベル | var titleParts = gHeatmapData[index].map[seq[j]].title.split(" / "); | ||
yLabels[j] = (parseInt(seq[j])+1) + "." + attrEscape(titleParts[0] + " / " + titleParts[1] + " / " + titleParts[3]); // Y軸ラベル | |||
// yLabels[j] = (parseInt(seq[j])+1) + "." + attrEscape(gHeatmapData[index].map[seq[j]].title.replace(/\/[^\/]+$/, "")); // Y軸ラベル | |||
} | } | ||
gBarData.reverse(); | |||
yLabels.reverse(); | yLabels.reverse(); | ||
chart[index].zoomOut(); | chart[index].zoomOut(); | ||
chart[index].series[0].setData(data, true); | chart[index].series[0].setData(data, true, true, false); | ||
chart[index].yAxis[0].setCategories(yLabels); | chart[index].yAxis[0].setCategories(yLabels); | ||
chart[index].xAxis[0].setCategories(xLabels); | chart[index].xAxis[0].setCategories(xLabels); | ||
Line 831: | Line 955: | ||
function showHeatmap(result) | function showHeatmap(result) | ||
{ | { | ||
gBarData = []; | |||
gHeatmapData = []; | gHeatmapData = []; | ||
var root = document.getElementById('container'); | var root = document.getElementById('container'); | ||
Line 855: | Line 980: | ||
inchi[j] = []; | inchi[j] = []; | ||
ratioData[j] = []; | ratioData[j] = []; | ||
gBarData[j] = {}; | |||
gBarData[j].adduct = []; | |||
for(var k = 0; k < result[i].map[j].data.length; k ++){ | for(var k = 0; k < result[i].map[j].data.length; k ++){ | ||
console.log(result[i].map[j].data[k]); | |||
data[index] = [k, length-j-1, attrEscape(result[i].map[j].data[k][0] * 100 / result[i].map[j].max)]; // 相対値の計算 | data[index] = [k, length-j-1, attrEscape(result[i].map[j].data[k][0] * 100 / result[i].map[j].max)]; // 相対値の計算 | ||
// data[index] = [k, length-j-1, attrEscape(result[i].map[j].data[k][0] * 100 / result[i].maxOfAll)]; | // data[index] = [k, length-j-1, attrEscape(result[i].map[j].data[k][0] * 100 / result[i].maxOfAll)]; | ||
inchi[j][k] = inchiEscape(result[i].map[j].data[k].meta["InChIKey"]); // インチ-キーの格納 | inchi[j][k] = inchiEscape(result[i].map[j].data[k].meta["InChIKey"]); // インチ-キーの格納 | ||
ratioData[j][k] = data[index][2]; // cutoff用%値 | ratioData[j][k] = data[index][2]; // cutoff用%値 | ||
gBarData[j].adduct[k] = result[i].map[j].data[k].meta["Adduct"]; | |||
index ++; | index ++; | ||
} | } | ||
/* var ionmode = ""; | |||
if(result[i].map[j].meta["Ion mode"] == "Positive") | |||
ionmode = "p"; | |||
else if(result[i].map[j].meta["Ion mode"] == "Negative") | |||
ionmode = "n"; | |||
gBarData[j] = ionmode; // LBG + lipid class + chain | |||
*/ | |||
var titleParts = result[i].map[j].title.split(" / "); | |||
yLabels[j] = (j+1) + "." + attrEscape(titleParts[0] + " / " + titleParts[1] + " / " + titleParts[3]); // Y軸ラベル | |||
} | } | ||
//console.log(gBarData); | |||
gBarData.reverse(); | |||
//console.log(gBarData); | |||
yLabels.reverse(); // highchartsの性質上、Y軸ラベルを反転させる | yLabels.reverse(); // highchartsの性質上、Y軸ラベルを反転させる | ||
for(var j = 0; j < result[i].x.length; j ++) | for(var j = 0; j < result[i].x.length; j ++) | ||
Line 894: | Line 1,034: | ||
var label = document.createElement("label"); | var label = document.createElement("label"); | ||
label.setAttribute("for", "item" + j); | label.setAttribute("for", "item" + j); | ||
// label.innerHTML = (j+1) + "." + escape(result[i].map[j].title); | |||
var titleParts = result[i].map[j].title.split(" / "); | |||
label.innerHTML = (j+1) + "." + escape(titleParts[0] + " / " + titleParts[1] + " / " + titleParts[3]); | |||
line.appendChild(label); | line.appendChild(label); | ||
listDiv.appendChild(line); | listDiv.appendChild(line); | ||
Line 952: | Line 1,094: | ||
style: { | style: { | ||
fontSize: '11px', | fontSize: '11px', | ||
fontWeight: 'bold', | |||
fontFamily: 'Verdana, sans-serif' | fontFamily: 'Verdana, sans-serif' | ||
}, | }, | ||
Line 985: | Line 1,128: | ||
formatter: function () { | formatter: function () { | ||
return this.series.yAxis.categories[this.point.y] + '<br />' + | return this.series.yAxis.categories[this.point.y] + '<br />' + | ||
this.series.xAxis.categories[this.point.x] + '<br />' + | this.series.xAxis.categories[this.point.x] + " [" + gHeatmapData[0].map[this.point.y].data[this.point.x].meta["Internal standard"] + ']<br />' + | ||
(Math.round(this.point.value*10)/10) + ' %'; | (Math.round(this.point.value*10)/10) + ' %'; | ||
} | } | ||
Line 1,029: | Line 1,172: | ||
var data = []; | var data = []; | ||
var xLabels = []; | var xLabels = []; | ||
adduct = []; | |||
// gBarData.ionmode = []; | |||
for(var k = 0; k < chart.srcdata.length; k ++){ | for(var k = 0; k < chart.srcdata.length; k ++){ | ||
if(target[k]){ // チェックボックスにチェックがついていれば表示対象 | if(target[k]){ // チェックボックスにチェックがついていれば表示対象 | ||
Line 1,036: | Line 1,181: | ||
else | else | ||
data[i] = {y:chart.srcdata[k], color:chart.colors[k%chart.colors.length]}; | data[i] = {y:chart.srcdata[k], color:chart.colors[k%chart.colors.length]}; | ||
xLabels[i++] = | xLabels[i] = chart.xLabels[k]; | ||
/* | |||
var ionmode = ""; | |||
if(gChainData.ionmode[k] == "Positive") | |||
ionmode = "p"; | |||
else if(gChainData.ionmode[k] == "Negative") | |||
ionmode = "n"; | |||
gBarData.ionmode[i++] = ionmode; | |||
*/ | |||
adduct[i++] = gBarData.adduct[k]; | |||
} | } | ||
} | } | ||
Line 1,042: | Line 1,196: | ||
// chart.yAxis[0].setExtremes(0, 100); | // chart.yAxis[0].setExtremes(0, 100); | ||
chart.yAxis[0].update({max: 100}); | chart.yAxis[0].update({max: 100}); | ||
chart.yAxis[0].axisTitle.attr({text: | chart.yAxis[0].axisTitle.attr({text: RELATIVE_LABEL}); | ||
chart.tooltip.options.formatter = | chart.tooltip.options.formatter = barchartTooltipPercent; | ||
} else { // 絶対値でのY軸タイトル | } else { // 絶対値でのY軸タイトル | ||
// chart.yAxis[0].setExtremes(0, chart.max); | // chart.yAxis[0].setExtremes(0, chart.max); | ||
chart.yAxis[0].update({max: chart.max}); | chart.yAxis[0].update({max: chart.max}); | ||
chart.yAxis[0].axisTitle.attr({text: | chart.yAxis[0].axisTitle.attr({text: chart.quantification}); | ||
chart.tooltip.options.formatter = | chart.tooltip.options.formatter = barchartTooltipValue; | ||
} | } | ||
chart.xAxis[0].categories = xLabels; | chart.xAxis[0].categories = xLabels; | ||
chart.series[0].setData(data, true); | chart.series[0].setData(data, true); | ||
chart.adduct = adduct; | |||
chart.xAxis[0].isDirty = true; | chart.xAxis[0].isDirty = true; | ||
Line 1,063: | Line 1,218: | ||
var colors = ['#ff7f7f','#7f7fff','#7fff7f','#ff7fbf','#bfff7f','#ff7fff','#7fffff','#000000','#bf7fff','#7fffbf','#ffbf7f','#808080']; | var colors = ['#ff7f7f','#7f7fff','#7fff7f','#ff7fbf','#bfff7f','#ff7fff','#7fffff','#000000','#bf7fff','#7fffbf','#ffbf7f','#808080']; | ||
gChainData = result; | |||
gChartType = "chain"; | gChartType = "chain"; | ||
Line 1,070: | Line 1,226: | ||
cutoffText.id = "cutoffValue"; | cutoffText.id = "cutoffValue"; | ||
cutoffText.type = "text"; | cutoffText.type = "text"; | ||
cutoffText.value = | cutoffText.value = 0; // デフォルトは1%カット | ||
cutoffText.min = 0; | cutoffText.min = 0; | ||
cutoffText.max = 80; | cutoffText.max = 80; | ||
Line 1,110: | Line 1,266: | ||
// データの整理 | // データの整理 | ||
gBarData = []; | |||
gBarData.lipidclass = result.lipidclass;//.replace("[","_").replace("](","(").replace(/:/g,"_"); | |||
gBarData.chain = result.chain; | |||
gBarData.adduct = []; | |||
var data = []; | var data = []; | ||
var srcdata = []; | var srcdata = []; | ||
Line 1,118: | Line 1,278: | ||
srcdata[j] = attrEscape(result.intensity[j]); | srcdata[j] = attrEscape(result.intensity[j]); | ||
xLabels[j] = attrEscape(result.x[j]); | xLabels[j] = attrEscape(result.x[j]); | ||
gBarData.adduct[j] = result.adduct[j]; | |||
/* var ionmode = ""; | |||
if(result.ionmode[j] == "Positive") | |||
ionmode = "p"; | |||
else if(result.ionmode[j] == "Negative") | |||
ionmode = "n"; | |||
gBarData.ionmode[j] = ionmode;*/ | |||
// var type = result[0].map[i].title.replace(/.*\//,""); | // var type = result[0].map[i].title.replace(/.*\//,""); | ||
// gBarData[i][j] = type + attrEscape(result[0].x[j]).replace("/","-"); // InChIキー | // gBarData[i][j] = type + attrEscape(result[0].x[j]).replace("/","-"); // InChIキー | ||
Line 1,143: | Line 1,311: | ||
rotation: -90, | rotation: -90, | ||
style: { | style: { | ||
fontSize: ' | fontSize: '15px', | ||
fontWeight: 'bold', | |||
fontFamily: 'Verdana, sans-serif' | fontFamily: 'Verdana, sans-serif' | ||
}, | }, | ||
Line 1,156: | Line 1,325: | ||
max: 100, | max: 100, | ||
title: { | title: { | ||
text: | text: RELATIVE_LABEL | ||
} | } | ||
}, | }, | ||
Line 1,164: | Line 1,333: | ||
tooltip: { | tooltip: { | ||
pointFormat: '<b>{point.y:.1f} %</b>', | pointFormat: '<b>{point.y:.1f} %</b>', | ||
formatter: | formatter: barchartTooltipPercent | ||
}, | |||
plotOptions: { | |||
column: { | |||
pointRange: 2 | |||
} | |||
}, | }, | ||
series: [{ | series: [{ | ||
Line 1,171: | Line 1,345: | ||
events: { | events: { | ||
click: function(event) { | click: function(event) { | ||
jumpToStructureOnChain(event.point.x); | |||
} | } | ||
} | } | ||
Line 1,184: | Line 1,358: | ||
chart.quantification = result.quantification; | chart.quantification = result.quantification; | ||
chart.colors = colors; | chart.colors = colors; | ||
chart.adduct = gBarData.adduct; | |||
// 絶対量か相対量か | // 絶対量か相対量か | ||
Line 1,203: | Line 1,378: | ||
if(result.quantification == "?") | if(result.quantification == "?") | ||
alert("intensityの単位が統一されていません。"); | alert("intensityの単位が統一されていません。"); | ||
} | |||
function jumpToStructureOnChain(x) | |||
{/* | |||
var link = gBarData.title + gBarData.ionmode[x]; | |||
window.open("http://133.242.136.63/wiki/Category:CS:" + link, "new"); | |||
console.log(x + " => " + link); | |||
*/ | |||
jumpToMassBank(gBarData.lipidclass, gBarData.chain, chart.adduct[x]); | |||
//console.log(gBarData.lipidclass + " " + gBarData.chain + " " + chart.adduct[x]); | |||
} | |||
// ツールチップ ////////////////////////////////////////////////////////// | |||
function barchartTooltipValue() | |||
{ | |||
return this.x + '<br/ ><b>' + this.y.toFixed(getFloatNumber()) + '</b>'; | |||
} | |||
function barchartTooltipPercent() | |||
{ | |||
return this.x + '<br/ ><b>' + this.y.toFixed(getFloatNumber()) + '%</b>'; | |||
} | |||
// ツールチップで表示する小数点数を取得する // | |||
function getFloatNumber() | |||
{ | |||
var fp = 1; | |||
if(!document.getElementById("ratio").checked && gDataType == 'normalized') | |||
fp = 3; | |||
return fp; | |||
} | } | ||
// ※未使用※ /////////////////////////////////////////////////////////////////////////////////////////////////////////////// | // ※未使用※ /////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
Line 1,214: | Line 1,415: | ||
} | } | ||
return null; | return null; | ||
} | } |
Latest revision as of 02:21, 23 March 2020
// Last-Update: 2020/03/23 // 定数 const DEFAULT_BAR_COLOR = "#7cb5ec"; const MARGIN = 30; const RELATIVE_LABEL = 'Relative Value (%)'; var barColor = DEFAULT_BAR_COLOR; // バーチャート(バンドル)のX軸ラベル変更用 var legendOptions = ["Sample name","Category","Tissue/Species","Genotype/Background","Perturbation","Diet/Culture"]; // グローバル変数 var gBarData; var chart; var piechart; var defaultTickInterval = currentTickInterval = 5; var gHeatmapData; var gChainData; // 初期化 /////////////////////////////////////////////////////////////////////////////////////////////////////////////// function lipoqulityChartInit() { // insert "Reset zoom" button var resetZoomButton = document.createElement("input"); resetZoomButton.setAttribute("type", "button"); resetZoomButton.value = "Reset zoom"; resetZoomButton.id = "resetZoomButton"; resetZoomButton.style.visibility = "hidden"; resetZoomButton.onclick = unzoomBarCharts; document.getElementById("resetZoom").appendChild(resetZoomButton); // ウィンドウサイズが変更されたら、チャートもリサイズする $(window).resize(function() { resizeChart(); }); } // ウィンドウサイズが変更されたとき、チャートの幅も修正する /////////////////////////////////////////////////////////////////////////////////////////////////////////////// function resizeChart() { if(chart == undefined || chart.length == 0) return; if(gChartType == "bar"){ // barchart & piechart var height = 300; var pieWidth = 400; if(document.getElementById("pieContainer").style.display == "none") pieWidth = 0; var width = $(window).width() - $("#sortableList").width() - $("#p-logo").width() - pieWidth - MARGIN; if(width < 300) width = 300; for(var i = 0; i < chart.length; i ++) $("#container" + i).highcharts().setSize(width, height); for(var i = 0; i < piechart.length; i ++) $("#pieContainer" + i).highcharts().setSize(pieWidth, height); } else if(gChartType == "chain"){ // chain var height = 500; var width = $(window).width() - $("#sortableList").width()- $("#p-logo").width() - MARGIN; $("#container0").highcharts().setSize(width, height); } else { // heatmap or barchart(bundle) var height = 400; var width = $(window).width() - $("#sortableList").width() - $("#p-logo").width() - MARGIN; for(var i = 0; i < chart.length; i ++) $("#container" + i).highcharts().setSize(width, height); } } // 指定されたIDを持つDOMの全子ノードを削除する // param id - 対象ID function removeAllChild(id) { var dom = document.getElementById(id); for(var i = dom.childNodes.length-1; i >= 0; i --) dom.removeChild(dom.childNodes[i]); } // チャート表示 /////////////////////////////////////////////////////////////////////////////////////////////////////////////// // すべてのチャートの起点となる function showChart(targets) { if(targets.length == 0) return; document.getElementById("resetZoomButton").style.visibility = "hidden"; document.getElementById("showButton").disabled = true; document.getElementById("bar") .disabled = true; document.getElementById("heatmap") .disabled = true; document.getElementById("sortableList").style.display = "none"; // 以前の結果(ソートリスト、カットオフ、パイチャート等)を削除 removeAllChild("sortableList"); removeAllChild("rate"); removeAllChild("optionHeader"); removeAllChild("cutoff"); removeAllChild("pieContainer"); removeAllChild("container"); // 「取得中」を表示 document.getElementById('retrieving').style.display = "block"; if(document.getElementById('bar').checked) chartType = 'bar'; else if(document.getElementById('heatmap').checked) chartType = 'heatmap'; else chartType = "bar_bundle"; gChartType = chartType var result = retrieveChartData(targets, chartType, gDataType); document.getElementById('retrieving').style.display = "none"; var root = document.getElementById('container'); root.textContent = ''; var cutoff = document.getElementById("cutoff"); var cutoffText = document.createElement("input"); cutoffText.id = "cutoffValue"; cutoffText.type = "text"; cutoffText.value = 0; // デフォルトは1%カット -> 初期表示は0%にしておく cutoffText.min = 0; cutoffText.max = 80; cutoffText.maxLength = 2; cutoffText.style.width = "4em"; cutoffText.style.textAlign = "right"; cutoff.appendChild(cutoffText); /* var unitLabel = document.createElement("span"); unitLabel.innerHTML = "%"; cutoff.appendChild(unitLabel); */ var cutoffButton = document.createElement("input"); cutoffButton.value = "% < cutoff"; cutoffButton.type = "button"; cutoff.appendChild(cutoffButton); //var result = JSON.parse(escape(jsonp)); if(gChartType == 'bar') showBarChart(result); else if(gChartType == 'heatmap'){ showHeatmap(result); }else showBarBundleChart(result); // 表示ボタン、チャートdom等を表示 document.getElementById("showButton").disabled = false; document.getElementById("bar") .disabled = false; document.getElementById("heatmap") .disabled = false; document.getElementById("sortableList").style.display = "block"; } // バーチャート(バンドル) ///////////////////////////////////////////////////////////////////////////////////////////////////// // JCBLの構造ページへ飛ぶ function jumpToStructureOnBundleBar(seq, x) { var chain = attrEscape(chart[0].xAxis[0].categories[x]); jumpToMassBank(gBarData[seq]["type"], chain, chart[0].adduct[seq][x]); //console.log(gBarData[seq]["type"] + " " + chain + " " + chart[0].adduct[seq][x]); } // データの切り替え(表示/非表示、0-intensity) /////////////////////////////////////////////////////////////////////////////////////////////////////////////// function setBarBundleData() { // inchiキー未処理 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// var target = []; // カットオフ値を考慮 var cutoff = parseInt(document.getElementById("cutoffValue").value); for(var j = 0; j < chart[0].data[0].length; j ++){ var not0 = false; for(var i = 0; i < chart[0].series.length; i ++){ if(chart[0].data[i][j][1] >= cutoff){ not0 = true; break; } } target[j] = not0; } var adduct = []; for(var j = 0; j < chart[0].series.length; j ++){ var i = 0; var data = []; var xLabels = []; adduct[j] = []; for(var k = 0; k < chart[0].srcdata[j].length; k ++){ if(target[k]){ // チェックボックスにチェックがついていれば表示対象 // data[i] = [chart[j].xLabels[k], chart[j].data[k][1]]; if(document.getElementById("ratio").checked) // 相対値か絶対値か data[i] = [chart[0].xLabels[k], chart[0].srcdata[j][k] * 100 / chart[0].max]; else data[i] = [chart[0].xLabels[k], chart[0].srcdata[j][k]]; xLabels[i] = chart[0].xLabels[k]; adduct[j][i] = gBarData[j][k]; i ++; } } if(document.getElementById("ratio").checked){ // 相対値でのY軸タイトル // chart[0].yAxis[0].setExtremes(0, 100); chart[0].yAxis[0].update({max: 100}); chart[0].yAxis[0].axisTitle.attr({text: RELATIVE_LABEL}); chart[0].tooltip.options.formatter = barchartTooltipPercent; } else { // 絶対値でのY軸タイトル // chart[0].yAxis[0].setExtremes(0, chart[0].max); chart[0].yAxis[0].update({max: chart.max}); chart[0].yAxis[0].axisTitle.attr({text: chart[0].quantification}); chart[0].tooltip.options.formatter = barchartTooltipValue; } chart[0].xAxis[0].categories = xLabels; chart[0].series[j].setData(data, true); } chart[0].adduct = adduct; unzoomBarCharts(); } // 表示 /////////////////////////////////////////////////////////////////////////////////////////////////////////////// function showBarBundleChart(result) { // create "ignore 0-intensity" button document.getElementById("cutoffValue").onchange = function(){ setBarBundleData(); }; // create "sortable list" var sortableList = document.getElementById("sortableList"); for(var i = 0; i < result[0].map.length; i ++){ var line = document.createElement("div"); var cbox = document.createElement("input"); cbox.setAttribute("type", "checkbox"); cbox.setAttribute("checked", "yes"); cbox.setAttribute("seq", i); cbox.setAttribute("disabled", "yes"); cbox.id = "item" + i; cbox.onchange = function(e){ // 表示/非表示の切り替え /* var index = this.parentElement.parentElement.id.replace("sortableList", ""); var sortableList = document.getElementById("sortableList" + index); var sequence = []; for(var i = 0, j = 0; i < sortableList.childNodes.length; i ++){ if(sortableList.childNodes[i].childNodes[0].checked) sequence[j++] = sortableList.childNodes[i].childNodes[0].getAttribute("seq"); }*/ setBarBundleData(); }; line.appendChild(cbox); var label = document.createElement("label"); label.setAttribute("for", "item" + i); label.innerHTML = escape(result[0].map[i].title); line.appendChild(label); sortableList.appendChild(line); } $('#sortableList').sortable(); $('#sortableList').sortable("disable"); /* $('#sortableList').sortable({ cursor: 'move', update: function(event, ui){ /* var index = ui.item[0].parentElement.id.replace("sortableList", ""); var sortableList = document.getElementById("sortableList" + index); var sequence = []; for(var i = 0, j = 0; i < sortableList.childNodes.length; i ++){ if(sortableList.childNodes[i].childNodes[0].checked) sequence[j++] = sortableList.childNodes[i].childNodes[0].getAttribute("seq"); }*//* setBarBundleData(); } });*/ // 凡例の切り替えを行うコンボボックス var changeLegend = document.getElementById("optionHeader"); var legendLabel = document.createElement("span"); legendLabel.innerHTML = "Legend"; changeLegend.appendChild(legendLabel); var selectLegend = document.createElement("select"); selectLegend.id = "selectLegend"; for(var i = 0; i < legendOptions.length; i ++){ var option = document.createElement('option'); option.setAttribute("value", legendOptions[i]); if(legendOptions[i] == "Genotype/Background") option.setAttribute("selected", "true"); option.innerHTML = legendOptions[i]; selectLegend.appendChild(option); } selectLegend.onchange = function(e){ var index = document.getElementById("selectLegend").selectedIndex; for(var i = 0; i < chart[0].series.length; i ++){ chart[0].series[i].update({name:chart[0].meta[i][legendOptions[index]]}, false); } chart[0].redraw(false); } changeLegend.appendChild(selectLegend); // create barchart(s) gBarData = []; chart = []; piechart = []; seriesData = []; data = []; srcdata = []; var meta = []; var root = document.getElementById('container'); var unifiedFlag = true; var unitType = ''; // データの整理 for(var i = 0; i < result[0].map.length; i ++){ // 単位の統一がなされているかチェック if(i == 0) // 一番最初の単位を基準とする unitType = result[0].map[i].meta.Quantification; else if(unitType != result[0].map[i].meta.Quantification){ // 基準の単位と違う単位を発見 unitType = '???'; unifiedFlag = false; } gBarData[i] = []; data[i] = []; srcdata[i] = []; var xLabels = []; for(var j = 0; j < result[0].map[i].data.length; j ++){ // data[j] = [attrEscape(result[0].x[j]), attrEscape(result[0].map[i].data[j][0] * 100 / result[0].map[i].max)]; data[i][j] = [attrEscape(result[0].x[j]), attrEscape(result[0].map[i].data[j][0] * 100 / result[0].maxOfAll)]; // 相対値を計算 srcdata[i][j] = attrEscape(result[0].map[i].data[j][0]); // もともとの値を計算 xLabels[j] = attrEscape(result[0].x[j] + " [" + result[0].map[i].data[j].meta["Internal standard"] + "]"); // X軸ラベル gBarData[i][j] = result[0].map[i].data[j].meta["Adduct"]; } // for link // var type = result[0].map[i].title.replace(/.*\//,"").replace("[","_").replace("]", ""); var type = result[0].map[i].title.split(" / ")[2]; var ionmode = ""; if(result[0].map[i].meta["Ion mode"] == "Positive") ionmode = "p"; else if(result[0].map[i].meta["Ion mode"] == "Negative") ionmode = "n"; gBarData[i]["type"] = type; gBarData[i]["ionmode"] = ionmode; //console.log(gBarData[i]); meta[i] = result[0].map[i].meta; seriesData[i] = { name: attrEscape(result[0].map[i].meta["Genotype/Background"]), data: data[i], events: { click: function(event) { //alert(event.point.name); var index = event.point.series.columnIndex; jumpToStructureOnBundleBar(index, event.point.x); } } } } // barchartの追加 var parent = document.createElement('div'); parent.id = 'container' + 0; parent.setAttribute("order", 0); root.appendChild(parent); chart[0] = new Highcharts.Chart({ chart: { type: 'column', zoomType: 'x', renderTo: parent }, title: { text: attrEscape(result[0].title) }, xAxis: { min: 0, type: 'category', labels: { rotation: -90, style: { fontSize: '11px', fontWeight: 'bold', fontFamily: 'Verdana, sans-serif' }, step: 1 } }, scrollbar: { enabled: true }, yAxis: { min: 0, max: 100, title: { text: RELATIVE_LABEL } }, legend: { enabled: true }, tooltip: { pointFormat: '<b>{point.y:.1f} %</b>', formatter: barchartTooltipPercent }, series: seriesData }); chart[0].xAxis[0].categories = xLabels; chart[0].data = data; chart[0].srcdata = srcdata; chart[0].max = result[0].maxOfAll; chart[0].xLabels = xLabels; chart[0].quantification = unitType; chart[0].meta = meta; chart[0].adduct = gBarData; // 絶対量/相対量を切り替えるチェックボックス var ratioCbox = document.createElement("input"); ratioCbox.setAttribute("type", "checkbox"); ratioCbox.setAttribute("checked", "no"); ratioCbox.id = "ratio"; ratioCbox.onchange = function(e){ setBarBundleData(); }; var label = document.createElement("label"); label.setAttribute("for", "ratio"); label.innerHTML = "ratio"; document.getElementById("rate").appendChild(ratioCbox); document.getElementById("rate").appendChild(label); resizeChart(); if(unifiedFlag == false) alert("intensityの単位が統一されていません。"); } // MassBankへ飛ぶ共通のメソッド function jumpToMassBank(lipidclass, chain, adduct) { var PRECURSOR_TYPE_NAMES = { '[M]+': 'p', '[M+H]+': 'Hp', '[M+Na]+': 'Nap', '[M+NH4]+': 'NH4p', '[M-H]-': 'Hm', '[M+FA-H]-': 'FAm', '[M+Hac-H]-': 'Hacm' }; var type = PRECURSOR_TYPE_NAMES[adduct]; window.open("http://133.242.136.63/wiki/Volatile:" + lipidclass + "?my_1=" + chain + "&my_2=" + type); // window.open("http://133.242.136.63/wiki/?lc=" + lipidclass + "&c=" + chain + "&p" + adduct, "new"); console.log(lipidclass +" " + chain +" " + adduct); } // バーチャート /////////////////////////////////////////////////////////////////////////////////////////////////////////////// // JCBLの構造ページへ飛ぶ function jumpToStructureOnBar(seq, x) { // window.open("http://jcbl.jp/wiki/LBG" + gBarData[seq][x], "new"); // window.open("http://133.242.136.63/wiki/Category:CS:" + gBarData[seq][x], "new"); // console.log(seq + "/" + x + " => " + gBarData[seq][x]); var chain = attrEscape(chart[0].xAxis[0].categories[x]); console.log(gBarData[seq]); jumpToMassBank(gBarData[seq]["type"], chain, chart[seq].adduct[x]); //console.log(gBarData[seq]["type"] + " " + chain + " " + chart[seq].adduct[x]); /* if(chain.indexOf("/") >= 0) chain = "(" + chain + ")"; else chain = "_" + chain; var link = gBarData[seq]["type"] + chain + gBarData[seq]["ionmode"]; window.open("http://133.242.136.63/wiki/Category:CS:" + link, "new"); console.log(seq + "/" + x + " => " + link); */ } // 全バーチャートのズーム解除 /////////////////////////////////////////////////////////////////////////////////////////////////////////////// function unzoomBarCharts() { for(var i = 0; i < chart.length; i ++){ //chart[i].xAxis[0].options.tickInterval = defaultTickInterval; chart[i].xAxis[0].isDirty = true; chart[i].xAxis[0].setExtremes(null, null, animation=true); } document.getElementById("resetZoomButton").style.visibility = "hidden"; } // バーチャートデータの切り替え(表示/非表示、0-intensityで呼ばれる) ////////////////////////////////////////////////////////////////////////////////////////////////////// function setBarchartData() { // inchiキー未処理 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// var target = []; var cutoff = parseInt(document.getElementById("cutoffValue").value); for(var j = 0; j < chart[0].data.length; j ++){ var not0 = false; for(var i = 0; i < chart.length; i ++){ if(chart[i].data[j][1] >= cutoff){ not0 = true; break; } } target[j] = not0; } for(var j = 0; j < chart.length; j ++){ var i = 0; var data = []; var xLabels = []; var adduct = []; for(var k = 0,l = 0; k < chart[j].data.length; k ++){ if(target[k]){ // data[i] = [chart[j].xLabels[k], chart[j].data[k][1]]; if(document.getElementById("ratio").checked) data[i] = [chart[j].xLabels[k], chart[j].srcdata[k] * 100 / chart[j].max]; else data[i] = [chart[j].xLabels[k], chart[j].srcdata[k]]; adduct[i] = gBarData[j].adduct[k]; xLabels[i++] = chart[j].xLabels[k]; } } if(document.getElementById("ratio").checked){ chart[j].yAxis[0].setExtremes(0, 100); // chart[j].yAxis[0].axisTitle.attr({text: "Relative Intensity (%)"}); chart[j].yAxis[0].axisTitle.attr({text: RELATIVE_LABEL}); chart[j].tooltip.options.formatter = barchartTooltipPercent; } else { chart[j].yAxis[0].setExtremes(0, chart[j].max); // chart[j].yAxis[0].axisTitle.attr({text: "Intensity (" + chart[j].quantification + ")"}); chart[j].yAxis[0].axisTitle.attr({text: chart[j].quantification}); chart[j].tooltip.options.formatter = barchartTooltipValue; } chart[j].xAxis[0].categories = xLabels; chart[j].series[0].setData(data, true); chart[j].adduct = adduct; } unzoomBarCharts(); } // 表示 /////////////////////////////////////////////////////////////////////////////////////////////////////////////// function showBarChart(result) { console.log(result); function computeTickInterval(xMin, xMax) { var zoomRange = xMax - xMin; if(zoomRange <= 2) currentTickInterval = 0.5; if(zoomRange < 20) currentTickInterval = 1; else if(zoomRange < 100) currentTickInterval = 5; } // create ignore 0-intensity button document.getElementById("cutoffValue").onchange = function(){ setBarchartData(); }; // create sortable list var sortableList = document.getElementById("sortableList"); for(var i = 0; i < result[0].map.length; i ++){ var line = document.createElement("div"); var cbox = document.createElement("input"); cbox.setAttribute("type", "checkbox"); cbox.setAttribute("checked", "yes"); cbox.setAttribute("seq", i); cbox.id = "item" + i; cbox.onchange = function(e){ // 表示/非表示の切り替え var seq = this.getAttribute("seq"); var option; if(this.checked){ option = "block"; } else { option = "none"; } document.getElementById("container" + seq).style.display = option; document.getElementById("pieContainer" + seq).style.display = option; }; line.appendChild(cbox); var label = document.createElement("label"); label.setAttribute("for", "item" + i); label.innerHTML = (i+1) + "." + escape(result[0].map[i].title); line.appendChild(label); sortableList.appendChild(line); } $('#sortableList').sortable({ cursor: 'move', update: function(event, ui){ var sortableList = document.getElementById("sortableList"); for(var i = 0; i < sortableList.childNodes.length; i ++){ var seq = sortableList.childNodes[i].childNodes[0].getAttribute("seq"); document.getElementById("container" + seq).setAttribute("order", i); document.getElementById("pieContainer" + seq).setAttribute("order", i); } $("#container").html( $("#container > div").sort(function(o1,o2) { var n1 = parseInt($(o1).attr("order"), 10); var n2 = parseInt($(o2).attr("order"), 10); if(n1 < n2) return -1; if(n1 > n2) return 1; return 0; }) ); $("#pieContainer").html( $("#pieContainer > div").sort(function(o1,o2) { var n1 = parseInt($(o1).attr("order"), 10); var n2 = parseInt($(o2).attr("order"), 10); if(n1 < n2) return -1; if(n1 > n2) return 1; return 0; }) ); } }); $('#sortableList').sortable("enable"); // パイチャートの表示/非表示の切り替え var switchPieHidden = document.getElementById("optionHeader"); var hiddenButton = document.createElement("input"); hiddenButton.setAttribute("type", "button"); hiddenButton.setAttribute("value", "hide piechart(s)"); hiddenButton.id = "switchPieHidden"; hiddenButton.onclick = function(e){ var pieContainer = document.getElementById("pieContainer"); if(pieContainer.style.display == "none"){ pieContainer.style.display = "block"; document.getElementById("switchPieHidden").setAttribute("value", "hide piechart(s)"); } else { pieContainer.style.display = "none"; document.getElementById("switchPieHidden").setAttribute("value", "show piechart(s)");; } resizeChart(); } switchPieHidden.appendChild(hiddenButton); // create barchart(s) gBarData = []; chart = []; piechart = []; var root = document.getElementById('container'); var pieRoot = document.getElementById('pieContainer'); for(var i = 0; i < result[0].map.length; i ++){ gBarData[i] = []; // データの整理 var data = []; var srcdata = []; var xLabels = []; gBarData[i].adduct = []; for(var j = 0; j < result[0].map[i].data.length; j ++){ // data[j] = [attrEscape(result[0].x[j]), attrEscape(result[0].map[i].data[j][0] * 100 / result[0].map[i].max)]; data[j] = [attrEscape(result[0].x[j]), attrEscape(result[0].map[i].data[j][0] * 100 / result[0].map[i].max)]; srcdata[j] = attrEscape(result[0].map[i].data[j][0]); xLabels[j] = attrEscape(result[0].x[j] + " [" + result[0].map[i].data[j].meta["Internal standard"] + "]"); gBarData[i].adduct[j] = result[0].map[i].data[j].meta["Adduct"]; // gBarData[i][j] = inchiEscape(result[0].map[i].data[j][2]); // InChIキー /* var type = result[0].map[i].title.replace(/.*\//,""); gBarData[i][j] = type + attrEscape(result[0].x[j]).replace("/","-"); // InChIキー*/ } // for link // var type = result[0].map[i].title.replace(/.*\//,"").replace("[","_").replace("]", ""); var type = result[0].map[i].title.split(" / ")[2]; var ionmode = ""; if(result[0].map[i].meta["Ion mode"] == "Positive") ionmode = "p"; else if(result[0].map[i].meta["Ion mode"] == "Negative") ionmode = "n"; gBarData[i]["type"] = type; gBarData[i]["ionmode"] = ionmode; gBarData[i]["pieclass"] = []; for(var j = 0; j < result[0].map[i].pie.length; j ++) gBarData[i]["pieclass"][j] = result[0].map[i].pie[j].name; // barchartの追加 var parent = document.createElement('div'); parent.id = 'container' + i; parent.setAttribute("order", i); root.appendChild(parent); chart[i] = new Highcharts.Chart({ chart: { type: 'column', zoomType: 'x', renderTo: parent, height: 250, resetZoomButton: { theme: { display: 'none' } } }, title: { text: (i+1) + '.' + attrEscape(result[0].map[i].title) }, xAxis: { min: 0, type: 'category', labels: { rotation: -90, style: { fontSize: '11px', fontWeight: 'bold', fontFamily: 'Verdana, sans-serif' }, step: 1 }, events : { afterSetExtremes: function(){ if(!this.chart.options.chart.isZoomed){ // 全バーチャートの拡大率を統一する if(this.chart.options.chart.isZoomed !== undefined) document.getElementById("resetZoomButton").style.visibility = "visible"; var xMin = this.chart.xAxis[0].min; var xMax = this.chart.xAxis[0].max; var zmRange = computeTickInterval(xMin, xMax); for(var i = 0; i < chart.length; i ++){ chart[i].xAxis[0].options.tickInterval = zmRange; chart[i].xAxis[0].isDirty = true; if(chart[i] !== this){ chart[i].options.chart.isZoomed = true; chart[i].xAxis[0].setExtremes(xMin, xMax, true); chart[i].options.chart.isZoomed = false; } } } }, } }, scrollbar: { enabled: true }, yAxis: { min: 0, max: 100, title: { text: RELATIVE_LABEL } }, legend: { enabled: false }, tooltip: { pointFormat: '<b>{point.y:.1f} %</b>', formatter: barchartTooltipPercent }, series: [{ name: 'Population', data: data, color: barColor, events: { click: function(event) { //alert(event.point.name); var index = event.target.farthestViewportElement.parentNode.parentElement.id.replace("container",""); jumpToStructureOnBar(index, event.point.x); } } }] }); chart[i].xAxis[0].categories = xLabels; chart[i].data = data; chart[i].srcdata = srcdata; chart[i].max = result[0].map[i].max; chart[i].xLabels = xLabels; chart[i].quantification = result[0].map[i].meta.Quantification; chart[i].adduct = gBarData[i].adduct; // piechartの追加 var pieParent = document.createElement('div'); pieParent.id = 'pieContainer' + i; pieParent.setAttribute("order", i); pieRoot.appendChild(pieParent); piechart[i] = new Highcharts.Chart({ chart: { plotBackgroundColor: null, plotBorderWidth: null, plotShadow: false, type: 'pie', renderTo: pieParent, height: 250 }, title: { text: (i+1) + '.Value ratio' }, tooltip: { pointFormat: '{series.name}: <b>{point.percentage:.1f}%</b>' }, plotOptions: { pie: { allowPointSelect: true, cursor: 'pointer', dataLabels: { enabled: true, format: '<b>{point.name}</b>: {point.percentage:.1f} %', style: { color: (Highcharts.theme && Highcharts.theme.contrastTextColor) || 'black' } } } }, series: [{ name: 'Rate', colorByPoint: true, data: result[0].map[i].pie, events: { click: function(event) { // パイチャートをクリックしたら、別lipidlcassへ切り替える barColor = event.point.color; var nextType = event.point.name; for(var i = 0; i < gBarData.length; i ++){ if(!(gBarData[i]["pieclass"].includes(nextType))){ alert("表示中の中に、" + nextType + "が含まれないデータがあるため、切り替えができません。"); return; } } var targets = []; var sortableList = document.getElementById("sortableList"); for(var i = 0; i < sortableList.childNodes.length; i ++){ var w = sortableList.childNodes[i].childNodes[1].innerHTML.replace(/^[0-9]+./,"").split(" / "); // targets.push(w[0] + " / " + w[1] + " / " + nextType + " / " + w[2]); targets.push(w[0] + " / " + w[1] + " / " + nextType + " / " + w[3]); } showChart(targets); } } }] }); } // 絶対量/相対量を切り替えるチェックボックス var ratioCbox = document.createElement("input"); ratioCbox.setAttribute("type", "checkbox"); ratioCbox.setAttribute("checked", "no"); ratioCbox.id = "ratio"; ratioCbox.onchange = function(e){ setBarchartData(); }; var label = document.createElement("label"); label.setAttribute("for", "ratio"); label.innerHTML = "ratio"; document.getElementById("rate").appendChild(ratioCbox); document.getElementById("rate").appendChild(label); resizeChart(); } // ヒートマップ /////////////////////////////////////////////////////////////////////////////////////////////////////////////// // JCBLの構造ページへ飛ぶ function jumpToStructureOnHeatmap(seq, x, y) { // window.open("http://jcbl.jp/wiki/LBG" + gHeatmapData[seq].map[0].title.replace(/.*\//, "") + gHeatmapData[seq].x[x].replace("/","-"), "new"); // window.open("http://133.242.136.63/wiki/Category:CS:" + gBarData[seq][x], "new"); // var type = gHeatmapData[0].map[0].title.replace(/.*\//,"").replace("[","_").replace("]", ""); var type = gHeatmapData[0].map[0].title.split(" / ")[2]; var chain = attrEscape(chart[0].xAxis[0].categories[x]); var adduct = gBarData[y].adduct[x]; jumpToMassBank(type, chain, adduct); //console.log(type + " " + chain + " " + adduct); /* if(chain.indexOf("/") >= 0) chain = "(" + chain + ")"; else chain = "_" + chain; var link = type + chain + gBarData[y]; window.open("http://133.242.136.63/wiki/Category:CS:" + link, "new"); console.log(seq + "/" + y + "/" + x + " => " + link); */ // console.log(seq + "/" + y + "/" + x + " => " + gHeatmapData[seq].x[x]); } // ヒートマップデータの切り替え(表示/非表示、0-intensityで呼ばれる) //////////////////////////////////////////////////////////////////////////////////////////////////////// // param index - 何番目のデータか(おそらく0のみ) // param seq - 順番を格納した配列 // return なし function setHeatmapData(index, seq) { var i = 0; var length = gHeatmapData[index].map.length; // カットオフ値の考慮 var target = []; var cutoff = parseInt(document.getElementById("cutoffValue").value); var xLabels = []; for(var k = 0; k < chart[index].data[0].length; k ++){ var not0 = false; for(var j = 0; j < length; j ++){ if(chart[index].data[j][k] >= cutoff){ not0 = true; break; } } target[k] = not0; if(not0) xLabels[i++] = gHeatmapData[index].x[k]; } // ジャンプ先の設定 gBarData = []; for(var j = 0; j < seq.length; j ++){ var ionmode = ""; if(gHeatmapData[index].map[seq[j]].meta["Ion mode"] == "Positive") ionmode = "p"; else if(gHeatmapData[index].map[seq[j]].meta["Ion mode"] == "Negative") ionmode = "n"; gBarData[j] = ionmode; // LBG + lipid class + chain } gBarData.reverse(); var data = []; var yLabels = []; chart[index].inchi = []; i = 0; // 表示されている中での最大値を取得する var maxOfDisplayedAll = 0; for(var j = 0; j < seq.length && j < length; j ++){ if(maxOfDisplayedAll < gHeatmapData[index].map[seq[j]].max) maxOfDisplayedAll = gHeatmapData[index].map[seq[j]].max; } var max = 0; // データのセット for(var j = 0; j < seq.length && j < length; j ++){ gBarData[j] = []; gBarData[j].adduct = []; if(document.getElementById("eachInRate").checked) max = gHeatmapData[index].map[seq[j]].max; else max = maxOfDisplayedAll; // max = gHeatmapData[index].maxOfAll; // 常に全ての最大値を基準にする場合はこちらを使う chart[index].inchi[j] = []; for(var k = 0,l = 0; k < gHeatmapData[index].map[seq[j]].data.length; k ++){ if(target[k]){ data[i] = [l, seq.length-j-1, attrEscape(gHeatmapData[index].map[seq[j]].data[k][0] * 100 / max)]; // 相対値の計算 chart[index].inchi[j][k] = inchiEscape(gHeatmapData[index].map[seq[j]].data[k].meta["InChIKey"]); // インチ―キー gBarData[j].adduct[l++] = gHeatmapData[index].map[seq[j]].data[k].meta["Adduct"]; i ++; } } var titleParts = gHeatmapData[index].map[seq[j]].title.split(" / "); yLabels[j] = (parseInt(seq[j])+1) + "." + attrEscape(titleParts[0] + " / " + titleParts[1] + " / " + titleParts[3]); // Y軸ラベル // yLabels[j] = (parseInt(seq[j])+1) + "." + attrEscape(gHeatmapData[index].map[seq[j]].title.replace(/\/[^\/]+$/, "")); // Y軸ラベル } gBarData.reverse(); yLabels.reverse(); chart[index].zoomOut(); chart[index].series[0].setData(data, true, true, false); chart[index].yAxis[0].setCategories(yLabels); chart[index].xAxis[0].setCategories(xLabels); // バグ対策用 - なぜか、データを再セットすると拡大されるため chart[index].xAxis[0].isDirty = true; chart[index].xAxis[0].setExtremes(null, null,animation=true); chart[index].yAxis[0].isDirty = true; chart[index].yAxis[0].setExtremes(null, null,animation=true); } // ヒートマップのデータを再設定する //////////////////////////////////////////////////////////////////////// // param index - ソートリストのインデックス(おそらく0のみ) // return なし function resetHeatmapData(index) { var sortableList = document.getElementById("sortableList" + index); var sequence = []; for(var i = 0, j = 0; i < sortableList.childNodes.length; i ++){ if(sortableList.childNodes[i].childNodes[0].checked) sequence[j++] = sortableList.childNodes[i].childNodes[0].getAttribute("seq"); } setHeatmapData(index, sequence); } // ヒートマップ作成 ///////////////////////////////////////////////////////////////////////////////////////// // param result チャートデータ // return なし function showHeatmap(result) { gBarData = []; gHeatmapData = []; var root = document.getElementById('container'); var sortableList = document.getElementById("sortableList"); chart = []; gHeatmapData = result; for(var i = 0; i < result.length; i ++){ var title = attrEscape(result[i].title); // 親要素 var parent = document.createElement('div'); parent.id = 'container' + i; root.appendChild(parent); var index = 0; var data = []; var yLabels = []; var length = result[i].map.length var inchi = []; var ratioData = []; // データの整理 for(var j = 0; j < length; j ++){ inchi[j] = []; ratioData[j] = []; gBarData[j] = {}; gBarData[j].adduct = []; for(var k = 0; k < result[i].map[j].data.length; k ++){ console.log(result[i].map[j].data[k]); data[index] = [k, length-j-1, attrEscape(result[i].map[j].data[k][0] * 100 / result[i].map[j].max)]; // 相対値の計算 // data[index] = [k, length-j-1, attrEscape(result[i].map[j].data[k][0] * 100 / result[i].maxOfAll)]; inchi[j][k] = inchiEscape(result[i].map[j].data[k].meta["InChIKey"]); // インチ-キーの格納 ratioData[j][k] = data[index][2]; // cutoff用%値 gBarData[j].adduct[k] = result[i].map[j].data[k].meta["Adduct"]; index ++; } /* var ionmode = ""; if(result[i].map[j].meta["Ion mode"] == "Positive") ionmode = "p"; else if(result[i].map[j].meta["Ion mode"] == "Negative") ionmode = "n"; gBarData[j] = ionmode; // LBG + lipid class + chain */ var titleParts = result[i].map[j].title.split(" / "); yLabels[j] = (j+1) + "." + attrEscape(titleParts[0] + " / " + titleParts[1] + " / " + titleParts[3]); // Y軸ラベル } //console.log(gBarData); gBarData.reverse(); //console.log(gBarData); yLabels.reverse(); // highchartsの性質上、Y軸ラベルを反転させる for(var j = 0; j < result[i].x.length; j ++) result[i].x[j] = attrEscape(result[i].x[j]); // X軸ラベル // create "ignore 0-intensity button" document.getElementById("cutoffValue").onchange = function(){ // 表示/非表示の切り替え // 下と同じなので、後でまとめる for(var index = 0; index < chart.length; index ++){ resetHeatmapData(index); } }; // create "sortable list" var listDiv = document.createElement("div"); listDiv.id = "sortableList" + i; for(var j = 0; j < result[i].map.length; j ++){ var line = document.createElement("div"); var cbox = document.createElement("input"); cbox.setAttribute("type", "checkbox"); cbox.setAttribute("checked", "yes"); cbox.setAttribute("seq", j); cbox.id = "item" + j; cbox.onchange = function(e){ // 表示/非表示の切り替え var index = this.parentElement.parentElement.id.replace("sortableList", ""); resetHeatmapData(index); }; line.appendChild(cbox); var label = document.createElement("label"); label.setAttribute("for", "item" + j); // label.innerHTML = (j+1) + "." + escape(result[i].map[j].title); var titleParts = result[i].map[j].title.split(" / "); label.innerHTML = (j+1) + "." + escape(titleParts[0] + " / " + titleParts[1] + " / " + titleParts[3]); line.appendChild(label); listDiv.appendChild(line); } sortableList.appendChild(listDiv); $('#sortableList' + i).sortable({ cursor: 'move', update: function(event, ui){ var index = ui.item[0].parentElement.id.replace("sortableList", ""); resetHeatmapData(index); } }); $('#sortableList').sortable(false); // それぞれのレート/全体でのレート var rateCbox = document.createElement("input"); rateCbox.setAttribute("type", "checkbox"); rateCbox.setAttribute("checked", "yes"); rateCbox.id = "eachInRate"; rateCbox.onchange = function(e){ // rateの切り替え resetHeatmapData(0); // 一つであると仮定するので、複数ある場合は修正が必要なことに注意 }; var label = document.createElement("label"); label.setAttribute("for", "eachInRate"); label.innerHTML = "ratio"; document.getElementById("rate").appendChild(rateCbox); document.getElementById("rate").appendChild(label); // ヒートマップ作成 chart[i] = new Highcharts.Chart({ chart: { type: 'heatmap', zoomType: 'xy', animation: 1, marginBottom: 0, plotBorderWidth: 0, renderTo: parent, animation: true, }, scrollbar: { enabled: true }, title: { text: title, align: 'left' }, xAxis: { categories: result[i].x, opposite: true, labels: { rotation: -90, style: { fontSize: '11px', fontWeight: 'bold', fontFamily: 'Verdana, sans-serif' }, step: 1 }, }, yAxis: { categories: yLabels, title: null, labels: { step: 1 } }, colorAxis: { min: 0, max: 100, minColor: '#ffffff', maxColor: Highcharts.getOptions().colors[8] }, legend: { align: 'right', layout: 'vertical', margin: 0, verticalAlign: 'top', y: 100, symbolHeight: 145 }, tooltip: { formatter: function () { return this.series.yAxis.categories[this.point.y] + '<br />' + this.series.xAxis.categories[this.point.x] + " [" + gHeatmapData[0].map[this.point.y].data[this.point.x].meta["Internal standard"] + ']<br />' + (Math.round(this.point.value*10)/10) + ' %'; } }, series: [{ name: 'HEK', borderWidth: 1, data: data, dataLabels: { enabled: false, color: '#000000' }, point: { events: { click: function(event){ // var index = event.target.farthestViewportElement.parentNode.parentElement.id.replace("container",""); jumpToStructureOnHeatmap(0, event.point.x, event.point.y); // jumpToJcbl(event.point.series.chart.inchi[event.point.y][event.point.x]); } } } }] }); chart[i].inchi = inchi; chart[i].data = ratioData; //chart.setSize(600,300,false); } resizeChart(); } // chainチャート //////////////////////////////////////////////////////////////////// // データの切り替え(表示/非表示、0-intensity) /////////////////////////////////////////////////////////////////////////////////////////////////////////////// function setChainData() { // inchiキー未処理 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// var target = []; // カットオフ値を考慮 var cutoff = parseInt(document.getElementById("cutoffValue").value); for(var j = 0; j < chart.data.length; j ++){ target[j] = chart.data[j]['y'] >= cutoff; } var i = 0; var data = []; var xLabels = []; adduct = []; // gBarData.ionmode = []; for(var k = 0; k < chart.srcdata.length; k ++){ if(target[k]){ // チェックボックスにチェックがついていれば表示対象 // data[i] = [chart[j].xLabels[k], chart[j].data[k][1]]; if(document.getElementById("ratio").checked) // 相対値か絶対値か data[i] = {y:chart.srcdata[k] * 100 / chart.max, color:chart.colors[k%chart.colors.length]}; else data[i] = {y:chart.srcdata[k], color:chart.colors[k%chart.colors.length]}; xLabels[i] = chart.xLabels[k]; /* var ionmode = ""; if(gChainData.ionmode[k] == "Positive") ionmode = "p"; else if(gChainData.ionmode[k] == "Negative") ionmode = "n"; gBarData.ionmode[i++] = ionmode; */ adduct[i++] = gBarData.adduct[k]; } } if(document.getElementById("ratio").checked){ // 相対値でのY軸タイトル // chart.yAxis[0].setExtremes(0, 100); chart.yAxis[0].update({max: 100}); chart.yAxis[0].axisTitle.attr({text: RELATIVE_LABEL}); chart.tooltip.options.formatter = barchartTooltipPercent; } else { // 絶対値でのY軸タイトル // chart.yAxis[0].setExtremes(0, chart.max); chart.yAxis[0].update({max: chart.max}); chart.yAxis[0].axisTitle.attr({text: chart.quantification}); chart.tooltip.options.formatter = barchartTooltipValue; } chart.xAxis[0].categories = xLabels; chart.series[0].setData(data, true); chart.adduct = adduct; chart.xAxis[0].isDirty = true; chart.xAxis[0].setExtremes(null, null, animation=true); } // param result 対象データ // return なし function showChainChart(result) { var colors = ['#ff7f7f','#7f7fff','#7fff7f','#ff7fbf','#bfff7f','#ff7fff','#7fffff','#000000','#bf7fff','#7fffbf','#ffbf7f','#808080']; gChainData = result; gChartType = "chain"; // cutoffボックス。冗長的なので、整理したい var cutoff = document.getElementById("cutoff"); var cutoffText = document.createElement("input"); cutoffText.id = "cutoffValue"; cutoffText.type = "text"; cutoffText.value = 0; // デフォルトは1%カット cutoffText.min = 0; cutoffText.max = 80; cutoffText.maxLength = 2; cutoffText.style.width = "4em"; cutoffText.style.textAlign = "right"; cutoffText.onchange = function(){ setChainData(); }; cutoff.appendChild(cutoffText); var cutoffButton = document.createElement("input"); cutoffButton.value = "% < cutoff"; cutoffButton.type = "button"; cutoff.appendChild(cutoffButton); // create "sortable list" var sortableList = document.getElementById("sortableList"); sortableList.style.display = "block"; for(var i = 0; i < result.x.length; i ++){ var line = document.createElement("div"); var cbox = document.createElement("input"); cbox.setAttribute("type", "checkbox"); cbox.setAttribute("checked", "yes"); cbox.setAttribute("seq", i); cbox.setAttribute("disabled", "yes"); cbox.id = "item" + i; line.appendChild(cbox); var label = document.createElement("label"); label.setAttribute("for", "item" + i); label.innerHTML = escape(result.x[i]); line.appendChild(label); sortableList.appendChild(line); } // create barchart(s) // gBarData = []; var root = document.getElementById('container'); // データの整理 gBarData = []; gBarData.lipidclass = result.lipidclass;//.replace("[","_").replace("](","(").replace(/:/g,"_"); gBarData.chain = result.chain; gBarData.adduct = []; var data = []; var srcdata = []; var xLabels = []; for(var j = 0; j < result.intensity.length; j ++){ // data[j] = [attrEscape(result.x[j]), attrEscape(result.intensity[j] * 100 / result.maxOfAll)]; // 相対値の計算 data[j] = {y:attrEscape(result.intensity[j] * 100 / result.maxOfAll), color:colors[j%colors.length]}; // 相対値の計算 srcdata[j] = attrEscape(result.intensity[j]); xLabels[j] = attrEscape(result.x[j]); gBarData.adduct[j] = result.adduct[j]; /* var ionmode = ""; if(result.ionmode[j] == "Positive") ionmode = "p"; else if(result.ionmode[j] == "Negative") ionmode = "n"; gBarData.ionmode[j] = ionmode;*/ // var type = result[0].map[i].title.replace(/.*\//,""); // gBarData[i][j] = type + attrEscape(result[0].x[j]).replace("/","-"); // InChIキー } // barchartの追加 var parent = document.createElement('div'); parent.id = 'container0'; root.appendChild(parent); chart = new Highcharts.Chart({ chart: { type: 'column', zoomType: 'x', renderTo: parent, height: 500 }, title: { text: attrEscape(result.title) }, xAxis: { min: 0, type: 'category', categories:result.x, labels: { rotation: -90, style: { fontSize: '15px', fontWeight: 'bold', fontFamily: 'Verdana, sans-serif' }, step: 1 } }, scrollbar: { enabled: true }, yAxis: { min: 0, max: 100, title: { text: RELATIVE_LABEL } }, legend: { enabled: false }, tooltip: { pointFormat: '<b>{point.y:.1f} %</b>', formatter: barchartTooltipPercent }, plotOptions: { column: { pointRange: 2 } }, series: [{ name: 'Population', data: data, events: { click: function(event) { jumpToStructureOnChain(event.point.x); } } }] }); // chart.xAxis[0].categories = result.x; chart.data = data; chart.srcdata = srcdata; chart.max = result.maxOfAll; chart.xLabels = xLabels; chart.quantification = result.quantification; chart.colors = colors; chart.adduct = gBarData.adduct; // 絶対量か相対量か var ratioCbox = document.createElement("input"); ratioCbox.setAttribute("type", "checkbox"); ratioCbox.setAttribute("checked", "no"); ratioCbox.id = "ratio"; ratioCbox.onchange = function(e){ setChainData(); }; var label = document.createElement("label"); label.setAttribute("for", "ratio"); label.innerHTML = "ratio"; document.getElementById("rate").appendChild(ratioCbox); document.getElementById("rate").appendChild(label); resizeChart(); if(result.quantification == "?") alert("intensityの単位が統一されていません。"); } function jumpToStructureOnChain(x) {/* var link = gBarData.title + gBarData.ionmode[x]; window.open("http://133.242.136.63/wiki/Category:CS:" + link, "new"); console.log(x + " => " + link); */ jumpToMassBank(gBarData.lipidclass, gBarData.chain, chart.adduct[x]); //console.log(gBarData.lipidclass + " " + gBarData.chain + " " + chart.adduct[x]); } // ツールチップ ////////////////////////////////////////////////////////// function barchartTooltipValue() { return this.x + '<br/ ><b>' + this.y.toFixed(getFloatNumber()) + '</b>'; } function barchartTooltipPercent() { return this.x + '<br/ ><b>' + this.y.toFixed(getFloatNumber()) + '%</b>'; } // ツールチップで表示する小数点数を取得する // function getFloatNumber() { var fp = 1; if(!document.getElementById("ratio").checked && gDataType == 'normalized') fp = 3; return fp; } // ※未使用※ /////////////////////////////////////////////////////////////////////////////////////////////////////////////// function getTarget(children, target) { for(var i = 0; i < children.length; i ++){ if(target == children[i].childNodes[0].textContent){ return $(children[i]); } // console.log(children[i].childNodes[0].textContent); } return null; }