aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--backend/api/api/Controllers/DatasetController.cs20
-rw-r--r--backend/api/api/Controllers/ModelController.cs40
-rw-r--r--backend/api/api/Models/Model.cs6
-rw-r--r--backend/api/api/Models/Predictor.cs47
-rw-r--r--backend/api/api/Program.cs2
-rw-r--r--backend/api/api/Services/DatasetService.cs12
-rw-r--r--backend/api/api/Services/FillAnEmptyDb.cs13
-rw-r--r--backend/api/api/Services/MlConnectionService.cs13
-rw-r--r--backend/api/api/appsettings.json10
-rw-r--r--backend/microservice/api/controller.py35
-rw-r--r--backend/microservice/api/newmlservice.py75
-rw-r--r--frontend/src/app/_data/Model.ts4
-rw-r--r--frontend/src/app/_data/Predictor.ts12
-rw-r--r--frontend/src/app/_elements/column-table/column-table.component.css2
-rw-r--r--frontend/src/app/_elements/column-table/column-table.component.html6
-rw-r--r--frontend/src/app/_elements/column-table/column-table.component.ts44
-rw-r--r--frontend/src/app/_elements/folder/folder.component.css4
-rw-r--r--frontend/src/app/_elements/folder/folder.component.html12
-rw-r--r--frontend/src/app/_elements/folder/folder.component.ts42
-rw-r--r--frontend/src/app/_elements/form-model/form-model.component.ts2
-rw-r--r--frontend/src/app/_modals/alert-dialog/alert-dialog.component.html16
-rw-r--r--frontend/src/app/_modals/alert-dialog/alert-dialog.component.ts6
-rw-r--r--frontend/src/app/_modals/encoding-dialog/encoding-dialog.component.html20
-rw-r--r--frontend/src/app/_modals/missingvalues-dialog/missingvalues-dialog.component.css4
-rw-r--r--frontend/src/app/_modals/yes-no-dialog/yes-no-dialog.component.html8
-rw-r--r--frontend/src/app/_modals/yes-no-dialog/yes-no-dialog.component.ts9
-rw-r--r--frontend/src/app/_pages/experiment/experiment.component.css8
-rw-r--r--frontend/src/app/_pages/experiment/experiment.component.html26
-rw-r--r--frontend/src/app/_pages/experiment/experiment.component.ts46
-rw-r--r--frontend/src/app/_services/models.service.ts8
-rw-r--r--frontend/src/app/app-routing.module.ts4
31 files changed, 323 insertions, 233 deletions
diff --git a/backend/api/api/Controllers/DatasetController.cs b/backend/api/api/Controllers/DatasetController.cs
index e4741412..849d9884 100644
--- a/backend/api/api/Controllers/DatasetController.cs
+++ b/backend/api/api/Controllers/DatasetController.cs
@@ -144,7 +144,6 @@ namespace api.Controllers
[Authorize(Roles = "User,Guest")]
public async Task<ActionResult<Dataset>> Post([FromBody] Dataset dataset)
{
- Console.WriteLine("PROBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
string uploaderId = getUserId();
dataset.uploaderId = uploaderId;
@@ -196,7 +195,7 @@ namespace api.Controllers
string ext = ".csv";
- //nesto
+
//Check Directory
if (!Directory.Exists(folderPath))
@@ -279,19 +278,4 @@ namespace api.Controllers
}
}
-}
-
-/*
-{
- "_id": "",
- "name": "name",
- "description": "description",
- "header" : ["ag","rt"],
- "fileId" : "652",
- "extension": "csb",
- "isPublic" : true,
- "accessibleByLink": true,
- "dateCreated": "dateCreated",
- "lastUpdated" : "proba12"
-}
-*/ \ No newline at end of file
+} \ No newline at end of file
diff --git a/backend/api/api/Controllers/ModelController.cs b/backend/api/api/Controllers/ModelController.cs
index 39eb7830..be30ae6f 100644
--- a/backend/api/api/Controllers/ModelController.cs
+++ b/backend/api/api/Controllers/ModelController.cs
@@ -211,6 +211,8 @@ namespace api.Controllers
return BadRequest("Bad parameters!");*/
model.uploaderId = getUserId();
+ model.dateCreated = DateTime.Now;
+ model.lastUpdated = DateTime.Now;
var existingModel = _modelService.GetOneModel(model.uploaderId, model.name);
@@ -232,6 +234,44 @@ namespace api.Controllers
}
}
+ // POST api/<ModelController>/stealModel
+ [HttpPost("stealModel")]
+ [Authorize(Roles = "User,Guest")]
+ public ActionResult<Model> StealModel([FromBody] Model model)//, bool overwrite)
+ {
+ bool overwrite = false;
+ //username="" ako je GUEST
+ //Experiment e = _experimentService.Get(model.experimentId); umesto 1 ide e.inputColumns.Length TODO!!!!!!!!!!!!!!!!!
+ //model.inputNeurons = e.inputColumns.Length;
+ /*if (_modelService.CheckHyperparameters(1, model.hiddenLayerNeurons, model.hiddenLayers, model.outputNeurons) == false)
+ return BadRequest("Bad parameters!");*/
+
+ model.uploaderId = getUserId();
+ model._id = "";
+ model.dateCreated = DateTime.Now;
+ model.lastUpdated = DateTime.Now;
+ model.isPublic = false;
+
+ var existingModel = _modelService.GetOneModel(model.uploaderId, model.name);
+
+
+ if (existingModel != null && !overwrite && model.validationSize < 1 && model.validationSize > 0)
+ return NotFound($"Model already exisits or validation size is not between 0-1");
+ else
+ {
+ //_modelService.Create(model);
+ //return Ok();
+ if (existingModel == null)
+ _modelService.Create(model);
+ else
+ {
+ _modelService.Replace(model);
+ }
+
+ return CreatedAtAction(nameof(Get), new { id = model._id }, model);
+ }
+ }
+
// PUT api/<ModelController>/{name}
[HttpPut("{name}")]
[Authorize(Roles = "User,Guest")]
diff --git a/backend/api/api/Models/Model.cs b/backend/api/api/Models/Model.cs
index a807316f..bbbf201e 100644
--- a/backend/api/api/Models/Model.cs
+++ b/backend/api/api/Models/Model.cs
@@ -14,18 +14,14 @@ namespace api.Models
public string name { get; set; }
public string description { get; set; }
- //datetime
public DateTime dateCreated { get; set; }
public DateTime lastUpdated { get; set; }
- //proveriti id
- //public string experimentId { get; set; }
//Neural net training
public string type { get; set; }
public string optimizer { get; set; }
public string lossFunction { get; set; }
- //public int inputNeurons { get; set; }
public int hiddenLayers { get; set; }
public string batchSize { get; set; }
public string learningRate { get; set; }
@@ -36,8 +32,6 @@ namespace api.Models
public string[] metrics { get; set; }
public int epochs { get; set; }
- //public bool isTrained { get; set; }
- //public NullValues[] nullValues { get; set; }
public bool randomOrder { get; set; }
public bool randomTestSet { get; set; }
public float randomTestSetDistribution { get; set; }
diff --git a/backend/api/api/Models/Predictor.cs b/backend/api/api/Models/Predictor.cs
index 530257b2..5a7b5eda 100644
--- a/backend/api/api/Models/Predictor.cs
+++ b/backend/api/api/Models/Predictor.cs
@@ -18,38 +18,25 @@ namespace api.Models
public string experimentId { get; set; }
public string modelId { get; set; }
public string h5FileId { get; set; }
- public Metric[] metrics { get; set; }
- public Metric[] finalMetrics { get; set; }
- }
- public class Metric
+ //public Metric[] metrics { get; set; }
+
+ public float[] metricsLoss { get; set; }
+ public float[] metricsValLoss { get; set; }
+ public float[] metricsAcc { get; set; }
+ public float[] metricsValAcc { get; set; }
+ public float[] metricsMae { get; set; }
+ public float[] metricsValMae { get; set; }
+ public float[] metricsMse { get; set; }
+ public float[] metricsValMse { get; set; }
+ //public Metric[] finalMetrics { get; set; }
+ }
+
+ /*public class Metric
{
string Name { get; set; }
string JsonValue { get; set; }
- }
-
-}
-
-/**
-* Paste one or more documents here
-
-{
- "_id": {
- "$oid": "625dc348b7856ace8a6f8702"
-
- },
- "uploaderId" : "6242ea59486c664208d4255c",
- "inputs": ["proba",
- "proba2",
- "proba3"
- ],
- "output" : "izlaz",
- "isPublic" : true,
- "accessibleByLink" : true,
- "dateCreated" : "2022-04-11T20:33:26.937+00:00",
- "experimentId" : "Neki id eksperimenta",
- "modelId" : "Neki id eksperimenta",
- "h5FileId" : "Neki id eksperimenta",
- "metrics" : [{ }]
-}*/ \ No newline at end of file
+ }*/
+
+} \ No newline at end of file
diff --git a/backend/api/api/Program.cs b/backend/api/api/Program.cs
index cf64d58d..5977e843 100644
--- a/backend/api/api/Program.cs
+++ b/backend/api/api/Program.cs
@@ -37,7 +37,7 @@ builder.Services.AddScoped<IFileService, FileService>();
builder.Services.AddScoped<IJwtToken, JwtToken>();
builder.Services.AddScoped<IExperimentService, ExperimentService>();
builder.Services.AddHostedService<TempFileService>();
-builder.Services.AddHostedService<FillAnEmptyDb>();
+//builder.Services.AddHostedService<FillAnEmptyDb>();
//Ml Api Ip Filter
builder.Services.AddScoped<MlApiCheckActionFilter>(container =>
diff --git a/backend/api/api/Services/DatasetService.cs b/backend/api/api/Services/DatasetService.cs
index f38a363b..0b84721e 100644
--- a/backend/api/api/Services/DatasetService.cs
+++ b/backend/api/api/Services/DatasetService.cs
@@ -104,16 +104,6 @@ namespace api.Services
return dataset._id;
}
- /*
-public bool CheckDb()
-{
- Dataset? dataset = null;
- dataset = _dataset.Find(dataset => dataset.username == "igrannonica").FirstOrDefault();
-
- if (dataset != null)
- return false;
- else
- return true;
-}*/
+
}
}
diff --git a/backend/api/api/Services/FillAnEmptyDb.cs b/backend/api/api/Services/FillAnEmptyDb.cs
index 811e723a..cd35dc78 100644
--- a/backend/api/api/Services/FillAnEmptyDb.cs
+++ b/backend/api/api/Services/FillAnEmptyDb.cs
@@ -54,7 +54,7 @@ namespace api.Services
dataset._id = "";
dataset.uploaderId = "000000000000000000000000";
- dataset.name = "Titanik dataset(public)";
+ dataset.name = "Titanik dataset (public)";
dataset.description = "Titanik dataset";
dataset.fileId = _fileService.GetFileId(fullPath);
dataset.extension = ".csv";
@@ -277,6 +277,7 @@ namespace api.Services
model.lossFunction = "sparse_categorical_crossentropy";
model.hiddenLayers = 5;
model.batchSize = "64";
+ model.learningRate = "1";
model.outputNeurons = 0;
model.layers = new[]
{
@@ -368,7 +369,7 @@ namespace api.Services
dataset._id = "";
dataset.uploaderId = "000000000000000000000000";
dataset.name = "IMDB-Movie-Data Dataset (public)";
- dataset.description = "IMDB-Movie-Data Dataset(public)";
+ dataset.description = "IMDB-Movie-Data Dataset (public)";
dataset.fileId = _fileService.GetFileId(fullPath);
dataset.extension = ".csv";
dataset.isPublic = true;
@@ -421,8 +422,8 @@ namespace api.Services
model._id = "";
model.uploaderId = "000000000000000000000000";
- model.name = "IMDB model";
- model.description = "IMDB model";
+ model.name = "IMDB model (public)";
+ model.description = "IMDB model (public)";
model.dateCreated = DateTime.Now;
model.lastUpdated = DateTime.Now;
model.type = "regresioni";
@@ -579,8 +580,8 @@ namespace api.Services
model._id = "";
model.uploaderId = "000000000000000000000000";
- model.name = "Churn model";
- model.description = "Churn model";
+ model.name = "Churn model (public)";
+ model.description = "Churn model (public)";
model.dateCreated = DateTime.Now;
model.lastUpdated = DateTime.Now;
model.type = "binarni-klasifikacioni";
diff --git a/backend/api/api/Services/MlConnectionService.cs b/backend/api/api/Services/MlConnectionService.cs
index 0ecdb1af..6a307e0d 100644
--- a/backend/api/api/Services/MlConnectionService.cs
+++ b/backend/api/api/Services/MlConnectionService.cs
@@ -63,19 +63,6 @@ namespace api.Services
foreach (var connection in ChatHub.getAllConnectionsOfUser(id))
await _ichat.Clients.Client(connection).SendAsync("NotifyDataset",newDataset.name,newDataset._id);
-
- string proba = "";
-
- for (int i = 0; i < newDataset.cMatrix.Length; i++)
- {
- proba = i +" ";
- for (int j = 0; j < newDataset.cMatrix[i].Length; j++)
- proba += newDataset.cMatrix[i][j] + "f, ";
-
- Console.WriteLine(proba);
- proba = "";
- }
-
return;
}
diff --git a/backend/api/api/appsettings.json b/backend/api/api/appsettings.json
index 44d63ac3..b502efeb 100644
--- a/backend/api/api/appsettings.json
+++ b/backend/api/api/appsettings.json
@@ -16,22 +16,26 @@
"UserStoreDatabaseSettings": {
/* LocalHost*/
- /*"ConnectionString": "mongodb://127.0.0.1:27017/",
+ "ConnectionString": "mongodb://127.0.0.1:27017/",
"DatabaseName": "si_project",
"CollectionName": "users",
"DatasetCollectionName": "Dataset",
"ModelCollectionName": "Model",
"PredictorCollectionName": "Predictor",
"FilesCollectionName": "Files",
- "ExperimentCollectionName": "Experiment"*/
+ "ExperimentCollectionName": "Experiment"
+ /*
"ConnectionString": "mongodb+srv://si_user:si_user@sidatabase.twtfm.mongodb.net/myFirstDatabase?retryWrites=true&w=majority",
+
+ "ConnectionString": "mongodb+srv://si_user:si_user@sidatabase.twtfm.mongodb.net/myFirstDatabase?retryWrites=true&w=majority",
+ 529394dd526811e059dfb5f8f76597ffd90b2fea
"DatabaseName": "si_db",
"CollectionName": "users",
"DatasetCollectionName": "Dataset",
"ModelCollectionName": "Model",
"PredictorCollectionName": "Predictor",
"FilesCollectionName": "Files",
- "ExperimentCollectionName": "Experiment"
+ "ExperimentCollectionName": "Experiment" */
}
} \ No newline at end of file
diff --git a/backend/microservice/api/controller.py b/backend/microservice/api/controller.py
index 7852b63d..c82634a2 100644
--- a/backend/microservice/api/controller.py
+++ b/backend/microservice/api/controller.py
@@ -69,22 +69,30 @@ def train():
#dataset, paramsModel, paramsExperiment, callback)
- filepath,result,finalMetrics= newmlservice.train(data, paramsModel, paramsExperiment,paramsDataset, train_callback)
+ filepath,histMetrics= newmlservice.train(data, paramsModel, paramsExperiment,paramsDataset, train_callback)
"""
f = request.json['filepath']
dataset = pd.read_csv(f)
filepath,result=newmlservice.train(dataset,request.json['model'],train_callback)
print(result)
"""
-
-
+ #m = []
+ #for attribute, value in result.items():
+ #m.append(histMetrics(attribute,str(value)).__dict__)
+ '''
+ m = []
+ for attribute, value in result.items():
+ m.append({"Name" : attribute, "JsonValue" : value}))
+
+ print("**************************************************************")
+ print(m)
+
+ print("**************************************************************")
+ '''
url = config.api_url + "/file/h5"
files = {'file': open(filepath, 'rb')}
r=requests.post(url, files=files,data={"uploaderId":paramsExperiment['uploaderId']})
fileId=r.text
- m = []
- for attribute, value in result.items():
- m.append({"Name" : attribute, "JsonValue" : value})
predictor = {
"_id" : "",
"uploaderId" : paramsModel["uploaderId"],
@@ -95,14 +103,21 @@ def train():
"experimentId" : paramsExperiment["_id"],
"modelId" : paramsModel["_id"],
"h5FileId" : fileId,
- "metrics" : m,
- "finalMetrics":finalMetrics
-
+ "metricsLoss":histMetrics[0],
+ "metricsValLoss":histMetrics[1],
+ "metricsAcc":histMetrics[2],
+ "metricsValAcc":histMetrics[3],
+ "metricsMae":histMetrics[4],
+ "metricsValMae":histMetrics[5],
+ "metricsMse":histMetrics[6],
+ "metricsValMse":histMetrics[7]
}
#print(predictor)
+
url = config.api_url + "/Predictor/add"
r = requests.post(url, json=predictor).text
- print(r)
+
+ #print(r)
return r
@app.route('/predict', methods = ['POST'])
diff --git a/backend/microservice/api/newmlservice.py b/backend/microservice/api/newmlservice.py
index fd21f8ce..85be0c2f 100644
--- a/backend/microservice/api/newmlservice.py
+++ b/backend/microservice/api/newmlservice.py
@@ -303,7 +303,7 @@ def train(dataset, paramsModel,paramsExperiment,paramsDataset,callback):
###OPTIMIZATORI
print(paramsModel['optimizer'])
if(paramsModel['optimizer']=='Adam'):
- opt=tf.keras.optimizers.Adam(learning_rate=3)
+ opt=tf.keras.optimizers.Adam(learning_rate=float(paramsModel['learningRate']))
elif(paramsModel['optimizer']=='Adadelta'):
opt=tf.keras.optimizers.Adadelta(learning_rate=float(paramsModel['learningRate']))
@@ -370,7 +370,7 @@ def train(dataset, paramsModel,paramsExperiment,paramsDataset,callback):
- classifier.compile(loss =paramsModel["lossFunction"] , optimizer =opt, metrics = ['mae','mse'])
+ classifier.compile(loss =paramsModel["lossFunction"] , optimizer =opt, metrics = ['accuracy','mae','mse'])
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))
@@ -383,9 +383,9 @@ def train(dataset, paramsModel,paramsExperiment,paramsDataset,callback):
scores = classifier.evaluate(x_test, y_test)
#print("\n%s: %.2f%%" % (classifier.metrics_names[1], scores[1]*100))
-
+ '''
classifier.save(filepath, save_format='h5')
- metrics={}
+
macro_averaged_precision=sm.precision_score(y_test, y_pred, average = 'macro')
micro_averaged_precision=sm.precision_score(y_test, y_pred, average = 'micro')
macro_averaged_recall=sm.recall_score(y_test, y_pred, average = 'macro')
@@ -393,20 +393,20 @@ def train(dataset, paramsModel,paramsExperiment,paramsDataset,callback):
macro_averaged_f1=sm.f1_score(y_test, y_pred, average = 'macro')
micro_averaged_f1=sm.f1_score(y_test, y_pred, average = 'micro')
- metrics= {
- "macro_averaged_precision" :float(macro_averaged_precision),
- "micro_averaged_precision" : float(micro_averaged_precision),
- "macro_averaged_recall" : float(macro_averaged_recall),
- "micro_averaged_recall" : float(micro_averaged_recall),
- "macro_averaged_f1" : float(macro_averaged_f1),
- "micro_averaged_f1" : float(micro_averaged_f1)
- }
-
+ metrics= [
+ {"Name":"macro_averaged_precision", "JsonValue":str(macro_averaged_precision)},
+ {"Name":"micro_averaged_precision" ,"JsonValue":str(micro_averaged_precision)},
+ {"Name":"macro_averaged_recall", "JsonValue":str(macro_averaged_recall)},
+ {"Name":"micro_averaged_recall" ,"JsonValue":str(micro_averaged_recall)},
+ {"Name":"macro_averaged_f1","JsonValue": str(macro_averaged_f1)},
+ {"Name":"micro_averaged_f1", "JsonValue": str(micro_averaged_f1)}
+ ]
+ '''
#vizuelizacija u python-u
#from ann_visualizer.visualize import ann_viz;
#ann_viz(classifier, title="My neural network")
- return filepath,hist,metrics
+ return filepath,[hist['loss'],hist['val_loss'],hist['accuracy'],hist['val_accuracy'],hist['mae'],hist['val_mae'],hist['mse'],hist['val_mse']]
elif(problem_type=='binarni-klasifikacioni'):
#print('*************************************************************************binarni')
@@ -444,6 +444,7 @@ def train(dataset, paramsModel,paramsExperiment,paramsDataset,callback):
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
+
y_pred=classifier.predict(x_test)
y_pred=(y_pred>=0.5).astype('int')
@@ -452,7 +453,7 @@ def train(dataset, paramsModel,paramsExperiment,paramsDataset,callback):
# ann_viz(classifier, title="My neural network")
classifier.save(filepath, save_format='h5')
-
+ """
accuracy = float(sm.accuracy_score(y_test,y_pred))
precision = float(sm.precision_score(y_test,y_pred))
recall = float(sm.recall_score(y_test,y_pred))
@@ -461,22 +462,9 @@ def train(dataset, paramsModel,paramsExperiment,paramsDataset,callback):
f1 = float(sm.f1_score(y_test,y_pred))
fpr, tpr, _ = sm.roc_curve(y_test,y_pred)
logloss = float(sm.log_loss(y_test, y_pred))
- metrics= {
- "accuracy" : accuracy,
- "precision" : precision,
- "recall" : recall,
- "specificity" : specificity,
- "f1" : f1,
- "tn" : float(tn),
- "fp" : float(fp),
- "fn" : float(fn),
- "tp" : float(tp),
- "fpr" : fpr.tolist(),
- "tpr" : tpr.tolist(),
- "logloss" : logloss
- }
+ """
- return filepath,hist,metrics
+ return filepath,[hist['loss'],hist['val_loss'],hist['accuracy'],hist['val_accuracy'],hist['mae'],hist['val_mae'],hist['mse'],hist['val_mse']]
elif(problem_type=='regresioni'):
reg=paramsModel['layers'][0]['regularisation']
@@ -514,13 +502,15 @@ def train(dataset, paramsModel,paramsExperiment,paramsDataset,callback):
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
+
y_pred=classifier.predict(x_test)
#print(classifier.evaluate(x_test, y_test))
classifier.save(filepath, save_format='h5')
-
+ '''
mse = float(sm.mean_squared_error(y_test,y_pred))
+
mae = float(sm.mean_absolute_error(y_test,y_pred))
mape = float(sm.mean_absolute_percentage_error(y_test,y_pred))
rmse = float(np.sqrt(sm.mean_squared_error(y_test,y_pred)))
@@ -531,16 +521,19 @@ def train(dataset, paramsModel,paramsExperiment,paramsDataset,callback):
n = 40
k = 2
adj_r2 = float(1 - ((1-r2)*(n-1)/(n-k-1)))
- metrics= {"mse" : mse,
- "mae" : mae,
- "mape" : mape,
- "rmse" : rmse,
- "rmsle" : rmsle,
- "r2" : r2,
- "adj_r2" : adj_r2
- }
-
- return filepath,hist,metrics
+
+ metrics= [
+ {"Name":"mse","JsonValue":str(mse)},
+
+ {"Name":"mae","JsonValue":str(mae)},
+ {"Name":"mape","JsonValue":str( mape)},
+ {"Name":"rmse","JsonValue":str(rmse)},
+ {"Name":"rmsle","JsonValue":str(rmsle)},
+ {"Name":"r2","JsonValue":str( r2)},
+ {"Name":"adj_r2","JsonValue":str(adj_r2)}
+ ]
+ '''
+ return filepath,[hist['loss'],hist['val_loss'],[],[],hist['mae'],hist['val_mae'],hist['mse'],hist['val_mse']]
def roc_auc_score_multiclass(actual_class, pred_class, average = "macro"):
diff --git a/frontend/src/app/_data/Model.ts b/frontend/src/app/_data/Model.ts
index 8fc36a31..f527dc7f 100644
--- a/frontend/src/app/_data/Model.ts
+++ b/frontend/src/app/_data/Model.ts
@@ -117,8 +117,8 @@ export enum ActivationFunctionOutputLayer
export enum LossFunction {
// binary classification loss functions
BinaryCrossEntropy = 'binary_crossentropy',
- SquaredHingeLoss = 'squared_hinge_loss',
- HingeLoss = 'hinge_loss',
+ SquaredHingeLoss = 'squared_hinge',
+ HingeLoss = 'hinge',
// multi-class classification loss functions
CategoricalCrossEntropy = 'categorical_crossentropy',
SparseCategoricalCrossEntropy = 'sparse_categorical_crossentropy',
diff --git a/frontend/src/app/_data/Predictor.ts b/frontend/src/app/_data/Predictor.ts
index c839a635..8de4cd17 100644
--- a/frontend/src/app/_data/Predictor.ts
+++ b/frontend/src/app/_data/Predictor.ts
@@ -13,8 +13,16 @@ export default class Predictor extends FolderFile {
public experimentId: string = "",
public modelId: string = "",
public h5FileId: string = "",
- public metrics: Metric[] = [],
- public finalMetrics: Metric[] = []
+ public metricsLoss:number[]=[],
+ public metricsValLoss:number []=[],
+ public metricsAcc:number[]=[],
+ public metricsValAcc: number[]=[],
+ public metricsMae :number []=[],
+ public metricsValMae :number []=[],
+ public metricsMse : number[]=[],
+ public metricsValMse : number[]=[],
+ //public metrics: Metric[] = [],
+ //public finalMetrics: Metric[] = []
) {
super(name, dateCreated, dateCreated);
}
diff --git a/frontend/src/app/_elements/column-table/column-table.component.css b/frontend/src/app/_elements/column-table/column-table.component.css
index f7f07e62..311773f7 100644
--- a/frontend/src/app/_elements/column-table/column-table.component.css
+++ b/frontend/src/app/_elements/column-table/column-table.component.css
@@ -22,7 +22,7 @@ table.fixed td {
table.fixed th {
overflow: hidden;
- max-width: 120px;
+ max-width: 250px;
min-width: 120px;
vertical-align: middle;
background-color: var(--ns-primary-50);
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 31c32dfd..e6a781be 100644
--- a/frontend/src/app/_elements/column-table/column-table.component.html
+++ b/frontend/src/app/_elements/column-table/column-table.component.html
@@ -35,7 +35,7 @@
</thead>
<tbody>
<tr *ngFor="let row of tableData; let i = index">
- <th>#{{i}}</th>
+ <th>#{{((this.begin/10)+1)*10-10+i+1}}</th>
<td *ngFor="let col of row; let j = index" [ngClass]="{'text-disabled' : !columnsChecked[j]}">
<div class="text-overflow">
{{col}}
@@ -200,7 +200,7 @@
</mat-menu>
</div>
<div *ngIf="colInfo.numNulls == 0" class="text-left">
- Nema null vrednosti.
+ Nema nedostajućih vrednosti.
</div>
</td>
</tr>
@@ -217,7 +217,7 @@
<div class="ns-col rounded">
<mat-form-field appearance="fill" class="align-items-center justify-content-center pt-3 w-100">
<mat-label>Izlazna kolona</mat-label>
- <mat-select [(value)]="experiment.outputColumn" (selectionChange)="changeProblemType()">
+ <mat-select [(value)]="experiment.outputColumn" (selectionChange)="outputColumnChanged()">
<mat-option *ngFor="let inputColumn of experiment.inputColumns" [value]="inputColumn">{{inputColumn}}</mat-option>
<mat-option *ngIf="experiment.inputColumns.length == 0" value="-">-</mat-option>
</mat-select>
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 ad78feaf..694b1a83 100644
--- a/frontend/src/app/_elements/column-table/column-table.component.ts
+++ b/frontend/src/app/_elements/column-table/column-table.component.ts
@@ -131,6 +131,7 @@ export class ColumnTableComponent implements AfterViewInit {
}
else {
this.dataset = dataset;
+ this.experimentChanged.emit();
this.columnsChecked = [];
this.dataset.columnInfo.forEach(column => {
if (this.experiment.inputColumns.find(x => x == column.columnName) != undefined)
@@ -157,9 +158,6 @@ export class ColumnTableComponent implements AfterViewInit {
this.resetPagging();
this.loadData();
this.loaded = true;
-
- this.updateCharts();
- this.updatePieChart();
}
loadData(){
@@ -249,6 +247,19 @@ export class ColumnTableComponent implements AfterViewInit {
}
}
+ outputColumnChanged() {
+ let outputColReplacer = this.experiment.nullValuesReplacers.find(x => x.column == this.experiment.outputColumn);
+ let index = this.experiment.nullValuesReplacers.findIndex(x => x.column == this.experiment.outputColumn);
+ if (outputColReplacer != undefined) {
+ outputColReplacer.option = NullValueOptions.DeleteRows;
+
+ let numOfRowsToDelete = (this.dataset!.columnInfo.filter(x => x.columnName == this.experiment.outputColumn)[0]).numNulls;
+ this.nullValOption[index] = "Obriši redove (" + numOfRowsToDelete + ")";
+ }
+
+ this.changeProblemType();
+ }
+
changeProblemType() {
if (this.experiment != undefined && this.dataset != undefined) {
let i = this.dataset.columnInfo.findIndex(x => x.columnName == this.experiment!.outputColumn);
@@ -300,14 +311,26 @@ export class ColumnTableComponent implements AfterViewInit {
if (selectedMissingValuesOption == NullValueOptions.DeleteColumns) {
this.experiment.nullValues = NullValueOptions.DeleteColumns;
+
+ let outputColReplacer = this.experiment.nullValuesReplacers.find(x => x.column == this.experiment.outputColumn);
+
this.experiment.nullValuesReplacers = [];
for (let i = 0; i < this.experiment.inputColumns.length; i++) {
- this.experiment.nullValuesReplacers.push({ //ovo zakomentarisano
- column: this.experiment.inputColumns[i],
- option: NullValueOptions.DeleteColumns,
- value: ""
- });
- this.nullValOption[i] = "Obriši kolonu";
+ if (this.experiment.inputColumns[i] != this.experiment.outputColumn) {
+ this.experiment.nullValuesReplacers.push({ //ovo zakomentarisano
+ column: this.experiment.inputColumns[i],
+ option: NullValueOptions.DeleteColumns,
+ value: ""
+ });
+ this.nullValOption[i] = "Obriši kolonu";
+ }
+ else {
+ if (outputColReplacer != undefined) {
+ this.experiment.nullValuesReplacers.push(outputColReplacer);
+ let numOfRowsToDelete = (this.dataset.columnInfo.filter(x => x.columnName == this.experiment!.inputColumns[i])[0]).numNulls;
+ this.nullValOption[i] = (outputColReplacer.option == NullValueOptions.DeleteRows) ? "Obriši redove (" + numOfRowsToDelete + ")" : "Popuni sa " + outputColReplacer.value + "";
+ }
+ }
}
//obrisi kolone koje sadrze nedostajuce vrednosti iz input kolona
/*for (let i = 0; i < this.dataset.columnInfo.length; i++) {
@@ -336,7 +359,8 @@ export class ColumnTableComponent implements AfterViewInit {
}
openMissingValuesDialog() {
const dialogRef = this.dialog.open(MissingvaluesDialogComponent, {
- width: '500px'
+ width: '500px',
+ panelClass: 'custom-modalbox'
});
dialogRef.afterClosed().subscribe(selectedMissingValuesOption => {
if (selectedMissingValuesOption != undefined)
diff --git a/frontend/src/app/_elements/folder/folder.component.css b/frontend/src/app/_elements/folder/folder.component.css
index 4a06faa4..9e7644b6 100644
--- a/frontend/src/app/_elements/folder/folder.component.css
+++ b/frontend/src/app/_elements/folder/folder.component.css
@@ -182,8 +182,8 @@
.file-bottom-buttons {
position: absolute;
- bottom: 15px;
- right: 15px;
+ bottom: 5px;
+ right: 4%;
display: flex;
flex-direction: row-reverse;
}
diff --git a/frontend/src/app/_elements/folder/folder.component.html b/frontend/src/app/_elements/folder/folder.component.html
index 97ccc311..97ae0d23 100644
--- a/frontend/src/app/_elements/folder/folder.component.html
+++ b/frontend/src/app/_elements/folder/folder.component.html
@@ -57,10 +57,10 @@
<div class="file-content" [ngClass]="{'form-hidden' : listView}">
<div class="file-bottom-buttons" *ngIf="selectedTab != TabType.NewFile">
<button *ngIf="this.selectedFile && selectedTab == TabType.File" class="btn-clear file-button" (click)="deleteFile(this.selectedFile, $event)">
- <mat-icon>delete</mat-icon>
+ <mat-icon matTooltip="Obriši" matTooltipPosition="right">delete</mat-icon>
</button>
<button *ngIf="this.selectedFile && selectedTab==TabType.File && FolderType.Dataset==this.type" class="btn-clear file-button" (click)="downloadFile(this.selectedFile,$event)" style="display: inline-block;">
- <mat-icon>download</mat-icon>
+ <mat-icon matTooltip="Preuzmi" matTooltipPosition="before">download</mat-icon>
</button>
@@ -82,20 +82,20 @@
</div>
<div class="mx-2 hover-show" *ngIf="selectedTab !== TabType.PublicDatasets && selectedTab !== TabType.PublicModels">
<button *ngIf="selectedTab==TabType.MyDatasets" class="btn-clear file-button" (click)="downloadFile(file,$event)" style="display: inline-block;">
- <mat-icon>download</mat-icon>
+ <mat-icon matTooltip="Preuzmi" matTooltipPosition="before">download</mat-icon>
</button>
<button class="btn-clear file-button" (click)="deleteFile(file, $event)" style="display: inline-block;">
- <mat-icon>delete</mat-icon>
+ <mat-icon matTooltip="Obriši" matTooltipPosition="right">delete</mat-icon>
</button>
</div>
<div class="mx-2 hover-show" *ngIf="selectedTab == TabType.PublicDatasets || selectedTab == TabType.PublicModels">
<button class="btn-clear file-button" (click)="addFile(file, $event)">
- <mat-icon>note_add</mat-icon>
+ <mat-icon matTooltip="Uvezi" matTooltipPosition="right">note_add</mat-icon>
</button>
</div>
</div>
<div *ngIf="type == FolderType.Experiment" class="list-view">
- <div *ngFor="let predictor of predictorsForExp[file._id];" class="list-item">
+ <div *ngFor="let predictor of predictorsForExp[file._id];" class="list-item" (click)="goToExperimentPageWithPredictor(file, predictor)">
<div class="mx-3">
<div class="f-row">
diff --git a/frontend/src/app/_elements/folder/folder.component.ts b/frontend/src/app/_elements/folder/folder.component.ts
index f13635e9..254298fb 100644
--- a/frontend/src/app/_elements/folder/folder.component.ts
+++ b/frontend/src/app/_elements/folder/folder.component.ts
@@ -107,7 +107,7 @@ export class FolderComponent implements AfterViewInit {
this.selectedFile = file;
this.fileToDisplay = file;
if (this.type == FolderType.Experiment && file) {
- this.router.navigate(['/experiment/', file._id]);
+ this.router.navigate(['/experiment/' + file._id]);
}
this.newFileSelected = false;
this.listView = false;
@@ -118,12 +118,10 @@ export class FolderComponent implements AfterViewInit {
if (this.type == FolderType.Dataset)
this.formDataset.loadExisting();
}
- /*
- goToExperimentPage(file: FolderFile) {
- console.log(<Experiment>file);
- //this.router.navigate(['/experiment/', this.experiment._id]);
+
+ goToExperimentPageWithPredictor(file: FolderFile, predictor: Predictor) {
+ this.router.navigate(['/experiment/' + file._id + "/" + predictor._id]);
}
- */
createNewFile() {
if (this.type == FolderType.Dataset) {
@@ -140,10 +138,7 @@ export class FolderComponent implements AfterViewInit {
_initialized: boolean = false;
refreshFiles(selectedDatasetId: string | null = null, selectedModelId: string | null = null) {
- this.files = []
- this.filteredFiles.length = 0;
- this.folders[TabType.NewFile] = [];
- this.folders[TabType.File] = [];
+
this.tabsToShow.forEach(tab => {
this.folders[tab] = [];
});
@@ -203,6 +198,7 @@ export class FolderComponent implements AfterViewInit {
refreshDatasets(selectedDatasetId: string | null) {
this.datasetsService.getMyDatasets().subscribe((datasets) => {
this.folders[TabType.MyDatasets] = datasets;
+ console.log(this.filteredFiles);
if (selectedDatasetId) {
this.selectFile(datasets.filter(x => x._id == selectedDatasetId)[0]);
}
@@ -239,7 +235,7 @@ export class FolderComponent implements AfterViewInit {
case FolderType.Dataset:
this.formDataset!.uploadDataset((dataset: Dataset) => {
this.newFile = undefined;
- Shared.openDialog("Obaveštenje", "Uspešno ste dodali novi izvor podataka u kolekciju. Molimo sačekajte par trenutaka da se procesira.");
+ Shared.openDialog("Obaveštenje", "Uspešno ste dodali novi izvor podataka u kolekciju. Molimo sačekajte par trenutaka da se obradi.");
this.refreshFiles();
},
() => {
@@ -288,17 +284,20 @@ export class FolderComponent implements AfterViewInit {
deleteFile(file: FolderFile, event: Event) {
event.stopPropagation();
- //console.log('delete');
+ this.filteredFiles.splice(this.filteredFiles.indexOf(file), 1);
+ this.files.splice(this.files.indexOf(file), 1);
switch (this.type) {
case FolderType.Dataset:
this.datasetsService.deleteDataset(<Dataset>file).subscribe((response) => {
- this.filteredFiles.splice(this.filteredFiles.indexOf(file), 1);
- this.refreshFiles(null);
+ Shared.openDialog("Obaveštenje", "Uspešno ste obrisali odabrani izvor podataka.");
+ //this.filteredFiles.splice(this.files.indexOf(file), 1);
+ //this.refreshFiles();
});
break;
case FolderType.Model:
this.modelsService.deleteModel(<Model>file).subscribe((response) => {
- this.refreshFiles(null);
+ Shared.openDialog("Obaveštenje", "Uspešno ste obrisali odabranu konfiguraciju neuronske mreže.");
+ //this.refreshFiles();
});
break;
case FolderType.Experiment:
@@ -332,13 +331,22 @@ export class FolderComponent implements AfterViewInit {
(<Dataset>file).isPreProcess = true;
(<Dataset>file).isPublic = false;
this.datasetsService.stealDataset(<Dataset>file).subscribe((response) => {
- this.filteredFiles.splice(this.filteredFiles.indexOf(file), 1);
+ Shared.openDialog("Obaveštenje", "Uspešno ste dodali javni izvor podataka u vašu kolekciju.");
this.refreshFiles(null);
+ }, (error:any) => {
+ if (error.error == "Dataset with this name already exists") {
+ Shared.openDialog("Obaveštenje", "Izvor podataka sa ovim imenom postoji u vašoj kolekciji.");
+ }
});
break;
case FolderType.Model:
- this.modelsService.addModel(<Model>file).subscribe((response) => {
+ this.modelsService.stealModel(<Model>file).subscribe((response) => {
+ Shared.openDialog("Obaveštenje", "Uspešno ste dodali javnu konfiguraciju neuronske mreže u vašu kolekciju.");
this.refreshFiles(null);
+ }, (error:any) => {
+ if (error.error == "Model already exisits or validation size is not between 0-1") {
+ Shared.openDialog("Obaveštenje", "Model sa ovim imenom postoji u vašoj kolekciji.");
+ }
});
break;
case FolderType.Experiment:
diff --git a/frontend/src/app/_elements/form-model/form-model.component.ts b/frontend/src/app/_elements/form-model/form-model.component.ts
index c9e2fc8e..9e6082c4 100644
--- a/frontend/src/app/_elements/form-model/form-model.component.ts
+++ b/frontend/src/app/_elements/form-model/form-model.component.ts
@@ -84,7 +84,7 @@ export class FormModelComponent implements AfterViewInit {
}
addLayer() {
- if (this.newModel.hiddenLayers < 128) {
+ if (this.newModel.hiddenLayers < 150) {
this.newModel.layers.push(new Layer(this.newModel.layers.length, this.selectedActivation, this.selectedNumberOfNeurons, this.selectedRegularisation, this.selectedRegularisationRate));
this.newModel.hiddenLayers += 1;
diff --git a/frontend/src/app/_modals/alert-dialog/alert-dialog.component.html b/frontend/src/app/_modals/alert-dialog/alert-dialog.component.html
index 2d7e4d86..84793260 100644
--- a/frontend/src/app/_modals/alert-dialog/alert-dialog.component.html
+++ b/frontend/src/app/_modals/alert-dialog/alert-dialog.component.html
@@ -1,9 +1,9 @@
-
-
- <h2 mat-dialog-title >{{data.title}}</h2>
- <div mat-dialog-content class="mt-4 text-offwhite" >
- {{data.message}}
- </div>
- <div mat-dialog-actions class="d-flex justify-content-center mt-4">
+<h2 mat-dialog-title>{{data.title}}</h2>
+<div mat-dialog-content class="mt-4 text-offwhite">
+ <form (keydown)="withEnterKey($event)">
+ {{data.message}}
+ </form>
+</div>
+<div mat-dialog-actions class="d-flex justify-content-center mt-4">
<button mat-raised-button cdkFocusInitial (click)="onOkClick()" color="basic">OK</button>
- </div> \ No newline at end of file
+</div> \ No newline at end of file
diff --git a/frontend/src/app/_modals/alert-dialog/alert-dialog.component.ts b/frontend/src/app/_modals/alert-dialog/alert-dialog.component.ts
index e15f3c6f..7558b527 100644
--- a/frontend/src/app/_modals/alert-dialog/alert-dialog.component.ts
+++ b/frontend/src/app/_modals/alert-dialog/alert-dialog.component.ts
@@ -20,9 +20,11 @@ export class AlertDialogComponent {
//public dialog: MatDialog
) {}
+ withEnterKey(keyboardEvent: KeyboardEvent) {
+ if (keyboardEvent.code == "Enter" || keyboardEvent.code == "NumpadEnter")
+ this.onOkClick();
+ }
onOkClick(): void {
this.dialogRef.close();
}
-
-
}
diff --git a/frontend/src/app/_modals/encoding-dialog/encoding-dialog.component.html b/frontend/src/app/_modals/encoding-dialog/encoding-dialog.component.html
index 08c1f26b..fed8f8d7 100644
--- a/frontend/src/app/_modals/encoding-dialog/encoding-dialog.component.html
+++ b/frontend/src/app/_modals/encoding-dialog/encoding-dialog.component.html
@@ -1,15 +1,17 @@
<h2 mat-dialog-title class="text-center">Enkodiranje svih kolona</h2>
<div mat-dialog-content class="mt-5 mb-4">
<p>Sve izabrane kolone biće enkodirane metodom:</p>
- <form (keydown)="withEnterKey($event)">
- <mat-form-field>
- <mat-select matNativeControl [(value)]="selectedEncodingType" cdkFocusInitial>
- <mat-option *ngFor="let option of Object.keys(Encoding); let optionName of Object.values(Encoding)" [value]="option">
- {{ optionName }}
- </mat-option>
- </mat-select>
- </mat-form-field>
- </form>
+ <div class="d-flex justify-content-center">
+ <form (keydown)="withEnterKey($event)">
+ <mat-form-field>
+ <mat-select matNativeControl [(value)]="selectedEncodingType" cdkFocusInitial>
+ <mat-option *ngFor="let option of Object.keys(Encoding); let optionName of Object.values(Encoding)" [value]="option">
+ {{ optionName }}
+ </mat-option>
+ </mat-select>
+ </mat-form-field>
+ </form>
+ </div>
</div>
<div mat-dialog-actions class="justify-content-center">
<button id="btnYes" mat-stroked-button color="basic" (click)="onYesClick()">Potvrdi</button>
diff --git a/frontend/src/app/_modals/missingvalues-dialog/missingvalues-dialog.component.css b/frontend/src/app/_modals/missingvalues-dialog/missingvalues-dialog.component.css
index e99a1e1e..64d7bd21 100644
--- a/frontend/src/app/_modals/missingvalues-dialog/missingvalues-dialog.component.css
+++ b/frontend/src/app/_modals/missingvalues-dialog/missingvalues-dialog.component.css
@@ -5,4 +5,8 @@
#btnNo {
color: gray;
+}
+
+::ng-deep.mat-dialog-content {
+ overflow: visible;
} \ No newline at end of file
diff --git a/frontend/src/app/_modals/yes-no-dialog/yes-no-dialog.component.html b/frontend/src/app/_modals/yes-no-dialog/yes-no-dialog.component.html
index 06e74093..77e7be42 100644
--- a/frontend/src/app/_modals/yes-no-dialog/yes-no-dialog.component.html
+++ b/frontend/src/app/_modals/yes-no-dialog/yes-no-dialog.component.html
@@ -1,8 +1,10 @@
<h2 mat-dialog-title class="text-muted">{{data.title}}</h2>
<div mat-dialog-content class="mt-4" style="color: rgb(81, 76, 76);">
- {{data.message}}
+ <form (keydown)="withEnterKey($event)">
+ {{data.message}}
+ </form>
</div>
<div mat-dialog-actions class="d-flex justify-content-center mt-4">
- <button mat-button cdkFocusInitial (click)="onYesClick()" style="background-color: lightgray;">Da</button>
- <button mat-button cdkFocusInitial (click)="onNoClick()" style="background-color: lightgray;">Ne</button>
+ <button mat-button cdkFocusInitial (click)="onYesClick()" style="background-color: lightgray;">Da</button>
+ <button mat-button cdkFocusInitial (click)="onNoClick()" style="background-color: lightgray;">Ne</button>
</div> \ No newline at end of file
diff --git a/frontend/src/app/_modals/yes-no-dialog/yes-no-dialog.component.ts b/frontend/src/app/_modals/yes-no-dialog/yes-no-dialog.component.ts
index de1cdd4f..a7db1e7f 100644
--- a/frontend/src/app/_modals/yes-no-dialog/yes-no-dialog.component.ts
+++ b/frontend/src/app/_modals/yes-no-dialog/yes-no-dialog.component.ts
@@ -24,10 +24,13 @@ export class YesNoDialogComponent {
onNoClick(): void {
this.dialogRef.close();
}
- onYesClick():void{
+
+ withEnterKey(keyboardEvent: KeyboardEvent) {
+ if (keyboardEvent.code == "Enter" || keyboardEvent.code == "NumpadEnter")
+ this.onYesClick();
+ }
+ onYesClick():void {
this.data.yesFunction();
this.dialogRef.close();
}
-
-
}
diff --git a/frontend/src/app/_pages/experiment/experiment.component.css b/frontend/src/app/_pages/experiment/experiment.component.css
index 2298ae48..59e004e9 100644
--- a/frontend/src/app/_pages/experiment/experiment.component.css
+++ b/frontend/src/app/_pages/experiment/experiment.component.css
@@ -48,6 +48,7 @@ mat-stepper {
flex-direction: row;
justify-content: center;
align-items: center;
+ /*margin-bottom: 100px;*/
}
.step-content-inside {
@@ -66,4 +67,11 @@ mat-stepper {
.text-overflow {
overflow-wrap: break-word;
+ width: 170px;
+ display: inline-block;
+ text-align: left;
+}
+
+.text-overflow-experiment-name {
+ overflow-wrap: break-word;
} \ No newline at end of file
diff --git a/frontend/src/app/_pages/experiment/experiment.component.html b/frontend/src/app/_pages/experiment/experiment.component.html
index 8f462f86..e807dd06 100644
--- a/frontend/src/app/_pages/experiment/experiment.component.html
+++ b/frontend/src/app/_pages/experiment/experiment.component.html
@@ -2,10 +2,10 @@
<div class="d-flex flex-colum align-items-center sidenav">
<div>
<div class="ekspName " style="width: 250px;">
- <div class="text-overflow" *ngIf="experiment.name=='exp1'" style="width: 250px;">
+ <div class="text-overflow-experiment-name" *ngIf="experiment.name=='exp1'" style="width: 250px;">
Novi Eksperiment
</div>
- <div class="text-overflow" *ngIf="experiment.name!='exp1'" style="width: 250px;">
+ <div class="text-overflow-experiment-name" *ngIf="experiment.name!='exp1'" style="width: 250px;">
{{experiment.name}}
</div>
@@ -14,37 +14,37 @@
<mat-step [completed]="this.step1">
<!--editable="false"-->
<ng-template matStepLabel>
- <span class="label" *ngIf="dataset==undefined">Izvor podataka </span>
- <span class="label addedElement" *ngIf="dataset!=undefined">{{dataset.name}}</span>
+ <span class="label text-overflow" *ngIf="dataset==undefined">Izvor podataka </span>
+ <span class="label addedElement text-overflow" *ngIf="dataset!=undefined">{{dataset.name}}</span>
</ng-template>
<ng-template matStepContent>
- <p class="text-left">Izaberite izvor podataka</p>
+ <p class="text-left text-overflow">Izaberite izvor podataka</p>
</ng-template>
</mat-step>
<mat-step [completed]="experiment._id!=''">
<ng-template matStepLabel>
- <span class="label addedElement" *ngIf="experiment._id!=''">Predvideti:{{experiment.outputColumn}}</span>
+ <span class="label addedElement text-overflow" *ngIf="experiment._id!=''">Predvideti:{{experiment.outputColumn}}</span>
<span *ngIf="!this.step1" class="align-middle"><mat-icon>lock</mat-icon></span>
- <span class="label" *ngIf="experiment._id==''">Odabir kolona </span>
+ <span class="label text-overflow" *ngIf="experiment._id==''">Odabir kolona </span>
</ng-template>
<ng-template matStepContent>
- <p class="text-left">Pripremite podatke i izaberite izlazne kolone</p>
+ <p class="text-left text-overflow">Pripremite podatke i izaberite izlazne kolone</p>
</ng-template>
</mat-step>
<mat-step [completed]="this.step3">
<ng-template matStepLabel>
<span *ngIf="experiment._id==''" class="align-middle"><mat-icon>lock</mat-icon></span>
- <span class="label addedElement" *ngIf="modelToTrain!=undefined">{{modelToTrain.name}}</span>
- <span class="label" *ngIf="modelToTrain==undefined">Treniranje</span>
+ <span class="label addedElement text-overflow" *ngIf="modelToTrain!=undefined">{{modelToTrain.name}}</span>
+ <span class="label text-overflow" *ngIf="modelToTrain==undefined">Treniranje</span>
</ng-template>
- <p class="text-left">Odaberite parametre i trenirajte model</p>
+ <p class="text-left text-overflow">Odaberite parametre i trenirajte model</p>
</mat-step>
<mat-step [completed]="this.step4">
<ng-template matStepLabel>
<span *ngIf="!this.step3" class="align-middle"><mat-icon>lock</mat-icon></span>
- <span class="label">Pregled rezultata<br> treniranja</span>
+ <span class="label text-overflow">Pregled rezultata<br> treniranja</span>
</ng-template>
- <p class="text-left">Pregledajte tok treniranja i<br> grafički prikaz rezultata</p>
+ <p class="text-left text-overflow">Pregledajte tok treniranja i<br> grafički prikaz rezultata</p>
</mat-step>
</mat-stepper>
</div>
diff --git a/frontend/src/app/_pages/experiment/experiment.component.ts b/frontend/src/app/_pages/experiment/experiment.component.ts
index 312b1af1..6c8e96b3 100644
--- a/frontend/src/app/_pages/experiment/experiment.component.ts
+++ b/frontend/src/app/_pages/experiment/experiment.component.ts
@@ -14,6 +14,7 @@ import { SignalRService } from 'src/app/_services/signal-r.service';
import { MetricViewComponent } from 'src/app/_elements/metric-view/metric-view.component';
import { ActivatedRoute, Router } from '@angular/router';
import { DatasetsService } from 'src/app/_services/datasets.service';
+import { PredictorsService } from 'src/app/_services/predictors.service';
@Component({
selector: 'app-experiment',
@@ -39,24 +40,47 @@ export class ExperimentComponent implements AfterViewInit, OnInit {
step3: boolean = false;
step4: boolean = false;
- constructor(private experimentsService: ExperimentsService, private modelsService: ModelsService, private datasetsService: DatasetsService, private signalRService: SignalRService, private route: ActivatedRoute) {
+ constructor(private experimentsService: ExperimentsService, private modelsService: ModelsService, private datasetsService: DatasetsService, private predictorsService: PredictorsService, private signalRService: SignalRService, private route: ActivatedRoute) {
this.experiment = new Experiment("exp1");
}
ngOnInit(): void {
this.route.queryParams.subscribe(params => {
+
let experimentId = this.route.snapshot.paramMap.get("id");
- if (experimentId == null)
- return;
- this.experimentsService.getExperimentById(experimentId).subscribe((response) => {
- this.experiment = response;
- this.datasetsService.getDatasetById(this.experiment.datasetId).subscribe((response: Dataset) => {
- this.dataset = response;
-
- this.folderDataset.forExperiment = this.experiment;
- this.folderDataset.selectFile(this.dataset);
+ let predictorId = this.route.snapshot.paramMap.get("predictorId");
+
+ if (predictorId != null && experimentId != null) {
+ this.experimentsService.getExperimentById(experimentId).subscribe((response) => {
+ this.experiment = response;
+ this.datasetsService.getDatasetById(this.experiment.datasetId).subscribe((response: Dataset) => {
+ this.dataset = response;
+ this.folderDataset.forExperiment = this.experiment;
+ this.folderDataset.selectFile(this.dataset); //sad 3. i 4. korak da se ucitaju
+
+ //this.predictorsService.getPredictor(predictorId!).subscribe((response) => {
+ let predictor = response;
+ //this.modelsService.getModelById(predictor.modelId).subscribe((response) => {
+ this.modelsService.getModelById("62853d70696d62ceeb8db7cd").subscribe((response) => {
+ //imamo model
+ this.folderModel.formModel.newModel = response;
+ //this.metricView.update(predictor.metrics);
+ });
+ //});
+ });
});
- });
+ }
+ else if (predictorId == null && experimentId != null) {
+ this.experimentsService.getExperimentById(experimentId).subscribe((response) => {
+ this.experiment = response;
+ this.datasetsService.getDatasetById(this.experiment.datasetId).subscribe((response: Dataset) => {
+ this.dataset = response;
+ this.folderDataset.forExperiment = this.experiment;
+ this.folderDataset.selectFile(this.dataset);
+ });
+ });
+ }
+
});
}
diff --git a/frontend/src/app/_services/models.service.ts b/frontend/src/app/_services/models.service.ts
index fc888556..f5d95ec1 100644
--- a/frontend/src/app/_services/models.service.ts
+++ b/frontend/src/app/_services/models.service.ts
@@ -31,6 +31,10 @@ export class ModelsService {
addModel(model: Model): Observable<any> {
return this.http.post(`${Configuration.settings.apiURL}/model/add`, model, { headers: this.authService.authHeader() });
}
+
+ stealModel(model: Model): Observable<any> {
+ return this.http.post(`${Configuration.settings.apiURL}/model/stealModel`, model, { headers: this.authService.authHeader() });
+ }
addDataset(dataset: Dataset): Observable<any> {
return this.http.post(`${Configuration.settings.apiURL}/dataset/add`, dataset, { headers: this.authService.authHeader() });
}
@@ -58,4 +62,8 @@ export class ModelsService {
return this.http.get<Model[]>(`${Configuration.settings.apiURL}/model/publicmodels`, { headers: this.authService.authHeader() });
}
+ getModelById(modelId: string): Observable<Model> {
+ return this.http.get<Model>(`${Configuration.settings.apiURL}/model/byid/${modelId}`, { headers: this.authService.authHeader() });
+ }
+
}
diff --git a/frontend/src/app/app-routing.module.ts b/frontend/src/app/app-routing.module.ts
index 9f8c623d..56442842 100644
--- a/frontend/src/app/app-routing.module.ts
+++ b/frontend/src/app/app-routing.module.ts
@@ -12,12 +12,14 @@ import { TestComponent } from './_pages/test/test.component';
const routes: Routes = [
{ path: '', component: HomeComponent, data: { title: 'Početna strana' } },
+ { path: 'experiment/:id/: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: 'profile', component: ProfileComponent, canActivate: [AuthGuardService], data: { title: 'Profil' } },
{ path: 'playground', component: PlaygroundComponent, data: { title: 'Zabava' } },
- { path: 'test', component: TestComponent, data: { title: 'Test' } }
+ { path: 'test', component: TestComponent, data: { title: 'Test' } },
+ { path: '**', redirectTo: '' }
];
@NgModule({