diff --git a/AUTHORS.md b/AUTHORS.md new file mode 100644 index 0000000..fb8c80a --- /dev/null +++ b/AUTHORS.md @@ -0,0 +1,4 @@ +**NUCLEUS** is developed by + +* Stephan Costabel (since 2020), stephan.costabel@bgr.de +* Thomas Hiller (since 2018), thomas.hiller@bgr.de \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index b9fb491..2274cc9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,14 @@ # Changelog +## [0.1.14] - 2023-09-27 + +### Added +- New optional sub GUI *FixedTimeView* in **NUCLEUSinv** that allows to fix relaxation times (up to five) if the *N free exp. (2-5)* option for inversion is chosen and thus only the corresponding amplitudes are fitted +- New import routine in **NUCLEUSinv** for the LIAG core scanner (several NMR measurements along a core) + +### Changed +- Changed the import routines in **NUCLEUSinv** for *BGR* devices (*Mouse* and *Helios*) due to device software updates + ## [0.1.13] - 2022-08-11 ### Changed @@ -65,7 +74,7 @@ ### Added - A *last export* entry added to the export menu. It always shows the last chosen export routine (speeds up exporting when handling a lot of data). **NUCLEUSinv** -- Session files from an older *NUCLEUSinv* version can now be imported (starting from v.0.1.8). **NUCLEUSinv** +- Session files from an older **NUCLEUSinv** version can now be imported (starting from v.0.1.8). **NUCLEUSinv** ### Changed - Within the context menu of the signal list the entry *all* was renamed to *batch*. Now it indicates what it is actually doing - batch processing of multiple files. **NUCLEUSinv** @@ -181,6 +190,7 @@ Initial Version +[0.1.14]: https://github.com/ThoHiller/nmr-nucleus/compare/v.0.1.13...v.0.1.14 [0.1.13]: https://github.com/ThoHiller/nmr-nucleus/compare/v.0.1.12...v.0.1.13 [0.1.12]: https://github.com/ThoHiller/nmr-nucleus/compare/v.0.1.11...v.0.1.12 [0.1.11]: https://github.com/ThoHiller/nmr-nucleus/compare/v.0.1.10...v.0.1.11 diff --git a/NUCLEUSinv/NUCLEUSinv.m b/NUCLEUSinv/NUCLEUSinv.m index edc8bdd..0a0df4d 100644 --- a/NUCLEUSinv/NUCLEUSinv.m +++ b/NUCLEUSinv/NUCLEUSinv.m @@ -38,8 +38,8 @@ if ~isempty(h0); close(h0); end %% GUI 'header' info and defaults -myui.version = '0.1.13'; -myui.date = '11.08.2022'; +myui.version = '0.1.14'; +myui.date = '27.09.2023'; myui.author = {'Stephan Costabel','Thomas Hiller'}; myui.email = 'thomas.hiller[at]bgr.de'; myui.fontsize = 10; diff --git a/NUCLEUSinv/NUCLEUSinv_createMenus.m b/NUCLEUSinv/NUCLEUSinv_createMenus.m index b1c535a..e132cee 100644 --- a/NUCLEUSinv/NUCLEUSinv_createMenus.m +++ b/NUCLEUSinv/NUCLEUSinv_createMenus.m @@ -67,17 +67,17 @@ % 1.1.1.2.3 Mouse CPMG data, single data subfolders from CPMG gui.menu.file_import_lab_bgr_mouse_cpmg = uimenu(gui.menu.file_import_lab_bgr,... 'Label','MouseCPMG','Tag','Lab','Callback',@onMenuImport); -% 1.1.1.2.4 Mouse plus Lift, single data subfolder from t1test,... -% ...cpmgfastautotest, or (old Prospa Versions) cpmgfastauto -gui.menu.file_import_lab_bgr_mouse_liftsingle = uimenu(gui.menu.file_import_lab_bgr,... - 'Label','MouseLiftSingle','Tag','Lab','Callback',@onMenuImport); -% 1.1.1.2.5 Mouse plus Lift, all data subfolders from t1test,... +% 1.1.1.2.4 Mouse plus Lift, all data subfolders from t1test,... % cpmgfastautotest, or (old Prospa Versions) cpmgfastauto -gui.menu.file_import_lab_bgr_mouse_liftall = uimenu(gui.menu.file_import_lab_bgr,... - 'Label','MouseLiftAll','Tag','Lab','Callback',@onMenuImport); -% 1.1.1.2.6 Helios -gui.menu.file_import_lab_bgr_helios = uimenu(gui.menu.file_import_lab_bgr,... - 'Label','Helios','Tag','Lab','Callback',@onMenuImport); +gui.menu.file_import_lab_bgr_mouse_lift = uimenu(gui.menu.file_import_lab_bgr,... + 'Label','MouseLift','Tag','Lab','Callback',@onMenuImport); +% 1.1.1.2.5 Helios CPMG standard data, single subfolders with individual data files +gui.menu.file_import_lab_bgr_helios_cpmg = uimenu(gui.menu.file_import_lab_bgr,... + 'Label','HeliosCPMG','Tag','Lab','Callback',@onMenuImport); +% 1.1.1.2.6 Helios series of CPMG data, several files of a series in the target +% folder, as used e.g. for T1 measurements +gui.menu.file_import_lab_bgr_helios_series = uimenu(gui.menu.file_import_lab_bgr,... + 'Label','HeliosSeries','Tag','Lab','Callback',@onMenuImport); % 1.1.1.3 LIAG gui.menu.file_import_lab_liag = uimenu(gui.menu.file_import_lab,... @@ -88,6 +88,9 @@ % 1.1.1.3.2 LIAG gui.menu.file_import_lab_liag_project = uimenu(gui.menu.file_import_lab_liag,... 'Label','LIAG from project','Tag','Lab','Callback',@onMenuImport); +% 1.1.1.3.3 LIAG +gui.menu.file_import_lab_liag_core = uimenu(gui.menu.file_import_lab_liag,... + 'Label','LIAG core','Tag','Lab','Callback',@onMenuImport); % 1.1.1.4 RWTH gui.menu.file_import_lab_rwth = uimenu(gui.menu.file_import_lab,... @@ -203,6 +206,9 @@ % 1.2.1.9 LIAG CSV T2 gui.menu.file_export_data_liag_csvT2 = uimenu(gui.menu.file_export_data,... 'Label','LIAG CSV T2','Callback',@onMenuExportData); +% 1.2.1.10 BGR data repository ascii +gui.menu.file_export_data_bgr_repo = uimenu(gui.menu.file_export_data,... + 'Label','BGR repository','Callback',@onMenuExportData); % 1.2.2 Graphics gui.menu.file_export_graphics = uimenu(gui.menu.file_export,... @@ -306,6 +312,9 @@ % 2.7 ConductVIEW -> hydraulic conductivity gui.menu.extra_conduct = uimenu(gui.menu.view,... 'Label','ConductView GUI','Enable','off','Callback',@onMenuViewFigures); +% 2.8 FixedTime VIEW +gui.menu.extra_fixedtime = uimenu(gui.menu.view,... + 'Label','FixedTimeView GUI','Enable','off','Callback',@FixedTimeView); %% 3. Extras gui.menu.extra = uimenu(gui.figh,... diff --git a/NUCLEUSinv/NUCLEUSinv_loadDefaults.m b/NUCLEUSinv/NUCLEUSinv_loadDefaults.m index 5e3985b..38b8a15 100644 --- a/NUCLEUSinv/NUCLEUSinv_loadDefaults.m +++ b/NUCLEUSinv/NUCLEUSinv_loadDefaults.m @@ -103,6 +103,9 @@ out.invstd.invtype = 'NNLS'; % when inversion method is 'free' choose No. of free relaxation times out.invstd.freeDT = 2; +% option to fix some of the 'free' relaxation times to a certain value +out.invstd.Tfixed_bool = [0 0 0 0 0]; +out.invstd.Tfixed_val = [0 0 0 0 0]; % regularization options for multi-exponential fitting routines % 'NNLS' and 'LU' out.invstd.regtype = 'manual'; diff --git a/NUCLEUSinv/NUCLEUSinv_updateInterface.m b/NUCLEUSinv/NUCLEUSinv_updateInterface.m index 9141613..b47f550 100644 --- a/NUCLEUSinv/NUCLEUSinv_updateInterface.m +++ b/NUCLEUSinv/NUCLEUSinv_updateInterface.m @@ -102,7 +102,7 @@ 'Value',data.invstd.freeDT,... 'String',{'1','2','3','4','5'}); set(gui.text_handles.invstd_InvTypeOpt,... - 'String','No. of free decay times T'); + 'String','No. of free relaxation times T'); % lambda, smoothness constraint and RTD limits gui = updateLambda(gui,data.invstd.regtype,0,0,0); @@ -586,7 +586,7 @@ 'Value',data.invstd.freeDT,... 'String',{'1','2','3','4','5'}); set(gui.text_handles.invstd_InvTypeOpt,... - 'String','No. of free decay times T'); + 'String','No. of relaxation decay times T'); % lambda, smoothness constraint and RTD limits gui = updateLambda(gui,data.invstd.regtype,0,0,0); @@ -675,22 +675,19 @@ switch gatetype - case 'log' - + case 'log' set(gui.radio_handles.process_gates_log,'Value',1); set(gui.radio_handles.process_gates_lin,'Value',0); set(gui.radio_handles.process_gates_none,'Value',0); set(gui.edit_handles.process_Nechoes,'Enable','on'); - case 'lin' - + case 'lin' set(gui.radio_handles.process_gates_log,'Value',0); set(gui.radio_handles.process_gates_lin,'Value',1); set(gui.radio_handles.process_gates_none,'Value',0); set(gui.edit_handles.process_Nechoes,'Enable','on'); - case 'raw' - + case 'raw' set(gui.radio_handles.process_gates_log,'Value',0); set(gui.radio_handles.process_gates_lin,'Value',0); set(gui.radio_handles.process_gates_none,'Value',1); diff --git a/NUCLEUSmod/NUCLEUSmod.m b/NUCLEUSmod/NUCLEUSmod.m index 9ed5920..1b1d52a 100644 --- a/NUCLEUSmod/NUCLEUSmod.m +++ b/NUCLEUSmod/NUCLEUSmod.m @@ -41,8 +41,8 @@ if ~isempty(h0); close(h0); end %% GUI 'header' info and defaults -myui.version = '0.1.13'; -myui.date = '11.08.2022'; +myui.version = '0.1.14'; +myui.date = '27.09.2023'; myui.author = {'Stephan Costabel','Thomas Hiller'}; myui.email = 'thomas.hiller[at]bgr.de'; myui.fontsize = 10; diff --git a/README.md b/README.md index ec75e0e..4c0cd75 100644 --- a/README.md +++ b/README.md @@ -108,7 +108,7 @@ In no particular order and without guarantee that it will ever happen :-) : ### Cite as If you use NUCLEUS for your research, please cite it as: -Thomas Hiller. (2022, Aug 11). ThoHiller/nmr-nucleus: v0.1.13 (Version v0.1.13). Zenodo. [https://doi.org/10.5281/zenodo.4022195] +Thomas Hiller. (2023, Sep 27). ThoHiller/nmr-nucleus: v0.1.14 (Version v0.1.14). Zenodo. [https://doi.org/10.5281/zenodo.4022195] 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. diff --git a/callbacks/listboxes/onListboxData.m b/callbacks/listboxes/onListboxData.m index 07706f7..1adc6b3 100644 --- a/callbacks/listboxes/onListboxData.m +++ b/callbacks/listboxes/onListboxData.m @@ -69,6 +69,13 @@ function onListboxData(src,~) data_upd.calib = data.calib; data_upd.pressure = data.pressure; data = data_upd; + + % if "mono" or "free" inversion is chossen update the internal + % fixed relaxation times field + if strcmp(data.invstd.invtype,'mono') ||... + strcmp(data.invstd.invtype,'free') + data.invstd.Tfixed_val = [data.results.invstd.T zeros(1,5-data.invstd.freeDT)]; + end setappdata(fig,'data',data); % update interface and plot axes @@ -190,6 +197,10 @@ function onListboxData(src,~) if ~isempty(findobj('Tag','PHASEVIEW')) PhaseView(gui.menu.extra_phaseview); end + % if the FixedTimeView window is open update it + if ~isempty(findobj('Tag','FIXEDTIMEVIEW')) + FixedTimeView(gui.menu.extra_fixedtime); + end else helpdlg({'onListboxData:','Only choose one data set at a time.'},... 'too many data'); diff --git a/callbacks/menus/onMenuExpert.m b/callbacks/menus/onMenuExpert.m index f566e50..f7505cf 100644 --- a/callbacks/menus/onMenuExpert.m +++ b/callbacks/menus/onMenuExpert.m @@ -55,6 +55,17 @@ function onMenuExpert(src,~) % update GUI data setappdata(fig,'data',data); setappdata(fig,'gui',gui); + + % dectivate FixedTime View GUI + data.invstd.Tfixed_bool = zeros(1,5); + data.invstd.Tfixed_val = zeros(1,5); + setappdata(fig,'data',data); + % check if the figure is already open + fig_fixedtime = findobj('Tag','FIXEDTIMEVIEW'); + if ~isempty(fig_fixedtime) + delete(fig_fixedtime); + end + set(gui.menu.extra_fixedtime,'Enable','off'); % deactivate solver menu and set to default onMenuSolver(gui.menu.extra_solver_lsqnonneg); @@ -87,7 +98,10 @@ function onMenuExpert(src,~) data.info.ExpertMode = 'on'; % menu entry set(gui.menu.extra_expert,'Checked','on'); - + + % activate FixedTime View GUI + set(gui.menu.extra_fixedtime,'Enable','on'); + % activate solver menu if optimization toolbox is available switch data.info.has_optim case 'on' diff --git a/callbacks/menus/onMenuExportData.m b/callbacks/menus/onMenuExportData.m index 9765c05..7d562b0 100644 --- a/callbacks/menus/onMenuExportData.m +++ b/callbacks/menus/onMenuExportData.m @@ -58,7 +58,9 @@ function onMenuExportData(src,~) case 'LIAG archive' exportData(fig_tag,'LIAG'); case 'LIAG CSV T2' - exportData(fig_tag,'LIAGcsvT2'); + exportData(fig_tag,'LIAGcsvT2'); + case 'BGR repository' + exportData(fig_tag,'BGR_repos'); end % update the "last export" value within the ini-file gui = getappdata(fig,'gui'); diff --git a/callbacks/menus/onMenuExtraColor.m b/callbacks/menus/onMenuExtraColor.m index 2c0860a..0fcb813 100644 --- a/callbacks/menus/onMenuExtraColor.m +++ b/callbacks/menus/onMenuExtraColor.m @@ -33,7 +33,6 @@ function onMenuExtraColor(src,~) fig = ancestor(src,'figure','toplevel'); fig_tag = get(fig,'Tag'); gui = getappdata(fig,'gui'); -data = getappdata(fig,'data'); % get the menu label label = get(src,'Label'); @@ -65,6 +64,11 @@ function onMenuExtraColor(src,~) % adjust the colors changeColorTheme(fig_tag,label); +% check the sub GUIs +if ~isempty(findobj('Tag','FIXEDTIMEVIEW')) + changeColorTheme('FIXEDTIMEVIEW',label); +end + end %------------- END OF CODE -------------- diff --git a/callbacks/popup/onPopupInvstdType.m b/callbacks/popup/onPopupInvstdType.m index fe4c6ee..f646451 100644 --- a/callbacks/popup/onPopupInvstdType.m +++ b/callbacks/popup/onPopupInvstdType.m @@ -47,12 +47,32 @@ function onPopupInvstdType(src,~) data.invstd.invtype = 'mono'; data.invstd.regtype = 'none'; data.invstd.lambda = 1; + data.invstd.freeDT = 1; + +% % if the FixedTimeView window is open update it +% if ~isempty(findobj('Tag','FIXEDTIMEVIEW')) +% data.invstd.Tfixed_bool = zeros(1,5); +% % update GUI data +% setappdata(fig,'data',data); +% FixedTimeView(gui.menu.extra_fixedtime); +% data = getappdata(fig,'data'); +% end case 2 data.invstd.invtype = 'free'; data.invstd.regtype = 'none'; data.invstd.lambda = 1; - + data.invstd.freeDT = 2; + +% % if the FixedTimeView window is open update it +% if ~isempty(findobj('Tag','FIXEDTIMEVIEW')) +% data.invstd.Tfixed_bool = zeros(1,5); +% % update GUI data +% setappdata(fig,'data',data); +% FixedTimeView(gui.menu.extra_fixedtime); +% data = getappdata(fig,'data'); +% end + case 3 data.invstd.invtype = 'NNLS'; data.invstd.regtype = 'manual'; @@ -75,11 +95,13 @@ function onPopupInvstdType(src,~) data.invstd.invtype = 'mono'; data.invstd.regtype = 'none'; data.invstd.lambda = 1; + data.invstd.freeDT = 1; case 2 data.invstd.invtype = 'free'; data.invstd.regtype = 'none'; data.invstd.lambda = 1; + data.invstd.freeDT = 2; case 3 data.invstd.invtype = 'NNLS'; @@ -107,6 +129,16 @@ function onPopupInvstdType(src,~) data.invstd.lambda = 1; end end + +% if the FixedTimeView window is open update it +if ~isempty(findobj('Tag','FIXEDTIMEVIEW')) + data.invstd.Tfixed_bool = zeros(1,5); + % update GUI data + setappdata(fig,'data',data); + FixedTimeView(gui.menu.extra_fixedtime); + data = getappdata(fig,'data'); +end + % update GUI data setappdata(fig,'data',data); % update interface diff --git a/callbacks/popup/onPopupInvstdTypeOptional.m b/callbacks/popup/onPopupInvstdTypeOptional.m index e9b6278..39371ca 100644 --- a/callbacks/popup/onPopupInvstdTypeOptional.m +++ b/callbacks/popup/onPopupInvstdTypeOptional.m @@ -46,8 +46,16 @@ function onPopupInvstdTypeOptional(src,~) % change settings accordingly switch invtype case 'free' - % # free decay times = value (1 to 5) + % # free relaxation times = value (1 to 5) data.invstd.freeDT = value; + + % if the FixedTimeView window is open update it + if ~isempty(findobj('Tag','FIXEDTIMEVIEW')) + % update GUI data + setappdata(fig,'data',data); + FixedTimeView(gui.menu.extra_fixedtime); + data = getappdata(fig,'data'); + end case 'NNLS' switch data.info.ExpertMode diff --git a/doc/menu.html b/doc/menu.html index 1cd7e85..2a650a4 100644 --- a/doc/menu.html +++ b/doc/menu.html @@ -16,7 +16,7 @@