Files
imdd_silas/Classes/Warehouse_class/classes/DataStorage.m
2025-11-21 15:37:58 +01:00

360 lines
14 KiB
Matlab

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 e
disp(e.message)
disp('Provide save path')
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) = StorageParameter(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
function addValueToStorageByLinIdx(obj, valueToStore ,storageVarName, lin_idx)
obj.sto.(storageVarName){lin_idx} = valueToStore;
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)
tmp = obj.sto.(storageVarName){lin_idx(i)};
if ~isempty(tmp)
if isa(tmp,'double')
try
value(i,:) = tmp ;
catch
a = size(value,2);
b = size(tmp,2);
if a > b
value(i,:) =[tmp,NaN(1,a-b)] ;
elseif a < b
value(i,:) = tmp(1:size(value,2)) ;
else
error('unknwon case...')
end
end
elseif isa(tmp,'Signal') || isa(tmp,'struct') || isa(tmp,'Exfo_laser') || isa(tmp,'DC_supply')
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} ;
else
value{i} = tmp ;
end
else
try
if i == 1
value = {};
end
value{i} = tmp ;
catch
% value(i,:) = tmp(1:size(value,2)) ;
if size(value,2) < size(tmp,2)
diff = size(tmp,2) - size(value,2);
value(:,end+1:end+diff) = NaN(size(value,1),diff);
value(i,:) = tmp ;
elseif size(value,2) > size(tmp,2)
diff = size(value,2) - size(tmp,2);
tmp(:,end+1:end+diff) = NaN(1,diff);
value(i,:) = tmp ;
end
end
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
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
function [phys_indices,param_name] = getPhysIndicesByLinIndex(obj, lin_idx)
% Converts a linear index into the corresponding physical parameter values
% Inputs:
% - lin_idx: The linear index within the storage array
% Output:
% - phys_indices: A cell array containing the physical parameter values for each dimension
% Initialize output cell array
phys_indices = cell(1, numel(obj.fn));
% Convert linear index to subscript indices
[subscripts{1:numel(obj.dim)}] = ind2sub(obj.dim, lin_idx);
% Map subscripts to physical values for each parameter
for i = 1:numel(obj.fn)
param_name{i} = obj.fn(i);
phys_indices{i} = obj.parameter.(param_name{i}).getPhysForIndex(subscripts{i});
end
end
function [physStruct, stored_value] = getPhysAndValueByLinIndex(obj, storageVarName, lin_idx)
% Retrieves a structure with physical parameter values as fieldnames,
% their corresponding parameter names as values, and the stored value
% for a given linear index.
% Inputs:
% - storageVarName: Name of the storage variable in obj.sto
% - lin_idx: The linear index within the storage array
% Outputs:
% - physStruct: A structure with physical parameter values as fieldnames
% and parameter names as values
% - stored_value: The value stored at the given linear index in the
% specified storage variable
% Initialize an empty structure
physStruct = struct();
% Convert linear index to subscript indices
[subscripts{1:numel(obj.dim)}] = ind2sub(obj.dim, lin_idx);
% Map subscripts to physical values and parameter names for each dimension
for i = 1:numel(obj.fn)
param_name = obj.fn(i);
phys_value = obj.parameter.(param_name).getPhysForIndex(subscripts{i});
% Add to the structure with phys_value as the fieldname and param_name as the value
physStruct.(param_name) = phys_value;
end
% Retrieve the stored value at the given linear index
stored_value = obj.sto.(storageVarName){lin_idx};
end
function num_elements = getLastLinIndice(obj)
% Returns all possible linear indices for the data structure
% Output:
% - lin_indices: A column vector containing all linear indices for the storage array
% Calculate the total number of elements in the storage array
num_elements = prod(obj.dim);
end
end
end