From 7d3b20a8c3e303712e9d81267618510dc6108345 Mon Sep 17 00:00:00 2001
From: Michael Innerberger <michael.innerberger@asc.tuwien.ac.at>
Date: Wed, 9 Aug 2023 10:51:53 -0400
Subject: [PATCH] Start refactoring Type

---
 lib/storage/@LevelData/LevelData.m            |   4 +-
 lib/storage/@LevelData/get.m                  |   9 +-
 lib/storage/@LevelData/plotLevel.m            |   4 +-
 lib/storage/@LevelData/set.m                  |   2 +-
 lib/storage/@LevelData/setAbsolute.m          |   2 +-
 lib/storage/@LevelData/setTime.m              |   2 +-
 .../LevelDataCollection.m                     |   6 +-
 lib/storage/@Type/Type.m                      |  96 -----------
 lib/storage/@Type/determineTypeValue.m        |  63 --------
 lib/storage/Type/RawType.m                    |  18 +++
 lib/storage/Type/ValueDetails.m               | 150 ++++++++++++++++++
 11 files changed, 180 insertions(+), 176 deletions(-)
 delete mode 100644 lib/storage/@Type/Type.m
 delete mode 100644 lib/storage/@Type/determineTypeValue.m
 create mode 100644 lib/storage/Type/RawType.m
 create mode 100644 lib/storage/Type/ValueDetails.m

diff --git a/lib/storage/@LevelData/LevelData.m b/lib/storage/@LevelData/LevelData.m
index 04c3ec1..bd02419 100644
--- a/lib/storage/@LevelData/LevelData.m
+++ b/lib/storage/@LevelData/LevelData.m
@@ -272,7 +272,7 @@ classdef LevelData < handle
 
         function width = getWidth(~, type)
             minimalWidth = 8;
-            width = num2str(max(type.width, minimalWidth));
+            width = num2str(max(type.printWidth, minimalWidth));
         end
 
         function spec = getHeaderSpecifier(obj, separator)
@@ -295,7 +295,7 @@ classdef LevelData < handle
                     separator = '\n';
                 end
                 t = obj.type.(obj.scalarVariable{j});
-                spec = [spec, '%', obj.getWidth(t), t.type, separator];
+                spec = [spec, '%', obj.getWidth(t), t.rawType.formatSpec, separator];
             end
         end
 
diff --git a/lib/storage/@LevelData/get.m b/lib/storage/@LevelData/get.m
index d801d43..9d06178 100644
--- a/lib/storage/@LevelData/get.m
+++ b/lib/storage/@LevelData/get.m
@@ -49,11 +49,6 @@ function data = get(obj, jLevel, variableName)
     for jVariable = 1:length(variableName)
         name = variableName{jVariable};
 
-        % Check for strings/character arrays
-        if ~strcmp(obj.type.(name).type, 'c') && ...
-                ~strcmp(obj.type.(name).type, 's')
-            containsCharOnly = false;
-        end
         % Determine index of current variable
         idx = obj.getIndex(name);
         if obj.isScalar(idx)
@@ -76,8 +71,8 @@ function data = get(obj, jLevel, variableName)
         % Save extracted data to return variable
         data(:,jVariable) = value;
         % Post-process character arrays
-        if containsCharOnly
+        if obj.type.(name).rawType == RawType.TEXT
             data = mat2cell(char(data), ones(length(data), 1));
         end
     end
-end
\ No newline at end of file
+end
diff --git a/lib/storage/@LevelData/plotLevel.m b/lib/storage/@LevelData/plotLevel.m
index e06d1e3..0434807 100644
--- a/lib/storage/@LevelData/plotLevel.m
+++ b/lib/storage/@LevelData/plotLevel.m
@@ -39,7 +39,7 @@ function ax = plotLevel(obj, plotFunction, xVariable, yVariable)
 
     % Iterate over given variables
     for j = 1:length(yVariable)
-        if ~obj.type.(yVariable{j}).isFloat
+        if obj.type.(yVariable{j}).rawType ~= RawType.FLOAT
             continue
         end
 
@@ -61,4 +61,4 @@ function ax = plotLevel(obj, plotFunction, xVariable, yVariable)
         % Add new line into the current figure when calling plotConvergence again
         hold(ax, 'on');
     end
-end
\ No newline at end of file
+end
diff --git a/lib/storage/@LevelData/set.m b/lib/storage/@LevelData/set.m
index 8aa3efa..7a8e287 100644
--- a/lib/storage/@LevelData/set.m
+++ b/lib/storage/@LevelData/set.m
@@ -50,7 +50,7 @@ function set(obj, jLevel, variableName, value)
         else
             % Determine type by example data
             [currentType, valueList] = ...
-                Type.determineTypeValue(length(jLevel), name, val);
+                ValueDetails.determineTypeValue(length(jLevel), name, val);
         end
         % Store type
         if ~ismember(name, obj.label)
diff --git a/lib/storage/@LevelData/setAbsolute.m b/lib/storage/@LevelData/setAbsolute.m
index 3eeba6a..0466416 100644
--- a/lib/storage/@LevelData/setAbsolute.m
+++ b/lib/storage/@LevelData/setAbsolute.m
@@ -53,7 +53,7 @@ function setAbsolute(obj, jLevel, variableName, value)
         else
             % Determine type by example data
             [currentType, valueList] = ...
-                Type.determineTypeValue(length(jLevel), name, val);
+                ValueDetails.determineTypeValue(length(jLevel), name, val);
         end
 
         if ~ismember(name, obj.absoluteVariable)
diff --git a/lib/storage/@LevelData/setTime.m b/lib/storage/@LevelData/setTime.m
index cc2c005..a908568 100644
--- a/lib/storage/@LevelData/setTime.m
+++ b/lib/storage/@LevelData/setTime.m
@@ -53,7 +53,7 @@ function setTime(obj, jLevel, variableName, value)
         else
             % Determine type by example data
             [currentType, valueList] = ...
-                Type.determineTypeValue(length(jLevel), name, val);
+                ValueDetails.determineTypeValue(length(jLevel), name, val);
         end
         % Store type
         if ~ismember(name, obj.label)
diff --git a/lib/storage/@LevelDataCollection/LevelDataCollection.m b/lib/storage/@LevelDataCollection/LevelDataCollection.m
index 90fd021..d0d56d5 100644
--- a/lib/storage/@LevelDataCollection/LevelDataCollection.m
+++ b/lib/storage/@LevelDataCollection/LevelDataCollection.m
@@ -144,9 +144,9 @@ classdef LevelDataCollection < handle
             for j = 1:obj.nTimeVariable
                 t = obj.item{1}.type.(obj.timeVariable{j});
                 if j < obj.nTimeVariable
-                    spec = [spec, '%', obj.getWidth(t), t.type, obj.separator];
+                    spec = [spec, '%', obj.getWidth(t), t.rawType.formatSpec, obj.separator];
                 else
-                    spec = [spec, '%', obj.getWidth(t), t.type, '\n'];
+                    spec = [spec, '%', obj.getWidth(t), t.rawType.formatSpec, '\n'];
                 end
             end
             if obj.nTimeVariable == 0
@@ -190,7 +190,7 @@ classdef LevelDataCollection < handle
 
     methods (Access = private)
         function width = getWidth(obj, type)
-            width = num2str(max(type.width, obj.minimalWidth));
+            width = num2str(max(type.printWidth, obj.minimalWidth));
         end
 
         printTable(obj, fid, variableName, data)
diff --git a/lib/storage/@Type/Type.m b/lib/storage/@Type/Type.m
deleted file mode 100644
index eaa6cbb..0000000
--- a/lib/storage/@Type/Type.m
+++ /dev/null
@@ -1,96 +0,0 @@
-classdef Type < handle
-%%TYPE class reprenting the type of a level oriented data
-
-% Copyright 2023 Philipp Bringmann
-%
-% This program is free software: you can redistribute it and/or modify
-% it under the terms of the GNU General Public License as published by
-% the Free Software Foundation, either version 3 of the License, or
-% (at your option) any later version.
-%
-% This program is distributed in the hope that it will be useful,
-% but WITHOUT ANY WARRANTY; without even the implied warranty of
-% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-% GNU General Public License for more details.
-%
-% You should have received a copy of the GNU General Public License
-% along with this program.  If not, see <http://www.gnu.org/licenses/>.
-%
-
-
-    properties
-        % Data type as in format specifier
-        type
-        % Shape of data (scalar, vector, or array)
-        shape
-        % Number of characters required for printing
-        width
-    end
-
-    properties (Dependent)
-        % Boolean determining if type is float
-        isFloat (1,1) boolean
-        % Boolean determining if type is scalar
-        isScalar (1,1) boolean
-    end
-
-    properties (Access=private)
-        % String representing type and formatting of floats
-        STR_FLOAT = '.5e';
-    end
-
-    methods
-        %% CONSTRUCTOR
-        function obj = Type(name, value)
-            %%TYPE creates an object of the Type class given an example
-            %value of the corresponding data
-            %   obj = TYPE(name, value)
-
-            % Determine data type and width
-            if isnan(value)
-                obj.type = 'd';
-                obj.width = 3;
-            elseif isinteger(value)
-                obj.type = 'd';
-                S = cellstr(num2str(value));
-                obj.width = max(cellfun(@(x) length(x), S(:)));
-            elseif isfloat(value)
-                obj.type = obj.STR_FLOAT;
-                obj.width = 6 + str2double(obj.STR_FLOAT(2));
-            elseif ischar(value)
-                obj.type = 'c';
-                obj.width = length(value);
-            elseif isstring(value)
-                obj.type = 's';
-                obj.width = max(cellfun(@(x) length(x), value(:)));
-            else
-                error('Invalid data type');
-            end
-
-            % Determine shape
-            if isscalar(value)
-                obj.shape = 's';
-            elseif isvector(value)
-                obj.shape = 'v';
-            else
-                obj.shape = 'a';
-            end
-
-            % Update width considering length of the name
-            obj.width = max(obj.width, length(name));
-        end
-
-        function bool = get.isFloat(obj)
-            bool = strcmp(obj.type, obj.STR_FLOAT);
-        end
-
-        function bool = get.isScalar(obj)
-            bool = strcmp(obj.shape, 's');
-        end
-    end
-
-    % AUXILIARY
-    methods (Static)
-        [type, valueList] = determineTypeValue(nLevel, variableName, value)
-    end
-end
diff --git a/lib/storage/@Type/determineTypeValue.m b/lib/storage/@Type/determineTypeValue.m
deleted file mode 100644
index 86796ce..0000000
--- a/lib/storage/@Type/determineTypeValue.m
+++ /dev/null
@@ -1,63 +0,0 @@
-function [type, valueList] = determineTypeValue(nLevel, variableName, value)
-%%DETERMINETYPEVALUE auxiliary function for determining type from an array
-%of values
-%    [type, valueList] = DETERMINETYPEVALUE(nLevel, variableName, value)
-
-% Copyright 2023 Philipp Bringmann
-%
-% This program is free software: you can redistribute it and/or modify
-% it under the terms of the GNU General Public License as published by
-% the Free Software Foundation, either version 3 of the License, or
-% (at your option) any later version.
-%
-% This program is distributed in the hope that it will be useful,
-% but WITHOUT ANY WARRANTY; without even the implied warranty of
-% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-% GNU General Public License for more details.
-%
-% You should have received a copy of the GNU General Public License
-% along with this program.  If not, see <http://www.gnu.org/licenses/>.
-%
-
-
-    if nLevel == 1
-        % Array value represents data on a single level
-        type = Type(variableName, value);
-        valueList = {value};
-    else
-        if isvector(value)
-            % Array value represents a vector of scalar values for each
-            % level
-            assert(length(value) == nLevel, ...
-                   'Length of argument invalid');
-            type = Type(variableName, value(1));
-            valueList = mat2cell(value(:), ones(nLevel, 1));
-        else
-            % Array value represents an higher dimensional objects for each
-            % level
-            dims = size(value);
-            if any(dims == nLevel)
-                levelDim = find(dims == nLevel);
-                remainingDim = 1:ndims(value);
-                remainingDim(levelDim) = [];
-                if sum(dims == nLevel) > 1
-                    % Several dimensions could represent the level
-                    % information
-                    warning(['Unclear dimensions of argument. ', ...
-                             'Assume level-oriented data in dimension ', ...
-                             num2str(levelDim)]);
-                end
-                % Extract and rearrange values
-                value = permute(value, [levelDim, remainingDim]);
-                valueList = cell(nLevel, 1);
-                ind = repmat({':'}, length(remainingDim), 1);
-                type = Type(variableName, value(1, ind{:}));
-                for k = 1:nLevel
-                    valueList{k} = value(k, ind{:});
-                end
-            else
-                error('Unable to extract data from argument');
-            end
-        end
-    end
-end
\ No newline at end of file
diff --git a/lib/storage/Type/RawType.m b/lib/storage/Type/RawType.m
new file mode 100644
index 0000000..94bdffa
--- /dev/null
+++ b/lib/storage/Type/RawType.m
@@ -0,0 +1,18 @@
+classdef RawType
+    enumeration
+        INT('d')
+        FLOAT('.5e')
+        TEXT('s')
+    end
+
+    properties (SetAccess=immutable, GetAccess=public)
+        formatSpec
+        
+    end
+
+    methods
+        function obj = RawType(formatSpec)
+            obj.formatSpec = formatSpec;
+        end
+    end
+end
\ No newline at end of file
diff --git a/lib/storage/Type/ValueDetails.m b/lib/storage/Type/ValueDetails.m
new file mode 100644
index 0000000..6dc7b66
--- /dev/null
+++ b/lib/storage/Type/ValueDetails.m
@@ -0,0 +1,150 @@
+classdef ValueDetails
+%%ValueDetails class representing the type and printing parameters of a level
+%oriented data
+
+% Copyright 2023 Philipp Bringmann
+%
+% This program is free software: you can redistribute it and/or modify
+% it under the terms of the GNU General Public License as published by
+% the Free Software Foundation, either version 3 of the License, or
+% (at your option) any later version.
+%
+% This program is distributed in the hope that it will be useful,
+% but WITHOUT ANY WARRANTY; without even the implied warranty of
+% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+% GNU General Public License for more details.
+%
+% You should have received a copy of the GNU General Public License
+% along with this program.  If not, see <http://www.gnu.org/licenses/>.
+%
+
+
+    properties (GetAccess=public, SetAccess=protected)
+        % Raw type
+        rawType
+        % Shape of data (scalar, vector, or array)
+        shape
+        % Number of characters required for printing
+        printWidth
+    end
+
+    properties (Dependent)
+        % Boolean determining if type is scalar
+        isScalar (1,1) boolean
+    end
+
+    methods
+        %% CONSTRUCTOR
+        function obj = ValueDetails(name, value)
+            %%TYPE creates an object of the Type class given an example
+            %value of the corresponding data
+            %   obj = TYPE(name, value)
+
+            % Determine data type and width
+            if isnan(value)
+                % NaN is treated as integer to avoid problems with plotting
+                obj.rawType = RawType.INT;
+                obj.printWidth = 3;
+            elseif isinteger(value)
+                obj.rawType = RawType.INT;
+                S = cellstr(num2str(value));
+                obj.printWidth = max(cellfun(@(x) length(x), S(:)));
+            elseif isfloat(value)
+                obj.rawType = RawType.FLOAT;
+                floatPrecision = str2double(RawType.FLOAT.formatSpec(2));
+                obj.printWidth = 6 + floatPrecision;
+            elseif ischar(value)
+                obj.rawType = RawType.TEXT;
+                obj.printWidth = length(value);
+            elseif isstring(value)
+                obj.rawType = RawType.TEXT;
+                obj.printWidth = max(cellfun(@(x) length(x), value(:)));
+            else
+                error('Invalid data type');
+            end
+
+            % Determine shape
+            if isscalar(value)
+                obj.shape = 's';
+            elseif isvector(value)
+                obj.shape = 'v';
+            else
+                obj.shape = 'a';
+            end
+
+            % Update width considering length of the name
+            obj.printWidth = max(obj.printWidth, length(name));
+        end
+
+        function bool = get.isScalar(obj)
+            bool = strcmp(obj.shape, 's');
+        end
+    end
+
+    % AUXILIARY
+    methods (Static)
+        function [type, valueList] = determineTypeValue(nLevel, variableName, value)
+        %%DETERMINETYPEVALUE auxiliary function for determining type from an array
+        %of values
+        %    [type, valueList] = DETERMINETYPEVALUE(nLevel, variableName, value)
+
+        % Copyright 2023 Philipp Bringmann
+        %
+        % This program is free software: you can redistribute it and/or modify
+        % it under the terms of the GNU General Public License as published by
+        % the Free Software Foundation, either version 3 of the License, or
+        % (at your option) any later version.
+        %
+        % This program is distributed in the hope that it will be useful,
+        % but WITHOUT ANY WARRANTY; without even the implied warranty of
+        % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+        % GNU General Public License for more details.
+        %
+        % You should have received a copy of the GNU General Public License
+        % along with this program.  If not, see <http://www.gnu.org/licenses/>.
+        %
+
+
+            if nLevel == 1
+                % Array value represents data on a single level
+                type = ValueDetails(variableName, value);
+                valueList = {value};
+            else
+                if isvector(value)
+                    % Array value represents a vector of scalar values for each
+                    % level
+                    assert(length(value) == nLevel, ...
+                        'Length of argument invalid');
+                    type = ValueDetails(variableName, value(1));
+                    valueList = mat2cell(value(:), ones(nLevel, 1));
+                else
+                    % Array value represents an higher dimensional objects for each
+                    % level
+                    dims = size(value);
+                    if any(dims == nLevel)
+                        levelDim = find(dims == nLevel);
+                        remainingDim = 1:ndims(value);
+                        remainingDim(levelDim) = [];
+                        if sum(dims == nLevel) > 1
+                            % Several dimensions could represent the level
+                            % information
+                            warning(['Unclear dimensions of argument. ', ...
+                                    'Assume level-oriented data in dimension ', ...
+                                    num2str(levelDim)]);
+                        end
+                        % Extract and rearrange values
+                        value = permute(value, [levelDim, remainingDim]);
+                        valueList = cell(nLevel, 1);
+                        ind = repmat({':'}, length(remainingDim), 1);
+                        type = ValueDetails(variableName, value(1, ind{:}));
+                        for k = 1:nLevel
+                            valueList{k} = value(k, ind{:});
+                        end
+                    else
+                        error('Unable to extract data from argument');
+                    end
+                end
+            end
+        end
+    end
+end
-- 
GitLab