diff --git a/BLOCHUS/BLOCHUS.m b/BLOCHUS/BLOCHUS.m index 140ba1e..9564ca4 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.2'; -myui.date = '17.05.2020'; +myui.version = '0.1.3'; +myui.date = '22.05.2020'; myui.author = 'Thomas Hiller'; myui.email = 'thomas.hiller[at]leibniz-liag.de'; diff --git a/BLOCHUS/BLOCHUS_createGUI.m b/BLOCHUS/BLOCHUS_createGUI.m index 7c5d72c..d263292 100644 --- a/BLOCHUS/BLOCHUS_createGUI.m +++ b/BLOCHUS/BLOCHUS_createGUI.m @@ -143,9 +143,9 @@ function BLOCHUS_createGUI(h,wbon) set(gui.main,'Visible','on'); %% enable all menus -set(gui.menu.file,'Enable','on'); -set(gui.menu.view,'Enable','on'); -set(gui.menu.help,'Enable','on'); +set(gui.menu_handles.file,'Enable','on'); +set(gui.menu_handles.view,'Enable','on'); +set(gui.menu_handles.help,'Enable','on'); %% update the GUI data gui.myui = myui; diff --git a/BLOCHUS/BLOCHUS_createMenus.m b/BLOCHUS/BLOCHUS_createMenus.m index a11b74c..c0f58ba 100644 --- a/BLOCHUS/BLOCHUS_createMenus.m +++ b/BLOCHUS/BLOCHUS_createMenus.m @@ -30,65 +30,77 @@ %------------- BEGIN CODE -------------- %% 1. File -gui.menu.file = uimenu(gui.figh,... - 'Label','File','Enable','off'); +gui.menu_handles.file = uimenu(gui.figh,... + 'Label','File',... + 'Enable','off'); % 1.1 Import -gui.menu.file_import = uimenu(gui.menu.file,... - 'Label','Import','Enable','on'); - -% 1.1.1 BLOCHUS session file -gui.menu.file_import_session = uimenu(gui.menu.file_import,... - 'Label','Session file','Callback',@onMenuImport); +gui.menu_handles.file_import = uimenu(gui.menu_handles.file,... + 'Label','Import Data',... + 'Callback',@onMenuImport); % 1.2 Export -gui.menu.file_export = uimenu(gui.menu.file,... - 'Label','Export'); - -% 1.2.1 BLOCHUS session file -gui.menu.file_export_session = uimenu(gui.menu.file_export,... - 'Label','Session file','Callback',@onMenuExport); +gui.menu_handles.file_export = uimenu(gui.menu_handles.file,... + 'Label','Export Data',... + 'Callback',@onMenuExport); % 1.3 Restart -gui.menu.file_restart = uimenu(gui.menu.file,... - 'Label','Restart','Separator','on','Callback',@onMenuRestartQuit); +gui.menu_handles.file_restart = uimenu(gui.menu_handles.file,... + 'Label','Restart',... + 'Separator','on',... + 'Callback',@onMenuRestartQuit); % 1.4 Quit -gui.menu.file_quit = uimenu(gui.menu.file,... - 'Label','Quit','Separator','on','Callback',@onMenuRestartQuit); +gui.menu_handles.file_quit = uimenu(gui.menu_handles.file,... + 'Label','Quit',... + 'Callback',@onMenuRestartQuit); %% 2. Extras -gui.menu.view = uimenu(gui.figh,... - 'Label','View','Enable','off'); +gui.menu_handles.view = uimenu(gui.figh,... + 'Label','View',... + 'Enable','off'); + % 2.1 Tooltips (on/off) -gui.menu.view_tooltips = uimenu(gui.menu.view,... - 'Label','Tooltips','Checked','on','Callback',@onMenuViewShow); +gui.menu_handles.view_tooltips = uimenu(gui.menu_handles.view,... + 'Label','Tooltips',... + 'Checked','on',... + 'Callback',@onMenuView); + % 2.2 Figure Toolbar -gui.menu.view_toolbar = uimenu(gui.menu.view,... - 'Label','Figure Toolbar','Callback',@onMenuViewShow); -% 2.3.1 Tigures -gui.menu.view_figures = uimenu(gui.menu.view,... +gui.menu_handles.view_toolbar = uimenu(gui.menu_handles.view,... + 'Label','Figure Toolbar',... + 'Callback',@onMenuView); +% 2.3.1 Figures +gui.menu_handles.view_figures = uimenu(gui.menu_handles.view,... 'Label','Figures','Separator','on'); % 2.3.1.1 current -gui.menu.view_figures_current = uimenu(gui.menu.view_figures,... - 'Label','Current View','Callback',@onMenuViewFigure); +gui.menu_handles.view_figures_current = uimenu(gui.menu_handles.view_figures,... + 'Label','Current View',... + 'Callback',@onMenuViewFigure); % 2.3.1.2 only magnetization -gui.menu.view_figures_mag = uimenu(gui.menu.view_figures,... - 'Label','Magnetization','Callback',@onMenuViewFigure); +gui.menu_handles.view_figures_mag = uimenu(gui.menu_handles.view_figures,... + 'Label','Magnetization',... + 'Callback',@onMenuViewFigure); % 2.3.1.3 only ramp -gui.menu.view_figures_ramp = uimenu(gui.menu.view_figures,... - 'Label','Switch-off Ramp','Enable','off','Callback',@onMenuViewFigure); +gui.menu_handles.view_figures_ramp = uimenu(gui.menu_handles.view_figures,... + 'Label','Switch-off Ramp',... + 'Enable','off',... + 'Callback',@onMenuViewFigure); % 2.3.1.4 only pulse -gui.menu.view_figures_pulse = uimenu(gui.menu.view_figures,... - 'Label','Pulse','Enable','off','Callback',@onMenuViewFigure); +gui.menu_handles.view_figures_pulse = uimenu(gui.menu_handles.view_figures,... + 'Label','Pulse',... + 'Enable','off',... + 'Callback',@onMenuViewFigure); %% 3. Help -gui.menu.help = uimenu(gui.figh,... - 'Label','Help','Enable','off'); +gui.menu_handles.help = uimenu(gui.figh,... + 'Label','Help',... + 'Enable','off'); % 3.1 About -gui.menu.help_about = uimenu(gui.menu.help,... - 'Label','About','Callback',@onMenuHelp); +gui.menu_handles.help_about = uimenu(gui.menu_handles.help,... + 'Label','About',... + 'Callback',@onMenuHelp); return diff --git a/BLOCHUS/BLOCHUS_createPanelPulse.m b/BLOCHUS/BLOCHUS_createPanelPulse.m index 405b09d..db5a666 100644 --- a/BLOCHUS/BLOCHUS_createPanelPulse.m +++ b/BLOCHUS/BLOCHUS_createPanelPulse.m @@ -414,6 +414,8 @@ jh.setVerticalAlignment(javax.swing.JLabel.CENTER) jh = findjobj(gui.text_handles.PulseAxis); jh.setVerticalAlignment(javax.swing.JLabel.CENTER) +jh = findjobj(gui.text_handles.PulsePolarization); +jh.setVerticalAlignment(javax.swing.JLabel.CENTER) jh = findjobj(gui.text_handles.PulseB1Factor); jh.setVerticalAlignment(javax.swing.JLabel.CENTER) jh = findjobj(gui.text_handles.PulseTtau); diff --git a/CHANGELOG.md b/CHANGELOG.md index be506bd..83a8b33 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## [0.1.3] - 2020-05-22 + +### Added +- Two additional examples that demonstrate the creation of lookup tables (one example for pre-polarization switch-off ramps and one example for adiabatic excitation pulses). + +### Changed +- Minor GUI improvements and consistency clean ups. + ## [0.1.2] - 2020-05-17 ### Changed @@ -24,6 +32,7 @@ Initial Version +[0.1.3]: https://github.com/ThoHiller/nmr-blochus/compare/v0.1.2...v0.1.3 [0.1.2]: https://github.com/ThoHiller/nmr-blochus/compare/v.0.1.1...v0.1.2 [0.1.1]: https://github.com/ThoHiller/nmr-blochus/compare/v.0.1.0...v.0.1.1 [0.1.0]: https://github.com/ThoHiller/nmr-blochus/releases/tag/v.0.1.0 diff --git a/README.md b/README.md index 66673f0..d012435 100644 --- a/README.md +++ b/README.md @@ -85,14 +85,14 @@ In no particular order and without guarantee that it will ever happen :-) : ### Cite as If you use BLOCHUS for your research, please cite it as: -Thomas Hiller. (2020, May 17). ThoHiller/nmr-blochus: v0.1.2 (Version v0.1.2). Zenodo. [https://doi.org/10.5281/zenodo.3829464] +Thomas Hiller. (2020, May 22). ThoHiller/nmr-blochus: v0.1.3 (Version v0.1.3). Zenodo. [https://doi.org/10.5281/zenodo.3829464] Note: Even though the version number might change due to updates, this DOI is permanent (represents all versions) and always links to the latest version. ### References -1. Hiller, T., Dlugosch, R. and Müller-Petke, M., "Utilizing pre-polarization to enhance SNMR signals - effect of imperfect switch-off", Geophysical Journal International **0**(0), p.1-15, 2020, [DOI](https://doi.org/10.1093/gji/ggaa216) +1. Hiller, T., Dlugosch, R. and Müller-Petke, M., "Utilizing pre-polarization to enhance SNMR signals - effect of imperfect switch-off", Geophysical Journal International **222**(2), p.815-826, 2020, [DOI](https://doi.org/10.1093/gji/ggaa216) - - -

MATLAB is a registered trademark of The Mathworks, Inc.

\ No newline at end of file diff --git a/callbacks/checkbox/onCheckPrePolPulse.m b/callbacks/checkbox/onCheckPrePolPulse.m index 60739c8..e5435e3 100644 --- a/callbacks/checkbox/onCheckPrePolPulse.m +++ b/callbacks/checkbox/onCheckPrePolPulse.m @@ -47,8 +47,8 @@ function onCheckPrePolPulse(src,~) data.basic.type = 'std'; % menu settings - set(gui.menu.view_figures_ramp,'Enable','off'); - set(gui.menu.view_figures_pulse,'Enable','off'); + set(gui.menu_handles.view_figures_ramp,'Enable','off'); + set(gui.menu_handles.view_figures_pulse,'Enable','off'); % std settings data.basic.Minit = [1 0 0]; @@ -111,8 +111,8 @@ function onCheckPrePolPulse(src,~) data.basic.type = 'prepol'; % menu settings - set(gui.menu.view_figures_ramp,'Enable','on'); - set(gui.menu.view_figures_pulse,'Enable','off'); + set(gui.menu_handles.view_figures_ramp,'Enable','on'); + set(gui.menu_handles.view_figures_pulse,'Enable','off'); % std settings data.basic.Tsim = data.prepol.Tramp; @@ -173,8 +173,8 @@ function onCheckPrePolPulse(src,~) data.basic.type = 'pulse'; % menu settings - set(gui.menu.view_figures_ramp,'Enable','off'); - set(gui.menu.view_figures_pulse,'Enable','on'); + set(gui.menu_handles.view_figures_ramp,'Enable','off'); + set(gui.menu_handles.view_figures_pulse,'Enable','on'); % std settings data.basic.Tsim = data.pulse.Ttau; @@ -223,8 +223,8 @@ function onCheckPrePolPulse(src,~) data.basic.type = 'prepolpulse'; % menu settings - set(gui.menu.view_figures_ramp,'Enable','on'); - set(gui.menu.view_figures_pulse,'Enable','on'); + set(gui.menu_handles.view_figures_ramp,'Enable','on'); + set(gui.menu_handles.view_figures_pulse,'Enable','on'); % std settings data.basic.Minit = [1 0 0]; diff --git a/callbacks/menus/onMenuHelp.m b/callbacks/menus/onMenuHelp.m index b1c0bcc..e646df8 100644 --- a/callbacks/menus/onMenuHelp.m +++ b/callbacks/menus/onMenuHelp.m @@ -74,7 +74,7 @@ function onMenuHelp(src,~) % create Figure hf = figure('Name','About BLOCHUS',... 'NumberTitle','off','Tag','Help','ToolBar','none','MenuBar','none',... - 'Resize','off','Position',[xp yp ww hh]); + 'Resize','off','Position',[xp yp ww hh],'Visible','off'); v1 = uix.VBox('Parent',hf,'Padding',10,'Spacing',10); % text area @@ -116,6 +116,9 @@ function onMenuHelp(src,~) % text hack jh = findjobj(t1); jh.setVerticalAlignment(javax.swing.JLabel.CENTER) + + % make the figure content visible + set(hf,'Visible','on'); else warndlg({'onMenuHelp:','There is no figure with the BLOCHUS Tag open.'},... diff --git a/callbacks/menus/onMenuViewShow.m b/callbacks/menus/onMenuView.m similarity index 71% rename from callbacks/menus/onMenuViewShow.m rename to callbacks/menus/onMenuView.m index 9bf2c98..d7857f9 100644 --- a/callbacks/menus/onMenuViewShow.m +++ b/callbacks/menus/onMenuView.m @@ -1,8 +1,8 @@ -function onMenuViewShow(src,~) -%onMenuViewShow handles the extra menu entries +function onMenuView(src,~) +%onMenuView handles the extra menu entries % % Syntax: -% onMenuViewShow(src) +% onMenuView(src) % % Inputs: % src - handle of the calling object @@ -11,7 +11,7 @@ function onMenuViewShow(src,~) % none % % Example: -% onMenuViewShow(src,~) +% onMenuView(src,~) % % Other m-files required: % switchToolTips @@ -39,26 +39,25 @@ function onMenuViewShow(src,~) data = getappdata(fig,'data'); switch get(src,'Label') - case 'Tooltips' % switch on/off Tooltips - onoff = get(gui.menu.view_tooltips,'Checked'); - switchToolTips(gui,onoff); - switch onoff - case 'on' - set(gui.menu.view_tooltips,'Checked','off'); + case 'Tooltips' % switch on/off Tooltips + switch get(src,'Checked') + case 'on' % if it is on, switch it off + switchToolTips(gui,'off'); + set(src,'Checked','off'); data.info.ToolTips = 0; case 'off' - set(gui.menu.view_tooltips,'Checked','on'); + switchToolTips(gui,'on'); + set(src,'Checked','on'); data.info.ToolTips = 1; end case 'Figure Toolbar' % switch on/off the default Figure Toolbar - onoff = get(gui.menu.view_toolbar,'Checked'); - switch onoff - case 'on' - set(gui.menu.view_toolbar,'Checked','off'); + switch get(src,'Checked') + case 'on' % if it is on, switch it off + set(src,'Checked','off'); viewmenufcn('FigureToolbar'); case 'off' - set(gui.menu.view_toolbar,'Checked','on'); + set(src,'Checked','on'); viewmenufcn('FigureToolbar'); end end @@ -70,7 +69,7 @@ function onMenuViewShow(src,~) updateStatusInformation(fig); else - warndlg({'onMenuViewShow:','There is no figure with the BLOCHUS Tag open.'},... + warndlg({'onMenuView:','There is no figure with the BLOCHUS Tag open.'},... 'BLOCHUS error'); end diff --git a/callbacks/push/onPushRun.m b/callbacks/push/onPushRun.m index c66f4f6..a9f2c84 100644 --- a/callbacks/push/onPushRun.m +++ b/callbacks/push/onPushRun.m @@ -196,9 +196,9 @@ function onPushRun(src,~) pulseparam.PulseType = data.pulse.Type; % gyromagnetic ratio [rad/s/T] pulseparam.gamma = odeparam.gamma; - % Larmor frequency [rad] + % Larmor frequency [rad/s] pulseparam.omega0 = getOmega0(odeparam.gamma,odeparam.B0); - % pulse amplitude [B0] + % pulse amplitude [T] pulseparam.Amp = odeparam.B0*data.pulse.B1Factor; % pulse frequency modulation [struct] pulseparam.fmod = data.results.pulse.fmod; @@ -263,7 +263,7 @@ function onPushRun(src,~) % set theta for all time steps after the pulse simply to % omega0*t theta(indT) = getOmega0(odeparam.gamma,odeparam.B0).*TT(indT); - % rotate M into rotating frame of reference + % get M(T) in rotating frame of reference Mrot = getMrot(MM,theta,dphi); % get FFT of M in the laboratory frame of reference [Xm,fmx] = getFFT(TT,MM(:,1:2)); @@ -274,7 +274,7 @@ function onPushRun(src,~) set(gui.text_handles.Status,'String','Calculation of excitation pulse & relaxation ... finished.'); pause(0.01); else - % rotate M into rotating frame of reference + % get M(T) in rotating frame of reference Mrot = getMrot(MM,theta); % get FFT of M in the laboratory frame of reference [Xm,fmx] = getFFT(TT,MM(:,1:2)); @@ -518,9 +518,8 @@ function onPushRun(src,~) % set theta for all time steps after the pulse simply to % omega0*t theta(indT) = getOmega0(odeparam.gamma,odeparam.B0).*TT(indT); - % rotate M into rotating frame of reference - % and account for the phase from the wait time before the - % pulse + % get M(T) in rotating frame of reference and account for + % the phase from the wait time before the pulse MM3rot = getMrot(MM,theta,dphi+phiWait); % get FFT of the pulse [Xb,fbx] = getFFT(TT(TT<=Ttau),Bpulse(TT<=Ttau,1:2)); @@ -530,9 +529,8 @@ function onPushRun(src,~) ' & relaxation ... finished.']); pause(0.01); else - % rotate M into rotating frame of reference - % and account for the phase from the wait time before the - % pulse + % get M(T) in rotating frame of reference and account for + % the phase from the wait time before the pulse MM3rot = getMrot(MM,theta,phiWait); % get FFT of the pulse [Xb,fbx] = getFFT(TT,Bpulse(:,1:2)); @@ -555,13 +553,16 @@ function onPushRun(src,~) % combine data from all stages TT = [TT1;TT2;TT3]; 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" + % 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]; diff --git a/doc/blochus/BLOCHUS/BLOCHUS.html b/doc/blochus/BLOCHUS/BLOCHUS.html index f677553..8e28ea9 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.2'; -0037 myui.date = '17.05.2020'; +0036 myui.version = '0.1.3'; +0037 myui.date = '22.05.2020'; 0038 myui.author = 'Thomas Hiller'; 0039 myui.email = 'thomas.hiller[at]leibniz-liag.de'; 0040 diff --git a/doc/blochus/BLOCHUS/BLOCHUS_createGUI.html b/doc/blochus/BLOCHUS/BLOCHUS_createGUI.html index afd83ba..9d67d8a 100644 --- a/doc/blochus/BLOCHUS/BLOCHUS_createGUI.html +++ b/doc/blochus/BLOCHUS/BLOCHUS_createGUI.html @@ -212,9 +212,9 @@

SOURCE CODE ^'Visible','on'); 0144 0145 %% enable all menus -0146 set(gui.menu.file,'Enable','on'); -0147 set(gui.menu.view,'Enable','on'); -0148 set(gui.menu.help,'Enable','on'); +0146 set(gui.menu_handles.file,'Enable','on'); +0147 set(gui.menu_handles.view,'Enable','on'); +0148 set(gui.menu_handles.help,'Enable','on'); 0149 0150 %% update the GUI data 0151 gui.myui = myui; diff --git a/doc/blochus/BLOCHUS/BLOCHUS_createMenus.html b/doc/blochus/BLOCHUS/BLOCHUS_createMenus.html index 8b3b816..1935e2e 100644 --- a/doc/blochus/BLOCHUS/BLOCHUS_createMenus.html +++ b/doc/blochus/BLOCHUS/BLOCHUS_createMenus.html @@ -58,7 +58,7 @@

DESCRIPTION ^CROSS-REFERENCE INFORMATION ^

This function calls: +
  • onMenuExport handles the extra menu entries
  • onMenuHelp shows the Help Information
  • onMenuImport handles the extra menu entries
  • onMenuRestartQuit restarts or closes the GUI
  • onMenuView handles the extra menu entries
  • onMenuViewFigure shows predefined figure layouts
  • This function is called by: @@ -99,88 +99,100 @@

    SOURCE CODE ^%------------- BEGIN CODE -------------- 0031 0032 %% 1. File -0033 gui.menu.file = uimenu(gui.figh,... -0034 'Label','File','Enable','off'); -0035 -0036 % 1.1 Import -0037 gui.menu.file_import = uimenu(gui.menu.file,... -0038 'Label','Import','Enable','on'); -0039 -0040 % 1.1.1 BLOCHUS session file -0041 gui.menu.file_import_session = uimenu(gui.menu.file_import,... -0042 'Label','Session file','Callback',@onMenuImport); -0043 -0044 % 1.2 Export -0045 gui.menu.file_export = uimenu(gui.menu.file,... -0046 'Label','Export'); -0047 -0048 % 1.2.1 BLOCHUS session file -0049 gui.menu.file_export_session = uimenu(gui.menu.file_export,... -0050 'Label','Session file','Callback',@onMenuExport); -0051 -0052 % 1.3 Restart -0053 gui.menu.file_restart = uimenu(gui.menu.file,... -0054 'Label','Restart','Separator','on','Callback',@onMenuRestartQuit); -0055 -0056 % 1.4 Quit -0057 gui.menu.file_quit = uimenu(gui.menu.file,... -0058 'Label','Quit','Separator','on','Callback',@onMenuRestartQuit); -0059 -0060 %% 2. Extras -0061 gui.menu.view = uimenu(gui.figh,... -0062 'Label','View','Enable','off'); +0033 gui.menu_handles.file = uimenu(gui.figh,... +0034 'Label','File',... +0035 'Enable','off'); +0036 +0037 % 1.1 Import +0038 gui.menu_handles.file_import = uimenu(gui.menu_handles.file,... +0039 'Label','Import Data',... +0040 'Callback',@onMenuImport); +0041 +0042 % 1.2 Export +0043 gui.menu_handles.file_export = uimenu(gui.menu_handles.file,... +0044 'Label','Export Data',... +0045 'Callback',@onMenuExport); +0046 +0047 % 1.3 Restart +0048 gui.menu_handles.file_restart = uimenu(gui.menu_handles.file,... +0049 'Label','Restart',... +0050 'Separator','on',... +0051 'Callback',@onMenuRestartQuit); +0052 +0053 % 1.4 Quit +0054 gui.menu_handles.file_quit = uimenu(gui.menu_handles.file,... +0055 'Label','Quit',... +0056 'Callback',@onMenuRestartQuit); +0057 +0058 %% 2. Extras +0059 gui.menu_handles.view = uimenu(gui.figh,... +0060 'Label','View',... +0061 'Enable','off'); +0062 0063 % 2.1 Tooltips (on/off) -0064 gui.menu.view_tooltips = uimenu(gui.menu.view,... -0065 'Label','Tooltips','Checked','on','Callback',@onMenuViewShow); -0066 % 2.2 Figure Toolbar -0067 gui.menu.view_toolbar = uimenu(gui.menu.view,... -0068 'Label','Figure Toolbar','Callback',@onMenuViewShow); -0069 % 2.3.1 Tigures -0070 gui.menu.view_figures = uimenu(gui.menu.view,... -0071 'Label','Figures','Separator','on'); -0072 % 2.3.1.1 current -0073 gui.menu.view_figures_current = uimenu(gui.menu.view_figures,... -0074 'Label','Current View','Callback',@onMenuViewFigure); -0075 % 2.3.1.2 only magnetization -0076 gui.menu.view_figures_mag = uimenu(gui.menu.view_figures,... -0077 'Label','Magnetization','Callback',@onMenuViewFigure); -0078 % 2.3.1.3 only ramp -0079 gui.menu.view_figures_ramp = uimenu(gui.menu.view_figures,... -0080 'Label','Switch-off Ramp','Enable','off','Callback',@onMenuViewFigure); -0081 % 2.3.1.4 only pulse -0082 gui.menu.view_figures_pulse = uimenu(gui.menu.view_figures,... -0083 'Label','Pulse','Enable','off','Callback',@onMenuViewFigure); -0084 -0085 %% 3. Help -0086 gui.menu.help = uimenu(gui.figh,... -0087 'Label','Help','Enable','off'); -0088 -0089 % 3.1 About -0090 gui.menu.help_about = uimenu(gui.menu.help,... -0091 'Label','About','Callback',@onMenuHelp); -0092 -0093 return +0064 gui.menu_handles.view_tooltips = uimenu(gui.menu_handles.view,... +0065 'Label','Tooltips',... +0066 'Checked','on',... +0067 'Callback',@onMenuView); +0068 +0069 % 2.2 Figure Toolbar +0070 gui.menu_handles.view_toolbar = uimenu(gui.menu_handles.view,... +0071 'Label','Figure Toolbar',... +0072 'Callback',@onMenuView); +0073 % 2.3.1 Figures +0074 gui.menu_handles.view_figures = uimenu(gui.menu_handles.view,... +0075 'Label','Figures','Separator','on'); +0076 % 2.3.1.1 current +0077 gui.menu_handles.view_figures_current = uimenu(gui.menu_handles.view_figures,... +0078 'Label','Current View',... +0079 'Callback',@onMenuViewFigure); +0080 % 2.3.1.2 only magnetization +0081 gui.menu_handles.view_figures_mag = uimenu(gui.menu_handles.view_figures,... +0082 'Label','Magnetization',... +0083 'Callback',@onMenuViewFigure); +0084 % 2.3.1.3 only ramp +0085 gui.menu_handles.view_figures_ramp = uimenu(gui.menu_handles.view_figures,... +0086 'Label','Switch-off Ramp',... +0087 'Enable','off',... +0088 'Callback',@onMenuViewFigure); +0089 % 2.3.1.4 only pulse +0090 gui.menu_handles.view_figures_pulse = uimenu(gui.menu_handles.view_figures,... +0091 'Label','Pulse',... +0092 'Enable','off',... +0093 'Callback',@onMenuViewFigure); 0094 -0095 %------------- END OF CODE -------------- -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/>. +0095 %% 3. Help +0096 gui.menu_handles.help = uimenu(gui.figh,... +0097 'Label','Help',... +0098 'Enable','off'); +0099 +0100 % 3.1 About +0101 gui.menu_handles.help_about = uimenu(gui.menu_handles.help,... +0102 'Label','About',... +0103 'Callback',@onMenuHelp); +0104 +0105 return +0106 +0107 %------------- END OF CODE -------------- +0108 +0109 %% License: +0110 % GNU GPLv3 +0111 % +0112 % BLOCHUS +0113 % Copyright (C) 2019 Thomas Hiller +0114 % +0115 % This program is free software: you can redistribute it and/or modify +0116 % it under the terms of the GNU General Public License as published by +0117 % the Free Software Foundation, either version 3 of the License, or +0118 % (at your option) any later version. +0119 % +0120 % This program is distributed in the hope that it will be useful, +0121 % but WITHOUT ANY WARRANTY; without even the implied warranty of +0122 % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +0123 % GNU General Public License for more details. +0124 % +0125 % You should have received a copy of the GNU General Public License +0126 % 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/BLOCHUS/BLOCHUS_createPanelPulse.html b/doc/blochus/BLOCHUS/BLOCHUS_createPanelPulse.html index 46e3eab..075ea6b 100644 --- a/doc/blochus/BLOCHUS/BLOCHUS_createPanelPulse.html +++ b/doc/blochus/BLOCHUS/BLOCHUS_createPanelPulse.html @@ -486,45 +486,47 @@

    SOURCE CODE ^return +0433 jh = findjobj(gui.text_handles.PulseTwait); +0434 jh.setVerticalAlignment(javax.swing.JLabel.CENTER) 0435 -0436 %------------- END OF CODE -------------- +0436 return 0437 -0438 %% License: -0439 % GNU GPLv3 -0440 % -0441 % BLOCHUS -0442 % Copyright (C) 2019 Thomas Hiller -0443 % -0444 % This program is free software: you can redistribute it and/or modify -0445 % it under the terms of the GNU General Public License as published by -0446 % the Free Software Foundation, either version 3 of the License, or -0447 % (at your option) any later version. -0448 % -0449 % This program is distributed in the hope that it will be useful, -0450 % but WITHOUT ANY WARRANTY; without even the implied warranty of -0451 % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -0452 % GNU General Public License for more details. -0453 % -0454 % You should have received a copy of the GNU General Public License -0455 % along with this program. If not, see <https://www.gnu.org/licenses/>. +0438 %------------- END OF CODE -------------- +0439 +0440 %% License: +0441 % GNU GPLv3 +0442 % +0443 % BLOCHUS +0444 % Copyright (C) 2019 Thomas Hiller +0445 % +0446 % This program is free software: you can redistribute it and/or modify +0447 % it under the terms of the GNU General Public License as published by +0448 % the Free Software Foundation, either version 3 of the License, or +0449 % (at your option) any later version. +0450 % +0451 % This program is distributed in the hope that it will be useful, +0452 % but WITHOUT ANY WARRANTY; without even the implied warranty of +0453 % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +0454 % GNU General Public License for more details. +0455 % +0456 % You should have received a copy of the GNU General Public License +0457 % 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/onCheckPrePolPulse.html b/doc/blochus/callbacks/checkbox/onCheckPrePolPulse.html index 1f0d3b1..4bc963d 100644 --- a/doc/blochus/callbacks/checkbox/onCheckPrePolPulse.html +++ b/doc/blochus/callbacks/checkbox/onCheckPrePolPulse.html @@ -118,8 +118,8 @@

    SOURCE CODE ^'std'; 0048 0049 % menu settings -0050 set(gui.menu.view_figures_ramp,'Enable','off'); -0051 set(gui.menu.view_figures_pulse,'Enable','off'); +0050 set(gui.menu_handles.view_figures_ramp,'Enable','off'); +0051 set(gui.menu_handles.view_figures_pulse,'Enable','off'); 0052 0053 % std settings 0054 data.basic.Minit = [1 0 0]; @@ -182,8 +182,8 @@

    SOURCE CODE ^'prepol'; 0112 0113 % menu settings -0114 set(gui.menu.view_figures_ramp,'Enable','on'); -0115 set(gui.menu.view_figures_pulse,'Enable','off'); +0114 set(gui.menu_handles.view_figures_ramp,'Enable','on'); +0115 set(gui.menu_handles.view_figures_pulse,'Enable','off'); 0116 0117 % std settings 0118 data.basic.Tsim = data.prepol.Tramp; @@ -244,8 +244,8 @@

    SOURCE CODE ^'pulse'; 0174 0175 % menu settings -0176 set(gui.menu.view_figures_ramp,'Enable','off'); -0177 set(gui.menu.view_figures_pulse,'Enable','on'); +0176 set(gui.menu_handles.view_figures_ramp,'Enable','off'); +0177 set(gui.menu_handles.view_figures_pulse,'Enable','on'); 0178 0179 % std settings 0180 data.basic.Tsim = data.pulse.Ttau; @@ -294,8 +294,8 @@

    SOURCE CODE ^'prepolpulse'; 0224 0225 % menu settings -0226 set(gui.menu.view_figures_ramp,'Enable','on'); -0227 set(gui.menu.view_figures_pulse,'Enable','on'); +0226 set(gui.menu_handles.view_figures_ramp,'Enable','on'); +0227 set(gui.menu_handles.view_figures_pulse,'Enable','on'); 0228 0229 % std settings 0230 data.basic.Minit = [1 0 0]; diff --git a/doc/blochus/callbacks/menus/menu.html b/doc/blochus/callbacks/menus/menu.html index bea8b9b..8986e51 100644 --- a/doc/blochus/callbacks/menus/menu.html +++ b/doc/blochus/callbacks/menus/menu.html @@ -18,7 +18,7 @@

    Index for blochus\callbacks\menus

    Matlab files in this directory:

    +
  • onMenuExport
  • onMenuHelp
  • onMenuImport
  • onMenuRestartQuit
  • onMenuView
  • onMenuViewFigure
  • onMenuViewShow
  • diff --git a/doc/blochus/callbacks/menus/onMenuHelp.html b/doc/blochus/callbacks/menus/onMenuHelp.html index 01f31e6..728d19b 100644 --- a/doc/blochus/callbacks/menus/onMenuHelp.html +++ b/doc/blochus/callbacks/menus/onMenuHelp.html @@ -143,7 +143,7 @@

    SOURCE CODE ^% create Figure 0075 hf = figure('Name','About BLOCHUS',... 0076 'NumberTitle','off','Tag','Help','ToolBar','none','MenuBar','none',... -0077 'Resize','off','Position',[xp yp ww hh]); +0077 'Resize','off','Position',[xp yp ww hh],'Visible','off'); 0078 v1 = uix.VBox('Parent',hf,'Padding',10,'Spacing',10); 0079 0080 % text area @@ -186,33 +186,36 @@

    SOURCE CODE ^else -0121 warndlg({'onMenuHelp:','There is no figure with the BLOCHUS Tag open.'},... -0122 'BLOCHUS error'); -0123 end -0124 -0125 end -0126 -0127 %------------- END OF CODE -------------- -0128 -0129 %% License: -0130 % GNU GPLv3 -0131 % -0132 % BLOCHUS -0133 % Copyright (C) 2019 Thomas Hiller +0120 % make the figure content visible +0121 set(hf,'Visible','on'); +0122 +0123 else +0124 warndlg({'onMenuHelp:','There is no figure with the BLOCHUS Tag open.'},... +0125 'BLOCHUS error'); +0126 end +0127 +0128 end +0129 +0130 %------------- END OF CODE -------------- +0131 +0132 %% License: +0133 % GNU GPLv3 0134 % -0135 % This program is free software: you can redistribute it and/or modify -0136 % it under the terms of the GNU General Public License as published by -0137 % the Free Software Foundation, either version 3 of the License, or -0138 % (at your option) any later version. -0139 % -0140 % This program is distributed in the hope that it will be useful, -0141 % but WITHOUT ANY WARRANTY; without even the implied warranty of -0142 % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -0143 % GNU General Public License for more details. -0144 % -0145 % You should have received a copy of the GNU General Public License -0146 % along with this program. If not, see <https://www.gnu.org/licenses/>. +0135 % BLOCHUS +0136 % Copyright (C) 2019 Thomas Hiller +0137 % +0138 % This program is free software: you can redistribute it and/or modify +0139 % it under the terms of the GNU General Public License as published by +0140 % the Free Software Foundation, either version 3 of the License, or +0141 % (at your option) any later version. +0142 % +0143 % This program is distributed in the hope that it will be useful, +0144 % but WITHOUT ANY WARRANTY; without even the implied warranty of +0145 % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +0146 % GNU General Public License for more details. +0147 % +0148 % You should have received a copy of the GNU General Public License +0149 % 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/onMenuViewShow.html b/doc/blochus/callbacks/menus/onMenuView.html similarity index 54% rename from doc/blochus/callbacks/menus/onMenuViewShow.html rename to doc/blochus/callbacks/menus/onMenuView.html index c6b99c9..2972b50 100644 --- a/doc/blochus/callbacks/menus/onMenuViewShow.html +++ b/doc/blochus/callbacks/menus/onMenuView.html @@ -2,8 +2,8 @@ "http://www.w3.org/TR/REC-html40/loose.dtd"> - Description of onMenuViewShow - + Description of onMenuView + @@ -16,20 +16,20 @@ -

    onMenuViewShow +

    onMenuView

    PURPOSE ^

    handles the extra menu entries

    SYNOPSIS ^

    -
    function onMenuViewShow(src,~)
    +
    function onMenuView(src,~)

    DESCRIPTION ^

    -
    onMenuViewShow handles the extra menu entries
    +
    onMenuView handles the extra menu entries
     
      Syntax:
    -       onMenuViewShow(src)
    +       onMenuView(src)
     
      Inputs:
            src - handle of the calling object
    @@ -38,7 +38,7 @@ 

    DESCRIPTION ^DESCRIPTION ^CROSS-REFERENCE INFORMATION ^

    This function calls: +
  • switchToolTips switches GUI tool tips either "on" or "off"
  • updateStatusInformation updates all fields inside the bottom status bar
  • This function is called by: @@ -68,11 +68,11 @@

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

    -
    0001 function onMenuViewShow(src,~)
    -0002 %onMenuViewShow handles the extra menu entries
    +
    0001 function onMenuView(src,~)
    +0002 %onMenuView handles the extra menu entries
     0003 %
     0004 % Syntax:
    -0005 %       onMenuViewShow(src)
    +0005 %       onMenuView(src)
     0006 %
     0007 % Inputs:
     0008 %       src - handle of the calling object
    @@ -81,7 +81,7 @@ 

    SOURCE CODE ^% none 0012 % 0013 % Example: -0014 % onMenuViewShow(src,~) +0014 % onMenuView(src,~) 0015 % 0016 % Other m-files required: 0017 % switchToolTips @@ -110,62 +110,61 @@

    SOURCE CODE ^switch get(src,'Label') 0042 case 'Tooltips' % switch on/off Tooltips -0043 onoff = get(gui.menu.view_tooltips,'Checked'); -0044 switchToolTips(gui,onoff); -0045 switch onoff -0046 case 'on' -0047 set(gui.menu.view_tooltips,'Checked','off'); -0048 data.info.ToolTips = 0; -0049 case 'off' -0050 set(gui.menu.view_tooltips,'Checked','on'); +0043 switch get(src,'Checked') +0044 case 'on' % if it is on, switch it off +0045 switchToolTips(gui,'off'); +0046 set(src,'Checked','off'); +0047 data.info.ToolTips = 0; +0048 case 'off' +0049 switchToolTips(gui,'on'); +0050 set(src,'Checked','on'); 0051 data.info.ToolTips = 1; 0052 end 0053 0054 case 'Figure Toolbar' % switch on/off the default Figure Toolbar -0055 onoff = get(gui.menu.view_toolbar,'Checked'); -0056 switch onoff -0057 case 'on' -0058 set(gui.menu.view_toolbar,'Checked','off'); -0059 viewmenufcn('FigureToolbar'); -0060 case 'off' -0061 set(gui.menu.view_toolbar,'Checked','on'); -0062 viewmenufcn('FigureToolbar'); -0063 end -0064 end -0065 -0066 % update GUI data -0067 setappdata(fig,'gui',gui); -0068 setappdata(fig,'data',data); -0069 % update status bar -0070 updateStatusInformation(fig); -0071 -0072 else -0073 warndlg({'onMenuViewShow:','There is no figure with the BLOCHUS Tag open.'},... -0074 'BLOCHUS error'); -0075 end -0076 -0077 end -0078 -0079 %------------- END OF CODE -------------- -0080 -0081 %% License: -0082 % GNU GPLv3 -0083 % -0084 % BLOCHUS -0085 % Copyright (C) 2019 Thomas Hiller -0086 % -0087 % This program is free software: you can redistribute it and/or modify -0088 % it under the terms of the GNU General Public License as published by -0089 % the Free Software Foundation, either version 3 of the License, or -0090 % (at your option) any later version. -0091 % -0092 % This program is distributed in the hope that it will be useful, -0093 % but WITHOUT ANY WARRANTY; without even the implied warranty of -0094 % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -0095 % GNU General Public License for more details. -0096 % -0097 % You should have received a copy of the GNU General Public License -0098 % along with this program. If not, see <https://www.gnu.org/licenses/>.

    +0055 switch get(src,'Checked') +0056 case 'on' % if it is on, switch it off +0057 set(src,'Checked','off'); +0058 viewmenufcn('FigureToolbar'); +0059 case 'off' +0060 set(src,'Checked','on'); +0061 viewmenufcn('FigureToolbar'); +0062 end +0063 end +0064 +0065 % update GUI data +0066 setappdata(fig,'gui',gui); +0067 setappdata(fig,'data',data); +0068 % update status bar +0069 updateStatusInformation(fig); +0070 +0071 else +0072 warndlg({'onMenuView:','There is no figure with the BLOCHUS Tag open.'},... +0073 'BLOCHUS error'); +0074 end +0075 +0076 end +0077 +0078 %------------- END OF CODE -------------- +0079 +0080 %% License: +0081 % GNU GPLv3 +0082 % +0083 % BLOCHUS +0084 % Copyright (C) 2019 Thomas Hiller +0085 % +0086 % This program is free software: you can redistribute it and/or modify +0087 % it under the terms of the GNU General Public License as published by +0088 % the Free Software Foundation, either version 3 of the License, or +0089 % (at your option) any later version. +0090 % +0091 % This program is distributed in the hope that it will be useful, +0092 % but WITHOUT ANY WARRANTY; without even the implied warranty of +0093 % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +0094 % GNU General Public License for more details. +0095 % +0096 % You should have received a copy of the GNU General Public License +0097 % 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 dae2f38..9dd577c 100644 --- a/doc/blochus/callbacks/push/onPushRun.html +++ b/doc/blochus/callbacks/push/onPushRun.html @@ -271,9 +271,9 @@

    SOURCE CODE ^% gyromagnetic ratio [rad/s/T] 0198 pulseparam.gamma = odeparam.gamma; -0199 % Larmor frequency [rad] +0199 % Larmor frequency [rad/s] 0200 pulseparam.omega0 = getOmega0(odeparam.gamma,odeparam.B0); -0201 % pulse amplitude [B0] +0201 % pulse amplitude [T] 0202 pulseparam.Amp = odeparam.B0*data.pulse.B1Factor; 0203 % pulse frequency modulation [struct] 0204 pulseparam.fmod = data.results.pulse.fmod; @@ -338,7 +338,7 @@

    SOURCE CODE ^% 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 +0266 % get M(T) in 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)); @@ -349,7 +349,7 @@

    SOURCE CODE ^'String','Calculation of excitation pulse & relaxation ... finished.'); 0275 pause(0.01); 0276 else -0277 % rotate M into rotating frame of reference +0277 % get M(T) in 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)); @@ -593,115 +593,116 @@

    SOURCE CODE ^% 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 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 +0521 % get M(T) in rotating frame of reference and account for +0522 % the phase from the wait time before the pulse +0523 MM3rot = getMrot(MM,theta,dphi+phiWait); +0524 % get FFT of the pulse +0525 [Xb,fbx] = getFFT(TT(TT<=Ttau),Bpulse(TT<=Ttau,1:2)); +0526 +0527 % update Info field +0528 set(gui.text_handles.Status,'String',['Calculation of excitation pulse',... +0529 ' & relaxation ... finished.']); +0530 pause(0.01); +0531 else +0532 % get M(T) in rotating frame of reference and account for +0533 % the phase from the wait time before the pulse +0534 MM3rot = getMrot(MM,theta,phiWait); +0535 % get FFT of the pulse +0536 [Xb,fbx] = getFFT(TT,Bpulse(:,1:2)); +0537 +0538 % update Info field +0539 set(gui.text_handles.Status,'String','Calculation of excitation pulse ... finished.'); +0540 pause(0.01); +0541 end +0542 +0543 % ------------------------------------------------------------- +0544 %% --- 4.) final data merging --------------------------------- 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/>.

    +0546 % because the simulation was done in "local" time +0547 % coordinates, shift the time vector to the end of the +0548 % wait time after the switch-off +0549 TT3 = TT + Tramp + Twait; +0550 % save data +0551 MM3 = MM; +0552 +0553 % combine data from all stages +0554 TT = [TT1;TT2;TT3]; +0555 MM = [MM1;MM2;MM3]; +0556 +0557 % because there is no M in the rotating frame of reference +0558 % during the switch-off ramp, use the lab-frame data instead +0559 % --- IMPORTANT NOTE: ---------------------------------------- +0560 % The pre-polarization switch-off only "lives" in the laboratory +0561 % frame of reference. However, for convenience reasons I plot +0562 % the lab-frame pre-polarization data also in the rotating +0563 % frame of reference! This is u-n-p-h-y-s-i-c-a-l and pure +0564 % "eye candy" +0565 % +0566 % MM1 is lab-frame data! +0567 % ------------------------------------------------------------- +0568 MMrot = [MM1;MM2rot;MM3rot]; +0569 +0570 % remove possible duplicate points +0571 [TT,ix] = unique(TT); +0572 MM = MM(ix,:); +0573 MMrot = MMrot(ix,:); +0574 +0575 % save combined data +0576 data.results.basic.T = TT; +0577 data.results.basic.M = MM; +0578 data.results.basic.Mrot = MMrot; +0579 +0580 % get FFT for the combined M +0581 [Xm,fmx] = getFFT(TT,MM(:,1:2)); +0582 data.results.basic.Mspec.fx = fmx; +0583 data.results.basic.Mspec.X = Xm; +0584 % save pulse FFT +0585 data.results.pulse.Bspec.fx = fbx; +0586 data.results.pulse.Bspec.X = Xb; +0587 +0588 end +0589 % time the calculation +0590 data.info.Timer = toc(t0); +0591 +0592 % update GUI data +0593 setappdata(fig,'data',data); +0594 % plot results +0595 plotResults(fig); +0596 % update status bar +0597 updateStatusInformation(fig); +0598 % activate animation button +0599 set(gui.push_handles.Animate,'Enable','on'); +0600 +0601 % change the pushbutton color back to green +0602 set(src,'BackGroundColor','g'); +0603 +0604 else +0605 warndlg({'onPushRun:','There is no figure with the BLOCHUS Tag open.'},... +0606 'BLOCHUS error'); +0607 end +0608 +0609 end +0610 +0611 %------------- END OF CODE -------------- +0612 +0613 %% License: +0614 % GNU GPLv3 +0615 % +0616 % BLOCHUS +0617 % Copyright (C) 2019 Thomas Hiller +0618 % +0619 % This program is free software: you can redistribute it and/or modify +0620 % it under the terms of the GNU General Public License as published by +0621 % the Free Software Foundation, either version 3 of the License, or +0622 % (at your option) any later version. +0623 % +0624 % This program is distributed in the hope that it will be useful, +0625 % but WITHOUT ANY WARRANTY; without even the implied warranty of +0626 % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +0627 % GNU General Public License for more details. +0628 % +0629 % You should have received a copy of the GNU General Public License +0630 % 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/plotResults.html b/doc/blochus/functions/interface/plotResults.html index 4e3cd31..2aad35d 100644 --- a/doc/blochus/functions/interface/plotResults.html +++ b/doc/blochus/functions/interface/plotResults.html @@ -236,174 +236,177 @@

    SOURCE CODE ^% 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 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; +0166 % set(get(lh,'Title'),'String',{'adiab. qual.',['p = ',sprintf('%4.3f',data.results.prepol.p)]}) +0167 set(get(ax,'Title'),'String',['adiabatic quality p = ',sprintf('%4.3f',data.results.prepol.p)]) +0168 else +0169 set(get(ax,'Title'),'String',''); +0170 end +0171 % font size +0172 set(ax,'FontSize',myui.axfontsize); +0173 +0174 end +0175 +0176 %% magnetization components on Bloch sphere +0177 function plotSphere(data,gui,frame) +0178 myui = gui.myui; 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); +0180 % for plotting everything is in [ms] +0181 T = data.results.basic.T.*1e3; +0182 +0183 % all relevant time marker +0184 Tsim = data.basic.Tsim; +0185 Ttau = data.pulse.Ttau; +0186 Tramp = data.prepol.Tramp; +0187 Twait = data.pulse.Twait; +0188 +0189 % choose reference frame to plot +0190 switch frame +0191 case 'lab' +0192 M = data.results.basic.M; +0193 ax = gui.axes_handles.SphereL; +0194 case 'rot' +0195 M = data.results.basic.Mrot; +0196 ax = gui.axes_handles.SphereR; +0197 end +0198 % norm of magnetization vector +0199 Mamp = sqrt(M(:,1).^2+M(:,2).^2+M(:,3).^2); 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 end -0273 -0274 %% FFT of magnetization and pulse -0275 function plotFFT(data,gui,type) +0201 % for visualization purposes M always gets normalized on Bloch sphere +0202 M = M./Mamp(1); +0203 +0204 % chhose what to plot depending on simulation type +0205 switch data.basic.type +0206 case 'std' +0207 indS1 = 1:numel(T); % relaxation +0208 indS2 = []; % relaxation at end of "prepolpulse"-type +0209 indR = []; % switch-off ramp +0210 indB = []; % switch-off B-field +0211 indP = []; % pulse +0212 indE = numel(T); % end point +0213 Beffn = [0 0 0]; +0214 +0215 case 'prepol' +0216 indS1 = T>Tramp; +0217 indS2 = []; +0218 indR = T<=Tramp; +0219 indB = []; +0220 indP = []; +0221 indE = numel(T); +0222 % switch-off B-field trajectory +0223 Bamp = sqrt(data.results.prepol.Beff(:,1).^2+... +0224 data.results.prepol.Beff(:,2).^2+... +0225 data.results.prepol.Beff(:,3).^2); +0226 Beffn = data.results.prepol.Beff./Bamp; +0227 +0228 case 'pulse' +0229 indS1 = T>Ttau; +0230 indS2 = []; +0231 indR = []; +0232 indB = []; +0233 indP = T<=Ttau; +0234 indE = numel(T); +0235 Beffn = [0 0 0]; +0236 +0237 case 'prepolpulse' +0238 indS2 = T>Tramp & T<=Tramp+Twait; +0239 indS1 = T>Tramp+Twait+Ttau; +0240 indR = T<=Tramp; +0241 indB = []; +0242 indP = T>Tramp+Twait & T<=Tramp+Twait+Ttau; +0243 indE = numel(T); +0244 % switch-off B-field trajectory +0245 Bamp = sqrt(data.results.prepol.Beff(:,1).^2+... +0246 data.results.prepol.Beff(:,2).^2+... +0247 data.results.prepol.Beff(:,3).^2); +0248 Beffn = data.results.prepol.Beff./Bamp; +0249 end +0250 +0251 % plot data +0252 clearSingleAxis(ax); +0253 hold(ax,'on'); +0254 plot3(M(indS1,1),M(indS1,2),M(indS1,3),'LineWidth',myui.linewidth,... +0255 'Color',myui.color.basic,'Parent',ax); +0256 plot3(M(indS2,1),M(indS2,2),M(indS2,3),'LineWidth',myui.linewidth,... +0257 'Color',myui.color.wait,'Parent',ax); +0258 plot3(M(indP,1),M(indP,2),M(indP,3),'LineWidth',myui.linewidth,... +0259 'Color',myui.color.pulse,'Parent',ax); +0260 plot3(M(indR,1),M(indR,2),M(indR,3),'LineWidth',myui.linewidth,... +0261 'Color',myui.color.prepol,'Parent',ax); +0262 plot3(Beffn(:,1),Beffn(:,2),Beffn(:,3),'LineWidth',myui.linewidth,... +0263 'Color',myui.color.prepolB,'Parent',ax) +0264 plot3(M(indE,1),M(indE,2),M(indE,3),'ko','MarkerSize',8,'Parent',ax); +0265 % plot actual Bloch sphere +0266 plotBSphere(18,18,ax); +0267 % axis settings +0268 view(ax,[-35 30]); +0269 hold(ax,'off'); +0270 set(ax,'XLim',[-1.05 1.05],'YLim',[-1.05 1.05],'ZLim',[-1.05 1.05]) +0271 set(ax,'Color','w','XColor','none','YColor','none','ZColor','none'); +0272 axis(ax,'equal'); +0273 axis(ax,'tight'); +0274 +0275 end 0276 -0277 % Larmor freq. [Hz] -0278 fL = getOmega0(data.basic.gamma,data.basic.B0)/2/pi; +0277 %% FFT of magnetization and pulse +0278 function plotFFT(data,gui,type) 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 +0280 % Larmor freq. [Hz] +0281 fL = getOmega0(data.basic.gamma,data.basic.B0)/2/pi; +0282 +0283 % choose what to plot +0284 switch type +0285 case 'M' +0286 ax = gui.axes_handles.MagFFT; +0287 f = data.results.basic.Mspec.fx; +0288 X = data.results.basic.Mspec.X; +0289 lgdstr = {'Mxy','\omega_0'}; +0290 case 'B' +0291 ax = gui.axes_handles.PulseFFT; +0292 f = data.results.pulse.Bspec.fx; +0293 X = data.results.pulse.Bspec.X; +0294 lgdstr = {'B','\omega_0'}; +0295 end +0296 +0297 % plot data +0298 clearSingleAxis(ax); +0299 hold(ax,'on'); +0300 plot(f,abs(X),'r','Parent',ax); +0301 % vertical line indicating Larmor frequency +0302 line([fL fL],[0 max(abs(X))],'Color','k','LineStyle','--',... +0303 'LineWidth',0.75,'Parent',ax); +0304 hold(ax,'off'); +0305 % axis settings +0306 set(ax,'XLim',[-abs(2*fL) abs(2*fL)],'YLim',[0 max(abs(X))].*1.1); +0307 grid(ax,'on'); +0308 set(get(ax,'XLabel'),'String','F [Hz]'); +0309 set(get(ax,'YLabel'),'String','amplitude'); +0310 % legend +0311 legend(ax,lgdstr,'Location','NorthEast'); +0312 % font size +0313 set(ax,'FontSize',gui.myui.axfontsize); +0314 +0315 end +0316 +0317 %------------- END OF CODE -------------- +0318 +0319 %% License: +0320 % GNU GPLv3 0321 % -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 % 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/>. +0322 % BLOCHUS +0323 % Copyright (C) 2019 Thomas Hiller +0324 % +0325 % This program is free software: you can redistribute it and/or modify +0326 % it under the terms of the GNU General Public License as published by +0327 % the Free Software Foundation, either version 3 of the License, or +0328 % (at your option) any later version. +0329 % +0330 % This program is distributed in the hope that it will be useful, +0331 % but WITHOUT ANY WARRANTY; without even the implied warranty of +0332 % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +0333 % GNU General Public License for more details. +0334 % +0335 % You should have received a copy of the GNU General Public License +0336 % 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/switchToolTips.html b/doc/blochus/functions/interface/switchToolTips.html index 9176c23..ceca91b 100644 --- a/doc/blochus/functions/interface/switchToolTips.html +++ b/doc/blochus/functions/interface/switchToolTips.html @@ -23,7 +23,7 @@

    PURPOSE ^ switches GUI tool tips either "on" or "off"

    SYNOPSIS ^

    -
    function switchToolTips(gui,onoff) %#ok
    +
    function switchToolTips(gui,onoff)

    DESCRIPTION ^

    switchToolTips switches GUI tool tips either "on" or "off"
    @@ -62,13 +62,13 @@ 

    CROSS-REFERENCE INFORMATION ^
 </ul>
 This function is called by:
 <ul style= -
  • onMenuViewShow handles the extra menu entries
  • +
  • onMenuView handles the extra menu entries
  • onMenuViewShow handles the extra menu entries
  • SOURCE CODE ^

    -
    0001 function switchToolTips(gui,onoff) %#ok<INUSL>
    +
    0001 function switchToolTips(gui,onoff)
     0002 %switchToolTips switches GUI tool tips either "on" or "off"
     0003 %
     0004 % Syntax:
    @@ -101,61 +101,66 @@ 

    SOURCE CODE ^%------------- BEGIN CODE -------------- 0032 0033 %% list of handles that have switchable tool tips -0034 h = {'check_handles','edit_handles','popup_handles','push_handles'}; -0035 -0036 %% process all handles -0037 switch lower(onoff) -0038 case 'off' % if it is off, switch it on -0039 for i = 1:numel(h) -0040 eval(['fnames = fieldnames(gui.',h{i},');']); -0041 for j = 1:numel(fnames) -0042 eval(['ud = get(gui.',h{i},'.',fnames{j},... -0043 ',''UserData'');']); -0044 if isfield(ud,'Tooltipstr') -0045 tstr = ud.Tooltipstr; -0046 eval(['set(gui.',h{i},'.',fnames{j},... -0047 ',''ToolTipString'',tstr);']); -0048 end -0049 end -0050 end -0051 -0052 case 'on' % if it is on, switch it off -0053 for i = 1:numel(h) -0054 eval(['fnames = fieldnames(gui.',h{i},');']); -0055 for j = 1:numel(fnames) -0056 eval(['ud = get(gui.',h{i},'.',fnames{j},... -0057 ',''UserData'');']); -0058 if isfield(ud,'Tooltipstr') -0059 tstr = ud.Tooltipstr; -0060 eval(['set(gui.',h{i},'.',fnames{j},... -0061 ',''ToolTipString'','''');']); -0062 end -0063 end -0064 end -0065 end -0066 -0067 end -0068 -0069 %------------- END OF CODE -------------- -0070 -0071 %% License: -0072 % GNU GPLv3 -0073 % -0074 % BLOCHUS -0075 % Copyright (C) 2019 Thomas Hiller -0076 % -0077 % This program is free software: you can redistribute it and/or modify -0078 % it under the terms of the GNU General Public License as published by -0079 % the Free Software Foundation, either version 3 of the License, or -0080 % (at your option) any later version. +0034 h = {'check_handles','edit_handles','popup_handles',... +0035 'push_handles'}; +0036 +0037 %% process all handles +0038 switch lower(onoff) +0039 case 'on' % switch tool tips on +0040 for i = 1:numel(h) +0041 if isfield(gui,h{i}) +0042 eval(['fnames = fieldnames(gui.',h{i},');']); +0043 for j = 1:numel(fnames) +0044 eval(['ud = get(gui.',h{i},'.',fnames{j},... +0045 ',''UserData'');']); +0046 if isfield(ud,'Tooltipstr') +0047 tstr = ud.Tooltipstr; +0048 eval(['set(gui.',h{i},'.',fnames{j},... +0049 ',''ToolTipString'',tstr);']); +0050 end +0051 end +0052 end +0053 end +0054 +0055 case 'off' % switch tool tips off +0056 for i = 1:numel(h) +0057 if isfield(gui,h{i}) +0058 eval(['fnames = fieldnames(gui.',h{i},');']); +0059 for j = 1:numel(fnames) +0060 eval(['ud = get(gui.',h{i},'.',fnames{j},... +0061 ',''UserData'');']); +0062 if isfield(ud,'Tooltipstr') +0063 tstr = ud.Tooltipstr; +0064 eval(['set(gui.',h{i},'.',fnames{j},... +0065 ',''ToolTipString'','''');']); +0066 end +0067 end +0068 end +0069 end +0070 end +0071 +0072 end +0073 +0074 %------------- END OF CODE -------------- +0075 +0076 %% License: +0077 % GNU GPLv3 +0078 % +0079 % BLOCHUS +0080 % Copyright (C) 2019 Thomas Hiller 0081 % -0082 % This program is distributed in the hope that it will be useful, -0083 % but WITHOUT ANY WARRANTY; without even the implied warranty of -0084 % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -0085 % GNU General Public License for more details. +0082 % This program is free software: you can redistribute it and/or modify +0083 % it under the terms of the GNU General Public License as published by +0084 % the Free Software Foundation, either version 3 of the License, or +0085 % (at your option) any later version. 0086 % -0087 % You should have received a copy of the GNU General Public License -0088 % along with this program. If not, see <https://www.gnu.org/licenses/>.

    +0087 % This program is distributed in the hope that it will be useful, +0088 % but WITHOUT ANY WARRANTY; without even the implied warranty of +0089 % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +0090 % GNU General Public License for more details. +0091 % +0092 % You should have received a copy of the GNU General Public License +0093 % 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/updateStatusInformation.html b/doc/blochus/functions/interface/updateStatusInformation.html index 11dbec1..fb3177a 100644 --- a/doc/blochus/functions/interface/updateStatusInformation.html +++ b/doc/blochus/functions/interface/updateStatusInformation.html @@ -61,7 +61,7 @@

    CROSS-REFERENCE INFORMATION ^
 </ul>
 This function is called by:
 <ul style= -
  • BLOCHUS is a graphical user interface (GUI) to simulate NMR spin dynamics
  • onCheckPrePolPulse activates / deactivates all control elements needed for
  • onMenuViewShow handles the extra menu entries
  • onPopupPulseType selects the pulse type
  • onPushRun starts the calculation
  • +
  • BLOCHUS is a graphical user interface (GUI) to simulate NMR spin dynamics
  • onCheckPrePolPulse activates / deactivates all control elements needed for
  • onMenuView handles the extra menu entries
  • onMenuViewShow handles the extra menu entries
  • onPopupPulseType selects the pulse type
  • onPushRun starts the calculation
  • diff --git a/functions/interface/plotResults.m b/functions/interface/plotResults.m index f226b50..ee1dea8 100644 --- a/functions/interface/plotResults.m +++ b/functions/interface/plotResults.m @@ -163,7 +163,10 @@ function plotMag(data,gui,frame) % adiabatic quality of switch-off ramp if strcmp(data.basic.type,'prepol') || strcmp(data.basic.type,'prepolpulse') - set(get(lh,'Title'),'String',['p=',sprintf('%4.3f',data.results.prepol.p)]) +% set(get(lh,'Title'),'String',{'adiab. qual.',['p = ',sprintf('%4.3f',data.results.prepol.p)]}) + set(get(ax,'Title'),'String',['adiabatic quality p = ',sprintf('%4.3f',data.results.prepol.p)]) +else + set(get(ax,'Title'),'String',''); end % font size set(ax,'FontSize',myui.axfontsize); diff --git a/functions/interface/switchToolTips.m b/functions/interface/switchToolTips.m index d74f3e4..3fedfbc 100644 --- a/functions/interface/switchToolTips.m +++ b/functions/interface/switchToolTips.m @@ -1,4 +1,4 @@ -function switchToolTips(gui,onoff) %#ok +function switchToolTips(gui,onoff) %switchToolTips switches GUI tool tips either "on" or "off" % % Syntax: @@ -31,34 +31,39 @@ function switchToolTips(gui,onoff) %#ok %------------- BEGIN CODE -------------- %% list of handles that have switchable tool tips -h = {'check_handles','edit_handles','popup_handles','push_handles'}; +h = {'check_handles','edit_handles','popup_handles',... + 'push_handles'}; %% process all handles switch lower(onoff) - case 'off' % if it is off, switch it on + case 'on' % switch tool tips on for i = 1:numel(h) - eval(['fnames = fieldnames(gui.',h{i},');']); - for j = 1:numel(fnames) - eval(['ud = get(gui.',h{i},'.',fnames{j},... - ',''UserData'');']); - if isfield(ud,'Tooltipstr') - tstr = ud.Tooltipstr; - eval(['set(gui.',h{i},'.',fnames{j},... - ',''ToolTipString'',tstr);']); + if isfield(gui,h{i}) + eval(['fnames = fieldnames(gui.',h{i},');']); + for j = 1:numel(fnames) + eval(['ud = get(gui.',h{i},'.',fnames{j},... + ',''UserData'');']); + if isfield(ud,'Tooltipstr') + tstr = ud.Tooltipstr; + eval(['set(gui.',h{i},'.',fnames{j},... + ',''ToolTipString'',tstr);']); + end end end end - case 'on' % if it is on, switch it off + case 'off' % switch tool tips off for i = 1:numel(h) - eval(['fnames = fieldnames(gui.',h{i},');']); - for j = 1:numel(fnames) - eval(['ud = get(gui.',h{i},'.',fnames{j},... - ',''UserData'');']); - if isfield(ud,'Tooltipstr') - tstr = ud.Tooltipstr; - eval(['set(gui.',h{i},'.',fnames{j},... - ',''ToolTipString'','''');']); + if isfield(gui,h{i}) + eval(['fnames = fieldnames(gui.',h{i},');']); + for j = 1:numel(fnames) + eval(['ud = get(gui.',h{i},'.',fnames{j},... + ',''UserData'');']); + if isfield(ud,'Tooltipstr') + tstr = ud.Tooltipstr; + eval(['set(gui.',h{i},'.',fnames{j},... + ',''ToolTipString'','''');']); + end end end end diff --git a/scripts/example1.m b/scripts/example1.m index 9b5f08b..ba9ec1a 100644 --- a/scripts/example1.m +++ b/scripts/example1.m @@ -2,8 +2,8 @@ % This script demonstrates the basic use of the BLOCHUS ode-solver. Two % different protons (H & He) are used to show the effect of the sign of the % gyromagnetic ratio \gamma -% 1.) Hydrogen proton (gyromagnetic ratio > 0 ) -% 2.) Helium proton (gyromagnetic ratio < 0 ) +% 1.) Hydrogen proton (gyromagnetic ratio > 0) +% 2.) Helium proton (gyromagnetic ratio < 0) % % general settings: % -> magnetic field B0 is set to 50 µT @@ -30,8 +30,6 @@ usetest = [1 1]; %% basic settings -% get default values -% defaults = BLOCHUS_loadDefaults('basic'); zunit = [0 0 1]'; % z unit vector % ODE solver error tolerance tol = 1e-9; @@ -44,22 +42,27 @@ % parameter needed for the ODE odeparam.type = 'std'; - odeparam.M0 = zunit; % equilibrium magnetization [A/m] - odeparam.B0 = 5e-5; % primary magnetic field B0 [T] - odeparam.T1 = 0.0010; % relaxation time T1 [s] - odeparam.T2 = 0.0005; % relaxation time T2 [s] - odeparam.gamma = getGyroRatio(nucleus); % gyromagnetic ratio [rad/s/T] + % equilibrium magnetization [A/m] + odeparam.M0 = zunit; + % primary magnetic field B0 [T] + odeparam.B0 = 5e-5; + % longitudinal relaxation time T1 [s] + odeparam.T1 = 0.0010; + % transversal relaxation time T2 [s] + odeparam.T2 = 0.0005; + % gyromagnetic ratio [rad/s/T] + odeparam.gamma = getGyroRatio(nucleus); - % initial magnetization pointing towards +x - Minit = [1 0 0]; % [A/m] - % simulation time - Tsim = 0.005; % [s] + % initial magnetization pointing towards +x [A/m] + Minit = [1 0 0]; + % simulation time [s] + Tsim = 0.005; % ODE solver call % OUTPUT: time T and magnetization M [T,M] = ode45(@(t,m) fcn_BLOCHUS_ode(t,m,odeparam),[0 Tsim],Minit,options); - % rotate M(T) vector into rotating reference frame + % get M(T) in rotating frame of reference Mrot = getMrot(M,getOmega0(odeparam.gamma,odeparam.B0).*T); f1 = figure; set(f1,'Name','example1a_ref'); @@ -99,14 +102,16 @@ axis equal tight; % --- Helium --- - nucleus = '3He'; % helium proton - odeparam.gamma = getGyroRatio(nucleus); % gyromagnetic ratio [rad/s/T] + % helium proton + nucleus = '3He'; + % gyromagnetic ratio [rad/s/T] + odeparam.gamma = getGyroRatio(nucleus); % ODE solver call % OUTPUT: time T and magnetization M [T,M] = ode45(@(t,m) fcn_BLOCHUS_ode(t,m,odeparam),[0 Tsim],Minit,options); - % rotate M(T) vector into rotating reference frame + % get M(T) in rotating frame of reference Mrot = getMrot(M,getOmega0(odeparam.gamma,odeparam.B0).*T); f2 = figure; set(f2,'Name','example1b_ref'); @@ -156,11 +161,16 @@ % --- T2 = T1 % parameter needed for the ODE odeparam.type = 'std'; - odeparam.M0 = zunit; % equilibrium magnetization [A/m] - odeparam.B0 = 5e-5; % primary magnetic field B0 [T] - odeparam.T1 = 0.0010; % relaxation time T1 [s] - odeparam.T2 = 0.0010; % relaxation time T2 [s] - odeparam.gamma = getGyroRatio(nucleus); % gyromagnetic ratio [rad/s/T] + % equilibrium magnetization [A/m] + odeparam.M0 = zunit; + % primary magnetic field B0 [T] + odeparam.B0 = 5e-5; + % longitudinal relaxation time T1 [s] + odeparam.T1 = 0.0010; + % transversal relaxation time T2 [s] + odeparam.T2 = 0.0010; + % gyromagnetic ratio [rad/s/T] + odeparam.gamma = getGyroRatio(nucleus); % initial magnetization pointing towards +x Minit = [1 0 0]; % [A/m] @@ -171,7 +181,7 @@ % OUTPUT: time T and magnetization M [T,M] = ode45(@(t,m) fcn_BLOCHUS_ode(t,m,odeparam),[0 Tsim],Minit,options); - % rotate M(T) vector into rotating reference frame + % get M(T) in rotating frame of reference Mrot = getMrot(M,getOmega0(odeparam.gamma,odeparam.B0).*T); f3 = figure; set(f3,'Name','example1c_ref'); @@ -193,13 +203,14 @@ set(get(ax2,'Title'),'String','T1 = T2'); % --- T2 = 2*T1 - odeparam.T2 = 0.0020; % relaxation time T2 [s] + % transversal relaxation time T2 [s] + odeparam.T2 = 0.0020; % ODE solver call % OUTPUT: time T and magnetization M [T,M] = ode45(@(t,m) fcn_BLOCHUS_ode(t,m,odeparam),[0 Tsim],Minit,options); - % rotate M(T) vector into rotating reference frame + % get M(T) in rotating frame of reference Mrot = getMrot(M,getOmega0(odeparam.gamma,odeparam.B0).*T); ax3 = subplot(3,2,3); hold(ax3,'on'); @@ -222,13 +233,14 @@ set(get(ax4,'Title'),'String','T2 = 2T1'); % --- T1 = 2*T2 - odeparam.T2 = 0.0005; % relaxation time T2 [s] + % transversal relaxation time T2 [s] + odeparam.T2 = 0.0005; % ODE solver call % OUTPUT: time T and magnetization M [T,M] = ode45(@(t,m) fcn_BLOCHUS_ode(t,m,odeparam),[0 Tsim],Minit,options); - % rotate M(T) vector into rotating reference frame + % get M(T) in rotating frame of reference Mrot = getMrot(M,getOmega0(odeparam.gamma,odeparam.B0).*T); ax5 = subplot(3,2,5); hold(ax5,'on'); diff --git a/scripts/example2.m b/scripts/example2.m index 39f9db5..4ca3478 100644 --- a/scripts/example2.m +++ b/scripts/example2.m @@ -1,6 +1,6 @@ % script: example2.m -% this script demonstrates how basic pulses are used with BLOCHUS -% everything is done with a Hydrogen proton (gyromagnetic ratio > 0 ) +% This script demonstrates how basic pulses can be simulated with BLOCHUS +% everything is done with a Hydrogen proton (gyromagnetic ratio > 0) % % settings: % -> magnetic field B0 is set to 50 µT @@ -40,53 +40,93 @@ options = odeset('RelTol',tol,'AbsTol',[tol tol tol]); %% standard parameter -nucleus = '1H'; % hydrogen proton +% hydrogen proton +nucleus = '1H'; % parameter needed for the ODE odeparam.type = 'pulse'; -odeparam.M0 = zunit; % equilibrium magnetization [A/m] -odeparam.B0 = 5e-5; % primary magnetic field B0 [T] -odeparam.T1 = 0.0010; % relaxation time T1 [s] -odeparam.T2 = 0.0005; % relaxation time T2 [s] -odeparam.gamma = getGyroRatio(nucleus); % gyromagnetic ratio [rad/s/T] +% equilibrium magnetization [A/m] +odeparam.M0 = zunit; +% primary magnetic field B0 [T] +odeparam.B0 = 5e-5; +% longitudinal relaxation time T1 [s] +odeparam.T1 = 0.0010; +% transversal relaxation time T2 [s] +odeparam.T2 = 0.0005; +% gyromagnetic ratio [rad/s/T] +odeparam.gamma = getGyroRatio(nucleus); %% pulse modulation standard values +% pulse type [string] fmod.PulseType = 'pi_half'; +% shape of the modulation function [string] fmod.shape = 'const'; +% pulse start time [s] fmod.t0 = 0; +% pulse end time [s] fmod.t1 = 0.005; +% time vector [s] fmod.t = 0; +% start frequency [Hz] fmod.v0 = 0; +% end frequency [Hz] fmod.v1 = 0; +% modulation parameter (MIDI) fmod.A = 1; +% modulation parameter (MIDI) fmod.B = 0; +% shape of the modulation function [string] Imod.shape = 'const'; +% check if quality factor tuning is activated [0/1] Imod.useQ = 0; +% quality factor Imod.Q = 0; +% quality factor off-resonance frequency [Hz] Imod.Qdf = 0; +% pulse start time [s] Imod.t0 = 0; +% pulse end time [s] Imod.t1 = 0.005; +% time vector [s] Imod.t = 0; +% start current [A] Imod.v0 = 1; +% end current [A] Imod.v1 = 1; +% modulation parameter (MIDI) Imod.A = 1; +% modulation parameter (MIDI) Imod.B = 0; %% 1.) pi/2 pulse if usetest(1) - % excitation pulse parameter + + % relaxation during pulse [0/1] odeparam.RDP = 0; - odeparam.Ttau = 0.005; % [s] + % pulse length [s] + odeparam.Ttau = 0.005; + + % excitation pulse parameter + % pulse type [string] pulseparam.PulseType = fmod.PulseType; - pulseparam.Amp = odeparam.B0*abs((pi/2/(odeparam.gamma*odeparam.B0*odeparam.Ttau))); + % gyromagnetic ratio [rad/s/T] pulseparam.gamma = odeparam.gamma; + % Larmor frequency [rad/s] pulseparam.omega0 = getOmega0(odeparam.gamma,odeparam.B0); + % pulse amplitude [T] + pulseparam.Amp = odeparam.B0*abs((pi/2/(odeparam.gamma*odeparam.B0*odeparam.Ttau))); + % pulse frequency modulation [struct] pulseparam.fmod = fmod; + % pulse current modulation [struct] pulseparam.Imod = Imod; + % auxiliary pulse phase [rad] pulseparam.phi = 0; + % pulse axis [string] pulseparam.PulseAxis = '+x'; + % pulse polarization [string] pulseparam.PulsePolarization = 'circular'; + % save pulse parameter settings odeparam.pulseparam = pulseparam; % initial magnetization pointing towards B0 (+z) @@ -98,7 +138,7 @@ % OUTPUT: time T and magnetization M [T,M] = ode45(@(t,m) fcn_BLOCHUS_ode(t,m,odeparam),[0 Tsim],Minit,options); - % rotate M(T) vector into rotating reference frame + % get M(T) in rotating frame of reference Mrot = getMrot(M,getOmega0(odeparam.gamma,odeparam.B0).*T); f1 = figure; set(f1,'Name','example2a_ref'); @@ -141,20 +181,35 @@ %% 2.) pi pulse if usetest(2) + % new pulse type fmod.PulseType = 'pi'; - % excitation pulse parameter + + % relaxation during pulse [0/1] odeparam.RDP = 0; - odeparam.Ttau = 0.005; % [s] + % pulse length [s] + odeparam.Ttau = 0.005; + + % excitation pulse parameter + % pulse type [string] pulseparam.PulseType = fmod.PulseType; - pulseparam.Amp = odeparam.B0*abs((pi/(odeparam.gamma*odeparam.B0*odeparam.Ttau))); + % gyromagnetic ratio [rad/s/T] pulseparam.gamma = odeparam.gamma; + % Larmor frequency [rad/s] pulseparam.omega0 = getOmega0(odeparam.gamma,odeparam.B0); + % pulse amplitude [T] + pulseparam.Amp = odeparam.B0*abs((pi/(odeparam.gamma*odeparam.B0*odeparam.Ttau))); + % pulse frequency modulation [struct] pulseparam.fmod = fmod; + % pulse current modulation [struct] pulseparam.Imod = Imod; + % auxiliary pulse phase [rad] pulseparam.phi = 0; + % pulse axis [string] pulseparam.PulseAxis = '+x'; + % pulse polarization [string] pulseparam.PulsePolarization = 'circular'; + % save pulse parameter settings odeparam.pulseparam = pulseparam; % initial magnetization pointing towards B0 (+z) @@ -166,7 +221,7 @@ % OUTPUT: time T and magnetization M [T,M] = ode45(@(t,m) fcn_BLOCHUS_ode(t,m,odeparam),[0 Tsim],Minit,options); - % rotate M(T) vector into rotating reference frame + % get M(T) in rotating frame of reference Mrot = getMrot(M,getOmega0(odeparam.gamma,odeparam.B0).*T); f2 = figure; set(f2,'Name','example2b_ref'); @@ -209,20 +264,36 @@ %% 3.) pi/2 pulses with different pulse axes if usetest(3) + % new pulse type fmod.PulseType = 'pi_half'; + % excitation pulse parameter + % relaxation during pulse [0/1] odeparam.RDP = 0; - odeparam.Ttau = 0.005; % [s] + % pulse length [s] + odeparam.Ttau = 0.005; + + % excitation pulse parameter + % pulse type [string] pulseparam.PulseType = fmod.PulseType; - pulseparam.Amp = odeparam.B0*abs((pi/2/(odeparam.gamma*odeparam.B0*odeparam.Ttau))); + % gyromagnetic ratio [rad/s/T] pulseparam.gamma = odeparam.gamma; + % Larmor frequency [rad/s] pulseparam.omega0 = getOmega0(odeparam.gamma,odeparam.B0); + % pulse amplitude [T] + pulseparam.Amp = odeparam.B0*abs((pi/2/(odeparam.gamma*odeparam.B0*odeparam.Ttau))); + % pulse frequency modulation [struct] pulseparam.fmod = fmod; + % pulse current modulation [struct] pulseparam.Imod = Imod; + % auxiliary pulse phase [rad] pulseparam.phi = 0; + % pulse axis [string] pulseparam.PulseAxis = '+x'; + % pulse polarization [string] pulseparam.PulsePolarization = 'circular'; + % save pulse parameter settings odeparam.pulseparam = pulseparam; % initial magnetization pointing towards B0 (+z) @@ -234,7 +305,7 @@ % OUTPUT: time T and magnetization M [T,M] = ode45(@(t,m) fcn_BLOCHUS_ode(t,m,odeparam),[0 Tsim],Minit,options); - % rotate M(T) vector into rotating reference frame + % get M(T) in rotating frame of reference Mrot = getMrot(M,getOmega0(odeparam.gamma,odeparam.B0).*T); f3 = figure; set(f3,'Name','example2c_ref'); @@ -296,23 +367,37 @@ % (i.e. instead of -2000 Hz it is -2100 Hz) % because of the negative Larmor frequency of H-protons the rotation axis % dips downwards for negative ratios -if usetest(4) +if usetest(4) % df/omega_nut ratio ratio = -4:1:4; - + % new pulse type fmod.PulseType = 'pi_half'; + % excitation pulse parameter + % relaxation during pulse [0/1] odeparam.RDP = 0; - odeparam.Ttau = 0.005; % [s] + % pulse length [s] + odeparam.Ttau = 0.005; + + % excitation pulse parameter + % pulse type [string] pulseparam.PulseType = fmod.PulseType; - pulseparam.Amp = odeparam.B0*abs((pi/2/(odeparam.gamma*odeparam.B0*odeparam.Ttau))); + % gyromagnetic ratio [rad/s/T] pulseparam.gamma = odeparam.gamma; + % Larmor frequency [rad/s] pulseparam.omega0 = getOmega0(odeparam.gamma,odeparam.B0); + % pulse amplitude [T] + pulseparam.Amp = odeparam.B0*abs((pi/2/(odeparam.gamma*odeparam.B0*odeparam.Ttau))); + % pulse frequency modulation [struct] pulseparam.fmod = fmod; + % pulse current modulation [struct] pulseparam.Imod = Imod; + % auxiliary pulse phase [rad] pulseparam.phi = 0; + % pulse axis [string] pulseparam.PulseAxis = '+y'; - pulseparam.PulsePolarization = 'circular'; + % pulse polarization [string] + pulseparam.PulsePolarization = 'circular'; % nutation frequency for a pi/2 pulse with 5 ms is 50 Hz omega_nut = (pi/2)/odeparam.Ttau/2/pi; % [Hz] @@ -320,10 +405,12 @@ f4 = figure; set(f4,'Name','example2d_ref'); for i = 1:numel(ratio) - df = ratio(i)*omega_nut; % frequency offsets [Hz] + % frequency offsets [Hz] + df = ratio(i)*omega_nut; pulseparam.fmod.v0 = df; pulseparam.fmod.v1 = df; + % save pulse parameter settings odeparam.pulseparam = pulseparam; % initial magnetization pointing towards B0 (+z) @@ -342,7 +429,7 @@ pulseparam.t = T; [Bpulse,~,~,theta]= getPulseTimeSeries(pulseparam); - % rotate M(T) vector into rotating reference frame + % get M(T) in rotating frame of reference Mrot = getMrot(M,theta); ax(i) = subplot(3,3,i); hold(ax(i),'on'); %#ok<*SAGROW> @@ -375,3 +462,4 @@ % % You should have received a copy of the GNU General Public License % along with this program. If not, see . + diff --git a/scripts/example3.m b/scripts/example3.m index 74d2ea8..f78490e 100644 --- a/scripts/example3.m +++ b/scripts/example3.m @@ -1,9 +1,10 @@ % script: example3.m -% This script demonstrates the basic use of the BLOCHUS ode-solver. +% This script demonstrates how pre-polarization switch-off ramps are simulated +% with BLOCHUS. % Both examples were also used as benchmark cases in the paper: % Hiller, T., Dlugosch, R. and Müller-Petke, M., "Utilizing pre- % polarization to enhance SNMR signals - effect of imperfect -% switch-off", Geophysical Journal International Vol. 0(0), p.1-15, 2020 +% switch-off", Geophysical Journal International Vol. 222(2), p.815-826, 2020 % % Two pre-polarization switch-off benchmarks are shown: % @@ -188,13 +189,13 @@ %% 2.) Conradi et al.(2017) if usetest(2) - % Fig. 4a + % Fig. 4a of Conradi et al.(2017) % conradi_Bmax = 16/1e3; % [T] % conradi_Bstar = [2000 250 120]./1e6; % [T] % conradi_Tslope = 6/1e3; % [s] % conradi_lgdstr = {'2000','250','120'}; - % Fig. 4b + % Fig. 4b of Conradi et al.(2017) conradi_Bmax = 2.5/1e3; % [T] conradi_Bstar = [250 60 1]./1e6; % [T] conradi_Tslope = 10/1e3; % [s] diff --git a/scripts/example4.m b/scripts/example4.m new file mode 100644 index 0000000..fcb8d24 --- /dev/null +++ b/scripts/example4.m @@ -0,0 +1,230 @@ +% script: example4.m +% This script demonstrates how to calculate lookup-tables for pre-polarization +% switch-off ramps that can subsequently be used with MRSMatlab to forward +% model MRS sounding curves. +% Basically this script allows to create the data that is shown in Fig. 4 +% of the paper: +% Hiller, T., Dlugosch, R. and Müller-Petke, M., "Utilizing pre- +% polarization to enhance SNMR signals - effect of imperfect +% switch-off", Geophysical Journal International Vol. 222(2), p.815-826, 2020 +% +% general settings: +% - magnetic field B0 is set to 48 µT +% - T1, T2 - relaxation is ignored +% +% lookup table parameters: +% - pre-polarization field Bp ranges between 4.8µT and 480mT +% - initial orientation between Bp and B0 varies between 0° and 180° +% +% See also: BLOCHUS +% Author: Thomas Hiller +% email: thomas.hiller[at]leibniz-liag.de +% License: GNU GPLv3 (at end) + +%------------- BEGIN CODE -------------- + +% clear data +clear variables; clc; + +% because this script takes approx. 30min, ask the user before continuing +answer = questdlg({'This script needs about 30 min. to run.',... + 'Do you want to continue?'},'Dessert Menu','Yes','No','Yes'); +% handle response +switch answer + case 'Yes' + % nothing to do + case {'No',''} + return +end + +% output switches +save_data = true; +plot_data = true; + +% --- LOOKUP TABLE SETTINGS ----------------------------------------------- +% global lookup table settings (change as you like): +% all four major ramp shapes +lookup_ramps = {'exp','linexp','halfcos','lin'}; +% only three distinct switch-off times [s] +lookup_Tramps = [0.1 1 4]/1e3; + +% IMPORTANT NOTE: +% This very coarse (and basically useless) Np=10 x Nt=10 grid takes for the +% 4x3 ramp combinations (shapes x times) roughly 30min! The resolution in +% Fig.4 of the paper is Np=51 x Nt=360 ... so you don't want to start this +% calculation on your normal machine. +% local lookup table settings (careful with the discretization) +Np = 10; +Nt = 10; +% pre-polarization factor [B0] +PPfac = logspace(-1,4,Np); +% angle between Bp and B0 [deg] +theta = linspace(0,180,Nt); +% ------------------------------------------------------------------------- + +% basic settings +zunit = [0 0 1]'; % z unit vector +% ODE solver error tolerance +tol = 1e-9; +% ODE solver options +options = odeset('RelTol',tol,'AbsTol',[tol tol tol]); + +% hydrogen proton +nucleus = '1H'; + +% parameter needed for the ODE solver +% simulation type [string] +odeparam.type = 'prepol'; +% equilibrium magnetization [A/m] +odeparam.M0 = zunit; +% primary (Earth's) magnetic field B0 [T] +odeparam.B0 = 4.8e-5; +% relaxation time T1 [s] +odeparam.T1 = 2; +% relaxation time T2 [s] +odeparam.T2 = 1; +% gyromagnetic ratio [rad/s/T] +odeparam.gamma = getGyroRatio(nucleus); + +% pre-polarization switch-off ramp parameter +% relaxation during switch-off [0/1] +odeparam.RDS = 0; + +% because Minit is not normalized to 1, M0 needs to be adjusted +odeparam.M0 = odeparam.B0*zunit; + +data = cell(numel(lookup_ramps),numel(lookup_Tramps)); +for i1 = 1:numel(lookup_ramps) + for i2 = 1:numel(lookup_Tramps) + % current switch-off ramp and time + ramp = lookup_ramps{i1}; + Tramp = lookup_Tramps(i2); + + infostr1 = ['running: Ramp=',ramp,' | Tramp=',... + sprintf('%3.1f',Tramp*1e3),' ms']; + disp(infostr1); + + % create the output data matrix + % adiabatic quality p + p = zeros(numel(theta),numel(PPfac)); + % final magnetization vector + Mfinal = zeros(numel(theta),numel(PPfac),3); + % loop over the local parameters + for tt = 1:numel(theta) + for pp = 1:numel(PPfac) + + % switch-off ramp type [string] + rampparam.ramp = ramp; + % gyromagnetic ratio [rad/s/T] + rampparam.gamma = odeparam.gamma; + % primary (Earth's) magnetic field B0 [T] + rampparam.B0 = odeparam.B0; + % amplitude of pre-polarization field [T] + rampparam.Bmax = PPfac(pp)*odeparam.B0; + % switch-off ramp time [s] + rampparam.Tramp = Tramp; + + % different ramps need different settings + switch ramp + case 'exp' + SwitchFactor = 1; + % switch over ramp time [s] + rampparam.Tslope = Tramp/10; + case 'linexp' + SwitchFactor = PPfac(pp)/10; + rampparam.Tslope = Tramp/2; + case {'halfcos','lin'} + SwitchFactor = 1; + rampparam.Tslope = Tramp; + end + % switch-over amplitude for the "linexp" ramp (factor*B0) [T] + rampparam.Bstar = SwitchFactor*odeparam.B0; + + % initial orientation is towards y-axis + orient = getRotationMatrixFromAngleandAxis(deg2rad(theta(tt)),[0 1 0])*zunit; + % initial magnetization in the direction of B0+Bp + Morient = orient*rampparam.Bmax + odeparam.B0*zunit; + % Minit does not get normalized in this case + Minit = Morient; + % orientation of the pre-polarization pulse axis (y-axis) + odeparam.orient = orient; + + % add the ramp parameter to the ode parameter struct + odeparam.rampparam = rampparam; + + % ODE solver call + % OUTPUT: time T and magnetization M + [T,M] = ode45(@(t,m) fcn_BLOCHUS_ode(t,m,odeparam),[0 rampparam.Tramp],Minit,options); + + % normalized magnetization vector at end of switch-off ramp + MMn = M(end,:)./norm(M(end,:)); + % "adiabatic quality" p of the switch-off ramp + % -> orientation of M with respect to z_unit + p(tt,pp) = dot(MMn(end,:),zunit)./norm(zunit); + % final orientation of M + Mfinal(tt,pp,1:3) = M(end,:); + + end + infostr2 = [' | theta=',num2str(theta(tt)),'°']; + disp([infostr1,infostr2]); + end + disp([infostr1,' ... finished.']); + + % save the local lookup table for this particular combination of + % ramp shape and ramp time + data{i1,i2}.Tramp = Tramp; + data{i1,i2}.ramp = ramp; + data{i1,i2}.PPfac = PPfac; + data{i1,i2}.theta = theta; + data{i1,i2}.odeparam = odeparam; + data{i1,i2}.M = Mfinal; + data{i1,i2}.p = p; + end +end + +% save lookup table +if save_data + save('example4_lookup_table.mat','data'); +end + +% plot data +if plot_data + [xx,yy] = meshgrid(theta,PPfac); + figure; + count = 0; + for i1 = 1:numel(lookup_ramps) + for i2 = 1:numel(lookup_Tramps) + count = count + 1; + p = data{i1,i2}.p; + subplot(numel(lookup_ramps),numel(lookup_Tramps),count); + pcolor(xx,yy,p'); + shading flat; + set(gca,'XTick',linspace(0,180,5),'YScale','log',... + 'YTick',logspace(-1,4,6),'FontSize',10); + xlabel('\theta [deg]'); + ylabel('Bp [B0]'); + title([lookup_ramps{i1},' | ',sprintf('%3.1f',lookup_Tramps(i2)*1e3),'ms']); + end + end +end + +%------------- END OF CODE -------------- + +%% License: +% GNU GPLv3 +% +% BLOCHUS +% Copyright (C) 2019 Thomas Hiller +% +% This program is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% 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 . diff --git a/scripts/example4_ref.png b/scripts/example4_ref.png new file mode 100644 index 0000000..e725d86 Binary files /dev/null and b/scripts/example4_ref.png differ diff --git a/scripts/example5.m b/scripts/example5.m new file mode 100644 index 0000000..d77776a --- /dev/null +++ b/scripts/example5.m @@ -0,0 +1,236 @@ +% script: example5.m +% This script demonstrates how to calculate lookup-tables for an adiabatic +% half passage excitation pulse that can subsequently be used with MRSMatlab +% to forward model MRS sounding curves. +% Basically this script allows to create the data that is shown in Fig. 4b +% of the paper: +% Grunewald, E., Grombacher, D. and Walsh, D., "Adiabatic pulses enhance +% surface nuclear magnetic resonance measurement and survey speed for +% groundwater investigations", Geophysics Vol. 81(4), WB85-WB96, 2016 +% DOI: 10.1190/GEO2015-0527.1 +% +% NOTE: In this simulation the "My" component has a switched sign compared +% to Grunewald et al., 2016 due to the implementation of the reference phase +% and therewith accounting for the sign of the Larmor frequency (see e.g. +% Levitt, 2002). In practice, this has no effect on the result. +% +% general settings: +% - magnetic field B0 is set to 50 µT +% - T1, T2 - relaxation is ignored +% +% lookup table parameters for SWEEP1: +% - B1 ranges between 0.01µT and 100µT +% - frequency sweeps linearly from 2100 Hz to 2300 Hz, so from -200 +% to 0 Hz +% - amplitude tuning with quality factor Q=10 +% +% See also: BLOCHUS +% Author: Thomas Hiller +% email: thomas.hiller[at]leibniz-liag.de +% License: GNU GPLv3 (at end) + +%------------- BEGIN CODE -------------- + +% clear data +clear variables; clc; + +% because this script takes approx. 75min, ask the user before continuing +answer = questdlg({'This script needs about 75 min. to run.',... + 'Do you want to continue?'},'Dessert Menu','Yes','No','Yes'); +% handle response +switch answer + case 'Yes' + % nothing to do + case {'No',''} + return +end + +% output switches +save_data = true; +plot_data = true; + +% --- LOOKUP TABLE SETTINGS ----------------------------------------------- +% global lookup table settings (change as you like): +% B1 excitation amplitude [T] +% in the Grunewald et al., 2016 paper, there are in total 5000 points which +% would increase the calculation time to more than 6h! +N = 1000; +B1 = logspace(-8,-4,N); +% pulse length [s] +Ttau = 0.08; +% ------------------------------------------------------------------------- + +% basic settings +zunit = [0 0 1]'; % z unit vector +% ODE solver error tolerance +tol = 1e-9; +% ODE solver options +options = odeset('RelTol',tol,'AbsTol',[tol tol tol]); + +% hydrogen proton +nucleus = '1H'; + +% parameter needed for the ODE solver +% simulation type [string] +odeparam.type = 'pulse'; +% equilibrium magnetization [A/m] +odeparam.M0 = zunit; +% relaxation time T1 [s] +odeparam.T1 = 2; +% relaxation time T2 [s] +odeparam.T2 = 1; +% gyromagnetic ratio [rad/s/T] +odeparam.gamma = getGyroRatio(nucleus); +% primary (Earth's) magnetic field B0 [T] +odeparam.B0 = getB0(odeparam.gamma,2300*2*pi); + +% pulse settings for BLOCHUS +% dummy time vector with sampling freq 50 kHz +tt = 0:1/50000:Ttau; % [s] +PulseType = 'AHP'; + +% pulse type [string] +fmod.PulseType = PulseType; +% shape of the modulation function [string] +fmod.shape = 'lin'; +% time vector [s] +fmod.t = tt; +% pulse start time [s] +fmod.t0 = tt(1); +% pulse end time [s] +fmod.t1 = tt(end); +% start frequency [Hz] +fmod.v0 = -200; +% end frequency [Hz] +fmod.v1 = 0; +% modulation parameter (MIDI) +fmod.A = 1; +% modulation parameter (MIDI) +fmod.B = 0; + +% pulse type [string] +Imod.PulseType = PulseType; +% shape of the modulation function [string] +Imod.shape = 'lin'; +% check if quality factor tuning is activated [0/1] +Imod.useQ = 1; +% quality factor +Imod.Q = 10; +% quality factor off-resonance frequency [Hz] +Imod.Qdf = 0; +% time vector [s] +Imod.t = tt; +% pulse start time [s] +Imod.t0 = tt(1); +% pulse end time [s] +Imod.t1 = tt(end); +% start current [A] +Imod.v0 = 1; +% end current [A] +Imod.v1 = 1; +% modulation parameter (MIDI) +Imod.A = 1; +% modulation parameter (MIDI) +Imod.B = 0; + +% output data +Mfinal = zeros(numel(B1),6); +for i = numel(B1):-1:1 + + % relaxation during pulse [0/1] + odeparam.RDP = 0; + % pulse length [s] + odeparam.Ttau = tt(end); + + % excitation pulse parameter + % pulse type [string] + pulseparam.PulseType = PulseType; + % gyromagnetic ratio [rad/s/T] + pulseparam.gamma = odeparam.gamma; + % Larmor frequency [rad/s] + pulseparam.omega0 = getOmega0(odeparam.gamma,odeparam.B0); + % pulse amplitude [T] + pulseparam.Amp = B1(i); + % pulse frequency modulation [struct] + pulseparam.fmod = fmod; + % pulse current modulation [struct] + pulseparam.Imod = Imod; + % auxiliary pulse phase [rad] + pulseparam.phi = 0; + % pulse axis [string] + pulseparam.PulseAxis = '+y'; + % pulse polarization [string] + pulseparam.PulsePolarization = 'circular'; + + % save pulse parameter settings + odeparam.pulseparam = pulseparam; + + % initial magnetization pointing towards B0 (+z) [A/m] + Minit = zunit; + + % ODE solver call + % OUTPUT: time T and magnetization M + [T,M] = ode45(@(t,m) fcn_BLOCHUS_ode(t,m,odeparam),[0 odeparam.Ttau],Minit,options); + + % in order to get M in the rotating frame of reference, get the pulse + % phase theta for all simulation time steps + pulseparam.fmod.t = T; + pulseparam.Imod.t = T; + pulseparam.t = T; + [Bpulse,~,~,theta]= getPulseTimeSeries(pulseparam); + + % get M(T) in rotating frame of reference + Mrot = getMrot(M,theta); + + % final magnetization in lab and rot fame + Mfinal(i,1:6) = [M(end,:) Mrot(end,:)]; + + % show status + disp([num2str(i),' / ',num2str(numel(B1)),' done']); +end + +% save lookup table +if save_data + data.odeparam = odeparam; + data.B1 = B1; + data.Mfinal = Mfinal; + save('example5_lookup_table.mat','data'); +end + +% plot data +if plot_data + figure; + subplot(121); + semilogy(Mfinal(:,4),B1.*1e6); + xlim([-1 1]); + xlabel('Mx'); + ylabel('B1 [µT]'); + grid on; + + subplot(122); + semilogy(Mfinal(:,5),B1.*1e6); + xlim([-1 1]); + xlabel('My'); + grid on; +end + +%------------- END OF CODE -------------- + +%% License: +% GNU GPLv3 +% +% BLOCHUS +% Copyright (C) 2019 Thomas Hiller +% +% This program is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% 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 . diff --git a/scripts/example5_ref.png b/scripts/example5_ref.png new file mode 100644 index 0000000..9af67b4 Binary files /dev/null and b/scripts/example5_ref.png differ