MediaWiki:LipoqualityChart.js: Difference between revisions
Jcblmaster (talk | contribs) No edit summary |
Jcblmaster (talk | contribs) No edit summary |
||
| (11 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 45: | 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 56: | 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 62: | 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 108: | 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 151: | 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 167: | 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 178: | 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 184: | 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 234: | 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 258: | 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 279: | 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 302: | 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]); // X軸ラベル | 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 | // for link | ||
// var type = result[0].map[i].title.replace(/.*\//,"").replace("[","_").replace("]", ""); | |||
var type = result[0].map[i].title.split(" / ")[2]; | |||
var ionmode = ""; | var ionmode = ""; | ||
if(result[0].map[i].meta["Ion mode"] == "Positive") | if(result[0].map[i].meta["Ion mode"] == "Positive") | ||
| Line 313: | Line 332: | ||
gBarData[i]["type"] = type; | gBarData[i]["type"] = type; | ||
gBarData[i]["ionmode"] = ionmode; | 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: { | ||
| Line 322: | Line 342: | ||
//alert(event.point.name); | //alert(event.point.name); | ||
var index = event.point.series.columnIndex; | var index = event.point.series.columnIndex; | ||
jumpToStructureOnBundleBar(index, event.point.x); | |||
} | } | ||
} | } | ||
| Line 349: | Line 369: | ||
style: { | style: { | ||
fontSize: '11px', | fontSize: '11px', | ||
fontWeight: 'bold', | |||
fontFamily: 'Verdana, sans-serif' | fontFamily: 'Verdana, sans-serif' | ||
}, | }, | ||
| Line 361: | Line 382: | ||
max: 100, | max: 100, | ||
title: { | title: { | ||
text: | text: RELATIVE_LABEL | ||
} | } | ||
}, | }, | ||
| Line 369: | Line 390: | ||
tooltip: { | tooltip: { | ||
pointFormat: '<b>{point.y:.1f} %</b>', | pointFormat: '<b>{point.y:.1f} %</b>', | ||
formatter: | formatter: barchartTooltipPercent | ||
}, | }, | ||
series: seriesData | series: seriesData | ||
| Line 380: | Line 401: | ||
chart[0].quantification = unitType; | chart[0].quantification = unitType; | ||
chart[0].meta = meta; | chart[0].meta = meta; | ||
chart[0].adduct = gBarData; | |||
// 絶対量/相対量を切り替えるチェックボックス | // 絶対量/相対量を切り替えるチェックボックス | ||
| Line 399: | 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 408: | Line 447: | ||
// window.open("http://133.242.136.63/wiki/Category:CS:" + 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]); | // console.log(seq + "/" + x + " => " + gBarData[seq][x]); | ||
var chain = attrEscape(chart[0].xAxis[0].categories[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 + ")"; | chain = "(" + chain + ")"; | ||
else | else | ||
| Line 416: | Line 458: | ||
window.open("http://133.242.136.63/wiki/Category:CS:" + link, "new"); | window.open("http://133.242.136.63/wiki/Category:CS:" + link, "new"); | ||
console.log(seq + "/" + x + " => " + link); | console.log(seq + "/" + x + " => " + link); | ||
*/ | |||
} | } | ||
// 全バーチャートのズーム解除 /////////////////////////////////////////////////////////////////////////////////////////////////////////////// | // 全バーチャートのズーム解除 /////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
| Line 443: | 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 453: | 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 458: | 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 475: | Line 523: | ||
function showBarChart(result) | function showBarChart(result) | ||
{ | { | ||
console.log(result); | |||
function computeTickInterval(xMin, xMax) | function computeTickInterval(xMin, xMax) | ||
{ | { | ||
| Line 516: | 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 552: | Line 600: | ||
} | } | ||
}); | }); | ||
$('#sortableList').sortable("enable"); | |||
// パイチャートの表示/非表示の切り替え | // パイチャートの表示/非表示の切り替え | ||
var switchPieHidden = document.getElementById("optionHeader"); | var switchPieHidden = document.getElementById("optionHeader"); | ||
| Line 583: | 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キー | ||
| Line 594: | Line 645: | ||
} | } | ||
// for link | // for link | ||
// var type = result[0].map[i].title.replace(/.*\//,"").replace("[","_").replace("]", ""); | |||
var type = result[0].map[i].title.split(" / ")[2]; | |||
var ionmode = ""; | var ionmode = ""; | ||
if(result[0].map[i].meta["Ion mode"] == "Positive") | if(result[0].map[i].meta["Ion mode"] == "Positive") | ||
| Line 602: | Line 654: | ||
gBarData[i]["type"] = type; | gBarData[i]["type"] = type; | ||
gBarData[i]["ionmode"] = ionmode; | 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 630: | Line 685: | ||
style: { | style: { | ||
fontSize: '11px', | fontSize: '11px', | ||
fontWeight: 'bold', | |||
fontFamily: 'Verdana, sans-serif' | fontFamily: 'Verdana, sans-serif' | ||
}, | }, | ||
| Line 665: | Line 721: | ||
max: 100, | max: 100, | ||
title: { | title: { | ||
text: | text: RELATIVE_LABEL | ||
} | } | ||
}, | }, | ||
| Line 673: | Line 729: | ||
tooltip: { | tooltip: { | ||
pointFormat: '<b>{point.y:.1f} %</b>', | pointFormat: '<b>{point.y:.1f} %</b>', | ||
formatter: | formatter: barchartTooltipPercent | ||
}, | }, | ||
series: [{ | series: [{ | ||
| Line 694: | 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 710: | Line 767: | ||
}, | }, | ||
title: { | title: { | ||
text: (i+1) + '. | text: (i+1) + '.Value ratio' | ||
}, | }, | ||
tooltip: { | tooltip: { | ||
| Line 738: | 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 772: | Line 836: | ||
// window.open("http://jcbl.jp/wiki/LBG" + gHeatmapData[seq].map[0].title.replace(/.*\//, "") + gHeatmapData[seq].x[x].replace("/","-"), "new"); | // 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"); | // 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 chain = attrEscape(chart[0].xAxis[0].categories[x]). | 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 + ")"; | chain = "(" + chain + ")"; | ||
else | else | ||
| Line 781: | Line 849: | ||
window.open("http://133.242.136.63/wiki/Category:CS:" + link, "new"); | window.open("http://133.242.136.63/wiki/Category:CS:" + link, "new"); | ||
console.log(seq + "/" + y + "/" + x + " => " + link); | console.log(seq + "/" + y + "/" + x + " => " + link); | ||
*/ | |||
// console.log(seq + "/" + y + "/" + x + " => " + gHeatmapData[seq].x[x]); | // console.log(seq + "/" + y + "/" + x + " => " + gHeatmapData[seq].x[x]); | ||
| Line 836: | 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 844: | 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 906: | 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") | if(result[i].map[j].meta["Ion mode"] == "Positive") | ||
ionmode = "p"; | ionmode = "p"; | ||
| Line 919: | Line 997: | ||
ionmode = "n"; | ionmode = "n"; | ||
gBarData[j] = ionmode; // LBG + lipid class + chain | gBarData[j] = ionmode; // LBG + lipid class + chain | ||
*/ | |||
yLabels[j] = (j+1) + "." + attrEscape( | 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(); | 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 953: | 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 1,011: | Line 1,094: | ||
style: { | style: { | ||
fontSize: '11px', | fontSize: '11px', | ||
fontWeight: 'bold', | |||
fontFamily: 'Verdana, sans-serif' | fontFamily: 'Verdana, sans-serif' | ||
}, | }, | ||
| Line 1,044: | 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,088: | Line 1,172: | ||
var data = []; | var data = []; | ||
var xLabels = []; | var xLabels = []; | ||
gBarData.ionmode = []; | 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,097: | Line 1,182: | ||
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] = chart.xLabels[k]; | xLabels[i] = chart.xLabels[k]; | ||
/* | |||
var ionmode = ""; | var ionmode = ""; | ||
if(gChainData.ionmode[k] == "Positive") | if(gChainData.ionmode[k] == "Positive") | ||
| Line 1,104: | Line 1,189: | ||
ionmode = "n"; | ionmode = "n"; | ||
gBarData.ionmode[i++] = ionmode; | gBarData.ionmode[i++] = ionmode; | ||
*/ | |||
adduct[i++] = gBarData.adduct[k]; | |||
} | } | ||
} | } | ||
| Line 1,109: | 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,179: | Line 1,267: | ||
// データの整理 | // データの整理 | ||
gBarData = []; | gBarData = []; | ||
gBarData. | gBarData.lipidclass = result.lipidclass;//.replace("[","_").replace("](","(").replace(/:/g,"_"); | ||
gBarData. | gBarData.chain = result.chain; | ||
gBarData.adduct = []; | |||
var data = []; | var data = []; | ||
var srcdata = []; | var srcdata = []; | ||
| Line 1,190: | Line 1,279: | ||
xLabels[j] = attrEscape(result.x[j]); | xLabels[j] = attrEscape(result.x[j]); | ||
var ionmode = ""; | gBarData.adduct[j] = result.adduct[j]; | ||
/* var ionmode = ""; | |||
if(result.ionmode[j] == "Positive") | if(result.ionmode[j] == "Positive") | ||
ionmode = "p"; | ionmode = "p"; | ||
else if(result.ionmode[j] == "Negative") | else if(result.ionmode[j] == "Negative") | ||
ionmode = "n"; | ionmode = "n"; | ||
gBarData.ionmode[j] = ionmode; | 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,221: | Line 1,311: | ||
rotation: -90, | rotation: -90, | ||
style: { | style: { | ||
fontSize: ' | fontSize: '15px', | ||
fontWeight: 'bold', | |||
fontFamily: 'Verdana, sans-serif' | fontFamily: 'Verdana, sans-serif' | ||
}, | }, | ||
| Line 1,234: | Line 1,325: | ||
max: 100, | max: 100, | ||
title: { | title: { | ||
text: | text: RELATIVE_LABEL | ||
} | } | ||
}, | }, | ||
| Line 1,242: | 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,262: | Line 1,358: | ||
chart.quantification = result.quantification; | chart.quantification = result.quantification; | ||
chart.colors = colors; | chart.colors = colors; | ||
chart.adduct = gBarData.adduct; | |||
// 絶対量か相対量か | // 絶対量か相対量か | ||
| Line 1,283: | Line 1,380: | ||
} | } | ||
function jumpToStructureOnChain(x) | function jumpToStructureOnChain(x) | ||
{ | {/* | ||
var link = gBarData.title + gBarData.ionmode[x]; | var link = gBarData.title + gBarData.ionmode[x]; | ||
window.open("http://133.242.136.63/wiki/Category:CS:" + link, "new"); | window.open("http://133.242.136.63/wiki/Category:CS:" + link, "new"); | ||
console.log(x + " => " + link); | 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; | |||
} | } | ||
// ※未使用※ /////////////////////////////////////////////////////////////////////////////////////////////////////////////// | // ※未使用※ /////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
Latest revision as of 11: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;
}