diff --git a/src/console/interfaces/acquisition_data.py b/src/console/interfaces/acquisition_data.py index 1f6e6d99..1762bf51 100644 --- a/src/console/interfaces/acquisition_data.py +++ b/src/console/interfaces/acquisition_data.py @@ -210,6 +210,7 @@ def save_ismrmrd( header=header, sequence=self.sequence, dataset_path=dataset_path, + channel_assignment=self.acquisition_parameters.channel_assignment, ) log.warning("Invalid MRD header, could not write MRD file.") diff --git a/src/console/utilities/data/write_acquisition_to_mrd.py b/src/console/utilities/data/write_acquisition_to_mrd.py index 62125aa3..f10ea30f 100644 --- a/src/console/utilities/data/write_acquisition_to_mrd.py +++ b/src/console/utilities/data/write_acquisition_to_mrd.py @@ -6,6 +6,7 @@ import numpy as np from pypulseq.Sequence.sequence import Sequence +from console.interfaces.dimensions import Dimensions from console.interfaces.rx_data import RxData from console.utilities.data import get_logger, mrd_helper @@ -17,6 +18,7 @@ def write_acquisition_to_mrd( header: ismrmrd.xsd.ismrmrdHeader, sequence: Sequence, dataset_path: Path, + channel_assignment: Dimensions, ) -> Path: """Write imaging data to ISMRMRD.""" with ismrmrd.Dataset(dataset_path) as dataset: @@ -25,9 +27,33 @@ def write_acquisition_to_mrd( # Create acquisition acq = ismrmrd.Acquisition() acq.version = int(version("ismrmrd")[0]) - acq.read_dir[0] = 1.0 - acq.phase_dir[1] = 1.0 - acq.slice_dir[2] = 1.0 + + # Set raw data orientation directions in LPS coordinates, assuming patient is lying supine, head first. + # This information is shared for all acquisitions + # The assumption is that the console output channels to physical gradient orientations are as follows + # ch output1 -> gradient from front to back (Patient: I to S) + # ch output2 -> gradient from top to bottom (Patient: P to A) + # ch output3 -> gradient from left to right (Patient: R to L) + # For LPS coordinates the direction P to A needs to be inverted, i.e., read_dir = [0,-1,0] + + # Map logical gradient axes to physical directions in LPS coordinates + direction_map = { + 1: (2, 1.0), # I to S -> [0, 0, 1] + 2: (1, -1.0), # P to A -> [0, -1, 0] (inverted for LPS) + 3: (0, 1.0), # R to L -> [1, 0, 0] + } + + # Set readout direction + idx, val = direction_map[int(channel_assignment.x)] + acq.read_dir[idx] = val + + # Set phase encoding direction + idx, val = direction_map[int(channel_assignment.y)] + acq.phase_dir[idx] = val + + # Set slice direction + idx, val = direction_map[int(channel_assignment.z)] + acq.slice_dir[idx] = val trajectory_position = 0 none_counter = 0