ParaMonte MATLAB 3.0.0
Parallel Monte Carlo and Machine Learning Library
See the latest version documentation.
SubplotEllipse3.m
Go to the documentation of this file.
1%> \brief
2%> This is the SubplotEllipse3 class for generating
3%> instances of 3-dimensional Ellipse [Subplot visualizations](@ref Subplot)
4%> based on the relevant MATLAB intrinsic functions.<br>
5%>
6%> \note
7%> See the documentation of the constructor of the class
8%> [pm.vis.SubplotEllipse3](@ref SubplotEllipse3::SubplotEllipse3) for example usage.<br>
9%>
10%> \note
11%> See the list of class attributes below,
12%> also those of the superclass [pm.vis.SubplotLineScatter3](@ref SubplotLineScatter3).<br>
13%>
14%> \see
15%> [pm.vis.Cascade](@ref Cascade)<br>
16%> [pm.vis.Subplot](@ref Subplot)<br>
17%> [pm.vis.Triplex](@ref Triplex)<br>
18%> [pm.vis.Figure](@ref Figure)<br>
19%> [pm.vis.Plot](@ref Plot)<br>
20%> [pm.vis.Tile](@ref Tile)<br>
21%>
22%> \final
23%>
24%> \author
25%> \FatemehBagheri, May 20 2024, 1:25 PM, NASA Goddard Space Flight Center (GSFC), Washington, D.C.<br>
26%> \AmirShahmoradi, May 16 2016, 9:03 AM, Oden Institute for Computational Engineering and Sciences (ICES), UT Austin<br>
27classdef SubplotEllipse3 < pm.vis.SubplotLineScatter3
28 properties(Access = public)
29 %>
30 %> ``names``
31 %>
32 %> The vector of MATLAB strings containing the names of dimensions
33 %> of the space within which the Gramian matrices are defined.<br>
34 %> The default is ``"Dimension i"`` where ``i`` is replaced
35 %> by the ID of the corresponding axis.<br>
36 %>
37 names = [];
38 %>
39 %> ``dimx``
40 %>
41 %> The MATLAB scalar (or vector) of whole-number(s) representing the dimension(s) of the
42 %> input ``gramian`` and ``center`` data to be used on the x-axis of 2D ellipsoid visualization.<br>
43 %> The default is ``1`` if ``dimy`` component is also unspecified, or the appropriate data column adjacent to ``dimmy``.<br>
44 %> If the condition ``dimx == dimy`` holds, then the resulting ellipses will be circles.<br>
45 %>
46 dimx = [];
47 %>
48 %> ``dimy``
49 %>
50 %> The MATLAB scalar (or vector) of whole-number(s) representing the dimension(s) of the
51 %> input ``gramian`` and ``center`` data to be used on the y-axis of 2D ellipsoid visualization.<br>
52 %> The default is ``1`` if ``dimx`` component is also unspecified, or the appropriate data column adjacent to ``dimmx``.<br>
53 %> If the condition ``dimx == dimy`` holds, then the resulting ellipses will be circles.<br>
54 %>
55 dimy = [];
56 %>
57 %> ``ellindex``
58 %>
59 %> The vector of MATLAB whole numbers representing the ellindex of the 2D
60 %> ellipsoids to display, represented by the input ``gramian`` and ``center``.<br>
61 %> The specified ellindex will serve as the visualization values on the z-axis.<br>
62 %> The default is ``ellindex = pm.array.logrange(start = 1, stop = nell, count = 75);``,
63 %> where ``nell`` represents the number of ellipsoids to visualize.<br>
64 %>
65 ellindex = [];
66 %>
67 %> ``gramian``
68 %>
69 %> A scalar object of class [pm.container.DataRef](@ref DataRef)
70 %> containing the user-specified Gramian data to visualize.<br>
71 %>
72 gramian = [];
73 %>
74 %> ``center``
75 %>
76 %> A scalar object of class [pm.container.DataRef](@ref DataRef)
77 %> containing the user-specified center data to visualize.<br>
78 %>
79 center = [];
80 %>
81 %> ``zval``
82 %>
83 %> A scalar object of class [pm.container.DataRef](@ref DataRef)
84 %> containing the user-specified z-axis data to visualize.<br>
85 %>
86 zval = [];
87 %>
88 %> ``cval``
89 %>
90 %> A scalar object of class [pm.container.DataRef](@ref DataRef)
91 %> containing the user-specified color data in colormap.<br>
92 %> If empty or unspecified, it will be set to ``zval`` component.<br>
93 %>
94 cval = [];
95 end
96
97 properties(Access = public, Hidden)
98 %>
99 %> ``ndim``
100 %>
101 %> A scalar MATLAB whole number representing the total number of the
102 %> dimensions of ellipsoids identified based on the input that can be visualized.<br>
103 %> It is set to ``max(2, size(gramian, 2), size(center, 1))``.<br>
104 %>
105 ndim = [];
106 %>
107 %> ``nell``
108 %>
109 %> A scalar MATLAB whole number representing the total number of
110 %> ellipsoids identified based on the input that can be visualized.<br>
111 %> It is set to ``max(20, size(gramian, 3), size(center, 2), size(zval, 2))``.<br>
112 %>
113 nell = [];
114 %>
115 %> ``npnt``
116 %>
117 %> The scalar MATLAB whole number representing the number of
118 %> points with which the 2D ellipsoid boundaries are delineated.<br>
119 %> It is set to ``max(size(zval, 1), size(cval, 1))`` or otherwise, ``100``.<br>
120 %>
121 npnt = [];
122 %>
123 %> ``workspace``
124 %>
125 %> A scalar MATLAB ``struct()`` containing the current visualization information.<br>
126 %> This information is updated with every call to the ``make()`` method.<br>
127 %> The contents of this component are temporary and must remain read-only.<br>
128 %> This component is solely provided for better insight into the internal
129 %> workings of the ``make()`` method of the parent object and
130 %> the resulting visualization.<br>
131 %>
132 workspace = [];
133 end
135 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
136
137 methods(Access = public)
138
139 %> \brief
140 %> Construct and return an object of class [pm.vis.SubplotEllipse](@ref SubplotEllipse).<br>
141 %>
142 %> \details
143 %> In the following documentation,
144 %> <ol>
145 %> <li> The variable ``ndim`` represents the number of ellipsoids in the input data.<br>
146 %> The value of ``ndim`` is inferred from the shapes of the input ``gramian``
147 %> and ``center`` arguments as ``max([2, size(gramian, 1), size(center, 1)])``.<br>
148 %>
149 %> <li> The variable ``nell`` represents the number of ellipsoids in the input data.<br>
150 %> The value of ``nell`` is inferred from the shapes
151 %> of the input ``gramian``, ``center``, ``zval``, and ``cval`` arguments
152 %> as ``max([size(gramian, 3), size(center, 2), size(zval, 2), size(cval, 2)])``.<br>
153 %> If the above expression yields zero, then ``nell`` is set to ``75``.<br>
154 %>
155 %> <li> The variable ``npnt`` represents the number of points used in visualizing each ellipsoid.<br>
156 %> The value of ``npnt`` is inferred from the shapes of the input arguments
157 %> ``zval`` and ``czval`` as ``max(size(zval, 1), size(cval, 1))``.<br>
158 %> If the above expression yields zero or one, then ``npnt`` is set to ``100``.<br>
159 %> </ol>
160 %>
161 %> \param[in] gramian : The MATLAB (function handle returning an) object that can be either,<br>
162 %> <ol>
163 %> <li> an empty object (e.g., ``[]``), in which case,
164 %> the value ``repmat(eye(ndim, ndim), 1, 1, nell)`` will be used.<br>
165 %>
166 %> <li> a scalar, containing the value of the diagonal elements
167 %> of the diagonal matrices representing the Gramian matrices
168 %> of all ``nell`` ellipsoids in the input data.<br>
169 %>
170 %> <li> a vector of shape ``[1, 1, nell]`` such that ``gramian(1, 1, iell)``
171 %> represents the diagonal value to be used in constructing the Gramian
172 %> matrix of the ellipsoid ``iell` in the input ``nell`` ellipsoid data.<br>
173 %>
174 %> <li> a matrix of shape ``[ndim, ndim, 1]`` used in constructing the Gramian
175 %> matrices of all ``nell`` ellipsoids in the input data.<br>
176 %>
177 %> <li> a tensor of shape ``[ndim, ndim, nell]`` such that ``gramian(:, :, iell)``
178 %> represents the Gramian matrix of the ellipsoid ``iell` in the input data.<br>
179 %> </ol>
180 %> While it is possible to pass a data directly to this class,
181 %> it is highly recommended to pass a function handle that returns
182 %> such data when called, allowing the visualization data to be
183 %> dynamically updated when needed.<br>
184 %> \param[in] center : The MATLAB (function handle returning an) object that can be either,<br>
185 %> <ol>
186 %> <li> an empty object (e.g., ``[]``), in which case,
187 %> the value ``zeros(ndim, nell)`` will be used.<br>
188 %>
189 %> <li> a scalar, containing the value to assign to all coordinates
190 %> of the centers of all ``nell`` ellipsoids in the input data.<br>
191 %>
192 %> <li> a vector of shape ``[1, nell]`` such that ``center(1, iell)``
193 %> represents the value of all coordinates of the center of the
194 %> ellipsoid ``iell` in the input ``nell`` ellipsoid data.<br>
195 %>
196 %> <li> a vector of shape ``[ndim, 1]`` such that ``center(idim, 1)``
197 %> represents the value of ``idim`` coordinate of the centers of
198 %> all ``nell`` ellipsoids in the input data.<br>
199 %>
200 %> <li> a matrix of shape ``[ndim, nell]`` such that ``center(:, iell)`` represents
201 %> the coordinates of the center of the ellipsoid ``iell` in the input data.<br>
202 %> </ol>
203 %> While it is possible to pass data directly to this class,
204 %> it is highly recommended to pass a function handle that returns
205 %> such data when called, allowing the visualization data to be
206 %> dynamically updated when needed.<br>
207 %> \param[in] zval : The MATLAB (function handle returning an) object that can be either,<br>
208 %> <ol>
209 %> <li> an empty object (e.g., ``[]``), in which case,
210 %> the value ``repmat(1 : nell, npnt, 1)`` will be used.<br>
211 %>
212 %> <li> a scalar, containing the value to assign to the z-axis
213 %> coordinates of all ``npnt`` points used in the visualization
214 %> of ``nell`` ellipsoids in the input data.<br>
215 %>
216 %> <li> a vector of shape ``[1, nell]`` such that ``zval(1, iell)``
217 %> represents the value of z-axis coordinates of all ``npnt``
218 %> points used in the visualization of the ellipsoid
219 %> ``iell` in the input ``nell`` ellipsoid data.<br>
220 %>
221 %> <li> a vector of shape ``[npnt, 1]`` such that ``zval(ipnt, 1)``
222 %> contains the z-axis value of ``ipnt`` points in the representations
223 %> of all ``nell`` ellipsoids in the input data.<br>
224 %>
225 %> <li> a matrix of shape ``[npnt, nell]`` such that ``zval(:, iell)`` represents
226 %> the z-axis coordinates of all ``npnt`` points used in the visualization of
227 %> the ellipsoid ``iell` in the input data.<br>
228 %> </ol>
229 %> While it is possible to pass data directly to this class,
230 %> it is highly recommended to pass a function handle that returns
231 %> such data when called, allowing the visualization data to be
232 %> dynamically updated when needed.<br>
233 %> \param[in] cval : The MATLAB (function handle returning an) object that can be either,<br>
234 %> <ol>
235 %> <li> an empty object (e.g., ``[]``), in which case,
236 %> the input value ``zval`` will be used.<br>
237 %>
238 %> <li> a scalar, containing the value to assign to color values
239 %> of all ``npnt`` points used in the visualization
240 %> of ``nell`` ellipsoids in the input data.<br>
241 %>
242 %> <li> a vector of shape ``[1, nell]`` such that ``cval(1, iell)``
243 %> represents the color values of all ``npnt`` points used in the
244 %> visualization of the ellipsoid ``iell` in the input ``nell`` ellipsoid data.<br>
245 %>
246 %> <li> a vector of shape ``[npnt, 1]`` such that ``cval(ipnt, 1)``
247 %> contains the color values of ``ipnt`` points in the representations
248 %> of all ``nell`` ellipsoids in the input data.<br>
249 %>
250 %> <li> a matrix of shape ``[npnt, nell]`` such that ``center(:, iell)`` represents
251 %> the color values of all ``npnt`` points used in the visualization of
252 %> the ellipsoid ``iell` in the input data.<br>
253 %> </ol>
254 %> While it is possible to pass data directly to this class,
255 %> it is highly recommended to pass a function handle that returns
256 %> such data when called, allowing the visualization data to be
257 %> dynamically updated when needed.<br>
258 %> The input value for ``cval`` is used only if ``colormap.enabled`` component of the
259 %> output object of class [pm.vis.SubplotEllipse3](@ref SubplotEllipse3) is set to ``true``.<br>
260 %> \param[in] varargin : Any ``property, value`` pair of the object.<br>
261 %> If the property is a ``struct()``, then its value must be given as a cell array,
262 %> with consecutive elements representing the struct ``property-name, property-value`` pairs.<br>
263 %> Note that all of these property-value pairs can be also directly set via the
264 %> parent object attributes, before calling the ``make()`` method.<br>
265 %>
266 %> \return
267 %> ``self`` : The output object of class [pm.vis.SubplotEllipse3](@ref SubplotEllipse3).<br>
268 %>
269 %> \interface{SubplotEllipse3}
270 %> \code{.m}
271 %> s = pm.vis.SubplotEllipse3();
272 %> s = pm.vis.SubplotEllipse3(gramian);
273 %> s = pm.vis.SubplotEllipse3(gramian, center);
274 %> s = pm.vis.SubplotEllipse3(gramian, center, zval);
275 %> s = pm.vis.SubplotEllipse3(gramian, center, zval, cval);
276 %> s = pm.vis.SubplotEllipse3(gramian, center, zval, cval, varargin);
277 %>
278 %> \endcode
279 %>
280 %> \note
281 %> To generate a 2D plot of ellipsoids, simply execute the
282 %> MATLAB command ``view(2)`` to change the camera view to 2D.<br>
283 %>
284 %> \note
285 %> See also the documentation of the attributes
286 %> of the superclass [pm.vis.SubplotLineScatter3](@ref SubplotLineScatter3).<br>
287 %>
288 %> \example{SubplotEllipse3}
289 %> \include{lineno} example/vis/SubplotEllipse3/main.m
290 %> \vis{SubplotEllipse3}
291 %> <br>\image html example/vis/SubplotEllipse3/SubplotEllipse3.1.png width=700
292 %>
293 %> \final{SubplotEllipse3}
294 %>
295 %> \author
296 %> \JoshuaOsborne, May 21 2024, 5:35 PM, University of Texas at Arlington<br>
297 %> \FatemehBagheri, May 20 2024, 1:25 PM, NASA Goddard Space Flight Center (GSFC), Washington, D.C.<br>
298 %> \AmirShahmoradi, May 16 2016, 9:03 AM, Oden Institute for Computational Engineering and Sciences (ICES), UT Austin<br>
299 function self = SubplotEllipse3(gramian, center, zval, cval, varargin)
300
301 %%%% Define the missing optional values as empty with the right rank.
302
303 if nargin < 4
304 cval = zeros(0, 0);
305 end
306 if nargin < 3
307 zval = zeros(0, 0);
308 end
309 if nargin < 2
310 center = zeros(0, 0);
311 end
312 if nargin < 1
313 gramian = zeros(0, 0, 0);
314 end
315
316 varargin = { "gramian", pm.container.DataRef(gramian) ...
317 , "center", pm.container.DataRef(center) ...
318 , "zval", pm.container.DataRef(zval) ...
319 , "cval", pm.container.DataRef(cval) ...
320 , varargin{:} ...
321 };
322 self = self@pm.vis.SubplotLineScatter3([], varargin{:})
323
324 end
325 end
326
327 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
328
329 methods(Access = public)
330
331 %> \brief
332 %> Reset the properties of the plot to the original default settings.<br>
333 %>
334 %> \details
335 %> Use this method when you change many attributes of the plot and
336 %> you want to clean up and go back to the default settings.<br>
337 %>
338 %> \param[inout] self : The **implicitly-passed** input argument representing the parent object of the method.<br>
339 %> \param[in] varargin : Any ``property, value`` pair of the parent object.<br>
340 %> If the property is a ``struct()``, then its value must be given as a cell array,
341 %> with consecutive elements representing the struct ``property-name, property-value`` pairs.<br>
342 %> Note that all of these property-value pairs can be also directly set via the
343 %> parent object attributes, before calling the ``make()`` method.<br>
344 %>
345 %> \interface{reset}
346 %> \code{.m}
347 %>
348 %> pm.vis.SubplotEllipse3.reset() % reset the plot to the default settings.
349 %> pm.vis.SubplotEllipse3.reset(varargin)
350 %>
351 %> \endcode
352 %>
353 %> \final{len}
354 %>
355 %> \author
356 %> \JoshuaOsborne, May 22 2024, 5:42 PM, University of Texas at Arlington<br>
357 %> \AmirShahmoradi, May 16 2016, 9:03 AM, Oden Institute for Computational Engineering and Sciences (ICES), UT Austin<br>
358 function reset(self, varargin)
359 self.dimx = [];
360 self.dimy = [];
361 self.npnt = [];
362 self.names = [];
363 self.ellindex = [];
364 reset@pm.vis.SubplotLineScatter3(self, varargin{:});
365 self.surface.lineWidth = [];
366 self.scatter3.enabled = [];
367 self.surface.enabled = [];
368 self.plot3.enabled = [];
369 self.colormap.map = []; %"winter"
370 self.colormap.enabled = [];
371 end
372
373 end
375 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
376
377 methods(Access = public, Hidden)
378
379 %> \brief
380 %> Prepare the subplot for visualization.<br>
381 %>
382 %> \warning
383 %> This method has side-effects by manipulating
384 %> the existing attributes of the parent object.<br>
385 %>
386 %> \param[inout] self : The input/output parent object of class [pm.vis.SubplotEllipse3](@ref SubplotEllipse3)
387 %> which is **implicitly** passed to this dynamic method (not by the user).<br>
388 %> \param[in] varargin : Any ``property, value`` pair of the parent object.<br>
389 %> If the property is a ``struct()``, then its value must be given as a cell array,
390 %> with consecutive elements representing the struct ``property-name, property-value`` pairs.<br>
391 %> Note that all of these property-value pairs can be also directly set via the
392 %> parent object attributes, before calling the ``premake()`` method.<br>
393 %>
394 %> \interface{premake}
395 %> \code{.m}
396 %>
397 %> pm.vis.SubplotEllipse3.premake();
398 %> pm.vis.SubplotEllipse3.premake(varargin);
399 %>
400 %> \endcode
401 %>
402 %> \example{premake}
403 %> \code{.m}
404 %>
405 %> s = pm.vis.SubplotEllipse3();
406 %> s.premake("dimx", 1, "dimy", 2], "colormap", {"map", "autumn"})
407 %>
408 %> \endcode
409 %>
410 %> \final{premake}
411 %>
412 %> \author
413 %> \JoshuaOsborne, May 22 2024, 5:45 PM, University of Texas at Arlington<br>
414 %> \FatemehBagheri, May 20 2024, 1:25 PM, NASA Goddard Space Flight Center (GSFC), Washington, D.C.<br>
415 %> \AmirShahmoradi, May 16 2016, 9:03 AM, Oden Institute for Computational Engineering and Sciences (ICES), UT Austin<br>
416 function premake(self, varargin)
417
418 if ~isempty(varargin)
419 self.hash2comp(varargin); % parse arguments
420 end
421
422 %%%%
423 %%%% Set the visualization types.
424 %%%%
425
426 if isempty(self.colormap.map)
427 self.colormap.map = "winter";
428 end
429
430 if isempty(self.colormap.enabled)
431 self.colormap.enabled = true;
432 end
434 if isempty(self.colorbar.enabled)
435 self.colorbar.enabled = self.colormap.enabled;
436 end
437
438 if isempty(self.plot3.enabled)
439 self.plot3.enabled = ~self.colormap.enabled;
440 end
441
442 if isempty(self.surface.enabled)
443 self.surface.enabled = self.colormap.enabled;
444 end
445
446 if isempty(self.scatter3.enabled)
447 self.scatter3.enabled = ~(self.plot3.enabled || self.surface.enabled);
448 end
449
450 %%%%
451 %%%% Set the visualization specs.
452 %%%%
453
454 if isempty(self.surface.lineWidth)
455 self.surface.lineWidth = 1.5;
456 end
457
458 %%%%
459 %%%% Set the visualization specs of the parent (and set the data components).
460 %%%%
461
462 premake@pm.vis.SubplotLineScatter3(self);
463
464 %%%%
465 %%%% Set the line color to default MATLAB blue only if scatter is disabled and colormap is disabled and color is unset by the user.
466 %%%%
467
468 if ~(self.colormap.enabled || self.scatter3.enabled)
469 [val, failed] = pm.matlab.hashmap.getKeyVal("plot3", varargin);
470 if ~failed
471 [~, failed] = pm.matlab.hashmap.getKeyVal("color", val);
472 end
473 if failed
474 self.plot3.color = [0, 0.4470, 0.7410];
475 end
476 end
477
478 %%%%
479 %%%% Set the data.
480 %%%%
481
482 self.workspace = struct();
483 self.workspace.cval = self.cval.copy();
484 self.workspace.zval = self.zval.copy();
485 self.workspace.center = self.center.copy();
486 self.workspace.gramian = self.gramian.copy();
487
488 %%%%
489 %%%% Get the shape of input data.
490 %%%%
491
492 %%%% The following ``size()`` syntax is essential for compatibility with MATLAB R2019a.
493
494 self.workspace.shape = struct();
495
496 [s1, s2] = size(self.workspace.cval);
497 self.workspace.shape.cval = [s1, s2];
498
499 [s1, s2] = size(self.workspace.zval);
500 self.workspace.shape.zval = [s1, s2];
501
502 [s1, s2] = size(self.workspace.center);
503 self.workspace.shape.center = [s1, s2];
504
505 [s1, s2, s3] = size(self.workspace.gramian);
506 self.workspace.shape.gramian = [s1, s2, s3];
507
508 %%%%
509 %%%% Infer ``ndim``.
510 %%%%
511
512 self.ndim = max([2, self.workspace.shape.gramian(1), self.workspace.shape.center(1)]);
513 if self.ndim < 2
514 self.ndim = 2;
515 end
516
517 %%%%
518 %%%% Infer ``nell``.
519 %%%%
520
521 self.nell = max([self.workspace.shape.gramian(3), self.workspace.shape.center(2), self.workspace.shape.zval(2), self.workspace.shape.cval(2)]);
522 if self.nell == 0
523 self.nell = 75;
524 end
525
526 %%%%
527 %%%% Infer ``npnt``.
528 %%%%
529
530 if isempty(self.npnt)
531 self.npnt = max(self.workspace.shape.zval(1), self.workspace.shape.cval(1));
532 if self.npnt < 2
533 self.npnt = 100;
534 end
535 end
536
537 %%%%
538 %%%% Assert data shape consistencies.
539 %%%%
540
541 asserted = true;
542 asserted = asserted && self.ndim == self.workspace.shape.center(1) || self.workspace.shape.center(1) < 2;
543 asserted = asserted && self.ndim == self.workspace.shape.gramian(1) || self.workspace.shape.gramian(1) < 2;
544 asserted = asserted && self.ndim == self.workspace.shape.gramian(2) || self.workspace.shape.gramian(2) < 2;
545 asserted = asserted && self.nell == self.workspace.shape.gramian(3) || self.workspace.shape.gramian(3) < 2;
546 asserted = asserted && self.nell == self.workspace.shape.center(2) || self.workspace.shape.center(2) < 2;
547 asserted = asserted && self.nell == self.workspace.shape.zval(2) || self.workspace.shape.zval(2) < 2;
548 asserted = asserted && self.nell == self.workspace.shape.cval(2) || self.workspace.shape.cval(2) < 2;
549
550 if ~asserted
551 help("pm.vis.SubplotEllipse3")
552 disp("size(gramian)")
553 disp( self.workspace.shape.gramian )
554 disp("size(center)")
555 disp( self.workspace.shape.center )
556 disp("size(zval)")
557 disp( self.workspace.shape.zval )
558 disp("size(cval)")
559 disp( self.workspace.shape.cval )
560 disp("[ndim, nell]")
561 disp( [self.ndim, self.nell] )
562 error ( newline ...
563 + "The shapes of the specified ``gramian``, ``center``, ``zval``, and ``cval`` are incompatible." + newline ...
564 + "For more information, see the documentation of the input arguments to the object constructor displayed above." + newline ...
565 + newline ...
566 );
567 end
568
569 %%%%
570 %%%% Set the default dimx and dimy or verify the custom values to visualize.
571 %%%%
572
573 if isempty(self.dimx) && isempty(self.dimy)
574 self.workspace.dimx = 1;
575 self.workspace.dimy = 2;
576 elseif isempty(self.dimx) && ~isempty(self.dimy)
577 self.workspace.dimy = self.dimy;
578 self.workspace.dimx = zeros(numel(self.dimy), 1);
579 for i = 1 : numel(self.dimy)
580 if self.dimy(i) == 1
581 self.workspace.dimx(i) = self.dimy(i) + 1;
582 else
583 self.workspace.dimx(i) = self.dimy(i) - 1;
584 end
585 end
586 elseif isempty(self.dimy) && ~isempty(self.dimx)
587 self.workspace.dimx = self.dimx;
588 self.workspace.dimy = zeros(numel(self.dimx), 1);
589 for i = 1 : numel(self.dimx)
590 if self.dimx(i) == 1
591 self.workspace.dimy(i) = self.dimx(i) + 1;
592 else
593 self.workspace.dimy(i) = self.dimx(i) - 1;
594 end
595 end
596 else
597 self.workspace.dimx = self.dimx;
598 self.workspace.dimy = self.dimy;
599 end
600
601 if numel(self.workspace.dimx) ~= numel(self.workspace.dimy)
602 if numel(self.workspace.dimx) == 1
603 self.workspace.dimx = self.workspace.dimx * ones(numel(self.workspace.dimy), 1);
604 elseif numel(self.workspace.dimy) == 1
605 self.workspace.dimy = self.workspace.dimy * ones(numel(self.workspace.dimx), 1);
606 else
607 help("pm.vis.SubplotEllipse3")
608 disp("self.dimx")
609 disp( self.dimx )
610 disp("size(self.dimx)")
611 disp( size(self.dimx) )
612 disp("self.dimy")
613 disp( self.dimy )
614 disp("size(self.dimy)")
615 disp( size(self.dimy) )
616 error ( newline ...
617 + "The sizes of the specified ``dimx`` and ``dimy`` must either be equal or one must have size of ``1``." + newline ...
618 + "For more information, see the documentation displayed above." + newline ...
619 + newline ...
620 );
621 end
622 end
623
624 %%%%
625 %%%% Check the consistency of shape of ``self.names``.
626 %%%%
627
628 if ~isempty(self.names) && pm.array.len(self.names) ~= self.ndim
629 help("pm.vis.SubplotEllipse3")
630 disp("string(self.names)")
631 disp( string(self.names) )
632 disp("length(string(self.names))")
633 disp( length(string(self.names)) )
634 error ( newline ...
635 + "The component ``names`` must be a vector of size ``ndim`` of strings." + newline ...
636 + "For more information, see the documentation displayed above." + newline ...
637 + newline ...
638 );
639 end
640
641 %%%%
642 %%%% Set the visualization axes names.
643 %%%%
644
645 if ~isempty(self.names)
646 self.workspace.names = string(self.names);
647 self.workspace.names = self.workspace.names(:);
648 else
649 self.workspace.names = strings(self.ndim, 1);
650 for idim = 1 : self.ndim
651 self.workspace.names(idim) = "Dimension " + string(idim);
652 end
653 end
654
655 if ~pm.array.len(self.xlabel.txt)
656 self.xlabel.txt = string(self.workspace.names(self.workspace.dimx(:)));
657 end
658 if ~pm.array.len(self.ylabel.txt)
659 self.ylabel.txt = string(self.workspace.names(self.workspace.dimy(:)));
660 end
661 if ~pm.array.len(self.zlabel.txt)
662 if ~isempty(self.workspace.zval)
663 self.zlabel.txt = "Z";
664 else
665 self.zlabel.txt = "Ellipsoid Index";
666 end
667 end
668
669 %%%%
670 %%%% Setup the gramian values.
671 %%%%
672
673 if numel(self.workspace.gramian) == 0
674 % The gramians of all ellipsoids are equal and identity matrix.
675 self.workspace.gramian = repmat(eye(self.ndim, self.ndim), 1, 1, self.nell);
676 elseif numel(self.workspace.gramian) == 1
677 % The gramians of all ellipsoids are equal and a multiple of the identity matrix.
678 self.workspace.gramian = repmat(self.workspace.gramian * eye(self.ndim, self.ndim), 1, 1, self.nell);
679 elseif size(self.workspace.gramian, 1) == self.ndim && size(self.workspace.gramian, 2) == self.ndim && size(self.workspace.gramian, 3) == 1
680 % All ellipsoids have the same user-prescribed self.workspace.gramian matrix.
681 self.workspace.gramian = repmat(self.workspace.gramian(:, :, 1), 1, 1, self.nell);
682 elseif size(self.workspace.gramian, 1) == 1 && size(self.workspace.gramian, 2) == 1 && size(self.workspace.gramian, 3) == self.nell
683 % Each ellipse has its unique diagonal self.workspace.gramian matrix whose diagonal values are all equal and prescribed by the user.
684 temp = zeros(self.ndim, self.ndim, self.nell);
685 for iell = 1 : self.nell
686 temp(:, :, iell) = self.workspace.gramian(1, 1, iell) * eye(self.ndim, self.ndim);
687 end
688 self.workspace.gramian = temp;
689 elseif size(self.workspace.gramian, 1) ~= self.ndim && size(self.workspace.gramian, 2) ~= self.ndim && size(self.workspace.gramian, 3) ~= self.nell
690 help("pm.vis.SubplotEllipse3")
691 disp("size(gramian)")
692 disp( size(self.workspace.gramian) )
693 disp("[self.ndim, self.nell]")
694 disp( [self.ndim, self.nell] )
695 error ( newline ...
696 + "The shapes of the specified ``gramian`` is incompatible with the" + newline ...
697 + "inferred number of ellipsoid dimensions ``ndim`` and the number of ellipsoids ``nell``." + newline ...
698 + "For more information, see the documentation of the ``gramian`` component displayed above." + newline ...
699 + newline ...
700 );
701 end
702
703 %%%%
704 %%%% Setup the center values.
705 %%%%
706
707 if numel(self.workspace.center) == 0
708 % The centers of all ellipsoids have the same coordinates and all coordinate axes have zero values.
709 self.workspace.center = zeros(self.ndim, self.nell);
710 elseif numel(self.workspace.center) == 1
711 % The centers of all ellipsoids have the same coordinates and all coordinate axes have equal non-zero values.
712 self.workspace.center = self.workspace.center * ones(self.ndim, self.nell);
713 elseif size(self.workspace.center, 1) == self.ndim && size(self.workspace.center, 2) == 1
714 % The centers of all ellipsoids have the same coordinates.
715 self.workspace.center = repmat(self.workspace.center, 1, self.nell);
716 elseif size(self.workspace.center, 1) == 1 && size(self.workspace.center, 2) == self.nell
717 % All coordinates of each ellipse self.workspace.center are the same.
718 self.workspace.center = repmat(self.workspace.center, self.ndim, 1);
719 elseif size(self.workspace.center, 1) ~= self.ndim || size(self.workspace.center, 2) ~= self.nell
720 help("pm.vis.SubplotEllipse3")
721 disp("size(self.workspace.center)")
722 disp( size(self.workspace.center) )
723 disp("[self.ndim, self.nell]")
724 disp( [self.ndim, self.nell] )
725 error ( newline ...
726 + "The shapes of the specified ``center`` is incompatible with the" + newline ...
727 + "inferred number of ellipsoid dimensions ``ndim`` and the number of ellipsoids ``nell``." + newline ...
728 + "For more information, see the documentation of the ``center`` component displayed above." + newline ...
729 + newline ...
730 );
731 end
732
733 %%%%
734 %%%% Setup the zval values.
735 %%%%
736
737 if numel(self.workspace.zval) == 0
738 % 2D plot in 3D visualization at zero z value.
739 self.workspace.zval = repmat(1 : self.nell, self.npnt, 1);
740 if isempty(self.zscale)
741 self.zscale = "log";
742 end
743 elseif numel(self.workspace.zval) == 1
744 % 2D plot in 3D visualization at a non-zero z value.
745 self.workspace.zval = self.workspace.zval * ones(self.npnt, self.nell);
746 elseif size(self.workspace.zval, 1) == self.npnt && size(self.workspace.zval, 2) == 1
747 % The corresponding points on all ellipsoids have the same z values.
748 self.workspace.zval = repmat(self.workspace.zval, 1, self.nell);
749 elseif size(self.workspace.zval, 1) == 1 && size(self.workspace.zval, 2) == self.nell
750 % All points on each ellipse have the same z values.
751 self.workspace.zval = repmat(self.workspace.zval, self.npnt, 1);
752 elseif size(self.workspace.zval, 1) ~= self.npnt || size(self.workspace.zval, 2) ~= self.nell
753 help("pm.vis.SubplotEllipse3")
754 disp("size(self.workspace.zval)")
755 disp( size(self.workspace.zval) )
756 disp("[self.ndim, self.nell]")
757 disp( [self.ndim, self.nell] )
758 error ( newline ...
759 + "The shapes of the specified ``zval`` is incompatible with" + newline ...
760 + "the inferred number of ellipsoids ``nell`` in the input self.workspace." + newline ...
761 + "For more information, see the documentation of the ``zval`` component displayed above." + newline ...
762 + newline ...
763 );
764 end
765
766 %%%%
767 %%%% Setup the cval values. This is relevant only to colormap mode.
768 %%%%
769
770 if numel(self.workspace.cval) == 0
771 self.workspace.cval = repmat(1 : self.nell, self.npnt, 1);
772 if ~pm.array.len(self.axes.colorScale)
773 self.axes.colorScale = "log";
774 end
775 elseif numel(self.workspace.cval) == 1
776 % 2D plot in 3D visualization at a non-zero z value.
777 self.workspace.cval = self.workspace.cval * ones(self.npnt, self.nell);
778 elseif size(self.workspace.cval, 1) == self.npnt && size(self.workspace.cval, 2) == 1
779 % The corresponding points on all ellipsoids have the same z values.
780 self.workspace.cval = repmat(self.workspace.cval, 1, self.nell);
781 elseif size(self.workspace.cval, 1) == 1 && size(self.workspace.cval, 2) == self.nell
782 % All points on each ellipse have the same z values.
783 self.workspace.cval = repmat(self.workspace.cval, self.npnt, 1);
784 elseif size(self.workspace.cval, 1) ~= self.npnt || size(self.workspace.cval, 2) ~= self.nell
785 help("pm.vis.SubplotEllipse3")
786 disp("size(self.workspace.cval)")
787 disp( size(self.workspace.cval) )
788 disp("[self.ndim, self.nell]")
789 disp( [self.ndim, self.nell] )
790 error ( newline ...
791 + "The shapes of the specified ``cval`` is incompatible with" + newline ...
792 + "the inferred number of ellipsoids ``nell`` in the input self.workspace." + newline ...
793 + "For more information, see the documentation of the ``cval`` component displayed above." + newline ...
794 + newline ...
795 );
796 end
797
798 %%%%
799 %%%% Check the consistency of shape of ``self.ellindex``.
800 %%%%
801
802 if ~isempty(self.ellindex)
803 self.workspace.ellindex = self.ellindex(:);
804 else
805 self.workspace.ellindex = pm.array.logrange(1, self.nell, 75);
806 end
807
808 %%%%
809 %%%% Generate column indices.
810 %%%%
811
812 fields = ["colx", "coly", "colz", "colc"];
813 for icol = 1 : length(fields)
814 field = fields(icol);
815 self.(field) = length(fields) * ((1 : length(self.workspace.ellindex) * numel(self.workspace.dimx)) - 1) + icol;
816 end
817
818 %%%%
819 %%%% Generate ellipse self.workspace.
820 %%%%
821
822 gramtmp = zeros(2, 2);
823 bcrd = zeros(size(self.workspace.zval, 1), length(fields) * length(self.workspace.ellindex) * numel(self.workspace.dimx));
824 for idim = 1 : numel(self.workspace.dimx)
825 for iell = 1 : length(self.workspace.ellindex)
826 jell = self.workspace.ellindex(iell);
827 icol = (iell - 1) * length(fields) + 1;
828 iset = (idim - 1) * length(fields) * length(self.workspace.ellindex);
829 dimxy = [self.workspace.dimx(idim), self.workspace.dimy(idim)];
830 if self.workspace.dimx(idim) ~= self.workspace.dimy(idim)
831 gramtmp(:, :) = self.workspace.gramian(dimxy, dimxy, jell);
832 else
833 sigmasq = self.workspace.gramian(self.workspace.dimx(idim), self.workspace.dimx(idim), jell);
834 gramtmp(:, :) = [sigmasq, 0; 0, sigmasq];
835 end
836 bcrd(:, iset + icol : iset + icol + 1) = pm.geom.ell2.getBorder ( gramtmp ...
837 , self.workspace.center(dimxy, jell) ...
838 , size(self.workspace.zval, 1) ...
839 );
840 bcrd(:, iset + icol + 2) = self.workspace.zval(:, jell);
841 if 3 < length(fields)
842 bcrd(:, iset + icol + 3) = self.workspace.cval(:, jell);
843 end
844 end
845 end
846
847 %%%%
848 %%%% Generate the dataframe.
849 %%%%
850
851 self.dfref = pm.container.DataFrame(bcrd);
852
853 end
854
855 end
856
857 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
858
859 methods(Access = public)
860
861 %> \brief
862 %> Generate a plot from the selected dimensions
863 %> of the input ellipsoid data to the object constructor.<br>
864 %>
865 %> \note
866 %> This method is pure, except for the changes in ``fout`` component.<br>
867 %>
868 %> \param[inout] self : The input/output parent object of class [pm.vis.SubplotEllipse3](@ref SubplotEllipse3)
869 %> which is **implicitly** passed to this dynamic method (not by the user).<br>
870 %> \param[in] varargin : Any ``property, value`` pair of the parent object.<br>
871 %> If the property is a ``struct()``, then its value must be given as a cell array,
872 %> with consecutive elements representing the struct ``property-name, property-value`` pairs.<br>
873 %> Note that all of these property-value pairs can be also directly set via the
874 %> parent object attributes, before calling the ``make()`` method.<br>
875 %>
876 %> \interface{make}
877 %> \code{.m}
878 %>
879 %> pm.vis.SubplotEllipse3.make();
880 %> pm.vis.SubplotEllipse3.make(varargin);
881 %>
882 %> \endcode
883 %>
884 %> \example{make}
885 %> \include{lineno} example/vis/SubplotEllipse3/main.m
886 %> \vis{make}
887 %> <br>\image html example/vis/SubplotEllipse3/SubplotEllipse3.1.png width=700
888 %>
889 %> \final{make}
890 %>
891 %> \author
892 %> \JoshuaOsborne, May 22 2024, 5:46 PM, University of Texas at Arlington<br>
893 %> \FatemehBagheri, May 20 2024, 1:25 PM, NASA Goddard Space Flight Center (GSFC), Washington, D.C.<br>
894 %> \AmirShahmoradi, May 16 2016, 9:03 AM, Oden Institute for Computational Engineering and Sciences (ICES), UT Austin<br>
895 function make(self, varargin)
896
897 make@pm.vis.SubplotLineScatter3(self, varargin{:});
898
899 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
900 %%%% RULE 0: No component of ``self`` is allowed to appear to the left of assignment operator, except ``fout``.
901 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
902
903 if self.colormap.enabled && self.colorbar.enabled
904 if prod(self.workspace.shape.cval) < 1
905 % input cval is empty
906 %self.fout.colorbar.Ticks = self.fout.axes.ZTick;
907 %%self.fout.colorbar.Limits = self.fout.axes.ZLim;
908 ylabel(self.fout.colorbar, "Ellipsoid Index");
909 else
910 ylabel(self.fout.colorbar, "Color Data");
911 end
912 end
914 end
915
916 end
917
918 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
919
920end
function verify(in varval, in vartype, in varsize, in varname)
Verify the type and number of elements of the input varval match the specified input vartype and vars...
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 a c...
Definition: Cascade.m:32
This is the abstract class for generating instances of objects that can contain basic attributes requ...
Definition: DataFrame.m:25
This is the abstract class for generating instances of objects that can contain basic attributes requ...
Definition: DataRef.m:27
This is the abstract class for generating instances of objects that contain the specifications of var...
Definition: Figure.m:27
This is the base class for generating instances of objects that contain the specifications of various...
Definition: Plot.m:29
This is the SubplotEllipse3 class for generating instances of 3-dimensional Ellipse Subplot visualiza...
function make(in self, in varargin)
Generate a plot from the selected dimensions of the input ellipsoid data to the object constructor.
function premake(in self, in varargin)
Prepare the subplot for visualization.
function reset(in self, in varargin)
Reset the properties of the plot to the original default settings.
function SubplotEllipse3(in gramian, in center, in zval, in cval, in varargin)
Construct and return an object of class pm.vis.SubplotEllipse.
This is the SubplotEllipse class for generating instances of 2-dimensional Ellipse Subplot visualizat...
This is the SubplotLineScatter3 class for generating instances of 3-dimensional Line-Scatter Subplot ...
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 abstract class for generating instances of objects that contain the specifications of var...
Definition: Tile.m:23
This is the base class for generating instances of figures containing a square symmetric tiling of su...
Definition: Triplex.m:31
function clean()
Remove all paths that contain the ParaMonte lib directory from the MATLAB path variable.
function copy(in from, in to, in field, in exclude)
Copy the contents of the struct/object from to the struct/object to recursively and without destroyin...
function getBorder(in gramian, in center, in npnt)
Return a matrix of MATLAB doubles of shape [npnt, 2] containing the coordinates of a set of points on...
function getKeyVal(in key, in hashmap)
Return the value corresponding to the input key in the input hashmap cell array.
function len(in obj)
Return a scalar MATLAB whole-number containing the length of the input scalar or vector object.
function logrange(in start, in stop, in sizemax)
Return a set of maximum sizemax unique integer spacings almost linearly spaced in the natural logarit...
function map()
Return a scalar MATLAB logical that is true if and only if the current installation of MATLAB contain...
function which(in vendor)
Return the a MATLAB string containing the path to the first mpiexec executable binary found in system...