From e74ecb40d4b07603e355a27a4ea920b063abdf23 Mon Sep 17 00:00:00 2001 From: Thomas Hiller Date: Sat, 16 May 2020 23:00:03 +0200 Subject: [PATCH] 1. bug fix: in `onPushRun.m` the adiabatic quality p was incorrectly calculated when the total simulation time exceeded the actual switch-off ramp time 2. bug fix: both axes for the pulse frequency and current modulation are now show correctly when exporting the *Current View* figure from the menu 3. new feature: an animation of the latest result can be played for all parameter combinations (e.g. *Pulse + Relaxation* or *Pre-polarization switch-off + Pulse + Relaxation*, etc.) 4. typo fixing within comments and `README.md` --- BLOCHUS/BLOCHUS.m | 4 +- BLOCHUS/BLOCHUS_createPanelBasic.m | 2 +- BLOCHUS/BLOCHUS_createPanelControl.m | 2 +- CHANGELOG.md | 13 + README.md | 4 +- callbacks/checkbox/onCheckPrePolPulse.m | 2 + callbacks/checkbox/onCheckPulseQ.m | 2 +- callbacks/edits/onEditValue.m | 82 +- callbacks/menus/onMenuViewFigure.m | 92 +- callbacks/popup/onPopupPulseAxis.m | 4 +- callbacks/popup/onPopupPulseDFmode.m | 2 +- callbacks/popup/onPopupPulseImode.m | 2 +- callbacks/popup/onPopupPulsePolarization.m | 2 +- callbacks/popup/onPopupPulseType.m | 2 +- callbacks/push/onPushAnimate.m | 1051 +++++++++++---- callbacks/push/onPushRun.m | 38 +- doc/blochus/BLOCHUS/BLOCHUS.html | 4 +- .../BLOCHUS/BLOCHUS_createPanelBasic.html | 2 +- .../BLOCHUS/BLOCHUS_createPanelControl.html | 4 +- .../checkbox/onCheckPrePolPulse.html | 58 +- .../callbacks/checkbox/onCheckPulseQ.html | 4 +- doc/blochus/callbacks/edits/onEditValue.html | 726 ++++++----- .../callbacks/menus/onMenuViewFigure.html | 358 +++--- .../callbacks/popup/onPopupPulseAxis.html | 8 +- .../callbacks/popup/onPopupPulseDFmode.html | 4 +- .../callbacks/popup/onPopupPulseImode.html | 4 +- .../popup/onPopupPulsePolarization.html | 4 +- .../callbacks/popup/onPopupPulseType.html | 4 +- doc/blochus/callbacks/push/menu.html | 2 +- doc/blochus/callbacks/push/onPushAnimate.html | 1129 ++++++++++++---- doc/blochus/callbacks/push/onPushRun.html | 1138 +++++++++-------- doc/blochus/functions/blochsim/getFFT.html | 2 +- doc/blochus/functions/blochsim/getOmega0.html | 2 +- .../functions/interface/clearSingleAxis.html | 2 +- .../interface/getPulseParameters.html | 70 +- .../interface/getRampParameters.html | 50 +- doc/blochus/functions/interface/menu.html | 2 +- .../functions/interface/plotBSphere.html | 2 +- .../{plotBpulse.html => plotPulse.html} | 93 +- doc/blochus/functions/interface/plotRamp.html | 2 +- .../functions/interface/plotResults.html | 461 +++---- functions/interface/getPulseParameters.m | 8 + functions/interface/getRampParameters.m | 2 + .../interface/{plotBpulse.m => plotPulse.m} | 33 +- functions/interface/plotResults.m | 41 +- 45 files changed, 3462 insertions(+), 2061 deletions(-) create mode 100644 CHANGELOG.md rename doc/blochus/functions/interface/{plotBpulse.html => plotPulse.html} (69%) rename functions/interface/{plotBpulse.m => plotPulse.m} (78%) diff --git a/BLOCHUS/BLOCHUS.m b/BLOCHUS/BLOCHUS.m index 8dac6e1..4aee16d 100644 --- a/BLOCHUS/BLOCHUS.m +++ b/BLOCHUS/BLOCHUS.m @@ -33,8 +33,8 @@ %------------- BEGIN CODE -------------- %% GUI 'header' info and default GUI settings -myui.version = '0.1.0'; -myui.date = '15.05.2020'; +myui.version = '0.1.1'; +myui.date = '16.05.2020'; myui.author = 'Thomas Hiller'; myui.email = 'thomas.hiller[at]leibniz-liag.de'; diff --git a/BLOCHUS/BLOCHUS_createPanelBasic.m b/BLOCHUS/BLOCHUS_createPanelBasic.m index 08994be..778e17b 100644 --- a/BLOCHUS/BLOCHUS_createPanelBasic.m +++ b/BLOCHUS/BLOCHUS_createPanelBasic.m @@ -83,7 +83,7 @@ 'FontSize',myui.fontsize,... 'UserData',struct('Tooltipstr',tstr,'defaults',data.init.B0),... 'Callback',@onEditValue); -tstr = 'Omega0 frequency in [Hz].
'; +tstr = ['Larmor frequency ',char(hex2dec('3C9')),'0 in [Hz].
']; gui.edit_handles.Omega0 = uicontrol('Style','Edit',... 'Parent',setB0,... 'String',sprintf('%7.2f',data.init.Omega0(1)),... diff --git a/BLOCHUS/BLOCHUS_createPanelControl.m b/BLOCHUS/BLOCHUS_createPanelControl.m index 746b224..48fbca3 100644 --- a/BLOCHUS/BLOCHUS_createPanelControl.m +++ b/BLOCHUS/BLOCHUS_createPanelControl.m @@ -45,7 +45,7 @@ 'UserData',struct('Tooltipstr',tstr),... 'Callback',@onPushRun); -tstr = 'Show animation of the last result.'; +tstr = 'Show animation of the latest result.'; gui.push_handles.Animate = uicontrol('Style','pushbutton',... 'Parent',gui.panels.Control.HBox,... 'String','ANIMATE',... diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..f930f9b --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,13 @@ +#### Changelog + +##### Version v.0.1.1 + +1. bug fix: in `onPushRun.m` the adiabatic quality p was incorrectly calculated when the total simulation time exceeded the actual switch-off ramp time +2. bug fix: both axes for the pulse frequency and current modulation are now show correctly when exporting the *Current View* figure from the menu +3. new feature: an animation of the latest result can be played for all parameter combinations (e.g. *Pulse + Relaxation* or *Pre-polarization switch-off + Pulse + Relaxation*, etc.) +4. typo fixing within comments and `README.md` + + +##### Version v.0.1.0 + +Initial Version diff --git a/README.md b/README.md index cbdf39f..8e3a367 100644 --- a/README.md +++ b/README.md @@ -11,9 +11,9 @@ **BLOCHUS** is a set of MATLABTM tools, that allow some basic simulations of (S)NMR spin dynamics based on the Bloch equations. The Bloch equations are solved in the laboratory frame of reference with MATLABs built-in `ode45` solver. Because it was developed within the scope of a near surface SNMR project, its main features are the simulation of (1) pre-polarization switch-off ramps and (2) excitation pulses. The main front-end to the underlying simulation tools is a graphical user interface (GUI) that allows playing around with the different features and helps to understand the basic concepts of (S)NMR spin dynamics. #### Basic features: -1. Choose between different protons (e.g. *Hydrogen*, *Helium*, *Flourine*, etc.) +1. Choose between different protons (e.g. *Hydrogen*, *Helium*, *Fluorine*, etc.) 2. Choose between different pre-polarization switch-off ramp shapes (e.g. *exponential*, *linear*, *half cosine*, etc.) with arbitrary ramp time -3. Choose between different excitation pulses (*pi/2*, *pi*, *adiabatic half passage*, etc.) with arbitrary off-resonant frequency, or in case of the adiabatic pulses, arbitrary frequency and current modulation. +3. Choose between different excitation pulses (*pi/2*, *pi*, *adiabatic half passage*, etc.) with arbitrary off-resonance frequency, or in case of the adiabatic pulses, arbitrary frequency and current modulation. - - - diff --git a/callbacks/checkbox/onCheckPrePolPulse.m b/callbacks/checkbox/onCheckPrePolPulse.m index 0463f2d..bee76f5 100644 --- a/callbacks/checkbox/onCheckPrePolPulse.m +++ b/callbacks/checkbox/onCheckPrePolPulse.m @@ -262,6 +262,8 @@ function onCheckPrePolPulse(src,~) data = getappdata(fig,'data'); end + % because the settings changed, deactivate the "Animate" button + set(gui.push_handles.Animate,'Enable','off'); % update all data inside the GUI setappdata(fig,'data',data); % update status bar diff --git a/callbacks/checkbox/onCheckPulseQ.m b/callbacks/checkbox/onCheckPulseQ.m index 9840913..0590785 100644 --- a/callbacks/checkbox/onCheckPulseQ.m +++ b/callbacks/checkbox/onCheckPulseQ.m @@ -53,7 +53,7 @@ function onCheckPulseQ(src,~) % get GUI data data = getappdata(fig,'data'); % plot pulse - plotBpulse(gui.figh); + plotPulse(gui.figh); else warndlg({'onCheckPulseQ:','There is no figure with the BLOCHUS Tag open.'},... diff --git a/callbacks/edits/onEditValue.m b/callbacks/edits/onEditValue.m index 73b2b25..35d06ef 100644 --- a/callbacks/edits/onEditValue.m +++ b/callbacks/edits/onEditValue.m @@ -19,7 +19,7 @@ function onEditValue(src,~) % getOmega0 % getPulseParameters % getRampParameters -% plotBpulse +% plotPulse % plotRamp % % Subfunctions: @@ -50,37 +50,20 @@ function onEditValue(src,~) % get the user data of the field ud = get(src,'UserData'); - if isstruct(ud) % for new fields - % get the default values [default min max] - defaults = ud.defaults; - - % check if the value is numeric - % if not reset to defaults stored in user data - if isnan(val) - set(src,'String',num2str(defaults(1))); - val = str2double(get(src,'String')); - end - % check if the value is out of bounds - % if yes reset to default - if val < defaults(2) || val > defaults(3) - set(src,'String',num2str(defaults(1))); - val = str2double(get(src,'String')); %#ok<*NASGU> - end - - else % old style (Needs to be removed after the refactoring) - % check if the value is numeric - % if not reset to defaults stored in user data - if isnan(val) - set(src,'String',num2str(ud(3))); - val = str2double(get(src,'String')); - end - % check if the value is out of bounds - % if yes reset to default - if val < ud(1) || val > ud(2) - set(src,'String',num2str(ud(3))); - val = str2double(get(src,'String')); %#ok<*NASGU> - end - disp(['there is still an old style edit field:',tag]) + % get the default values [default min max] + defaults = ud.defaults; + + % check if the value is numeric + % if not reset to defaults stored in user data + if isnan(val) + set(src,'String',num2str(defaults(1))); + val = str2double(get(src,'String')); + end + % check if the value is out of bounds + % if yes reset to default + if val < defaults(2) || val > defaults(3) + set(src,'String',num2str(defaults(1))); + val = str2double(get(src,'String')); %#ok<*NASGU> end % get the data field to update from the field tag @@ -175,6 +158,7 @@ function onEditValue(src,~) % ------------------------------------------------------------- % --- PRE-POLARIZATION ---------------------------------------- % ------------------------------------------------------------- + case {'prepol_Factor','prepol_SwitchFactor'} % check if the ramp type is "melton1995", if yes update the % switch-off time to maintain the same switch-off rate @@ -231,6 +215,7 @@ function onEditValue(src,~) % ------------------------------------------------------------- % --- PULSE --------------------------------------------------- % ------------------------------------------------------------- + case 'pulse_B1Factor' % if the pulse amplitude changes some settings have to be % adjusted, depending on the chosen pulse type @@ -239,10 +224,12 @@ function onEditValue(src,~) switch data.pulse.Type case 'pi_half' % in case of "pi_half" the pulse length gets updated - data.pulse.Ttau = abs(1e3*(pi/2/(data.basic.gamma*data.basic.B0*data.pulse.B1Factor))); + data.pulse.Ttau = abs(1e3*(pi/2/(data.basic.gamma*... + data.basic.B0*data.pulse.B1Factor))); case 'pi' % in case of "pi" the pulse length gets updated - data.pulse.Ttau = abs(1e3*(pi/(data.basic.gamma*data.basic.B0*data.pulse.B1Factor))); + data.pulse.Ttau = abs(1e3*(pi/(data.basic.gamma*... + data.basic.B0*data.pulse.B1Factor))); end set(gui.edit_handles.PulseTtau,'String',num2str(data.pulse.Ttau)); % in case of pure "Pulse" update the total simulation time @@ -257,13 +244,13 @@ function onEditValue(src,~) % update pulse settings getPulseParameters(fig); data = getappdata(fig,'data'); - plotBpulse(fig); + plotPulse(fig); otherwise % update pulse settings getPulseParameters(fig); data = getappdata(fig,'data'); - plotBpulse(fig); + plotPulse(fig); end case 'pulse_Ttau' @@ -274,10 +261,12 @@ function onEditValue(src,~) switch data.pulse.Type case 'pi_half' % in case of "pi_half" the pulse amplitude gets updated - data.pulse.B1Factor = abs(1e3*(pi/2/(data.basic.gamma*data.basic.B0*data.pulse.Ttau))); + data.pulse.B1Factor = abs(1e3*(pi/2/(data.basic.gamma*... + data.basic.B0*data.pulse.Ttau))); case 'pi' % in case of "pi" the pulse amplitude gets updated - data.pulse.B1Factor = abs(1e3*(pi/(data.basic.gamma*data.basic.B0*data.pulse.Ttau))); + data.pulse.B1Factor = abs(1e3*(pi/(data.basic.gamma*... + data.basic.B0*data.pulse.Ttau))); end set(gui.edit_handles.PulseB1Factor,'String',num2str(data.pulse.B1Factor)); % in case of pure "Pulse" update the total simulation time @@ -292,7 +281,7 @@ function onEditValue(src,~) % update pulse settings getPulseParameters(fig); data = getappdata(fig,'data'); - plotBpulse(fig); + plotPulse(fig); case 'MIDI_OR' % in case of "MIDI_OR" the PulseTtau-field holds the @@ -301,7 +290,8 @@ function onEditValue(src,~) % update pulse length data.pulse.Ttau = abs(data.pulse.MIDINP/data.basic.Omega0)*1e3; % update pulse amplitude to pi/2 value - data.pulse.B1Factor = abs(1e3*(pi/2/(data.basic.gamma*data.basic.B0*data.pulse.Ttau))); + data.pulse.B1Factor = abs(1e3*(pi/2/(data.basic.gamma*... + data.basic.B0*data.pulse.Ttau))); set(gui.edit_handles.PulseB1Factor,'String',num2str(data.pulse.B1Factor)); % in case of pure "Pulse" update the total simulation time switch data.basic.type @@ -315,7 +305,7 @@ function onEditValue(src,~) % update pulse settings getPulseParameters(fig); data = getappdata(fig,'data'); - plotBpulse(fig); + plotPulse(fig); case 'MIDI_AP' % in case of "MIDI_AP" the PulseTtau-field holds the @@ -339,7 +329,7 @@ function onEditValue(src,~) end setappdata(fig,'data',data); % update pulse plot - plotBpulse(fig); + plotPulse(fig); otherwise % for all other pulse types ("free" & "AHP") @@ -356,7 +346,7 @@ function onEditValue(src,~) % update pulse settings getPulseParameters(fig); data = getappdata(fig,'data'); - plotBpulse(fig); + plotPulse(fig); end otherwise @@ -366,10 +356,12 @@ function onEditValue(src,~) setappdata(fig,'data',data); getPulseParameters(fig); data = getappdata(fig,'data'); - plotBpulse(fig); + plotPulse(fig); otherwise - % nothing to do for all other fields e.g. T1, T2, Tsim + % because the pulse data changed, deactivate the + % "Animate" button + set(gui.push_handles.Animate,'Enable','off'); end end diff --git a/callbacks/menus/onMenuViewFigure.m b/callbacks/menus/onMenuViewFigure.m index 2635c61..0d7fab3 100644 --- a/callbacks/menus/onMenuViewFigure.m +++ b/callbacks/menus/onMenuViewFigure.m @@ -42,14 +42,54 @@ function onMenuViewFigure(src,~) % opening the export figure expfig = figure; - % create the axes layout on the export figure + % due to the two axes on the pulse modulation panel, we need to know + % before creating the new figure if this panel is active + isdual = false; + if get(gui.panels.Plot.Pulse,'Selection') == 1 + isdual = true; + end + + % create the axes layout on the export figure and get the axes + % positions switch get(src,'Label') - case {'Current View','Magnetization','Switch-off Ramp'} + case 'Current View' + % we copy all visible axes in a 2x2 grid + ax1 = subplot(2,2,1,'Parent',expfig); + ax2 = subplot(2,2,2,'Parent',expfig); + ax3 = subplot(2,2,3,'Parent',expfig); + pos1 = get(ax1,'Position'); + pos2 = get(ax2,'Position'); + pos3 = get(ax3,'Position'); + delete(ax1); + delete(ax2); + delete(ax3); + if isdual + ax4a = subplot(2,4,7,'Parent',expfig); + ax4b = subplot(2,4,8,'Parent',expfig); + pos4a = get(ax4a,'Position'); + pos4b = get(ax4b,'Position'); + delete(ax4a); + delete(ax4b); + else + ax4 = subplot(2,2,4,'Parent',expfig); + pos4 = get(ax4,'Position'); + delete(ax4); + end + + case {'Magnetization','Switch-off Ramp'} % we copy all visible axes in a 2x2 grid ax1 = subplot(2,2,1,'Parent',expfig); ax2 = subplot(2,2,2,'Parent',expfig); ax3 = subplot(2,2,3,'Parent',expfig); ax4 = subplot(2,2,4,'Parent',expfig); + pos1 = get(ax1,'Position'); + pos2 = get(ax2,'Position'); + pos3 = get(ax3,'Position'); + pos4 = get(ax4,'Position'); + delete(ax1); + delete(ax2); + delete(ax3); + delete(ax4); case 'Pulse' % we copy pulse parameter in a 3x2 grid @@ -57,14 +97,15 @@ function onMenuViewFigure(src,~) ax2 = subplot(3,2,2,'Parent',expfig); ax3 = subplot(3,2,[3 4],'Parent',expfig); ax4 = subplot(3,2,[5 6],'Parent',expfig); + pos1 = get(ax1,'Position'); + pos2 = get(ax2,'Position'); + pos3 = get(ax3,'Position'); + pos4 = get(ax4,'Position'); + delete(ax1); + delete(ax2); + delete(ax3); + delete(ax4); end - % get the default positions - pos1 = get(ax1,'Position'); - pos2 = get(ax2,'Position'); - pos3 = get(ax3,'Position'); - pos4 = get(ax4,'Position'); - % delete axes - delete(ax1);delete(ax2);delete(ax3);delete(ax4); % copy the GUI axes to the export figure switch get(src,'Label') @@ -99,7 +140,8 @@ function onMenuViewFigure(src,~) end switch pul case 1 - ax4 = copyobj(gui.axes_handles.PulseSetupF,expfig); + ax4a = copyobj(gui.axes_handles.PulseSetupF,expfig); + ax4b = copyobj(gui.axes_handles.PulseSetupI,expfig); case 2 ax4 = copyobj(gui.axes_handles.PulseB,expfig); case 3 @@ -132,11 +174,26 @@ function onMenuViewFigure(src,~) set(expfig,'Name','BLOCHUS: Pulse'); end + % adjust the axes positions - set(ax1,'Position',pos1); - set(ax2,'Position',pos2); - set(ax3,'Position',pos3); - set(ax4,'Position',pos4); + switch get(src,'Label') + case 'Current View' + set(ax1,'Position',pos1); + set(ax2,'Position',pos2); + set(ax3,'Position',pos3); + if isdual + set(ax4a,'Position',pos4a); + set(ax4b,'Position',pos4b); + else + set(ax4,'Position',pos4); + end + + otherwise + set(ax1,'Position',pos1); + set(ax2,'Position',pos2); + set(ax3,'Position',pos3); + set(ax4,'Position',pos4); + end % adjust the position of the export figure set(expfig,'Position',[posf(1)+300 posf(2) (posf(3)-300)*0.8 posf(4)*0.8]); @@ -146,7 +203,12 @@ function onMenuViewFigure(src,~) case 'Current View' lgh1 = legend(ax1,'show'); lgh3 = legend(ax3,'show'); - lgh4 = legend(ax4,'show'); + if isdual + lgh4a = legend(ax4a,'show'); + lgh4b = legend(ax4b,'show'); + else + lgh4 = legend(ax4,'show'); + end case 'Magnetization' lgh1 = legend(ax1,'show'); diff --git a/callbacks/popup/onPopupPulseAxis.m b/callbacks/popup/onPopupPulseAxis.m index 2dfaed7..e8ec384 100644 --- a/callbacks/popup/onPopupPulseAxis.m +++ b/callbacks/popup/onPopupPulseAxis.m @@ -15,7 +15,7 @@ function onPopupPulseAxis(src,~) % % Other m-files required: % getPulseParameters -% plotBpulse +% plotPulse % % Subfunctions: % none @@ -60,7 +60,7 @@ function onPopupPulseAxis(src,~) % get GUI data data = getappdata(fig,'data'); % plot pulse - plotBpulse(gui.figh); + plotPulse(gui.figh); else warndlg({'onPopupPulseAxis:','There is no figure with the BLOCHUS Tag open.'},... diff --git a/callbacks/popup/onPopupPulseDFmode.m b/callbacks/popup/onPopupPulseDFmode.m index 556e929..14d1ef1 100644 --- a/callbacks/popup/onPopupPulseDFmode.m +++ b/callbacks/popup/onPopupPulseDFmode.m @@ -83,7 +83,7 @@ function onPopupPulseDFmode(src,~) % update GUI data setappdata(fig,'data',data); % plot pulse - plotBpulse(gui.figh); + plotPulse(gui.figh); else warndlg({'onPopupPulseDFmode:','There is no figure with the BLOCHUS Tag open.'},... diff --git a/callbacks/popup/onPopupPulseImode.m b/callbacks/popup/onPopupPulseImode.m index a44732d..5806b9c 100644 --- a/callbacks/popup/onPopupPulseImode.m +++ b/callbacks/popup/onPopupPulseImode.m @@ -85,7 +85,7 @@ function onPopupPulseImode(src,~) % update GUI data setappdata(fig,'data',data); % plot pulse - plotBpulse(gui.figh); + plotPulse(gui.figh); else warndlg({'onPopupPulseDFmode:','There is no figure with the BLOCHUS Tag open.'},... diff --git a/callbacks/popup/onPopupPulsePolarization.m b/callbacks/popup/onPopupPulsePolarization.m index d531903..2b8ec8d 100644 --- a/callbacks/popup/onPopupPulsePolarization.m +++ b/callbacks/popup/onPopupPulsePolarization.m @@ -58,7 +58,7 @@ function onPopupPulsePolarization(src,~) % update GUI data setappdata(fig,'data',data); % plot pulse - plotBpulse(gui.figh); + plotPulse(gui.figh); else warndlg({'onPopupPulsePolarization:','There is no figure with the BLOCHUS Tag open.'},... diff --git a/callbacks/popup/onPopupPulseType.m b/callbacks/popup/onPopupPulseType.m index a73468d..7b26288 100644 --- a/callbacks/popup/onPopupPulseType.m +++ b/callbacks/popup/onPopupPulseType.m @@ -226,7 +226,7 @@ function onPopupPulseType(src,~) % update GUI data setappdata(fig,'data',data); % plot pulse - plotBpulse(fig); + plotPulse(fig); % update status bar updateStatusInformation(fig); else diff --git a/callbacks/push/onPushAnimate.m b/callbacks/push/onPushAnimate.m index 80bf0d4..271eaf5 100644 --- a/callbacks/push/onPushAnimate.m +++ b/callbacks/push/onPushAnimate.m @@ -1,264 +1,829 @@ function onPushAnimate(src,~) -fig = findobj('Tag','BLOCHUS'); -gui = getappdata(fig,'gui'); -data = getappdata(fig,'data'); +%onPushAnimate animates the results of the latest simulation +% +% Syntax: +% onPushAnimate(src) +% +% Inputs: +% src - handle of the calling object +% +% Outputs: +% none +% +% Example: +% onPushAnimate(src) +% +% Other m-files required: +% clearSingleAxis +% plotBSphere +% plotPulse +% plotRamp +% plotResults +% +% Subfunctions: +% none +% +% MAT-files required: +% none +% +% See also: BLOCHUS +% Author: Thomas Hiller +% email: thomas.hiller[at]leibniz-liag.de +% License: GNU GPLv3 (at end) -% change the pushbutton color to indicate that an animation is running -set(src,'BackGroundColor','r'); -pause(0.01); +%------------- BEGIN CODE -------------- -NoFrames = 100; -FPS = 24; +% get GUI handle +fig = ancestor(src,'figure','toplevel'); -newblue = [0 0.4470 0.7410]; -neworange = [0.8500 0.3250 0.0980]; - -switch data.basic.type +if ~isempty(fig) && strcmp(get(fig,'Tag'),'BLOCHUS') + % get GUI data + gui = getappdata(fig,'gui'); + data = getappdata(fig,'data'); + myui = gui.myui; - case 'std' - set(gui.text_handles.Status,'String','Animation running ...'); - pause(0.01); - Mamp = zeros(numel(data.TT),1); - for i=1:numel(data.TT) - Mamp(i,1) = norm(data.MM(i,:)); % amplitude of M - end - - dt = data.TT(end)/NoFrames; - time = 0:dt:data.TT(end); - - axes(gui.axes_handles.MagL); - cla(gui.axes_handles.MagL); - h1 = animatedline('Color','r','LineWidth',2,'Parent',gui.axXYZL); - h2 = animatedline('Color','g','LineWidth',2,'Parent',gui.axXYZL); - h3 = animatedline('Color','b','LineWidth',2,'Parent',gui.axXYZL); - h4 = animatedline('Color','k','LineWidth',2,'LineStyle','--','Parent',gui.axXYZL); - - axes(gui.axes_handles.MagR); - cla(gui.axes_handles.MagR); - h7 = animatedline('Color','r','LineWidth',2,'Parent',gui.axXYZR); - h8 = animatedline('Color','g','LineWidth',2,'Parent',gui.axXYZR); - h9 = animatedline('Color','b','LineWidth',2,'Parent',gui.axXYZR); - h10 = animatedline('Color','k','LineWidth',2,'LineStyle','--','Parent',gui.axXYZR); - - axes(gui.axSphereL); - cla(gui.axSphereL); - hold(gui.axSphereL,'on'); - plotBSphere(18,18,gui.axSphereL); - h5 = animatedline('Color',myui.color.basic,'LineWidth',2,'Parent',gui.axSphereL); - - axes(gui.axSphereR); - cla(gui.axSphereR); - hold(gui.axSphereR,'on'); - plotBSphere(18,18,gui.axSphereR); - h6 = animatedline('Color',myui.color.basic,'LineWidth',2,'Parent',gui.axSphereR); - - for nf = 1:NoFrames-1 - - x1 = data.TT(data.TT>=time(nf) & data.TT=time(nf) & data.TT=time(nf) & data.TT=time(nf) & data.TT=time(nf) & data.TT=time(nf) & data.TT=time(nf) & data.TT=time(nf) & data.TT=time(nf) & data.TT=time(nf) & data.TT=time(nf) & data.TT=time(nf) & data.TT=time(nf) & data.TT=time(nf) & data.TT=time(nf) & data.TT=t(nf) & T=t(nf) & T1=t(nf) & T2=time(nf) & data.TT=time(nf) & data.TT=time(nf) & data.TT=t(nf) & T1=t(nf) & T2=time(nf) & data.TT=time(nf) & data.results.prepol.t./1e3=time(nf) & data.results.prepol.t./1e3=time(nf) & data.results.prepol.t./1e3= time(nf) - x2 = data.results.prepol.t(data.results.prepol.t./1e3>=time(nf) & data.results.prepol.t./1e3=time(nf) & tt./1e3=t(nf) & T1t(nf) & T2<=t(nf+1); % t2? + yBx = Beffn(indt2,1); + yBy = Beffn(indt2,2); + yBz = Beffn(indt2,3); + yBramp = Bval(indt2,1); + + % add the M data to the sphere (prepol color) + addpoints(h3dMa,yMxx,yMyy,yMzz); + % add the B-field trace to the sphere + addpoints(h3dB,yBx,yBy,yBz); + elseif t(nf)>Tramp && t(nf) <= Tramp+Twait + % add the M data to the sphere (wait color) + addpoints(h3dMb,yMxx,yMyy,yMzz); + elseif t(nf)>Tramp+Twait && t(nf) <= Tsim-Trelax + % add the M data to the sphere (pulse color) + addpoints(h3dMc,yMxx,yMyy,yMzz); + elseif t(nf) > Tsim-Trelax + % after the pulse is over + % add the M data to the sphere (basic color) + addpoints(h3dMd,yMxx,yMyy,yMzz); + end + % sphere axis settings + view(ax2,Mview); + set(ax2,'XLim',[-1.05 1.05],'YLim',[-1.05 1.05],'ZLim',[-1.05 1.05]) + set(ax2,'Color','w','XColor','none','YColor','none','ZColor','none'); + axis(ax2,'equal'); + axis(ax2,'tight'); - y10 = y10a(data.results.prepol.t./1e3>=time(nf) & data.results.prepol.t./1e3=time(nf) & data.results.prepol.t./1e3=Tramp+Twait && t(nf) < Tsim-Trelax + indt3 = T3+Tramp+Twait>=t(nf) & T3+Tramp+Twait=time(nf) & tt./1e3=time(nf) & tt./1e3. diff --git a/callbacks/push/onPushRun.m b/callbacks/push/onPushRun.m index 889fdf9..c66f4f6 100644 --- a/callbacks/push/onPushRun.m +++ b/callbacks/push/onPushRun.m @@ -45,6 +45,8 @@ function onPushRun(src,~) % change the pushbutton color to indicate that a calculation is running set(src,'BackGroundColor','r'); + % reset the color of the animate button + set(gui.push_handles.Animate,'BackGroundColor',[.94 .94 .94]); % basic parameter that are always needed % z unit vector @@ -151,10 +153,13 @@ function onPushRun(src,~) [TT,MM] = ode45(@(t,m) fcn_BLOCHUS_ode(t,m,odeparam),[0 Tsim],Minit,options); % normalized magnetization vector at end of switch-off ramp - MMn = MM(end,:)./norm(MM(end,:)); + % because the simulation can be longer than the ramp, find the + % last point of the ramp to calculate the adiabatic quality p + indt = find(TT<=rampparam.Tramp,1,'last'); + MMn = MM(indt,:)./norm(MM(indt,:)); % "adiabatic quality" p of the switch-off ramp - % -> orientation of M with respect to z_unit - p = dot(MMn(end,:),zunit)./norm(zunit); + % -> orientation of M with respect to z_unit + p = dot(MMn,zunit)./norm(zunit); % save data data.results.basic.T = TT; @@ -260,9 +265,9 @@ function onPushRun(src,~) theta(indT) = getOmega0(odeparam.gamma,odeparam.B0).*TT(indT); % rotate M into rotating frame of reference Mrot = getMrot(MM,theta,dphi); - % get FFTof M in the laboratory frame of reference + % get FFT of M in the laboratory frame of reference [Xm,fmx] = getFFT(TT,MM(:,1:2)); - % get FFT for the pulse + % get FFT of the pulse [Xb,fbx] = getFFT(TT(TT<=Ttau),Bpulse(TT<=Ttau,1:2)); % update Info field @@ -271,9 +276,9 @@ function onPushRun(src,~) else % rotate M into rotating frame of reference Mrot = getMrot(MM,theta); - % get FFTof M in the laboratory frame of reference + % get FFT of M in the laboratory frame of reference [Xm,fmx] = getFFT(TT,MM(:,1:2)); - % get FFT for the pulse + % get FFT of the pulse [Xb,fbx] = getFFT(TT,Bpulse(:,1:2)); % update Info field @@ -292,6 +297,12 @@ function onPushRun(src,~) % this is basically the combination of all of the above % simulation types + % --- IMPORTANT NOTE: ---------------------------------------- + % The pre-polarization switch-off only "lives" in the laboratory + % frame of reference. However, for convenience reasons I plot + % the lab-frame pre-polarization data also in the rotating + % frame of reference! This is u-n-p-h-y-s-i-c-a-l and pure "eye candy" + % ------------------------------------------------------------- % these times we will later on, so init them already here % total simulation time [s] @@ -511,7 +522,7 @@ function onPushRun(src,~) % and account for the phase from the wait time before the % pulse MM3rot = getMrot(MM,theta,dphi+phiWait); - % get FFT pulse B-field + % get FFT of the pulse [Xb,fbx] = getFFT(TT(TT<=Ttau),Bpulse(TT<=Ttau,1:2)); % update Info field @@ -523,7 +534,7 @@ function onPushRun(src,~) % and account for the phase from the wait time before the % pulse MM3rot = getMrot(MM,theta,phiWait); - % get FFT pulse B-field + % get FFT of the pulse [Xb,fbx] = getFFT(TT,Bpulse(:,1:2)); % update Info field @@ -546,6 +557,13 @@ function onPushRun(src,~) MM = [MM1;MM2;MM3]; % because there is no M in the rotating frame of reference % during the switch-off ramp, use the lab-frame data instead + % --- IMPORTANT NOTE: ---------------------------------------- + % The pre-polarization switch-off only "lives" in the laboratory + % frame of reference. However, for convenience reasons I plot + % the lab-frame pre-polarization data also in the rotating + % frame of reference! This is u-n-p-h-y-s-i-c-a-l and pure "eye candy" + % MM1 is lab-frame data! + % ------------------------------------------------------------- MMrot = [MM1;MM2rot;MM3rot]; % remove possible duplicate points @@ -608,4 +626,4 @@ function onPushRun(src,~) % GNU General Public License for more details. % % You should have received a copy of the GNU General Public License -% along with this program. If not, see . \ No newline at end of file +% along with this program. If not, see . diff --git a/doc/blochus/BLOCHUS/BLOCHUS.html b/doc/blochus/BLOCHUS/BLOCHUS.html index 0a6e019..cc1f0b7 100644 --- a/doc/blochus/BLOCHUS/BLOCHUS.html +++ b/doc/blochus/BLOCHUS/BLOCHUS.html @@ -105,8 +105,8 @@

SOURCE CODE ^%------------- BEGIN CODE -------------- 0034 0035 %% GUI 'header' info and default GUI settings -0036 myui.version = '0.1.0'; -0037 myui.date = '15.05.2020'; +0036 myui.version = '0.1.1'; +0037 myui.date = '16.05.2020'; 0038 myui.author = 'Thomas Hiller'; 0039 myui.email = 'thomas.hiller[at]leibniz-liag.de'; 0040 diff --git a/doc/blochus/BLOCHUS/BLOCHUS_createPanelBasic.html b/doc/blochus/BLOCHUS/BLOCHUS_createPanelBasic.html index 35a3501..8bdfb8c 100644 --- a/doc/blochus/BLOCHUS/BLOCHUS_createPanelBasic.html +++ b/doc/blochus/BLOCHUS/BLOCHUS_createPanelBasic.html @@ -155,7 +155,7 @@

SOURCE CODE ^'FontSize',myui.fontsize,... 0084 'UserData',struct('Tooltipstr',tstr,'defaults',data.init.B0),... 0085 'Callback',@onEditValue); -0086 tstr = '<HTML><b>Omega</b><sub>0</sub> frequency in [Hz].<br>'; +0086 tstr = ['<HTML>Larmor frequency <b>',char(hex2dec('3C9')),'</b><sub>0</sub> in [Hz].<br>']; 0087 gui.edit_handles.Omega0 = uicontrol('Style','Edit',... 0088 'Parent',setB0,... 0089 'String',sprintf('%7.2f',data.init.Omega0(1)),... diff --git a/doc/blochus/BLOCHUS/BLOCHUS_createPanelControl.html b/doc/blochus/BLOCHUS/BLOCHUS_createPanelControl.html index 198806a..ed0698c 100644 --- a/doc/blochus/BLOCHUS/BLOCHUS_createPanelControl.html +++ b/doc/blochus/BLOCHUS/BLOCHUS_createPanelControl.html @@ -60,7 +60,7 @@

DESCRIPTION ^CROSS-REFERENCE INFORMATION ^

This function calls: +
  • onPushAnimate animates the results of the latest simulation
  • onPushGrid resets the axes grid to equal size
  • onPushRun starts the calculation
  • This function is called by: @@ -116,7 +116,7 @@

    SOURCE CODE ^'UserData',struct('Tooltipstr',tstr),... 0046 'Callback',@onPushRun); 0047 -0048 tstr = 'Show animation of the last result.'; +0048 tstr = 'Show animation of the latest result.'; 0049 gui.push_handles.Animate = uicontrol('Style','pushbutton',... 0050 'Parent',gui.panels.Control.HBox,... 0051 'String','ANIMATE',... diff --git a/doc/blochus/callbacks/checkbox/onCheckPrePolPulse.html b/doc/blochus/callbacks/checkbox/onCheckPrePolPulse.html index cea12a6..dbc219c 100644 --- a/doc/blochus/callbacks/checkbox/onCheckPrePolPulse.html +++ b/doc/blochus/callbacks/checkbox/onCheckPrePolPulse.html @@ -333,37 +333,39 @@

    SOURCE CODE ^'data'); 0263 end 0264 -0265 % update all data inside the GUI -0266 setappdata(fig,'data',data); -0267 % update status bar -0268 updateStatusInformation(fig); -0269 else -0270 warndlg({'onCheckPrePolPulse:','There is no figure with the BLOCHUS Tag open.'},... -0271 'BLOCHUS error'); -0272 end -0273 +0265 % because the settings changed, deactivate the "Animate" button +0266 set(gui.push_handles.Animate,'Enable','off'); +0267 % update all data inside the GUI +0268 setappdata(fig,'data',data); +0269 % update status bar +0270 updateStatusInformation(fig); +0271 else +0272 warndlg({'onCheckPrePolPulse:','There is no figure with the BLOCHUS Tag open.'},... +0273 'BLOCHUS error'); 0274 end 0275 -0276 %------------- END OF CODE -------------- +0276 end 0277 -0278 %% License: -0279 % GNU GPLv3 -0280 % -0281 % BLOCHUS -0282 % Copyright (C) 2019 Thomas Hiller -0283 % -0284 % This program is free software: you can redistribute it and/or modify -0285 % it under the terms of the GNU General Public License as published by -0286 % the Free Software Foundation, either version 3 of the License, or -0287 % (at your option) any later version. -0288 % -0289 % This program is distributed in the hope that it will be useful, -0290 % but WITHOUT ANY WARRANTY; without even the implied warranty of -0291 % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -0292 % GNU General Public License for more details. -0293 % -0294 % You should have received a copy of the GNU General Public License -0295 % along with this program. If not, see <https://www.gnu.org/licenses/>. +0278 %------------- END OF CODE -------------- +0279 +0280 %% License: +0281 % GNU GPLv3 +0282 % +0283 % BLOCHUS +0284 % Copyright (C) 2019 Thomas Hiller +0285 % +0286 % This program is free software: you can redistribute it and/or modify +0287 % it under the terms of the GNU General Public License as published by +0288 % the Free Software Foundation, either version 3 of the License, or +0289 % (at your option) any later version. +0290 % +0291 % This program is distributed in the hope that it will be useful, +0292 % but WITHOUT ANY WARRANTY; without even the implied warranty of +0293 % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +0294 % GNU General Public License for more details. +0295 % +0296 % You should have received a copy of the GNU General Public License +0297 % along with this program. If not, see <https://www.gnu.org/licenses/>.
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/blochus/callbacks/checkbox/onCheckPulseQ.html b/doc/blochus/callbacks/checkbox/onCheckPulseQ.html index 9d5acac..c8af8c8 100644 --- a/doc/blochus/callbacks/checkbox/onCheckPulseQ.html +++ b/doc/blochus/callbacks/checkbox/onCheckPulseQ.html @@ -58,7 +58,7 @@

    DESCRIPTION ^CROSS-REFERENCE INFORMATION ^

    This function calls: +
  • getPulseParameters updates all relevant pulse settings
  • plotPulse plots different pulse parameter
  • This function is called by: @@ -122,7 +122,7 @@

    SOURCE CODE ^% get GUI data 0054 data = getappdata(fig,'data'); 0055 % plot pulse -0056 plotBpulse(gui.figh); +0056 plotPulse(gui.figh); 0057 0058 else 0059 warndlg({'onCheckPulseQ:','There is no figure with the BLOCHUS Tag open.'},... diff --git a/doc/blochus/callbacks/edits/onEditValue.html b/doc/blochus/callbacks/edits/onEditValue.html index 90b47c7..867530e 100644 --- a/doc/blochus/callbacks/edits/onEditValue.html +++ b/doc/blochus/callbacks/edits/onEditValue.html @@ -46,7 +46,7 @@

    DESCRIPTION ^DESCRIPTION ^CROSS-REFERENCE INFORMATION ^

    This function calls:
      -
    • onEditValue updates all edit field values, checks for wrong inputs and
    • onPopupPrePolRamp selects the pre-polarization switch-off ramp
    • getB0 calculates the magnetic field from a given angular frequency and
    • getOmega0 calculates the angular frequency from a given B-field and
    • getPulseParameters updates all relevant pulse settings
    • getRampParameters updates all relevant switch-off ramp settings
    • plotBpulse plots different pulse parameter
    • plotRamp plots different pre-polarization switch-off ramp parameter
    +
  • onEditValue updates all edit field values, checks for wrong inputs and
  • onPopupPrePolRamp selects the pre-polarization switch-off ramp
  • getB0 calculates the magnetic field from a given angular frequency and
  • getOmega0 calculates the angular frequency from a given B-field and
  • getPulseParameters updates all relevant pulse settings
  • getRampParameters updates all relevant switch-off ramp settings
  • plotPulse plots different pulse parameter
  • plotRamp plots different pre-polarization switch-off ramp parameter
  • This function is called by: @@ -96,7 +96,7 @@

    SOURCE CODE ^% getOmega0 0020 % getPulseParameters 0021 % getRampParameters -0022 % plotBpulse +0022 % plotPulse 0023 % plotRamp 0024 % 0025 % Subfunctions: @@ -127,373 +127,365 @@

    SOURCE CODE ^% get the user data of the field 0051 ud = get(src,'UserData'); 0052 -0053 if isstruct(ud) % for new fields -0054 % get the default values [default min max] -0055 defaults = ud.defaults; -0056 -0057 % check if the value is numeric -0058 % if not reset to defaults stored in user data -0059 if isnan(val) -0060 set(src,'String',num2str(defaults(1))); -0061 val = str2double(get(src,'String')); -0062 end -0063 % check if the value is out of bounds -0064 % if yes reset to default -0065 if val < defaults(2) || val > defaults(3) -0066 set(src,'String',num2str(defaults(1))); -0067 val = str2double(get(src,'String')); %#ok<*NASGU> -0068 end -0069 -0070 else % old style (Needs to be removed after the refactoring) -0071 % check if the value is numeric -0072 % if not reset to defaults stored in user data -0073 if isnan(val) -0074 set(src,'String',num2str(ud(3))); -0075 val = str2double(get(src,'String')); -0076 end -0077 % check if the value is out of bounds -0078 % if yes reset to default -0079 if val < ud(1) || val > ud(2) -0080 set(src,'String',num2str(ud(3))); -0081 val = str2double(get(src,'String')); %#ok<*NASGU> -0082 end -0083 disp(['there is still an old style edit field:',tag]) -0084 end -0085 -0086 % get the data field to update from the field tag -0087 out = createDataString(tag); -0088 % update the corresponding data field -0089 updstr = [out.updstr,'=val;']; -0090 eval(updstr); -0091 -0092 % update the data inside the GUI -0093 setappdata(fig,'data',data); -0094 -0095 % depending on the particular edit field, further actions are -0096 % necessary -0097 switch tag -0098 % ----------------------------------------------------------------- -0099 % --- BASICS ------------------------------------------------------ -0100 % ----------------------------------------------------------------- -0101 case 'basic_B0' -0102 % new Larmor frequency due to changed B0 -0103 data.basic.Omega0 = getOmega0(data.basic.gamma,data.basic.B0)/2/pi; -0104 % update the GUI fields -0105 set(gui.edit_handles.Omega0,'String',sprintf('%7.2f',data.basic.Omega0)); -0106 setappdata(fig,'data',data); -0107 % if "Pulse" is activated, update the pulse as if the -0108 % pulse length (or number of periods) would have been changed -0109 % manually -0110 if get(gui.check_handles.Pulse,'Value') == 1 -0111 onEditValue(gui.edit_handles.PulseTtau); -0112 data = getappdata(fig,'data'); -0113 end -0114 % if "PrePol" is activated and the active ramp is "melton1995" -0115 % update the switch-off ramp settings due to the changed Larmor -0116 % frequency -0117 if get(gui.check_handles.PrePol,'Value') == 1 && ... -0118 get(gui.popup_handles.PrePolRamp,'Value') == 5 -0119 setappdata(fig,'data',data); -0120 onPopupPrePolRamp(gui.popup_handles.PrePolRamp); -0121 data = getappdata(fig,'data'); -0122 end -0123 if get(gui.check_handles.PrePol,'Value') == 1 -0124 setappdata(fig,'data',data); -0125 getRampParameters(fig); -0126 data = getappdata(fig,'data'); -0127 end -0128 -0129 case 'basic_Omega0' -0130 % fix sign if it is wrong -0131 if (data.basic.gamma > 0 && data.basic.Omega0 > 0) || ... -0132 (data.basic.gamma < 0 && data.basic.Omega0 < 0) -0133 data.basic.Omega0 = -data.basic.Omega0; -0134 end -0135 % new B0 due to changed Larmor frequency -0136 data.basic.B0 = getB0(data.basic.gamma,data.basic.Omega0*2*pi); -0137 % update the GUI fields -0138 set(gui.edit_handles.Omega0,'String',sprintf('%7.2f',data.basic.Omega0)); -0139 set(gui.edit_handles.B0,'String',sprintf('%5.4e',data.basic.B0)); -0140 setappdata(fig,'data',data); -0141 % if "Pulse" is activated, update the pulse as if the -0142 % pulse length (or number of periods) would have been changed -0143 % manually -0144 if get(gui.check_handles.Pulse,'Value') == 1 -0145 onEditValue(gui.edit_handles.PulseTtau); -0146 data = getappdata(fig,'data'); -0147 end -0148 % if "PrePol" is activated and the active ramp is "melton1995" -0149 % update the switch-off ramp settings due to the changed Larmor -0150 % frequency -0151 if get(gui.check_handles.PrePol,'Value') == 1 && ... -0152 get(gui.popup_handles.PrePolRamp,'Value') == 5 -0153 setappdata(fig,'data',data); -0154 onPopupPrePolRamp(gui.popup_handles.PrePolRamp); -0155 data = getappdata(fig,'data'); -0156 end -0157 if get(gui.check_handles.PrePol,'Value') == 1 -0158 setappdata(fig,'data',data); -0159 getRampParameters(fig); -0160 data = getappdata(fig,'data'); -0161 end -0162 -0163 case 'basic_Minitx' -0164 % x-component of init magnetization -0165 data.basic.Minit(1) = val; -0166 -0167 case 'basic_Minity' -0168 % y-component of init magnetization -0169 data.basic.Minit(2) = val; -0170 -0171 case 'basic_Minitz' -0172 % z-component of init magnetization -0173 data.basic.Minit(3) = val; -0174 -0175 % ------------------------------------------------------------- -0176 % --- PRE-POLARIZATION ---------------------------------------- -0177 % ------------------------------------------------------------- -0178 case {'prepol_Factor','prepol_SwitchFactor'} -0179 % check if the ramp type is "melton1995", if yes update the -0180 % switch-off time to maintain the same switch-off rate -0181 if get(gui.popup_handles.PrePolRamp,'Value') == 5 -0182 % k / rate -0183 GAMMA = data.prepol.Factor/data.prepol.SwitchFactor; -0184 % corresponding ramp time -0185 Tramp = GAMMA/(data.basic.B0*data.basic.gamma)*1e3; % [ms] -0186 data.prepol.Tramp = Tramp; -0187 data.prepol.Tslope = Tramp; -0188 switch data.basic.type -0189 case 'prepol' -0190 data.basic.Tsim = Tramp; -0191 set(gui.edit_handles.Tsim,'String',num2str(data.basic.Tsim)); -0192 otherwise -0193 % nothing to do -0194 end -0195 setappdata(fig,'data',data); -0196 set(gui.edit_handles.PrePolTramp,'String',num2str(data.prepol.Tramp)); -0197 set(gui.edit_handles.PrePolTslope,'String',num2str(data.prepol.Tslope)); -0198 end -0199 % update switch-off ramp settings -0200 getRampParameters(fig); -0201 data = getappdata(fig,'data'); -0202 plotRamp(fig); -0203 -0204 case {'prepol_Theta','prepol_Phi','prepol_Tslope'} -0205 % update switch-off ramp settings -0206 getRampParameters(fig); -0207 data = getappdata(fig,'data'); -0208 plotRamp(fig); -0209 -0210 case 'prepol_Tramp' -0211 % for "linear" and "half cosine" ramp set the Tslope value, -0212 % which is not need here equal to Tramp -0213 if strcmp(data.prepol.Ramp,'lin') || strcmp(data.prepol.Ramp,'halfcos') -0214 data.prepol.Tslope = data.prepol.Tramp; -0215 set(gui.edit_handles.PrePolTslope,'String',num2str(data.prepol.Tslope)); -0216 end -0217 % in case of pure "PrePol" update the total simulation time -0218 switch data.basic.type -0219 case 'prepol' -0220 data.basic.Tsim = data.prepol.Tramp; -0221 set(gui.edit_handles.Tsim,'String',num2str(data.basic.Tsim)); -0222 otherwise -0223 % nothing to do -0224 end -0225 setappdata(fig,'data',data); -0226 % update switch-off ramp settings -0227 getRampParameters(fig); -0228 data = getappdata(fig,'data'); -0229 plotRamp(fig); -0230 -0231 % ------------------------------------------------------------- -0232 % --- PULSE --------------------------------------------------- -0233 % ------------------------------------------------------------- -0234 case 'pulse_B1Factor' -0235 % if the pulse amplitude changes some settings have to be -0236 % adjusted, depending on the chosen pulse type -0237 switch data.pulse.Type -0238 case {'pi_half','pi'} -0239 switch data.pulse.Type -0240 case 'pi_half' -0241 % in case of "pi_half" the pulse length gets updated -0242 data.pulse.Ttau = abs(1e3*(pi/2/(data.basic.gamma*data.basic.B0*data.pulse.B1Factor))); -0243 case 'pi' -0244 % in case of "pi" the pulse length gets updated -0245 data.pulse.Ttau = abs(1e3*(pi/(data.basic.gamma*data.basic.B0*data.pulse.B1Factor))); -0246 end -0247 set(gui.edit_handles.PulseTtau,'String',num2str(data.pulse.Ttau)); -0248 % in case of pure "Pulse" update the total simulation time -0249 switch data.basic.type -0250 case 'pulse' -0251 data.basic.Tsim = data.pulse.Ttau; -0252 set(gui.edit_handles.Tsim,'String',num2str(data.basic.Tsim)); -0253 otherwise -0254 % nothing to do -0255 end -0256 setappdata(fig,'data',data); -0257 % update pulse settings -0258 getPulseParameters(fig); -0259 data = getappdata(fig,'data'); -0260 plotBpulse(fig); -0261 -0262 otherwise -0263 % update pulse settings -0264 getPulseParameters(fig); -0265 data = getappdata(fig,'data'); -0266 plotBpulse(fig); -0267 end -0268 -0269 case 'pulse_Ttau' -0270 % if the pulse length changes some settings have to be -0271 % adjusted, depending on the chosen pulse type -0272 switch data.pulse.Type -0273 case {'pi_half','pi'} -0274 switch data.pulse.Type -0275 case 'pi_half' -0276 % in case of "pi_half" the pulse amplitude gets updated -0277 data.pulse.B1Factor = abs(1e3*(pi/2/(data.basic.gamma*data.basic.B0*data.pulse.Ttau))); -0278 case 'pi' -0279 % in case of "pi" the pulse amplitude gets updated -0280 data.pulse.B1Factor = abs(1e3*(pi/(data.basic.gamma*data.basic.B0*data.pulse.Ttau))); -0281 end -0282 set(gui.edit_handles.PulseB1Factor,'String',num2str(data.pulse.B1Factor)); -0283 % in case of pure "Pulse" update the total simulation time -0284 switch data.basic.type -0285 case 'pulse' -0286 data.basic.Tsim = data.pulse.Ttau; -0287 set(gui.edit_handles.Tsim,'String',num2str(data.basic.Tsim)); -0288 otherwise -0289 % nothing to do -0290 end -0291 setappdata(fig,'data',data); -0292 % update pulse settings -0293 getPulseParameters(fig); -0294 data = getappdata(fig,'data'); -0295 plotBpulse(fig); -0296 -0297 case 'MIDI_OR' -0298 % in case of "MIDI_OR" the PulseTtau-field holds the -0299 % number of periods -0300 data.pulse.MIDINP = val; -0301 % update pulse length -0302 data.pulse.Ttau = abs(data.pulse.MIDINP/data.basic.Omega0)*1e3; -0303 % update pulse amplitude to pi/2 value -0304 data.pulse.B1Factor = abs(1e3*(pi/2/(data.basic.gamma*data.basic.B0*data.pulse.Ttau))); -0305 set(gui.edit_handles.PulseB1Factor,'String',num2str(data.pulse.B1Factor)); -0306 % in case of pure "Pulse" update the total simulation time -0307 switch data.basic.type -0308 case 'pulse' -0309 data.basic.Tsim = data.pulse.Ttau; -0310 set(gui.edit_handles.Tsim,'String',num2str(data.basic.Tsim)); -0311 otherwise -0312 % nothing to do -0313 end -0314 setappdata(fig,'data',data); -0315 % update pulse settings -0316 getPulseParameters(fig); -0317 data = getappdata(fig,'data'); -0318 plotBpulse(fig); -0319 -0320 case 'MIDI_AP' -0321 % in case of "MIDI_AP" the PulseTtau-field holds the -0322 % number of periods -0323 data.pulse.MIDINP = val; -0324 % update pulse length assuming a constant frequency -0325 data.pulse.Ttau = abs(data.pulse.MIDINP/data.basic.Omega0)*1e3; -0326 % now calculate the actual pulse settings -0327 setappdata(fig,'data',data); -0328 getPulseParameters(fig); -0329 data = getappdata(fig,'data'); -0330 % adjust the pulse length to the actual value -0331 data.pulse.Ttau = data.pulse_MIDI.t(end)*1e3; -0332 % in case of pure "Pulse" update the total simulation time -0333 switch data.basic.type -0334 case 'pulse' -0335 data.basic.Tsim = data.pulse.Ttau; -0336 set(gui.edit_handles.Tsim,'String',num2str(data.basic.Tsim)); -0337 otherwise -0338 % nothing to do -0339 end -0340 setappdata(fig,'data',data); -0341 % update pulse plot -0342 plotBpulse(fig); -0343 -0344 otherwise -0345 % for all other pulse types ("free" & "AHP") -0346 % in case of pure "Pulse" update the total simulation time -0347 switch data.basic.type -0348 case 'pulse' -0349 data.basic.Tsim = data.pulse.Ttau; -0350 set(gui.edit_handles.Tsim,'String',num2str(data.basic.Tsim)); -0351 otherwise -0352 % nothing to do -0353 end -0354 % update GUI data -0355 setappdata(fig,'data',data); -0356 % update pulse settings +0053 % get the default values [default min max] +0054 defaults = ud.defaults; +0055 +0056 % check if the value is numeric +0057 % if not reset to defaults stored in user data +0058 if isnan(val) +0059 set(src,'String',num2str(defaults(1))); +0060 val = str2double(get(src,'String')); +0061 end +0062 % check if the value is out of bounds +0063 % if yes reset to default +0064 if val < defaults(2) || val > defaults(3) +0065 set(src,'String',num2str(defaults(1))); +0066 val = str2double(get(src,'String')); %#ok<*NASGU> +0067 end +0068 +0069 % get the data field to update from the field tag +0070 out = createDataString(tag); +0071 % update the corresponding data field +0072 updstr = [out.updstr,'=val;']; +0073 eval(updstr); +0074 +0075 % update the data inside the GUI +0076 setappdata(fig,'data',data); +0077 +0078 % depending on the particular edit field, further actions are +0079 % necessary +0080 switch tag +0081 % ----------------------------------------------------------------- +0082 % --- BASICS ------------------------------------------------------ +0083 % ----------------------------------------------------------------- +0084 case 'basic_B0' +0085 % new Larmor frequency due to changed B0 +0086 data.basic.Omega0 = getOmega0(data.basic.gamma,data.basic.B0)/2/pi; +0087 % update the GUI fields +0088 set(gui.edit_handles.Omega0,'String',sprintf('%7.2f',data.basic.Omega0)); +0089 setappdata(fig,'data',data); +0090 % if "Pulse" is activated, update the pulse as if the +0091 % pulse length (or number of periods) would have been changed +0092 % manually +0093 if get(gui.check_handles.Pulse,'Value') == 1 +0094 onEditValue(gui.edit_handles.PulseTtau); +0095 data = getappdata(fig,'data'); +0096 end +0097 % if "PrePol" is activated and the active ramp is "melton1995" +0098 % update the switch-off ramp settings due to the changed Larmor +0099 % frequency +0100 if get(gui.check_handles.PrePol,'Value') == 1 && ... +0101 get(gui.popup_handles.PrePolRamp,'Value') == 5 +0102 setappdata(fig,'data',data); +0103 onPopupPrePolRamp(gui.popup_handles.PrePolRamp); +0104 data = getappdata(fig,'data'); +0105 end +0106 if get(gui.check_handles.PrePol,'Value') == 1 +0107 setappdata(fig,'data',data); +0108 getRampParameters(fig); +0109 data = getappdata(fig,'data'); +0110 end +0111 +0112 case 'basic_Omega0' +0113 % fix sign if it is wrong +0114 if (data.basic.gamma > 0 && data.basic.Omega0 > 0) || ... +0115 (data.basic.gamma < 0 && data.basic.Omega0 < 0) +0116 data.basic.Omega0 = -data.basic.Omega0; +0117 end +0118 % new B0 due to changed Larmor frequency +0119 data.basic.B0 = getB0(data.basic.gamma,data.basic.Omega0*2*pi); +0120 % update the GUI fields +0121 set(gui.edit_handles.Omega0,'String',sprintf('%7.2f',data.basic.Omega0)); +0122 set(gui.edit_handles.B0,'String',sprintf('%5.4e',data.basic.B0)); +0123 setappdata(fig,'data',data); +0124 % if "Pulse" is activated, update the pulse as if the +0125 % pulse length (or number of periods) would have been changed +0126 % manually +0127 if get(gui.check_handles.Pulse,'Value') == 1 +0128 onEditValue(gui.edit_handles.PulseTtau); +0129 data = getappdata(fig,'data'); +0130 end +0131 % if "PrePol" is activated and the active ramp is "melton1995" +0132 % update the switch-off ramp settings due to the changed Larmor +0133 % frequency +0134 if get(gui.check_handles.PrePol,'Value') == 1 && ... +0135 get(gui.popup_handles.PrePolRamp,'Value') == 5 +0136 setappdata(fig,'data',data); +0137 onPopupPrePolRamp(gui.popup_handles.PrePolRamp); +0138 data = getappdata(fig,'data'); +0139 end +0140 if get(gui.check_handles.PrePol,'Value') == 1 +0141 setappdata(fig,'data',data); +0142 getRampParameters(fig); +0143 data = getappdata(fig,'data'); +0144 end +0145 +0146 case 'basic_Minitx' +0147 % x-component of init magnetization +0148 data.basic.Minit(1) = val; +0149 +0150 case 'basic_Minity' +0151 % y-component of init magnetization +0152 data.basic.Minit(2) = val; +0153 +0154 case 'basic_Minitz' +0155 % z-component of init magnetization +0156 data.basic.Minit(3) = val; +0157 +0158 % ------------------------------------------------------------- +0159 % --- PRE-POLARIZATION ---------------------------------------- +0160 % ------------------------------------------------------------- +0161 +0162 case {'prepol_Factor','prepol_SwitchFactor'} +0163 % check if the ramp type is "melton1995", if yes update the +0164 % switch-off time to maintain the same switch-off rate +0165 if get(gui.popup_handles.PrePolRamp,'Value') == 5 +0166 % k / rate +0167 GAMMA = data.prepol.Factor/data.prepol.SwitchFactor; +0168 % corresponding ramp time +0169 Tramp = GAMMA/(data.basic.B0*data.basic.gamma)*1e3; % [ms] +0170 data.prepol.Tramp = Tramp; +0171 data.prepol.Tslope = Tramp; +0172 switch data.basic.type +0173 case 'prepol' +0174 data.basic.Tsim = Tramp; +0175 set(gui.edit_handles.Tsim,'String',num2str(data.basic.Tsim)); +0176 otherwise +0177 % nothing to do +0178 end +0179 setappdata(fig,'data',data); +0180 set(gui.edit_handles.PrePolTramp,'String',num2str(data.prepol.Tramp)); +0181 set(gui.edit_handles.PrePolTslope,'String',num2str(data.prepol.Tslope)); +0182 end +0183 % update switch-off ramp settings +0184 getRampParameters(fig); +0185 data = getappdata(fig,'data'); +0186 plotRamp(fig); +0187 +0188 case {'prepol_Theta','prepol_Phi','prepol_Tslope'} +0189 % update switch-off ramp settings +0190 getRampParameters(fig); +0191 data = getappdata(fig,'data'); +0192 plotRamp(fig); +0193 +0194 case 'prepol_Tramp' +0195 % for "linear" and "half cosine" ramp set the Tslope value, +0196 % which is not need here equal to Tramp +0197 if strcmp(data.prepol.Ramp,'lin') || strcmp(data.prepol.Ramp,'halfcos') +0198 data.prepol.Tslope = data.prepol.Tramp; +0199 set(gui.edit_handles.PrePolTslope,'String',num2str(data.prepol.Tslope)); +0200 end +0201 % in case of pure "PrePol" update the total simulation time +0202 switch data.basic.type +0203 case 'prepol' +0204 data.basic.Tsim = data.prepol.Tramp; +0205 set(gui.edit_handles.Tsim,'String',num2str(data.basic.Tsim)); +0206 otherwise +0207 % nothing to do +0208 end +0209 setappdata(fig,'data',data); +0210 % update switch-off ramp settings +0211 getRampParameters(fig); +0212 data = getappdata(fig,'data'); +0213 plotRamp(fig); +0214 +0215 % ------------------------------------------------------------- +0216 % --- PULSE --------------------------------------------------- +0217 % ------------------------------------------------------------- +0218 +0219 case 'pulse_B1Factor' +0220 % if the pulse amplitude changes some settings have to be +0221 % adjusted, depending on the chosen pulse type +0222 switch data.pulse.Type +0223 case {'pi_half','pi'} +0224 switch data.pulse.Type +0225 case 'pi_half' +0226 % in case of "pi_half" the pulse length gets updated +0227 data.pulse.Ttau = abs(1e3*(pi/2/(data.basic.gamma*... +0228 data.basic.B0*data.pulse.B1Factor))); +0229 case 'pi' +0230 % in case of "pi" the pulse length gets updated +0231 data.pulse.Ttau = abs(1e3*(pi/(data.basic.gamma*... +0232 data.basic.B0*data.pulse.B1Factor))); +0233 end +0234 set(gui.edit_handles.PulseTtau,'String',num2str(data.pulse.Ttau)); +0235 % in case of pure "Pulse" update the total simulation time +0236 switch data.basic.type +0237 case 'pulse' +0238 data.basic.Tsim = data.pulse.Ttau; +0239 set(gui.edit_handles.Tsim,'String',num2str(data.basic.Tsim)); +0240 otherwise +0241 % nothing to do +0242 end +0243 setappdata(fig,'data',data); +0244 % update pulse settings +0245 getPulseParameters(fig); +0246 data = getappdata(fig,'data'); +0247 plotPulse(fig); +0248 +0249 otherwise +0250 % update pulse settings +0251 getPulseParameters(fig); +0252 data = getappdata(fig,'data'); +0253 plotPulse(fig); +0254 end +0255 +0256 case 'pulse_Ttau' +0257 % if the pulse length changes some settings have to be +0258 % adjusted, depending on the chosen pulse type +0259 switch data.pulse.Type +0260 case {'pi_half','pi'} +0261 switch data.pulse.Type +0262 case 'pi_half' +0263 % in case of "pi_half" the pulse amplitude gets updated +0264 data.pulse.B1Factor = abs(1e3*(pi/2/(data.basic.gamma*... +0265 data.basic.B0*data.pulse.Ttau))); +0266 case 'pi' +0267 % in case of "pi" the pulse amplitude gets updated +0268 data.pulse.B1Factor = abs(1e3*(pi/(data.basic.gamma*... +0269 data.basic.B0*data.pulse.Ttau))); +0270 end +0271 set(gui.edit_handles.PulseB1Factor,'String',num2str(data.pulse.B1Factor)); +0272 % in case of pure "Pulse" update the total simulation time +0273 switch data.basic.type +0274 case 'pulse' +0275 data.basic.Tsim = data.pulse.Ttau; +0276 set(gui.edit_handles.Tsim,'String',num2str(data.basic.Tsim)); +0277 otherwise +0278 % nothing to do +0279 end +0280 setappdata(fig,'data',data); +0281 % update pulse settings +0282 getPulseParameters(fig); +0283 data = getappdata(fig,'data'); +0284 plotPulse(fig); +0285 +0286 case 'MIDI_OR' +0287 % in case of "MIDI_OR" the PulseTtau-field holds the +0288 % number of periods +0289 data.pulse.MIDINP = val; +0290 % update pulse length +0291 data.pulse.Ttau = abs(data.pulse.MIDINP/data.basic.Omega0)*1e3; +0292 % update pulse amplitude to pi/2 value +0293 data.pulse.B1Factor = abs(1e3*(pi/2/(data.basic.gamma*... +0294 data.basic.B0*data.pulse.Ttau))); +0295 set(gui.edit_handles.PulseB1Factor,'String',num2str(data.pulse.B1Factor)); +0296 % in case of pure "Pulse" update the total simulation time +0297 switch data.basic.type +0298 case 'pulse' +0299 data.basic.Tsim = data.pulse.Ttau; +0300 set(gui.edit_handles.Tsim,'String',num2str(data.basic.Tsim)); +0301 otherwise +0302 % nothing to do +0303 end +0304 setappdata(fig,'data',data); +0305 % update pulse settings +0306 getPulseParameters(fig); +0307 data = getappdata(fig,'data'); +0308 plotPulse(fig); +0309 +0310 case 'MIDI_AP' +0311 % in case of "MIDI_AP" the PulseTtau-field holds the +0312 % number of periods +0313 data.pulse.MIDINP = val; +0314 % update pulse length assuming a constant frequency +0315 data.pulse.Ttau = abs(data.pulse.MIDINP/data.basic.Omega0)*1e3; +0316 % now calculate the actual pulse settings +0317 setappdata(fig,'data',data); +0318 getPulseParameters(fig); +0319 data = getappdata(fig,'data'); +0320 % adjust the pulse length to the actual value +0321 data.pulse.Ttau = data.pulse_MIDI.t(end)*1e3; +0322 % in case of pure "Pulse" update the total simulation time +0323 switch data.basic.type +0324 case 'pulse' +0325 data.basic.Tsim = data.pulse.Ttau; +0326 set(gui.edit_handles.Tsim,'String',num2str(data.basic.Tsim)); +0327 otherwise +0328 % nothing to do +0329 end +0330 setappdata(fig,'data',data); +0331 % update pulse plot +0332 plotPulse(fig); +0333 +0334 otherwise +0335 % for all other pulse types ("free" & "AHP") +0336 % in case of pure "Pulse" update the total simulation time +0337 switch data.basic.type +0338 case 'pulse' +0339 data.basic.Tsim = data.pulse.Ttau; +0340 set(gui.edit_handles.Tsim,'String',num2str(data.basic.Tsim)); +0341 otherwise +0342 % nothing to do +0343 end +0344 % update GUI data +0345 setappdata(fig,'data',data); +0346 % update pulse settings +0347 getPulseParameters(fig); +0348 data = getappdata(fig,'data'); +0349 plotPulse(fig); +0350 end +0351 +0352 otherwise +0353 switch data.basic.type +0354 % update all changes related to the pulse modulation +0355 case {'pulse','prepolpulse'} +0356 setappdata(fig,'data',data); 0357 getPulseParameters(fig); 0358 data = getappdata(fig,'data'); -0359 plotBpulse(fig); -0360 end -0361 -0362 otherwise -0363 switch data.basic.type -0364 % update all changes related to the pulse modulation -0365 case {'pulse','prepolpulse'} -0366 setappdata(fig,'data',data); -0367 getPulseParameters(fig); -0368 data = getappdata(fig,'data'); -0369 plotBpulse(fig); -0370 -0371 otherwise -0372 % nothing to do for all other fields e.g. T1, T2, Tsim -0373 end -0374 end -0375 -0376 % update GUI data -0377 setappdata(fig,'data',data); -0378 else -0379 warndlg({'onEditValue:','There is no figure with the BLOCHUS Tag open.'},... -0380 'BLOCHUS error'); -0381 end -0382 -0383 end -0384 -0385 %% helper function to create the update string -0386 function out = createDataString(tag) -0387 % find the underscore -0388 ind = strfind(tag,'_'); -0389 % the panel name is before the underscore -0390 out.panel = tag(1:ind(1)-1); -0391 % the field name afterwards -0392 out.field = tag(ind(1)+1:end); -0393 % replace the underscore with a dot -0394 tag(ind) = '.'; -0395 % create the update string -0396 out.updstr = ['data.',tag]; -0397 -0398 end -0399 -0400 %------------- END OF CODE -------------- -0401 -0402 %% License: -0403 % GNU GPLv3 +0359 plotPulse(fig); +0360 +0361 otherwise +0362 % because the pulse data changed, deactivate the +0363 % "Animate" button +0364 set(gui.push_handles.Animate,'Enable','off'); +0365 end +0366 end +0367 +0368 % update GUI data +0369 setappdata(fig,'data',data); +0370 else +0371 warndlg({'onEditValue:','There is no figure with the BLOCHUS Tag open.'},... +0372 'BLOCHUS error'); +0373 end +0374 +0375 end +0376 +0377 %% helper function to create the update string +0378 function out = createDataString(tag) +0379 % find the underscore +0380 ind = strfind(tag,'_'); +0381 % the panel name is before the underscore +0382 out.panel = tag(1:ind(1)-1); +0383 % the field name afterwards +0384 out.field = tag(ind(1)+1:end); +0385 % replace the underscore with a dot +0386 tag(ind) = '.'; +0387 % create the update string +0388 out.updstr = ['data.',tag]; +0389 +0390 end +0391 +0392 %------------- END OF CODE -------------- +0393 +0394 %% License: +0395 % GNU GPLv3 +0396 % +0397 % BLOCHUS +0398 % Copyright (C) 2019 Thomas Hiller +0399 % +0400 % This program is free software: you can redistribute it and/or modify +0401 % it under the terms of the GNU General Public License as published by +0402 % the Free Software Foundation, either version 3 of the License, or +0403 % (at your option) any later version. 0404 % -0405 % BLOCHUS -0406 % Copyright (C) 2019 Thomas Hiller -0407 % -0408 % This program is free software: you can redistribute it and/or modify -0409 % it under the terms of the GNU General Public License as published by -0410 % the Free Software Foundation, either version 3 of the License, or -0411 % (at your option) any later version. -0412 % -0413 % This program is distributed in the hope that it will be useful, -0414 % but WITHOUT ANY WARRANTY; without even the implied warranty of -0415 % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -0416 % GNU General Public License for more details. -0417 % -0418 % You should have received a copy of the GNU General Public License -0419 % along with this program. If not, see <https://www.gnu.org/licenses/>. +0405 % This program is distributed in the hope that it will be useful, +0406 % but WITHOUT ANY WARRANTY; without even the implied warranty of +0407 % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +0408 % GNU General Public License for more details. +0409 % +0410 % You should have received a copy of the GNU General Public License +0411 % along with this program. If not, see <https://www.gnu.org/licenses/>.
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/blochus/callbacks/menus/onMenuViewFigure.html b/doc/blochus/callbacks/menus/onMenuViewFigure.html index 1a16a7b..f6b3ed8 100644 --- a/doc/blochus/callbacks/menus/onMenuViewFigure.html +++ b/doc/blochus/callbacks/menus/onMenuViewFigure.html @@ -111,156 +111,218 @@

    SOURCE CODE ^% opening the export figure 0043 expfig = figure; 0044 -0045 % create the axes layout on the export figure -0046 switch get(src,'Label') -0047 case {'Current View','Magnetization','Switch-off Ramp'} -0048 % we copy all visible axes in a 2x2 grid -0049 ax1 = subplot(2,2,1,'Parent',expfig); -0050 ax2 = subplot(2,2,2,'Parent',expfig); -0051 ax3 = subplot(2,2,3,'Parent',expfig); -0052 ax4 = subplot(2,2,4,'Parent',expfig); -0053 -0054 case 'Pulse' -0055 % we copy pulse parameter in a 3x2 grid -0056 ax1 = subplot(3,2,1,'Parent',expfig); -0057 ax2 = subplot(3,2,2,'Parent',expfig); -0058 ax3 = subplot(3,2,[3 4],'Parent',expfig); -0059 ax4 = subplot(3,2,[5 6],'Parent',expfig); -0060 end -0061 % get the default positions -0062 pos1 = get(ax1,'Position'); -0063 pos2 = get(ax2,'Position'); -0064 pos3 = get(ax3,'Position'); -0065 pos4 = get(ax4,'Position'); -0066 % delete axes -0067 delete(ax1);delete(ax2);delete(ax3);delete(ax4); -0068 -0069 % copy the GUI axes to the export figure -0070 switch get(src,'Label') -0071 case 'Current View' -0072 mag = get(gui.panels.Plot.Mag,'Selection'); -0073 sph = get(gui.panels.Plot.Sphere,'Selection'); -0074 pre = get(gui.panels.Plot.PrePol,'Selection'); -0075 pul = get(gui.panels.Plot.Pulse,'Selection'); -0076 switch mag -0077 case 1 -0078 ax1 = copyobj(gui.axes_handles.MagL,expfig); -0079 case 2 -0080 ax1 = copyobj(gui.axes_handles.MagR,expfig); -0081 case 3 -0082 ax1 = copyobj(gui.axes_handles.MagFFT,expfig); -0083 end -0084 switch sph -0085 case 1 -0086 ax2 = copyobj(gui.axes_handles.SphereL,expfig); -0087 case 2 -0088 ax2 = copyobj(gui.axes_handles.SphereR,expfig); -0089 end -0090 switch pre -0091 case 1 -0092 ax3 = copyobj(gui.axes_handles.Bpre,expfig); -0093 case 2 -0094 ax3 = copyobj(gui.axes_handles.alpha,expfig); -0095 case 3 -0096 ax3 = copyobj(gui.axes_handles.dadt,expfig); -0097 case 4 -0098 ax3 = copyobj(gui.axes_handles.wda,expfig); -0099 end -0100 switch pul -0101 case 1 -0102 ax4 = copyobj(gui.axes_handles.PulseSetupF,expfig); -0103 case 2 -0104 ax4 = copyobj(gui.axes_handles.PulseB,expfig); -0105 case 3 -0106 ax4 = copyobj(gui.axes_handles.PulseFFT,expfig); -0107 end -0108 -0109 set(expfig,'Name','BLOCHUS: Current View'); -0110 -0111 case 'Magnetization' -0112 ax1 = copyobj(gui.axes_handles.MagL,expfig); -0113 ax2 = copyobj(gui.axes_handles.SphereL,expfig); -0114 ax3 = copyobj(gui.axes_handles.MagR,expfig); -0115 ax4 = copyobj(gui.axes_handles.SphereR,expfig); -0116 -0117 set(expfig,'Name','BLOCHUS: Magnetization'); -0118 -0119 case 'Switch-off Ramp' -0120 ax1 = copyobj(gui.axes_handles.Bpre,expfig); -0121 ax2 = copyobj(gui.axes_handles.alpha,expfig); -0122 ax3 = copyobj(gui.axes_handles.dadt,expfig); -0123 ax4 = copyobj(gui.axes_handles.wda,expfig); -0124 -0125 set(expfig,'Name','BLOCHUS: Switch-off Ramp'); -0126 -0127 case 'Pulse' -0128 ax1 = copyobj(gui.axes_handles.PulseSetupF,expfig); -0129 ax2 = copyobj(gui.axes_handles.PulseSetupI,expfig); -0130 ax3 = copyobj(gui.axes_handles.PulseB,expfig); -0131 ax4 = copyobj(gui.axes_handles.PulseFFT,expfig); -0132 -0133 set(expfig,'Name','BLOCHUS: Pulse'); -0134 end -0135 % adjust the axes positions -0136 set(ax1,'Position',pos1); -0137 set(ax2,'Position',pos2); -0138 set(ax3,'Position',pos3); -0139 set(ax4,'Position',pos4); -0140 -0141 % adjust the position of the export figure -0142 set(expfig,'Position',[posf(1)+300 posf(2) (posf(3)-300)*0.8 posf(4)*0.8]); -0143 -0144 % show legends -0145 switch get(src,'Label') -0146 case 'Current View' -0147 lgh1 = legend(ax1,'show'); -0148 lgh3 = legend(ax3,'show'); -0149 lgh4 = legend(ax4,'show'); +0045 % due to the two axes on the pulse modulation panel, we need to know +0046 % before creating the new figure if this panel is active +0047 isdual = false; +0048 if get(gui.panels.Plot.Pulse,'Selection') == 1 +0049 isdual = true; +0050 end +0051 +0052 % create the axes layout on the export figure and get the axes +0053 % positions +0054 switch get(src,'Label') +0055 case 'Current View' +0056 % we copy all visible axes in a 2x2 grid +0057 ax1 = subplot(2,2,1,'Parent',expfig); +0058 ax2 = subplot(2,2,2,'Parent',expfig); +0059 ax3 = subplot(2,2,3,'Parent',expfig); +0060 pos1 = get(ax1,'Position'); +0061 pos2 = get(ax2,'Position'); +0062 pos3 = get(ax3,'Position'); +0063 delete(ax1); +0064 delete(ax2); +0065 delete(ax3); +0066 if isdual +0067 ax4a = subplot(2,4,7,'Parent',expfig); +0068 ax4b = subplot(2,4,8,'Parent',expfig); +0069 pos4a = get(ax4a,'Position'); +0070 pos4b = get(ax4b,'Position'); +0071 delete(ax4a); +0072 delete(ax4b); +0073 else +0074 ax4 = subplot(2,2,4,'Parent',expfig); +0075 pos4 = get(ax4,'Position'); +0076 delete(ax4); +0077 end +0078 +0079 case {'Magnetization','Switch-off Ramp'} +0080 % we copy all visible axes in a 2x2 grid +0081 ax1 = subplot(2,2,1,'Parent',expfig); +0082 ax2 = subplot(2,2,2,'Parent',expfig); +0083 ax3 = subplot(2,2,3,'Parent',expfig); +0084 ax4 = subplot(2,2,4,'Parent',expfig); +0085 pos1 = get(ax1,'Position'); +0086 pos2 = get(ax2,'Position'); +0087 pos3 = get(ax3,'Position'); +0088 pos4 = get(ax4,'Position'); +0089 delete(ax1); +0090 delete(ax2); +0091 delete(ax3); +0092 delete(ax4); +0093 +0094 case 'Pulse' +0095 % we copy pulse parameter in a 3x2 grid +0096 ax1 = subplot(3,2,1,'Parent',expfig); +0097 ax2 = subplot(3,2,2,'Parent',expfig); +0098 ax3 = subplot(3,2,[3 4],'Parent',expfig); +0099 ax4 = subplot(3,2,[5 6],'Parent',expfig); +0100 pos1 = get(ax1,'Position'); +0101 pos2 = get(ax2,'Position'); +0102 pos3 = get(ax3,'Position'); +0103 pos4 = get(ax4,'Position'); +0104 delete(ax1); +0105 delete(ax2); +0106 delete(ax3); +0107 delete(ax4); +0108 end +0109 +0110 % copy the GUI axes to the export figure +0111 switch get(src,'Label') +0112 case 'Current View' +0113 mag = get(gui.panels.Plot.Mag,'Selection'); +0114 sph = get(gui.panels.Plot.Sphere,'Selection'); +0115 pre = get(gui.panels.Plot.PrePol,'Selection'); +0116 pul = get(gui.panels.Plot.Pulse,'Selection'); +0117 switch mag +0118 case 1 +0119 ax1 = copyobj(gui.axes_handles.MagL,expfig); +0120 case 2 +0121 ax1 = copyobj(gui.axes_handles.MagR,expfig); +0122 case 3 +0123 ax1 = copyobj(gui.axes_handles.MagFFT,expfig); +0124 end +0125 switch sph +0126 case 1 +0127 ax2 = copyobj(gui.axes_handles.SphereL,expfig); +0128 case 2 +0129 ax2 = copyobj(gui.axes_handles.SphereR,expfig); +0130 end +0131 switch pre +0132 case 1 +0133 ax3 = copyobj(gui.axes_handles.Bpre,expfig); +0134 case 2 +0135 ax3 = copyobj(gui.axes_handles.alpha,expfig); +0136 case 3 +0137 ax3 = copyobj(gui.axes_handles.dadt,expfig); +0138 case 4 +0139 ax3 = copyobj(gui.axes_handles.wda,expfig); +0140 end +0141 switch pul +0142 case 1 +0143 ax4a = copyobj(gui.axes_handles.PulseSetupF,expfig); +0144 ax4b = copyobj(gui.axes_handles.PulseSetupI,expfig); +0145 case 2 +0146 ax4 = copyobj(gui.axes_handles.PulseB,expfig); +0147 case 3 +0148 ax4 = copyobj(gui.axes_handles.PulseFFT,expfig); +0149 end 0150 -0151 case 'Magnetization' -0152 lgh1 = legend(ax1,'show'); -0153 lgh3 = legend(ax3,'show'); -0154 -0155 case 'Switch-off Ramp' -0156 lgh1 = legend(ax1,'show'); -0157 lgh2 = legend(ax2,'show'); -0158 lgh4 = legend(ax4,'show'); -0159 set(lgh4,'Interpreter','latex','Location','best'); +0151 set(expfig,'Name','BLOCHUS: Current View'); +0152 +0153 case 'Magnetization' +0154 ax1 = copyobj(gui.axes_handles.MagL,expfig); +0155 ax2 = copyobj(gui.axes_handles.SphereL,expfig); +0156 ax3 = copyobj(gui.axes_handles.MagR,expfig); +0157 ax4 = copyobj(gui.axes_handles.SphereR,expfig); +0158 +0159 set(expfig,'Name','BLOCHUS: Magnetization'); 0160 -0161 case 'Pulse' -0162 lgh1 = legend(ax1,'show'); -0163 lgh2 = legend(ax2,'show'); -0164 lgh3 = legend(ax3,'show'); -0165 lgh4 = legend(ax4,'show'); -0166 end -0167 -0168 else -0169 warndlg({'onMenuViewFigure:','There is no figure with the BLOCHUS Tag open.'},... -0170 'BLOCHUS error'); -0171 end -0172 -0173 end -0174 -0175 %------------- END OF CODE -------------- -0176 -0177 %% License: -0178 % GNU GPLv3 -0179 % -0180 % BLOCHUS -0181 % Copyright (C) 2019 Thomas Hiller -0182 % -0183 % This program is free software: you can redistribute it and/or modify -0184 % it under the terms of the GNU General Public License as published by -0185 % the Free Software Foundation, either version 3 of the License, or -0186 % (at your option) any later version. -0187 % -0188 % This program is distributed in the hope that it will be useful, -0189 % but WITHOUT ANY WARRANTY; without even the implied warranty of -0190 % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -0191 % GNU General Public License for more details. -0192 % -0193 % You should have received a copy of the GNU General Public License -0194 % along with this program. If not, see <https://www.gnu.org/licenses/>. +0161 case 'Switch-off Ramp' +0162 ax1 = copyobj(gui.axes_handles.Bpre,expfig); +0163 ax2 = copyobj(gui.axes_handles.alpha,expfig); +0164 ax3 = copyobj(gui.axes_handles.dadt,expfig); +0165 ax4 = copyobj(gui.axes_handles.wda,expfig); +0166 +0167 set(expfig,'Name','BLOCHUS: Switch-off Ramp'); +0168 +0169 case 'Pulse' +0170 ax1 = copyobj(gui.axes_handles.PulseSetupF,expfig); +0171 ax2 = copyobj(gui.axes_handles.PulseSetupI,expfig); +0172 ax3 = copyobj(gui.axes_handles.PulseB,expfig); +0173 ax4 = copyobj(gui.axes_handles.PulseFFT,expfig); +0174 +0175 set(expfig,'Name','BLOCHUS: Pulse'); +0176 end +0177 +0178 % adjust the axes positions +0179 switch get(src,'Label') +0180 case 'Current View' +0181 set(ax1,'Position',pos1); +0182 set(ax2,'Position',pos2); +0183 set(ax3,'Position',pos3); +0184 if isdual +0185 set(ax4a,'Position',pos4a); +0186 set(ax4b,'Position',pos4b); +0187 else +0188 set(ax4,'Position',pos4); +0189 end +0190 +0191 otherwise +0192 set(ax1,'Position',pos1); +0193 set(ax2,'Position',pos2); +0194 set(ax3,'Position',pos3); +0195 set(ax4,'Position',pos4); +0196 end +0197 +0198 % adjust the position of the export figure +0199 set(expfig,'Position',[posf(1)+300 posf(2) (posf(3)-300)*0.8 posf(4)*0.8]); +0200 +0201 % show legends +0202 switch get(src,'Label') +0203 case 'Current View' +0204 lgh1 = legend(ax1,'show'); +0205 lgh3 = legend(ax3,'show'); +0206 if isdual +0207 lgh4a = legend(ax4a,'show'); +0208 lgh4b = legend(ax4b,'show'); +0209 else +0210 lgh4 = legend(ax4,'show'); +0211 end +0212 +0213 case 'Magnetization' +0214 lgh1 = legend(ax1,'show'); +0215 lgh3 = legend(ax3,'show'); +0216 +0217 case 'Switch-off Ramp' +0218 lgh1 = legend(ax1,'show'); +0219 lgh2 = legend(ax2,'show'); +0220 lgh4 = legend(ax4,'show'); +0221 set(lgh4,'Interpreter','latex','Location','best'); +0222 +0223 case 'Pulse' +0224 lgh1 = legend(ax1,'show'); +0225 lgh2 = legend(ax2,'show'); +0226 lgh3 = legend(ax3,'show'); +0227 lgh4 = legend(ax4,'show'); +0228 end +0229 +0230 else +0231 warndlg({'onMenuViewFigure:','There is no figure with the BLOCHUS Tag open.'},... +0232 'BLOCHUS error'); +0233 end +0234 +0235 end +0236 +0237 %------------- END OF CODE -------------- +0238 +0239 %% License: +0240 % GNU GPLv3 +0241 % +0242 % BLOCHUS +0243 % Copyright (C) 2019 Thomas Hiller +0244 % +0245 % This program is free software: you can redistribute it and/or modify +0246 % it under the terms of the GNU General Public License as published by +0247 % the Free Software Foundation, either version 3 of the License, or +0248 % (at your option) any later version. +0249 % +0250 % This program is distributed in the hope that it will be useful, +0251 % but WITHOUT ANY WARRANTY; without even the implied warranty of +0252 % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +0253 % GNU General Public License for more details. +0254 % +0255 % You should have received a copy of the GNU General Public License +0256 % along with this program. If not, see <https://www.gnu.org/licenses/>.
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/blochus/callbacks/popup/onPopupPulseAxis.html b/doc/blochus/callbacks/popup/onPopupPulseAxis.html index 73f3d1b..4a28444 100644 --- a/doc/blochus/callbacks/popup/onPopupPulseAxis.html +++ b/doc/blochus/callbacks/popup/onPopupPulseAxis.html @@ -42,7 +42,7 @@

    DESCRIPTION ^DESCRIPTION ^CROSS-REFERENCE INFORMATION ^

    This function calls: +
  • getPulseParameters updates all relevant pulse settings
  • plotPulse plots different pulse parameter
  • This function is called by: @@ -85,7 +85,7 @@

    SOURCE CODE ^% 0016 % Other m-files required: 0017 % getPulseParameters -0018 % plotBpulse +0018 % plotPulse 0019 % 0020 % Subfunctions: 0021 % none @@ -130,7 +130,7 @@

    SOURCE CODE ^% get GUI data 0061 data = getappdata(fig,'data'); 0062 % plot pulse -0063 plotBpulse(gui.figh); +0063 plotPulse(gui.figh); 0064 0065 else 0066 warndlg({'onPopupPulseAxis:','There is no figure with the BLOCHUS Tag open.'},... diff --git a/doc/blochus/callbacks/popup/onPopupPulseDFmode.html b/doc/blochus/callbacks/popup/onPopupPulseDFmode.html index 91e46e2..dd31982 100644 --- a/doc/blochus/callbacks/popup/onPopupPulseDFmode.html +++ b/doc/blochus/callbacks/popup/onPopupPulseDFmode.html @@ -59,7 +59,7 @@

    DESCRIPTION ^CROSS-REFERENCE INFORMATION ^

    This function calls: +
  • getPulseParameters updates all relevant pulse settings
  • plotPulse plots different pulse parameter
  • This function is called by: @@ -153,7 +153,7 @@

    SOURCE CODE ^% update GUI data 0084 setappdata(fig,'data',data); 0085 % plot pulse -0086 plotBpulse(gui.figh); +0086 plotPulse(gui.figh); 0087 0088 else 0089 warndlg({'onPopupPulseDFmode:','There is no figure with the BLOCHUS Tag open.'},... diff --git a/doc/blochus/callbacks/popup/onPopupPulseImode.html b/doc/blochus/callbacks/popup/onPopupPulseImode.html index 22a29ee..99e93de 100644 --- a/doc/blochus/callbacks/popup/onPopupPulseImode.html +++ b/doc/blochus/callbacks/popup/onPopupPulseImode.html @@ -59,7 +59,7 @@

    DESCRIPTION ^CROSS-REFERENCE INFORMATION ^

    This function calls: +
  • getPulseParameters updates all relevant pulse settings
  • plotPulse plots different pulse parameter
  • This function is called by: @@ -155,7 +155,7 @@

    SOURCE CODE ^% update GUI data 0086 setappdata(fig,'data',data); 0087 % plot pulse -0088 plotBpulse(gui.figh); +0088 plotPulse(gui.figh); 0089 0090 else 0091 warndlg({'onPopupPulseDFmode:','There is no figure with the BLOCHUS Tag open.'},... diff --git a/doc/blochus/callbacks/popup/onPopupPulsePolarization.html b/doc/blochus/callbacks/popup/onPopupPulsePolarization.html index a1b5e12..75219be 100644 --- a/doc/blochus/callbacks/popup/onPopupPulsePolarization.html +++ b/doc/blochus/callbacks/popup/onPopupPulsePolarization.html @@ -59,7 +59,7 @@

    DESCRIPTION ^CROSS-REFERENCE INFORMATION ^

    This function calls: +
  • getPulseParameters updates all relevant pulse settings
  • plotPulse plots different pulse parameter
  • This function is called by: @@ -128,7 +128,7 @@

    SOURCE CODE ^% update GUI data 0059 setappdata(fig,'data',data); 0060 % plot pulse -0061 plotBpulse(gui.figh); +0061 plotPulse(gui.figh); 0062 0063 else 0064 warndlg({'onPopupPulsePolarization:','There is no figure with the BLOCHUS Tag open.'},... diff --git a/doc/blochus/callbacks/popup/onPopupPulseType.html b/doc/blochus/callbacks/popup/onPopupPulseType.html index 480e5be..d39daaf 100644 --- a/doc/blochus/callbacks/popup/onPopupPulseType.html +++ b/doc/blochus/callbacks/popup/onPopupPulseType.html @@ -59,7 +59,7 @@

    DESCRIPTION ^CROSS-REFERENCE INFORMATION ^

    This function calls: +
  • onEditValue updates all edit field values, checks for wrong inputs and
  • onPopupPulseDFmode selects the frequency modulation for an adiabatic pulse
  • onPopupPulseImode selects the current modulation for an adiabatic pulse
  • getPulseParameters updates all relevant pulse settings
  • plotPulse plots different pulse parameter
  • updateStatusInformation updates all fields inside the bottom status bar
  • This function is called by: @@ -296,7 +296,7 @@

    SOURCE CODE ^% update GUI data 0227 setappdata(fig,'data',data); 0228 % plot pulse -0229 plotBpulse(fig); +0229 plotPulse(fig); 0230 % update status bar 0231 updateStatusInformation(fig); 0232 else diff --git a/doc/blochus/callbacks/push/menu.html b/doc/blochus/callbacks/push/menu.html index 561abd1..a9987d0 100644 --- a/doc/blochus/callbacks/push/menu.html +++ b/doc/blochus/callbacks/push/menu.html @@ -18,7 +18,7 @@

    Index for blochus\callbacks\push

    Matlab files in this directory:

    +
  • onPushAnimate
  • onPushAxView
  • onPushGrid
  • onPushRun
  • diff --git a/doc/blochus/callbacks/push/onPushAnimate.html b/doc/blochus/callbacks/push/onPushAnimate.html index 3e10666..3a5c9d0 100644 --- a/doc/blochus/callbacks/push/onPushAnimate.html +++ b/doc/blochus/callbacks/push/onPushAnimate.html @@ -4,7 +4,7 @@ Description of onPushAnimate - + @@ -20,19 +20,49 @@

    onPushAnimate

    PURPOSE ^

    -
    +
    animates the results of the latest simulation

    SYNOPSIS ^

    function onPushAnimate(src,~)

    DESCRIPTION ^

    -
    +
    onPushAnimate animates the results of the latest simulation
    +
    + Syntax:
    +       onPushAnimate(src)
    +
    + Inputs:
    +       src - handle of the calling object
    +
    + Outputs:
    +       none
    +
    + Example:
    +       onPushAnimate(src)
    +
    + Other m-files required:
    +       clearSingleAxis
    +       plotBSphere
    +       plotPulse
    +       plotRamp
    +       plotResults
    +
    + Subfunctions:
    +       none
    +
    + MAT-files required:
    +       none
    +
    + See also: BLOCHUS
    + Author: Thomas Hiller
    + email: thomas.hiller[at]leibniz-liag.de
    + License: GNU GPLv3 (at end)

    CROSS-REFERENCE INFORMATION ^

    This function calls:
      -
    • plotBSphere plots a (Bloch)-Sphere (basically a unit sphere) with
    • plotResults plots results depending on the chosen settings
    +
  • clearSingleAxis clears an individual axis
  • plotBSphere plots a (Bloch)-Sphere (basically a unit sphere) with
  • plotPulse plots different pulse parameter
  • plotRamp plots different pre-polarization switch-off ramp parameter
  • plotResults plots results depending on the chosen settings
  • This function is called by: @@ -42,269 +72,834 @@

    CROSS-REFERENCE INFORMATION ^
 
 <h2><a name=SOURCE CODE ^

    0001 function onPushAnimate(src,~)
    -0002 fig  = findobj('Tag','BLOCHUS');
    -0003 gui  = getappdata(fig,'gui');
    -0004 data = getappdata(fig,'data');
    -0005 
    -0006 % change the pushbutton color to indicate that an animation is running
    -0007 set(src,'BackGroundColor','r');
    -0008 pause(0.01);
    -0009 
    -0010 NoFrames = 100;
    -0011 FPS = 24;
    -0012 
    -0013 newblue = [0 0.4470 0.7410];
    -0014 neworange = [0.8500 0.3250 0.0980];
    -0015 
    -0016 switch data.basic.type
    -0017     
    -0018     case 'std'
    -0019         set(gui.text_handles.Status,'String','Animation running ...');
    -0020         pause(0.01);
    -0021         Mamp = zeros(numel(data.TT),1);
    -0022         for i=1:numel(data.TT)
    -0023             Mamp(i,1) = norm(data.MM(i,:)); % amplitude of M
    -0024         end
    -0025         
    -0026         dt = data.TT(end)/NoFrames;
    -0027         time = 0:dt:data.TT(end);
    -0028         
    -0029         axes(gui.axes_handles.MagL);
    -0030         cla(gui.axes_handles.MagL);
    -0031         h1 = animatedline('Color','r','LineWidth',2,'Parent',gui.axXYZL);
    -0032         h2 = animatedline('Color','g','LineWidth',2,'Parent',gui.axXYZL);
    -0033         h3 = animatedline('Color','b','LineWidth',2,'Parent',gui.axXYZL);
    -0034         h4 = animatedline('Color','k','LineWidth',2,'LineStyle','--','Parent',gui.axXYZL);
    -0035         
    -0036         axes(gui.axes_handles.MagR);
    -0037         cla(gui.axes_handles.MagR);
    -0038         h7 = animatedline('Color','r','LineWidth',2,'Parent',gui.axXYZR);
    -0039         h8 = animatedline('Color','g','LineWidth',2,'Parent',gui.axXYZR);
    -0040         h9 = animatedline('Color','b','LineWidth',2,'Parent',gui.axXYZR);
    -0041         h10 = animatedline('Color','k','LineWidth',2,'LineStyle','--','Parent',gui.axXYZR);
    -0042         
    -0043         axes(gui.axSphereL);
    -0044         cla(gui.axSphereL);
    -0045         hold(gui.axSphereL,'on');
    -0046         plotBSphere(18,18,gui.axSphereL);
    -0047         h5 = animatedline('Color',myui.color.basic,'LineWidth',2,'Parent',gui.axSphereL);
    -0048         
    -0049         axes(gui.axSphereR);
    -0050         cla(gui.axSphereR);
    -0051         hold(gui.axSphereR,'on');
    -0052         plotBSphere(18,18,gui.axSphereR); 
    -0053         h6 = animatedline('Color',myui.color.basic,'LineWidth',2,'Parent',gui.axSphereR);
    -0054         
    -0055         for nf = 1:NoFrames-1
    -0056             
    -0057             x1 = data.TT(data.TT>=time(nf) & data.TT<time(nf+1)).*1e3;
    -0058             y1 = data.MM(data.TT>=time(nf) & data.TT<time(nf+1),1);
    -0059             y2 = data.MM(data.TT>=time(nf) & data.TT<time(nf+1),2);
    -0060             y3 = data.MM(data.TT>=time(nf) & data.TT<time(nf+1),3);
    -0061             y1R = data.MMrot(data.TT>=time(nf) & data.TT<time(nf+1),1);
    -0062             y2R = data.MMrot(data.TT>=time(nf) & data.TT<time(nf+1),2);
    -0063             y3R = data.MMrot(data.TT>=time(nf) & data.TT<time(nf+1),3);
    -0064             y4 = Mamp(data.TT>=time(nf) & data.TT<time(nf+1))./Mamp(1);
    -0065             addpoints(h1,x1,y1);
    -0066             addpoints(h2,x1,y2);
    -0067             addpoints(h3,x1,y3);
    -0068             addpoints(h4,x1,y4);
    -0069             
    -0070             legend(gui.axes_handles.MagL,'M_x','M_y','M_z','Location','SouthEast');
    -0071             set(gui.axes_handles.MagL,'XLim',[min(data.TT.*1e3) max(data.TT.*1e3)],...
    -0072                 'XTick',linspace(min(data.TT.*1e3),max(data.TT.*1e3),5))
    -0073             set(get(gui.axes_handles.MagL,'XLabel'),'String','t [ms]');
    -0074             set(get(gui.axes_handles.MagL,'YLabel'),'String','M');
    -0075             set(get(gui.axes_handles.MagL,'Title'),'String','magnetization components - lab frame');
    -0076             
    -0077             
    -0078             addpoints(h7,x1,y1R);
    -0079             addpoints(h8,x1,y2R);
    -0080             addpoints(h9,x1,y3R);
    -0081             addpoints(h10,x1,y4);
    -0082             
    -0083             legend(gui.axes_handles.MagR,'M_x','M_y','M_z','Location','SouthEast');
    -0084             set(gui.axXYZR,'XLim',[min(data.TT.*1e3) max(data.TT.*1e3)],...
    -0085                 'XTick',linspace(min(data.TT.*1e3),max(data.TT.*1e3),5))
    -0086             set(get(gui.axes_handles.MagR,'XLabel'),'String','t [ms]');
    -0087             set(get(gui.axes_handles.MagR,'YLabel'),'String','M');
    -0088             set(get(gui.axes_handles.MagR,'Title'),'String','magnetization components - rot frame');
    -0089             
    -0090             addpoints(h5,y1,y2,y3);
    -0091             view([134 30]);
    -0092             set(gui.axSphereL,'Color','w','XColor','none','YColor','none','ZColor','none');
    -0093             axis equal tight
    -0094             
    -0095             addpoints(h6,y1R,y2R,y3R);
    -0096             set(gui.axSphereR,'Color','w','XColor','none','YColor','none','ZColor','none');
    -0097             axis equal tight
    -0098             
    -0099             pause(1/FPS);
    -0100         end
    -0101         hold(gui.axes_handles.MagL,'off');
    -0102         hold(gui.axes_handles.MagR,'off');
    -0103         hold(gui.axSphereL,'off');
    -0104         hold(gui.axSphereR,'off');
    -0105         set(gui.text_handles.Status,'String','Animation running ... done.');
    -0106         pause(0.01);
    -0107         
    -0108     case 'prepol'
    -0109         set(gui.text_handles.Status,'String','Animation running ...');
    -0110         pause(0.01);
    -0111         Mamp = zeros(numel(data.TT),1);
    -0112         MM = zeros(numel(data.TT),3);
    -0113         for i=1:numel(data.TT)
    -0114             Mamp(i,1) = norm(data.MM(i,:)); % amplitude of M
    -0115             MM(i,:) = data.MM(i,:)./Mamp(1); % normalize to initial M
    -0116         end
    -0117         Beffn = zeros(numel(data.results.prepol.t),3);
    -0118         for i=1:numel(data.results.prepol.t)
    -0119             Beffn(i,:) = data.results.prepol.Beff(i,:)./norm(data.results.prepol.Beff(i,:));
    -0120         end
    -0121         
    -0122         dt = data.TT(end)/NoFrames;
    -0123         time = 0:dt:data.TT(end);
    -0124         
    -0125         cla(gui.axXYZL);
    -0126         axes(gui.axXYZL);
    -0127         h1 = animatedline('Color','r','LineWidth',2,'Parent',gui.axXYZL);
    -0128         h2 = animatedline('Color','g','LineWidth',2,'Parent',gui.axXYZL);
    -0129         h3 = animatedline('Color','b','LineWidth',2,'Parent',gui.axXYZL);
    -0130         h4 = animatedline('Color','k','LineWidth',2,'LineStyle','--','Parent',gui.axXYZL);
    -0131         if data.prepol.Tramp < data.basic.Tsim
    -0132             h11 = animatedline('Color',[0.8 0.8 0.8],'LineWidth',1,'Parent',gui.axXYZL);
    -0133         end
    -0134         
    -0135         cla(gui.axSphereL);
    -0136         axes(gui.axSphereL);
    -0137         plotBlochSphere(30,30); hold on;
    -0138         h5a = animatedline('Color',myui.color.prepol,'LineWidth',2,'Parent',gui.axSphereL);
    -0139         h5b = animatedline('Color',myui.color.basic,'LineWidth',2,'Parent',gui.axSphereL);
    -0140         h6 = animatedline('Color',myui.color.prepolB,'LineWidth',2,'Parent',gui.axSphereL);
    -0141         
    -0142         cla(gui.axBpre);
    -0143         axes(gui.axBpre);
    -0144         h10 = animatedline('Color',myui.color.prepolB,'LineWidth',2,'Parent',gui.axBpre);
    -0145         y10a = data.results.prepol.Bp./data.basic.B0;
    -0146         
    -0147         cla(gui.axalpha);
    -0148         axes(gui.axalpha);
    -0149         h7 = animatedline('Color',myui.color.prepolB,'LineWidth',2,'Parent',gui.axalpha);
    -0150         
    -0151         cla(gui.axes_handles.dadt);
    -0152         axes(gui.axes_handles.dadt);
    -0153         h8 = animatedline('Color',myui.color.prepolB,'LineWidth',2,'Parent',gui.axes_handles.dadt);
    -0154         y8a = data.results.prepol.dadt;
    -0155         tt = data.results.prepol.t(1:end-1);
    -0156         
    -0157         cla(gui.axes_handles.wda);
    -0158         axes(gui.axes_handles.wda);
    -0159         h9 = animatedline('Color',myui.color.prepolB,'LineWidth',2,'Parent',gui.axes_handles.wda);
    -0160         y9a = data.results.prepol.omega(1:numel(data.results.prepol.dadt))./data.results.prepol.dadt;
    -0161         
    -0162         for nf = 1:NoFrames-1
    -0163             
    -0164             x1 = data.TT(data.TT>=time(nf) & data.TT<time(nf+1)).*1e3;
    -0165             y1 = MM(data.TT>=time(nf) & data.TT<time(nf+1),1);
    -0166             y2 = MM(data.TT>=time(nf) & data.TT<time(nf+1),2);
    -0167             y3 = MM(data.TT>=time(nf) & data.TT<time(nf+1),3);
    -0168             
    -0169             if time(nf)<data.prepol.Tramp/1e3
    -0170                 y1a = MM(data.TT>=time(nf) & data.TT<time(nf+1),1);
    -0171                 y2a = MM(data.TT>=time(nf) & data.TT<time(nf+1),2);
    -0172                 y3a = MM(data.TT>=time(nf) & data.TT<time(nf+1),3);
    -0173             else
    -0174                 y1b = MM(data.TT>=time(nf) & data.TT<time(nf+1),1);
    -0175                 y2b = MM(data.TT>=time(nf) & data.TT<time(nf+1),2);
    -0176                 y3b = MM(data.TT>=time(nf) & data.TT<time(nf+1),3);
    -0177             end
    -0178             
    -0179             y4 = Mamp(data.TT>=time(nf) & data.TT<time(nf+1))./Mamp(1);
    -0180             addpoints(h1,x1,y1);
    -0181             addpoints(h2,x1,y2);
    -0182             addpoints(h3,x1,y3);
    -0183             addpoints(h4,x1,y4);
    -0184             if data.prepol.Tramp < data.basic.Tsim
    -0185                 addpoints(h11,[data.prepol.Tramp data.prepol.Tramp],[min(min(MM)) max(max(MM))]);
    -0186             end
    -0187             
    -0188             legend(gui.axXYZL,'M_x','M_y','M_z','Location','SouthEast');
    -0189             set(gui.axXYZL,'XLim',[min(data.TT.*1e3) max(data.TT.*1e3)],...
    -0190                 'XTick',linspace(min(data.TT.*1e3),max(data.TT.*1e3),5),...
    -0191                 'YLim',[min(min(MM)) max(max(MM))])
    -0192             set(get(gui.axXYZL,'XLabel'),'String','t [ms]');
    -0193             set(get(gui.axXYZL,'YLabel'),'String','M');
    -0194             set(get(gui.axXYZL,'Title'),'String',['projection M \rightarrow B_0 p = ',sprintf('%4.3f',data.results.prepol.p)]);
    -0195             
    -0196             y6(:,1) = Beffn(data.results.prepol.t./1e3>=time(nf) & data.results.prepol.t./1e3<time(nf+1),1);
    -0197             y6(:,2) = Beffn(data.results.prepol.t./1e3>=time(nf) & data.results.prepol.t./1e3<time(nf+1),2);
    -0198             y6(:,3) = Beffn(data.results.prepol.t./1e3>=time(nf) & data.results.prepol.t./1e3<time(nf+1),3);
    -0199             if time(nf)<data.prepol.Tramp/1e3
    -0200                 addpoints(h5a,y1a,y2a,y3a);
    -0201             else
    -0202                 addpoints(h5b,y1b,y2b,y3b);
    -0203             end
    -0204             addpoints(h6,y6(:,1),y6(:,2),y6(:,3));
    -0205             set(gui.axSphereL,'XGrid','on','YGrid','on','ZGrid','on','Box','on');
    -0206             axis(gui.axSphereL,'equal','tight'); view(3);
    -0207             set(get(gui.axSphereL,'XLabel'),'String','X');
    -0208             set(get(gui.axSphereL,'YLabel'),'String','Y');
    -0209             set(get(gui.axSphereL,'ZLabel'),'String','Z');
    -0210             set(get(gui.axSphereL,'Title'),'String','"Bloch sphere"');
    -0211             
    -0212             if data.results.prepol.t(end)/1e3 >= time(nf)
    -0213                 x2 = data.results.prepol.t(data.results.prepol.t./1e3>=time(nf) & data.results.prepol.t./1e3<time(nf+1));
    -0214                 x3 = tt(tt./1e3>=time(nf) & tt./1e3<time(nf+1));
    -0215                 
    -0216                 y10 = y10a(data.results.prepol.t./1e3>=time(nf) & data.results.prepol.t./1e3<time(nf+1));
    -0217                 addpoints(h10,x2,y10);
    -0218                 set(gui.axBpre,'XLim',[min(data.results.prepol.t) max(data.results.prepol.t)],'YLim',[0 data.prepol.Factor]);
    -0219                 set(get(gui.axBpre,'XLabel'),'String','t [ms]');
    -0220                 set(get(gui.axBpre,'YLabel'),'String','B_{pre} [B_0]');
    -0221                 set(get(gui.axBpre,'Title'),'String','B_{pre} switch-off ramp');
    -0222                 
    -0223                 y7 = data.results.prepol.alpha(data.results.prepol.t./1e3>=time(nf) & data.results.prepol.t./1e3<time(nf+1));
    -0224                 addpoints(h7,x2,y7);
    -0225                 set(gui.axalpha,'XLim',[min(data.results.prepol.t) max(data.results.prepol.t)],'YLim',[min(data.results.prepol.alpha) max(data.results.prepol.alpha)]);
    -0226                 set(get(gui.axalpha,'XLabel'),'String','t [ms]');
    -0227                 set(get(gui.axalpha,'YLabel'),'String','\alpha [deg]');
    -0228                 set(get(gui.axalpha,'Title'),'String','angle \alpha between B_0 and B_{eff}');
    -0229                 
    -0230                 y8 = y8a(tt./1e3>=time(nf) & tt./1e3<time(nf+1));
    -0231                 addpoints(h8,x3,y8);
    -0232                 set(gui.axes_handles.dadt,'XLim',[min(data.results.prepol.t) max(data.results.prepol.t)],'YLim',[min(data.results.prepol.dadt) max(data.results.prepol.dadt)]);
    -0233                 set(get(gui.axes_handles.dadt,'XLabel'),'String','t [ms]');
    -0234                 set(get(gui.axes_handles.dadt,'YLabel'),'String','d\alpha / dt');
    -0235                 set(get(gui.axes_handles.dadt,'Title'),'String','time derivative of \alpha');
    -0236                 
    -0237                 y9 = y9a(tt./1e3>=time(nf) & tt./1e3<time(nf+1));
    -0238                 addpoints(h9,x3,y9);
    -0239                 set(gui.axes_handles.wda,'XLim',[min(data.results.prepol.t) max(data.results.prepol.t)],'YScale','log','YLim',[min(y9a) max(y9a)]);
    -0240                 set(get(gui.axes_handles.wda,'XLabel'),'String','t [ms]');
    -0241                 set(get(gui.axes_handles.wda,'YLabel'),'String','\omega / d\alpha');
    -0242                 set(get(gui.axes_handles.wda,'Title'),'String','adiabatic criterion(?)');
    -0243             end
    -0244             clear y1 y2 y3 y4 y6 y7 y8 y9
    -0245             pause(1/FPS);
    -0246         end
    -0247         hold(gui.axXYZL,'off');
    -0248         hold(gui.axSphereL,'off');
    -0249         set(gui.text_handles.Status,'String','Animation running ... done.');
    -0250         pause(0.01);
    -0251         
    -0252     case 'pulse'
    -0253         mgh = msgbox('Not yet implemented.','BLOCHUS info');
    -0254         
    -0255     case 'prepolpulse'
    -0256         mgh = msgbox('Not yet implemented.','BLOCHUS info');
    -0257 end
    -0258 
    -0259 
    -0260 % change the pushbutton color back to green
    -0261 % set(src,'BackGroundColor','g');
    -0262 set(src,'BackGroundColor',[.94 .94 .94]);
    -0263 plotResults(fig);
    -0264 end % onPushAnimate
    +0002 %onPushAnimate animates the results of the latest simulation +0003 % +0004 % Syntax: +0005 % onPushAnimate(src) +0006 % +0007 % Inputs: +0008 % src - handle of the calling object +0009 % +0010 % Outputs: +0011 % none +0012 % +0013 % Example: +0014 % onPushAnimate(src) +0015 % +0016 % Other m-files required: +0017 % clearSingleAxis +0018 % plotBSphere +0019 % plotPulse +0020 % plotRamp +0021 % plotResults +0022 % +0023 % Subfunctions: +0024 % none +0025 % +0026 % MAT-files required: +0027 % none +0028 % +0029 % See also: BLOCHUS +0030 % Author: Thomas Hiller +0031 % email: thomas.hiller[at]leibniz-liag.de +0032 % License: GNU GPLv3 (at end) +0033 +0034 %------------- BEGIN CODE -------------- +0035 +0036 % get GUI handle +0037 fig = ancestor(src,'figure','toplevel'); +0038 +0039 if ~isempty(fig) && strcmp(get(fig,'Tag'),'BLOCHUS') +0040 % get GUI data +0041 gui = getappdata(fig,'gui'); +0042 data = getappdata(fig,'data'); +0043 myui = gui.myui; +0044 +0045 % change the pushbutton color to indicate that an animation is running +0046 set(src,'BackGroundColor','r'); +0047 % update the status info +0048 set(gui.text_handles.Status,'String','Animation running ...'); +0049 pause(0.01); +0050 +0051 % ask the user for the number of frames to show +0052 % default is 100 +0053 prompt = {'\fontsize{9} Number of frames (default is 100):'}; +0054 title = 'Number of Frames'; +0055 dims = [1 50]; +0056 definput = {'100'}; +0057 opts.Interpreter = 'tex'; +0058 answer = inputdlg(prompt,title,dims,definput); +0059 if ~isempty(answer) +0060 NoFrames = str2double(answer{1}); +0061 if isnan(NoFrames) || NoFrames<1 +0062 NoFrames = 100; +0063 end +0064 else +0065 NoFrames = 100; +0066 end +0067 +0068 switch data.basic.type +0069 case 'std' +0070 % the two important timings +0071 Tsim = data.basic.Tsim; +0072 +0073 % get the data to animate +0074 T = data.results.basic.T.*1e3; +0075 M = data.results.basic.M; +0076 Mrot = data.results.basic.Mrot; +0077 Mxy = sqrt(M(:,1).^2+M(:,2).^2); +0078 Mamp = sqrt(M(:,1).^2+M(:,2).^2+M(:,3).^2); +0079 +0080 % get the visible magnetization axis and data +0081 switch get(gui.panels.Plot.Mag,'Selection') +0082 case 1 +0083 ax1 = gui.axes_handles.MagL; +0084 M1 = M; +0085 case 2 +0086 ax1 = gui.axes_handles.MagR; +0087 M1 = Mrot; +0088 case 3 +0089 ax1 = gui.axes_handles.MagL; +0090 % auto set FFT to lab frame +0091 set(gui.panels.Plot.Mag,'Selection',1) +0092 end +0093 Mylim = get(ax1,'YLim'); +0094 % get the visible Bloch sphere axis and data +0095 switch get(gui.panels.Plot.Sphere,'Selection') +0096 case 1 +0097 ax2 = gui.axes_handles.SphereL; +0098 M2 = M; +0099 case 2 +0100 ax2 = gui.axes_handles.SphereR; +0101 M2 = Mrot; +0102 end +0103 Mview = get(ax2,'View'); +0104 +0105 % time vector +0106 t = linspace(0,Tsim,NoFrames); +0107 +0108 % initialize all axes and animation lines +0109 axes(ax1); +0110 cla(ax1); +0111 hMx = animatedline('Color','r','LineWidth',2,'Parent',ax1); +0112 hMy = animatedline('Color','g','LineWidth',2,'Parent',ax1); +0113 hMz = animatedline('Color','b','LineWidth',2,'Parent',ax1); +0114 hMxy = animatedline('Color','m','LineWidth',2,'Parent',ax1); +0115 hMn = animatedline('Color','k','LineWidth',2,'LineStyle','--','Parent',ax1); +0116 set(get(ax1,'XLabel'),'String','t [ms]'); +0117 set(get(ax1,'YLabel'),'String','magnetization M'); +0118 grid(ax1,'on'); +0119 set(ax1,'FontSize',myui.axfontsize); +0120 +0121 axes(ax2); +0122 cla(ax2); +0123 hold(ax2,'on'); +0124 plotBSphere(18,18,ax2); +0125 h3dM = animatedline('Color',myui.color.basic,'LineWidth',2,'Parent',ax2); +0126 +0127 % loop over the data +0128 for nf = 1:NoFrames-1 +0129 +0130 % get the index vector of the current data to plot +0131 indt = T>=t(nf) & T<t(nf+1); +0132 % current time vector +0133 x = T(indt); +0134 +0135 % get data to plot for M +0136 % left panel +0137 yMx = M1(indt,1); +0138 yMy = M1(indt,2); +0139 yMz = M1(indt,3); +0140 yMxy = Mxy(indt,1); +0141 yMn = Mamp(indt,1); +0142 +0143 % plot data into axes +0144 addpoints(hMx,x,yMx); +0145 addpoints(hMy,x,yMy); +0146 addpoints(hMz,x,yMz); +0147 addpoints(hMxy,x,yMxy); +0148 addpoints(hMn,x,yMn); +0149 +0150 legend(ax1,'x','M','z','Location','SouthWest'); +0151 set(ax1,'XLim',[min(T) max(T)],'YLim',Mylim); +0152 lh = legend(ax1,'x','y','z','|xy|','|M|','Location','SouthWest'); +0153 +0154 % Bloch sphere +0155 yMxx = M2(indt,1); +0156 yMyy = M2(indt,2); +0157 yMzz = M2(indt,3); +0158 +0159 addpoints(h3dM,yMxx,yMyy,yMzz); +0160 view(ax2,Mview); +0161 set(ax2,'Color','w','XColor','none','YColor','none','ZColor','none'); +0162 axis(ax2,'equal'); +0163 axis(ax2,'tight'); +0164 +0165 % pause a bit to show the animation +0166 % drawnow limitrate works also but is a bit too fast +0167 pause(1/24); +0168 % drawnow limitrate; +0169 end +0170 hold(ax1,'off'); +0171 hold(ax2,'off'); +0172 +0173 case 'prepol' +0174 % get the results data +0175 basic = data.results.basic; +0176 prepol = data.results.prepol; +0177 +0178 % the two important timings +0179 Tsim = data.basic.Tsim; +0180 Tramp = data.prepol.Tramp; +0181 +0182 % get the data to animate +0183 T1 = basic.T.*1e3; +0184 M = basic.M; +0185 Mxy = sqrt(M(:,1).^2+M(:,2).^2); +0186 Mamp = sqrt(M(:,1).^2+M(:,2).^2+M(:,3).^2); +0187 M = M./data.basic.B0; +0188 Mxy = Mxy./data.basic.B0; +0189 Mamp = Mamp./data.basic.B0; +0190 % switch-off B-field trajectory +0191 Bamp = sqrt(prepol.Beff(:,1).^2+prepol.Beff(:,2).^2+prepol.Beff(:,3).^2); +0192 Beffn = prepol.Beff./Bamp; +0193 +0194 % set the M axes handles +0195 set(gui.panels.Plot.Mag,'Selection',1); +0196 set(gui.panels.Plot.Sphere,'Selection',1); +0197 ax1 = gui.axes_handles.MagL; +0198 ax2 = gui.axes_handles.SphereL; +0199 Mylim = get(ax1,'YLim'); +0200 Mview = get(ax2,'View'); +0201 +0202 % get the visible PrePol Ramp parameter axes and data +0203 % only this needs to be shown +0204 T2 = prepol.t.*1e3; +0205 switch get(gui.panels.Plot.PrePol,'Selection') +0206 case 1 +0207 ax3 = gui.axes_handles.Bpre; +0208 Bval = prepol.Bp./data.basic.B0; +0209 ylab = 'Bp [B0]'; +0210 case 2 +0211 ax3 = gui.axes_handles.alpha; +0212 Bval = rad2deg(prepol.alpha); +0213 ylab = '\alpha [deg]'; +0214 case 3 +0215 ax3 = gui.axes_handles.dadt; +0216 Bval = prepol.dadt; +0217 ylab = 'd\alpha / dt'; +0218 case 4 +0219 ax3 = gui.axes_handles.wda; +0220 Bval = prepol.dadt./prepol.omega(1:numel(prepol.dadt)); +0221 ylab = '(d\alpha/dt) / \gammaB'; +0222 end +0223 Bylim = get(ax3,'YLim'); +0224 +0225 % time vector +0226 dt = Tsim(end)/NoFrames; +0227 % including all relevant time markers +0228 t = unique([0:dt:Tsim Tramp]); +0229 % adapt the number frames +0230 NoFrames = numel(t); +0231 +0232 % initialize all axes and animation lines +0233 axes(ax1); +0234 cla(ax1); +0235 hMx = animatedline('Color','r','LineWidth',2,'Parent',ax1); +0236 hMy = animatedline('Color','g','LineWidth',2,'Parent',ax1); +0237 hMz = animatedline('Color','b','LineWidth',2,'Parent',ax1); +0238 hMxy = animatedline('Color','m','LineWidth',2,'Parent',ax1); +0239 hMn = animatedline('Color','k','LineWidth',2,'LineStyle','--','Parent',ax1); +0240 set(get(ax1,'XLabel'),'String','t [ms]'); +0241 set(get(ax1,'YLabel'),'String','magnetization M'); +0242 grid(ax1,'on'); +0243 set(ax1,'FontSize',myui.axfontsize); +0244 +0245 axes(ax2); +0246 cla(ax2); +0247 hold(ax2,'on'); +0248 plotBSphere(18,18,ax2); +0249 h3dMa = animatedline('Color',myui.color.prepol,'LineWidth',2,'Parent',ax2); +0250 h3dMb = animatedline('Color',myui.color.basic,'LineWidth',2,'Parent',ax2); +0251 h3dB = animatedline('Color',myui.color.prepolB,'LineWidth',2,'Parent',ax2); +0252 +0253 axes(ax3); +0254 clearSingleAxis(ax3); +0255 hB = animatedline('Color',myui.color.prepolB,'LineWidth',2,'Parent',ax3); +0256 set(get(ax3,'XLabel'),'String','t [ms]'); +0257 set(get(ax3,'YLabel'),'String',ylab); +0258 grid(ax3,'on'); +0259 set(ax3,'FontSize',myui.axfontsize); +0260 +0261 % loop over the data +0262 for nf = 1:NoFrames-1 +0263 % get the index vector of the current data to plot +0264 indt = T1>=t(nf) & T1<t(nf+1); +0265 % get the current time vector for M +0266 x1 = T1(indt); +0267 % get data to plot for M +0268 yMx = M(indt,1); +0269 yMy = M(indt,2); +0270 yMz = M(indt,3); +0271 yMxy = Mxy(indt,1); +0272 yMn = Mamp(indt,1); +0273 +0274 % plot M into lab frame axes +0275 addpoints(hMx,x1,yMx); +0276 addpoints(hMy,x1,yMy); +0277 addpoints(hMz,x1,yMz); +0278 addpoints(hMxy,x1,yMxy); +0279 addpoints(hMn,x1,yMn); +0280 % M axis settings +0281 set(ax1,'XLim',[min(T1) max(T1)],'YLim',Mylim); +0282 lh = legend(ax1,'x','y','z','|xy|','|M|','Location','SouthWest'); +0283 +0284 % as long as we are in the "ramp" phase gather the data of +0285 % the effective B-field to plot as a trace on the Bloch +0286 % sphere and the ramp parameter that is plotted into the +0287 % prepol-panel +0288 if t(nf) < Tramp +0289 indt2 = T2>=t(nf) & T2<t(nf+1); +0290 yBx = Beffn(indt2,1); +0291 yBy = Beffn(indt2,2); +0292 yBz = Beffn(indt2,3); +0293 yBramp = Bval(indt2,1); +0294 +0295 % add the M data to the sphere (prepol color) +0296 addpoints(h3dMa,yMx./Mamp(1),yMy./Mamp(1),yMz./Mamp(1)); +0297 % add the B-field trace to the sphere +0298 addpoints(h3dB,yBx,yBy,yBz); +0299 else +0300 % after the ramp is over +0301 % add the M data to the sphere (basic color) +0302 addpoints(h3dMb,yMx./Mamp(1),yMy./Mamp(1),yMz./Mamp(1)); +0303 end +0304 % sphere axis settings +0305 view(ax2,Mview); +0306 set(ax2,'XLim',[-1.05 1.05],'YLim',[-1.05 1.05],'ZLim',[-1.05 1.05]) +0307 set(ax2,'Color','w','XColor','none','YColor','none','ZColor','none'); +0308 axis(ax2,'equal'); +0309 axis(ax2,'tight'); +0310 +0311 % plot the ramp parameter +0312 if t(nf) < Tramp +0313 x2 = T2(indt2); +0314 addpoints(hB,x2,yBramp); +0315 set(ax3,'XLim',[min(T2) max(T2)],'YLim',Bylim); +0316 end +0317 +0318 % pause a bit to show the animation +0319 % drawnow limitrate works also but is a bit too fast +0320 pause(1/24); +0321 % drawnow limitrate; +0322 +0323 end +0324 hold(ax1,'off'); +0325 hold(ax2,'off'); +0326 hold(ax3,'off'); +0327 +0328 % show the Ramp parameter again +0329 plotRamp(fig); +0330 +0331 case 'pulse' +0332 % get the results data +0333 basic = data.results.basic; +0334 pulse = data.results.pulse; +0335 +0336 % the two important timings +0337 Tsim = data.basic.Tsim; +0338 Ttau = data.pulse.Ttau; +0339 +0340 % get the data to animate +0341 T1 = basic.T.*1e3; +0342 M = basic.M; +0343 Mrot = basic.Mrot; +0344 Mxy = sqrt(M(:,1).^2+M(:,2).^2); +0345 Mamp = sqrt(M(:,1).^2+M(:,2).^2+M(:,3).^2); +0346 +0347 % get the visible magnetization axis and data +0348 switch get(gui.panels.Plot.Mag,'Selection') +0349 case 1 +0350 ax1 = gui.axes_handles.MagL; +0351 M1 = M; +0352 case 2 +0353 ax1 = gui.axes_handles.MagR; +0354 M1 = Mrot; +0355 case 3 +0356 ax1 = gui.axes_handles.MagL; +0357 % auto set FFT to lab frame +0358 set(gui.panels.Plot.Mag,'Selection',1) +0359 end +0360 Mylim = get(ax1,'YLim'); +0361 % get the visible Bloch sphere axis and data +0362 switch get(gui.panels.Plot.Sphere,'Selection') +0363 case 1 +0364 ax2 = gui.axes_handles.SphereL; +0365 M2 = M; +0366 case 2 +0367 ax2 = gui.axes_handles.SphereR; +0368 M2 = Mrot; +0369 end +0370 Mview = get(ax2,'View'); +0371 +0372 % get the visible Pulse parameter axes and data +0373 % only this needs to be shown +0374 T2 = pulse.t; +0375 % switch for df/I modulation axes +0376 showdual = false; +0377 switch get(gui.panels.Plot.Pulse,'Selection') +0378 case 1 +0379 ax3a = gui.axes_handles.PulseSetupF; +0380 ax3b = gui.axes_handles.PulseSetupI; +0381 P1 = [pulse.df pulse.I]; +0382 ylaba = 'df [Hz]'; +0383 ylabb = 'I [A]'; +0384 Pylima = get(ax3a,'YLim'); +0385 Pylimb = get(ax3b,'YLim'); +0386 showdual = true; +0387 case {2,3} +0388 ax3 = gui.axes_handles.PulseB; +0389 P1 = pulse.Bxy./data.basic.B0; +0390 ylab = 'B_1 [B_0]'; +0391 % if FFT is visible, set axes to pulse amplitude +0392 set(gui.panels.Plot.Pulse,'Selection',2) +0393 Pylim = get(ax3,'YLim'); +0394 end +0395 +0396 % time vector +0397 dt = Tsim(end)/NoFrames; +0398 % including all relevant time markers +0399 t = unique([0:dt:Tsim Ttau]); +0400 % adapt the number frames +0401 NoFrames = numel(t); +0402 +0403 % initialize all axes and animation lines +0404 axes(ax1); +0405 cla(ax1); +0406 hMx = animatedline('Color','r','LineWidth',2,'Parent',ax1); +0407 hMy = animatedline('Color','g','LineWidth',2,'Parent',ax1); +0408 hMz = animatedline('Color','b','LineWidth',2,'Parent',ax1); +0409 hMxy = animatedline('Color','m','LineWidth',2,'Parent',ax1); +0410 hMn = animatedline('Color','k','LineWidth',2,'LineStyle','--','Parent',ax1); +0411 set(get(ax1,'XLabel'),'String','t [ms]'); +0412 set(get(ax1,'YLabel'),'String','magnetization M'); +0413 grid(ax1,'on'); +0414 set(ax1,'FontSize',myui.axfontsize); +0415 +0416 axes(ax2); +0417 cla(ax2); +0418 hold(ax2,'on'); +0419 plotBSphere(18,18,ax2); +0420 h3dMa = animatedline('Color',myui.color.pulse,'LineWidth',2,'Parent',ax2); +0421 h3dMb = animatedline('Color',myui.color.basic,'LineWidth',2,'Parent',ax2); +0422 +0423 if showdual +0424 clearSingleAxis(ax3a); +0425 hPx = animatedline('Color',myui.color.pulse,'LineWidth',2,'Parent',ax3a); +0426 set(get(ax3a,'XLabel'),'String','t [ms]'); +0427 set(get(ax3a,'YLabel'),'String',ylaba); +0428 grid(ax3a,'on'); +0429 set(ax3a,'FontSize',myui.axfontsize); +0430 +0431 clearSingleAxis(ax3b); +0432 hPy = animatedline('Color',myui.color.pulse,'LineWidth',2,'Parent',ax3b); +0433 set(get(ax3b,'XLabel'),'String','t [ms]'); +0434 set(get(ax3b,'YLabel'),'String',ylabb); +0435 grid(ax3b,'on'); +0436 set(ax3b,'FontSize',myui.axfontsize); +0437 else +0438 clearSingleAxis(ax3); +0439 hPx = animatedline('Color','r','LineWidth',2,'Parent',ax3); +0440 hPy = animatedline('Color','g','LineWidth',2,'Parent',ax3); +0441 set(get(ax3,'XLabel'),'String','t [ms]'); +0442 set(get(ax3,'YLabel'),'String',ylab); +0443 grid(ax3,'on'); +0444 set(ax3,'FontSize',myui.axfontsize); +0445 end +0446 +0447 % loop over the data +0448 for nf = 1:NoFrames-1 +0449 % get the index vector of the current data to plot +0450 indt = T1>=t(nf) & T1<t(nf+1); +0451 % get the current time vector for M +0452 x1 = T1(indt); +0453 % get data to plot for M +0454 yMx = M1(indt,1); +0455 yMy = M1(indt,2); +0456 yMz = M1(indt,3); +0457 yMxx = M2(indt,1); +0458 yMyy = M2(indt,2); +0459 yMzz = M2(indt,3); +0460 yMxy = Mxy(indt,1); +0461 yMn = Mamp(indt,1); +0462 +0463 % plot M into lab frame axes +0464 addpoints(hMx,x1,yMx); +0465 addpoints(hMy,x1,yMy); +0466 addpoints(hMz,x1,yMz); +0467 addpoints(hMxy,x1,yMxy); +0468 addpoints(hMn,x1,yMn); +0469 % M axis settings +0470 set(ax1,'XLim',[min(T1) max(T1)],'YLim',Mylim); +0471 lh = legend(ax1,'x','y','z','|xy|','|M|','Location','SouthWest'); +0472 +0473 % as long as we are in the "pulse" phase +0474 if t(nf) < Ttau +0475 % add the M data to the sphere (pulse color) +0476 addpoints(h3dMa,yMxx,yMyy,yMzz); +0477 else +0478 % after the ramp is over +0479 % add the M data to the sphere (basic color) +0480 addpoints(h3dMb,yMxx,yMyy,yMzz); +0481 end +0482 % sphere axis settings +0483 view(ax2,Mview); +0484 set(ax2,'XLim',[-1.05 1.05],'YLim',[-1.05 1.05],'ZLim',[-1.05 1.05]) +0485 set(ax2,'Color','w','XColor','none','YColor','none','ZColor','none'); +0486 axis(ax2,'equal'); +0487 axis(ax2,'tight'); +0488 +0489 % plot the Pulse parameter +0490 if t(nf) < Ttau +0491 indt2 = T2>=t(nf) & T2<t(nf+1); % t2? +0492 x2 = T2(indt2); +0493 yBx = P1(indt2,1); +0494 yBy = P1(indt2,2); +0495 +0496 addpoints(hPx,x2,yBx); +0497 addpoints(hPy,x2,yBy); +0498 if showdual +0499 set(ax3a,'XLim',[min(T2) max(T2)],'YLim',Pylima); +0500 lh = legend(ax3a,'df mod.','Location','SouthEast'); +0501 +0502 set(ax3b,'XLim',[min(T2) max(T2)],'YLim',Pylimb); +0503 lh = legend(ax3b,'I mod.','Location','SouthEast'); +0504 else +0505 set(ax3,'XLim',[min(T2) max(T2)],'YLim',Pylim); +0506 lh = legend(ax3,'x','y','Location','SouthWest'); +0507 end +0508 end +0509 +0510 % pause a bit to show the animation +0511 % drawnow limitrate works also but is a bit too fast +0512 pause(1/24); +0513 % drawnow limitrate; +0514 +0515 end +0516 hold(ax1,'off'); +0517 hold(ax2,'off'); +0518 if showdual +0519 hold(ax3a,'off'); +0520 hold(ax3b,'off'); +0521 else +0522 hold(ax3,'off'); +0523 end +0524 % show the Pulse parameter again +0525 plotPulse(fig); +0526 +0527 case 'prepolpulse' +0528 % get the results data +0529 basic = data.results.basic; +0530 prepol = data.results.prepol; +0531 pulse = data.results.pulse; +0532 +0533 % the important timings +0534 Tsim = data.basic.Tsim; +0535 Tramp = data.prepol.Tramp; +0536 Ttau = data.pulse.Ttau; +0537 Twait = data.pulse.Twait; +0538 Trelax = Tsim-Tramp-Twait-Ttau; +0539 +0540 % get the data to animate +0541 T1 = basic.T.*1e3; +0542 M = basic.M; +0543 Mrot = basic.Mrot; +0544 Mxy = sqrt(M(:,1).^2+M(:,2).^2); +0545 Mamp = sqrt(M(:,1).^2+M(:,2).^2+M(:,3).^2); +0546 % normalize the magnetization +0547 M = M./data.basic.B0; +0548 Mrot = Mrot./data.basic.B0; +0549 Mxy = Mxy./data.basic.B0; +0550 Mamp = Mamp./data.basic.B0; +0551 % switch-off B-field trajectory +0552 Bamp = sqrt(prepol.Beff(:,1).^2+prepol.Beff(:,2).^2+prepol.Beff(:,3).^2); +0553 Beffn = prepol.Beff./Bamp; +0554 +0555 % get the visible magnetization axis and data +0556 switch get(gui.panels.Plot.Mag,'Selection') +0557 case 1 +0558 ax1 = gui.axes_handles.MagL; +0559 M1 = M; +0560 case 2 +0561 ax1 = gui.axes_handles.MagR; +0562 M1 = Mrot; +0563 case 3 +0564 ax1 = gui.axes_handles.MagL; +0565 % auto set FFT to lab frame +0566 set(gui.panels.Plot.Mag,'Selection',1) +0567 end +0568 Mylim = get(ax1,'YLim'); +0569 % get the visible Bloch sphere axis and data +0570 switch get(gui.panels.Plot.Sphere,'Selection') +0571 case 1 +0572 ax2 = gui.axes_handles.SphereL; +0573 M2 = M; +0574 case 2 +0575 ax2 = gui.axes_handles.SphereR; +0576 M2 = Mrot; +0577 end +0578 Mview = get(ax2,'View'); +0579 +0580 % get the visible PrePol Ramp parameter axis and data +0581 T2 = prepol.t.*1e3; +0582 switch get(gui.panels.Plot.PrePol,'Selection') +0583 case 1 +0584 ax3 = gui.axes_handles.Bpre; +0585 Bval = prepol.Bp./data.basic.B0; +0586 ylab = 'Bp [B0]'; +0587 case 2 +0588 ax3 = gui.axes_handles.alpha; +0589 Bval = rad2deg(prepol.alpha); +0590 ylab = '\alpha [deg]'; +0591 case 3 +0592 ax3 = gui.axes_handles.dadt; +0593 Bval = prepol.dadt; +0594 ylab = 'd\alpha / dt'; +0595 case 4 +0596 ax3 = gui.axes_handles.wda; +0597 Bval = prepol.dadt./prepol.omega(1:numel(prepol.dadt)); +0598 Bval = [Bval;Bval(end)]; +0599 ylab = '(d\alpha/dt) / \gammaB'; +0600 end +0601 Bylim = get(ax3,'YLim'); +0602 +0603 % get the visible Pulse parameter axes and data +0604 T3 = pulse.t; +0605 % switch for df/I modulation axes +0606 showdual = false; +0607 switch get(gui.panels.Plot.Pulse,'Selection') +0608 case 1 +0609 ax4a = gui.axes_handles.PulseSetupF; +0610 ax4b = gui.axes_handles.PulseSetupI; +0611 P1 = [pulse.df pulse.I]; +0612 ylaba = 'df [Hz]'; +0613 ylabb = 'I [A]'; +0614 Pylima = get(ax4a,'YLim'); +0615 Pylimb = get(ax4b,'YLim'); +0616 showdual = true; +0617 case {2,3} +0618 ax4 = gui.axes_handles.PulseB; +0619 P1 = pulse.Bxy./data.basic.B0; +0620 ylab = 'B_1 [B_0]'; +0621 % if FFT is visible, set axes to pulse amplitude +0622 set(gui.panels.Plot.Pulse,'Selection',2) +0623 Pylim = get(ax4,'YLim'); +0624 end +0625 +0626 % time vector +0627 dt = Tsim(end)/NoFrames; +0628 % including all relevant time markers +0629 t = unique([0:dt:Tsim Tramp Tramp+Twait Tramp+Twait+Ttau]); +0630 % adapt the number frames +0631 NoFrames = numel(t); +0632 +0633 % initialize all axes and animation lines +0634 axes(ax1); +0635 cla(ax1); +0636 hMx = animatedline('Color','r','LineWidth',2,'Parent',ax1); +0637 hMy = animatedline('Color','g','LineWidth',2,'Parent',ax1); +0638 hMz = animatedline('Color','b','LineWidth',2,'Parent',ax1); +0639 hMxy = animatedline('Color','m','LineWidth',2,'Parent',ax1); +0640 hMn = animatedline('Color','k','LineWidth',2,'LineStyle','--','Parent',ax1); +0641 set(get(ax1,'XLabel'),'String','t [ms]'); +0642 set(get(ax1,'YLabel'),'String','magnetization M'); +0643 grid(ax1,'on'); +0644 set(ax1,'FontSize',myui.axfontsize); +0645 +0646 axes(ax2); +0647 cla(ax2); +0648 hold(ax2,'on'); +0649 plotBSphere(18,18,ax2); +0650 h3dMa = animatedline('Color',myui.color.prepol,'LineWidth',2,'Parent',ax2); +0651 h3dMb = animatedline('Color',myui.color.wait,'LineWidth',2,'Parent',ax2); +0652 h3dMc = animatedline('Color',myui.color.pulse,'LineWidth',2,'Parent',ax2); +0653 h3dMd = animatedline('Color',myui.color.basic,'LineWidth',2,'Parent',ax2); +0654 h3dB = animatedline('Color',myui.color.prepolB,'LineWidth',2,'Parent',ax2); +0655 +0656 axes(ax3); +0657 clearSingleAxis(ax3); +0658 hB = animatedline('Color',myui.color.prepolB,'LineWidth',2,'Parent',ax3); +0659 set(get(ax3,'XLabel'),'String','t [ms]'); +0660 set(get(ax3,'YLabel'),'String',ylab); +0661 grid(ax3,'on'); +0662 set(ax3,'FontSize',myui.axfontsize); +0663 +0664 if showdual +0665 clearSingleAxis(ax4a); +0666 hPx = animatedline('Color',myui.color.pulse,'LineWidth',2,'Parent',ax4a); +0667 set(get(ax4a,'XLabel'),'String','t [ms]'); +0668 set(get(ax4a,'YLabel'),'String',ylaba); +0669 grid(ax4a,'on'); +0670 set(ax4a,'FontSize',myui.axfontsize); +0671 +0672 clearSingleAxis(ax4b); +0673 hPy = animatedline('Color',myui.color.pulse,'LineWidth',2,'Parent',ax4b); +0674 set(get(ax4b,'XLabel'),'String','t [ms]'); +0675 set(get(ax4b,'YLabel'),'String',ylabb); +0676 grid(ax4b,'on'); +0677 set(ax4b,'FontSize',myui.axfontsize); +0678 else +0679 clearSingleAxis(ax4); +0680 hPx = animatedline('Color','r','LineWidth',2,'Parent',ax4); +0681 hPy = animatedline('Color','g','LineWidth',2,'Parent',ax4); +0682 set(get(ax4,'XLabel'),'String','t [ms]'); +0683 set(get(ax4,'YLabel'),'String',ylab); +0684 grid(ax4,'on'); +0685 set(ax4,'FontSize',myui.axfontsize); +0686 end +0687 +0688 % loop over the data +0689 for nf = 1:NoFrames-1 +0690 % get the index vector of the current M data to plot +0691 indt = T1>=t(nf) & T1<t(nf+1); +0692 % get the current time vector for M +0693 x1 = T1(indt); +0694 % get data to plot for M +0695 yMx = M1(indt,1); +0696 yMy = M1(indt,2); +0697 yMz = M1(indt,3); +0698 yMxx = M2(indt,1)./Mamp(1); +0699 yMyy = M2(indt,2)./Mamp(1); +0700 yMzz = M2(indt,3)./Mamp(1); +0701 yMxy = Mxy(indt,1); +0702 yMn = Mamp(indt,1); +0703 +0704 % plot M into the left panel +0705 addpoints(hMx,x1,yMx); +0706 addpoints(hMy,x1,yMy); +0707 addpoints(hMz,x1,yMz); +0708 addpoints(hMxy,x1,yMxy); +0709 addpoints(hMn,x1,yMn); +0710 % M axis settings +0711 set(ax1,'XLim',[min(T1) max(T1)],'YLim',Mylim); +0712 lh = legend(ax1,'x','y','z','|xy|','|M|','Location','SouthWest'); +0713 +0714 % plot into the Bloch sphere +0715 % as long as we are in the "pulse" phase +0716 if t(nf) < Tramp +0717 indt2 = T2>t(nf) & T2<=t(nf+1); % t2? +0718 yBx = Beffn(indt2,1); +0719 yBy = Beffn(indt2,2); +0720 yBz = Beffn(indt2,3); +0721 yBramp = Bval(indt2,1); +0722 +0723 % add the M data to the sphere (prepol color) +0724 addpoints(h3dMa,yMxx,yMyy,yMzz); +0725 % add the B-field trace to the sphere +0726 addpoints(h3dB,yBx,yBy,yBz); +0727 elseif t(nf)>Tramp && t(nf) <= Tramp+Twait +0728 % add the M data to the sphere (wait color) +0729 addpoints(h3dMb,yMxx,yMyy,yMzz); +0730 elseif t(nf)>Tramp+Twait && t(nf) <= Tsim-Trelax +0731 % add the M data to the sphere (pulse color) +0732 addpoints(h3dMc,yMxx,yMyy,yMzz); +0733 elseif t(nf) > Tsim-Trelax +0734 % after the pulse is over +0735 % add the M data to the sphere (basic color) +0736 addpoints(h3dMd,yMxx,yMyy,yMzz); +0737 end +0738 % sphere axis settings +0739 view(ax2,Mview); +0740 set(ax2,'XLim',[-1.05 1.05],'YLim',[-1.05 1.05],'ZLim',[-1.05 1.05]) +0741 set(ax2,'Color','w','XColor','none','YColor','none','ZColor','none'); +0742 axis(ax2,'equal'); +0743 axis(ax2,'tight'); +0744 +0745 % plot the ramp parameter +0746 if t(nf) < Tramp +0747 x2 = T2(indt2); +0748 addpoints(hB,x2,yBramp); +0749 set(ax3,'XLim',[min(T2) max(T2)],'YLim',Bylim); +0750 end +0751 +0752 % plot the Pulse parameter +0753 if t(nf)>=Tramp+Twait && t(nf) < Tsim-Trelax +0754 indt3 = T3+Tramp+Twait>=t(nf) & T3+Tramp+Twait<t(nf+1); +0755 x3 = T3(indt3); +0756 yBx = P1(indt3,1); +0757 yBy = P1(indt3,2); +0758 +0759 addpoints(hPx,x3,yBx); +0760 addpoints(hPy,x3,yBy); +0761 if showdual +0762 set(ax4a,'XLim',[min(T3) max(T3)],'YLim',Pylima); +0763 lh = legend(ax4a,'df mod.','Location','SouthEast'); +0764 +0765 set(ax4b,'XLim',[min(T3) max(T3)],'YLim',Pylimb); +0766 lh = legend(ax4b,'I mod.','Location','SouthEast'); +0767 else +0768 set(ax4,'XLim',[min(T3) max(T3)],'YLim',Pylim); +0769 lh = legend(ax4,'x','y','Location','SouthWest'); +0770 end +0771 end +0772 +0773 % pause a bit to show the animation +0774 % drawnow limitrate works also but is a bit too fast +0775 pause(1/24); +0776 % drawnow limitrate; +0777 +0778 end +0779 hold(ax1,'off'); +0780 hold(ax2,'off'); +0781 hold(ax3,'off'); +0782 if showdual +0783 hold(ax4a,'off'); +0784 hold(ax4b,'off'); +0785 else +0786 hold(ax4,'off'); +0787 end +0788 % show the Ramp parameter again +0789 plotRamp(fig); +0790 % show the Pulse parameter again +0791 plotPulse(fig); +0792 end +0793 +0794 % reset the pushbutton color +0795 set(src,'BackGroundColor',[.94 .94 .94]); +0796 % update the status info +0797 set(gui.text_handles.Status,'String','Animation running ... finished.'); +0798 % done +0799 pause(0.01); +0800 % show the results parameter again +0801 plotResults(fig); +0802 +0803 else +0804 warndlg({'onPushAnimate:','There is no figure with the BLOCHUS Tag open.'},... +0805 'BLOCHUS error'); +0806 end +0807 +0808 end +0809 +0810 %------------- END OF CODE -------------- +0811 +0812 %% License: +0813 % GNU GPLv3 +0814 % +0815 % BLOCHUS +0816 % Copyright (C) 2019 Thomas Hiller +0817 % +0818 % This program is free software: you can redistribute it and/or modify +0819 % it under the terms of the GNU General Public License as published by +0820 % the Free Software Foundation, either version 3 of the License, or +0821 % (at your option) any later version. +0822 % +0823 % This program is distributed in the hope that it will be useful, +0824 % but WITHOUT ANY WARRANTY; without even the implied warranty of +0825 % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +0826 % GNU General Public License for more details. +0827 % +0828 % You should have received a copy of the GNU General Public License +0829 % along with this program. If not, see <https://www.gnu.org/licenses/>.
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/blochus/callbacks/push/onPushRun.html b/doc/blochus/callbacks/push/onPushRun.html index 79ef27d..dae2f38 100644 --- a/doc/blochus/callbacks/push/onPushRun.html +++ b/doc/blochus/callbacks/push/onPushRun.html @@ -120,570 +120,588 @@

    SOURCE CODE ^% change the pushbutton color to indicate that a calculation is running 0047 set(src,'BackGroundColor','r'); -0048 -0049 % basic parameter that are always needed -0050 % z unit vector -0051 zunit = [0 0 1]'; -0052 % initial magnetization [A/m] -0053 Minit = data.basic.Minit(:); -0054 % total simulation time Tsim [s] -0055 Tsim = data.basic.Tsim/1e3; -0056 -0057 % parameter needed for the ODE solver -0058 % simulation type [string] -0059 odeparam.type = data.basic.type; -0060 % equilibrium magnetization [A/m] -0061 odeparam.M0 = data.basic.M0(:); -0062 % primary (Earth's) magnetic field B0 [T] -0063 odeparam.B0 = data.basic.B0; -0064 % longitudinal relaxation time T1 [s] -0065 odeparam.T1 = data.basic.T1relax/1e3; -0066 % transversal relaxation time T2 [s] -0067 odeparam.T2 = data.basic.T2relax/1e3; -0068 % gyromagnetic ratio [rad/s/T] -0069 odeparam.gamma = data.basic.gamma; -0070 -0071 % ODE solver error tolerance -0072 tol = 1e-9; -0073 % ODE solver options -0074 options = odeset('RelTol',tol,'AbsTol',[tol tol tol]); -0075 -0076 % time the calculation -0077 t0 = tic; -0078 switch data.basic.type -0079 case 'std' -0080 % update Info field -0081 set(gui.text_handles.Status,'String','Calculation of relaxation ...'); -0082 pause(0.01); -0083 -0084 % normalized initial magnetization -0085 Minit = Minit./norm(Minit); -0086 % update the corresponding GUI fields -0087 data.basic.Minit = Minit; -0088 set(gui.edit_handles.Minitx,'String',sprintf('%4.3f',Minit(1))); -0089 set(gui.edit_handles.Minity,'String',sprintf('%4.3f',Minit(2))); -0090 set(gui.edit_handles.Minitz,'String',sprintf('%4.3f',Minit(3))); -0091 -0092 % ODE solver call -0093 % OUTPUT: time T and magnetization M -0094 [TT,MM] = ode45(@(t,m) fcn_BLOCHUS_ode(t,m,odeparam),[0 Tsim],Minit,options); -0095 -0096 % save data -0097 data.results.basic.T = TT; -0098 data.results.basic.M = MM; -0099 -0100 % rotate M into rotating frame of reference -0101 Mrot = getMrot(MM,getOmega0(odeparam.gamma,odeparam.B0).*TT); -0102 data.results.basic.Mrot = Mrot; -0103 -0104 % get FFTof M in the laboratory frame of reference -0105 [Xm,fx] = getFFT(TT,MM(:,1:2)); -0106 data.results.basic.Mspec.fx = fx; -0107 data.results.basic.Mspec.X = Xm; -0108 -0109 % update Info field -0110 set(gui.text_handles.Status,'String','Calculation of relaxation ... finished.'); -0111 pause(0.01); -0112 -0113 case 'prepol' -0114 % update Info field -0115 set(gui.text_handles.Status,'String','Calculation of pre-polarization switch-off ...'); -0116 pause(0.01); -0117 -0118 % initial magnetization in the direction of B0+Bp -0119 Morient = data.results.prepol.orient*data.results.prepol.Bmax + odeparam.B0*zunit; -0120 % Minit does not get normalized in this case -0121 Minit = Morient;%./norm(Morient); -0122 % because Minit is not normalized to 1, M0 needs to be adjusted -0123 odeparam.M0 = odeparam.B0*zunit; -0124 % update the corresponding GUI fields -0125 set(gui.edit_handles.Minitx,'String',sprintf('%4.3f',Minit(1)/norm(Minit))); -0126 set(gui.edit_handles.Minity,'String',sprintf('%4.3f',Minit(2)/norm(Minit))); -0127 set(gui.edit_handles.Minitz,'String',sprintf('%4.3f',Minit(3)/norm(Minit))); -0128 -0129 % orientation of the pre-polarization pulse axis -0130 odeparam.orient = data.results.prepol.orient; -0131 -0132 % pre-polarization switch-off ramp parameter -0133 % relaxation during switch-off [0/1] -0134 odeparam.RDS = data.prepol.RDS; -0135 % switch-off ramp type [string] -0136 rampparam.ramp = data.prepol.Ramp; -0137 % amplitude of pre-polarization field -0138 rampparam.Bmax = data.results.prepol.Bmax; -0139 % switch over magnetization (for linexp case) -0140 rampparam.Bstar = data.results.prepol.Bstar; -0141 % switch-off ramp time [s] -0142 rampparam.Tramp = data.prepol.Tramp/1e3; -0143 % switch over ramp time [s] (for linexp case) -0144 rampparam.Tslope = data.prepol.Tslope/1e3; -0145 -0146 % add the ramp parameter to the ode parameter struct -0147 odeparam.rampparam = rampparam; -0148 -0149 % ODE solver call -0150 % OUTPUT: time T and magnetization M -0151 [TT,MM] = ode45(@(t,m) fcn_BLOCHUS_ode(t,m,odeparam),[0 Tsim],Minit,options); -0152 -0153 % normalized magnetization vector at end of switch-off ramp -0154 MMn = MM(end,:)./norm(MM(end,:)); -0155 % "adiabatic quality" p of the switch-off ramp -0156 % -> orientation of M with respect to z_unit -0157 p = dot(MMn(end,:),zunit)./norm(zunit); -0158 -0159 % save data -0160 data.results.basic.T = TT; -0161 data.results.basic.M = MM; -0162 data.results.prepol.p = p; +0048 % reset the color of the animate button +0049 set(gui.push_handles.Animate,'BackGroundColor',[.94 .94 .94]); +0050 +0051 % basic parameter that are always needed +0052 % z unit vector +0053 zunit = [0 0 1]'; +0054 % initial magnetization [A/m] +0055 Minit = data.basic.Minit(:); +0056 % total simulation time Tsim [s] +0057 Tsim = data.basic.Tsim/1e3; +0058 +0059 % parameter needed for the ODE solver +0060 % simulation type [string] +0061 odeparam.type = data.basic.type; +0062 % equilibrium magnetization [A/m] +0063 odeparam.M0 = data.basic.M0(:); +0064 % primary (Earth's) magnetic field B0 [T] +0065 odeparam.B0 = data.basic.B0; +0066 % longitudinal relaxation time T1 [s] +0067 odeparam.T1 = data.basic.T1relax/1e3; +0068 % transversal relaxation time T2 [s] +0069 odeparam.T2 = data.basic.T2relax/1e3; +0070 % gyromagnetic ratio [rad/s/T] +0071 odeparam.gamma = data.basic.gamma; +0072 +0073 % ODE solver error tolerance +0074 tol = 1e-9; +0075 % ODE solver options +0076 options = odeset('RelTol',tol,'AbsTol',[tol tol tol]); +0077 +0078 % time the calculation +0079 t0 = tic; +0080 switch data.basic.type +0081 case 'std' +0082 % update Info field +0083 set(gui.text_handles.Status,'String','Calculation of relaxation ...'); +0084 pause(0.01); +0085 +0086 % normalized initial magnetization +0087 Minit = Minit./norm(Minit); +0088 % update the corresponding GUI fields +0089 data.basic.Minit = Minit; +0090 set(gui.edit_handles.Minitx,'String',sprintf('%4.3f',Minit(1))); +0091 set(gui.edit_handles.Minity,'String',sprintf('%4.3f',Minit(2))); +0092 set(gui.edit_handles.Minitz,'String',sprintf('%4.3f',Minit(3))); +0093 +0094 % ODE solver call +0095 % OUTPUT: time T and magnetization M +0096 [TT,MM] = ode45(@(t,m) fcn_BLOCHUS_ode(t,m,odeparam),[0 Tsim],Minit,options); +0097 +0098 % save data +0099 data.results.basic.T = TT; +0100 data.results.basic.M = MM; +0101 +0102 % rotate M into rotating frame of reference +0103 Mrot = getMrot(MM,getOmega0(odeparam.gamma,odeparam.B0).*TT); +0104 data.results.basic.Mrot = Mrot; +0105 +0106 % get FFTof M in the laboratory frame of reference +0107 [Xm,fx] = getFFT(TT,MM(:,1:2)); +0108 data.results.basic.Mspec.fx = fx; +0109 data.results.basic.Mspec.X = Xm; +0110 +0111 % update Info field +0112 set(gui.text_handles.Status,'String','Calculation of relaxation ... finished.'); +0113 pause(0.01); +0114 +0115 case 'prepol' +0116 % update Info field +0117 set(gui.text_handles.Status,'String','Calculation of pre-polarization switch-off ...'); +0118 pause(0.01); +0119 +0120 % initial magnetization in the direction of B0+Bp +0121 Morient = data.results.prepol.orient*data.results.prepol.Bmax + odeparam.B0*zunit; +0122 % Minit does not get normalized in this case +0123 Minit = Morient;%./norm(Morient); +0124 % because Minit is not normalized to 1, M0 needs to be adjusted +0125 odeparam.M0 = odeparam.B0*zunit; +0126 % update the corresponding GUI fields +0127 set(gui.edit_handles.Minitx,'String',sprintf('%4.3f',Minit(1)/norm(Minit))); +0128 set(gui.edit_handles.Minity,'String',sprintf('%4.3f',Minit(2)/norm(Minit))); +0129 set(gui.edit_handles.Minitz,'String',sprintf('%4.3f',Minit(3)/norm(Minit))); +0130 +0131 % orientation of the pre-polarization pulse axis +0132 odeparam.orient = data.results.prepol.orient; +0133 +0134 % pre-polarization switch-off ramp parameter +0135 % relaxation during switch-off [0/1] +0136 odeparam.RDS = data.prepol.RDS; +0137 % switch-off ramp type [string] +0138 rampparam.ramp = data.prepol.Ramp; +0139 % amplitude of pre-polarization field +0140 rampparam.Bmax = data.results.prepol.Bmax; +0141 % switch over magnetization (for linexp case) +0142 rampparam.Bstar = data.results.prepol.Bstar; +0143 % switch-off ramp time [s] +0144 rampparam.Tramp = data.prepol.Tramp/1e3; +0145 % switch over ramp time [s] (for linexp case) +0146 rampparam.Tslope = data.prepol.Tslope/1e3; +0147 +0148 % add the ramp parameter to the ode parameter struct +0149 odeparam.rampparam = rampparam; +0150 +0151 % ODE solver call +0152 % OUTPUT: time T and magnetization M +0153 [TT,MM] = ode45(@(t,m) fcn_BLOCHUS_ode(t,m,odeparam),[0 Tsim],Minit,options); +0154 +0155 % normalized magnetization vector at end of switch-off ramp +0156 % because the simulation can be longer than the ramp, find the +0157 % last point of the ramp to calculate the adiabatic quality p +0158 indt = find(TT<=rampparam.Tramp,1,'last'); +0159 MMn = MM(indt,:)./norm(MM(indt,:)); +0160 % "adiabatic quality" p of the switch-off ramp +0161 % -> orientation of M with respect to z_unit +0162 p = dot(MMn,zunit)./norm(zunit); 0163 -0164 % update Info field -0165 set(gui.text_handles.Status,'String','Calculation of pre-polarization switch-off ... finished.'); -0166 pause(0.01); -0167 -0168 % activate the lab-frame panels to show the results -0169 set(gui.panels.Plot.Mag,'Selection',1); -0170 set(gui.panels.Plot.Sphere,'Selection',1); -0171 -0172 case 'pulse' -0173 % update Info field -0174 set(gui.text_handles.Status,'String','Calculation of excitation pulse ...'); -0175 pause(0.01); +0164 % save data +0165 data.results.basic.T = TT; +0166 data.results.basic.M = MM; +0167 data.results.prepol.p = p; +0168 +0169 % update Info field +0170 set(gui.text_handles.Status,'String','Calculation of pre-polarization switch-off ... finished.'); +0171 pause(0.01); +0172 +0173 % activate the lab-frame panels to show the results +0174 set(gui.panels.Plot.Mag,'Selection',1); +0175 set(gui.panels.Plot.Sphere,'Selection',1); 0176 -0177 % normalized initial magnetization -0178 Minit = Minit./norm(Minit); -0179 % update the corresponding GUI fields -0180 data.basic.Minit = Minit; -0181 set(gui.edit_handles.Minitx,'String',sprintf('%4.3f',Minit(1))); -0182 set(gui.edit_handles.Minity,'String',sprintf('%4.3f',Minit(2))); -0183 set(gui.edit_handles.Minitz,'String',sprintf('%4.3f',Minit(3))); -0184 -0185 % excitation pulse parameter -0186 % relaxation during pulse [0/1] -0187 odeparam.RDP = data.pulse.RDP; -0188 % pulse length [s] -0189 odeparam.Ttau = data.pulse.Ttau/1e3; -0190 % pulse type [string] -0191 pulseparam.PulseType = data.pulse.Type; -0192 % gyromagnetic ratio [rad/s/T] -0193 pulseparam.gamma = odeparam.gamma; -0194 % Larmor frequency [rad] -0195 pulseparam.omega0 = getOmega0(odeparam.gamma,odeparam.B0); -0196 % pulse amplitude [B0] -0197 pulseparam.Amp = odeparam.B0*data.pulse.B1Factor; -0198 % pulse frequency modulation [struct] -0199 pulseparam.fmod = data.results.pulse.fmod; -0200 % pulse current modulation [struct] -0201 pulseparam.Imod = data.results.pulse.Imod; -0202 % auxiliary pulse phase [rad] -0203 pulseparam.phi = 0; -0204 % pulse axis [string] -0205 pulseparam.PulseAxis = data.pulse.Axis; -0206 % pulse polarization [string] -0207 pulseparam.PulsePolarization = data.pulse.Polarization; -0208 % if the discrete MIDI pulses are used add the corresponding -0209 % data -0210 if isfield(data,'pulse_MIDI') -0211 % MIDI pulse data [struct] -0212 pulseparam.MIDI = data.pulse_MIDI; -0213 end -0214 -0215 % add the pulse parameter to the ode parameter struct -0216 odeparam.pulseparam = pulseparam; -0217 -0218 % ODE solver call -0219 % OUTPUT: time T and magnetization M -0220 switch data.pulse.Type -0221 case {'MIDI_OR','MIDI_AP'} -0222 % if Tsim > Ttau extend the discrete time steps -0223 % this is needed because for the discrete pulses -0224 % specific time steps are fed into the solver -0225 Tsim = unique([data.pulse_MIDI.t;(0:1/50e3:Tsim)']); -0226 [TT,MM] = ode45(@(t,m) fcn_BLOCHUS_ode(t,m,odeparam),Tsim,Minit,options); -0227 otherwise -0228 [TT,MM] = ode45(@(t,m) fcn_BLOCHUS_ode(t,m,odeparam),[0 Tsim],Minit,options); -0229 end -0230 -0231 % save data -0232 data.results.basic.T = TT; -0233 data.results.basic.M = MM; -0234 -0235 % in order to transform M in the rotating frame of reference -0236 % get the pulse phase theta for all simulated time steps -0237 pulseparam.fmod.t = TT; -0238 pulseparam.Imod.t = TT; -0239 pulseparam.t = TT; -0240 % get also the pulse amplitudes at these time steps -0241 [Bpulse,~,~,theta] = getPulseTimeSeries(pulseparam); -0242 -0243 % if the simulation is longer then the pulse (additional -0244 % relaxation afterwards), correct for the pulse phase for -0245 % points AFTER the pulse by simply calculating the phase at -0246 % the end of the pulse -0247 if data.basic.Tsim>data.pulse.Ttau -0248 % correction phase -0249 dphi = zeros(size(theta)); -0250 % pulse length -0251 Ttau = odeparam.Ttau; -0252 % get pulse phase at the end of the pulse -0253 dphival = getPulsePhase(Ttau,0,pulseparam,1); -0254 % and add it to the correction phase for all time steps after -0255 % the pulse -0256 indT = TT>Ttau; -0257 dphi(indT) = dphival; -0258 % set theta for all time steps after the pulse simply to -0259 % omega0*t -0260 theta(indT) = getOmega0(odeparam.gamma,odeparam.B0).*TT(indT); -0261 % rotate M into rotating frame of reference -0262 Mrot = getMrot(MM,theta,dphi); -0263 % get FFTof M in the laboratory frame of reference -0264 [Xm,fmx] = getFFT(TT,MM(:,1:2)); -0265 % get FFT for the pulse -0266 [Xb,fbx] = getFFT(TT(TT<=Ttau),Bpulse(TT<=Ttau,1:2)); -0267 -0268 % update Info field -0269 set(gui.text_handles.Status,'String','Calculation of excitation pulse & relaxation ... finished.'); -0270 pause(0.01); -0271 else -0272 % rotate M into rotating frame of reference -0273 Mrot = getMrot(MM,theta); -0274 % get FFTof M in the laboratory frame of reference -0275 [Xm,fmx] = getFFT(TT,MM(:,1:2)); -0276 % get FFT for the pulse -0277 [Xb,fbx] = getFFT(TT,Bpulse(:,1:2)); -0278 -0279 % update Info field -0280 set(gui.text_handles.Status,'String','Calculation of excitation pulse ... finished.'); -0281 pause(0.01); -0282 end -0283 -0284 % save data -0285 data.results.basic.Mrot = Mrot; -0286 data.results.basic.Mspec.fx = fmx; -0287 data.results.basic.Mspec.X = Xm; -0288 data.results.pulse.Bspec.fx = fbx; -0289 data.results.pulse.Bspec.X = Xb; -0290 -0291 case 'prepolpulse' -0292 -0293 % this is basically the combination of all of the above -0294 % simulation types +0177 case 'pulse' +0178 % update Info field +0179 set(gui.text_handles.Status,'String','Calculation of excitation pulse ...'); +0180 pause(0.01); +0181 +0182 % normalized initial magnetization +0183 Minit = Minit./norm(Minit); +0184 % update the corresponding GUI fields +0185 data.basic.Minit = Minit; +0186 set(gui.edit_handles.Minitx,'String',sprintf('%4.3f',Minit(1))); +0187 set(gui.edit_handles.Minity,'String',sprintf('%4.3f',Minit(2))); +0188 set(gui.edit_handles.Minitz,'String',sprintf('%4.3f',Minit(3))); +0189 +0190 % excitation pulse parameter +0191 % relaxation during pulse [0/1] +0192 odeparam.RDP = data.pulse.RDP; +0193 % pulse length [s] +0194 odeparam.Ttau = data.pulse.Ttau/1e3; +0195 % pulse type [string] +0196 pulseparam.PulseType = data.pulse.Type; +0197 % gyromagnetic ratio [rad/s/T] +0198 pulseparam.gamma = odeparam.gamma; +0199 % Larmor frequency [rad] +0200 pulseparam.omega0 = getOmega0(odeparam.gamma,odeparam.B0); +0201 % pulse amplitude [B0] +0202 pulseparam.Amp = odeparam.B0*data.pulse.B1Factor; +0203 % pulse frequency modulation [struct] +0204 pulseparam.fmod = data.results.pulse.fmod; +0205 % pulse current modulation [struct] +0206 pulseparam.Imod = data.results.pulse.Imod; +0207 % auxiliary pulse phase [rad] +0208 pulseparam.phi = 0; +0209 % pulse axis [string] +0210 pulseparam.PulseAxis = data.pulse.Axis; +0211 % pulse polarization [string] +0212 pulseparam.PulsePolarization = data.pulse.Polarization; +0213 % if the discrete MIDI pulses are used add the corresponding +0214 % data +0215 if isfield(data,'pulse_MIDI') +0216 % MIDI pulse data [struct] +0217 pulseparam.MIDI = data.pulse_MIDI; +0218 end +0219 +0220 % add the pulse parameter to the ode parameter struct +0221 odeparam.pulseparam = pulseparam; +0222 +0223 % ODE solver call +0224 % OUTPUT: time T and magnetization M +0225 switch data.pulse.Type +0226 case {'MIDI_OR','MIDI_AP'} +0227 % if Tsim > Ttau extend the discrete time steps +0228 % this is needed because for the discrete pulses +0229 % specific time steps are fed into the solver +0230 Tsim = unique([data.pulse_MIDI.t;(0:1/50e3:Tsim)']); +0231 [TT,MM] = ode45(@(t,m) fcn_BLOCHUS_ode(t,m,odeparam),Tsim,Minit,options); +0232 otherwise +0233 [TT,MM] = ode45(@(t,m) fcn_BLOCHUS_ode(t,m,odeparam),[0 Tsim],Minit,options); +0234 end +0235 +0236 % save data +0237 data.results.basic.T = TT; +0238 data.results.basic.M = MM; +0239 +0240 % in order to transform M in the rotating frame of reference +0241 % get the pulse phase theta for all simulated time steps +0242 pulseparam.fmod.t = TT; +0243 pulseparam.Imod.t = TT; +0244 pulseparam.t = TT; +0245 % get also the pulse amplitudes at these time steps +0246 [Bpulse,~,~,theta] = getPulseTimeSeries(pulseparam); +0247 +0248 % if the simulation is longer then the pulse (additional +0249 % relaxation afterwards), correct for the pulse phase for +0250 % points AFTER the pulse by simply calculating the phase at +0251 % the end of the pulse +0252 if data.basic.Tsim>data.pulse.Ttau +0253 % correction phase +0254 dphi = zeros(size(theta)); +0255 % pulse length +0256 Ttau = odeparam.Ttau; +0257 % get pulse phase at the end of the pulse +0258 dphival = getPulsePhase(Ttau,0,pulseparam,1); +0259 % and add it to the correction phase for all time steps after +0260 % the pulse +0261 indT = TT>Ttau; +0262 dphi(indT) = dphival; +0263 % set theta for all time steps after the pulse simply to +0264 % omega0*t +0265 theta(indT) = getOmega0(odeparam.gamma,odeparam.B0).*TT(indT); +0266 % rotate M into rotating frame of reference +0267 Mrot = getMrot(MM,theta,dphi); +0268 % get FFT of M in the laboratory frame of reference +0269 [Xm,fmx] = getFFT(TT,MM(:,1:2)); +0270 % get FFT of the pulse +0271 [Xb,fbx] = getFFT(TT(TT<=Ttau),Bpulse(TT<=Ttau,1:2)); +0272 +0273 % update Info field +0274 set(gui.text_handles.Status,'String','Calculation of excitation pulse & relaxation ... finished.'); +0275 pause(0.01); +0276 else +0277 % rotate M into rotating frame of reference +0278 Mrot = getMrot(MM,theta); +0279 % get FFT of M in the laboratory frame of reference +0280 [Xm,fmx] = getFFT(TT,MM(:,1:2)); +0281 % get FFT of the pulse +0282 [Xb,fbx] = getFFT(TT,Bpulse(:,1:2)); +0283 +0284 % update Info field +0285 set(gui.text_handles.Status,'String','Calculation of excitation pulse ... finished.'); +0286 pause(0.01); +0287 end +0288 +0289 % save data +0290 data.results.basic.Mrot = Mrot; +0291 data.results.basic.Mspec.fx = fmx; +0292 data.results.basic.Mspec.X = Xm; +0293 data.results.pulse.Bspec.fx = fbx; +0294 data.results.pulse.Bspec.X = Xb; 0295 -0296 % these times we will later on, so init them already here -0297 % total simulation time [s] -0298 Tsim = data.basic.Tsim/1e3; -0299 % switch-off ramp time [s] -0300 Tramp = data.prepol.Tramp/1e3; -0301 % wait time between switch-off ramp and pulse [s] -0302 Twait = data.pulse.Twait/1e3; -0303 % pulse length [s] -0304 Ttau = data.pulse.Ttau/1e3; -0305 -0306 % check if the simulation time is long enough to process all -0307 % different stages, if not fix it -0308 % NOTE: of course the simulation time can be longer (relaxation) -0309 % after the pulse -0310 if Tsim-(Tramp+Twait+Ttau) < 0 -0311 Tsim = Tramp+Twait+Ttau; -0312 % update the corresponding GUI data and field -0313 data.basic.Tsim = Tsim*1e3; % [ms] -0314 set(gui.edit_handles.Tsim,'String',num2str(data.basic.Tsim)); -0315 % no relaxation after excitation pulse -0316 Trelax = 0; -0317 else -0318 % relaxation after excitation pulse [s] -0319 Trelax = Tsim-(Tramp+Twait+Ttau); -0320 end -0321 -0322 % ------------------------------------------------------------- -0323 %% --- 1.) pre-polarization switch-off ------------------------ -0324 % ------------------------------------------------------------- -0325 % update Info field -0326 set(gui.text_handles.Status,'String','Calculation of pre-polarization switch-off ...'); -0327 pause(0.01); -0328 -0329 % initial magnetization in the direction of B0+Bp -0330 Morient = data.results.prepol.orient*data.results.prepol.Bmax + odeparam.B0*zunit; -0331 % Minit does not get normalized in this case -0332 Minit = Morient;%./norm(Morient); -0333 % because Minit is not normalized to 1, M0 needs to be adjusted -0334 odeparam.M0 = odeparam.B0*zunit; -0335 % update the corresponding GUI fields -0336 set(gui.edit_handles.Minitx,'String',sprintf('%4.3f',Minit(1)/norm(Minit))); -0337 set(gui.edit_handles.Minity,'String',sprintf('%4.3f',Minit(2)/norm(Minit))); -0338 set(gui.edit_handles.Minitz,'String',sprintf('%4.3f',Minit(3)/norm(Minit))); -0339 -0340 % update the simulation type -0341 odeparam.type = 'prepol'; -0342 -0343 % orientation of the pre-polarization pulse axis -0344 odeparam.orient = data.results.prepol.orient; -0345 -0346 % pre-polarization switch-off ramp parameter -0347 % relaxation during switch-off [0/1] -0348 odeparam.RDS = data.prepol.RDS; -0349 % switch-off ramp type [string] -0350 rampparam.ramp = data.prepol.Ramp; -0351 % amplitude of pre-polarization field -0352 rampparam.Bmax = data.results.prepol.Bmax; -0353 % switch over magnetization (for linexp case) -0354 rampparam.Bstar = data.results.prepol.Bstar; -0355 % switch-off ramp time [s] -0356 rampparam.Tramp = Tramp; -0357 % switch over ramp time [s] (for linexp case) -0358 rampparam.Tslope = data.prepol.Tslope/1e3; -0359 -0360 % add the ramp parameter to the ode parameter struct -0361 odeparam.rampparam = rampparam; -0362 -0363 % ODE solver call -0364 % OUTPUT: time T and magnetization M -0365 [TT,MM] = ode45(@(t,m) fcn_BLOCHUS_ode(t,m,odeparam),[0 Tramp],Minit,options); -0366 -0367 % data of the first stage -0368 TT1 = TT; -0369 MM1 = MM; -0370 -0371 % normalized magnetization vector at end of switch-off ramp -0372 MMn = MM(end,:)./norm(MM(end,:)); -0373 % "adiabatic quality" p of the switch-off ramp -0374 % -> orientation of M with respect to z_unit -0375 data.results.prepol.p = dot(MMn(end,:),zunit)./norm(zunit); -0376 -0377 % ------------------------------------------------------------- -0378 %% --- 2.) wait time (if any) --------------------------------- -0379 % ------------------------------------------------------------- -0380 if Twait > 0 -0381 % update Info field -0382 set(gui.text_handles.Status,'String','Calculation of wait time ...'); -0383 pause(0.01); -0384 % initial magnetization is the end of the switch-off ramp -0385 Minit2 = MM1(end,:)'; -0386 % update the simulation type -0387 odeparam.type = 'std'; -0388 -0389 % ODE solver call -0390 % OUTPUT: time T and magnetization M -0391 [TT,MM] = ode45(@(t,m) fcn_BLOCHUS_ode(t,m,odeparam),[0 Twait],Minit2,options); -0392 -0393 % rotate M into rotating frame of reference -0394 MM2rot = getMrot(MM,getOmega0(odeparam.gamma,odeparam.B0).*TT); -0395 % get the additional phase at the end of the wait time -0396 phiWait = getOmega0(odeparam.gamma,odeparam.B0).*TT(end); -0397 -0398 % because the simulation was done in "local" time -0399 % coordinates, shift the time vector to the end of the -0400 % switch-off ramp -0401 TT2 = TT + Tramp; -0402 % save data -0403 MM2 = MM; -0404 % initial magnetization for the pulse is the end of the -0405 % wait time period -0406 Minit3 = MM2(end,:)'; -0407 else -0408 % if wait time is 0, use dummy values -0409 TT2 = []; -0410 MM2 = []; -0411 MM2rot = []; -0412 phiWait = 0; -0413 % initial magnetization for the pulse is the end of the -0414 % switch-off ramp -0415 Minit3 = MM1(end,:)'; -0416 end -0417 -0418 % ------------------------------------------------------------- -0419 %% --- 3.) excitation pulse ----------------------------------- -0420 % ------------------------------------------------------------- -0421 -0422 % update the simulation type -0423 odeparam.type = 'pulse'; -0424 -0425 % excitation pulse parameter -0426 % relaxation during pulse [0/1] -0427 odeparam.RDP = data.pulse.RDP; -0428 % pulse length [s] -0429 odeparam.Ttau = Ttau; -0430 -0431 % pulse type [string] -0432 pulseparam.PulseType = data.pulse.Type; -0433 % gyromagnetic ratio [rad/s/T] -0434 pulseparam.gamma = odeparam.gamma; -0435 % Larmor frequency [rad] -0436 pulseparam.omega0 = getOmega0(odeparam.gamma,odeparam.B0); -0437 % pulse amplitude [B0] -0438 pulseparam.Amp = odeparam.B0*data.pulse.B1Factor; -0439 % pulse frequency modulation [struct] -0440 pulseparam.fmod = data.results.pulse.fmod; -0441 % pulse current modulation [struct] -0442 pulseparam.Imod = data.results.pulse.Imod; -0443 % auxiliary pulse phase [rad] -0444 pulseparam.phi = 0; -0445 % pulse axis [string] -0446 pulseparam.PulseAxis = data.pulse.Axis; -0447 % pulse polarization [string] -0448 pulseparam.PulsePolarization = data.pulse.Polarization; -0449 % if the discrete MIDI pulses are used add the corresponding -0450 % data -0451 if isfield(data,'pulse_MIDI') -0452 % MIDI pulse data [struct] -0453 pulseparam.MIDI = data.pulse_MIDI; -0454 end -0455 -0456 % add the pulse parameter to the ode parameter struct -0457 odeparam.pulseparam = pulseparam; -0458 -0459 % update Info field -0460 set(gui.text_handles.Status,'String','Calculation of excitation pulse ...'); -0461 pause(0.01); -0462 -0463 % if there is a time span after the pulse -0464 if abs(Trelax) > eps -0465 % the "local" simulation time is prolonged -0466 Tsim1 = Ttau+Trelax; -0467 else -0468 % otherwise the "local" simulation time is simply the pulse -0469 % length -0470 Tsim1 = Ttau; -0471 end -0472 -0473 % ODE solver call -0474 % OUTPUT: time T and magnetization M -0475 switch data.pulse.Type -0476 case {'MIDI_OR','MIDI_AP'} -0477 % if Tsim1 > Ttau extend the discrete time steps -0478 % this is needed because for the discrete pulses -0479 % specific time steps are fed into the solver -0480 Tsim1 = unique([data.pulse_MIDI.t;(0:1/50e3:Tsim1)']); -0481 [TT,MM] = ode45(@(t,m) fcn_BLOCHUS_ode(t,m,odeparam),Tsim1,Minit3,options); -0482 otherwise -0483 [TT,MM] = ode45(@(t,m) fcn_BLOCHUS_ode(t,m,odeparam),[0 Tsim1],Minit3,options); -0484 end -0485 -0486 % in order to transform M in the rotating frame of reference -0487 % get the pulse phase theta for all simulated time steps -0488 pulseparam.fmod.t = TT; -0489 pulseparam.Imod.t = TT; -0490 pulseparam.t = TT; -0491 % get also the pulse amplitudes at these time steps -0492 [Bpulse,~,~,theta] = getPulseTimeSeries(pulseparam); -0493 -0494 % if the simulation is longer then the pulse (additional -0495 % relaxation afterwards), correct for the pulse phase for -0496 % points AFTER the pulse by simply calculating the phase at -0497 % the end of the pulse -0498 if abs(Trelax) > eps%max(Tsim1)>Ttau -0499 % correction phase -0500 dphi = zeros(size(theta)); -0501 % get pulse phase at the end of the pulse -0502 dphival = getPulsePhase(Ttau,0,pulseparam,1); -0503 % and add it to the correction phase for all time steps after -0504 % the pulse -0505 indT = TT>Ttau; -0506 dphi(indT) = dphival; -0507 % set theta for all time steps after the pulse simply to -0508 % omega0*t -0509 theta(indT) = getOmega0(odeparam.gamma,odeparam.B0).*TT(indT); -0510 % rotate M into rotating frame of reference -0511 % and account for the phase from the wait time before the -0512 % pulse -0513 MM3rot = getMrot(MM,theta,dphi+phiWait); -0514 % get FFT pulse B-field -0515 [Xb,fbx] = getFFT(TT(TT<=Ttau),Bpulse(TT<=Ttau,1:2)); -0516 -0517 % update Info field -0518 set(gui.text_handles.Status,'String',['Calculation of excitation pulse',... -0519 ' & relaxation ... finished.']); -0520 pause(0.01); -0521 else -0522 % rotate M into rotating frame of reference -0523 % and account for the phase from the wait time before the -0524 % pulse -0525 MM3rot = getMrot(MM,theta,phiWait); -0526 % get FFT pulse B-field -0527 [Xb,fbx] = getFFT(TT,Bpulse(:,1:2)); -0528 -0529 % update Info field -0530 set(gui.text_handles.Status,'String','Calculation of excitation pulse ... finished.'); +0296 case 'prepolpulse' +0297 +0298 % this is basically the combination of all of the above +0299 % simulation types +0300 % --- IMPORTANT NOTE: ---------------------------------------- +0301 % The pre-polarization switch-off only "lives" in the laboratory +0302 % frame of reference. However, for convenience reasons I plot +0303 % the lab-frame pre-polarization data also in the rotating +0304 % frame of reference! This is u-n-p-h-y-s-i-c-a-l and pure "eye candy" +0305 % ------------------------------------------------------------- +0306 +0307 % these times we will later on, so init them already here +0308 % total simulation time [s] +0309 Tsim = data.basic.Tsim/1e3; +0310 % switch-off ramp time [s] +0311 Tramp = data.prepol.Tramp/1e3; +0312 % wait time between switch-off ramp and pulse [s] +0313 Twait = data.pulse.Twait/1e3; +0314 % pulse length [s] +0315 Ttau = data.pulse.Ttau/1e3; +0316 +0317 % check if the simulation time is long enough to process all +0318 % different stages, if not fix it +0319 % NOTE: of course the simulation time can be longer (relaxation) +0320 % after the pulse +0321 if Tsim-(Tramp+Twait+Ttau) < 0 +0322 Tsim = Tramp+Twait+Ttau; +0323 % update the corresponding GUI data and field +0324 data.basic.Tsim = Tsim*1e3; % [ms] +0325 set(gui.edit_handles.Tsim,'String',num2str(data.basic.Tsim)); +0326 % no relaxation after excitation pulse +0327 Trelax = 0; +0328 else +0329 % relaxation after excitation pulse [s] +0330 Trelax = Tsim-(Tramp+Twait+Ttau); +0331 end +0332 +0333 % ------------------------------------------------------------- +0334 %% --- 1.) pre-polarization switch-off ------------------------ +0335 % ------------------------------------------------------------- +0336 % update Info field +0337 set(gui.text_handles.Status,'String','Calculation of pre-polarization switch-off ...'); +0338 pause(0.01); +0339 +0340 % initial magnetization in the direction of B0+Bp +0341 Morient = data.results.prepol.orient*data.results.prepol.Bmax + odeparam.B0*zunit; +0342 % Minit does not get normalized in this case +0343 Minit = Morient;%./norm(Morient); +0344 % because Minit is not normalized to 1, M0 needs to be adjusted +0345 odeparam.M0 = odeparam.B0*zunit; +0346 % update the corresponding GUI fields +0347 set(gui.edit_handles.Minitx,'String',sprintf('%4.3f',Minit(1)/norm(Minit))); +0348 set(gui.edit_handles.Minity,'String',sprintf('%4.3f',Minit(2)/norm(Minit))); +0349 set(gui.edit_handles.Minitz,'String',sprintf('%4.3f',Minit(3)/norm(Minit))); +0350 +0351 % update the simulation type +0352 odeparam.type = 'prepol'; +0353 +0354 % orientation of the pre-polarization pulse axis +0355 odeparam.orient = data.results.prepol.orient; +0356 +0357 % pre-polarization switch-off ramp parameter +0358 % relaxation during switch-off [0/1] +0359 odeparam.RDS = data.prepol.RDS; +0360 % switch-off ramp type [string] +0361 rampparam.ramp = data.prepol.Ramp; +0362 % amplitude of pre-polarization field +0363 rampparam.Bmax = data.results.prepol.Bmax; +0364 % switch over magnetization (for linexp case) +0365 rampparam.Bstar = data.results.prepol.Bstar; +0366 % switch-off ramp time [s] +0367 rampparam.Tramp = Tramp; +0368 % switch over ramp time [s] (for linexp case) +0369 rampparam.Tslope = data.prepol.Tslope/1e3; +0370 +0371 % add the ramp parameter to the ode parameter struct +0372 odeparam.rampparam = rampparam; +0373 +0374 % ODE solver call +0375 % OUTPUT: time T and magnetization M +0376 [TT,MM] = ode45(@(t,m) fcn_BLOCHUS_ode(t,m,odeparam),[0 Tramp],Minit,options); +0377 +0378 % data of the first stage +0379 TT1 = TT; +0380 MM1 = MM; +0381 +0382 % normalized magnetization vector at end of switch-off ramp +0383 MMn = MM(end,:)./norm(MM(end,:)); +0384 % "adiabatic quality" p of the switch-off ramp +0385 % -> orientation of M with respect to z_unit +0386 data.results.prepol.p = dot(MMn(end,:),zunit)./norm(zunit); +0387 +0388 % ------------------------------------------------------------- +0389 %% --- 2.) wait time (if any) --------------------------------- +0390 % ------------------------------------------------------------- +0391 if Twait > 0 +0392 % update Info field +0393 set(gui.text_handles.Status,'String','Calculation of wait time ...'); +0394 pause(0.01); +0395 % initial magnetization is the end of the switch-off ramp +0396 Minit2 = MM1(end,:)'; +0397 % update the simulation type +0398 odeparam.type = 'std'; +0399 +0400 % ODE solver call +0401 % OUTPUT: time T and magnetization M +0402 [TT,MM] = ode45(@(t,m) fcn_BLOCHUS_ode(t,m,odeparam),[0 Twait],Minit2,options); +0403 +0404 % rotate M into rotating frame of reference +0405 MM2rot = getMrot(MM,getOmega0(odeparam.gamma,odeparam.B0).*TT); +0406 % get the additional phase at the end of the wait time +0407 phiWait = getOmega0(odeparam.gamma,odeparam.B0).*TT(end); +0408 +0409 % because the simulation was done in "local" time +0410 % coordinates, shift the time vector to the end of the +0411 % switch-off ramp +0412 TT2 = TT + Tramp; +0413 % save data +0414 MM2 = MM; +0415 % initial magnetization for the pulse is the end of the +0416 % wait time period +0417 Minit3 = MM2(end,:)'; +0418 else +0419 % if wait time is 0, use dummy values +0420 TT2 = []; +0421 MM2 = []; +0422 MM2rot = []; +0423 phiWait = 0; +0424 % initial magnetization for the pulse is the end of the +0425 % switch-off ramp +0426 Minit3 = MM1(end,:)'; +0427 end +0428 +0429 % ------------------------------------------------------------- +0430 %% --- 3.) excitation pulse ----------------------------------- +0431 % ------------------------------------------------------------- +0432 +0433 % update the simulation type +0434 odeparam.type = 'pulse'; +0435 +0436 % excitation pulse parameter +0437 % relaxation during pulse [0/1] +0438 odeparam.RDP = data.pulse.RDP; +0439 % pulse length [s] +0440 odeparam.Ttau = Ttau; +0441 +0442 % pulse type [string] +0443 pulseparam.PulseType = data.pulse.Type; +0444 % gyromagnetic ratio [rad/s/T] +0445 pulseparam.gamma = odeparam.gamma; +0446 % Larmor frequency [rad] +0447 pulseparam.omega0 = getOmega0(odeparam.gamma,odeparam.B0); +0448 % pulse amplitude [B0] +0449 pulseparam.Amp = odeparam.B0*data.pulse.B1Factor; +0450 % pulse frequency modulation [struct] +0451 pulseparam.fmod = data.results.pulse.fmod; +0452 % pulse current modulation [struct] +0453 pulseparam.Imod = data.results.pulse.Imod; +0454 % auxiliary pulse phase [rad] +0455 pulseparam.phi = 0; +0456 % pulse axis [string] +0457 pulseparam.PulseAxis = data.pulse.Axis; +0458 % pulse polarization [string] +0459 pulseparam.PulsePolarization = data.pulse.Polarization; +0460 % if the discrete MIDI pulses are used add the corresponding +0461 % data +0462 if isfield(data,'pulse_MIDI') +0463 % MIDI pulse data [struct] +0464 pulseparam.MIDI = data.pulse_MIDI; +0465 end +0466 +0467 % add the pulse parameter to the ode parameter struct +0468 odeparam.pulseparam = pulseparam; +0469 +0470 % update Info field +0471 set(gui.text_handles.Status,'String','Calculation of excitation pulse ...'); +0472 pause(0.01); +0473 +0474 % if there is a time span after the pulse +0475 if abs(Trelax) > eps +0476 % the "local" simulation time is prolonged +0477 Tsim1 = Ttau+Trelax; +0478 else +0479 % otherwise the "local" simulation time is simply the pulse +0480 % length +0481 Tsim1 = Ttau; +0482 end +0483 +0484 % ODE solver call +0485 % OUTPUT: time T and magnetization M +0486 switch data.pulse.Type +0487 case {'MIDI_OR','MIDI_AP'} +0488 % if Tsim1 > Ttau extend the discrete time steps +0489 % this is needed because for the discrete pulses +0490 % specific time steps are fed into the solver +0491 Tsim1 = unique([data.pulse_MIDI.t;(0:1/50e3:Tsim1)']); +0492 [TT,MM] = ode45(@(t,m) fcn_BLOCHUS_ode(t,m,odeparam),Tsim1,Minit3,options); +0493 otherwise +0494 [TT,MM] = ode45(@(t,m) fcn_BLOCHUS_ode(t,m,odeparam),[0 Tsim1],Minit3,options); +0495 end +0496 +0497 % in order to transform M in the rotating frame of reference +0498 % get the pulse phase theta for all simulated time steps +0499 pulseparam.fmod.t = TT; +0500 pulseparam.Imod.t = TT; +0501 pulseparam.t = TT; +0502 % get also the pulse amplitudes at these time steps +0503 [Bpulse,~,~,theta] = getPulseTimeSeries(pulseparam); +0504 +0505 % if the simulation is longer then the pulse (additional +0506 % relaxation afterwards), correct for the pulse phase for +0507 % points AFTER the pulse by simply calculating the phase at +0508 % the end of the pulse +0509 if abs(Trelax) > eps%max(Tsim1)>Ttau +0510 % correction phase +0511 dphi = zeros(size(theta)); +0512 % get pulse phase at the end of the pulse +0513 dphival = getPulsePhase(Ttau,0,pulseparam,1); +0514 % and add it to the correction phase for all time steps after +0515 % the pulse +0516 indT = TT>Ttau; +0517 dphi(indT) = dphival; +0518 % set theta for all time steps after the pulse simply to +0519 % omega0*t +0520 theta(indT) = getOmega0(odeparam.gamma,odeparam.B0).*TT(indT); +0521 % rotate M into rotating frame of reference +0522 % and account for the phase from the wait time before the +0523 % pulse +0524 MM3rot = getMrot(MM,theta,dphi+phiWait); +0525 % get FFT of the pulse +0526 [Xb,fbx] = getFFT(TT(TT<=Ttau),Bpulse(TT<=Ttau,1:2)); +0527 +0528 % update Info field +0529 set(gui.text_handles.Status,'String',['Calculation of excitation pulse',... +0530 ' & relaxation ... finished.']); 0531 pause(0.01); -0532 end -0533 -0534 % ------------------------------------------------------------- -0535 %% --- 4.) final data merging --------------------------------- -0536 % ------------------------------------------------------------- -0537 % because the simulation was done in "local" time -0538 % coordinates, shift the time vector to the end of the -0539 % wait time after the switch-off -0540 TT3 = TT + Tramp + Twait; -0541 % save data -0542 MM3 = MM; -0543 -0544 % combine data from all stages -0545 TT = [TT1;TT2;TT3]; -0546 MM = [MM1;MM2;MM3]; -0547 % because there is no M in the rotating frame of reference -0548 % during the switch-off ramp, use the lab-frame data instead -0549 MMrot = [MM1;MM2rot;MM3rot]; -0550 -0551 % remove possible duplicate points -0552 [TT,ix] = unique(TT); -0553 MM = MM(ix,:); -0554 MMrot = MMrot(ix,:); -0555 -0556 % save combined data -0557 data.results.basic.T = TT; -0558 data.results.basic.M = MM; -0559 data.results.basic.Mrot = MMrot; -0560 -0561 % get FFT for the combined M -0562 [Xm,fmx] = getFFT(TT,MM(:,1:2)); -0563 data.results.basic.Mspec.fx = fmx; -0564 data.results.basic.Mspec.X = Xm; -0565 % save pulse FFT -0566 data.results.pulse.Bspec.fx = fbx; -0567 data.results.pulse.Bspec.X = Xb; -0568 -0569 end -0570 % time the calculation -0571 data.info.Timer = toc(t0); -0572 -0573 % update GUI data -0574 setappdata(fig,'data',data); -0575 % plot results -0576 plotResults(fig); -0577 % update status bar -0578 updateStatusInformation(fig); -0579 % activate animation button -0580 set(gui.push_handles.Animate,'Enable','on'); -0581 -0582 % change the pushbutton color back to green -0583 set(src,'BackGroundColor','g'); -0584 -0585 else -0586 warndlg({'onPushRun:','There is no figure with the BLOCHUS Tag open.'},... -0587 'BLOCHUS error'); -0588 end -0589 -0590 end -0591 -0592 %------------- END OF CODE -------------- -0593 -0594 %% License: -0595 % GNU GPLv3 -0596 % -0597 % BLOCHUS -0598 % Copyright (C) 2019 Thomas Hiller -0599 % -0600 % This program is free software: you can redistribute it and/or modify -0601 % it under the terms of the GNU General Public License as published by -0602 % the Free Software Foundation, either version 3 of the License, or -0603 % (at your option) any later version. -0604 % -0605 % This program is distributed in the hope that it will be useful, -0606 % but WITHOUT ANY WARRANTY; without even the implied warranty of -0607 % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -0608 % GNU General Public License for more details. -0609 % -0610 % You should have received a copy of the GNU General Public License -0611 % along with this program. If not, see <https://www.gnu.org/licenses/>. +0532 else +0533 % rotate M into rotating frame of reference +0534 % and account for the phase from the wait time before the +0535 % pulse +0536 MM3rot = getMrot(MM,theta,phiWait); +0537 % get FFT of the pulse +0538 [Xb,fbx] = getFFT(TT,Bpulse(:,1:2)); +0539 +0540 % update Info field +0541 set(gui.text_handles.Status,'String','Calculation of excitation pulse ... finished.'); +0542 pause(0.01); +0543 end +0544 +0545 % ------------------------------------------------------------- +0546 %% --- 4.) final data merging --------------------------------- +0547 % ------------------------------------------------------------- +0548 % because the simulation was done in "local" time +0549 % coordinates, shift the time vector to the end of the +0550 % wait time after the switch-off +0551 TT3 = TT + Tramp + Twait; +0552 % save data +0553 MM3 = MM; +0554 +0555 % combine data from all stages +0556 TT = [TT1;TT2;TT3]; +0557 MM = [MM1;MM2;MM3]; +0558 % because there is no M in the rotating frame of reference +0559 % during the switch-off ramp, use the lab-frame data instead +0560 % --- IMPORTANT NOTE: ---------------------------------------- +0561 % The pre-polarization switch-off only "lives" in the laboratory +0562 % frame of reference. However, for convenience reasons I plot +0563 % the lab-frame pre-polarization data also in the rotating +0564 % frame of reference! This is u-n-p-h-y-s-i-c-a-l and pure "eye candy" +0565 % MM1 is lab-frame data! +0566 % ------------------------------------------------------------- +0567 MMrot = [MM1;MM2rot;MM3rot]; +0568 +0569 % remove possible duplicate points +0570 [TT,ix] = unique(TT); +0571 MM = MM(ix,:); +0572 MMrot = MMrot(ix,:); +0573 +0574 % save combined data +0575 data.results.basic.T = TT; +0576 data.results.basic.M = MM; +0577 data.results.basic.Mrot = MMrot; +0578 +0579 % get FFT for the combined M +0580 [Xm,fmx] = getFFT(TT,MM(:,1:2)); +0581 data.results.basic.Mspec.fx = fmx; +0582 data.results.basic.Mspec.X = Xm; +0583 % save pulse FFT +0584 data.results.pulse.Bspec.fx = fbx; +0585 data.results.pulse.Bspec.X = Xb; +0586 +0587 end +0588 % time the calculation +0589 data.info.Timer = toc(t0); +0590 +0591 % update GUI data +0592 setappdata(fig,'data',data); +0593 % plot results +0594 plotResults(fig); +0595 % update status bar +0596 updateStatusInformation(fig); +0597 % activate animation button +0598 set(gui.push_handles.Animate,'Enable','on'); +0599 +0600 % change the pushbutton color back to green +0601 set(src,'BackGroundColor','g'); +0602 +0603 else +0604 warndlg({'onPushRun:','There is no figure with the BLOCHUS Tag open.'},... +0605 'BLOCHUS error'); +0606 end +0607 +0608 end +0609 +0610 %------------- END OF CODE -------------- +0611 +0612 %% License: +0613 % GNU GPLv3 +0614 % +0615 % BLOCHUS +0616 % Copyright (C) 2019 Thomas Hiller +0617 % +0618 % This program is free software: you can redistribute it and/or modify +0619 % it under the terms of the GNU General Public License as published by +0620 % the Free Software Foundation, either version 3 of the License, or +0621 % (at your option) any later version. +0622 % +0623 % This program is distributed in the hope that it will be useful, +0624 % but WITHOUT ANY WARRANTY; without even the implied warranty of +0625 % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +0626 % GNU General Public License for more details. +0627 % +0628 % You should have received a copy of the GNU General Public License +0629 % along with this program. If not, see <https://www.gnu.org/licenses/>.
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/blochus/functions/blochsim/getFFT.html b/doc/blochus/functions/blochsim/getFFT.html index a22018e..9fca5cc 100644 --- a/doc/blochus/functions/blochsim/getFFT.html +++ b/doc/blochus/functions/blochsim/getFFT.html @@ -63,7 +63,7 @@

    CROSS-REFERENCE INFORMATION ^
 </ul>
 This function is called by:
 <ul style= -
  • onPushRun starts the calculation
  • +
  • onPushRun starts the calculation
  • getPulseParameters updates all relevant pulse settings
  • diff --git a/doc/blochus/functions/blochsim/getOmega0.html b/doc/blochus/functions/blochsim/getOmega0.html index 13807c7..8b46092 100644 --- a/doc/blochus/functions/blochsim/getOmega0.html +++ b/doc/blochus/functions/blochsim/getOmega0.html @@ -63,7 +63,7 @@

    CROSS-REFERENCE INFORMATION ^
 </ul>
 This function is called by:
 <ul style= -
  • BLOCHUS_loadDefaults loads default GUI data values
  • onEditValue updates all edit field values, checks for wrong inputs and
  • onPopupNucleus selects the nucleus (proton) to use for the simulation
  • onPushRun starts the calculation
  • getPulseParameters updates all relevant pulse settings
  • plotResults plots results depending on the chosen settings
  • +
  • BLOCHUS_loadDefaults loads default GUI data values
  • onEditValue updates all edit field values, checks for wrong inputs and
  • onPopupNucleus selects the nucleus (proton) to use for the simulation
  • onPushRun starts the calculation
  • getPulseParameters updates all relevant pulse settings
  • plotPulse plots different pulse parameter
  • plotResults plots results depending on the chosen settings
  • diff --git a/doc/blochus/functions/interface/clearSingleAxis.html b/doc/blochus/functions/interface/clearSingleAxis.html index 35215db..21bae86 100644 --- a/doc/blochus/functions/interface/clearSingleAxis.html +++ b/doc/blochus/functions/interface/clearSingleAxis.html @@ -61,7 +61,7 @@

    CROSS-REFERENCE INFORMATION ^
 </ul>
 This function is called by:
 <ul style= -
  • BLOCHUS_createGridPlots creates the "Plots" grid panel
  • onCheckPrePolPulse activates / deactivates all control elements needed for
  • plotResults plots results depending on the chosen settings
  • +
  • BLOCHUS_createGridPlots creates the "Plots" grid panel
  • onCheckPrePolPulse activates / deactivates all control elements needed for
  • onPushAnimate animates the results of the latest simulation
  • plotPulse plots different pulse parameter
  • plotResults plots results depending on the chosen settings
  • diff --git a/doc/blochus/functions/interface/getPulseParameters.html b/doc/blochus/functions/interface/getPulseParameters.html index 93b6807..a6ac509 100644 --- a/doc/blochus/functions/interface/getPulseParameters.html +++ b/doc/blochus/functions/interface/getPulseParameters.html @@ -60,7 +60,7 @@

    DESCRIPTION ^CROSS-REFERENCE INFORMATION ^

    This function calls:
      -
    • getMIDI_Tx creates discrete on-resonant or adiabatic pulses
    • getOmega0 calculates the angular frequency from a given B-field and
    • getPulseTimeSeries returns the B-field amplitudes of the pulse either for a
    +
  • getFFT calculates the FFT for a given time and signal pair
  • getMIDI_Tx creates discrete on-resonant or adiabatic pulses
  • getOmega0 calculates the angular frequency from a given B-field and
  • getPulseTimeSeries returns the B-field amplitudes of the pulse either for a
  • This function is called by: @@ -310,38 +310,46 @@

    SOURCE CODE ^% dummy time vector [ms] 0240 data.results.pulse.t = pulse_t'.*1e3; 0241 -0242 % update data -0243 data.results.pulse.fmod = fmod; -0244 data.results.pulse.Imod = Imod; -0245 data.results.pulse.df = df; -0246 data.results.pulse.I = I; -0247 data.results.pulse.Bxy = pulse_Bxy; -0248 -0249 % update GUI data -0250 setappdata(fig,'data',data); -0251 -0252 end +0242 % get FFT of the pulse +0243 [Xb,fbx] = getFFT(pulse_t(:),pulse_Bxy(:,1:2)); +0244 +0245 % update data +0246 data.results.pulse.fmod = fmod; +0247 data.results.pulse.Imod = Imod; +0248 data.results.pulse.df = df; +0249 data.results.pulse.I = I; +0250 data.results.pulse.Bxy = pulse_Bxy; +0251 data.results.pulse.Bspec.fx = fbx; +0252 data.results.pulse.Bspec.X = Xb; 0253 -0254 %------------- END OF CODE -------------- -0255 -0256 %% License: -0257 % GNU GPLv3 -0258 % -0259 % BLOCHUS -0260 % Copyright (C) 2019 Thomas Hiller -0261 % -0262 % This program is free software: you can redistribute it and/or modify -0263 % it under the terms of the GNU General Public License as published by -0264 % the Free Software Foundation, either version 3 of the License, or -0265 % (at your option) any later version. +0254 % because the pulse data changed, deactivate the "Animate" button +0255 set(gui.push_handles.Animate,'Enable','off'); +0256 +0257 % update GUI data +0258 setappdata(fig,'data',data); +0259 +0260 end +0261 +0262 %------------- END OF CODE -------------- +0263 +0264 %% License: +0265 % GNU GPLv3 0266 % -0267 % This program is distributed in the hope that it will be useful, -0268 % but WITHOUT ANY WARRANTY; without even the implied warranty of -0269 % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -0270 % GNU General Public License for more details. -0271 % -0272 % You should have received a copy of the GNU General Public License -0273 % along with this program. If not, see <https://www.gnu.org/licenses/>. +0267 % BLOCHUS +0268 % Copyright (C) 2019 Thomas Hiller +0269 % +0270 % This program is free software: you can redistribute it and/or modify +0271 % it under the terms of the GNU General Public License as published by +0272 % the Free Software Foundation, either version 3 of the License, or +0273 % (at your option) any later version. +0274 % +0275 % This program is distributed in the hope that it will be useful, +0276 % but WITHOUT ANY WARRANTY; without even the implied warranty of +0277 % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +0278 % GNU General Public License for more details. +0279 % +0280 % You should have received a copy of the GNU General Public License +0281 % along with this program. If not, see <https://www.gnu.org/licenses/>.
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/blochus/functions/interface/getRampParameters.html b/doc/blochus/functions/interface/getRampParameters.html index 6637438..45e3f83 100644 --- a/doc/blochus/functions/interface/getRampParameters.html +++ b/doc/blochus/functions/interface/getRampParameters.html @@ -172,31 +172,33 @@

    SOURCE CODE ^% update GUI data -0106 setappdata(fig,'data',data); -0107 end -0108 -0109 %------------- END OF CODE -------------- +0104 % because the ramp data changed, deactivate the "Animate" button +0105 set(gui.push_handles.Animate,'Enable','off'); +0106 +0107 % update GUI data +0108 setappdata(fig,'data',data); +0109 end 0110 -0111 %% License: -0112 % GNU GPLv3 -0113 % -0114 % BLOCHUS -0115 % Copyright (C) 2019 Thomas Hiller -0116 % -0117 % This program is free software: you can redistribute it and/or modify -0118 % it under the terms of the GNU General Public License as published by -0119 % the Free Software Foundation, either version 3 of the License, or -0120 % (at your option) any later version. -0121 % -0122 % This program is distributed in the hope that it will be useful, -0123 % but WITHOUT ANY WARRANTY; without even the implied warranty of -0124 % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -0125 % GNU General Public License for more details. -0126 % -0127 % You should have received a copy of the GNU General Public License -0128 % along with this program. If not, see <https://www.gnu.org/licenses/>. +0111 %------------- END OF CODE -------------- +0112 +0113 %% License: +0114 % GNU GPLv3 +0115 % +0116 % BLOCHUS +0117 % Copyright (C) 2019 Thomas Hiller +0118 % +0119 % This program is free software: you can redistribute it and/or modify +0120 % it under the terms of the GNU General Public License as published by +0121 % the Free Software Foundation, either version 3 of the License, or +0122 % (at your option) any later version. +0123 % +0124 % This program is distributed in the hope that it will be useful, +0125 % but WITHOUT ANY WARRANTY; without even the implied warranty of +0126 % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +0127 % GNU General Public License for more details. +0128 % +0129 % You should have received a copy of the GNU General Public License +0130 % along with this program. If not, see <https://www.gnu.org/licenses/>.
    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/blochus/functions/interface/menu.html b/doc/blochus/functions/interface/menu.html index d421ef2..53c5991 100644 --- a/doc/blochus/functions/interface/menu.html +++ b/doc/blochus/functions/interface/menu.html @@ -18,7 +18,7 @@

    Index for blochus\functions\interface

    Matlab files in this directory:

    +
  • clearSingleAxis
  • findParentOfType
  • getAngleBetweenVectors
  • getPulseParameters
  • getRampParameters
  • minimizePanel
  • onFigureSizeChange
  • plotBSphere
  • plotBpulse
  • plotPulse
  • plotRamp
  • plotResults
  • switchToolTips
  • updateStatusInformation
  • Other Matlab-specific files in this directory:

      diff --git a/doc/blochus/functions/interface/plotBSphere.html b/doc/blochus/functions/interface/plotBSphere.html index 95545c7..e98f26a 100644 --- a/doc/blochus/functions/interface/plotBSphere.html +++ b/doc/blochus/functions/interface/plotBSphere.html @@ -66,7 +66,7 @@

      CROSS-REFERENCE INFORMATION ^
 </ul>
 This function is called by:
 <ul style= -
    • onPushAnimate
    • plotResults plots results depending on the chosen settings
    +
  • onPushAnimate animates the results of the latest simulation
  • plotResults plots results depending on the chosen settings
  • diff --git a/doc/blochus/functions/interface/plotBpulse.html b/doc/blochus/functions/interface/plotPulse.html similarity index 69% rename from doc/blochus/functions/interface/plotBpulse.html rename to doc/blochus/functions/interface/plotPulse.html index d2a938a..d3088a0 100644 --- a/doc/blochus/functions/interface/plotBpulse.html +++ b/doc/blochus/functions/interface/plotPulse.html @@ -2,8 +2,8 @@ "http://www.w3.org/TR/REC-html40/loose.dtd"> - Description of plotBpulse - + Description of plotPulse + @@ -16,20 +16,20 @@ -

    plotBpulse +

    plotPulse

    PURPOSE ^

    plots different pulse parameter

    SYNOPSIS ^

    -
    function plotBpulse(fig)
    +
    function plotPulse(fig)

    DESCRIPTION ^

    -
    plotBpulse plots different pulse parameter
    +
    plotPulse plots different pulse parameter
     
      Syntax:
    -       plotBpulse(fig)
    +       plotPulse(fig)
     
      Inputs:
            fig - figure handle
    @@ -38,7 +38,7 @@ 

    DESCRIPTION ^DESCRIPTION ^CROSS-REFERENCE INFORMATION ^

    This function calls:
      -
    +
  • getOmega0 calculates the angular frequency from a given B-field and
  • clearSingleAxis clears an individual axis
  • This function is called by: +
  • onCheckPulseQ updates the checkbox that activates quality factor tuning
  • onEditValue updates all edit field values, checks for wrong inputs and
  • onPopupPulseAxis sets the orientation of the pulse axis
  • onPopupPulseDFmode selects the frequency modulation for an adiabatic pulse
  • onPopupPulseImode selects the current modulation for an adiabatic pulse
  • onPopupPulsePolarization selects the pulse polarization
  • onPopupPulseType selects the pulse type
  • onPushAnimate animates the results of the latest simulation
  • SOURCE CODE ^

    -
    0001 function plotBpulse(fig)
    -0002 %plotBpulse plots different pulse parameter
    +
    0001 function plotPulse(fig)
    +0002 %plotPulse plots different pulse parameter
     0003 %
     0004 % Syntax:
    -0005 %       plotBpulse(fig)
    +0005 %       plotPulse(fig)
     0006 %
     0007 % Inputs:
     0008 %       fig - figure handle
    @@ -80,7 +80,7 @@ 

    SOURCE CODE ^% none 0012 % 0013 % Example: -0014 % plotBpulse(gui.figh) +0014 % plotPulse(gui.figh) 0015 % 0016 % Other m-files required: 0017 % none @@ -159,28 +159,53 @@

    SOURCE CODE ^'x','y','Location','SouthWest'); 0091 set(ax,'FontSize',myui.axfontsize); 0092 -0093 end -0094 -0095 %------------- END OF CODE -------------- +0093 %% FFT +0094 % Larmor freq. [Hz] +0095 fL = getOmega0(data.basic.gamma,data.basic.B0)/2/pi; 0096 -0097 %% License: -0098 % GNU GPLv3 -0099 % -0100 % BLOCHUS -0101 % Copyright (C) 2019 Thomas Hiller -0102 % -0103 % This program is free software: you can redistribute it and/or modify -0104 % it under the terms of the GNU General Public License as published by -0105 % the Free Software Foundation, either version 3 of the License, or -0106 % (at your option) any later version. -0107 % -0108 % This program is distributed in the hope that it will be useful, -0109 % but WITHOUT ANY WARRANTY; without even the implied warranty of -0110 % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -0111 % GNU General Public License for more details. -0112 % -0113 % You should have received a copy of the GNU General Public License -0114 % along with this program. If not, see <https://www.gnu.org/licenses/>.

    +0097 ax = gui.axes_handles.PulseFFT; +0098 f = data.results.pulse.Bspec.fx; +0099 X = data.results.pulse.Bspec.X; +0100 % plot data +0101 clearSingleAxis(ax); +0102 hold(ax,'on'); +0103 plot(f,abs(X),'r','Parent',ax); +0104 % vertical line indicating Larmor frequency +0105 line([fL fL],[0 max(abs(X))],'Color','k','LineStyle','--',... +0106 'LineWidth',0.75,'Parent',ax); +0107 hold(ax,'off'); +0108 % axis settings +0109 set(ax,'XLim',[-abs(2*fL) abs(2*fL)],'YLim',[0 max(abs(X))].*1.1); +0110 grid(ax,'on'); +0111 set(get(ax,'XLabel'),'String','F [Hz]'); +0112 set(get(ax,'YLabel'),'String','amplitude'); +0113 % legend +0114 legend(ax,'B','\omega_0','Location','NorthEast'); +0115 % font size +0116 set(ax,'FontSize',myui.axfontsize); +0117 +0118 end +0119 +0120 %------------- END OF CODE -------------- +0121 +0122 %% License: +0123 % GNU GPLv3 +0124 % +0125 % BLOCHUS +0126 % Copyright (C) 2019 Thomas Hiller +0127 % +0128 % This program is free software: you can redistribute it and/or modify +0129 % it under the terms of the GNU General Public License as published by +0130 % the Free Software Foundation, either version 3 of the License, or +0131 % (at your option) any later version. +0132 % +0133 % This program is distributed in the hope that it will be useful, +0134 % but WITHOUT ANY WARRANTY; without even the implied warranty of +0135 % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +0136 % GNU General Public License for more details. +0137 % +0138 % You should have received a copy of the GNU General Public License +0139 % along with this program. If not, see <https://www.gnu.org/licenses/>.

    Generated by m2html © 2005
    \ No newline at end of file diff --git a/doc/blochus/functions/interface/plotRamp.html b/doc/blochus/functions/interface/plotRamp.html index 840d1a9..aefd2fa 100644 --- a/doc/blochus/functions/interface/plotRamp.html +++ b/doc/blochus/functions/interface/plotRamp.html @@ -61,7 +61,7 @@

    CROSS-REFERENCE INFORMATION ^
 </ul>
 This function is called by:
 <ul style= -
  • onEditValue updates all edit field values, checks for wrong inputs and
  • onPopupPrePolRamp selects the pre-polarization switch-off ramp
  • +
  • onEditValue updates all edit field values, checks for wrong inputs and
  • onPopupPrePolRamp selects the pre-polarization switch-off ramp
  • onPushAnimate animates the results of the latest simulation
  • diff --git a/doc/blochus/functions/interface/plotResults.html b/doc/blochus/functions/interface/plotResults.html index d0b9010..4e3cd31 100644 --- a/doc/blochus/functions/interface/plotResults.html +++ b/doc/blochus/functions/interface/plotResults.html @@ -63,7 +63,7 @@

    CROSS-REFERENCE INFORMATION ^
 <li><a href=getOmega0 calculates the angular frequency from a given B-field and
  • clearSingleAxis clears an individual axis
  • plotBSphere plots a (Bloch)-Sphere (basically a unit sphere) with
  • This function is called by: +
  • onMenuImport handles the extra menu entries
  • onPushAnimate animates the results of the latest simulation
  • onPushRun starts the calculation
  • SUBFUNCTIONS ^

    @@ -168,237 +168,242 @@

    SOURCE CODE ^end -0098 % norm of magnetization vector -0099 Mamp = sqrt(M(:,1).^2+M(:,2).^2+M(:,3).^2); -0100 -0101 % normalize M in case of pre-polarization -0102 % and adjust axis limits -0103 switch data.basic.type -0104 case {'prepol','prepolpulse'} -0105 M = M./data.basic.B0; -0106 Mamp = Mamp./data.basic.B0; -0107 d = max(M(:))-min(M(:)); -0108 ymin = min(M(:))-d/20; -0109 ymax = max(M(:))+d/20; -0110 otherwise -0111 ymin = -1.05; -0112 ymax = 1.05; -0113 end -0114 -0115 % plot the data -0116 clearSingleAxis(ax); -0117 hold(ax,'on'); -0118 plot(T,M(:,1),'LineWidth',gui.myui.linewidth,'Color','r','Parent',ax); -0119 plot(T,M(:,2),'LineWidth',gui.myui.linewidth,'Color','g','Parent',ax); -0120 plot(T,M(:,3),'LineWidth',gui.myui.linewidth,'Color','b','Parent',ax); -0121 plot(T,sqrt(M(:,1).^2+M(:,2).^2),'LineWidth',gui.myui.linewidth,... -0122 'Color','m','Parent',ax); -0123 plot(T,Mamp,'LineWidth',gui.myui.linewidth,'Color','k',... -0124 'LineStyle','--','Parent',ax); -0125 set(ax,'XLim',[min(T) max(T)],'YLim',[ymin ymax]); -0126 -0127 % ------------------------------------------------------------------------- -0128 % plot vertical line at end of switch-off ramp -0129 if (strcmp(data.basic.type,'prepol') || strcmp(data.basic.type,'prepolpulse'))... -0130 && Tramp < Tsim -0131 plot([Tramp Tramp],get(ax,'YLim'),'LineStyle','--',... -0132 'Color',myui.color.prepol,'LineWidth',1,'Tag','MarkerLines',... -0133 'HandleVisibility','off','Parent',ax); -0134 end -0135 % plot vertical line at end of pulse -0136 if strcmp(data.basic.type,'pulse') && Ttau < Tsim -0137 plot([Ttau Ttau],get(ax,'YLim'),'LineStyle','--',... -0138 'Color',myui.color.pulse,'LineWidth',1,'Tag','MarkerLines',... -0139 'HandleVisibility','off','Parent',ax); -0140 end -0141 % plot vertical line at end of pulse -0142 if strcmp(data.basic.type,'prepolpulse') -0143 plot([Ttau+Tramp+Twait Ttau+Tramp+Twait],get(ax,'YLim'),'LineStyle','--',... -0144 'Color',myui.color.pulse,'LineWidth',1,'Tag','MarkerLines',... -0145 'HandleVisibility','off','Parent',ax); -0146 if Twait > 0 -0147 plot([Tramp+Twait Tramp+Twait],get(ax,'YLim'),'LineStyle','--',... -0148 'Color',myui.color.wait,'LineWidth',1,'Tag','MarkerLines',... -0149 'HandleVisibility','off','Parent',ax); -0150 end -0151 end -0152 % ------------------------------------------------------------------------- -0153 hold(ax,'off'); -0154 -0155 % axis settings -0156 grid(ax,'on'); -0157 set(get(ax,'XLabel'),'String','t [ms]'); -0158 set(get(ax,'YLabel'),'String','magnetization M'); -0159 % legend -0160 lh = legend(ax,'x','y','z','|xy|','|M|','Location','SouthWest'); -0161 -0162 % adiabatic quality of switch-off ramp -0163 if strcmp(data.basic.type,'prepol') || strcmp(data.basic.type,'prepolpulse') -0164 set(get(lh,'Title'),'String',['p=',sprintf('%4.3f',data.results.prepol.p)]) -0165 end -0166 % font size -0167 set(ax,'FontSize',gui.myui.axfontsize); -0168 -0169 end +0098 % xy-component of magnetization vector +0099 Mxy = sqrt(M(:,1).^2+M(:,2).^2); +0100 % norm of magnetization vector +0101 Mamp = sqrt(M(:,1).^2+M(:,2).^2+M(:,3).^2); +0102 +0103 % normalize M in case of pre-polarization +0104 % and adjust axis limits +0105 switch data.basic.type +0106 case {'prepol','prepolpulse'} +0107 M = M./data.basic.B0; +0108 Mxy = Mxy./data.basic.B0; +0109 Mamp = Mamp./data.basic.B0; +0110 d = max([M(:);Mxy(:)])-min([M(:);Mxy(:)]); +0111 ymin = min([M(:);Mxy(:)])-d/20; +0112 ymax = max([M(:);Mxy(:)])+d/20; +0113 otherwise +0114 ymin = -1.05; +0115 ymax = 1.05; +0116 end +0117 +0118 % plot the data +0119 clearSingleAxis(ax); +0120 hold(ax,'on'); +0121 plot(T,M(:,1),'LineWidth',myui.linewidth,'Color','r','Parent',ax); +0122 plot(T,M(:,2),'LineWidth',myui.linewidth,'Color','g','Parent',ax); +0123 plot(T,M(:,3),'LineWidth',myui.linewidth,'Color','b','Parent',ax); +0124 plot(T,Mxy,'LineWidth',myui.linewidth,'Color','m','Parent',ax); +0125 plot(T,Mamp,'LineWidth',myui.linewidth,'Color','k',... +0126 'LineStyle','--','Parent',ax); +0127 set(ax,'XLim',[min(T) max(T)],'YLim',[ymin ymax]); +0128 +0129 % ------------------------------------------------------------------------- +0130 % plot vertical line at end of switch-off ramp +0131 if (strcmp(data.basic.type,'prepol') || strcmp(data.basic.type,'prepolpulse'))... +0132 && Tramp < Tsim +0133 plot([Tramp Tramp],get(ax,'YLim'),'LineStyle','--',... +0134 'Color',myui.color.prepol,'LineWidth',1,'Tag','MarkerLines',... +0135 'HandleVisibility','off','Parent',ax); +0136 end +0137 % plot vertical line at end of pulse +0138 if strcmp(data.basic.type,'pulse') && Ttau < Tsim +0139 plot([Ttau Ttau],get(ax,'YLim'),'LineStyle','--',... +0140 'Color',myui.color.pulse,'LineWidth',1,'Tag','MarkerLines',... +0141 'HandleVisibility','off','Parent',ax); +0142 end +0143 % plot vertical line at end of pulse +0144 if strcmp(data.basic.type,'prepolpulse') +0145 plot([Ttau+Tramp+Twait Ttau+Tramp+Twait],get(ax,'YLim'),'LineStyle','--',... +0146 'Color',myui.color.pulse,'LineWidth',1,'Tag','MarkerLines',... +0147 'HandleVisibility','off','Parent',ax); +0148 if Twait > 0 +0149 plot([Tramp+Twait Tramp+Twait],get(ax,'YLim'),'LineStyle','--',... +0150 'Color',myui.color.wait,'LineWidth',1,'Tag','MarkerLines',... +0151 'HandleVisibility','off','Parent',ax); +0152 end +0153 end +0154 % ------------------------------------------------------------------------- +0155 hold(ax,'off'); +0156 +0157 % axis settings +0158 grid(ax,'on'); +0159 set(get(ax,'XLabel'),'String','t [ms]'); +0160 set(get(ax,'YLabel'),'String','magnetization M'); +0161 % legend +0162 lh = legend(ax,'x','y','z','|xy|','|M|','Location','SouthWest'); +0163 +0164 % adiabatic quality of switch-off ramp +0165 if strcmp(data.basic.type,'prepol') || strcmp(data.basic.type,'prepolpulse') +0166 set(get(lh,'Title'),'String',['p=',sprintf('%4.3f',data.results.prepol.p)]) +0167 end +0168 % font size +0169 set(ax,'FontSize',myui.axfontsize); 0170 -0171 %% magnetization components on Bloch sphere -0172 function plotSphere(data,gui,frame) -0173 myui = gui.myui; -0174 -0175 % for plotting everything is in [ms] -0176 T = data.results.basic.T.*1e3; -0177 -0178 % all relevant time marker -0179 Tsim = data.basic.Tsim; -0180 Ttau = data.pulse.Ttau; -0181 Tramp = data.prepol.Tramp; -0182 Twait = data.pulse.Twait; -0183 -0184 % choose reference frame to plot -0185 switch frame -0186 case 'lab' -0187 M = data.results.basic.M; -0188 ax = gui.axes_handles.SphereL; -0189 case 'rot' -0190 M = data.results.basic.Mrot; -0191 ax = gui.axes_handles.SphereR; -0192 end -0193 % norm of magnetization vector -0194 Mamp = sqrt(M(:,1).^2+M(:,2).^2+M(:,3).^2); -0195 -0196 % for visualization purposes M always gets normalized on Bloch sphere -0197 M = M./Mamp(1); -0198 -0199 % chhose what to plot depending on simulation type -0200 switch data.basic.type -0201 case 'std' -0202 indS1 = 1:numel(T); % relaxation -0203 indS2 = []; % relaxation at end of "prepolpulse"-type -0204 indR = []; % switch-off ramp -0205 indB = []; % switch-off B-field -0206 indP = []; % pulse -0207 indE = numel(T); % end point -0208 Beffn = [0 0 0]; -0209 -0210 case 'prepol' -0211 indS1 = T>Tramp; -0212 indS2 = []; -0213 indR = T<=Tramp; -0214 indB = []; -0215 indP = []; -0216 indE = numel(T); -0217 % switch-off B-field trajectory -0218 Bamp = sqrt(data.results.prepol.Beff(:,1).^2+data.results.prepol.Beff(:,2).^2+data.results.prepol.Beff(:,3).^2); -0219 Beffn = data.results.prepol.Beff./Bamp; -0220 -0221 case 'pulse' -0222 indS1 = T>Ttau; -0223 indS2 = []; -0224 indR = []; -0225 indB = []; -0226 indP = T<=Ttau; -0227 indE = numel(T); -0228 Beffn = [0 0 0]; -0229 -0230 case 'prepolpulse' -0231 indS2 = T>Tramp & T<=Tramp+Twait; -0232 indS1 = T>Tramp+Twait+Ttau; -0233 indR = T<=Tramp; -0234 indB = []; -0235 indP = T>Tramp+Twait & T<=Tramp+Twait+Ttau; -0236 indE = numel(T); -0237 % switch-off B-field trajectory -0238 Bamp = sqrt(data.results.prepol.Beff(:,1).^2+data.results.prepol.Beff(:,2).^2+data.results.prepol.Beff(:,3).^2); -0239 Beffn = data.results.prepol.Beff./Bamp; -0240 end -0241 -0242 % plot data -0243 clearSingleAxis(ax); -0244 hold(ax,'on'); -0245 plot3(M(indS1,1),M(indS1,2),M(indS1,3),'LineWidth',gui.myui.linewidth,... -0246 'Color',myui.color.basic,'Parent',ax); -0247 plot3(M(indS2,1),M(indS2,2),M(indS2,3),'LineWidth',gui.myui.linewidth,... -0248 'Color',myui.color.wait,'Parent',ax); -0249 plot3(M(indP,1),M(indP,2),M(indP,3),'LineWidth',gui.myui.linewidth,... -0250 'Color',myui.color.pulse,'Parent',ax); -0251 plot3(M(indR,1),M(indR,2),M(indR,3),'LineWidth',gui.myui.linewidth,... -0252 'Color',myui.color.prepol,'Parent',ax); -0253 plot3(Beffn(:,1),Beffn(:,2),Beffn(:,3),'LineWidth',gui.myui.linewidth,... -0254 'Color',myui.color.prepolB,'Parent',ax) -0255 plot3(M(indE,1),M(indE,2),M(indE,3),'ko','MarkerSize',8,'Parent',ax); -0256 % plot actual Bloch sphere -0257 plotBSphere(18,18,ax); -0258 % axis settings -0259 view(ax,[-35 30]); -0260 hold(ax,'off'); -0261 set(ax,'XLim',[-1.05 1.05],'YLim',[-1.05 1.05],'ZLim',[-1.05 1.05]) -0262 set(ax,'Color','w','XColor','none','YColor','none','ZColor','none'); -0263 axis(ax,'equal'); -0264 axis(ax,'tight'); -0265 -0266 end -0267 -0268 %% FFT of magnetization and pulse -0269 function plotFFT(data,gui,type) -0270 myui = gui.myui; +0171 end +0172 +0173 %% magnetization components on Bloch sphere +0174 function plotSphere(data,gui,frame) +0175 myui = gui.myui; +0176 +0177 % for plotting everything is in [ms] +0178 T = data.results.basic.T.*1e3; +0179 +0180 % all relevant time marker +0181 Tsim = data.basic.Tsim; +0182 Ttau = data.pulse.Ttau; +0183 Tramp = data.prepol.Tramp; +0184 Twait = data.pulse.Twait; +0185 +0186 % choose reference frame to plot +0187 switch frame +0188 case 'lab' +0189 M = data.results.basic.M; +0190 ax = gui.axes_handles.SphereL; +0191 case 'rot' +0192 M = data.results.basic.Mrot; +0193 ax = gui.axes_handles.SphereR; +0194 end +0195 % norm of magnetization vector +0196 Mamp = sqrt(M(:,1).^2+M(:,2).^2+M(:,3).^2); +0197 +0198 % for visualization purposes M always gets normalized on Bloch sphere +0199 M = M./Mamp(1); +0200 +0201 % chhose what to plot depending on simulation type +0202 switch data.basic.type +0203 case 'std' +0204 indS1 = 1:numel(T); % relaxation +0205 indS2 = []; % relaxation at end of "prepolpulse"-type +0206 indR = []; % switch-off ramp +0207 indB = []; % switch-off B-field +0208 indP = []; % pulse +0209 indE = numel(T); % end point +0210 Beffn = [0 0 0]; +0211 +0212 case 'prepol' +0213 indS1 = T>Tramp; +0214 indS2 = []; +0215 indR = T<=Tramp; +0216 indB = []; +0217 indP = []; +0218 indE = numel(T); +0219 % switch-off B-field trajectory +0220 Bamp = sqrt(data.results.prepol.Beff(:,1).^2+... +0221 data.results.prepol.Beff(:,2).^2+... +0222 data.results.prepol.Beff(:,3).^2); +0223 Beffn = data.results.prepol.Beff./Bamp; +0224 +0225 case 'pulse' +0226 indS1 = T>Ttau; +0227 indS2 = []; +0228 indR = []; +0229 indB = []; +0230 indP = T<=Ttau; +0231 indE = numel(T); +0232 Beffn = [0 0 0]; +0233 +0234 case 'prepolpulse' +0235 indS2 = T>Tramp & T<=Tramp+Twait; +0236 indS1 = T>Tramp+Twait+Ttau; +0237 indR = T<=Tramp; +0238 indB = []; +0239 indP = T>Tramp+Twait & T<=Tramp+Twait+Ttau; +0240 indE = numel(T); +0241 % switch-off B-field trajectory +0242 Bamp = sqrt(data.results.prepol.Beff(:,1).^2+... +0243 data.results.prepol.Beff(:,2).^2+... +0244 data.results.prepol.Beff(:,3).^2); +0245 Beffn = data.results.prepol.Beff./Bamp; +0246 end +0247 +0248 % plot data +0249 clearSingleAxis(ax); +0250 hold(ax,'on'); +0251 plot3(M(indS1,1),M(indS1,2),M(indS1,3),'LineWidth',myui.linewidth,... +0252 'Color',myui.color.basic,'Parent',ax); +0253 plot3(M(indS2,1),M(indS2,2),M(indS2,3),'LineWidth',myui.linewidth,... +0254 'Color',myui.color.wait,'Parent',ax); +0255 plot3(M(indP,1),M(indP,2),M(indP,3),'LineWidth',myui.linewidth,... +0256 'Color',myui.color.pulse,'Parent',ax); +0257 plot3(M(indR,1),M(indR,2),M(indR,3),'LineWidth',myui.linewidth,... +0258 'Color',myui.color.prepol,'Parent',ax); +0259 plot3(Beffn(:,1),Beffn(:,2),Beffn(:,3),'LineWidth',myui.linewidth,... +0260 'Color',myui.color.prepolB,'Parent',ax) +0261 plot3(M(indE,1),M(indE,2),M(indE,3),'ko','MarkerSize',8,'Parent',ax); +0262 % plot actual Bloch sphere +0263 plotBSphere(18,18,ax); +0264 % axis settings +0265 view(ax,[-35 30]); +0266 hold(ax,'off'); +0267 set(ax,'XLim',[-1.05 1.05],'YLim',[-1.05 1.05],'ZLim',[-1.05 1.05]) +0268 set(ax,'Color','w','XColor','none','YColor','none','ZColor','none'); +0269 axis(ax,'equal'); +0270 axis(ax,'tight'); 0271 -0272 % Larmor freq. [Hz] -0273 fL = getOmega0(data.basic.gamma,data.basic.B0)/2/pi; -0274 -0275 % choose what to plot -0276 switch type -0277 case 'M' -0278 ax = gui.axes_handles.MagFFT; -0279 f = data.results.basic.Mspec.fx; -0280 X = data.results.basic.Mspec.X; -0281 lgdstr = {'Mxy','\omega_0'}; -0282 case 'B' -0283 ax = gui.axes_handles.PulseFFT; -0284 f = data.results.pulse.Bspec.fx; -0285 X = data.results.pulse.Bspec.X; -0286 lgdstr = {'B','\omega_0'}; -0287 end -0288 -0289 % plot data -0290 clearSingleAxis(ax); -0291 hold(ax,'on'); -0292 plot(f,abs(X),'r','Parent',ax); -0293 % vertical line indicating Larmor frequency -0294 line([fL fL],[0 max(abs(X))],'Color','k','LineStyle','--',... -0295 'LineWidth',0.75,'Parent',ax); -0296 hold(ax,'off'); -0297 % axis settings -0298 set(ax,'XLim',[-abs(2*fL) abs(2*fL)],'YLim',[0 max(abs(X))].*1.1); -0299 grid(ax,'on'); -0300 set(get(ax,'XLabel'),'String','F [Hz]'); -0301 set(get(ax,'YLabel'),'String','amplitude'); -0302 % legend -0303 legend(ax,lgdstr,'Location','NorthEast'); -0304 % font size -0305 set(ax,'FontSize',gui.myui.axfontsize); -0306 -0307 end -0308 -0309 %------------- END OF CODE -------------- -0310 -0311 %% License: -0312 % GNU GPLv3 -0313 % -0314 % BLOCHUS -0315 % Copyright (C) 2019 Thomas Hiller -0316 % -0317 % This program is free software: you can redistribute it and/or modify -0318 % it under the terms of the GNU General Public License as published by -0319 % the Free Software Foundation, either version 3 of the License, or -0320 % (at your option) any later version. +0272 end +0273 +0274 %% FFT of magnetization and pulse +0275 function plotFFT(data,gui,type) +0276 +0277 % Larmor freq. [Hz] +0278 fL = getOmega0(data.basic.gamma,data.basic.B0)/2/pi; +0279 +0280 % choose what to plot +0281 switch type +0282 case 'M' +0283 ax = gui.axes_handles.MagFFT; +0284 f = data.results.basic.Mspec.fx; +0285 X = data.results.basic.Mspec.X; +0286 lgdstr = {'Mxy','\omega_0'}; +0287 case 'B' +0288 ax = gui.axes_handles.PulseFFT; +0289 f = data.results.pulse.Bspec.fx; +0290 X = data.results.pulse.Bspec.X; +0291 lgdstr = {'B','\omega_0'}; +0292 end +0293 +0294 % plot data +0295 clearSingleAxis(ax); +0296 hold(ax,'on'); +0297 plot(f,abs(X),'r','Parent',ax); +0298 % vertical line indicating Larmor frequency +0299 line([fL fL],[0 max(abs(X))],'Color','k','LineStyle','--',... +0300 'LineWidth',0.75,'Parent',ax); +0301 hold(ax,'off'); +0302 % axis settings +0303 set(ax,'XLim',[-abs(2*fL) abs(2*fL)],'YLim',[0 max(abs(X))].*1.1); +0304 grid(ax,'on'); +0305 set(get(ax,'XLabel'),'String','F [Hz]'); +0306 set(get(ax,'YLabel'),'String','amplitude'); +0307 % legend +0308 legend(ax,lgdstr,'Location','NorthEast'); +0309 % font size +0310 set(ax,'FontSize',gui.myui.axfontsize); +0311 +0312 end +0313 +0314 %------------- END OF CODE -------------- +0315 +0316 %% License: +0317 % GNU GPLv3 +0318 % +0319 % BLOCHUS +0320 % Copyright (C) 2019 Thomas Hiller 0321 % -0322 % This program is distributed in the hope that it will be useful, -0323 % but WITHOUT ANY WARRANTY; without even the implied warranty of -0324 % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -0325 % GNU General Public License for more details. +0322 % This program is free software: you can redistribute it and/or modify +0323 % it under the terms of the GNU General Public License as published by +0324 % the Free Software Foundation, either version 3 of the License, or +0325 % (at your option) any later version. 0326 % -0327 % You should have received a copy of the GNU General Public License -0328 % along with this program. If not, see <https://www.gnu.org/licenses/>.

    +0327 % This program is distributed in the hope that it will be useful, +0328 % but WITHOUT ANY WARRANTY; without even the implied warranty of +0329 % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +0330 % GNU General Public License for more details. +0331 % +0332 % You should have received a copy of the GNU General Public License +0333 % along with this program. If not, see <https://www.gnu.org/licenses/>.

    Generated by m2html © 2005
    \ No newline at end of file diff --git a/functions/interface/getPulseParameters.m b/functions/interface/getPulseParameters.m index cf389ae..43c730c 100644 --- a/functions/interface/getPulseParameters.m +++ b/functions/interface/getPulseParameters.m @@ -239,12 +239,20 @@ function getPulseParameters(fig) % dummy time vector [ms] data.results.pulse.t = pulse_t'.*1e3; +% get FFT of the pulse +[Xb,fbx] = getFFT(pulse_t(:),pulse_Bxy(:,1:2)); + % update data data.results.pulse.fmod = fmod; data.results.pulse.Imod = Imod; data.results.pulse.df = df; data.results.pulse.I = I; data.results.pulse.Bxy = pulse_Bxy; +data.results.pulse.Bspec.fx = fbx; +data.results.pulse.Bspec.X = Xb; + +% because the pulse data changed, deactivate the "Animate" button +set(gui.push_handles.Animate,'Enable','off'); % update GUI data setappdata(fig,'data',data); diff --git a/functions/interface/getRampParameters.m b/functions/interface/getRampParameters.m index 14ea588..56553f5 100644 --- a/functions/interface/getRampParameters.m +++ b/functions/interface/getRampParameters.m @@ -101,6 +101,8 @@ function getRampParameters(fig) data.results.prepol.omega = omega; data.results.prepol.dadt = dadt; +% because the ramp data changed, deactivate the "Animate" button +set(gui.push_handles.Animate,'Enable','off'); % update GUI data setappdata(fig,'data',data); diff --git a/functions/interface/plotBpulse.m b/functions/interface/plotPulse.m similarity index 78% rename from functions/interface/plotBpulse.m rename to functions/interface/plotPulse.m index 1fb3983..74c969c 100644 --- a/functions/interface/plotBpulse.m +++ b/functions/interface/plotPulse.m @@ -1,8 +1,8 @@ -function plotBpulse(fig) -%plotBpulse plots different pulse parameter +function plotPulse(fig) +%plotPulse plots different pulse parameter % % Syntax: -% plotBpulse(fig) +% plotPulse(fig) % % Inputs: % fig - figure handle @@ -11,7 +11,7 @@ function plotBpulse(fig) % none % % Example: -% plotBpulse(gui.figh) +% plotPulse(gui.figh) % % Other m-files required: % none @@ -90,6 +90,31 @@ function plotBpulse(fig) legend(ax,'x','y','Location','SouthWest'); set(ax,'FontSize',myui.axfontsize); +%% FFT +% Larmor freq. [Hz] +fL = getOmega0(data.basic.gamma,data.basic.B0)/2/pi; + +ax = gui.axes_handles.PulseFFT; +f = data.results.pulse.Bspec.fx; +X = data.results.pulse.Bspec.X; +% plot data +clearSingleAxis(ax); +hold(ax,'on'); +plot(f,abs(X),'r','Parent',ax); +% vertical line indicating Larmor frequency +line([fL fL],[0 max(abs(X))],'Color','k','LineStyle','--',... + 'LineWidth',0.75,'Parent',ax); +hold(ax,'off'); +% axis settings +set(ax,'XLim',[-abs(2*fL) abs(2*fL)],'YLim',[0 max(abs(X))].*1.1); +grid(ax,'on'); +set(get(ax,'XLabel'),'String','F [Hz]'); +set(get(ax,'YLabel'),'String','amplitude'); +% legend +legend(ax,'B','\omega_0','Location','NorthEast'); +% font size +set(ax,'FontSize',myui.axfontsize); + end %------------- END OF CODE -------------- diff --git a/functions/interface/plotResults.m b/functions/interface/plotResults.m index 1017835..f226b50 100644 --- a/functions/interface/plotResults.m +++ b/functions/interface/plotResults.m @@ -95,6 +95,8 @@ function plotMag(data,gui,frame) M = data.results.basic.Mrot; ax = gui.axes_handles.MagR; end +% xy-component of magnetization vector +Mxy = sqrt(M(:,1).^2+M(:,2).^2); % norm of magnetization vector Mamp = sqrt(M(:,1).^2+M(:,2).^2+M(:,3).^2); @@ -103,10 +105,11 @@ function plotMag(data,gui,frame) switch data.basic.type case {'prepol','prepolpulse'} M = M./data.basic.B0; + Mxy = Mxy./data.basic.B0; Mamp = Mamp./data.basic.B0; - d = max(M(:))-min(M(:)); - ymin = min(M(:))-d/20; - ymax = max(M(:))+d/20; + d = max([M(:);Mxy(:)])-min([M(:);Mxy(:)]); + ymin = min([M(:);Mxy(:)])-d/20; + ymax = max([M(:);Mxy(:)])+d/20; otherwise ymin = -1.05; ymax = 1.05; @@ -115,12 +118,11 @@ function plotMag(data,gui,frame) % plot the data clearSingleAxis(ax); hold(ax,'on'); -plot(T,M(:,1),'LineWidth',gui.myui.linewidth,'Color','r','Parent',ax); -plot(T,M(:,2),'LineWidth',gui.myui.linewidth,'Color','g','Parent',ax); -plot(T,M(:,3),'LineWidth',gui.myui.linewidth,'Color','b','Parent',ax); -plot(T,sqrt(M(:,1).^2+M(:,2).^2),'LineWidth',gui.myui.linewidth,... - 'Color','m','Parent',ax); -plot(T,Mamp,'LineWidth',gui.myui.linewidth,'Color','k',... +plot(T,M(:,1),'LineWidth',myui.linewidth,'Color','r','Parent',ax); +plot(T,M(:,2),'LineWidth',myui.linewidth,'Color','g','Parent',ax); +plot(T,M(:,3),'LineWidth',myui.linewidth,'Color','b','Parent',ax); +plot(T,Mxy,'LineWidth',myui.linewidth,'Color','m','Parent',ax); +plot(T,Mamp,'LineWidth',myui.linewidth,'Color','k',... 'LineStyle','--','Parent',ax); set(ax,'XLim',[min(T) max(T)],'YLim',[ymin ymax]); @@ -164,7 +166,7 @@ function plotMag(data,gui,frame) set(get(lh,'Title'),'String',['p=',sprintf('%4.3f',data.results.prepol.p)]) end % font size -set(ax,'FontSize',gui.myui.axfontsize); +set(ax,'FontSize',myui.axfontsize); end @@ -215,7 +217,9 @@ function plotSphere(data,gui,frame) indP = []; indE = numel(T); % switch-off B-field trajectory - Bamp = sqrt(data.results.prepol.Beff(:,1).^2+data.results.prepol.Beff(:,2).^2+data.results.prepol.Beff(:,3).^2); + Bamp = sqrt(data.results.prepol.Beff(:,1).^2+... + data.results.prepol.Beff(:,2).^2+... + data.results.prepol.Beff(:,3).^2); Beffn = data.results.prepol.Beff./Bamp; case 'pulse' @@ -235,22 +239,24 @@ function plotSphere(data,gui,frame) indP = T>Tramp+Twait & T<=Tramp+Twait+Ttau; indE = numel(T); % switch-off B-field trajectory - Bamp = sqrt(data.results.prepol.Beff(:,1).^2+data.results.prepol.Beff(:,2).^2+data.results.prepol.Beff(:,3).^2); + Bamp = sqrt(data.results.prepol.Beff(:,1).^2+... + data.results.prepol.Beff(:,2).^2+... + data.results.prepol.Beff(:,3).^2); Beffn = data.results.prepol.Beff./Bamp; end % plot data clearSingleAxis(ax); hold(ax,'on'); -plot3(M(indS1,1),M(indS1,2),M(indS1,3),'LineWidth',gui.myui.linewidth,... +plot3(M(indS1,1),M(indS1,2),M(indS1,3),'LineWidth',myui.linewidth,... 'Color',myui.color.basic,'Parent',ax); -plot3(M(indS2,1),M(indS2,2),M(indS2,3),'LineWidth',gui.myui.linewidth,... +plot3(M(indS2,1),M(indS2,2),M(indS2,3),'LineWidth',myui.linewidth,... 'Color',myui.color.wait,'Parent',ax); -plot3(M(indP,1),M(indP,2),M(indP,3),'LineWidth',gui.myui.linewidth,... +plot3(M(indP,1),M(indP,2),M(indP,3),'LineWidth',myui.linewidth,... 'Color',myui.color.pulse,'Parent',ax); -plot3(M(indR,1),M(indR,2),M(indR,3),'LineWidth',gui.myui.linewidth,... +plot3(M(indR,1),M(indR,2),M(indR,3),'LineWidth',myui.linewidth,... 'Color',myui.color.prepol,'Parent',ax); -plot3(Beffn(:,1),Beffn(:,2),Beffn(:,3),'LineWidth',gui.myui.linewidth,... +plot3(Beffn(:,1),Beffn(:,2),Beffn(:,3),'LineWidth',myui.linewidth,... 'Color',myui.color.prepolB,'Parent',ax) plot3(M(indE,1),M(indE,2),M(indE,3),'ko','MarkerSize',8,'Parent',ax); % plot actual Bloch sphere @@ -267,7 +273,6 @@ function plotSphere(data,gui,frame) %% FFT of magnetization and pulse function plotFFT(data,gui,type) -myui = gui.myui; % Larmor freq. [Hz] fL = getOmega0(data.basic.gamma,data.basic.B0)/2/pi;