diff options
author | Danijel Anđelković <adanijel99@gmail.com> | 2022-06-06 05:24:26 +0200 |
---|---|---|
committer | Danijel Anđelković <adanijel99@gmail.com> | 2022-06-06 05:24:26 +0200 |
commit | 5dc30c02319ba9fa8e8ddb33e9574272f05598fe (patch) | |
tree | e514ed32fe74b2b47dd04cd78e796daa4e28d6a1 /frontend/src/app/_elements/_charts/line-chart | |
parent | d1763481d6c08c955885ed490a284e634a56296b (diff) | |
parent | ec46487761e888935411cf4daa9e740913f2ee9b (diff) |
Merge branch 'redesign' of http://gitlab.pmf.kg.ac.rs/igrannonica/neuronstellar
Diffstat (limited to 'frontend/src/app/_elements/_charts/line-chart')
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; } } |