CyteBode's solution to "Create cool js visualization of data - radial histogram / circos"

Dependencies<\/strong><\/p>\n\n

    \n
  • d3<\/li>\n
  • d3-queue<\/li>\n
  • circosJS<\/li>\n<\/ul>\n\n

    Download the spreadsheet as a CSV (diagnostics - Sheet1.csv<\/code>) and put it in the same directory as the following HTML file:<\/p>\n

    <!DOCTYPE html><\/span>\n<html><\/span>\n  <head><\/span>\n    <meta<\/span> charset=<\/span>&quot;utf-8&quot;<\/span>><\/span>\n    <script<\/span> src=<\/span>'https://cdnjs.cloudflare.com/ajax/libs/d3/4.5.0/d3.js'<\/span>></script><\/span>\n    <script<\/span> src=<\/span>'https://cdnjs.cloudflare.com/ajax/libs/d3-queue/3.0.3/d3-queue.js'<\/span>></script><\/span>\n    <script<\/span> src=<\/span>'https://cdn.jsdelivr.net/gh/nicgirault/circosJS@v2/dist/circos.js'<\/span>></script><\/span>\n  </head><\/span>\n  <body><\/span>\n    <div<\/span> id=<\/span>&quot;modeBtns&quot;<\/span>><\/span>\n      <button<\/span> onclick=<\/span>&quot;renderPerc();&quot;<\/span>><\/span>Percentage</button><\/span>\n      <button<\/span> onclick=<\/span>&quot;renderNum()&quot;<\/span>><\/span>Number</button><\/span>\n    </div><\/span>\n    <div<\/span> id=<\/span>'chart'<\/span>></svg><\/span>\n\n    <script><\/span>\n      const MONTHS = [\n        {&quot;<\/span>len&quot;<\/span>: 31, &quot;<\/span>color&quot;<\/span>: &quot;<\/span>#8dd3c7&quot;<\/span>, &quot;<\/span>label&quot;<\/span>: &quot;<\/span>January&quot;<\/span>, &quot;<\/span>id&quot;<\/span>: &quot;<\/span>january&quot;<\/span>},\n        {&quot;<\/span>len&quot;<\/span>: 28, &quot;<\/span>color&quot;<\/span>: &quot;<\/span>#ffffb3&quot;<\/span>, &quot;<\/span>label&quot;<\/span>: &quot;<\/span>February&quot;<\/span>, &quot;<\/span>id&quot;<\/span>: &quot;<\/span>february&quot;<\/span>},\n        {&quot;<\/span>len&quot;<\/span>: 31, &quot;<\/span>color&quot;<\/span>: &quot;<\/span>#bebada&quot;<\/span>, &quot;<\/span>label&quot;<\/span>: &quot;<\/span>March&quot;<\/span>, &quot;<\/span>id&quot;<\/span>: &quot;<\/span>march&quot;<\/span>},\n        {&quot;<\/span>len&quot;<\/span>: 30, &quot;<\/span>color&quot;<\/span>: &quot;<\/span>#fb8072&quot;<\/span>, &quot;<\/span>label&quot;<\/span>: &quot;<\/span>April&quot;<\/span>, &quot;<\/span>id&quot;<\/span>: &quot;<\/span>april&quot;<\/span>},\n        {&quot;<\/span>len&quot;<\/span>: 31, &quot;<\/span>color&quot;<\/span>: &quot;<\/span>#80b1d3&quot;<\/span>, &quot;<\/span>label&quot;<\/span>: &quot;<\/span>May&quot;<\/span>, &quot;<\/span>id&quot;<\/span>: &quot;<\/span>may&quot;<\/span>},\n        {&quot;<\/span>len&quot;<\/span>: 30, &quot;<\/span>color&quot;<\/span>: &quot;<\/span>#fdb462&quot;<\/span>, &quot;<\/span>label&quot;<\/span>: &quot;<\/span>June&quot;<\/span>, &quot;<\/span>id&quot;<\/span>: &quot;<\/span>june&quot;<\/span>},\n        {&quot;<\/span>len&quot;<\/span>: 31, &quot;<\/span>color&quot;<\/span>: &quot;<\/span>#b3de69&quot;<\/span>, &quot;<\/span>label&quot;<\/span>: &quot;<\/span>July&quot;<\/span>, &quot;<\/span>id&quot;<\/span>: &quot;<\/span>july&quot;<\/span>},\n        {&quot;<\/span>len&quot;<\/span>: 31, &quot;<\/span>color&quot;<\/span>: &quot;<\/span>#fccde5&quot;<\/span>, &quot;<\/span>label&quot;<\/span>: &quot;<\/span>August&quot;<\/span>, &quot;<\/span>id&quot;<\/span>: &quot;<\/span>august&quot;<\/span>},\n        {&quot;<\/span>len&quot;<\/span>: 30, &quot;<\/span>color&quot;<\/span>: &quot;<\/span>#d9d9d9&quot;<\/span>, &quot;<\/span>label&quot;<\/span>: &quot;<\/span>September&quot;<\/span>, &quot;<\/span>id&quot;<\/span>: &quot;<\/span>september&quot;<\/span>},\n        {&quot;<\/span>len&quot;<\/span>: 31, &quot;<\/span>color&quot;<\/span>: &quot;<\/span>#bc80bd&quot;<\/span>, &quot;<\/span>label&quot;<\/span>: &quot;<\/span>October&quot;<\/span>, &quot;<\/span>id&quot;<\/span>: &quot;<\/span>october&quot;<\/span>},\n        {&quot;<\/span>len&quot;<\/span>: 30, &quot;<\/span>color&quot;<\/span>: &quot;<\/span>#ccebc5&quot;<\/span>, &quot;<\/span>label&quot;<\/span>: &quot;<\/span>November&quot;<\/span>, &quot;<\/span>id&quot;<\/span>: &quot;<\/span>november&quot;<\/span>},\n        {&quot;<\/span>len&quot;<\/span>: 31, &quot;<\/span>color&quot;<\/span>: &quot;<\/span>#ffed6f&quot;<\/span>, &quot;<\/span>label&quot;<\/span>: &quot;<\/span>December&quot;<\/span>, &quot;<\/span>id&quot;<\/span>: &quot;<\/span>december&quot;<\/span>}\n      ];\n\n      const WIDTH = 500;\n\n      function splitDateRange(dateRange) {\n        function convertMonth(month) {\n          month = month.trim().toLowerCase();\n          for (var monthID of MONTHS.map(function(m) { return m.id; })) {\n            if (monthID.startsWith(month)) {\n              return monthID;\n            }\n          }\n        }\n        dateRange = dateRange.split(&quot;<\/span> to &quot;<\/span>);\n        if (dateRange.length !== 2) {\n          return;\n        }\n\n        var start = dateRange[0].split(&quot;<\/span> &quot;<\/span>);\n        var end = dateRange[1].split(&quot;<\/span> &quot;<\/span>);\n\n        var monthStart = convertMonth(start[0]);\n        var monthEnd = convertMonth(end[0]);\n\n        if (end.length === 1 || monthStart === monthEnd) {\n          return [\n            [convertMonth(start[0]), Number(start[1]) - 1,\n             monthEnd ? Number(end[1]) : Number(end[0])]\n          ];\n        } else {\n          var monthDays = MONTHS.filter(function(m) { return m.id === monthStart; })\n                                .map(function(m) { return m.len; })[0];\n          return [\n            [monthStart, Number(start[1]) - 1, monthDays],\n            [monthEnd, 0, Number(end[1])]\n          ];\n        }\n      }\n\n      function drawCircos(mode, year) {\n        return function(error, diagnosesCSV) {\n          document.getElementById(&quot;<\/span>chart&quot;<\/span>).innerHTML = &quot;&quot;<\/span>;\n\n          var circos = new Circos({\n            container: '#chart',\n            width: WIDTH,\n            height: WIDTH\n          });\n\n          diagnoses = {};\n          for (var row of diagnosesCSV) {\n            var split = splitDateRange(row[&quot;<\/span>Week&quot;<\/span>]);\n            if (typeof split === &quot;<\/span>undefined&quot;<\/span>) {\n              continue;\n            }\n\n            var year_ = row[&quot;<\/span>year&quot;<\/span>].trim();\n            var diagnosed = Number(row[&quot;<\/span>number of diagnosed &quot;<\/span>]);\n            var totalCases = Number(row[&quot;<\/span>Total cases&quot;<\/span>]);\n\n            if (diagnosed === 0) {\n              continue;\n            }\n\n            if (typeof diagnoses[year_] === &quot;<\/span>undefined&quot;<\/span>) {\n              diagnoses[year_] = [];\n            }\n\n            for (var range of split) {\n              diagnoses[year_].push({\n                &quot;<\/span>block_id&quot;<\/span>: range[0],\n                &quot;<\/span>start&quot;<\/span>: range[1],\n                &quot;<\/span>end&quot;<\/span>: range[2],\n                &quot;<\/span>value&quot;<\/span>: mode === &quot;<\/span>percentage&quot;<\/span> ? diagnosed/totalCases : diagnosed,\n                &quot;<\/span>diagnosed&quot;<\/span>: diagnosed,\n                &quot;<\/span>totalCases&quot;<\/span>: totalCases,\n                &quot;<\/span>dateRange&quot;<\/span>: row[&quot;<\/span>Week&quot;<\/span>]\n              });\n            }\n          }\n\n          circos.layout(MONTHS, {\n            innerRadius: WIDTH / 2 - 80,\n            outerRadius: WIDTH / 2 - 30,\n            ticks: {display: false},\n            labels: {\n              position: &quot;<\/span>center&quot;<\/span>,\n              display: true,\n              size: 12,\n              color: &quot;<\/span>#000&quot;<\/span>\n            }\n          }).heatmap(&quot;<\/span>diagnoses&quot;<\/span>, diagnoses[year], {\n            innerRadius: 0.6,\n            outerRadius: 0.98,\n            logScale: true,\n            color: &quot;<\/span>-Spectral&quot;<\/span>,\n            tooltipContent: function(datum, index) {\n              var value = (mode === &quot;<\/span>percentage&quot;<\/span> ?\n                datum.value.toFixed(4) + &quot;<\/span>%&quot;<\/span> :\n                datum.diagnosed + &quot;<\/span>/&quot;<\/span> + datum.totalCases);\n              return datum.dateRange + &quot;<\/span>: &quot;<\/span> + value;\n            }\n          }).render();\n        }\n      }\n\n      function renderPerc() {\n        d3.queue()\n          .defer(d3.csv, &quot;<\/span>./diagnostics - Sheet1.csv&quot;<\/span>)\n          .await(drawCircos(&quot;<\/span>percentage&quot;<\/span>, &quot;<\/span>2018&quot;<\/span>));\n      }\n\n      function renderNum() {\n        d3.queue()\n          .defer(d3.csv, &quot;<\/span>./diagnostics - Sheet1.csv&quot;<\/span>)\n          .await(drawCircos(&quot;<\/span>number&quot;<\/span>, &quot;<\/span>2018&quot;<\/span>));\n      }\n\n      renderPerc();\n    </script><\/span>\n  </body><\/span>\n</html><\/span>\n<\/pre><\/div>
    
**Dependencies** * d3 * d3-queue * circosJS Download the spreadsheet as a CSV (`diagnostics - Sheet1.csv`) and put it in the same directory as the following HTML file:
div> **Edit**: Fixed typo (`svg> >` -> `
`).
**Dependencies** * d3 * d3-queue * circosJS Download the spreadsheet as a CSV (`diagnostics - Sheet1.csv`) and put it in the same directory as the following HTML file:
modeBtns">
**Note**: This won't work in Chrome/Chromium because of the CORS policy, so use the CodePen instead: https://codepen.io/anon/pen/JVvBoo **Edit 1**: Fixed typo (`` -> `
`). **Edit 2**: Added dynamic year switching from data, removed ES6 features (`const`, `for ... of`) for compatibility, fixed percentage", "2018")); } function renderNum() { d3display.queue() .defer(d3.csv, "./diagnostics - Sheet1.csv") .await(drawCircos("number", "2018")); } renderPerc(); **Edit**: Fixed typo (`` -> `
`).

User: CyteBode

Question: Create cool js visualization of data - radial histogram / circos

Back to question