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

ENH: Enable models for sparsely sampled fMRI series #376

Open
wants to merge 15 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
ENH: Calculate TA and store in run_info
  • Loading branch information
effigies committed Feb 5, 2019
commit 90b861d7a4683e65a50f22e11c8071daec3322d3
13 changes: 11 additions & 2 deletions bids/analysis/analysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -388,13 +388,22 @@ def get_design_matrix(self, names=None, format='long', mode='both',

if sampling_rate == 'TR':
trs = {var.run_info[0].tr for var in self.collection.variables.values()}
tas = {var.run_info[0].ta for var in self.collection.variables.values()}
if not trs:
raise ValueError("Repetition time unavailable; specify sampling_rate "
"explicitly")
elif len(trs) > 1:
raise ValueError("Non-unique Repetition times found ({!r}); specify "
"sampling_rate explicitly")
sampling_rate = 1. / trs.pop()
"sampling_rate explicitly".format(trs))
TR = trs.pop()
if not tas:
warnings.warn("Acquisition time unavailable; assuming TA = TR")
tas = {TR}
elif len(tas) > 1:
raise ValueError("Non-unique acquisition times found ({!r})".format(tas))

sampling_rate = 1. / TR
acquisition_time = tas.pop()
elif sampling_rate == 'highest':
sampling_rate = None
dense_df = coll.to_df(names, format='wide',
Expand Down
8 changes: 5 additions & 3 deletions bids/variables/entities.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,23 +36,25 @@ class RunNode(Node):
image_file (str): The full path to the corresponding nifti image.
duration (float): Duration of the run, in seconds.
repetition_time (float): TR for the run.
acquisition_time (float): TA for the run.
task (str): The task name for this run.
'''

def __init__(self, entities, image_file, duration, repetition_time):
def __init__(self, entities, image_file, duration, repetition_time, acquisition_time):
self.image_file = image_file
self.duration = duration
self.repetition_time = repetition_time
self.acquisition_time = acquisition_time
super(RunNode, self).__init__('run', entities)

def get_info(self):

return RunInfo(self.entities, self.duration, self.repetition_time,
self.image_file)
self.acquisition_time, self.image_file)


# Stores key information for each Run.
RunInfo = namedtuple('RunInfo', ['entities', 'duration', 'tr', 'image'])
RunInfo = namedtuple('RunInfo', ['entities', 'duration', 'tr', 'ta', 'image'])


class NodeIndex(Node):
Expand Down
26 changes: 23 additions & 3 deletions bids/variables/io.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,24 @@ def load_variables(layout, types=None, levels=None, skip_empty=True,
return dataset


def _get_timing_info(img_md):
if 'RepetitionTime' in img_md:
tr = img_md['RepetitionTime']
if 'DelayTime' in img_md:
ta = tr - img_md['DelayTime']
elif 'SliceTiming' in img_md:
slicetimes = sorted(img_md['SliceTiming'])
# a, b ... z
# z = final slice onset, b - a = slice duration
ta = slicetimes[-1] + slicetimes[1] - slicetimes[0]
effigies marked this conversation as resolved.
Show resolved Hide resolved
else:
ta = tr
elif 'VolumeTiming' in img_md:
return NotImplemented

return tr, ta


def _load_time_variables(layout, dataset=None, columns=None, scan_length=None,
drop_na=True, events=True, physio=True, stim=True,
regressors=True, skip_empty=True, **selectors):
Expand Down Expand Up @@ -141,8 +159,9 @@ def _load_time_variables(layout, dataset=None, columns=None, scan_length=None,
if 'run' in entities:
entities['run'] = int(entities['run'])

tr = layout.get_metadata(img_f, suffix='bold', domains=domains,
full_search=True)['RepetitionTime']
img_md = layout.get_metadata(img_f, suffix='bold', domains=domains,
full_search=True)
tr, ta = _get_timing_info(img_md)

# Get duration of run: first try to get it directly from the image
# header; if that fails, try to get NumberOfVolumes from the
Expand All @@ -162,7 +181,8 @@ def _load_time_variables(layout, dataset=None, columns=None, scan_length=None,
raise ValueError(msg)

run = dataset.get_or_create_node('run', entities, image_file=img_f,
duration=duration, repetition_time=tr)
duration=duration, repetition_time=tr,
acquisition_time=ta)
run_info = run.get_info()

# Process event files
Expand Down