diff --git a/foqus_lib/framework/sdoe/plot_utils.py b/foqus_lib/framework/sdoe/plot_utils.py index 25eed71bc..0cb7a5fa0 100644 --- a/foqus_lib/framework/sdoe/plot_utils.py +++ b/foqus_lib/framework/sdoe/plot_utils.py @@ -150,15 +150,17 @@ def load_data(fname, hname): def remove_xticklabels(ax): - labels = [item.get_text() for item in ax.get_xticklabels()] - no_labels = [""] * len(labels) + ticks_loc = ax.get_xticks().tolist() + no_labels = [""] * len(ticks_loc) + ax.set_xticks(ticks_loc) ax.set_xticklabels(no_labels) return ax def remove_yticklabels(ax): - labels = [item.get_text() for item in ax.get_yticklabels()] - no_labels = [""] * len(labels) + ticks_loc = ax.get_yticks().tolist() + no_labels = [""] * len(ticks_loc) + ax.set_yticks(ticks_loc) ax.set_yticklabels(no_labels) return ax @@ -435,7 +437,7 @@ def plot( else: cand = None wcol = None - _fig1 = plot_candidates( + fig1 = plot_candidates( df, hf, show, title, scatter_label, cand, wcol=wcol, nImpPts=nImpPts ) if nusf: @@ -451,9 +453,10 @@ def plot( cand_ = scale_y(scale_method, mwr, cand_np, idw_np) wts = cand_[:, idw_np] # scaled weights from all candidates title = "SDOE (NUSF) Weight Visualization for MWR={}".format(mwr) - _fig2 = plot_weights(xs, wt, wts, title) - - plt.show() + fig2 = plot_weights(xs, wt, wts, title) + return fig1, fig2 + else: + return fig1 def plot_pareto(pf, results, cand, hname): # Plot Pareto front with hovering labels @@ -524,4 +527,4 @@ def onpick(event): # Define nested function onpick fig.canvas.manager.set_window_title("Pareto Front") fig.canvas.mpl_connect("pick_event", onpick) - plt.show() + return fig diff --git a/foqus_lib/framework/sdoe/test/results_irsf.json b/foqus_lib/framework/sdoe/test/results_irsf.json new file mode 100644 index 000000000..e7ddf5933 --- /dev/null +++ b/foqus_lib/framework/sdoe/test/results_irsf.json @@ -0,0 +1 @@ +{"pareto_front": {"Design": {"0": 1, "1": 2, "2": 3, "3": 4, "4": 5, "5": 6, "6": 7, "7": 8, "8": 9, "9": 10, "10": 11, "11": 12, "12": 13, "13": 14, "14": 15, "15": 16, "16": 17, "17": 18, "18": 19, "19": 20, "20": 21, "21": 22, "22": 23, "23": 24, "24": 25, "25": 26, "26": 27, "27": 28, "28": 29, "29": 30, "30": 31, "31": 32, "32": 33, "33": 34, "34": 35, "35": 36, "36": 37, "37": 38, "38": 39, "39": 40, "40": 41, "41": 42, "42": 43, "43": 44, "44": 45, "45": 46, "46": 47, "47": 48, "48": 49, "49": 50, "50": 51, "51": 52, "52": 53, "53": 54, "54": 55, "55": 56, "56": 57, "57": 58, "58": 59, "59": 60}, "Best Input": {"0": 0.7071067811865476, "1": 0.7433034373659253, "2": 0.7778174593052023, "3": 0.7810249675906654, "4": 0.8139410298049854, "5": 0.8200609733428363, "6": 0.848528137423857, "7": 0.8514693182963201, "8": 0.8602325267042626, "9": 0.8845903006477066, "10": 0.8902246907382427, "11": 0.9013878188659973, "12": 0.9192388155425119, "13": 0.9219544457292886, "14": 0.9300537618869137, "15": 0.95524865872714, "16": 0.9604686356149273, "17": 0.97082439194738, "18": 0.9899494936611665, "19": 0.9924716620639604, "20": 1.0, "21": 1.0124228365658292, "22": 1.0259142264341596, "23": 1.0307764064044151, "24": 1.0404326023342405, "25": 1.0606601717798212, "26": 1.063014581273465, "27": 1.0700467279516348, "28": 1.0735455276791943, "29": 1.0816653826391966, "30": 1.0965856099730655, "31": 1.101135777277262, "32": 1.110180165558726, "33": 1.118033988749895, "34": 1.1236102527122116, "35": 1.1313708498984762, "36": 1.1335784048754634, "37": 1.140175425099138, "38": 1.1412712210513327, "39": 1.1510864433221337, "40": 1.1672617529928753, "41": 1.1715374513859982, "42": 1.1800423721205946, "43": 1.1926860441876563, "44": 1.2020815280171306, "45": 1.2041594578792296, "46": 1.2103718436910205, "47": 1.2206555615733703, "48": 1.2379418403139948, "49": 1.241974234837422, "50": 1.25, "51": 1.2727922061357855, "52": 1.2747548783981961, "53": 1.2806248474865698, "54": 1.3086252328302401, "55": 1.3124404748406686, "56": 1.3435028842544403, "57": 1.3453624047073711, "58": 1.379311422413372, "59": 1.4142135623730951}, "Best Response": {"0": 1.0, "1": 0.9965, "2": 0.99, "3": 0.986, "4": 0.9765, "5": 0.9685, "6": 0.96, "7": 0.956, "8": 0.944, "9": 0.9365, "10": 0.9285, "11": 0.9125, "12": 0.91, "13": 0.906, "14": 0.894, "15": 0.8765, "16": 0.8685, "17": 0.8525, "18": 0.84, "19": 0.836, "20": 0.824, "21": 0.804, "22": 0.7965, "23": 0.7885, "24": 0.7725, "25": 0.75, "26": 0.746, "27": 0.734, "28": 0.7165, "29": 0.714, "30": 0.6965, "31": 0.6885, "32": 0.6725, "33": 0.65, "34": 0.6485, "35": 0.64, "36": 0.636, "37": 0.624, "38": 0.6165, "39": 0.604, "40": 0.5765, "41": 0.5685, "42": 0.5525, "43": 0.5285, "44": 0.51, "45": 0.506, "46": 0.494, "47": 0.474, "48": 0.4365, "49": 0.4285, "50": 0.4125, "51": 0.36, "52": 0.356, "53": 0.344, "54": 0.2765, "55": 0.2685, "56": 0.19, "57": 0.186, "58": 0.0965, "59": 0.0}}, "design_id": {"1": 1, "2": 2, "3": 3, "4": 4, "5": 5, "6": 6, "7": 7, "8": 8, "9": 9, "10": 10, "11": 11, "12": 12, "13": 13, "14": 14, "15": 15, "16": 16, "17": 17, "18": 18, "19": 19, "20": 20, "21": 21, "22": 22, "23": 23, "24": 24, "25": 25, "26": 26, "27": 27, "28": 28, "29": 29, "30": 30, "31": 31, "32": 32, "33": 33, "34": 34, "35": 35, "36": 36, "37": 37, "38": 38, "39": 39, "40": 40, "41": 41, "42": 42, "43": 43, "44": 44, "45": 45, "46": 46, "47": 47, "48": 48, "49": 49, "50": 50, "51": 51, "52": 52, "53": 53, "54": 54, "55": 55, "56": 56, "57": 57, "58": 58, "59": 59, "60": 60}, "des": {"1": {"V1": {"0": 0.5, "1": 1.0}, "V2": {"0": 0.5, "1": 1.0}, "Y": {"0": 1.0, "1": 0.0}}, "2": {"V1": {"0": 0.45, "1": 1.0}, "V2": {"0": 0.5, "1": 1.0}, "Y": {"0": 0.9965, "1": 0.0}}, "3": {"V1": {"0": 0.45, "1": 1.0}, "V2": {"0": 0.45, "1": 1.0}, "Y": {"0": 0.99, "1": 0.0}}, "4": {"V1": {"0": 0.4, "1": 1.0}, "V2": {"0": 0.5, "1": 1.0}, "Y": {"0": 0.986, "1": 0.0}}, "5": {"V1": {"0": 0.4, "1": 1.0}, "V2": {"0": 0.45, "1": 1.0}, "Y": {"0": 0.9765, "1": 0.0}}, "6": {"V1": {"0": 0.35, "1": 1.0}, "V2": {"0": 0.5, "1": 1.0}, "Y": {"0": 0.9685, "1": 0.0}}, "7": {"V1": {"0": 0.4, "1": 1.0}, "V2": {"0": 0.4, "1": 1.0}, "Y": {"0": 0.96, "1": 0.0}}, "8": {"V1": {"0": 0.35, "1": 1.0}, "V2": {"0": 0.45, "1": 1.0}, "Y": {"0": 0.956, "1": 0.0}}, "9": {"V1": {"0": 0.3, "1": 1.0}, "V2": {"0": 0.5, "1": 1.0}, "Y": {"0": 0.944, "1": 0.0}}, "10": {"V1": {"0": 0.35, "1": 1.0}, "V2": {"0": 0.4, "1": 1.0}, "Y": {"0": 0.9365, "1": 0.0}}, "11": {"V1": {"0": 0.3, "1": 1.0}, "V2": {"0": 0.45, "1": 1.0}, "Y": {"0": 0.9285, "1": 0.0}}, "12": {"V1": {"0": 0.25, "1": 1.0}, "V2": {"0": 0.5, "1": 1.0}, "Y": {"0": 0.9125, "1": 0.0}}, "13": {"V1": {"0": 0.35, "1": 1.0}, "V2": {"0": 0.35, "1": 1.0}, "Y": {"0": 0.91, "1": 0.0}}, "14": {"V1": {"0": 0.3, "1": 1.0}, "V2": {"0": 0.4, "1": 1.0}, "Y": {"0": 0.906, "1": 0.0}}, "15": {"V1": {"0": 0.25, "1": 1.0}, "V2": {"0": 0.45, "1": 1.0}, "Y": {"0": 0.894, "1": 0.0}}, "16": {"V1": {"0": 0.3, "1": 1.0}, "V2": {"0": 0.35, "1": 1.0}, "Y": {"0": 0.8765, "1": 0.0}}, "17": {"V1": {"0": 0.25, "1": 1.0}, "V2": {"0": 0.4, "1": 1.0}, "Y": {"0": 0.8685, "1": 0.0}}, "18": {"V1": {"0": 0.2, "1": 1.0}, "V2": {"0": 0.45, "1": 1.0}, "Y": {"0": 0.8525, "1": 0.0}}, "19": {"V1": {"0": 0.3, "1": 1.0}, "V2": {"0": 0.3, "1": 1.0}, "Y": {"0": 0.84, "1": 0.0}}, "20": {"V1": {"0": 0.25, "1": 1.0}, "V2": {"0": 0.35, "1": 1.0}, "Y": {"0": 0.836, "1": 0.0}}, "21": {"V1": {"0": 0.2, "1": 1.0}, "V2": {"0": 0.4, "1": 1.0}, "Y": {"0": 0.824, "1": 0.0}}, "22": {"V1": {"0": 0.15, "1": 1.0}, "V2": {"0": 0.45, "1": 1.0}, "Y": {"0": 0.804, "1": 0.0}}, "23": {"V1": {"0": 0.25, "1": 1.0}, "V2": {"0": 0.3, "1": 1.0}, "Y": {"0": 0.7965, "1": 0.0}}, "24": {"V1": {"0": 0.2, "1": 1.0}, "V2": {"0": 0.35, "1": 1.0}, "Y": {"0": 0.7885, "1": 0.0}}, "25": {"V1": {"0": 0.15, "1": 1.0}, "V2": {"0": 0.4, "1": 1.0}, "Y": {"0": 0.7725, "1": 0.0}}, "26": {"V1": {"0": 0.25, "1": 1.0}, "V2": {"0": 0.25, "1": 1.0}, "Y": {"0": 0.75, "1": 0.0}}, "27": {"V1": {"0": 0.2, "1": 1.0}, "V2": {"0": 0.3, "1": 1.0}, "Y": {"0": 0.746, "1": 0.0}}, "28": {"V1": {"0": 0.15, "1": 1.0}, "V2": {"0": 0.35, "1": 1.0}, "Y": {"0": 0.734, "1": 0.0}}, "29": {"V1": {"0": 0.05, "1": 1.0}, "V2": {"0": 0.5, "1": 1.0}, "Y": {"0": 0.7165, "1": 0.0}}, "30": {"V1": {"0": 0.1, "1": 1.0}, "V2": {"0": 0.4, "1": 1.0}, "Y": {"0": 0.714, "1": 0.0}}, "31": {"V1": {"0": 0.2, "1": 1.0}, "V2": {"0": 0.25, "1": 1.0}, "Y": {"0": 0.6965, "1": 0.0}}, "32": {"V1": {"0": 0.15, "1": 1.0}, "V2": {"0": 0.3, "1": 1.0}, "Y": {"0": 0.6885, "1": 0.0}}, "33": {"V1": {"0": 0.1, "1": 1.0}, "V2": {"0": 0.35, "1": 1.0}, "Y": {"0": 0.6725, "1": 0.0}}, "34": {"V1": {"0": 0.0, "1": 1.0}, "V2": {"0": 0.5, "1": 1.0}, "Y": {"0": 0.65, "1": 0.0}}, "35": {"V1": {"0": 0.05, "1": 1.0}, "V2": {"0": 0.4, "1": 1.0}, "Y": {"0": 0.6485, "1": 0.0}}, "36": {"V1": {"0": 0.2, "1": 1.0}, "V2": {"0": 0.2, "1": 1.0}, "Y": {"0": 0.64, "1": 0.0}}, "37": {"V1": {"0": 0.15, "1": 1.0}, "V2": {"0": 0.25, "1": 1.0}, "Y": {"0": 0.636, "1": 0.0}}, "38": {"V1": {"0": 0.1, "1": 1.0}, "V2": {"0": 0.3, "1": 1.0}, "Y": {"0": 0.624, "1": 0.0}}, "39": {"V1": {"0": 0.0, "1": 1.0}, "V2": {"0": 0.45, "1": 1.0}, "Y": {"0": 0.6165, "1": 0.0}}, "40": {"V1": {"0": 0.05, "1": 1.0}, "V2": {"0": 0.35, "1": 1.0}, "Y": {"0": 0.604, "1": 0.0}}, "41": {"V1": {"0": 0.15, "1": 1.0}, "V2": {"0": 0.2, "1": 1.0}, "Y": {"0": 0.5765, "1": 0.0}}, "42": {"V1": {"0": 0.1, "1": 1.0}, "V2": {"0": 0.25, "1": 1.0}, "Y": {"0": 0.5685, "1": 0.0}}, "43": {"V1": {"0": 0.05, "1": 1.0}, "V2": {"0": 0.3, "1": 1.0}, "Y": {"0": 0.5525, "1": 0.0}}, "44": {"V1": {"0": 0.0, "1": 1.0}, "V2": {"0": 0.35, "1": 1.0}, "Y": {"0": 0.5285, "1": 0.0}}, "45": {"V1": {"0": 0.15, "1": 1.0}, "V2": {"0": 0.15, "1": 1.0}, "Y": {"0": 0.51, "1": 0.0}}, "46": {"V1": {"0": 0.1, "1": 1.0}, "V2": {"0": 0.2, "1": 1.0}, "Y": {"0": 0.506, "1": 0.0}}, "47": {"V1": {"0": 0.05, "1": 1.0}, "V2": {"0": 0.25, "1": 1.0}, "Y": {"0": 0.494, "1": 0.0}}, "48": {"V1": {"0": 0.0, "1": 1.0}, "V2": {"0": 0.3, "1": 1.0}, "Y": {"0": 0.474, "1": 0.0}}, "49": {"V1": {"0": 0.1, "1": 1.0}, "V2": {"0": 0.15, "1": 1.0}, "Y": {"0": 0.4365, "1": 0.0}}, "50": {"V1": {"0": 0.05, "1": 1.0}, "V2": {"0": 0.2, "1": 1.0}, "Y": {"0": 0.4285, "1": 0.0}}, "51": {"V1": {"0": 0.0, "1": 1.0}, "V2": {"0": 0.25, "1": 1.0}, "Y": {"0": 0.4125, "1": 0.0}}, "52": {"V1": {"0": 0.1, "1": 1.0}, "V2": {"0": 0.1, "1": 1.0}, "Y": {"0": 0.36, "1": 0.0}}, "53": {"V1": {"0": 0.05, "1": 1.0}, "V2": {"0": 0.15, "1": 1.0}, "Y": {"0": 0.356, "1": 0.0}}, "54": {"V1": {"0": 0.0, "1": 1.0}, "V2": {"0": 0.2, "1": 1.0}, "Y": {"0": 0.344, "1": 0.0}}, "55": {"V1": {"0": 0.05, "1": 1.0}, "V2": {"0": 0.1, "1": 1.0}, "Y": {"0": 0.2765, "1": 0.0}}, "56": {"V1": {"0": 0.0, "1": 1.0}, "V2": {"0": 0.15, "1": 1.0}, "Y": {"0": 0.2685, "1": 0.0}}, "57": {"V1": {"0": 0.05, "1": 1.0}, "V2": {"0": 0.05, "1": 1.0}, "Y": {"0": 0.19, "1": 0.0}}, "58": {"V1": {"0": 0.0, "1": 1.0}, "V2": {"0": 0.1, "1": 1.0}, "Y": {"0": 0.186, "1": 0.0}}, "59": {"V1": {"0": 0.0, "1": 1.0}, "V2": {"0": 0.05, "1": 1.0}, "Y": {"0": 0.0965, "1": 0.0}}, "60": {"V1": {"0": 0.0, "1": 1.0}, "V2": {"0": 0.0, "1": 1.0}, "Y": {"0": 0.0, "1": 0.0}}}, "mode": "maximin", "design_size": 2, "num_restarts": 5, "num_designs": 60} \ No newline at end of file diff --git a/foqus_lib/framework/sdoe/test/results_nusf.json b/foqus_lib/framework/sdoe/test/results_nusf.json new file mode 100644 index 000000000..d66388e7a --- /dev/null +++ b/foqus_lib/framework/sdoe/test/results_nusf.json @@ -0,0 +1 @@ +{"best_cand_scaled": {"Run": {"357": 358.0, "293": 1.0}, "L": {"357": 0.6893091915580671, "293": 0.019259600968746397}, "G": {"357": 1.0, "293": 0.0}, "w": {"357": 0.0, "293": 1.0}, "lldg": {"357": 1.0, "293": 1.0}, "CI Width Prior": {"357": 5.0, "293": 3.44149502933341}}, "best_cand": {"Run": {"357": 358.0, "293": 294.0}, "L": {"357": 8981.0, "293": 3066.0}, "G": {"357": 2750.0, "293": 2750.0}, "w": {"357": 0.125, "293": 0.175}, "lldg": {"357": 0.3, "293": 0.1}, "CI Width Prior": {"357": 9.298917081, "293": 6.309039504}}, "best_index": [357, 293], "best_val": 42.140529389626565, "best_mdpts": [0, 1], "best_mties": 1, "best_dmat": [[9999.0, 42.140529389626565], [42.140529389626565, 9999.0]], "mode": "maximin", "design_size": 2, "num_restarts": 10, "mwr": 5, "elapsed_time": 69.98497295379639} \ No newline at end of file diff --git a/foqus_lib/framework/sdoe/test/test_plot_utils.py b/foqus_lib/framework/sdoe/test/test_plot_utils.py index ec1c2516e..c3609c003 100644 --- a/foqus_lib/framework/sdoe/test/test_plot_utils.py +++ b/foqus_lib/framework/sdoe/test/test_plot_utils.py @@ -12,11 +12,15 @@ # respectively. This file is also available online at the URL # "https://github.com/CCSI-Toolset/FOQUS". ################################################################################# +import matplotlib.pyplot as plt +import pandas as pd import pytest -from foqus_lib.framework.sdoe import plot_utils +from foqus_lib.framework.sdoe import sdoe, nusf, plot_utils, df_utils from unittest import mock from importlib import resources from pathlib import Path +import configparser +import json @mock.patch("foqus_lib.framework.sdoe.plot_utils.plt") @@ -29,9 +33,76 @@ def test_plot(fake_plt: mock.MagicMock): copy_from_package(fname) scatter_label = "something" - plot_utils.plot(fname=fname, scatter_label=scatter_label) + fig = plot_utils.plot(fname=fname, scatter_label=scatter_label) - assert fake_plt.show.call_count > 0 + assert fig is not None + + +@mock.patch("foqus_lib.framework.sdoe.plot_utils.plt") +def test_plot_weights(fake_plt: mock.MagicMock): + + fake_fig = mock.MagicMock() + fake_ax1 = mock.MagicMock() + fake_ax2 = mock.MagicMock() + fake_plt.subplots.return_value = (fake_fig, (fake_ax1, fake_ax2)) + + config_file = "config_nusf.ini" + copy_from_package(config_file) + + cand_file = "candidates_nusf.csv" + copy_from_package(cand_file) + cand = df_utils.load(cand_file) + + results_file = "results_nusf.json" + copy_from_package(results_file) + with open(results_file) as file: + results_dict = json.load(file) + + config = configparser.ConfigParser(allow_no_value=True) + config.read(config_file) + scale_method = config["SF"]["scale_method"] + include = [s.strip() for s in config["INPUT"]["include"].split(",")] + types = [s.strip() for s in config["INPUT"]["types"].split(",")] + + i = types.index("Weight") + wcol = include[i] # weight column name + + des = pd.DataFrame.from_dict(results_dict["best_cand_scaled"]).values + xs = des[:, :-1] # scaled coordinates from best candidate + wt = des[:, -1] # scaled weights from best candidate + + idw_np = cand.columns.get_loc(wcol) + cand_np = cand.to_numpy() + mwr = results_dict["mwr"] + cand_ = nusf.scale_y(scale_method, mwr, cand_np, idw_np) + wts = cand_[:, idw_np] # scaled weights from all candidates + title = "SDOE (NUSF) Weight Visualization for MWR={}".format(mwr) + fig = plot_utils.plot_weights(xs, wt, wts, title) + + assert fig is not None + + +@mock.patch("foqus_lib.framework.sdoe.plot_utils.plt") +def test_plot_pareto(fake_plt: mock.MagicMock): + + fake_fig = mock.MagicMock() + fake_axes = mock.MagicMock() + fake_plt.subplots.return_value = (fake_fig, fake_axes) + + cand_file = "candidates_irsf.csv" + copy_from_package(cand_file) + cand = df_utils.load(cand_file) + + results_file = "results_irsf.json" + copy_from_package(results_file) + with open(results_file) as file: + results_dict = json.load(file) + + pf = pd.DataFrame.from_dict(results_dict["pareto_front"]) + + fig = plot_utils.plot_pareto(pf, results_dict, cand, None) + + assert fig is not None def copy_from_package(file_name: str) -> None: diff --git a/foqus_lib/gui/sdoe/sdoeAnalysisDialog.py b/foqus_lib/gui/sdoe/sdoeAnalysisDialog.py index a772d45b7..b07c942a2 100644 --- a/foqus_lib/gui/sdoe/sdoeAnalysisDialog.py +++ b/foqus_lib/gui/sdoe/sdoeAnalysisDialog.py @@ -20,7 +20,7 @@ from foqus_lib.framework.sdoe.df_utils import load from foqus_lib.framework.sdoe.plot_utils import plot_pareto from .sdoeSetupFrame import * -from .sdoePreview import sdoePreview +from .sdoePreview import sdoePreview, Window from PyQt5 import uic from PyQt5.QtCore import Qt @@ -1301,7 +1301,11 @@ def editSdoe(self): results = self.analysis[row].results cand = load(cfile) irsf = {"cand": cand} - plot_pareto(pf, results, irsf["cand"], hname) + fig = plot_pareto(pf, results, irsf["cand"], hname) + dialog = Window(fig, None, self) + title = "SDoE (IRSF) Pareto Front" + dialog.setWindowTitle(title) + dialog.show() return fullName = self.analysis[row].fnames["cand"] diff --git a/foqus_lib/gui/sdoe/sdoeAnalysisDialog_UI.ui b/foqus_lib/gui/sdoe/sdoeAnalysisDialog_UI.ui index 33e13f0b4..f16088f90 100755 --- a/foqus_lib/gui/sdoe/sdoeAnalysisDialog_UI.ui +++ b/foqus_lib/gui/sdoe/sdoeAnalysisDialog_UI.ui @@ -10,7 +10,7 @@ 0 0 1440 - 1027 + 993 diff --git a/foqus_lib/gui/sdoe/sdoePreview.py b/foqus_lib/gui/sdoe/sdoePreview.py index 66839f950..b09fa1a0f 100644 --- a/foqus_lib/gui/sdoe/sdoePreview.py +++ b/foqus_lib/gui/sdoe/sdoePreview.py @@ -14,14 +14,18 @@ ################################################################################# import os +from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas +from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar + from foqus_lib.framework.uq.Model import Model from foqus_lib.framework.sdoe import plot_utils -# from Preview_UI import Ui_Dialog - from PyQt5 import uic from PyQt5.QtCore import Qt from PyQt5.QtWidgets import ( + QDialog, + QVBoxLayout, + QHBoxLayout, QListWidgetItem, QAbstractItemView, QApplication, @@ -141,14 +145,75 @@ def plotSdoe(self): irsf = self.irsf scatterLabel = self.scatterLabel nImpPts = self.nImpPts - plot_utils.plot( - fname, - scatterLabel, - hname=hname, - show=show, - usf=usf, - nusf=nusf, - irsf=irsf, - nImpPts=nImpPts, - ) - self.setModal(True) + + if nusf: + fig1, fig2 = plot_utils.plot( + fname, + scatterLabel, + hname=hname, + show=show, + usf=usf, + nusf=nusf, + irsf=irsf, + nImpPts=nImpPts, + ) + else: + fig1 = plot_utils.plot( + fname, + scatterLabel, + hname=hname, + show=show, + usf=usf, + nusf=nusf, + irsf=irsf, + nImpPts=nImpPts, + ) + fig2 = None + + dialog = Window(fig1, fig2, self) + if nusf: + title = "SDoE (NUSF) Weights and Designs Visualization" + elif usf: + title = "SDoE (USF) Designs Visualization" + else: + title = "SDoE Candidates Visualization" + + dialog.setWindowTitle(title) + dialog.show() + + +class Window(QDialog): + def __init__(self, fig1, fig2, parent=None): + super(Window, self).__init__(parent) + + # a figure instance to plot on + self.fig1 = fig1 + if fig2 is not None: + self.fig2 = fig2 + + # this is the Canvas Widget that displays the `figure` + # it takes the `figure` instance as a parameter to __init__ + self.canvas1 = FigureCanvas(self.fig1) + if fig2 is not None: + self.canvas2 = FigureCanvas(self.fig2) + + # this is the Navigation widget + # it takes the Canvas widget and a parent + self.toolbar1 = NavigationToolbar(self.canvas1, self) + if fig2 is not None: + self.toolbar2 = NavigationToolbar(self.canvas2, self) + + # set the layout + layout1 = QVBoxLayout() + layout1.addWidget(self.toolbar1) + layout1.addWidget(self.canvas1) + if fig2 is not None: + main_layout = QHBoxLayout() + layout2 = QVBoxLayout() + layout2.addWidget(self.toolbar2) + layout2.addWidget(self.canvas2) + main_layout.addLayout(layout2) + main_layout.addLayout(layout1) + self.setLayout(main_layout) + else: + self.setLayout(layout1) diff --git a/foqus_lib/gui/sdoe/sdoePreview_UI.ui b/foqus_lib/gui/sdoe/sdoePreview_UI.ui index db078f9e0..83a75abb0 100644 --- a/foqus_lib/gui/sdoe/sdoePreview_UI.ui +++ b/foqus_lib/gui/sdoe/sdoePreview_UI.ui @@ -2,6 +2,9 @@ Dialog + + Qt::NonModal + 0 @@ -15,6 +18,9 @@ 10 + + Qt::NoFocus + CCSI SDOE - Preview Inputs diff --git a/foqus_lib/gui/sdoe/sdoeSetupFrame.py b/foqus_lib/gui/sdoe/sdoeSetupFrame.py index 0379f1feb..1889b0ab1 100644 --- a/foqus_lib/gui/sdoe/sdoeSetupFrame.py +++ b/foqus_lib/gui/sdoe/sdoeSetupFrame.py @@ -1057,7 +1057,6 @@ def launchSdoe(self): candidateData, dname, analysis, historyData, type, self ) dialog.open() - # dialog.deleteLater() def initUQToolBox(self): diff --git a/foqus_lib/gui/tests/test_sdoe.py b/foqus_lib/gui/tests/test_sdoe.py index 6bfd79a40..fc76c009c 100644 --- a/foqus_lib/gui/tests/test_sdoe.py +++ b/foqus_lib/gui/tests/test_sdoe.py @@ -21,6 +21,7 @@ from foqus_lib.gui.sdoe.sdoeSetupFrame import sdoeSetupFrame from foqus_lib.framework.sampleResults.results import Results from foqus_lib.gui.sdoe.sdoeAnalysisDialog import sdoeAnalysisDialog +from foqus_lib.gui.sdoe.sdoePreview import sdoePreview import pytest @@ -55,6 +56,18 @@ def test_run_sdoe(self, qtbot, start_analysis): qtbot.using(spin_box="Number of Random Starts: n = 10^").enter_value(2) qtbot.wait(1000) qtbot.click(button="Run SDoE") + qtbot.wait(10_000) + with qtbot.searching_within(self.analysis_dialog): + with qtbot.searching_within(group_box="Created Designs"): + with qtbot.focusing_on(table=any): + qtbot.select_row(0) + with qtbot.waiting_for_modal(timeout=10_000): + qtbot.using(column="Plot SDoE").click() + with qtbot.searching_within(sdoePreview): + with qtbot.searching_within(group_box="Plots"): + qtbot.click(button="Plot SDoE") + qtbot.wait(1000) + qtbot.click(button="OK") @pytest.fixture(scope="class") def start_analysis(self, qtbot, foqus_examples_dir): @@ -66,6 +79,25 @@ def has_dialog(): foqus_examples_dir / "tutorial_files/SDOE/SDOE_Ex1_Candidates.csv" ): qtbot.click(button="Load Existing\n Set") + with qtbot.focusing_on(self.frame.filesTable): + qtbot.select_row(0) + with qtbot.waiting_for_modal(timeout=10_000): + qtbot.using(column="Visualize").click() + with qtbot.searching_within(sdoePreview): + with qtbot.searching_within(group_box="Plots"): + qtbot.click(button="Plot SDoE") + qtbot.wait(1000) + qtbot.click(button="OK") qtbot.click(button="Continue") + qtbot.wait(1000) + with qtbot.focusing_on(self.frame.aggFilesTable): + qtbot.select_row(0) + with qtbot.waiting_for_modal(timeout=10_000): + qtbot.using(column="Visualize").click() + with qtbot.searching_within(sdoePreview): + with qtbot.searching_within(group_box="Plots"): + qtbot.click(button="Plot SDoE") + qtbot.wait(1000) + qtbot.click(button="OK") qtbot.click(button="Open SDoE Dialog") qtbot.wait_until(has_dialog, timeout=10_000)