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 { - + this.props.onFileChange(event)} style={{backgroundColor: "white", color: "black"}} id="my_input_file_form"/> @@ -104,17 +40,17 @@ class DatasetSelector extends React.Component { - + - + diff --git a/frontend/src/components/FullPage.js b/frontend/src/components/FullPage.js index 4ee24cd..a6ce74c 100644 --- a/frontend/src/components/FullPage.js +++ b/frontend/src/components/FullPage.js @@ -30,38 +30,17 @@ class FullPage extends React.Component { super(props); // The states of the children that need to be shared are "lifted" here - this.initial_state = { - dataset_name : null, - - formatted_features : null, - feature_search_query: '', - search_filtered_features_list : null, - - selected_class_feature: null, - class_values_to_display: null, - unique_values_search_query: '', - search_filtered_unique_values_list : null, + this.user_default_state_values = { + field_separator: ',', - image_to_display: null, show_unknown_only: false, - n_features_used: null, - n_known_classes: null, - - view_in_encoder_dict: {}, - estimated_times_to_train: {}, - // Default rules generation parameters decision_tree_training_mode: "one_vs_rest", decision_tree_unknown_classes_only: false, decision_tree_max_depth: null, decision_tree_min_samples_split: 2, decision_tree_max_leaf_nodes: 10, - decision_tree_response_text_rules: "", - decision_tree_response_pdf_file: null, - decision_tree_response_accuracy_score: null, - - selected_model : "pbn", // Default PBN parameters model_pbn_epochs : 200, @@ -85,7 +64,7 @@ class FullPage extends React.Component { model_tabncd_activation_fct : "relu", model_tabncd_hidden_layers: [], - // Default k means parameters + // Default k-means parameters model_k_means_n_clusters: 10, // Default spectral clustering parameters @@ -100,14 +79,131 @@ class FullPage extends React.Component { model_projection_in_classifier_lr_value : 0.001, model_projection_in_classifier_activation_fct: "relu", model_projection_in_classifier_training_progress: 0, + } + this.dataset_default_state_values = { + selectedFile: "", + dataset_name : null, + + formatted_features : null, + feature_search_query: '', + search_filtered_features_list : null, + + selected_class_feature: null, + class_values_to_display: null, + unique_values_search_query: '', + search_filtered_unique_values_list : null, + + image_to_display: null, + + n_features_used: null, + n_known_classes: null, + + decision_tree_response_pdf_file: null, + } + this.other_default_state_values = { + selected_model : "pbn", + + view_in_encoder_dict: {}, // For each modal, the value of the 'view_in_encoder' checkbox. Keys are the modal id. + estimated_times_to_train: {},// For each modal, the estimated times to train. Keys are the modal id. // Feature modal, opened when a point is clicked in the scatter plot feature_modal_is_open: false, point_feature_names: null, point_feature_values: null, - }; + } - this.state = this.initial_state; + // Set the initial state as the concatenation of all these dicts: + this.state = { ...this.user_default_state_values, ...this.dataset_default_state_values, ...this.other_default_state_values}; + } + + 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}) + } + + // Open the waiting notification on screen + const key = enqueueSnackbar({ + anchorOrigin: { vertical: 'top', horizontal: 'left', }, + persist: true, + content: (key) => , + }) + + 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 => { + this.setState({dataset_name: dataset_name}) + + // The features we just received from the server are sent to the FullPage.js component + const new_formatted_features = response['file_header'].map((feature, index) => ({"name": feature, "checked": true, "index": index, "disabled": false})) + this.setState({formatted_features: new_formatted_features}) + this.setState({search_filtered_features_list: this.getUpdatedFilteredList(new_formatted_features, this.state.feature_search_query)}) + const tmp_n_feat = this.getNumberOfCheckedValues(new_formatted_features) + this.setState({n_features_used: tmp_n_feat}) + + // Add default layers to models: + this.setState({model_projection_in_classifier_hidden_layers: [Math.floor(0.75*tmp_n_feat), Math.floor(0.5*tmp_n_feat)]}) + this.setState({model_tabncd_hidden_layers: [Math.floor(0.75*tmp_n_feat), Math.floor(0.5*tmp_n_feat)]}) + this.setState({model_pbn_hidden_layers: [Math.floor(0.75*tmp_n_feat), Math.floor(0.5*tmp_n_feat)]}) + }) + } + }) + .finally(() => { + closeSnackbar(key) + }) + } + + onFileChange = event => { + this.setState({ selectedFile: event.target.files[0].name }) + } + + onDatasetUnload = () => { + // We don't want to reset every parameter the user defined before, just the values related to the dataset: + document.getElementById("my_input_file_form").value = ""; + this.setState({ ...this.dataset_default_state_values}) + } + + onResetParametersToDefault = () => { + Swal.fire({ + title: 'Reset parameters', + text: "All the parameters, buttons and checkboxes will be reset to the default values.", + showDenyButton: true, + confirmButtonText: 'Reset', + denyButtonText: `Don't reset`, + }).then((result) => { + if (result.isConfirmed) { + document.getElementById("my_input_file_form").value = ""; + this.setState({ ...this.user_default_state_values}) + } + }) + } + + onDatasetSeparatorChange = selected_sep => { + this.setState({field_separator: selected_sep.target.value}) } onFeatureRadioButtonChange = (feature_name) => { @@ -153,19 +249,6 @@ class FullPage extends React.Component { }) } - onNewFeaturesLoaded = (new_features) => { - const new_formatted_features = new_features.map((feature, index) => ({"name": feature, "checked": true, "index": index, "disabled": false})) - this.setState({formatted_features: new_formatted_features}) - this.setState({search_filtered_features_list: this.getUpdatedFilteredList(new_formatted_features, this.state.feature_search_query)}) - const tmp_n_feat = this.getNumberOfCheckedValues(new_formatted_features) - this.setState({n_features_used: tmp_n_feat}) - - // Add default layers to models: - this.setState({model_projection_in_classifier_hidden_layers: [Math.floor(0.75*tmp_n_feat), Math.floor(0.5*tmp_n_feat)]}) - this.setState({model_tabncd_hidden_layers: [Math.floor(0.75*tmp_n_feat), Math.floor(0.5*tmp_n_feat)]}) - this.setState({model_pbn_hidden_layers: [Math.floor(0.75*tmp_n_feat), Math.floor(0.5*tmp_n_feat)]}) - } - onChangeFeaturesSearch = query => { this.setState({ feature_search_query: query.target.value }) @@ -425,14 +508,6 @@ class FullPage extends React.Component { }) } - setDatasetNameHandler = (dataset_name) => { - this.setState({dataset_name: dataset_name}) - } - - unloadDatasetHandler = () => { - this.setState(this.initial_state) - } - onRulesRunButtonClick = () => { // Build the request const requestOptions = { @@ -689,8 +764,6 @@ class FullPage extends React.Component { return } - console.log(model_config) - // Build the request const requestOptions = { method: 'POST', @@ -810,11 +883,11 @@ class FullPage extends React.Component { anchorOrigin: { vertical: 'top', horizontal: 'left', }, persist: true, content: (key, message) => , + message={message} + thread_id={thread_id} + refreshIntervalId={refreshIntervalId} + onSeeResultsButtonClick={this.onSeeResultsButtonClick} + onViewInEncoderSwitchChange={this.onViewInEncoderSwitchChange}/>, }) })) // Other clustering models are fast, so we just wait for the result @@ -935,19 +1008,6 @@ class FullPage extends React.Component { this.setState({feature_modal_is_open: false}) } - onSaveImageButtonClick = () => { - if(this.state.image_to_display !== null) { - const link = document.createElement('a') - link.href = this.state.image_to_display - link.setAttribute('download', this.state.dataset_name + '.png') - document.body.appendChild(link) - link.click() - link.parentNode.removeChild(link) // Clean up and remove the link - } else { - FireSwalError("No image to save.") - } - } - onProjectionInClassifierAddLayerButtonClick = () => { const layer_size = document.getElementById('projectionInClassifierLayerSizeInput').value @@ -1051,8 +1111,8 @@ class FullPage extends React.Component { onClearCacheButtonClick = () => { Swal.fire({ - title: 'Are you sure?', - text: "Clearing the server\'s temporary files might increase the processing time of the next requests.", + title: 'Clear the server\' cached data', + text: "Clear the computed t-SNEs and saved images from the server's files. The processing time of the next requests will increase.", showDenyButton: true, confirmButtonText: 'Clear', denyButtonText: `Don't clear`, @@ -1073,11 +1133,7 @@ class FullPage extends React.Component { }) } if (serverPromise.status === 200) { - Swal.fire('Done!', '', 'success') - - this.setState(this.initial_state) - - // closeSnackbar() // Closes all opened snackbars + Swal.fire('Cleared the server\'s files!', '', 'success') } }) } @@ -1109,7 +1165,6 @@ class FullPage extends React.Component { } if (serverPromise.status === 200) { serverPromise.json().then(server_json_response => { - console.log(server_json_response) this.setState({ point_feature_names: server_json_response.point_feature_names, point_feature_values: server_json_response.point_feature_values, @@ -1131,9 +1186,11 @@ class FullPage extends React.Component { - @@ -1169,7 +1226,8 @@ class FullPage extends React.Component { onShowUnknownOnlySwitchChange={this.onShowUnknownOnlySwitchChange} show_unknown_only={this.state.show_unknown_only} - onSaveImageButtonClick={this.onSaveImageButtonClick} + onResetParametersToDefault={this.onResetParametersToDefault} + onClearCacheButtonClick={this.onClearCacheButtonClick} handlePointClick={this.handlePointClick} @@ -1181,6 +1239,8 @@ class FullPage extends React.Component { { - this.props.updateSelectedModel(event.target.value) - this.setState({selected_model: event.target.value}) - }; - render() { return ( @@ -52,7 +39,7 @@ class ModelSelection extends React.Component { Model - + this.props.updateSelectedModel(event.target.value)} className="my-row" value={this.props.selected_model}> @@ -65,11 +52,13 @@ class ModelSelection extends React.Component {
- {this.state.selected_model === "pbn" && + {this.props.selected_model === "pbn" && } - {this.state.selected_model === "tabularncd" && + {this.props.selected_model === "tabularncd" && } - {this.state.selected_model === "k_means" && + {this.props.selected_model === "k_means" && } - {this.state.selected_model === "spectral_clustering" && + {this.props.selected_model === "spectral_clustering" && } - {this.state.selected_model === "projection_in_classifier" && + {this.props.selected_model === "projection_in_classifier" && diff --git a/frontend/src/components/RulesGenerator.js b/frontend/src/components/RulesGenerator.js index 539368b..eb18dd4 100644 --- a/frontend/src/components/RulesGenerator.js +++ b/frontend/src/components/RulesGenerator.js @@ -19,7 +19,6 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import { regular } from '@fortawesome/fontawesome-svg-core/import.macro' class RulesGenerator extends React.Component { - render() { return ( @@ -64,6 +63,7 @@ class RulesGenerator extends React.Component { key="switch_train_unknown_ony" id="switch_train_unknown_ony" onChange={this.props.onRulesUnknownClassesOnlySwitchChange} + checked={this.props.decision_tree_unknown_classes_only} style={{marginRight: "10px"}} /> @@ -123,7 +123,7 @@ class RulesGenerator extends React.Component { min={0} placeholder="Max depth" step={1} - defaultValue={this.props.decision_tree_decision_tree_max_leaf_nodes} + value={this.props.decision_tree_decision_tree_max_leaf_nodes} onChange={this.props.on_decision_tree_decision_tree_max_leaf_nodes_change} /> diff --git a/frontend/src/components/models_parameters/KMeansParameters.js b/frontend/src/components/models_parameters/KMeansParameters.js index e23bf78..cf4dcd1 100644 --- a/frontend/src/components/models_parameters/KMeansParameters.js +++ b/frontend/src/components/models_parameters/KMeansParameters.js @@ -34,13 +34,12 @@ const KMeansParameters = (props) => { placeholder="n clusters" step={1} onChange={props.on_kmeans_n_clusters_change} - defaultValue={props.k_means_n_clusters} + value={props.k_means_n_clusters} />
) - } export default KMeansParameters; \ No newline at end of file diff --git a/frontend/src/components/models_parameters/PBNParameters.js b/frontend/src/components/models_parameters/PBNParameters.js index d8107e3..9b29ae3 100644 --- a/frontend/src/components/models_parameters/PBNParameters.js +++ b/frontend/src/components/models_parameters/PBNParameters.js @@ -65,7 +65,7 @@ const PBNParameters = (props) => { placeholder="n clusters" step={1} onChange={props.on_pbn_n_clusters_change} - defaultValue={props.pbn_n_clusters_value} + value={props.pbn_n_clusters_value} />
@@ -85,7 +85,7 @@ const PBNParameters = (props) => { placeholder="w" step={0.1} onChange={props.on_pbn_w_change} - defaultValue={props.pbn_w_value} + value={props.pbn_w_value} />
@@ -105,7 +105,7 @@ const PBNParameters = (props) => { placeholder="lr" step={0.001} onChange={props.on_pbn_lr_change} - defaultValue={props.pbn_lr_value} + value={props.pbn_lr_value} /> @@ -124,7 +124,7 @@ const PBNParameters = (props) => { placeholder="epochs" step={1} onChange={props.on_pbn_epochs_change} - defaultValue={props.pbn_epochs_value} + value={props.pbn_epochs_value} /> @@ -144,7 +144,7 @@ const PBNParameters = (props) => { placeholder="dropout" step={0.1} onChange={props.on_pbn_dropout_change} - defaultValue={props.pbn_dropout_value} + value={props.pbn_dropout_value} /> @@ -161,6 +161,7 @@ const PBNParameters = (props) => { diff --git a/frontend/src/components/models_parameters/ProjectionInClassifierParameters.js b/frontend/src/components/models_parameters/ProjectionInClassifierParameters.js index c01110b..16ae2bf 100644 --- a/frontend/src/components/models_parameters/ProjectionInClassifierParameters.js +++ b/frontend/src/components/models_parameters/ProjectionInClassifierParameters.js @@ -66,7 +66,7 @@ const ProjectionInClassifierParameters = (props) => { placeholder="n clusters" step={1} onChange={props.on_projection_in_classifier_n_clusters_change} - defaultValue={props.projection_in_classifier_n_clusters} + value={props.projection_in_classifier_n_clusters} /> @@ -86,7 +86,7 @@ const ProjectionInClassifierParameters = (props) => { placeholder="dropout" step={0.1} onChange={props.on_projection_in_classifier_dropout_change} - defaultValue={props.projection_in_classifier_dropout} + value={props.projection_in_classifier_dropout} /> @@ -106,7 +106,7 @@ const ProjectionInClassifierParameters = (props) => { placeholder="learning rate" step={0.001} onChange={props.on_projection_in_classifier_lr_change} - defaultValue={props.projection_in_classifier_lr_value} + value={props.projection_in_classifier_lr_value} /> @@ -125,7 +125,7 @@ const ProjectionInClassifierParameters = (props) => { placeholder="epochs" step={1} onChange={props.on_projection_in_classifier_epochs_change} - defaultValue={props.projection_in_classifier_epochs} + value={props.projection_in_classifier_epochs} /> @@ -142,6 +142,7 @@ const ProjectionInClassifierParameters = (props) => { diff --git a/frontend/src/components/models_parameters/SpectralClusteringParameters.js b/frontend/src/components/models_parameters/SpectralClusteringParameters.js index 1f392e0..34c41bc 100644 --- a/frontend/src/components/models_parameters/SpectralClusteringParameters.js +++ b/frontend/src/components/models_parameters/SpectralClusteringParameters.js @@ -35,7 +35,7 @@ const SpectralClusteringParameters = (props) => { placeholder="n clusters" step={1} onChange={props.on_spectral_clustering_n_clusters_change} - defaultValue={props.spectral_clustering_n_clusters} + value={props.spectral_clustering_n_clusters} /> @@ -52,6 +52,7 @@ const SpectralClusteringParameters = (props) => { diff --git a/frontend/src/components/models_parameters/TabularNCDParameters.js b/frontend/src/components/models_parameters/TabularNCDParameters.js index 446f4f6..abb4359 100644 --- a/frontend/src/components/models_parameters/TabularNCDParameters.js +++ b/frontend/src/components/models_parameters/TabularNCDParameters.js @@ -65,7 +65,7 @@ const TabularNCDParameters = (props) => { placeholder="n clusters" step={1} onChange={props.on_tabncd_n_clusters_change} - defaultValue={props.tabncd_n_clusters_value} + value={props.tabncd_n_clusters_value} /> @@ -85,7 +85,7 @@ const TabularNCDParameters = (props) => { placeholder="w1" step={0.1} onChange={props.on_tabncd_w1_change} - defaultValue={props.tabncd_w1_value} + value={props.tabncd_w1_value} /> @@ -104,7 +104,7 @@ const TabularNCDParameters = (props) => { placeholder="w2" step={0.1} onChange={props.on_tabncd_w2_change} - defaultValue={props.tabncd_w2_value} + value={props.tabncd_w2_value} /> @@ -124,7 +124,7 @@ const TabularNCDParameters = (props) => { placeholder="top k" step={0.1} onChange={props.on_tabncd_topk_change} - defaultValue={props.tabncd_topk_value} + value={props.tabncd_topk_value} /> @@ -144,7 +144,7 @@ const TabularNCDParameters = (props) => { placeholder="lr" step={0.001} onChange={props.on_tabncd_lr_change} - defaultValue={props.tabncd_lr_value} + value={props.tabncd_lr_value} /> @@ -163,7 +163,7 @@ const TabularNCDParameters = (props) => { placeholder="epochs" step={1} onChange={props.on_tabncd_epochs_change} - defaultValue={props.tabncd_epochs_value} + value={props.tabncd_epochs_value} /> @@ -182,7 +182,7 @@ const TabularNCDParameters = (props) => { placeholder="k neighbors" step={1} onChange={props.on_tabncd_k_neighbors_change} - defaultValue={props.tabncd_k_neighbors_value} + value={props.tabncd_k_neighbors_value} /> @@ -202,7 +202,7 @@ const TabularNCDParameters = (props) => { placeholder="dropout" step={0.1} onChange={props.on_tabncd_dropout_change} - defaultValue={props.tabncd_dropout_value} + value={props.tabncd_dropout_value} /> @@ -219,6 +219,7 @@ const TabularNCDParameters = (props) => { diff --git a/frontend/src/components/pop_up_notifiers/ModelTrainingSnackbar.js b/frontend/src/components/pop_up_notifiers/ModelTrainingSnackbar.js index 0fb7f48..b738656 100644 --- a/frontend/src/components/pop_up_notifiers/ModelTrainingSnackbar.js +++ b/frontend/src/components/pop_up_notifiers/ModelTrainingSnackbar.js @@ -18,7 +18,7 @@ import FireSwalError from "./FireSwalError"; const ModelTrainingSnackbar = forwardRef((props, ref) => { - function onCancelTrainingButtonClick() { + function onCancelTrainingButtonClick(props) { clearInterval(props.refreshIntervalId) const cancelThreadRequestOptions = { @@ -69,7 +69,7 @@ const ModelTrainingSnackbar = forwardRef((props, ref) => {
-
+
@@ -94,7 +94,7 @@ const ModelTrainingSnackbar = forwardRef((props, ref) => { -