Commit b0da5bf6 authored by Rosanny Sihombing's avatar Rosanny Sihombing
Browse files

first commit

parent 7abcb82b
Showing with 1027 additions and 576 deletions
+1027 -576
venv/
__pycache__/
result/
input/
\ No newline at end of file
# disaggregation # disaggregation - web application
This branch is the web app implementation of the master branch, in which the grids are visualized in a 3D globe using CesiumJS.
Source code for disaggregation ### Demo
\ No newline at end of file http://193.196.55.138/ensource2/
\ No newline at end of file
File moved
This diff is collapsed.
This source diff could not be displayed because it is too large. You can view the blob instead.
<html>
<head>
<title>ENsource Disaggregation Report</title>
<meta charset="UTF-8">
<style>
h1 {
text-align: center;
color: #002C55;
}
h2 {
text-align: left;
font-size: 25px;
font-weight: "bold";
color: #002C55;
}
h1 span {
color: #549925;
}
</style>
</head>
<body>
<h1><span>EN</span>source Disaggregation Report</h1>
<h2 style="float:left; width: 100%;">Run Results</h2>
<!-- TO BE ADDED: HELP? -->
<form action = "http://127.0.0.1:5000/ensource2/" method = "POST" enctype = "multipart/form-data">
<p>Input CSV file:
<input type=file name=file required>
</p>
<input type=submit value=Run>
</form>
<br/>
<p><a href="data/sample.csv">Download a sample of input CSV file</a></p>
<p><small><strong>IMPORTANT:</strong> The header of the CSV input file MUST BE named as the following:
<ul>
<li>ID</li>
<li>GMLId</li>
<li>Stat PrimaryUsageZoneType</li>
<li>Stat Class year of construction</li>
<li>Building Count</li>
<li>Total Yearly Heat+DHW demand</li>
<li>January Heating Demand</li>
<li>February Heating Demand</li>
<li>March Heating Demand</li>
<li>April Heating Demand</li>
<li>May Heating Demand</li>
<li>June Heating Demand</li>
<li>July Heating Demand</li>
<li>August Heating Demand</li>
<li>September Heating Demand</li>
<li>October Heating Demand</li>
<li>November Heating Demand</li>
<li>December Heating Demand</li>
<li>Total Distance</li>
<li>Length</li>
<li>geometry</li>
<li>neighbor</li>
</ul>
</small></p>
</body>
</html>
<html>
<head>
<title>ENsource Disaggregation Report</title>
<meta charset="UTF-8">
<!-- Include the CesiumJS JavaScript and CSS files -->
<script src="https://cesium.com/downloads/cesiumjs/releases/1.78/Build/Cesium/Cesium.js"></script>
<link href="https://cesium.com/downloads/cesiumjs/releases/1.78/Build/Cesium/Widgets/widgets.css" rel="stylesheet">
<!-- Terraformer and WKT Parser -->
<script src="https://unpkg.com/terraformer@1.0.7/terraformer.js"></script>
<script src="https://unpkg.com/terraformer-wkt-parser@1.1.2/terraformer-wkt-parser.js"></script>
<!-- proj4js -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/proj4js/2.7.2/proj4.min.js" integrity="sha512-dNFx8aqYHHdVRrTfm7fzMSakZd+cD8Bf24ZqvAIh799ORCeyVdzN1w4wiqLtLON7VPkZ1vQmMi+CJRF/b3v/7A==" crossorigin="anonymous"></script>
<style>
h1 {
text-align: center;
color: #002C55;
}
h2 {
text-align: left;
font-size: 25px;
font-weight: "bold";
color: #002C55;
}
h1 span {
color: #549925;
}
table {
border-collapse: collapse;
border: 1px solid #DFDCDC;
border-spacing: 0;
}
th {
background-color: #549925;
color: white;
text-align: left;
padding: 8px;
}
td {
text-align: left;
padding: 8px;
}
tr:nth-child(even) {
background-color: #e7f4d9;
}
table th,
table td {
border-top: 1px #efe9e3;
border-right: 0px #efe9e3;
border-bottom: 0px #efe9e3;
border-left: 1px #efe9e3;
}
.button {
float: left;
padding: 6px 9px;
cursor: pointer;
margin-top: 20px;
margin-left: 15px;
border-radius: 5px;
background-color: #549925;
font-size: 12px;
font-weight: bold;
color: #fff;
width: 30px;
}
.collapsible {
background-color: #549925;
color: #002C55;
cursor: pointer;
padding: 18px;
width: 100%;
border: none;
text-align: left;
outline: none;
font-size: 25px;
font-weight: bold;
}
.active, .collapsible:hover {
background-color: #BAD6A7;
}
.collapsible:after {
content: '\002B'; /* Unicode character for "plus" sign (+) */
color: #002C55;
font-weight: bold;
float: right;
margin-left: 5px;
}
.active:after {
content: "\2212"; /* Unicode character for "minus" sign (-) */
}
.content {
padding: 0 18px;
display: none;
overflow: hidden;
}
</style>
</head>
<body>
<h1><span>EN</span>source Disaggregation Report</h1>
<h2 style="float:left; width: 100%;">Run Results</h2>
<form action = "http://127.0.0.1:5000//ensource2/" method = "POST" enctype = "multipart/form-data">
<input type=file name=file required>
<input type=submit value=Run>
</form>
<table style="float:left; width: 49%; margin-right: 10;">
<tr>
<th>Target Demand (kWh)</th>
<td id="target-demand">N/A</td>
</tr>
<tr>
<th>Results Files</th>
<td id="file-name"><a id="jsonResult" href=#></a> | <a id="csvResult" href=#></a></td>
</tr>
<tr>
<th>Segments File</th>
<td id="segments-file-name">N/A</td>
</tr>
<tr>
<th>Available Segments</th>
<td id="available-segments">N/A</td>
</tr>
<tr>
<th>Grid provided</th>
<td id="grid-provided">N/A</td>
</tr>
</table>
<table style="float:left;width: 49%;">
<tr>
<th>Accumulated demand (kWh)</th>
<td id="accumulated-demand">N/A</td>
</tr>
<tr>
<th>Investment cost (EUR)</th>
<td id="investment-cost">N/A</td>
</tr>
<tr>
<th>Total grid length (m)</th>
<td id="total-length">N/A</td>
</tr>
<tr>
<th>Used segments</th>
<td id="used-segments">N/A</td>
</tr>
<tr>
<th>Grid provided IDs</th>
<td id="grid-provided-ids">{{ givenGridIds }}</td>
</tr>
</table>
<button type="button" class="collapsible">Calculated Grid</button>
<div class="content">
<table id="result-table" border=1 style="width: 99%;">
<tr>
<th> Segment ID </th>
<th> Demand (kWh)</th>
<th> Length (m)</th>
<th> Acc. Demand (kWh)</th>
<th> Acc. Length (m)</th>
<th> Acc. Grid Cost (EUR)</th>
</table>
</div>
<button type="button" class="collapsible">Grid Visualization</button> <!-- span>+</span -->
<div class="content">
<div id="toolbar" style="position: absolute; padding: 25px; z-index: 1;">
<!-- select id="myColor" onchange="doStyling()">
<option value="1">Show/hide grids</option>
<option value="2">Color grids by segment demand (kWh)</option>
<option value="0">Show/hide buildings</option>
</select -->
</div>
<div id="cesiumContainer"></div>
</div>
<script>
//var myViewer
var myWholeGrid
var myGrid
// collapsible
var coll = document.getElementsByClassName("collapsible")
var i
for (i = 0; i < coll.length; i++) {
coll[i].addEventListener("click", function() {
this.classList.toggle("active")
var content = this.nextElementSibling
if (content.style.display === "block") {
content.style.display = "none"
} else {
content.style.display = "block"
}
})
}
/*
function doStyling() {
let id = document.getElementById("myColor").value
if (id == 0) {
// show/hide buildings
} else if(id == 1) {
// show/hide grids
} else if(id == 2) {
for (var segment in myGrid.segments) {
let linesReprojected = myGrid.segments[segment].geometryReprojected
for (let i = 0; i < (linesReprojected.length-1); i++) {
myViewer.entities.add({
polyline: {
positions: Cesium.Cartesian3.fromDegreesArray([linesReprojected[i][0], linesReprojected[i][1], linesReprojected[i+1][0], linesReprojected[i+1][1]]),
width: 5,
material: Cesium.Color.GREEN,
clampToGround: true,
}
});
}
}
}
} */
function gridCost(total_demand_kWh, total_length_m, a, c1, c2){
const q_s = (total_demand_kWh/(10**6))*3600;
const d_a = 0.0486 * Math.log(q_s / total_length_m) + 0.0007;
grid_investment_cost_EUR = a*(c1 + c2 * d_a) * total_length_m;
return grid_investment_cost_EUR;
}
function displayTable(grid) {
const table = document.getElementById('result-table');
table.children = null;
//element.texContent = JSON.stringify(result);
const tblBody = document.createElement("tbody");
let accDemand = 0;
let accLength = 0;
// creating all cells
const target = document.getElementById('target-demand');
target.textContent = grid.targetDemand;
const segmentsFile = document.getElementById('segments-file-name');
segmentsFile.textContent = grid.segmentsFile;
const availSegments = document.getElementById('available-segments');
availSegments.textContent = grid.availableSegmentsCount;
const gridProvided = document.getElementById('grid-provided');
gridProvided.textContent = grid.givenGridStr;
const accumulatedDemand = document.getElementById('accumulated-demand');
accumulatedDemand.textContent = grid.accumulatedDemand;
const investmentCost = document.getElementById('investment-cost');
investmentCost.textContent = grid.investmentCost.toFixed(3);
const totalLength = document.getElementById('total-length');
totalLength.textContent = grid.totalLength;
const calcGridTitle = document.getElementById('used-segments');
//calcGridTitle.textContent = `${grid.segments.length}`;
calcGridTitle.textContent = grid.segments.length;
for (var segment in grid.segments) {
var row = document.createElement("tr");
const id = document.createElement("td");
let cellText = document.createTextNode(grid.segments[segment].id);
id.appendChild(cellText);
const demand = document.createElement("td");
cellText = document.createTextNode(grid.segments[segment].demand);
demand.appendChild(cellText);
const length = document.createElement("td");
cellText = document.createTextNode(grid.segments[segment].length);
length.appendChild(cellText);
var accDemandCell = document.createElement("td");
cellText = document.createTextNode(accDemand += grid.segments[segment].demand);
accDemandCell.appendChild(cellText);
var accLengthCell = document.createElement("td");
cellText = document.createTextNode((accLength += grid.segments[segment].length).toFixed(3));
accLengthCell.appendChild(cellText);
var accCostCell = document.createElement("td");
cellText = document.createTextNode((gridCost(accDemand,accLength, grid.a, grid.c1, grid.c2)).toFixed(3));
accCostCell.appendChild(cellText);
row.appendChild(id);
row.appendChild(demand);
row.appendChild(length);
row.appendChild(accDemandCell);
row.appendChild(accLengthCell);
row.appendChild(accCostCell);
// add the row to the end of the table body
tblBody.appendChild(row);
}
// put the <tbody> in the <table>
if (table.children[1]) table.children[1].replaceWith(tblBody);
else table.appendChild(tblBody);
}
function drawBaseGrid(viewer, wholeGrid) {
// todo: clear entities
for (var segment in wholeGrid) {
// parse a WKT string, converting it into a Terraformer.Primitive
let geojsonLineString = Terraformer.WKT.parse(wholeGrid[segment].geometry)
let coordinates = []
for (let i = 0; i < (geojsonLineString.coordinates.length); i++) {
let projWebCoordinate = reprojectCoordinate(geojsonLineString.coordinates[i])
coordinates.push(projWebCoordinate)
}
// draw grids based on coordinates
for (let i = 0; i < (coordinates.length-1); i++) {
viewer.entities.add({
id: "BaseGrid"+"_Segment-"+wholeGrid[segment].id+"-"+i,
polyline: {
positions: Cesium.Cartesian3.fromDegreesArray([coordinates[i][0], coordinates[i][1], coordinates[i+1][0], coordinates[i+1][1]]),
width: 2,
material: Cesium.Color.BLACK,
clampToGround: true,
}
})
}
}
}
function drawGrid(viewer, grid) {
for (var segment in grid.segments) {
// parse a WKT string, converting it into a Terraformer.Primitive
let geojsonLineString = Terraformer.WKT.parse(grid.segments[segment].geometry)
let coordinates = []
for (let i = 0; i < (geojsonLineString.coordinates.length); i++) {
let projWebCoordinate = reprojectCoordinate(geojsonLineString.coordinates[i])
coordinates.push(projWebCoordinate)
}
// draw grids based on coordinates
for (let i = 0; i < (coordinates.length-1); i++) {
viewer.entities.add({
id: "Grid"+"_Segment-"+grid.segments[segment].id+"-"+i,
polyline: {
positions: Cesium.Cartesian3.fromDegreesArray([coordinates[i][0], coordinates[i][1], coordinates[i+1][0], coordinates[i+1][1]]),
width: 5,
material: Cesium.Color.RED,
clampToGround: true,
},
});
}
}
}
function reprojectCoordinate(coordinate) {
let firstProj = "+proj=tmerc +lat_0=0 +lon_0=9 +k=1 +x_0=3500000 +y_0=0 +ellps=bessel +datum=potsdam +units=m +no_defs"; // EPSG:31467
let secondProj = "+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs"; // EPSG:4326
// convert the passed coordinate to geographic coordinate
let geoCoordinate = Terraformer.Tools.positionToGeographic(coordinate)
// converts the passed coordinate to web mercator spatial reference.
let webCoordinate = Terraformer.Tools.positionToMercator(geoCoordinate)
// project coordinate to EPSG 4326
let projWebCoordinate = proj4(firstProj, secondProj, webCoordinate)
return projWebCoordinate
}
function init() {
// set links to the result files
let aJson = document.getElementById('jsonResult')
let resultJsonFilename = {{ resultFileJson | tojson }}
aJson.href = "result/"+resultJsonFilename
aJson.textContent = resultJsonFilename
let aCsv = document.getElementById('csvResult')
let resultCsvFilename = {{ resultFileCsv | tojson }}
aCsv.href = "result/"+resultCsvFilename
aCsv.textContent = resultCsvFilename
// load cesiumjs
Cesium.Ion.defaultAccessToken = 'put-your-cesium-token-here'
let viewer = new Cesium.Viewer("cesiumContainer", {
animation: false,
timeline: false,
terrainProvider: Cesium.createWorldTerrain(),
imageryProvider : new Cesium.OpenStreetMapImageryProvider({
url : 'https://a.tile.openstreetmap.org/'})
});
// Add Cesium OSM buildings to the scene
//viewer.scene.primitives.add(Cesium.createOsmBuildings());
//myViewer = viewer
myWholeGrid = JSON.parse({{ wholeGrid | tojson }})
myGrid = JSON.parse({{ grid | tojson }})
displayTable(myGrid)
drawBaseGrid(viewer, myWholeGrid)
drawGrid(viewer, myGrid)
viewer.zoomTo(viewer.entities)
}
init()
</script>
</body>
</html>
wsgi.py 0 → 100644
from disaggregation import app
if __name__ == '__main__':
app.run(debug=False)
\ No newline at end of file
Supports Markdown
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