diff --git a/backend/__pycache__/server.cpython-310.pyc b/backend/__pycache__/server.cpython-310.pyc
index 5df2a31..497ed68 100644
Binary files a/backend/__pycache__/server.cpython-310.pyc and b/backend/__pycache__/server.cpython-310.pyc differ
diff --git a/backend/server.py b/backend/server.py
index d900e3a..c9f43a3 100644
--- a/backend/server.py
+++ b/backend/server.py
@@ -35,6 +35,8 @@
import gc
import re
+os.environ["OMP_NUM_THREADS"] = '1' # For the k-means warning...
+
app = Flask(__name__)
logging.basicConfig(level=logging.DEBUG)
# app.secret_key = "My Secret key"
@@ -164,50 +166,34 @@ def equal_dicts(d1, d2, ignore_keys):
return d1_filtered == d2_filtered
+def used_classes(config_dict):
+ # In the case where we show only the unknown classes, only the set of unknown classes should be equal
+ if config_dict['show_unknown_only'] is True:
+ return config_dict['unknown_classes']
+ # Otherwise, all the classes have to be the same
+ else:
+ return config_dict['known_classes'] + config_dict['unknown_classes']
+
+
def findTSNEConfig(results_dict, dataset_name, tsne_config_to_find):
+ # If it has to be viewed in a latent space, its complicated...
+ if tsne_config_to_find['view_in_encoder'] is True:
+ return None, None
+
if dataset_name in results_dict.keys():
for tsne_run_name in results_dict[dataset_name].keys():
tsne_run = results_dict[dataset_name][tsne_run_name]
-
- # If it has to be viewed in a latent space, its complicated...
- if tsne_run['tsne_config']['view_in_encoder'] is True or tsne_config_to_find['view_in_encoder'] is True:
- return None, None
- else:
- same_tsne_config = False
- if (tsne_run['tsne_config']['tsne_seed'] == tsne_config_to_find['tsne_seed']
- and tsne_run['tsne_config']['tsne_perplexity'] == tsne_config_to_find['tsne_perplexity']
- and set(tsne_run['tsne_config']['selected_features']) == set(tsne_config_to_find['selected_features'])):
- if tsne_run["tsne_config"]['show_unknown_only'] == tsne_config_to_find['show_unknown_only']:
- # In the case where we show only the unknown classes, only the set of unknown classes should be equal
- if tsne_config_to_find['show_unknown_only'] is True:
- if set(tsne_run['tsne_config']['unknown_classes']) == set(tsne_config_to_find['unknown_classes']):
- same_tsne_config = True
- else:
- # Otherwise, all the classes have to be the same
- if set(tsne_run['tsne_config']['known_classes'] + tsne_run['tsne_config']['unknown_classes']) == set(tsne_config_to_find['known_classes'] + tsne_config_to_find['unknown_classes']):
- same_tsne_config = True
-
- if same_tsne_config is True:
- if os.path.isfile(tsne_run['tsne_filepath']):
- app.logger.debug("Re-using t-SNE at " + tsne_run['tsne_filepath'])
- tsne_array = pd.read_csv(tsne_run['tsne_filepath'], header=None)
- return tsne_array, tsne_run_name
-
- # # In the case where we show all classes, only the set of known + unknown classes should be equal
- # if tsne_config_to_find['show_unknown_only'] is False and tsne_run["tsne_config"][
- # 'show_unknown_only'] is False:
- # if set(tsne_run["tsne_config"]['known_classes'] + tsne_run["tsne_config"]['unknown_classes']) == set(
- # tsne_config_to_find['known_classes'] + tsne_config_to_find['unknown_classes']):
- # # If the sets are equal, we compare the two dicts while ignoring the keys 'known_classes' and 'unknown_classes'
- # if equal_dicts(tsne_run["tsne_config"], tsne_config_to_find, ['known_classes', 'unknown_classes']):
- # if os.path.isfile(tsne_run['tsne_filepath']):
- # tsne_array = pd.read_csv(tsne_run['tsne_filepath'], header=None)
- # return tsne_array, tsne_run_name
- # # If we show only the known classes, the whole config should be equal
- # elif tsne_run["tsne_config"] == tsne_config_to_find:
- # if os.path.isfile(tsne_run['tsne_filepath']):
- # tsne_array = pd.read_csv(tsne_run['tsne_filepath'], header=None)
- # return tsne_array, tsne_run_name
+ # We compare only the configuration elements that matter for the t-SNE:
+ # For instance, the target doesn't matter in the t-SNE, it only matters when coloring the plot.
+ if (tsne_run['tsne_config']['view_in_encoder'] == tsne_config_to_find['view_in_encoder']
+ and tsne_run['tsne_config']['tsne_seed'] == tsne_config_to_find['tsne_seed']
+ and tsne_run['tsne_config']['tsne_perplexity'] == tsne_config_to_find['tsne_perplexity']
+ and set(tsne_run['tsne_config']['selected_features']) == set(tsne_config_to_find['selected_features'])
+ and set(used_classes(tsne_run["tsne_config"])) == set(used_classes(tsne_config_to_find))):
+ if os.path.isfile(tsne_run['tsne_filepath']):
+ app.logger.debug("Re-using t-SNE at " + tsne_run['tsne_filepath'])
+ tsne_array = pd.read_csv(tsne_run['tsne_filepath'], header=None)
+ return tsne_array, tsne_run_name
return None, None
diff --git a/frontend/src/components/AgglomerativeClustering.js b/frontend/src/components/AgglomerativeClustering.js
index a4d0489..bdc5887 100644
--- a/frontend/src/components/AgglomerativeClustering.js
+++ b/frontend/src/components/AgglomerativeClustering.js
@@ -42,6 +42,7 @@ class AgglomerativeClustering extends React.Component {
max={42} // To set to the total number of clusters
tooltip='off'
onChange={changeEvent => this.setState({agglomerative_clustering_value: changeEvent.target.value})}
+ // ToDo control component's value directly with value={...}
/>
diff --git a/frontend/src/components/DataVisualization.js b/frontend/src/components/DataVisualization.js
index 6595c67..37ac9fe 100644
--- a/frontend/src/components/DataVisualization.js
+++ b/frontend/src/components/DataVisualization.js
@@ -17,6 +17,7 @@ import { Tooltip } from "@mui/material";
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { regular } from '@fortawesome/fontawesome-svg-core/import.macro'
import Plot from 'react-plotly.js';
+import { faRotate } from "@fortawesome/free-solid-svg-icons";
class DataVisualization extends React.Component {
@@ -26,23 +27,27 @@ class DataVisualization extends React.Component {
-
Data visualization
- {/*
-
-
diff --git a/frontend/src/components/DatasetSelector.js b/frontend/src/components/DatasetSelector.js
index 85a41be..034dbf0 100644
--- a/frontend/src/components/DatasetSelector.js
+++ b/frontend/src/components/DatasetSelector.js
@@ -12,75 +12,11 @@ import Container from "react-bootstrap/Container";
import React from 'react';
import Col from "react-bootstrap/Col";
import Row from "react-bootstrap/Row";
-import FireSwalError from "./pop_up_notifiers/FireSwalError";
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
import {regular} from "@fortawesome/fontawesome-svg-core/import.macro";
import Tooltip from "@mui/material/Tooltip";
class DatasetSelector extends React.Component {
-
- constructor(props) {
- super(props);
- this.state = {
- selectedFile: "",
- field_separator: ',',
- };
- }
-
- onFileChange = event => {
- this.setState({ selectedFile: event.target.files[0].name })
- }
-
- onDatasetUnload = () => {
- this.setState({selectedFile: ""})
- document.getElementById("my_input_file_form").value = "";
- this.props.unloadDatasetHandler()
- }
-
- onDatasetSeparatorChange = selected_sep => {
- this.setState({field_separator: selected_sep.target.value})
- }
-
- onFileUpload = () => {
- if (this.state.selectedFile === ""){
- FireSwalError('Please select a file to load')
- return
- }
-
- if (this.state.field_separator === ""){
- FireSwalError('Please specify a field separator')
- return
- }
-
- const dataset_name = this.state.selectedFile.replace(/\.[^/.]+$/, "")
- const requestOptions = {
- method: 'POST',
- headers: { 'Content-Type': 'application/json' },
- body: JSON.stringify({
- 'selected_file_path': this.state.selectedFile,
- 'field_separator': this.state.field_separator,
- 'dataset_name': dataset_name})
- }
- fetch('/getFileHeader', requestOptions) // Don't need to specify the full localhost:5000/... as the proxy is set in package.json
- .then(serverPromise => {
- if (serverPromise.status === 500) {
- FireSwalError('Status 500 - Server error', 'Please make sure that the server is running')
- }
- if (serverPromise.status === 422) {
- serverPromise.json().then(error => {
- FireSwalError('Status 422 - Server error', error['error_message'])
- })
- }
- if (serverPromise.status === 200) {
- serverPromise.json().then(response => {
- // The features we just received from the server are sent to the FullPage.js component
- this.props.onNewFeaturesLoaded(response['file_header'])
- this.props.setDatasetNameHandler(dataset_name)
- })
- }
- })
- };
-
render() {
return (
@@ -90,7 +26,7 @@ class DatasetSelector extends React.Component {