5151import warnings
5252from typing import TYPE_CHECKING
5353
54+ import guidata .dataset as gds
5455import guidata .dataset .qtwidgets as gdq
5556import numpy as np
5657import plotpy .io
6869from cdl .core .gui import actionhandler , objectmodel , objectview , roieditor
6970from cdl .core .io .base import IOAction
7071from cdl .core .model .base import ResultShape , items_to_json
72+ from cdl .core .model .signal import create_signal
7173from cdl .env import execenv
7274from cdl .utils .qthelpers import (
7375 create_progress_bar ,
7779)
7880
7981if TYPE_CHECKING : # pragma: no cover
80- import guidata .dataset as gds
8182 from plotpy .plot import PlotWidget
8283 from plotpy .tools import GuiTool
8384
@@ -236,6 +237,15 @@ def remove_all_objects(self):
236237 self .SIG_OBJECT_REMOVED .emit ()
237238
238239
240+ @dataclasses .dataclass
241+ class ResultData :
242+ """Result data associated to a shapetype"""
243+
244+ results : list [ResultShape ] = None
245+ xlabels : list [str ] = None
246+ ylabels : list [str ] = None
247+
248+
239249class BaseDataPanel (AbstractPanel ):
240250 """Object handling the item list, the selected item properties and plot"""
241251
@@ -1010,37 +1020,49 @@ def add_results_button(self) -> None:
10101020 select_condition = actionhandler .SelectCond .at_least_one ,
10111021 )
10121022
1013- def show_results (self ) -> None :
1014- """Show results"""
1015-
1016- @dataclasses .dataclass
1017- class ResultData :
1018- """Result data associated to a shapetype"""
1019-
1020- results : list [ResultShape ] = None
1021- xlabels : list [str ] = None
1022- ylabels : list [str ] = None
1023-
1023+ def __get_resultdata_dict (
1024+ self , objs : list [SignalObj | ImageObj ]
1025+ ) -> dict [ShapeTypes , ResultData ]:
1026+ """Return result data dictionary"""
10241027 rdatadict : dict [ShapeTypes , ResultData ] = {}
1025- objs = self .objview .get_sel_objects (include_groups = True )
10261028 for obj in objs :
10271029 for result in obj .iterate_resultshapes ():
10281030 rdata = rdatadict .setdefault (result .shapetype , ResultData ([], None , []))
1029- title = f"{ result .label } "
10301031 rdata .results .append (result )
10311032 rdata .xlabels = result .shown_xlabels
10321033 for _i_row_res in range (result .array .shape [0 ]):
10331034 ylabel = f"{ obj .short_id } : { result .label } "
10341035 rdata .ylabels .append (ylabel )
1036+ return rdatadict
1037+
1038+ def __show_no_result_warning (self ):
1039+ """Show no result warning"""
1040+ msg = "<br>" .join (
1041+ [
1042+ _ ("No result currently available for this object." ),
1043+ "" ,
1044+ _ (
1045+ "This feature leverages the results of previous computations "
1046+ "performed on the selected object(s).<br><br>"
1047+ "To compute results, select one or more objects and choose "
1048+ "a computing feature in the <u>Compute</u> menu."
1049+ ),
1050+ ]
1051+ )
1052+ QW .QMessageBox .information (self , APP_NAME , msg )
1053+
1054+ def show_results (self ) -> None :
1055+ """Show results"""
1056+ objs = self .objview .get_sel_objects (include_groups = True )
1057+ rdatadict = self .__get_resultdata_dict (objs )
10351058 if rdatadict :
10361059 with warnings .catch_warnings ():
10371060 warnings .simplefilter ("ignore" , RuntimeWarning )
10381061 for rdata in rdatadict .values ():
10391062 dlg = ArrayEditor (self .parent ())
1040- title = _ ("Results" )
10411063 dlg .setup_and_check (
10421064 np .vstack ([result .shown_array for result in rdata .results ]),
1043- title ,
1065+ _ ( "Results" ) ,
10441066 readonly = True ,
10451067 xlabels = rdata .xlabels ,
10461068 ylabels = rdata .ylabels ,
@@ -1049,17 +1071,68 @@ class ResultData:
10491071 dlg .resize (750 , 300 )
10501072 exec_dialog (dlg )
10511073 else :
1052- msg = "<br>" .join (
1053- [
1054- _ ("No result currently available for this object." ),
1055- "" ,
1074+ self .__show_no_result_warning ()
1075+
1076+ def plot_results (self ) -> None :
1077+ """Plot results"""
1078+ objs = self .objview .get_sel_objects (include_groups = True )
1079+ rdatadict = self .__get_resultdata_dict (objs )
1080+ if rdatadict :
1081+ for shapetype , rdata in rdatadict .items ():
1082+ xchoices = (("indexes" , _ ("Indexes" )),)
1083+ for xlabel in rdata .xlabels [1 :]:
1084+ xchoices += ((xlabel , xlabel ),)
1085+ ychoices = xchoices [1 :]
1086+
1087+ class PlotResultParam (gds .DataSet ):
1088+ """Plot results parameters"""
1089+
1090+ xaxis = gds .ChoiceItem (_ ("X axis" ), xchoices , default = "indexes" )
1091+ yaxis = gds .ChoiceItem (
1092+ _ ("Y axis" ), ychoices , default = ychoices [0 ][0 ]
1093+ )
1094+
1095+ comment = (
10561096 _ (
1057- "This feature shows result arrays as displayed after "
1058- 'calling one of the computing feature (see "Compute" menu).'
1059- ),
1060- ]
1061- )
1062- QW .QMessageBox .information (self , APP_NAME , msg )
1097+ "Plot results obtained from previous computations.<br><br>"
1098+ "This plot is based on the results under the form of '%s'."
1099+ )
1100+ % shapetype .name .lower ()
1101+ )
1102+ param = PlotResultParam (_ ("Plot results" ), comment = comment )
1103+ if not param .edit (parent = self ):
1104+ return
1105+
1106+ # Regrouping ResultShape results by their `label` attribute:
1107+ grouped_results : dict [str , list [ResultShape ]] = {}
1108+ for result in rdata .results :
1109+ grouped_results .setdefault (result .label , []).append (result )
1110+
1111+ # Plotting each group of results:
1112+ for label , results in grouped_results .items ():
1113+ x , y = [], []
1114+ for index , result in enumerate (results ):
1115+ if param .xaxis == "indexes" :
1116+ x .append (index )
1117+ else :
1118+ x .append (
1119+ result .shown_array [0 ][rdata .xlabels .index (param .xaxis )]
1120+ )
1121+ y .append (
1122+ result .shown_array [0 ][rdata .xlabels .index (param .yaxis )]
1123+ )
1124+ xdata = np .array (x , dtype = float )
1125+ ydata = np .array (y , dtype = float )
1126+
1127+ obj = create_signal (
1128+ title = f"{ label } : { param .yaxis } = f({ param .xaxis } )" ,
1129+ x = xdata ,
1130+ y = ydata ,
1131+ labels = [param .xaxis , param .yaxis ],
1132+ )
1133+ self .mainwindow .signalpanel .add_object (obj )
1134+ else :
1135+ self .__show_no_result_warning ()
10631136
10641137 def add_label_with_title (self , title : str | None = None ) -> None :
10651138 """Add a label with object title on the associated plot
0 commit comments