Commit 04d778fa authored by qlobbe's avatar qlobbe

working on xAxis phylo

parent 2a2a0fb8
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<!-- lib CSS -->
<link rel="stylesheet" type="text/css" href="./lib/css/documentation.css">
<title>Documentation</title>
</head>
<body>
<!-- row 1 -->
<div class="phylo-documentation">
<h3 class="font-bold">How to build a phylomemy ?</h3>
<p>So far just have a look at the original publication <a href="https://journals.plos.org/plosone/article?id=10.1371/journal.pone.0054847">here</a>.</p>
<p>Or see the <a href="https://iscpif.fr/epique/epique-project-description/">epique</a> Web site.</p>
</div>
<!-- row 2 -->
<div class="phylo-footer font-bold font-small">iscpif // cnrs // 2019</div>
</body>
</script>
</html>
\ No newline at end of file
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- lib CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/css/bootstrap.min.css" integrity="sha384-GJzZqFGwb1QTTN6wy59ffF1BuGJpLSa9DkKMp0DgiMDm4iYMj70gZWKYbI706tWS" crossorigin="anonymous">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.6.3/css/all.css" integrity="sha384-UHRtZLI+pbxtHCWp1t77Bi1L4ZtiqrqD80Kn4Z8NTSRyMA2Fd33n5dQ8lWUE00s/" crossorigin="anonymous">
<link rel="stylesheet" type="text/css" href="./lib/css/qlobbe.css">
<link rel="stylesheet" type="text/css" href="./lib/css/awesome-bootstrap-checkbox.css">
<!-- lib Font -->
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Montserrat:600|Open+Sans">
<!-- lib JS -->
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.6/umd/popper.min.js" integrity="sha384-wHAiFfRlMFy6i5SRaxvfOCifBUQy1xHdJ/yoi7FRNXMRBu5WHdZYu1hA6ZOblgut" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/js/bootstrap.min.js" integrity="sha384-B0UglyR+jN6CkvvICOB2joaf5I4l3gm9GU6Hc1og6Ls7i6U/mkkaduKaBhlAXv9k" crossorigin="anonymous"></script>
<script src="https://d3js.org/d3.v5.min.js"></script>
<script type="text/javascript" src="./lib/js/utils.js"></script>
<title>Mèmiescape</title>
</head>
<body>
<div class="container-fluid h-100" id="main_view">
<div class="row h-100">
<div class="col-2" id="left_view">
<h5 class="title">
MÈMIESCAPE <small class="text-muted">v0.1</small>
</h5>
<hr>
<form>
<div class="form-group">
<div class="custom-file" id="#btn_file">
<input type="file" class="custom-file-input" id="get_file">
<label class="custom-file-label" for="get_file">Load a phylomemy ...</label>
</div>
</div>
<button type="button" class="btn btn-draw btn-block" id="btn_draw" desabled>Draw</button>
</form>
<div id="options">
<hr>
<div id="layer-group">
<a href="#" id="layer-btn" class="drop-down-menu" onclick="toggleDiv('layer-radio',200);"><i class="fa fa-caret-right rotate"></i> layer</a>
<ul id="layer-radio">
<li>
<div class="radio">
<input type="radio" name="radio1" id="radio1" value="option1" checked="">
<label for="radio1">inline</label>
</div>
</li>
<li>
<div class="radio">
<input type="radio" name="radio1" id="radio2" value="option2">
<label for="radio2">grid</label>
</div>
</li>
</ul>
</div>
</div>
</div>
<div class="col-10" id="right_view">
<div class="alert alert-info" id="processing">
<p class="text-center alert-label"><i class="fa fa-spinner fa-pulse fa-fw"></i> Processing the phylomemy ... </p>
</div>
</div>
</div>
</div>
<script type="text/javascript">
/*
* Draw functions
*/
function draw(phyloData) {
// set up margin
var margin = {t:0, r:30, b:15, l:0};
var w = document.getElementById("right_view").offsetWidth - margin.l - margin.r,
h = $(window).height() - margin.t - margin.b;
// draw svg view
var svg = d3.select("#right_view").append("svg")
.attr("width",w)
.attr("height",h);
var g = svg.append("g").attr("id","svg-view");
// draw phylomemy from file
var cptBranches = 0;
var cptNodes = 0;
var cptEdges = 0;
d3.xml(phyloData).then(data => {
var newNodes = document.importNode(data.documentElement,true);
svg.attr("viewBox", newNodes.getAttribute("viewBox"));
g.each(function(){
this.appendChild(newNodes);
})
svg.call(zoom)
d3.select("#right_view")
.append('button')
.attr("type","button")
.attr("id","btn_reset")
.attr("class","btn btn-light")
.append('i')
.attr("class","fas fa-expand-arrows-alt");
d3.select("#btn_reset").on("click", reset);
toggleDiv("processing",0)
})
// set up d3 zoom
var transform = d3.zoomIdentity;
zoom = d3.zoom()
.scaleExtent([1, 50])
.on("zoom", zoomed);
function zoomed() {
g.attr("transform", d3.event.transform);
}
function reset() {
console.log("coucou")
svg.transition().call(zoom.transform, d3.zoomIdentity);
}
}
/*
* Control functions
*/
window.onload = function() {
document.getElementById("btn_draw").disabled = true;
if ($('#get_file').val() != "C:\\fakepath\\") {
processInput($('#get_file'))
}
};
$('#btn_draw').on('click',function(){
clean()
toggleDiv("processing",0)
readFile(draw)
})
$('#get_file').on('change',function(){
processInput($(this))
})
$(".drop-down-menu").click(function () {
$(".rotate").toggleClass("down");
})
</script>
</body>
</html>
\ No newline at end of file
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<!-- lib CSS -->
<link rel="stylesheet" type="text/css" href="./lib/css/qlobbe.css">
<!-- external lib JS -->
<script type="text/javascript" src="./lib/js/d3.min.js"></script>
<script type="text/javascript" src="./lib/js/viz.js"></script>
<script type="text/javascript" src="./lib/js/full.render.js"></script>
<script type="text/javascript" src="./lib/js/jquery.min.js"></script>
<script type="text/javascript" src="./lib/js/JSXTransformer.js"></script>
<!-- home made lib JS -->
<script src="tools.js"></script>
<title>Mèmiescape</title>
</head>
<body>
<!-- row 1 -->
<div class="phylo-title font-bold">Mèmiescape</div>
<div class="phylo-folder">
<label for="file-path" class="input-file">
load a phylomemy →
</label>
<input type="file" id="file-path">
<label id="file-name" class="input-name"></label>
<button id="draw" class="input-draw">
draw
</button>
</div>
<!-- row 2 -->
<div class="phylo-info" id="phyloInfo"></div>
<div class="phylo-tree" id="phyloTree"></div>
<div class="phylo-proximity" id="phyloProximity">
<div class="proxi-info" id="proxiInfo"></div>
</div>
<!-- row 3 -->
<div class="phylo-compass">compas</div>
<!-- row 4 -->
<div class="phylo-timeline">timeline</div>
<div class="phylo-scape">phylomemy</div>
<!-- row 5 -->
<div class="phylo-footer font-bold font-small">iscpif // cnrs // 2019</div>
</body>
<script type="text/javascript">
var globalBranches = 0;
var globalGroups = 0;
var globalPeriods = 0;
// display the Draw button after loading a phylo
document.querySelector("#file-path").onchange = function(){
document.querySelector("#file-name").textContent = this.files[0].name;
document.querySelector("#draw").style.display = "inline-block";
}
// draw the phylo
document.querySelector("#draw").onclick = function() {
var file = document.getElementById("file-path").files[0];
var reader = new FileReader();
reader.onload = (function(f) {
return function(e) {
var viz = new Viz();
viz.renderJSONObject(e.target.result).then(function(json) {
draw(json)
});
};
})(file);
reader.readAsText(file, "UTF-8");
}
function draw(dotData) {
var docs = dotData.nbDocs;
var branches = dotData.objects.filter(node => node.nodeType == "branch");
var groups = dotData.objects.filter(node => node.nodeType == "group");
var periods = dotData.objects.filter(node => node.nodeType == "period");
globalGroups = groups.length;
globalBranches = branches.length;
globalPeriods = periods.length;
var proxiName = dotData.proxiName
var proxiInit = parseFloat(dotData.proxiInit)
var proxiStep = parseFloat(dotData.proxiStep)
var quaFactor = parseFloat(dotData.quaFactor)
drawProximity(proxiName,proxiInit,proxiStep,quaFactor)
drawTree(proxiInit,proxiStep,docs,toBranchTree(branches))
ReactDOM.render(React.createElement(phyloInfo, {
className: "info-out",
nbBranches: branches.length,
nbGroups: groups.length,
nbPeriods: periods.length
}), document.getElementById('phyloInfo'));
}
function toBranchTree (branches) {
var branchTree = [];
branches.forEach(function(b){
let arrId = (b.branchId).split(' ')
// if (arrId.length == 12) {
// arrId = arrId.slice(0,10)
// }
// console.log(arrId + ' : ' + arrId.length + ' : ' + (arrId.length - 1))
branchTree.push({"id":arrId,"level":arrId.length - 1,"label":b.label,"groups":parseInt(b.size)});
});
// console.log(branches.length)
return branchTree;
}
function drawTree (init, step, docs, branches) {
var $cell = $('#phyloTree'),
m = {t: 10, r: 3, b: 10, l: 10},
w = $cell.width(),
h = $cell.height()
pady = (h - m.t - m.b) / ((1 - init) / step)
padx = (w - 2 * m.r) / (2 * branches.length);
var svg =
d3.select("#phyloTree")
.append("svg")
.attr("width", w)
.attr("height", h)
var level = 0
for (var i = init; i <= 1; i = i + step) {
if (i == init) {
svg.append('text')
.attr("class","tree-head-text")
.attr("id","nbDocs")
.attr("dx",w / 2).attr("dy",m.t)
.text(parseInt(docs) + " documents");
var headWidth = d3.select("#nbDocs").node().getBoundingClientRect().width
svg.append('line')
.attr("class","tree-head-line")
.attr("x1",0 + m.r).attr("y1",m.t).attr("x2",w / 2 - headWidth / 2 - m.l).attr("y2",m.t);
svg.append('line')
.attr("class","tree-head-line")
.attr("x1",w / 2 + headWidth / 2 + m.l).attr("y1",m.t).attr("x2",w - m.r).attr("y2",m.t);
} else {
var cpt = 0,
x1 = 0,
x2 = 0,
cy = pady * level + m.t,
nbGroups = 0,
nbBranchs = 0;
branches.forEach(function (b){
nbBranchs ++;
var cx = m.r + padx + cpt * 2 * padx,
currId = (b.id).slice(0,level + 1),
nextId = [];
if (branches[cpt + 1] != undefined)
nextId = (branches[cpt + 1].id).slice(0,level + 1)
nbGroups = nbGroups + b.groups
if (currId.join('-') != nextId.join('-')) {
x2 = cx + padx - 5
if (cpt == 0)
x1 = cx - padx;
if (cpt + 1 == branches.length)
x2 = cx + padx;
if (b.level > level) {
drawTreeLine(x1,x2,cy,"tree-line",nbBranchs,nbGroups,"",init + level * step, init);
}
if (b.level == level) {
drawTreeLine(x1,x2,cy,"tree-branch-line",1,nbGroups,b.label,init + level * step, init);
}
if (b.level > 10 && level == 10) {
drawTreeLine(x1,x2,cy,"tree-branch-line",1,nbGroups,b.label,init + level * step, init);
}
nbBranchs = 0
nbGroups = 0
x1 = cx + padx + 5
}
cpt ++;
})
}
level ++;
}
function drawTreeLine (x1,x2,y,name,nbBranchs,nbGroups,label,proxi, init) {
svg.append('line')
.attr("class",name)
.attr("nbBranchs",nbBranchs)
.attr("nbGroups",nbGroups)
.attr("proxi",proxi)
.attr("x1",x1).attr("y1",y).attr("x2",x2).attr("y2",y)
.on("mouseover", function (d,i) {
ReactDOM.render(React.createElement(phyloInfo, {
className: "info-over",
nbPeriods: globalPeriods,
nbBranches: d3.select(this).attr("nbBranchs"),
nbGroups: d3.select(this).attr("nbGroups")
}), document.getElementById('phyloInfo'));
var $cell = $('#phyloProximity'),
m = {t: 10, r: 2, b: 10, l: 5},
w = $cell.width(),
h = $cell.height();
var proxiScale =
d3.scaleLinear()
.domain([init, 1])
.range([h - m.t, 0 + m.t]);
d3.select("#proxiSvg")
.append("g")
.attr("class", "proxi-axis-dot-hover")
.append("circle")
.attr("cx", 0.5 + m.l)
.attr("cy", proxiScale(1 - proxi))
.attr("r", 1.6 * m.r);
if (proxi != 1)
d3.select("#proxiSvg")
.append("g")
.attr("class", "proxi-axis-text-hover")
.append("text")
.attr("x", 3 * m.l)
.attr("y", proxiScale(1 - proxi))
.attr("dy","0.32em")
.text(proxi.toFixed(1));
})
.on("mouseout", function (d,i){
ReactDOM.render(React.createElement(phyloInfo, {
className: "info-out",
nbPeriods: globalPeriods,
nbBranches: globalBranches,
nbGroups: globalGroups
}), document.getElementById('phyloInfo'));
d3.selectAll(".proxi-axis-dot-hover").remove();
d3.selectAll(".proxi-axis-text-hover").remove();
})
}
}
function drawProximity (name,init,step,relevance) {
var $cell = $('#phyloProximity'),
m = {t: 10, r: 2, b: 10, l: 5},
w = $cell.width(),
h = $cell.height();
var svg =
d3.select("#phyloProximity")
.append("svg")
.attr("width", w)
.attr("height", h)
.attr("id","proxiSvg")
.attr("class","proxi-svg")
var proxiScale =
d3.scaleLinear()
.domain([init, 1])
.range([h - m.t, 0 + m.t]);
var proxiAxis =
svg => svg.attr("transform", `translate(${m.l},0)`)
.call(
d3.axisLeft(proxiScale)
.ticks(1)
.tickSize(0)
.tickFormat(formatTick))
.call(g => g.selectAll(".tick text")
.attr("x", 5 * m.l)
.attr("font-family", "Inter-Regular"))
svg.append("g").attr("class", "proxi-axis").call(proxiAxis);
svg.append("g").attr("class", "proxi-axis-dot")
.append("circle")
.attr("cx", 0.5 + m.l)
.attr("cy", m.t)
.attr("r", 1.5 * m.r);
svg.append("g")
.attr("class", "proxi-axis-text")
.append("text")
.attr("x", 3 * m.l)
.attr("y", m.t)
.attr("dy","0.32em")
.text(init.toFixed(1));
svg.append("g").attr("class", "proxi-axis-dot")
.append("circle")
.attr("cx", 0.5 + m.l)
.attr("cy", h - m.t)
.attr("r", 1.5 * m.r);
svg.append("g")
.attr("class", "proxi-axis-text")
.append("text")
.attr("x", 3 * m.l)
.attr("y", h - m.t)
.attr("dy","0.32em")
.text(1);
function formatTick(d) {
return "";
}
ReactDOM.render(React.createElement(proxiInfo, {
proxiName: name,
proxiQual: relevance
}), document.getElementById('proxiInfo'));
}
function drawPhylo(branches) {
console.log(branches)
}
</script>
<!-- lib react -->
<script src="./lib/js/react.development.js"></script>
<script src="./lib/js/react-dom.development.js"></script>
<script type="text/jsx">
class phyloInfo extends React.Component {
render() {
return <p>
<b>{this.props.nbPeriods}</b> periods<br></br>
<b className={this.props.className}>{this.props.nbBranches}</b> branches<br></br>
<b className={this.props.className}>{this.props.nbGroups}</b> groups
</p>;
}
}
class proxiInfo extends React.Component {
render() {
return <p>
proximity {this.props.proxiName}<br></br>
accuracy factor <b>{this.props.proxiQual}</b>
</p>;
}
}
</script>
</html>
\ No newline at end of file
...@@ -9,14 +9,11 @@ ...@@ -9,14 +9,11 @@
<!-- external lib JS --> <!-- external lib JS -->
<script type="text/javascript" src="./lib/js/d3.min.js"></script> <script type="text/javascript" src="./lib/js/d3.min.js"></script>
<script type="text/javascript" src="./lib/js/viz.js"></script>
<script type="text/javascript" src="./lib/js/full.render.js"></script>
<script type="text/javascript" src="./lib/js/JSXTransformer.js"></script> <script type="text/javascript" src="./lib/js/JSXTransformer.js"></script>
<script type="text/javascript" src="https://d3js.org/d3-contour.v1.js"></script>
<script src="https://d3js.org/d3-contour.v1.js"></script>
<!-- home made lib JS --> <!-- home made lib JS -->
<script src="tools.js"></script> <script type="text/javascript" src="./ressources.js"></script>
<title>Mèmiescape</title> <title>Mèmiescape</title>
...@@ -56,16 +53,11 @@ ...@@ -56,16 +53,11 @@
<!-- row 4 --> <!-- row 4 -->
<div class="phylo-compass">compas</div> <div class="phylo-scape" id="phyloScape"></div>
<div class="phylo-timeline" id="phyloTimeline"></div>
<!-- row 5 --> <!-- row 5 -->
<div class="phylo-timeline">timeline</div>
<div class="phylo-scape">phylomemy</div>
<!-- row 6 -->
<div class="phylo-footer font-bold font-small">iscpif // cnrs // 2020</div> <div class="phylo-footer font-bold font-small">iscpif // cnrs // 2020</div>
</body> </body>
...@@ -82,12 +74,6 @@ ...@@ -82,12 +74,6 @@
document.querySelector("#draw").onclick = function() { document.querySelector("#draw").onclick = function() {
var file = document.getElementById("file-path").files[0]; var file = document.getElementById("file-path").files[0];
// console.log(document.getElementById("file-path").files[0].mozFullPath)
// d3.json(file, function(data) {
// console.log(data);
// });
var reader = new FileReader(); var reader = new FileReader();
reader.onload = (function(f) { reader.onload = (function(f) {
return function(e) { return function(e) {
...@@ -97,11 +83,6 @@ ...@@ -97,11 +83,6 @@
} catch (error) { } catch (error) {
console.log(error) console.log(error)
} }
// // console.log(e.target.result)
// var viz = new Viz();
// viz.renderJSONObject(e.target.result).then(function(json) {
// draw(json)
// });
}; };
})(file); })(file);
reader.readAsText(file, "UTF-8"); reader.readAsText(file, "UTF-8");
...@@ -229,7 +210,6 @@ ...@@ -229,7 +210,6 @@
} }
} }
function draw(dotData) { function draw(dotData) {
// draw PhyloInfo // draw PhyloInfo
...@@ -256,6 +236,10 @@ ...@@ -256,6 +236,10 @@
// draw isoline caption // draw isoline caption
drawCaption(branches); drawCaption(branches);
// draw the phylo
drawPhylo(branches);
} }
......
...@@ -26,7 +26,7 @@ body { ...@@ -26,7 +26,7 @@ body {
font-size: 16px; font-size: 16px;
display: grid; display: grid;
grid-template-columns: repeat(15, 1fr); grid-template-columns: repeat(15, 1fr);
grid-template-rows: 2% 7% 7% 4% auto 1%; grid-template-rows: 2% 7% 7% auto 1%;
grid-gap: 10px; grid-gap: 10px;
height: calc(100vh - 20px); height: calc(100vh - 20px);
color: #0d1824; color: #0d1824;
...@@ -109,6 +109,7 @@ body { ...@@ -109,6 +109,7 @@ body {
grid-column: 15 / 16; grid-column: 15 / 16;
font-size: 14px; font-size: 14px;
padding-left: 15%; padding-left: 15%;
padding-bottom: 2px;
z-index: 2; z-index: 2;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
...@@ -117,30 +118,21 @@ body { ...@@ -117,30 +118,21 @@ body {
/* -------------------- */ /* -------------------- */
.phylo-compass { .phylo-scape {
grid-row: 4; grid-row: 4;
grid-column: 2 / 16; grid-column: 1 / 16;
background: rgba(223,216,200,0.25); /*background: #FFCC73;*/
} }
/* -------------------- */
.phylo-timeline { .phylo-timeline {
grid-row: 5; grid-row: 4;
grid-column: 1 / 2; grid-column: 1 / 2;
background: #B3822D;
}
.phylo-scape {
grid-row: 5;
grid-column: 2 / 16;
background: #FFCC73;
} }
/* -------------------- */ /* -------------------- */
.phylo-footer { .phylo-footer {
grid-row: 6; grid-row: 5;
grid-column: 2 / 16; grid-column: 2 / 16;
} }
...@@ -284,16 +276,19 @@ i.how:hover span { ...@@ -284,16 +276,19 @@ i.how:hover span {
} }
.peak-label { .peak-label {
text-align: center;
font-family: "Inter-Regular"; font-family: "Inter-Regular";
font-size: 14px; font-size: 14px;
font-style: normal; font-style: normal;
font-weight: 400; font-weight: 400;
border-radius: 3px;
color: #FFFFFF; color: #FFFFFF;
border-radius: 3px;
border-style: solid;
border-width: 2px;
border-color: white;
background: #0d1824; background: #0d1824;
padding :5px; padding: 5px;
text-align: center;
position: absolute;
z-index: 10; z-index: 10;
position: absolute;
visibility: hidden; visibility: hidden;
} }
\ No newline at end of file
class counter extends React.Component {
render() {
return React.createElement(
"div", null,
"↱ ", this.props.branchCount, " branches • ", this.props.groupCount, " groups • from ", this.props.from, " to ", this.props.to
);
}
}
class branchName extends React.Component {
render() {
return React.createElement(
"div", null,
this.props.name, this.props.groups
);
}
}
\ No newline at end of file
/* memiescape v2.0
contact : quentin.lobbe@iscpif.fr */
/* functions */
// draw the phylo
function drawPhylo(branches) {
var div = d3.select('#phyloScape')
.node().getBoundingClientRect(),
left = d3.select('#phyloTimeline')
.node().getBoundingClientRect().width,
top = left / 1.618,
m = {t:10, b:10, l:10, r:10},
w = div.width,
h = div.height - m.t - m.b;
var svg = d3
.select('#phyloScape')
.append("svg")
.attr("width" , w)
.attr("height", h + m.t + m.b)
.append("g")
.attr("transform", "translate(" + left + m.l + "," + top + m.t + ")");
// console.log(branches.map(b => b.x))
// var xAxis = d3.scaleLinear().domain([0,Math.max(...branches.map(b => b.x))]).range([2 * m.l, w - 2 * m.l]),
// = d3.scaleOrdinal().domain()
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment