From dd6d756233fffc471ddf3c66ee678cfab86229fb Mon Sep 17 00:00:00 2001 From: TAMARA JERINIC Date: Mon, 23 May 2022 00:52:30 +0200 Subject: Dodat datum kreiranja prediktora u arhivu i margina u form-model. --- frontend/src/app/_elements/folder/folder.component.html | 2 +- frontend/src/app/_elements/form-model/form-model.component.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'frontend/src/app/_elements') diff --git a/frontend/src/app/_elements/folder/folder.component.html b/frontend/src/app/_elements/folder/folder.component.html index a557edde..52f19753 100644 --- a/frontend/src/app/_elements/folder/folder.component.html +++ b/frontend/src/app/_elements/folder/folder.component.html @@ -105,7 +105,7 @@
- {{predictor.lastUpdated | date}} + {{predictor.dateCreated| date}}
+ +
\ No newline at end of file diff --git a/frontend/src/app/_modals/update-experiment-dialog/update-experiment-dialog.component.spec.ts b/frontend/src/app/_modals/update-experiment-dialog/update-experiment-dialog.component.spec.ts new file mode 100644 index 00000000..e0f26b2c --- /dev/null +++ b/frontend/src/app/_modals/update-experiment-dialog/update-experiment-dialog.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { UpdateExperimentDialogComponent } from './update-experiment-dialog.component'; + +describe('UpdateExperimentDialogComponent', () => { + let component: UpdateExperimentDialogComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ UpdateExperimentDialogComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(UpdateExperimentDialogComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/frontend/src/app/_modals/update-experiment-dialog/update-experiment-dialog.component.ts b/frontend/src/app/_modals/update-experiment-dialog/update-experiment-dialog.component.ts new file mode 100644 index 00000000..068aa2ef --- /dev/null +++ b/frontend/src/app/_modals/update-experiment-dialog/update-experiment-dialog.component.ts @@ -0,0 +1,68 @@ +import { Component, Inject, OnInit } from '@angular/core'; +import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; +import Experiment from 'src/app/_data/Experiment'; +import { ExperimentsService } from 'src/app/_services/experiments.service'; + +interface DialogData { + experiment: Experiment; + selectedOption: number; +} + +@Component({ + selector: 'app-update-experiment-dialog', + templateUrl: './update-experiment-dialog.component.html', + styleUrls: ['./update-experiment-dialog.component.css'] +}) +export class UpdateExperimentDialogComponent implements OnInit { + + selectedOption: number = 1; + selectedName: string = ''; + wrongAlreadyExists: boolean = false; + wrongEmptyName: boolean = false; + + constructor(public dialogRef: MatDialogRef, @Inject(MAT_DIALOG_DATA) public data: DialogData, private experimentService: ExperimentsService) { + this.wrongAlreadyExists = false; + this.wrongEmptyName = false; + } + + ngOnInit(): void { + } + + onNoClick() { + this.dialogRef.close(); + } + + saveWithEnterKey(keyboardEvent: KeyboardEvent) { + if (keyboardEvent.code == "Enter" || keyboardEvent.code == "NumpadEnter") + this.onYesClick(); + } + + onYesClick() { + if (this.selectedOption == 1) { //update + this.experimentService.updateExperiment(this.data.experiment).subscribe((response) => { + this.data.experiment = response; + this.dialogRef.close(this.data.experiment); + }); + } + else { //save new + if (this.selectedName == "") { + this.wrongEmptyName = true; + return; + } + this.wrongEmptyName = false; + + const newExperiment = new Experiment(); + Object.assign(newExperiment, this.data.experiment); + newExperiment.name = this.selectedName; + newExperiment._id = ''; + this.experimentService.addExperiment(newExperiment!).subscribe((response) => { + this.wrongAlreadyExists = false; + this.dialogRef.close(response); + }, (error) => { + if (error.error == "Experiment with this name exists") { + this.wrongAlreadyExists = true; + } + }); + } + } +} diff --git a/frontend/src/app/app.module.ts b/frontend/src/app/app.module.ts index 89d53115..e2823761 100644 --- a/frontend/src/app/app.module.ts +++ b/frontend/src/app/app.module.ts @@ -22,6 +22,7 @@ import { YesNoDialogComponent } from './_modals/yes-no-dialog/yes-no-dialog.comp import { EncodingDialogComponent } from './_modals/encoding-dialog/encoding-dialog.component'; import { MissingvaluesDialogComponent } from './_modals/missingvalues-dialog/missingvalues-dialog.component'; import { SaveExperimentDialogComponent } from './_modals/save-experiment-dialog/save-experiment-dialog.component'; +import { UpdateExperimentDialogComponent } from './_modals/update-experiment-dialog/update-experiment-dialog.component'; // Pages import { HomeComponent } from './_pages/home/home.component'; import { ProfileComponent } from './_pages/profile/profile.component'; @@ -93,7 +94,8 @@ export function initializeApp(appConfig: Configuration) { MetricViewComponent, LineChartComponent, SaveExperimentDialogComponent, - SpinnerComponent + SpinnerComponent, + UpdateExperimentDialogComponent ], imports: [ BrowserModule, -- cgit v1.2.3 From 7f587b3feeeb3f59666176ec1cbcd8f450fe590d Mon Sep 17 00:00:00 2001 From: Sonja Galovic Date: Wed, 25 May 2022 00:36:57 +0200 Subject: Dodata linija this.experiment._columnsSelected = true --- frontend/src/app/_elements/column-table/column-table.component.ts | 1 + 1 file changed, 1 insertion(+) (limited to 'frontend/src/app/_elements') 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 41153353..8398f7ef 100644 --- a/frontend/src/app/_elements/column-table/column-table.component.ts +++ b/frontend/src/app/_elements/column-table/column-table.component.ts @@ -378,6 +378,7 @@ export class ColumnTableComponent implements AfterViewInit { else Shared.openDialog("Izmena eksperimenta", "Uspešno ste izmenili podatke o eksperimentu."); Object.assign(this.experiment, experiment); + this.experiment._columnsSelected = true; this.experimentChanged.emit(); }); } -- cgit v1.2.3 From cc7a29e73371b4b8546a43e3f9115507557a5259 Mon Sep 17 00:00:00 2001 From: Ognjen Cirkovic Date: Wed, 25 May 2022 02:04:59 +0200 Subject: Dugmici za delete i download spusteni ispod forme. Dodat background-color da bi se lakse uocili. Napravljena class-a file-bootom-buttons-helper da ih pozicionira. --- .../src/app/_elements/folder/folder.component.css | 11 ++++++--- .../src/app/_elements/folder/folder.component.html | 27 +++++++++++++--------- 2 files changed, 24 insertions(+), 14 deletions(-) (limited to 'frontend/src/app/_elements') diff --git a/frontend/src/app/_elements/folder/folder.component.css b/frontend/src/app/_elements/folder/folder.component.css index 682fc645..810ad05d 100644 --- a/frontend/src/app/_elements/folder/folder.component.css +++ b/frontend/src/app/_elements/folder/folder.component.css @@ -184,9 +184,13 @@ } .file-bottom-buttons { - position: absolute; - bottom: 5px; - right: 4%; + position: relative; + position: relative; + top:-36px + +} +.file-bottom-buttons-helper{ + position: relative; display: flex; flex-direction: row-reverse; } @@ -196,6 +200,7 @@ color: var(--offwhite); border-radius: 4px; border: 1px solid var(--ns-primary); + background-color: var(--ns-bg-dark-50); margin: 5px; padding: 5px; cursor: pointer; diff --git a/frontend/src/app/_elements/folder/folder.component.html b/frontend/src/app/_elements/folder/folder.component.html index 52f19753..afb6085d 100644 --- a/frontend/src/app/_elements/folder/folder.component.html +++ b/frontend/src/app/_elements/folder/folder.component.html @@ -58,17 +58,6 @@
-
- - - -
@@ -160,4 +149,20 @@
+
+
+
+ + +
+ +
+
+ \ No newline at end of file -- cgit v1.2.3 From e20385c4adcfc966f33345060f05af9bb41c3c78 Mon Sep 17 00:00:00 2001 From: Ognjen Cirkovic Date: Wed, 25 May 2022 20:37:09 +0200 Subject: Ispravljen bug ukoliko korisnik brzo dvaput klikne da sacuva dataset. I onda se dataset dvaput obradjuje i dva se dodaju u kolekciju sa istim nazivom. --- frontend/src/app/_elements/folder/folder.component.html | 2 +- frontend/src/app/_elements/folder/folder.component.ts | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'frontend/src/app/_elements') diff --git a/frontend/src/app/_elements/folder/folder.component.html b/frontend/src/app/_elements/folder/folder.component.html index afb6085d..54444e95 100644 --- a/frontend/src/app/_elements/folder/folder.component.html +++ b/frontend/src/app/_elements/folder/folder.component.html @@ -115,7 +115,7 @@ 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 8398f7ef..8d2875a5 100644 --- a/frontend/src/app/_elements/column-table/column-table.component.ts +++ b/frontend/src/app/_elements/column-table/column-table.component.ts @@ -7,7 +7,7 @@ import { MatDialog } from '@angular/material/dialog'; import { MissingvaluesDialogComponent } from 'src/app/_modals/missingvalues-dialog/missingvalues-dialog.component'; import { MatCheckboxChange } from '@angular/material/checkbox'; import { CsvParseService } from 'src/app/_services/csv-parse.service'; -import { ProblemType } from 'src/app/_data/Model'; +import { NullValReplacer, ProblemType } from 'src/app/_data/Model'; import { ExperimentsService } from 'src/app/_services/experiments.service'; import { SaveExperimentDialogComponent } from 'src/app/_modals/save-experiment-dialog/save-experiment-dialog.component'; import { AlertDialogComponent } from 'src/app/_modals/alert-dialog/alert-dialog.component'; @@ -181,8 +181,13 @@ export class ColumnTableComponent implements AfterViewInit { this.columnTableChanged.emit(); } - columnTypeChanged(columnName: string) { - if (this.experiment.outputColumn == columnName) + columnTypeChanged(columnName: string, colIndex: number) { + + this.experiment.nullValuesReplacers[colIndex].option = NullValueOptions.DeleteRows; + this.experiment.nullValuesReplacers[colIndex].value = ""; + this.nullValOption[colIndex] = "Obriši redove (" + this.dataset?.columnInfo[colIndex].numNulls + ")"; + + if (this.experiment.outputColumn == columnName) this.changeProblemType(); else this.columnTableChangeDetected(); -- cgit v1.2.3 From 1a5b7cc3cc03e47c559f52528e075d314b804932 Mon Sep 17 00:00:00 2001 From: Sonja Galovic Date: Wed, 25 May 2022 23:45:21 +0200 Subject: Text-overflow postavljen svuda gde treba. --- .../column-table/column-table.component.html | 26 ++++++++++++++-------- .../src/app/_elements/folder/folder.component.css | 17 ++++++++++---- .../src/app/_elements/folder/folder.component.html | 14 ++++++------ 3 files changed, 37 insertions(+), 20 deletions(-) (limited to 'frontend/src/app/_elements') 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 e970bfb4..d5273d59 100644 --- a/frontend/src/app/_elements/column-table/column-table.component.html +++ b/frontend/src/app/_elements/column-table/column-table.component.html @@ -27,7 +27,9 @@ #
- #{{i + 1}}  {{colInfo.columnName}} +
+ #{{i + 1}}  {{colInfo.columnName}} +
@@ -63,7 +65,9 @@ Kolona
- #{{i + 1}}  {{colInfo.columnName}} +
+ #{{i + 1}}  {{colInfo.columnName}} +
@@ -72,7 +76,7 @@ -
+
{{dataset.columnInfo[i].columnName}}
@@ -97,7 +101,9 @@ Naziv
- #{{i + 1}}  {{colInfo.columnName}} +
+ #{{i + 1}}  {{colInfo.columnName}} +
@@ -168,11 +174,13 @@
+
+
+ {{nullValOption[i]}} +
+ arrow_drop_down +
+ diff --git a/frontend/src/app/_elements/folder/folder.component.css b/frontend/src/app/_elements/folder/folder.component.css index 810ad05d..fe21e7b1 100644 --- a/frontend/src/app/_elements/folder/folder.component.css +++ b/frontend/src/app/_elements/folder/folder.component.css @@ -1,6 +1,5 @@ #folder { width: 100%; - } #tabs { @@ -186,10 +185,10 @@ .file-bottom-buttons { position: relative; position: relative; - top:-36px - + top: -36px } -.file-bottom-buttons-helper{ + +.file-bottom-buttons-helper { position: relative; display: flex; flex-direction: row-reverse; @@ -226,4 +225,14 @@ .highlight-exp { /*font-size: 16px;*/ font-weight: 700; +} + +.text-overflow { + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; +} + +.selected-file-tab { + max-width: 230px !important; } \ No newline at end of file diff --git a/frontend/src/app/_elements/folder/folder.component.html b/frontend/src/app/_elements/folder/folder.component.html index 54444e95..bf0bad10 100644 --- a/frontend/src/app/_elements/folder/folder.component.html +++ b/frontend/src/app/_elements/folder/folder.component.html @@ -13,8 +13,8 @@ {{tabTitles[tab]}}
-
@@ -105,7 +105,7 @@
-
+
@@ -152,17 +152,17 @@
- - -
+
- +
\ No newline at end of file -- cgit v1.2.3 From 305dac6f0e327a2582dc4f93e83794b5169d7c8f Mon Sep 17 00:00:00 2001 From: Danijel Anđelković Date: Wed, 25 May 2022 23:45:24 +0200 Subject: Popravio dosta bugova vezane za prebacivanje izmedju novog dataseta, i postojeceg dataseta, isto i za modele, u folderu. Popravio presporo prebacivanje sa jednog taba na drugi u folderu. Popravio pogresan tip stope normalizacije na backendu. --- .gitignore | 2 + backend/api/api/Models/Model.cs | 4 +- backend/api/api/Services/FillAnEmptyDb.cs | 36 ++--- .../src/app/_elements/folder/folder.component.html | 19 ++- .../src/app/_elements/folder/folder.component.ts | 160 ++++++++++++--------- .../_elements/form-model/form-model.component.html | 2 +- 6 files changed, 129 insertions(+), 94 deletions(-) (limited to 'frontend/src/app/_elements') diff --git a/.gitignore b/.gitignore index 247afbd9..e11b4739 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,5 @@ backend/microservice/api/__pycache__/ production/app/node_modules/ production/app/dist/ backend/microservice/api/temp/ +backend/microservice/Boston.csv +backend/microservice/diamonds.csv diff --git a/backend/api/api/Models/Model.cs b/backend/api/api/Models/Model.cs index bbbf201e..6278cf8a 100644 --- a/backend/api/api/Models/Model.cs +++ b/backend/api/api/Models/Model.cs @@ -44,7 +44,7 @@ namespace api.Models { - public Layer(int layerNumber, string activationFunction, int neurons, string regularisation, float regularisationRate) + public Layer(int layerNumber, string activationFunction, int neurons, string regularisation, string regularisationRate) { this.layerNumber = layerNumber; this.activationFunction = activationFunction; @@ -57,7 +57,7 @@ namespace api.Models public string activationFunction { get; set; } public int neurons { get; set; } public string regularisation { get; set; } - public float regularisationRate { get; set; } + public string regularisationRate { get; set; } } } diff --git a/backend/api/api/Services/FillAnEmptyDb.cs b/backend/api/api/Services/FillAnEmptyDb.cs index cd35dc78..c74de67d 100644 --- a/backend/api/api/Services/FillAnEmptyDb.cs +++ b/backend/api/api/Services/FillAnEmptyDb.cs @@ -117,10 +117,10 @@ namespace api.Services model.outputNeurons = 0; model.layers = new[] { - new Layer ( 0,"sigmoid", 3,"l1", 1f ), - new Layer ( 1,"sigmoid", 3,"l1", 1f ), - new Layer ( 2,"sigmoid", 3,"l1", 1f ), - new Layer ( 3,"sigmoid", 3,"l1", 1f ), + new Layer ( 0,"sigmoid", 3,"l1", "0" ), + new Layer ( 1,"sigmoid", 3,"l1", "0" ), + new Layer ( 2,"sigmoid", 3,"l1", "0" ), + new Layer ( 3,"sigmoid", 3,"l1", "0" ), }; model.outputLayerActivationFunction = "sigmoid"; model.metrics = new string[] { }; @@ -281,11 +281,11 @@ namespace api.Services model.outputNeurons = 0; model.layers = new[] { - new Layer ( 0,"softmax", 3,"l1", 3f ), - new Layer ( 1,"softmax", 3,"l1", 3f ), - new Layer ( 2,"softmax", 3,"l1", 3f ), - new Layer ( 3,"softmax", 3,"l1", 3f ), - new Layer ( 4,"softmax", 3,"l1", 3f ) + new Layer ( 0,"softmax", 3,"l1", "0" ), + new Layer ( 1,"softmax", 3,"l1", "0" ), + new Layer ( 2,"softmax", 3,"l1", "0" ), + new Layer ( 3,"softmax", 3,"l1", "0" ), + new Layer ( 4,"softmax", 3,"l1", "0" ) }; model.outputLayerActivationFunction = "softmax"; model.metrics = new string[] { }; @@ -435,9 +435,9 @@ namespace api.Services model.outputNeurons = 0; model.layers = new[] { - new Layer ( 0,"relu", 3,"l1", 1f ), - new Layer ( 1,"relu", 3,"l1", 1f ), - new Layer ( 2,"relu", 3,"l1", 1f ) + new Layer ( 0,"relu", 3,"l1", "0" ), + new Layer ( 1,"relu", 3,"l1", "0" ), + new Layer ( 2,"relu", 3,"l1", "0" ) }; model.outputLayerActivationFunction = "relu"; model.metrics = new string[] { }; @@ -593,10 +593,10 @@ namespace api.Services model.outputNeurons = 0; model.layers = new[] { - new Layer ( 0,"sigmoid", 3,"l1", 1f ), - new Layer ( 1,"sigmoid", 3,"l1", 1f ), - new Layer ( 2,"sigmoid", 3,"l1", 1f ), - new Layer ( 3,"sigmoid", 3,"l1", 1f ) + new Layer ( 0,"sigmoid", 3,"l1", "0" ), + new Layer ( 1,"sigmoid", 3,"l1", "0" ), + new Layer ( 2,"sigmoid", 3,"l1", "0" ), + new Layer ( 3,"sigmoid", 3,"l1", "0" ) }; model.outputLayerActivationFunction = "sigmoid"; model.metrics = new string[] { }; @@ -748,8 +748,8 @@ namespace api.Services model.outputNeurons = 0; model.layers = new[] { - new Layer ( 0,"relu", 3,"l1", 1f ), - new Layer ( 1,"relu", 3,"l1", 1f ) + new Layer ( 0,"relu", 3,"l1", "0" ), + new Layer ( 1,"relu", 3,"l1", "0" ) }; model.outputLayerActivationFunction = "relu"; model.metrics = new string[] { }; diff --git a/frontend/src/app/_elements/folder/folder.component.html b/frontend/src/app/_elements/folder/folder.component.html index afb6085d..ebee92d2 100644 --- a/frontend/src/app/_elements/folder/folder.component.html +++ b/frontend/src/app/_elements/folder/folder.component.html @@ -58,8 +58,13 @@
- - + + + + + +
@@ -105,7 +110,7 @@
-
+
@@ -152,17 +157,17 @@
- - -
+
- +
\ No newline at end of file diff --git a/frontend/src/app/_elements/folder/folder.component.ts b/frontend/src/app/_elements/folder/folder.component.ts index 93ef9043..de1dfae9 100644 --- a/frontend/src/app/_elements/folder/folder.component.ts +++ b/frontend/src/app/_elements/folder/folder.component.ts @@ -23,8 +23,10 @@ import isEqual from 'lodash.isequal'; }) export class FolderComponent implements AfterViewInit { - @ViewChild(FormDatasetComponent) formDataset!: FormDatasetComponent; - @ViewChild(FormModelComponent) formModel!: FormModelComponent; + @ViewChild('selectedDataset') formDataset!: FormDatasetComponent; + @ViewChild('selectedModel') formModel!: FormModelComponent; + @ViewChild('newDataset') formNewDataset!: FormDatasetComponent; + @ViewChild('newModel') formNewModel!: FormModelComponent; @Input() folderName: string = 'Moji podaci'; @Input() files!: FolderFile[] @@ -41,8 +43,6 @@ export class FolderComponent implements AfterViewInit { selectedFile?: FolderFile; hoveringOverFileIndex: number = -1; - fileToDisplay?: FolderFile; - @Output() selectedFileChanged: EventEmitter = new EventEmitter(); @Output() fileFromRoute: EventEmitter = new EventEmitter(); @Output() okPressed: EventEmitter = new EventEmitter(); @@ -68,59 +68,70 @@ export class FolderComponent implements AfterViewInit { } displayFile() { - if (this.type == FolderType.Dataset) { - this.formDataset.dataset = this.fileToDisplay; - this.formDataset.existingFlag = false; - } - else if (this.type == FolderType.Model) - this.formModel.newModel = this.fileToDisplay; - } - - hoverOverFile(i: number) { - /*this.hoveringOverFileIndex = i; - if (i != -1) { - this.fileToDisplay = this.files[i]; + if (this.newFileSelected) { + if (this.type == FolderType.Dataset) { + this.formNewDataset.dataset = this.newFile; + this.formNewDataset.existingFlag = false; + } + else if (this.type == FolderType.Model) + this.formNewModel.newModel = this.newFile; } else { - if (this.newFileSelected) { - this.fileToDisplay = this.newFile; - } else { - this.fileToDisplay = this.files[this.selectedFileIndex]; + if (this.type == FolderType.Dataset) { + this.formDataset.dataset = this.selectedFile; + this.formDataset.existingFlag = false; } + else if (this.type == FolderType.Model) + this.formModel.newModel = this.selectedFile; } - this.displayFile();*/ } selectNewFile() { if (!this.newFile) { this.createNewFile(); } - this.fileToDisplay = this.newFile; this.newFileSelected = true; this.listView = false; this.displayFile(); + + this.selectedTab = TabType.NewFile; + if (this.type == FolderType.Dataset) { - this.formDataset.clear(); + this.formNewDataset.clear(); } } selectFile(file?: FolderFile) { this.formDataset.resetPagging(); this.selectedFile = file; - Object.assign(this.lastFileData, this.selectedFile); - this.fileToDisplay = file; + this.updateLastFileData(file); if (this.type == FolderType.Experiment && file) { this.router.navigate(['/experiment/' + file._id]); } this.newFileSelected = false; this.listView = false; this.selectedFileChanged.emit(this.selectedFile); - this.selectTab(TabType.File); this.displayFile(); + this.selectedTab = TabType.File; + if (this.type == FolderType.Dataset) this.formDataset.loadExisting(); } + updateLastFileData(file: FolderFile | undefined) { + if (!file) return; + + Object.assign(this.lastFileData, file); + if (this.type == FolderType.Model) { + const lastModel = (this.lastFileData) + lastModel.layers = []; + (file).layers.forEach(layer => { + const clone = Object.assign({}, layer); + lastModel.layers.push(clone); + }) + } + } + goToExperimentPageWithPredictor(file: FolderFile, predictor: Predictor) { this.router.navigate(['/experiment/p/' + predictor._id]); } @@ -172,7 +183,7 @@ export class FolderComponent implements AfterViewInit { if (!this._initialized) { this.files = this.folders[this.startingTab]; this.filteredFiles = []; - this.selectTab(this.startingTab); + setTimeout(() => this.selectTab(this.startingTab)); this._initialized = true; } } @@ -238,7 +249,7 @@ export class FolderComponent implements AfterViewInit { this.loadingAction = true; switch (this.type) { case FolderType.Dataset: - this.formDataset!.uploadDataset((dataset: Dataset) => { + this.formNewDataset!.uploadDataset((dataset: Dataset) => { this.newFile = undefined; this.loadingAction = false; this.okPressed.emit(); @@ -250,7 +261,7 @@ export class FolderComponent implements AfterViewInit { }); break; case FolderType.Model: - this.formModel.newModel.type = this.formModel.forProblemType; + this.formNewModel.newModel.type = this.formModel.forProblemType; this.modelsService.addModel(this.formModel.newModel).subscribe(model => { this.newFile = undefined; this.loadingAction = false; @@ -300,10 +311,29 @@ export class FolderComponent implements AfterViewInit { onFileChange() { setTimeout(() => { - this.selectedFileHasChanges = !((this.selectedTab == TabType.NewFile) || isEqual(this.selectedFile, this.lastFileData)); + this.selectedFileHasChanges = !((this.selectedTab == TabType.NewFile) || this.checkFileDataEqualToLastFileData()); }); } + checkFileDataEqualToLastFileData() { + if (this.type == FolderType.Model) { + let layersEqual = true; + const oldModel = (this.lastFileData); + const selectedModel = (this.selectedFile) + const oldLayers = oldModel.layers; + oldModel.layers = selectedModel.layers; + const objEqual = isEqual(this.selectedFile, oldModel); + oldLayers.forEach((layer, index) => { + if (!isEqual(layer, selectedModel.layers[index])) { + layersEqual = false; + } + }); + return objEqual && layersEqual; + } else { + return isEqual(this.selectedFile, this.lastFileData); + } + } + updateFile() { const file = this.selectedFile; this.loadingAction = true; @@ -324,7 +354,7 @@ export class FolderComponent implements AfterViewInit { fileUpdatedSuccess() { this.loadingAction = false; this.selectedFileHasChanges = false; - Object.assign(this.lastFileData, this.selectedFile); + this.updateLastFileData(this.selectedFile); this.refreshFiles(); this.selectedFileChanged.emit(this.selectedFile); } @@ -336,16 +366,16 @@ export class FolderComponent implements AfterViewInit { case FolderType.Dataset: const dataset = file; Shared.openYesNoDialog("Obriši izvor podataka", "Eksperimenti i trenirani modeli nad ovim izvorom podataka će takođe biti obrisani, da li ste sigurni da želite da obrišete izvor: " + dataset.name + "?", () => { - if(this.selectedTab==TabType.MyDatasets){ - this.filteredFiles.splice(this.filteredFiles.indexOf(file), 1); - this.files.splice(this.files.indexOf(file), 1); + if (this.selectedTab == TabType.MyDatasets) { + this.filteredFiles.splice(this.filteredFiles.indexOf(file), 1); + this.files.splice(this.files.indexOf(file), 1); } this.loadingAction = true; this.datasetsService.deleteDataset(dataset).subscribe((response) => { this.loadingAction = false; - if(this.selectedTab==TabType.File){ + if (this.selectedTab == TabType.File) { this.refreshDatasets(null); - this.selectedFile=undefined!; + this.selectedFile = undefined!; setTimeout(() => { this.selectTab(TabType.MyDatasets); }); @@ -357,16 +387,16 @@ export class FolderComponent implements AfterViewInit { case FolderType.Model: const model = file; Shared.openYesNoDialog("Obriši konfiguraciju neuronske mreže", "Trenirani modeli za ovu konfiguraciju će takođe biti obrisani, da li ste sigurni da želite da obrišete konfiguraciju: " + model.name + "?", () => { - if(this.selectedTab==TabType.MyModels){ - this.filteredFiles.splice(this.filteredFiles.indexOf(file), 1); - this.files.splice(this.files.indexOf(file), 1); + if (this.selectedTab == TabType.MyModels) { + this.filteredFiles.splice(this.filteredFiles.indexOf(file), 1); + this.files.splice(this.files.indexOf(file), 1); } this.loadingAction = true; this.modelsService.deleteModel(file).subscribe((response) => { this.loadingAction = false; - if(this.selectedTab==TabType.File){ + if (this.selectedTab == TabType.File) { this.refreshModels(null); - this.selectedFile=undefined!; + this.selectedFile = undefined!; setTimeout(() => { this.selectTab(TabType.MyModels); }); @@ -389,20 +419,20 @@ export class FolderComponent implements AfterViewInit { } else { const experiment = file; Shared.openYesNoDialog("Obriši eksperiment", "Trenirani modeli za ovaj eksperiment će takođe biti obrisani, da li ste sigurni da želite da obrišete eksperiment: " + experiment.name + "?", () => { - if(this.selectedTab==TabType.MyExperiments){ - this.filteredFiles.splice(this.filteredFiles.indexOf(file), 1); - this.files.splice(this.files.indexOf(file), 1); + if (this.selectedTab == TabType.MyExperiments) { + this.filteredFiles.splice(this.filteredFiles.indexOf(file), 1); + this.files.splice(this.files.indexOf(file), 1); } this.loadingAction = true; this.experimentsService.deleteExperiment(experiment).subscribe((response) => { - this.loadingAction = false; - if(this.selectedTab==TabType.File){ - this.refreshExperiments(); - this.selectedFile=undefined!; - setTimeout(() => { - this.selectTab(TabType.MyExperiments); - }); - } + this.loadingAction = false; + if (this.selectedTab == TabType.File) { + this.refreshExperiments(); + this.selectedFile = undefined!; + setTimeout(() => { + this.selectTab(TabType.MyExperiments); + }); + } }); }); } @@ -489,21 +519,19 @@ export class FolderComponent implements AfterViewInit { hoverTab: TabType = TabType.None; selectTab(tab: TabType) { - setTimeout(() => { - if (tab == TabType.NewFile) { - this.selectNewFile(); - this.selectedFile=undefined!; - } - - this.listView = this.getListView(tab); - this.type = this.getFolderType(tab); - this.privacy = this.getPrivacy(tab); - this.selectedTab = tab; - this.files = this.folders[tab]; + if (tab == TabType.NewFile) { + this.selectNewFile(); + } else if (tab == TabType.File) { + this.selectFile(this.selectedFile); + } + this.listView = this.getListView(tab); + this.type = this.getFolderType(tab); + this.privacy = this.getPrivacy(tab); + this.selectedTab = tab; + this.files = this.folders[tab]; - if (tab !== TabType.File && tab !== TabType.NewFile) - this.searchTermsChanged(); - }); + if (tab !== TabType.File && tab !== TabType.NewFile) + this.searchTermsChanged(); } getListView(tab: TabType) { 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 1133eb52..9051a2d4 100644 --- a/frontend/src/app/_elements/form-model/form-model.component.html +++ b/frontend/src/app/_elements/form-model/form-model.component.html @@ -229,7 +229,7 @@ Stopa regularizacije - + {{ optionName }} -- cgit v1.2.3 From e32da78201f0c906553742a4b1aba96c2b252fe9 Mon Sep 17 00:00:00 2001 From: Ognjen Cirkovic Date: Thu, 26 May 2022 00:25:24 +0200 Subject: Ispravljen bag kada se one na stranicu kolekcija da se eksperimenti ne prikazuje dok se ne klikne da dugme eksperimenti. --- frontend/src/app/_elements/folder/folder.component.ts | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'frontend/src/app/_elements') diff --git a/frontend/src/app/_elements/folder/folder.component.ts b/frontend/src/app/_elements/folder/folder.component.ts index 5c8751eb..177ea403 100644 --- a/frontend/src/app/_elements/folder/folder.component.ts +++ b/frontend/src/app/_elements/folder/folder.component.ts @@ -172,7 +172,9 @@ export class FolderComponent implements AfterViewInit { if (!this._initialized) { this.files = this.folders[this.startingTab]; this.filteredFiles = []; - this.selectTab(this.startingTab); + setTimeout(()=>{ + this.selectTab(this.startingTab); + }); this._initialized = true; } } @@ -229,6 +231,8 @@ export class FolderComponent implements AfterViewInit { }) /* ------------------------------------------------ */ this.searchTermsChanged(); + if(this.selectedTab==TabType.MyExperiments) + this.selectTab(TabType.MyExperiments); }) }); }); @@ -352,6 +356,10 @@ export class FolderComponent implements AfterViewInit { this.selectTab(TabType.MyDatasets); }); } + if(this.archive) + { + this.refreshExperiments(); + } }); }) @@ -373,6 +381,10 @@ export class FolderComponent implements AfterViewInit { this.selectTab(TabType.MyModels); }); } + if(this.archive) + { + this.refreshExperiments(); + } }); }) -- cgit v1.2.3 From ec6816d0d9a737f9fe70ec8d77f15afcd4720354 Mon Sep 17 00:00:00 2001 From: TAMARA JERINIC Date: Thu, 26 May 2022 00:58:36 +0200 Subject: Ispravljen raspored prikaza metrika, svaka vrednost i odgovarajuća vrednost na validacionom skupu se prikazuju na pojedinačnom grafiku. Metrike su filtrirane u zavisnosti od tipa problema. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/microservice/api/newmlservice.py | 13 +- .../_charts/line-chart/line-chart.component.css | 12 +- .../_charts/line-chart/line-chart.component.html | 26 ++- .../_charts/line-chart/line-chart.component.ts | 249 +++++++++++++++++++-- .../metric-view/metric-view.component.html | 21 +- .../_pages/experiment/experiment.component.html | 7 +- .../app/_pages/experiment/experiment.component.ts | 7 +- 7 files changed, 285 insertions(+), 50 deletions(-) (limited to 'frontend/src/app/_elements') diff --git a/backend/microservice/api/newmlservice.py b/backend/microservice/api/newmlservice.py index 99e3cae5..943e18a1 100644 --- a/backend/microservice/api/newmlservice.py +++ b/backend/microservice/api/newmlservice.py @@ -1,3 +1,4 @@ +from cmath import nan from enum import unique from itertools import count import os @@ -374,13 +375,15 @@ def train(dataset, paramsModel,paramsExperiment,paramsDataset,callback): - classifier.compile(loss =paramsModel["lossFunction"] , optimizer =opt, metrics = ['accuracy','mae','mse']) + classifier.compile(loss =paramsModel["lossFunction"] , optimizer =opt, metrics = ['accuracy']) history=classifier.fit( x=x_train, y=y_train, epochs = paramsModel['epochs'],batch_size=int(paramsModel['batchSize']),callbacks=callback(x_test, y_test,paramsModel['_id']),validation_data=(x_val, y_val)) hist=history.history #plt.plot(hist['accuracy']) - #plt.show() + plt.plot(history.history['loss']) + plt.plot(history.history['val_loss']) + plt.show() y_pred=classifier.predict(x_test) y_pred=np.argmax(y_pred,axis=1) @@ -410,7 +413,7 @@ def train(dataset, paramsModel,paramsExperiment,paramsDataset,callback): #from ann_visualizer.visualize import ann_viz; #ann_viz(classifier, title="My neural network") - return filepath,[hist['loss'],hist['val_loss'],hist['accuracy'],hist['val_accuracy'],hist['mae'],hist['val_mae'],hist['mse'],hist['val_mse']] + return filepath,[hist['loss'],hist['val_loss'],hist['accuracy'],hist['val_accuracy'],[],[],[],[]] elif(problem_type=='binarni-klasifikacioni'): #print('*************************************************************************binarni') @@ -444,7 +447,7 @@ def train(dataset, paramsModel,paramsExperiment,paramsDataset,callback): classifier.add(tf.keras.layers.Dense(units=1, activation=paramsModel['outputLayerActivationFunction']))#izlazni sloj - classifier.compile(loss =paramsModel["lossFunction"] , optimizer =opt , metrics = ['accuracy','mae','mse']) + classifier.compile(loss =paramsModel["lossFunction"] , optimizer =opt , metrics = ['accuracy']) history=classifier.fit( x=x_train, y=y_train, epochs = paramsModel['epochs'],batch_size=int(paramsModel['batchSize']),callbacks=callback(x_test, y_test,paramsModel['_id']),validation_data=(x_val, y_val)) hist=history.history @@ -468,7 +471,7 @@ def train(dataset, paramsModel,paramsExperiment,paramsDataset,callback): logloss = float(sm.log_loss(y_test, y_pred)) """ - return filepath,[hist['loss'],hist['val_loss'],hist['accuracy'],hist['val_accuracy'],hist['mae'],hist['val_mae'],hist['mse'],hist['val_mse']] + return filepath,[hist['loss'],hist['val_loss'],hist['accuracy'],hist['val_accuracy'],[],[],[],[]] elif(problem_type=='regresioni'): reg=paramsModel['layers'][0]['regularisation'] 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..ea150b0f 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,17 @@ canvas{ width:100% !important; - height:90% !important; + height:100% !important; border: 1px solid var(--ns-primary); background-color: var(--ns-bg-dark-100); border-radius: 5px; - margin: 10px; + margin: 0; font-size: 11 !important; + padding: 10px; } - \ No newline at end of file +.ns-col{ + margin: 5px; +} +.hide{ + display: none; +} 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..e36d0dcf 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,24 @@ -
- - +
+
+
+ + +
+
+ + +
+
+
+
+ + +
+
+ + +
+ +
+
\ 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..acba7201 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,7 @@ -import { Component, AfterViewInit, ElementRef, ViewChild } from '@angular/core'; +import { Component, AfterViewInit, ElementRef, ViewChild, Input } from '@angular/core'; import { Chart } from 'chart.js'; +import Experiment from 'src/app/_data/Experiment'; +import Model, { ProblemType } from 'src/app/_data/Model'; @Component({ selector: 'app-line-chart', @@ -23,14 +25,18 @@ export class LineChartComponent implements AfterViewInit { wrapper!: ElementRef; @ViewChild('canvas') canvas!: ElementRef; - + @Input() experiment!:Experiment; constructor() { } 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.height = this.wrapper.nativeElement.offsetHeight; @@ -69,14 +75,69 @@ 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("myChartacc", { type: 'line', data: { @@ -92,7 +153,59 @@ export class LineChartComponent implements AfterViewInit { 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 + } + } + } + }, + scales: { + x: { + ticks: { + color: 'white' + }, + grid: { + color: "rgba(0, 99, 171, 0.5)" + }, + }, + y: { + beginAtZero: true, + ticks: { + color: 'white' + + }, + grid: { + color: "rgba(0, 99, 171, 0.5)" + } + } + }, + animation: { + duration: 0 + } + + } + }, + + ); + this.myChartLoss = new Chart("myChartloss", + { + type: 'line', + data: { + labels: this.dataEpoch, + datasets: [ { label: 'Loss', data: this.dataLOSS, @@ -103,16 +216,58 @@ export class LineChartComponent implements AfterViewInit { data: this.dataValLoss, borderWidth: 1 }, - { - label: 'MAE', - data: this.dataMAE, - 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: 'Val_MAE', - data: this.dataValMAE, - borderWidth: 1 + scales: { + x: { + ticks: { + color: 'white' + }, + grid: { + color: "rgba(0, 99, 171, 0.5)" + }, + }, + y: { + beginAtZero: true, + ticks: { + color: 'white' + + }, + grid: { + color: "rgba(0, 99, 171, 0.5)" + } + } + }, + animation: { + duration: 0 + } + + } + }, + + ); + this.myChartMse = new Chart("myChartmse", + { + type: 'line', + data: { + labels: this.dataEpoch, + datasets: [ { label: 'MSE', data: this.dataMSE, @@ -166,8 +321,72 @@ export class LineChartComponent implements AfterViewInit { } } - } + }, + ); + this.myChartMae = new Chart("myChartmae", + { + 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, + + plugins: { + legend: { + labels: { + // This more specific font property overrides the global property + color:'white', + font: { + size: 10 + } + } + } + }, + scales: { + x: { + ticks: { + color: 'white' + }, + grid: { + color: "rgba(0, 99, 171, 0.5)" + }, + }, + y: { + beginAtZero: true, + ticks: { + color: 'white' + + }, + grid: { + color: "rgba(0, 99, 171, 0.5)" + } + } + + }, + animation: { + duration: 0 + } + + } + }, + + ); + } } diff --git a/frontend/src/app/_elements/metric-view/metric-view.component.html b/frontend/src/app/_elements/metric-view/metric-view.component.html index 2ab0a425..139597f9 100644 --- a/frontend/src/app/_elements/metric-view/metric-view.component.html +++ b/frontend/src/app/_elements/metric-view/metric-view.component.html @@ -1,21 +1,2 @@ - - - + diff --git a/frontend/src/app/_pages/experiment/experiment.component.html b/frontend/src/app/_pages/experiment/experiment.component.html index 17a6539d..b11729a7 100644 --- a/frontend/src/app/_pages/experiment/experiment.component.html +++ b/frontend/src/app/_pages/experiment/experiment.component.html @@ -67,7 +67,12 @@
- + +
+
+
+
+
diff --git a/frontend/src/app/_pages/experiment/experiment.component.ts b/frontend/src/app/_pages/experiment/experiment.component.ts index ec4275fa..ff17500a 100644 --- a/frontend/src/app/_pages/experiment/experiment.component.ts +++ b/frontend/src/app/_pages/experiment/experiment.component.ts @@ -15,6 +15,7 @@ import { MetricViewComponent } from 'src/app/_elements/metric-view/metric-view.c import { ActivatedRoute, Router } from '@angular/router'; import { DatasetsService } from 'src/app/_services/datasets.service'; import { PredictorsService } from 'src/app/_services/predictors.service'; +import { LineChartComponent } from 'src/app/_elements/_charts/line-chart/line-chart.component'; @Component({ selector: 'app-experiment', @@ -33,7 +34,7 @@ export class ExperimentComponent implements AfterViewInit { @ViewChild("folderDataset") folderDataset!: FolderComponent; @ViewChild(ColumnTableComponent) columnTable!: ColumnTableComponent; @ViewChild("folderModel") folderModel!: FolderComponent; - @ViewChild("metricView") metricView!: MetricViewComponent; + @ViewChild(LineChartComponent) linechartComponent!: LineChartComponent; step1: boolean = false; step2: boolean = false; @@ -89,7 +90,7 @@ export class ExperimentComponent implements AfterViewInit { if (this.modelToTrain?._id == mId) { stat = stat.replace(/'/g, '"'); this.history.push(JSON.parse(stat)); - this.metricView.update(this.history,this.modelToTrain.epochs); + this.linechartComponent.updateAll(this.history,this.modelToTrain.epochs); } }); @@ -115,7 +116,7 @@ export class ExperimentComponent implements AfterViewInit { this.step3 = true; let numOfEpochsArray = Array.from({length: model.epochs}, (_, i) => i + 1); setTimeout(() => { - this.metricView.linechartComponent.update(numOfEpochsArray, predictor.metricsAcc, predictor.metricsLoss, predictor.metricsMae, predictor.metricsMse, predictor.metricsValAcc, predictor.metricsValLoss, predictor.metricsValMae, predictor.metricsValMse); + this.linechartComponent.update(numOfEpochsArray, predictor.metricsAcc, predictor.metricsLoss, predictor.metricsMae, predictor.metricsMse, predictor.metricsValAcc, predictor.metricsValLoss, predictor.metricsValMae, predictor.metricsValMse); }) }); }); -- cgit v1.2.3 From c6f1ca72c5ada7fc42985e129da362796883cb2f Mon Sep 17 00:00:00 2001 From: TAMARA JERINIC Date: Thu, 26 May 2022 17:21:32 +0200 Subject: Dodato imenovanje osa. --- .../_charts/line-chart/line-chart.component.css | 2 +- .../_charts/line-chart/line-chart.component.ts | 42 +++++++++++++++++++++- 2 files changed, 42 insertions(+), 2 deletions(-) (limited to 'frontend/src/app/_elements') 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 ea150b0f..7dbbde7a 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 @@ -7,7 +7,7 @@ canvas{ border-radius: 5px; margin: 0; font-size: 11 !important; - padding: 10px; + padding: 0; } .ns-col{ margin: 5px; 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 acba7201..2b97d6b4 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 @@ -159,7 +159,6 @@ export class LineChartComponent implements AfterViewInit { options: { responsive: true, maintainAspectRatio: true, - plugins: { legend: { labels: { @@ -179,6 +178,11 @@ export class LineChartComponent implements AfterViewInit { grid: { color: "rgba(0, 99, 171, 0.5)" }, + title: { + display: true, + text: 'Epoha', + color:"white" + } }, y: { beginAtZero: true, @@ -188,6 +192,11 @@ export class LineChartComponent implements AfterViewInit { }, grid: { color: "rgba(0, 99, 171, 0.5)" + }, + title: { + display: true, + text: 'Vrednost', + color:"white" } } @@ -200,6 +209,7 @@ export class LineChartComponent implements AfterViewInit { }, ); + if(this.experiment.type==ProblemType.BinaryClassification || this.experiment.type==ProblemType.MultiClassification){} this.myChartLoss = new Chart("myChartloss", { type: 'line', @@ -241,6 +251,11 @@ export class LineChartComponent implements AfterViewInit { grid: { color: "rgba(0, 99, 171, 0.5)" }, + title: { + display: true, + text: 'Epoha', + color:"white" + } }, y: { beginAtZero: true, @@ -250,6 +265,11 @@ export class LineChartComponent implements AfterViewInit { }, grid: { color: "rgba(0, 99, 171, 0.5)" + }, + title: { + display: true, + text: 'Vrednost', + color:"white" } } @@ -303,6 +323,11 @@ export class LineChartComponent implements AfterViewInit { grid: { color: "rgba(0, 99, 171, 0.5)" }, + title: { + display: true, + text: 'Epoha', + color:"white" + } }, y: { beginAtZero: true, @@ -312,6 +337,11 @@ export class LineChartComponent implements AfterViewInit { }, grid: { color: "rgba(0, 99, 171, 0.5)" + }, + title: { + display: true, + text: 'Vrednost', + color:"white" } } @@ -365,6 +395,11 @@ export class LineChartComponent implements AfterViewInit { grid: { color: "rgba(0, 99, 171, 0.5)" }, + title: { + display: true, + text: 'Epoha', + color:"white" + } }, y: { beginAtZero: true, @@ -374,6 +409,11 @@ export class LineChartComponent implements AfterViewInit { }, grid: { color: "rgba(0, 99, 171, 0.5)" + }, + title: { + display: true, + text: 'Vrednost', + color:"white" } } -- cgit v1.2.3 From 78a10dadf619e4d090d93e19f08f9e35bcbd5a6d Mon Sep 17 00:00:00 2001 From: Ivan Ljubisavljevic Date: Thu, 26 May 2022 21:29:26 +0200 Subject: Deaktiviran button za dodavanje csv-a kada se ucita postojeci csv --- .../src/app/_elements/form-dataset/form-dataset.component.html | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'frontend/src/app/_elements') 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 6194a1a8..2a956128 100644 --- a/frontend/src/app/_elements/form-dataset/form-dataset.component.html +++ b/frontend/src/app/_elements/form-dataset/form-dataset.component.html @@ -2,7 +2,11 @@
- +
@@ -38,7 +42,7 @@ file_upload - +
-- cgit v1.2.3 From d9f2acad56bc42a05ae9c0b4fd25827fb6cea374 Mon Sep 17 00:00:00 2001 From: Ivan Ljubisavljevic Date: Thu, 26 May 2022 22:07:42 +0200 Subject: Ispravljen bug sa OK dugmetom (kod ucitanog dataseta) --- .../src/app/_elements/folder/folder.component.css | 9 ++++-- .../src/app/_elements/folder/folder.component.html | 35 +++++++++++----------- .../notifications/notifications.component.html | 2 +- 3 files changed, 26 insertions(+), 20 deletions(-) (limited to 'frontend/src/app/_elements') diff --git a/frontend/src/app/_elements/folder/folder.component.css b/frontend/src/app/_elements/folder/folder.component.css index fe21e7b1..dd984918 100644 --- a/frontend/src/app/_elements/folder/folder.component.css +++ b/frontend/src/app/_elements/folder/folder.component.css @@ -184,14 +184,19 @@ .file-bottom-buttons { position: relative; - position: relative; - top: -36px + display: flex; + flex-direction: row-reverse; + height: 0; + } + .file-bottom-buttons-helper { position: relative; display: flex; flex-direction: row-reverse; + width: fit-content; + height: 45px; } .file-button { diff --git a/frontend/src/app/_elements/folder/folder.component.html b/frontend/src/app/_elements/folder/folder.component.html index bf0bad10..eed0eb1e 100644 --- a/frontend/src/app/_elements/folder/folder.component.html +++ b/frontend/src/app/_elements/folder/folder.component.html @@ -72,10 +72,10 @@
@@ -114,6 +114,21 @@
+
+
+
+ + +
+ +
+
-
-
-
- - -
- -
-
+ \ No newline at end of file diff --git a/frontend/src/app/_elements/notifications/notifications.component.html b/frontend/src/app/_elements/notifications/notifications.component.html index 3b2f4eaa..d3218a96 100644 --- a/frontend/src/app/_elements/notifications/notifications.component.html +++ b/frontend/src/app/_elements/notifications/notifications.component.html @@ -1,4 +1,4 @@ -
+

Notifikacije -- cgit v1.2.3 From fc704e582e633b7ae92cf185de7a52405b2a1fbb Mon Sep 17 00:00:00 2001 From: TAMARA JERINIC Date: Sun, 29 May 2022 19:01:03 +0200 Subject: Dodata komponenta form-predictor sa html i css fajlovima. --- .../form-predictor/form-predictor.component.css | 24 +++++++++++++ .../form-predictor/form-predictor.component.html | 32 +++++++++++++++++ .../form-predictor.component.spec.ts | 25 +++++++++++++ .../form-predictor/form-predictor.component.ts | 42 ++++++++++++++++++++++ 4 files changed, 123 insertions(+) create mode 100644 frontend/src/app/_elements/form-predictor/form-predictor.component.css create mode 100644 frontend/src/app/_elements/form-predictor/form-predictor.component.html create mode 100644 frontend/src/app/_elements/form-predictor/form-predictor.component.spec.ts create mode 100644 frontend/src/app/_elements/form-predictor/form-predictor.component.ts (limited to 'frontend/src/app/_elements') diff --git a/frontend/src/app/_elements/form-predictor/form-predictor.component.css b/frontend/src/app/_elements/form-predictor/form-predictor.component.css new file mode 100644 index 00000000..569a9887 --- /dev/null +++ b/frontend/src/app/_elements/form-predictor/form-predictor.component.css @@ -0,0 +1,24 @@ +th{ + margin-right: 5px; +} +.container{ + background-color: var(--ns-bg-dark-50); + border-radius: 10px; + border: 1px solid var(--ns-primary); + width: 100%; + height: 100%;} +#input{ + color: whitesmoke; + background-color: var(--ns-bg-dark-100); + margin-top: 10px; +} +h3{ + color: whitesmoke; +} +#output{ + background-color: var(--ns-bg-dark-100); + color:whitesmoke; +} +#output b{ + height: 50px; +} diff --git a/frontend/src/app/_elements/form-predictor/form-predictor.component.html b/frontend/src/app/_elements/form-predictor/form-predictor.component.html new file mode 100644 index 00000000..3ebb666c --- /dev/null +++ b/frontend/src/app/_elements/form-predictor/form-predictor.component.html @@ -0,0 +1,32 @@ +
+

+ Unesi vrednosti za predikciju +

+
+
+
+ +
+
+
+ +
+
+ +
+ + +
+ +
+ +
+
+ Izlazna vrednost za kolonu "output":"input" +
+ +
\ No newline at end of file diff --git a/frontend/src/app/_elements/form-predictor/form-predictor.component.spec.ts b/frontend/src/app/_elements/form-predictor/form-predictor.component.spec.ts new file mode 100644 index 00000000..f873e3af --- /dev/null +++ b/frontend/src/app/_elements/form-predictor/form-predictor.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { FormPredictorComponent } from './form-predictor.component'; + +describe('FormPredictorComponent', () => { + let component: FormPredictorComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ FormPredictorComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(FormPredictorComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/frontend/src/app/_elements/form-predictor/form-predictor.component.ts b/frontend/src/app/_elements/form-predictor/form-predictor.component.ts new file mode 100644 index 00000000..fbdce569 --- /dev/null +++ b/frontend/src/app/_elements/form-predictor/form-predictor.component.ts @@ -0,0 +1,42 @@ +import { Component, OnInit ,Input,Output, ViewChild} from '@angular/core'; +import Predictor from 'src/app/_data/Predictor'; +import {PredictorsService } from 'src/app/_services/predictors.service'; +import { ActivatedRoute } from '@angular/router'; +@Component({ + selector: 'app-form-predictor', + templateUrl: './form-predictor.component.html', + styleUrls: ['./form-predictor.component.css'] +}) +export class FormPredictorComponent implements OnInit { + inputs : Column[] = []; + + predictor?:Predictor ; + predictorsForExp: { [expId: string]: Predictor[] } = {} + predictorsService: any; + experimentsService: any; + folders: any; + constructor(private predictS : PredictorsService, private route: ActivatedRoute) { + + } + + ngOnInit(): void { + /* this.route.params.subscribe(url => { + console.log("**********************************************"); + this.predictS.getPredictor(url["id"]).subscribe(p => { + + this.predictor = p; + this.predictor.inputs.forEach((p,index)=> this.inputs[index] = new Column(p, "")); + }) + }); + } + +*/ +} + +} + +export class Column { + constructor( + public name : string, + public value : (number | string)){ + }} -- cgit v1.2.3 From 3f0e6c18174915ae245d30c93e6d9d8e15f31749 Mon Sep 17 00:00:00 2001 From: Danijel Anđelković Date: Fri, 3 Jun 2022 21:22:14 +0200 Subject: Promenio naslov "arhiva" u "kolekcije". Popravio bug sa dodavanjem modela. --- frontend/src/app/_elements/folder/folder.component.ts | 2 +- frontend/src/app/app-routing.module.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'frontend/src/app/_elements') diff --git a/frontend/src/app/_elements/folder/folder.component.ts b/frontend/src/app/_elements/folder/folder.component.ts index 451f16ef..fc3b98b2 100644 --- a/frontend/src/app/_elements/folder/folder.component.ts +++ b/frontend/src/app/_elements/folder/folder.component.ts @@ -268,7 +268,7 @@ export class FolderComponent implements AfterViewInit { break; case FolderType.Model: this.formNewModel.newModel.type = this.formModel.forProblemType; - this.modelsService.addModel(this.formModel.newModel).subscribe(model => { + this.modelsService.addModel(this.formNewModel.newModel).subscribe(model => { this.newFile = undefined; this.loadingAction = false; //Shared.openDialog("Obaveštenje", "Uspešno ste dodali novu konfiguraciju neuronske mreže u kolekciju."); diff --git a/frontend/src/app/app-routing.module.ts b/frontend/src/app/app-routing.module.ts index d5552ce9..507089a8 100644 --- a/frontend/src/app/app-routing.module.ts +++ b/frontend/src/app/app-routing.module.ts @@ -15,7 +15,7 @@ const routes: Routes = [ { path: 'experiment/p/:predictorId', component: ExperimentComponent, data: { title: 'Eksperiment' } }, { path: 'experiment/:id', component: ExperimentComponent, data: { title: 'Eksperiment' } }, { path: 'experiment', component: ExperimentComponent, data: { title: 'Eksperiment' } }, - { path: 'archive', component: ArchiveComponent, data: { title: 'Arhiva' } }, + { path: 'archive', component: ArchiveComponent, data: { title: 'Kolekcije' } }, { path: 'profile', component: ProfileComponent, canActivate: [AuthGuardService], data: { title: 'Profil' } }, { path: 'playground', component: PlaygroundComponent, data: { title: 'Zabava' } }, { path: 'test', component: TestComponent, data: { title: 'Test' } }, -- cgit v1.2.3 From d2dd01cb33a906d28f830b586c295231f3464c32 Mon Sep 17 00:00:00 2001 From: Danijel Anđelković Date: Fri, 3 Jun 2022 21:22:49 +0200 Subject: Pomerio funkciju za upload csv fajla u datasets service. --- .../form-dataset/form-dataset.component.ts | 4 +-- frontend/src/app/_services/datasets.service.ts | 29 ++++++++++++++++------ frontend/src/app/_services/models.service.ts | 15 ----------- 3 files changed, 24 insertions(+), 24 deletions(-) (limited to 'frontend/src/app/_elements') diff --git a/frontend/src/app/_elements/form-dataset/form-dataset.component.ts b/frontend/src/app/_elements/form-dataset/form-dataset.component.ts index 1a29f74e..8714ae7f 100644 --- a/frontend/src/app/_elements/form-dataset/form-dataset.component.ts +++ b/frontend/src/app/_elements/form-dataset/form-dataset.component.ts @@ -89,7 +89,7 @@ export class FormDatasetComponent { update() { this.firstInput = true; - if (this.files.length < 1){ + if (this.files.length < 1) { this.loadExisting(); return; } @@ -158,7 +158,7 @@ export class FormDatasetComponent { return; } - return this.modelsService.uploadData(this.files[0]).subscribe((file) => { + return this.datasetsService.uploadData(this.files[0]).subscribe((file) => { this.dataset._id = ""; this.dataset.fileId = file._id; this.dataset.uploaderId = shared.userId; diff --git a/frontend/src/app/_services/datasets.service.ts b/frontend/src/app/_services/datasets.service.ts index 2775613c..42fa5e55 100644 --- a/frontend/src/app/_services/datasets.service.ts +++ b/frontend/src/app/_services/datasets.service.ts @@ -1,4 +1,4 @@ -import { HttpClient } from '@angular/common/http'; +import { HttpClient, HttpParams } from '@angular/common/http'; import { Injectable } from '@angular/core'; import { Observable } from 'rxjs'; import { Configuration } from './configuration.service'; @@ -12,6 +12,21 @@ export class DatasetsService { constructor(private http: HttpClient, private authService: AuthService) { } + uploadData(file: File): Observable { + let formData = new FormData(); + formData.append('file', file, file.name); + + let params = new HttpParams(); + + const options = { + params: params, + reportProgress: false, + headers: this.authService.authHeader() + }; + + return this.http.post(`${Configuration.settings.apiURL}/file/csv`, formData, options); + } + getPublicDatasets(): Observable { return this.http.get(`${Configuration.settings.apiURL}/dataset/publicdatasets`, { headers: this.authService.authHeader() }); } @@ -31,10 +46,10 @@ export class DatasetsService { getDatasetFile(fileId: any): any { return this.http.get(`${Configuration.settings.apiURL}/file/csvRead/${fileId}/-1/11`, { headers: this.authService.authHeader(), responseType: 'text' }); } - getDatasetFilePaging(fileId:any,begin:any,end:any){ + getDatasetFilePaging(fileId: any, begin: any, end: any) { return this.http.get(`${Configuration.settings.apiURL}/file/csvRead/${fileId}/${begin}/${end}`, { headers: this.authService.authHeader(), responseType: 'text' }); } - getDatasetHeader(fileId:any){ + getDatasetHeader(fileId: any) { return this.http.get(`${Configuration.settings.apiURL}/file/csvRead/${fileId}/-1/1`, { headers: this.authService.authHeader(), responseType: 'text' }); } getDatasetFilePartial(fileId: any, startRow: number, rowNum: number): Observable { @@ -44,15 +59,15 @@ export class DatasetsService { return this.http.get(`${Configuration.settings.apiURL}/dataset/get/${datasetId}`, { headers: this.authService.authHeader() }); } - editDataset(dataset: Dataset){ - return this.http.put(`${Configuration.settings.apiURL}/dataset/` + dataset._id, dataset, { headers: this.authService.authHeader() ,responseType:'text'}); + editDataset(dataset: Dataset) { + return this.http.put(`${Configuration.settings.apiURL}/dataset/` + dataset._id, dataset, { headers: this.authService.authHeader(), responseType: 'text' }); } deleteDataset(dataset: Dataset) { return this.http.delete(`${Configuration.settings.apiURL}/dataset/` + dataset._id, { headers: this.authService.authHeader(), responseType: "text" }); } - downloadFile(id:string):Observable{ - return this.http.get(`${Configuration.settings.apiURL}/file/Download?id=`+id, { headers: this.authService.authHeader(), responseType: 'blob' }); + downloadFile(id: string): Observable { + return this.http.get(`${Configuration.settings.apiURL}/file/Download?id=` + id, { headers: this.authService.authHeader(), responseType: 'blob' }); } } diff --git a/frontend/src/app/_services/models.service.ts b/frontend/src/app/_services/models.service.ts index 2b8fe8f2..016fa9bc 100644 --- a/frontend/src/app/_services/models.service.ts +++ b/frontend/src/app/_services/models.service.ts @@ -13,21 +13,6 @@ export class ModelsService { constructor(private http: HttpClient, private authService: AuthService) { } - uploadData(file: File): Observable { - let formData = new FormData(); - formData.append('file', file, file.name); - - let params = new HttpParams(); - - const options = { - params: params, - reportProgress: false, - headers: this.authService.authHeader() - }; - - return this.http.post(`${Configuration.settings.apiURL}/file/csv`, formData, options); - } - addModel(model: Model): Observable { return this.http.post(`${Configuration.settings.apiURL}/model/add`, model, { headers: this.authService.authHeader() }); } -- cgit v1.2.3 From 854e21f08d1c876cf62c7a360bd5bd142675d705 Mon Sep 17 00:00:00 2001 From: Danijel Anđelković Date: Fri, 3 Jun 2022 22:17:06 +0200 Subject: Dodao mogucnost download-ovanja H5 fajla za prediktor. Popravio bug kada se tooltipovi nisu uvak pojavljivali kada bi trebalo. Popravio bug sa layout-om grafa modela. --- .../_charts/line-chart/line-chart.component.css | 45 +++- .../_charts/line-chart/line-chart.component.html | 29 +-- .../_charts/line-chart/line-chart.component.ts | 230 +++++++++++---------- .../src/app/_elements/folder/folder.component.html | 22 +- .../_elements/form-model/form-model.component.html | 6 +- .../_pages/experiment/experiment.component.html | 2 +- .../app/_pages/experiment/experiment.component.ts | 8 +- frontend/src/app/_services/predictors.service.ts | 4 + 8 files changed, 200 insertions(+), 146 deletions(-) (limited to 'frontend/src/app/_elements') 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 7dbbde7a..9694119d 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,17 +1,46 @@ -canvas{ +.canvas-container { + height: 50%; + margin: 5px; +} + +.bottom { + height: 10%; +} - width:100% !important; - height:100% !important; +canvas { + max-height: 100%; border: 1px solid var(--ns-primary); background-color: var(--ns-bg-dark-100); border-radius: 5px; margin: 0; font-size: 11 !important; padding: 0; - } -.ns-col{ - margin: 5px; } -.hide{ - display: none; + +.ns-col { + margin: 5px; +} + +.hide { + display: none; } + +.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 e36d0dcf..a81f9dc4 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,24 +1,29 @@ -
-
-
- +
+
+
+
-
- +
+
-
-
- +
+
+
-
- +
+
+
+ +
+
-
\ 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 2b97d6b4..ceff02bd 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,7 +1,10 @@ -import { Component, AfterViewInit, ElementRef, ViewChild, Input } 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', @@ -15,19 +18,34 @@ 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; - @Input() experiment!:Experiment; - constructor() { - + @ViewChildren('canvas') + canvas!: QueryList; + @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; @@ -36,18 +54,13 @@ export class LineChartComponent implements AfterViewInit { myChartMae!: Chart; myChartMse!: Chart; myChartLoss!: Chart; - ProblemType=ProblemType; + 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); @@ -80,7 +93,7 @@ export class LineChartComponent implements AfterViewInit { this.myChartMae.update(); this.myChartMse.update(); } - updateAll(history: any[],totalEpochs:number) { + updateAll(history: any[], totalEpochs: number) { const myAcc: number[] = []; const myMae: number[] = []; const myMse: number[] = []; @@ -93,11 +106,10 @@ export class LineChartComponent implements AfterViewInit { 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; + if (totalEpochs > 100) { + let epochEstimate = epoch * Math.round(Math.sqrt(totalEpochs)) + if (epochEstimate > totalEpochs) + epochEstimate = totalEpochs; myEpochs.push(epochEstimate); } else @@ -131,10 +143,10 @@ export class LineChartComponent implements AfterViewInit { } }); - this.update(myEpochs, myAcc, myLoss, myMae, myMse, myValAcc,myValLoss,myValMAE,myValMSE); + this.update(myEpochs, myAcc, myLoss, myMae, myMse, myValAcc, myValLoss, myValMAE, myValMSE); } ngAfterViewInit(): void { - + window.addEventListener('resize', () => { this.resize() }); this.resize(); this.myChartAcc = new Chart("myChartacc", @@ -147,27 +159,27 @@ 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, + //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: { @@ -181,14 +193,14 @@ export class LineChartComponent implements AfterViewInit { title: { display: true, text: 'Epoha', - color:"white" + color: "white" } }, y: { beginAtZero: true, ticks: { color: 'white' - + }, grid: { color: "rgba(0, 99, 171, 0.5)" @@ -196,7 +208,7 @@ export class LineChartComponent implements AfterViewInit { title: { display: true, text: 'Vrednost', - color:"white" + color: "white" } } @@ -207,40 +219,40 @@ export class LineChartComponent implements AfterViewInit { } }, - + ); - if(this.experiment.type==ProblemType.BinaryClassification || this.experiment.type==ProblemType.MultiClassification){} + if (this.experiment.type == ProblemType.BinaryClassification || this.experiment.type == ProblemType.MultiClassification) { } this.myChartLoss = new Chart("myChartloss", { type: 'line', data: { labels: this.dataEpoch, datasets: [ - { - label: 'Loss', - data: this.dataLOSS, - borderWidth: 1 - }, - { - label: 'Val_Loss', - data: this.dataValLoss, - borderWidth: 1 - }, + { + label: 'Loss', + data: this.dataLOSS, + borderWidth: 1 + }, + { + label: 'Val_Loss', + data: this.dataValLoss, + 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: { @@ -254,14 +266,14 @@ export class LineChartComponent implements AfterViewInit { title: { display: true, text: 'Epoha', - color:"white" + color: "white" } }, y: { beginAtZero: true, ticks: { color: 'white' - + }, grid: { color: "rgba(0, 99, 171, 0.5)" @@ -269,7 +281,7 @@ export class LineChartComponent implements AfterViewInit { title: { display: true, text: 'Vrednost', - color:"white" + color: "white" } } @@ -280,7 +292,7 @@ export class LineChartComponent implements AfterViewInit { } }, - + ); this.myChartMse = new Chart("myChartmse", { @@ -288,31 +300,31 @@ export class LineChartComponent implements AfterViewInit { data: { labels: this.dataEpoch, datasets: [ - { - label: 'MSE', - data: this.dataMSE, - borderWidth: 1 - }, - { - label: 'Val_MSE', - data: this.dataValMSE, - borderWidth: 1 - } + { + label: 'MSE', + data: this.dataMSE, + borderWidth: 1 + }, + { + label: 'Val_MSE', + data: this.dataValMSE, + 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: { @@ -326,14 +338,14 @@ export class LineChartComponent implements AfterViewInit { title: { display: true, text: 'Epoha', - color:"white" + color: "white" } }, y: { beginAtZero: true, ticks: { color: 'white' - + }, grid: { color: "rgba(0, 99, 171, 0.5)" @@ -341,7 +353,7 @@ export class LineChartComponent implements AfterViewInit { title: { display: true, text: 'Vrednost', - color:"white" + color: "white" } } @@ -352,7 +364,7 @@ export class LineChartComponent implements AfterViewInit { } }, - + ); this.myChartMae = new Chart("myChartmae", { @@ -360,31 +372,31 @@ export class LineChartComponent implements AfterViewInit { data: { labels: this.dataEpoch, datasets: [ - { - label: 'MAE', - data: this.dataMAE, - borderWidth: 1 - }, - { - label: 'Val_MAE', - data: this.dataValMAE, - borderWidth: 1 - }, + { + 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: { @@ -398,14 +410,14 @@ export class LineChartComponent implements AfterViewInit { title: { display: true, text: 'Epoha', - color:"white" + color: "white" } }, y: { beginAtZero: true, ticks: { color: 'white' - + }, grid: { color: "rgba(0, 99, 171, 0.5)" @@ -413,7 +425,7 @@ export class LineChartComponent implements AfterViewInit { title: { display: true, text: 'Vrednost', - color:"white" + color: "white" } } @@ -424,9 +436,9 @@ export class LineChartComponent implements AfterViewInit { } }, - + ); - + } } diff --git a/frontend/src/app/_elements/folder/folder.component.html b/frontend/src/app/_elements/folder/folder.component.html index 34cd4693..5d5e7822 100644 --- a/frontend/src/app/_elements/folder/folder.component.html +++ b/frontend/src/app/_elements/folder/folder.component.html @@ -76,16 +76,16 @@ {{file.lastUpdated | date}}
- -
-
+
@@ -122,11 +122,11 @@
- -
-
-
+
+
diff --git a/frontend/src/app/_pages/experiment/experiment.component.html b/frontend/src/app/_pages/experiment/experiment.component.html index abb5a6d5..2e5a269c 100644 --- a/frontend/src/app/_pages/experiment/experiment.component.html +++ b/frontend/src/app/_pages/experiment/experiment.component.html @@ -67,7 +67,7 @@
- +
- + +
diff --git a/frontend/src/app/_elements/graph/graph.component.css b/frontend/src/app/_elements/graph/graph.component.css index 456a8df1..f8604125 100644 --- a/frontend/src/app/_elements/graph/graph.component.css +++ b/frontend/src/app/_elements/graph/graph.component.css @@ -10,11 +10,14 @@ /*border: 1px solid red;*/ transform: translate(-50%, -50%); } - -.node-text:not(.inputs) { +.output{ + font-weight: bold; + color: var(--offwhite); +} +.node-text:not(.output) { color: transparent; } -.node-text:not(.inputs):hover { +.node-text:not(.output):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 411e8b53..2ba42eba 100644 --- a/frontend/src/app/_elements/graph/graph.component.html +++ b/frontend/src/app/_elements/graph/graph.component.html @@ -1,8 +1,10 @@
- +
+ +
+ {{ i == 0 ? (inputColumns && inputColumns.length >= j ? inputColumns[j] : 'nepoznato') : (i > 0 && i + < layers.length - 1 ? model!.layers[i-1].activationFunction : (i==layers.length - 1 ? " "+outputColumn : '')) }}
+
+
\ 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 04be9f04..f14e54e7 100644 --- a/frontend/src/app/_elements/graph/graph.component.ts +++ b/frontend/src/app/_elements/graph/graph.component.ts @@ -28,7 +28,8 @@ export class GraphComponent implements AfterViewInit { @Input() outputNodeColor: string = '#dfd7d7'; private ctx!: CanvasRenderingContext2D; - @Input() inputColumns?: string[]; + @Input() inputColumns?: string[]=[]; + @Input() outputColumn?:string=""; constructor() { } @@ -81,7 +82,7 @@ export class GraphComponent implements AfterViewInit { this.layers.push([new Node(outX, outY, this.outputNodeColor)]) this.draw(); } - + draw() { this.ctx.clearRect(0, 0, this.canvas.nativeElement.width, this.canvas.nativeElement.height); -- cgit v1.2.3 From 09a33e72501affb6d07507e396151f02d16daf9a Mon Sep 17 00:00:00 2001 From: Danijel Anđelković Date: Mon, 6 Jun 2022 02:45:47 +0200 Subject: Dodao deljenje datasetova i modela, dialog za podesavanje opcija za deljenje (isPublic accessibleByLink), sa mogucnoscu kopiranja linka za deljenje. Dodao stranice za prikaz javnih datasetova / modela. --- backend/api/api/Controllers/DatasetController.cs | 32 ++++++++++ backend/api/api/Controllers/ModelController.cs | 32 ++++++++++ backend/api/api/Interfaces/IDatasetService.cs | 3 + backend/api/api/Interfaces/IModelService.cs | 3 + backend/api/api/Services/DatasetService.cs | 20 +++++- backend/api/api/Services/ModelService.cs | 16 +++++ docs/SpecifikacijaDizajnaSoftvera.docx | Bin 0 -> 5793452 bytes .../_charts/line-chart/line-chart.component.css | 3 +- .../_charts/line-chart/line-chart.component.html | 10 ++- .../src/app/_elements/folder/folder.component.html | 10 ++- .../src/app/_elements/folder/folder.component.ts | 36 ++++++++++- .../form-dataset/form-dataset.component.html | 8 +-- .../form-dataset/form-dataset.component.ts | 1 + .../_elements/form-model/form-model.component.ts | 2 + .../share-dialog/share-dialog.component.css | 0 .../share-dialog/share-dialog.component.html | 14 +++++ .../share-dialog/share-dialog.component.spec.ts | 25 ++++++++ .../_modals/share-dialog/share-dialog.component.ts | 70 +++++++++++++++++++++ .../_pages/page-dataset/page-dataset.component.css | 0 .../page-dataset/page-dataset.component.html | 4 ++ .../page-dataset/page-dataset.component.spec.ts | 25 ++++++++ .../_pages/page-dataset/page-dataset.component.ts | 45 +++++++++++++ .../app/_pages/page-model/page-model.component.css | 0 .../_pages/page-model/page-model.component.html | 4 ++ .../_pages/page-model/page-model.component.spec.ts | 25 ++++++++ .../app/_pages/page-model/page-model.component.ts | 41 ++++++++++++ frontend/src/app/_services/datasets.service.ts | 8 +++ frontend/src/app/_services/models.service.ts | 8 +++ frontend/src/app/app-routing.module.ts | 4 ++ frontend/src/app/app.module.ts | 8 ++- frontend/src/styles/layout.css | 12 +++- 31 files changed, 449 insertions(+), 20 deletions(-) create mode 100644 docs/SpecifikacijaDizajnaSoftvera.docx create mode 100644 frontend/src/app/_modals/share-dialog/share-dialog.component.css create mode 100644 frontend/src/app/_modals/share-dialog/share-dialog.component.html create mode 100644 frontend/src/app/_modals/share-dialog/share-dialog.component.spec.ts create mode 100644 frontend/src/app/_modals/share-dialog/share-dialog.component.ts create mode 100644 frontend/src/app/_pages/page-dataset/page-dataset.component.css create mode 100644 frontend/src/app/_pages/page-dataset/page-dataset.component.html create mode 100644 frontend/src/app/_pages/page-dataset/page-dataset.component.spec.ts create mode 100644 frontend/src/app/_pages/page-dataset/page-dataset.component.ts create mode 100644 frontend/src/app/_pages/page-model/page-model.component.css create mode 100644 frontend/src/app/_pages/page-model/page-model.component.html create mode 100644 frontend/src/app/_pages/page-model/page-model.component.spec.ts create mode 100644 frontend/src/app/_pages/page-model/page-model.component.ts (limited to 'frontend/src/app/_elements') diff --git a/backend/api/api/Controllers/DatasetController.cs b/backend/api/api/Controllers/DatasetController.cs index c93ac9db..9a3c3d86 100644 --- a/backend/api/api/Controllers/DatasetController.cs +++ b/backend/api/api/Controllers/DatasetController.cs @@ -282,5 +282,37 @@ namespace api.Controllers return Ok($"Dataset with ID = {id} deleted"); } + + [HttpPut("UpdateAccessibleByLink/{datasetId}")] + [Authorize(Roles = "User")] + public ActionResult UpdateAccessibleByLink(string datasetId, [FromBody] bool accessibleByLink) + { + string uploaderId = getUserId(); + + Dataset dataset = _datasetService.GetOneDataset(datasetId); + + if (uploaderId != dataset.uploaderId) + return Unauthorized(); + + _datasetService.UpdateAccessibleByLink(datasetId, accessibleByLink); + + return Ok(dataset.accessibleByLink); + } + + [HttpPut("UpdateIsPublic/{datasetId}")] + [Authorize(Roles = "User")] + public ActionResult UpdateIsPublic(string datasetId, [FromBody] bool isPublic) + { + string uploaderId = getUserId(); + + Dataset dataset = _datasetService.GetOneDataset(datasetId); + + if (uploaderId != dataset.uploaderId) + return Unauthorized(); + + _datasetService.UpdateIsPublic(datasetId, isPublic); + + return Ok(dataset.isPublic); + } } } \ No newline at end of file diff --git a/backend/api/api/Controllers/ModelController.cs b/backend/api/api/Controllers/ModelController.cs index c574de28..c7dfe89c 100644 --- a/backend/api/api/Controllers/ModelController.cs +++ b/backend/api/api/Controllers/ModelController.cs @@ -312,6 +312,38 @@ namespace api.Controllers } + [HttpPut("UpdateAccessibleByLink/{modelId}")] + [Authorize(Roles = "User")] + public ActionResult UpdateAccessibleByLink(string modelId, [FromBody] bool accessibleByLink) + { + string uploaderId = getUserId(); + + Model model = _modelService.GetOneModel(modelId); + + if (uploaderId != model.uploaderId) + return Unauthorized(); + + _modelService.UpdateAccessibleByLink(modelId, accessibleByLink); + + return Ok(model.accessibleByLink); + } + + [HttpPut("UpdateIsPublic/{modelId}")] + [Authorize(Roles = "User")] + public ActionResult UpdateIsPublic(string modelId, [FromBody] bool isPublic) + { + string uploaderId = getUserId(); + + Model model = _modelService.GetOneModel(modelId); + + if (uploaderId != model.uploaderId) + return Unauthorized(); + + _modelService.UpdateIsPublic(modelId, isPublic); + + return Ok(model.isPublic); + } + } public class TrainModelObject diff --git a/backend/api/api/Interfaces/IDatasetService.cs b/backend/api/api/Interfaces/IDatasetService.cs index 2f7d0010..5a91c82b 100644 --- a/backend/api/api/Interfaces/IDatasetService.cs +++ b/backend/api/api/Interfaces/IDatasetService.cs @@ -19,5 +19,8 @@ namespace api.Services public void Update(Dataset dataset); string GetDatasetId(string fileId); //bool CheckDb(); + + public void UpdateAccessibleByLink(string datasetId, bool accessibleByLink); + public void UpdateIsPublic(string datasetId, bool isPublic); } } diff --git a/backend/api/api/Interfaces/IModelService.cs b/backend/api/api/Interfaces/IModelService.cs index 41cd279c..949c7278 100644 --- a/backend/api/api/Interfaces/IModelService.cs +++ b/backend/api/api/Interfaces/IModelService.cs @@ -19,6 +19,9 @@ namespace api.Services void Delete(string userId, string name); bool CheckHyperparameters(int inputNeurons, int hiddenLayerNeurons, int hiddenLayers, int outputNeurons); bool CheckDb(); + + public void UpdateAccessibleByLink(string modelId, bool accessibleByLink); + public void UpdateIsPublic(string modelId, bool isPublic); } } diff --git a/backend/api/api/Services/DatasetService.cs b/backend/api/api/Services/DatasetService.cs index 0b84721e..cd27f275 100644 --- a/backend/api/api/Services/DatasetService.cs +++ b/backend/api/api/Services/DatasetService.cs @@ -75,7 +75,7 @@ namespace api.Services public Dataset GetOneDataset(string userId, string id) { - return _dataset.Find(dataset => dataset.uploaderId == userId && dataset._id == id && dataset.isPreProcess).FirstOrDefault(); + return _dataset.Find(dataset => (dataset.uploaderId == userId || dataset.isPublic || dataset.accessibleByLink) && dataset._id == id && dataset.isPreProcess).FirstOrDefault(); } public Dataset GetOneDatasetN(string userId, string name) { @@ -104,6 +104,22 @@ namespace api.Services return dataset._id; } - + + public void UpdateAccessibleByLink(string datasetId, bool accessibleByLink) + { + Dataset dataset = _dataset.Find(dataset => dataset._id == datasetId).FirstOrDefault(); + dataset.accessibleByLink = accessibleByLink; + + _dataset.ReplaceOne(dataset => dataset._id == datasetId, dataset); + } + + public void UpdateIsPublic(string datasetId, bool isPublic) + { + Dataset dataset = _dataset.Find(dataset => dataset._id == datasetId).FirstOrDefault(); + dataset.isPublic = isPublic; + + _dataset.ReplaceOne(dataset => dataset._id == datasetId, dataset); + } + } } diff --git a/backend/api/api/Services/ModelService.cs b/backend/api/api/Services/ModelService.cs index 71db6340..1c690ca7 100644 --- a/backend/api/api/Services/ModelService.cs +++ b/backend/api/api/Services/ModelService.cs @@ -106,5 +106,21 @@ namespace api.Services return true; } + + public void UpdateAccessibleByLink(string modelId, bool accessibleByLink) + { + Model model = _model.Find(model => model._id == modelId).FirstOrDefault(); + model.accessibleByLink = accessibleByLink; + + _model.ReplaceOne(model => model._id == modelId, model); + } + + public void UpdateIsPublic(string modelId, bool isPublic) + { + Model model = _model.Find(model => model._id == modelId).FirstOrDefault(); + model.isPublic = isPublic; + + _model.ReplaceOne(model => model._id == modelId, model); + } } } diff --git a/docs/SpecifikacijaDizajnaSoftvera.docx b/docs/SpecifikacijaDizajnaSoftvera.docx new file mode 100644 index 00000000..dfc5345b Binary files /dev/null and b/docs/SpecifikacijaDizajnaSoftvera.docx differ 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 862a86e1..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 @@ -22,7 +22,8 @@ canvas { } .hide { - display: none; + display: none !important; + background-color: red; } .dl-button { 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 cc1c0121..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,5 +1,5 @@
-
+
@@ -9,18 +9,16 @@
-
-
+
+
-
+
- -

Model treniran za konfiguraciju: {{modelName}}Model se trenira za konfiguraciju: {{modelName}}

+ @@ -122,12 +125,15 @@
- - +