55import warnings
66from pathlib import Path
77
8+ import numpy as np
9+
10+ from ..events import EventTypes , PlotEventData , ProgressEventData , notify
811from ..outputs import Results
912from ..project import Project
1013from ..wrappers import MatlabWrapper
2124customControls = customControl();
2225customControls.update(controls);
2326customControls.filePath = '{ipc_path}';
24- if any(strcmpi(controls.procedure, {{procedures.DE.value, procedures.Simplex.value}}))
25- useLivePlot(1);
26- end
27+
2728for i=1:project.customFile.rowCount
2829 addpath(project.customFile.varTable{{i, 5}});
2930end
31+ eventManager.register(eventTypes.Message, @(x) logger('{msg_log_path}', x));
32+ eventManager.register(eventTypes.Progress, @(x) logger('{progress_log_path}', x));
33+ eventManager.register(eventTypes.Plot, @(x) logger('{plot_log_path}', x));
3034[project, results] = RAT(project, customControls);
3135
3236projectToJson(project, '{project}');
3337resultsToJson(results, '{result}');
38+ eventManager.clear();
3439close all
3540end
3641"""
5459end
5560"""
5661
62+ LOGGER = """function logger(logPath, data)
63+ fid = fopen(logPath, "a");
64+ cleanup = onCleanup(@() fclose(fid));
65+ if isstruct(data)
66+ entry = plotDataToJson(data);
67+ elseif iscell(data)
68+ entry = [data{1}, ',', num2str(data{2})];
69+ else
70+ entry = strip(data, 'right');
71+ end
72+ fprintf(fid, "%s\\ n", entry);
73+ end
74+
75+ function encoded = plotDataToJson(data)
76+ % Encodes the results into a json file...
77+ tmpResults = struct();
78+ for fn = fieldnames(data)'
79+ tmpResults.(fn{1}) = data.(fn{1});
80+ end
81+
82+ tmpResults.reflectivity = correctCellArray(tmpResults.reflectivity);
83+ tmpResults.shiftedData = correctCellArray(tmpResults.shiftedData);
84+ tmpResults.sldProfiles = makeCellJson(tmpResults.sldProfiles);
85+ tmpResults.resampledLayers = makeCellJson(tmpResults.resampledLayers);
86+
87+ encoded = jsonencode(tmpResults,ConvertInfAndNaN=false);
88+ encoded = strrep(encoded, ']"', ']');
89+ encoded = strrep(encoded, '"[', '[');
90+ end
91+
92+ function outputArray = makeCellJson(cellArray)
93+ % The jsonencode function flattens 2d cell arrays this is a workaround to
94+ % avoid flattening by converting to a string array with is not flattened.
95+ [row, col] = size(cellArray, [1, 2]);
96+ outputArray = strings([row, col]);
97+ for i=1:row
98+ for j=1:col
99+ entry = cellArray{i, j};
100+ if size(entry, 1) == 1
101+ entry = {entry};
102+ end
103+ if col == 1
104+ entry = {entry};
105+ end
106+ outputArray(i, j) = jsonencode(entry);
107+ end
108+ end
109+ if row == 1
110+ outputArray = {outputArray};
111+ end
112+
113+ end
114+
115+ function cellArray = correctCellArray(cellArray)
116+ % Corrects array with single row so its written as 2D array in json
117+ [row, col] = size(cellArray, [1, 2]);
118+ for i=1:row
119+ for j=1:col
120+ if size(cellArray{i, j}, 1) == 1
121+ cellArray{i, j} = {cellArray{i, j}};
122+ end
123+ end
124+ end
125+ end
126+ """
127+
57128
58129def run_matlab_directly (project , controls , matlab_rat_path , ipc_path = "" , stdout = None , stderr = None ):
59130 """Run User provided MATLAB RAT for the given project and controls inputs.
@@ -84,6 +155,10 @@ def run_matlab_directly(project, controls, matlab_rat_path, ipc_path="", stdout=
84155 result_file = Path (tmp , "results.json" )
85156 runner_file = Path (tmp , "executeRAT.m" )
86157 custom_controls_file = Path (tmp , "customControl.m" )
158+ msg_log_file = Path (tmp , "runner_msg_log.txt" )
159+ progress_log_file = Path (tmp , "runner_progress_log.txt" )
160+ plot_log_file = Path (tmp , "runner_plot_log.txt" )
161+ Path (tmp , "logger.m" ).write_text (LOGGER )
87162 with open (custom_controls_file , "w" ) as f :
88163 f .write (CONTROL )
89164
@@ -95,6 +170,9 @@ def run_matlab_directly(project, controls, matlab_rat_path, ipc_path="", stdout=
95170 result = result_file ,
96171 rat_path = matlab_rat_path ,
97172 ipc_path = ipc_path ,
173+ msg_log_path = msg_log_file ,
174+ progress_log_path = progress_log_file ,
175+ plot_log_path = plot_log_file ,
98176 )
99177 )
100178
@@ -107,8 +185,54 @@ def run_matlab_directly(project, controls, matlab_rat_path, ipc_path="", stdout=
107185 )
108186
109187 engine .addpath (tmp , nargout = 0 )
110- engine .executeRAT (nargout = 0 , stdout = stdout , stderr = stderr )
188+ future = engine .executeRAT (nargout = 0 , stdout = stdout , stderr = stdout , background = True )
189+ msg_cur_line = 0
190+ plot_cur_line = 0
191+ progress_cur_line = 0
192+ while not future .done ():
193+ if msg_log_file .exists ():
194+ with open (msg_log_file , encoding = "utf-8" ) as handle :
195+ handle .seek (msg_cur_line )
196+ text = handle .read ()
197+ msg_cur_line = handle .tell ()
198+ if text :
199+ notify (EventTypes .Message , text )
200+ if progress_log_file .exists ():
201+ with open (progress_log_file , encoding = "utf-8" ) as handle :
202+ handle .seek (progress_cur_line )
203+ lines = handle .readlines ()
204+ progress_cur_line = handle .tell ()
205+ if lines :
206+ msg , percent = lines [- 1 ].strip ().rsplit ("," , 1 )
207+ progress_data = ProgressEventData ()
208+ progress_data .message = msg
209+ progress_data .percent = float (percent )
210+ notify (EventTypes .Progress , progress_data )
211+ if plot_log_file .exists ():
212+ with open (plot_log_file , encoding = "utf-8" ) as handle :
213+ handle .seek (plot_cur_line )
214+ lines = handle .readlines ()
215+ plot_cur_line = handle .tell ()
216+ if lines :
217+ plot_data = PlotEventData ()
218+ plot_json = json .loads (lines [- 1 ])
219+ plot_data .modelType = plot_json ["modelType" ]
220+ plot_data .reflectivity = [np .array (ref ) for ref in plot_json ["reflectivity" ]]
221+ plot_data .shiftedData = [np .array (sd ) for sd in plot_json ["shiftedData" ]]
222+ plot_data .sldProfiles = [
223+ [np .array (prof ) for prof in profiles ] for profiles in plot_json ["sldProfiles" ]
224+ ]
225+ plot_data .resampledLayers = [
226+ [np .array (lay ) for lay in layers ] for layers in plot_json ["resampledLayers" ]
227+ ]
228+ plot_data .dataPresent = plot_json ["dataPresent" ]
229+ plot_data .subRoughs = plot_json ["subRoughs" ]
230+ plot_data .resample = plot_json ["resample" ]
231+ plot_data .contrastNames = plot_json ["contrastNames" ]
232+ notify (EventTypes .Plot , plot_data )
111233 engine .rmpath (tmp , nargout = 0 )
234+ if future .result () is not None :
235+ raise RuntimeError (future .result ())
112236
113237 project = Project .load (project_file )
114238 results = Results .load (result_file )
0 commit comments