tapas icon indicating copy to clipboard operation
tapas copied to clipboard

PhysIO Not Accepting 7T .resp, .ext and .puls Files?

Open EmilyJD777 opened this issue 1 year ago • 19 comments

Hi there,

I've got raw PMU fomatted data for Siemens 7T fMRI (as .ext. .puls and .resp files). I can't seem to get PhysIO to read the formatting, which looks like this: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 5003 ECG Freq Per: 0 0 PULS Freq Per: 65 911 RESP Freq Per: 10 5980 EXT Freq Per: 0 0 EXT2 Freq Per: 0 0 ECG Min Max Avg StdDiff: 110 545 276 123 PULS Min Max Avg StdDiff: 547 2823 909 15 RESP Min Max Avg StdDiff: 3380 11720 5859 776 EXT Min Max Avg StdDiff: 1660 30005 6694 4698 EXT2 Min Max Avg StdDiff: 0 0 0 0 NrTrig NrMP NrArr AcqWin: 0 0 0 0 LogStartMDHTime: 9405947 LogStopMDHTime: 14579527 LogStartMPCUTime: 37313200 LogStopMPCUTime: 42486697 6003

Is this is known issue in PhysIO or have I missed something? Any help you might have would be greatly appreciated. Thanks again!

EmilyJD777 avatar Oct 08 '24 15:10 EmilyJD777

Dear Emily,

Thank you for trying out the PhysIO Toolbox!

This looks like the standard Siemens VB / IdeaCmdTool log format, and you could start from that example to adapt your script or matlab job. Would you be able to export your job file as a .m and paste it here. Or provide some error message output when you try to run it?

Thank you and

All the best, Lars

mrikasper avatar Oct 08 '24 17:10 mrikasper

Hi Lars,

Thanks for your quick response! Here is a copy of the base script I am trying to get functional: ` logDir = 'Z:\derivatives\brainstem_funk\BIDS_DAY2\sub-001\physio'; % /baseDir/physio/s01/run01 cd (logDir); PULS = dir('.puls'); RESP = dir('.resp'); EXT = dir('*.ext');

% 2. Define physio model structure physio = tapas_physio_new();

% 3. Define input files physio.save_dir = 'Z:\derivatives\brainstem_funk\BIDS_DAY2\sub-001\physio'; % enter directory to save physIO output physio.log_files.cardiac = 'sub-001_allruns.puls'; % .puls file physio.log_files.respiration = 'sub-001_allruns.resp'; % .resp file physio.log_files.scan_timing = 'sub-001_allruns.ext'; % Log file physio.log_files.vendor = 'Siemens_Tics'; % Vendor physio.log_files.relative_start_acquisition = 0; % only used for Philips physio.log_files.align_scan = 'last'; % sync log and EPI files from the last scan

% 4. Define scan timing parameters physio.scan_timing.sqpar.Nslices = 52; % number of slices in EPI volume physio.scan_timing.sqpar.TR = 1; % TR in secs physio.scan_timing.sqpar.Ndummies = 0; % Real dummy are not recorded physio.scan_timing.sqpar.Nscans = 426; % number of time points/scans/volumes physio.scan_timing.sqpar.onset_slice = 51; % slice of interest (choose middle slice if unsure?) physio.scan_timing.sync.method = 'scan_timing_log'; % using info file

% 5. Define cardiac data parameters physio.preproc.cardiac.modality = 'PPU'; % cardiac data acquired with PPU physio.preproc.cardiac.initial_cpulse_select.auto_matched.min = -0.4; physio.preproc.cardiac.initial_cpulse_select.auto_matched.file = 'initial_cpulse_kRpeakfile.mat'; physio.preproc.cardiac.posthoc_cpulse_select.off = struct([]);

% 6. Define generic physio model parameters physio.model.orthogonalise = 'none'; physio.model.output_multiple_regressors = 'multiple_regressors.txt'; %% regressor output filename`

Here is the error I am getting: `Error using regexp The 'STRING' input must be either a char row vector, a cell array of char row vectors, or a string array.

Error in tapas_physio_read_columnar_textfiles (line 107) haveFoundColumnHeader = any(regexp(upper(strLine), strColumnHeader));

Error in tapas_physio_read_physlogfiles_siemens_tics (line 109) C = tapas_physio_read_columnar_textfiles(log_files.respiration, 'RESP');

Error in tapas_physio_read_physlogfiles (line 92) tapas_physio_read_physlogfiles_siemens_tics(log_files, cardiac_modality, verbose);

Error in tapas_physio_main_create_regressors (line 121) verbose] = tapas_physio_read_physlogfiles(...

Error in physIO_example_script_TEST (line 82) tapas_physio_main_create_regressors(physio);`

Is Siemens_Tics the proper input for physio.log_files.vendor? Or is this error related to something else? It's looks like formatting to me.

EmilyJD777 avatar Oct 08 '24 20:10 EmilyJD777

Dear Emily,

The format you have is not Siemens_Tics, but Siemens. You will have to change this in the physio.log_files.vendor field.

Have a look at the example data for PhysIO: After typing tapas_init() in the TAPAS main folder, download the example data via tapas_download_example_data() and check the tapas/examples/<your_version>/PhysIO/Siemens_VB/PPU3T_Sync_First folder for the matlab script .m file.

The SPM job code version of the example comes with the code, if you use SPM anyway.

Also, I would recommend using the DICOM file of your first or last volume in the fMRI run as input for physio.log_files.scan_timing. On most scanners, the .ext file does not contain any triggers, but only 0s.

I hope that helps.

All the best, Lars

mrikasper avatar Oct 08 '24 20:10 mrikasper

Sorry, I'm a bit new. Unfortunately, I don't have access to the dicoms for this particular data set, but there does appear to be triggers in the .ext file (at least I think so). There are a lot of zeroes but a sequence every so often ' 1 1 5000 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1'. Does this signify a trigger? Are the fMRI DICOM files necessary to run PhysIO?

When modifying it to 'Siemens' I get this following error: Index exceeds the number of array elements. Index must not exceed 0.

Error in tapas_physio_read_physlogfiles_siemens (line 104) tStartScanDicom = dicomHeader{1}.AcquisitionTime;

Error in tapas_physio_read_physlogfiles (line 87) tapas_physio_read_physlogfiles_siemens(log_files, cardiac_modality, verbose, ...

Error in tapas_physio_main_create_regressors (line 121) verbose] = tapas_physio_read_physlogfiles(...

Error in physIO_example_script_TEST (line 82) tapas_physio_main_create_regressors(physio);

Is this related to the lack of DICOM files?

Apologies if the questions are obvious, but I'm new to this and just trying to figure it all out. Thanks again so much for your help here.

EmilyJD777 avatar Oct 08 '24 21:10 EmilyJD777

Dear Emily,

You can just put physio.scan_timing.sync.method = 'nominal' to see whether it runs through at all.

If you don't have a DICOM file, maybe you got a .json sidecar file instead with your fMRI run (same name as the .nii file, but with .json file extension)? The information is in there as well, and I have a development version of the PhysIO code that could work with that one.

All the best, Lars

mrikasper avatar Oct 09 '24 15:10 mrikasper

Thanks again for this info! This has been really helpful. I have another question couple questions for you if that's okay.

  1. What is the best way to calculate log_files.relative_start_acquisition if I know my physiological data was started before the scan began and do not have access to dicom files? I have, say an acquisition time of 10:43:49.480000 and start and stop times in the physio logs for: LogStartMDHTime: 10282865 LogStopMDHTime: 10756050 LogStartMPCUTime: 38491580 LogStopMPCUTime: 38964792

Why is there a discrepancy between LogStopMPCUTime - LogStartMPCUTime and LogStopMDHTime - LogStartMDHTime? Which should I use? If I have 189 volumes, will it correctly align the start time with how many volumes?

  1. Some of our earlier participants only have one long .res, .puls and .ext file for all runs combined. Is it still possible to parse these out somehow?

Again, thank you so much for your time!

EmilyJD777 avatar Oct 09 '24 17:10 EmilyJD777

Dear Emily,

  1. You don't have to parse out the relative_start_acquisition (just leave it at 0), if you provide a scan_timing_log file, e.g., the .json sidecar and the AcquisitionTime variable therein.. The parsing and synchronization is exactly what PhysIO will do for you in the initial read-in steps. The intricacies of the LogStart/Stop and MDH/MPCU Time variables have been scrutinized multiple times, for example here in our Wiki. I don't think there is a satisfactory answer.
  2. Yes, it's possible. Again, if you have the actual .json sidecar file (or AcquisitionTime variable) for the actual run you want to compute the physiological noise regressors for, PhysIO will sync the timing for you automatically. I would recommend to use physio.log_files.align_scan = 'first';, if you base it on the AcquisitionTime from the .json sidecar file.

All the best, Lars

mrikasper avatar Oct 09 '24 20:10 mrikasper

I've tried having the log_files.scan_timing as my .ext file path with the triggers in it (which would be optimal) and I've also tried the log_files.scan_timing as my .json file path. I've also tried both scan_timing.sync.method = 'nominal'; and scan_timing.sync.method = 'scan_timing_log';

I've tried each combination of these parameters and no matter what, I am getting the following error:

tapas_physio_main_create_regressors(physio)
Warning: Z:\derivatives\brainstem_funk\physio\YA\Day2\001\001.ext: Not a DICOM file. 
In spm_dicom_header (line 54)
In spm_dicom_headers (line 27)
In tapas_physio_read_physlogfiles_siemens (line 103)
In tapas_physio_read_physlogfiles (line 87)
In tapas_physio_main_create_regressors (line 137) 
Index exceeds the number of array elements. Index must not exceed 0.
Error in tapas_physio_read_physlogfiles_siemens (line 114)
        dc = dicomHeader{1};
Error in tapas_physio_read_physlogfiles (line 87)
            tapas_physio_read_physlogfiles_siemens(log_files, cardiac_modality, verbose, ...
Error in tapas_physio_main_create_regressors (line 137)
                verbose] = tapas_physio_read_physlogfiles(... 
>> 

It seems as though it keeps looking for a DICOM file. Is there any way around using the DICOMS?

**Edited for length.

EmilyJD777 avatar Oct 09 '24 22:10 EmilyJD777

Really hoping to find a solution to this! Thanks again!

EmilyJD777 avatar Oct 16 '24 21:10 EmilyJD777

Dear Emily,

  1. scan_timing.sync.method = 'nominal' should work without specifying a log_files.scan_timing_log file. Can you try to leave the file empty, i.e., physio.log_files.scan_timing = '';
  2. Are you able to share the .json file you tried to use? It might be that you are running into an issue I fixed in a development branch of PhysIO and haven't released yet.

Thank you and

All the best, Lars

mrikasper avatar Oct 17 '24 15:10 mrikasper

When I run it with physio.log_files.scan_timing = ''; and scan_timing.sync.method = 'nominal', it does run and outputs figures, but then runs into an error saying:

Error using tapas_physio_main_create_regressors Please specify an onset slice.

I've attached a .json file here. sub-001_task-cloudy_acq-ep2d19mm_run-01_echo-1_bold.json

EmilyJD777 avatar Oct 17 '24 19:10 EmilyJD777

Just wanted to follow up on this as it is still an issue. Thanks again!

EmilyJD777 avatar Oct 22 '24 15:10 EmilyJD777

Dear Emily,

For the 'nominal' scan timing setting, did you specify the onset slice like in your example above, i.e.,

physio.scan_timing.sqpar.onset_slice = 51;

?

It's really odd why that part is not working, but I will only have time next week to look closely into this.

All the best, Lars

mrikasper avatar Oct 23 '24 18:10 mrikasper

I did. I have even managed to get access to the dicoms so that I could make use of the data and the last dicom isn't working either. I'd rather use the trigger files if possible, but if there were any way to get this up and rolling, it would be so very appreciated.

EmilyJD777 avatar Oct 28 '24 21:10 EmilyJD777

Dear Emily,

I am really at a loss here, this should work. Would you be able to send me the example logfile that belongs to the json file you sent as well the matlabbatch or m-file script that you are trying to run?

You can send it via email if you don't want to post it here (see below).

Thank you!

All the best, Lars

-- Lars Kasper, PhD (he/him) @.***

MR Physicist Toronto Neuroimaging Facility (ToNI), Department of Psychology, University of Toronto

325 Huron St, Toronto, ON M5S 3J7 phone: +1 416-978-7613 (office) / +1 416-946-0356 (scanner)


From: EmilyJD777 @.> Sent: Monday, October 28, 2024 5:17:56 PM To: translationalneuromodeling/tapas @.> Cc: Lars Kasper @.>; Assign @.> Subject: Re: [translationalneuromodeling/tapas] PhysIO Not Accepting 7T .resp, .ext and .puls Files? (Issue #283)

I did. I have even managed to get access to the dicoms so that I could make use of the data and the last dicom isn't working either. I'd rather use the trigger files if possible, but if there were any way to get this up and rolling, it would be so very appreciated.

— Reply to this email directly, view it on GitHubhttps://github.com/translationalneuromodeling/tapas/issues/283#issuecomment-2442648375, or unsubscribehttps://github.com/notifications/unsubscribe-auth/ADFUIX7J2ZO7S7MPILOZJ3TZ52SYJAVCNFSM6AAAAABPSTFML6VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDINBSGY2DQMZXGU. You are receiving this because you were assigned.Message ID: @.***>

mrikasper avatar Nov 13 '24 14:11 mrikasper

Could you DM me your email address? I tried emailing through github but the file size of the .m is too large.

EmilyJD777 avatar Nov 13 '24 20:11 EmilyJD777

Hi Emily,

You can use my email at the top of the PhysIO README.

Thank you for sending the data!

All the best, Lars

mrikasper avatar Nov 13 '24 23:11 mrikasper

Hi there,

Just wanted to follow up and see if any progress was made with the data I sent. Thanks again!

EmilyJD777 avatar Nov 26 '24 18:11 EmilyJD777

Dear Emily,

Sorry for the delay. I was able to find out what created the issue:

  1. Typically, we use the MDH (measurement data header) time stamp in the physiological logfiles, as other packages and knowledgeable researchers in this domain, e.g., Chris Rorden, @neurolabusc (dcm2niix, 'MRIcroGL`) recommend when synchronizing DICOM data. See more info in our wiki.
  2. For your data, this timestamp is completely off, but the other one, MPCU (from the Physiological monitoring unit) seems to work.
  3. I have added an option to change this in the PhysIO Code. Not very user-friendly yet, but in the attached beta version of the upcoming PhysIO Release, you can already set it in tapas_physio_read_physlogfiles_siemens as referenceClockString = 'MPCU' (line 164).
  4. NB: This version already works with the .json sidecar files created by dcm2niix conversion and does not need the Dicoms as input.

I hope that helps!

All the best, Lars

mrikasper avatar Dec 02 '24 23:12 mrikasper