Skip to content

Commit ca25b98

Browse files
committed
Add matlab file events
1 parent 0942c69 commit ca25b98

1 file changed

Lines changed: 128 additions & 4 deletions

File tree

ratapi/utils/matlab.py

Lines changed: 128 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55
import warnings
66
from pathlib import Path
77

8+
import numpy as np
9+
10+
from ..events import EventTypes, PlotEventData, ProgressEventData, notify
811
from ..outputs import Results
912
from ..project import Project
1013
from ..wrappers import MatlabWrapper
@@ -21,16 +24,18 @@
2124
customControls = customControl();
2225
customControls.update(controls);
2326
customControls.filePath = '{ipc_path}';
24-
if any(strcmpi(controls.procedure, {{procedures.DE.value, procedures.Simplex.value}}))
25-
useLivePlot(1);
26-
end
27+
2728
for i=1:project.customFile.rowCount
2829
addpath(project.customFile.varTable{{i, 5}});
2930
end
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
3236
projectToJson(project, '{project}');
3337
resultsToJson(results, '{result}');
38+
eventManager.clear();
3439
close all
3540
end
3641
"""
@@ -54,6 +59,72 @@
5459
end
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

58129
def 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

Comments
 (0)