ParaMonte MATLAB 3.0.0
Parallel Monte Carlo and Machine Learning Library
See the latest version documentation.
Triplex.m
Go to the documentation of this file.
1%> \brief
2%> This is the base class for generating instances of
3%> figures containing a square symmetric tiling of subplots.<br>
4%>
5%> \details
6%> This class generates figures containing three types of plots in the
7%> upper-triangle, lower-triangle, and diagonal subplots of the figure.<br>
8%> For more information, see the documentation of the class constructor [pm.vis.Triplex.Triplex](@ref Triplex::Triplex).<br>
9%>
10%> \note
11%> This class is not meant to be used directly by the end users.<br>
12%> Instead, use the subclasses of this parent class.<br>
13%>
14%> \note
15%> See the list of class attributes below,
16%> also those of the superclass [pm.vis.figure.Figure](@ref Figure).<br>
17%>
18%> \todo
19%> \phigh
20%> The ``hideShow()`` method of this class still has unresolved bugs that lead to missing X and Y axes labels and tick marks.<br>
21%> Consequently, the ``show()`` and ``hide()`` class methods are also unavailable until the issues are resolved.<br>
22%> For now, all of these functionalities are commented out.<br>
23%> A simple bypass is to generate tilings with prior contemplation about
24%> its design so that post-visualization modifications are unnecessary.<br>
25%>
26%> \final
27%>
28%> \author
29%> \AmirShahmoradi, August 31 2024, 6:40 AM, NASA Goddard Space Flight Center (GSFC), Washington, D.C.<br>
30classdef Triplex < pm.vis.figure.Figure
31
32 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
33
34 properties(Access = public)
35 %>
36 %> ``layout``
37 %>
38 %> The scalar object of class [pm.vis.TilingLayout](@ref TilingLayout)
39 %> containing the default layout of the Triplex plot.<br>
40 %> The information includes the subplots and colorbar positions.<br>
41 %> This information is applied only to figure
42 %> components whose positions are unset.<br>
43 %>
44 layout = [];
45 %>
46 %> ``diago``
47 %>
48 %> The scalar object of superclass [pm.vis.Subplot](@ref Subplot)
49 %> representing the template of the diagonal subplots to display.<br>
50 %> Note that only the visualization properties of the template are used.<br>
51 %> The data properties of the template are set by the ``make()`` method.<br>
52 %> (**optional**. The default value is [pm.vis.SubplotHistogram](@ref SubplotHistogram).)
53 %>
54 diago = [];
55 %>
56 %> ``lower``
57 %>
58 %> The scalar object of superclass [pm.vis.Subplot](@ref Subplot)
59 %> representing the template of the lower-triangle subplots to display.<br>
60 %> The data properties of the template are set by the ``make()`` method.<br>
61 %> (**optional**. The default value is [pm.vis.SubplotContour](@ref SubplotContour).)
62 %>
63 lower = [];
64 %>
65 %> ``upper``
66 %>
67 %> The scalar object of superclass [pm.vis.Subplot](@ref Subplot)
68 %> representing the template of the upper-triangle subplots to display.<br>
69 %> The data properties of the template are set by the ``make()`` method.<br>
70 %> (**optional**. The default value is [pm.vis.SubplotLineScatter](@ref SubplotLineScatter).)
71 %>
72 upper = [];
73 %>
74 %> ``tile``
75 %>
76 %> The MATLAB cell matrix containing objects of superclass [pm.vis.Subplot](@ref Subplot)
77 %> each of which represents one tile (subplot) axes to display in the figure.<br>
78 %>
79 tile = cell(0, 0);
80 end
81
82 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
83
84 properties(Access = public, Hidden)
85 %>
86 %> ``diagYTick``
87 %>
88 %> The MATLAB ``cell`` vector of length `nrow``, containing the diagonal y-tick labels.<br>
89 %>
90 %> \warning
91 %> This is an internal ``Hidden`` class attribute
92 %> that is inaccessible to the end users.<br>
93 %>
94 diagYTick = struct();
95 end
96
97 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
98
99 methods(Access = public)
100
101 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
103 %> \brief
104 %> Construct and return an object of class [pm.vis.Triplex](@ref Triplex).<br>
105 %>
106 %> \details
107 %> This is the constructor of the class [pm.vis.Triplex](@ref Triplex).<br>
108 %> The input dataset to each plot section is assumed to be common among all plots (though not necessarily).<br>
109 %> As such, all axes labels and tick marks of all subplots are dropped by default,
110 %> except for subplots in the left and bottom boundaries of the figure.<br>
111 %>
112 %> If any of the three input subplot types has colorbar, it is disabled for individual subplots.<br>
113 %> Instead, universal colorbar(s) will be added to the right and top sides of the Triplex plot.<br>
114 %>
115 %> \param[in] lower : The input scalar MATLAB object of superclass [pm.vis.Subplot](@ref Subplot) containing information for
116 %> the kind the subplot that must be added to the lower-triangular elements of the Triplex matrix of subplots.<br>
117 %> (**optional**, default = ``[]``. If empty, no lower-triangular subplots will be visualized.)
118 %> \param[in] diago : The input scalar MATLAB object of superclass [pm.vis.Subplot](@ref Subplot) containing information for
119 %> the kind the subplot that must be added to the diagonal elements of the Triplex matrix of subplots.<br>
120 %> (**optional**, default = ``[]``. If empty, no diagonal subplots will be visualized.)
121 %> \param[in] upper : The input scalar MATLAB object of superclass [pm.vis.Subplot](@ref Subplot) containing information for
122 %> the kind the subplot that must be added to the upper-triangular elements of the Triplex matrix of subplots.<br>
123 %> (**optional**, default = ``[]``. If empty, no upper-triangular subplots will be visualized.)
124 %> \param[in] varargin : Any ``property, value`` pair of the parent object.<br>
125 %> If the property is a ``struct()``, then its value must be given as a cell array,
126 %> with consecutive elements representing the struct ``property-name, property-value`` pairs.<br>
127 %> Note that all of these property-value pairs can be also directly set via the
128 %> parent object attributes, before calling the ``make()`` method.<br>
129 %>
130 %> \return
131 %> ``self`` : The output scalar object of class [pm.vis.Triplex](@ref Triplex).<br>
132 %>
133 %> \interface{Triplex}
134 %> \code{.m}
135 %>
136 %> g = pm.vis.Triplex(diago, [], [], varargin);
137 %> g = pm.vis.Triplex([], [], upper, varargin);
138 %> g = pm.vis.Triplex([], lower, [], varargin);
139 %>
140 %> g = pm.vis.Triplex(diago, lower, [], varargin);
141 %> g = pm.vis.Triplex(diago, [], upper, varargin);
142 %> g = pm.vis.Triplex([], lower, upper, varargin);
143 %>
144 %> g = pm.vis.Triplex(lower, diago, upper, varargin);
145 %>
146 %> \endcode
147 %>
148 %> \warning
149 %> The data columns to be plotted in each Triplex section must be consistent with other sections.<br>
150 %> Failure to ensure this will lead to undefined behavior and possibly a runtime error.<br>
151 %>
152 %> \note
153 %> See the list of class attributes below,
154 %> also those of the superclass [pm.vis.figure.Figure](@ref Figure).<br>
155 %>
156 %> \example{Triplex}
157 %> \include{lineno} example/vis/Triplex/main.m
158 %> \vis{Triplex}
159 %> <br><br>
160 %> \image html example/vis/Triplex/Triplex.1.png width=700
161 %> <br><br>
162 %> \image html example/vis/Triplex/Triplex.2.png width=700
163 %> <br><br>
164 %> \image html example/vis/Triplex/Triplex.3.png width=700
165 %> <br><br>
166 %> \image html example/vis/Triplex/Triplex.4.png width=700
167 %> <br><br>
168 %> \image html example/vis/Triplex/Triplex.5.png width=700
169 %> <br><br>
170 %> \image html example/vis/Triplex/Triplex.6.png width=700
171 %>
172 %> \final{Triplex}
173 %>
174 %> \author
175 %> \AmirShahmoradi, August 31 2024, 6:40 AM, NASA Goddard Space Flight Center (GSFC), Washington, D.C.<br>
176 function self = Triplex(lower, diago, upper, varargin)
177
178 varargin = {"lower", lower, "diago", diago, "upper", upper, varargin{:}};
179 self = self@pm.vis.figure.Figure(varargin{:});
180
181 end
182
183 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
184
185 %> \brief
186 %> Reset the properties of the figure to the original default settings.<br>
187 %>
188 %> \details
189 %> Use this method when you change many attributes of the plot and
190 %> you want to clean up and go back to the default settings.<br>
191 %>
192 %> \param[in] self : The **implicitly-passed** input argument representing the parent object of the method.<br>
193 %> \param[in] varargin : Any ``property, value`` pair of the parent object.<br>
194 %> If the property is a ``struct()``, then its value must be given as a cell array,
195 %> with consecutive elements representing the struct ``property-name, property-value`` pairs.<br>
196 %> Note that all of these property-value pairs can be also directly set via the
197 %> parent object attributes, before calling the ``make()`` method.<br>
198 %>
199 %> \interface{reset}
200 %> \code{.m}
201 %>
202 %> g = pm.vis.Triplex(lower, diago, upper, varargin);
203 %> g.reset(varargin); % reset all object properties to the default settings.
204 %>
205 %> \endcode
206 %>
207 %> \final{reset}
208 %>
209 %> \author
210 %> \JoshuaOsborne, May 21 2024, 9:25 AM, University of Texas at Arlington<br>
211 %> \FatemehBagheri, May 20 2024, 1:25 PM, NASA Goddard Space Flight Center (GSFC), Washington, D.C.<br>
212 %> \AmirShahmoradi, July 7 2024, 12:53 AM, NASA Goddard Space Flight Center (GSFC), Washington, D.C.<br>
213 function reset(self, varargin)
214
215 reset@pm.vis.figure.Figure(self, varargin{:});
216
217 %%%%
218 %%%% Ensure equal number of data columns are specified.
219 %%%%
220
221 nrow = [];
222 ncol = [];
223 shape = struct("lower", [], "upper", []);
224 for comp = ["lower", "upper"]
225 if isa(self.(comp), "pm.vis.SubplotEllipsoid3")
226 shape.(comp) = [numel(self.(comp).dimy), numel(self.(comp).dimx)];
227 elseif isa(self.(comp), "pm.vis.Subplot") && isprop(self.(comp), "coly")
228 shape.(comp) = [numel(self.(comp).coly), numel(self.(comp).colx)];
229 elseif ~isempty(self.(comp))
230 help("pm.vis.Triplex");
231 disp("class(self.(comp))");
232 disp( class(self.(comp)) );
233 error ( newline ...
234 + "The specified upper/lower triangular component must be a 2D X-Y" + newline ...
235 + "subplot object of superclass ``pm.vis.SubplotEllipsoid3`` or ``pm.vis.Subplot``." + newline ...
236 + "For more information, see the class documentation displayed above." + newline ...
237 + newline ...
238 );
239 end
240 if ~isempty(self.(comp))
241 nrow = shape.(comp)(1);
242 ncol = shape.(comp)(2);
243 end
244 end
245
246 if ~isempty(shape.lower) && ~isempty(shape.upper) % lower and upper both present.
247 if ~all(shape.lower == shape.upper)
248 help("pm.vis.Triplex");
249 disp("shape.lower");
250 disp( shape.lower );
251 disp("shape.upper");
252 disp( shape.upper );
253 error ( newline ...
254 + "The corresponding number of x and y columns in the specified input" + newline ...
255 + "``lower``, ``diago``, and ``upper`` subplot templates must be equal." + newline ...
256 + "For more information, see the class documentation displayed above." + newline ...
257 + newline ...
258 );
259 end
260 elseif ~isempty(nrow) && ~isempty(ncol) && isa(self.diago, "pm.vis.Subplot") % either lower or upper present.
261 if numel(self.diago.colx) ~= min(nrow, ncol)
262 help("pm.vis.Triplex");
263 disp("[nrow, ncol]");
264 disp( [nrow, ncol] );
265 disp("numel(self.diago.colx)");
266 disp( numel(self.diago.colx) );
267 error ( newline ...
268 + "The condition ``numel(self.diago.colx) == min(nrow, ncol)`` must hold." + newline ...
269 + "For more information, see the class documentation displayed above." + newline ...
270 + newline ...
271 );
272 end
273 elseif isa(self.diago, "pm.vis.Subplot") % neither lower nor upper present.
274 nrow = numel(self.diago.colx);
275 ncol = numel(self.diago.colx);
276 elseif ~isempty(self.diago)
277 help("pm.vis.Triplex");
278 error ( newline ...
279 + "The input ``diago`` must be 1D plotting object of type number of x and y columns in the specified input" + newline ...
280 + "``lower``, ``diago``, and ``upper`` subplot templates must be equal." + newline ...
281 + "For more information, see the class documentation displayed above." + newline ...
282 + newline ...
283 );
284 end
285
286 if ~isempty(nrow) && ~isempty(ncol)
287 self.layout = pm.vis.TilingLayout(nrow, ncol);
288 self.layout.cbarv.enabled = [];
289 self.layout.cbarh.enabled = [];
290 else
291 help("pm.vis.Triplex");
292 disp("class(self.lower)");
293 disp( class(self.lower) );
294 disp("class(self.diago)");
295 disp( class(self.diago) );
296 disp("class(self.upper)");
297 disp( class(self.upper) );
298 error ( newline ...
299 + "The Triplex class constructor could not determine" + newline ...
300 + "the tiling shape from the specified input arguments." + newline ...
301 + "For more information, see the class documentation displayed above." + newline ...
302 + newline ...
303 );
304 end
305
306 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
307 %%%% RULE 0: Any non-MATLAB-default setting must be preferably set in the make() method to override user null values.
308 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
309
310 %self.premake(varargin{:}); % This is the subclass method!
311
312 end
313
314 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
315
316 %> \brief
317 %> Preset the tiling settings before making it.<br>
318 %>
319 %> \param[in] self : The **implicitly-passed** input argument representing the parent object of the method.<br>
320 %> \param[in] varargin : Any ``property, value`` pair of the parent object.<br>
321 %> If the property is a ``struct()``, then its value must be given as a cell array,
322 %> with consecutive elements representing the struct ``property-name, property-value`` pairs.<br>
323 %> Note that all of these property-value pairs can be also directly set via the
324 %> parent object attributes, before calling the ``make()`` method.<br>
325 %>
326 %> \interface{premake}
327 %> \code{.m}
328 %>
329 %> g = pm.vis.Triplex(lower, diago, upper, varargin);
330 %> g.premake(varargin);
331 %>
332 %> \endcode
333 %>
334 %> \warning
335 %> This method causes side-effects by manipulating
336 %> the existing attributes of the object.<br>
337 %>
338 %> \final{premake}
339 %>
340 %> \author
341 %> \JoshuaOsborne, May 21 2024, 9:28 AM, University of Texas at Arlington<br>
342 %> \FatemehBagheri, May 20 2024, 1:25 PM, NASA Goddard Space Flight Center (GSFC), Washington, D.C.<br>
343 %> \AmirShahmoradi, July 7 2024, 12:53 AM, NASA Goddard Space Flight Center (GSFC), Washington, D.C.<br>
344 function premake(self, varargin)
345
346 premake@pm.vis.figure.Figure(self, varargin{:});
347
348 %%%%
349 %%%% Reposition figure.
350 %%%%
351
352 if isempty(self.figure.position)
353 self.figure.position = self.layout.position;
354 end
356 %%%%
357 %%%% Update the fontsize settings.
358 %%%%
359
360 for comp = ["lower", "diago", "upper"]
361 if isa(self.(comp), "pm.vis.Subplot")
362 for prop = ["axes", "xlabel", "ylabel", "zlabel", "colorbar"]
363 if isprop(self.(comp), prop)
364 if ~isfield(self.(comp).(prop), "fontSize") || isempty(self.(comp).(prop).fontSize)
365 self.(comp).(prop).fontSize = 12;
366 end
367 end
368 end
369 end
370 end
371
372 %%%%
373 %%%% Update the tiling layout to match the latest settings.
374 %%%%
375
376 if isempty(self.layout.cbarv.enabled)
377 self.layout.cbarv.enabled = ~isempty(self.lower);
378 if self.layout.cbarv.enabled && isempty(self.lower.cenabled)
379 self.lower.premake();
380 self.layout.cbarv.enabled = self.lower.cenabled && ~self.lower.colorbar.enabled;
381 end
382 if ~self.layout.cbarv.enabled && ~isempty(self.upper)
383 if isempty(self.upper.cenabled)
384 self.upper.premake();
385 end
386 self.layout.cbarv.enabled = self.upper.cenabled && ~self.upper.colorbar.enabled;
387 end
388 end
389 if isempty(self.layout.cbarh.enabled)
390 %%%% Activate cbarh only after cbarv is activated.
391 self.layout.cbarh.enabled = self.layout.cbarv.enabled && ~isempty(self.lower) && ~isempty(self.upper);
392 self.layout.cbarh.enabled = self.layout.cbarh.enabled && self.lower.cenabled && ~self.lower.colorbar.enabled;
393 if self.layout.cbarh.enabled
394 if isempty(self.upper.cenabled)
395 self.upper.premake();
396 end
397 self.layout.cbarh.enabled = self.upper.cenabled && ~self.upper.colorbar.enabled;
398 end
399 end
400 self.layout.update();
401
402 end
403
404 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
405
406 %> \brief
407 %> Configure the figure settings and specifications,
408 %> make the figure and the subplots, and return nothing.<br>
409 %>
410 %> \details
411 %> The subplots are made by calling their ``make()`` methods.<br>
412 %>
413 %> \param[in] self : The **implicitly-passed** input argument representing the parent object of the method.<br>
414 %> \param[in] varargin : Any ``property, value`` pair of the parent object.<br>
415 %> If the property is a ``struct()``, then its value must be given as a cell array,
416 %> with consecutive elements representing the struct ``property-name, property-value`` pairs.<br>
417 %> Note that all of these property-value pairs can be also directly set via the
418 %> parent object attributes, before calling the ``make()`` method.<br>
419 %>
420 %> \interface{make}
421 %> \code{.m}
422 %>
423 %> g = pm.vis.Triplex(lower, diago, upper, varargin);
424 %> g.make(varargin);
425 %>
426 %> \endcode
427 %>
428 %> \warning
429 %> This method has side-effects by manipulating
430 %> the existing attributes of the parent object.<br>
431 %>
432 %> \final{make}
433 %>
434 %> \author
435 %> \AmirShahmoradi, July 7 2024, 12:53 AM, NASA Goddard Space Flight Center (GSFC), Washington, D.C.<br>
436 function make(self, varargin)
437
438 make@pm.vis.figure.Figure(self, varargin{:});
439
440 self.fout.axes = axes ( "Parent", self.fout.figure ...
441 , "position", self.layout.tiling.position ...
442 , "xlim", [0, 1], "ylim", [0, 1] ...
443 , "visible", "off" ...
444 , "color", "none" ...
445 );
446
447 %%%%
448 %%%% Define the subplot cell matrix.
449 %%%%
450
451 iplt = 0;
452 timer = pm.timing.Timer();
453 spinner = pm.timing.Spinner();
454 self.tile = cell(self.layout.tiling.nrow, self.layout.tiling.ncol);
455 self.diagYTick = cell(min(self.layout.tiling.nrow, self.layout.tiling.ncol), 1);
456 for icol = 1 : self.layout.tiling.ncol
457 for irow = 1 : self.layout.tiling.nrow
458
459 iplt = iplt + 1;
460 if ~self.silent
461 spinner.spin(iplt / numel(self.tile));
462 end
463
464 %%%%
465 %%%% Copy data from template to the current tile.
466 %%%%
467
468 comp = [];
469 if icol < irow && ~isempty(self.lower)
470 comp = "lower";
471 elseif icol == irow && ~isempty(self.diago)
472 comp = "diago";
473 elseif icol > irow && ~isempty(self.upper)
474 comp = "upper";
475 end
476
477 if ~isempty(comp)
478
479 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
480 %%%% The byte stream approach leads to serious problems with
481 %%%% figures when generated from within sampler components.
482 %self.tile{irow, icol} = getArrayFromByteStream(getByteStreamFromArray(self.(comp)));
483 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
484 self.tile{irow, icol} = pm.matlab.copy(self.(comp), eval(string(class(self.(comp))) + "()"));
485 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
486
487 %%%%
488 %%%% Set the data columns to plot in the current tile.
489 %%%%
490
491 if isa(self.tile{irow, icol}, "pm.vis.SubplotEllipse3")
492 self.tile{irow, icol}.dimx = self.tile{irow, icol}.dimx(icol);
493 self.tile{irow, icol}.dimy = self.tile{irow, icol}.dimy(irow);
494 elseif isa(self.tile{irow, icol}, "pm.vis.Subplot")
495 if isprop(self.tile{irow, icol}, "colx")
496 self.tile{irow, icol}.colx = self.tile{irow, icol}.colx(icol);
497 end
498 if isprop(self.tile{irow, icol}, "coly")
499 self.tile{irow, icol}.coly = self.tile{irow, icol}.coly(irow);
500 end
501 elseif ~isempty(self.tile{irow, icol})
502 error ( newline ...
503 + "Unrecognized/unsupported class: " + string(class(self.tile{irow, icol})) + newline ...
504 + "For more information, see the documentation displayed above." + newline ...
505 + newline ...
506 );
507 end
508
509 if ~isempty(self.tile{irow, icol})
510
511 %%%%
512 %%%% Set the current tile position.
513 %%%%
514
515 self.tile{irow, icol}.axes.position = self.layout.tiling.tile.position(:, irow, icol);
516 self.tile{irow, icol}.axes.visible = "on";
517 self.tile{irow, icol}.axes.box = "on";
518
519 %%%%
520 %%%% Create the current tile axes.
521 %%%%
522
523 axes_kws = self.tile{irow, icol}.comp2hash("axes");
524 axes(axes_kws{:});
525
526 %%%%
527 %%%% Make the subplot.
528 %%%%
529
530 self.tile{irow, icol}.make();
531
532 %%%%
533 %%%% Set the diagonal YTicks
534 %%%%
535
536 if irow == icol
537 xlower = self.tile{irow, icol}.fout.axes.XLim(1);
538 xupper = self.tile{irow, icol}.fout.axes.XLim(2);
539 xrange = xupper - xlower;
540 ylower = self.tile{irow, icol}.fout.axes.YLim(1);
541 yupper = self.tile{irow, icol}.fout.axes.YLim(2);
542 yrange = yupper - ylower;
543 self.diagYTick{irow}.original = struct();
544 self.diagYTick{irow}.modified = struct();
545 self.diagYTick{irow}.original.values = self.tile{irow, icol}.fout.axes.YTick;
546 self.diagYTick{irow}.original.labels = self.tile{irow, icol}.fout.axes.YTickLabel;
547 self.diagYTick{irow}.modified.values = (self.tile{irow, icol}.fout.axes.XTick - xlower) * yrange / xrange + ylower;
548 self.diagYTick{irow}.modified.labels = self.tile{irow, icol}.fout.axes.XTickLabel;
549 end
550
551 end
552
553 end
554
555 end
556 end
557
558 %%%%
559 %%%% Reset the marginal axes labels.
560 %%%%
561
562 self.hideShowAxesLabels();
563
564 %%%%
565 %%%% Add colorbars.
566 %%%%
567
568 shown = struct();
569 shown.cbarh = false;
570 shown.cbarv = false;
571 indexlist = [ self.layout.tiling.nrow, 1 ... lower
572 ; 1, self.layout.tiling.ncol ... upper
573 ; self.layout.tiling.nrow, self.layout.tiling.ncol ... diago
574 ]';
575 location = struct();
576 location.cbarv = "east";
577 location.cbarh = "north";
578 for icomp = 1 : size(indexlist, 2)
579 irow = indexlist(1, icomp);
580 icol = indexlist(2, icomp);
581 if ~isempty(self.tile{irow, icol}) && isprop(self.tile{irow, icol}, "cenabled") && self.tile{irow, icol}.cenabled
582 for cbar = ["cbarv", "cbarh"]
583 if ~shown.(cbar) && self.layout.(cbar).enabled
584
585 %%%%
586 %%%% Make a dummy plot with colorbar from the corresponding tile in the main axes.
587 %%%%
588
589 kws = {"position", self.layout.tiling.position, "xlim", [0, 1], "ylim", [0, 1], "visible", "off", "color", "none"};
590 dumaxes = axes("Parent", self.fout.figure, kws{:});
591
592 set(self.fout.figure, 'CurrentAxes', dumaxes);
593 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
594 %%%% The byte stream approach leads to serious problems with
595 %%%% figures when generated from within sampler components.
596 %dumplot = getArrayFromByteStream(getByteStreamFromArray(self.tile{irow, icol}));
597 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
598 dumplot = pm.matlab.copy(self.tile{irow, icol}, eval(string(class(self.tile{irow, icol})) + "()"), [], "fout");
599 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
600 dumplot.colorbar.position = self.layout.(cbar).position;
601 dumplot.colorbar.location = location.(cbar);
602 dumplot.colorbar.enabled = true;
603 if isprop(dumplot, "axes") % Heatmap plots do not have axes property.
604 dumplot.make("axes", kws)
605 else
606 dumplot.make("axes")
607 end
608 dumaxes.Visible = "off";
609 set([dumaxes; dumaxes.Children], 'Visible', 'off');
610
611 %kws = self.tile{irow, icol}.comp2hash("colorbar");
612 %self.fout.(cbar) = colorbar(dumaxes, kws{:}, "position", self.layout.(cbar).position, "location", location.(cbar));
613 %dfcopy = self.tile{irow, icol}.df.copy();
614 %if ~isprop(self.tile{irow, icol}, "colc")
615 % colnamc = ["Density"];
616 %elseif ~isempty(self.tile{irow, icol}.colc)
617 % [~, colnamc] = pm.str.locname(dfcopy.Properties.VariableNames, self.tile{irow, icol}.colc);
618 %else
619 % colnamc = "Row Index";
620 %end
621 %xlabel(self.fout.(cbar), colnamc(1));
622 %cmap = colormap(self.tile{irow, icol}.fout.axes);
623 %if ~isfield(self.fout, "colormap")
624 % self.fout.colormap = struct();
625 %end
626 %self.fout.colormap.(cbar) = colormap(self.fout.(cbar), cmap);
627 shown.(cbar) = true;
628 break;
629
630 end
631 end
632 if shown.cbarh && shown.cbarv
633 break;
634 end
635 end
636 end
637
638 try
639 self.setAxesLimits();
640 catch me
641 warning ( newline ...
642 + string(me.identifier) + " : " + string(me.message) + newline ...
643 + "Failed to readjust the subplot limits. skipping..." + newline ...
644 + newline ...
645 );
646 end
647
648 if ~self.silent
649 disp("done in " + sprintf("%.6f", string(timer.toc())) + " seconds.");
650 end
651
652 end % function
653
654 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
655
656 %> \brief
657 %> Rotate the axes labels of the subplots of the Triplex, and return nothing.<br>
658 %>
659 %> \details
660 %> All axes labels in the tiling will be impacted by this routine,
661 %> even though only a selected subset might be visible.<br>
662 %>
663 %> \param[in] self : The **implicitly-passed** input argument representing the parent object of the method.<br>
664 %> \param[in] degx : The input scalar MATLAB positive whole-number, representing the amount of
665 %> rotation to be applied to the x-axis labels with respect to the horizontal line.<br>
666 %> If it is set to empty ``[]``, the axis label orientation will remain intact.<br>
667 %> (**optional**, default = ``45``. It must be present if and only if ``degy`` is also present.)
668 %> \param[in] degy : The input scalar MATLAB positive whole-number, representing the amount of
669 %> rotation to be applied to the y-axis labels with respect to the horizontal line.<br>
670 %> If it is set to empty ``[]``, the axis label orientation will remain intact.<br>
671 %> (**optional**, default = ``45``. It must be present if and only if ``degx`` is also present.)
672 %>
673 %> \interface{rotateAxesLabels}
674 %> \code{.m}
675 %>
676 %> g = pm.vis.Triplex(lower, diago, upper, varargin);
677 %> g.make(varargin);
678 %>
679 %> g.rotateAxesLabels(); % rotate all axes labels by 45 degrees.
680 %> g.rotateAxesLabels(degx, []); % rotate x-axis labels by ``degx`` degrees.
681 %> g.rotateAxesLabels([], degy); % rotate y-axis labels by ``degy`` degrees.
682 %> g.rotateAxesLabels(degx, degy); % rotate x-axis and y-axis labels by ``degx`` and ``degy`` degrees.
683 %>
684 %> \endcode
685 %>
686 %> \warning
687 %> This method has side-effects by manipulating the existing attributes of the parent object.<br>
688 %>
689 %> \final{rotateAxesLabels}
690 %>
691 %> \author
692 %> \AmirShahmoradi, July 7 2024, 12:53 AM, NASA Goddard Space Flight Center (GSFC), Washington, D.C.<br>
693 function rotateAxesLabels(self, degx, degy)
694 if nargin < 2
695 degx = 45;
696 degy = 45;
697 elseif nargin ~= 3
698 help("pm.vis.Triplex.rotateAxesLabels");
699 error ( newline ...
700 + "The ``rotateAxesLabels()`` method takes either no or exactly two input arguments." + newline ...
701 + "If no argument is passed, axes labels will be rotated 45 degrees." + newline ...
702 + "For more information, see the class documentation displayed above." + newline ...
703 + newline ...
704 );
705 end
706 for icol = 1 : size(self.tile, 2)
707 for irow = 1 : size(self.tile, 1)
708 self.tile{irow, icol}.fout.axes.XLabel.Rotation = degx;
709 self.tile{irow, icol}.fout.axes.YLabel.Rotation = degy;
710 self.tile{irow, icol}.fout.axes.XLabel.VerticalAlignment = "top";
711 self.tile{irow, icol}.fout.axes.YLabel.VerticalAlignment = "middle";
712 self.tile{irow, icol}.fout.axes.XLabel.HorizontalAlignment = "right";
713 self.tile{irow, icol}.fout.axes.YLabel.HorizontalAlignment = "right";
714 end
715 end
716 end % rotateAxesLabels
717
718 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
719
720 %> \brief
721 %> Set the axes x-y limits of the subplots that are currently
722 %> present in the GridPlot to the input user-provided values.<br>
723 %>
724 %> \param[in] self : The **implicitly-passed** input argument representing the parent object of the method.<br>
725 %> \param[in] limits : A MATLAB ``cell`` vector of maximum length ``max(size(self.tile))``,
726 %> each element of which corresponds to one row of the Triplex plot, from the top-left corner.<br>
727 %> Each element of the cell array must be a real vector of length ``2`` whose values determine the
728 %> lower and upper limits of the vertical axis of the corresponding subplot in the visualization.<br>
729 %> The the axes limits of all subplots whose corresponding elements in the input cell array ``limits``
730 %> are set to empty ``[]``, will be set to the appropriate default value
731 %> taken from the maximum range possible in the relevant plots.<br>
732 %> (**optional**, default = ``cell(max(size(self.tile)), 1)``)
733 %>
734 %> \interface{setAxesLimits}
735 %> \code{.m}
736 %>
737 %> g = pm.vis.Triplex(lower, diago, upper, varargin);
738 %> g.make(varargin);
739 %>
740 %> g.setAxesLimits(); % reset all axes limits to the maximum ranges among all relevant plots.
741 %> g.setAxesLimits({}); % reset all axes limits to the maximum ranges among all relevant plots.
742 %> g.setAxesLimits(limits); % reset all axes limits to the custom ranges among all relevant plots.
743 %>
744 %> \endcode
745 %>
746 %> \example{setAxesLimits}
747 %> \code{.m}
748 %>
749 %> g = pm.vis.Triplex(lower, diago, upper, varargin);
750 %> g.make(varargin);
751 %>
752 %> g.setAxesLimits({[-10,10], [-20, 0]})
753 %> g.setAxesLimits({[-10,10], [], [-20, 0]}) % the limits for the second variable will remain unchanged.
754 %>
755 %> \endcode
756 %>
757 %> \warning
758 %> This method has side-effects by manipulating the existing attributes of the parent object.<br>
759 %>
760 %> \final{setAxesLimits}
761 %>
762 %> \author
763 %> \AmirShahmoradi, July 7 2024, 12:53 AM, NASA Goddard Space Flight Center (GSFC), Washington, D.C.<br>
764 function setAxesLimits(self, limits)
765
766 if nargin < 2
767 limits = {};
768 end
769
770 %%%%
771 %%%% Check the ``limits`` length.
772 %%%%
773
774 if numel(limits) == 0
775 limits = cell(max(size(self.tile)), 1);
776 else
777 if numel(limits) > max(size(self.tile))
778 help("pm.vis.Triplex.setAxesLimits");
779 disp("numel(limits)");
780 disp( numel(limits) );
781 error ( newline ...
782 + "The input ``limits`` must be a cell array of maximum length " + string(max(size(self.tile))) + "." + newline ...
783 + "The input value is " + strjoin(string(limits),", ") + newline ...
784 + "For more information, see the documentation displayed above." + newline ...
785 + newline ...
786 );
787 end
788 end
789
790 %%%%
791 %%%% Check the ``limits`` elements lengths.
792 %%%%
793
794 for iell = 1 : numel(limits)
795 limitsElementLen = numel(limits{iell});
796 if limitsElementLen == 0
797 limits{iell} = [-Inf, +Inf];
798 for irow = 1 : size(self.tile, 2)
799 %if ~self.tile{irow, iell}.type.is.d1; end
800 if ~isempty(self.tile{irow, iell})% && strcmpi(self.tile{irow, iell}.fout.axes.Visible, "on")
801 limits{iell}(1) = max(limits{iell}(1), self.tile{irow, iell}.fout.axes.XLim(1));
802 limits{iell}(2) = min(limits{iell}(2), self.tile{irow, iell}.fout.axes.XLim(2));
803 end
804 end
805 elseif limitsElementLen ~= 2
806 error ( newline ...
807 + "The element ``" + string(iell) + "`` of the input cell array ``limits`` is invalid. " + newline ...
808 + "The limits specified by the input cell must be either vectors of length two, or empty vectors." + newline ...
809 + "You have entered the following value for the element " + string(iell) + ": " + newline ...
810 + newline ...
811 + pm.io.tab + strjoin(string(limits{iell})) + newline ...
812 + newline ...
813 );
814 end
815 end
816
817 for icol = 1 : size(self.tile, 2)
818 for irow = 1 : size(self.tile, 1)
819 if ~isempty(self.tile{irow, icol})% && strcmpi(self.tile{irow, icol}.fout.axes.Visible, "on")
820 xlim(self.tile{irow, icol}.fout.axes, limits{icol}(:));
821 if icol ~= irow
822 %|| (icol == 1 && irow == 1 && ~isempty(self.tile{irow, icol + 1})) ...
823 %|| (icol == size(self.tile, 2) && irow == size(self.tile, 1) && ~isempty(self.tile{irow, icol - 1}))
824 ylim(self.tile{irow, icol}.fout.axes, limits{irow}(:));
825 end
826 end
827 end
828 end
829
830 end
831
832 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
833
834 %%%> \brief
835 %%%> Hide the requested section(s) of the Triplex, and return nothing.<br>
836 %%%>
837 %%%> \details
838 %%%> Note that the main axes colorbar associated with the specified component is also automatically hidden.<br>
839 %%%>
840 %%%> \param[in] self : The **implicitly-passed** input argument representing the parent object of the method.<br>
841 %%%> \param[in] complist : The input vector of MATLAB strings each of which can be any of the following:
842 %%%> <ol>
843 %%%> <li> ``"lower"`` : corresponding to the lower triangle of the Triplex plot.
844 %%%> <li> ``"diago"`` : corresponding to the diagonal tiles in the Triplex plot.
845 %%%> <li> ``"upper"`` : corresponding to the upper triangle of the Triplex plot.
846 %%%> </ol>
847 %%%> (**optional**, default = ``["lower", "diago", "upper"]``.)<br>
848 %%%>
849 %%%> \interface{hide}
850 %%%> \code{.m}
851 %%%>
852 %%%> g = pm.vis.Triplex(lower, diago, upper, varargin);
853 %%%> g.make(varargin);
854 %%%> g.hide(complist);
855 %%%> g.hide([]);
856 %%%>
857 %%%> \endcode
858 %%%>
859 %%%> \warning
860 %%%> This method has side-effects by manipulating the existing attributes of the parent object.<br>
861 %%%>
862 %%%> \example{hide}
863 %%%> \code{.m}
864 %%%>
865 %%%> g = pm.vis.Triplex(lower, diago, upper, varargin);
866 %%%> g.make(varargin);
867 %%%> g.hide() % hide all parts of the Triplex plot and the associated colorbars in the Triplex plot.
868 %%%> g.hide(["diago", "upper"]) % hide the diagonal subplots and the associated colorbars in the Triplex plot.
869 %%%> g.hide("lower") % hide the lower triangle subplots of the Triplex plot and its associated colorbar in the Triplex plot.
870 %%%>
871 %%%> \endcode
872 %%%>
873 %%%> \final{hide}
874 %%%>
875 %%%> \author
876 %%%> \AmirShahmoradi, July 7 2024, 12:53 AM, NASA Goddard Space Flight Center (GSFC), Washington, D.C.<br>
877 %%function hide(self, complist)
878 %% if nargin < 2
879 %% complist = [];
880 %% end
881 %% self.hideShow("hide", complist);
882 %%end
883 %%
884 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
885 %%
886 %%%> \brief
887 %%%> Show the requested section(s) of the Triplex, and return nothing.<br>
888 %%%>
889 %%%> \details
890 %%%> Note that the main axes colorbar associated with the specified component is also automatically shown.<br>
891 %%%>
892 %%%> \param[in] complist : The input vector of MATLAB strings each of which can be any of the following:
893 %%%> <ol>
894 %%%> <li> ``"lower"`` : corresponding to the lower triangle of the Triplex plot.
895 %%%> <li> ``"diago"`` : corresponding to the diagonal tiles in the Triplex plot.
896 %%%> <li> ``"upper"`` : corresponding to the upper triangle of the Triplex plot.
897 %%%> </ol>
898 %%%> (**optional**, default = ``["lower", "diago", "upper"]``.)<br>
899 %%%>
900 %%%> \interface{show}
901 %%%> \code{.m}
902 %%%>
903 %%%> g = pm.vis.Triplex(lower, diago, upper, varargin);
904 %%%> g.make(varargin);
905 %%%> g.show(complist);
906 %%%>
907 %%%> \endcode
908 %%%>
909 %%%> \warning
910 %%%> This method has side-effects by manipulating the existing attributes of the parent object.<br>
911 %%%>
912 %%%> \example{show}
913 %%%> \code{.m}
914 %%%>
915 %%%> g = pm.vis.Triplex(lower, diago, upper, varargin);
916 %%%> g.make(varargin);
917 %%%> g.show() % show all parts of the Triplex plot and the associated colorbars in the Triplex plot.
918 %%%> g.show(["diago", "upper"]) % show the diagonal subplots and the associated colorbars in the Triplex plot.
919 %%%> g.show("lower") % show the lower triangle subplots of the Triplex plot and its associated colorbar in the Triplex plot.
920 %%%>
921 %%%> \endcode
922 %%%>
923 %%%> \final{show}
924 %%%>
925 %%%> \author
926 %%%> \AmirShahmoradi, July 7 2024, 12:53 AM, NASA Goddard Space Flight Center (GSFC), Washington, D.C.<br>
927 %%function show(self, complist)
928 %% if nargin < 2
929 %% complist = [];
930 %% end
931 %% self.hideShow("show", complist);
932 %%end
933
934 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
935
936 end
937
938 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
939
940 methods(Access = public, Hidden)
941
942 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
943
944 %%%> \brief
945 %%%> Hide/Show the requested section(s) of the Triplex, and return nothing.<br>
946 %%%>
947 %%%> \details
948 %%%> This is an internal (hidden) method of the class and inaccessible to end users.<br>
949 %%%> Note that the main axes colorbar associated with the specified component is also automatically impacted.<br>
950 %%%>
951 %%%> \param[in] self : The **implicitly-passed** input argument representing the parent object of the method.<br>
952 %%%> \param[in] action : The input scalar MATLAB string that can be any of the following:<br>
953 %%%> <ol>
954 %%%> <li> ``"hide"`` : hide the specified components of the Triplex plot in the input argument ``complist``.
955 %%%> <li> ``"show"`` : show the specified components of the Triplex plot in the input argument ``complist``.
956 %%%> </ol>
957 %%%> (**optional**, default = ``["lower", "diago", "upper"]``.)<br>
958 %%%> \param[in] complist : The input vector of MATLAB strings each of which can be any of the following:
959 %%%> <ol>
960 %%%> <li> ``"lower"`` : corresponding to the lower triangle of the Triplex plot.
961 %%%> <li> ``"diago"`` : corresponding to the diagonal tiles in the Triplex plot.
962 %%%> <li> ``"upper"`` : corresponding to the upper triangle of the Triplex plot.
963 %%%> </ol>
964 %%%> (**optional**, default = ``["lower", "diago", "upper"]``.)<br>
965 %%%>
966 %%%> \interface{show}
967 %%%> \code{.m}
968 %%%>
969 %%%> g = pm.vis.Triplex(lower, diago, upper, varargin);
970 %%%> g.make(varargin);
971 %%%> g.hideShow(action, []);
972 %%%> g.hideShow(action, complist);
973 %%%>
974 %%%> \endcode
975 %%%>
976 %%%> \warning
977 %%%> This method has side-effects by manipulating the existing attributes of the parent object.<br>
978 %%%>
979 %%%> \final{show}
980 %%%>
981 %%%> \author
982 %%%> \AmirShahmoradi, July 7 2024, 12:53 AM, NASA Goddard Space Flight Center (GSFC), Washington, D.C.<br>
983 %%function hideShow(self, action, complist)
984 %%
985 %% action = string(action);
986 %% showit = strcmpi(action, "show");
987 %% hideit = strcmpi(action, "hide");
988 %% if showit
989 %% onoff = "on";
990 %% elseif hideit
991 %% onoff = "off";
992 %% end
993 %%
994 %% %%%%
995 %% %%%% Determine which figure parts to act on.
996 %% %%%%
997 %%
998 %% if nargin == 2 || isempty(complist)
999 %% complist = ["lower", "diago", "upper"];
1000 %% end
1001 %%
1002 %% %%%%
1003 %% %%%% Act on the specific requested parts of the figure.
1004 %% %%%%
1005 %%
1006 %% enabled = struct();
1007 %% enabled.diago = false;
1008 %% enabled.lower = false;
1009 %% enabled.upper = false;
1010 %% complist = lower(string(complist));
1011 %% for comp = complist
1012 %% if strcmpi(comp, "diag") || strcmpi(comp, "diago")
1013 %% enabled.diago = true;
1014 %% elseif strcmpi(comp, "upper")
1015 %% enabled.upper = true;
1016 %% elseif strcmpi(comp, "lower")
1017 %% enabled.lower = true;
1018 %% else
1019 %% help("pm.vis.Triplex." + action);
1020 %% error ( newline ...
1021 %% + "Unrecognized input argument pass to the " + action + "() method: " + newline ...
1022 %% + newline ...
1023 %% + comp + newline ...
1024 %% + newline ...
1025 %% + "The " + action + "() method accepts only a list of comma-separated" + newline ...
1026 %% + "string values representing the ""part"" of the figure to " + action + "." + newline ...
1027 %% + "For more information, see the documentation of the method displayed above." + newline ...
1028 %% + newline ...
1029 %% );
1030 %% end
1031 %% end
1032 %%
1033 %% %%%%
1034 %% %%%% Perform action.
1035 %% %%%%
1036 %%
1037 %% for icol = 1 : size(self.tile, 2)
1038 %% for irow = 1 : size(self.tile, 1)
1039 %% if (icol < irow && enabled.lower) || (irow < icol && enabled.upper) || (icol == irow && enabled.diago)
1040 %% if ~isempty(self.tile{irow, icol}.axes)
1041 %% self.tile{irow, icol}.fout.axes.Visible = onoff;
1042 %% set(get(self.tile{irow, icol}.fout.axes, "children"), "visible", onoff);
1043 %% %if icol < irow && self.layout.cbarv.enabled
1044 %% % if strcmpi(onoff, "hide")
1045 %% % end
1046 %% %end
1047 %% end
1048 %% end
1049 %% end
1050 %% end
1051 %%
1052 %% if enabled.lower || enabled.upper || enabled.diago
1053 %% self.hideShowAxesLabels();
1054 %% end
1055 %%
1056 %%end % function hideShow
1057
1058 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1059
1060 %> \brief
1061 %> Hide or show axis labels and ticks depending on the presence of the neighbor subplots.<br>
1062 %>
1063 %> \details
1064 %> This is an internal (hidden) method of the class and inaccessible to end users.<br>
1065 %>
1066 %> \param[in] self : The **implicitly-passed** input argument representing the parent object of the method.<br>
1067 %>
1068 %> \interface{hideShowAxesLabels}
1069 %> \code{.m}
1070 %>
1071 %> g = pm.vis.Triplex(lower, diago, upper, varargin);
1072 %> g.hideShowAxesLabels();
1073 %>
1074 %> \endcode
1075 %>
1076 %> \warning
1077 %> This method causes side-effects by manipulating the existing attributes of the object.<br>
1078 %>
1079 %> \final{hideShowAxesLabels}
1080 %>
1081 %> \author
1082 %> \JoshuaOsborne, May 21 2024, 9:28 AM, University of Texas at Arlington<br>
1083 %> \FatemehBagheri, May 20 2024, 1:25 PM, NASA Goddard Space Flight Center (GSFC), Washington, D.C.<br>
1084 %> \AmirShahmoradi, July 7 2024, 12:53 AM, NASA Goddard Space Flight Center (GSFC), Washington, D.C.<br>
1085 function hideShowAxesLabels(self)
1086
1087 %%%%
1088 %%%% (Un)set the tile axes labels and ticks.
1089 %%%%
1090
1091 for icol = 1 : size(self.tile, 2)
1092 for irow = 1 : size(self.tile, 1)
1093
1094 if ~isempty(self.tile{irow, icol})% && strcmpi(self.tile{irow, icol}.fout.axes.XLabel.Visible, "on")
1095
1096 zisabled = false;
1097 if irow < size(self.tile, 1)
1098 if ~isempty(self.tile{irow + 1, icol}) && strcmpi(self.tile{irow + 1, icol}.fout.axes.XLabel.Visible, "on")
1099 self.tile{irow, icol}.fout.axes.XLabel.Visible = "off";
1100 %self.tile{irow, icol}.fout.axes.XLabel.String = "";
1101 self.tile{irow, icol}.fout.axes.XTickLabel = [];
1102 zisabled = true;
1103 elseif isempty(self.tile{irow + 1, icol})
1104 self.tile{irow, icol}.fout.axes.XTickLabelMode = "auto";
1105 % self.tile{irow, icol}.fout.axes.XLabel.Visible = "on";
1106 end
1107 end
1108
1109 if icol > 1
1110 if ~isempty(self.tile{irow, icol - 1}) && strcmpi(self.tile{irow, icol - 1}.fout.axes.Visible, "on")
1111 self.tile{irow, icol}.fout.axes.YLabel.Visible = "off";
1112 %self.tile{irow, icol}.fout.axes.YLabel.String = "";
1113 self.tile{irow, icol}.fout.axes.YTickLabel = [];
1114 zisabled = true;
1115 elseif isempty(self.tile{irow, icol - 1})
1116 self.tile{irow, icol}.fout.axes.YTickLabelMode = "auto";
1117 % self.tile{irow, icol}.fout.axes.YLabel.Visible = "on";
1118 end
1119 end
1120
1121 if zisabled
1122 self.tile{irow, icol}.fout.axes.ZLabel.Visible = "off";
1123 %self.tile{irow, icol}.fout.axes.ZLabel.String = "";
1124 self.tile{irow, icol}.fout.axes.ZTickLabel = [];
1125 else
1126 self.tile{irow, icol}.fout.axes.ZTickLabelMode = "auto";
1127 % self.tile{irow, icol}.fout.axes.ZLabel.Visible = "off";
1128 end
1129
1130 if icol ~= 1
1131 self.tile{irow, icol}.fout.axes.YLabel.Rotation = 45;
1132 self.tile{irow, icol}.fout.axes.YLabel.VerticalAlignment = "middle";
1133 self.tile{irow, icol}.fout.axes.YLabel.HorizontalAlignment = "right";
1134 self.tile{irow, icol}.fout.axes.YLabel.FontSize = self.tile{irow, icol}.fout.axes.FontSize;
1135 end
1136
1137 if irow ~= size(self.tile, 1)
1138 self.tile{irow, icol}.fout.axes.XLabel.Rotation = 45;
1139 self.tile{irow, icol}.fout.axes.XLabel.VerticalAlignment = "top";
1140 self.tile{irow, icol}.fout.axes.XLabel.HorizontalAlignment = "right";
1141 self.tile{irow, icol}.fout.axes.XLabel.FontSize = self.tile{irow, icol}.fout.axes.FontSize;
1142 end
1143
1144 end
1145
1146 end
1147 end
1148
1149 self.setDiagoTicksY();
1150
1151 end
1152
1153 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1154
1155 %> \brief
1156 %> Hide or show axis labels and ticks depending on the presence of the neighbor subplots.<br>
1157 %>
1158 %> \details
1159 %> This is an internal (hidden) method of the class and inaccessible to end users.<br>
1160 %>
1161 %> \param[in] self : The **implicitly-passed** input argument representing the parent object of the method.<br>
1162 %>
1163 %> \interface{hideShowAxesLabels}
1164 %> \code{.m}
1165 %>
1166 %> g = pm.vis.Triplex(lower, diago, upper, varargin);
1167 %> g.hideShowAxesLabels();
1168 %>
1169 %> \endcode
1170 %>
1171 %> \warning
1172 %> This method causes side-effects by manipulating the existing attributes of the object.<br>
1173 %>
1174 %> \final{hideShowAxesLabels}
1175 %>
1176 %> \author
1177 %> \JoshuaOsborne, May 21 2024, 9:28 AM, University of Texas at Arlington<br>
1178 %> \FatemehBagheri, May 20 2024, 1:25 PM, NASA Goddard Space Flight Center (GSFC), Washington, D.C.<br>
1179 %> \AmirShahmoradi, July 7 2024, 12:53 AM, NASA Goddard Space Flight Center (GSFC), Washington, D.C.<br>
1180 function setDiagoTicksY(self)
1181
1182 %%%%
1183 %%%% reset the ytick labels of the diagonal subplots to x-axis ticks when there are subplots to their right.
1184 %%%%
1185
1186 for iell = 1 : min(size(self.tile))
1187
1188 if ~isempty(self.tile{iell, iell}) && strcmp(self.tile{iell, iell}.fout.axes.Visible, "on")
1189
1190 %%%%
1191 %%%% Do NOT change the order of conditions in the if blocks. short-circuit is at work.
1192 %%%%
1193
1194 if (iell == size(self.tile, 2) && (isempty(self.tile{iell, iell - 1}) || strcmp(self.tile{iell, iell - 1}.fout.axes.Visible, "off"))) ...
1195 || (iell == 1 && (isempty(self.tile{iell, iell + 1}) || strcmp(self.tile{iell, iell + 1}.fout.axes.Visible, "off"))) ...
1196 || (iell ~= 1 && iell ~= size(self.tile, 2) ...
1197 && ...
1198 ( isempty(self.tile{iell, iell + 1}) || strcmp(self.tile{iell, iell + 1}.fout.axes.Visible, "off")) ...
1199 && ...
1200 ( isempty(self.tile{iell, iell - 1}) || strcmp(self.tile{iell, iell - 1}.fout.axes.Visible, "off")) ...
1201 )
1202
1203 %%%%
1204 %%%% Let the histograms have their own y-ranges.
1205 %%%%
1206
1207 %set(self.tile{iell, iell}.fout.axes, "YTickMode", "auto", "YTickLabelMode", "auto");
1208
1209 elseif iell < size(self.tile, 2)
1210
1211 %%%%
1212 %%%% Set the y-range and ticklabels according to the needs of the neighbor plots.
1213 %%%%
1214
1215 %%%% ``self.tile{iell, iell}.fout`` is the current tile.
1216 %%%% ``self.tile{inei, iell}.fout`` is the neighbor tile.
1217
1218 if iell == 1 || isempty(self.tile{iell, iell - 1}) || strcmp(self.tile{iell, iell - 1}.fout.axes.Visible, "off")
1219
1220 if ~isempty(self.tile{end, iell})
1221 inei = size(self.tile, 1);
1222 else
1223 inei = iell;
1224 end
1225 yticks(self.tile{iell, iell}.fout.axes, self.diagYTick{iell}.modified.values);
1226 yticklabels(self.tile{iell, iell}.fout.axes, self.diagYTick{iell}.modified.labels);
1227
1228 %%%%
1229 %%%% Set Y-axis label.
1230 %%%%
1231
1232 failed = ~isfield(self.tile{inei, iell}.fout, "xlabel") || isempty(self.tile{inei, iell}.fout.xlabel.String);
1233 if ~failed
1234 try
1235 self.tile{iell, iell}.fout.axes.YLabel.String = self.tile{inei, iell}.fout.xlabel.String;
1236 catch
1237 failed = true;
1238 end
1239 end
1240 if failed
1241 failed = isempty(self.tile{iell, iell}.fout.xlabel.String);
1242 if ~failed
1243 try
1244 self.tile{iell, iell}.fout.axes.YLabel.String = self.tile{inei, iell}.fout.xlabel.String;
1245 catch
1246 failed = true;
1247 end
1248 end
1249 if failed
1250 self.tile{iell, iell}.fout.axes.YLabel.String = string(self.tile{iell, iell}.df.Properties.VariableNames(iell));
1251 end
1252 end
1253
1254 end
1255
1256 end
1257
1258 end
1259
1260 end
1261
1262 end
1263
1264 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1265
1266 end
1267
1268 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1269
1270end
function name(in vendor)
Return the MPI library name as used in naming the ParaMonte MATLAB shared library directories.
function list()
Return a list of MATLAB strings containing the names of OS platforms supported by the ParaMonte MATLA...
This is the abstract class for generating instances of objects that contain the specifications of var...
Definition: Figure.m:27
This is the abstract class for generating instances of axes with various types of plots from one or m...
Definition: Subplot.m:188
This is the base class for generating instances of objects that contains layout information for a set...
Definition: TilingLayout.m:27
This is the base class for generating instances of figures containing a square symmetric tiling of su...
Definition: Triplex.m:31
function setDiagoTicksY(in self)
Hide or show axis labels and ticks depending on the presence of the neighbor subplots.
function premake(in self, in varargin)
Preset the tiling settings before making it.
Property lower
Definition: Triplex.m:68
Property diago
Definition: Triplex.m:58
Property layout
Definition: Triplex.m:47
function reset(in self, in varargin)
Reset the properties of the figure to the original default settings.
function Triplex(in lower, in diago, in upper, in varargin)
Construct and return an object of class pm.vis.Triplex.
function hideShowAxesLabels(in self)
Hide or show axis labels and ticks depending on the presence of the neighbor subplots.
function make(in self, in varargin)
Configure the figure settings and specifications, make the figure and the subplots,...
function setAxesLimits(in self, in limits)
Set the axes x-y limits of the subplots that are currently present in the GridPlot to the input user-...
function rotateAxesLabels(in self, in degx, in degy)
Rotate the axes labels of the subplots of the Triplex, and return nothing.
Property tile
Definition: Triplex.m:86
Property upper
Definition: Triplex.m:78
Property diagYTick
Definition: Triplex.m:102
function clean()
Remove all paths that contain the ParaMonte lib directory from the MATLAB path variable.
function show(in obj, in name, in hidden)
Display the components of an input MATLAB variable on MATLAB Console recursively.
function which(in vendor)
Return the a MATLAB string containing the path to the first mpiexec executable binary found in system...