aboutsummaryrefslogtreecommitdiff
path: root/frontend/src/app/_elements
diff options
context:
space:
mode:
authorIvan Ljubisavljevic <ivan996sk@gmail.com>2022-04-30 00:45:38 +0200
committerIvan Ljubisavljevic <ivan996sk@gmail.com>2022-04-30 00:45:38 +0200
commit1c723f051d723a743718f11c69e39b7913235bb7 (patch)
tree2987fcc40a9e79d3b0ee1c59531fd1c8126c46d4 /frontend/src/app/_elements
parent46502957863f8366232b63738f40fd4df4e995fa (diff)
parent7257f187324a59864d7db29c72fdb63f12900f40 (diff)
Merge branch 'redesign' of http://gitlab.pmf.kg.ac.rs/igrannonica/neuronstellar into redesign
# Conflicts: # frontend/src/app/_elements/folder/folder.component.html # frontend/src/app/_elements/folder/folder.component.ts
Diffstat (limited to 'frontend/src/app/_elements')
-rw-r--r--frontend/src/app/_elements/column-table/column-table.component.css12
-rw-r--r--frontend/src/app/_elements/column-table/column-table.component.html6
-rw-r--r--frontend/src/app/_elements/column-table/column-table.component.ts2
-rw-r--r--frontend/src/app/_elements/folder/folder.component.css3
-rw-r--r--frontend/src/app/_elements/folder/folder.component.html25
-rw-r--r--frontend/src/app/_elements/folder/folder.component.ts127
-rw-r--r--frontend/src/app/_elements/form-dataset/form-dataset.component.html2
-rw-r--r--frontend/src/app/_elements/form-model/form-model.component.html14
-rw-r--r--frontend/src/app/_elements/form-model/form-model.component.ts46
-rw-r--r--frontend/src/app/_elements/graph/graph.component.css17
-rw-r--r--frontend/src/app/_elements/graph/graph.component.html9
-rw-r--r--frontend/src/app/_elements/graph/graph.component.ts53
12 files changed, 236 insertions, 80 deletions
diff --git a/frontend/src/app/_elements/column-table/column-table.component.css b/frontend/src/app/_elements/column-table/column-table.component.css
index fdf69dbc..108efb32 100644
--- a/frontend/src/app/_elements/column-table/column-table.component.css
+++ b/frontend/src/app/_elements/column-table/column-table.component.css
@@ -192,7 +192,8 @@ table ::ng-deep .mat-form-field-wrapper {
}
.hidden {
- display: none;
+ visibility: hidden;
+ height: 1px;
}
.bottom-button {
@@ -210,4 +211,13 @@ table ::ng-deep .mat-form-field-wrapper {
display: flex;
flex-direction: row;
justify-content: center;
+}
+
+.pad-fix {
+ padding-top: 0.6rem;
+ padding-bottom: 0;
+}
+
+.long {
+ height: 3rem;
} \ No newline at end of file
diff --git a/frontend/src/app/_elements/column-table/column-table.component.html b/frontend/src/app/_elements/column-table/column-table.component.html
index 811df4bd..53cb3551 100644
--- a/frontend/src/app/_elements/column-table/column-table.component.html
+++ b/frontend/src/app/_elements/column-table/column-table.component.html
@@ -83,7 +83,7 @@
<tbody>
<tr>
<th>Tip</th>
- <td *ngFor="let colInfo of dataset.columnInfo; let i = index">
+ <td *ngFor="let colInfo of dataset.columnInfo; let i = index" class="pad-fix">
<mat-form-field>
<mat-select matNativeControl [(value)]="colInfo.isNumber">
<mat-option [value]="false">Kategorijski</mat-option>
@@ -120,11 +120,11 @@
</td>
</tr>
<tr style="padding: 0">
- <th class="brighter cell-align" (click)="openEncodingDialog()">
+ <th class="brighter cell-align long" (click)="openEncodingDialog()">
<span class="verticalAlign">Enkodiranje</span>&nbsp;
<span class="material-icons-round verticalAlign">settings</span>
</th>
- <td *ngFor="let colInfo of dataset.columnInfo; let i = index">
+ <td *ngFor="let colInfo of dataset.columnInfo; let i = index" class="pad-fix">
<mat-form-field>
<mat-select matNativeControl [(value)]="experiment.encodings[i].encoding">
<mat-option *ngFor="let option of Object.keys(Encoding); let optionName of Object.values(Encoding)" [value]="option">
diff --git a/frontend/src/app/_elements/column-table/column-table.component.ts b/frontend/src/app/_elements/column-table/column-table.component.ts
index 0745f73d..9cabf190 100644
--- a/frontend/src/app/_elements/column-table/column-table.component.ts
+++ b/frontend/src/app/_elements/column-table/column-table.component.ts
@@ -35,6 +35,8 @@ export class ColumnTableComponent implements AfterViewInit {
this.datasetService.getMyDatasets().subscribe((datasets) => {
this.dataset = datasets[0];
this.experiment = new Experiment();
+
+ console.log(datasets);
for (let i = 0; i < this.dataset?.columnInfo.length; i++) {
this.experiment?.inputColumns.push(this.dataset.columnInfo[i].columnName);
}
diff --git a/frontend/src/app/_elements/folder/folder.component.css b/frontend/src/app/_elements/folder/folder.component.css
index 458e6b4f..137a9643 100644
--- a/frontend/src/app/_elements/folder/folder.component.css
+++ b/frontend/src/app/_elements/folder/folder.component.css
@@ -21,7 +21,6 @@
justify-content: space-between;
align-items: center;
position: relative;
- overflow-x: hidden;
height: 2.5rem;
background-color: var(--ns-bg-dark-100);
border-color: var(--ns-primary);
@@ -32,7 +31,6 @@
.folder-tab:not(:first-child) {
margin-block-start: auto;
- width: 4rem;
}
.selected-tab {
@@ -54,6 +52,7 @@
color: var(--offwhite) !important;
text-decoration: none !important;
cursor: pointer;
+ padding: 0.5rem;
}
.tab-link:active {
diff --git a/frontend/src/app/_elements/folder/folder.component.html b/frontend/src/app/_elements/folder/folder.component.html
index d1e36ce0..36f70c97 100644
--- a/frontend/src/app/_elements/folder/folder.component.html
+++ b/frontend/src/app/_elements/folder/folder.component.html
@@ -1,21 +1,24 @@
<div id="folder">
<div id="tabs">
- <div id="new-file-tab" class="folder-tab p-1 rounded-top" [style]="'z-index:' + newFileZIndex() + ' ;'" [ngClass]="{'selected-tab' : newFileSelected, 'hover-tab' : hoveringOverFileIndex == -2}">
+ <div id="new-file-tab" class="folder-tab p-1 rounded-top" [style]="'z-index:' + (selectedTab == TabType.NewFile ? 11 : 10) + ' ;'" [ngClass]="{'selected-tab' : selectedTab == TabType.NewFile, 'hover-tab' : hoverTab == TabType.NewFile}">
<mat-icon class="text-offwhite">add</mat-icon>
- <a class="stretched-link tab-link" (click)="selectNewFile()" (mouseenter)="hoverOverFile(-2)" (mouseleave)="hoverOverFile(-1)">
- <p class="m-1" *ngIf="newFile != undefined">{{newFile.name}}</p>
+ <a class="stretched-link tab-link" (click)="selectTab(TabType.NewFile)" (mouseenter)="hoverOverTab(TabType.NewFile)" (mouseleave)="hoverOverTab(TabType.None)">
+ {{tabTitles[TabType.NewFile]}}
</a>
</div>
- <div class="folder-tab p-1 rounded-top" *ngFor="let file of filteredFiles; let i = index" [style]="'z-index:' + calcZIndex(i) + ' ;'" [ngClass]="{'selected-tab' : selectedFileIndex == i, 'hover-tab' : hoveringOverFileIndex == i}">
+ <!--<div class="folder-tab p-1 rounded-top" *ngFor="let file of filteredFiles; let i = index" [style]="'z-index:' + calcZIndex(i) + ' ;'" [ngClass]="{'selected-tab' : selectedFileIndex == i, 'hover-tab' : hoveringOverFileIndex == i}">
<a class="m-1 stretched-link tab-link" (click)="selectFile(i)" (mouseenter)="hoverOverFile(i)" (mouseleave)="hoverOverFile(-1)">{{file.name}}</a>
+ </div>-->
+ <div class="folder-tab p-1 rounded-top" *ngFor="let tab of tabsToShow; let i = index" [style]="'z-index:' + (selectedTab == tab ? 11 : (tabsToShow.length - i)) + ' ;'" [ngClass]="{'selected-tab' : selectedTab == tab, 'hover-tab' : hoverTab == tab}">
+ <a class="m-1 stretched-link tab-link" (click)="selectTab(tab)" (mouseenter)="hoverOverTab(tab)" (mouseleave)="hoverOverTab(TabType.None)">{{tabTitles[tab]}}</a>
</div>
</div>
<div id="selected-content" class="rounded-bottom text-offwhite">
- <div id="searchbar">
- <div id="path" class="ps-2">{{folderName}}
+ <div id="searchbar" *ngIf="listView">
+ <!-- <div id="path" class="ps-2">{{folderName}}
</div>
- <mat-icon>keyboard_arrow_right</mat-icon>
- <div id="search" class="text-offwhite">
+ <mat-icon>keyboard_arrow_right</mat-icon> -->
+ <div id="search" class="text-offwhite mx-1">
<mat-form-field>
<button matPrefix class="btn-clear input-icon"><mat-icon>search</mat-icon></button>
<input type="search" matInput name="search" [(ngModel)]="searchTerm" (input)="searchTermsChanged()">
@@ -40,9 +43,9 @@
<button class="btn-clear icon-toggle" data-bs-toggle="collapse" data-bs-target="#collapseSort" aria-expanded="false" aria-controls="collapseSort">
<mat-icon>sort</mat-icon>
</button>
- <button class="btn-clear icon-toggle separator" [ngClass]="{'icon-toggle-on': listView}" (click)="toggleListView()">
+ <!-- <button class="btn-clear icon-toggle separator" [ngClass]="{'icon-toggle-on': listView}" (click)="toggleListView()">
<mat-icon>view_list</mat-icon>
- </button>
+ </button> -->
</div>
</div>
<!--{{fileToDisplay ? fileToDisplay.name : 'No file selected.'}} {{selectedFileIndex}} {{hoveringOverFileIndex}}-->
@@ -59,7 +62,7 @@
<mat-icon>zoom_out_map</mat-icon>
</button>
</div>
- <app-form-model [model]="fileToDisplay" *ngSwitchCase="FolderType.Model"></app-form-model>
+ <app-form-model [forExperiment]="forExperiment" [model]="fileToDisplay" *ngSwitchCase="FolderType.Model"></app-form-model>
<app-form-dataset *ngSwitchCase="FolderType.Dataset" ></app-form-dataset>
</div>
<div *ngSwitchCase="true" class="list-view">
diff --git a/frontend/src/app/_elements/folder/folder.component.ts b/frontend/src/app/_elements/folder/folder.component.ts
index 80633300..06b4d893 100644
--- a/frontend/src/app/_elements/folder/folder.component.ts
+++ b/frontend/src/app/_elements/folder/folder.component.ts
@@ -6,7 +6,9 @@ import { DatasetsService } from 'src/app/_services/datasets.service';
import shared from 'src/app/Shared';
import { ModelsService } from 'src/app/_services/models.service';
import { FormDatasetComponent } from '../form-dataset/form-dataset.component';
-
+import Experiment from 'src/app/_data/Experiment';
+import { ExperimentsService } from 'src/app/_services/experiments.service';
+import { PredictorsService } from 'src/app/_services/predictors.service';
@Component({
selector: 'app-folder',
@@ -25,6 +27,8 @@ export class FolderComponent implements OnInit {
@Input() type: FolderType = FolderType.Dataset;
+ @Input() forExperiment?: Experiment;
+
newFileSelected: boolean = true;
selectedFileIndex: number = -1;
@@ -38,13 +42,17 @@ export class FolderComponent implements OnInit {
searchTerm: string = '';
- myDatasets : Dataset[] = [];
-
- constructor(private datasets: DatasetsService, private modelsService: ModelsService) {
+ constructor(private datasetsService: DatasetsService, private experimentsService: ExperimentsService, private modelsService: ModelsService, private predictorsService: PredictorsService) {
//PLACEHOLDER
+ this.forExperiment = new Experiment();
+ this.forExperiment.inputColumns = ['kolona1', 'kol2', '???', 'test'];
+
+ this.folders[TabType.File] = [];
+ this.folders[TabType.NewFile] = [];
this.refreshFiles();
+
}
ngOnInit(): void {
@@ -78,7 +86,6 @@ export class FolderComponent implements OnInit {
if (!this.newFile) {
this.createNewFile();
}
- this.selectedFileIndex = -1;
this.fileToDisplay = this.newFile;
this.selectedFile = this.newFile;
this.newFileSelected = true;
@@ -88,7 +95,6 @@ export class FolderComponent implements OnInit {
}
selectFile(index: number) {
- this.selectedFileIndex = index;
this.selectedFile = this.filteredFiles[index];
this.fileToDisplay = this.filteredFiles[index];
this.newFileSelected = false;
@@ -110,11 +116,34 @@ export class FolderComponent implements OnInit {
}
refreshFiles(){
- this.datasets.getMyDatasets().subscribe((datasets) => {
- this.myDatasets = datasets;
- this.files = this.myDatasets;
- this.searchTermsChanged();
+ this.datasetsService.getMyDatasets().subscribe((datasets) => {
+ this.folders[TabType.MyDatasets] = datasets;
+ });
+
+ this.datasetsService.getPublicDatasets().subscribe((datasets) => {
+ this.folders[TabType.PublicDatasets] = datasets;
+ });
+
+ this.modelsService.getMyModels().subscribe((models) => {
+ this.folders[TabType.MyModels] = models;
});
+
+ /*this.modelsService.getMyModels().subscribe((models) => {
+ this.folders[TabType.PublicModels] = models;
+ });*/
+ this.folders[TabType.PublicModels] = [];
+
+ this.experimentsService.getMyExperiments().subscribe((experiments) => {
+ this.folders[TabType.MyExperiments] = experiments;
+ });
+
+ this.files = [];
+
+ this.filteredFiles.length = 0;
+ this.filteredFiles.push(...this.files);
+
+ this.searchTermsChanged();
+
}
saveNewFile() {
@@ -122,7 +151,7 @@ export class FolderComponent implements OnInit {
this.formDataset!.uploadDataset();
}
- calcZIndex(i: number) {
+ /*calcZIndex(i: number) {
let zIndex = (this.files.length - i - 1)
if (this.selectedFileIndex == i)
zIndex = this.files.length + 2;
@@ -133,7 +162,7 @@ export class FolderComponent implements OnInit {
newFileZIndex() {
return (this.files.length + 1);
- }
+ }*/
clearSearchTerm() {
this.searchTerm = '';
@@ -164,10 +193,84 @@ export class FolderComponent implements OnInit {
console.log('delete');
}
+ folders: { [tab: number]: FolderFile[] } = {};
+
+ tabTitles: { [tab: number]: string } = {
+ [TabType.File]: 'Fajl',
+ [TabType.NewFile]: 'Novi fajl',
+ [TabType.MyDatasets]: 'Moji izvori podataka',
+ [TabType.PublicDatasets]: 'Javni izvori podataka',
+ [TabType.MyModels]: 'Moje konfiguracije neuronske mreže',
+ [TabType.PublicModels]: 'Javne konfiguracije neuronske mreže',
+ [TabType.MyExperiments]: 'Eksperimenti',
+ };
+
FolderType = FolderType;
+
+ TabType = TabType;
+
+ @Input() tabsToShow: TabType[] = [
+ TabType.MyDatasets,
+ TabType.PublicDatasets,
+ TabType.MyModels,
+ TabType.PublicModels,
+ TabType.MyExperiments,
+ TabType.File
+ ]
+
+ @Input() selectedTab: TabType = TabType.NewFile;
+ hoverTab: TabType = TabType.None;
+
+ selectTab(tab: TabType) {
+ this.checkListView(tab);
+ this.selectedTab = tab;
+ this.files = this.folders[tab];
+
+ this.searchTermsChanged();
+ }
+
+ checkListView(tab: TabType) {
+ switch (tab) {
+ case TabType.File:
+ case TabType.NewFile:
+ case TabType.None:
+ this.listView = false;
+ break;
+ case TabType.MyExperiments:
+ case TabType.MyDatasets:
+ case TabType.MyModels:
+ case TabType.PublicDatasets:
+ case TabType.PublicModels:
+ this.listView = true;
+ break;
+ }
+ }
+
+ hoverOverTab(tab: TabType) {
+ this.checkListView(tab);
+ this.hoverTab = tab;
+ if (tab == TabType.None) {
+ this.checkListView(this.selectedTab);
+ this.files = this.folders[this.selectedTab];
+ } else {
+ this.files = this.folders[tab];
+ }
+ this.searchTermsChanged();
+ }
}
export enum Privacy {
Private,
Public
+}
+
+export enum TabType {
+ NewFile,
+ File,
+ MyDatasets,
+ PublicDatasets,
+ MyModels,
+ PublicModels,
+ MyExperiments,
+ None
} \ No newline at end of file
diff --git a/frontend/src/app/_elements/form-dataset/form-dataset.component.html b/frontend/src/app/_elements/form-dataset/form-dataset.component.html
index c7aebd07..2176b130 100644
--- a/frontend/src/app/_elements/form-dataset/form-dataset.component.html
+++ b/frontend/src/app/_elements/form-dataset/form-dataset.component.html
@@ -30,7 +30,7 @@
<div class="row">
<mat-form-field class="example-full-width" appearance="fill">
<mat-label>Naziv</mat-label>
- <input type="text" matInput value="{{dataset.name}}">
+ <input type="text" matInput value="{{dataset?.name}}">
<!--[formControl]="nameFormControl"-->
<mat-error *ngIf="nameFormControl.hasError('required')">
diff --git a/frontend/src/app/_elements/form-model/form-model.component.html b/frontend/src/app/_elements/form-model/form-model.component.html
index f11b609d..76601465 100644
--- a/frontend/src/app/_elements/form-model/form-model.component.html
+++ b/frontend/src/app/_elements/form-model/form-model.component.html
@@ -90,17 +90,17 @@
<!--kraj unosa parametara-->
<hr>
<div class="m-2">
- <app-graph [model]="newModel" [inputCols]="newModel.inputColNum"></app-graph>
+ <app-graph [model]="newModel" [inputColumns]="forExperiment?.inputColumns"></app-graph>
</div>
<div class="ns-row">
<div class="ns-col" id="layers-control">
<div>Broj Skrivenih Slojeva</div>
- <button class="btn-clear btn-icon" (click)="addLayer()">
+ <button class="btn-clear btn-icon bubble" (click)="addLayer()">
<mat-icon>add</mat-icon>
</button>
<div>{{newModel.hiddenLayers}}</div>
- <button class="btn-clear btn-icon" (click)="removeLayer()">
+ <button class="btn-clear btn-icon bubble" (click)="removeLayer()">
<mat-icon>remove</mat-icon>
</button>
@@ -120,8 +120,8 @@
<div class="ns-col">
<mat-form-field appearance="fill" class="mat-fix">
- <mat-label>Broj Neurona svih slojeva</mat-label>
- <input matInput type="number" [(ngModel)]="selectedNumberOfNeurons" (change)="changeAllNumberOfNeurons()">
+ <mat-label>Broj neurona svih slojeva</mat-label>
+ <input matInput type="number" min="1" max="18" [(ngModel)]="selectedNumberOfNeurons" (change)="changeAllNumberOfNeurons()">
</mat-form-field>
</div>
<div class="break-2"></div>
@@ -172,11 +172,11 @@
<div class="d-flex flex-row align-items-center justify-content-center tm">
<div class="col-6" style="font-size: 13px;">Broj čvorova</div>
- <button class="btn-clear btn-icon" (click)="addNeuron(i)">
+ <button class="btn-clear btn-icon bubble" (click)="addNeuron(i)">
<mat-icon>add</mat-icon>
</button>
<div class="col-2 text-center">{{newModel.layers[i].neurons}}</div>
- <button class="btn-clear btn-icon" (click)="removeNeuron(i)">
+ <button class="btn-clear btn-icon bubble" (click)="removeNeuron(i)">
<mat-icon>remove</mat-icon>
</button>
</div>
diff --git a/frontend/src/app/_elements/form-model/form-model.component.ts b/frontend/src/app/_elements/form-model/form-model.component.ts
index 062c380e..2c78cd56 100644
--- a/frontend/src/app/_elements/form-model/form-model.component.ts
+++ b/frontend/src/app/_elements/form-model/form-model.component.ts
@@ -60,7 +60,7 @@ export class FormModelComponent implements AfterViewInit {
showMyModels: boolean = true;
updateGraph() {
- console.log(this.newModel.layers);
+ //console.log(this.newModel.layers);
this.graph.update();
}
@@ -73,7 +73,7 @@ export class FormModelComponent implements AfterViewInit {
}
addLayer() {
if (this.newModel.hiddenLayers < 128) {
- this.newModel.layers.push(new Layer(this.newModel.layers.length));
+ this.newModel.layers.push(new Layer(this.newModel.layers.length, this.selectedActivation, this.selectedNumberOfNeurons, this.selectedRegularisation, this.selectedRegularisationRate));
this.newModel.hiddenLayers += 1;
this.updateGraph();
@@ -98,7 +98,7 @@ export class FormModelComponent implements AfterViewInit {
}
}
addNeuron(index: number) {
- if (this.newModel.layers[index].neurons < 100) {
+ if (this.newModel.layers[index].neurons < 18) {
this.newModel.layers[index].neurons += 1;
this.updateGraph();
}
@@ -106,37 +106,33 @@ export class FormModelComponent implements AfterViewInit {
selectedActivation: ActivationFunction = ActivationFunction.Sigmoid;
selectedRegularisationRate: RegularisationRate = RegularisationRate.RR1;
selectedRegularisation: Regularisation = Regularisation.L1;
- selectedNumberOfNeurons:number=1;
+ selectedNumberOfNeurons: number = 3;
+
+ changeAllActivation() {
+ for (let i = 0; i < this.newModel.layers.length; i++) {
+ this.newModel.layers[i].activationFunction = this.selectedActivation;
- changeAllActivation(){
- for(let i=0;i<this.newModel.layers.length;i++)
- {
- this.newModel.layers[i].activationFunction=this.selectedActivation;
-
}
-
+
}
- changeAllRegularisation(){
- for(let i=0;i<this.newModel.layers.length;i++)
- {
- this.newModel.layers[i].regularisation=this.selectedRegularisation;
+ changeAllRegularisation() {
+ for (let i = 0; i < this.newModel.layers.length; i++) {
+ this.newModel.layers[i].regularisation = this.selectedRegularisation;
}
}
- changeAllRegularisationRate(){
+ changeAllRegularisationRate() {
- for(let i=0;i<this.newModel.layers.length;i++)
- {
- this.newModel.layers[i].regularisationRate=this.selectedRegularisationRate;
+ for (let i = 0; i < this.newModel.layers.length; i++) {
+ this.newModel.layers[i].regularisationRate = this.selectedRegularisationRate;
}
}
- changeAllNumberOfNeurons(){
- for(let i=0;i<this.newModel.layers.length;i++)
- {
- this.newModel.layers[i].neurons=this.selectedNumberOfNeurons;
+ changeAllNumberOfNeurons() {
+ for (let i = 0; i < this.newModel.layers.length; i++) {
+ this.newModel.layers[i].neurons = this.selectedNumberOfNeurons;
this.updateGraph();
}
}
-
-
-
+
+
+
}
diff --git a/frontend/src/app/_elements/graph/graph.component.css b/frontend/src/app/_elements/graph/graph.component.css
index e69de29b..361e7249 100644
--- a/frontend/src/app/_elements/graph/graph.component.css
+++ b/frontend/src/app/_elements/graph/graph.component.css
@@ -0,0 +1,17 @@
+.node-text {
+ position: absolute;
+ color: transparent;
+ width: 100px;
+ height: 40px;
+ text-align: center;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ /*border: 1px solid red;*/
+ transform: translate(-50%, -50%);
+}
+
+.node-text:hover {
+ color: var(--offwhite);
+} \ No newline at end of file
diff --git a/frontend/src/app/_elements/graph/graph.component.html b/frontend/src/app/_elements/graph/graph.component.html
index b8220115..19e5c14a 100644
--- a/frontend/src/app/_elements/graph/graph.component.html
+++ b/frontend/src/app/_elements/graph/graph.component.html
@@ -1,3 +1,8 @@
-<div #graphWrapper class="w-100" style="height: 14rem;">
+<div #graphWrapper class="w-100 position-relative" style="height: 14rem;">
+ <ng-container *ngFor="let layer of layers; let i = index">
+ <div class="node-text" *ngFor="let node of layer; let j = index" [style.left.%]="node.x * 99.4" [style.top.%]="node.y * 100">
+ {{ i == 0 ? (inputColumns ? inputColumns[j] : 'nepoznato') : (i > 0 && i
+ < layers.length - 1 ? model!.layers[i-1].activationFunction : (i==layers.length - 1 ? 'out' : '')) }} </div>
+ </ng-container>
<canvas #graphCanvas></canvas>
-</div> \ No newline at end of file
+ </div> \ No newline at end of file
diff --git a/frontend/src/app/_elements/graph/graph.component.ts b/frontend/src/app/_elements/graph/graph.component.ts
index 5dec3152..31814c2c 100644
--- a/frontend/src/app/_elements/graph/graph.component.ts
+++ b/frontend/src/app/_elements/graph/graph.component.ts
@@ -1,5 +1,6 @@
import { AfterViewInit, Component, ElementRef, Input, OnInit, ViewChild } from '@angular/core';
-import Dataset from 'src/app/_data/Dataset';
+import { RgbColor } from '@syncfusion/ej2-angular-heatmap';
+import Dataset, { ColumnInfo } from 'src/app/_data/Dataset';
import Model, { Layer } from 'src/app/_data/Model';
@Component({
@@ -15,18 +16,19 @@ export class GraphComponent implements AfterViewInit {
canvas!: ElementRef;
@Input() model?: Model;
- @Input() inputCols: number = 1;
+ //@Input() inputCols: number = 1;
@Input() lineThickness: number = 2;
@Input() nodeRadius: number = 15;
- @Input() lineColor: string = '#00a8e8';
+ @Input() lineColor1: RgbColor = new RgbColor(0, 168, 232);
+ @Input() lineColor2: RgbColor = new RgbColor(0, 70, 151);
@Input() nodeColor: string = '#222277';
@Input() borderColor: string = '#00a8e8';
@Input() inputNodeColor: string = '#00a8e8';
@Input() outputNodeColor: string = '#dfd7d7';
private ctx!: CanvasRenderingContext2D;
- @Input() inputNeurons: number = 1;
+ @Input() inputColumns?: string[] = [];
constructor() { }
@@ -43,16 +45,16 @@ export class GraphComponent implements AfterViewInit {
this.resize();
}
- layers?: Node[][];
+ layers: Node[][] = [];
update() {
- this.layers = [];
+ this.layers.length = 0;
let inputNodeIndex = 0;
const inputLayer: Node[] = [];
- while (inputNodeIndex < this.inputCols) {
+ while (this.inputColumns && inputNodeIndex < this.inputColumns.length) {
const x = 0.5 / (this.model!.hiddenLayers + 2);
- const y = (inputNodeIndex + 0.5) / this.inputCols;
+ const y = (inputNodeIndex + 0.5) / this.inputColumns.length;
const node = new Node(x, y, this.inputNodeColor);
inputLayer.push(node);
inputNodeIndex += 1;
@@ -94,27 +96,36 @@ export class GraphComponent implements AfterViewInit {
}
for (let layer of this.layers!) {
- for (let node of layer) {
- this.drawNode(node);
- }
+ layer.forEach((node, index) => {
+ this.drawNode(node, 0.5 / layer.length + 0.5);
+ });
}
}
+ bezierOffset = 5;
+
drawLine(node1: Node, node2: Node) {
- this.ctx.strokeStyle = this.lineColor;
+ const lineColor: RgbColor = this.lerpColor(this.lineColor1, this.lineColor2, node1.y);
+ this.ctx.strokeStyle = `rgb(${lineColor.R}, ${lineColor.G}, ${lineColor.B})`;
this.ctx.lineWidth = this.lineThickness;
this.ctx.beginPath();
this.ctx.moveTo(node1.x * this.width, node1.y * this.height);
- this.ctx.lineTo(node2.x * this.width, node2.y * this.height);
+ //this.ctx.lineTo(node2.x * this.width, node2.y * this.height);
+ const middle = (node1.x + (node2.x - node1.x) / 2) * this.width;
+ this.ctx.bezierCurveTo(
+ middle, node1.y * this.height,
+ middle, node2.y * this.height,
+ node2.x * this.width, node2.y * this.height);
this.ctx.stroke();
}
- drawNode(node: Node) {
+ drawNode(node: Node, sizeMult: number) {
+ const lineColor: RgbColor = this.lerpColor(this.lineColor1, this.lineColor2, node.y);
+ this.ctx.strokeStyle = `rgb(${lineColor.R}, ${lineColor.G}, ${lineColor.B})`;
this.ctx.fillStyle = node.color;
- this.ctx.strokeStyle = this.borderColor;
this.ctx.lineWidth = this.lineThickness;
this.ctx.beginPath();
- this.ctx.arc(node.x * this.width, node.y * this.height, this.nodeRadius, 0, 2 * Math.PI);
+ this.ctx.arc(node.x * this.width, node.y * this.height, this.nodeRadius * sizeMult, 0, 2 * Math.PI);
this.ctx.fill();
this.ctx.stroke();
}
@@ -135,6 +146,16 @@ export class GraphComponent implements AfterViewInit {
this.draw();
}
+
+ lerpColor(value1: RgbColor, value2: RgbColor, amount: number): RgbColor {
+ const newColor = new RgbColor(0, 0, 0);
+ amount = amount < 0 ? 0 : amount;
+ amount = amount > 1 ? 1 : amount;
+ newColor.R = value1.R + (value2.R - value1.R) * amount;
+ newColor.G = value1.G + (value2.G - value1.G) * amount;
+ newColor.B = value1.B + (value2.B - value1.B) * amount;
+ return newColor;
+ };
}
class Node {