Auswertung Experiment

Database tüddelei
DBHanlder läuft gut für DIESE Datanbank struktur...
App begonnen aber weit entfernt von gutem Stand
This commit is contained in:
sioe
2024-11-15 16:51:37 +01:00
parent 553ed19b9f
commit 397cfa61dd
219 changed files with 584 additions and 854 deletions

View File

@@ -254,7 +254,12 @@ classdef Signal
CallingModifier = evalin('caller','obj');
end
CallingModifierStruct = obj.objToStructFilteredRecursive(CallingModifier);
if isa(CallingModifier,"Signal")
CallingModifierStruct = obj.objToStructFilteredRecursive(CallingModifier);
ModifierCopy = {CallingModifierStruct};
end
ModifierCopy = {CallingModifier};
SignalType = [string(class(obj))];
TimeStamp = [(datetime('now','TimeZone','local','Format','HH:mm:ss'))];
@@ -263,7 +268,7 @@ classdef Signal
Nase = [0];
SignalCopy = obj.signal;
ModifierName = class(CallingModifier);
ModifierCopy = {CallingModifierStruct};
cell = {SignalType , TimeStamp , Length , SignalPower(1) , Nase, SignalCopy, ModifierName, ModifierCopy, Description};

View File

@@ -1,4 +1,4 @@
classdef EQ %< handle
classdef EQ < handle
%EQ Summary of this class goes here
% Detailed explanation goes here
@@ -289,9 +289,9 @@ classdef EQ %< handle
e_dc = e_dc - obj.DCmu*error;
obj.error_log.e_ffe(cnt,trainloops) = e_ffe;
obj.error_log.e_dfe(cnt,trainloops) = e_dfe;
obj.error_log.e_(cnt,trainloops) = error;
% obj.error_log.e_ffe(cnt,trainloops) = e_ffe;
% obj.error_log.e_dfe(cnt,trainloops) = e_dfe;
% obj.error_log.e_(cnt,trainloops) = error;
cnt = cnt+1;
if obj.Nb(1) > 0
@@ -460,7 +460,7 @@ classdef EQ %< handle
if 1%mu_mat ~= 0
e_dc = e_dc - obj.DCmu*error;
error_log(cnt,dd_loop) = e_dc;
% error_log(cnt,dd_loop) = e_dc;
cnt = cnt+1;
end

View File

@@ -0,0 +1,60 @@
classdef Postfilter < handle
%NAME Summary of this class goes here
% Detailed explanation goes here
properties(Access=public)
ncoeff = 2;
burg_coeff = [];
end
methods (Access=public)
function obj = Postfilter(options)
%NAME Construct an instance of this class
% Detailed explanation goes here
arguments
options.ncoeff double = 2
end
%
fn = fieldnames(options);
for n = 1:numel(fn)
try
obj.(fn{n}) = options.(fn{n});
end
end
% do more stuff
end
function signalclass_out = process(obj,signalclass_in,noiseclass_in)
obj.burg_coeff = arburg(noiseclass_in.signal,obj.ncoeff);
signalclass_in = signalclass_in.filter(obj.burg_coeff,1);
% append to logbook
lbdesc = ['Postfilter'];
signalclass_in = signalclass_in.logbookentry(lbdesc);
% write to output
signalclass_out = signalclass_in;
end
function showFilter(obj,noiseclass_in)
noiseclass_in.spectrum('displayname','Noise PSD shifted to 0dBm','fignum',123,'normalizeTo0dB',1);
[h,w] = freqz(1,obj.burg_coeff,length(noiseclass_in),"whole",noiseclass_in.fs);
h = h/max(abs(h));
hold on
w_ = (w - noiseclass_in.fs/2);
plot(w_.*1e-9,20*log10(fftshift(h)),'DisplayName',['Burg Coeffs: ', num2str(obj.burg_coeff), ' ']);
end
end
end

View File

@@ -1,4 +1,4 @@
classdef MLSE
classdef MLSE < handle
%MLSE calculates the most probable sequence for an input signal with given/ known channel impulse response of any length
properties(Access=public)

View File

@@ -38,10 +38,22 @@ classdef DBHandler < handle
error('Failed to connect to the database: %s', e.message);
end
% Get table names and the first rows of each table to understand the structure
obj.getTableNames();
obj.getTables();
obj.getDistinctValues();
if obj.dbIsHealthy
obj.refresh();
else
error('DB seems to be corrupt')
end
end
function obj = refresh(obj)
% Get table names and the first rows of each table to understand the structure
obj.getTableNames();
obj.getTables();
obj.getDistinctValues();
end
function obj = getTableNames(obj)
@@ -86,10 +98,10 @@ classdef DBHandler < handle
obj.distinctValues = struct();
% Iterate over each table in obj.tables
tableNames = fieldnames(obj.tables);
tableNames_ = fieldnames(obj.tables);
for i = 1:numel(tableNames)
tableName = tableNames{i};
for i = 1:numel(tableNames_)
tableName = tableNames_{i};
% Initialize a sub-struct to store distinct values for each field in the table
obj.distinctValues.(tableName) = struct();
@@ -101,10 +113,10 @@ classdef DBHandler < handle
for j = 1:numel(fieldNames)
fieldName = fieldNames{j};
% Skip fields ending with '_id' as they don't contain useful distinct values
if endsWith(fieldName, '_id')
continue;
end
% % Skip fields ending with '_id' as they don't contain useful distinct values
% if endsWith(fieldName, '_id')
% continue;
% end
% Construct SQL to get distinct values for the current field
query = sprintf('SELECT DISTINCT %s FROM %s', fieldName, tableName);
@@ -123,17 +135,38 @@ classdef DBHandler < handle
obj.distinctValues.(tableName).(fieldName) = distinctValues;
catch e
warning('Failed to retrieve distinct values for %s.%s: %s', tableName, fieldName, e.message);
% warning('Failed to retrieve distinct values for %s.%s: %s', tableName, fieldName, e.message);
obj.distinctValues.(tableName).(fieldName) = [];
end
end
end
% Display the distinct values (optional, for debugging purposes)
disp('Distinct values for each field:');
disp(obj.distinctValues);
end
function healthyDB = dbIsHealthy(obj)
healthyDB = false;
num_runs = obj.fetch('SELECT COUNT(*) AS total_runs FROM Runs');
num_configs = obj.fetch('SELECT COUNT(*) AS total_configurations FROM Configurations');
num_meas = obj.fetch('SELECT COUNT(*) AS total_measurements FROM Measurements');
assert((num_runs{1,1}==num_configs{1,1})&&(num_configs{1,1}==num_meas{1,1}),'Different num of entries per table');
%Check for any duplicate paths
duplictae_raw = obj.fetch("SELECT COALESCE(Runs.rx_raw_path,'NaN') AS rx_raw_path, COUNT(*) AS occurrences FROM Runs GROUP BY rx_raw_path HAVING COUNT(*) > 1");
duplictae_sync = obj.fetch("SELECT COALESCE(Runs.rx_sync_path,'NaN') AS rx_sync_path, COUNT(*) AS occurrences FROM Runs GROUP BY rx_sync_path HAVING COUNT(*) > 1");
if size(duplictae_raw,2) > 1
for i = 1:size(duplictae_raw,2)-1
fprintf('Raw Rx Paths: Found %d duplictaes of %s \n',duplictae_raw.occurrences(i),duplictae_raw.rx_raw_path(i));
end
end
healthyDB = true;
end
function lastID = appendToTable(obj, tableName, newRow)
% appendToTable Appends a new row to the specified table
@@ -241,11 +274,87 @@ classdef DBHandler < handle
end
end
function addBEREntry(obj, berValue, occurrence, runID, ffe, dfe, mlse, pf, eqType, ffe_order, dfe_order, len_tr, mu_ffe, mu_dfe, mu_dc, comment)
% addBEREntry Adds a BER entry linked to an existing or new Equalizer entry.
% Usage:
% addBEREntry(runID, eq, ffe, dfe, mlse, pf, eqType, ffe_order, dfe_order, len_tr, mu_ffe, mu_dfe, mu_dc, berValue, comment)
if isempty(pf)
postfilter_taps = [];
else
postfilter_taps = pf.burg_coeff;
end
% Create equalizer data struct for searching and adding if necessary
equalizerData = struct( ...
'ffe', jsonencode(ffe), ...
'dfe', jsonencode(dfe), ...
'mlse', jsonencode(mlse), ...
'pf', jsonencode(pf), ...
'eq_type', string(eqType), ...
'ffe_order', jsonencode(ffe_order), ...
'dfe_order', jsonencode(dfe_order), ...
'postfilter_taps',jsonencode(postfilter_taps),...
'len_tr', len_tr, ...
'mu_ffe', jsonencode(mu_ffe), ...
'mu_dfe', mu_dfe, ...
'mu_dc', mu_dc, ...
'comment', comment ...
);
% Check if exact Equalizer and BER entries already exist in the DB ...
selectedFields = {'Runs.run_id','BERs.ber_id','Equalizer.eq_id','BERs.ber',['BERs.occurrence' ...
'']};
filterParams = obj.tables;
filterParams.Equalizer = equalizerData;
[dataTable,sql_query] = obj.queryDB(filterParams, selectedFields);
% get or insert Equalizer
if ~isempty(dataTable)
% Equalizer entry already exists, use the existing eq_id
cur_eq_id = dataTable.eq_id;
else
% Insert the new Equalizer entry
cur_eq_id = obj.appendToTable('Equalizer', equalizerData);
end
% skip if already here or insert BER entry
if ~isempty(dataTable)
% A BER entry with the same eq_id, run_id, and occurrence already exists
existingBERValue = dataTable.ber;
% Compare the existing BER value with the new BER value
if existingBERValue == berValue
fprintf('The BER entry %.2e || -- eq_id: %d -- run_id: %d -- occurrence: %d already exists. \n',berValue, cur_eq_id, runID, occurrence);
else
fprintf('Already found BER for EQ: %.2e ~= %.2e || -- eq_id: %d -- run_id: %d -- occurrence: %d already exists.\n', berValue, existingBERValue, cur_eq_id, runID, occurrence);
end
else
% No such BER entry exists, insert the new BER entry
berData = struct( ...
'run_id', runID, ...
'eq_id', cur_eq_id, ...
'ber', berValue, ...
'occurrence', occurrence ...
);
obj.appendToTable('BERs', berData);
end
end
function answer = fetch(obj,query)
answer = fetch(obj.conn,query);
end
function result = getPathsWithFlexibleFilter(obj, filterParams, selectedFields)
function [result,query] = queryDB(obj, filterParams, selectedFields)
% getPathsWithFlexibleFilter Retrieves values from Runs table with flexible filtering
% and lets the user select which fields to include in the SELECT statement.
%
@@ -257,8 +366,9 @@ classdef DBHandler < handle
% If left empty, two popup windows will prompt the user for input.
%
% Outputs:
% rxRawPaths: Cell array of values from the Runs table matching the criteria.
% filteredValues: Table of distinct values for parameters included in filterParams.
% result: table with sql return
% query: this was send to SQL DB
arguments
obj
filterParams = [];
@@ -299,7 +409,7 @@ classdef DBHandler < handle
fieldName = fieldParts{2};
if isnumeric(obj.tables.(tableName).(fieldName))
selectClause = [selectClause, 'COALESCE(', selectedFields{i}, ', -1) AS ', fieldName];
selectClause = [selectClause, 'COALESCE(', selectedFields{i}, ', ''NaN'') AS ', fieldName];
else
selectClause = [selectClause, 'COALESCE(', selectedFields{i}, ', '''') AS ', fieldName];
end
@@ -321,10 +431,10 @@ classdef DBHandler < handle
% Loop through each table in filterParams
filterClauses = [];
tableNames = fieldnames(filterParams);
tableNames_ = fieldnames(filterParams);
for t = 1:numel(tableNames)
tableName = tableNames{t};
for t = 1:numel(tableNames_)
tableName = tableNames_{t};
tableParams = filterParams.(tableName);
% Loop through each parameter in the table
@@ -343,12 +453,14 @@ classdef DBHandler < handle
elseif isnumeric(value) && isnan(value)
% If value is NaN, use IS NULL in SQL
filterClause = sprintf('%s IS NULL', fullName);
elseif isnumeric(value)
elseif isnumeric(value) && ~isEnumeration(value)
filterClause = sprintf('%s = %f', fullName, value);
elseif islogical(value) || (isnumeric(value) && ismember(value, [0, 1]))
elseif islogical(value) || (isnumeric(value) && ismember(value, [0, 1])) && ~isEnumeration(value)
filterClause = sprintf('%s = %d', fullName, value);
elseif ischar(value) || isstring(value)
filterClause = sprintf('%s = "%s"', fullName, value);
filterClause = sprintf('%s = ''%s''', fullName, char(value)); %nicht nach string suchen sondern nach chararray -> 'bla' statt "bla"
elseif isEnumeration(value)
filterClause = sprintf('%s = ''%s''', fullName, value);
else
error('Unsupported data type for field "%s".', fullName);
end
@@ -376,6 +488,7 @@ classdef DBHandler < handle
end
function selectedFields = promptSelectFields(obj)
% promptSelectFields Prompts the user to select fields from multiple tables to include in the SELECT statement using settingsdlg.
@@ -436,41 +549,67 @@ classdef DBHandler < handle
% promptFilterParameters Prompts the user to enter filter parameters using the settingsdlg framework.
% Get all possible parameters from all tables (excluding sqlite_sequence)
tableNames = fieldnames(obj.tables);
tableNames = setdiff(tableNames, {'sqlite_sequence'}); % Remove sqlite_sequence
tableNames_ = fieldnames(obj.tables);
tableNames_ = setdiff(tableNames_, {'sqlite_sequence'}); % Remove sqlite_sequence
% Prepare the inputs for settingsdlg with sections and separators
promptSettings = {};
allFieldsFullName = {};
convertedFieldNames = {};
for i = 1:numel(tableNames)
for i = 1:numel(tableNames_)
% Add a separator for each table section
promptSettings{end + 1} = 'separator';
promptSettings{end + 1} = tableNames{i};
promptSettings{end + 1} = tableNames_{i};
% Get all fields from the current table
tableFields = fieldnames(obj.tables.(tableNames{i}));
tableFields = fieldnames(obj.tables.(tableNames_{i}));
% Prepare each field to be added to the dialog
for j = 1:numel(tableFields)
fieldName = tableFields{j};
fullName = sprintf('%s.%s', tableNames{i}, fieldName);
fullName = sprintf('%s.%s', tableNames_{i}, fieldName);
convertedName = strrep(fullName, '.', '_'); % Replace '.' with '_'
% Skip fields that do not have distinct values stored
if ~isfield(obj.distinctValues.(tableNames_{i}), fieldName)
continue;
end
% Get the distinct values for the field
distinctValues_ = obj.distinctValues.(tableNames_{i}).(fieldName);
% Prepare distinct values for dropdown
if isempty(distinctValues_)
% If there are no distinct values, use only an "All" entry
distinctValues_ = {'All'};
else
% Ensure distinctValues is a cell array of strings
if isnumeric(distinctValues_)
distinctValues_ = arrayfun(@(x) num2str(x), distinctValues_, 'UniformOutput', false);
elseif isstring(distinctValues_)
distinctValues_ = cellstr(distinctValues_);
elseif iscell(distinctValues_) && ~iscellstr(distinctValues_)
distinctValues_ = cellfun(@num2str, distinctValues_, 'UniformOutput', false);
end
% Add an "All" option at the beginning of the distinct values list
distinctValues_ = [{'All'}; distinctValues_];
end
allFieldsFullName{end + 1} = fullName; % Add full name to the list
convertedFieldNames{end + 1} = convertedName; % Store the converted name
% Add the field name and value setting to the prompt
promptSettings{end + 1} = {sprintf('%s', fullName), convertedName};
promptSettings{end + 1} = [];
promptSettings{end + 1} = distinctValues_; % Add distinct values as dropdown options
end
end
% Create the settings dialog
[settings, button] = settingsdlg(...
'title', 'Input Parameters for Filtering', ...
'description', 'Enter the values for each field to filter. Leave empty to include all values. Type NaN for NULL.', ...
'description', 'Enter the values for each field to filter. Select "All" to include all values.', ...
promptSettings{:} ...
);
@@ -497,7 +636,7 @@ classdef DBHandler < handle
end
% Assign values to the respective fields under each table
if isempty(value)
if strcmp(value, 'All')
filterParams.(tableName).(fieldName) = []; % Set to empty to include all values
elseif isnumeric(value) && isnan(value)
filterParams.(tableName).(fieldName) = NaN; % Use NaN to handle as NULL
@@ -510,5 +649,6 @@ classdef DBHandler < handle
end
end