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>
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.
12%> See below
for information on the attributes (properties).<br>
15%> See below
for information on the methods.<br>
20%> \JoshuaOsborne, May 21 2024, 1:13 AM, University of Texas at Arlington<br>
21%> \FatemehBagheri, May 20 2024, 1:25 PM, NASA Goddard Space Flight Center (GSFC), Washington, D.C.<br>
22%> \AmirShahmoradi, May 16 2016, 9:03 AM, Oden Institute
for Computational Engineering and Sciences (ICES), UT Austin<br>
25 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
27 properties(Access =
public)
31 %> The scalar MATLAB ``
struct`` containing the set of
32 %> computed properties extracted from the report file.<br>
38 %> The scalar MATLAB
string containing the entire
39 %> contents of the report file with all Carriage Return
40 %> characters removed (relevant only to Windows OS).<br>
46 %> The vector of MATLAB strings containing the set of
47 %> all lines in the report file with all Carriage Return
48 %> and New Line characters removed.<br>
54 %> The scalar MATLAB ``
struct`` containing the set of
55 %> predefined visualizations
for the output data.<br>
61 %> The scalar MATLAB ``
string`` containing the ParaMonte
62 %> library
banner as appearing in the report file.<br>
68 % % The scalar MATLAB ``
struct`` containing the sampler
69 % % setup information extracted from the report file.
75 % % The scalar MATLAB ``
struct`` containing the set of
76 % % simulation specifications extracted from the report file.
81 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
87 %> This is an internal
class variable inaccessible to the end users.<br>
93 % %> The scalar MATLAB integer representing the number of indentation
94 % %> characters at the beginning of each description line in the report file.<br>
95 % %> This is an internal
class variable inaccessible to the end users.<br>
97 % indentLen = 4; % indent length of the records
101 % %> The scalar MATLAB integer representing the minimum length of two of decoration symbols.<br>
102 % %> This is an internal
class variable inaccessible to the end users.<br>
108 %> The scalar MATLAB
string representing the decoration symbol used in
109 %> the report file, to be determined at runtime (currently ``%``).<br>
110 %> This is an internal
class variable inaccessible to the end users.<br>
116 %> The scalar MATLAB
string representing the prefix used in the description lines of the report file.<br>
117 %> This is an internal
class variable inaccessible to the end users.<br>
119 prefix =
' - NOTE: ';
123 %> The scalar MATLAB
string representing the sample
name.<br>
124 %> This is an internal
class variable inaccessible to the end users.<br>
130 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
132 methods(Access =
public)
135 %> Return a scalar
object of
class [pm.sampling.FileContentsReport](@ref
FileContentsReport).<br>
138 %> This is the constructor of the
class [pm.sampling.FileContentsReport](@ref
FileContentsReport).<br>
140 %> \param[in] file : The input scalar MATLAB
string containing the path to an external report file.<br>
141 %> \param[in] silent : See the corresponding argument of [pm.io.FileContents](@ref
FileContents)
class.<br>
142 %> (**optional**. The
default is set by [pm.io.FileContents](@ref
FileContents).)
143 %> \param[in] method : The input scalar MATLAB
string
144 %> containing the sampling method
name.<br>
145 %> The input value must be any of the following:<br>
147 %> <li> ``
"ParaDRAM"``
148 %> <li> ``
"ParaDISE"``
149 %> <li> ``
"ParaNest"``
151 %> (**optional**. If missing, some of the report file contents may not be properly parsed.)
154 %> ``self`` : The output scalar
object of
class [pm.sampling.FileContentsReport](@ref
FileContentsReport).<br>
160 %> contents = pm.sampling.FileContentsReport(file, [])
161 %> contents = pm.sampling.FileContentsReport(file, silent)
162 %> contents = pm.sampling.FileContentsReport(file, [], [])
163 %> contents = pm.sampling.FileContentsReport(file, silent, [])
164 %> contents = pm.sampling.FileContentsReport(file, silent, method)
172 %> \image html example/sampling/
Paradram/himmelblau/
Paradram.himmelblau.parallelism.speedup.scaling.strong.sameeff.png width=700
174 %> \image html example/sampling/
Paradram/himmelblau/
Paradram.himmelblau.parallelism.speedup.scaling.strong.zeroeff.png width=700
179 %> \JoshuaOsborne, May 21 2024, 1:30 AM, University of Texas at Arlington<br>
180 %> \FatemehBagheri, May 20 2024, 1:25 PM, NASA Goddard Space Flight Center (GSFC), Washington, D.C.<br>
181 %> \AmirShahmoradi, May 16 2016, 9:03 AM, Oden Institute
for Computational Engineering and Sciences (ICES), UT Austin<br>
187 self = self@pm.io.FileContents(file, silent);
189 self.
method = convertStringsToChars(method);
190 self.prefix = [self.method, self.prefix];
194 %%%% remove any CARRIAGE RETURN.
197 self.contents = strrep(fileread(file),
char(13),
'');
198 self.contents = strrep(self.contents, newline, [
' ', newline]);
199 self.lineList = strsplit(self.contents, newline);
200 self.lineListLen = length(self.lineList);
201 iend = 1; % the line we are about to parse.
203 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
204 %%%% determine the decoration symbol and read the
banner.
205 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
208 %%%% Here we assume the first non-empty line starts with the symbol character (likely ``%``).
211 ibeg = self.skipNull(iend);
212 failed = self.lineListLen < ibeg || length(self.lineList{ibeg}) < 4;
214 line = self.lineList{ibeg};
215 failed = any(line(1) ~= line(2 : 4));
217 iend = self.skipFull(ibeg + 1);
218 failed = self.lineListLen < iend;
223 self.banner = self.concat(self.lineList(ibeg : iend));
225 self.warn(line,
"Failed to detect the decoration symbol used in the report file.");
228 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
229 %%%% read the ParaMonte MATLAB library
interface specifications
230 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
232 %self.setup.library.interface = self.parseSection(
"interface.specifications");
234 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
236 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
238 %self.setup.library.compiler.version = self.parseSection(
"compiler.version");
240 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
241 %%%% read the ParaMonte MATLAB library
compiler options
242 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
244 %self.setup.library.compiler.options = self.parseSection(
"compiler.options");
246 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
247 %%%% read the Runtime platform specifications
248 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
250 %self.setup.platform = self.parseSection(
"runtime.platform.specifications");
252 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
253 %%%% read the simulation environment
254 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
256 %self.setup.io = self.parseSection(
"simulation.environment");
258 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
259 %%%% read the simulation specifications
260 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
262 %self.spec.base = self.parseSection(
"simulation.specifications.base");
263 %
if self.method ==
"ParaDRAM" || self.method ==
"ParaDISE"
264 % self.spec.mcmc = self.parseSection(
"simulation.specifications.mcmc");
265 % self.spec.dram = self.parseSection(
"simulation.specifications.dram");
266 %elseif self.method ==
"ParaNest"
267 % self.spec.nest = self.parseSection(
"simulation.specifications.nest");
270 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
271 %%%%
statistics:
this must be always the last item to parse
272 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
274 self.checkpoint(
"parsing the simulation statistics...", 1);
278 item = self.lineList{iend};
280 self.spinner.spin(iend / self.lineListLen);
282 if strcmp(item(1 : min(6, length(item))),
'stats.')
285 %%%% First non-empty line.
288 ibeg = self.skipNull(iend + 1);
289 failed = self.lineListLen < ibeg;
291 iend = self.skipFull(ibeg + 1);
292 failed = self.lineListLen < iend;
294 % Retrieve the value.
295 % The strategy is to read all values as table by dumping
296 % the value in a temporary file and reading it as a table.
297 tempfile = tempname();
298 fid = fopen(tempfile,
"w");
299 fprintf(fid, self.concat(strtrim(self.lineList(ibeg : iend - 1))));
301 df = readtable(tempfile);
302 %
if numel(df.Properties.VariableNames) == 1
303 %
if strcmpi(df.Properties.VariableNames(1),
"Var1")
304 % df.Properties.VariableNames(1) =
"value";
307 %self.(strtrim(item)).df = df;
308 eval([
'self.', strtrim(item),
'.df = df;']);
313 %%%% Retrieve the description.
316 ibeg = self.skipNull(iend + 1);
317 iend = self.skipFull(ibeg + 1);
318 if ~all(self.isdesc(self.lineList(ibeg : iend - 1)))
319 self.warn(
string(ibeg) + "-" +
string(iend), "A description record does not contain """ +
string(self.prefix) + """");
321 % Concatenate lines and remove prefixes from each description lines.
322 desc = strrep(self.concat(strtrim(self.lineList(ibeg : iend - 1))), self.prefix, '');
323 eval(['self.', strtrim(item), '.description = desc;']);
324 %self.(strtrim(item)).description = desc;
330 if self.lineListLen < iend
336 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
341 %%%% Add the
parallel scaling visualizations.
344 silent_kws = {
"silent", self.silent};
347 for parcond = [
"sameeff",
"zeroeff"]
348 if strcmp(parcond,
"sameeff")
349 titletext = "Strong Scaling: Current-Efficiency Sampling";
350 elseif strcmp(parcond, "zeroeff")
351 titletext = "Strong Scaling: Zero-Efficiency Sampling";
354 + "Internal ParaMonte library error occurred." + newline ...
355 + "Please report this error to the ParaMonte library developers." + newline ...
359 self.stats.parallelism.speedup.scaling.strong.(parcond).vis = struct();
360 self.stats.parallelism.speedup.scaling.strong.(parcond).vis.desc ...
361 = "This component is added in the post-processing phase to facilitate quick " ...
362 + "visualization of the
parallel scaling behavior of the sampler under the " + parcond + "
parallel conditions.";
363 self.stats.parallelism.speedup.scaling.strong.(parcond).vis.lineScatter = ...
364 pm.vis.
PlotLineScatter ( self.stats.parallelism.speedup.scaling.strong.(parcond).df ...
365 , "colx", 1, "coly", 2, "colc", 2, "axes", {
"xscale",
"log"} ...
366 ,
"scatter", {
"size", 10,
"color", pm.vis.color.rgb(
"red")} ...
367 ...,
"colormap", {
"enabled",
false,
"map",
"autumn"} ...
368 ,
"title", {
"enabled",
true,
"titletext", titletext} ...
369 ,
"plot", {
"linewidth", 2.5} ...
374 warning ( newline ...
375 +
"Failed to create the visualizations for the parallelization scaling behavior of the sampler." + newline ...
376 +
"It is possible that the component ``stats.parallelism.speedup.scaling.strong.(parcond).df`` of the " + newline ...
377 +
"output ``report`` object of class ``pm.sampling.FileContentsReport`` does not exist, where " + newline ...
378 +
"the string `parcond` can be either ``optimal`` or ``perfect``." + newline ...
379 +
"Here is the error message:" + newline ...
381 +
string(me.identifier) + newline +
string(me.message) + newline ...
387 %%%% Add the
parallel process contribution visualizations.
392 %%%% Set up the Cyclic Geometric fit to
parallel processes contributions.
395 cgfit = @(iproc, successProb, normFac, processCount) ...
396 successProb .* normFac .* (1 - successProb).^(iproc - 1) ./ (1 - (1 - successProb).^processCount);
399 %%%% Set up the data frame containing the processes contributions and its Cyclic Geometric fit to
parallel processes contributions.
402 dfpc = self.stats.parallelism.process.contribution.count.current.df;
403 dfpc.cyclicGeometricFit = cgfit ( dfpc.processID ...
404 , self.stats.parallelism.process.contribution.count.current.fit.df.successProb ...
405 , self.stats.parallelism.process.contribution.count.current.fit.df.normFac ...
406 , self.stats.parallelism.process.count.current.df.Var1 ...
408 self.stats.parallelism.process.contribution.count.current.vis =
struct();
409 self.stats.parallelism.process.contribution.count.current.vis.desc = ...
410 "This component is added in the post-processing phase to facilitate quick " + ...
411 "visualization of the contributions of the parallel processes to the final chain.";
412 self.stats.parallelism.process.contribution.count.current.vis.line = ...
413 pm.vis.PlotLine ( dfpc ...
414 ,
"colx",
"processID",
"coly", 2:3,
"axes", {
"xscale",
"log",
"yscale",
"log"} ...
415 ,
"ylabel", {
"txt",
"Accepted-Sample Contribution"} ...
416 ,
"xlabel", {
"txt",
"Process ID"} ...
417 ,
"colormap", {
"enabled",
false} ...
418 ,
"legend", {
"enabled",
true} ...
419 ,
"plot", {
"linewidth", 2.5} ...
423 warning ( newline ...
424 +
"Failed to create the visualizations for the parallel processes contributions and their Cyclic Geomtric fit." + newline ...
425 +
"It is possible that the component ``stats.parallelism.current.process.contribution`` of the " + newline ...
426 +
"output ``report`` object of class ``pm.sampling.FileContentsReport`` does not exist, or " + newline ...
427 +
"its sub-components are missing." + newline ...
428 +
"Here is the error message:" + newline ...
430 +
string(me.identifier) + newline +
string(me.message) + newline ...
437 end % methods(Access =
public)
439 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
441 methods(Hidden, Static)
443 %function reportParseFailure(topic)
444 % topic = string(strtrim(strrep(strrep(topic, newline,
' '),
char(13),
' ')));
445 % warning ( newline ...
446 % +
"Failed to parse the record """ + topic +
""". " + newline ...
447 % +
"The structure of the report file appears to have been compromised. Skipping..." + newline ...
452 %function reportMissingValue(topic)
453 % topic = string(strtrim(strrep(strrep(topic, newline,
' '),
char(13),
' ')));
454 % warning ( newline ...
455 % +
"Failed to parse the value corresponding to the record """ + topic +
""". " + newline ...
456 % +
"The structure of the report file appears to have been compromised. Skipping..." + newline ...
461 function str = concat(lines)
462 % Concatenate the elements of an input cell array by
463 % the
new line character and
return the result as a single
string.
464 str = string(join(lines, newline));
469 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
473 %function result = isSectionHeader(self, record)
474 % result = self.dsymLen < length(record) && contains(record(1 : self.dsymLen), self.dsym);
477 %function stopBeforeNextSectionHeader(self)
478 % % NOTE:
if it is already within a section header, it will skip it and
find the next section header.
479 % record = self.lineList{iend};
480 % isCurrentSectionHeader = self.dsymLen < length(record) && contains(record(1 : self.dsymLen), self.dsym);
482 %
if iend == self.lineListLen
485 % record = self.lineList{iend};
486 %
if self.dsymLen < length(record) && contains(record(1 : self.dsymLen), self.dsym)
487 %
if isCurrentSectionHeader
495 % isCurrentSectionHeader =
false;
502 %function skipCurrentSectionHeader(self)
504 % record = self.lineList{iend};
505 %
if self.dsymLen < length(record) && contains(record(1 : self.dsymLen), self.dsym)
507 %
if iend == self.lineListLen
517 %function section = parseSection(self, topic)
518 % ilineLastSuccess = iend;
519 % topic = lower(topic);
521 % topicFound =
false;
524 %
if self.lineListLen <= iend
527 % record = lower(self.lineList{iend});
528 %
if contains(record, topic)
536 % self.skipCurrentSectionHeader();
538 % self.stopBeforeNextSectionHeader();
539 % section = self.concat(lineStart, iend);
541 % self.reportParseFailure(topic);
542 % iend = ilineLastSuccess;
546 function result = isdesc(self, record)
547 result = contains(record, self.prefix);
550 function iend = skipNull(self, ibeg)
551 % skip the empty lines after the current
552 % until encountering the first non-empty line.
555 if self.lineListLen < iend
557 elseif ~isempty(strtrim(self.lineList{iend}))
564 function iend = skipFull(self, ibeg)
565 % skip the nonempty lines after the current
566 % until encountering the first empty line.
569 if self.lineListLen < iend
571 elseif isempty(strtrim(self.lineList{iend}))
580 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function name(in vendor)
Return the MPI library name as used in naming the ParaMonte MATLAB shared library directories.
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.
This is the ParaDRAM class for generating instances of serial and parallel Delayed-Rejection Adaptive...
This is the PlotLineScatter class for generating instances of 2-dimensional Line-Scatter Plot visuali...
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 parallel()
Return a scalar MATLAB logical that is true if and only if the current installation of MATLAB contain...
function statistics()
Return a scalar MATLAB logical that is true if and only if the current installation of MATLAB contain...