From 7d34be6f18171ebb7e5592fdfd20f1f34bdb9424 Mon Sep 17 00:00:00 2001 From: Sven Schneider <icedoggy@gmx.de> Date: Thu, 20 May 2021 22:38:18 +0200 Subject: [PATCH] heatmap implemented using d3 and plotly libraries as well as fixed some labels on RibbonPlot --- index.html | 9 +- public/js/appChart.js | 111 +------------------ public/js/createPlotlyPlots.js | 188 +++++++++++++++++++++++++++------ 3 files changed, 160 insertions(+), 148 deletions(-) diff --git a/index.html b/index.html index d28e2a8..d0bbf38 100644 --- a/index.html +++ b/index.html @@ -196,18 +196,17 @@ <!-- end row --> <div class="row"> - <div class="col-xl-6"> + <div class="col-xl-12"> <div class="card mb-4"> <div class="card-header"> - <i class="fas fa-chart-area mr-1"></i> - 2d heatmap + <i class="fas fa-globe mr-1"></i> + PLotly heatmap2d </div> <div class="card-body"> <div id="heatmap2d" width="100%" - height="40" - style="max-width: 100%; max-height: 600px" + height="40" > <!-- Plotly chart will be drawn inside this DIV --> </div> diff --git a/public/js/appChart.js b/public/js/appChart.js index b80dddc..9df0c44 100644 --- a/public/js/appChart.js +++ b/public/js/appChart.js @@ -463,111 +463,7 @@ followNextLink( jsonFromArr.forEach((obj) => renameKey(obj, "0", "x")); let jsonFromArr2 = jsonFromArr; jsonFromArr2.forEach((obj) => renameKey(obj, "1", "y")); - - - - - /////////////////////////////////////////////////// - function prep2dHistogramData(jsonData) { - var resList = []; - - const L = jsonData.length; - - var startVal = 1; - var currentDay = 1; - var hourInMonth = 0; - - var x = []; - var y = []; - var z = []; - for (var d = 0; d < L; d++) { - let tmpDate = new Date(jsonData[d].x); - // let datum = tmpDate.getDate(); // gets the day of the month 1...31 - let hour = tmpDate.getHours(); - let day = tmpDate.getUTCDate(); - let month = tmpDate.getUTCMonth(); // gets the month as numeric value - - if (currentDay == day) { - x.push([startVal, startVal + 1]); - y.push([hourInMonth,hourInMonth]); - z.push([jsonData[d].y, jsonData[d].y]); - hourInMonth++; - } else { - resList.push({x:x, y:y, z:z } ); - var x = []; - var y = []; - var z = []; - currentMonth += 1; - startVal += 2; - hourInMonth = 0; - - x.push([startVal, startVal + 1]); - y.push([hourInMonth,hourInMonth]); - z.push([jsonData[d].y, jsonData[d].y]); - } - } // end of for loop - - // add results for last month as else statement will not be reached for the december - // as the condition d < L will be true before the condition currentMonth === month can be evaluated - - // re-activate following line when i have more than one data point for the next month - // resList.push({x:x, y:y, z:z } ); - - return resList; - } - - - - /////////////////////////////////////////////////// - function prepRibbonData(jsonData) { - var resList = []; - - const L = jsonData.length; - - var startVal = 2; - var currentMonth = 0; - var hourInMonth = 0; - - var x = []; - var y = []; - var z = []; - for (var d = 0; d < L; d++) { - let tmpDate = new Date(jsonData[d].x); - // let datum = tmpDate.getDate(); // gets the day of the month 1...31 - let hour = tmpDate.getHours(); - let month = tmpDate.getUTCMonth(); // gets the month as numeric value - - if (currentMonth == month) { - x.push([startVal, startVal + 1]); - y.push([hourInMonth,hourInMonth]); - z.push([jsonData[d].y, jsonData[d].y]); - hourInMonth++; - } else { - resList.push({x:x, y:y, z:z } ); - var x = []; - var y = []; - var z = []; - currentMonth += 1; - startVal += 2; - hourInMonth = 0; - - x.push([startVal, startVal + 1]); - y.push([hourInMonth,hourInMonth]); - z.push([jsonData[d].y, jsonData[d].y]); - } - - } // end of for loop - - // add results for last month as else statement will not be reached for the december - // as the condition d < L will be true before the condition currentMonth === month can be evaluated - - // re-activate following line when i have more than one data point for the next month - // resList.push({x:x, y:y, z:z } ); - - return resList; - } - /////////////////////////////////////////////////// let datx=[]; let daty=[]; @@ -690,10 +586,9 @@ followNextLink( location.appendChild(scriptTag); }; - var preppedData = prepRibbonData(jsonFromArr2); - - loadJS('js/createPlotlyPlots.js', makeRibbonPlot(preppedData), document.body); - loadJS('js/createPlotlyPlots.js', makeHeatmap(preppedData), document.body); + + loadJS('js/createPlotlyPlots.js', makeRibbonPlot(jsonFromArr2), document.body); + makeHeatmap(jsonFromArr2); /////////////////////////////////////// diff --git a/public/js/createPlotlyPlots.js b/public/js/createPlotlyPlots.js index b05d2bd..bb8a264 100644 --- a/public/js/createPlotlyPlots.js +++ b/public/js/createPlotlyPlots.js @@ -1,4 +1,54 @@ +function prepRibbonData(jsonData) { + var resList = []; + + const L = jsonData.length; + + var startVal = 2; + var currentMonth = 0; + var hourInMonth = 0; + + var x = []; + var y = []; + var z = []; + for (var d = 0; d < L; d++) { + let tmpDate = new Date(jsonData[d].x); + // let datum = tmpDate.getDate(); // gets the day of the month 1...31 + let hour = tmpDate.getHours(); + let month = tmpDate.getUTCMonth(); // gets the month as numeric value + + if (currentMonth == month) { + x.push([startVal, startVal + 1]); + y.push([hourInMonth, hourInMonth]); + z.push([jsonData[d].y, jsonData[d].y]); + hourInMonth++; + } else { + resList.push({ x: x, y: y, z: z }); + var x = []; + var y = []; + var z = []; + currentMonth += 1; + startVal += 2; + hourInMonth = 0; + + x.push([startVal, startVal + 1]); + y.push([hourInMonth, hourInMonth]); + z.push([jsonData[d].y, jsonData[d].y]); + } + } // end of for loop + + // add results for last month as else statement will not be reached for the december + // as the condition d < L will be true before the condition currentMonth === month can be evaluated + + // re-activate following line when i have more than one data point for the next month + // resList.push({x:x, y:y, z:z } ); + + return resList; +} + function makeRibbonPlot(dat) { + preppedData = prepRibbonData(dat); + dat = preppedData; + // https://plotly.com/javascript/ribbon-plots/ var trace1 = { x: dat[0].x, @@ -83,46 +133,114 @@ function makeRibbonPlot(dat) { }, }; Plotly.newPlot("RibbonPlot", data, layout); +} +//////////////////////////////////////////////////////////// - function make2dHistogram(dat) { - ////////////////////////////// - // make heatmap or 2d histogram plot +function prepHeatmapData(jsonData) { + const L = jsonData.length; - var x = []; - var y = []; - for (var i = 0; i < 500; i++) { - x[i] = Math.random(); - y[i] = Math.random() + 1; - } + var z = []; + var hourCnt = 0; + const maxH = 24; + const incr = Math.round(L / maxH) + 1; - var data = [ - { - x: x, - y: y, - z: x, - type: "histogram2d", // try this type as well 'histogram2dcontour' or this one 'histogram2d' - }, - ]; - Plotly.newPlot("heatmap2d", data); + // span up the matrix that holds my temperature values + for (var d = 0; d < L; d += incr) { + // z.push( [...Array(incr).keys(NaN)] ); + z.push(Array(incr).fill(NaN)); } - ///////////////////////////////////// - - function makeHeatmap(dat) { - var data = [ - { - z: [ - [1, null, 30, 50, 1], - [20, 1, 60, 80, 30], - [30, 60, 1, -10, 20], - ], - x: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"], - y: ["Morning", "Afternoon", "Evening"], - type: "heatmap", - hoverongaps: false, - }, - ]; + // now populate the empty (nan-filled) array with appropriate values + var cnt = 0; + var breakOut = false; + for (var hour = 0; hour < z.length; hour++) { + for (var day = 0; day < incr; day++) { + idx = (day * maxH) + hour ; + if (idx >= L) + continue; + z[hour][day] = jsonData[idx].y; + cnt++; + if (cnt >= L) { + breakOut = true; + break; + } + } + if (breakOut) + break; + } + + // window.alert(cnt); + + return z; +} - Plotly.newPlot("heatmap2d", data); +///////////////////////////////////// + +function makeHeatmap(dat) { + z_data = prepHeatmapData(dat); + + layout = { // all "layout" attributes: #layout + title: 'Inlet flow Overview of 2020 - 1st Jan - 30th Jun', // more about "layout.title": #layout-title + showlegend: true, + autosize: true, + width: 1400, + height: 800, + xaxis: { // all "layout.xaxis" attributes: #layout-xaxis + title: 'Number of the day of the year', + tickmode: "array", + tickvals: [0 , 31, 60, 91, 121, 152, 182], + ticktext: ["1st. Jan", "1st Feb", "1st Mar", "1st Apr", "1st May", "1st Jun", "1st Jul"], // more about "layout.xaxis.title": #layout-xaxis-title + }, + yaxis: { + title: "Hours of the day", + tickmode: "array", + tickvals: [...Array(24).keys()], + ticktext: String([...Array(24).keys()]), + + }, + + annotations: [ // all "annotation" attributes: #layout-annotations + // { + // text: '1st of February', // #layout-annotations-text + // x: 0, // #layout-annotations-x + // xref: 'paper', // #layout-annotations-xref + // y: 0, // #layout-annotations-y + // yref: 'paper' // #layout-annotations-yref + // } + ] +} + + var data = [ + { + // z: [ [1, 20, 30 , 20], [20, 1, 60, 10 ], [30, 60, 1, 5], [1, 20, 30 , 20], [20, 1, 60, 10 ], [30, 60, 1, 5] ], + z: z_data, + type: "heatmap", + }, + ]; + + Plotly.newPlot("heatmap2d", data, layout); +} + +function make2dHistogram(dat) { + ////////////////////////////// + // make heatmap or 2d histogram plot + + + + var x = []; + var y = []; + for (var i = 0; i < 500; i++) { + x[i] = Math.random(); + y[i] = Math.random() + 1; } + + var data = [ + { + x: x, + y: y, + z: x, + type: "histogram2d", // try this type as well 'histogram2dcontour' or this one 'histogram2d' + }, + ]; + Plotly.newPlot("heatmap2d", data); } -- GitLab