Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion +exploreFNIRS/processMethods.m
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ function processMethods(rawMethodStr,oxyMethodStr)
% oxyMethodStr - Name of the oxy processing method
%
% Example:
% exploreFNIRS.processMethods('x5_TDDR', 'takizawa_easy');
% exploreFNIRS.processMethods('OD_TDDR', 'takizawa_easy');
% exploreFNIRS.processMethods([], 'None'); % oxy-only reprocessing
%
% See also: processFNIRS2, pf2.methods.raw.list, pf2.methods.oxy.list,
Expand Down
2 changes: 1 addition & 1 deletion +pf2/+methods/+raw/describeMethod.m
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
% pf2.methods.raw.describeMethod('x2_lpf_smar');
%
% % Get method details as variables for programmatic use
% [desc, funcs] = pf2.methods.raw.describeMethod('x5_TDDR');
% [desc, funcs] = pf2.methods.raw.describeMethod('OD_TDDR');
% fprintf('Method has %d processing functions\n', length(funcs));
%
% % Describe method by index
Expand Down
2 changes: 1 addition & 1 deletion +pf2/+methods/+raw/setMethod.m
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ function setMethod(raw_method, ctx)
%
% % Typical workflow
% pf2.methods.raw.list(); % View available methods
% pf2.methods.raw.setMethod('x5_TDDR'); % Select TDDR method
% pf2.methods.raw.setMethod('OD_TDDR'); % Select TDDR method
% data = processFNIRS2(rawData); % Process with selected method
%
% See also: pf2.methods.raw.list, pf2.methods.raw.describeMethod,
Expand Down
30 changes: 30 additions & 0 deletions +pf2/+methods/+seeds/+oxy/BPF.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
function p = BPF()
% BPF Factory for the "BPF" oxy method (0.01-0.1 Hz Butterworth band-pass)
%
% Builds the shipped "BPF" oxy (Stage 3) processing method as an OxyPipeline: a
% single Butterworth band-pass filter (0.01-0.1 Hz) applied to hemoglobin
% signals, isolating the typical task-hemodynamic band while removing slow drift
% and high-frequency noise. Used by pf2_initialize and pf2.methods.resetDefaults
% to (re-)seed the default oxy methods. Returns a pipeline object you can save()
% to register or run() directly.
%
% Syntax:
% p = pf2.methods.seeds.oxy.BPF()
%
% Inputs:
% None
%
% Outputs:
% p - pf2_base.OxyPipeline named 'BPF', ready for save() or run()
%
% Example:
% p = pf2.methods.seeds.oxy.BPF();
% p.save();
%
% See also: pf2.methods.seeds.oxy.LPF, pf2.methods.seeds.oxy.HPF,
% pf2.methods.resetDefaults, pf2_base.OxyPipeline

p = pf2_base.OxyPipeline('BPF', ...
'Description', 'Butterworth band-pass filter (0.01-0.1 Hz) on hemoglobin signals');
p = p.add('pf2_bpf_butter', 'lowF', 0.01, 'highF', 0.1);
end
29 changes: 29 additions & 0 deletions +pf2/+methods/+seeds/+oxy/HPF.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
function p = HPF()
% HPF Factory for the "HPF" oxy method (0.01 Hz high-pass filter)
%
% Builds the shipped "HPF" oxy (Stage 3) processing method as an OxyPipeline: a
% single 0.01 Hz high-pass filter applied to hemoglobin signals to remove slow
% drift. Used by pf2_initialize and pf2.methods.resetDefaults to (re-)seed the
% default oxy methods. Returns a pipeline object you can save() to register or
% run() directly.
%
% Syntax:
% p = pf2.methods.seeds.oxy.HPF()
%
% Inputs:
% None
%
% Outputs:
% p - pf2_base.OxyPipeline named 'HPF', ready for save() or run()
%
% Example:
% p = pf2.methods.seeds.oxy.HPF();
% p.save();
%
% See also: pf2.methods.seeds.oxy.LPF, pf2.methods.seeds.oxy.BPF,
% pf2.methods.resetDefaults, pf2_base.OxyPipeline

p = pf2_base.OxyPipeline('HPF', ...
'Description', 'High-pass filter at 0.01 Hz on hemoglobin signals (drift removal)');
p = p.add('pf2_hpf', 'freq_cut', 0.01);
end
44 changes: 44 additions & 0 deletions +pf2/+methods/+seeds/+oxy/takizawa_easy.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
function p = takizawa_easy()
% TAKIZAWA_EASY Factory for the "takizawa_easy" oxy method (lenient rejection)
%
% Builds the shipped "takizawa_easy" oxy (Stage 3) processing method as an
% OxyPipeline: automatic channel rejection using the Takizawa criteria with the
% lenient (non-strict) rule combination. Rejected channels are marked in the
% data's fchMask rather than having their hemoglobin values transformed. Used by
% pf2_initialize and pf2.methods.resetDefaults to (re-)seed the default oxy
% methods. Returns a pipeline object you can save() to register or run()
% directly.
%
% The strict/lenient switch is the pf2_TakizawaRejection strictCriteria flag:
% lenient (strictCriteria = 0) combines the rejection rules with AND, so a
% channel is dropped only when it fails every rule; the strict variant
% (takizawa_hard) uses OR.
%
% Syntax:
% p = pf2.methods.seeds.oxy.takizawa_easy()
%
% Inputs:
% None
%
% Outputs:
% p - pf2_base.OxyPipeline named 'takizawa_easy', ready for save() or run()
%
% Example:
% % Build and register the takizawa_easy oxy method
% p = pf2.methods.seeds.oxy.takizawa_easy();
% p.save();
%
% References:
% Takizawa, R., Kasai, K., Kawakubo, Y., Marumo, K., Kawasaki, S.,
% Yamasue, H., & Fukuda, M. (2008). Reduced frontopolar activation during
% verbal fluency task in schizophrenia: A multi-channel near-infrared
% spectroscopy study. Schizophrenia Research, 99(1-3), 250-262.
% DOI: 10.1016/j.schres.2007.10.025
%
% See also: pf2.methods.seeds.oxy.takizawa_hard, pf2.methods.seeds.oxy.LPF,
% pf2.methods.resetDefaults, pf2_TakizawaRejection, pf2_base.OxyPipeline

p = pf2_base.OxyPipeline('takizawa_easy', ...
'Description', 'Takizawa automatic channel rejection, lenient criteria (Takizawa et al. 2008)');
p = p.add('pf2_TakizawaRejection', 'strictCriteria', 0);
end
44 changes: 44 additions & 0 deletions +pf2/+methods/+seeds/+oxy/takizawa_hard.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
function p = takizawa_hard()
% TAKIZAWA_HARD Factory for the "takizawa_hard" oxy method (strict rejection)
%
% Builds the shipped "takizawa_hard" oxy (Stage 3) processing method as an
% OxyPipeline: automatic channel rejection using the Takizawa criteria with the
% strict rule combination. Rejected channels are marked in the data's fchMask
% rather than having their hemoglobin values transformed. Used by
% pf2_initialize and pf2.methods.resetDefaults to (re-)seed the default oxy
% methods. Returns a pipeline object you can save() to register or run()
% directly.
%
% The strict/lenient switch is the pf2_TakizawaRejection strictCriteria flag:
% strict (strictCriteria = 1) combines the rejection rules with OR, so a channel
% is dropped when it fails any rule; the lenient variant (takizawa_easy) uses
% AND.
%
% Syntax:
% p = pf2.methods.seeds.oxy.takizawa_hard()
%
% Inputs:
% None
%
% Outputs:
% p - pf2_base.OxyPipeline named 'takizawa_hard', ready for save() or run()
%
% Example:
% % Build and register the takizawa_hard oxy method
% p = pf2.methods.seeds.oxy.takizawa_hard();
% p.save();
%
% References:
% Takizawa, R., Kasai, K., Kawakubo, Y., Marumo, K., Kawasaki, S.,
% Yamasue, H., & Fukuda, M. (2008). Reduced frontopolar activation during
% verbal fluency task in schizophrenia: A multi-channel near-infrared
% spectroscopy study. Schizophrenia Research, 99(1-3), 250-262.
% DOI: 10.1016/j.schres.2007.10.025
%
% See also: pf2.methods.seeds.oxy.takizawa_easy, pf2.methods.seeds.oxy.LPF,
% pf2.methods.resetDefaults, pf2_TakizawaRejection, pf2_base.OxyPipeline

p = pf2_base.OxyPipeline('takizawa_hard', ...
'Description', 'Takizawa automatic channel rejection, strict criteria (Takizawa et al. 2008)');
p = p.add('pf2_TakizawaRejection', 'strictCriteria', 1);
end
31 changes: 31 additions & 0 deletions +pf2/+methods/+seeds/+raw/OD_SMAR.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
function p = OD_SMAR()
% OD_SMAR Factory for the "OD_SMAR" raw method (SMAR motion correction)
%
% Builds the shipped "OD_SMAR" raw (Stage 1) processing method as a RawPipeline:
% log transform to optical density, then Sliding-window Motion Artifact
% Rejection (SMAR), which rejects samples whose windowed coefficient of
% variation falls outside acceptable bounds. Used by pf2_initialize and
% pf2.methods.resetDefaults to (re-)seed the default raw methods. Returns a
% pipeline object you can save() to register or run() directly.
%
% Syntax:
% p = pf2.methods.seeds.raw.OD_SMAR()
%
% Inputs:
% None
%
% Outputs:
% p - pf2_base.RawPipeline named 'OD_SMAR', ready for save() or run()
%
% Example:
% p = pf2.methods.seeds.raw.OD_SMAR();
% p.save();
%
% See also: pf2.methods.seeds.raw.OD_TDDR, pf2.methods.resetDefaults,
% pf2_base.RawPipeline, pf2_SMAR

p = pf2_base.RawPipeline('OD_SMAR', ...
'Description', 'Log transform then SMAR (sliding-window motion artifact rejection)');
p = p.add('pf2_Intensity2OD');
p = p.add('pf2_SMAR');
end
2 changes: 1 addition & 1 deletion +pf2/+methods/+seeds/+raw/OD_TDDR.m
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
% p = pf2.methods.seeds.raw.OD_TDDR();
% p.save();
%
% See also: pf2.methods.seeds.raw.OD_TDDR_lpf, pf2.methods.resetDefaults,
% See also: pf2.methods.seeds.raw.OD_SMAR, pf2.methods.resetDefaults,
% pf2_base.RawPipeline, pf2_MotionCorrectTDDR

p = pf2_base.RawPipeline('OD_TDDR', ...
Expand Down
37 changes: 0 additions & 37 deletions +pf2/+methods/+seeds/+raw/OD_TDDR_lpf.m

This file was deleted.

2 changes: 1 addition & 1 deletion +pf2/+methods/Editor.m
Original file line number Diff line number Diff line change
Expand Up @@ -862,7 +862,7 @@ function onSeedDefaults(app)
sel = uiconfirm(app.UIFigure, ...
sprintf(['Install repo seed methods for the %s stage? ' ...
'This will overwrite any existing methods with the ' ...
'same names (OD_TDDR, OD_TDDR_lpf for raw; ' ...
'same names (OD_TDDR, OD_SMAR for raw; ' ...
'LPF, LPF_ROI for oxy). Other user methods are kept.'], ...
app.Stage), ...
'Install seed methods', ...
Expand Down
2 changes: 1 addition & 1 deletion +pf2/+process/processRaw.m
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@
%
% % Compare different raw methods before committing to oxy processing
% result1 = pf2.process.processRaw(data, 'x2_lpf_smar');
% result2 = pf2.process.processRaw(data, 'x5_TDDR');
% result2 = pf2.process.processRaw(data, 'OD_TDDR');
%
% Notes:
% - This function sets 'SkipOxy' to true internally
Expand Down
29 changes: 2 additions & 27 deletions +pf2/ProcessingContext.m
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
% ctx = pf2.ProcessingContext(Name, Value, ...)
%
% Inputs (Name-Value pairs; all optional):
% 'RawMethod' - Name of a raw-stage method (e.g. 'x5_TDDR')
% 'RawMethod' - Name of a raw-stage method (e.g. 'OD_TDDR')
% 'OxyMethod' - Name of an oxy-stage method (e.g. 'takizawa_easy')
% 'DPFmode' - 'None' | 'Fixed' | 'Calc'
% 'FixedDPF' - Fixed DPF value (used when DPFmode is 'Fixed')
Expand All @@ -36,18 +36,12 @@
%
% Examples:
% % Configure once, in one call, without touching globals
% ctx = pf2.ProcessingContext('RawMethod','x5_TDDR', ...
% ctx = pf2.ProcessingContext('RawMethod','OD_TDDR', ...
% 'DPFmode','Calc', 'SubjectAge',25, 'blLength',10);
% out = processFNIRS2(data, 'Context', ctx);
% % ...or let the context be the receiver:
% out = ctx.process(data);
%
% % Save an analysis "recipe" and reload it in a fresh session
% recipe = ctx.toStruct();
% save('study_protocol.mat', '-struct', 'recipe');
% s = load('study_protocol.mat');
% ctx = pf2.ProcessingContext.fromRecipe(s); % fully usable again
%
% % Parallel, one independent context per worker (note copy(), not '='):
% parfor i = 1:numel(allData)
% c = ctx.copy();
Expand Down Expand Up @@ -156,23 +150,4 @@ function applySetting(obj, key, val)
end
end

methods (Static)
function obj = fromRecipe(s)
% FROMRECIPE Rebuild a usable context from a saved settings struct
%
% Delegates deserialization to the inherited (base) fromStruct --
% the single source of truth for which fields round-trip, and which
% also reloads the method libraries -- then returns the settings as
% a public pf2.ProcessingContext.
%
% Syntax:
% ctx = pf2.ProcessingContext.fromRecipe(s)

base = pf2_base.ProcessingContext.fromStruct(s);
obj = pf2.ProcessingContext();
for p = properties(base)'
obj.(p{1}) = base.(p{1});
end
end
end
end
24 changes: 24 additions & 0 deletions +pf2_base/+identity/Contents.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
% PF2_BASE.IDENTITY Internal deterministic semantic-identity primitives.
%
% These functions support the future Recipe/RunSpec executor. They are not a
% user-facing authoring API; public clients should eventually construct typed
% artifacts and let the canonical executor apply identity policy.
%
% Semantic identity:
% canonicalBytes - Canonically encode schema-neutral MATLAB values.
% hashProjection - Hash a canonical value in an explicit artifact domain.
%
% Input identity and fail-closed verification:
% importedContentFingerprint - Hash normalized computation-visible input.
% preflightImport - Verify source/imported identity before Layer-1.
% sha256File - Stream and hash exact file bytes.
% sourceFingerprint - Hash a portable multi-file source manifest.
% verifyExpected - Enforce an expected digest without warning fallback.
%
% Phase-0 proof carrier (not the future human-facing Recipe JSON format):
% decodeJsonTransport - Decode a lossless tagged canonical-value carrier.
% encodeJsonTransport - Encode a lossless tagged canonical-value carrier.
%
% Implementation support:
% normalizeText - Normalize valid text to Unicode NFC and UTF-8.
% sha256Bytes - Compute a lowercase prefixed SHA-256 byte digest.
Loading