From 4a1e609c635c64f541b4321236a3ef0593f8a685 Mon Sep 17 00:00:00 2001 From: MahdiAll99 Date: Wed, 4 Mar 2026 14:36:11 -0500 Subject: [PATCH 01/12] fixed issue in default params in train model node --- .../learning/nodesTypes/trainModelNode.jsx | 28 +++++-------------- 1 file changed, 7 insertions(+), 21 deletions(-) diff --git a/renderer/components/learning/nodesTypes/trainModelNode.jsx b/renderer/components/learning/nodesTypes/trainModelNode.jsx index 79d820b8..f2c2f715 100644 --- a/renderer/components/learning/nodesTypes/trainModelNode.jsx +++ b/renderer/components/learning/nodesTypes/trainModelNode.jsx @@ -30,11 +30,11 @@ const TrainModelNode = ({ id, data }) => { const [modalShowTuning, setModalShowTuning] = useState(false) const { updateNode } = useContext(FlowFunctionsContext) const [IntegrateTuning, setIntegrateTuning] = useState(data.internal.isTuningEnabled ?? false) - const [optimizeThresh, setOptimizeThresh] = useState(data.internal.isOptimizeThreshold ?? false) - const [ensembleEnabled, setEnsembleEnabled] = useState(data.internal.settings.isEnsembleEnabled ?? false) - const [calibrateEnabled, setCalibrateEnabled] = useState(data.internal.settings.isCalibrateEnabled ?? false) + const [optimizeThresh, setOptimizeThresh] = useState(data.internal.optimizeThreshold ?? false) + const [ensembleEnabled, setEnsembleEnabled] = useState(data.internal.ensembleEnabled ?? false) + const [calibrateEnabled, setCalibrateEnabled] = useState(data.internal.calibrateEnabled ?? false) - // Check if isTuningEnabled exists in data.internal, if not initialize it + // Check if default settings exists in data.internal, if not initialize it useEffect(() => { let hasUpdates = false @@ -58,8 +58,9 @@ const TrainModelNode = ({ id, data }) => { const defaults = { isTuningEnabled: false, useTuningGrid: false, - isEnsembleEnabled: false, - isCalibrateEnabled: false, + ensembleEnabled: false, + calibrateEnabled: false, + optimizeThreshold: false, settingsEnsembling: {}, settingsCalibration: {} } @@ -185,21 +186,6 @@ const TrainModelNode = ({ id, data }) => { }) } - /** - * - * @param {Object} e the event of the checkbox - * @description - * This function is used to handle the checkbox for enabling the tuning - */ - const handleIntegration = (e) => { - setIntegrateTuning(e.value) - data.internal.isTuningEnabled = e.value - updateNode({ - id: id, - updatedData: data.internal - }) - } - return ( <> {/* build on top of the Node component */} From 0c24eeff61ceea5ef5aa599185dce65b4d27d716 Mon Sep 17 00:00:00 2001 From: MahdiAll99 Date: Wed, 4 Mar 2026 14:36:29 -0500 Subject: [PATCH 02/12] requests path bug fixed --- go_server/src/utils.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/go_server/src/utils.go b/go_server/src/utils.go index f5616e1c..750df4bb 100644 --- a/go_server/src/utils.go +++ b/go_server/src/utils.go @@ -239,7 +239,8 @@ func copyOutput(r io.Reader, response *string) { // ReadFile reads a file and returns its content as a string func ReadFile(filename string) string { - absPath, _ := filepath.Abs(filename) + cleanPath := strings.Trim(filename, "\" \t\n\r") + absPath, _ := filepath.Abs(cleanPath) log.Println("Reading file: " + absPath) data, err := os.ReadFile(absPath) if err != nil { From fae4ae325e566b47caf50f89392c09e8e8193f57 Mon Sep 17 00:00:00 2001 From: MahdiAll99 Date: Wed, 4 Mar 2026 14:36:48 -0500 Subject: [PATCH 03/12] very minor bug fix --- pythonCode/med_libs/MEDml/nodes/ModelHandler.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pythonCode/med_libs/MEDml/nodes/ModelHandler.py b/pythonCode/med_libs/MEDml/nodes/ModelHandler.py index 85f9370f..8935f2c3 100644 --- a/pythonCode/med_libs/MEDml/nodes/ModelHandler.py +++ b/pythonCode/med_libs/MEDml/nodes/ModelHandler.py @@ -1,3 +1,4 @@ +import ast import copy import json from typing import Union @@ -131,6 +132,7 @@ def __calculate_all_metrics(self, y_true, y_pred, y_pred_proba=None): metrics['MCC'] = round(matthews_corrcoef(y_true, y_pred), 3) except Exception as e: + raise ValueError(f"Error calculating metrics: {e}") print(f"Error calculating metrics: {e}") # Set default values for all metrics default_metrics = ["AUC", "Sensitivity", "Specificity", "PPV", "NPV", "Accuracy", "F1", "MCC"] @@ -145,7 +147,7 @@ def __calculate_overall_metrics(self, fold_metrics): log_metrics = {} if not fold_metrics: - return overall_metrics + return overall_metrics, log_metrics # Get all metric names from first fold first_fold_metrics = list(fold_metrics.values())[0] From db6c0ea657f0219f0c0dbf9c8638a8b64758673f Mon Sep 17 00:00:00 2001 From: MahdiAll99 Date: Wed, 4 Mar 2026 14:40:46 -0500 Subject: [PATCH 04/12] Minor css improvement --- renderer/components/learning/nodesTypes/splitNode.jsx | 2 +- renderer/styles/theme.css | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/renderer/components/learning/nodesTypes/splitNode.jsx b/renderer/components/learning/nodesTypes/splitNode.jsx index e49729bd..c75bb545 100644 --- a/renderer/components/learning/nodesTypes/splitNode.jsx +++ b/renderer/components/learning/nodesTypes/splitNode.jsx @@ -254,7 +254,7 @@ const SplitNode = ({ id, data }) => { key={id} id={id} data={data} - color="#EAD196" + color="#cea037" setupParam={data.setupParam} nodeLink="/documentation/split" defaultSettings={ diff --git a/renderer/styles/theme.css b/renderer/styles/theme.css index f264e17e..2697e456 100644 --- a/renderer/styles/theme.css +++ b/renderer/styles/theme.css @@ -105,7 +105,6 @@ label { .card-header, .p-card-header { - background-color: var(--card-bg) !important; border-bottom-color: var(--border-color) !important; color: var(--text-primary) !important; } From 94bfa28c0f75e8e1b3a6181e21c6254b4429d241 Mon Sep 17 00:00:00 2001 From: MahdiAll99 Date: Thu, 5 Mar 2026 10:18:57 -0500 Subject: [PATCH 05/12] more css fixes --- renderer/styles/flow/reactFlow.css | 1 - renderer/styles/theme.css | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/renderer/styles/flow/reactFlow.css b/renderer/styles/flow/reactFlow.css index e6e474b2..70be7632 100644 --- a/renderer/styles/flow/reactFlow.css +++ b/renderer/styles/flow/reactFlow.css @@ -121,7 +121,6 @@ } .draggable-side-node.p-card { - background: #f3f3f3; color: #495057; box-shadow: 2px 2px 3px -1px rgb(0 0 0 / 20%), diff --git a/renderer/styles/theme.css b/renderer/styles/theme.css index 2697e456..0d6c52da 100644 --- a/renderer/styles/theme.css +++ b/renderer/styles/theme.css @@ -15,7 +15,7 @@ --button-bg: #0d6efd; --button-text: #ffffff; --button-hover: #0b5ed7; - --card-bg: #ffffff; + --card-bg: #f8f9fa; --card-border: #dee2e6; --input-bg: #ffffff; --input-border: #ced4da; From b9bbb1bfbdbdecc5c879c0b57af11f62176af226 Mon Sep 17 00:00:00 2001 From: MahdiAll99 Date: Thu, 5 Mar 2026 10:19:30 -0500 Subject: [PATCH 06/12] Code generation fixes --- pythonCode/med_libs/MEDml/nodes/ModelHandler.py | 6 +++--- pythonCode/med_libs/MEDml/nodes/Split.py | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pythonCode/med_libs/MEDml/nodes/ModelHandler.py b/pythonCode/med_libs/MEDml/nodes/ModelHandler.py index 8935f2c3..b3c23921 100644 --- a/pythonCode/med_libs/MEDml/nodes/ModelHandler.py +++ b/pythonCode/med_libs/MEDml/nodes/ModelHandler.py @@ -393,7 +393,7 @@ def __custom_train_and_evaluate( self.CodeHandler.add_line("code", f"best_model = pycaret_exp.calibrate_model(best_model, {self.CodeHandler.convert_dict_to_params(self.settingsCalibrate)})", indent=0) if self.optimize_threshold: self.CodeHandler.add_line("code", f"# Optimizing model threshold based on {self.threshold_optimization_metric}", indent=0) - self.CodeHandler.add_line("code", f"best_model = pycaret_exp.optimize_threshold(best_model, metric='{self.threshold_optimization_metric}')", indent=0) + self.CodeHandler.add_line("code", f"best_model = pycaret_exp.optimize_threshold(best_model, optimize='{self.threshold_optimization_metric}')", indent=0) # Finalize the model if finalize: @@ -541,7 +541,7 @@ def __handle_splitted_data(self, experiment: dict, settings: dict, **kwargs) -> ) self.CodeHandler.add_line( "code", - f"trained_models = [pycaret_exp.optimize_threshold(trained_models[0], metric='{self.threshold_optimization_metric}')]" + f"trained_models = [pycaret_exp.optimize_threshold(trained_models[0], optimize='{self.threshold_optimization_metric}')]" ) #trained_model = pycaret_exp.optimize_threshold(trained_model, optimize=self.threshold_optimization_metric) @@ -697,7 +697,7 @@ def _execute(self, experiment: dict = None, **kwargs) -> json: if self.optimize_threshold: trained_models = [experiment['pycaret_exp'].optimize_threshold(trained_models[0], optimize=self.threshold_optimization_metric)] - self.CodeHandler.add_line("code", f"trained_models = [pycaret_exp.optimize_threshold(trained_models[0], metric='{self.threshold_optimization_metric}')]") + self.CodeHandler.add_line("code", f"trained_models = [pycaret_exp.optimize_threshold(trained_models[0], optimize='{self.threshold_optimization_metric}')]") if finalize: trained_models = [experiment['pycaret_exp'].finalize_model(model) for model in trained_models] diff --git a/pythonCode/med_libs/MEDml/nodes/Split.py b/pythonCode/med_libs/MEDml/nodes/Split.py index 85ff9972..27efc7d0 100644 --- a/pythonCode/med_libs/MEDml/nodes/Split.py +++ b/pythonCode/med_libs/MEDml/nodes/Split.py @@ -269,7 +269,7 @@ def _execute(self, experiment: dict = None, **kwargs) -> json: splitter = StratifiedKFold(n_splits=cv_folds, shuffle=True, random_state=random_state) self.CodeHandler.add_line("code", f"splitter = StratifiedKFold(n_splits={cv_folds}, shuffle=True, random_state={random_state})") fold_iter = splitter.split(np.zeros(n_samples), y) - self.CodeHandler.add_line("code", f"fold_iter = splitter.split(np.zeros({n_samples}), y)") + self.CodeHandler.add_line("code", f"fold_iter = splitter.split(np.zeros(len(dataset)), y)") else: splitter = KFold(n_splits=cv_folds, shuffle=True, random_state=random_state) self.CodeHandler.add_line("code", f"splitter = KFold(n_splits={cv_folds}, shuffle=True, random_state={random_state})") From aca26f1dc0dcf68e1f7dac049d4a48ddd2a90605 Mon Sep 17 00:00:00 2001 From: MahdiAll99 Date: Thu, 5 Mar 2026 10:36:13 -0500 Subject: [PATCH 07/12] Model finalization issue fixed when optim thresh is activated --- pythonCode/med_libs/MEDml/nodes/ModelIO.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/pythonCode/med_libs/MEDml/nodes/ModelIO.py b/pythonCode/med_libs/MEDml/nodes/ModelIO.py index 97e2b6d6..453c51a0 100644 --- a/pythonCode/med_libs/MEDml/nodes/ModelIO.py +++ b/pythonCode/med_libs/MEDml/nodes/ModelIO.py @@ -58,7 +58,12 @@ def _execute(self, experiment: dict = None, **kwargs) -> json: if dir(fitted_model).__contains__('feature_names_in_'): model_features = fitted_model.__getattribute__('feature_names_in_') elif dir(fitted_model).__contains__('feature_name_') and model_features is None: - model_features = fitted_model.__getattribute__('feature_name_') + model_features = fitted_model.__getattribute__('feature_names_in_') + elif dir(fitted_model).__contains__('classifier_') and dir(fitted_model.classifier_).__contains__('feature_names_in_'): + model_features = fitted_model.classifier_.feature_names_in_ + else: + raise ValueError(f"Model with type {type(fitted_model)} does not have retrievable feature names.") + model_features = list(model_features) # Model's name From cee4ab242d7771fd127de650fe9dab9ea43824b6 Mon Sep 17 00:00:00 2001 From: MahdiAll99 Date: Thu, 5 Mar 2026 10:36:51 -0500 Subject: [PATCH 08/12] Pycaret upgrade --- .../utils/settings_generator/requirements.txt | Bin 4252 -> 4210 bytes pythonEnv/merged_requirements.txt | 2 +- pythonEnv/requirements.txt | 3 +-- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/pythonCode/med_libs/MEDml/utils/settings_generator/requirements.txt b/pythonCode/med_libs/MEDml/utils/settings_generator/requirements.txt index 7c59e7bf04e50a6ba40c509cb978f19309265441..34cd9faef706af867a83b77096a7fa4ca43c9383 100644 GIT binary patch delta 23 ecmbQE_(@@d2p6j{gC2v?W=Sq%rp;wMYAgUvp#`7- delta 51 zcmeyQFh_BN2p6j%gC2vyW=Sq%Ch;7GRE9)`B8EH$TOb5U7=iF)K_21FK0InH03MtP A$p8QV diff --git a/pythonEnv/merged_requirements.txt b/pythonEnv/merged_requirements.txt index c86792a6..85c8ed8b 100644 --- a/pythonEnv/merged_requirements.txt +++ b/pythonEnv/merged_requirements.txt @@ -19,7 +19,7 @@ numpy==1.22.4 numpyencoder==0.3.0 pandas==1.4.4 plotly==5.14.1 -pycaret==3.1.0 +pycaret==3.3.2 pydicom==1.2.2 pymongo==4.7.3 pyunpack==0.3 diff --git a/pythonEnv/requirements.txt b/pythonEnv/requirements.txt index fc3cc7af..e86f8a8b 100644 --- a/pythonEnv/requirements.txt +++ b/pythonEnv/requirements.txt @@ -202,7 +202,7 @@ psutil==5.9.4 ptyprocess==0.7.0 pure-eval==0.2.2 pyarrow==10.0.1 -pycaret==3.1.0 +pycaret==3.3.2 pycparser==2.21 pydantic==2.4.2 pydantic_core==2.10.1 @@ -243,7 +243,6 @@ safetensors==0.4.0 schemdraw==0.15 scikit-base==0.5.2 scikit-image==0.19.3 -scikit-learn==1.2.0 scikit-plot==0.3.7 scipy==1.10.1 seaborn==0.12.2 From 33e4bdd57df5fa7737c2b7d39d83a4c7f3935404 Mon Sep 17 00:00:00 2001 From: MahdiAll99 Date: Fri, 6 Mar 2026 16:43:25 -0500 Subject: [PATCH 09/12] fixed bug when empty dict is present in params --- .../learning/results/utilities/parameters.jsx | 42 +++++++++++++++---- 1 file changed, 34 insertions(+), 8 deletions(-) diff --git a/renderer/components/learning/results/utilities/parameters.jsx b/renderer/components/learning/results/utilities/parameters.jsx index b84c65ab..7d99d51f 100644 --- a/renderer/components/learning/results/utilities/parameters.jsx +++ b/renderer/components/learning/results/utilities/parameters.jsx @@ -15,19 +15,45 @@ import { Column } from "primereact/column" const Parameters = ({ params, tableProps, columnNames }) => { const [data, setData] = useState([]) const [selectedRows, setSelectedRows] = useState([]) + + const isEmptyOrNull = (value) => { + // Check specifically for null or undefined + if (value == null) { // Using loose equality (==) checks for both null and undefined + return true + } + + // Check if the value is an object (but not null, which typeof also calls "object") + if (typeof value === 'object') { + // A robust check for an empty object: ensure its constructor is Object and it has no own properties + return Object.keys(value).length === 0 && value.constructor === Object + } + + // Other non-object, non-null values (like strings, numbers, booleans) + // are not considered "empty objects" or "null" by this definition. + return false + } + useEffect(() => { if (params) { let dataList = [] Object.keys(params).forEach((key) => { - let value = params[key] - // For array values - if (Array.isArray(value)) { - value = JSON.stringify(value) + // skip null or undefined values + if (isEmptyOrNull(params[key])) { + dataList.push({ + param: key, + Value: "null" + }) + } else { + let value = params[key] + // For array values + if (Array.isArray(value)) { + value = JSON.stringify(value) + } + dataList.push({ + param: key, + Value: value != null ? value : "null" + }) } - dataList.push({ - param: key, - Value: value != null ? value : "null" - }) }) setData(dataList) } From 315f3a7915625cc784d9c4bc55423bfb698ccff3 Mon Sep 17 00:00:00 2001 From: MahdiAll99 Date: Sun, 8 Mar 2026 14:07:55 -0400 Subject: [PATCH 10/12] fixed missing cols bug --- renderer/components/mainPages/application.jsx | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/renderer/components/mainPages/application.jsx b/renderer/components/mainPages/application.jsx index 46f881db..55d746f0 100644 --- a/renderer/components/mainPages/application.jsx +++ b/renderer/components/mainPages/application.jsx @@ -358,9 +358,8 @@ const ApplicationPage = ({ pageId }) => { * @param {Array} columnsArray An array of the columns of the dataset */ const checkWarnings = (columnsArray) => { - let datasetColsString = JSON.stringify(columnsArray) - let modelColsString = JSON.stringify(modelFeatures) - if (datasetColsString !== modelColsString && modelFeatures && columnsArray) { + if (!modelFeatures.every((col) => columnsArray.includes(col)) && modelFeatures && columnsArray) { + const missingCols = modelFeatures.filter(col => !columnsArray.includes(col)) setDatasetHasWarning({ state: true, tooltip: ( @@ -371,17 +370,9 @@ const ApplicationPage = ({ pageId }) => {
-

Needed columns:

+

Missing columns:

    - {modelFeatures.sort().map((col) => { - return
  • {col}
  • - })} -
- - -

Received columns:

-
    - {columnsArray.sort().map((col) => { + {missingCols.map((col) => { return
  • {col}
  • })}
From 3f97cb306bd1aa2c54a58d89f1024763da1c1c3c Mon Sep 17 00:00:00 2001 From: MahdiAll99 Date: Sun, 8 Mar 2026 15:36:46 -0400 Subject: [PATCH 11/12] reversed pycaret version change (avoid risk for POC1) --- .../utils/settings_generator/requirements.txt | Bin 4210 -> 4210 bytes pythonEnv/merged_requirements.txt | 2 +- pythonEnv/requirements.txt | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pythonCode/med_libs/MEDml/utils/settings_generator/requirements.txt b/pythonCode/med_libs/MEDml/utils/settings_generator/requirements.txt index 34cd9faef706af867a83b77096a7fa4ca43c9383..d34e01d57568e0c0946629d32151a70e94af47f1 100644 GIT binary patch delta 18 ZcmeyQ@JV5V2p6j%gC2vyW=XC{HUK!h1iSzM delta 18 ZcmeyQ@JV5V2p6j{gC2v?W=XC{HUK!>1i%0Q diff --git a/pythonEnv/merged_requirements.txt b/pythonEnv/merged_requirements.txt index 85c8ed8b..c86792a6 100644 --- a/pythonEnv/merged_requirements.txt +++ b/pythonEnv/merged_requirements.txt @@ -19,7 +19,7 @@ numpy==1.22.4 numpyencoder==0.3.0 pandas==1.4.4 plotly==5.14.1 -pycaret==3.3.2 +pycaret==3.1.0 pydicom==1.2.2 pymongo==4.7.3 pyunpack==0.3 diff --git a/pythonEnv/requirements.txt b/pythonEnv/requirements.txt index e86f8a8b..af2c490a 100644 --- a/pythonEnv/requirements.txt +++ b/pythonEnv/requirements.txt @@ -202,7 +202,7 @@ psutil==5.9.4 ptyprocess==0.7.0 pure-eval==0.2.2 pyarrow==10.0.1 -pycaret==3.3.2 +pycaret==3.1.0 pycparser==2.21 pydantic==2.4.2 pydantic_core==2.10.1 From 5eaa7310ccc959ec7de33999087339aeef19ee59 Mon Sep 17 00:00:00 2001 From: MahdiAll99 Date: Mon, 9 Mar 2026 10:34:23 -0400 Subject: [PATCH 12/12] fixed macOS issues in superset env and superset service kill --- .../modules/superset/SupersetEnvManager.py | 16 +++++++++++++++- .../mainPages/superset/SupersetFrame.jsx | 2 +- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/pythonCode/modules/superset/SupersetEnvManager.py b/pythonCode/modules/superset/SupersetEnvManager.py index d3cdc85f..31c693a7 100644 --- a/pythonCode/modules/superset/SupersetEnvManager.py +++ b/pythonCode/modules/superset/SupersetEnvManager.py @@ -41,7 +41,21 @@ def _get_build_env(self): """ env = os.environ.copy() - if sys.platform != "win32": + if sys.platform == "darwin": + # Force the compiler to use the system SDK and headers + cc = shutil.which("clang") or shutil.which("gcc") + cxx = shutil.which("clang++") or shutil.which("g++") + if cc: + env["CC"] = cc + if cxx: + env["CXX"] = cxx + + # Critical for 'cryptography' and 'python-geohash' compilation + env["LDFLAGS"] = "-L/usr/local/opt/openssl/lib -L/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib" + env["CPPFLAGS"] = "-I/usr/local/opt/openssl/include -I/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include" + # Prevents error: 'implicit declaration of function' during geohash build + env["CFLAGS"] = "-Wno-error=implicit-function-declaration" + elif sys.platform != "win32": cc = shutil.which("gcc") or shutil.which("cc") cxx = shutil.which("g++") or shutil.which("c++") if cc: diff --git a/renderer/components/mainPages/superset/SupersetFrame.jsx b/renderer/components/mainPages/superset/SupersetFrame.jsx index 5dace1e0..fcafff8c 100644 --- a/renderer/components/mainPages/superset/SupersetFrame.jsx +++ b/renderer/components/mainPages/superset/SupersetFrame.jsx @@ -299,7 +299,7 @@ const SupersetDashboard = () => { }) } else if (system === "darwin") { // macOS - exec(`pkill -f superset`, (err, stdout, stderr) => { + exec(`/usr/bin/pkill -f superset`, (err, stdout, stderr) => { if (err) { console.error(err) toast.error("Error killing Superset", {autoClose: 5000})