1- from PyQt5 .QtWidgets import QDialog , QVBoxLayout , QHBoxLayout , QPushButton , QLabel , QFormLayout , QRadioButton , QMessageBox , QFileDialog
1+ from PyQt5 .QtWidgets import QDialog , QVBoxLayout , QHBoxLayout , QFormLayout , QPushButton , QLabel , QFormLayout , QRadioButton , QMessageBox , QFileDialog , QComboBox
22
33import matplotlib .pyplot as plt
44from matplotlib .backends .backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
55from matplotlib .widgets import SpanSelector
66
77import numpy as np
88
9- from data_extractor import getInputOutputData
9+ from data_extractor import DataExtractor
1010
1111class DataSelectionWindow (QDialog ):
1212 def __init__ (self , filename ):
1313 QDialog .__init__ (self )
1414
15+ self .t = []
16+ self .u = []
17+ self .y = []
18+ self .t_start = None
19+ self .t_stop = None
20+
21+ self .input_ref = None
22+ self .output_ref = None
1523 self .figure = plt .figure (1 )
1624 self .canvas = FigureCanvas (self .figure )
25+ self .initPlot ()
1726
1827 layout_v = QVBoxLayout ()
1928
@@ -22,51 +31,59 @@ def __init__(self, filename):
2231 btn_browse .clicked .connect (self .browseFiles )
2332 top_group .addWidget (btn_browse )
2433
34+ in_out_group = QFormLayout ()
35+ self .combo_u = QComboBox ()
36+ self .combo_u .setEditable (True )
37+ self .combo_u .setInsertPolicy (QComboBox .NoInsert )
38+ self .combo_u .currentIndexChanged .connect (self .selectUData )
39+ in_out_group .addRow (QLabel ("Input:" ), self .combo_u )
40+
41+ self .combo_y = QComboBox ()
42+ self .combo_y .setEditable (True )
43+ self .combo_y .setInsertPolicy (QComboBox .NoInsert )
44+ self .combo_y .currentIndexChanged .connect (self .selectYData )
45+ in_out_group .addRow (QLabel ("Output:" ), self .combo_y )
46+ top_group .addLayout (in_out_group )
47+
2548 layout_v .addLayout (top_group )
2649 layout_v .addWidget (self .canvas )
2750
28- xyz_group = QHBoxLayout ()
29- r_x = QRadioButton ("x" )
30- r_x .setChecked (True )
31- r_y = QRadioButton ("y" )
32- r_z = QRadioButton ("z" )
33- xyz_group .addWidget (QLabel ("Axis" ))
34- xyz_group .addWidget (r_x )
35- xyz_group .addWidget (r_y )
36- xyz_group .addWidget (r_z )
37- r_x .clicked .connect (self .loadXData )
38- r_y .clicked .connect (self .loadYData )
39- r_z .clicked .connect (self .loadZData )
40-
41- layout_v .addLayout (xyz_group )
42-
4351 btn_ok = QPushButton ("Load selection" )
44- btn_ok .clicked .connect (self .loadLog )
52+ btn_ok .clicked .connect (self .loadSelection )
4553 layout_v .addWidget (btn_ok )
4654
4755 self .setLayout (layout_v )
4856
4957 if filename :
5058 self .file_name = filename
51- self .refreshInputOutputData ()
59+ self .openFile ()
5260
5361 else :
5462 self .browseFiles ()
5563
56- def loadLog (self ):
57- if self .t_stop > self .t_start :
58- (self .t , self .u , self .y , self .v ) = getInputOutputData (self .file_name , self .axis , self .t_start , self .t_stop )
64+ def loadSelection (self ):
65+ if ( self .t_start is None and self . t_start is None ) or ( self . t_stop > self .t_start ) :
66+ (self .t , self .u , self .y , self .v ) = self . data_extractor . getInputOutputData (self .topics [ self . index_u ] , self .topics [ self . index_y ] , self .t_start , self .t_stop )
5967 self .accept ()
6068 else :
6169 self .printRangeError ()
6270
6371 def browseFiles (self ):
6472 options = QFileDialog .Options ()
6573 options |= QFileDialog .DontUseNativeDialog
66- self .file_name , _ = QFileDialog .getOpenFileName (self ,"QFileDialog.getOpenFileName()" , "" ,"ULog (*.ulg)" , options = options )
74+ file_name , _ = QFileDialog .getOpenFileName (self ,"Select ULog file" , "" ,"ULog (*.ulg)" , options = options )
75+ self .file_name = file_name
76+ self .openFile ()
6777
78+ def openFile (self ):
6879 if self .file_name :
69- self .refreshInputOutputData ()
80+ self .data_extractor = DataExtractor (self .file_name )
81+ self .topics = self .data_extractor .get_topics_list ()
82+ list_names = [f"{ topic .topic_name } /{ topic .variable_name } .{ topic .instance } " for topic in self .topics ]
83+ self .combo_u .clear ()
84+ self .combo_u .addItems (list_names )
85+ self .combo_y .clear ()
86+ self .combo_y .addItems (list_names )
7087
7188 def printRangeError (self ):
7289 msg = QMessageBox ()
@@ -75,55 +92,59 @@ def printRangeError(self):
7592 msg .setText ("Range is invalid" )
7693 msg .exec_ ()
7794
78- def loadXData (self ):
79- if self .file_name :
80- self .refreshInputOutputData (0 )
81-
82- def loadYData (self ):
83- if self .file_name :
84- self .refreshInputOutputData (1 )
85-
86- def loadZData (self ):
87- if self .file_name :
88- self .refreshInputOutputData (2 )
89-
90- def refreshInputOutputData (self , axis = 0 ):
91- if self .file_name :
92- self .axis = axis
93- (t , u , y , _ ) = getInputOutputData (self .file_name , axis )
94-
95- if (len (t ) > 10e3 ):
96- # Downsample to speed up plotting preview
97- downsampling_factor = int (len (t )/ 10e3 )+ 1
98- self .t = t [:- downsampling_factor + 1 :downsampling_factor ]
99- self .u = u [:- downsampling_factor + 1 :downsampling_factor ]
100- self .y = y [:- downsampling_factor + 1 :downsampling_factor ]
101-
102- else :
103- self .t = t
104- self .u = u
105- self .y = y
106-
107- self .plotInputOutput (redraw = True )
108-
109- def plotInputOutput (self , redraw = False ):
110- self .figure .clear ()
111- self .ax = self .figure .add_subplot (1 ,1 ,1 )
112- self .ax .plot (self .t , self .u , self .t , self .y )
113- self .ax .set_title ("Click and drag to select data range" )
114- self .ax .set_xlabel ("Time (s)" )
115- self .ax .set_ylabel ("Amplitude" )
116- self .ax .legend (["Input" , "Output" ])
117-
118- self .span = SpanSelector (self .ax , self .onselect , 'horizontal' , useblit = False ,
119- props = dict (alpha = 0.2 , facecolor = 'green' ), interactive = True )
95+ def selectUData (self , index ):
96+ self .index_u = index
97+ (self .t , self .u ) = self .data_extractor .getPreview (self .topics [index ])
98+ self .plotU ()
99+
100+ def selectYData (self , index ):
101+ self .index_y = index
102+ (self .t , self .y ) = self .data_extractor .getPreview (self .topics [index ])
103+ self .plotY ()
104+
105+ def initPlot (self ):
106+ if self .input_ref is None :
107+ self .figure .clear ()
108+ self .ax = self .figure .add_subplot (1 ,1 ,1 )
109+ plot_refs = self .ax .plot ([], [])
110+ self .input_ref = plot_refs [0 ]
111+
112+ plot_refs = self .ax .plot ([], [])
113+ self .output_ref = plot_refs [0 ]
114+ self .ax .autoscale (False )
115+
116+ self .ax .set_title ("Click and drag to select data range" )
117+ self .ax .set_xlabel ("Time (s)" )
118+ self .ax .set_ylabel ("Amplitude" )
119+ self .ax .legend (["Input" , "Output" ])
120+
121+ self .span = SpanSelector (self .ax , self .onselect , 'horizontal' , useblit = False ,
122+ props = dict (alpha = 0.2 , facecolor = 'green' ), interactive = True )
123+
124+ self .canvas .mpl_connect ('scroll_event' , self .zoom_fun )
125+ self .canvas .draw ()
126+
127+ def plotU (self ):
128+ self .input_ref .set_xdata (self .t )
129+ self .input_ref .set_ydata (self .u )
130+ self .resetXYLim ()
131+ self .canvas .draw ()
120132
121- self .t_start = self .t [0 ]
122- self .t_stop = self .t [- 1 ]
133+ def plotY (self ):
134+ self .output_ref .set_xdata (self .t )
135+ self .output_ref .set_ydata (self .y )
136+ self .resetXYLim ()
137+ self .canvas .draw ()
123138
124- self .canvas .mpl_connect ('scroll_event' , self .zoom_fun )
139+ def resetXYLim (self ):
140+ self .ax .set_xlim ([self .t [0 ], self .t [- 1 ]])
125141
126- self .canvas .draw ()
142+ if len (self .u ) > 0 and len (self .y ) > 0 :
143+ self .ax .set_ylim ([min ([min (self .u ), min (self .y )]), max ([max (self .u ), max (self .y )])])
144+ elif len (self .u ) > 0 :
145+ self .ax .set_ylim ([min (self .u ), max (self .u )])
146+ elif len (self .y ) > 0 :
147+ self .ax .set_ylim ([min (self .y ), max (self .y )])
127148
128149 def onselect (self , xmin , xmax ):
129150 indmin , indmax = np .searchsorted (self .t , (xmin , xmax ))
0 commit comments