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