Skip to content

Commit

Permalink
BICAS: Mv qual. QRC array funcs. to new bicas.proc.qual
Browse files Browse the repository at this point in the history
modified:   src/+bicas/+proc/+L1L2/qual.m
modified:   src/+bicas/+proc/+L1L2/qual___UTEST.m
new file:   src/+bicas/+proc/qual.m
new file:   src/+bicas/+proc/qual___UTEST.m
  • Loading branch information
ErikPGJ committed Dec 18, 2023
1 parent df8657e commit 7bebf58
Show file tree
Hide file tree
Showing 4 changed files with 373 additions and 319 deletions.
125 changes: 2 additions & 123 deletions mission/solar_orbiter/bicas/src/+bicas/+proc/+L1L2/qual.m
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@
% PROPOSAL: Abolish function. Make code part of
% get_UFV_quality_ZVs().

QrcFlagsMap = bicas.proc.L1L2.qual.NSO_table_to_QRC_flag_arrays(...
QrcFlagsMap = bicas.proc.qual.NSO_table_to_QRC_flag_arrays(...
fieldnames(bicas.const.QRCID), NsoTable, Epoch, L);

% Add autodetected saturation.
Expand All @@ -130,133 +130,12 @@
QrcFlagsMap(bicas.const.QRCID.FULL_SATURATION) = b;

[QUALITY_FLAG, L2_QUALITY_BITMASK] = ...
bicas.proc.L1L2.qual.QRC_flag_arrays_to_quality_ZVs(...
bicas.proc.qual.QRC_flag_arrays_to_quality_ZVs(...
size(Epoch, 1), QrcFlagsMap, QrcidSettingsMap);
end



% IMPLEMENTATION NOTE: Without allQrcidCa, the function can not create a
% return value map that contains keys for all QRCIDs, in case the
% NsoTable does not contain all QRCIDs.
%
% IMPLEMENTATION NOTE: allQrcidCa is an argument due to automated tests.
% Could otherwise be derived from constants.
%
% ARGUMENTS
% =========
% allQrcidCa
% 1D cell array of all QRCIDs.
%
% RETURN VALUE
% ============
% QrcFlagsMap
% containers.Map. QRCID->logical array
% Contains keys for all QRCIDs specified in allQrcidCa, not just
% those present in NsoTable.
%
function QrcFlagsMap = NSO_table_to_QRC_flag_arrays(...
allQrcidCa, NsoTable, Epoch, L)

% Local variable naming conventions:
% ----------------------------------
% GE = Global Event = NSO event in global NSO event table.
% CE = CDF Event = NSO event that overlaps with CDF records.
% Ar = (Non-cell) Array

% NOTE: iCeAr = CDF events as indices to global events.
[bCeRecordsCa, ceQrcidCa, iCeAr] = NsoTable.get_NSO_timestamps(Epoch);
nCe = numel(ceQrcidCa);
nGe = numel(NsoTable.evtQrcidCa);
L.logf('info', ...
['Searched non-standard operations (NSO) table.', ...
' Found %i relevant NSO events out of a total of %i NSO events.'], ...
nCe, nGe);

% Initialize "empty" nsoPerRecordsMap
% -----------------------------------
% IMPLEMENTATION NOTE: valueType=logical implies scalar (sic!).
QrcFlagsMap = containers.Map('keyType', 'char', 'valueType', 'any');
for i = 1:numel(allQrcidCa)
QrcFlagsMap(allQrcidCa{i}) = false(size(Epoch));
end

% Iterate over index into LOCAL/CDF NSO events table.
for kCe = 1:nCe

% Index into GLOBAL NSO events table.
iGe = iCeAr(kCe);
eventQrcid = ceQrcidCa{kCe};
% Indices into ZVs.
bCeRecords = bCeRecordsCa{kCe};

%===========================================================
% Log the relevant NSO event in the GLOBAL NSO events table
%===========================================================
L.logf('info', ' %s -- %s %s', ...
irf.cdf.TT2000_to_UTC_str(NsoTable.evtStartTt2000Array(iGe)), ...
irf.cdf.TT2000_to_UTC_str(NsoTable.evtStopTt2000Array( iGe)), ...
eventQrcid);

% ASSERTION
% NOTE: Not perfect assertion on legal QRCIDs since code only
% checks those relevant for the data (time interval) currently
% processed. (Therefore also checks all QRCIDs when reads NSO
% table.)
assert(ismember(eventQrcid, allQrcidCa), 'Can not interpret QRCID "%s".', eventQrcid)

%================================
% Take action depending on QRCID
%================================
bQrc = QrcFlagsMap(eventQrcid);
bQrc(bCeRecords) = true;
QrcFlagsMap(eventQrcid) = bQrc;
end % for
end



% NOTE: Does not return FPA, since internal algorithm can not produce
% unknown values.
%
% ARGUMENTS
% =========
% nRec
% Number of CDF records (rows).
% IMPLEMENTATION NOTE: Needed for handling the case of zero
% QRCIDs.
function [QUALITY_FLAG, L2_QUALITY_BITMASK] = QRC_flag_arrays_to_quality_ZVs(...
nRec, QrcFlagsMap, QrcidSettingsMap)

% Create "empty" arrays
QUALITY_FLAG = ones( nRec, 1, 'uint8' ) * bicas.const.QUALITY_FLAG_MAX;
L2_QUALITY_BITMASK = zeros(nRec, 1, 'uint16');

qrcidCa = QrcFlagsMap.keys();
for i = 1:numel(qrcidCa)
qrcid = qrcidCa{i};
QrcidSetting = QrcidSettingsMap(qrcid);
bQrcid = QrcFlagsMap(qrcid);

assert(isequal( size(bQrcid), [nRec, 1] ))

% Set QUALITY_FLAG
% ----------------
% IMPLEMENTATION NOTE: Only adjusts relevant indices since the
% operation is more natural (simpler) that way.
QUALITY_FLAG(bQrcid) = min(...
QUALITY_FLAG(bQrcid), ...
QrcidSetting.QUALITY_FLAG);

% Set L2_QUALITY_BITMASK
L2_QUALITY_BITMASK = bitor(...
L2_QUALITY_BITMASK, ...
QrcidSetting.L2_QUALITY_BITMASK * uint16(bQrcid));
end
end



% Overwrite selected records of voltage & current with FVs.
%
% ARGUMENTS
Expand Down
196 changes: 0 additions & 196 deletions mission/solar_orbiter/bicas/src/+bicas/+proc/+L1L2/qual___UTEST.m
Original file line number Diff line number Diff line change
Expand Up @@ -17,202 +17,6 @@



function test_NSO_table_to_QRC_flag_arrays(testCase)

function test(allQrcidCa, NsoTable, Epoch, ExpQrcFlagsMap)
% Normalize/modify arguments
Epoch = int64(Epoch(:));

L = bicas.Logger('human-readable', false);

% CALL TESTED FUNCTION
ActQrcFlagsMap = bicas.proc.L1L2.qual.NSO_table_to_QRC_flag_arrays(...
allQrcidCa, NsoTable, Epoch, L);

% ASSERT EXPECTED RESULT
% ----------------------
% IMPLEMENTATION NOTE: testCase.assertEqual() (and isequaln())
% can handle containers.Map, but that is not very helpful for
% debugging by understanding any found difference between the
% two maps. Therefore explicitly comparing the map subcomponents.
testCase.assertEqual(...
sort(ActQrcFlagsMap.keys), ...
sort(ExpQrcFlagsMap.keys))

qrcidCa = ActQrcFlagsMap.keys;
for i = 1:numel(qrcidCa)
qrcid = qrcidCa{i}
testCase.assertEqual(...
ActQrcFlagsMap(qrcid), ...
ExpQrcFlagsMap(qrcid))
end
end

ALL_ENABLED = true;
%ALL_ENABLED = false;

%====================================
% Empty NSO table. Various Epoch ZVs
%====================================
if ALL_ENABLED
EMPTY_NSO_TABLE = bicas.NsoTable(...
int64(zeros(0, 1)), ...
int64(zeros(0, 1)), ...
cell(0, 1));
EPOCH_DOUBLE_CA = {zeros(0,1), [10], [10;20;30]};
for i = 1:numel(EPOCH_DOUBLE_CA)
Epoch_double = EPOCH_DOUBLE_CA{i};
ExpQrcFlagsMap = containers.Map();
test(...
{}, EMPTY_NSO_TABLE, ...
Epoch_double, ...
ExpQrcFlagsMap ...
)
end
end

%=========================================
% Two non-overlapping NSOs, one at a time
%=========================================
% Nontrivial NSO settings.
ALL_QRCID_CA = {'QRCID1', 'QRCID2'};
NSO_TABLE = bicas.NsoTable(...
int64([1, 4]'*1e9), ...
int64([2, 5]'*1e9), ...
{'QRCID1', 'QRCID2'}');

if ALL_ENABLED
% Time interval is superset of NSO 1/2.
ExpQrcFlagsMap = containers.Map();
ExpQrcFlagsMap('QRCID1') = logical([0 1 1 0]');
ExpQrcFlagsMap('QRCID2') = false(4,1);
test(...
ALL_QRCID_CA, NSO_TABLE, ...
[0:3]*1e9, ...
ExpQrcFlagsMap ...
);
end

if ALL_ENABLED
% Time interval is superset of NSO 2/2.
ExpQrcFlagsMap = containers.Map();
ExpQrcFlagsMap('QRCID1') = false(4,1);
ExpQrcFlagsMap('QRCID2') = logical([0 1 1 0]');
test(...
ALL_QRCID_CA, NSO_TABLE, ...
[3:6]*1e9, ...
ExpQrcFlagsMap ...
);
end

if ALL_ENABLED
% Time interval from middle of NSO 1 to middle of NSO 2.
ExpQrcFlagsMap = containers.Map();
ExpQrcFlagsMap('QRCID1') = logical([1 0 0]');
ExpQrcFlagsMap('QRCID2') = logical([0 0 1]');
test(...
ALL_QRCID_CA, NSO_TABLE, ...
[2:4]'*1e9, ...
ExpQrcFlagsMap ...
);
end

%========================================
% Two overlapping NSOs, one unused QRCID
%========================================
ALL_QRCID_CA = {'QRCID1', 'QRCID2', 'QRCID3'};
NSO_TABLE = bicas.NsoTable(...
int64([1, 2]'*1e9), ...
int64([2, 3]'*1e9), ...
{'QRCID1', 'QRCID2'}');

if ALL_ENABLED
% Time interval covers all NSOs.
ExpQrcFlagsMap = containers.Map();
ExpQrcFlagsMap('QRCID1') = logical([0 1 1 0 0]');
ExpQrcFlagsMap('QRCID2') = logical([0 0 1 1 0]');
ExpQrcFlagsMap('QRCID3') = logical([0 0 0 0 0]');
test(...
ALL_QRCID_CA, NSO_TABLE, ...
[0:4]*1e9, ...
ExpQrcFlagsMap ...
);
end

if ALL_ENABLED
% Epoch does not overlap with any NSOs (though time interval does).
ExpQrcFlagsMap = containers.Map();
ExpQrcFlagsMap('QRCID1') = logical([0 0]');
ExpQrcFlagsMap('QRCID2') = logical([0 0]');
ExpQrcFlagsMap('QRCID3') = logical([0 0]');
test(...
ALL_QRCID_CA, NSO_TABLE, ...
[-1, 4]*1e9, ...
ExpQrcFlagsMap ...
);
end
end



function test_QRC_flag_arrays_to_quality_ZVs(testCase)

function test(nRec, QrcFlagsMap, QrcidSettingsMap, ...
exp_QUALITY_FLAG, exp_L2_QUALITY_BITMASK)
exp_QUALITY_FLAG = uint8( exp_QUALITY_FLAG(:));
exp_L2_QUALITY_BITMASK = uint16(exp_L2_QUALITY_BITMASK(:));

% CALL TESTED FUNCTION
[act_QUALITY_FLAG, act_L2_QUALITY_BITMASK] = ...
bicas.proc.L1L2.qual.QRC_flag_arrays_to_quality_ZVs(...
nRec, QrcFlagsMap, QrcidSettingsMap);

testCase.assertEqual(act_QUALITY_FLAG, exp_QUALITY_FLAG)
testCase.assertEqual(act_L2_QUALITY_BITMASK, exp_L2_QUALITY_BITMASK)
end

% =======================
% Zero QRCIDs are defined
% =======================
QrcidSettingsMap = containers.Map();
QrcFlagsMap = containers.Map();

% Zero records
test(0, QrcFlagsMap, QrcidSettingsMap, ...
[], [] ...
)

% Non-zero records
test(3, QrcFlagsMap, QrcidSettingsMap, ...
3*ones(3,1), zeros(3,1) ...
)

% ==========================
% Several QRCIDs are defined
% ==========================
QrcidSettingsMap = containers.Map();
QrcidSettingsMap('QRCID1') = bicas.proc.L1L2.QrcidSetting(uint8(2), uint16(2));
QrcidSettingsMap('QRCID2') = bicas.proc.L1L2.QrcidSetting(uint8(3), uint16(4));

% Zero records
QrcFlagsMap = containers.Map();
QrcFlagsMap('QRCID1') = false(0, 1);
QrcFlagsMap('QRCID2') = false(0, 1);
test(0, QrcFlagsMap, QrcidSettingsMap, ...
[], [] ...
)

% Non-zero records
QrcFlagsMap = containers.Map();
QrcFlagsMap('QRCID1') = logical([0 0 1 1]');
QrcFlagsMap('QRCID2') = logical([0 1 0 1]');
test(4, QrcFlagsMap, QrcidSettingsMap, ...
[3 3 2 2], [0 4 2 4+2] ...
)
end



function test_set_voltage_current_FV(testCase)

function test(...
Expand Down
Loading

0 comments on commit 7bebf58

Please sign in to comment.