Closed jcherry-risklens closed 4 years ago
Hi @jcherry-risklens - can you please share the Python code that generates this error so I can look at it for you?
Is that not what the images are showing? The error occurs after line 76.
Hi @jcherry-risklens - the screenshots are showing the invocation of Chord followed by the error, I need to see what transition_matrix is to help you with why! Most of it is missing in out
cell [75].
You could also call .to_html() and attach the .html file.
The content of transition_matrix is showing on the first image, line 75.
Here's the .html file:
<!DOCTYPE html>
<html>
<head>
<!--Chord - Python wrapper around d3-chord
This package enables the generation of Chord diagrams. They can be saved
directly to HTML files or displayed in a Jupyter Notebook output cell.
Copyright 2020, Dr. Shahin Rostami
http://shahinrostami.com
https://github.com/shahinrostami/chord
https://pypi.org/project/chord/
-->
<!--LICENSE
Chord (https://github.com/shahinrostami/chord) generates interactive chord diagrams.
Copyright (C) 2020 Dr. Shahin Rostami
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
-->
<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
<title>Chord Diagram</title>
<!-- Google Fonts -->
<script src="https://d3js.org/d3.v5.min.js"></script>
<link
href="https://fonts.googleapis.com/css?family=Lato:400,900"
rel="stylesheet"
type="text/css"
/>
<style>
.tippy-content {
font-family: "Lato", sans-serif;
}
#chart-d27af929, #featured-chart-d27af929 {
font-size: 16px;
font-family: "Lato", sans-serif;
text-align: center;
fill: #454545;
}
#chart-d27af929 svg, #featured-chart-d27af929 svg {
max-width: 700px;
}
@media (min-width: 600px) {
#chart-d27af929{
font-size: 20px;
}
}
</style>
</head>
<body>
<div id="chart-d27af929" class="chord">
</div>
<script src="https://unpkg.com/@popperjs/core@2"></script>
<script src="https://unpkg.com/tippy.js@6"></script>
<script>
var script = document.createElement("script");
script.type = "text/javascript";
script.src = "https://d3js.org/d3.v5.min.js";
script.onload = function () {
var script2 = document.createElement("script");
script2.type = "text/javascript";
script2.src = "https://datacrayon.com/assets/chord/script.js";
script2.onload = function () {
margin = {
left: 0,
top: 0,
right: 0,
bottom: 0
};
width = Math.min(window.innerWidth, 700) - margin.left - margin.right;
height = Math.min(window.innerWidth, 700) - margin.top - margin.bottom;
innerRadius = Math.min(width, height) * 0.39;
outerRadius = innerRadius * 1.1;
tag_id = "chart-d27af929";
padding = 0.01;
Names = Index(['1/1', '13/1', '14/17', '14/18', '14/19', '14/20', '14/21', '14/23',
'14/24', '14/25', '14/26', '14/27', '14/28', '14/29', '14/30', '14/31',
'14/32', '14/34', '14/35', '14/36', '14/41', '15/1', '16/1', '17/12',
'17/42', '17/45', '17/5', '18/12', '18/5', '19/12', '19/5', '2/1',
'4/12', '4/14', '4/2', '4/3', '4/38', '4/42', '4/5', '4/7', '4/8',
'4/9', '5/12', '5/13', '5/14', '5/2', '5/3', '5/37', '5/38', '5/4',
'5/40', '5/42', '5/5', '5/6', '5/7', '5/8', '5/9', '6/12', '6/14',
'6/3', '6/33', '6/38', '6/42', '6/43', '6/44', '6/5', '6/7', '6/8',
'7/12', '7/14', '7/2', '7/3', '7/38', '7/42', '7/5', '7/7', '7/8',
'7/9'],
dtype='object', name='ClientActionObjectID');
colors = d3.schemeSet1;
opacityDefault = 0.8;
matrix = [[1.45774427e-01 6.07393444e-03 2.09446015e-04 ... 0.00000000e+00
1.04723008e-04 0.00000000e+00]
[4.95121951e-01 3.25609756e-01 0.00000000e+00 ... 0.00000000e+00
0.00000000e+00 0.00000000e+00]
[0.00000000e+00 0.00000000e+00 1.25000000e-01 ... 0.00000000e+00
0.00000000e+00 0.00000000e+00]
...
[2.70270270e-02 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00
0.00000000e+00 0.00000000e+00]
[1.75438596e-02 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00
3.50877193e-02 0.00000000e+00]
[1.07526882e-02 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00
0.00000000e+00 0.00000000e+00]];
wrap_labels = true;
credit = false
////////////////////////////////////////////////////////////
/////////// Create scale and layout functions //////////////
////////////////////////////////////////////////////////////
var colors = d3
.scaleOrdinal()
.domain(d3.range(Names.length))
.range(colors);
//A "custom" d3 chord function that automatically sorts the order of the chords in such a manner to reduce overlap
var chord = customChordLayout()
.padding(padding)
.sortChords(d3.descending) //which chord should be shown on top when chords cross. Now the biggest chord is at the bottom
.matrix(matrix);
var arc = d3
.arc()
.innerRadius(innerRadius * 1.01)
.outerRadius(outerRadius);
var path = d3.ribbon().radius(innerRadius);
////////////////////////////////////////////////////////////
////////////////////// Create SVG //////////////////////////
///////////////////////////////////////////////////////////
var svg = d3
.select("#" + tag_id)
.append("svg")
.attr(
"viewBox",
"0 0 " +
(width + margin.left + margin.right) +
" " +
(height + margin.top + margin.bottom)
)
.attr("preserveAspectRatio", "xMinYMin meet")
.append("g")
.attr(
"transform",
"translate(" +
(width / 2 + margin.left) +
"," +
(height / 2 + margin.top) +
")"
);
d3
.select("#" + tag_id)
.append("span")
.style("display", "block")
.style("font-size", "12px")
.style("text-align", "right")
.style("font-family", '"Arial", sans-serif')
.html('get <a href="https://m8.fyi/chord">chord pro</a> [<a href="https://twitter.com/shahinrostami">@ShahinRostami</a>]');
d3
.select("#" + tag_id)
.select("span")
.append("span")
.style("font-size", "12px")
.style("font-family", '"Arial", sans-serif')
.html('<br>see more at <a href="https://stamilabs.com">StamiLabs.com</a>');
////////////////////////////////////////////////////////////
/////////////// Create the gradient fills //////////////////
////////////////////////////////////////////////////////////
//Function to create the id for each chord gradient
function getGradID(d) {
return (
"linkGrad-" + tag_id + "-" + d.source.index + "-" + d.target.index
);
}
//Create the gradients definitions for each chord
var grads = svg
.append("defs")
.selectAll("linearGradient")
.data(chord.chords())
.enter()
.append("linearGradient")
.attr("id", getGradID)
.attr("gradientUnits", "userSpaceOnUse")
.attr("x1", function (d, i) {
return (
innerRadius *
Math.cos(
(d.source.endAngle - d.source.startAngle) / 2 +
d.source.startAngle -
Math.PI / 2
)
);
})
.attr("y1", function (d, i) {
return (
innerRadius *
Math.sin(
(d.source.endAngle - d.source.startAngle) / 2 +
d.source.startAngle -
Math.PI / 2
)
);
})
.attr("x2", function (d, i) {
return (
innerRadius *
Math.cos(
(d.target.endAngle - d.target.startAngle) / 2 +
d.target.startAngle -
Math.PI / 2
)
);
})
.attr("y2", function (d, i) {
return (
innerRadius *
Math.sin(
(d.target.endAngle - d.target.startAngle) / 2 +
d.target.startAngle -
Math.PI / 2
)
);
});
//Set the starting color (at 0%)
grads
.append("stop")
.attr("offset", "0%")
.attr("stop-color", function (d) {
return colors(d.source.index);
});
//Set the ending color (at 100%)
grads
.append("stop")
.attr("offset", "100%")
.attr("stop-color", function (d) {
return colors(d.target.index);
});
////////////////////////////////////////////////////////////
////////////////// Draw outer Arcs /////////////////////////
////////////////////////////////////////////////////////////
var outerArcs = svg
.selectAll("g.group")
.data(chord.groups)
.enter()
.append("g")
.attr("class", "group")
.on("mouseover", fade(0.1, 1))
.on("mouseout", fade(opacityDefault, opacityDefault));
outerArcs
.append("path")
.style("fill", function (d) {
return colors(d.index);
})
.attr("d", arc)
.each(function (d, i) {
//Search pattern for everything between the start and the first capital L
var firstArcSection = /(^.+?)L/;
//Grab everything up to the first Line statement
var newArc = firstArcSection.exec(d3.select(this).attr("d"))[1];
//Replace all the comma's so that IE can handle it
newArc = newArc.replace(/,/g, " ");
//If the end angle lies beyond a quarter of a circle (90 degrees or pi/2)
//flip the end and start position
if (
(d.endAngle > (90 * Math.PI) / 180) &
(d.startAngle < (270 * Math.PI) / 180)
) {
var startLoc = /M(.*?)A/, //Everything between the first capital M and first capital A
middleLoc = /A(.*?)0 0 1/, //Everything between the first capital A and 0 0 1
endLoc = /0 0 1 (.*?)$/; //Everything between the first 0 0 1 and the end of the string (denoted by $)
//Flip the direction of the arc by switching the start en end point (and sweep flag)
//of those elements that are below the horizontal line
var newStart = endLoc.exec(newArc)[1];
var newEnd = startLoc.exec(newArc)[1];
var middleSec = middleLoc.exec(newArc)[1];
//Build up the new arc notation, set the sweep-flag to 0
newArc = "M" + newStart + "A" + middleSec + "0 0 0 " + newEnd;
} //if
//Create a new invisible arc that the text can flow along
svg
.append("path")
.attr("class", "hiddenArcs")
.attr("id", "arc-" + tag_id + "-" + i)
.attr("d", newArc)
.style("fill", "none");
});
////////////////////////////////////////////////////////////
////////////////// Append Names ////////////////////////////
////////////////////////////////////////////////////////////
//Append the label names on the outside
if (wrap_labels) {
outerArcs
.append("text")
.attr("class", "titles")
.attr("dy", function (d, i) {
return (d.endAngle > (90 * Math.PI) / 180) &
(d.startAngle < (270 * Math.PI) / 180)
? 25
: -16;
})
.append("textPath")
.attr("startOffset", "50%")
.style("text-anchor", "middle")
.attr("xlink:href", function (d, i) {
return "#arc-" + tag_id + "-" + i;
})
.text(function (d, i) {
return Names[i];
});
} else {
//Append the label names on the outside
outerArcs
.append("text")
.each(function (d) {
d.angle = (d.startAngle + d.endAngle) / 2;
})
.attr("dy", ".35em")
.attr("class", "titles")
.attr("text-anchor", function (d) {
return d.angle > Math.PI ? "end" : null;
})
.attr("transform", function (d) {
return (
"rotate(" +
((d.angle * 180) / Math.PI - 90) +
")" +
"translate(" +
(outerRadius + 10) +
")" +
(d.angle > Math.PI ? "rotate(180)" : "")
);
})
.text(function (d, i) {
return Names[i];
});
}
////////////////////////////////////////////////////////////
////////////////// Draw inner chords ///////////////////////
////////////////////////////////////////////////////////////
svg
.selectAll("path.chord")
.data(chord.chords)
.enter()
.append("path")
.attr("class", "chord")
.style("fill", function (d) {
return "url(#" + getGradID(d) + ")";
})
.style("opacity", opacityDefault)
.attr("d", path)
.on("mouseover", mouseoverChord())
.on("mouseout", mouseoutChord(opacityDefault, opacityDefault));
////////////////////////////////////////////////////////////
////////////////// Extra Functions /////////////////////////
////////////////////////////////////////////////////////////
//Returns an event handler for fading a given chord group.
function fade(opacityIn, opacityOut) {
return function (d, i) {
d3.select(this.ownerSVGElement)
.selectAll("path.chord")
.filter(function (d) {
return d.source.index !== i && d.target.index !== i;
})
.transition()
.style("opacity", opacityIn);
d3.select(this.ownerSVGElement)
.selectAll("path.chord")
.filter(function (d) {
return d.source.index == i || d.target.index == i;
})
.transition()
.style("opacity", opacityOut);
};
} //fade
//Highlight hovered over chord
function mouseoverChord() {
return function (d, i) {
d3.select(this.ownerSVGElement)
.selectAll("path.chord")
.transition()
.style("opacity", 0.1);
//Show hovered over chord with full opacity
d3.select(this).transition().style("opacity", 1);
tippy_content = "<span style='font-weight:900'>" +
Names[d.source.index] +
"</span> and <span style='font-weight:900'>" +
Names[d.target.index] +
"</span><br>occur together in <span style='font-weight:900'>" +
d.source.value +
"</span> instances";
if(this._tippy == null)
{
tippy(this, {
allowHTML: true,
followCursor: true,
content: tippy_content,
size: "large",
arrow: true,
});
}
};
} //fade
//Bring all chords back to default opacity
function mouseoutChord(opacityIn, opacityOut) {
return function (d, i) {
d3.select(this.ownerSVGElement)
.selectAll("path.chord")
.transition()
.style("opacity", opacityOut);
};
//Set opacity back to default for all
} //function mouseoutChord
};
document.body.appendChild(script2);
};
document.body.appendChild(script);
</script>
<script></script>
</body>
</html>
The matrix variable is concerning... it's truncating it for some reason...
Well I'll be darned... this works perfectly: Chord(transition_matrix.values.tolist(), transition_matrix.index.values.tolist()).show()
.
and there we have the culprit!
Try passing in .values.tolist()
...
Well I'll be darned... this works perfectly:
Chord(transition_matrix.values.tolist(), transition_matrix.index.values.tolist()).show()
.
Seems you updated your reply as I was posting mine - I'm glad it's working for you now 👍! If you're interested, Chord Pro has many more features https://datacrayon.com/shop/product/chord-pro/ 💯
Thanks, seems like such a simple little thing. I've been spoiled by using pandas and numpy!
I'm trying to render a chord plot in Jupyter Lab, but am getting an empty space where the output should be:
Currently running chord v0.3.0, and jupyterlab v2.1.1. Browser is Chrome.