Skip to content

Instantly share code, notes, and snippets.

@jkw552403
Last active October 25, 2020 14:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jkw552403/c630ddfbbb1af97e86e17e1d0bf4eb83 to your computer and use it in GitHub Desktop.
Save jkw552403/c630ddfbbb1af97e86e17e1d0bf4eb83 to your computer and use it in GitHub Desktop.
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"from string import Template\n",
"from IPython.display import Javascript"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Load d3 related scripts"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<script src=\"https://d3js.org/d3.v6.min.js\"></script>\n",
"<script src=\"https://d3js.org/d3-hierarchy.v2.min.js\"></script>\n"
],
"text/plain": [
"<IPython.core.display.HTML object>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"%%html\n",
"<script src=\"https://d3js.org/d3.v6.min.js\"></script>\n",
"<script src=\"https://d3js.org/d3-hierarchy.v2.min.js\"></script>"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Read data into a Python str"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"# Assume flare-2.json exists in your working directory\n",
"with open('./flare-2.json') as f:\n",
" data_str = f.read()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Create JavaScript template in Python"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"tree_js_template = Template(\"\"\"\n",
"const dx = 10;\n",
"const width = 1080;\n",
"const dy = width / 6;\n",
"const margin = ({ top: 10, right: 120, bottom: 10, left: 40 })\n",
"const root = d3.hierarchy($data);\n",
"const tree = d3.tree().nodeSize([dx, dy])\n",
"const diagonal = d3.linkHorizontal().x(d => d.y).y(d => d.x)\n",
"\n",
"root.x0 = dy / 2;\n",
"root.y0 = 0;\n",
"root.descendants().forEach((d, i) => {\n",
" d.id = i;\n",
" d._children = d.children;\n",
" if (d.depth && d.data.name.length !== 7) d.children = null;\n",
"});\n",
"\n",
"// Select the cell output DOM\n",
"const svg = d3.select(element)\n",
" .append(\"svg\")\n",
" .attr(\"viewBox\", [-margin.left, -margin.top, width, dx])\n",
" .style(\"font\", \"10px sans-serif\")\n",
" .style(\"user-select\", \"none\");\n",
"\n",
"const gLink = svg.append(\"g\")\n",
" .attr(\"fill\", \"none\")\n",
" .attr(\"stroke\", \"#555\")\n",
" .attr(\"stroke-opacity\", 0.4)\n",
" .attr(\"stroke-width\", 1.5);\n",
"\n",
"const gNode = svg.append(\"g\")\n",
" .attr(\"cursor\", \"pointer\")\n",
" .attr(\"pointer-events\", \"all\");\n",
"\n",
"function update(source) {\n",
" const duration = d3.event && d3.event.altKey ? 2500 : 250;\n",
" const nodes = root.descendants().reverse();\n",
" const links = root.links();\n",
"\n",
" // Compute the new tree layout.\n",
" tree(root);\n",
"\n",
" let left = root;\n",
" let right = root;\n",
" root.eachBefore(node => {\n",
" if (node.x < left.x) left = node;\n",
" if (node.x > right.x) right = node;\n",
" });\n",
"\n",
" const height = right.x - left.x + margin.top + margin.bottom;\n",
"\n",
" const transition = svg.transition()\n",
" .duration(duration)\n",
" .attr(\"viewBox\", [-margin.left, left.x - margin.top, width, height])\n",
" .tween(\"resize\", window.ResizeObserver ? null : () => () => svg.dispatch(\"toggle\"));\n",
"\n",
" // Update the nodes…\n",
" const node = gNode.selectAll(\"g\")\n",
" .data(nodes, d => d.id);\n",
"\n",
" // Enter any new nodes at the parent's previous position.\n",
" const nodeEnter = node.enter().append(\"g\")\n",
" .attr(\"transform\", d => `translate(${source.y0},${source.x0})`)\n",
" .attr(\"fill-opacity\", 0)\n",
" .attr(\"stroke-opacity\", 0)\n",
" .on(\"click\", (event, d) => {\n",
" d.children = d.children ? null : d._children;\n",
" update(d);\n",
" });\n",
"\n",
" nodeEnter.append(\"circle\")\n",
" .attr(\"r\", 2.5)\n",
" .attr(\"fill\", d => d._children ? \"#555\" : \"#999\")\n",
" .attr(\"stroke-width\", 10);\n",
"\n",
" nodeEnter.append(\"text\")\n",
" .attr(\"dy\", \"0.31em\")\n",
" .attr(\"x\", d => d._children ? -6 : 6)\n",
" .attr(\"text-anchor\", d => d._children ? \"end\" : \"start\")\n",
" .text(d => d.data.name)\n",
" .clone(true).lower()\n",
" .attr(\"stroke-linejoin\", \"round\")\n",
" .attr(\"stroke-width\", 3)\n",
" .attr(\"stroke\", \"white\");\n",
"\n",
" // Transition nodes to their new position.\n",
" const nodeUpdate = node.merge(nodeEnter).transition(transition)\n",
" .attr(\"transform\", d => `translate(${d.y},${d.x})`)\n",
" .attr(\"fill-opacity\", 1)\n",
" .attr(\"stroke-opacity\", 1);\n",
"\n",
" // Transition exiting nodes to the parent's new position.\n",
" const nodeExit = node.exit().transition(transition).remove()\n",
" .attr(\"transform\", d => `translate(${source.y},${source.x})`)\n",
" .attr(\"fill-opacity\", 0)\n",
" .attr(\"stroke-opacity\", 0);\n",
"\n",
" // Update the links…\n",
" const link = gLink.selectAll(\"path\")\n",
" .data(links, d => d.target.id);\n",
"\n",
" // Enter any new links at the parent's previous position.\n",
" const linkEnter = link.enter().append(\"path\")\n",
" .attr(\"d\", d => {\n",
" const o = { x: source.x0, y: source.y0 };\n",
" return diagonal({ source: o, target: o });\n",
" });\n",
"\n",
" // Transition links to their new position.\n",
" link.merge(linkEnter).transition(transition)\n",
" .attr(\"d\", diagonal);\n",
"\n",
" // Transition exiting nodes to the parent's new position.\n",
" link.exit().transition(transition).remove()\n",
" .attr(\"d\", d => {\n",
" const o = { x: source.x, y: source.y };\n",
" return diagonal({ source: o, target: o });\n",
" });\n",
"\n",
" // Stash the old positions for transition.\n",
" root.eachBefore(d => {\n",
" d.x0 = d.x;\n",
" d.y0 = d.y;\n",
" });\n",
"}\n",
"\n",
"update(root);\n",
"\n",
"\"\"\"\n",
" )"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Run!!!"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"data": {
"application/javascript": [
"\n",
"const dx = 10;\n",
"const width = 1080;\n",
"const dy = width / 6;\n",
"const margin = ({ top: 10, right: 120, bottom: 10, left: 40 })\n",
"const root = d3.hierarchy({\n",
" \"name\": \"flare\",\n",
" \"children\": [\n",
" {\n",
" \"name\": \"analytics\",\n",
" \"children\": [\n",
" {\n",
" \"name\": \"cluster\",\n",
" \"children\": [\n",
" {\"name\": \"AgglomerativeCluster\", \"value\": 3938},\n",
" {\"name\": \"CommunityStructure\", \"value\": 3812},\n",
" {\"name\": \"HierarchicalCluster\", \"value\": 6714},\n",
" {\"name\": \"MergeEdge\", \"value\": 743}\n",
" ]\n",
" },\n",
" {\n",
" \"name\": \"graph\",\n",
" \"children\": [\n",
" {\"name\": \"BetweennessCentrality\", \"value\": 3534},\n",
" {\"name\": \"LinkDistance\", \"value\": 5731},\n",
" {\"name\": \"MaxFlowMinCut\", \"value\": 7840},\n",
" {\"name\": \"ShortestPaths\", \"value\": 5914},\n",
" {\"name\": \"SpanningTree\", \"value\": 3416}\n",
" ]\n",
" },\n",
" {\n",
" \"name\": \"optimization\",\n",
" \"children\": [\n",
" {\"name\": \"AspectRatioBanker\", \"value\": 7074}\n",
" ]\n",
" }\n",
" ]\n",
" },\n",
" {\n",
" \"name\": \"animate\",\n",
" \"children\": [\n",
" {\"name\": \"Easing\", \"value\": 17010},\n",
" {\"name\": \"FunctionSequence\", \"value\": 5842},\n",
" {\n",
" \"name\": \"interpolate\",\n",
" \"children\": [\n",
" {\"name\": \"ArrayInterpolator\", \"value\": 1983},\n",
" {\"name\": \"ColorInterpolator\", \"value\": 2047},\n",
" {\"name\": \"DateInterpolator\", \"value\": 1375},\n",
" {\"name\": \"Interpolator\", \"value\": 8746},\n",
" {\"name\": \"MatrixInterpolator\", \"value\": 2202},\n",
" {\"name\": \"NumberInterpolator\", \"value\": 1382},\n",
" {\"name\": \"ObjectInterpolator\", \"value\": 1629},\n",
" {\"name\": \"PointInterpolator\", \"value\": 1675},\n",
" {\"name\": \"RectangleInterpolator\", \"value\": 2042}\n",
" ]\n",
" },\n",
" {\"name\": \"ISchedulable\", \"value\": 1041},\n",
" {\"name\": \"Parallel\", \"value\": 5176},\n",
" {\"name\": \"Pause\", \"value\": 449},\n",
" {\"name\": \"Scheduler\", \"value\": 5593},\n",
" {\"name\": \"Sequence\", \"value\": 5534},\n",
" {\"name\": \"Transition\", \"value\": 9201},\n",
" {\"name\": \"Transitioner\", \"value\": 19975},\n",
" {\"name\": \"TransitionEvent\", \"value\": 1116},\n",
" {\"name\": \"Tween\", \"value\": 6006}\n",
" ]\n",
" },\n",
" {\n",
" \"name\": \"data\",\n",
" \"children\": [\n",
" {\n",
" \"name\": \"converters\",\n",
" \"children\": [\n",
" {\"name\": \"Converters\", \"value\": 721},\n",
" {\"name\": \"DelimitedTextConverter\", \"value\": 4294},\n",
" {\"name\": \"GraphMLConverter\", \"value\": 9800},\n",
" {\"name\": \"IDataConverter\", \"value\": 1314},\n",
" {\"name\": \"JSONConverter\", \"value\": 2220}\n",
" ]\n",
" },\n",
" {\"name\": \"DataField\", \"value\": 1759},\n",
" {\"name\": \"DataSchema\", \"value\": 2165},\n",
" {\"name\": \"DataSet\", \"value\": 586},\n",
" {\"name\": \"DataSource\", \"value\": 3331},\n",
" {\"name\": \"DataTable\", \"value\": 772},\n",
" {\"name\": \"DataUtil\", \"value\": 3322}\n",
" ]\n",
" },\n",
" {\n",
" \"name\": \"display\",\n",
" \"children\": [\n",
" {\"name\": \"DirtySprite\", \"value\": 8833},\n",
" {\"name\": \"LineSprite\", \"value\": 1732},\n",
" {\"name\": \"RectSprite\", \"value\": 3623},\n",
" {\"name\": \"TextSprite\", \"value\": 10066}\n",
" ]\n",
" },\n",
" {\n",
" \"name\": \"flex\",\n",
" \"children\": [\n",
" {\"name\": \"FlareVis\", \"value\": 4116}\n",
" ]\n",
" },\n",
" {\n",
" \"name\": \"physics\",\n",
" \"children\": [\n",
" {\"name\": \"DragForce\", \"value\": 1082},\n",
" {\"name\": \"GravityForce\", \"value\": 1336},\n",
" {\"name\": \"IForce\", \"value\": 319},\n",
" {\"name\": \"NBodyForce\", \"value\": 10498},\n",
" {\"name\": \"Particle\", \"value\": 2822},\n",
" {\"name\": \"Simulation\", \"value\": 9983},\n",
" {\"name\": \"Spring\", \"value\": 2213},\n",
" {\"name\": \"SpringForce\", \"value\": 1681}\n",
" ]\n",
" },\n",
" {\n",
" \"name\": \"query\",\n",
" \"children\": [\n",
" {\"name\": \"AggregateExpression\", \"value\": 1616},\n",
" {\"name\": \"And\", \"value\": 1027},\n",
" {\"name\": \"Arithmetic\", \"value\": 3891},\n",
" {\"name\": \"Average\", \"value\": 891},\n",
" {\"name\": \"BinaryExpression\", \"value\": 2893},\n",
" {\"name\": \"Comparison\", \"value\": 5103},\n",
" {\"name\": \"CompositeExpression\", \"value\": 3677},\n",
" {\"name\": \"Count\", \"value\": 781},\n",
" {\"name\": \"DateUtil\", \"value\": 4141},\n",
" {\"name\": \"Distinct\", \"value\": 933},\n",
" {\"name\": \"Expression\", \"value\": 5130},\n",
" {\"name\": \"ExpressionIterator\", \"value\": 3617},\n",
" {\"name\": \"Fn\", \"value\": 3240},\n",
" {\"name\": \"If\", \"value\": 2732},\n",
" {\"name\": \"IsA\", \"value\": 2039},\n",
" {\"name\": \"Literal\", \"value\": 1214},\n",
" {\"name\": \"Match\", \"value\": 3748},\n",
" {\"name\": \"Maximum\", \"value\": 843},\n",
" {\n",
" \"name\": \"methods\",\n",
" \"children\": [\n",
" {\"name\": \"add\", \"value\": 593},\n",
" {\"name\": \"and\", \"value\": 330},\n",
" {\"name\": \"average\", \"value\": 287},\n",
" {\"name\": \"count\", \"value\": 277},\n",
" {\"name\": \"distinct\", \"value\": 292},\n",
" {\"name\": \"div\", \"value\": 595},\n",
" {\"name\": \"eq\", \"value\": 594},\n",
" {\"name\": \"fn\", \"value\": 460},\n",
" {\"name\": \"gt\", \"value\": 603},\n",
" {\"name\": \"gte\", \"value\": 625},\n",
" {\"name\": \"iff\", \"value\": 748},\n",
" {\"name\": \"isa\", \"value\": 461},\n",
" {\"name\": \"lt\", \"value\": 597},\n",
" {\"name\": \"lte\", \"value\": 619},\n",
" {\"name\": \"max\", \"value\": 283},\n",
" {\"name\": \"min\", \"value\": 283},\n",
" {\"name\": \"mod\", \"value\": 591},\n",
" {\"name\": \"mul\", \"value\": 603},\n",
" {\"name\": \"neq\", \"value\": 599},\n",
" {\"name\": \"not\", \"value\": 386},\n",
" {\"name\": \"or\", \"value\": 323},\n",
" {\"name\": \"orderby\", \"value\": 307},\n",
" {\"name\": \"range\", \"value\": 772},\n",
" {\"name\": \"select\", \"value\": 296},\n",
" {\"name\": \"stddev\", \"value\": 363},\n",
" {\"name\": \"sub\", \"value\": 600},\n",
" {\"name\": \"sum\", \"value\": 280},\n",
" {\"name\": \"update\", \"value\": 307},\n",
" {\"name\": \"variance\", \"value\": 335},\n",
" {\"name\": \"where\", \"value\": 299},\n",
" {\"name\": \"xor\", \"value\": 354},\n",
" {\"name\": \"_\", \"value\": 264}\n",
" ]\n",
" },\n",
" {\"name\": \"Minimum\", \"value\": 843},\n",
" {\"name\": \"Not\", \"value\": 1554},\n",
" {\"name\": \"Or\", \"value\": 970},\n",
" {\"name\": \"Query\", \"value\": 13896},\n",
" {\"name\": \"Range\", \"value\": 1594},\n",
" {\"name\": \"StringUtil\", \"value\": 4130},\n",
" {\"name\": \"Sum\", \"value\": 791},\n",
" {\"name\": \"Variable\", \"value\": 1124},\n",
" {\"name\": \"Variance\", \"value\": 1876},\n",
" {\"name\": \"Xor\", \"value\": 1101}\n",
" ]\n",
" },\n",
" {\n",
" \"name\": \"scale\",\n",
" \"children\": [\n",
" {\"name\": \"IScaleMap\", \"value\": 2105},\n",
" {\"name\": \"LinearScale\", \"value\": 1316},\n",
" {\"name\": \"LogScale\", \"value\": 3151},\n",
" {\"name\": \"OrdinalScale\", \"value\": 3770},\n",
" {\"name\": \"QuantileScale\", \"value\": 2435},\n",
" {\"name\": \"QuantitativeScale\", \"value\": 4839},\n",
" {\"name\": \"RootScale\", \"value\": 1756},\n",
" {\"name\": \"Scale\", \"value\": 4268},\n",
" {\"name\": \"ScaleType\", \"value\": 1821},\n",
" {\"name\": \"TimeScale\", \"value\": 5833}\n",
" ]\n",
" },\n",
" {\n",
" \"name\": \"util\",\n",
" \"children\": [\n",
" {\"name\": \"Arrays\", \"value\": 8258},\n",
" {\"name\": \"Colors\", \"value\": 10001},\n",
" {\"name\": \"Dates\", \"value\": 8217},\n",
" {\"name\": \"Displays\", \"value\": 12555},\n",
" {\"name\": \"Filter\", \"value\": 2324},\n",
" {\"name\": \"Geometry\", \"value\": 10993},\n",
" {\n",
" \"name\": \"heap\",\n",
" \"children\": [\n",
" {\"name\": \"FibonacciHeap\", \"value\": 9354},\n",
" {\"name\": \"HeapNode\", \"value\": 1233}\n",
" ]\n",
" },\n",
" {\"name\": \"IEvaluable\", \"value\": 335},\n",
" {\"name\": \"IPredicate\", \"value\": 383},\n",
" {\"name\": \"IValueProxy\", \"value\": 874},\n",
" {\n",
" \"name\": \"math\",\n",
" \"children\": [\n",
" {\"name\": \"DenseMatrix\", \"value\": 3165},\n",
" {\"name\": \"IMatrix\", \"value\": 2815},\n",
" {\"name\": \"SparseMatrix\", \"value\": 3366}\n",
" ]\n",
" },\n",
" {\"name\": \"Maths\", \"value\": 17705},\n",
" {\"name\": \"Orientation\", \"value\": 1486},\n",
" {\n",
" \"name\": \"palette\",\n",
" \"children\": [\n",
" {\"name\": \"ColorPalette\", \"value\": 6367},\n",
" {\"name\": \"Palette\", \"value\": 1229},\n",
" {\"name\": \"ShapePalette\", \"value\": 2059},\n",
" {\"name\": \"SizePalette\", \"value\": 2291}\n",
" ]\n",
" },\n",
" {\"name\": \"Property\", \"value\": 5559},\n",
" {\"name\": \"Shapes\", \"value\": 19118},\n",
" {\"name\": \"Sort\", \"value\": 6887},\n",
" {\"name\": \"Stats\", \"value\": 6557},\n",
" {\"name\": \"Strings\", \"value\": 22026}\n",
" ]\n",
" },\n",
" {\n",
" \"name\": \"vis\",\n",
" \"children\": [\n",
" {\n",
" \"name\": \"axis\",\n",
" \"children\": [\n",
" {\"name\": \"Axes\", \"value\": 1302},\n",
" {\"name\": \"Axis\", \"value\": 24593},\n",
" {\"name\": \"AxisGridLine\", \"value\": 652},\n",
" {\"name\": \"AxisLabel\", \"value\": 636},\n",
" {\"name\": \"CartesianAxes\", \"value\": 6703}\n",
" ]\n",
" },\n",
" {\n",
" \"name\": \"controls\",\n",
" \"children\": [\n",
" {\"name\": \"AnchorControl\", \"value\": 2138},\n",
" {\"name\": \"ClickControl\", \"value\": 3824},\n",
" {\"name\": \"Control\", \"value\": 1353},\n",
" {\"name\": \"ControlList\", \"value\": 4665},\n",
" {\"name\": \"DragControl\", \"value\": 2649},\n",
" {\"name\": \"ExpandControl\", \"value\": 2832},\n",
" {\"name\": \"HoverControl\", \"value\": 4896},\n",
" {\"name\": \"IControl\", \"value\": 763},\n",
" {\"name\": \"PanZoomControl\", \"value\": 5222},\n",
" {\"name\": \"SelectionControl\", \"value\": 7862},\n",
" {\"name\": \"TooltipControl\", \"value\": 8435}\n",
" ]\n",
" },\n",
" {\n",
" \"name\": \"data\",\n",
" \"children\": [\n",
" {\"name\": \"Data\", \"value\": 20544},\n",
" {\"name\": \"DataList\", \"value\": 19788},\n",
" {\"name\": \"DataSprite\", \"value\": 10349},\n",
" {\"name\": \"EdgeSprite\", \"value\": 3301},\n",
" {\"name\": \"NodeSprite\", \"value\": 19382},\n",
" {\n",
" \"name\": \"render\",\n",
" \"children\": [\n",
" {\"name\": \"ArrowType\", \"value\": 698},\n",
" {\"name\": \"EdgeRenderer\", \"value\": 5569},\n",
" {\"name\": \"IRenderer\", \"value\": 353},\n",
" {\"name\": \"ShapeRenderer\", \"value\": 2247}\n",
" ]\n",
" },\n",
" {\"name\": \"ScaleBinding\", \"value\": 11275},\n",
" {\"name\": \"Tree\", \"value\": 7147},\n",
" {\"name\": \"TreeBuilder\", \"value\": 9930}\n",
" ]\n",
" },\n",
" {\n",
" \"name\": \"events\",\n",
" \"children\": [\n",
" {\"name\": \"DataEvent\", \"value\": 2313},\n",
" {\"name\": \"SelectionEvent\", \"value\": 1880},\n",
" {\"name\": \"TooltipEvent\", \"value\": 1701},\n",
" {\"name\": \"VisualizationEvent\", \"value\": 1117}\n",
" ]\n",
" },\n",
" {\n",
" \"name\": \"legend\",\n",
" \"children\": [\n",
" {\"name\": \"Legend\", \"value\": 20859},\n",
" {\"name\": \"LegendItem\", \"value\": 4614},\n",
" {\"name\": \"LegendRange\", \"value\": 10530}\n",
" ]\n",
" },\n",
" {\n",
" \"name\": \"operator\",\n",
" \"children\": [\n",
" {\n",
" \"name\": \"distortion\",\n",
" \"children\": [\n",
" {\"name\": \"BifocalDistortion\", \"value\": 4461},\n",
" {\"name\": \"Distortion\", \"value\": 6314},\n",
" {\"name\": \"FisheyeDistortion\", \"value\": 3444}\n",
" ]\n",
" },\n",
" {\n",
" \"name\": \"encoder\",\n",
" \"children\": [\n",
" {\"name\": \"ColorEncoder\", \"value\": 3179},\n",
" {\"name\": \"Encoder\", \"value\": 4060},\n",
" {\"name\": \"PropertyEncoder\", \"value\": 4138},\n",
" {\"name\": \"ShapeEncoder\", \"value\": 1690},\n",
" {\"name\": \"SizeEncoder\", \"value\": 1830}\n",
" ]\n",
" },\n",
" {\n",
" \"name\": \"filter\",\n",
" \"children\": [\n",
" {\"name\": \"FisheyeTreeFilter\", \"value\": 5219},\n",
" {\"name\": \"GraphDistanceFilter\", \"value\": 3165},\n",
" {\"name\": \"VisibilityFilter\", \"value\": 3509}\n",
" ]\n",
" },\n",
" {\"name\": \"IOperator\", \"value\": 1286},\n",
" {\n",
" \"name\": \"label\",\n",
" \"children\": [\n",
" {\"name\": \"Labeler\", \"value\": 9956},\n",
" {\"name\": \"RadialLabeler\", \"value\": 3899},\n",
" {\"name\": \"StackedAreaLabeler\", \"value\": 3202}\n",
" ]\n",
" },\n",
" {\n",
" \"name\": \"layout\",\n",
" \"children\": [\n",
" {\"name\": \"AxisLayout\", \"value\": 6725},\n",
" {\"name\": \"BundledEdgeRouter\", \"value\": 3727},\n",
" {\"name\": \"CircleLayout\", \"value\": 9317},\n",
" {\"name\": \"CirclePackingLayout\", \"value\": 12003},\n",
" {\"name\": \"DendrogramLayout\", \"value\": 4853},\n",
" {\"name\": \"ForceDirectedLayout\", \"value\": 8411},\n",
" {\"name\": \"IcicleTreeLayout\", \"value\": 4864},\n",
" {\"name\": \"IndentedTreeLayout\", \"value\": 3174},\n",
" {\"name\": \"Layout\", \"value\": 7881},\n",
" {\"name\": \"NodeLinkTreeLayout\", \"value\": 12870},\n",
" {\"name\": \"PieLayout\", \"value\": 2728},\n",
" {\"name\": \"RadialTreeLayout\", \"value\": 12348},\n",
" {\"name\": \"RandomLayout\", \"value\": 870},\n",
" {\"name\": \"StackedAreaLayout\", \"value\": 9121},\n",
" {\"name\": \"TreeMapLayout\", \"value\": 9191}\n",
" ]\n",
" },\n",
" {\"name\": \"Operator\", \"value\": 2490},\n",
" {\"name\": \"OperatorList\", \"value\": 5248},\n",
" {\"name\": \"OperatorSequence\", \"value\": 4190},\n",
" {\"name\": \"OperatorSwitch\", \"value\": 2581},\n",
" {\"name\": \"SortOperator\", \"value\": 2023}\n",
" ]\n",
" },\n",
" {\"name\": \"Visualization\", \"value\": 16540}\n",
" ]\n",
" }\n",
" ]\n",
"}\n",
");\n",
"const tree = d3.tree().nodeSize([dx, dy])\n",
"const diagonal = d3.linkHorizontal().x(d => d.y).y(d => d.x)\n",
"\n",
"root.x0 = dy / 2;\n",
"root.y0 = 0;\n",
"root.descendants().forEach((d, i) => {\n",
" d.id = i;\n",
" d._children = d.children;\n",
" if (d.depth && d.data.name.length !== 7) d.children = null;\n",
"});\n",
"\n",
"// Select the cell output DOM\n",
"const svg = d3.select(element)\n",
" .append(\"svg\")\n",
" .attr(\"viewBox\", [-margin.left, -margin.top, width, dx])\n",
" .style(\"font\", \"10px sans-serif\")\n",
" .style(\"user-select\", \"none\");\n",
"\n",
"const gLink = svg.append(\"g\")\n",
" .attr(\"fill\", \"none\")\n",
" .attr(\"stroke\", \"#555\")\n",
" .attr(\"stroke-opacity\", 0.4)\n",
" .attr(\"stroke-width\", 1.5);\n",
"\n",
"const gNode = svg.append(\"g\")\n",
" .attr(\"cursor\", \"pointer\")\n",
" .attr(\"pointer-events\", \"all\");\n",
"\n",
"function update(source) {\n",
" const duration = d3.event && d3.event.altKey ? 2500 : 250;\n",
" const nodes = root.descendants().reverse();\n",
" const links = root.links();\n",
"\n",
" // Compute the new tree layout.\n",
" tree(root);\n",
"\n",
" let left = root;\n",
" let right = root;\n",
" root.eachBefore(node => {\n",
" if (node.x < left.x) left = node;\n",
" if (node.x > right.x) right = node;\n",
" });\n",
"\n",
" const height = right.x - left.x + margin.top + margin.bottom;\n",
"\n",
" const transition = svg.transition()\n",
" .duration(duration)\n",
" .attr(\"viewBox\", [-margin.left, left.x - margin.top, width, height])\n",
" .tween(\"resize\", window.ResizeObserver ? null : () => () => svg.dispatch(\"toggle\"));\n",
"\n",
" // Update the nodes…\n",
" const node = gNode.selectAll(\"g\")\n",
" .data(nodes, d => d.id);\n",
"\n",
" // Enter any new nodes at the parent's previous position.\n",
" const nodeEnter = node.enter().append(\"g\")\n",
" .attr(\"transform\", d => `translate(${source.y0},${source.x0})`)\n",
" .attr(\"fill-opacity\", 0)\n",
" .attr(\"stroke-opacity\", 0)\n",
" .on(\"click\", (event, d) => {\n",
" d.children = d.children ? null : d._children;\n",
" update(d);\n",
" });\n",
"\n",
" nodeEnter.append(\"circle\")\n",
" .attr(\"r\", 2.5)\n",
" .attr(\"fill\", d => d._children ? \"#555\" : \"#999\")\n",
" .attr(\"stroke-width\", 10);\n",
"\n",
" nodeEnter.append(\"text\")\n",
" .attr(\"dy\", \"0.31em\")\n",
" .attr(\"x\", d => d._children ? -6 : 6)\n",
" .attr(\"text-anchor\", d => d._children ? \"end\" : \"start\")\n",
" .text(d => d.data.name)\n",
" .clone(true).lower()\n",
" .attr(\"stroke-linejoin\", \"round\")\n",
" .attr(\"stroke-width\", 3)\n",
" .attr(\"stroke\", \"white\");\n",
"\n",
" // Transition nodes to their new position.\n",
" const nodeUpdate = node.merge(nodeEnter).transition(transition)\n",
" .attr(\"transform\", d => `translate(${d.y},${d.x})`)\n",
" .attr(\"fill-opacity\", 1)\n",
" .attr(\"stroke-opacity\", 1);\n",
"\n",
" // Transition exiting nodes to the parent's new position.\n",
" const nodeExit = node.exit().transition(transition).remove()\n",
" .attr(\"transform\", d => `translate(${source.y},${source.x})`)\n",
" .attr(\"fill-opacity\", 0)\n",
" .attr(\"stroke-opacity\", 0);\n",
"\n",
" // Update the links…\n",
" const link = gLink.selectAll(\"path\")\n",
" .data(links, d => d.target.id);\n",
"\n",
" // Enter any new links at the parent's previous position.\n",
" const linkEnter = link.enter().append(\"path\")\n",
" .attr(\"d\", d => {\n",
" const o = { x: source.x0, y: source.y0 };\n",
" return diagonal({ source: o, target: o });\n",
" });\n",
"\n",
" // Transition links to their new position.\n",
" link.merge(linkEnter).transition(transition)\n",
" .attr(\"d\", diagonal);\n",
"\n",
" // Transition exiting nodes to the parent's new position.\n",
" link.exit().transition(transition).remove()\n",
" .attr(\"d\", d => {\n",
" const o = { x: source.x, y: source.y };\n",
" return diagonal({ source: o, target: o });\n",
" });\n",
"\n",
" // Stash the old positions for transition.\n",
" root.eachBefore(d => {\n",
" d.x0 = d.x;\n",
" d.y0 = d.y;\n",
" });\n",
"}\n",
"\n",
"update(root);\n",
"\n"
],
"text/plain": [
"<IPython.core.display.Javascript object>"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"Javascript(tree_js_template.safe_substitute(data=data_str))"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.6"
}
},
"nbformat": 4,
"nbformat_minor": 4
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment