ParaMonte MATLAB 3.0.0
Parallel Monte Carlo and Machine Learning Library
See the latest version documentation.
FileContentsReport.m
Go to the documentation of this file.
1%> \brief
2%> This is the base class for generating objects
3%> that contain the contents of a report file
4%> generated by a ParaMonte sampler.<br>
5%>
6%> \details
7%> This class is meant to be primarily internally
8%> used by the ParaMonte MATLAB library samplers.<br>
9%> See the documentation of the class constructor.
10%>
11%> \note
12%> See below for information on the attributes (properties).<br>
13%>
14%> \note
15%> See below for information on the methods.<br>
16%>
17%> \return
18%> An object of class [pm.sampling.FileContentsReport](@ref FileContentsReport).<br>
19%>
20%> \final{FileContentsReport}
21%>
22%> \author
23%> \JoshuaOsborne, May 21 2024, 1:13 AM, University of Texas at Arlington<br>
24%> \FatemehBagheri, May 20 2024, 1:25 PM, NASA Goddard Space Flight Center (GSFC), Washington, D.C.<br>
25%> \AmirShahmoradi, May 16 2016, 9:03 AM, Oden Institute for Computational Engineering and Sciences (ICES), UT Austin<br>
26classdef FileContentsReport < pm.io.FileContents
27
28 properties(Access = public)
29 %>
30 %> ``stats`` : The scalar MATLAB ``struct`` containing the set of
31 %> computed properties extracted from the report file.<br>
32 %>
33 stats = struct();
34 %>
35 %> ``contents`` : The scalar MATLAB string containing the entire
36 %> contents of the report file with all Carriage Return
37 %> characters removed (relevant only to Windows OS).<br>
38 %>
39 contents = [];
40 %>
41 %> ``lineList`` : The vector of MATLAB strings containing the set of
42 %> all lines in the report file with all Carriage Return
43 %> and New Line characters removed.<br>
44 %>
45 lineList = [];
46 % %
47 % % setup
48 % %
49 % % The scalar MATLAB ``struct`` containing the sampler
50 % % setup information extracted from the report file.
51 % %
52 % setup = struct();
53 % %
54 % % spec
55 % %
56 % % The scalar MATLAB ``struct`` containing the set of
57 % % simulation specifications extracted from the report file.
58 % %
59 % spec = struct();
60 banner = "";
61 end
62
63 properties(Hidden)
64 %iend = 0;
65 lineListLen = [];
66 indentLen = 4; % indent length of the records
67 dsymLen = 2; % assume a minimum length of two of decoration symbols.
68 dsym = ''; % decoration symbol to be determined at runtime (currently ``%``).
69 prefix = ' - NOTE: ';
70 method = '';
71 end
73 methods(Access = public)
75 %> \brief
76 %> Return a scalar object of class [pm.sampling.FileContentsReport](@ref FileContentsReport).<br>
77 %> \details
78 %> This is the constructor of the class [pm.sampling.FileContentsReport](@ref FileContentsReport).<br>
79 %>
80 %> \param[in] file : The input scalar MATLAB string containing the path to an external report file.<br>
81 %> \param[in] silent : See the corresponding argument of [pm.io.FileContents](@ref FileContents) class.<br>
82 %> (**optional**. The default is set by [pm.io.FileContents](@ref FileContents).)
83 %> \param[in] method : The input scalar MATLAB string
84 %> containing the sampling method name.<br>
85 %> The input value must be any of the following:<br>
86 %> <ol>
87 %> <li> ``"ParaDRAM"``
88 %> <li> ``"ParaDISE"``
89 %> <li> ``"ParaNest"``
90 %> </ol>
91 %> (**optional**. If missing, some of the report file contents may not be properly parsed.)
92 %>
93 %> \return
94 %> ``self`` : The output scalar object of class [pm.sampling.FileContentsReport](@ref FileContentsReport).<br>
95 %>
96 %> \interface{FileContentsReport}
97 %> \code{.m}
98 %>
99 %> contents = pm.sampling.FileContentsReport(file)
100 %> contents = pm.sampling.FileContentsReport(file, [])
101 %> contents = pm.sampling.FileContentsReport(file, silent)
102 %> contents = pm.sampling.FileContentsReport(file, [], [])
103 %> contents = pm.sampling.FileContentsReport(file, silent, [])
104 %> contents = pm.sampling.FileContentsReport(file, silent, method)
105 %>
106 %> \endcode
107 %>
108 %> \final{FileContentsReport}
109 %>
110 %> \author
111 %> \JoshuaOsborne, May 21 2024, 1:30 AM, University of Texas at Arlington<br>
112 %> \FatemehBagheri, May 20 2024, 1:25 PM, NASA Goddard Space Flight Center (GSFC), Washington, D.C.<br>
113 %> \AmirShahmoradi, May 16 2016, 9:03 AM, Oden Institute for Computational Engineering and Sciences (ICES), UT Austin<br>
114 function self = FileContentsReport(file, silent, method)
115 if nargin < 2
116 silent = [];
117 end
118 self = self@pm.io.FileContents(file, silent);
119 if 2 < nargin
120 self.method = convertStringsToChars(method);
121 self.prefix = [self.method, self.prefix];
122 end
123 % remove any CARRIAGE RETURN.
124 self.contents = strrep(fileread(file), char(13), '');
125 self.contents = strrep(self.contents, newline, [' ', newline]);
126 self.lineList = strsplit(self.contents, newline);
127 self.lineListLen = length(self.lineList);
128 iend = 1; % the line we are about to parse.
129
130 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
131 %%%% determine the decoration symbol and read the banner.
132 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
133
134 % Here we assume the first non-empty line starts with the symbol character (likely ``%``).
135
136 ibeg = self.skipNull(iend);
137 failed = self.lineListLen < ibeg || length(self.lineList{ibeg}) < 4;
138 if ~failed
139 line = self.lineList{ibeg};
140 failed = any(line(1) ~= line(2 : 4));
141 if ~failed
142 iend = self.skipFull(ibeg + 1);
143 failed = self.lineListLen < iend;
144 end
145 end
146 if ~failed
147 self.dsym = line(1);
148 self.banner = self.concat(self.lineList(ibeg : iend));
149 else
150 self.warn(line, "Failed to detect the decoration symbol used in the report file.");
151 end
152
153 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
154 %%%% read the ParaMonte MATLAB library interface specifications
155 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
156
157 %self.setup.library.interface = self.parseSection("interface.specifications");
158
159 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
160 %%%% read the ParaMonte MATLAB library compiler version
161 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
162
163 %self.setup.library.compiler.version = self.parseSection("compiler.version");
164
165 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
166 %%%% read the ParaMonte MATLAB library compiler options
167 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
168
169 %self.setup.library.compiler.options = self.parseSection("compiler.options");
170
171 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
172 %%%% read the Runtime platform specifications
173 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
174
175 %self.setup.platform = self.parseSection("runtime.platform.specifications");
176
177 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
178 %%%% read the simulation environment
179 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
180
181 %self.setup.io = self.parseSection("simulation.environment");
182
183 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
184 %%%% read the simulation specifications
185 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
186
187 %self.spec.base = self.parseSection("simulation.specifications.base");
188 %if self.method == "ParaDRAM" || self.method == "ParaDISE"
189 % self.spec.mcmc = self.parseSection("simulation.specifications.mcmc");
190 % self.spec.dram = self.parseSection("simulation.specifications.dram");
191 %elseif self.method == "ParaNest"
192 % self.spec.nest = self.parseSection("simulation.specifications.nest");
193 %end
194
195 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
196 %%%% statistics: this must be always the last item to parse
197 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
198
199 self.checkpoint("parsing the simulation statistics...", 1);
200
201 while true
202
203 item = self.lineList{iend};
204 if ~self.silent
205 self.spinner.spin(iend / self.lineListLen);
206 end
207 if strcmp(item(1 : min(6, length(item))), 'stats.')
208
209 % first non-empty line.
210 ibeg = self.skipNull(iend + 1);
211 failed = self.lineListLen < ibeg;
212 if ~failed
213 iend = self.skipFull(ibeg + 1);
214 failed = self.lineListLen < iend;
215 if ~failed
216 % Retrieve the value.
217 % The strategy is to read all values as table by dumping
218 % the value in a temporary file and reading it as a table.
219 tempfile = tempname();
220 fid = fopen(tempfile, "w");
221 fprintf(fid, self.concat(strtrim(self.lineList(ibeg : iend - 1))));
222 fclose(fid);
223 value = readtable(tempfile);
224 %self.(strtrim(item)).value = value;
225 eval(['self.', strtrim(item), '.value = value;']);
226 end
227 end
228
229 % Retrieve the description.
230
231 ibeg = self.skipNull(iend + 1);
232 iend = self.skipFull(ibeg + 1);
233 if ~all(self.isdesc(self.lineList(ibeg : iend - 1)))
234 self.warn(string(ibeg) + "-" + string(iend), "A description record does not contain """ + string(self.prefix) + """");
235 else
236 % Concatenate lines and remove prefixes from each description lines.
237 desc = strrep(self.concat(strtrim(self.lineList(ibeg : iend - 1))), self.prefix, '');
238 eval(['self.', strtrim(item), '.description = desc;']);
239 %self.(strtrim(item)).description = desc;
240 end
241
242 end % new item found
243
244 iend = iend + 1;
245 if self.lineListLen < iend
246 break;
247 end
248
249 end % while
250
251 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
252
253 self.checkpoint();
254
255 end % constructor
256
257 end % methods(Access = public)
258
259 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
260
261 methods(Hidden, Static)
262
263 %function reportParseFailure(topic)
264 % topic = string(strtrim(strrep(strrep(topic, newline, ' '), char(13), ' ')));
265 % warning ( newline ...
266 % + "Failed to parse the record """ + topic + """. " + newline ...
267 % + "The structure of the report file appears to have been compromised. Skipping..." + newline ...
268 % + newline ...
269 % );
270 %end
271 %
272 %function reportMissingValue(topic)
273 % topic = string(strtrim(strrep(strrep(topic, newline, ' '), char(13), ' ')));
274 % warning ( newline ...
275 % + "Failed to parse the value corresponding to the record """ + topic + """. " + newline ...
276 % + "The structure of the report file appears to have been compromised. Skipping..." + newline ...
277 % + newline ...
278 % );
279 %end
280
281 function str = concat(lines)
282 % Concatenate the elements of an input cell array by
283 % the new line character and return the result as a single string.
284 str = string(join(lines, newline));
285 end
286
287 end
288
289 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
290
291 methods(Hidden)
292
293 %function result = isSectionHeader(self, record)
294 % result = self.dsymLen < length(record) && contains(record(1 : self.dsymLen), self.dsym);
295 %end
296 %
297 %function stopBeforeNextSectionHeader(self)
298 % % NOTE: if it is already within a section header, it will skip it and find the next section header.
299 % record = self.lineList{iend};
300 % isCurrentSectionHeader = self.dsymLen < length(record) && contains(record(1 : self.dsymLen), self.dsym);
301 % while true
302 % if iend == self.lineListLen
303 % break;
304 % end
305 % record = self.lineList{iend};
306 % if self.dsymLen < length(record) && contains(record(1 : self.dsymLen), self.dsym)
307 % if isCurrentSectionHeader
308 % iend = iend + 1;
309 % continue;
310 % else
311 % iend = iend - 1;
312 % break;
313 % end
314 % else
315 % isCurrentSectionHeader = false;
316 % iend = iend + 1;
317 % continue;
318 % end
319 % end
320 %end
321 %
322 %function skipCurrentSectionHeader(self)
323 % while true
324 % record = self.lineList{iend};
325 % if self.dsymLen < length(record) && contains(record(1 : self.dsymLen), self.dsym)
326 % iend = iend + 1;
327 % if iend == self.lineListLen
328 % break;
329 % end
330 % continue;
331 % else
332 % break;
333 % end
334 % end
335 %end
336 %
337 %function section = parseSection(self, topic)
338 % ilineLastSuccess = iend;
339 % topic = lower(topic);
340 % section = [];
341 % topicFound = false;
342 % while true
343 % iend = iend + 1;
344 % if self.lineListLen <= iend
345 % break;
346 % end
347 % record = lower(self.lineList{iend});
348 % if contains(record, topic)
349 % topicFound = true;
350 % break;
351 % else
352 % continue;
353 % end
354 % end
355 % if topicFound
356 % self.skipCurrentSectionHeader();
357 % lineStart = iend;
358 % self.stopBeforeNextSectionHeader();
359 % section = self.concat(lineStart, iend);
360 % else
361 % self.reportParseFailure(topic);
362 % iend = ilineLastSuccess;
363 % end
364 %end
365
366 function result = isdesc(self, record)
367 result = contains(record, self.prefix);
368 end
369
370 function iend = skipNull(self, ibeg)
371 % skip the empty lines after the current
372 % until encountering the first non-empty line.
373 iend = ibeg;
374 while true
375 if self.lineListLen < iend
376 break;
377 elseif ~isempty(strtrim(self.lineList{iend}))
378 break;
379 end
380 iend = iend + 1;
381 end
382 end
383
384 function iend = skipFull(self, ibeg)
385 % skip the nonempty lines after the current
386 % until encountering the first empty line.
387 iend = ibeg;
388 while true
389 if self.lineListLen < iend
390 break;
391 elseif isempty(strtrim(self.lineList{iend}))
392 break;
393 end
394 iend = iend + 1;
395 end
396 end
397
398 end
399
400 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
402end
function name(in vendor)
Return the MPI library name as used in naming the ParaMonte MATLAB shared libraries.
function version(in silent)
Return a scalar MATLAB string containing the latest available ParaMonte MATLAB version newer than the...
function banner()
Return a scalar MATLAB string containing the ParaMonte MATLAB library banner.
This is the base class for generating objects that contain the contents of a report file generated by...
function skipNull(in self, in ibeg)
function isdesc(in self, in record)
function skipFull(in self, in ibeg)
static function concat(in lines)
function FileContentsReport(in file, in silent, in method)
Return a scalar object of class pm.sampling.FileContentsReport.
This is the base class for generating objects that contain the contents of a given file.
Definition: FileContents.m:27
function compiler()
Return a scalar MATLAB logical that is true if and only if the current installation of MATLAB contain...
function find(in vendor)
Return a list of scalar MATLAB strings containing the paths to all detected mpiexec binaries installe...
function statistics()
Return a scalar MATLAB logical that is true if and only if the current installation of MATLAB contain...