-
Notifications
You must be signed in to change notification settings - Fork 181
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: save validation result as json and show the static dashboard us…
…ing js Signed-off-by: Parul Singh <parsingh@redhat.com>
- Loading branch information
1 parent
c607a6d
commit 6a6017b
Showing
6 changed files
with
366 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
<head> | ||
<meta charset="UTF-8"> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||
<title>Chart with JSON Data</title> | ||
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script> | ||
<script defer src="script.js"></script> | ||
<style> | ||
body { | ||
display: flex; | ||
} | ||
#chart-container { | ||
width: 70%; | ||
padding: 20px; | ||
} | ||
#info-container { | ||
width: 30%; | ||
padding: 20px; | ||
} | ||
ul { | ||
list-style-type: none; | ||
} | ||
</style> | ||
</head> | ||
<body> | ||
<div id="chart-container"> | ||
<canvas id="myChart"></canvas> | ||
</div> | ||
<div id="info-container"> | ||
<div id="build-info"> | ||
<h3>Build Info</h3> | ||
<ul></ul> | ||
</div> | ||
<div id="machine-spec"> | ||
<h3>Machine Spec</h3> | ||
<ul></ul> | ||
</div> | ||
</div> | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
async function fetchJSONFile(filePath) { | ||
try { | ||
const response = await fetch(filePath); | ||
const data = await response.json(); | ||
return data; | ||
} catch (error) { | ||
console.error('Error fetching JSON file:', error); | ||
} | ||
} | ||
|
||
function processJSONData(data) { | ||
const revisions = []; | ||
const mseValues = []; | ||
const mapeValues = []; | ||
const labels = []; | ||
|
||
data.build_info.forEach(buildInfo => { | ||
const buildInfoObj = JSON.parse(buildInfo); | ||
const revision = buildInfoObj.revision; | ||
if (!revisions.includes(revision)) { | ||
revisions.push(revision); | ||
} | ||
}); | ||
|
||
data.result.forEach(result => { | ||
labels.push(result['metric-name']); | ||
mseValues.push(parseFloat(result.value.mse)); | ||
mapeValues.push(parseFloat(result.value.mape)); | ||
}); | ||
|
||
return { revisions, mseValues, mapeValues, labels }; | ||
} | ||
|
||
function plotChart(revisions, mseValues, mapeValues, labels) { | ||
const ctx = document.getElementById('myChart').getContext('2d'); | ||
new Chart(ctx, { | ||
type: 'line', | ||
data: { | ||
labels: labels, | ||
datasets: [{ | ||
label: `MSE - ${revisions.join(', ')}`, | ||
data: mseValues, | ||
borderColor: 'rgba(75, 192, 192, 1)', | ||
backgroundColor: 'rgba(75, 192, 192, 0.2)', | ||
fill: false | ||
}, { | ||
label: `MAPE - ${revisions.join(', ')}`, | ||
data: mapeValues, | ||
borderColor: 'rgba(255, 99, 132, 1)', | ||
backgroundColor: 'rgba(255, 99, 132, 0.2)', | ||
fill: false | ||
}] | ||
}, | ||
options: { | ||
responsive: true, | ||
scales: { | ||
x: { | ||
beginAtZero: true | ||
}, | ||
y: { | ||
beginAtZero: true, | ||
title: { | ||
display: true, | ||
text: 'Values' | ||
} | ||
} | ||
}, | ||
plugins: { | ||
legend: { | ||
display: true, | ||
position: 'top' | ||
}, | ||
tooltip: { | ||
callbacks: { | ||
label: function(context) { | ||
let label = context.dataset.label || ''; | ||
if (label) { | ||
label += ': '; | ||
} | ||
if (context.parsed.y !== null) { | ||
label += new Intl.NumberFormat('en-US', { maximumFractionDigits: 2 }).format(context.parsed.y); | ||
} | ||
return label; | ||
} | ||
} | ||
} | ||
} | ||
} | ||
}); | ||
} | ||
|
||
function displayBuildInfo(data) { | ||
const buildInfoContainer = document.getElementById('build-info').querySelector('ul'); | ||
data.build_info.forEach(info => { | ||
const buildInfoObj = JSON.parse(info); | ||
const listItem = document.createElement('li'); | ||
listItem.textContent = `Revision: ${buildInfoObj.revision}, Version: ${buildInfoObj.version}`; | ||
buildInfoContainer.appendChild(listItem); | ||
}); | ||
} | ||
|
||
function displayMachineSpec(data) { | ||
const machineSpecContainer = document.getElementById('machine-spec').querySelector('ul'); | ||
data.machine_spec.forEach(spec => { | ||
const listItem = document.createElement('li'); | ||
listItem.innerHTML = ` | ||
<strong>Type:</strong> ${spec.type}<br> | ||
<strong>Model:</strong> ${spec.model}<br> | ||
<strong>Cores:</strong> ${spec.cores}<br> | ||
<strong>Threads:</strong> ${spec.threads}<br> | ||
<strong>Sockets:</strong> ${spec.sockets}<br> | ||
<strong>DRAM:</strong> ${spec.dram} | ||
`; | ||
machineSpecContainer.appendChild(listItem); | ||
}); | ||
} | ||
|
||
// Path to the single JSON file | ||
const filePath = '/tmp/v0.2-2315-g859d9bf1/v0.2-2316-gc607a6df.json'; // Change to the actual path of your JSON file | ||
|
||
fetchJSONFile(filePath) | ||
.then(data => { | ||
const { revisions, mseValues, mapeValues, labels } = processJSONData(data); | ||
plotChart(revisions, mseValues, mapeValues, labels); | ||
displayBuildInfo(data); | ||
displayMachineSpec(data); | ||
}) | ||
.catch(error => console.error('Error processing data:', error)); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
body { | ||
font-family: Arial, sans-serif; | ||
display: flex; | ||
justify-content: center; | ||
align-items: center; | ||
height: 100vh; | ||
margin: 0; | ||
background-color: #f4f4f4; | ||
} | ||
|
||
#dashboard { | ||
width: 80%; | ||
max-width: 800px; | ||
background: white; | ||
padding: 20px; | ||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); | ||
border-radius: 8px; | ||
} | ||
|
||
canvas { | ||
max-width: 100%; | ||
height: auto; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
import json | ||
from typing import Any | ||
|
||
|
||
class Value: | ||
def __init__(self, mse: str = "", mape: str = "", status: str = ""): | ||
self.mse = mse | ||
self.mape = mape | ||
self.status = status | ||
|
||
def to_dict(self): | ||
return {"mse": self.mse, "mape": self.mape, "status": self.status} | ||
|
||
def __repr__(self): | ||
return f"Value(mse='{self.mse}', mape='{self.mape}', status='{self.status}')" | ||
|
||
|
||
class Result: | ||
def __init__(self, metric_name: str, value: dict[str, Any]): | ||
if value is None: | ||
value = {} | ||
self.metric_name = metric_name | ||
self.value = Value(**value) | ||
|
||
def to_dict(self): | ||
return {"metric-name": self.metric_name, "value": self.value.to_dict()} | ||
|
||
def __repr__(self): | ||
return f"Result(metric_name='{self.metric_name}', value={self.value})" | ||
|
||
|
||
class JsonTemplate: | ||
def __init__( | ||
self, | ||
file_path: str, | ||
build_info: list[Any], | ||
node_info: list[Any], | ||
machine_spec: list[Any], | ||
result: list[dict[str, Any]], | ||
): | ||
if build_info is None: | ||
build_info = [] | ||
if node_info is None: | ||
node_info = [] | ||
if machine_spec is None: | ||
machine_spec = [] | ||
if result is None: | ||
result = [] | ||
|
||
self.file_path = file_path | ||
self.build_info = build_info | ||
self.node_info = node_info | ||
self.machine_spec = machine_spec | ||
self.result = [] | ||
for res in result: | ||
for key, value in res.items(): | ||
self.result.append(Result(key, value)) | ||
|
||
def to_dict(self): | ||
return { | ||
"file_path": self.file_path, | ||
"build_info": self.build_info, | ||
"node_info": self.node_info, | ||
"machine_spec": self.machine_spec, | ||
"result": [res.to_dict() for res in self.result], | ||
} | ||
|
||
def __repr__(self): | ||
return ( | ||
f"JsonTemplate(file_path='{self.file_path}', build_info={self.build_info}, " | ||
f"node_info={self.node_info}, machine_spec={self.machine_spec}, " | ||
f"result={self.result})" | ||
) | ||
|
||
|
||
class CustomEncoder(json.JSONEncoder): | ||
def default(self, obj): | ||
if hasattr(obj, "to_dict"): | ||
return obj.to_dict() | ||
return super().default(obj) |
Oops, something went wrong.