classdef DataStorage < handle %DATASTORAGE Summary of this class goes here % Detailed explanation goes here properties inputParams = struct; parameter = struct; fn = []; dim = []; sto = {}; % getPhysForIndex = struct; % getIndexForPhys = struct; end methods function obj = DataStorage(inputParams) %DATASTORAGE Construct an instance of this class % Detailed explanation goes here % scheiß Variablenname obj.inputParams = inputParams; % Field Names obj.fn = string(fieldnames(inputParams)); % _______________ % Two dicts that map between physical and array index :-) % Dictionary: 10 km -> 3 % obj.getIndexForPhys = obj.buildIndexDict(); % Dictionary: 3 -> 10Km % obj.getPhysForIndex = obj.buildPhysDict(); % _______________ % This is the 2nd Idea -> ecery given Param will be a class % instance of "Parameter", therin user can access the dicts and % informations... Have not decided which way is best.. obj = obj.buildParameter(); % get dimension of dataStorage % e.g. if we have L = [1,2,10,80] and D=[8, 17, 21], we would % need an array with dimesion [4,3]. obj.dim = obj.getDimension(); % finally, create the main storage as cell array obj.sto = struct; end function save(obj,path) try save(path,"obj"); catch end end function showInfo(obj) disp("Data Structure with fields:"); fprintf('%-12s', 'Name'); fprintf('%1s', '| '); fprintf('%0s ', 'Dimension'); fprintf('%4s', '| '); fprintf('%0s ', 'Physical Values'); fprintf('\n'); disp('----------------------------------------------------------------'); for i = 1:numel(obj.fn) fprintf('%-12s', char(obj.fn(i))); fprintf('%1s', '| '); fprintf('%8.1i ', obj.dim(i)); fprintf('%5s', '| '); fprintf('%-7s ', string(obj.parameter.(obj.fn(i)).values) ); fprintf('\n'); end disp('----------------------------------------------------------------'); stofn = string(fieldnames(obj.sto)); for s = 1:numel(stofn) nonempty = numel(find(~cellfun(@isempty,obj.sto.(stofn(s))))); overall = numel(obj.sto.(stofn(s))); fprintf('%-8s', 'Storage '); fprintf('%-10s', char(stofn(s))); fprintf('%4s', 'filled with '); fprintf('%-5s', num2str(nonempty)); fprintf('%-1s', ' entries -> '); fprintf('%-5s', num2str(nonempty/overall*100)); fprintf('%-1s', '% filled'); fprintf('\n'); end end function dim = getDimension(obj) dim = zeros(1,numel(obj.fn)); for p = 1:numel(obj.fn) %loop all parameter names and add their length :-) dim(p)=obj.parameter.(obj.fn(p)).length; end end function obj = buildParameter(obj) for p = 1:numel(obj.fn) name = obj.fn(p); values = obj.inputParams.(name); obj.parameter.(name) = Parameter(name,values); end end function addStorage(obj,varName) % add a storage storage = cell(obj.dim); obj.sto.(string(varName)) = storage; end function addValueToStorage(obj, valueToStore ,storageVarName, varargin) if nargin-3 == numel(obj.fn) lin_idx = obj.getIndicesByPhys(varargin); obj.sto.(storageVarName){lin_idx} = valueToStore; else error('Specify all the indices to access the right place in storage!') end end % Access Value(s) function value = getStoValue(obj,storageVarName, varargin) if nargin-2 == numel(obj.fn) %es wurden aausreichend argumente übergeben :-) %es gibt jedoch erstmal keinen Check ob die Reihenfolge %richtig ist value = []; lin_idx = obj.getIndicesByPhys(varargin); errcnt = 0; for i=1:numel(lin_idx) try tmp = obj.sto.(storageVarName){lin_idx(i)}; if ~isempty(tmp) if isa(tmp,'Signal') if i == 1 value = {}; end value{i} = tmp ; elseif isa(tmp,'cell') if isa(tmp{1},'Signal') if i == 1 value = {}; end value{i} = tmp{1} ; end else value(i,:) = tmp ; end else errcnt = errcnt+1; if errcnt < 3 %get back the n-dimensional subiondices... [sub{1:length(size(obj.sto.(storageVarName)))}] = ind2sub(size(obj.sto.(storageVarName)),lin_idx(i)); %get back the physical representaion word = []; for phys_idx = 1:numel(obj.fn) parametername = obj.fn(phys_idx); word = [word,char(parametername),': ', num2str(obj.parameter.(parametername).getPhysForIndex(sub{phys_idx})),' ;']; end % warning(['Requested Data is not in Warehouse ', word]); elseif errcnt == 3 % warning(['... ', word]); end end if errcnt > 2 % warning([num2str(errcnt),' requested datapoint(s) not in warehouse.']); end catch error('Error in Datastorage: Something happened while looking up in warehouse.') end end else error('Wrong Request using ExampleWarehouse.getStoValue(*parameter set*). Give me all the Parameters! Please!') end end % Mapping for several Indices (calls the mapping for single index) function lin_idx = getIndicesByPhys(obj,varargin) %map _all_ phys. to indices - several calls of single mapping inputsz = cellfun(@size,varargin{1},'UniformOutput',false); inputmax = cell2mat(cellfun(@max,inputsz,'UniformOutput',false)); % I wrote this method for a single query, then refined it for vectorial % inputs (which work fine), but lastly recognized that I % destroyed single query... however, this if / else will fix it! if sum(inputmax)==length(inputmax) vecQuery = 1; %set any value to one else vecQuery = find(inputmax~=1); %position of vectorial queries end q={}; for i = 1:numel(vecQuery) q{i} = varargin{1,1}{vecQuery(i)}; %the two vectors end combination = combvec(q{:}); %combine all possible combinations for c = 1:length(combination) %loop over all possible combinations indices = {}; str = []; for r = 1:numel(vecQuery) %replace varargin with current query (could have been renamed... however it works) varargin{1}{vecQuery(r)} = combination(r,c); end for p = 1:numel(obj.fn) curPhysQuery = varargin{1}{p}; %can be: a) single value // b) range curParameterName = obj.fn(p); indices{end+1} = obj.getIndexByPhys(curParameterName,curPhysQuery); % str = [str, ',indices{', num2str(p), '}']; end %append to index list :-) fn_=fieldnames(obj.sto); n_ = fn_{1}; lin_idx(c,:) = sub2ind(size(obj.sto.(n_)),indices{:}); % lin_idx(c,:) = eval(['sub2ind(size(obj.sto.',n_,')',str,');']); end end % Mapping for single Index function idx = getIndexByPhys(obj,fieldname,phys) %map single phys to index idx = obj.parameter.(fieldname).getIndexForPhys(phys); end end end