Unable to create GUI for 20 subjects

Dear Osprey-team,

I ran into a problem when trying to analyze all my patients (N=20) at once. It first runs all the steps of the analysis normally, and then runs into an error just before generating the GUI (see below). I’m using the HERCULES sequence, and interestingly have no trouble running the control group (N=11) through the same analysis and generating a GUI to visually inspect data quality. So it seems somewhat linked to sample size. Do you have any advice how to deal with this error?

Full Osprey runtime: 3602.327713 seconds
Timestamp July 06, 2023 16:14:09 Osprey 2.4.0 OspreyGUI
Index in position 1 exceeds array bounds. Index must not exceed 12.

Error in osp_plotOverviewSpec (line 189)
plot(data{1}.ppm,real(data{1}.specs(:,ind))+shift ,‘color’, cb(g,:), ‘LineWidth’, 1); %data

Error in osp_iniOverviewWindow (line 110)
temp = osp_plotOverviewSpec(MRSCont, tempSubNames{1}, g, gui.layout.shiftind);

Error in OspreyGUI (line 509)
osp_iniOverviewWindow(gui);

Thank you in advance!

Hi @Kia_Puustinen,

thanks for reaching out.

We have actually analyzed HERCULES/HERMES data with > 100 subjects and visualized it in the GUI so there must be another issue in your specific case. A few questions to possibly figure this out:

  • Did you use the GUI to create the jobfile?
  • Did you create a group csv file to indicate the different subgroups for the analysis?

Best,
Helge

Hi Helge,

Thank you for your response! That’s what I was thinking, should be completely possible to analyze all 20, but I just don’t know where things went wrong. My jobfile was not created through the GUI, and the csv file should be correct, as I did similar things for the control group. Do you have any other ideas for where the problem could lie? All suggestions are warmly welcome! Thank you so much in advance.

Best,
Kia

What’s the exact sequence of commands you’ve been running for the control analysis and the patient analysis? Did you run them in two separate sessions?

Hi Georg,

The commands I use look like this, and I run it separately for patients and controls indeed.

jobFileLocation = ‘path to script’;

MRSCont = OspreyJob(jobFileLocation); % Generate MRS container

MRSCont = OspreyLoad(MRSCont); % Load data into MRS container

MRSCont = OspreyProcess(MRSCont); % Process data

MRSCont = OspreyFit(MRSCont); % Linear-combination modelling

MRSCont = OspreyCoreg(MRSCont); % Coregistration module

MRSCont = OspreySeg(MRSCont); % Segmentation module

MRSCont = OspreyQuantify(MRSCont); % Quantification module

MRSCont = OspreyOverview(MRSCont); % Create visualization

gui = OspreyGUI(MRSCont)% Start GUI (optional)

The jobfile is nearly identical for both groups, I only correct the exact path to each folder of data.

%% jobSDAT.m
%
% This function describes an Osprey job defined in a MATLAB script.
%
% AUTHOR:
% Dr. Georg Oeltzschner (Johns Hopkins University, 2019-07-15)
% goeltzs1@jhmi.edu
% 2019-07-15: First version of the code.
%
% ADAPTED:
% Dra. Kia Puustinen (UHasselt, 2023-02-16)
% kia.puustinen@uhasselt.be
%
% ADAPTED:
% Melina Hehl (KUL/UHasselt, 2023-02-19)
% melina.hehl@kuleuven.be.
% → Adapted to fit BIDS structure with .sdat and .spar files
% (see markings with %MH 2023-02-19)

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% 1. SPECIFY SEQUENCE INFORMATION %%%

% Specify sequence type
seqType = ‘HERCULES’; % OPTIONS: - ‘unedited’ (default)
% - ‘MEGA’
% - ‘HERMES’
% - ‘HERCULES’

% Specify editing targets
editTarget = {‘GABA’, ‘GSH’}; % OPTIONS: - {‘none’} (default if ‘unedited’)
% - {‘GABA’}, {‘GSH’}, {‘Lac’}, {‘PE322’}, {‘PE398’} (for ‘MEGA’)
% - {‘GABA’, ‘GSH’}, {‘GABA’, ‘Lac’}, {‘NAA’, ‘NAAG’} (for 'HERMES’and ‘HERCULES’)

                            % Specify data scenario

dataScenario = ‘invivo’; % OPTIONS: - ‘invivo’ (default)
% - ‘phantom’
% - ‘PRIAM’
% - ‘MRSI’
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% 2. SPECIFY DATA HANDLING AND MODELING OPTIONS %%%
% Which spectral registration method should be used? Robust spectral
% registration is default, a frequency restricted spectral registration
% method is also availaible and is linked to the fit range.
opts.SpecReg = ‘RobSpecReg’; % OPTIONS: - ‘RobSpecReg’ (default) Spectral aligment with Water/Lipid removal, using simialrity meric, and weighted averaging
% - ‘ProbSpecReg’ Probabilistic aligment to median target and weighted averaging
% - ‘RestrSpecReg’ Frequency restricted (fit range) spectral aligment, using simialrity meric, and weighted averaging
% - ‘none’

% Which algorithm do you want to align the sub spectra? L2 norm
% optimization is the default. This is only used for edited MRS!
%Perform correction on the metabolite data (raw) or metabolite
%-nulled data (mm).
opts.SubSpecAlignment.mets = ‘L1Norm’; % OPTIONS: - ‘L2Norm’
% - ‘L1Norm’
% - ‘none’

%Perform eddy-current correction on the metabolite data (raw) or metabolite
%-nulled data (mm). This can either be done similar for all data sets by
%supplying a single value or specified for each dataset individually by supplying
% multiple entries (number has to match the number of datasets) e.g. to perform ECC
% for the second dataset only:
% opts.ECC.raw = [0 1];
% opts.ECC.mm = [0 1];

opts.ECC.raw = 1; % OPTIONS: - ‘1’ (default)
opts.ECC.mm = 1; % - ‘0’ (no)
% - array

% Save LCModel-exportable files for each spectrum?
opts.saveLCM = 1; % OPTIONS: - 0 (no, default)
% - 1 (yes)
% Save jMRUI-exportable files for each spectrum?
opts.savejMRUI = 0; % OPTIONS: - 0 (no, default)
% - 1 (yes)

% Save processed spectra in vendor-specific format (SDAT/SPAR, RDA, P)?
opts.saveVendor = 0; % OPTIONS: - 0 (no, default)
% - 1 (yes)

% Save processed spectra in NIfTI-MRS format?
opts.saveNII = 0; % OPTIONS: - 0 (no, default)
% - 1 (yes)

% Save PDF output for all Osprey modules and subjects?
opts.savePDF = 0; % OPTIONS: - 0 (no, default)
% - 1 (yes)

% Select the metabolites to be included in the basis set as a cell array,
% with entries separates by commas.
% With default Osprey basis sets, you can select the following metabolites:
% Ala, Asc, Asp, bHB, bHG, Cit, Cr, Cystat, CrCH2, EtOH, GABA, GPC, GSH, Glc, Gln,
% Glu, Gly, H2O, mI, Lac, NAA, NAAG, PCh, PCr, PE, Phenyl, sI, Ser,
% Tau, Tyros, MM09, MM12, MM14, MM17, MM20, Lip09, Lip13, Lip20.
% If you enter ‘default’, the basis set will include all of the above
% except for Ala, bHB, bHG, Cit, Cystat, EtOH, Glc, Gly, Phenyl, Ser, and Tyros.
opts.fit.includeMetabs = { ‘Asc’ ‘Asp’ ‘Cr’ ‘CrCH2’ ‘GABA’ ‘GPC’ ‘GSH’ ‘Gln’ ‘Glu’ ‘H2O’ ‘mI’ ‘Lac’ ‘NAA’ ‘NAAG’ ‘PCh’ ‘PCr’ ‘PE’ ‘sI’ ‘Tau’ ‘MM09’ ‘MM12’ ‘MM14’ ‘MM17’ ‘MM20’ ‘Lip09’ ‘Lip13’ ‘Lip20’}; % OPTIONS: - {‘default’}
% - {custom}

% Choose the fitting algorithm
opts.fit.method = ‘Osprey’; % OPTIONS: - ‘Osprey’ (default)
% - ‘LCModel’

% Choose the fitting style for difference-edited datasets (MEGA, HERMES, HERCULES)
% (only available for the Osprey fitting method)
opts.fit.style = ‘Separate’; % OPTIONS: - ‘Concatenated’ (default) - will fit DIFF and SUM simultaneously)
% - ‘Separate’ - will fit DIFF and OFF separately

% Determine fitting range (in ppm) for the metabolite and water spectra
opts.fit.range = [0.5 4]; % [ppm] Default: [0.5 4]
opts.fit.rangeWater = [2.0 7.4]; % [ppm] Default: [2.0 7.4]

% Determine the baseline knot spacing (in ppm) for the metabolite spectra
opts.fit.bLineKnotSpace = 0.4; % [ppm] Default: 0.4.

% Add macromolecule and lipid basis functions to the fit?
opts.fit.fitMM = 1; % OPTIONS: - 0 (no)
% - 1 (yes, default)
opts.UnstableWater = 1;

% Optional: In case the automatic basisset picker is not working you can manually
% select the path to the basis set in the osprey/fit/basis, i.e.:
% opts.fit.basisSetFile = ‘osprey/fit/basis/3T/philips/mega/press/gaba68/basis_philips_megapress_gaba68.mat’;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% 3. SPECIFY MRS DATA AND STRUCTURAL IMAGING FILES %%

% Clear existing files
clear files files_ref files_w files_nii files_mm

% Data folder in BIDS format
% The filparts(which()) comment is needed to find the data on your machine. If you set
% up the jobFile for your own data you can set a direct path to your data
% folder e.g., data_folder = /Volumes/MyProject/data/’

data_folder = ‘C:\Users\kiapu\Desktop\S65741\BIDS_new\patient\HERCULES’;

% The following lines perform an automated set-up of the jobFile which
% takes advatage of the BIDS foramt. If you are not using BIDS (highly
% recommended) you can look at the definitions below the loop to see how to
% set up direct path links to your data.

subs = dir(data_folder);
subs(1:2) = ;
subs = subs([subs.isdir]);
subs = subs(contains({subs.name},‘sub’));
counter = 1;

for kk = 1:length(subs)
% Loop over sessions
sess = dir([subs(kk).folder filesep subs(kk).name]);
sess(1:2) = ;
sess = sess([sess.isdir]);
sess = sess(contains({sess.name},‘ses’));
for ll = 1:length(sess)

    % Specify metabolite data
    % (MANDATORY)
    dir_metabolite    = dir([sess(ll).folder filesep sess(ll).name filesep 'mrs' filesep subs(kk).name '_' sess(ll).name '_acq-ACChercules_svs.SDAT']); %MH 2023-02-19
    files(counter)    = {[dir_metabolite(end).folder filesep dir_metabolite(end).name]};

    % Specify water reference data for eddy-current correction (same sequence as metabolite data!)
    % (OPTIONAL)
    % Leave empty for GE P-files (.7) - these include water reference data by
    % default.
    dir_ref    = dir([sess(ll).folder filesep sess(ll).name filesep 'mrs' filesep subs(kk).name '_' sess(ll).name '_acq-ACChercules_ref.SDAT']);  %MH 2023-02-19
    files_ref(counter)  = {[dir_ref(end).folder filesep dir_ref(end).name]};

    % Specify water data for quantification (e.g. short-TE water scan)
    % (OPTIONAL)
    files_w     = {};

    % Specify metabolite-nulled data for quantification
    % (OPTIONAL)
    files_mm     = {};

   % Specify T1-weighted structural imaging data
    % (OPTIONAL)
    % Link to single NIfTI (*.nii) files for Siemens and Philips data
    % Link to DICOM (*.dcm) folders for GE data
    %files_nii(counter)  = {[sess(ll).folder filesep sess(ll).name filesep 'anat' filesep subs(kk).name filesep sess(ll).name '_T1w.nii']};
    files_nii(counter)  = {[sess(ll).folder filesep sess(ll).name filesep 'anat' filesep subs(kk).name '_' sess(ll).name '_T1w.nii']};

    % External segmentation results
    % (OPTIONAL)
    % Link to NIfTI (*.nii or *.nii.gz) files with segmentation results
    % Add supply gray matter, white matter, and CSF as 1 x 3 cell within a
    % cell array  or a single 4D file in the same order supplied as 1 x 1 cell;

% files_seg(counter) = {{[sess(ll).folder filesep sess(ll).name filesep ‘anat’ filesep subs(kk).name filesep ‘c1’ sess(ll).name ‘_T1w.nii.gz’],…
% [sess(ll).folder filesep sess(ll).name filesep ‘anat’ filesep subs(kk).name filesep ‘c2’ sess(ll).name ‘_T1w.nii.gz’],…
% [sess(ll).folder filesep sess(ll).name filesep ‘anat’ filesep subs(kk).name filesep ‘c3’ sess(ll).name ‘_T1w.nii.gz’]}};

% files_seg(counter) = {{[sess(ll).folder filesep sess(ll).name filesep ‘anat’ filesep subs(kk).name filesep ‘4D’ sess(ll).name ‘_T1w.nii.gz’]}};

    counter             = counter + 1;
end

end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% 4. SPECIFY STAT FILE %%%
% file_stat = fullfile(data_folder, ‘stat.csv’);
file_stat = fullfile(data_folder, ‘stat.csv’);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% 5. SPECIFY OUTPUT FOLDER %%
outputFolder = ‘C:\Users\kiapu\Documents\Osprey output’;

Sorry for the long reply. Have a great day!

Hi @Kia_Puustinen,

Thanks for the info. I don’t see any obvious issues in there. Could you also post the stat.csv file that is referenced in the jobfile?

Best,
Helge

Here it is! Doesn’t usually give me trouble with the controls, but I’m not sure I did it exactly correctly. stat.csv (274 Bytes)

Thanks. I think I see why it is crashing now.

The ‘group’ column is a numerical identifier to separate the whole dataset into for example controls and patients. If you have two groups you would set all control subjects to 1 and the patients to 2. In your file, you are counting from 1 to 20 which is just passing the limit of possible colors in the colorbrewer (currently initialized with 12 colors). If you set all of them to one it should work just fine (see attached).

Could you try replacing the stat file and re-running OspreyOverview.

stat.csv (261 Bytes)

Thank you so much! Indeed, this was incorrect, and now it ran the analysis smoothly. Thank you for the help!