From 2428e8004788e36b2c0d9bdd156ee3450e1b967e Mon Sep 17 00:00:00 2001 From: Peter T Date: Wed, 3 Sep 2025 14:58:46 -0400 Subject: [PATCH 1/2] Updates for Octave Updated a few files for them to work in Octave. So far only tested out with the functions associated with "run_megapressproc_auto" and "run_specialproc_auto". --- exampleRunScripts/run_megapressproc_auto.m | 10 ++++- exampleRunScripts/run_megaspecialproc_auto.m | 10 ++++- exampleRunScripts/run_specialproc_auto.m | 10 ++++- inputOutput/mapVBVD/read_twix_hdr.m | 2 +- .../distinguishable_colors.m | 37 +++++++++++++++++-- processingTools/op_alignMPSubspecs.m | 35 +++++++++++++----- processingTools/op_lorentz.m | 5 +++ 7 files changed, 90 insertions(+), 19 deletions(-) diff --git a/exampleRunScripts/run_megapressproc_auto.m b/exampleRunScripts/run_megapressproc_auto.m index d0aec758..8336d63f 100644 --- a/exampleRunScripts/run_megapressproc_auto.m +++ b/exampleRunScripts/run_megapressproc_auto.m @@ -50,8 +50,14 @@ %Ensure that filestring is an absolute path, otherwise you can get yourself %in a tangle later inserting figures at the report stage. -if ~java.io.File(filestring).isAbsolute - filestring = cd(cd(filestring)); +if exist('OCTAVE_VERSION', 'builtin') ~= 0 %Option for Octave (doesn't have java library) - **PT**2025 + if ~is_absolute_filename(filestring) + filestring = canonicalize_file_name(filestring); + end +else + if ~java.io.File(filestring).isAbsolute + filestring = cd(cd(filestring)); + end end %make a new directory for the output report and figures: diff --git a/exampleRunScripts/run_megaspecialproc_auto.m b/exampleRunScripts/run_megaspecialproc_auto.m index 392125c5..484c97c6 100644 --- a/exampleRunScripts/run_megaspecialproc_auto.m +++ b/exampleRunScripts/run_megaspecialproc_auto.m @@ -52,8 +52,14 @@ %Ensure that filestring is an absolute path, otherwise you can get yourself %in a tangle later inserting figures at the report stage. -if ~java.io.File(filestring).isAbsolute - filestring = cd(cd(filestring)); +if exist('OCTAVE_VERSION', 'builtin') ~= 0 %Option for Octave (doesn't have java library) - **PT**2025 + if ~is_absolute_filename(filestring) + filestring = canonicalize_file_name(filestring); + end +else + if ~java.io.File(filestring).isAbsolute + filestring = cd(cd(filestring)); + end end %make a new directory for the output report and figures: diff --git a/exampleRunScripts/run_specialproc_auto.m b/exampleRunScripts/run_specialproc_auto.m index 7eb54cf4..067552a5 100644 --- a/exampleRunScripts/run_specialproc_auto.m +++ b/exampleRunScripts/run_specialproc_auto.m @@ -45,8 +45,14 @@ %Ensure that filestring is an absolute path, otherwise you can get yourself %in a tangle later inserting figures at the report stage. -if ~java.io.File(filestring).isAbsolute - filestring = cd(cd(filestring)); +if exist('OCTAVE_VERSION', 'builtin') ~= 0 %Option for Octave (doesn't have java library) - **PT**2025 + if ~is_absolute_filename(filestring) + filestring = canonicalize_file_name(filestring); + end +else + if ~java.io.File(filestring).isAbsolute + filestring = cd(cd(filestring)); + end end %make a new directory for the output report and figures: diff --git a/inputOutput/mapVBVD/read_twix_hdr.m b/inputOutput/mapVBVD/read_twix_hdr.m index d85ae596..a2524184 100644 --- a/inputOutput/mapVBVD/read_twix_hdr.m +++ b/inputOutput/mapVBVD/read_twix_hdr.m @@ -156,7 +156,7 @@ breaked = false; for k=1:numel(v) if isOctave - vk = v{k}; + vk = v(k); %Originally with {} brackets, but octave doesn't use this. Fixed in official map_VBVD - **PT**2025 if iscell(vk.name) % lazy fix that throws some info away vk.name = vk.name{1}; diff --git a/processingTools/distinguishable_colors/distinguishable_colors.m b/processingTools/distinguishable_colors/distinguishable_colors.m index f9e9e256..a756d48d 100644 --- a/processingTools/distinguishable_colors/distinguishable_colors.m +++ b/processingTools/distinguishable_colors/distinguishable_colors.m @@ -90,9 +90,15 @@ lab = func(rgb); bglab = func(bg); else - C = makecform('srgb2lab'); - lab = applycform(rgb,C); - bglab = applycform(bg,C); + %Octave doesn't has makecform,applycform libraries - **PT**2025 + if exist('OCTAVE_VERSION','builtin')~=0 % Running in Octave + lab = rgb2lab_oct(rgb); + bglab = rgb2lab_oct(bg); + else % Running in MATLAB + C = makecform('srgb2lab'); + lab = applycform(rgb,C); + bglab = applycform(bg,C); + end end % If the user specified multiple background colors, compute distances @@ -150,3 +156,28 @@ end end end + +%Adding in function for Octave, as it doesn't support makecform&applycform - **PT**2025 +function lab = rgb2lab_oct(rgb) + mask = rgb <= 0.04045; + rgb(mask) = rgb(mask)/12.92; + rgb(~mask) = ((rgb(~mask)+0.055)/1.055).^2.4; + rgb = rgb * 100; + + M = [0.4124564 0.3575761 0.1804375; + 0.2126729 0.7151522 0.0721750; + 0.0193339 0.1191920 0.9503041]; + XYZ = rgb * M'; + + refX = 95.047; refY = 100.000; refZ = 108.883; + X = XYZ(:,1)/refX; Y = XYZ(:,2)/refY; Z = XYZ(:,3)/refZ; + + f = @(t) (t > 0.008856) .* (t.^(1/3)) + (t <= 0.008856) .* (7.787.*t + 16/116); + fX = f(X); fY = f(Y); fZ = f(Z); + + L = 116*fY - 16; + a = 500*(fX - fY); + b = 200*(fY - fZ); + + lab = [L a b]; +end \ No newline at end of file diff --git a/processingTools/op_alignMPSubspecs.m b/processingTools/op_alignMPSubspecs.m index 3cb626f5..1e25444a 100644 --- a/processingTools/op_alignMPSubspecs.m +++ b/processingTools/op_alignMPSubspecs.m @@ -92,15 +92,32 @@ %DO FITTING n=1; %disp(['fitting subspec number ' num2str(m) ' and average number ' num2str(n)]); -parsFit=nlinfit(in.fids(:,2),base,@op_freqPhaseShiftComplexNest,parsGuess,... - 'weights', [ppmWeights ppmWeights]'); -A=op_freqPhaseShiftNest(parsFit,in.fids(:,2),phShift); -size(A); -size(fids); -fids(:,1)=in.fids(:,1); -fids(:,2)=A; -fs=parsFit(1); -phs=parsFit(2)+phShift; +if exist('OCTAVE_VERSION', 'builtin') ~= 0 %If using Octave, nlinfit doesn't have 'weights' option - **PT**2025 + % Combine weights for real + imaginary parts + combinedWeights = [ppmWeights ppmWeights]'; % column + + % Scale y and create a model that returns scaled predictions + yWeighted = sqrt(combinedWeights) .* base; + weightedModel = @(pars, input) sqrt(combinedWeights) .* op_freqPhaseShiftComplexNest(pars, input); + + % Fit using Octave's nlinfit + parsFit = nlinfit(in.fids(:,2), yWeighted, weightedModel, parsGuess); + A = op_freqPhaseShiftNest(parsFit, in.fids(:,2), phShift); + fids(:,1) = in.fids(:,1); + fids(:,2) = A; + fs = parsFit(1); + phs = parsFit(2) + phShift; +else + parsFit=nlinfit(in.fids(:,2),base,@op_freqPhaseShiftComplexNest,parsGuess,... + 'weights', [ppmWeights ppmWeights]'); + A=op_freqPhaseShiftNest(parsFit,in.fids(:,2),phShift); + size(A); + size(fids); + fids(:,1)=in.fids(:,1); + fids(:,2)=A; + fs=parsFit(1); + phs=parsFit(2)+phShift; +end %plot(in.ppm,fftshift(ifft(fids(:,1,m))),in.ppm,fftshift(ifft(fids(:,n,m)))); %re-calculate Specs using fft diff --git a/processingTools/op_lorentz.m b/processingTools/op_lorentz.m index 768114e8..e97053a7 100644 --- a/processingTools/op_lorentz.m +++ b/processingTools/op_lorentz.m @@ -26,6 +26,11 @@ function [y]=op_lorentz(pars,ppm) +% For Octave, force pars to be a row vector - **PT**2025 +if exist('OCTAVE_VERSION','builtin')~=0 + pars = pars(:).'; +end + A=pars(:,1); %Amplitude (Use only positive Numbers) w=pars(:,2); %full width at half max ppm0=pars(:,3); %centre frequency of peak From 90150fd8b5123ea2b5a488f05bc1b1e4637a2f6c Mon Sep 17 00:00:00 2001 From: Peter T Date: Mon, 8 Sep 2025 15:22:33 -0400 Subject: [PATCH 2/2] Update distinguishable_colors.m Adding in comments. --- .../distinguishable_colors.m | 51 +++++++++++++++---- 1 file changed, 41 insertions(+), 10 deletions(-) diff --git a/processingTools/distinguishable_colors/distinguishable_colors.m b/processingTools/distinguishable_colors/distinguishable_colors.m index a756d48d..90aa492e 100644 --- a/processingTools/distinguishable_colors/distinguishable_colors.m +++ b/processingTools/distinguishable_colors/distinguishable_colors.m @@ -159,25 +159,56 @@ %Adding in function for Octave, as it doesn't support makecform&applycform - **PT**2025 function lab = rgb2lab_oct(rgb) + % RGB2LAB_OCT: Convert sRGB values in [0,1] to CIELAB (Lab) color space. + % Input: Nx3 matrix of RGB values, range [0,1] + % Output: Nx3 matrix of Lab values [L*, a*, b*] + + % --- Step 1: Linearize sRGB (remove gamma correction) --- + % sRGB is gamma-compressed; we need to convert it to linear light values. + % Reference: IEC 61966-2-1 (sRGB standard) mask = rgb <= 0.04045; - rgb(mask) = rgb(mask)/12.92; - rgb(~mask) = ((rgb(~mask)+0.055)/1.055).^2.4; - rgb = rgb * 100; + rgb(mask) = rgb(mask)/12.92; % linear for dark values + rgb(~mask) = ((rgb(~mask)+0.055)/1.055).^2.4; % power law for bright values + rgb = rgb * 100; % scale to [0,100] (matches XYZ reference scale) - M = [0.4124564 0.3575761 0.1804375; - 0.2126729 0.7151522 0.0721750; - 0.0193339 0.1191920 0.9503041]; + % --- Step 2: sRGB → CIE XYZ --- + % This is a linear transformation using the sRGB-to-XYZ matrix + % under D65 illuminant (standard daylight white point). + % Numbers come from the official sRGB specification. + M = [0.4124564 0.3575761 0.1804375; % X coefficients + 0.2126729 0.7151522 0.0721750; % Y coefficients + 0.0193339 0.1191920 0.9503041]; % Z coefficients XYZ = rgb * M'; - refX = 95.047; refY = 100.000; refZ = 108.883; - X = XYZ(:,1)/refX; Y = XYZ(:,2)/refY; Z = XYZ(:,3)/refZ; + % --- Step 3: Normalize by reference white (D65) --- + % CIELAB requires normalization relative to a "reference white". + % D65 white point in CIE XYZ is: + refX = 95.047; + refY = 100.000; + refZ = 108.883; + X = XYZ(:,1)/refX; + Y = XYZ(:,2)/refY; + Z = XYZ(:,3)/refZ; + + % --- Step 4: XYZ → Lab nonlinear transform --- + % CIELAB uses a cube root transform, but with a linear fallback for very + % small values to avoid instability. Threshold = 0.008856. + f = @(t) (t > 0.008856) .* (t.^(1/3)) + ... + (t <= 0.008856) .* (7.787.*t + 16/116); - f = @(t) (t > 0.008856) .* (t.^(1/3)) + (t <= 0.008856) .* (7.787.*t + 16/116); - fX = f(X); fY = f(Y); fZ = f(Z); + fX = f(X); + fY = f(Y); + fZ = f(Z); + % --- Step 5: Compute L*, a*, b* --- + % Standard CIELAB equations: + % L* = 116*f(Y) - 16 (0 = black, 100 = white) + % a* = 500*(f(X) - f(Y)) (green ↔ red axis) + % b* = 200*(f(Y) - f(Z)) (blue ↔ yellow axis) L = 116*fY - 16; a = 500*(fX - fY); b = 200*(fY - fZ); + % --- Output --- lab = [L a b]; end \ No newline at end of file