diff --git a/BLOCHUS/BLOCHUS.m b/BLOCHUS/BLOCHUS.m index 4aee16d..140ba1e 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.1'; -myui.date = '16.05.2020'; +myui.version = '0.1.2'; +myui.date = '17.05.2020'; myui.author = 'Thomas Hiller'; myui.email = 'thomas.hiller[at]leibniz-liag.de'; diff --git a/CHANGELOG.md b/CHANGELOG.md index f930f9b..be506bd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,13 +1,29 @@ -#### Changelog +# Changelog -##### Version v.0.1.1 +## [0.1.2] - 2020-05-17 -1. bug fix: in `onPushRun.m` the adiabatic quality p was incorrectly calculated when the total simulation time exceeded the actual switch-off ramp time -2. bug fix: both axes for the pulse frequency and current modulation are now show correctly when exporting the *Current View* figure from the menu -3. new feature: an animation of the latest result can be played for all parameter combinations (e.g. *Pulse + Relaxation* or *Pre-polarization switch-off + Pulse + Relaxation*, etc.) -4. typo fixing within comments and `README.md` +### Changed +- Updated `README.md` and `CHANGELOG.md`. +### Fixed -##### Version v.0.1.0 +- When switching the *Pulse* panel on/off, the quality factor settings did not behave as expected. + +## [0.1.1] - 2020-05-16 + +### Added +- An animation of the latest result can be played for all parameter combinations (e.g. *Pulse + Relaxation* or *Pre-polarization switch-off + Pulse + Relaxation*, etc.). + +### Fixed + +- The adiabatic quality p was incorrectly calculated in `onPushRun.m` when the total simulation time exceeded the actual switch-off ramp time. +- When exporting the *Current View* figure from the menu, both axes for the pulse setup (frequency and current modulation) are now correctly shown. +- Fixed typos in comments and `README.md`. + +## [0.1.0] - 2020-05-15 Initial Version + +[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 8e3a367..66673f0 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,25 @@ ## BLOCHUS + + **BLOCH** **U**niversal **S**imulator [![release](https://img.shields.io/github/release/ThoHiller/nmr-blochus.svg)](https://github.com/ThoHiller/nmr-blochus/releases/latest) [![DOI](https://zenodo.org/badge/264257175.svg)](https://zenodo.org/badge/latestdoi/264257175) - - - +### Table of Contents +1. [About](#about) +2. [Requirements](#requirements) +3. [Installation](#installation) +4. [Usage](#usage) +5. [Documentation](#documentation) +6. [ToDo](#todo) +7. [Cite as & References](#references) +8. [Changelog](CHANGELOG.md) + +- - - + ### About **BLOCHUS** is a set of MATLABTM tools, that allow some basic simulations of (S)NMR spin dynamics based on the Bloch equations. The Bloch equations are solved in the laboratory frame of reference with MATLABs built-in `ode45` solver. Because it was developed within the scope of a near surface SNMR project, its main features are the simulation of (1) pre-polarization switch-off ramps and (2) excitation pulses. The main front-end to the underlying simulation tools is a graphical user interface (GUI) that allows playing around with the different features and helps to understand the basic concepts of (S)NMR spin dynamics. @@ -15,31 +29,35 @@ 2. Choose between different pre-polarization switch-off ramp shapes (e.g. *exponential*, *linear*, *half cosine*, etc.) with arbitrary ramp time 3. Choose between different excitation pulses (*pi/2*, *pi*, *adiabatic half passage*, etc.) with arbitrary off-resonance frequency, or in case of the adiabatic pulses, arbitrary frequency and current modulation. -- - - + + + +- - - + ### Requirements In order to work properly you need to meet the following requirements: -1. The [Mathworks](https://www.mathworks.com) MATLABTM software development environment (tested with R2017b and newer) +1. The [Mathworks](https://www.mathworks.com) MATLABTM software development environment (tested with R2017a and newer) 2. The GUI Layout Toolbox (get it from [FEX](https://de.mathworks.com/matlabcentral/fileexchange/47982-gui-layout-toolbox)) (required) 3. `findjobj` (get it from [FEX](https://de.mathworks.com/matlabcentral/fileexchange/14317-findjobj-find-java-handles-of-matlab-graphic-objects)) (required) #### Operating System -I tested it successfully under Windows 7 (64bit) and 10 (64bit) with Matlab R2018a. +I tested it successfully under Windows 7 (64bit) and 10 (64bit) with Matlab R2017a and newer. Always with the latest version of the GUI Layout Toolbox (current version is v2.3.4) **NOTE:** So far I did not test anything on Linux or a Mac. If you get it to work on either of the two systems (which it basically should I guess) please let me know. - - - - + ### Installation 1. It is recommended to install the GUI Layout Toolbox directly into MATLABTM via the mltbx-file (but it should also work via the old-school way of adding the toolbox folders to the MATLABTM path) 2. To use **BLOCHUS** you just need to place the `blochus` folder from the git repository on your hard drive and use the start script `startBLOCHUS` (within this script all necessary **BLOCHUS** folders are added to the MATLABTM path) - - - - + ### Usage 1. By executing the start scripts (see above) @@ -47,14 +65,14 @@ I tested it successfully under Windows 7 (64bit) and 10 (64bit) with Matlab R201 3. Check the example scripts for the usage of the core functions without the GUI (inside the `scripts` folder) - - - - + ### Documentation A basic documentation to **BLOCHUS** can be found in the `blochus\doc` folder. Just open the `index.html` in the web browser of your choice. The documentation was created with [m2html](https://www.artefact.tk/software/matlab/m2html/) by Guillaume Flandin. - - - - -### TODO + +### ToDo In no particular order and without guarantee that it will ever happen :-) : @@ -63,6 +81,14 @@ In no particular order and without guarantee that it will ever happen :-) : 3. ... - - - + +### 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] + +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 diff --git a/blochus_gui_ahp.png b/blochus_gui_ahp.png new file mode 100644 index 0000000..2db9379 Binary files /dev/null and b/blochus_gui_ahp.png differ diff --git a/blochus_gui_linexp.png b/blochus_gui_linexp.png new file mode 100644 index 0000000..9db16be Binary files /dev/null and b/blochus_gui_linexp.png differ diff --git a/blochus_logo_small.png b/blochus_logo_small.png new file mode 100644 index 0000000..0b65e06 Binary files /dev/null and b/blochus_logo_small.png differ diff --git a/callbacks/checkbox/onCheckPrePolPulse.m b/callbacks/checkbox/onCheckPrePolPulse.m index bee76f5..60739c8 100644 --- a/callbacks/checkbox/onCheckPrePolPulse.m +++ b/callbacks/checkbox/onCheckPrePolPulse.m @@ -97,6 +97,9 @@ function onCheckPrePolPulse(src,~) set(gui.edit_handles.PulseIend,'Enable','off'); set(gui.edit_handles.PulseIA,'Enable','off'); set(gui.edit_handles.PulseIB,'Enable','off'); + set(gui.check_handles.PulseQ,'Enable','off'); + set(gui.edit_handles.PulseQ,'Enable','off'); + set(gui.edit_handles.PulseQdf,'Enable','off'); % clear Pulse axes clearSingleAxis(gui.axes_handles.PulseB); @@ -156,6 +159,9 @@ function onCheckPrePolPulse(src,~) set(gui.edit_handles.PulseIend,'Enable','off'); set(gui.edit_handles.PulseIA,'Enable','off'); set(gui.edit_handles.PulseIB,'Enable','off'); + set(gui.check_handles.PulseQ,'Enable','off'); + set(gui.edit_handles.PulseQ,'Enable','off'); + set(gui.edit_handles.PulseQdf,'Enable','off'); % clear Pulse axes clearSingleAxis(gui.axes_handles.PulseB); diff --git a/callbacks/checkbox/onCheckPulseQ.m b/callbacks/checkbox/onCheckPulseQ.m index 0590785..6a3bab1 100644 --- a/callbacks/checkbox/onCheckPulseQ.m +++ b/callbacks/checkbox/onCheckPulseQ.m @@ -39,9 +39,13 @@ function onCheckPulseQ(src,~) switch get(src,'Value') case 0 + data.pulse.Istart = 0; + set(gui.edit_handles.PulseIstart,'String',num2str(data.pulse.Istart)); set(gui.edit_handles.PulseQ,'Enable','off'); set(gui.edit_handles.PulseQdf,'Enable','off'); - case 1 + case 1 + data.pulse.Istart = 1; + set(gui.edit_handles.PulseIstart,'String',num2str(data.pulse.Istart)); set(gui.edit_handles.PulseQ,'Enable','on'); set(gui.edit_handles.PulseQdf,'Enable','on'); end diff --git a/callbacks/popup/onPopupPulseDFmode.m b/callbacks/popup/onPopupPulseDFmode.m index 14d1ef1..0ab2058 100644 --- a/callbacks/popup/onPopupPulseDFmode.m +++ b/callbacks/popup/onPopupPulseDFmode.m @@ -59,14 +59,14 @@ function onPopupPulseDFmode(src,~) case 3 % tanh GMR data.pulse.DFmode = 'tanhGMR'; - data.pulse.DFstart = -300; + data.pulse.DFstart = -200; set(gui.edit_handles.PulseDFstart,'String',num2str(data.pulse.DFstart)); set(gui.edit_handles.PulseDFA,'Enable','off'); set(gui.edit_handles.PulseDFB,'Enable','off'); case 4 % exp data.pulse.DFmode = 'exp'; - data.pulse.DFstart = -300; + data.pulse.DFstart = -200; data.pulse.DFA = 10; set(gui.edit_handles.PulseDFstart,'String',num2str(data.pulse.DFstart)); set(gui.edit_handles.PulseDFA,'String',num2str(data.pulse.DFA)); diff --git a/callbacks/popup/onPopupPulseImode.m b/callbacks/popup/onPopupPulseImode.m index 5806b9c..000924b 100644 --- a/callbacks/popup/onPopupPulseImode.m +++ b/callbacks/popup/onPopupPulseImode.m @@ -50,10 +50,8 @@ function onPopupPulseImode(src,~) case 2 % tanh MIDI data.pulse.Imode = 'tanhMIDI'; - data.pulse.Istart = 0; data.pulse.IA = 0.5; data.pulse.IB = 1; - set(gui.edit_handles.PulseIstart,'String',num2str(data.pulse.Istart)); set(gui.edit_handles.PulseIA,'String',num2str(data.pulse.IA)); set(gui.edit_handles.PulseIA,'Enable','on'); set(gui.edit_handles.PulseIB,'String',num2str(data.pulse.IB)); @@ -61,16 +59,12 @@ function onPopupPulseImode(src,~) case 3 % tanh GMR data.pulse.Imode = 'tanhGMR'; - data.pulse.Istart = 0; - set(gui.edit_handles.PulseIstart,'String',num2str(data.pulse.Istart)); set(gui.edit_handles.PulseIA,'Enable','off'); set(gui.edit_handles.PulseIB,'Enable','off'); case 4 % exp data.pulse.Imode = 'exp'; - data.pulse.Istart = 0; data.pulse.IA = 10; - set(gui.edit_handles.PulseIstart,'String',num2str(data.pulse.Istart)); set(gui.edit_handles.PulseIA,'String',num2str(data.pulse.IA)); set(gui.edit_handles.PulseIA,'Enable','on'); set(gui.edit_handles.PulseIB,'Enable','off'); diff --git a/callbacks/popup/onPopupPulseType.m b/callbacks/popup/onPopupPulseType.m index 7b26288..1d815c5 100644 --- a/callbacks/popup/onPopupPulseType.m +++ b/callbacks/popup/onPopupPulseType.m @@ -69,6 +69,8 @@ function onPopupPulseType(src,~) set(gui.edit_handles.PulseIA,'Enable','off'); set(gui.edit_handles.PulseIB,'Enable','off'); set(gui.check_handles.PulseQ,'Enable','off'); + set(gui.edit_handles.PulseQ,'Enable','off'); + set(gui.edit_handles.PulseQdf,'Enable','off'); case 2 % pi data.pulse.Type = 'pi'; @@ -96,6 +98,8 @@ function onPopupPulseType(src,~) set(gui.edit_handles.PulseIA,'Enable','off'); set(gui.edit_handles.PulseIB,'Enable','off'); set(gui.check_handles.PulseQ,'Enable','off'); + set(gui.edit_handles.PulseQ,'Enable','off'); + set(gui.edit_handles.PulseQdf,'Enable','off'); case 3 % free data.pulse.Type = 'free'; @@ -120,6 +124,8 @@ function onPopupPulseType(src,~) set(gui.edit_handles.PulseIA,'Enable','off'); set(gui.edit_handles.PulseIB,'Enable','off'); set(gui.check_handles.PulseQ,'Enable','off'); + set(gui.edit_handles.PulseQ,'Enable','off'); + set(gui.edit_handles.PulseQdf,'Enable','off'); case 4 % AHP data.pulse.Type = 'AHP'; @@ -133,7 +139,11 @@ function onPopupPulseType(src,~) set(gui.edit_handles.PulseDFA,'Enable','off'); set(gui.edit_handles.PulseDFB,'Enable','off'); - data.pulse.Istart = 0; + if get(gui.check_handles.PulseQ,'Value') == 0 + data.pulse.Istart = 0; + else + data.pulse.Istart = 1; + end data.pulse.Iend = 1; set(gui.popup_handles.PulseImode,'Enable','on'); set(gui.edit_handles.PulseIstart,'Enable','on','String',num2str(data.pulse.Istart)); @@ -142,6 +152,9 @@ function onPopupPulseType(src,~) set(gui.edit_handles.PulseIB,'Enable','off'); set(gui.check_handles.PulseQ,'Enable','on'); + setappdata(fig,'data',data); + onCheckPulseQ(gui.check_handles.PulseQ); + data = getappdata(fig,'data'); setappdata(fig,'data',data); onPopupPulseDFmode(gui.popup_handles.PulseDFmode); data = getappdata(fig,'data'); @@ -173,6 +186,8 @@ function onPopupPulseType(src,~) set(gui.edit_handles.PulseIA,'Enable','off'); set(gui.edit_handles.PulseIB,'Enable','off'); set(gui.check_handles.PulseQ,'Enable','off'); + set(gui.edit_handles.PulseQ,'Enable','off'); + set(gui.edit_handles.PulseQdf,'Enable','off'); % update the GUI as if the number of periods would have been % changed manually @@ -209,6 +224,8 @@ function onPopupPulseType(src,~) set(gui.edit_handles.PulseIA,'Enable','on','String',num2str(data.pulse.IA)); set(gui.edit_handles.PulseIB,'Enable','on','String',num2str(data.pulse.IB)); set(gui.check_handles.PulseQ,'Enable','off'); + set(gui.edit_handles.PulseQ,'Enable','off'); + set(gui.edit_handles.PulseQdf,'Enable','off'); % update the GUI as if the number of periods would have been % changed manually diff --git a/doc/blochus/BLOCHUS/BLOCHUS.html b/doc/blochus/BLOCHUS/BLOCHUS.html index cc1f0b7..f677553 100644 --- a/doc/blochus/BLOCHUS/BLOCHUS.html +++ b/doc/blochus/BLOCHUS/BLOCHUS.html @@ -105,8 +105,8 @@