diff options
author | Ognjen Cirkovic <ciraboxkg@gmail.com> | 2022-03-22 15:04:36 +0000 |
---|---|---|
committer | Ognjen Cirkovic <ciraboxkg@gmail.com> | 2022-03-22 15:04:36 +0000 |
commit | 012fb19a54f4d55a6e4cc73227f738f64539cf04 (patch) | |
tree | 57b3de84ad41037e8c7b1403dba4a5bad24a4752 | |
parent | b4f0cd025a86c68a5c35a58e62c22b7cedf3d8b5 (diff) | |
parent | 31642f68564e67175301235546b74baf56ac5882 (diff) |
Merge branch 'dev' into 'Privremeno-cuvanje-podataka'
# Conflicts:
# backend/api/api/Controllers/ModelController.cs
46 files changed, 1082 insertions, 246 deletions
diff --git a/backend/api/api/Controllers/DatasetController.cs b/backend/api/api/Controllers/DatasetController.cs index f08e55f8..bae05ba9 100644 --- a/backend/api/api/Controllers/DatasetController.cs +++ b/backend/api/api/Controllers/DatasetController.cs @@ -22,9 +22,8 @@ namespace api.Controllers jwtToken = new JwtToken(configuration); } - // GET: api/<DatasetController>/mydatasets - [HttpGet("/mydatasets")] + [HttpGet("mydatasets")] [Authorize(Roles = "User")] public ActionResult<List<Dataset>> Get() { @@ -43,19 +42,79 @@ namespace api.Controllers //ako bude trebao ID, samo iz baze uzeti - return _datasetService.GetMyDatesets(username); + return _datasetService.GetMyDatasets(username); + } + + // GET: api/<DatasetController>/datesort/{ascdsc}/{latest} + //asc - rastuce 1 + //desc - opadajuce 0 + //ako se posalje 0 kao latest onda ce da izlista sve u nekom poretku + [HttpGet("datesort/{ascdsc}/{latest}")] + [Authorize(Roles = "User")] + public ActionResult<List<Dataset>> SortDatasets(bool ascdsc, int latest) + { + string username; + var header = Request.Headers[HeaderNames.Authorization]; + if (AuthenticationHeaderValue.TryParse(header, out var headerValue)) + { + var scheme = headerValue.Scheme; + var parameter = headerValue.Parameter; + username = jwtToken.TokenToUsername(parameter); + if (username == null) + return null; + } + else + return BadRequest(); + + List<Dataset> lista = _datasetService.SortDatasets(username, ascdsc, latest); + + + if (latest == 0) + return lista; + else + { + List<Dataset> novaLista = new List<Dataset>(); + for (int i = 0; i < latest; i++) + novaLista.Add(lista[i]); + return novaLista; + } } // GET: api/<DatasetController>/publicdatasets - [HttpGet("/datasets")] + [HttpGet("publicdatasets")] public ActionResult<List<Dataset>> GetPublicDS() { - return _datasetService.GetPublicDatesets(); + return _datasetService.GetPublicDatasets(); } + //SEARCH za datasets (public ili private sa ovim imenom ) + // GET api/<DatasetController>/search/{name} + [HttpGet("search/{name}")] + [Authorize(Roles = "User")] + public ActionResult<List<Dataset>> Search(string name) + { + string username; + var header = Request.Headers[HeaderNames.Authorization]; + if (AuthenticationHeaderValue.TryParse(header, out var headerValue)) + { + var scheme = headerValue.Scheme; + var parameter = headerValue.Parameter; + username = jwtToken.TokenToUsername(parameter); + if (username == null) + return null; + } + else + return BadRequest(); + + //ako bude trebao ID, samo iz baze uzeti + + return _datasetService.SearchDatasets(name, username); + } + + // GET api/<DatasetController>/{name} //get odredjeni dataset - [HttpGet("/{name}")] + [HttpGet("{name}")] [Authorize(Roles = "User")] public ActionResult<Dataset> Get(string name) { @@ -75,7 +134,7 @@ namespace api.Controllers var dataset = _datasetService.GetOneDataset(username, name); if (dataset == null) - return NotFound($"Dataset with name = {name} or user with username = {username} not found"); + return NotFound($"Dataset with name = {name} not found or dataset is not public"); return dataset; } @@ -115,7 +174,7 @@ namespace api.Controllers } // PUT api/<DatasetController>/{name} - [HttpPut("/{name}")] + [HttpPut("{name}")] [Authorize(Roles = "User")] public ActionResult Put(string name, [FromBody] Dataset dataset) { @@ -138,13 +197,15 @@ namespace api.Controllers if (existingDataset == null) return NotFound($"Dataset with name = {name} or user with username = {username} not found"); + dataset.lastUpdated = DateTime.UtcNow; + _datasetService.Update(username, name, dataset); return Ok($"Dataset with name = {name} updated"); } // DELETE api/<DatasetController>/name - [HttpDelete("/{name}")] + [HttpDelete("{name}")] [Authorize(Roles = "User")] public ActionResult Delete(string name) { diff --git a/backend/api/api/Controllers/ModelController.cs b/backend/api/api/Controllers/ModelController.cs index 77bf1ef3..b4a4b4f2 100644 --- a/backend/api/api/Controllers/ModelController.cs +++ b/backend/api/api/Controllers/ModelController.cs @@ -1,4 +1,4 @@ -using api.Models; +using api.Models; using api.Services; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; @@ -34,7 +34,7 @@ namespace api.Controllers } // GET: api/<ModelController>/mymodels - [HttpGet("/mymodels")] + [HttpGet("mymodels")] [Authorize(Roles = "User")] public ActionResult<List<Model>> Get() { @@ -54,9 +54,9 @@ namespace api.Controllers return _modelService.GetMyModels(username); } - // name modela + // vraca svoj model prema nekom imenu // GET api/<ModelController>/{name} - [HttpGet("/{name}")] + [HttpGet("{name}")] [Authorize(Roles = "User")] public ActionResult<Model> Get(string name) { @@ -76,17 +76,59 @@ namespace api.Controllers var model = _modelService.GetOneModel(username, name); if (model == null) - return NotFound($"Model with name = {name} or user with username = {username} not found"); + return NotFound($"Model with name = {name} not found"); return model; } + //odraditi da vraca modele prema nekom imenu + + + + // moze da vraca sve modele pa da se ovde odradi orderByDesc + //odraditi to i u Datasetove i Predictore + // GET: api/<ModelController>/getlatestmodels/{number} + [HttpGet("getlatestmodels/{latest}")] + [Authorize(Roles = "User")] + public ActionResult<List<Model>> GetLatestModels(int latest) + { + string username; + var header = Request.Headers[HeaderNames.Authorization]; + if (AuthenticationHeaderValue.TryParse(header, out var headerValue)) + { + var scheme = headerValue.Scheme; + var parameter = headerValue.Parameter; + username = jwtToken.TokenToUsername(parameter); + if (username == null) + return null; + } + else + return BadRequest(); + + //ako bude trebao ID, samo iz baze uzeti + + List<Model> lista = _modelService.GetLatestModels(username); + + List<Model> novaLista = new List<Model>(); + + for (int i = 0; i < latest; i++) + novaLista.Add(lista[i]); + + return novaLista; + } + + + + // POST api/<ModelController>/add [HttpPost("add")] [Authorize(Roles = "User,Guest")] public ActionResult<Model> Post([FromBody] Model model) { //username="" ako je GUEST + if (_modelService.CheckHyperparameters(model.inputNeurons, model.hiddenLayerNeurons, model.hiddenLayers, model.outputNeurons) == false) + return BadRequest("Bad parameters!"); + var existingModel = _modelService.GetOneModel(model.username, model.name); if (existingModel != null) @@ -99,7 +141,7 @@ namespace api.Controllers } } - // PUT api/<ModelController>/{username}/{name} + // PUT api/<ModelController>/{name} [HttpPut("{name}")] [Authorize(Roles = "User")] public ActionResult Put(string name, [FromBody] Model model) @@ -127,7 +169,7 @@ namespace api.Controllers return NoContent(); } - // DELETE api/<ModelController>/username + // DELETE api/<ModelController>/name [HttpDelete("{name}")] [Authorize(Roles = "User")] public ActionResult Delete(string name) diff --git a/backend/api/api/Controllers/PredictorController.cs b/backend/api/api/Controllers/PredictorController.cs index d5a55b3c..7f8f1692 100644 --- a/backend/api/api/Controllers/PredictorController.cs +++ b/backend/api/api/Controllers/PredictorController.cs @@ -48,8 +48,35 @@ namespace api.Controllers return _predictorService.GetPublicPredictors(); } + + + //SEARCH za predictore (public ili private sa ovim imenom ) + // GET api/<PredictorController>/search/{name} + [HttpGet("search/{name}")] + [Authorize(Roles = "User")] + public ActionResult<List<Predictor>> Search(string name) + { + string username; + var header = Request.Headers[HeaderNames.Authorization]; + if (AuthenticationHeaderValue.TryParse(header, out var headerValue)) + { + var scheme = headerValue.Scheme; + var parameter = headerValue.Parameter; + username = jwtToken.TokenToUsername(parameter); + if (username == null) + return null; + } + else + return BadRequest(); + + //ako bude trebao ID, samo iz baze uzeti + + return _predictorService.SearchPredictors(name, username); + } + + //da li da se odvoji search za public i posebno za private? // GET api/<PredictorController>/{name} - [HttpGet("/{name}")] + [HttpGet("{name}")] [Authorize(Roles = "User")] public ActionResult<Predictor> Get(string name) { @@ -69,19 +96,57 @@ namespace api.Controllers var predictor = _predictorService.GetOnePredictor(username, name); if (predictor == null) - return NotFound($"Predictor with name = {name} or user with username = {username} not found"); + return NotFound($"Predictor with name = {name} not found or predictor is not public"); return predictor; } + // moze da vraca sve modele pa da se ovde odradi orderByDesc + //odraditi to i u Datasetove i Predictore + // GET: api/<PredictorController>/datesort/{ascdsc}/{latest} + //asc - rastuce 1 + //desc - opadajuce 0 + //ako se posalje 0 kao latest onda ce da izlista sve u nekom poretku + [HttpGet("datesort/{ascdsc}/{latest}")] + [Authorize(Roles = "User")] + public ActionResult<List<Predictor>> SortPredictors(bool ascdsc, int latest) + { + string username; + var header = Request.Headers[HeaderNames.Authorization]; + if (AuthenticationHeaderValue.TryParse(header, out var headerValue)) + { + var scheme = headerValue.Scheme; + var parameter = headerValue.Parameter; + username = jwtToken.TokenToUsername(parameter); + if (username == null) + return null; + } + else + return BadRequest(); + + //ako bude trebao ID, samo iz baze uzeti + List<Predictor> lista = _predictorService.SortPredictors(username, ascdsc, latest); + + if(latest == 0) + return lista; + else + { + List<Predictor> novaLista = new List<Predictor>(); + + for (int i = 0; i < latest; i++) + novaLista.Add(lista[i]); + + return novaLista; + } + } // POST api/<PredictorController>/add [HttpPost("add")] [Authorize(Roles = "User")] public ActionResult<Predictor> Post([FromBody] Predictor predictor) { - var existingModel = _predictorService.GetOnePredictor(predictor.username, predictor.name); + var existingPredictor = _predictorService.GetOnePredictor(predictor.username, predictor.name); - if (existingModel != null) + if (existingPredictor != null) return NotFound($"Predictor with name = {predictor.name} exisits"); else { @@ -94,7 +159,7 @@ namespace api.Controllers // PUT api/<PredictorController>/{name} - [HttpPut("/{name}")] + [HttpPut("{name}")] [Authorize(Roles = "User")] public ActionResult Put(string name, [FromBody] Predictor predictor) { @@ -111,10 +176,10 @@ namespace api.Controllers else return BadRequest(); - var existingDataset = _predictorService.GetOnePredictor(username, name); + var existingPredictor = _predictorService.GetOnePredictor(username, name); //ne mora da se proverava - if (existingDataset == null) + if (existingPredictor == null) return NotFound($"Predictor with name = {name} or user with username = {username} not found"); _predictorService.Update(username, name, predictor); @@ -122,9 +187,16 @@ namespace api.Controllers return Ok($"Predictor with name = {name} updated"); } + // odraditi pretragu predictora + //potrebna public i private pretraga + //prvo da napakuje svoje pa onda ostale + // + //isto odraditi i za datasetove + // + // DELETE api/<PredictorController>/name - [HttpDelete("/{name}")] + [HttpDelete("{name}")] [Authorize(Roles = "User")] public ActionResult Delete(string name) { diff --git a/backend/api/api/Controllers/UserController.cs b/backend/api/api/Controllers/UserController.cs index 58121656..dcab53cc 100644 --- a/backend/api/api/Controllers/UserController.cs +++ b/backend/api/api/Controllers/UserController.cs @@ -2,7 +2,9 @@ using api.Services; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; +using Microsoft.Net.Http.Headers; using System.Diagnostics; +using System.Net.Http.Headers; // For more information on enabling Web API for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860 //dovrsi kontroler @@ -13,10 +15,12 @@ namespace api.Controllers public class UserController : ControllerBase { private readonly IUserService userService; + private JwtToken jwtToken; - public UserController(IUserService userService) + public UserController(IUserService userService, IConfiguration configuration) { this.userService = userService; + jwtToken = new JwtToken(configuration); } // GET: api/<UserController> @@ -38,12 +42,29 @@ namespace api.Controllers return user; } - /* + + + + // GET api/<UserController>/5 //potrebno za profile page - [HttpGet("{id}")] - public ActionResult<User> GetUserUsername(string username) + [HttpGet("myprofile")] + [Authorize(Roles = "User")] + public ActionResult<User> MyProfilePage() { + string username; + var header = Request.Headers[HeaderNames.Authorization]; + if (AuthenticationHeaderValue.TryParse(header, out var headerValue)) + { + var scheme = headerValue.Scheme; + var parameter = headerValue.Parameter; + username = jwtToken.TokenToUsername(parameter); + if (username == null) + return null; + } + else + return BadRequest(); + var user = userService.GetUserUsername(username); if (user == null) @@ -51,7 +72,7 @@ namespace api.Controllers return user; } - */ + // POST api/<UserController> [HttpPost] public ActionResult<User> Post([FromBody] User user) diff --git a/backend/api/api/Models/Dataset.cs b/backend/api/api/Models/Dataset.cs index d4649c17..1bf080ec 100644 --- a/backend/api/api/Models/Dataset.cs +++ b/backend/api/api/Models/Dataset.cs @@ -18,8 +18,8 @@ namespace api.Models public string extension { get; set; } public bool isPublic { get; set; } public bool accessibleByLink { get; set; } - public string dateCreated { get; set; } - public string lastUpdated { get; set; } + public DateTime dateCreated { get; set; } + public DateTime lastUpdated { get; set; } } } diff --git a/backend/api/api/Models/Model.cs b/backend/api/api/Models/Model.cs index dfc4336a..5678daaf 100644 --- a/backend/api/api/Models/Model.cs +++ b/backend/api/api/Models/Model.cs @@ -15,8 +15,8 @@ namespace api.Models public string name { get; set; } public string description { get; set; } //datetime - public string dateCreated { get; set; } - public string lastUpdated { get; set; } + public DateTime dateCreated { get; set; } + public DateTime lastUpdated { get; set; } //proveriti id public string datasetId { get; set; } @@ -36,6 +36,8 @@ namespace api.Models public int hiddenLayerNeurons { get; set; } public int hiddenLayers { get; set; } public int batchSize { get; set; } + // na izlazu je moguce da bude vise neurona (klasifikacioni problem sa vise od 2 klase) + public int outputNeurons { get; set; } public string inputLayerActivationFunction { get; set; } public string hiddenLayerActivationFunction { get; set; } public string outputLayerActivationFunction { get; set; } diff --git a/backend/api/api/Models/Predictor.cs b/backend/api/api/Models/Predictor.cs index cd2f4557..568719fc 100644 --- a/backend/api/api/Models/Predictor.cs +++ b/backend/api/api/Models/Predictor.cs @@ -16,7 +16,7 @@ namespace api.Models public string output { get; set; } public bool isPublic { get; set; } public bool accessibleByLink { get; set; } - public string dateCreated { get; set; } + public DateTime dateCreated { get; set; } } } diff --git a/backend/api/api/Services/DatasetService.cs b/backend/api/api/Services/DatasetService.cs index 27a8b3ee..5e708d11 100644 --- a/backend/api/api/Services/DatasetService.cs +++ b/backend/api/api/Services/DatasetService.cs @@ -13,6 +13,12 @@ namespace api.Services var database = mongoClient.GetDatabase(settings.DatabaseName); _dataset = database.GetCollection<Dataset>(settings.DatasetCollectionName); } + + public List<Dataset> SearchDatasets(string name, string username) + { + return _dataset.Find(dataset => dataset.name == name && dataset.isPublic == true).ToList(); + } + //kreiranje dataseta public Dataset Create(Dataset dataset) { @@ -26,11 +32,25 @@ namespace api.Services _dataset.DeleteOne(dataset => (dataset.username == username && dataset.name == name)); } - public List<Dataset> GetMyDatesets(string username) + public List<Dataset> GetMyDatasets(string username) { return _dataset.Find(dataset => dataset.username == username).ToList(); } - public List<Dataset> GetPublicDatesets() + + //poslednji datasetovi + public List<Dataset> SortDatasets(string username, bool ascdsc, int latest) + { + List<Dataset> list = _dataset.Find(dataset => dataset.username == username).ToList(); + + if(ascdsc) + list = list.OrderBy(dataset => dataset.lastUpdated).ToList(); + else + list = list.OrderByDescending(dataset => dataset.lastUpdated).ToList(); + + return list; + } + + public List<Dataset> GetPublicDatasets() { return _dataset.Find(dataset => dataset.isPublic == true).ToList(); } @@ -46,5 +66,7 @@ namespace api.Services { _dataset.ReplaceOne(dataset => dataset.username == username && dataset.name == name, dataset); } + + } } diff --git a/backend/api/api/Services/IDatasetService.cs b/backend/api/api/Services/IDatasetService.cs index 61a04b94..be56f5cb 100644 --- a/backend/api/api/Services/IDatasetService.cs +++ b/backend/api/api/Services/IDatasetService.cs @@ -6,8 +6,10 @@ namespace api.Services public interface IDatasetService { Dataset GetOneDataset(string username, string name); - List<Dataset> GetMyDatesets(string username); - List<Dataset> GetPublicDatesets(); + List<Dataset> SearchDatasets(string name, string username); + List<Dataset> GetMyDatasets(string username); + List<Dataset> SortDatasets(string username, bool ascdsc, int latest); + List<Dataset> GetPublicDatasets(); Dataset Create(Dataset dataset); void Update(string username, string name, Dataset dataset); void Delete(string username, string name); diff --git a/backend/api/api/Services/IModelService.cs b/backend/api/api/Services/IModelService.cs index c1931ffa..ee5c279f 100644 --- a/backend/api/api/Services/IModelService.cs +++ b/backend/api/api/Services/IModelService.cs @@ -7,10 +7,12 @@ namespace api.Services { Model GetOneModel(string username, string name); List<Model> GetMyModels(string username); + List<Model> GetLatestModels(string username); //List<Model> GetPublicModels(); Model Create(Model model); void Update(string username, string name, Model model); void Delete(string username, string name); + bool CheckHyperparameters(int inputNeurons, int hiddenLayerNeurons, int hiddenLayers, int outputNeurons); } } diff --git a/backend/api/api/Services/IPredictorService.cs b/backend/api/api/Services/IPredictorService.cs index 594b233b..2017add2 100644 --- a/backend/api/api/Services/IPredictorService.cs +++ b/backend/api/api/Services/IPredictorService.cs @@ -6,7 +6,9 @@ namespace api.Services public interface IPredictorService { Predictor GetOnePredictor(string username, string name); + List<Predictor> SearchPredictors(string name, string username); List<Predictor> GetMyPredictors(string username); + List<Predictor> SortPredictors(string username, bool ascdsc, int latest); List<Predictor> GetPublicPredictors(); Predictor Create(Predictor predictor); void Update(string username, string name, Predictor predictor); diff --git a/backend/api/api/Services/ModelService.cs b/backend/api/api/Services/ModelService.cs index 2ba3c54d..f42219f5 100644 --- a/backend/api/api/Services/ModelService.cs +++ b/backend/api/api/Services/ModelService.cs @@ -7,7 +7,6 @@ namespace api.Services { public class ModelService : IModelService { - private readonly IMongoCollection<Model> _model; public ModelService(IUserStoreDatabaseSettings settings, IMongoClient mongoClient) @@ -31,6 +30,15 @@ namespace api.Services { return _model.Find(model => model.username == username).ToList(); } + public List<Model> GetLatestModels(string username) + { + List<Model> list = _model.Find(model => model.username == username).ToList(); + + list = list.OrderByDescending(model => model.lastUpdated).ToList(); + + return list; + } + /* public List<Model> GetPublicModels() { @@ -46,6 +54,18 @@ namespace api.Services { _model.ReplaceOne(model => model.username == username && model.name == name, model); } + // + public bool CheckHyperparameters(int inputNeurons, int hiddenLayerNeurons, int hiddenLayers, int outputNeurons) + { + if (hiddenLayers <= 0 || hiddenLayerNeurons <= 0) + return false; + if (hiddenLayers > inputNeurons) + return false; + if (hiddenLayerNeurons <= 2 * inputNeurons || hiddenLayerNeurons <= (2 / 3) * inputNeurons + outputNeurons || (hiddenLayerNeurons <= Math.Max(inputNeurons, outputNeurons) && hiddenLayerNeurons >= Math.Min(inputNeurons, outputNeurons))) + return true; + return false; + } + } } diff --git a/backend/api/api/Services/PredictorService.cs b/backend/api/api/Services/PredictorService.cs index 69fb25c9..05860126 100644 --- a/backend/api/api/Services/PredictorService.cs +++ b/backend/api/api/Services/PredictorService.cs @@ -14,6 +14,11 @@ namespace api.Services _predictor = database.GetCollection<Predictor>(settings.PredictorCollectionName); } + public List<Predictor> SearchPredictors(string name, string username) + { + return _predictor.Find(predictor => predictor.name == name && predictor.isPublic == true).ToList(); + } + public Predictor Create(Predictor predictor) { _predictor.InsertOne(predictor); @@ -35,6 +40,18 @@ namespace api.Services return _predictor.Find(predictor => predictor.username == username && predictor.name == name).FirstOrDefault(); } + //last private models + public List<Predictor> SortPredictors(string username, bool ascdsc, int latest) + { + List<Predictor> list = _predictor.Find(predictor => predictor.username == username).ToList(); + + + if (ascdsc) + list = list.OrderBy(predictor => predictor.dateCreated).ToList(); + else + list = list.OrderByDescending(predictor => predictor.dateCreated).ToList(); + return list; + } public List<Predictor> GetPublicPredictors() { @@ -46,5 +63,6 @@ namespace api.Services _predictor.ReplaceOne(predictor => predictor.username == username && predictor.name == name, predictor); } + } } diff --git a/backend/microservice/PythonServer/project/api/api.py b/backend/microservice/api.py index b2fb503b..b2fb503b 100644 --- a/backend/microservice/PythonServer/project/api/api.py +++ b/backend/microservice/api.py diff --git a/backend/microservice/PythonServer/project/api/templates/data.html b/backend/microservice/data.html index d2fb44ab..d2fb44ab 100644 --- a/backend/microservice/PythonServer/project/api/templates/data.html +++ b/backend/microservice/data.html diff --git a/backend/microservice/fcnn.ipynb b/backend/microservice/fcnn.ipynb index 52bcf790..494ca1d9 100644 --- a/backend/microservice/fcnn.ipynb +++ b/backend/microservice/fcnn.ipynb @@ -13,7 +13,8 @@ }, "language_info": { "name": "python" - } + }, + "accelerator": "GPU" }, "cells": [ { @@ -27,7 +28,7 @@ }, { "cell_type": "code", - "execution_count": 209, + "execution_count": 1, "metadata": { "id": "V-j3D7ZDhxOl" }, @@ -44,7 +45,7 @@ "metadata": { "id": "1JWeUSyJrxLz" }, - "execution_count": 210, + "execution_count": 2, "outputs": [] }, { @@ -66,9 +67,9 @@ "base_uri": "https://localhost:8080/" }, "id": "Wjvd-3oBtdpW", - "outputId": "97277f04-34be-4eaf-e906-49fabbfb69ce" + "outputId": "f14d5464-c985-4360-ec0b-c09412eeb835" }, - "execution_count": 211, + "execution_count": 3, "outputs": [ { "output_type": "execute_result", @@ -90,7 +91,7 @@ ] }, "metadata": {}, - "execution_count": 211 + "execution_count": 3 } ] }, @@ -113,9 +114,9 @@ "base_uri": "https://localhost:8080/" }, "id": "eIOQ2r3WsNjc", - "outputId": "11b9e11c-94ea-475b-a2ba-144922b5f112" + "outputId": "f9f7d9a0-5ae2-4a30-9127-610ee1254b18" }, - "execution_count": 212, + "execution_count": 4, "outputs": [ { "output_type": "execute_result", @@ -134,7 +135,7 @@ ] }, "metadata": {}, - "execution_count": 212 + "execution_count": 4 } ] }, @@ -157,9 +158,9 @@ "base_uri": "https://localhost:8080/" }, "id": "GuGUR4MjsVAt", - "outputId": "89240693-611e-4f7b-9f2f-5cfad26e6634" + "outputId": "9e94a049-a738-4ea2-e3a6-c72f0fd42949" }, - "execution_count": 213, + "execution_count": 5, "outputs": [ { "output_type": "execute_result", @@ -169,7 +170,7 @@ ] }, "metadata": {}, - "execution_count": 213 + "execution_count": 5 } ] }, @@ -192,9 +193,9 @@ "base_uri": "https://localhost:8080/" }, "id": "JNaqQhAzsdM4", - "outputId": "76c91cdd-e659-4685-f857-cce3e73338db" + "outputId": "126cea03-aa32-423a-c433-96aa1b84dcee" }, - "execution_count": 214, + "execution_count": 6, "outputs": [ { "output_type": "execute_result", @@ -204,7 +205,7 @@ ] }, "metadata": {}, - "execution_count": 214 + "execution_count": 6 } ] }, @@ -218,9 +219,9 @@ "base_uri": "https://localhost:8080/" }, "id": "DuOj9XjKtNET", - "outputId": "58f90430-84f3-4e68-e6fe-ded889bbf6b4" + "outputId": "0e28d6b0-109e-43b7-bdca-1b9ab0983f7a" }, - "execution_count": 215, + "execution_count": 7, "outputs": [ { "output_type": "execute_result", @@ -255,7 +256,7 @@ ] }, "metadata": {}, - "execution_count": 215 + "execution_count": 7 } ] }, @@ -269,9 +270,9 @@ "base_uri": "https://localhost:8080/" }, "id": "mcX29JkpuI71", - "outputId": "b079071c-a689-46a9-de6a-e345f0531b98" + "outputId": "0eb7c5eb-156b-4445-bd2e-56f2cc7d76d4" }, - "execution_count": 216, + "execution_count": 8, "outputs": [ { "output_type": "execute_result", @@ -281,7 +282,7 @@ ] }, "metadata": {}, - "execution_count": 216 + "execution_count": 8 } ] }, @@ -293,7 +294,7 @@ "metadata": { "id": "rhnFUqKRr6f1" }, - "execution_count": 217, + "execution_count": 9, "outputs": [] }, { @@ -313,7 +314,7 @@ "metadata": { "id": "DYt9-pEGr_AG" }, - "execution_count": 218, + "execution_count": 10, "outputs": [] }, { @@ -324,7 +325,7 @@ "metadata": { "id": "-drBC0Wvtil3" }, - "execution_count": 219, + "execution_count": 11, "outputs": [] }, { @@ -344,7 +345,7 @@ "metadata": { "id": "GwbnpRsbtmha" }, - "execution_count": 220, + "execution_count": 12, "outputs": [] }, { @@ -357,9 +358,9 @@ "base_uri": "https://localhost:8080/" }, "id": "vTElNnAJtvGL", - "outputId": "78aae55d-78e7-45b9-edca-182b9516fbe6" + "outputId": "15eea781-ab94-4a7f-87f6-3a8b8bffba93" }, - "execution_count": 221, + "execution_count": 13, "outputs": [ { "output_type": "execute_result", @@ -369,7 +370,7 @@ ] }, "metadata": {}, - "execution_count": 221 + "execution_count": 13 } ] }, @@ -383,9 +384,9 @@ "base_uri": "https://localhost:8080/" }, "id": "VMnIE4ARuAnv", - "outputId": "1c9533aa-55ec-4263-d59b-9e38d24b0e82" + "outputId": "05bfffb3-1d50-4dd9-e185-e0e570967014" }, - "execution_count": 222, + "execution_count": 14, "outputs": [ { "output_type": "execute_result", @@ -395,7 +396,7 @@ ] }, "metadata": {}, - "execution_count": 222 + "execution_count": 14 } ] }, @@ -418,9 +419,9 @@ "base_uri": "https://localhost:8080/" }, "id": "9aCST5jHvAkE", - "outputId": "36b91b77-1531-4399-8282-c0c4a78927d9" + "outputId": "a539e40e-6918-418c-daed-a2901e593457" }, - "execution_count": 223, + "execution_count": 15, "outputs": [ { "output_type": "execute_result", @@ -434,7 +435,7 @@ ] }, "metadata": {}, - "execution_count": 223 + "execution_count": 15 } ] }, @@ -455,7 +456,7 @@ "metadata": { "id": "1jaGEMe9vdL6" }, - "execution_count": 224, + "execution_count": 16, "outputs": [] }, { @@ -479,7 +480,7 @@ "metadata": { "id": "HtsqX74Gve7i" }, - "execution_count": 225, + "execution_count": 17, "outputs": [] }, { @@ -492,9 +493,9 @@ "base_uri": "https://localhost:8080/" }, "id": "0zGchJnWzWhh", - "outputId": "3f2778cb-dd2a-4967-b75d-a7f877c70472" + "outputId": "68ba5b26-9222-4dba-9073-c6abb42afa4a" }, - "execution_count": 226, + "execution_count": 18, "outputs": [ { "output_type": "execute_result", @@ -509,7 +510,7 @@ ] }, "metadata": {}, - "execution_count": 226 + "execution_count": 18 } ] }, @@ -533,7 +534,7 @@ "metadata": { "id": "PHZDe92Dn12k" }, - "execution_count": 227, + "execution_count": 19, "outputs": [] }, { @@ -563,23 +564,23 @@ "base_uri": "https://localhost:8080/" }, "id": "qKso0x4Pn5th", - "outputId": "87f1ab66-965d-4d41-8003-08db5935403b" + "outputId": "614cc227-974b-456d-b0f5-7d95c0a14128" }, - "execution_count": 228, + "execution_count": 20, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ - "Model: \"sequential_6\"\n", + "Model: \"sequential\"\n", "_________________________________________________________________\n", " Layer (type) Output Shape Param # \n", "=================================================================\n", - " dense_15 (Dense) (None, 100) 3100 \n", + " dense (Dense) (None, 100) 3100 \n", " \n", - " dense_16 (Dense) (None, 40) 4040 \n", + " dense_1 (Dense) (None, 40) 4040 \n", " \n", - " dense_17 (Dense) (None, 1) 41 \n", + " dense_2 (Dense) (None, 1) 41 \n", " \n", "=================================================================\n", "Total params: 7,181\n", @@ -626,7 +627,7 @@ "metadata": { "id": "iAY-da-In_pT" }, - "execution_count": 229, + "execution_count": 21, "outputs": [] }, { @@ -657,54 +658,77 @@ "base_uri": "https://localhost:8080/" }, "id": "gF31rSh6oDCd", - "outputId": "e036c5eb-2846-4a6f-9a81-06040771627f" + "outputId": "ce87f1ce-7948-44e9-9440-4d3652b3a188" }, - "execution_count": 230, + "execution_count": 22, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ "Epoch 1/20\n", - "5/5 [==============================] - 1s 46ms/step - loss: 0.7196 - accuracy: 0.4843 - val_loss: 0.5961 - val_accuracy: 0.7250\n", + "5/5 [==============================] - 3s 55ms/step - loss: 0.5302 - accuracy: 0.8365 - val_loss: 0.4567 - val_accuracy: 0.8625\n", "Epoch 2/20\n", - "5/5 [==============================] - 0s 9ms/step - loss: 0.4791 - accuracy: 0.9277 - val_loss: 0.4321 - val_accuracy: 0.9125\n", + "5/5 [==============================] - 0s 10ms/step - loss: 0.3698 - accuracy: 0.9214 - val_loss: 0.3395 - val_accuracy: 0.9000\n", "Epoch 3/20\n", - "5/5 [==============================] - 0s 11ms/step - loss: 0.3433 - accuracy: 0.9465 - val_loss: 0.3273 - val_accuracy: 0.9375\n", + "5/5 [==============================] - 0s 10ms/step - loss: 0.2711 - accuracy: 0.9403 - val_loss: 0.2566 - val_accuracy: 0.9375\n", "Epoch 4/20\n", - "5/5 [==============================] - 0s 11ms/step - loss: 0.2586 - accuracy: 0.9434 - val_loss: 0.2569 - val_accuracy: 0.9625\n", + "5/5 [==============================] - 0s 9ms/step - loss: 0.2082 - accuracy: 0.9465 - val_loss: 0.1980 - val_accuracy: 0.9375\n", "Epoch 5/20\n", - "5/5 [==============================] - 0s 13ms/step - loss: 0.2032 - accuracy: 0.9528 - val_loss: 0.2095 - val_accuracy: 0.9625\n", + "5/5 [==============================] - 0s 10ms/step - loss: 0.1673 - accuracy: 0.9591 - val_loss: 0.1589 - val_accuracy: 0.9375\n", "Epoch 6/20\n", - "5/5 [==============================] - 0s 10ms/step - loss: 0.1657 - accuracy: 0.9560 - val_loss: 0.1775 - val_accuracy: 0.9625\n", + "5/5 [==============================] - 0s 10ms/step - loss: 0.1417 - accuracy: 0.9654 - val_loss: 0.1308 - val_accuracy: 0.9750\n", "Epoch 7/20\n", - "5/5 [==============================] - 0s 10ms/step - loss: 0.1420 - accuracy: 0.9623 - val_loss: 0.1549 - val_accuracy: 0.9625\n", + "5/5 [==============================] - 0s 10ms/step - loss: 0.1251 - accuracy: 0.9654 - val_loss: 0.1103 - val_accuracy: 0.9875\n", "Epoch 8/20\n", - "5/5 [==============================] - 0s 10ms/step - loss: 0.1232 - accuracy: 0.9717 - val_loss: 0.1399 - val_accuracy: 0.9625\n", + "5/5 [==============================] - 0s 10ms/step - loss: 0.1115 - accuracy: 0.9717 - val_loss: 0.0972 - val_accuracy: 0.9875\n", "Epoch 9/20\n", - "5/5 [==============================] - 0s 10ms/step - loss: 0.1094 - accuracy: 0.9717 - val_loss: 0.1303 - val_accuracy: 0.9625\n", + "5/5 [==============================] - 0s 11ms/step - loss: 0.1019 - accuracy: 0.9748 - val_loss: 0.0864 - val_accuracy: 1.0000\n", "Epoch 10/20\n", - "5/5 [==============================] - 0s 11ms/step - loss: 0.0999 - accuracy: 0.9717 - val_loss: 0.1231 - val_accuracy: 0.9625\n", + "5/5 [==============================] - 0s 10ms/step - loss: 0.0946 - accuracy: 0.9748 - val_loss: 0.0783 - val_accuracy: 1.0000\n", "Epoch 11/20\n", - "5/5 [==============================] - 0s 9ms/step - loss: 0.0920 - accuracy: 0.9717 - val_loss: 0.1177 - val_accuracy: 0.9625\n", + "5/5 [==============================] - 0s 10ms/step - loss: 0.0891 - accuracy: 0.9811 - val_loss: 0.0715 - val_accuracy: 1.0000\n", "Epoch 12/20\n", - "5/5 [==============================] - 0s 12ms/step - loss: 0.0865 - accuracy: 0.9717 - val_loss: 0.1131 - val_accuracy: 0.9750\n", + "5/5 [==============================] - 0s 11ms/step - loss: 0.0846 - accuracy: 0.9811 - val_loss: 0.0664 - val_accuracy: 1.0000\n", "Epoch 13/20\n", - "5/5 [==============================] - 0s 10ms/step - loss: 0.0812 - accuracy: 0.9717 - val_loss: 0.1096 - val_accuracy: 0.9750\n", + "5/5 [==============================] - 0s 11ms/step - loss: 0.0810 - accuracy: 0.9811 - val_loss: 0.0620 - val_accuracy: 1.0000\n", "Epoch 14/20\n", - "5/5 [==============================] - 0s 11ms/step - loss: 0.0779 - accuracy: 0.9717 - val_loss: 0.1086 - val_accuracy: 0.9625\n", + "5/5 [==============================] - 0s 10ms/step - loss: 0.0771 - accuracy: 0.9811 - val_loss: 0.0579 - val_accuracy: 1.0000\n", "Epoch 15/20\n", - "5/5 [==============================] - 0s 10ms/step - loss: 0.0738 - accuracy: 0.9780 - val_loss: 0.1051 - val_accuracy: 0.9625\n", + "5/5 [==============================] - 0s 10ms/step - loss: 0.0742 - accuracy: 0.9811 - val_loss: 0.0554 - val_accuracy: 1.0000\n", "Epoch 16/20\n", - "5/5 [==============================] - 0s 11ms/step - loss: 0.0707 - accuracy: 0.9780 - val_loss: 0.1028 - val_accuracy: 0.9750\n", + "5/5 [==============================] - 0s 10ms/step - loss: 0.0713 - accuracy: 0.9811 - val_loss: 0.0513 - val_accuracy: 1.0000\n", "Epoch 17/20\n", - "5/5 [==============================] - 0s 10ms/step - loss: 0.0681 - accuracy: 0.9780 - val_loss: 0.1016 - val_accuracy: 0.9750\n", + "5/5 [==============================] - 0s 10ms/step - loss: 0.0687 - accuracy: 0.9811 - val_loss: 0.0485 - val_accuracy: 1.0000\n", "Epoch 18/20\n", - "5/5 [==============================] - 0s 11ms/step - loss: 0.0652 - accuracy: 0.9811 - val_loss: 0.0993 - val_accuracy: 0.9750\n", + "5/5 [==============================] - 0s 11ms/step - loss: 0.0659 - accuracy: 0.9811 - val_loss: 0.0461 - val_accuracy: 1.0000\n", "Epoch 19/20\n", - "5/5 [==============================] - 0s 9ms/step - loss: 0.0627 - accuracy: 0.9843 - val_loss: 0.0980 - val_accuracy: 0.9750\n", + "5/5 [==============================] - 0s 10ms/step - loss: 0.0639 - accuracy: 0.9811 - val_loss: 0.0446 - val_accuracy: 1.0000\n", "Epoch 20/20\n", - "5/5 [==============================] - 0s 11ms/step - loss: 0.0605 - accuracy: 0.9843 - val_loss: 0.0977 - val_accuracy: 0.9750\n" + "5/5 [==============================] - 0s 10ms/step - loss: 0.0616 - accuracy: 0.9811 - val_loss: 0.0421 - val_accuracy: 1.0000\n" + ] + } + ] + }, + { + "cell_type": "code", + "source": [ + "pip install ann_visualizer" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "2reQpFLKF8bt", + "outputId": "b9ee84df-6ff8-4748-a3d4-0b62879ed6ad" + }, + "execution_count": 26, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Requirement already satisfied: ann_visualizer in /usr/local/lib/python3.7/dist-packages (2.5)\n" ] } ] @@ -712,6 +736,28 @@ { "cell_type": "code", "source": [ + "from ann_visualizer.visualize import ann_viz;" + ], + "metadata": { + "id": "_kcAIbmgGMu7" + }, + "execution_count": 27, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "ann_viz(model, view=True, title=\"test\", filename=\"visualized\")" + ], + "metadata": { + "id": "qO_6X1buGl8k" + }, + "execution_count": 29, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ "history.epoch" ], "metadata": { @@ -721,7 +767,7 @@ "id": "EUbVgdutD3-L", "outputId": "e5bd59e4-44c0-463f-f3db-ac7ac915f163" }, - "execution_count": 231, + "execution_count": null, "outputs": [ { "output_type": "execute_result", @@ -743,7 +789,7 @@ "metadata": { "id": "CmTvhOiFoJsb" }, - "execution_count": 232, + "execution_count": null, "outputs": [] }, { @@ -770,7 +816,7 @@ "id": "dPoCecWwoKzk", "outputId": "bfdaac91-e0a8-4b63-b581-277b4284b382" }, - "execution_count": 233, + "execution_count": null, "outputs": [ { "output_type": "execute_result", @@ -810,7 +856,7 @@ "id": "MJpq_PEBoQTT", "outputId": "3a13860c-7f1a-491a-9127-7564c5c9a83c" }, - "execution_count": 234, + "execution_count": null, "outputs": [ { "output_type": "execute_result", @@ -859,7 +905,7 @@ "id": "j9qI4bbZoRHH", "outputId": "ce60c889-af9f-400e-ea00-1a9abce7d6e6" }, - "execution_count": 235, + "execution_count": null, "outputs": [ { "output_type": "stream", @@ -906,7 +952,7 @@ "metadata": { "id": "o2u2R2peoUdQ" }, - "execution_count": 236, + "execution_count": null, "outputs": [] }, { @@ -928,7 +974,7 @@ "id": "67OXuSK4od4-", "outputId": "f1c6d7ba-9ad3-43be-fdfa-d5bde9d43e6c" }, - "execution_count": 237, + "execution_count": null, "outputs": [ { "output_type": "stream", @@ -947,7 +993,7 @@ "metadata": { "id": "WVVUQDVZojDB" }, - "execution_count": 238, + "execution_count": null, "outputs": [] }, { @@ -958,7 +1004,7 @@ "metadata": { "id": "CtO0VIVDos5F" }, - "execution_count": 239, + "execution_count": null, "outputs": [] }, { @@ -973,7 +1019,7 @@ "id": "Mx-qvrayotTl", "outputId": "856603a8-bfa7-447b-8047-907aa3344764" }, - "execution_count": 240, + "execution_count": null, "outputs": [ { "output_type": "execute_result", @@ -999,7 +1045,7 @@ "id": "J18nkwLsotnW", "outputId": "1b2f2c44-9fc4-4c16-a828-a720998deb06" }, - "execution_count": 241, + "execution_count": null, "outputs": [ { "output_type": "execute_result", @@ -1025,7 +1071,7 @@ "id": "TDuqhqW2ozix", "outputId": "7e21ac31-f96c-4301-9c2b-f03eb744315e" }, - "execution_count": 242, + "execution_count": null, "outputs": [ { "output_type": "execute_result", @@ -1053,7 +1099,7 @@ "id": "DQJ5ImLcOR4Q", "outputId": "a4d65d3b-2f1a-41c7-a64d-cb64029cb6e4" }, - "execution_count": 243, + "execution_count": null, "outputs": [ { "output_type": "execute_result", @@ -1084,7 +1130,7 @@ "metadata": { "id": "418_Fqi2o1Vd" }, - "execution_count": 244, + "execution_count": null, "outputs": [] }, { @@ -1098,7 +1144,7 @@ "metadata": { "id": "nUEFLoC1o3oQ" }, - "execution_count": 245, + "execution_count": null, "outputs": [] }, { @@ -1113,7 +1159,7 @@ "id": "wYFb_UtuOjDL", "outputId": "7e78d7b3-0d39-4455-e386-faaa24345051" }, - "execution_count": 246, + "execution_count": null, "outputs": [ { "output_type": "execute_result", @@ -1141,7 +1187,7 @@ "id": "rCtetAZIOvhl", "outputId": "84fb81e0-ce85-4ece-8a86-acb43ab85d66" }, - "execution_count": 247, + "execution_count": null, "outputs": [ { "output_type": "execute_result", @@ -1195,7 +1241,7 @@ "id": "Q2mrvuqTo6XK", "outputId": "ac11cbdf-24fd-486b-8705-1f390a4b1645" }, - "execution_count": 248, + "execution_count": null, "outputs": [ { "output_type": "stream", @@ -1226,7 +1272,7 @@ "metadata": { "id": "YtafEf6Ho6rU" }, - "execution_count": 249, + "execution_count": null, "outputs": [] }, { @@ -1250,7 +1296,7 @@ "id": "CGtGSzlOo659", "outputId": "6b332ab3-7737-458d-d65b-0d471f5799b7" }, - "execution_count": 250, + "execution_count": null, "outputs": [ { "output_type": "stream", @@ -1314,7 +1360,7 @@ "id": "wS-Ktb5Co7LA", "outputId": "4c0a02fa-3188-4632-ab87-fc821220d722" }, - "execution_count": 251, + "execution_count": null, "outputs": [ { "output_type": "execute_result", @@ -1354,7 +1400,7 @@ "id": "JwJfrlo8pDJ5", "outputId": "af949097-15e9-4609-9362-6be4d3f139a2" }, - "execution_count": 252, + "execution_count": null, "outputs": [ { "output_type": "execute_result", @@ -1392,7 +1438,7 @@ "id": "s0B7C3S_pDGp", "outputId": "cb6766e1-4621-45d4-d264-403556138512" }, - "execution_count": 253, + "execution_count": null, "outputs": [ { "output_type": "stream", @@ -1422,7 +1468,7 @@ "metadata": { "id": "3XTt8tjEpDDa" }, - "execution_count": 254, + "execution_count": null, "outputs": [] }, { @@ -1433,7 +1479,7 @@ "metadata": { "id": "I4hWvlyepC_w" }, - "execution_count": 255, + "execution_count": null, "outputs": [] }, { @@ -1444,7 +1490,7 @@ "metadata": { "id": "LCO4fGnCpC8c" }, - "execution_count": 256, + "execution_count": null, "outputs": [] }, { @@ -1463,7 +1509,7 @@ "id": "dUu5UdsbpCy1", "outputId": "47d822fc-9616-477a-9d58-f52ab47982b7" }, - "execution_count": 257, + "execution_count": null, "outputs": [ { "output_type": "stream", @@ -1502,7 +1548,7 @@ "metadata": { "id": "P7FAagykpCmG" }, - "execution_count": 300, + "execution_count": null, "outputs": [] }, { @@ -1513,7 +1559,7 @@ "metadata": { "id": "Y74hvjABpXYa" }, - "execution_count": 301, + "execution_count": null, "outputs": [] }, { @@ -1539,7 +1585,7 @@ "id": "c34Ie_JSpXVt", "outputId": "b1657516-8848-4b8b-bdf3-1b118979f4c7" }, - "execution_count": 302, + "execution_count": null, "outputs": [ { "output_type": "execute_result", @@ -1565,7 +1611,7 @@ "id": "YfrApCbfpXTS", "outputId": "53ce422c-fbae-412f-a849-5c6665f94347" }, - "execution_count": 303, + "execution_count": null, "outputs": [ { "output_type": "execute_result", @@ -1593,7 +1639,7 @@ "id": "cva5m83-pXQi", "outputId": "bb860358-2911-4ab9-d769-b4f3e5b01276" }, - "execution_count": 304, + "execution_count": null, "outputs": [ { "output_type": "execute_result", @@ -1642,7 +1688,7 @@ "id": "nctQM_cUpXN6", "outputId": "3a479125-23fc-42ce-cb94-c7cbb9bc5f0f" }, - "execution_count": 305, + "execution_count": null, "outputs": [ { "output_type": "execute_result", @@ -1669,7 +1715,7 @@ "id": "zHqaqabFpXK-", "outputId": "a5f67a83-05a0-4c9a-a3aa-1b72305a212f" }, - "execution_count": 306, + "execution_count": null, "outputs": [ { "output_type": "execute_result", @@ -1695,7 +1741,7 @@ "id": "Rm6eaTpIpXH0", "outputId": "f16b81d1-0ccf-4124-dd66-2a59c45345e7" }, - "execution_count": 307, + "execution_count": null, "outputs": [ { "output_type": "execute_result", @@ -1718,7 +1764,7 @@ "metadata": { "id": "3nEc4nJTpXE_" }, - "execution_count": 266, + "execution_count": null, "outputs": [] }, { @@ -1729,7 +1775,7 @@ "metadata": { "id": "W-vWpFEPptY5" }, - "execution_count": 308, + "execution_count": null, "outputs": [] }, { @@ -1749,7 +1795,7 @@ "metadata": { "id": "_mDvqQ5AptVn" }, - "execution_count": 309, + "execution_count": null, "outputs": [] }, { @@ -1764,7 +1810,7 @@ "id": "ITk_zSDDptSv", "outputId": "0d8320dc-6ec6-4877-a204-170a1a888b54" }, - "execution_count": 310, + "execution_count": null, "outputs": [ { "output_type": "execute_result", @@ -1790,7 +1836,7 @@ "id": "kLdsXkVHptPm", "outputId": "46a39c8d-dfa6-4675-f971-2a4cea4cb34b" }, - "execution_count": 311, + "execution_count": null, "outputs": [ { "output_type": "execute_result", @@ -1812,7 +1858,7 @@ "metadata": { "id": "vPM0dY0jX_yj" }, - "execution_count": 312, + "execution_count": null, "outputs": [] }, { @@ -1827,7 +1873,7 @@ "id": "3DXntlPIYEDg", "outputId": "1347661a-01a2-43f2-cca9-81e6ad699265" }, - "execution_count": 313, + "execution_count": null, "outputs": [ { "output_type": "execute_result", @@ -1853,7 +1899,7 @@ "id": "FM_UUBtPptM9", "outputId": "638e2905-2e3a-46a5-cbef-9df410c9ce79" }, - "execution_count": 314, + "execution_count": null, "outputs": [ { "output_type": "execute_result", @@ -1937,7 +1983,7 @@ "metadata": { "id": "Fe5hjC_9ptKT" }, - "execution_count": 315, + "execution_count": null, "outputs": [] }, { @@ -1952,7 +1998,7 @@ "id": "Q0zmpxfrptHS", "outputId": "3a1eeec0-c68d-4483-d02f-5c1f67fa58b0" }, - "execution_count": 316, + "execution_count": null, "outputs": [ { "output_type": "execute_result", @@ -2134,7 +2180,7 @@ "id": "EP8E0gfvptEl", "outputId": "aec779b0-e150-48ef-a240-27ed4d68fe44" }, - "execution_count": 317, + "execution_count": null, "outputs": [ { "output_type": "execute_result", @@ -2160,7 +2206,7 @@ "id": "1ITXT_PAptBh", "outputId": "d63590d0-0c56-406d-c4bb-80bef8fd8aa5" }, - "execution_count": 318, + "execution_count": null, "outputs": [ { "output_type": "execute_result", @@ -2183,7 +2229,7 @@ "metadata": { "id": "z2Himo4-ps92" }, - "execution_count": 319, + "execution_count": null, "outputs": [] }, { @@ -2202,7 +2248,7 @@ "id": "2teoM5sjps7A", "outputId": "93b4b151-97d8-4068-8469-f304f8067fd9" }, - "execution_count": 320, + "execution_count": null, "outputs": [ { "output_type": "stream", @@ -2236,7 +2282,7 @@ "metadata": { "id": "UP7T50GKps0c" }, - "execution_count": 321, + "execution_count": null, "outputs": [] }, { @@ -2247,7 +2293,7 @@ "metadata": { "id": "Boyap8pipse1" }, - "execution_count": 322, + "execution_count": null, "outputs": [] }, { @@ -2262,7 +2308,7 @@ "id": "FSKPF94NqDMu", "outputId": "8e5d751c-0759-422d-bf46-cb9a7b25d54e" }, - "execution_count": 323, + "execution_count": null, "outputs": [ { "output_type": "stream", @@ -2305,7 +2351,7 @@ "id": "Gh1HOc0nqDAI", "outputId": "5590807f-bd11-4eeb-904e-369b1970cf92" }, - "execution_count": 324, + "execution_count": null, "outputs": [ { "output_type": "execute_result", @@ -2339,7 +2385,7 @@ "metadata": { "id": "hs2pqyifrWwf" }, - "execution_count": 296, + "execution_count": null, "outputs": [] }, { @@ -2350,7 +2396,7 @@ "metadata": { "id": "AHP4hJ-3rYC0" }, - "execution_count": 297, + "execution_count": null, "outputs": [] }, { @@ -2365,7 +2411,7 @@ "id": "ZlVuLx1qd8m7", "outputId": "4bfad379-aefc-4e73-aae2-148cf507bcbf" }, - "execution_count": 325, + "execution_count": null, "outputs": [ { "output_type": "execute_result", @@ -2397,7 +2443,7 @@ "id": "aIMGNDbpeBAp", "outputId": "bea2b826-041c-4dc2-aac3-75140a027899" }, - "execution_count": 326, + "execution_count": null, "outputs": [ { "output_type": "execute_result", @@ -2429,7 +2475,7 @@ "id": "Am2WtlHyrZy0", "outputId": "7b73649a-9b38-4a4d-a16b-97cb8293874e" }, - "execution_count": 327, + "execution_count": null, "outputs": [ { "output_type": "stream", @@ -2462,7 +2508,7 @@ "id": "syg7Ftq8rcTk", "outputId": "44f3bc9b-7981-45fd-bc8c-22646321b453" }, - "execution_count": 328, + "execution_count": null, "outputs": [ { "output_type": "stream", @@ -2485,7 +2531,7 @@ "id": "81Eo4m0Zreov", "outputId": "13fcb2f5-296f-4e00-bf65-3b37dbac7b57" }, - "execution_count": 329, + "execution_count": null, "outputs": [ { "output_type": "execute_result", @@ -2511,7 +2557,7 @@ "id": "qRqRU23Vrf0W", "outputId": "9ee72ce9-47de-40c7-8ebd-f656864ebd3e" }, - "execution_count": 330, + "execution_count": null, "outputs": [ { "output_type": "execute_result", @@ -2537,7 +2583,7 @@ "id": "qsI8pRM5rhl5", "outputId": "568825f3-c1ec-40b7-d48b-14046530e15f" }, - "execution_count": 331, + "execution_count": null, "outputs": [ { "output_type": "execute_result", @@ -2573,7 +2619,7 @@ "id": "U3VVHL-UrkCa", "outputId": "f12c40ba-7b88-4e01-84de-fc6aa1d2a141" }, - "execution_count": 332, + "execution_count": null, "outputs": [ { "output_type": "execute_result", @@ -2599,7 +2645,7 @@ "id": "eUFCCciArlLu", "outputId": "97da500a-d7c1-4822-e10a-42f2bb5882e4" }, - "execution_count": 333, + "execution_count": null, "outputs": [ { "output_type": "execute_result", @@ -2626,7 +2672,7 @@ "id": "2LnkkaOlrmhp", "outputId": "46e65722-9a6d-4929-99e8-88898a29f012" }, - "execution_count": 339, + "execution_count": null, "outputs": [ { "output_type": "execute_result", @@ -2662,7 +2708,7 @@ "metadata": { "id": "QHbV6P1Krogm" }, - "execution_count": 335, + "execution_count": null, "outputs": [] }, { @@ -2677,7 +2723,7 @@ "id": "T8-EEGvGrpeN", "outputId": "59bf3c52-12ef-4d0e-dc25-94340b2f49f3" }, - "execution_count": 340, + "execution_count": null, "outputs": [ { "output_type": "execute_result", @@ -2699,7 +2745,7 @@ "metadata": { "id": "hcIYHksfrrIS" }, - "execution_count": 341, + "execution_count": null, "outputs": [] }, { @@ -2719,7 +2765,7 @@ "id": "G3-q4lPvruG7", "outputId": "62500d33-ea1b-4cde-fe3e-07927d65708a" }, - "execution_count": 343, + "execution_count": null, "outputs": [ { "output_type": "stream", diff --git a/backend/microservice/PythonServer/project/api/templates/index.html b/backend/microservice/index.html index 98b35d52..98b35d52 100644 --- a/backend/microservice/PythonServer/project/api/templates/index.html +++ b/backend/microservice/index.html diff --git a/backend/microservice/mlservice.py b/backend/microservice/mlservice.py index 01a79c1a..3a0d41bd 100644 --- a/backend/microservice/mlservice.py +++ b/backend/microservice/mlservice.py @@ -1,4 +1,4 @@ -from typing_extensions import Self +#from typing_extensions import Self import pandas as pd import tensorflow as tf import keras @@ -335,6 +335,11 @@ def obuka(dataunos,params): ### 27)ROC fpr, tpr, _ = sm.roc_curve(y_test,y_pred) + # https://scikit-learn.org/stable/modules/generated/sklearn.metrics.confusion_matrix.html + # tn, fp, fn, tp = confusion_matrix(y_test, y_pred).ravel() + # Korelaciona matrica + # https://datatofish.com/correlation-matrix-pandas/ + ''' plt.plot(fpr, tpr, color='blue') plt.title('ROC') diff --git a/backend/microservice/network1.gv.pdf b/backend/microservice/network1.gv.pdf Binary files differnew file mode 100644 index 00000000..797b23db --- /dev/null +++ b/backend/microservice/network1.gv.pdf diff --git a/backend/microservice/PythonServer/project/api/titanic.csv b/backend/microservice/titanic.csv index 5cc466e9..5cc466e9 100644 --- a/backend/microservice/PythonServer/project/api/titanic.csv +++ b/backend/microservice/titanic.csv diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 5b23f3d2..0333f749 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -24,9 +24,11 @@ "@ng-bootstrap/ng-bootstrap": "^12.0.0", "@popperjs/core": "^2.10.2", "bootstrap": "^5.1.3", + "chart.js": "^3.7.1", "csv-parser": "^3.0.0", "mdb-angular-ui-kit": "^2.0.0", "ng-uikit-pro-standard": "^1.0.0", + "ng2-charts": "^3.0.8", "ngx-cookie-service": "^13.1.2", "ngx-csv-parser": "^0.0.7", "rxjs": "~7.5.0", @@ -3792,6 +3794,11 @@ "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", "dev": true }, + "node_modules/chart.js": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-3.7.1.tgz", + "integrity": "sha512-8knRegQLFnPQAheZV8MjxIXc5gQEfDFD897BJgv/klO/vtIyFFmgMXrNfgrXpbTr/XbTturxRgxIXx/Y+ASJBA==" + }, "node_modules/chokidar": { "version": "3.5.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", @@ -7376,6 +7383,11 @@ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "dev": true }, + "node_modules/lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==" + }, "node_modules/lodash.debounce": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", @@ -7949,6 +7961,21 @@ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" }, + "node_modules/ng2-charts": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/ng2-charts/-/ng2-charts-3.0.8.tgz", + "integrity": "sha512-ELlpN0b/IJO4ka/P2sFBKeng3bV7XOQuh40f0J5hx9UveWPaSxOYQAOiGxV7BN2VSnKq6GRkjRvqTrcQPyJYww==", + "dependencies": { + "lodash-es": "^4.17.15", + "tslib": "^2.3.0" + }, + "peerDependencies": { + "@angular/common": ">=11.0.0", + "@angular/core": ">=11.0.0", + "chart.js": "^3.4.0", + "rxjs": "^6.5.3 || ^7.4.0" + } + }, "node_modules/ngx-cookie-service": { "version": "13.1.2", "resolved": "https://registry.npmjs.org/ngx-cookie-service/-/ngx-cookie-service-13.1.2.tgz", @@ -14259,6 +14286,11 @@ "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", "dev": true }, + "chart.js": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-3.7.1.tgz", + "integrity": "sha512-8knRegQLFnPQAheZV8MjxIXc5gQEfDFD897BJgv/klO/vtIyFFmgMXrNfgrXpbTr/XbTturxRgxIXx/Y+ASJBA==" + }, "chokidar": { "version": "3.5.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", @@ -16856,6 +16888,11 @@ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "dev": true }, + "lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==" + }, "lodash.debounce": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", @@ -17286,6 +17323,15 @@ } } }, + "ng2-charts": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/ng2-charts/-/ng2-charts-3.0.8.tgz", + "integrity": "sha512-ELlpN0b/IJO4ka/P2sFBKeng3bV7XOQuh40f0J5hx9UveWPaSxOYQAOiGxV7BN2VSnKq6GRkjRvqTrcQPyJYww==", + "requires": { + "lodash-es": "^4.17.15", + "tslib": "^2.3.0" + } + }, "ngx-cookie-service": { "version": "13.1.2", "resolved": "https://registry.npmjs.org/ngx-cookie-service/-/ngx-cookie-service-13.1.2.tgz", diff --git a/frontend/package.json b/frontend/package.json index 01cdf462..c3f0310e 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -26,9 +26,11 @@ "@ng-bootstrap/ng-bootstrap": "^12.0.0", "@popperjs/core": "^2.10.2", "bootstrap": "^5.1.3", + "chart.js": "^3.7.1", "csv-parser": "^3.0.0", "mdb-angular-ui-kit": "^2.0.0", "ng-uikit-pro-standard": "^1.0.0", + "ng2-charts": "^3.0.8", "ngx-cookie-service": "^13.1.2", "ngx-csv-parser": "^0.0.7", "rxjs": "~7.5.0", @@ -49,4 +51,4 @@ "karma-jasmine-html-reporter": "~1.7.0", "typescript": "~4.5.2" } -}
\ No newline at end of file +} diff --git a/frontend/src/app/_data/Model.ts b/frontend/src/app/_data/Model.ts index a891c10c..0768a374 100644 --- a/frontend/src/app/_data/Model.ts +++ b/frontend/src/app/_data/Model.ts @@ -12,7 +12,7 @@ export default class Model { public columnToPredict: string = '', public randomOrder: boolean = true, public randomTestSet: boolean = true, - public randomTestSetDistribution: number = 0.10, //0.1-0.9 (10% - 90%) + public randomTestSetDistribution: number = 0.1, //0.1-0.9 (10% - 90%) JESTE OVDE ZAKUCANO 10, AL POSLATO JE KAO 0.1 BACK-U // Neural net training settings public type: ANNType = ANNType.FullyConnected, @@ -39,21 +39,61 @@ export enum ANNType { // removeOutliers export enum Encoding { Label = 'label', - OneHot = 'one hot' + OneHot = 'one hot', + BackwardDifference = 'backward difference', + BaseN = 'baseN', + Binary = 'binary', + CatBoost = 'cat boost', + Count = 'count', + GLMM = 'glmm', + Hashing = 'hashing', + Helmert = 'helmert', + JamesStein = 'james stein', + LeaveOneOut = 'leave one out', + MEstimate = 'MEstimate', + Ordinal = 'ordinal', + Sum = 'sum', + Polynomial = 'polynomial', + Target = 'target', + WOE = 'woe', + Quantile = 'quantile' } export enum ActivationFunction { + // linear + Binary_Step = 'binaryStep', + Linear = 'linear', + // non-linear Relu = 'relu', + Leaky_Relu = 'leakyRelu', + Parameterised_Relu = 'parameterisedRelu', + Exponential_Linear_Unit = 'exponentialLinearUnit', + Swish = 'swish', Sigmoid = 'sigmoid', Tanh = 'tanh', - Linear = 'linear' + Softmax = 'softmax' } export enum LossFunction { + // binary classification loss functions BinaryCrossEntropy = 'binary_crossentropy', - MeanSquaredError = 'mean_squared_error' + HingeLoss = 'hinge_loss', + // multi-class classiication loss functions + CategoricalCrossEntropy = 'categorical_crossentropy', + KLDivergence = 'kullback_leibler_divergence', + // regression loss functions + MeanSquaredError = 'mean_squared_error', + MeanAbsoluteError = 'mean_absolute_error', + HuberLoss = 'Huber', } export enum Optimizer { - Adam = 'adam' + Adam = 'Adam', + Adadelta = 'Adadelta', + Adagrad = 'Adagrad', + Ftrl = 'Ftrl', + Nadam = 'Nadam', + SGD = 'SGD', + SGDMomentum = 'SGDMomentum', + RMSprop = 'RMSprop' }
\ No newline at end of file diff --git a/frontend/src/app/_elements/dataset-load/dataset-load.component.html b/frontend/src/app/_elements/dataset-load/dataset-load.component.html index fcec6ec3..76fc40e2 100644 --- a/frontend/src/app/_elements/dataset-load/dataset-load.component.html +++ b/frontend/src/app/_elements/dataset-load/dataset-load.component.html @@ -30,7 +30,7 @@ </div> </div> - <div class="table-responsive"> + <div class="table-responsive" *ngIf="hasInput"> <table *ngIf="csvRecords.length > 0 && hasHeader" class="table table-bordered table-light mt-4"> <thead> <tr> @@ -53,7 +53,7 @@ </table> </div> - <div *ngIf="csvRecords.length > 0" id="info"> + <div *ngIf="csvRecords.length > 0 && hasInput" id="info"> . . . <br> {{rowsNumber}} x {{colsNumber}} </div> diff --git a/frontend/src/app/_elements/dataset-load/dataset-load.component.ts b/frontend/src/app/_elements/dataset-load/dataset-load.component.ts index 913592eb..bccf13b7 100644 --- a/frontend/src/app/_elements/dataset-load/dataset-load.component.ts +++ b/frontend/src/app/_elements/dataset-load/dataset-load.component.ts @@ -16,7 +16,7 @@ export class DatasetLoadComponent { hasHeader: boolean = true; - slice: string = ""; + hasInput: boolean = false; csvRecords: any[] = []; files: File[] = []; @@ -33,6 +33,15 @@ export class DatasetLoadComponent { changeListener($event: any): void { this.files = $event.srcElement.files; + if (this.files.length == 0 || this.files[0] == null) { + //console.log("NEMA FAJLA"); + //this.loaded.emit("not loaded"); + this.hasInput = false; + return; + } + else + this.hasInput = true; + console.log(this.files); this.update(); } diff --git a/frontend/src/app/_elements/item-dataset/item-dataset.component.html b/frontend/src/app/_elements/item-dataset/item-dataset.component.html index cf39a125..46840cdd 100644 --- a/frontend/src/app/_elements/item-dataset/item-dataset.component.html +++ b/frontend/src/app/_elements/item-dataset/item-dataset.component.html @@ -2,7 +2,7 @@ <div class="card-header"> {{dataset.name}} </div> - <div class="card-body"> + <div class="card-body overflow-hidden"> <p class="card-text"> {{dataset.description}} </p> diff --git a/frontend/src/app/_modals/login-modal/login-modal.component.html b/frontend/src/app/_modals/login-modal/login-modal.component.html index d694ea58..d7836848 100644 --- a/frontend/src/app/_modals/login-modal/login-modal.component.html +++ b/frontend/src/app/_modals/login-modal/login-modal.component.html @@ -20,12 +20,12 @@ <input [(ngModel)]="password" name="password" type="password" id="password" class="form-control form-control" placeholder="Unesite lozinku..." /> </div> - - <div class="text-center text-lg-start mt-5 pt-2"> - <p *ngIf="wrongCreds" class="small fw-bold mt-2 pt-1 mb-0 text-danger">Lozinka ili e-mail su pogrešni - </p> - </div> </form> + + <div class="text-center text-lg-start mt-5"> + <p *ngIf="wrongCreds" class="small fw-bold text-danger text-center">Unesite ispravan e-mail i lozinku.</p> + </div> + <div class="col-md-12 d-flex justify-content-center"> <button type="button" class="btn btn-lg" style="color:white; background-color: #003459; margin-right: 10px;" (click)="doLogin()">Prijavite se</button> <button type="button" class="btn btn-lg btn-outline-secondary" data-bs-dismiss="modal" (click)="resetData()">Odustanite</button> diff --git a/frontend/src/app/_modals/login-modal/login-modal.component.ts b/frontend/src/app/_modals/login-modal/login-modal.component.ts index d17d7017..1b634c9a 100644 --- a/frontend/src/app/_modals/login-modal/login-modal.component.ts +++ b/frontend/src/app/_modals/login-modal/login-modal.component.ts @@ -13,7 +13,7 @@ export class LoginModalComponent implements OnInit { username: string = ''; password: string = ''; - public wrongCreds: boolean = false; //RAZMOTRITI + wrongCreds: boolean = false; constructor( private authService: AuthService, @@ -26,17 +26,26 @@ export class LoginModalComponent implements OnInit { doLogin() { if (this.username.length > 0 && this.password.length > 0) { - this.authService.login(this.username, this.password).subscribe((response) => { //ako nisu ok podaci, ne ide hide nego mora opet da ukucava!!!!podesi + this.authService.login(this.username, this.password).subscribe((response) => { console.log(response); - this.authService.authenticate(response); - (<HTMLSelectElement>document.getElementById('closeButton')).click(); - }, error => { - console.warn(error); //NETACNI PODACI + + if (response == "Username doesn't exist" || response == "Wrong password") { + this.wrongCreds = true; + this.password = ''; + } + else { + this.authService.authenticate(response); + (<HTMLSelectElement>document.getElementById('closeButton')).click(); + } }); } - + else { + this.wrongCreds = true; + this.password = ''; + } } resetData() { + this.wrongCreds = false; this.username = ''; this.password = ''; } diff --git a/frontend/src/app/_modals/register-modal/register-modal.component.html b/frontend/src/app/_modals/register-modal/register-modal.component.html index 7098c040..68025a46 100644 --- a/frontend/src/app/_modals/register-modal/register-modal.component.html +++ b/frontend/src/app/_modals/register-modal/register-modal.component.html @@ -4,7 +4,7 @@ <div class="modal-dialog modal-dialog-centered modal-dialog modal-lg"> <div class="modal-content"> <div class="modal-header" style="background-color: #003459;"> - <button type="button" class="btn-close" data-bs-dismiss="modal" style="background-color: white;" + <button id="closeButtonReg" type="button" class="btn-close" data-bs-dismiss="modal" style="background-color: white;" aria-label="Close" (click)="resetData()"></button> </div> <div class="modal-body" style="color:#003459"> diff --git a/frontend/src/app/_modals/register-modal/register-modal.component.ts b/frontend/src/app/_modals/register-modal/register-modal.component.ts index c02a4e1a..c045f1ce 100644 --- a/frontend/src/app/_modals/register-modal/register-modal.component.ts +++ b/frontend/src/app/_modals/register-modal/register-modal.component.ts @@ -136,15 +136,21 @@ export class RegisterModalComponent implements OnInit { .subscribe( (response) => { console.log(response); - if (response === 'User added') { - this.resetData(); - (<HTMLSelectElement>document.getElementById('linkToLoginModal')).click(); + if (response == 'User added') { + //nakon sto je registrovan, nek bude ulogovan + this.authService.login(this.username, this.pass1).subscribe((response) => { + + this.authService.authenticate(response); + console.log("close button"); + (<HTMLSelectElement>document.getElementById('closeButtonReg')).click(); + //(<HTMLSelectElement>document.getElementById('linkToLoginModal')).click(); + }, (error) => console.warn(error)); } - else if (response === 'Email Already Exists') { + else if (response == 'Email Already Exists') { alert('Nalog sa unetim email-om već postoji!'); (<HTMLSelectElement>document.getElementById('email')).focus(); } - else if (response === 'Username Already Exists') { + else if (response == 'Username Already Exists') { alert('Nalog sa unetim korisničkim imenom već postoji!'); (<HTMLSelectElement>document.getElementById('username-register')).focus(); } diff --git a/frontend/src/app/_pages/add-model/add-model.component.css b/frontend/src/app/_pages/add-model/add-model.component.css index 4bf569cc..6d961287 100644 --- a/frontend/src/app/_pages/add-model/add-model.component.css +++ b/frontend/src/app/_pages/add-model/add-model.component.css @@ -15,4 +15,21 @@ #wrapper { color: #003459; +} + +.btnType1 { + background-color: #003459; + color: white; +} +.btnType2 { + background-color: white; + color: #003459; + border-color: #003459; +} +.selectedDatasetClass { + /*border-color: 2px solid #003459;*/ + background-color: lightblue; +} +ul li:hover { + background-color: lightblue; }
\ No newline at end of file diff --git a/frontend/src/app/_pages/add-model/add-model.component.html b/frontend/src/app/_pages/add-model/add-model.component.html index c6f21f1e..33066f80 100644 --- a/frontend/src/app/_pages/add-model/add-model.component.html +++ b/frontend/src/app/_pages/add-model/add-model.component.html @@ -6,7 +6,7 @@ <div id="container" class="container p-5" style="background-color: white; min-height: 100%;"> - <div class="form-group row mb-4 d-flex justify-content-center"> + <div class="form-group row mt-3 mb-2 d-flex justify-content-center"> <!--justify-content-center--> <h2 class="col-2"> Nov model: </h2> <div class="col-3"> @@ -26,22 +26,87 @@ </div> </div> - <div class="mt-5 justify-content-center"> - <h2>Izvor podataka:</h2> - <app-dataset-load id="dataset" (loaded)="datasetLoaded = true"></app-dataset-load> + <div class="py-3 pr-5 justify-content-center"> + + <div class="col-12 d-flex my-5"> + <h2 class="">Izvor podataka:</h2> + <div class="col-1"> + </div> + <button type="button" id="btnMyDataset" class="btn" (click)="viewMyDatasetsForm()" + [ngClass]="{'btnType1': showMyDatasets, 'btnType2': !showMyDatasets}"> + Izaberite dataset iz kolekcije + </button> + <h3 class="mt-3 mx-3">ili</h3> + <button type="button" id="btnNewDataset" class="btn" (click)="viewNewDatasetForm()" + [ngClass]="{'btnType1': !showMyDatasets, 'btnType2': showMyDatasets}"> + Dodajte novi dataset + </button> + </div> + + <!-- POSTOJECI ILI NOVI DATASET --> + + <!-- POSTOJECI --> + <div class="px-5"> + <div *ngIf="showMyDatasets" class="overflow-auto" style="max-height: 500px;"> + <ul class="list-group"> + <li class="list-group-item p-3" *ngFor="let dataset of myDatasets" [ngClass]="{'selectedDatasetClass': this.selectedDataset == dataset}"> + <app-item-dataset name="usersDataset" [dataset]="dataset" (click)="selectThisDataset(dataset)"></app-item-dataset> + </li> + </ul> + </div> + </div> + + <!-- NOVI --> + <app-dataset-load *ngIf="!showMyDatasets" id="dataset" (loaded)="datasetLoaded = true"></app-dataset-load> </div> - <div *ngIf="datasetLoaded"> - <div *ngIf="datasetLoadComponent" class="row"> + + <!-- ULAZNE/IZLAZNE KOLONE - POSTOJECI DATASET --> + <div *ngIf="showMyDatasets && this.selectedDataset" class="mt-4"> + <h2 class="text-center"> + Izabrali ste dataset: <span style="color: #003459; font-weight: bold">{{this.selectedDataset.name}}</span> + </h2> + <div class="row mt-5"> + <div class="col d-flex justify-content-center"> + <h3>Izaberite ulazne kolone:</h3> + <div id="divInputs" class="form-check mt-2"> + <br> + <div *ngFor="let item of this.selectedDataset.header; let i = index"> + <input class="form-check-input" type="checkbox" value="{{item}}" + id="cb_{{item}}" name="cbsExisting" checked [disabled]="this.selectedOutputColumnVal == item"> + <label class="form-check-label" for="cb_{{item}}"> + {{item}} + </label> + </div> + </div> + </div> + <div class="col d-flex justify-content-left"> + <h3>Izaberite izlaznu kolonu:</h3> + <div id="divOutputs" class="form-check mt-2"> + <br> + <div *ngFor="let item of this.selectedDataset.header; let i = index"> + <input class="form-check-input" type="radio" value="{{item}}" + id="rb_{{item}}" name="rbsExisting" (change)="this.selectedOutputColumnVal = item"> + <label class="form-check-label" for="rb_{{item}}"> + {{item}} + </label> + </div> + </div> + </div> + </div> + </div> + + + <!-- ULAZNE/IZLAZNE KOLONE - NOVI DATASET--> + <div *ngIf="!showMyDatasets && datasetLoaded"> + <div *ngIf="datasetLoadComponent && datasetLoadComponent.files[0]" class="row"> <div class="col d-flex justify-content-center"> <h3>Izaberite ulazne kolone:</h3> <div id="divInputs" class="form-check mt-2"> <br> <div *ngFor="let item of datasetLoadComponent.dataset.header; let i = index"> - <input *ngIf="i == 0" class="form-check-input" type="checkbox" value="{{item}}" - id="cb_{{item}}" name="cbs" checked> - <input *ngIf="i != 0" class="form-check-input" type="checkbox" value="{{item}}" - id="cb_{{item}}" name="cbs"> + <input class="form-check-input" type="checkbox" value="{{item}}" + id="cb_{{item}}" name="cbsNew" checked [disabled]="this.selectedOutputColumnVal == item"> <label class="form-check-label" for="cb_{{item}}"> {{item}} </label> @@ -53,10 +118,8 @@ <div id="divOutputs" class="form-check mt-2"> <br> <div *ngFor="let item of datasetLoadComponent.dataset.header; let i = index"> - <input *ngIf="i == 0" class="form-check-input" type="radio" value="{{item}}" - id="rb_{{item}}" name="rbs" checked> - <input *ngIf="i != 0" class="form-check-input" type="radio" value="{{item}}" - id="rb_{{item}}" name="rbs"> + <input class="form-check-input" type="radio" value="{{item}}" + id="rb_{{item}}" name="rbsNew" (change)="this.selectedOutputColumnVal = item"> <label class="form-check-label" for="rb_{{item}}"> {{item}} </label> @@ -193,15 +256,10 @@ <div class="col-1"> </div> <div class="col-5"> - <label for="type" class="form-check-label">Podela test skupa: - <input class="form-check-input" type="checkbox" [checked]="newModel.randomTestSet" + <label for="splitYesNo" class="form-check-label">Podela test skupa: + <input id="splitYesNo" class="form-check-input" type="checkbox" [checked]="newModel.randomTestSet" (change)="newModel.randomTestSet = !newModel.randomTestSet"> - </label> - test - <mat-slider min="0.1" max="0.9" step="0.1" value="0.2" name="randomTestSetDistribution" thumbLabel - [disabled]="!newModel.randomTestSet" [(ngModel)]="newModel.randomTestSetDistribution"> - </mat-slider> - trening + </label> </div> <div class="col"> </div> @@ -224,9 +282,14 @@ </option> </select> </div> - <div class="col"> + <div class="col-1"> </div> - <div class="col"> + <div class="col-2"> + <label for="percentage" class="form-label">Procenat podataka koji se uzima za trening skup:</label> + </div> + <div class="col-1"> + <input id="percentage" type="number" class="form-control" min="10" max="90" step="10" value="90" [(ngModel)]="tempTestSetDistribution" + [disabled] = "!newModel.randomTestSet"> </div> </div> @@ -247,7 +310,14 @@ </option> </select> </div> + <div class="col-1"> + </div> <div class="col"> + trening + <mat-slider min="10" max="90" step="10" value="10" name="randomTestSetDistribution" thumbLabel + [disabled]="!newModel.randomTestSet" [(ngModel)]="tempTestSetDistribution"> + </mat-slider> + test </div> <div class="col"> </div> diff --git a/frontend/src/app/_pages/add-model/add-model.component.ts b/frontend/src/app/_pages/add-model/add-model.component.ts index a4cabb82..7bfb7204 100644 --- a/frontend/src/app/_pages/add-model/add-model.component.ts +++ b/frontend/src/app/_pages/add-model/add-model.component.ts @@ -1,10 +1,10 @@ import { Component, OnInit, ViewChild } from '@angular/core'; -import { Observable, of } from 'rxjs'; import Model from 'src/app/_data/Model'; import { ANNType, Encoding, ActivationFunction, LossFunction, Optimizer } from 'src/app/_data/Model'; import { DatasetLoadComponent } from 'src/app/_elements/dataset-load/dataset-load.component'; import { ModelsService } from 'src/app/_services/models.service'; import shared from 'src/app/Shared'; +import Dataset from 'src/app/_data/Dataset'; @Component({ @@ -27,63 +27,145 @@ export class AddModelComponent implements OnInit { Object = Object; shared = shared; + selectedOutputColumnVal: string = ''; + + showMyDatasets: boolean = true; + myDatasets?: Dataset[]; + existingDatasetSelected: boolean = false; + selectedDataset?: Dataset; + + tempTestSetDistribution: number = 90; + constructor(private models: ModelsService) { this.newModel = new Model(); + + this.models.getMyDatasets().subscribe((datasets) => { + this.myDatasets = datasets; + }); } ngOnInit(): void { + (<HTMLInputElement>document.getElementById("btnMyDataset")).focus(); + } + + viewMyDatasetsForm() { + this.showMyDatasets = true; + this.resetSelectedDataset(); + this.datasetLoaded = false; + this.resetCbsAndRbs(); + } + viewNewDatasetForm() { + this.showMyDatasets = false; + this.resetSelectedDataset(); + this.resetCbsAndRbs(); } addModel() { - this.saveModel(false); //trajno cuvanje + if (!this.showMyDatasets) + this.saveModelWithNewDataset(); + else + this.saveModelWithExistingDataset(); } trainModel() { - this.saveModel(true).subscribe((modelId: any) => { + this.saveModelWithNewDataset().subscribe((modelId: any) => { if (modelId) this.models.trainModel(modelId); }); //privremeno cuvanje modela => vraca id sacuvanog modela koji cemo da treniramo sad } - saveModel(temporary: boolean): any { + saveModelWithNewDataset(): any { + this.getCheckedInputCols(); this.getCheckedOutputCol(); + if (this.validationInputsOutput()) { console.log('ADD MODEL: STEP 1 - UPLOAD FILE'); if (this.datasetLoadComponent) { + this.models.uploadData(this.datasetLoadComponent.files[0]).subscribe((file) => { console.log('ADD MODEL: STEP 2 - ADD DATASET WITH FILE ID ' + file._id); if (this.datasetLoadComponent) { this.datasetLoadComponent.dataset.fileId = file._id; this.datasetLoadComponent.dataset.username = shared.username; + this.models.addDataset(this.datasetLoadComponent.dataset).subscribe((dataset) => { console.log('ADD MODEL: STEP 3 - ADD MODEL WITH DATASET ID ', dataset._id); this.newModel.datasetId = dataset._id; + + //da se doda taj dataset u listu postojecih, da bude izabran + this.refreshMyDatasetList(); + this.showMyDatasets = true; + this.selectThisDataset(dataset); + + this.newModel.randomTestSetDistribution = 1 - Math.round(this.tempTestSetDistribution / 100 * 10) / 10; + this.tempTestSetDistribution = 90; this.newModel.username = shared.username; + this.models.addModel(this.newModel).subscribe((response) => { console.log('ADD MODEL: DONE! REPLY:\n', response); - }); - }); - } + }, (error) => { + alert("Model sa unetim nazivom već postoji u Vašoj kolekciji.\nPromenite naziv modela i nastavite sa kreiranim datasetom."); + }); //kraj addModel subscribe + }, (error) => { + alert("Dataset sa unetim nazivom već postoji u Vašoj kolekciji.\nIzmenite naziv ili iskoristite postojeći dataset."); + }); //kraj addDataset subscribe + } //kraj treceg ifa + }, (error) => { + //alert("greska uploadData"); + }); //kraj uploadData subscribe + + } //kraj drugog ifa + } //kraj prvog ifa + } + + saveModelWithExistingDataset(): any { + + if (this.selectedDataset) { //dataset je izabran + this.getCheckedInputCols(); + this.getCheckedOutputCol(); + + if (this.validationInputsOutput()) { + this.newModel.datasetId = this.selectedDataset._id; + + this.newModel.randomTestSetDistribution = 1 - Math.round(this.tempTestSetDistribution / 100 * 10) / 10; + this.tempTestSetDistribution = 90; + this.newModel.username = shared.username; + + this.models.addModel(this.newModel).subscribe((response) => { + console.log('ADD MODEL: DONE! REPLY:\n', response); + }, (error) => { + alert("Model sa unetim nazivom već postoji u Vašoj kolekciji.\nPromenite naziv modela i nastavite sa kreiranim datasetom."); }); } } + else { + alert("Molimo Vas da izaberete neki dataset iz kolekcije."); + } } getCheckedInputCols() { this.newModel.inputColumns = []; - let checkboxes = document.getElementsByName("cbs"); - + let checkboxes: any; + if (this.showMyDatasets) + checkboxes = document.getElementsByName("cbsExisting"); + else + checkboxes = document.getElementsByName("cbsNew"); + for (let i = 0; i < checkboxes.length; i++) { let thatCb = <HTMLInputElement>checkboxes[i]; - if (thatCb.checked) + if (thatCb.checked == true && thatCb.disabled == false) this.newModel.inputColumns.push(thatCb.value); } //console.log(this.checkedInputCols); } getCheckedOutputCol() { this.newModel.columnToPredict = ''; - let radiobuttons = document.getElementsByName("rbs"); + let radiobuttons: any; + if (this.showMyDatasets) + radiobuttons = document.getElementsByName("rbsExisting"); + else + radiobuttons = document.getElementsByName("rbsNew"); for (let i = 0; i < radiobuttons.length; i++) { let thatRb = <HTMLInputElement>radiobuttons[i]; @@ -95,8 +177,16 @@ export class AddModelComponent implements OnInit { //console.log(this.checkedOutputCol); } validationInputsOutput(): boolean { - if (this.newModel.inputColumns.length == 0) { - alert("Molimo Vas da izaberete ulaznu kolonu/kolone za mrežu.") + if (this.newModel.inputColumns.length == 0 && this.newModel.columnToPredict == '') { + alert("Molimo Vas da izaberete ulazne i izlazne kolone za mrežu."); + return false; + } + else if (this.newModel.inputColumns.length == 0) { + alert("Molimo Vas da izaberete ulaznu kolonu/kolone za mrežu."); + return false; + } + else if (this.newModel.columnToPredict == '') { + alert("Molimo Vas da izaberete izlaznu kolonu za mrežu."); return false; } for (let i = 0; i < this.newModel.inputColumns.length; i++) { @@ -109,4 +199,65 @@ export class AddModelComponent implements OnInit { return true; } + selectThisDataset(dataset: Dataset) { + this.selectedDataset = dataset; + this.existingDatasetSelected = true; + + /*let datasets = document.getElementsByClassName("usersDataset") as HTMLCollection; + for (let i = 0; i < datasets.length; i++) { + if (datasets[i]._id == dataset._id) + }*/ + + this.resetCbsAndRbs(); + } + + resetSelectedDataset(): boolean { + this.existingDatasetSelected = false; + this.selectedDataset = undefined; + return true; + } + resetCbsAndRbs(): boolean { + this.uncheckRbs(); + this.checkAllCbs(); + return true; + } + checkAllCbs() { + let checkboxes: any; + //if (this.showMyDatasets) + checkboxes = document.getElementsByName("cbsExisting"); + //else + //checkboxes = document.getElementsByName("cbsNew"); + + for (let i = 0; i < checkboxes.length; i++) { + (<HTMLInputElement>checkboxes[i]).checked = true; + (<HTMLInputElement>checkboxes[i]).disabled = false; + } + + checkboxes = document.getElementsByName("cbsNew"); + for (let i = 0; i < checkboxes.length; i++) { + (<HTMLInputElement>checkboxes[i]).checked = true; + (<HTMLInputElement>checkboxes[i]).disabled = false; + } + } + uncheckRbs() { + this.selectedOutputColumnVal = ''; + let radiobuttons: any; + //if (this.showMyDatasets) + radiobuttons = document.getElementsByName("rbsExisting"); + //else + //radiobuttons = document.getElementsByName("rbsNew"); + + for (let i = 0; i < radiobuttons.length; i++) + (<HTMLInputElement>radiobuttons[i]).checked = false; + radiobuttons = document.getElementsByName("rbsNew"); + for (let i = 0; i < radiobuttons.length; i++) + (<HTMLInputElement>radiobuttons[i]).checked = false; + } + + refreshMyDatasetList() { + this.models.getMyDatasets().subscribe((datasets) => { + this.myDatasets = datasets; + }); + } + } diff --git a/frontend/src/app/_services/models.service.ts b/frontend/src/app/_services/models.service.ts index 8299016b..30d63956 100644 --- a/frontend/src/app/_services/models.service.ts +++ b/frontend/src/app/_services/models.service.ts @@ -38,4 +38,8 @@ export class ModelsService { trainModel(modelId: string): Observable<any> { return this.http.post(`${API_SETTINGS.apiURL}/model/train`, modelId, { headers: this.authService.authHeader() }); } + + getMyDatasets(): Observable<Dataset[]> { + return this.http.get<Dataset[]>(`${API_SETTINGS.apiURL}/dataset/mydatasets`, { headers: this.authService.authHeader() });//responsetype text da l treba?? + } } diff --git a/frontend/src/app/app.component.html b/frontend/src/app/app.component.html index 35e5adb1..24828a06 100644 --- a/frontend/src/app/app.component.html +++ b/frontend/src/app/app.component.html @@ -1,4 +1,6 @@ <app-navbar></app-navbar> <div class="container h-100"> <router-outlet></router-outlet> -</div>
\ No newline at end of file + <app-barchart></app-barchart> + <app-scatterchart></app-scatterchart> +</div> diff --git a/frontend/src/app/app.module.ts b/frontend/src/app/app.module.ts index 5aa405fb..7f076421 100644 --- a/frontend/src/app/app.module.ts +++ b/frontend/src/app/app.module.ts @@ -6,6 +6,8 @@ import { HttpClientModule } from '@angular/common/http'; import { MatSliderModule } from '@angular/material/slider'; import { MatIconModule } from '@angular/material/icon'; +import {NgChartsModule} from 'ng2-charts'; + import { AppComponent } from './app.component'; import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; import { DatasetLoadComponent } from './_elements/dataset-load/dataset-load.component'; @@ -29,6 +31,8 @@ import { MyModelsComponent } from './_pages/my-models/my-models.component'; import { BrowseDatasetsComponent } from './_pages/browse-datasets/browse-datasets.component'; import { BrowsePredictorsComponent } from './_pages/browse-predictors/browse-predictors.component'; import { PredictComponent } from './_pages/predict/predict.component'; +import { ScatterchartComponent } from './scatterchart/scatterchart.component'; +import { BarchartComponent } from './barchart/barchart.component'; @NgModule({ declarations: [ @@ -49,7 +53,9 @@ import { PredictComponent } from './_pages/predict/predict.component'; MyModelsComponent, BrowseDatasetsComponent, BrowsePredictorsComponent, - PredictComponent + PredictComponent, + ScatterchartComponent, + BarchartComponent ], imports: [ BrowserModule, @@ -61,7 +67,8 @@ import { PredictComponent } from './_pages/predict/predict.component'; MaterialModule, ReactiveFormsModule, MatSliderModule, - MatIconModule + MatIconModule, + NgChartsModule ], providers: [], bootstrap: [AppComponent] diff --git a/frontend/src/app/barchart/barchart.component.css b/frontend/src/app/barchart/barchart.component.css new file mode 100644 index 00000000..c3634c9f --- /dev/null +++ b/frontend/src/app/barchart/barchart.component.css @@ -0,0 +1,6 @@ +#divBarChart{ + background-color: beige; + display: block; + width: 400px; + height: 200px; +} diff --git a/frontend/src/app/barchart/barchart.component.html b/frontend/src/app/barchart/barchart.component.html new file mode 100644 index 00000000..48b7bd3e --- /dev/null +++ b/frontend/src/app/barchart/barchart.component.html @@ -0,0 +1,4 @@ +<p>Bar chart:</p> +<div id="divBarChart"> + <canvas id="Barchart"> </canvas> +</div>
\ No newline at end of file diff --git a/frontend/src/app/barchart/barchart.component.spec.ts b/frontend/src/app/barchart/barchart.component.spec.ts new file mode 100644 index 00000000..8b346d1c --- /dev/null +++ b/frontend/src/app/barchart/barchart.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { BarchartComponent } from './barchart.component'; + +describe('BarchartComponent', () => { + let component: BarchartComponent; + let fixture: ComponentFixture<BarchartComponent>; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ BarchartComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(BarchartComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/frontend/src/app/barchart/barchart.component.ts b/frontend/src/app/barchart/barchart.component.ts new file mode 100644 index 00000000..def64b7d --- /dev/null +++ b/frontend/src/app/barchart/barchart.component.ts @@ -0,0 +1,54 @@ +import { Component, OnInit } from '@angular/core'; +import {Chart} from 'node_modules/chart.js'; + +@Component({ + selector: 'app-barchart', + templateUrl: './barchart.component.html', + styleUrls: ['./barchart.component.css'] +}) +export class BarchartComponent implements OnInit { + + constructor() { } + + ngOnInit(){ + const myChart = new Chart("Barchart", { + type: 'bar', + data: { + labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'], + datasets: [{ + label: 'Number of Votes', + data: [12, 19, 3, 5, 2, 3], + backgroundColor: [ + 'rgba(255, 99, 132, 1)', + 'rgba(54, 162, 235, 1)', + 'rgba(255, 206, 86, 1)', + 'rgba(75, 192, 192, 1)', + 'rgba(153, 102, 255, 1)', + 'rgba(255, 159, 64, 1)' + ], + borderColor: [ + 'rgba(255, 99, 132, 1)', + 'rgba(54, 162, 235, 1)', + 'rgba(255, 206, 86, 1)', + 'rgba(75, 192, 192, 1)', + 'rgba(153, 102, 255, 1)', + 'rgba(255, 159, 64, 1)' + ], + borderWidth: 1 + }] + }, + options: { + scales: { + y: { + beginAtZero: true + } + } + } + + + }); + + + } + +} diff --git a/frontend/src/app/scatterchart/scatterchart.component.css b/frontend/src/app/scatterchart/scatterchart.component.css new file mode 100644 index 00000000..5735217e --- /dev/null +++ b/frontend/src/app/scatterchart/scatterchart.component.css @@ -0,0 +1,6 @@ +#divScatterChart{ + background-color: beige; + display: block; + width: 400px; + height: 200px; +}
\ No newline at end of file diff --git a/frontend/src/app/scatterchart/scatterchart.component.html b/frontend/src/app/scatterchart/scatterchart.component.html new file mode 100644 index 00000000..2b30fe1f --- /dev/null +++ b/frontend/src/app/scatterchart/scatterchart.component.html @@ -0,0 +1,4 @@ +<p>Scatter chart:</p> +<div id="divScatterChart"> + <canvas id="ScatterCharts"> </canvas> +</div>
\ No newline at end of file diff --git a/frontend/src/app/scatterchart/scatterchart.component.spec.ts b/frontend/src/app/scatterchart/scatterchart.component.spec.ts new file mode 100644 index 00000000..1db81051 --- /dev/null +++ b/frontend/src/app/scatterchart/scatterchart.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ScatterchartComponent } from './scatterchart.component'; + +describe('ScatterchartComponent', () => { + let component: ScatterchartComponent; + let fixture: ComponentFixture<ScatterchartComponent>; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ScatterchartComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ScatterchartComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/frontend/src/app/scatterchart/scatterchart.component.ts b/frontend/src/app/scatterchart/scatterchart.component.ts new file mode 100644 index 00000000..1da88fe7 --- /dev/null +++ b/frontend/src/app/scatterchart/scatterchart.component.ts @@ -0,0 +1,32 @@ +import { Component, OnInit } from '@angular/core'; +import {Chart} from 'node_modules/chart.js'; + +@Component({ + selector: 'app-scatterchart', + templateUrl: './scatterchart.component.html', + styleUrls: ['./scatterchart.component.css'] +}) +export class ScatterchartComponent implements OnInit { + + constructor() { } + + ngOnInit(){ + const myChart = new Chart("ScatterCharts", { + type: 'scatter', + data: { + datasets: [{ + label: 'Scatter Example:', + data: [{x: 1, y: 11}, {x:2, y:12}, {x: 1, y: 2}, {x: 2, y: 4}, {x: 3, y: 8},{x: 4, y: 16}, {x: 1, y: 3}, {x: 3, y: 4}, {x: 4, y: 6}, {x: 6, y: 9}], + backgroundColor: 'rgb(255, 99, 132)' + }] + }, + options: { + scales: { + y: { + beginAtZero: true + } + } + } + }); + } +} diff --git a/frontend/src/index.html b/frontend/src/index.html index b3b6eb54..0079969e 100644 --- a/frontend/src/index.html +++ b/frontend/src/index.html @@ -12,5 +12,6 @@ </head> <body class="mat-typography"> <app-root></app-root> + <script src="node_modules/chart.js/src/chart.js"></script> </body> </html> diff --git a/frontend/src/styles.css b/frontend/src/styles.css index d37ab6f1..5a30802b 100644 --- a/frontend/src/styles.css +++ b/frontend/src/styles.css @@ -1,3 +1,4 @@ +@import '~bootstrap/dist/css/bootstrap.min.css'; body { background-image: url('/assets/images/add_model_background.jpg'); }
\ No newline at end of file |