Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
EmilyJD777 opened this issue Oct 8, 2024 · 19 comments
Open

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

EmilyJD777 opened this issue Oct 8, 2024 · 19 comments
Assignees
Labels
physio Issues related to PhysIO Toolbox

Comments

@EmilyJD777
Copy link

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!

@mrikasper mrikasper self-assigned this Oct 8, 2024
@mrikasper mrikasper added the physio Issues related to PhysIO Toolbox label Oct 8, 2024
@mrikasper mrikasper added this to PhysIO Oct 8, 2024
@github-project-automation github-project-automation bot moved this to To do in PhysIO Oct 8, 2024
@mrikasper
Copy link
Member

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

@EmilyJD777
Copy link
Author

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.

@mrikasper
Copy link
Member

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

@EmilyJD777
Copy link
Author

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.

@mrikasper
Copy link
Member

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

@EmilyJD777
Copy link
Author

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!

@mrikasper
Copy link
Member

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

@EmilyJD777
Copy link
Author

EmilyJD777 commented Oct 9, 2024

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
Copy link
Author

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

@mrikasper
Copy link
Member

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

@EmilyJD777
Copy link
Author

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
Copy link
Author

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

@mrikasper
Copy link
Member

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

@EmilyJD777
Copy link
Author

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.

@mrikasper
Copy link
Member

mrikasper commented Nov 13, 2024 via email

@EmilyJD777
Copy link
Author

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

@mrikasper
Copy link
Member

Hi Emily,

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

Thank you for sending the data!

All the best,
Lars

@EmilyJD777
Copy link
Author

Hi there,

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

@mrikasper
Copy link
Member

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
physio Issues related to PhysIO Toolbox
Projects
Status: To do
Development

No branches or pull requests

2 participants