fix bar chart

master
parent 74151a6094
commit 4967b2c370
  1. BIN
      __pycache__/run.cpython-37.pyc
  2. 2
      cache_dir/joblib/run/GridSearchForModels/6ca078b89780ce51f8c908be394b0a91/metadata.json
  3. 0
      cache_dir/joblib/run/GridSearchForModels/6ca078b89780ce51f8c908be394b0a91/output.pkl
  4. 1
      cache_dir/joblib/run/GridSearchForModels/b32ac658efc96fe80763fbc6cdd8559c/metadata.json
  5. 0
      cache_dir/joblib/run/GridSearchForModels/b32ac658efc96fe80763fbc6cdd8559c/output.pkl
  6. 96
      cache_dir/joblib/run/GridSearchForModels/func_code.py
  7. 1
      cache_dir/joblib/run/GridSearchForParameters/6ca078b89780ce51f8c908be394b0a91/metadata.json
  8. BIN
      cache_dir/joblib/run/GridSearchForParameters/6ca078b89780ce51f8c908be394b0a91/output.pkl
  9. 2
      cache_dir/joblib/run/GridSearchForParameters/b32ac658efc96fe80763fbc6cdd8559c/metadata.json
  10. BIN
      cache_dir/joblib/run/GridSearchForParameters/b32ac658efc96fe80763fbc6cdd8559c/output.pkl
  11. 66
      cache_dir/joblib/run/GridSearchForParameters/func_code.py
  12. BIN
      cachedir/joblib/run/GridSearchForModels/1ace3632acb8ced29677b3bf1fd54ebb/output.pkl
  13. 1
      cachedir/joblib/run/GridSearchForModels/369469c4c53064fdb6191f1f295902f7/metadata.json
  14. BIN
      cachedir/joblib/run/GridSearchForModels/4b0679293742f99381cce3660e671df7/output.pkl
  15. 1
      cachedir/joblib/run/GridSearchForModels/d44ab74114f87bbccdbdd1a5d904bd4a/metadata.json
  16. 128
      cachedir/joblib/run/GridSearchForModels/func_code.py
  17. 300
      frontend/package-lock.json
  18. 18
      frontend/package.json
  19. 4
      frontend/src/components/AlgorithmHyperParam.vue
  20. 141
      frontend/src/components/Algorithms.vue
  21. 133
      frontend/src/components/BalancePredictions.vue
  22. 273
      frontend/src/components/BarChart.vue
  23. 1
      frontend/src/components/Controller.vue
  24. 4
      frontend/src/components/FinalResultsLinePlot.vue
  25. 40
      frontend/src/components/Main.vue
  26. 5
      frontend/src/components/PerMetricBarChart.vue
  27. 91
      frontend/src/components/Provenance.vue
  28. 73
      frontend/src/components/ScatterPlot.vue
  29. 4
      frontend/src/main.js
  30. 3
      package-lock.json
  31. 476
      run.py

Binary file not shown.

@ -1 +1 @@
{"duration": 15.238354921340942, "input_args": {"clf": "RandomForestClassifier(bootstrap=True, class_weight=None, criterion='gini',\n max_depth=None, max_features='auto', max_leaf_nodes=None,\n min_impurity_decrease=0.0, min_impurity_split=None,\n min_samples_leaf=1, min_samples_split=2,\n min_weight_fraction_leaf=0.0, n_estimators='warn',\n n_jobs=None, oob_score=False, random_state=None,\n verbose=0, warm_start=False)", "params": "{'n_estimators': [80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119], 'criterion': ['gini', 'entropy']}"}}
{"duration": 13.885742902755737, "input_args": {"clf": "RandomForestClassifier(bootstrap=True, class_weight=None, criterion='gini',\n max_depth=None, max_features='auto', max_leaf_nodes=None,\n min_impurity_decrease=0.0, min_impurity_split=None,\n min_samples_leaf=1, min_samples_split=2,\n min_weight_fraction_leaf=0.0, n_estimators='warn',\n n_jobs=None, oob_score=False, random_state=None,\n verbose=0, warm_start=False)", "params": "{'n_estimators': [80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119], 'criterion': ['gini', 'entropy']}", "eachAlgor": "'RF'", "factors": "[1, 1, 1, 1, 1, 1]"}}

@ -0,0 +1 @@
{"duration": 36.23512291908264, "input_args": {"clf": "KNeighborsClassifier(algorithm='auto', leaf_size=30, metric='minkowski',\n metric_params=None, n_jobs=None, n_neighbors=5, p=2,\n weights='uniform')", "params": "{'n_neighbors': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24], 'weights': ['uniform', 'distance'], 'algorithm': ['brute', 'kd_tree', 'ball_tree'], 'metric': ['chebyshev', 'manhattan', 'euclidean', 'minkowski']}", "eachAlgor": "'KNN'", "factors": "[1, 1, 1, 1, 1, 1]"}}

@ -0,0 +1,96 @@
# first line: 714
def GridSearchForModels(clf, params, eachAlgor, factors):
# scoring parameters
global scoring
# number of scoring parameters
global NumberofscoringMetrics
# crossvalidation number
global crossValidation
# instantiate spark session
spark = (
SparkSession
.builder
.getOrCreate()
)
sc = spark.sparkContext
# this is the grid we use to train the models
grid = DistGridSearchCV(
estimator=clf, param_grid=params,
sc=sc, cv=crossValidation, refit='accuracy', scoring=scoring,
verbose=0, n_jobs=-1)
# fit and extract the probabilities
grid.fit(XData, yData)
yPredict = grid.predict(XData)
# process the results
cv_results = []
cv_results.append(grid.cv_results_)
df_cv_results = pd.DataFrame.from_dict(cv_results)
# number of models stored
number_of_models = len(df_cv_results.iloc[0][0])
# initialize results per row
df_cv_results_per_row = []
# loop through number of models
for i in range(number_of_models):
# initialize results per item
df_cv_results_per_item = []
for column in df_cv_results.iloc[0]:
df_cv_results_per_item.append(column[i])
df_cv_results_per_row.append(df_cv_results_per_item)
# store the results into a pandas dataframe
df_cv_results_classifiers = pd.DataFrame(data = df_cv_results_per_row, columns= df_cv_results.columns)
# copy and filter in order to get only the metrics
metrics = df_cv_results_classifiers.copy()
metrics = metrics.filter(['mean_test_accuracy','mean_test_f1_macro','mean_test_precision','mean_test_recall','mean_test_jaccard'])
# control the factors
sumperModel = []
for row in metrics.iterrows():
rowSum = 0
lengthFactors = NumberofscoringMetrics
for loop,elements in enumerate(row):
lengthFactors = lengthFactors - 1 + factors[loop]
rowSum = elements*factors[loop] + rowSum
if lengthFactors is 0:
sumperModel = 0
else:
sumperModel.append(rowSum/lengthFactors)
# summarize all models metrics
summarizedMetrics = pd.DataFrame(sumperModel)
summarizedMetrics.rename(columns={0:'sum'})
yPredictProb.append(grid.predict_proba(XData))
# retrieve target names (class names)
global target_names
PerClassMetric = []
PerClassMetric.append(classification_report(yData, yPredict, target_names=target_names, digits=2, output_dict=True))
PerClassMetricPandas = pd.DataFrame(PerClassMetric)
print(PerClassMetricPandas)
del PerClassMetricPandas['accuracy']
del PerClassMetricPandas['macro avg']
del PerClassMetricPandas['weighted avg']
PerClassMetricPandas = PerClassMetricPandas.to_json()
# concat parameters and performance
parameters = pd.DataFrame(df_cv_results_classifiers['params'])
parametersPerformancePerModel = pd.concat([summarizedMetrics, parameters], axis=1)
parametersPerformancePerModel = parametersPerformancePerModel.to_json()
# make global the parameters performance to send it back
global allParametersPerformancePerModel
allParametersPerformancePerModel.append(parametersPerformancePerModel)
allParametersPerformancePerModel.append(PerClassMetricPandas)
return 'Everything is okay'

@ -0,0 +1 @@
{"duration": 11.80344295501709, "input_args": {"clf": "RandomForestClassifier(bootstrap=True, class_weight=None, criterion='gini',\n max_depth=None, max_features='auto', max_leaf_nodes=None,\n min_impurity_decrease=0.0, min_impurity_split=None,\n min_samples_leaf=1, min_samples_split=2,\n min_weight_fraction_leaf=0.0, n_estimators='warn',\n n_jobs=None, oob_score=False, random_state=None,\n verbose=0, warm_start=False)", "params": "{'n_estimators': [80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119], 'criterion': ['gini', 'entropy']}", "eachAlgor": "'RF'", "factors": "[1, 1, 1, 1, 1, 1]"}}

@ -1 +1 @@
{"duration": 4.3733649253845215, "input_args": {"clf": "KNeighborsClassifier(algorithm='auto', leaf_size=30, metric='minkowski',\n metric_params=None, n_jobs=None, n_neighbors=5, p=2,\n weights='uniform')", "params": "{'n_neighbors': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24], 'weights': ['uniform', 'distance'], 'algorithm': ['brute', 'kd_tree', 'ball_tree'], 'metric': ['chebyshev', 'manhattan', 'euclidean', 'minkowski']}"}}
{"duration": 28.940529108047485, "input_args": {"clf": "KNeighborsClassifier(algorithm='auto', leaf_size=30, metric='minkowski',\n metric_params=None, n_jobs=None, n_neighbors=5, p=2,\n weights='uniform')", "params": "{'n_neighbors': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24], 'weights': ['uniform', 'distance'], 'algorithm': ['brute', 'kd_tree', 'ball_tree'], 'metric': ['chebyshev', 'manhattan', 'euclidean', 'minkowski']}", "eachAlgor": "'KNN'", "factors": "[1, 1, 1, 1, 1, 1]"}}

@ -1,16 +1,33 @@
# first line: 484
def GridSearchForParameters(clf, params):
grid = GridSearchCV(estimator=clf,
param_grid=params,
scoring='accuracy',
cv=crossValidation,
n_jobs = -1)
# first line: 705
def GridSearchForParameters(clf, params, eachAlgor, factors):
global scoring
global NumberofscoringMetrics
# instantiate spark session
spark = (
SparkSession
.builder
.getOrCreate()
)
sc = spark.sparkContext
scoring = {'accuracy': 'accuracy', 'f1_macro': 'f1_weighted', 'precision': 'precision_weighted', 'recall': 'recall_weighted', 'jaccard': 'jaccard_weighted'}
global crossValidation
NumberofscoringMetrics = len(scoring)
grid = DistGridSearchCV(
estimator=clf, param_grid=params,
sc=sc, cv=crossValidation, refit='accuracy', scoring=scoring,
verbose=0, n_jobs=-1)
grid.fit(XData, yData)
yPredict = grid.predict(XData)
cv_results = []
cv_results.append(grid.cv_results_)
df_cv_results = pd.DataFrame.from_dict(cv_results)
number_of_classifiers = len(df_cv_results.iloc[0][0])
number_of_columns = len(df_cv_results.iloc[0])
df_cv_results_per_item = []
df_cv_results_per_row = []
@ -22,7 +39,38 @@ def GridSearchForParameters(clf, params):
df_cv_results_classifiers = pd.DataFrame(data = df_cv_results_per_row, columns= df_cv_results.columns)
global allParametersPerformancePerModel
parametersPerformancePerModel = df_cv_results_classifiers[['mean_test_score','params']]
global parametersPerformancePerModel
metrics = df_cv_results_classifiers.copy()
metrics = metrics.filter(['mean_test_accuracy','mean_test_f1_macro','mean_test_precision','mean_test_recall','mean_test_jaccard'])
sumperModel = []
global rowSum
for index, row in metrics.iterrows():
rowSum = 0
lengthFactors = NumberofscoringMetrics
for loop,elements in enumerate(row):
lengthFactors = lengthFactors - 1 + factors[loop]
rowSum = elements*factors[loop] + rowSum
if lengthFactors is 0:
sumperModel = 0
else:
sumperModel.append(rowSum/lengthFactors)
global target_names
global PerClassMetric
global PerClassMetricPandas
PerClassMetric = []
yPredictProb.append(grid.predict_proba(XData))
PerClassMetric.append(classification_report(yData, yPredict, target_names=target_names, digits=2, output_dict=True))
PerClassMetricPandas = pd.DataFrame(PerClassMetric)
del PerClassMetricPandas['accuracy']
del PerClassMetricPandas['macro avg']
del PerClassMetricPandas['weighted avg']
summarizedMetrics = pd.DataFrame(sumperModel)
summarizedMetrics.rename(columns={0:'sum'})
parameters = pd.DataFrame(df_cv_results_classifiers['params'])
parametersPerformancePerModel = pd.concat([summarizedMetrics, parameters], axis=1)
PerClassMetricPandas = PerClassMetricPandas.to_json()
parametersPerformancePerModel = parametersPerformancePerModel.to_json()
allParametersPerformancePerModel.append(parametersPerformancePerModel)
allParametersPerformancePerModel.append(PerClassMetricPandas)
return 'Everything is okay'

@ -0,0 +1 @@
{"duration": 288.6949689388275, "input_args": {"clf": "KNeighborsClassifier(algorithm='ball_tree', leaf_size=30, metric='minkowski',\n metric_params=None, n_jobs=None, n_neighbors=24, p=2,\n weights='distance')", "params": "{'n_neighbors': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24], 'weights': ['uniform', 'distance'], 'algorithm': ['brute', 'kd_tree', 'ball_tree'], 'metric': ['chebyshev', 'manhattan', 'euclidean', 'minkowski']}", "eachAlgor": "'KNN'", "factors": "[1, 1, 1, 1, 1]", "AlgorithmsIDsEnd": "0"}}

@ -0,0 +1 @@
{"duration": 227.36859011650085, "input_args": {"clf": "RandomForestClassifier(bootstrap=True, class_weight=None, criterion='entropy',\n max_depth=None, max_features='auto', max_leaf_nodes=None,\n min_impurity_decrease=0.0, min_impurity_split=None,\n min_samples_leaf=1, min_samples_split=2,\n min_weight_fraction_leaf=0.0, n_estimators=119,\n n_jobs=None, oob_score=False, random_state=None,\n verbose=0, warm_start=False)", "params": "{'n_estimators': [80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119], 'criterion': ['gini', 'entropy']}", "eachAlgor": "'RF'", "factors": "[1, 1, 1, 1, 1]", "AlgorithmsIDsEnd": "576"}}

@ -0,0 +1,128 @@
# first line: 634
@memory.cache
def GridSearchForModels(clf, params, eachAlgor, factors, AlgorithmsIDsEnd):
# instantiate spark session
spark = (
SparkSession
.builder
.getOrCreate()
)
sc = spark.sparkContext
# this is the grid we use to train the models
grid = DistGridSearchCV(
estimator=clf, param_grid=params,
sc=sc, cv=crossValidation, refit='accuracy', scoring=scoring,
verbose=0, n_jobs=-1)
# fit and extract the probabilities
grid.fit(XData, yData)
# process the results
cv_results = []
cv_results.append(grid.cv_results_)
df_cv_results = pd.DataFrame.from_dict(cv_results)
# number of models stored
number_of_models = len(df_cv_results.iloc[0][0])
# initialize results per row
df_cv_results_per_row = []
# loop through number of models
modelsIDs = []
for i in range(number_of_models):
modelsIDs.append(AlgorithmsIDsEnd+i)
# initialize results per item
df_cv_results_per_item = []
for column in df_cv_results.iloc[0]:
df_cv_results_per_item.append(column[i])
df_cv_results_per_row.append(df_cv_results_per_item)
# store the results into a pandas dataframe
df_cv_results_classifiers = pd.DataFrame(data = df_cv_results_per_row, columns= df_cv_results.columns)
# copy and filter in order to get only the metrics
metrics = df_cv_results_classifiers.copy()
metrics = metrics.filter(['mean_test_accuracy','mean_test_f1_macro','mean_test_precision','mean_test_recall','mean_test_jaccard'])
# control the factors
sumperModel = []
for index, row in metrics.iterrows():
rowSum = 0
lengthFactors = NumberofscoringMetrics
for loop,elements in enumerate(row):
lengthFactors = lengthFactors - 1 + factors[loop]
rowSum = elements*factors[loop] + rowSum
if lengthFactors is 0:
sumperModel = 0
else:
sumperModel.append(rowSum/lengthFactors)
# summarize all models metrics
summarizedMetrics = pd.DataFrame(sumperModel)
summarizedMetrics.rename(columns={0:'sum'})
# concat parameters and performance
parameters = pd.DataFrame(df_cv_results_classifiers['params'])
parametersPerformancePerModel = pd.concat([summarizedMetrics, parameters], axis=1)
parametersPerformancePerModel = parametersPerformancePerModel.to_json()
parametersLocal = json.loads(parametersPerformancePerModel)['params'].copy()
Models = []
for index, items in enumerate(parametersLocal):
Models.append(str(index))
parametersLocalNew = [ parametersLocal[your_key] for your_key in Models ]
permList = []
PerFeatureAccuracy = []
PerClassMetric = []
for eachModelParameters in parametersLocalNew:
clf.set_params(**eachModelParameters)
perm = PermutationImportance(clf, cv = None, refit = True, n_iter = 25).fit(XData, yData)
permList.append(perm.feature_importances_)
n_feats = XData.shape[1]
for i in range(n_feats):
scores = model_selection.cross_val_score(clf, XData.values[:, i].reshape(-1, 1), yData, cv=crossValidation)
PerFeatureAccuracy.append(scores.mean())
clf.fit(XData, yData)
yPredict = clf.predict(XData)
# retrieve target names (class names)
PerClassMetric.append(classification_report(yData, yPredict, target_names=target_names, digits=2, output_dict=True))
PerClassMetricPandas = pd.DataFrame(PerClassMetric)
del PerClassMetricPandas['accuracy']
del PerClassMetricPandas['macro avg']
del PerClassMetricPandas['weighted avg']
PerClassMetricPandas = PerClassMetricPandas.to_json()
perm_imp_eli5PD = pd.DataFrame(permList)
perm_imp_eli5PD = perm_imp_eli5PD.to_json()
PerFeatureAccuracyPandas = pd.DataFrame(PerFeatureAccuracy)
PerFeatureAccuracyPandas = PerFeatureAccuracyPandas.to_json()
bestfeatures = SelectKBest(score_func=chi2, k='all')
fit = bestfeatures.fit(XData,yData)
dfscores = pd.DataFrame(fit.scores_)
dfcolumns = pd.DataFrame(XData.columns)
featureScores = pd.concat([dfcolumns,dfscores],axis=1)
featureScores.columns = ['Specs','Score'] #naming the dataframe columns
featureScores = featureScores.to_json()
# gather the results and send them back
results.append(modelsIDs) # Position: 0 and so on
results.append(parametersPerformancePerModel) # Position: 1 and so on
results.append(PerClassMetricPandas) # Position: 2 and so on
results.append(PerFeatureAccuracyPandas) # Position: 3 and so on
results.append(perm_imp_eli5PD) # Position: 4 and so on
results.append(featureScores) # Position: 5 and so on
return results

@ -1807,9 +1807,9 @@
"integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA=="
},
"@types/node": {
"version": "12.7.9",
"resolved": "https://registry.npmjs.org/@types/node/-/node-12.7.9.tgz",
"integrity": "sha512-P57oKTJ/vYivL2BCfxCC5tQjlS8qW31pbOL6qt99Yrjm95YdHgNZwjrTTjMBh+C2/y6PXIX4oz253+jUzxKKfQ=="
"version": "12.7.11",
"resolved": "https://registry.npmjs.org/@types/node/-/node-12.7.11.tgz",
"integrity": "sha512-Otxmr2rrZLKRYIybtdG/sgeO+tHY20GxeDjcGmUnmmlCWyEnv2a2x1ZXBo3BTec4OiTXMQCiazB8NMBf0iRlFw=="
},
"@types/q": {
"version": "1.5.2",
@ -2188,6 +2188,14 @@
}
}
},
"allofw": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/allofw/-/allofw-0.1.0.tgz",
"integrity": "sha1-AmxSVpoJaAeGrxOwva3uYRLXfPY=",
"requires": {
"tar": "^4.1.1"
}
},
"almost-equal": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/almost-equal/-/almost-equal-1.1.0.tgz",
@ -3043,31 +3051,77 @@
"integrity": "sha1-/vF92Erx3NKlYz/UbTsa3LCEvzs="
},
"autoprefixer": {
"version": "9.6.1",
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.6.1.tgz",
"integrity": "sha512-aVo5WxR3VyvyJxcJC3h4FKfwCQvQWb1tSI5VHNibddCVWrcD1NvlxEweg3TSgiPztMnWfjpy2FURKA2kvDE+Tw==",
"version": "9.6.4",
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.6.4.tgz",
"integrity": "sha512-Koz2cJU9dKOxG8P1f8uVaBntOv9lP4yz9ffWvWaicv9gHBPhpQB22nGijwd8gqW9CNT+UdkbQOQNLVI8jN1ZfQ==",
"dev": true,
"requires": {
"browserslist": "^4.6.3",
"caniuse-lite": "^1.0.30000980",
"browserslist": "^4.7.0",
"caniuse-lite": "^1.0.30000998",
"chalk": "^2.4.2",
"normalize-range": "^0.1.2",
"num2fraction": "^1.2.2",
"postcss": "^7.0.17",
"postcss-value-parser": "^4.0.0"
"postcss": "^7.0.18",
"postcss-value-parser": "^4.0.2"
},
"dependencies": {
"browserslist": {
"version": "4.7.0",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.7.0.tgz",
"integrity": "sha512-9rGNDtnj+HaahxiVV38Gn8n8Lr8REKsel68v1sPFfIGEK6uSXTY3h9acgiT1dZVtOOUtifo/Dn8daDQ5dUgVsA==",
"dev": true,
"requires": {
"caniuse-lite": "^1.0.30000989",
"electron-to-chromium": "^1.3.247",
"node-releases": "^1.1.29"
}
},
"caniuse-lite": {
"version": "1.0.30000984",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000984.tgz",
"integrity": "sha512-n5tKOjMaZ1fksIpQbjERuqCyfgec/m9pferkFQbLmWtqLUdmt12hNhjSwsmPdqeiG2NkITOQhr1VYIwWSAceiA==",
"version": "1.0.30000999",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000999.tgz",
"integrity": "sha512-1CUyKyecPeksKwXZvYw0tEoaMCo/RwBlXmEtN5vVnabvO0KPd9RQLcaAuR9/1F+KDMv6esmOFWlsXuzDk+8rxg==",
"dev": true
},
"electron-to-chromium": {
"version": "1.3.277",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.277.tgz",
"integrity": "sha512-Czmsrgng89DOgJlIknnw9bn5431QdtnUwGp5YYiPwU1DbZQUxCLF+rc1ZC09VNAdalOPcvH6AE8BaA0H5HjI/w==",
"dev": true
},
"node-releases": {
"version": "1.1.34",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.34.tgz",
"integrity": "sha512-fNn12JTEfniTuCqo0r9jXgl44+KxRH/huV7zM/KAGOKxDKrHr6EbT7SSs4B+DNxyBE2mks28AD+Jw6PkfY5uwA==",
"dev": true,
"requires": {
"semver": "^6.3.0"
}
},
"postcss": {
"version": "7.0.18",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.18.tgz",
"integrity": "sha512-/7g1QXXgegpF+9GJj4iN7ChGF40sYuGYJ8WZu8DZWnmhQ/G36hfdk3q9LBJmoK+lZ+yzZ5KYpOoxq7LF1BxE8g==",
"dev": true,
"requires": {
"chalk": "^2.4.2",
"source-map": "^0.6.1",
"supports-color": "^6.1.0"
}
},
"postcss-value-parser": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.0.0.tgz",
"integrity": "sha512-ESPktioptiSUchCKgggAkzdmkgzKfmp0EU8jXH+5kbIUB+unr0Y4CY9SRMvibuvYUBjNh1ACLbxqYNpdTQOteQ==",
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.0.2.tgz",
"integrity": "sha512-LmeoohTpp/K4UiyQCwuGWlONxXamGzCMtFxLq4W1nZVGIQLYvMCJx3yAF9qyyuFpflABI9yVdtJAqbihOsCsJQ==",
"dev": true
},
"supports-color": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
"integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
"dev": true,
"requires": {
"has-flag": "^3.0.0"
}
}
}
},
@ -5205,9 +5259,9 @@
"integrity": "sha1-K4hTT8G5mGdPh3+Yug2LW3Q+lv4="
},
"bootstrap-vue": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/bootstrap-vue/-/bootstrap-vue-2.0.2.tgz",
"integrity": "sha512-hbGJjc/om9JfVNUFK76dnh+YutlZdZlKbpWw6OE9gHTkmbwstP/KxxELpZZgK/4SYtdxUPt/6W1CvdaeT1bNvQ==",
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/bootstrap-vue/-/bootstrap-vue-2.0.3.tgz",
"integrity": "sha512-foI+NRs54lmjpneuwgXrmoOVDg8419ai9IwZNQq29Mnfmfui66UKS89GJnA4RjXJPjFbrIgjnjniaeqF/GOWBQ==",
"requires": {
"@nuxt/opencollective": "^0.3.0",
"bootstrap": ">=4.3.1 <5.0.0",
@ -10455,11 +10509,11 @@
}
},
"fs-minipass": {
"version": "1.2.6",
"resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.6.tgz",
"integrity": "sha512-crhvyXcMejjv3Z5d2Fa9sf5xLYVCF5O1c71QxbVnbLsmYMBEvDAftewesN/HhY03YRoA7zOMxjNGrF5svGaaeQ==",
"version": "1.2.7",
"resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz",
"integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==",
"requires": {
"minipass": "^2.2.1"
"minipass": "^2.6.0"
}
},
"fs-write-stream-atomic": {
@ -14579,9 +14633,9 @@
}
},
"yallist": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz",
"integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A=="
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
"integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="
}
}
},
@ -15372,27 +15426,27 @@
"integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0="
},
"minipass": {
"version": "2.6.0",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-2.6.0.tgz",
"integrity": "sha512-OuNZ0OHrrI+jswzmgivYBZ+fAAGHZA4293d5q0z631/I9QSw3yumKB92njxHIHiB1eAdGRsE+3CcOPkoEyV5FQ==",
"version": "2.9.0",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz",
"integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==",
"requires": {
"safe-buffer": "^5.1.2",
"yallist": "^3.0.0"
},
"dependencies": {
"yallist": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz",
"integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A=="
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
"integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="
}
}
},
"minizlib": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.2.2.tgz",
"integrity": "sha512-hR3At21uSrsjjDTWrbu0IMLTpnkpv8IIMFDFaoz43Tmu4LkmAXfH44vNNzpTnf+OAQQCHrb91y/wc2J4x5XgSQ==",
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz",
"integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==",
"requires": {
"minipass": "^2.2.1"
"minipass": "^2.9.0"
}
},
"mississippi": {
@ -15814,9 +15868,9 @@
}
},
"node-forge": {
"version": "0.8.2",
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.8.2.tgz",
"integrity": "sha512-mXQ9GBq1N3uDCyV1pdSzgIguwgtVpM7f5/5J4ipz12PKWElmPpVWLDuWl8iXmhysr21+WmX/OJ5UKx82wjomgg==",
"version": "0.9.0",
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.9.0.tgz",
"integrity": "sha512-7ASaDa3pD+lJ3WvXFsxekJQelBKRpne+GOVbLbtHYdd7pFspyeuJHnWfLplGf3SwKGbfs/aYl5V/JCIaHVUKKQ==",
"dev": true
},
"node-libs-browser": {
@ -16002,9 +16056,9 @@
"integrity": "sha1-RWNg5g7Odfvve11+FgSA5//Rb+U="
},
"normalize-url": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.3.0.tgz",
"integrity": "sha512-0NLtR71o4k6GLP+mr6Ty34c5GA6CMoEsncKJxvQd8NzPxaHRJNnb5gZE8R1XF4CPIS7QPHLJ74IFszwtNVAHVQ=="
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.0.tgz",
"integrity": "sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ=="
},
"normals": {
"version": "1.1.0",
@ -16025,14 +16079,14 @@
"integrity": "sha512-8/JCaftHwbd//k6y2rEWp6k1wxVfpFzB6t1p825+cUb7Ym2XQfhwIC5KwhrvzZRJu+LtDE585zVaS32+CGtf0g=="
},
"npm-check-updates": {
"version": "3.1.23",
"resolved": "https://registry.npmjs.org/npm-check-updates/-/npm-check-updates-3.1.23.tgz",
"integrity": "sha512-Z2dkMdNgue6OPkQDPcAK62Qrwv+G1PaEmKrDrrSAiSP7pRD3u30xOVy1nLukS1XrJ2/zF8XTVxFe9/ubcvlcPQ==",
"version": "3.1.24",
"resolved": "https://registry.npmjs.org/npm-check-updates/-/npm-check-updates-3.1.24.tgz",
"integrity": "sha512-8CxlXsSPo8RCAHHqycxU9gcDcSkoBI0I2bkh37HJry2VJhqGxeVnEVq8vtFcigzIRrUgbSOyKgSm+jvu3ookMw==",
"requires": {
"chalk": "^2.4.2",
"cint": "^8.2.1",
"cli-table": "^0.3.1",
"commander": "^3.0.1",
"commander": "^3.0.2",
"fast-diff": "^1.2.0",
"find-up": "4.1.0",
"get-stdin": "^7.0.0",
@ -16052,9 +16106,9 @@
},
"dependencies": {
"commander": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/commander/-/commander-3.0.1.tgz",
"integrity": "sha512-UNgvDd+csKdc9GD4zjtkHKQbT8Aspt2jCBqNSPp53vAS0L1tS9sXB2TCEOPHJ7kt9bN/niWkYj8T3RQSoMXdSQ=="
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/commander/-/commander-3.0.2.tgz",
"integrity": "sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow=="
},
"find-up": {
"version": "4.1.0",
@ -16138,9 +16192,9 @@
}
},
"npm-registry-fetch": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-4.0.1.tgz",
"integrity": "sha512-1ZQ+yjnxc698R5h9Yje9CASapzAZr7aYDkJDdERg9xg2hOEY0vRJwskOaJAXq8N/eLavzvW4g564YAfq6zMn/A==",
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-4.0.2.tgz",
"integrity": "sha512-Z0IFtPEozNdeZRPh3aHHxdG+ZRpzcbQaJLthsm3VhNf6DScicTFRHZzK82u8RsJUsUHkX+QH/zcB/5pmd20H4A==",
"requires": {
"JSONStream": "^1.3.4",
"bluebird": "^3.5.1",
@ -16165,9 +16219,9 @@
"integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg=="
},
"yallist": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz",
"integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A=="
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
"integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="
}
}
},
@ -16832,9 +16886,9 @@
}
},
"chownr": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.2.tgz",
"integrity": "sha512-GkfeAQh+QNy3wquu9oIZr6SS5x7wGdSgNQvD10X3r+AZr1Oys22HW8kAmDMvNg2+Dm0TeGaEuO8gFwdBXxwO8A=="
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.3.tgz",
"integrity": "sha512-i70fVHhmV3DtTl6nqvZOnIjbY0Pe4kAUjwHj8z0zAdgBtYrJyYwLKCCuRBQ5ppkyL0AkN7HKRnETdmdp1zqNXw=="
},
"lru-cache": {
"version": "5.1.1",
@ -16858,9 +16912,9 @@
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ=="
},
"yallist": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz",
"integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A=="
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
"integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="
}
}
},
@ -18683,9 +18737,9 @@
}
},
"json5": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/json5/-/json5-2.1.0.tgz",
"integrity": "sha512-8Mh9h6xViijj36g7Dxi+Y4S6hNGV96vcJZr/SrlHh1LR/pEn/8j/+qIBbs44YKl69Lrfctp4QD+AdWLTMqEZAQ==",
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/json5/-/json5-2.1.1.tgz",
"integrity": "sha512-l+3HXD0GEI3huGq1njuqtzYK8OYJyXMkOLtQ53pjWh89tvWS2h6l+1zMkYWqlb57+SiQodKZyvMEFb2X+KrFhQ==",
"requires": {
"minimist": "^1.2.0"
}
@ -18703,9 +18757,9 @@
}
},
"react": {
"version": "16.10.1",
"resolved": "https://registry.npmjs.org/react/-/react-16.10.1.tgz",
"integrity": "sha512-2bisHwMhxQ3XQz4LiJJwG3360pY965pTl/MRrZYxIBKVj4fOHoDs5aZAkYXGxDRO1Li+SyjTAilQEbOmtQJHzA==",
"version": "16.10.2",
"resolved": "https://registry.npmjs.org/react/-/react-16.10.2.tgz",
"integrity": "sha512-MFVIq0DpIhrHFyqLU0S3+4dIcBhhOvBE8bJ/5kHPVOVaGdo0KuiQzpcjCPsf585WvhypqtrMILyoE2th6dT+Lw==",
"requires": {
"loose-envify": "^1.1.0",
"object-assign": "^4.1.1",
@ -18713,20 +18767,20 @@
}
},
"react-dom": {
"version": "16.10.1",
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.10.1.tgz",
"integrity": "sha512-SmM4ZW0uug0rn95U8uqr52I7UdNf6wdGLeXDmNLfg3y5q5H9eAbdjF5ubQc3bjDyRrvdAB2IKG7X0GzSpnn5Mg==",
"version": "16.10.2",
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.10.2.tgz",
"integrity": "sha512-kWGDcH3ItJK4+6Pl9DZB16BXYAZyrYQItU4OMy0jAkv5aNqc+mAKb4TpFtAteI6TJZu+9ZlNhaeNQSVQDHJzkw==",
"requires": {
"loose-envify": "^1.1.0",
"object-assign": "^4.1.1",
"prop-types": "^15.6.2",
"scheduler": "^0.16.1"
"scheduler": "^0.16.2"
}
},
"react-is": {
"version": "16.10.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.10.1.tgz",
"integrity": "sha512-BXUMf9sIOPXXZWqr7+c5SeOKJykyVr2u0UDzEf4LNGc6taGkQe1A9DFD07umCIXz45RLr9oAAwZbAJ0Pkknfaw=="
"version": "16.10.2",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.10.2.tgz",
"integrity": "sha512-INBT1QEgtcCCgvccr5/86CfD71fw9EPmDxgiJX4I2Ddr6ZsV6iFXsuby+qWJPtmNuMY0zByTsG4468P7nHuNWA=="
},
"read-cache": {
"version": "1.0.0",
@ -19709,9 +19763,9 @@
"integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw=="
},
"scheduler": {
"version": "0.16.1",
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.16.1.tgz",
"integrity": "sha512-MIuie7SgsqMYOdCXVFZa8SKoNorJZUWHW8dPgto7uEHn1lX3fg2Gu0TzgK8USj76uxV7vB5eRMnZs/cdEHg+cg==",
"version": "0.16.2",
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.16.2.tgz",
"integrity": "sha512-BqYVWqwz6s1wZMhjFvLfVR5WXP7ZY32M/wYPo04CcuPM7XZEbV2TBNW7Z0UkguPTl0dWMA59VbNXxK6q+pHItg==",
"requires": {
"loose-envify": "^1.1.0",
"object-assign": "^4.1.1"
@ -19759,12 +19813,12 @@
"dev": true
},
"selfsigned": {
"version": "1.10.6",
"resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.6.tgz",
"integrity": "sha512-i3+CeqxL7DpAazgVpAGdKMwHuL63B5nhJMh9NQ7xmChGkA3jNFflq6Jyo1LLJYcr3idWiNOPWHCrm4zMayLG4w==",
"version": "1.10.7",
"resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.7.tgz",
"integrity": "sha512-8M3wBCzeWIJnQfl43IKwOmC4H/RAp50S8DF60znzjW5GVqTcSe2vWclt7hmYVPkKPlHWOu5EaWOMZ2Y6W8ZXTA==",
"dev": true,
"requires": {
"node-forge": "0.8.2"
"node-forge": "0.9.0"
}
},
"semver": {
@ -20582,14 +20636,20 @@
"integrity": "sha512-to7oADIniaYwS3MhtCa/sQhrxidCCQiF/qp4/m5iN3ipf0Y7Xlri0f6eG29r08aL7JYl8n32AF3Q5GYBZ7K8vw==",
"dev": true
},
"stardust": {
"version": "0.52.5",
"resolved": "https://registry.npmjs.org/stardust/-/stardust-0.52.5.tgz",
"integrity": "sha1-ilnEKnLLVRor61806kqBr92cpDM=",
"stardust-allofw": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/stardust-allofw/-/stardust-allofw-0.1.1.tgz",
"integrity": "sha512-93pnjWtMQx6OT+FmULpEYkJGPJOF5beW4AYrdrAaPnU7ktP4UbzMySbQ0otrUjrO91TT8IWxyyVJg9XHYrd+iw==",
"requires": {
"classnames": "^2.1.5",
"debug": "^2.2.0",
"lodash": "^4.6.1"
"allofw": "0.1.0",
"stardust-core": "^0.1.0"
},
"dependencies": {
"stardust-core": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/stardust-core/-/stardust-core-0.1.1.tgz",
"integrity": "sha1-6gtcxBKrgpnfcf7NrmcN9K5WhPA="
}
}
},
"stardust-core": {
@ -21226,13 +21286,13 @@
}
},
"tar": {
"version": "4.4.10",
"resolved": "https://registry.npmjs.org/tar/-/tar-4.4.10.tgz",
"integrity": "sha512-g2SVs5QIxvo6OLp0GudTqEf05maawKUxXru104iaayWA09551tFCTI8f1Asb4lPfkBr91k07iL4c11XO3/b0tA==",
"version": "4.4.13",
"resolved": "https://registry.npmjs.org/tar/-/tar-4.4.13.tgz",
"integrity": "sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==",
"requires": {
"chownr": "^1.1.1",
"fs-minipass": "^1.2.5",
"minipass": "^2.3.5",
"minipass": "^2.8.6",
"minizlib": "^1.2.1",
"mkdirp": "^0.5.0",
"safe-buffer": "^5.1.2",
@ -21240,9 +21300,9 @@
},
"dependencies": {
"yallist": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz",
"integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A=="
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
"integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="
}
}
},
@ -22467,16 +22527,22 @@
}
},
"url-loader": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/url-loader/-/url-loader-2.1.0.tgz",
"integrity": "sha512-kVrp/8VfEm5fUt+fl2E0FQyrpmOYgMEkBsv8+UDP1wFhszECq5JyGF33I7cajlVY90zRZ6MyfgKXngLvHYZX8A==",
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/url-loader/-/url-loader-2.2.0.tgz",
"integrity": "sha512-G8nk3np8ZAnwhHXas1JxJEwJyQdqFXAKJehfgZ/XrC48volFBRtO+FIKtF2u0Ma3bw+4vnDVjHPAQYlF9p2vsw==",
"dev": true,
"requires": {
"loader-utils": "^1.2.3",
"mime": "^2.4.4",
"schema-utils": "^2.0.0"
"schema-utils": "^2.4.1"
},
"dependencies": {
"ajv-keywords": {
"version": "3.4.1",
"resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.4.1.tgz",
"integrity": "sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ==",
"dev": true
},
"mime": {
"version": "2.4.4",
"resolved": "https://registry.npmjs.org/mime/-/mime-2.4.4.tgz",
@ -22484,13 +22550,13 @@
"dev": true
},
"schema-utils": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.0.1.tgz",
"integrity": "sha512-HJFKJ4JixDpRur06QHwi8uu2kZbng318ahWEKgBjc0ZklcE4FDvmm2wghb448q0IRaABxIESt8vqPFvwgMB80A==",
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.4.1.tgz",
"integrity": "sha512-RqYLpkPZX5Oc3fw/kHHHyP56fg5Y+XBpIpV8nCg0znIALfq3OH+Ea9Hfeac9BAMwG5IICltiZ0vxFvJQONfA5w==",
"dev": true,
"requires": {
"ajv": "^6.1.0",
"ajv-keywords": "^3.1.0"
"ajv": "^6.10.2",
"ajv-keywords": "^3.4.1"
}
}
}
@ -24038,9 +24104,9 @@
}
},
"webpack-dev-middleware": {
"version": "3.7.1",
"resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-3.7.1.tgz",
"integrity": "sha512-5MWu9SH1z3hY7oHOV6Kbkz5x7hXbxK56mGHNqHTe6d+ewxOwKUxoUJBs7QIaJb33lPjl9bJZ3X0vCoooUzC36A==",
"version": "3.7.2",
"resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-3.7.2.tgz",
"integrity": "sha512-1xC42LxbYoqLNAhV6YzTYacicgMZQTqRd27Sim9wn5hJrX3I5nxYy1SxSd4+gjUFsz1dQFj+yEe6zEVmSkeJjw==",
"dev": true,
"requires": {
"memory-fs": "^0.4.1",
@ -24059,9 +24125,9 @@
}
},
"webpack-dev-server": {
"version": "3.8.1",
"resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-3.8.1.tgz",
"integrity": "sha512-9F5DnfFA9bsrhpUCAfQic/AXBVHvq+3gQS+x6Zj0yc1fVVE0erKh2MV4IV12TBewuTrYeeTIRwCH9qLMvdNvTw==",
"version": "3.8.2",
"resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-3.8.2.tgz",
"integrity": "sha512-0xxogS7n5jHDQWy0WST0q6Ykp7UGj4YvWh+HVN71JoE7BwPxMZrwgraBvmdEMbDVMBzF0u+mEzn8TQzBm5NYJQ==",
"dev": true,
"requires": {
"ansi-html": "0.0.7",
@ -24073,18 +24139,18 @@
"del": "^4.1.1",
"express": "^4.17.1",
"html-entities": "^1.2.1",
"http-proxy-middleware": "^0.19.1",
"http-proxy-middleware": "0.19.1",
"import-local": "^2.0.0",
"internal-ip": "^4.3.0",
"ip": "^1.1.5",
"is-absolute-url": "^3.0.2",
"is-absolute-url": "^3.0.3",
"killable": "^1.0.1",
"loglevel": "^1.6.4",
"opn": "^5.5.0",
"p-retry": "^3.0.1",
"portfinder": "^1.0.24",
"schema-utils": "^1.0.0",
"selfsigned": "^1.10.6",
"selfsigned": "^1.10.7",
"semver": "^6.3.0",
"serve-index": "^1.9.1",
"sockjs": "0.3.19",
@ -24093,7 +24159,7 @@
"strip-ansi": "^3.0.1",
"supports-color": "^6.1.0",
"url": "^0.11.0",
"webpack-dev-middleware": "^3.7.1",
"webpack-dev-middleware": "^3.7.2",
"webpack-log": "^2.0.0",
"ws": "^6.2.1",
"yargs": "12.0.5"
@ -24129,9 +24195,9 @@
}
},
"is-absolute-url": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-3.0.2.tgz",
"integrity": "sha512-+5g/wLlcm1AcxSP7014m6GvbPHswDx980vD/3bZaap8aGV9Yfs7Q6y6tfaupgZ5O74Byzc8dGrSCJ+bFXx0KdA==",
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-3.0.3.tgz",
"integrity": "sha512-opmNIX7uFnS96NtPmhWQgQx6/NYFgsUXYMllcfzwWKUMwfo8kku1TvE6hkNcH+Q1ts5cMVrsY7j0bxXQDciu9Q==",
"dev": true
},
"ms": {

@ -19,7 +19,7 @@
"@fortawesome/vue-fontawesome": "^0.1.7",
"@statnett/vue-plotly": "^0.3.2",
"@types/d3-drag": "^1.2.3",
"@types/node": "^12.7.9",
"@types/node": "^12.7.11",
"ajv": "^6.10.2",
"audit": "0.0.6",
"axios": "^0.19.0",
@ -28,7 +28,7 @@
"blob": "0.0.5",
"bootstrap": "^4.3.1",
"bootstrap-toggle": "^2.2.2",
"bootstrap-vue": "^2.0.2",
"bootstrap-vue": "^2.0.3",
"circlepack-chart": "^1.3.0",
"clean-webpack-plugin": "^3.0.0",
"colorbrewer": "^1.3.0",
@ -50,14 +50,14 @@
"jquery": "^3.4.1",
"mdbvue": "^5.8.3",
"mini-css-extract-plugin": "^0.8.0",
"npm-check-updates": "^3.1.23",
"npm-check-updates": "^3.1.24",
"papaparse": "^5.1.0",
"parcoord-es": "^2.2.10",
"plotly.js": "^1.49.5",
"popper.js": "^1.15.0",
"react": "^16.10.1",
"react-dom": "^16.10.1",
"stardust": "^0.52.5",
"react": "^16.10.2",
"react-dom": "^16.10.2",
"stardust-allofw": "^0.1.1",
"stardust-core": "^0.2.4",
"stardust-webgl": "^0.2.4",
"strip-loader": "^0.1.2",
@ -88,7 +88,7 @@
"@babel/plugin-syntax-jsx": "^7.2.0",
"@babel/plugin-transform-runtime": "^7.6.2",
"@babel/preset-env": "^7.6.2",
"autoprefixer": "^9.6.1",
"autoprefixer": "^9.6.4",
"babel-eslint": "^10.0.3",
"babel-helper-vue-jsx-merge-props": "^2.0.3",
"babel-loader": "^8.0.6",
@ -122,7 +122,7 @@
"semver": "^6.3.0",
"shelljs": "^0.8.3",
"uglifyjs-webpack-plugin": "^2.2.0",
"url-loader": "^2.1.0",
"url-loader": "^2.2.0",
"vue-class-component": "^7.1.0",
"vue-cli-plugin-vuetify": "^0.6.3",
"vue-loader": "^15.7.1",
@ -133,7 +133,7 @@
"vuetify-loader": "^1.3.0",
"webpack": "^4.41.0",
"webpack-bundle-analyzer": "^3.5.2",
"webpack-dev-server": "^3.8.1",
"webpack-dev-server": "^3.8.2",
"webpack-merge": "^4.2.2"
},
"browserslist": [

@ -31,10 +31,10 @@ export default {
var Combined = 0
if (this.selAlgorithm == 'KNN') {
Combined = JSON.parse(this.ModelsPerformance[0])
Combined = JSON.parse(this.ModelsPerformance[1])
colorGiv = colors[0]
} else {
Combined = JSON.parse(this.ModelsPerformance[2])
Combined = JSON.parse(this.ModelsPerformance[7])
colorGiv = colors[1]
}
var valuesPerf = Object.values(Combined['0'])

@ -1,7 +1,7 @@
<template>
<div>
<div id="exploding_boxplot" class="exploding_boxplot" ref="myClickable"></div>
</div>
<div>
<div id="exploding_boxplot" class="exploding_boxplot"></div>
</div>
</template>
<script>
@ -34,70 +34,75 @@ export default {
},
methods: {
boxplot () {
// reset the boxplot
d3.selectAll("#exploding_boxplot > *").remove();
const PerformAlgor1 = JSON.parse(this.PerformanceAllModels[0])
const PerformAlgor2 = JSON.parse(this.PerformanceAllModels[2])
this.algorithm1 = []
this.algorithm2 = []
var parameters = []
for (var i = 0; i < Object.keys(PerformAlgor1['0']).length; i++) {
this.algorithm1.push({Performance: Object.values(PerformAlgor1['0'])[i]*100,Algorithm:'KNN',Model:'Model ' + i + '; Parameters '+JSON.stringify(Object.values(PerformAlgor1['params'])[i])+'; Performance ',ModelID:i})
parameters.push(JSON.stringify(Object.values(PerformAlgor1['params'])[i]))
}
var temp = i
for (let j = 0; j < Object.keys(PerformAlgor2['0']).length; j++) {
temp = i + j
this.algorithm2.push({Performance: Object.values(PerformAlgor2['0'])[j]*100,Algorithm:'RF',Model:'Model ' + temp + '; Parameters '+JSON.stringify(Object.values(PerformAlgor2['params'])[j])+'; Performance ',ModelID:temp})
parameters.push(JSON.stringify(Object.values(PerformAlgor2['params'])[j]))
}
EventBus.$emit('ParametersAll', parameters)
var data = this.algorithm1.concat(this.algorithm2)
// aesthetic :
// y : point's value on y axis
// group : how to group data on x axis
// color : color of the point / boxplot
// label : displayed text in toolbox
this.chart = exploding_boxplot(data, {y:'Performance',group:'Algorithm',color:'Algorithm',label:'Model'})
// retrieve models ID
const Algor1IDs = this.PerformanceAllModels[0]
const Algor2IDs = this.PerformanceAllModels[6]
this.chart.width(this.WH[0]*3)
this.chart.height(this.WH[1])
//call chart on a div
this.chart('#exploding_boxplot')
const previousColor = ['#8dd3c7','#ffffb3','#bebada','#fb8072','#80b1d3','#fdb462','#b3de69','#fccde5','#d9d9d9','#bc80bd','#ccebc5','#ffed6f']
var el = document.getElementsByClassName('d3-exploding-boxplot boxcontent')
// retrieve the results like performance
const PerformAlgor1 = JSON.parse(this.PerformanceAllModels[1])
const PerformAlgor2 = JSON.parse(this.PerformanceAllModels[7])
this.brushStatus = document.getElementsByClassName('extent')
// initialize/instansiate algorithms and parameters
this.algorithm1 = []
this.algorithm2 = []
var parameters = []
el[0].onclick = function() {
var allPoints = document.getElementsByClassName('d3-exploding-boxplot point KNN')
for (let i = 0; i < allPoints.length; i++) {
//if (modelsActive.indexOf(i) == -1) {
allPoints[i].style.fill = previousColor[0]
allPoints[i].style.opacity = '1.0'
//}
}
for (var i = 0; i < Object.keys(PerformAlgor1['0']).length; i++) {
this.algorithm1.push({Performance: Object.values(PerformAlgor1['0'])[i]*100,Algorithm:'KNN',Model:'Model ' + Algor1IDs[i] + '; Parameters '+JSON.stringify(Object.values(PerformAlgor1['params'])[i])+'; Performance Metrics ',ModelID:Algor1IDs[i]})
parameters.push(JSON.stringify(Object.values(PerformAlgor1['params'])[i]))
}
for (let j = 0; j < Object.keys(PerformAlgor2['0']).length; j++) {
this.algorithm2.push({Performance: Object.values(PerformAlgor2['0'])[j]*100,Algorithm:'RF',Model:'Model ' + Algor2IDs[j] + '; Parameters '+JSON.stringify(Object.values(PerformAlgor2['params'])[j])+'; Performance Metrics ',ModelID:Algor2IDs[j]})
parameters.push(JSON.stringify(Object.values(PerformAlgor2['params'])[j]))
}
EventBus.$emit('PCPCall', 'KNN')
}
el[1].onclick = function() {
var allPoints = document.getElementsByClassName('d3-exploding-boxplot point RF')
for (let i = 0; i < allPoints.length; i++) {
//if (modelsActive.indexOf(i) == -1) {
allPoints[i].style.fill = previousColor[1]
allPoints[i].style.opacity = '1.0'
//}
}
EventBus.$emit('PCPCall', 'RF')
}
EventBus.$emit('ParametersAll', parameters)
const myObserver = new ResizeObserver(entries => {
EventBus.$emit('brusheAllOn')
});
// concat the data
var data = this.algorithm1.concat(this.algorithm2)
var brushRect = document.querySelector('.extent');
// aesthetic :
// y : point's value on y axis
// group : how to group data on x axis
// color : color of the point / boxplot
// label : displayed text in toolbox
this.chart = exploding_boxplot(data, {y:'Performance',group:'Algorithm',color:'Algorithm',label:'Model'})
this.chart.width(this.WH[0]*3) // interactive visualization
this.chart.height(this.WH[1]) // interactive visualization
//call chart on a div
this.chart('#exploding_boxplot')
myObserver.observe(brushRect);
// colorscale
const previousColor = ['#8dd3c7','#ffffb3','#bebada','#fb8072','#80b1d3','#fdb462','#b3de69','#fccde5','#d9d9d9','#bc80bd','#ccebc5','#ffed6f']
// check for brushing
var el = document.getElementsByClassName('d3-exploding-boxplot boxcontent')
this.brushStatus = document.getElementsByClassName('extent')
// on clicks
el[0].onclick = function() {
var allPoints = document.getElementsByClassName('d3-exploding-boxplot point KNN')
for (let i = 0; i < allPoints.length; i++) {
allPoints[i].style.fill = previousColor[0]
allPoints[i].style.opacity = '1.0'
}
EventBus.$emit('PCPCall', 'KNN')
}
el[1].onclick = function() {
var allPoints = document.getElementsByClassName('d3-exploding-boxplot point RF')
for (let i = 0; i < allPoints.length; i++) {
allPoints[i].style.fill = previousColor[1]
allPoints[i].style.opacity = '1.0'
}
EventBus.$emit('PCPCall', 'RF')
}
// check if brushed through all boxplots and not only one at a time
const myObserver = new ResizeObserver(entries => {
EventBus.$emit('brusheAllOn')
})
var brushRect = document.querySelector('.extent')
myObserver.observe(brushRect);
},
brushActivationAll () {
// continue here and select the correct points.
@ -163,7 +168,6 @@ export default {
}
}
}
this.UpdateBarChart()
},
brushed () {
@ -217,14 +221,13 @@ export default {
}
}
}
this.UpdateBarChart()
},
UpdateBarChart () {
var allPoints = document.getElementsByClassName('d3-exploding-boxplot point')
var activeModels = []
var algorithmsSelected = []
var parameters = []
var modelsSelected =[]
for (let i = 0; i < allPoints.length; i++) {
if (allPoints[i].style.fill != "rgb(211, 211, 211)") {
activeModels.push(allPoints[i].__data__.Model)
@ -240,18 +243,18 @@ export default {
} else {
for (let i = 0; i<activeModels.length; i++) {
var array = activeModels[i].split(';')
var temp2 = array[1].split(' ')
parameters.push(temp2[2])
var temp = array[0].split(' ')
modelsSelected.push(temp[1])
}
EventBus.$emit('ReturningAlgorithmsBar', algorithmsSelected)
EventBus.$emit('ReturningBrushedPointsParamsBar', parameters)
}
EventBus.$emit('updateBarChartAlgorithm', algorithmsSelected)
EventBus.$emit('updateBarChart', modelsSelected)
},
selectedPointsPerAlgorithm () {
var allPoints = document.getElementsByClassName('d3-exploding-boxplot point')
var activeModels = []
var algorithmsSelected = []
var parameters = []
var models = []
for (let i = 0; i < allPoints.length; i++) {
if (allPoints[i].style.fill != "rgb(211, 211, 211)") {
activeModels.push(allPoints[i].__data__.Model)
@ -268,11 +271,11 @@ export default {
} else {
for (let i = 0; i<activeModels.length; i++) {
var array = activeModels[i].split(';')
var temp2 = array[1].split(' ')
parameters.push(temp2[2])
var temp = array[0].split(' ')
models.push(temp[1])
}
EventBus.$emit('ReturningAlgorithms', algorithmsSelected)
EventBus.$emit('ReturningBrushedPointsParams', parameters)
EventBus.$emit('ReturningBrushedPointsIDs', models)
}
},
previousBoxPlotState () {

@ -1,41 +1,128 @@
<template>
<div>
<p><font-awesome-icon icon="balance-scale"/> Optimize Selection:<b-form-slider ref="basic1" v-model="basicValue" :min="0" :max="100" trigger-change-event @slide-start="slideStart" @slide-stop="slideStop" style="padding-right: 15px;padding-left:15px"></b-form-slider>{{ basicValue }}%</p>
<div id="my_dataviz"></div>
</div>
</template>
<script>
import bFormSlider from 'vue-bootstrap-slider/es/form-slider';
import 'bootstrap-slider/dist/css/bootstrap-slider.css'
import { EventBus } from '../main.js'
import * as d3Base from 'd3'
// attach all d3 plugins to the d3 library
const d3 = Object.assign(d3Base)
export default {
name: 'BalancePredictions',
data () {
return {
basicValue: 0,
resultsfromOverview: 0,
}
},
methods: {
slideStart () {
},
slideStop () {
//var basicValues = []
//EventBus.$emit('CallFactorsView', basicValues)
},
Balance () {
// set the dimensions and margins of the graph
var margin = {top: 30, right: 30, bottom: 30, left: 60},
width = 600 - margin.left - margin.right,
height = 200 - margin.top - margin.bottom;
// append the svg object to the body of the page
var svg = d3.select("#my_dataviz")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform",
"translate(" + margin.left + "," + margin.top + ")");
// get the data
d3.csv("https://raw.githubusercontent.com/holtzy/D3-graph-gallery/master/DATA/data_doubleHist.csv").then( function(data) {
// add the x Axis
var x = d3.scaleLinear()
.domain([-10,15])
.range([0, width]);
svg.append("g")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x));
// add the first y Axis
var y1 = d3.scaleLinear()
.range([height/2, 0])
.domain([0, 0.12]);
svg.append("g")
.attr("transform", "translate(-20,0)")
.call(d3.axisLeft(y1).tickValues([0.05, 0.1]));
// add the first y Axis
var y2 = d3.scaleLinear()
.range([height/2, height])
.domain([0, 0.12]);
svg.append("g")
.attr("transform", "translate(-20,0)")
.call(d3.axisLeft(y2).ticks(2).tickSizeOuter(0));
// Compute kernel density estimation
var kde = kernelDensityEstimator(kernelEpanechnikov(7), x.ticks(60))
var density1 = kde( data.filter( function(d){return d.type === "variable 1"} ).map(function(d){ return d.value; }) )
var density2 = kde( data.filter( function(d){return d.type === "variable 2"} ).map(function(d){ return d.value; }) )
// Plot the area
svg.append("path")
.attr("class", "mypath")
.datum(density1)
.attr("fill", "#69b3a2")
.attr("opacity", ".6")
.attr("stroke", "#000")
.attr("stroke-width", 1)
.attr("stroke-linejoin", "round")
.attr("d", d3.line()
.curve(d3.curveBasis)
.x(function(d) { return x(d[0]); })
.y(function(d) { return y1(d[1]); })
);
// Plot the area
svg.append("path")
.attr("class", "mypath")
.datum(density2)
.attr("fill", "#404080")
.attr("opacity", ".6")
.attr("stroke", "#000")
.attr("stroke-width", 1)
.attr("stroke-linejoin", "round")
.attr("d", d3.line()
.curve(d3.curveBasis)
.x(function(d) { return x(d[0]); })
.y(function(d) { return y2(d[1]); })
);
}).catch(function(error){
// handle error
})
// Handmade legend
svg.append("circle").attr("cx",290).attr("cy",30).attr("r", 6).style("fill", "#69b3a2")
svg.append("circle").attr("cx",290).attr("cy",60).attr("r", 6).style("fill", "#404080")
svg.append("text").attr("x", 310).attr("y", 30).text("variable A").style("font-size", "15px").attr("alignment-baseline","middle")
svg.append("text").attr("x", 310).attr("y", 60).text("variable B").style("font-size", "15px").attr("alignment-baseline","middle")
// Function to compute density
function kernelDensityEstimator(kernel, X) {
return function(V) {
return X.map(function(x) {
return [x, d3.mean(V, function(v) { return kernel(x - v); })];
});
};
}
function kernelEpanechnikov(k) {
return function(v) {
return Math.abs(v /= k) <= 1 ? 0.75 * (1 - v * v) / k : 0;
};
}
}
},
mounted () {
EventBus.$on('emittedEventCallingBalanceView', data => { this.resultsfromOverview = data} )
EventBus.$on('emittedEventCallingBalanceView', this.Balance)
}
}
</script>
<style>
p {
margin: 0 !important;
padding: 0 !important;
}
.slider.slider-horizontal {
width: 150px !important;
}
.slider-handle {
background: black;
}
</style>

@ -16,99 +16,101 @@ export default {
return {
PerformanceResults: '',
ClassNamesOverview: '',
PerformanceResultsSel: []
algorithmsinBar: [],
modelsSelectedinBar: [],
KNNModels: 576, //KNN models
WH: []
}
},
methods: {
BarChartView () {
const PerClassMetrics = JSON.parse(this.PerformanceResults[2])
const PerClassMetrics2 = JSON.parse(this.PerformanceResults[8])
const PerClassMetrics = JSON.parse(this.PerformanceResults[1])
const PerClassMetrics2 = JSON.parse(this.PerformanceResults[3])
var UpdateFeatures = 0
UpdateFeatures = JSON.parse(this.PerformanceResultsSel[0])
var UpdateFeatures2 = 0
UpdateFeatures2 = JSON.parse(this.PerformanceResultsSel[1])
var KNNModels = []
var RFModels = []
for (let i=0; i<this.algorithmsinBar.length;i++) {
if (this.algorithmsinBar[i] === "KNN") {
KNNModels.push(JSON.parse(this.modelsSelectedinBar[i]))
} else {
RFModels.push(JSON.parse(this.modelsSelectedinBar[i]) - this.KNNModels)
}
}
console.log(KNNModels)
console.log(RFModels)
var target_names
target_names = Object.keys(PerClassMetrics)
var sum = []
var temp = 0
var temp2 = 0
for (var i=0;i<target_names.length;i++) {
temp = 0
temp = (Object.values(PerClassMetrics)[i][0]['f1-score']+Object.values(PerClassMetrics)[i][0]['precision']+Object.values(PerClassMetrics)[i][0]['recall'])/3
sum.push(temp)
temp = 0
temp = (Object.values(PerClassMetrics2)[i][0]['f1-score']+Object.values(PerClassMetrics2)[i][0]['precision']+Object.values(PerClassMetrics2)[i][0]['recall'])/3
temp2 = 0
for (var j=0;j<Object.keys(PerClassMetrics[target_names[i]]).length;j++){
temp = temp + (Object.values(PerClassMetrics)[i][j]['f1-score']+Object.values(PerClassMetrics)[i][j]['precision']+Object.values(PerClassMetrics)[i][j]['recall'])/3
}
temp = temp/Object.keys(PerClassMetrics[target_names[i]]).length
sum.push(temp)
for (var k=0;k<Object.keys(PerClassMetrics2[target_names[i]]).length;k++){
temp2 = temp2 + (Object.values(PerClassMetrics2)[i][k]['f1-score']+Object.values(PerClassMetrics2)[i][k]['precision']+Object.values(PerClassMetrics2)[i][k]['recall'])/3
}
temp2 = temp2/Object.keys(PerClassMetrics2[target_names[i]]).length
sum.push(temp2)
}
var sumLine = []
var temp = 0
var temp2 = 0
for (var i=0;i<target_names.length;i++) {
if (UpdateFeatures != 0) {
temp = 0
temp = (Object.values(UpdateFeatures)[i][0]['f1-score']+Object.values(UpdateFeatures)[i][0]['precision']+Object.values(UpdateFeatures)[i][0]['recall'])/3
sumLine.push(temp)
temp = 0
temp2 = 0
if (KNNModels.length == 0) {
for (var j=0;j<Object.keys(PerClassMetrics[target_names[i]]).length;j++){
temp = temp + (Object.values(PerClassMetrics)[i][j]['f1-score']+Object.values(PerClassMetrics)[i][j]['precision']+Object.values(PerClassMetrics)[i][j]['recall'])/3
}
temp = temp/Object.keys(PerClassMetrics[target_names[i]]).length
} else {
temp = 0
temp = (Object.values(PerClassMetrics)[i][0]['f1-score']+Object.values(PerClassMetrics)[i][0]['precision']+Object.values(PerClassMetrics)[i][0]['recall'])/3
sumLine.push(temp)
for (var j=0;j<KNNModels.length;j++){
temp = temp + (Object.values(PerClassMetrics)[i][KNNModels[j]]['f1-score']+Object.values(PerClassMetrics)[i][KNNModels[j]]['precision']+Object.values(PerClassMetrics)[i][KNNModels[j]]['recall'])/3
temp = temp/KNNModels.length
}
}
if (UpdateFeatures2 != 0) {
temp = 0
temp = (Object.values(UpdateFeatures2)[i][0]['f1-score']+Object.values(UpdateFeatures2)[i][0]['precision']+Object.values(UpdateFeatures2)[i][0]['recall'])/3
sumLine.push(temp)
sumLine.push(temp)
if (KNNModels.length == 0) {
for (var k=0;k<Object.keys(PerClassMetrics2[target_names[i]]).length;k++){
temp2 = temp2 + (Object.values(PerClassMetrics2)[i][k]['f1-score']+Object.values(PerClassMetrics2)[i][k]['precision']+Object.values(PerClassMetrics2)[i][k]['recall'])/3
}
temp2 = temp2/Object.keys(PerClassMetrics2[target_names[i]]).length
} else {
temp = 0
temp = (Object.values(PerClassMetrics2)[i][0]['f1-score']+Object.values(PerClassMetrics2)[i][0]['precision']+Object.values(PerClassMetrics2)[i][0]['recall'])/3
sumLine.push(temp)
for (var k=0;k<RFModels.length;k++){
temp2 = temp2 + (Object.values(PerClassMetrics2)[i][RFModels[k]]['f1-score']+Object.values(PerClassMetrics2)[i][RFModels[k]]['precision']+Object.values(PerClassMetrics2)[i][RFModels[k]]['recall'])/3
temp2 = temp2/RFModels.length
}
}
sumLine.push(temp2)
}
/* console.log(PerClassMetrics)
if (this.ModelsChosen != []) {
console.log('mpike')
for (var i=0;i<target_names.length;i++) {
temp = 0
temp = (Object.values(PerClassMetrics)[i][0]['f1-score']+Object.values(PerClassMetrics)[i][0]['f1-score']+Object.values(PerClassMetrics)[i][0]['f1-score'])/3
sum.push(temp)
temp = 0
temp = (Object.values(PerClassMetrics2)[i][0]['f1-score']+Object.values(PerClassMetrics2)[i][0]['f1-score']+Object.values(PerClassMetrics2)[i][0]['f1-score'])/3
sum.push(temp)
}
}*/
console.log(sumLine)
Plotly.purge('barChart')
const f1ScorePerClass = []
/* for (let j = 0; j < ClassNames.length; j++) {
f1ScorePerClass[j] = []
for (let i = 0; i < limitList.length; i++) { // Fix this tomorrow! 0 to 16 and we want the ids..
f1ScorePerClass[j].push(PerClassMetrics[limitList[i]][ClassNames[j]]['f1-score'])
}
}*/
var layout = {
autosize: true,
barmode: 'group',
width: 650,
height: 400,
width: this.WH[0]*3,
height: this.WH[1],
xaxis: {
title: 'Algorithm',
type:"category",
titlefont: {
family: 'Arial, sans-serif',
size: 18,
color: 'grey'
},
showticklabels: true,
tickangle: 'auto',
tickfont: {
family: 'Old Standard TT, serif',
size: 14,
color: 'black'
},
exponentformat: 'e',
showexponent: 'all'
},
yaxis: {
title: 'Per Class Performance',
title: 'Per Class Performance Metrics',
titlefont: {
family: 'Arial, sans-serif',
size: 18,
@ -118,18 +120,8 @@ export default {
xaxis2: {
overlaying: 'x',
type:"category",
titlefont: {
family: 'Arial, sans-serif',
size: 18,
color: 'grey'
},
showticklabels: true,
tickangle: 'auto',
tickfont: {
family: 'Old Standard TT, serif',
size: 14,
color: 'black'
},
exponentformat: 'e',
showexponent: 'all'
},
@ -141,110 +133,38 @@ export default {
pad: 0
}
}
/*for (let j = 0; j < ClassNames.length; j++) {
let len = f1ScorePerClass[j].length
let indices = new Array(len)
for (let i = 0; i < len; ++i) indices[i] = i
indices.sort(function (a, b) { return f1ScorePerClass[j][b] < f1ScorePerClass[j][a] ? -1 : f1ScorePerClass[j][b] > f1ScorePerClass[j][a] ? 1 : 0 })
f1ScorePerClass[j].sort((function(a, b){return b-a}))
f1ScoreData = [
{
x: indices.map(String),
y: f1ScorePerClass[j],
type: 'bar',
marker: {
color: 'rgb(158,202,225)',
opacity: 0.6,
line: {
color: 'rgb(8,48,107)',
width: 1.5
}
}
}
]*/
var traces = []
var tracesSel = []
var data = []
var colors = ['#a6cee3','#1f78b4','#b2df8a','#33a02c','#fb9a99','#e31a1c','#fdbf6f','#ff7f00','#cab2d6','#6a3d9a']
var trace1 = {
x: ['KNN', 'RF'],
y: [sum[0],sum[1]],
name: target_names[0],
opacity: 0.5,
marker: {
opacity: 0.5,
color: colors[0]
},
type: 'bar'
};
var trace2 = {
x: ['KNN', 'RF'],
y: [sum[2],sum[3]],
name: target_names[1],
opacity: 0.5,
marker: {
opacity: 0.5,
color: colors[1]
},
type: 'bar'
};
var trace3 = {
x: ['KNN', 'RF'],
y: [sum[4],sum[5]],
name: target_names[2],
opacity: 0.5,
marker: {
opacity: 0.5,
color: colors[2]
},
type: 'bar'
};
var trace4 = {
type: 'bar',
x: ['KNN', 'RF'],
y: [sumLine[0],sumLine[1]],
name: target_names[0]+' (Sel)',
xaxis: 'x2',
mode: 'markers',
marker: {
opacity: 1.0,
color: colors[0],
},
width: [0.1, 0.1]
};
var trace5 = {
type: 'bar',
x: ['KNN', 'RF'],
y: [sumLine[2],sumLine[3]],
name: target_names[1]+' (Sel)',
xaxis: 'x2',
mode: 'markers',
marker: {
opacity: 1.0,
color: colors[1],
},
width: [0.1, 0.1]
};
var trace6 = {
type: 'bar',
x: ['KNN', 'RF'],
y: [sumLine[4],sumLine[5]],
name: target_names[2]+' (Sel)',
xaxis: 'x2',
mode: 'markers',
marker: {
opacity: 1.0,
color: colors[2],
},
width: [0.1, 0.1]
};
var data = [trace1, trace4, trace2, trace5, trace3, trace6];
for (var i = 0; i < target_names.length; i++) {
traces[i] = {
x: ['KNN', 'RF'],
y: [sum[i+i],sum[i+i+1]],
name: target_names[i],
opacity: 0.5,
marker: {
opacity: 0.5,
color: colors[i]
},
type: 'bar'
};
tracesSel[i] = {
type: 'bar',
x: ['KNN', 'RF'],
y: [sumLine[i+i],sumLine[i+i+1]],
name: target_names[i]+' (Sel)',
xaxis: 'x2',
mode: 'markers',
marker: {
opacity: 1.0,
color: colors[i],
},
width: [0.1, 0.1]
};
data.push(traces[i])
data.push(tracesSel[i])
}
Plotly.newPlot('barChart', data, layout)
},
reset ()
@ -253,15 +173,18 @@ export default {
}
},
mounted() {
this.PerformanceResultsSel[0] = 0
this.PerformanceResultsSel[1] = 0
EventBus.$on('emittedEventCallingBarChartUpdatedFeatures', data => { this.PerformanceResultsSel = data })
EventBus.$on('emittedEventCallingBarChartUpdatedFeatures', this.BarChartView)
EventBus.$on('updateBarChartAlgorithm', data => { this.algorithmsinBar = data })
EventBus.$on('updateBarChart', data => { this.modelsSelectedinBar = data })
EventBus.$on('updateBarChart', this.BarChartView)
EventBus.$on('emittedEventCallingBarChart', data => { this.PerformanceResults = data })
EventBus.$on('emittedEventCallingBarChart', this.BarChartView)
EventBus.$on('emittedEventCallingUpdateBarChart', data => { this.ModelsChosen = data })
EventBus.$on('emittedEventCallingUpdateBarChart', this.BarChartView)
EventBus.$on('resetViews', this.reset)
EventBus.$on('Responsive', data => {
this.WH = data})
EventBus.$on('ResponsiveandChange', data => {
this.WH = data})
}
}
</script>

@ -17,7 +17,6 @@ export default {
name: 'Controller',
data () {
return {
value: 'Add to Stack',
valueExecute: 'Execute Stacking Ensemble'
}
},

@ -46,7 +46,7 @@ export default {
text: text,
line: {color: "rgb(0,100,80)"},
mode: "lines+markers",
name: "Accuracy",
name: "Current Accuracy",
type: "scatter"
}
@ -58,7 +58,7 @@ export default {
fill: "tozerox",
fillcolor: "rgba(0,100,80,0.2)",
line: {color: "transparent"},
name: "Accuracy",
name: "Current Accuracy",
showlegend: false,
type: "scatter"
}

@ -75,9 +75,11 @@
</mdb-card-body>
</b-col>
</b-row>
<mdb-card-text>
<mdb-card-body>
<ToggleSelection/>
</mdb-card-body>
</mdb-card-text>
</mdb-card>
</b-col>
<b-col cols="3">
@ -197,15 +199,13 @@ export default Vue.extend({
toggle2: 1,
toggle3: 1,
modelsUpdate: [],
parametersUpdate: [],
AlgorithmsUpdate: []
AlgorithmsUpdate: [],
}
},
methods: {
selectVisualRepresentation () {
const representationSelectionDocum = document.getElementById('selectBarChart')
this.representationSelection = representationSelectionDocum.options[representationSelectionDocum.selectedIndex].value
console.log(this.representationSelection)
EventBus.$emit('RepresentationSelection', this.representationSelection)
},
getCollection () {
@ -251,6 +251,7 @@ export default Vue.extend({
this.OverviewResults = response.data.OverviewResults
console.log('Server successfully sent all the data related to visualizations!')
EventBus.$emit('emittedEventCallingScatterPlot', this.OverviewResults)
EventBus.$emit('InitializeProvenance', this.OverviewResults)
EventBus.$emit('InitializeMetricsBarChart', this.OverviewResults)
this.valueSel = 0
this.valueAll = 0
@ -264,6 +265,7 @@ export default Vue.extend({
EventBus.$emit('emittedEventCallingTableView', this.OverviewResults)
EventBus.$emit('emittedEventCallingDataSpacePlotView', this.OverviewResults)
EventBus.$emit('emittedEventCallingPredictionsSpacePlotView', this.OverviewResults)
EventBus.$emit('emittedEventCallingBalanceView', this.OverviewResults)
this.getFinalResults()
})
.catch(error => {
@ -295,27 +297,6 @@ export default Vue.extend({
console.log(error)
})
},
UpdateModelsFeaturePerformance () {
const path = `http://localhost:5000/data/UpdatePerFeaturePerformance`
const axiosConfig = {
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Headers': 'Origin, Content-Type, X-Auth-Token',
'Access-Control-Allow-Methods': 'GET, PUT, POST, DELETE, OPTIONS'
}
}
axios.get(path, axiosConfig)
.then(response => {
this.PerformanceCheck = response.data.PerformanceCheck
console.log('Server successfully sent all the performance data related to models!')
EventBus.$emit('emittedEventCallingBarChartUpdatedFeatures', this.PerformanceCheck)
})
.catch(error => {
console.log(error)
})
},
SendSelectedPointsToServer () {
if (this.ClassifierIDsList === ''){
this.OverSelLength = 0
@ -342,6 +323,7 @@ export default Vue.extend({
EventBus.$emit('emittedEventCallingTableView', this.OverviewResults)
EventBus.$emit('emittedEventCallingDataSpacePlotView', this.OverviewResults)
EventBus.$emit('emittedEventCallingPredictionsSpacePlotView', this.OverviewResults)
EventBus.$emit('emittedEventCallingBalanceView', this.OverviewResults)
this.getFinalResults()
})
.catch(error => {
@ -376,7 +358,6 @@ export default Vue.extend({
const path = `http://127.0.0.1:5000/data/ServerRequest`
const postData = {
fileName: this.RetrieveValueFile,
featureSelection: this.SelectedFeaturesPerClassifier
}
const axiosConfig = {
headers: {
@ -421,7 +402,7 @@ export default Vue.extend({
EventBus.$emit('emittedEventCallingModelBrushed')
const path = `http://127.0.0.1:5000/data/SendBrushedParam`
const postData = {
parameters: this.parametersofModels,
models: this.modelsUpdate,
algorithms: this.selectedAlgorithms
}
const axiosConfig = {
@ -448,7 +429,7 @@ export default Vue.extend({
UpdateBarChartFeatures () {
const path = `http://127.0.0.1:5000/data/FeaturesScoresUpdate`
const postData = {
parameters: this.parametersUpdate,
models: this.modelsUpdate,
algorithms: this.AlgorithmsUpdate
}
const axiosConfig = {
@ -612,9 +593,8 @@ export default Vue.extend({
$(window).on("unload", function(e) {
alert('Handler for .unload() called.');
})
EventBus.$on('ReturningAlgorithmsBar', data => { this.AlgorithmsUpdate = data })
EventBus.$on('ReturningBrushedPointsParamsBar', data => { this.parametersUpdate = data })
EventBus.$on('ReturningBrushedPointsParamsBar', this.UpdateBarChartFeatures )
EventBus.$on('ReturningBrushedPointsIDs', data => { this.modelsUpdate = data })
//EventBus.$on('ReturningBrushedPointsIDs', this.UpdateBarChartFeatures )
EventBus.$on('ConfirmDataSet', this.fileNameSend)
EventBus.$on('reset', this.Reset)
EventBus.$on('UploadedFile', this.Reset)

@ -17,7 +17,6 @@ export default {
LineBar () {
var metricsPerModel = JSON.parse(this.barchartmetrics[9])
var vh = 80
/*if (this.representationDefault === 'bar'){
var type = 'bar';
} else if (this.representationDefault === 'line'){
@ -73,7 +72,7 @@ export default {
x: ['Acc','F1s','Pre','Rec','Jac'],
y: metricsPerModel,
name: 'Projection average',
type: type,
type: 'bar',
marker: {
color: 'rgb(0,0,0)'
}
@ -82,7 +81,7 @@ export default {
x: ['Acc','F1s','Pre','Rec','Jac'],
y: metricsPerModel,
name: 'Selected points',
type: type,
type: 'bar',
marker: {
color: 'rgb(0, 187, 187)'
}

@ -2,39 +2,98 @@
<div>
<div class="squares-container">
<canvas id="main-canvas"></canvas>
<svg id="main-svg"></svg>
</div>
</div>
</template>
<script>
import * as d3Base from 'd3'
import { EventBus } from '../main.js'
// attach all d3 plugins to the d3 library
const d3 = Object.assign(d3Base)
import * as Stardust from 'stardust-core'
import * as StardustGL from 'stardust-webgl'
export default {
name: 'Provenance',
data () {
return {
stackInformation: ''
}
},
methods: {
provenance () {
var container = d3.select(".squares-container");
var vis = new SquaresVisualization(container.node());
loadData("mnist.csv", DATA => {
vis.layout();
vis.setInstances(DATA.slice(0, 4000));
vis.setLayoutParameter({
y0: 10,
numberBins: 10,
squaresPerBin: 11,
squareSize: 3,
squareSpacing: 4,
xSpacing: 88
});
});
var canvas = document.getElementById("main-canvas");
var width = 960;
var height = 500;
// Create a WebGL 2D platform on the canvas:
var platform = Stardust.platform("webgl-2d", canvas, width, height);
var data = [];
[27, 53, 91, 52, 112, 42, 107, 91, 68, 56, 115, 86, 26, 102, 28, 23, 119, 110].forEach((x, index) => {
for (let i = 0; i < x; i++) {
data.push({
type: index % 3,
column: Math.floor(index / 3)
});
}
});
var typeCounter = [0, 0, 0];
var typeColumnCounter = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
data.forEach(d => {
d.typeIndex = typeCounter[d.type]++;
d.typeColumnIndex = typeColumnCounter[3 * d.column + d.type]++;
});
// Convert the SVG file to Stardust mark spec.
let isotype = new Stardust.mark.circle();
// Create the mark object.
let isotypes = Stardust.mark.create(isotype, platform);
let isotypeHeight = 18;
let colors = [[141,211,199], [255,255,179], [190,186,218]];
colors = colors.map(x => [x[0] / 255, x[1] / 255, x[2] / 255, 1]);
let pScale = Stardust.scale.custom(`
Vector2(
20 + column * 160 + type * 45 + typeColumnIndex % 5 * 8,
460 - floor(typeColumnIndex / 5) * 10
)
`);
pScale.attr("typeColumnIndex", d => d.typeColumnIndex);
pScale.attr("column", d => d.column);
pScale.attr("typeIndex", d => d.typeIndex);
pScale.attr("type", d => d.type);
let qScale = Stardust.scale.custom(`
Vector2(
65 + type * 300 + typeIndex % 30 * 8,
460 - floor(typeIndex / 15) * 18
)
`);
qScale.attr("typeIndex", d => d.typeIndex);
qScale.attr("type", d => d.type);
let interpolateScale = Stardust.scale.interpolate("Vector2");
interpolateScale.t(0);
isotypes.attr("center", interpolateScale(pScale(), qScale()));
isotypes.attr("radius", 4.0);
isotypes.attr("color", d => colors[d.type]);
isotypes.data(data);
isotypes.render();
}
},
mount () {
mounted () {
EventBus.$on('InitializeProvenance', data => {this.stackInformation = data})
EventBus.$on('InitializeProvenance', this.provenance)
}
}
</script>

@ -1,5 +1,21 @@
<template>
<div>
<div align="center">
<button
id="AddStack"
v-on:click="AddStack">
<font-awesome-icon icon="plus" />
{{ valueStackAdd }}
</button>
<button
id="RemoveStack"
v-on:click="RemoveStack">
<font-awesome-icon icon="minus" />
{{ valueStackRemove }}
</button>
</div>
<div id="OverviewPlotly" class="OverviewPlotly"></div>
</div>
</template>
<script>
@ -16,16 +32,24 @@ export default {
data () {
return {
ScatterPlotResults: '',
representationDef: 'MDS',
representationDef: 'mds',
colorsforOver: [],
brushedBox : [],
max: 0,
min: 0,
parametersAll: [],
length: 0,
valueStackAdd: 'Add to Stack',
valueStackRemove: 'Remove from Stack'
}
},
methods: {
AddStack () {
//EventBus.$emit('PCPCallDB')
},
RemoveStack () {
//EventBus.$emit('PCPCallDB')
},
ScatterPlotView () {
function isEquivalent(a, b) {
@ -57,8 +81,20 @@ export default {
Plotly.purge('OverviewPlotly')
var colorsforScatterPlot = JSON.parse(this.ScatterPlotResults[0])
var MDSData = JSON.parse(this.ScatterPlotResults[1])
console.log(colorsforScatterPlot)
var parameters = JSON.parse(this.ScatterPlotResults[2])
var tSNEData = JSON.parse(this.ScatterPlotResults[12])
var TSNEData = JSON.parse(this.ScatterPlotResults[12])
if (this.colorsforOver.length != 0) {
if (this.colorsforOver[1].length != 0) {
MDSData = this.colorsforOver[1]
TSNEData = this.colorsforOver[2]
}
if (this.colorsforOver[0].length != 0) {
colorsforScatterPlot = this.colorsforOver[0]
}
}
parameters = JSON.parse(parameters)
var classifiersInfo = this.brushedBox
@ -97,23 +133,13 @@ export default {
}
}
if (this.colorsforOver.length != 0) {
if (this.colorsforOver[1].length != 0) {
MDSData = this.colorsforOver[1]
}
if (this.colorsforOver[0].length != 0) {
colorsforScatterPlot = this.colorsforOver[0]
}
}
console.log(MDSData)
console.log(tSNEData)
var classifiersInfoProcessing = []
for (let i = 0; i < modelsDetails.length; i++) {
classifiersInfoProcessing[i] = 'Model ID: ' + modelsIDs[i] + '; Details: ' + modelsDetails[i]
}
var DataGeneral
var layout
if (this.representationDef == 'MDS') {
if (this.representationDef == 'mds') {
DataGeneral = [{
type: 'scatter',
mode: 'markers',
@ -150,11 +176,22 @@ export default {
legend: {orientation: 'h', y: -0.3},
}
} else {
var result = TSNEData.reduce(function(r, a) {
a.forEach(function(s, i) {
var key = i === 0 ? 'Xax' : 'Yax';
r[key] || (r[key] = []); // if key not found on result object, add the key with empty array as the value
r[key].push(s);
})
return r;
}, {})
DataGeneral = [{
type: 'scatter',
mode: 'markers',
x: tSNEData[0],
y: tSNEData[1],
x: result.Xax,
y: result.Yax,
hovertemplate:
"<b>%{text}</b><br><br>" +
"<extra></extra>",
@ -170,21 +207,19 @@ export default {
}
}]
layout = {
title: 'Models Performance (MDS)',
title: 'Models Performance (t-SNE)',
xaxis: {
visible: false
},
yaxis: {
visible: false
},
autosize: true,
width: 400,
height: 400,
dragmode: 'lasso',
hovermode: "closest",
hoverlabel: { bgcolor: "#FFF" },
legend: {orientation: 'h', y: -0.3},
}
}
var config = {scrollZoom: true, displaylogo: false, showLink: false, showSendToCloud: false, modeBarButtonsToRemove: ['toImage', 'toggleSpikelines', 'autoScale2d', 'hoverClosestGl2d','hoverCompareCartesian','select2d','hoverClosestCartesian','zoomIn2d','zoomOut2d','zoom2d'], responsive: true}

@ -6,10 +6,10 @@ import 'bootstrap-vue/dist/bootstrap-vue.css'
import router from './router'
import { library } from '@fortawesome/fontawesome-svg-core'
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'
import { faUpload, faPlay, faCheck, faSave, faTrash, faPlus, faBalanceScale} from '@fortawesome/free-solid-svg-icons'
import { faUpload, faPlay, faCheck, faSave, faTrash, faPlus, faBalanceScale, faMinus} from '@fortawesome/free-solid-svg-icons'
import bFormSlider from 'vue-bootstrap-slider'
library.add(faUpload, faPlay, faCheck, faSave, faTrash, faPlus, faBalanceScale)
library.add(faUpload, faPlay, faCheck, faSave, faTrash, faPlus, faBalanceScale, faMinus)
Vue.component('font-awesome-icon', FontAwesomeIcon)

3
package-lock.json generated

@ -0,0 +1,3 @@
{
"lockfileVersion": 1
}

476
run.py

@ -25,8 +25,6 @@ from sklearn.manifold import MDS
from sklearn.manifold import TSNE
from sklearn.metrics import classification_report
from sklearn.preprocessing import scale
#from sklearn.metrics import r2_score
#from rfpimp import permutation_importances
import eli5
from eli5.sklearn import PermutationImportance
from sklearn.feature_selection import SelectKBest
@ -37,6 +35,9 @@ from sklearn.decomposition import PCA
from mlxtend.classifier import StackingCVClassifier
from mlxtend.feature_selection import ColumnSelector
from skdist.distribute.search import DistGridSearchCV
from pyspark.sql import SparkSession
# This block of code is for the connection between the server, the database, and the client (plus routing).
# Access MongoDB
@ -108,16 +109,20 @@ def Reset():
target_names = []
return 'The reset was done!'
# Retrieve data from client
# Retrieve data from client and select the correct data set
@cross_origin(origin='localhost',headers=['Content-Type','Authorization'])
@app.route('/data/ServerRequest', methods=["GET", "POST"])
def RetrieveFileName():
fileName = request.get_data().decode('utf8').replace("'", '"')
global featureSelection
featureSelection = request.get_data().decode('utf8').replace("'", '"')
featureSelection = json.loads(featureSelection)
#global featureSelection
#featureSelection = request.get_data().decode('utf8').replace("'", '"')
#featureSelection = json.loads(featureSelection)
global DataRawLength
global DataResultsRaw
global RANDOM_SEED
RANDOM_SEED = 42
@ -153,14 +158,22 @@ def RetrieveFileName():
global crossValidation
crossValidation = 3
global scoring
scoring = {'accuracy': 'accuracy', 'f1_macro': 'f1_weighted', 'precision': 'precision_weighted', 'recall': 'recall_weighted', 'jaccard': 'jaccard_weighted'}
#scoring = {'accuracy': 'accuracy', 'f1_macro': 'f1_weighted', 'precision': 'precision_weighted', 'recall': 'recall_weighted', 'jaccard': 'jaccard_weighted', 'neg_log_loss': 'neg_log_loss', 'r2': 'r2', 'neg_mean_absolute_error': 'neg_mean_absolute_error', 'neg_mean_absolute_error': 'neg_mean_absolute_error'}
global NumberofscoringMetrics
NumberofscoringMetrics = len(scoring)
global yPredictProb
yPredictProb = []
global loopFeatures
loopFeatures = 2
global factors
factors = [1,1,1,1,1]
global columns
columns = []
@ -255,112 +268,6 @@ def column_index(df, query_cols):
sidx = np.argsort(cols)
return sidx[np.searchsorted(cols,query_cols,sorter=sidx)].tolist()
global mem
mem = Memory("./cache_dir")
def GridSearch(clf, params):
global XData
global yData
global scoring
global target_names
grid = GridSearchCV(estimator=clf,
param_grid=params,
scoring=scoring,
cv=crossValidation,
refit='accuracy',
n_jobs = -1)
grid.fit(XData, yData)
cv_results = []
cv_results.append(grid.cv_results_)
df_cv_results = pd.DataFrame.from_dict(cv_results)
number_of_classifiers = len(df_cv_results.iloc[0][0])
number_of_columns = len(df_cv_results.iloc[0])
df_cv_results_per_item = []
df_cv_results_per_row = []
for i in range(number_of_classifiers):
df_cv_results_per_item = []
for column in df_cv_results.iloc[0]:
df_cv_results_per_item.append(column[i])
df_cv_results_per_row.append(df_cv_results_per_item)
df_cv_results_classifiers = pd.DataFrame(data = df_cv_results_per_row, columns= df_cv_results.columns)
parameters = df_cv_results_classifiers['params']
PerClassMetrics = []
#perm_imp_rfpimp = []
#FeatureImp = []
#RFEList = []
permList = []
PerFeatureAccuracy = []
global subset
global loopFeatures
global yPredictProb
global columns
columns = []
counter = 0
subset = XData
for i, eachClassifierParams in enumerate(grid.cv_results_['params']):
eachClassifierParamsDictList = {}
for key, value in eachClassifierParams.items():
Listvalue = []
Listvalue.append(value)
eachClassifierParamsDictList[key] = Listvalue
counter = counter + 1
grid = GridSearchCV(estimator=clf,
param_grid=eachClassifierParamsDictList,
scoring=scoring,
cv=crossValidation,
refit='accuracy',
n_jobs = -1)
if (featureSelection['featureSelection'] == ''):
subset = XData
else:
featureSelected = []
for indices, each in enumerate(XData.columns):
if (int(''.join(x for x in featureSelection['featureSelection'][loopFeatures] if x.isdigit())) == 1):
featureSelected.append(each)
loopFeatures = loopFeatures + 3
subset = XData[featureSelected]
element = (column_index(XData, featureSelected))
columns.append(element)
grid.fit(subset, yData)
#perm_imp_rfpimp.append(permutation_importances(grid.best_estimator_, subset, yData, r2)['Importance'])
perm = PermutationImportance(grid.best_estimator_, cv = None, refit = True, n_iter = 50).fit(subset, yData)
permList.append(perm.feature_importances_)
n_feats = subset.shape[1]
for i in range(n_feats):
scores = model_selection.cross_val_score(grid.best_estimator_, subset.values[:, i].reshape(-1, 1), yData, cv=crossValidation)
PerFeatureAccuracy.append(scores.mean())
yPredict = grid.predict(subset)
yPredictProb.append(grid.predict_proba(subset))
PerClassMetrics.append(classification_report(yData, yPredict, target_names=target_names, digits=2, output_dict=True))
#if (FI == 1):
# X = subset.values
# Y = array(yData)
# FeatureImp.append(class_feature_importance(X, Y, grid.best_estimator_.feature_importances_))
# rfe = RFE(grid.best_estimator_, 3)
# fit = rfe.fit(subset, yData)
# RFEList.append(fit.ranking_)
bestfeatures = SelectKBest(score_func=chi2, k='all')
fit = bestfeatures.fit(subset,yData)
dfscores = pd.DataFrame(fit.scores_)
dfcolumns = pd.DataFrame(subset.columns)
#concat two dataframes for better visualization
featureScores = pd.concat([dfcolumns,dfscores],axis=1)
featureScores.columns = ['Specs','Score'] #naming the dataframe columns
#FeatureImpPandas = pd.DataFrame(FeatureImp)
#RFEListPD = pd.DataFrame(RFEList)
#perm_imp_rfpimp = pd.DataFrame(perm_imp_rfpimp)
perm_imp_eli5PD = pd.DataFrame(permList)
PerClassMetricsPandas = pd.DataFrame(PerClassMetrics)
PerFeatureAccuracyPandas = pd.DataFrame(PerFeatureAccuracy)
return df_cv_results_classifiers, parameters, PerClassMetricsPandas, PerFeatureAccuracyPandas, perm_imp_eli5PD, featureScores
#def r2(rf, X_train, y_train):
# return r2_score(y_train, rf.predict(X_train))
def class_feature_importance(X, Y, feature_importances):
N, M = X.shape
X = scale(X)
@ -403,12 +310,8 @@ def Preprocessing():
global factors
factors = [1,1,1,1,1,1]
global df_cv_results_classifiers_metrics
global NumberofscoringMetrics
del df_cv_results_classifiers['params']
df_cv_results_classifiers_metrics = df_cv_results_classifiers.copy()
del df_cv_results_classifiers_metrics['mean_fit_time']
del df_cv_results_classifiers_metrics['mean_score_time']
df_cv_results_classifiers_metrics = df_cv_results_classifiers_metrics.ix[:, 0:NumberofscoringMetrics]
df_cv_results_classifiers_metrics = df_cv_results_classifiers_metrics.filter(['mean_test_accuracy','mean_test_f1_macro','mean_test_precision','mean_test_recall','mean_test_jaccard'])
return [parameters,PerClassMetrics,FeatureAccuracy,df_cv_results_classifiers_metrics,perm_imp_eli5PDCon,featureScoresCon]
def sumPerMetric(factors):
@ -416,7 +319,6 @@ def sumPerMetric(factors):
preProcessResults = []
preProcessResults = Preprocessing()
loopThroughMetrics = preProcessResults[3]
global scoring
global metricsPerModel
metricsPerModel = []
@ -425,7 +327,7 @@ def sumPerMetric(factors):
metricsPerModel.append(loopThroughMetrics['mean_test_precision'].sum()/loopThroughMetrics['mean_test_precision'].count())
metricsPerModel.append(loopThroughMetrics['mean_test_recall'].sum()/loopThroughMetrics['mean_test_recall'].count())
metricsPerModel.append(loopThroughMetrics['mean_test_jaccard'].sum()/loopThroughMetrics['mean_test_jaccard'].count())
for index, row in loopThroughMetrics.iterrows():
for row in loopThroughMetrics.iterrows():
rowSum = 0
lengthFactors = len(scoring)
for loop,elements in enumerate(row):
@ -496,7 +398,6 @@ def InitializeEnsemble():
ModelSpaceMDS = FunMDS(XClassifiers)
ModelSpaceTSNE = FunTsne(XClassifiers)
ModelSpaceTSNE = ModelSpaceTSNE.tolist()
print(ModelSpaceTSNE)
global ClassifierIDsList
key = 0
EnsembleModel(ClassifierIDsList, key)
@ -697,70 +598,89 @@ def SendToPlot():
}
return jsonify(response)
# Retrieve data from client
# Initialize every model for each algorithm
@cross_origin(origin='localhost',headers=['Content-Type','Authorization'])
@app.route('/data/ServerRequestSelParameters', methods=["GET", "POST"])
def RetrieveModel():
global RetrievedModel
# get the models from the frontend
RetrievedModel = request.get_data().decode('utf8').replace("'", '"')
RetrievedModel = json.loads(RetrievedModel)
global parametersPerformancePerModel
parametersPerformancePerModel = []
global algorithms
global factors
factors = [1,1,1,1,1,1]
algorithms = RetrievedModel['Algorithms']
# loop through the algorithms
global allParametersPerformancePerModel
for eachAlgor in algorithms:
if (eachAlgor) == 'KNN':
clf = KNeighborsClassifier()
params = {'n_neighbors': list(range(1, 25)), 'weights': ['uniform', 'distance'], 'algorithm': ['brute', 'kd_tree', 'ball_tree'], 'metric': ['chebyshev', 'manhattan', 'euclidean', 'minkowski']}
AlgorithmsIDsEnd = 0
else:
clf = RandomForestClassifier()
params = {'n_estimators': list(range(80, 120)), 'criterion': ['gini', 'entropy']}
GridSearchForParameters(clf, params, eachAlgor, factors)
AlgorithmsIDsEnd = 576
allParametersPerformancePerModel = GridSearchForModels(clf, params, eachAlgor, factors, AlgorithmsIDsEnd)
# call the function that sends the results to the frontend
SendEachClassifiersPerformanceToVisualize()
return 'Everything Okay'
def GridSearchForParameters(clf, params, eachAlgor, factors):
global scoring
global NumberofscoringMetrics
location = './cachedir'
memory = Memory(location, verbose=0)
scoring = {'accuracy': 'accuracy', 'f1_macro': 'f1_weighted', 'precision': 'precision_weighted', 'recall': 'recall_weighted', 'jaccard': 'jaccard_weighted'}
NumberofscoringMetrics = len(scoring)
# calculating for all algorithms and models the performance and other results
@memory.cache
def GridSearchForModels(clf, params, eachAlgor, factors, AlgorithmsIDsEnd):
grid = GridSearchCV(estimator=clf,
param_grid=params,
scoring=scoring,
cv=crossValidation,
refit='accuracy',
n_jobs = -1)
# instantiate spark session
spark = (
SparkSession
.builder
.getOrCreate()
)
sc = spark.sparkContext
# this is the grid we use to train the models
grid = DistGridSearchCV(
estimator=clf, param_grid=params,
sc=sc, cv=crossValidation, refit='accuracy', scoring=scoring,
verbose=0, n_jobs=-1)
# fit and extract the probabilities
grid.fit(XData, yData)
yPredict = grid.predict(XData)
# process the results
cv_results = []
cv_results.append(grid.cv_results_)
df_cv_results = pd.DataFrame.from_dict(cv_results)
number_of_classifiers = len(df_cv_results.iloc[0][0])
number_of_columns = len(df_cv_results.iloc[0])
df_cv_results_per_item = []
# number of models stored
number_of_models = len(df_cv_results.iloc[0][0])
# initialize results per row
df_cv_results_per_row = []
for i in range(number_of_classifiers):
# loop through number of models
modelsIDs = []
for i in range(number_of_models):
modelsIDs.append(AlgorithmsIDsEnd+i)
# initialize results per item
df_cv_results_per_item = []
for column in df_cv_results.iloc[0]:
df_cv_results_per_item.append(column[i])
df_cv_results_per_row.append(df_cv_results_per_item)
df_cv_results_classifiers = pd.DataFrame(data = df_cv_results_per_row, columns= df_cv_results.columns)
global allParametersPerformancePerModel
global parametersPerformancePerModel
# store the results into a pandas dataframe
df_cv_results_classifiers = pd.DataFrame(data = df_cv_results_per_row, columns= df_cv_results.columns)
# copy and filter in order to get only the metrics
metrics = df_cv_results_classifiers.copy()
del metrics['mean_fit_time']
del metrics['mean_score_time']
metrics = metrics.ix[:, 0:NumberofscoringMetrics]
metrics = metrics.filter(['mean_test_accuracy','mean_test_f1_macro','mean_test_precision','mean_test_recall','mean_test_jaccard'])
# control the factors
sumperModel = []
global rowSum
for index, row in metrics.iterrows():
rowSum = 0
lengthFactors = NumberofscoringMetrics
@ -771,31 +691,77 @@ def GridSearchForParameters(clf, params, eachAlgor, factors):
sumperModel = 0
else:
sumperModel.append(rowSum/lengthFactors)
global target_names
global PerClassMetric
global PerClassMetricPandas
# summarize all models metrics
summarizedMetrics = pd.DataFrame(sumperModel)
summarizedMetrics.rename(columns={0:'sum'})
# concat parameters and performance
parameters = pd.DataFrame(df_cv_results_classifiers['params'])
parametersPerformancePerModel = pd.concat([summarizedMetrics, parameters], axis=1)
parametersPerformancePerModel = parametersPerformancePerModel.to_json()
parametersLocal = json.loads(parametersPerformancePerModel)['params'].copy()
Models = []
for index, items in enumerate(parametersLocal):
Models.append(str(index))
parametersLocalNew = [ parametersLocal[your_key] for your_key in Models ]
permList = []
PerFeatureAccuracy = []
PerClassMetric = []
yPredictProb.append(grid.predict_proba(XData))
PerClassMetric.append(classification_report(yData, yPredict, target_names=target_names, digits=2, output_dict=True))
for eachModelParameters in parametersLocalNew:
clf.set_params(**eachModelParameters)
perm = PermutationImportance(clf, cv = None, refit = True, n_iter = 25).fit(XData, yData)
permList.append(perm.feature_importances_)
n_feats = XData.shape[1]
for i in range(n_feats):
scores = model_selection.cross_val_score(clf, XData.values[:, i].reshape(-1, 1), yData, cv=crossValidation)
PerFeatureAccuracy.append(scores.mean())
clf.fit(XData, yData)
yPredict = clf.predict(XData)
# retrieve target names (class names)
PerClassMetric.append(classification_report(yData, yPredict, target_names=target_names, digits=2, output_dict=True))
PerClassMetricPandas = pd.DataFrame(PerClassMetric)
del PerClassMetricPandas['accuracy']
del PerClassMetricPandas['macro avg']
del PerClassMetricPandas['weighted avg']
summarizedMetrics = pd.DataFrame(sumperModel)
summarizedMetrics.rename(columns={0:'sum'})
parameters = pd.DataFrame(df_cv_results_classifiers['params'])
parametersPerformancePerModel = pd.concat([summarizedMetrics, parameters], axis=1)
PerClassMetricPandas = PerClassMetricPandas.to_json()
parametersPerformancePerModel = parametersPerformancePerModel.to_json()
allParametersPerformancePerModel.append(parametersPerformancePerModel)
allParametersPerformancePerModel.append(PerClassMetricPandas)
return 'Everything is okay'
#GridSearchForParameters = mem.cache(GridSearchForParameters)
# Sending each model's results
perm_imp_eli5PD = pd.DataFrame(permList)
perm_imp_eli5PD = perm_imp_eli5PD.to_json()
PerFeatureAccuracyPandas = pd.DataFrame(PerFeatureAccuracy)
PerFeatureAccuracyPandas = PerFeatureAccuracyPandas.to_json()
bestfeatures = SelectKBest(score_func=chi2, k='all')
fit = bestfeatures.fit(XData,yData)
dfscores = pd.DataFrame(fit.scores_)
dfcolumns = pd.DataFrame(XData.columns)
featureScores = pd.concat([dfcolumns,dfscores],axis=1)
featureScores.columns = ['Specs','Score'] #naming the dataframe columns
featureScores = featureScores.to_json()
# gather the results and send them back
results.append(modelsIDs) # Position: 0 and so on
results.append(parametersPerformancePerModel) # Position: 1 and so on
results.append(PerClassMetricPandas) # Position: 2 and so on
results.append(PerFeatureAccuracyPandas) # Position: 3 and so on
results.append(perm_imp_eli5PD) # Position: 4 and so on
results.append(featureScores) # Position: 5 and so on
return results
# Sending each model's results to frontend
@app.route('/data/PerformanceForEachModel', methods=["GET", "POST"])
def SendEachClassifiersPerformanceToVisualize ():
def SendEachClassifiersPerformanceToVisualize():
response = {
'PerformancePerModel': allParametersPerformancePerModel,
}
@ -833,161 +799,55 @@ def RetrieveModelsParam():
results = []
counter1 = 0
counter2 = 0
KNNModels = []
RFModels = []
parametersLocalKNN = json.loads(allParametersPerformancePerModel[1])['params'].copy()
your_key = '496'
parametersLocalRF = json.loads(allParametersPerformancePerModel[4])['params'].copy()
for index, items in enumerate(algorithmList):
if (items == 'KNN'):
counter1 = counter1 + 1
KNNModels.append(RetrieveModelsPar['models'][index])
else:
counter2 = counter2 + 1
output = pd.DataFrame()
for d in RetrieveModelsPar['parameters']:
output = output.append(json.loads(d), ignore_index=True)
RetrieveModelsPandSel = output.loc[0:counter1,:]
RetrieveModelsPandSel2 = output.loc[counter1:counter1+counter2,:]
RetrieveModelsPandSelDic = RetrieveModelsPandSel.to_dict(orient='list')
RetrieveModelsPandSelDic2 = RetrieveModelsPandSel2.to_dict(orient='list')
RetrieveModels = {}
for key, value in RetrieveModelsPandSelDic.items():
withoutDuplicates = Remove(value)
RetrieveModels[key] = withoutDuplicates
RetrieveModels2 = {}
for key, value in RetrieveModelsPandSelDic2.items():
withoutDuplicates = Remove(value)
RetrieveModels2[key] = withoutDuplicates
RFModels.append(str(int(RetrieveModelsPar['models'][index])-576))
parametersLocalKNNNew = [ parametersLocalKNN[your_key] for your_key in KNNModels ]
parametersLocalRFNew = [ parametersLocalRF[your_key] for your_key in RFModels ]
#output = pd.DataFrame()
#print(RetrieveModelsPar['models'])
#for d in RetrieveModelsPar['parameters']:
# output = output.append(json.loads(d), ignore_index=True)
#RetrieveModelsPandSel = output.loc[0:counter1,:]
#RetrieveModelsPandSel2 = output.loc[counter1:counter1+counter2,:]
#RetrieveModelsPandSelDic = RetrieveModelsPandSel.to_dict(orient='list')
#RetrieveModelsPandSelDic2 = RetrieveModelsPandSel2.to_dict(orient='list')
#print(RetrieveModelsPandSelDic)
#RetrieveModels = {}
#for key, value in RetrieveModelsPandSelDic.items():
# withoutDuplicates = Remove(value)
# RetrieveModels[key] = withoutDuplicates
#RetrieveModels2 = {}
#for key, value in RetrieveModelsPandSelDic2.items():
# withoutDuplicates = Remove(value)
# RetrieveModels2[key] = withoutDuplicates
global resultsList
resultsList = []
for alg in count:
if (alg == 'KNN'):
clf = KNeighborsClassifier()
params = RetrieveModels
detailsParams.append(params)
results.append(GridSearch(clf, params))
#params = RetrieveModels
#detailsParams.append(params)
results.append(GridSearch(clf, parametersLocalKNNNew))
resultsList.append(results[0])
elif (alg == 'RF'):
clf = RandomForestClassifier()
params = RetrieveModels2
detailsParams.append(params)
results.append(GridSearch(clf, params))
#params = RetrieveModels2
#detailsParams.append(params)
results.append(GridSearch(clf, parametersLocalRFNew))
resultsList.append(results[0])
else:
pass
return 'Everything Okay'
# Retrieve data from client
@cross_origin(origin='localhost',headers=['Content-Type','Authorization'])
@app.route('/data/FeaturesScoresUpdate', methods=["GET", "POST"])
def UpdateBarChartLine():
RetrieveModelsforUpdate = request.get_data().decode('utf8').replace("'", '"')
RetrieveModelsforUpdate = json.loads(RetrieveModelsforUpdate)
algorithms = RetrieveModelsforUpdate['algorithms']
count = []
if ('KNN' in algorithms):
count.append('KNN')
else:
count.append(0)
if ('RF' in algorithms):
count.append('RF')
else:
count.append(0)
results = []
counter1 = 0
counter2 = 0
for index, items in enumerate(algorithms):
if (items == 'KNN'):
counter1 = counter1 + 1
else:
counter2 = counter2 + 1
output = pd.DataFrame()
output2 = pd.DataFrame()
loop = 0
for d in RetrieveModelsforUpdate['parameters']:
if (loop < counter1):
output = output.append(json.loads(d), ignore_index=True)
else:
output2 = output2.append(json.loads(d), ignore_index=True)
loop = loop + 1
output.dropna(axis='columns')
output2.dropna(axis='columns')
if (output.empty):
pass
else:
RetrieveModelsPandSel = output.loc[0:counter1,:]
RetrieveModelsPandSelDic = RetrieveModelsPandSel.to_dict(orient='list')
RetrieveModels = {}
for key, value in RetrieveModelsPandSelDic.items():
withoutDuplicates = Remove(value)
RetrieveModels[key] = withoutDuplicates
if (output2.empty):
pass
else:
RetrieveModelsPandSel2 = output2.loc[0:counter2,:]
RetrieveModelsPandSelDic2 = RetrieveModelsPandSel2.to_dict(orient='list')
RetrieveModels2 = {}
for key, value in RetrieveModelsPandSelDic2.items():
withoutDuplicates = Remove(value)
RetrieveModels2[key] = withoutDuplicates
factors = [1,1,1,1,1,1]
global allParametersPerformancePerModelUpdate
allParametersPerformancePerModelUpdate = []
for alg in count:
if (alg == 'KNN'):
clf = KNeighborsClassifier()
params = RetrieveModels
GridSearchForUpdate(clf, params, factors)
elif (alg == 'RF'):
clf = RandomForestClassifier()
params = RetrieveModels2
GridSearchForUpdate(clf, params, factors)
else:
allParametersPerformancePerModelUpdate.append(0)
SendEachClassifiersPerformanceToVisualizeLinePlot()
return 'Everything Okay'
def GridSearchForUpdate(clf, params, factors):
global scoring
global NumberofscoringMetrics
scoring = {'accuracy': 'accuracy', 'f1_macro': 'f1_weighted', 'precision': 'precision_weighted', 'recall': 'recall_weighted', 'jaccard': 'jaccard_weighted'}
NumberofscoringMetrics = len(scoring)
grid = GridSearchCV(estimator=clf,
param_grid=params,
scoring=scoring,
cv=crossValidation,
refit='accuracy',
n_jobs = -1)
grid.fit(XData, yData)
yPredict = grid.predict(XData)
global allParametersPerformancePerModelUpdate
global target_names
global PerClassUpd
global PerClassMetricUpdate
PerClassUpd = []
PerClassMetricUpdate = []
PerClassUpd.append(classification_report(yData, yPredict, target_names=target_names, digits=2, output_dict=True))
PerClassMetricUpdate = pd.DataFrame(PerClassUpd)
del PerClassMetricUpdate['accuracy']
del PerClassMetricUpdate['macro avg']
del PerClassMetricUpdate['weighted avg']
PerClassMetricUpdate = PerClassMetricUpdate.to_json()
allParametersPerformancePerModelUpdate.append(PerClassMetricUpdate)
return 'Everything is okay'
# Sending each model's results
@app.route('/data/UpdatePerFeaturePerformance', methods=["GET", "POST"])
def SendEachClassifiersPerformanceToVisualizeLinePlot ():
global allParametersPerformancePerModelUpdate
response = {
'PerformanceCheck': allParametersPerformancePerModelUpdate,
}
return jsonify(response)
Loading…
Cancel
Save