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.Figure](@ref Figure)<br>
18%> [pm.vis.Corner](@ref Corner)<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.data.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.data.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.data.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.data.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.data.DataRef(gramian) ...
317 , "center", pm.data.DataRef(center) ...
318 , "zval", pm.data.DataRef(zval) ...
319 , "cval", pm.data.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 input/output parent object of class [pm.vis.SubplotEllipse3](@ref SubplotEllipse3)
339 %> which is **implicitly** passed to this dynamic method (not by the user).<br>
340 %> \param[in] varargin : Any ``property, value`` pair of the parent object.<br>
341 %> If the property is a ``struct()``, then its value must be given as a cell array,
342 %> with consecutive elements representing the struct ``property-name, property-value`` pairs.<br>
343 %> Note that all of these property-value pairs can be also directly set via the
344 %> parent object attributes, before calling the ``make()`` method.<br>
345 %>
346 %> \interface{reset}
347 %> \code{.m}
348 %>
349 %> pm.vis.SubplotEllipse3.reset() % reset the plot to the default settings.
350 %> pm.vis.SubplotEllipse3.reset(varargin)
351 %>
352 %> \endcode
353 %>
354 %> \final{len}
355 %>
356 %> \author
357 %> \JoshuaOsborne, May 22 2024, 5:42 PM, University of Texas at Arlington<br>
358 %> \AmirShahmoradi, May 16 2016, 9:03 AM, Oden Institute for Computational Engineering and Sciences (ICES), UT Austin<br>
359 function reset(self, varargin)
360 self.dimx = [];
361 self.dimy = [];
362 self.npnt = [];
363 self.names = [];
364 self.ellindex = [];
365 reset@pm.vis.SubplotLineScatter3(self, varargin{:});
366 self.surface.lineWidth = [];
367 self.scatter3.enabled = [];
368 self.surface.enabled = [];
369 self.plot3.enabled = [];
370 self.colormap.map = []; %"winter"
371 self.colormap.enabled = [];
372 end
373
374 end
376 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
377
378 methods(Access = public, Hidden)
379
380 %> \brief
381 %> Prepare the subplot for visualization.<br>
382 %>
383 %> \warning
384 %> This method has side-effects by manipulating
385 %> the existing attributes of the parent object.<br>
386 %>
387 %> \param[inout] self : The input/output parent object of class [pm.vis.SubplotEllipse3](@ref SubplotEllipse3)
388 %> which is **implicitly** passed to this dynamic method (not by the user).<br>
389 %> \param[in] varargin : Any ``property, value`` pair of the parent object.<br>
390 %> If the property is a ``struct()``, then its value must be given as a cell array,
391 %> with consecutive elements representing the struct ``property-name, property-value`` pairs.<br>
392 %> Note that all of these property-value pairs can be also directly set via the
393 %> parent object attributes, before calling the ``premake()`` method.<br>
394 %>
395 %> \interface{premake}
396 %> \code{.m}
397 %>
398 %> pm.vis.SubplotEllipse3.premake();
399 %> pm.vis.SubplotEllipse3.premake(varargin);
400 %>
401 %> \endcode
402 %>
403 %> \example{premake}
404 %> \code{.m}
405 %>
406 %> s = pm.vis.SubplotEllipse3();
407 %> s.premake("dimx", 1, "dimy", 2], "colormap", {"map", "autumn"})
408 %>
409 %> \endcode
410 %>
411 %> \final{premake}
412 %>
413 %> \author
414 %> \JoshuaOsborne, May 22 2024, 5:45 PM, University of Texas at Arlington<br>
415 %> \FatemehBagheri, May 20 2024, 1:25 PM, NASA Goddard Space Flight Center (GSFC), Washington, D.C.<br>
416 %> \AmirShahmoradi, May 16 2016, 9:03 AM, Oden Institute for Computational Engineering and Sciences (ICES), UT Austin<br>
417 function premake(self, varargin)
418
419 if ~isempty(varargin)
420 self.hash2comp(varargin); % parse arguments
421 end
422
423 %%%%
424 %%%% Set the visualization types.
425 %%%%
426
427 if isempty(self.colormap.map)
428 self.colormap.map = "winter";
429 end
430
431 if isempty(self.colormap.enabled)
432 self.colormap.enabled = true;
433 end
435 if isempty(self.colorbar.enabled)
436 self.colorbar.enabled = self.colormap.enabled;
437 end
438
439 if isempty(self.plot3.enabled)
440 self.plot3.enabled = ~self.colormap.enabled;
441 end
442
443 if isempty(self.surface.enabled)
444 self.surface.enabled = self.colormap.enabled;
445 end
446
447 if isempty(self.scatter3.enabled)
448 self.scatter3.enabled = ~(self.plot3.enabled || self.surface.enabled);
449 end
450
451 %%%%
452 %%%% Set the visualization specs.
453 %%%%
454
455 if isempty(self.surface.lineWidth)
456 self.surface.lineWidth = 1.5;
457 end
458
459 %%%%
460 %%%% Set the visualization specs of the parent (and set the data components).
461 %%%%
462
463 premake@pm.vis.SubplotLineScatter3(self);
464
465 %%%%
466 %%%% Set the line color to default MATLAB blue only if scatter is disabled and colormap is disabled and color is unset by the user.
467 %%%%
468
469 if ~(self.colormap.enabled || self.scatter3.enabled)
470 [val, failed] = pm.matlab.hashmap.getKeyVal("plot3", varargin);
471 if ~failed
472 [~, failed] = pm.matlab.hashmap.getKeyVal("color", val);
473 end
474 if failed
475 self.plot3.color = [0, 0.4470, 0.7410];
476 end
477 end
478
479 %%%%
480 %%%% Set the data.
481 %%%%
482
483 self.workspace = struct();
484 self.workspace.cval = self.cval.copy();
485 self.workspace.zval = self.zval.copy();
486 self.workspace.center = self.center.copy();
487 self.workspace.gramian = self.gramian.copy();
488
489 %%%%
490 %%%% Get the shape of input data.
491 %%%%
492
493 %%%% The following ``size()`` syntax is essential for compatibility with MATLAB R2019a.
494
495 self.workspace.shape = struct();
496
497 [s1, s2] = size(self.workspace.cval);
498 self.workspace.shape.cval = [s1, s2];
499
500 [s1, s2] = size(self.workspace.zval);
501 self.workspace.shape.zval = [s1, s2];
502
503 [s1, s2] = size(self.workspace.center);
504 self.workspace.shape.center = [s1, s2];
505
506 [s1, s2, s3] = size(self.workspace.gramian);
507 self.workspace.shape.gramian = [s1, s2, s3];
508
509 %%%%
510 %%%% Infer ``ndim``.
511 %%%%
512
513 self.ndim = max([2, self.workspace.shape.gramian(1), self.workspace.shape.center(1)]);
514 if self.ndim < 2
515 self.ndim = 2;
516 end
517
518 %%%%
519 %%%% Infer ``nell``.
520 %%%%
521
522 self.nell = max([self.workspace.shape.gramian(3), self.workspace.shape.center(2), self.workspace.shape.zval(2), self.workspace.shape.cval(2)]);
523 if self.nell == 0
524 self.nell = 75;
525 end
526
527 %%%%
528 %%%% Infer ``npnt``.
529 %%%%
530
531 if isempty(self.npnt)
532 self.npnt = max(self.workspace.shape.zval(1), self.workspace.shape.cval(1));
533 if self.npnt < 2
534 self.npnt = 100;
535 end
536 end
537
538 %%%%
539 %%%% Assert data shape consistencies.
540 %%%%
541
542 asserted = true;
543 asserted = asserted && self.ndim == self.workspace.shape.center(1) || self.workspace.shape.center(1) < 2;
544 asserted = asserted && self.ndim == self.workspace.shape.gramian(1) || self.workspace.shape.gramian(1) < 2;
545 asserted = asserted && self.ndim == self.workspace.shape.gramian(2) || self.workspace.shape.gramian(2) < 2;
546 asserted = asserted && self.nell == self.workspace.shape.gramian(3) || self.workspace.shape.gramian(3) < 2;
547 asserted = asserted && self.nell == self.workspace.shape.center(2) || self.workspace.shape.center(2) < 2;
548 asserted = asserted && self.nell == self.workspace.shape.zval(2) || self.workspace.shape.zval(2) < 2;
549 asserted = asserted && self.nell == self.workspace.shape.cval(2) || self.workspace.shape.cval(2) < 2;
550
551 if ~asserted
552 help("pm.vis.SubplotEllipse3")
553 disp("size(gramian)")
554 disp( self.workspace.shape.gramian )
555 disp("size(center)")
556 disp( self.workspace.shape.center )
557 disp("size(zval)")
558 disp( self.workspace.shape.zval )
559 disp("size(cval)")
560 disp( self.workspace.shape.cval )
561 disp("[ndim, nell]")
562 disp( [self.ndim, self.nell] )
563 error ( newline ...
564 + "The shapes of the specified ``gramian``, ``center``, ``zval``, and ``cval`` are incompatible." + newline ...
565 + "For more information, see the documentation of the input arguments to the object constructor displayed above." + newline ...
566 + newline ...
567 );
568 end
569
570 %%%%
571 %%%% Set the default dimx and dimy or verify the custom values to visualize.
572 %%%%
573
574 if isempty(self.dimx) && isempty(self.dimy)
575 self.workspace.dimx = 1;
576 self.workspace.dimy = 2;
577 elseif isempty(self.dimx) && ~isempty(self.dimy)
578 self.workspace.dimy = self.dimy;
579 self.workspace.dimx = zeros(numel(self.dimy), 1);
580 for i = 1 : numel(self.dimy)
581 if self.dimy(i) == 1
582 self.workspace.dimx(i) = self.dimy(i) + 1;
583 else
584 self.workspace.dimx(i) = self.dimy(i) - 1;
585 end
586 end
587 elseif isempty(self.dimy) && ~isempty(self.dimx)
588 self.workspace.dimx = self.dimx;
589 self.workspace.dimy = zeros(numel(self.dimx), 1);
590 for i = 1 : numel(self.dimx)
591 if self.dimx(i) == 1
592 self.workspace.dimy(i) = self.dimx(i) + 1;
593 else
594 self.workspace.dimy(i) = self.dimx(i) - 1;
595 end
596 end
597 else
598 self.workspace.dimx = self.dimx;
599 self.workspace.dimy = self.dimy;
600 end
601
602 if numel(self.workspace.dimx) ~= numel(self.workspace.dimy)
603 if numel(self.workspace.dimx) == 1
604 self.workspace.dimx = self.workspace.dimx * ones(numel(self.workspace.dimy), 1);
605 elseif numel(self.workspace.dimy) == 1
606 self.workspace.dimy = self.workspace.dimy * ones(numel(self.workspace.dimx), 1);
607 else
608 help("pm.vis.SubplotEllipse3")
609 disp("self.dimx")
610 disp( self.dimx )
611 disp("size(self.dimx)")
612 disp( size(self.dimx) )
613 disp("self.dimy")
614 disp( self.dimy )
615 disp("size(self.dimy)")
616 disp( size(self.dimy) )
617 error ( newline ...
618 + "The sizes of the specified ``dimx`` and ``dimy`` must either be equal or one must have size of ``1``." + newline ...
619 + "For more information, see the documentation displayed above." + newline ...
620 + newline ...
621 );
622 end
623 end
624
625 %%%%
626 %%%% Check the consistency of shape of ``self.names``.
627 %%%%
628
629 if ~isempty(self.names) && pm.array.len(self.names) ~= self.ndim
630 help("pm.vis.SubplotEllipse3")
631 disp("string(self.names)")
632 disp( string(self.names) )
633 disp("length(string(self.names))")
634 disp( length(string(self.names)) )
635 error ( newline ...
636 + "The component ``names`` must be a vector of size ``ndim`` of strings." + newline ...
637 + "For more information, see the documentation displayed above." + newline ...
638 + newline ...
639 );
640 end
641
642 %%%%
643 %%%% Set the visualization axes names.
644 %%%%
645
646 if ~isempty(self.names)
647 self.workspace.names = string(self.names);
648 self.workspace.names = self.workspace.names(:);
649 else
650 self.workspace.names = strings(self.ndim, 1);
651 for idim = 1 : self.ndim
652 self.workspace.names(idim) = "Dimension " + string(idim);
653 end
654 end
655
656 if ~pm.array.len(self.xlabel.txt)
657 self.xlabel.txt = string(self.workspace.names(self.workspace.dimx(:)));
658 end
659 if ~pm.array.len(self.ylabel.txt)
660 self.ylabel.txt = string(self.workspace.names(self.workspace.dimy(:)));
661 end
662 if ~pm.array.len(self.zlabel.txt)
663 if ~isempty(self.workspace.zval)
664 self.zlabel.txt = "Z";
665 else
666 self.zlabel.txt = "Ellipsoid Index";
667 end
668 end
669
670 %%%%
671 %%%% Setup the gramian values.
672 %%%%
673
674 if numel(self.workspace.gramian) == 0
675 % The gramians of all ellipsoids are equal and identity matrix.
676 self.workspace.gramian = repmat(eye(self.ndim, self.ndim), 1, 1, self.nell);
677 elseif numel(self.workspace.gramian) == 1
678 % The gramians of all ellipsoids are equal and a multiple of the identity matrix.
679 self.workspace.gramian = repmat(self.workspace.gramian * eye(self.ndim, self.ndim), 1, 1, self.nell);
680 elseif size(self.workspace.gramian, 1) == self.ndim && size(self.workspace.gramian, 2) == self.ndim && size(self.workspace.gramian, 3) == 1
681 % All ellipsoids have the same user-prescribed self.workspace.gramian matrix.
682 self.workspace.gramian = repmat(self.workspace.gramian(:, :, 1), 1, 1, self.nell);
683 elseif size(self.workspace.gramian, 1) == 1 && size(self.workspace.gramian, 2) == 1 && size(self.workspace.gramian, 3) == self.nell
684 % Each ellipse has its unique diagonal self.workspace.gramian matrix whose diagonal values are all equal and prescribed by the user.
685 temp = zeros(self.ndim, self.ndim, self.nell);
686 for iell = 1 : self.nell
687 temp(:, :, iell) = self.workspace.gramian(1, 1, iell) * eye(self.ndim, self.ndim);
688 end
689 self.workspace.gramian = temp;
690 elseif size(self.workspace.gramian, 1) ~= self.ndim && size(self.workspace.gramian, 2) ~= self.ndim && size(self.workspace.gramian, 3) ~= self.nell
691 help("pm.vis.SubplotEllipse3")
692 disp("size(gramian)")
693 disp( size(self.workspace.gramian) )
694 disp("[self.ndim, self.nell]")
695 disp( [self.ndim, self.nell] )
696 error ( newline ...
697 + "The shapes of the specified ``gramian`` is incompatible with the" + newline ...
698 + "inferred number of ellipsoid dimensions ``ndim`` and the number of ellipsoids ``nell``." + newline ...
699 + "For more information, see the documentation of the ``gramian`` component displayed above." + newline ...
700 + newline ...
701 );
702 end
703
704 %%%%
705 %%%% Setup the center values.
706 %%%%
707
708 if numel(self.workspace.center) == 0
709 % The centers of all ellipsoids have the same coordinates and all coordinate axes have zero values.
710 self.workspace.center = zeros(self.ndim, self.nell);
711 elseif numel(self.workspace.center) == 1
712 % The centers of all ellipsoids have the same coordinates and all coordinate axes have equal non-zero values.
713 self.workspace.center = self.workspace.center * ones(self.ndim, self.nell);
714 elseif size(self.workspace.center, 1) == self.ndim && size(self.workspace.center, 2) == 1
715 % The centers of all ellipsoids have the same coordinates.
716 self.workspace.center = repmat(self.workspace.center, 1, self.nell);
717 elseif size(self.workspace.center, 1) == 1 && size(self.workspace.center, 2) == self.nell
718 % All coordinates of each ellipse self.workspace.center are the same.
719 self.workspace.center = repmat(self.workspace.center, self.ndim, 1);
720 elseif size(self.workspace.center, 1) ~= self.ndim || size(self.workspace.center, 2) ~= self.nell
721 help("pm.vis.SubplotEllipse3")
722 disp("size(self.workspace.center)")
723 disp( size(self.workspace.center) )
724 disp("[self.ndim, self.nell]")
725 disp( [self.ndim, self.nell] )
726 error ( newline ...
727 + "The shapes of the specified ``center`` is incompatible with the" + newline ...
728 + "inferred number of ellipsoid dimensions ``ndim`` and the number of ellipsoids ``nell``." + newline ...
729 + "For more information, see the documentation of the ``center`` component displayed above." + newline ...
730 + newline ...
731 );
732 end
733
734 %%%%
735 %%%% Setup the zval values.
736 %%%%
737
738 if numel(self.workspace.zval) == 0
739 % 2D plot in 3D visualization at zero z value.
740 self.workspace.zval = repmat(1 : self.nell, self.npnt, 1);
741 if isempty(self.zscale)
742 self.zscale = "log";
743 end
744 elseif numel(self.workspace.zval) == 1
745 % 2D plot in 3D visualization at a non-zero z value.
746 self.workspace.zval = self.workspace.zval * ones(self.npnt, self.nell);
747 elseif size(self.workspace.zval, 1) == self.npnt && size(self.workspace.zval, 2) == 1
748 % The corresponding points on all ellipsoids have the same z values.
749 self.workspace.zval = repmat(self.workspace.zval, 1, self.nell);
750 elseif size(self.workspace.zval, 1) == 1 && size(self.workspace.zval, 2) == self.nell
751 % All points on each ellipse have the same z values.
752 self.workspace.zval = repmat(self.workspace.zval, self.npnt, 1);
753 elseif size(self.workspace.zval, 1) ~= self.npnt || size(self.workspace.zval, 2) ~= self.nell
754 help("pm.vis.SubplotEllipse3")
755 disp("size(self.workspace.zval)")
756 disp( size(self.workspace.zval) )
757 disp("[self.ndim, self.nell]")
758 disp( [self.ndim, self.nell] )
759 error ( newline ...
760 + "The shapes of the specified ``zval`` is incompatible with" + newline ...
761 + "the inferred number of ellipsoids ``nell`` in the input self.workspace." + newline ...
762 + "For more information, see the documentation of the ``zval`` component displayed above." + newline ...
763 + newline ...
764 );
765 end
766
767 %%%%
768 %%%% Setup the cval values. This is relevant only to colormap mode.
769 %%%%
770
771 if numel(self.workspace.cval) == 0
772 self.workspace.cval = repmat(1 : self.nell, self.npnt, 1);
773 if ~pm.array.len(self.axes.colorScale)
774 self.axes.colorScale = "log";
775 end
776 elseif numel(self.workspace.cval) == 1
777 % 2D plot in 3D visualization at a non-zero z value.
778 self.workspace.cval = self.workspace.cval * ones(self.npnt, self.nell);
779 elseif size(self.workspace.cval, 1) == self.npnt && size(self.workspace.cval, 2) == 1
780 % The corresponding points on all ellipsoids have the same z values.
781 self.workspace.cval = repmat(self.workspace.cval, 1, self.nell);
782 elseif size(self.workspace.cval, 1) == 1 && size(self.workspace.cval, 2) == self.nell
783 % All points on each ellipse have the same z values.
784 self.workspace.cval = repmat(self.workspace.cval, self.npnt, 1);
785 elseif size(self.workspace.cval, 1) ~= self.npnt || size(self.workspace.cval, 2) ~= self.nell
786 help("pm.vis.SubplotEllipse3")
787 disp("size(self.workspace.cval)")
788 disp( size(self.workspace.cval) )
789 disp("[self.ndim, self.nell]")
790 disp( [self.ndim, self.nell] )
791 error ( newline ...
792 + "The shapes of the specified ``cval`` is incompatible with" + newline ...
793 + "the inferred number of ellipsoids ``nell`` in the input self.workspace." + newline ...
794 + "For more information, see the documentation of the ``cval`` component displayed above." + newline ...
795 + newline ...
796 );
797 end
798
799 %%%%
800 %%%% Check the consistency of shape of ``self.ellindex``.
801 %%%%
802
803 if ~isempty(self.ellindex)
804 self.workspace.ellindex = self.ellindex(:);
805 else
806 self.workspace.ellindex = pm.array.logrange(1, self.nell, 75);
807 end
808
809 %%%%
810 %%%% Generate column indices.
811 %%%%
812
813 fields = ["colx", "coly", "colz", "colc"];
814 for icol = 1 : length(fields)
815 field = fields(icol);
816 self.(field) = length(fields) * ((1 : length(self.workspace.ellindex) * numel(self.workspace.dimx)) - 1) + icol;
817 end
818
819 %%%%
820 %%%% Generate ellipse self.workspace.
821 %%%%
822
823 gramtmp = zeros(2, 2);
824 bcrd = zeros(size(self.workspace.zval, 1), length(fields) * length(self.workspace.ellindex) * numel(self.workspace.dimx));
825 for idim = 1 : numel(self.workspace.dimx)
826 for iell = 1 : length(self.workspace.ellindex)
827 jell = self.workspace.ellindex(iell);
828 icol = (iell - 1) * length(fields) + 1;
829 iset = (idim - 1) * length(fields) * length(self.workspace.ellindex);
830 dimxy = [self.workspace.dimx(idim), self.workspace.dimy(idim)];
831 if self.workspace.dimx(idim) ~= self.workspace.dimy(idim)
832 gramtmp(:, :) = self.workspace.gramian(dimxy, dimxy, jell);
833 else
834 sigmasq = self.workspace.gramian(self.workspace.dimx(idim), self.workspace.dimx(idim), jell);
835 gramtmp(:, :) = [sigmasq, 0; 0, sigmasq];
836 end
837 bcrd(:, iset + icol : iset + icol + 1) = pm.geom.ell2.getBorder ( gramtmp ...
838 , self.workspace.center(dimxy, jell) ...
839 , size(self.workspace.zval, 1) ...
840 );
841 bcrd(:, iset + icol + 2) = self.workspace.zval(:, jell);
842 if 3 < length(fields)
843 bcrd(:, iset + icol + 3) = self.workspace.cval(:, jell);
844 end
845 end
846 end
847
848 %%%%
849 %%%% Generate the dataframe.
850 %%%%
851
852 self.df = pm.data.DataFrame(bcrd);
853
854 end
855
856 end
857
858 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
859
860 methods(Access = public)
861
862 %> \brief
863 %> Generate a plot from the selected dimensions
864 %> of the input ellipsoid data to the object constructor.<br>
865 %>
866 %> \note
867 %> This method is pure, except for the changes in ``fout`` component.<br>
868 %>
869 %> \param[inout] self : The input/output parent object of class [pm.vis.SubplotEllipse3](@ref SubplotEllipse3)
870 %> which is **implicitly** passed to this dynamic method (not by the user).<br>
871 %> \param[in] varargin : Any ``property, value`` pair of the parent object.<br>
872 %> If the property is a ``struct()``, then its value must be given as a cell array,
873 %> with consecutive elements representing the struct ``property-name, property-value`` pairs.<br>
874 %> Note that all of these property-value pairs can be also directly set via the
875 %> parent object attributes, before calling the ``make()`` method.<br>
876 %>
877 %> \interface{make}
878 %> \code{.m}
879 %>
880 %> pm.vis.SubplotEllipse3.make();
881 %> pm.vis.SubplotEllipse3.make(varargin);
882 %>
883 %> \endcode
884 %>
885 %> \example{make}
886 %> \include{lineno} example/vis/SubplotEllipse3/main.m
887 %> \vis{make}
888 %> <br>\image html example/vis/SubplotEllipse3/SubplotEllipse3.1.png width=700
889 %>
890 %> \final{make}
891 %>
892 %> \author
893 %> \JoshuaOsborne, May 22 2024, 5:46 PM, University of Texas at Arlington<br>
894 %> \FatemehBagheri, May 20 2024, 1:25 PM, NASA Goddard Space Flight Center (GSFC), Washington, D.C.<br>
895 %> \AmirShahmoradi, May 16 2016, 9:03 AM, Oden Institute for Computational Engineering and Sciences (ICES), UT Austin<br>
896 function make(self, varargin)
897
898 make@pm.vis.SubplotLineScatter3(self, varargin{:});
899
900 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
901 %%%% RULE 0: No component of ``self`` is allowed to appear to the left of assignment operator, except ``fout``.
902 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
903
904 if self.colormap.enabled && self.colorbar.enabled
905 if prod(self.workspace.shape.cval) < 1
906 % input cval is empty
907 %self.fout.colorbar.Ticks = self.fout.axes.ZTick;
908 %%self.fout.colorbar.Limits = self.fout.axes.ZLim;
909 ylabel(self.fout.colorbar, "Ellipsoid Index");
910 else
911 ylabel(self.fout.colorbar, "Color Data");
912 end
913 end
915 end
916
917 end
918
919 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
920
921end
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 libraries.
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 base class for generating instances of figures containing a symmetric square grid or corn...
Definition: Corner.m:19
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:9
function clean()
Remove all paths that contain the ParaMonte lib directory from the MATLAB path variable.
function copy(in from, in to, in fields)
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...