Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

KomaMRIFiles: Include .seq produced by pypulseq or pulseq #318

Open
1 of 2 tasks
beorostica opened this issue Mar 7, 2024 · 2 comments · Fixed by #321
Open
1 of 2 tasks

KomaMRIFiles: Include .seq produced by pypulseq or pulseq #318

beorostica opened this issue Mar 7, 2024 · 2 comments · Fixed by #321

Comments

@beorostica
Copy link
Contributor

beorostica commented Mar 7, 2024

It is a good idea to go deeper in the creation of code tests. This really will help to accept the contribution of other guys.
For instance, tests for KomaMRIFiles for pulseq files .seq.

@curtcorum
Copy link
Contributor

It could possibly be good to leverage the tests for related KomaMRI or julia functions (read or generate seq or other files) from pulseq or pypulseq directly by sending KomaMRI input or output visa versa to those tests.

@cncastillo
Copy link
Member

This was done in https://github.com/JuliaHealth/KomaMRI.jl/blob/master/KomaMRIFiles/test/runtests.jl#L53-L82

To include more tests, we just need to include Pulseq files in KomaMRIFiles/test/test_files/pulseq_read_comparison. We still need to add some examples for files generated with PyPulseq (#367).

To generate the corresponding .mat I used this script:

%% Just read a .seq and write the .mat
clc
cd('/home/ccp/Documents/KomaMRI.jl/KomaMRIFiles/test/test_files/pulseq_read_comparison/')
sys = mr.opts();            % Default system
seq = mr.Sequence(sys);     % Default sequence

files = dir('*.seq');
for i = 1:length(files)
    seq.read(files(i).name); 
    seq_name = split(files(i).name, '.');
    seq.setDefinition('FileName', seq_name{1});
    seq.plot() %<---- Modified version that saves the generated samples
end

and the modified seq.plot function

diff --git a/matlab/+mr/@Sequence/Sequence.m b/matlab/+mr/@Sequence/Sequence.m
index acf3d18..e7b45b4 100644
--- a/matlab/+mr/@Sequence/Sequence.m
+++ b/matlab/+mr/@Sequence/Sequence.m
@@ -1255,6 +1255,17 @@ classdef Sequence < handle
                 end
             end            
             %for iB=1:size(obj.blockEvents,1)
+            % Generating struct to save event samples to then compare them with Koma
+            koma_gamma = 42577468.8;
+            sequence = cell(1, length(obj.blockEvents));
+            for i = 1:length(obj.blockEvents)
+                sequence{i} = struct('rf', struct('t', [], 'A', []),... 
+                                     'df', struct('t', [], 'A', []),...
+                                     'gx', struct('t', [], 'A', []),... 
+                                     'gy', struct('t', [], 'A', []),... 
+                                     'gz', struct('t', [], 'A', []),... 
+                                     'adc',struct('t', [], 'A', []));
+            end
             for iB=1:length(obj.blockEvents)
                 block = obj.getBlock(iB);
                 isValid = t0+obj.blockDurations(iB)>timeRange(1) && t0<=timeRange(2);
@@ -1286,22 +1297,28 @@ classdef Sequence < handle
                                 label_legend_2plot=[];
                             end
                         end
+                        % Saving the ADC points to compare with Koma
+                        sequence{iB}.adc.t = tFactor * (t0 + t);
+                        sequence{iB}.adc.A = ones(size(t));
                     end
                     if ~isempty(block.rf)
                         rf=block.rf;
                         [tc,ic]=mr.calcRfCenter(rf);
                         sc=rf.signal(ic);
-                        if max(abs(diff(rf.t)-rf.t(2)+rf.t(1)))<1e-9 && length(rf.t)>100
-                            % homogeneous sampling and long pulses -- use lower time resolution for better display and performance
-                            dt=rf.t(2)-rf.t(1);
-                            st=round(obj.sys.gradRasterTime/dt);
-                            t=rf.t(1:st:end);
-                            s=rf.signal(1:st:end);
-                        else
+                        %if max(abs(diff(rf.t)-rf.t(2)+rf.t(1)))<1e-9 && length(rf.t)>100
+                        %    % homogeneous sampling and long pulses -- use lower time resolution for better display and performance
+                        %    dt=rf.t(2)-rf.t(1);
+                        %    st=round(obj.sys.gradRasterTime/dt);
+                        %    t=rf.t(1:st:end);
+                        %    s=rf.signal(1:st:end);
+                        %else
                             t=rf.t;
                             s=rf.signal;
-                        end
+                        %end
                         sreal=max(abs(imag(s)))/max(abs(real(s)))<1e-6; %all(isreal(s));
+                        % Saving raw waveform to compare with Koma
+                        s_saved = [0; s; 0];
+                        t_saved = [t(1); t; t(end)];
                         if abs(s(1))~=0 % fix strangely looking phase / amplitude in the beginning
                             s=[0; s];
                             t=[t(1); t];
@@ -1318,6 +1335,12 @@ classdef Sequence < handle
                             plot(tFactor*(t0+t+rf.delay),  abs(s),'Parent',ax(2));
                             plot(tFactor*(t0+t+rf.delay),  angle(s*exp(1i*rf.phaseOffset).*exp(1i*2*pi*t    *rf.freqOffset)), tFactor*(t0+tc+rf.delay), angle(sc*exp(1i*rf.phaseOffset).*exp(1i*2*pi*tc*rf.freqOffset)),'xb', 'Parent',ax(3));
                         end                        
+                        % Saving the RF points to compare with Koma
+                        sequence{iB}.rf.t = tFactor * (t0 + t_saved + rf.delay);
+                        sequence{iB}.rf.A = s_saved * exp(1i*rf.phaseOffset) / koma_gamma;
+                        t_saved = [t(1); t(1); t(end); t(end)];
+                        sequence{iB}.df.t = tFactor * (t0 + t_saved + rf.delay);
+                        sequence{iB}.df.A = [0; rf.freqOffset; rf.freqOffset; 0];
                         %plot(tFactor*(t0+t+rf.delay),  angle(  exp(1i*rf.phaseOffset).*exp(1i*2*pi*t    *rf.freqOffset)), tFactor*(t0+tc+rf.delay), angle(      exp(1i*rf.phaseOffset).*exp(1i*2*pi*t(ic)*rf.freqOffset)),'xb', 'Parent',ax(3));
                     end
                     gradChannels={'gx','gy','gz'};
@@ -1331,9 +1354,29 @@ classdef Sequence < handle
                                 %t=grad.delay + [0; grad.t + (grad.t(2)-grad.t(1))/2; grad.t(end) + grad.t(2)-grad.t(1)];
                                 t= grad.delay+[0; grad.tt; grad.shape_dur];
                                 waveform=1e-3* [grad.first; grad.waveform; grad.last];
+                                % Saving waveform to compare with Koma
+                                t_saved = t;
+                                wave_saved = [grad.first; grad.waveform; grad.last];
                             else
                                 t=cumsum([0 grad.delay grad.riseTime grad.flatTime grad.fallTime]);
                                 waveform=1e-3*grad.amplitude*[0 0 1 1 0];
+                                % Saving waveform to compare with Koma
+                                t_saved = t(2:end);
+                                wave_saved = grad.amplitude*[0 1 1 0];
+                            end
+                            if sum(abs(waveform)) ~= 0
+                                gi_t = tFactor * (t0 + t_saved);
+                                gi_A = wave_saved / koma_gamma;
+                                if j == 1
+                                    sequence{iB}.gx.t = gi_t;
+                                    sequence{iB}.gx.A = gi_A;
+                                elseif j == 2
+                                    sequence{iB}.gy.t = gi_t;
+                                    sequence{iB}.gy.A = gi_A;
+                                elseif j == 3
+                                    sequence{iB}.gz.t = gi_t;
+                                    sequence{iB}.gz.A = gi_A;
+                                end
                             end
                             plot(tFactor*(t0+t),waveform,'Parent',ax(3+j));
                         end
@@ -1342,6 +1385,9 @@ classdef Sequence < handle
                 t0=t0+obj.blockDurations(iB);%mr.calcDuration(block);
             end
             
+            filename = strcat('/home/ccp/Documents/KomaMRI.jl/KomaMRIFiles/test/test_files/pulseq_read_comparison/', obj.definitions('FileName'), '.mat');
+            display(filename)
+            save(filename, 'sequence')
             % Set axis limits and zoom properties
             dispRange = tFactor*[timeRange(1) min(timeRange(2),t0)];
             arrayfun(@(x)xlim(x,dispRange),ax);

Modified_plot_seq_Pulseq.zip

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants