schorschinho / osprey

All-in-one toolbox for processing of magnetic resonance spectroscopy data.
https://schorschinho.github.io/osprey
MIT License
52 stars 41 forks source link

Issue with running Osprey on dcm file #705

Closed Mtay316 closed 3 months ago

Mtay316 commented 3 months ago

Hi Osprey team,

I have followed the tutorial documentations on your website and was able to generate all the results using your example data. Now I am going to test it on my data. We used single voxel MRS sequence using GE (3.0 T Premier) scanner. Now I have one single dicom image. When I ran your code on my single dcm image, I get this error:

Error using contains First argument must be text.

Error in read_dcm_header (line 36) if contains(tline,'HFS')

Error in io_loadspec_dicom (line 37) DicomHeader = read_dcm_header(filesInFolder{1});

Error in osp_LoadDICOM (line 67) raw = io_loadspec_dicom(MRSCont.files{metab_ll,kk});

Error in OspreyLoad (line 201) [MRSCont] = osp_LoadDICOM(MRSCont);

Error in osp_onLoad (line 35) MRSCont = OspreyLoad(MRSCont);

Error while evaluating UIControl Callback.


I assume there is something related to metadata of the file. It expects the first argument to be text and seems like mine is an integer. You can see the first lines of the metadata of my file and also the second image is the single dicome file I used as an input. Could you please help me to find out where the issue is and how to fix it?

Screenshot 2024-03-28 at 12 26 17 PM Screenshot 2024-03-28 at 12 25 46 PM

Computer configuration (please complete the following information):


My modified code:

%%% 3. SPECIFY MRS DATA AND STRUCTURAL IMAGING FILES %% % When using single-average Siemens RDA or DICOM files, specify their % folders instead of single 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 = fileparts(which(fullfile('MERP_test','UnEdited','jobSDAT.m')));

% 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 '_press' filesep '*.dcm']);
    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 '_press-ref' filesep '*.dcm']);
    %files_ref(counter)  = {};

    % 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 subs(kk).name '_' sess(ll).name '_T1w.nii.gz']};

    % 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


Regards, Maryam

schorschinho commented 3 months ago

Thanks for reaching out. I am not sure that your job file is sufficiently modified. Can you try pointing the files variable to the explicit path on your drive instead of trying to use the loop structure (which requires that your data is strictly organized according to a BIDS-like subject/session structure)?

Mtay316 commented 3 months ago

Thanks Georg for you reply. First, I decided to put my data in your BIDS structure folders and run it. But now with your suggestion, I have modified it and defined my path like below:

data_folder = '/Users/mtay316/Documents/osprey-develop/MERP_test/Test/data';

% 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 '_press' filesep '*.dcm']);
    files     = {'/Users/mtay316/Documents/osprey-develop/MERP_test/Test/data/sub-01_ses-01.dcm',...
                 '/Users/mtay316/Documents/osprey-develop/MERP_test/Test/data/sub-02_ses-01.dcm'};

    % 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 '_press-ref' filesep '*.dcm']);
    %files_ref(counter)  = {};

    % 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 = {'/Users/mtay316/Documents/osprey-develop/MERP_test/Test/data/sub-01_ses-01_T1w.nii.gz',...
                           '/Users/mtay316/Documents/osprey-develop/MERP_test/Test/data/sub-02_ses-01_T1w.nii.gz'};

However, I have received the same error :

Error using contains First argument must be text.

Error in read_dcm_header (line 36) if contains(tline,'HFS')

Error in io_loadspec_dicom (line 37) DicomHeader = read_dcm_header(filesInFolder{1});

Error in osp_LoadDICOM (line 67) raw = io_loadspec_dicom(MRSCont.files{metab_ll,kk});

Error in OspreyLoad (line 201) [MRSCont] = osp_LoadDICOM(MRSCont);

Error in osp_onLoad (line 35) MRSCont = OspreyLoad(MRSCont);

Error while evaluating UIControl Callback.


Anything specifically in my metadata you think I need to modify?

schorschinho commented 3 months ago

Hmm - odd. I am not too familiar with the GE DICOMs, so I'm unsure what could be going on. Is it possible for you to de-identify this file and share it (or acquire a dataset in a phantom bottle)?

Mtay316 commented 3 months ago

Ax PROBE SV 35TE LT FRONTAL - 18.zip

I could not send the T1w file because the size limit does not allow me. But the MRS single dicom file is attached. Thanks for checking it.

schorschinho commented 3 months ago

How did you obtain this DICOM file?

This appears to be a DICOM file of the 1.2.840.10008.5.1.4.1.1.4 SOP class with DICOM tag (0002,0002) - this class contains images, and indeed, if I open it in my DICOM viewer, I can see an image of the spectrum.

But this class does not contain the raw data that is needed for data analysis (these will have the SOP class UID 1.2.840.10008.5.1.4.1.1.4.2), and there is no way to retrospectively obtain it without re-exporting.

I'm not familiar enough with GE scanners to give detailed instructions on how to export the necessary (correct) DICOM files, but I'm hoping @alexcraven might. Otherwise you'll have to export P-files (ending in .7).

Mtay316 commented 3 months ago

Thanks, Georg, for your clarification. I am new to MRS processing, so I have no idea what raw data on MRS looks like. I will wait to see if Alex knows how to export the required correct DICOM files. Hopefully, there is a way, otherwise, all my data will be useless.

alexcraven commented 3 months ago

Hi @Mtay316. For GE systems, we don't usually use DICOM for MRS data storage -- what you have here is an image of the reconstructed spectrum, without the underlying data.

To get the data itself, you will need to open a command prompt on your scanner console and find the right files under /usr/g/mrraw. These will have names like P01234.7. You can use the command ls -ltr to list these with dates/times, most recent at the end. It's best to copy the necessary file to a network share, but you can also use a mounted USB drive for example. It might be worth checking with your local GE rep and/or local IT to find a good solution for your environment.

You should fetch the raw data immediately after scanning -- filenames are recycled, so on a busy system they are likely to be overwritten in a couple of days.

If you're still in the piloting stage, I suggest you spend a little more time optimising the protocol. The quality here isn't great. Frontal placements can be difficult, but you would probably get some improvements by adjusting the positioning a little, maybe changing the frequency direction, and increasing the number of averages.

alexcraven commented 3 months ago

@schorschinho : since this was raised as an Osprey issue, perhaps the documentation (around section 2.3) could be updated to include "preferred" formats for the major vendors, and suggestions for where to get hold of these? If it's out of scope for the Osprey docs, could instead add it to MRSHub with a link from the Osprey docs? I could make a start for GE and Siemens.

schorschinho commented 3 months ago

Thanks so much, Alex - super helpful. I generally think that this is a bit out of scope for Osprey documentation indeed. There's a pretty good rationale for keeping "how-to" practical guides for data export over at the MRSHub. We certainly have very detailed instructions for the various Philips raw data formats that we could put join up with your GE/Siemens bits! I love the idea.

Mtay316 commented 3 months ago

Thanks @alexcraven , that was a very helpful point. I will check with our GE rep. Unfortuently we finished our data collection. I hope there is still a way to get .7 data. Regarding optimizing the sequence, I will definetly share it with our team and technician. Thanks a lot