33import ctypes
44import sys
55from pathlib import Path
6+
67parentFolder = str (Path (__file__ ).parent .parent )
78activate_path = parentFolder + '\\ env\\ Scripts\\ activate_this.py'
9+
810if os .path .exists (activate_path ):
911 exec (open (activate_path ).read (), {'__file__' : activate_path })
1012 print (f'Aivia virtual environment activated\n Using python: { activate_path } ' )
2123
2224import wx
2325import matplotlib .pyplot as plt
26+ from matplotlib .widgets import RadioButtons
2427import re
28+ import concurrent .futures
2529
2630"""
2731Extracts Deep Learning training info (epochs with their relative loss and validation loss values)
3337scikit-image
3438matplotlib
3539re
36- wxpython or pyside2 (needed for UI created by matplotlib)
40+ wxpython
3741
3842Parameters
3943----------
4953"""
5054
5155
52- def run ():
56+ # [INPUT Name:inputPath Type:string DisplayName:'Any channel']
57+ # [OUTPUT Name:resultPath Type:string DisplayName:'Dummy to delete']
58+ def run (params ):
5359 print ("Running" )
5460 # Setting colors for chart
5561 col1 = 'royalblue'
5662 col2 = 'r'
5763
64+ # GUI to select a log file
65+ print ('Starting wxPython app' )
66+ app = wx .App ()
5867 logfile = pick_file ()
68+ print ('-- Selected file: {}--' .format (logfile ))
5969
6070 # Check if log file is from local Aivia or Google Cloud Platform
6171 is_local = True
@@ -64,54 +74,107 @@ def run():
6474
6575 file = open (logfile , "r+" )
6676 all_lines = file .read ()
77+ list_n_epoch , list_i_epoch = [], []
6778 if is_local :
68- (n_epoch , i_epoch ) = extract_data (all_lines )
79+ print ('-- Extracting local DL data --' )
80+ indiv_data_blocks = extract_DL_runs (all_lines )
81+
82+ for data in indiv_data_blocks :
83+ list_n_epoch_tmp , list_i_epoch_tmp = extract_data (data )
84+ list_n_epoch .append (list_n_epoch_tmp )
85+ list_i_epoch .append (list_i_epoch_tmp )
86+
6987 else :
70- (n_epoch , i_epoch ) = extract_data_GCP (all_lines )
88+ print ('-- Extracting Google Cloud DL data --' )
89+ # (n_epoch, i_epoch) = extract_data_GCP(all_lines) # TODO: now n_epoch is a list of lists
7190
7291 # If nothing found, exit
73- if n_epoch == 0 :
74- Mbox ('No info found' , 'No Deep Learning training info found in this log.' , 0 )
92+ if list_n_epoch is None :
93+ concurrent .futures .ThreadPoolExecutor ().submit (Mbox , 'No info found' ,
94+ 'No Deep Learning training info found in this log.' , 0 )
7595 sys .exit ("No Deep Learning training info found in this log." )
7696
77- n_epoch = list (map (int , n_epoch ))
78-
79- # extracting values from individual info
80- if is_local :
81- (all_v1 , all_v2 ) = extract_epoch_val ('\n ' .join (i_epoch )+ '\n ' )
82- else :
83- (all_v1 , all_v2 ) = extract_epoch_val_GCP ('\n ' .join (i_epoch ) + '\n ' )
84- all_v1 = list (map (float , all_v1 ))
85- all_v2 = list (map (float , all_v2 ))
86-
87- ymax1 = max (all_v1 ) * 1.1
88- ymax2 = max (all_v2 ) * 1.1
97+ print ('-- Found {} DL training blocks --' .format (len (list_n_epoch )))
8998
90- fig = plt .figure (figsize = plt .figaspect (0.5 ))
99+ # Init chart
100+ fig = plt .figure (figsize = plt .figaspect (0.4 ))
91101 ax1 = fig .add_subplot (111 )
92102 ax1 .set_xlabel ('epochs' )
93103 ax1 .set_ylabel ('loss' , color = col1 )
94104 ax1 .tick_params (axis = 'y' , labelcolor = col1 )
95- ax1 .set_ylim (0 , ymax1 )
96- # ax1.yaxis.set_major_locator(ticker.MultipleLocator(0.1))
97105
98106 # Create second axis
99107 ax2 = ax1 .twinx ()
100108 ax2 .set_ylabel ('validation_loss' , color = col2 )
101109 ax2 .tick_params (axis = 'y' , labelcolor = col2 )
102- ax2 .set_ylim (0 , ymax2 )
103- # ax2.yaxis.set_major_locator(ticker.MultipleLocator(1))
104110
105- # Plot values
106- all_v1_nonsci = [float ('{:.4f}' .format (v )) for v in all_v1 ] # Remove scientific notation for loss value
107- ax1 .plot (n_epoch , all_v1_nonsci , color = col1 , linewidth = 1 )
108- ax2 .plot (n_epoch , all_v2 , color = col2 , linewidth = 1 )
111+ # Create buttons to switch to another DL run
112+ # sub-plot for radio button with
113+ # left, bottom, width, height values
114+ plt .subplots_adjust (right = 0.7 )
115+ rax = plt .axes ([0.8 , 0.1 , 0.16 , 0.8 ])
116+ radio_button = RadioButtons (rax , tuple (['DL training no {}' .format (x ) for x in range (1 , len (list_n_epoch ) + 1 )]),
117+ active = len (list_n_epoch ) - 1 )
118+
119+ def get_values (run_index ):
120+ run_index -= 1
121+ n_epoch = list (map (int , list_n_epoch [run_index ]))
122+ i_epoch = list_i_epoch [run_index ]
123+
124+ # extracting values from individual info
125+ if is_local :
126+ (all_v1 , all_v2 ) = extract_epoch_val ('\n ' .join (i_epoch ) + '\n ' )
127+ else :
128+ (all_v1 , all_v2 ) = extract_epoch_val_GCP ('\n ' .join (i_epoch ) + '\n ' )
129+ all_v1 = list (map (float , all_v1 ))
130+ all_v2 = list (map (float , all_v2 ))
131+
132+ all_v1_nonsci = [float ('{:.4f}' .format (v )) for v in all_v1 ] # Remove scientific notation for loss value
133+
134+ ymax1 = max (all_v1 ) * 1.1
135+ ymax2 = max (all_v2 ) * 1.1
136+
137+ return n_epoch , all_v1_nonsci , all_v2 , ymax1 , ymax2
138+
139+ # Define function for the radio buttons
140+ def change_DL_run (label ):
141+ run_no = int (str (label ).split ('no ' )[- 1 ])
142+ n_epoch , all_v1_nonsci , all_v2 , ymax1 , ymax2 = get_values (run_no )
143+ print ('Selected DL run: {}' .format (run_no ))
144+
145+ # Clear values
146+ ax1 .cla ()
147+ ax2 .cla ()
148+
149+ # Plot values
150+ ax1 .plot (n_epoch , all_v1_nonsci , color = col1 , linewidth = 1 )
151+ ax2 .plot (n_epoch , all_v2 , color = col2 , linewidth = 1 )
152+
153+ ax1 .set_ylim (0 , ymax1 )
154+ ax2 .set_ylim (0 , ymax2 )
155+
156+ plt .draw () # Update plot
157+
158+ radio_button .on_clicked (change_DL_run )
159+
160+ # Process the last DL run
161+ run_index = len (list_n_epoch )
162+ change_DL_run (run_index )
109163
110164 plt .show ()
111165
112166
113- def extract_data (s ): # TODO
114- # The following regex is for the Worklog from the GCP - from restoration model (see PSNR)
167+ def extract_DL_runs (s ):
168+ # To detect and extract all DL runs in the same log
169+ start_pattern = re .compile (r"(.+DeepLearning:Epoch\s+1/\d+.+\n)" )
170+ str_split = start_pattern .split (s )
171+ blocks = [a + b for a , b in zip (str_split [1 ::2 ], str_split [2 ::2 ])]
172+
173+ return blocks
174+
175+
176+ def extract_data (s ): # TODO
177+ # The following regex is for the log from Aivia - from restoration model (see PSNR)
115178 pattern = re .compile (r""".+DeepLearning:Epoch\s?(?P<epoch>\d*)\/(?P<totalEpochs>\d+) # First line
116179 \n(.*\n){0,20} # followed by several info lines
117180 (.*DeepLearning:.*\n){2,258} # lines for iterations
@@ -128,7 +191,7 @@ def extract_data(s): # TODO
128191 return n_epoc , i_epoc
129192
130193
131- def extract_epoch_val (s ): # TODO
194+ def extract_epoch_val (s ): # TODO
132195 # The following regex is for the Worklog from Aivia - from restoration model (see PSNR)
133196 in_pattern = re .compile (r""".*\sloss:\s(?P<vloss>\d+\.?\d*e?-?\d*)
134197 \s.*-\sval_loss:\s(?P<vdloss>\d+\.?\d*e?-?\d*)
@@ -174,15 +237,12 @@ def extract_epoch_val_GCP(s):
174237
175238
176239def pick_file ():
177- print ('Starting wxPython app' )
178- app = wx .App ()
179- frame = wx .Frame (None , - 1 , 'File picker' )
180-
181240 # Create open file dialog
182- openFileDialog = wx .FileDialog (frame , "Select a log file to process" , ".\\ " , "" ,
241+ openFileDialog = wx .FileDialog (None , "Select a log file to process" , ".\\ " , "" ,
183242 "Log files (*.log)|*.log" , wx .FD_OPEN | wx .FD_FILE_MUST_EXIST )
184243
185- openFileDialog .ShowModal ()
244+ if openFileDialog .ShowModal () == wx .ID_CANCEL :
245+ sys .exit ()
186246 fname = openFileDialog .GetPath ()
187247 print ("Selected file: " , fname )
188248 openFileDialog .Destroy ()
@@ -192,8 +252,12 @@ def pick_file():
192252def Mbox (title , text , style ):
193253 return ctypes .windll .user32 .MessageBoxW (0 , text , title , style )
194254
195-
196- run ()
255+ if __name__ == '__main__' :
256+ params = {}
257+ run (params )
197258 # image_location = params['inputImagePath']
198259 # result_location = params['resultPath']
199260 # imsave(result_location, output_data)
261+
262+ # Changelog:
263+ # v1.10: - Bug fixed with wxPython app not being run in v1.00
0 commit comments