aboutsummaryrefslogtreecommitdiff
path: root/frontend/src/app/_elements/_charts/line-chart
diff options
context:
space:
mode:
authorDanijel Anđelković <adanijel99@gmail.com>2022-06-06 05:24:26 +0200
committerDanijel Anđelković <adanijel99@gmail.com>2022-06-06 05:24:26 +0200
commit5dc30c02319ba9fa8e8ddb33e9574272f05598fe (patch)
treee514ed32fe74b2b47dd04cd78e796daa4e28d6a1 /frontend/src/app/_elements/_charts/line-chart
parentd1763481d6c08c955885ed490a284e634a56296b (diff)
parentec46487761e888935411cf4daa9e740913f2ee9b (diff)
Merge branch 'redesign' of http://gitlab.pmf.kg.ac.rs/igrannonica/neuronstellar
Diffstat (limited to 'frontend/src/app/_elements/_charts/line-chart')
-rw-r--r--frontend/src/app/_elements/_charts/line-chart/line-chart.component.css48
-rw-r--r--frontend/src/app/_elements/_charts/line-chart/line-chart.component.html30
-rw-r--r--frontend/src/app/_elements/_charts/line-chart/line-chart.component.ts396
3 files changed, 408 insertions, 66 deletions
diff --git a/frontend/src/app/_elements/_charts/line-chart/line-chart.component.css b/frontend/src/app/_elements/_charts/line-chart/line-chart.component.css
index 2eea561e..60b341d0 100644
--- a/frontend/src/app/_elements/_charts/line-chart/line-chart.component.css
+++ b/frontend/src/app/_elements/_charts/line-chart/line-chart.component.css
@@ -1,11 +1,47 @@
-canvas{
+.canvas-container {
+ height: 50%;
+ margin: 5px;
+}
- width:100% !important;
- height:90% !important;
+.bottom {
+ height: 30px;
+}
+
+canvas {
+ max-height: 100%;
border: 1px solid var(--ns-primary);
background-color: var(--ns-bg-dark-100);
border-radius: 5px;
- margin: 10px;
+ margin: 0;
font-size: 11 !important;
- }
- \ No newline at end of file
+ padding: 0;
+}
+
+.ns-col {
+ margin: 5px;
+}
+
+.hide {
+ display: none !important;
+ background-color: red;
+}
+
+.dl-button {
+ position: relative;
+ color: var(--offwhite);
+ border-radius: 4px;
+ border: 1px solid var(--ns-primary);
+ background-color: var(--ns-bg-dark-50);
+ margin: 5px;
+ padding: 10px;
+ cursor: pointer;
+ z-index: 1001;
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ justify-content: center;
+}
+
+.dl-button:hover {
+ background-color: var(--ns-primary);
+} \ No newline at end of file
diff --git a/frontend/src/app/_elements/_charts/line-chart/line-chart.component.html b/frontend/src/app/_elements/_charts/line-chart/line-chart.component.html
index 1c711562..505dd50b 100644
--- a/frontend/src/app/_elements/_charts/line-chart/line-chart.component.html
+++ b/frontend/src/app/_elements/_charts/line-chart/line-chart.component.html
@@ -1,4 +1,28 @@
-<div #wrapper class="position-relative" style="width:100%;height:95%;">
- <canvas id="myChart" #canvas>
- </canvas>
+<div #wrapper class="position-relative" style="width:100%;height:95%; border: 1px solid var(--ns-accent); background-color: var(--ns-bg-dark-100); border-radius: 15px;">
+ <div class="d-flex flex-column align-items-stretch" [ngClass]="{'hide':experiment.type !== ProblemType.Regression}" style="width: 100%; height: 90%;">
+ <div class="canvas-container">
+ <canvas #myChartmae>
+ </canvas>
+ </div>
+ <div class="canvas-container">
+ <canvas #myChartmse>
+ </canvas>
+ </div>
+ </div>
+ <div class="d-flex flex-column align-items-stretch" [ngClass]="{'hide':experiment.type === ProblemType.Regression}" style="width: 100%; height: 90%;">
+ <div class="canvas-container">
+ <canvas #myChartloss>
+ </canvas>
+ </div>
+ <div class="canvas-container">
+ <canvas #myChartacc>
+ </canvas>
+ </div>
+ </div>
+ <div class="bottom d-flex flex-row" style="justify-content: space-between; align-items: center;">
+ <h3 class="mt-5 mx-2"><span *ngIf="modelName.length > 0 && predictor">Model treniran za konfiguraciju: {{modelName}}</span><span *ngIf="modelName.length > 0 && !predictor">Model se trenira za konfiguraciju: {{modelName}}</span></h3>
+ <button *ngIf="predictor" class="mt-5 mx-2 btn-clear dl-button d-flex flex-row" (click)="downloadFile();" style="display: inline-block;" matTooltip="Preuzmi H5" matTooltipPosition="above">
+ <mat-icon>download</mat-icon> <div>H5</div>
+ </button>
+ </div>
</div> \ No newline at end of file
diff --git a/frontend/src/app/_elements/_charts/line-chart/line-chart.component.ts b/frontend/src/app/_elements/_charts/line-chart/line-chart.component.ts
index 7d21129c..b2eec377 100644
--- a/frontend/src/app/_elements/_charts/line-chart/line-chart.component.ts
+++ b/frontend/src/app/_elements/_charts/line-chart/line-chart.component.ts
@@ -1,5 +1,10 @@
-import { Component, AfterViewInit, ElementRef, ViewChild } from '@angular/core';
+import { Component, AfterViewInit, ElementRef, ViewChild, Input, ViewChildren, QueryList } from '@angular/core';
import { Chart } from 'chart.js';
+import FileSaver from 'file-saver';
+import Experiment from 'src/app/_data/Experiment';
+import Model, { ProblemType } from 'src/app/_data/Model';
+import Predictor from 'src/app/_data/Predictor';
+import { PredictorsService } from 'src/app/_services/predictors.service';
@Component({
selector: 'app-line-chart',
@@ -13,35 +18,53 @@ export class LineChartComponent implements AfterViewInit {
dataMAE: number[] = [];
dataMSE: number[] = [];
dataLOSS: number[] = [];
- dataValAcc:number[]=[];
- dataValMAE:number[]=[];
- dataValMSE:number[]=[];
- dataValLoss:number[]=[];
+ dataValAcc: number[] = [];
+ dataValMAE: number[] = [];
+ dataValMSE: number[] = [];
+ dataValLoss: number[] = [];
dataEpoch: number[] = [];
@ViewChild('wrapper')
wrapper!: ElementRef;
- @ViewChild('canvas')
- canvas!: ElementRef;
- constructor() {
-
+ @ViewChild('myChartacc') myChartacc!: ElementRef;
+ @ViewChild('myChartloss') myChartloss!: ElementRef;
+ @ViewChild('myChartmse') myChartmse!: ElementRef;
+ @ViewChild('myChartmae') myChartmae!: ElementRef;
+
+ @Input() experiment!: Experiment;
+ @Input() predictor?: Predictor;
+
+
+ downloadFile() {
+ if (!this.predictor) {
+ return;
+ }
+
+ const fileId = this.predictor.h5FileId;
+ if (fileId != undefined)
+ this.predictorsService.downloadH5(fileId).subscribe((response) => {
+ FileSaver.saveAs(response, fileId + '.h5');
+ });
+ }
+
+ constructor(private predictorsService: PredictorsService) {
+
}
width = 700;
height = 400;
-
- myChart!: Chart;
+ history: any[] = [];
+ myChartAcc!: Chart;
+ myChartMae!: Chart;
+ myChartMse!: Chart;
+ myChartLoss!: Chart;
+ ProblemType = ProblemType;
resize() {
- this.width = this.wrapper.nativeElement.offsetWidth;
+ //this.width = this.wrapper.nativeElement.offsetWidth;
this.height = this.wrapper.nativeElement.offsetHeight;
-
- if (this.canvas) {
- this.canvas.nativeElement.width = this.width;
- this.canvas.nativeElement.height = this.height;
- }
}
- update(myEpochs: number[], myAcc: number[], myLoss: number[], myMae: number[], myMse: number[], myValAcc:number[],myValLoss:number[],myValMae:number[],myValMse:number[]) {
-
+ update(myEpochs: number[], myAcc: number[], myLoss: number[], myMae: number[], myMse: number[], myValAcc: number[], myValLoss: number[], myValMae: number[], myValMse: number[]) {
+
this.dataEpoch.length = 0;
this.dataEpoch.push(...myEpochs);
@@ -69,14 +92,68 @@ export class LineChartComponent implements AfterViewInit {
this.dataValMSE.length = 0;
this.dataValMSE.push(...myValMse);
- this.myChart.update();
+ this.myChartAcc.update();
+ this.myChartLoss.update();
+ this.myChartMae.update();
+ this.myChartMse.update();
}
+ updateAll(history: any[], totalEpochs: number) {
+ const myAcc: number[] = [];
+ const myMae: number[] = [];
+ const myMse: number[] = [];
+ const myLoss: number[] = [];
+ const myValLoss: number[] = [];
+ const myValAcc: number[] = [];
+ const myValMAE: number[] = [];
+ const myValMSE: number[] = [];
+ const myEpochs: number[] = [];
+ this.history = history;
+ this.history.forEach((metrics, epoch) => {
+ if (totalEpochs > 100) {
+ let epochEstimate = epoch * Math.round(Math.sqrt(totalEpochs))
+ if (epochEstimate > totalEpochs)
+ epochEstimate = totalEpochs;
+ myEpochs.push(epochEstimate);
+ }
+ else
+ myEpochs.push(epoch + 1);
+ for (let key in metrics) {
+ let value = metrics[key];
+ if (key === 'accuracy') {
+ myAcc.push(parseFloat(value));
+ }
+ else if (key === 'loss') {
+ myLoss.push(parseFloat(value));
+ }
+ else if (key === 'mae') {
+ myMae.push(parseFloat(value));
+ }
+ else if (key === 'mse') {
+ myMse.push(parseFloat(value));
+ }
+ else if (key === 'val_acc') {
+ myValAcc.push(parseFloat(value));
+ }
+ else if (key === 'val_loss') {
+ myValLoss.push(parseFloat(value));
+ }
+ else if (key === 'val_mae') {
+ myValMAE.push(parseFloat(value));
+ }
+ else if (key === 'val_mse') {
+ myValMSE.push(parseFloat(value));
+ }
+ }
+ });
+
+ this.update(myEpochs, myAcc, myLoss, myMae, myMse, myValAcc, myValLoss, myValMAE, myValMSE);
+ }
ngAfterViewInit(): void {
-
+
window.addEventListener('resize', () => { this.resize() });
this.resize();
- this.myChart = new Chart("myChart",
+ this.myChartAcc = new Chart(this.myChartacc.nativeElement,
{
type: 'line',
data: {
@@ -86,58 +163,244 @@ export class LineChartComponent implements AfterViewInit {
label: 'Accuracy',
data: this.dataAcc,
borderWidth: 1,
-
+
},
{
label: 'Val_Accuracy',
data: this.dataValAcc,
borderWidth: 1
+ }
+ ]
+ },
+ options: {
+ //responsive: true,
+ //maintainAspectRatio: true,
+ plugins: {
+ legend: {
+ labels: {
+ // This more specific font property overrides the global property
+ color: 'white',
+ font: {
+ size: 10
+ }
+ }
+ }
},
- {
- label: 'Loss',
- data: this.dataLOSS,
- borderWidth: 1
+ scales: {
+ x: {
+ ticks: {
+ color: 'white'
+ },
+ grid: {
+ color: "rgba(0, 99, 171, 0.5)"
+ },
+ title: {
+ display: true,
+ text: 'Epoha',
+ color: "white"
+ }
+ },
+ y: {
+ beginAtZero: true,
+ ticks: {
+ color: 'white'
+
+ },
+ grid: {
+ color: "rgba(0, 99, 171, 0.5)"
+ },
+ title: {
+ display: true,
+ text: 'Vrednost',
+ color: "white"
+ }
+ }
+
},
- {
- label: 'Val_Loss',
- data: this.dataValLoss,
- borderWidth: 1
+ animation: {
+ duration: 0
+ }
+
+ }
+ },
+
+ );
+ if (this.experiment.type == ProblemType.BinaryClassification || this.experiment.type == ProblemType.MultiClassification) { }
+ this.myChartLoss = new Chart(this.myChartloss.nativeElement,
+ {
+ type: 'line',
+ data: {
+ labels: this.dataEpoch,
+ datasets: [
+ {
+ label: 'Loss',
+ data: this.dataLOSS,
+ borderWidth: 1
+ },
+ {
+ label: 'Val_Loss',
+ data: this.dataValLoss,
+ borderWidth: 1
+ },
+ ]
+ },
+ options: {
+ //responsive: true,
+ //maintainAspectRatio: true,
+
+ plugins: {
+ legend: {
+ labels: {
+ // This more specific font property overrides the global property
+ color: 'white',
+ font: {
+ size: 10
+ }
+ }
+ }
},
- {
- label: 'MAE',
- data: this.dataMAE,
- borderWidth: 1
+ scales: {
+ x: {
+ ticks: {
+ color: 'white'
+ },
+ grid: {
+ color: "rgba(0, 99, 171, 0.5)"
+ },
+ title: {
+ display: true,
+ text: 'Epoha',
+ color: "white"
+ }
+ },
+ y: {
+ beginAtZero: true,
+ ticks: {
+ color: 'white'
+
+ },
+ grid: {
+ color: "rgba(0, 99, 171, 0.5)"
+ },
+ title: {
+ display: true,
+ text: 'Vrednost',
+ color: "white"
+ }
+ }
+
},
- {
- label: 'Val_MAE',
- data: this.dataValMAE,
- borderWidth: 1
+ animation: {
+ duration: 0
+ }
+
+ }
+ },
+
+ );
+ this.myChartMse = new Chart(this.myChartmse.nativeElement,
+ {
+ type: 'line',
+ data: {
+ labels: this.dataEpoch,
+ datasets: [
+ {
+ label: 'MSE',
+ data: this.dataMSE,
+ borderWidth: 1
+ },
+ {
+ label: 'Val_MSE',
+ data: this.dataValMSE,
+ borderWidth: 1
+ }
+ ]
+ },
+ options: {
+ //responsive: true,
+ //maintainAspectRatio: true,
+
+ plugins: {
+ legend: {
+ labels: {
+ // This more specific font property overrides the global property
+ color: 'white',
+ font: {
+ size: 10
+ }
+ }
+ }
},
- {
- label: 'MSE',
- data: this.dataMSE,
- borderWidth: 1
+ scales: {
+ x: {
+ ticks: {
+ color: 'white'
+ },
+ grid: {
+ color: "rgba(0, 99, 171, 0.5)"
+ },
+ title: {
+ display: true,
+ text: 'Epoha',
+ color: "white"
+ }
+ },
+ y: {
+ beginAtZero: true,
+ ticks: {
+ color: 'white'
+
+ },
+ grid: {
+ color: "rgba(0, 99, 171, 0.5)"
+ },
+ title: {
+ display: true,
+ text: 'Vrednost',
+ color: "white"
+ }
+ }
+
},
- {
- label: 'Val_MSE',
- data: this.dataValMSE,
- borderWidth: 1
+ animation: {
+ duration: 0
}
+
+ }
+ },
+
+ );
+ this.myChartMae = new Chart(this.myChartmae.nativeElement,
+ {
+ type: 'line',
+ data: {
+ labels: this.dataEpoch,
+ datasets: [
+ {
+ label: 'MAE',
+ data: this.dataMAE,
+ borderWidth: 1
+ },
+ {
+ label: 'Val_MAE',
+ data: this.dataValMAE,
+ borderWidth: 1
+ },
]
},
options: {
- responsive: true,
- maintainAspectRatio: true,
+ //responsive: true,
+ //maintainAspectRatio: true,
plugins: {
legend: {
- labels: {
- // This more specific font property overrides the global property
- color:'white',
- font: {
- size: 10
- }
+ labels: {
+ // This more specific font property overrides the global property
+ color: 'white',
+ font: {
+ size: 10
}
+ }
}
},
scales: {
@@ -148,15 +411,25 @@ export class LineChartComponent implements AfterViewInit {
grid: {
color: "rgba(0, 99, 171, 0.5)"
},
+ title: {
+ display: true,
+ text: 'Epoha',
+ color: "white"
+ }
},
y: {
beginAtZero: true,
ticks: {
color: 'white'
-
+
},
grid: {
color: "rgba(0, 99, 171, 0.5)"
+ },
+ title: {
+ display: true,
+ text: 'Vrednost',
+ color: "white"
}
}
@@ -166,8 +439,17 @@ export class LineChartComponent implements AfterViewInit {
}
}
- }
+ },
+
);
+
+ }
+
+ modelName: string = '';
+
+ setName(name: string) {
+ this.modelName = name;
+ this.predictor = undefined;
}
}