[ismrmrd] 181/281: New matlab API. Acquisitions are working. Lots more to do.
Ghislain Vaillant
ghisvail-guest at moszumanska.debian.org
Wed Jan 14 20:01:12 UTC 2015
This is an automated email from the git hooks/post-receive script.
ghisvail-guest pushed a commit to annotated tag ismrmrd0.5
in repository ismrmrd.
commit 54f99e1f79520e7817e48af57bf93990dcdb7885
Author: Souheil Inati <souheil.inati at nih.gov>
Date: Wed Sep 4 15:32:53 2013 -0400
New matlab API. Acquisitions are working. Lots more to do.
---
matlab/+ismrmrd/Acquisition.m | 282 ++++++++++++++++++++++----
matlab/+ismrmrd/AcquisitionFlags.m | 3 +-
matlab/+ismrmrd/AcquisitionHeader.m | 293 ++++-----------------------
matlab/+ismrmrd/AcquisitionHeaderFromBytes.m | 47 +++++
matlab/+ismrmrd/AcquisitionHeaderToBytes.m | 47 +++++
matlab/+ismrmrd/Flags.m | 65 ++++++
matlab/+ismrmrd/ImageFlags.m | 4 +-
matlab/+ismrmrd/ImageHeader.m | 283 +++++---------------------
matlab/+ismrmrd/ImageHeaderFromBytes.m | 32 +++
matlab/+ismrmrd/ImageHeaderToBytes.m | 32 +++
matlab/+ismrmrd/ImageType.m | 10 +-
matlab/+ismrmrd/IsmrmrdDataset.m | 107 +++++-----
12 files changed, 631 insertions(+), 574 deletions(-)
diff --git a/matlab/+ismrmrd/Acquisition.m b/matlab/+ismrmrd/Acquisition.m
index a39e893..8b20d56 100644
--- a/matlab/+ismrmrd/Acquisition.m
+++ b/matlab/+ismrmrd/Acquisition.m
@@ -1,49 +1,261 @@
-% Acquisition
-classdef Acquisition
+classdef Acquisition < handle
- % Properties
properties
+ head = [];
+ traj = {};
+ data = {};
+ end
- head = ismrmrd.AcquisitionHeader;
- traj = single([]);
- data = single([]);
-
- end % Properties
-
- % Methods
methods
- function obj = set.head(obj,v)
- if isa(v,'ismrmrd.AcquisitionHeader')
- obj.head = v;
+ function obj = Acquisition(arg1, traj, data)
+ switch nargin
+ case 0
+ % No argument constructor
+ % initialize to a single acquisition
+ extend(obj,1);
+
+ case 1
+ % One argument constructor
+ if isfield(arg1, 'version')
+ % First argument is a header
+ M = length(arg1.version);
+ obj.head = arg1;
+ obj.traj{M} = [];
+ obj.data{M} = [];
+ else
+ % First argument is a number
+ M = arg1;
+ extend(obj,M);
+ end
+
+ case 3
+ % Three argument constructor
+ obj.head = arg1;
+ M = length(arg1.version);
+ if isempty(traj)
+ obj.traj{M} = [];
+ else
+ obj.traj = traj;
+ end
+ if isempty(data)
+ obj.data{M} = [];
+ else
+ if isreal(data{1})
+ dataFromFloat(obj,data);
+ else
+ obj.data = data;
+ end
+ end
+
+ otherwise
+ error('ismrmrd.Acquistion constructor, wrong number of arguments.');
+ end
+ end
+
+ function nacq = getNumberOfAcquisitions(obj)
+ if isfield(obj.head,'version')
+ nacq = length(obj.head.version);
else
- % not of the correct type, hope it's a struct
- % and try to copy one element at a time
- u = fieldnames(obj.head);
- for p = 1:length(u)
- obj.head = setfield(obj.head, u{p}, getfield(v, u{p}));
- end
+ nacq = 0;
end
end
-
- function obj = set.traj(obj,v)
- obj.traj = single(v);
+
+ function acq = select(obj, range)
+ % Return a copy of a range of acquisitions
+
+ % create an empty acquisition
+ M = length(range);
+ acq = ismrmrd.Acquisition(M);
+ % Fill the header
+ acq.head.version = obj.head.version(range);
+ acq.head.flags = obj.head.flags(range);
+ acq.head.measurement_uid = obj.head.measurement_uid(range);
+ acq.head.scan_counter = obj.head.scan_counter(range);
+ acq.head.acquisition_time_stamp = obj.head.acquisition_time_stamp(range);
+ acq.head.physiology_time_stamp = obj.head.physiology_time_stamp(:,range);
+ acq.head.number_of_samples = obj.head.number_of_samples(range);
+ acq.head.available_channels = obj.head.available_channels(range);
+ acq.head.active_channels = obj.head.active_channels(range);
+ acq.head.channel_mask = obj.head.channel_mask(:,range);
+ acq.head.discard_pre = obj.head.discard_pre(range);
+ acq.head.discard_post = obj.head.discard_post(range);
+ acq.head.center_sample = obj.head.center_sample(range);
+ acq.head.encoding_space_ref = obj.head.encoding_space_ref(range);
+ acq.head.trajectory_dimensions = obj.head.trajectory_dimensions(range);
+ acq.head.sample_time_us = obj.head.sample_time_us(range);
+ acq.head.position = obj.head.position(:,range);
+ acq.head.read_dir = obj.head.read_dir(:,range);
+ acq.head.phase_dir = obj.head.phase_dir(:,range);
+ acq.head.slice_dir = obj.head.slice_dir(:,range);
+ acq.head.patient_table_position = obj.head.patient_table_position(:,range);
+ acq.head.idx.kspace_encode_step_1 = obj.head.idx.kspace_encode_step_1(range);
+ acq.head.idx.kspace_encode_step_2 = obj.head.idx.kspace_encode_step_2(range);
+ acq.head.idx.average = obj.head.idx.average(range);
+ acq.head.idx.slice = obj.head.idx.slice(range);
+ acq.head.idx.contrast = obj.head.idx.contrast(range);
+ acq.head.idx.phase = obj.head.idx.phase(range);
+ acq.head.idx.repetition = obj.head.idx.repetition(range);
+ acq.head.idx.set = obj.head.idx.set(range);
+ acq.head.idx.segment = obj.head.idx.segment(range);
+ acq.head.idx.user = obj.head.idx.user(:,range);
+ acq.head.user_int = obj.head.user_int(:,range);
+ acq.head.user_float = obj.head.user_float(:,range);
+
+ % Fill the trajectory and the data
+ for p = 1:M
+ acq.traj{p} = obj.traj{range(p)};
+ acq.data{p} = obj.data{range(p)};
+ end
end
-
- function obj = set.data(obj,v)
- obj.data = single(v);
+
+ function append(obj, head, traj, data)
+ Nstart = obj.getNumberOfAcquisitions + 1;
+ Nend = obj.getNumberOfAcquisitions + length(head.version);
+ Nrange = Nstart:Nend;
+ obj.head.version(Nrange) = hdr.version;
+ obj.head.flags(Nrange) = hdr.flags;
+ obj.head.measurement_uid(Nrange) = hdr.measurement_uid;
+ obj.head.scan_counter(Nrange) = hdr.scan_counter;
+ obj.head.acquisition_time_stamp(Nrange) = hdr.acquisition_time_stamp;
+ obj.head.physiology_time_stamp(:,Nrange) = hdr.physiology_time_stamp;
+ obj.head.number_of_samples(Nrange) = hdr.number_of_samples;
+ obj.head.available_channels(Nrange) = hdr.available_channels;
+ obj.head.active_channels(Nrange) = hdr.active_channels;
+ obj.head.channel_mask(:,Nrange) = hdr.channel_mask;
+ obj.head.discard_pre(Nrange) = hdr.discard_pre;
+ obj.head.discard_post(Nrange) = hdr.discard_post;
+ obj.head.center_sample(Nrange) = hdr.center_sample;
+ obj.head.encoding_space_ref(Nrange) = hdr.encoding_space_ref;
+ obj.head.trajectory_dimensions(Nrange) = hdr.trajectory_dimensions;
+ obj.head.sample_time_us(Nrange) = hdr.sample_time_us;
+ obj.head.position(:,Nrange) = hdr.position;
+ obj.head.read_dir(:,Nrange) = hdr.read_dir;
+ obj.head.phase_dir(:,Nrange) = hdr.phase_dir;
+ obj.head.slice_dir(:,Nrange) = hdr.slice_dir;
+ obj.head.patient_table_position(:,Nrange) = hdr.patient_table_position;
+ obj.head.idx.kspace_encode_step_1(Nrange) = hdr.idx.kspace_encode_step_1;
+ obj.head.idx.kspace_encode_step_2(Nrange) = hdr.idx.kspace_encode_step_2;
+ obj.head.idx.average(Nrange) = hdr.idx.average;
+ obj.head.idx.slice(Nrange) = hdr.idx.slice;
+ obj.head.idx.contrast(Nrange) = hdr.idx.contrast;
+ obj.head.idx.phase(Nrange) = hdr.idx.phase;
+ obj.head.idx.repetition(Nrange) = hdr.idx.repetition;
+ obj.head.idx.set(Nrange) = hdr.idx.set;
+ obj.head.idx.segment(Nrange) = hdr.idx.segment;
+ obj.head.idx.user(:,Nrange) = hdr.idx.user;
+ obj.head.user_int(:,Nrange) = hdr.user_int;
+ obj.head.user_float(:,Nrange) = hdr.user_float;
+ if isempty(traj) > 0
+ obj.traj{Nrange} = traj;
+ end
+ if isempty(data) > 0
+ obj.data{Nrange} = data;
+ end
+
end
-
- function b = isFlagSet(obj,flag)
- bitflag = ismrmrd.FlagBit(flag);
- b = bitflag.isSet(obj.head.flag);
+
+ function extend(obj,N)
+ % Extend with blank head and empty traj and data.
+ M = N+obj.getNumberOfAcquisitions();
+ hdr = ismrmrd.AcquisitionHeader();
+ obj.head.version(M) = hdr.version;
+ obj.head.flags(M) = hdr.flags;
+ obj.head.measurement_uid(M) = hdr.measurement_uid;
+ obj.head.scan_counter(M) = hdr.scan_counter;
+ obj.head.acquisition_time_stamp(M) = hdr.acquisition_time_stamp;
+ obj.head.physiology_time_stamp(:,M) = hdr.physiology_time_stamp;
+ obj.head.number_of_samples(M) = hdr.number_of_samples;
+ obj.head.available_channels(M) = hdr.available_channels;
+ obj.head.active_channels(M) = hdr.active_channels;
+ obj.head.channel_mask(:,M) = hdr.channel_mask;
+ obj.head.discard_pre(M) = hdr.discard_pre;
+ obj.head.discard_post(M) = hdr.discard_post;
+ obj.head.center_sample(M) = hdr.center_sample;
+ obj.head.encoding_space_ref(M) = hdr.encoding_space_ref;
+ obj.head.trajectory_dimensions(M) = hdr.trajectory_dimensions;
+ obj.head.sample_time_us(M) = hdr.sample_time_us;
+ obj.head.position(:,M) = hdr.position;
+ obj.head.read_dir(:,M) = hdr.read_dir;
+ obj.head.phase_dir(:,M) = hdr.phase_dir;
+ obj.head.slice_dir(:,M) = hdr.slice_dir;
+ obj.head.patient_table_position(:,M) = hdr.patient_table_position;
+ obj.head.idx.kspace_encode_step_1(M) = hdr.idx.kspace_encode_step_1;
+ obj.head.idx.kspace_encode_step_2(M) = hdr.idx.kspace_encode_step_2;
+ obj.head.idx.average(M) = hdr.idx.average;
+ obj.head.idx.slice(M) = hdr.idx.slice;
+ obj.head.idx.contrast(M) = hdr.idx.contrast;
+ obj.head.idx.phase(M) = hdr.idx.phase;
+ obj.head.idx.repetition(M) = hdr.idx.repetition;
+ obj.head.idx.set(M) = hdr.idx.set;
+ obj.head.idx.segment(M) = hdr.idx.segment;
+ obj.head.idx.user(:,M) = hdr.idx.user;
+ obj.head.user_int(:,M) = hdr.user_int;
+ obj.head.user_float(:,M) = hdr.user_float;
+ obj.traj{M} = [];
+ obj.data{M} = [];
end
-
- function obj = setFlag(obj,flag)
- bitflag = ismrmrd.FlagBit(flag);
- obj.head.flag = bitor(obj.head.flag, bitflag.bitmask);
+
+ function obj = setHead(obj,p,hdr)
+ obj.head.version(p) = hdr.version;
+ obj.head.flags(p) = hdr.flags;
+ obj.head.measurement_uid(p) = hdr.measurement_uid;
+ obj.head.scan_counter(p) = hdr.scan_counter;
+ obj.head.acquisition_time_stamp(p) = hdr.acquisition_time_stamp;
+ obj.head.physiology_time_stamp(:,p) = hdr.physiology_time_stamp;
+ obj.head.number_of_samples(p) = hdr.number_of_samples;
+ obj.head.available_channels(p) = hdr.available_channels;
+ obj.head.active_channels(p) = hdr.active_channels;
+ obj.head.channel_mask(:,p) = hdr.channel_mask;
+ obj.head.discard_pre(p) = hdr.discard_pre;
+ obj.head.discard_post(p) = hdr.discard_post;
+ obj.head.center_sample(p) = hdr.center_sample;
+ obj.head.encoding_space_ref(p) = hdr.encoding_space_ref;
+ obj.head.trajectory_dimensions(p) = hdr.trajectory_dimensions;
+ obj.head.sample_time_us(p) = hdr.sample_time_us;
+ obj.head.position(:,p) = hdr.position;
+ obj.head.read_dir(:,p) = hdr.read_dir;
+ obj.head.phase_dir(:,p) = hdr.phase_dir;
+ obj.head.slice_dir(:,p) = hdr.slice_dir;
+ obj.head.patient_table_position(:,p) = hdr.patient_table_position;
+ obj.head.idx.kspace_encode_step_1(p) = hdr.idx.kspace_encode_step_1;
+ obj.head.idx.kspace_encode_step_2(p) = hdr.idx.kspace_encode_step_2;
+ obj.head.idx.average(p) = hdr.idx.average;
+ obj.head.idx.slice(p) = hdr.idx.slice;
+ obj.head.idx.contrast(p) = hdr.idx.contrast;
+ obj.head.idx.phase(p) = hdr.idx.phase;
+ obj.head.idx.repetition(p) = hdr.idx.repetition;
+ obj.head.idx.set(p) = hdr.idx.set;
+ obj.head.idx.segment(p) = hdr.idx.segment;
+ obj.head.idx.user(:,p) = hdr.idx.user;
+ obj.head.user_int(:,p) = hdr.user_int;
+ obj.head.user_float(:,p) = hdr.user_float;
+ end
+
+ function dataFromFloat(obj,v)
+ if (isempty(obj.head) || (length(v) ~= length(obj.head.version)))
+ error('Mismatch between size of head and data. Please set head first.');
+ end
+ obj.data = cell(1,length(v));
+ for p = 1:length(v)
+ dims = [obj.head.number_of_samples(p), ...
+ obj.head.active_channels(p)];
+ buff = v{p};
+ obj.data{p} = reshape(buff(1:2:end) + 1j*buff(2:2:end), dims);
+ end
end
- end % Methods
+ function v = dataToFloat(obj)
+ v = cell(1,length(obj.data));
+ for p = 1:length(obj.data)
+ dim = size(obj.data{p});
+ buff = zeros([2*prod(dim),1],'single');
+ buff(1:2:end) = real(reshape(obj.data{p},prod(dim),1));
+ buff(2:2:end) = imag(reshape(obj.data{p},prod(dim),1));
+ v{p} = buff;
+ end
+ end
+
+ end
-end
+end
\ No newline at end of file
diff --git a/matlab/+ismrmrd/AcquisitionFlags.m b/matlab/+ismrmrd/AcquisitionFlags.m
index f8ea364..01e2aab 100644
--- a/matlab/+ismrmrd/AcquisitionFlags.m
+++ b/matlab/+ismrmrd/AcquisitionFlags.m
@@ -1,4 +1,4 @@
-classdef AcquisitionFlags
+classdef AcquisitionFlags < ismrmrd.Flags
properties(Constant)
% Looping indicators %
ACQ_FIRST_IN_ENCODE_STEP1 = 1,
@@ -35,4 +35,5 @@ classdef AcquisitionFlags
ACQ_USER7 = 63,
ACQ_USER8 = 64
end
+
end
\ No newline at end of file
diff --git a/matlab/+ismrmrd/AcquisitionHeader.m b/matlab/+ismrmrd/AcquisitionHeader.m
index 7dc468a..024ce7a 100644
--- a/matlab/+ismrmrd/AcquisitionHeader.m
+++ b/matlab/+ismrmrd/AcquisitionHeader.m
@@ -1,250 +1,47 @@
-classdef AcquisitionHeader
-
- properties
- version = uint16(0); % First unsigned int indicates the version %
- flags = uint64(0); % bit field with flags %
- measurement_uid = uint32(0); % Unique ID for the measurement %
- scan_counter = uint32(0); % Current acquisition number in the measurement %
- acquisition_time_stamp = uint32(0); % Acquisition clock %
- % TODO: physiology_time_stamp should be 3.
- %physiology_time_stamp = zeros(3,1,'uint32'); % Physiology time stamps, e.g. ecg, breating, etc. %
- physiology_time_stamp = zeros(8,1,'uint32'); % Physiology time stamps, e.g. ecg, breating, etc. %
- number_of_samples = uint16(0); % Number of samples acquired %
- available_channels = uint16(0); % Available coils %
- active_channels = uint16(0); % Active coils on current acquisiton %
- channel_mask = zeros(16,1,'uint64'); % Mask to indicate which channels are active. Support for 1024 channels %
- discard_pre = uint16(0); % Samples to be discarded at the beginning of acquisition %
- discard_post = uint16(0); % Samples to be discarded at the end of acquisition %
- center_sample = uint16(0); % Sample at the center of k-space %
- encoding_space_ref = uint16(0); % Reference to an encoding space, typically only one per acquisition %
- trajectory_dimensions = uint16(0); % Indicates the dimensionality of the trajectory vector (0 means no trajectory) %
- sample_time_us = single(0); % Time between samples in micro seconds, sampling BW %
- position = zeros(3,1,'single'); % Three-dimensional spatial offsets from isocenter %
- read_dir = zeros(3,1,'single'); % Directional cosines of the readout/frequency encoding %
- phase_dir = zeros(3,1,'single'); % Directional cosines of the phase encoding %
- slice_dir = zeros(3,1,'single'); % Directional cosines of the slice %
- patient_table_position = zeros(3,1, 'single'); % Patient table off-center %
- idx = ismrmrd.EncodingCounters; % Encoding loop counters, see above %
- user_int = zeros(8,1,'int32'); % Free user parameters %
- user_float = zeros(8,1,'single'); % Free user parameters %
- end
-
- methods
-
- % Constructor
- function obj = AcquisitionHeader(bytes)
- if (nargin == 1)
- off = 1;
- obj.version = typecast(bytes(off:off+1), 'uint16'); off=off+2;
- obj.flags = typecast(bytes(off:off+7), 'uint64'); off=off+8;
- obj.measurement_uid = typecast(bytes(off:off+3), 'uint32'); off=off+4;
- obj.scan_counter = typecast(bytes(off:off+3), 'uint32'); off=off+4;
- obj.acquisition_time_stamp = typecast(bytes(off:off+3), 'uint32'); off=off+4;
- % TODO: physiology_time_stamp should be 3.
- %obj.physiology_time_stamp = typecast(bytes(off:off+11), 'uint32'); off=off+12;
- obj.physiology_time_stamp = typecast(bytes(off:off+31), 'uint32'); off=off+32;
- obj.number_of_samples = typecast(bytes(off:off+1), 'uint16'); off=off+2;
- obj.available_channels = typecast(bytes(off:off+1), 'uint16'); off=off+2;
- obj.active_channels = typecast(bytes(off:off+1), 'uint16'); off=off+2;
- obj.channel_mask = typecast(bytes(off:off+127),'uint64'); off=off+128;
- obj.discard_pre = typecast(bytes(off:off+1), 'uint16'); off=off+2;
- obj.discard_post = typecast(bytes(off:off+1), 'uint16'); off=off+2;
- obj.center_sample = typecast(bytes(off:off+1), 'uint16'); off=off+2;
- obj.encoding_space_ref = typecast(bytes(off:off+1), 'uint16'); off=off+2;
- obj.trajectory_dimensions = typecast(bytes(off:off+1), 'uint16'); off=off+2;
- obj.sample_time_us = typecast(bytes(off:off+3), 'single'); off=off+4;
- obj.position = typecast(bytes(off:off+11), 'single'); off=off+12;
- obj.read_dir = typecast(bytes(off:off+11), 'single'); off=off+12;
- obj.phase_dir = typecast(bytes(off:off+11), 'single'); off=off+12;
- obj.slice_dir = typecast(bytes(off:off+11), 'single'); off=off+12;
- obj.patient_table_position = typecast(bytes(off:off+11), 'single'); off=off+12;
- obj.idx = ismrmrd.EncodingCounters(bytes(off:off+33)); off=off+34;
- obj.user_int = typecast(bytes(off:off+31), 'uint32'); off=off+32;
- obj.user_float = typecast(bytes(off:off+31), 'single');
- end
- end
-
- % Convert to Bytes
- function bytes = toBytes(obj)
- % TODO: physiology_time_stamp should be 3.
- %bytes = zeros(340,1,'int8');
- bytes = zeros(360,1,'int8');
- off = 1;
- bytes(off:off+1) = typecast(obj.version ,'int8'); off=off+2;
- bytes(off:off+7) = typecast(obj.flags ,'int8'); off=off+8;
- bytes(off:off+3) = typecast(obj.measurement_uid ,'int8'); off=off+4;
- bytes(off:off+3) = typecast(obj.scan_counter ,'int8'); off=off+4;
- bytes(off:off+3) = typecast(obj.acquisition_time_stamp,'int8'); off=off+4;
- % TODO: physiology_time_stamp should be 3.
- %bytes(off:off+11) = typecast(obj.physiology_time_stamp ,'int8'); off=off+12;
- bytes(off:off+31) = typecast(obj.physiology_time_stamp ,'int8'); off=off+32;
- bytes(off:off+1) = typecast(obj.number_of_samples ,'int8'); off=off+2;
- bytes(off:off+1) = typecast(obj.available_channels ,'int8'); off=off+2;
- bytes(off:off+1) = typecast(obj.active_channels ,'int8'); off=off+2;
- bytes(off:off+127) = typecast(obj.channel_mask ,'int8'); off=off+128;
- bytes(off:off+1) = typecast(obj.discard_pre ,'int8'); off=off+2;
- bytes(off:off+1) = typecast(obj.discard_post ,'int8'); off=off+2;
- bytes(off:off+1) = typecast(obj.center_sample ,'int8'); off=off+2;
- bytes(off:off+1) = typecast(obj.encoding_space_ref ,'int8'); off=off+2;
- bytes(off:off+1) = typecast(obj.trajectory_dimensions ,'int8'); off=off+2;
- bytes(off:off+3) = typecast(obj.sample_time_us ,'int8'); off=off+4;
- bytes(off:off+11) = typecast(obj.position ,'int8'); off=off+12;
- bytes(off:off+11) = typecast(obj.read_dir ,'int8'); off=off+12;
- bytes(off:off+11) = typecast(obj.phase_dir ,'int8'); off=off+12;
- bytes(off:off+11) = typecast(obj.slice_dir ,'int8'); off=off+12;
- bytes(off:off+11) = typecast(obj.patient_table_position,'int8'); off=off+12;
- bytes(off:off+33) = obj.idx.toBytes(); off=off+34;
- bytes(off:off+31) = typecast(obj.user_int ,'int8'); off=off+32;
- bytes(off:off+31) = typecast(obj.user_float ,'int8');
- end
-
- % The flag methods
- function val = isFlagSet(obj,flagstring)
- flagbit = ismrmrd.FlagBit(getfield(ismrmrd.AcquisitionFlags,flagstring));
- val = flagbit.isSet(obj.flags);
- end
-
- function obj = setFlag(obj,flagstring)
- flagbit = ismrmrd.FlagBit(getfield(ismrmrd.AcquisitionFlags,flagstring));
- obj.flags = bitor(obj.flags, flagbit.bitmask);
- end
-
- % Set methods
- function obj = set.version(obj,v)
- obj.version = uint16(v);
- end
-
- function obj = set.flags(obj,v)
- obj.flags = uint64(v);
- end
-
- function obj = set.measurement_uid(obj,v)
- obj.measurement_uid = uint32(v);
- end
-
- function obj = set.scan_counter(obj,v)
- obj.scan_counter = uint32(v);
- end
-
- function obj = set.acquisition_time_stamp(obj,v)
- obj.acquisition_time_stamp = uint32(v);
- end
-
- function obj = set.physiology_time_stamp(obj,v)
- % TODO: physiology_time_stamp should be 3.
- %if (length(v)~=3)
- % error('AcquisitionHeader.physiology_time_stamp must have 3 elements')
- %end
- %obj.physiology_time_stamp = uint32(v);
- obj.physiology_time_stamp(1:3) = uint32(v(1:3));
- obj.physiology_time_stamp(4:8) = uint32(0);
- end
-
- function obj = set.number_of_samples(obj,v)
- obj.number_of_samples = uint16(v);
- end
-
- function obj = set.available_channels(obj,v)
- obj.available_channels = uint16(v);
- end
-
- function obj = set.active_channels(obj,v)
- obj.active_channels = uint16(v);
- end
-
- function obj = set.channel_mask(obj,v)
- if (length(v)~=16)
- error('AcquisitionHeader.channel_mask must have 16 elements')
- end
- obj.channel_mask = uint64(v);
- end
-
- function obj = set.discard_pre(obj,v)
- obj.discard_pre = uint16(v);
- end
-
- function obj = set.discard_post(obj,v)
- obj.discard_post = uint16(v);
- end
-
- function obj = set.center_sample(obj,v)
- obj.center_sample = uint16(v);
- end
-
- function obj = set.encoding_space_ref(obj,v)
- obj.encoding_space_ref = uint16(v);
- end
-
- function obj = set.trajectory_dimensions(obj,v)
- obj.trajectory_dimensions = uint16(v);
- end
-
- function obj = set.sample_time_us(obj,v)
- obj.sample_time_us = single(v);
- end
-
- function obj = set.position(obj,v)
- if (length(v)~=3)
- error('AcquisitionHeader.position must have 3 elements')
- end
- obj.position = single(v);
- end
-
- function obj = set.read_dir(obj,v)
- if (length(v)~=3)
- error('AcquisitionHeader.read_dir must have 3 elements')
- end
- obj.read_dir = single(v);
- end
-
- function obj = set.phase_dir(obj,v)
- if (length(v)~=3)
- error('AcquisitionHeader.phase_dir must have 3 elements')
- end
- obj.phase_dir = single(v);
- end
-
- function obj = set.slice_dir(obj,v)
- if (length(v)~=3)
- error('AcquisitionHeader.slice_dir must have 3 elements')
- end
- obj.slice_dir = single(v);
- end
-
- function obj = set.patient_table_position(obj,v)
- if (length(v)~=3)
- error('AcquisitionHeader.patient_table_position must have 3 elements')
- end
- obj.patient_table_position = single(v);
- end
-
- function obj = set.idx(obj,v)
- if isa(v,'ismrmrd.EncodingCounters')
- obj.idx = v;
- else
- % not of the correct type, hope it's a struct
- % and try to copy one element at a time
- u = fieldnames(obj.idx);
- for p = 1:length(u)
- obj.idx = setfield(obj.idx,u{p},getfield(v,u{p}));
- end
- end
- end
-
- function obj = set.user_int(obj,v)
- if (length(v)~=8)
- error('AcquisitionHeader.user_int must have 8 elements')
- end
- obj.user_int = int32(v);
- end
-
- function obj = set.user_float(obj,v)
- if (length(v)~=8)
- error('AcquisitionHeader.user_float must have 8 elements')
- end
- obj.user_float = single(v);
- end
-
- end
+function hdr = AcquisitionHeader()
+% Return an initialized ISMRMRD AcquisitionHeader
+
+hdr = struct( ...
+ 'version', uint16(0), ... % First unsigned int indicates the version %
+ 'flags', uint64(0), ... % bit field with flags %
+ 'measurement_uid', uint32(0), ... % Unique ID for the measurement %
+ 'scan_counter', uint32(0), ... % Current acquisition number in the measurement %
+ 'acquisition_time_stamp', uint32(0), ... % Acquisition clock %
+ 'physiology_time_stamp', zeros(3,1,'uint32'), ... % Physiology time stamps, e.g. ecg, breating, etc. %
+ ... % TODO: the C header has a bug. 3 is correct
+ 'number_of_samples', uint16(0), ... % Number of samples acquired %
+ 'available_channels', uint16(0), ... % Available coils %
+ 'active_channels', uint16(0), ... % Active coils on current acquisiton %
+ 'channel_mask', zeros(16,1,'uint64'), ... % Mask to indicate which channels are active. Support for 1024 channels %
+ 'discard_pre', uint16(0), ... % Samples to be discarded at the beginning of acquisition %
+ 'discard_post', uint16(0), ... % Samples to be discarded at the end of acquisition %
+ 'center_sample', uint16(0), ... % Sample at the center of k-space %
+ 'encoding_space_ref', uint16(0), ... % Reference to an encoding space, typically only one per acquisition %
+ 'trajectory_dimensions', uint16(0), ... % Indicates the dimensionality of the trajectory vector (0 means no trajectory) %
+ 'sample_time_us', single(0), ... % Time between samples in micro seconds, sampling BW %
+ 'position', zeros(3,1,'single'), ... % Three-dimensional spatial offsets from isocenter %
+ 'read_dir', zeros(3,1,'single'), ... % Directional cosines of the readout/frequency encoding %
+ 'phase_dir', zeros(3,1,'single'), ... % Directional cosines of the phase encoding %
+ 'slice_dir', zeros(3,1,'single'), ... % Directional cosines of the slice %
+ 'patient_table_position', zeros(3,1, 'single'), ... % Patient table off-center %
+ 'idx', struct(), ... % Encoding counters %
+ 'user_int', zeros(8,1,'int32'), ... % Free user parameters %
+ 'user_float', zeros(8,1,'single') ... % Free user parameters %
+ );
+
+
+% Encoding Counters
+hdr.idx = struct( ...
+ 'kspace_encode_step_1', uint16(0), ... % phase encoding line number %
+ 'kspace_encode_step_2', uint16(0), ... % partition encodning number %
+ 'average', uint16(0), ... % signal average number %
+ 'slice', uint16(0), ... % imaging slice number %
+ 'contrast', uint16(0), ... % echo number in multi-echo %
+ 'phase', uint16(0), ... % cardiac phase number %
+ 'repetition', uint16(0), ... % dynamic number for dynamic scanning %
+ 'set', uint16(0), ... % flow encoding set %
+ 'segment', uint16(0), ... % segment number for segmented acquisition %
+ 'user', zeros(8,1,'uint16') ... % Free user parameters %
+ );
end
diff --git a/matlab/+ismrmrd/AcquisitionHeaderFromBytes.m b/matlab/+ismrmrd/AcquisitionHeaderFromBytes.m
new file mode 100644
index 0000000..70352a8
--- /dev/null
+++ b/matlab/+ismrmrd/AcquisitionHeaderFromBytes.m
@@ -0,0 +1,47 @@
+function hdr = AcquisitionHeaderFromBytes(bytes)
+% Construct an ISMRMRD Acquisition Header structure from a byte array.
+
+hdr = struct( ...
+ 'version', typecast(bytes( 1: 2), 'uint16'), ... % First unsigned int indicates the version %
+ 'flags', typecast(bytes( 3: 10), 'uint64'), ... % bit field with flags %
+ 'measurement_uid', typecast(bytes( 11: 10), 'uint32'), ... % Unique ID for the measurement %
+ 'scan_counter', typecast(bytes( 15: 14), 'uint32'), ... % Current acquisition number in the measurement %
+ 'acquisition_time_stamp', typecast(bytes( 19: 18), 'uint32'), ... % Acquisition clock %
+ 'physiology_time_stamp', typecast(bytes( 23: 30), 'uint32'), ... % Physiology time stamps, e.g. ecg, breating, etc. %
+ ... % TODO: the C header has a bug. 3 is correct
+ 'number_of_samples', typecast(bytes( 55: 56), 'uint16'), ... % Number of samples acquired %
+ 'available_channels', typecast(bytes( 57: 58), 'uint16'), ... % Available coils %
+ 'active_channels', typecast(bytes( 59: 60), 'uint16'), ... % Active coils on current acquisiton %
+ 'channel_mask', typecast(bytes( 61:188), 'uint64'), ... % Mask to indicate which channels are active. Support for 1024 channels %
+ 'discard_pre', typecast(bytes(189:190), 'uint16'), ... % Samples to be discarded at the beginning of acquisition %
+ 'discard_post', typecast(bytes(191:192), 'uint16'), ... % Samples to be discarded at the end of acquisition %
+ 'center_sample', typecast(bytes(193:194), 'uint16'), ... % Sample at the center of k-space %
+ 'encoding_space_ref', typecast(bytes(195:196), 'uint16'), ... % Reference to an encoding space, typically only one per acquisition %
+ 'trajectory_dimensions', typecast(bytes(197:198), 'uint16'), ... % Indicates the dimensionality of the trajectory vector (0 means no trajectory) %
+ 'sample_time_us', typecast(bytes(199:202), 'single'), ... % Time between samples in micro seconds, sampling BW %
+ 'position', typecast(bytes(203:214), 'single'), ... % Three-dimensional spatial offsets from isocenter %
+ 'read_dir', typecast(bytes(215:226), 'single'), ... % Directional cosines of the readout/frequency encoding %
+ 'phase_dir', typecast(bytes(227:238), 'single'), ... % Directional cosines of the phase encoding %
+ 'slice_dir', typecast(bytes(239:250), 'single'), ... % Directional cosines of the slice %
+ 'patient_table_position', typecast(bytes(251:262), 'single'), ... % Patient table off-center %
+ 'idx', struct(), ... % Encoding counters %
+ 'user_int', typecast(bytes(297:328), 'int32'), ... % Free user parameters %
+ 'user_float', typecast(bytes(329:360), 'single') ... % Free user parameters %
+ );
+
+
+% Encoding Counters
+hdr.idx = struct( ...
+ 'kspace_encode_step_1', typecast(bytes(263:264), 'uint16'), ... % phase encoding line number %
+ 'kspace_encode_step_2', typecast(bytes(265:266), 'uint16'), ... % partition encodning number %
+ 'average', typecast(bytes(263:268), 'uint16'), ... % signal average number %
+ 'slice', typecast(bytes(265:270), 'uint16'), ... % imaging slice number %
+ 'contrast', typecast(bytes(267:272), 'uint16'), ... % echo number in multi-echo %
+ 'phase', typecast(bytes(269:274), 'uint16'), ... % cardiac phase number %
+ 'repetition', typecast(bytes(271:276), 'uint16'), ... % dynamic number for dynamic scanning %
+ 'set', typecast(bytes(273:278), 'uint16'), ... % flow encoding set %
+ 'segment', typecast(bytes(275:280), 'uint16'), ... % segment number for segmented acquisition %
+ 'user', typecast(bytes(281:296), 'uint16') ... % Free user parameters %
+ );
+
+end
diff --git a/matlab/+ismrmrd/AcquisitionHeaderToBytes.m b/matlab/+ismrmrd/AcquisitionHeaderToBytes.m
new file mode 100644
index 0000000..f0f4292
--- /dev/null
+++ b/matlab/+ismrmrd/AcquisitionHeaderToBytes.m
@@ -0,0 +1,47 @@
+function bytes = AcquisitionHeaderToBytes(hdr)
+% Convert to an ISMRMRD AcquisitionHeader struct to a byte array.
+
+ % TODO: physiology_time_stamp should be 3.
+ %bytes = zeros(340,1,'int8');
+ bytes = zeros(360,1,'int8');
+ off = 1;
+ bytes(off:off+1) = typecast(hdr.version ,'int8'); off=off+2;
+ bytes(off:off+7) = typecast(hdr.flags ,'int8'); off=off+8;
+ bytes(off:off+3) = typecast(hdr.measurement_uid ,'int8'); off=off+4;
+ bytes(off:off+3) = typecast(hdr.scan_counter ,'int8'); off=off+4;
+ bytes(off:off+3) = typecast(hdr.acquisition_time_stamp,'int8'); off=off+4;
+
+ % TODO: physiology_time_stamp should be 3.
+ % but the C struct has a bug, so convert to padding.
+ bytes(off:off+11) = typecast(hdr.physiology_time_stamp ,'int8'); off=off+12;
+ off = off+20; % Discard 5*uint32;
+
+ bytes(off:off+1) = typecast(hdr.number_of_samples ,'int8'); off=off+2;
+ bytes(off:off+1) = typecast(hdr.available_channels ,'int8'); off=off+2;
+ bytes(off:off+1) = typecast(hdr.active_channels ,'int8'); off=off+2;
+ bytes(off:off+127) = typecast(hdr.channel_mask ,'int8'); off=off+128;
+ bytes(off:off+1) = typecast(hdr.discard_pre ,'int8'); off=off+2;
+ bytes(off:off+1) = typecast(hdr.discard_post ,'int8'); off=off+2;
+ bytes(off:off+1) = typecast(hdr.center_sample ,'int8'); off=off+2;
+ bytes(off:off+1) = typecast(hdr.encoding_space_ref ,'int8'); off=off+2;
+ bytes(off:off+1) = typecast(hdr.trajectory_dimensions ,'int8'); off=off+2;
+ bytes(off:off+3) = typecast(hdr.sample_time_us ,'int8'); off=off+4;
+ bytes(off:off+11) = typecast(hdr.position ,'int8'); off=off+12;
+ bytes(off:off+11) = typecast(hdr.read_dir ,'int8'); off=off+12;
+ bytes(off:off+11) = typecast(hdr.phase_dir ,'int8'); off=off+12;
+ bytes(off:off+11) = typecast(hdr.slice_dir ,'int8'); off=off+12;
+ bytes(off:off+11) = typecast(hdr.patient_table_position,'int8'); off=off+12;
+ bytes(off:off+1) = typecast(hdr.idx.kspace_encode_step_1,'int8'); off=off+2;
+ bytes(off:off+1) = typecast(hdr.idx.kspace_encode_step_2,'int8'); off=off+2;
+ bytes(off:off+1) = typecast(hdr.idx.average ,'int8'); off=off+2;
+ bytes(off:off+1) = typecast(hdr.idx.slice ,'int8'); off=off+2;
+ bytes(off:off+1) = typecast(hdr.idx.contrast ,'int8'); off=off+2;
+ bytes(off:off+1) = typecast(hdr.idx.phase ,'int8'); off=off+2;
+ bytes(off:off+1) = typecast(hdr.idx.repetition ,'int8'); off=off+2;
+ bytes(off:off+1) = typecast(hdr.idx.set ,'int8'); off=off+2;
+ bytes(off:off+1) = typecast(hdr.idx.segment ,'int8'); off=off+2;
+ bytes(off:off+15) = typecast(hdr.idx.user ,'int8'); off=off+16;
+ bytes(off:off+31) = typecast(hdr.user_int ,'int8'); off=off+32;
+ bytes(off:off+31) = typecast(hdr.user_float ,'int8');
+
+end
diff --git a/matlab/+ismrmrd/Flags.m b/matlab/+ismrmrd/Flags.m
new file mode 100644
index 0000000..dc056c1
--- /dev/null
+++ b/matlab/+ismrmrd/Flags.m
@@ -0,0 +1,65 @@
+classdef Flags
+
+ methods
+
+ function ret = isSet(obj, flagbits, flag)
+ if isa(flag, 'char')
+ b = obj.(flag);
+ elseif (flag>0)
+ b = uint64(flag);
+ else
+ error('Flag is of the wrong type.');
+ end
+ bitmask = bitshift(uint64(1),(b-1));
+
+ ret = (bitand(flagbits, bitmask)>0);
+
+ end
+
+ function ret = set(obj, flagbits, flag)
+
+ if isa(flag, 'char')
+ b = obj.(flag);
+ elseif (flag>0)
+ b = uint64(flag);
+ else
+ error('Flag is of the wrong type.');
+ end
+ bitmask = bitshift(uint64(1),(b-1));
+
+ if (obj.isSet(flagbits, flag))
+ % Already set
+ ret = flagbits;
+ else
+ ret = flagbits + bitmask;
+ end
+
+ end
+
+ function ret = clear(obj, flagbits, flag)
+ if (nargin < 3)
+ ret = uint64(0);
+ return
+ end
+
+ if isa(flag, 'char')
+ b = obj.(flag);
+ elseif (flag>0)
+ b = uint64(flag);
+ else
+ error('Flag is of the wrong type.');
+ end
+ bitmask = bitshift(uint64(1),(b-1));
+
+ if ~(obj.isSet(flagbits, flag))
+ % Already cleared
+ ret = flagbits;
+ else
+ ret = flagbits - bitmask;
+ end
+
+ end
+
+ end
+
+end % classdef
\ No newline at end of file
diff --git a/matlab/+ismrmrd/ImageFlags.m b/matlab/+ismrmrd/ImageFlags.m
index fda74b5..3ad2b87 100644
--- a/matlab/+ismrmrd/ImageFlags.m
+++ b/matlab/+ismrmrd/ImageFlags.m
@@ -1,5 +1,5 @@
-% IMAGE FLAGS %
-classdef ImageFlags
+classdef ImageFlags < ismrmrd.Flags
+% IMAGE FLAGS
properties(Constant)
IMAGE_IS_NAVIGATION_DATA = 23,
IMAGE_USER1 = 57,
diff --git a/matlab/+ismrmrd/ImageHeader.m b/matlab/+ismrmrd/ImageHeader.m
index 6503b0f..42f960a 100644
--- a/matlab/+ismrmrd/ImageHeader.m
+++ b/matlab/+ismrmrd/ImageHeader.m
@@ -1,238 +1,51 @@
-classdef ImageHeader
-
- properties
- version = uint16(0); % First unsigned int indicates the version %
- flags = uint64(0); % bit field with flags %
- measurement_uid = uint32(0); % Unique ID for the measurement %
- matrix_size = zeros(3,1,'uint16'); % Pixels in the 3 spatial dimensions
- field_of_view = zeros(3,1,'single'); % Size (in mm) of the 3 spatial dimensions %
- channels = uint16(0); % Number of receive channels %
- position = zeros(3,1,'single'); % Three-dimensional spatial offsets from isocenter %
- read_dir = zeros(3,1,'single'); % Directional cosines of the readout/frequency encoding %
- phase_dir = zeros(3,1,'single'); % Directional cosines of the phase encoding %
- slice_dir = zeros(3,1,'single'); % Directional cosines of the slice %
- patient_table_position = zeros(3,1,'single'); % Patient table off-center %
- average = uint16(0); % e.g. signal average number %
- slice = uint16(0); % e.g. imaging slice number %
- contrast = uint16(0); % e.g. echo number in multi-echo %
- phase = uint16(0); % e.g. cardiac phase number %
- repetition = uint16(0); % e.g. dynamic number for dynamic scanning %
- set = uint16(0); % e.g. flow encodning set %
- acquisition_time_stamp = uint32(0); % Acquisition clock %
- physiology_time_stamp = zeros(8,1,'uint32'); % Physiology time stamps, e.g. ecg, breating, etc. %
- image_data_type = uint16(0); % e.g. unsigned short, float, complex float, etc. %
- image_type = uint16(0); % e.g. magnitude, phase, complex, real, imag, etc. %
- image_index = uint16(0); % e.g. image number in series of images %
- image_series_index = uint16(0); % e.g. series number %
- user_int = zeros(8,1,'int32'); % Free user parameters %
- user_float = zeros(8,1,'single'); % Free user parameters %
- end
-
- methods
-
- % Constructor
- function obj = ImageHeader(bytes)
- if (nargin == 1)
- off = 1;
- obj.version = typecast(bytes(off:off+1), 'uint16'); off=off+2;
- obj.flags = typecast(bytes(off:off+7), 'uint64'); off=off+8;
- obj.measurement_uid = typecast(bytes(off:off+3), 'uint32'); off=off+4;
- obj.matrix_size = typecast(bytes(off:off+5), 'uint16'); off=off+6;
- obj.field_of_view = typecast(bytes(off:off+11), 'single'); off=off+12;
- obj.channels = typecast(bytes(off:off+1), 'uint16'); off=off+2;
- obj.position = typecast(bytes(off:off+11), 'single'); off=off+12;
- obj.read_dir = typecast(bytes(off:off+11), 'single'); off=off+12;
- obj.phase_dir = typecast(bytes(off:off+11), 'single'); off=off+12;
- obj.slice_dir = typecast(bytes(off:off+11), 'single'); off=off+12;
- obj.patient_table_position = typecast(bytes(off:off+11), 'single'); off=off+12;
- obj.average = typecast(bytes(off:off+1), 'uint16'); off=off+2;
- obj.slice = typecast(bytes(off:off+1), 'uint16'); off=off+2;
- obj.contrast = typecast(bytes(off:off+1), 'uint16'); off=off+2;
- obj.phase = typecast(bytes(off:off+1), 'uint16'); off=off+2;
- obj.repetition = typecast(bytes(off:off+1), 'uint16'); off=off+2;
- obj.set = typecast(bytes(off:off+1), 'uint16'); off=off+2;
- obj.acquisition_time_stamp = typecast(bytes(off:off+3), 'uint32'); off=off+4;
- obj.physiology_time_stamp = typecast(bytes(off:off+31), 'uint32'); off=off+32;
- obj.image_data_type = typecast(bytes(off:off+1), 'uint16'); off=off+2;
- obj.image_type = typecast(bytes(off:off+1), 'uint16'); off=off+2;
- obj.image_index = typecast(bytes(off:off+1), 'uint16'); off=off+2;
- obj.image_series_index = typecast(bytes(off:off+1), 'uint16'); off=off+2;
- obj.user_int = typecast(bytes(off:off+31), 'uint32'); off=off+32;
- obj.user_float = typecast(bytes(off:off+31), 'single');
- end
- end
-
- function bytes = toBytes(obj)
- bytes = zeros(214,1,'int8');
- off = 1;
- bytes(off:off+1) = typecast(obj.version ,'int8'); off=off+2;
- bytes(off:off+7) = typecast(obj.flags ,'int8'); off=off+8;
- bytes(off:off+3) = typecast(obj.measurement_uid ,'int8'); off=off+4;
- bytes(off:off+5) = typecast(obj.matrix_size ,'int8'); off=off+6;
- bytes(off:off+11) = typecast(obj.field_of_view ,'int8'); off=off+12;
- bytes(off:off+1) = typecast(obj.channels ,'int8'); off=off+2;
- bytes(off:off+11) = typecast(obj.position ,'int8'); off=off+12;
- bytes(off:off+11) = typecast(obj.read_dir ,'int8'); off=off+12;
- bytes(off:off+11) = typecast(obj.phase_dir ,'int8'); off=off+12;
- bytes(off:off+11) = typecast(obj.slice_dir ,'int8'); off=off+12;
- bytes(off:off+11) = typecast(obj.patient_table_position,'int8'); off=off+12;
- bytes(off:off+1) = typecast(obj.average ,'int8'); off=off+2;
- bytes(off:off+1) = typecast(obj.slice ,'int8'); off=off+2;
- bytes(off:off+1) = typecast(obj.contrast ,'int8'); off=off+2;
- bytes(off:off+1) = typecast(obj.phase ,'int8'); off=off+2;
- bytes(off:off+1) = typecast(obj.repetition ,'int8'); off=off+2;
- bytes(off:off+1) = typecast(obj.set ,'int8'); off=off+2;
- bytes(off:off+3) = typecast(obj.acquisition_time_stamp,'int8'); off=off+4;
- bytes(off:off+31) = typecast(obj.physiology_time_stamp ,'int8'); off=off+32;
- bytes(off:off+1) = typecast(obj.image_data_type ,'int8'); off=off+2;
- bytes(off:off+1) = typecast(obj.image_type ,'int8'); off=off+2;
- bytes(off:off+1) = typecast(obj.image_index ,'int8'); off=off+2;
- bytes(off:off+1) = typecast(obj.image_series_index ,'int8'); off=off+2;
- bytes(off:off+31) = typecast(obj.user_int ,'int8'); off=off+32;
- bytes(off:off+31) = typecast(obj.user_float ,'int8');
- end
-
- % The flag methods
- function val = isFlagSet(obj,flagstring)
- flagbit = ismrmrd.FlagBit(getfield(ismrmrd.ImageFlags,flagstring));
- val = flagbit.isSet(obj.flags);
- end
-
- function obj = setFlag(obj,flagstring)
- flagbit = ismrmrd.FlagBit(getfield(ismrmrd.ImageFlags,flagstring));
- obj.flags = bitor(obj.flags, flagbit.bitmask);
- end
-
- % Set methods
- function obj = set.version(obj,v)
- obj.version = uint16(v);
- end
-
- function obj = set.flags(obj,v)
- obj.flags = uint64(v);
- end
-
- function obj = set.measurement_uid(obj,v)
- obj.measurement_uid = uint32(v);
- end
-
- function obj = set.matrix_size(obj,v)
- if (length(v)~=3)
- error('ImageHeader.matrix_size must have 3 elements')
- end
- obj.matrix_size = uint16(v);
- end
-
- function obj = set.field_of_view(obj,v)
- if (length(v)~=3)
- error('ImageHeader.field_of_view must have 3 elements')
- end
- obj.field_of_view = single(v);
- end
-
- function obj = set.channels(obj,v)
- obj.channels = uint16(v);
- end
-
- function obj = set.position(obj,v)
- if (length(v)~=3)
- error('AcquisitionHeader.position must have 3 elements')
- end
- obj.position = single(v);
- end
-
- function obj = set.read_dir(obj,v)
- if (length(v)~=3)
- error('AcquisitionHeader.read_dir must have 3 elements')
- end
- obj.read_dir = single(v);
- end
-
- function obj = set.phase_dir(obj,v)
- if (length(v)~=3)
- error('AcquisitionHeader.phase_dir must have 3 elements')
- end
- obj.phase_dir = single(v);
- end
-
- function obj = set.slice_dir(obj,v)
- if (length(v)~=3)
- error('AcquisitionHeader.slice_dir must have 3 elements')
- end
- obj.slice_dir = single(v);
+function hdr = ImageHeader(imtype)
+% Return an initialized ISMRMRD ImageHeader
+%
+% hdr = ImageHeader(imtype)
+%
+% imtype is one of the types defined in ismrmrd.ImageType
+%
+% example usage:
+% hdr_c = ImageHeader(ismrmrd.ImageType.TYPE_COMPLEX)
+%
+
+ % Check for a valid type
+ fnames = fieldnames(ismrmrd.ImageType);
+ b = false;
+ for p = 1:length(fnames)
+ if uint16(imtype) == ismrmrd.ImageType.(fnames{p})
+ b = true;
+ break;
end
-
- function obj = set.patient_table_position(obj,v)
- if (length(v)~=3)
- error('AcquisitionHeader.patient_table_position must have 3 elements')
- end
- obj.patient_table_position = single(v);
- end
-
- function obj = set.average(obj,v)
- obj.average = uint16(v);
- end
-
- function obj = set.slice(obj,v)
- obj.slice = uint16(v);
- end
-
- function obj = set.contrast(obj,v)
- obj.contrast = uint16(v);
- end
-
- function obj = set.phase(obj,v)
- obj.phase = uint16(v);
- end
-
- function obj = set.repetition(obj,v)
- obj.repetition = uint16(v);
- end
-
- function obj = set.set(obj,v)
- obj.set = uint16(v);
- end
-
- function obj = set.acquisition_time_stamp(obj,v)
- obj.acquisition_time_stamp = uint32(v);
- end
-
- function obj = set.physiology_time_stamp(obj,v)
- if (length(v)~=8)
- error('AcquisitionHeader.physiology_time_stamp must have 8 elements')
- end
- obj.physiology_time_stamp = uint32(v);
- end
-
- function obj = set.image_data_type(obj,v)
- obj.image_data_type = uint16(v);
- end
-
- function obj = set.image_type(obj,v)
- obj.image_type = uint16(v);
- end
-
- function obj = set.image_index(obj,v)
- obj.image_index = uint16(v);
- end
- function obj = set.image_series_index(obj,v)
- obj.image_series_index = uint16(v);
- end
-
- function obj = set.user_int(obj,v)
- if (length(v)~=8)
- error('AcquisitionHeader.user_int must have 8 elements')
- end
- obj.user_int = int32(v);
- end
-
- function obj = set.user_float(obj,v)
- if (length(v)~=8)
- error('AcquisitionHeader.user_float must have 8 elements')
- end
- obj.user_float = single(v);
- end
-
+ end
+ if ~b
+ error('%d is an unknown ISMRMRD image type.',imtype);
end
-end
+ hdr.version = uint16(0); % First unsigned int indicates the version %
+ hdr.flags = uint64(0); % bit field with flags %
+ hdr.measurement_uid = uint32(0); % Unique ID for the measurement %
+ hdr.matrix_size = zeros(3,1,'uint16'); % Pixels in the 3 spatial dimensions
+ hdr.field_of_view = zeros(3,1,'single'); % Size (in mm) of the 3 spatial dimensions %
+ hdr.channels = uint16(0); % Number of receive channels %
+ hdr.position = zeros(3,1,'single'); % Three-dimensional spatial offsets from isocenter %
+ hdr.read_dir = zeros(3,1,'single'); % Directional cosines of the readout/frequency encoding %
+ hdr.phase_dir = zeros(3,1,'single'); % Directional cosines of the phase encoding %
+ hdr.slice_dir = zeros(3,1,'single'); % Directional cosines of the slice %
+ hdr.patient_table_position = zeros(3,1,'single'); % Patient table off-center %
+ hdr.average = uint16(0); % e.g. signal average number %
+ hdr.slice = uint16(0); % e.g. imaging slice number %
+ hdr.contrast = uint16(0); % e.g. echo number in multi-echo %
+ hdr.phase = uint16(0); % e.g. cardiac phase number %
+ hdr.repetition = uint16(0); % e.g. dynamic number for dynamic scanning %
+ hdr.set = uint16(0); % e.g. flow encodning set %
+ hdr.acquisition_time_stamp = uint32(0); % Acquisition clock %
+ hdr.physiology_time_stamp = zeros(8,1,'uint32'); % Physiology time stamps, e.g. ecg, breating, etc. %
+ hdr.image_data_type = uint16(0); % e.g. unsigned short, float, complex float, etc. %
+ hdr.image_type = uint16(imtype); % e.g. magnitude, phase, complex, real, imag, etc. %
+ hdr.image_index = uint16(0); % e.g. image number in series of images %
+ hdr.image_series_index = uint16(0); % e.g. series number %
+ hdr.user_int = zeros(8,1,'int32'); % Free user parameters %
+ hdr.user_float = zeros(8,1,'single'); % Free user parameters %
+
+end
\ No newline at end of file
diff --git a/matlab/+ismrmrd/ImageHeaderFromBytes.m b/matlab/+ismrmrd/ImageHeaderFromBytes.m
new file mode 100644
index 0000000..c5bde23
--- /dev/null
+++ b/matlab/+ismrmrd/ImageHeaderFromBytes.m
@@ -0,0 +1,32 @@
+function hdr = ImageHeaderFromBytes(bytes)
+% Construct an ISMRMRD Image Header structure from a byte array.
+
+ off = 1;
+ hdr = struct();
+ hdr.version = typecast(bytes(off:off+1), 'uint16'); off=off+2;
+ hdr.flags = typecast(bytes(off:off+7), 'uint64'); off=off+8;
+ hdr.measurement_uid = typecast(bytes(off:off+3), 'uint32'); off=off+4;
+ hdr.matrix_size = typecast(bytes(off:off+5), 'uint16'); off=off+6;
+ hdr.field_of_view = typecast(bytes(off:off+11), 'single'); off=off+12;
+ hdr.channels = typecast(bytes(off:off+1), 'uint16'); off=off+2;
+ hdr.position = typecast(bytes(off:off+11), 'single'); off=off+12;
+ hdr.read_dir = typecast(bytes(off:off+11), 'single'); off=off+12;
+ hdr.phase_dir = typecast(bytes(off:off+11), 'single'); off=off+12;
+ hdr.slice_dir = typecast(bytes(off:off+11), 'single'); off=off+12;
+ hdr.patient_table_position = typecast(bytes(off:off+11), 'single'); off=off+12;
+ hdr.average = typecast(bytes(off:off+1), 'uint16'); off=off+2;
+ hdr.slice = typecast(bytes(off:off+1), 'uint16'); off=off+2;
+ hdr.contrast = typecast(bytes(off:off+1), 'uint16'); off=off+2;
+ hdr.phase = typecast(bytes(off:off+1), 'uint16'); off=off+2;
+ hdr.repetition = typecast(bytes(off:off+1), 'uint16'); off=off+2;
+ hdr.set = typecast(bytes(off:off+1), 'uint16'); off=off+2;
+ hdr.acquisition_time_stamp = typecast(bytes(off:off+3), 'uint32'); off=off+4;
+ hdr.physiology_time_stamp = typecast(bytes(off:off+31), 'uint32'); off=off+32;
+ hdr.image_data_type = typecast(bytes(off:off+1), 'uint16'); off=off+2;
+ hdr.image_type = typecast(bytes(off:off+1), 'uint16'); off=off+2;
+ hdr.image_index = typecast(bytes(off:off+1), 'uint16'); off=off+2;
+ hdr.image_series_index = typecast(bytes(off:off+1), 'uint16'); off=off+2;
+ hdr.user_int = typecast(bytes(off:off+31), 'uint32'); off=off+32;
+ hdr.user_float = typecast(bytes(off:off+31), 'single');
+
+end
\ No newline at end of file
diff --git a/matlab/+ismrmrd/ImageHeaderToBytes.m b/matlab/+ismrmrd/ImageHeaderToBytes.m
new file mode 100644
index 0000000..54f2452
--- /dev/null
+++ b/matlab/+ismrmrd/ImageHeaderToBytes.m
@@ -0,0 +1,32 @@
+function bytes = ImageHeaderToBytes(hdr)
+% Convert to an ISMRMRD ImageHeader struct to a byte array.
+
+ bytes = zeros(214,1,'int8');
+ off = 1;
+ bytes(off:off+1) = typecast(hdr.version ,'int8'); off=off+2;
+ bytes(off:off+7) = typecast(hdr.flags ,'int8'); off=off+8;
+ bytes(off:off+3) = typecast(hdr.measurement_uid ,'int8'); off=off+4;
+ bytes(off:off+5) = typecast(hdr.matrix_size ,'int8'); off=off+6;
+ bytes(off:off+11) = typecast(hdr.field_of_view ,'int8'); off=off+12;
+ bytes(off:off+1) = typecast(hdr.channels ,'int8'); off=off+2;
+ bytes(off:off+11) = typecast(hdr.position ,'int8'); off=off+12;
+ bytes(off:off+11) = typecast(hdr.read_dir ,'int8'); off=off+12;
+ bytes(off:off+11) = typecast(hdr.phase_dir ,'int8'); off=off+12;
+ bytes(off:off+11) = typecast(hdr.slice_dir ,'int8'); off=off+12;
+ bytes(off:off+11) = typecast(hdr.patient_table_position,'int8'); off=off+12;
+ bytes(off:off+1) = typecast(hdr.average ,'int8'); off=off+2;
+ bytes(off:off+1) = typecast(hdr.slice ,'int8'); off=off+2;
+ bytes(off:off+1) = typecast(hdr.contrast ,'int8'); off=off+2;
+ bytes(off:off+1) = typecast(hdr.phase ,'int8'); off=off+2;
+ bytes(off:off+1) = typecast(hdr.repetition ,'int8'); off=off+2;
+ bytes(off:off+1) = typecast(hdr.set ,'int8'); off=off+2;
+ bytes(off:off+3) = typecast(hdr.acquisition_time_stamp,'int8'); off=off+4;
+ bytes(off:off+31) = typecast(hdr.physiology_time_stamp ,'int8'); off=off+32;
+ bytes(off:off+1) = typecast(hdr.image_data_type ,'int8'); off=off+2;
+ bytes(off:off+1) = typecast(hdr.image_type ,'int8'); off=off+2;
+ bytes(off:off+1) = typecast(hdr.image_index ,'int8'); off=off+2;
+ bytes(off:off+1) = typecast(hdr.image_series_index ,'int8'); off=off+2;
+ bytes(off:off+31) = typecast(hdr.user_int ,'int8'); off=off+32;
+ bytes(off:off+31) = typecast(hdr.user_float ,'int8');
+
+end
diff --git a/matlab/+ismrmrd/ImageType.m b/matlab/+ismrmrd/ImageType.m
index 7e1cd59..8f16274 100644
--- a/matlab/+ismrmrd/ImageType.m
+++ b/matlab/+ismrmrd/ImageType.m
@@ -1,9 +1,9 @@
classdef ImageType
properties(Constant)
- TYPE_MAGNITUDE = 1,
- TYPE_PHASE = 2,
- TYPE_REAL = 3,
- TYPE_IMAG = 4,
- TYPE_COMPLEX = 5
+ TYPE_MAGNITUDE = uint16(1);
+ TYPE_PHASE = uint16(2);
+ TYPE_REAL = uint16(3);
+ TYPE_IMAG = uint16(4);
+ TYPE_COMPLEX = uint16(5);
end
end
diff --git a/matlab/+ismrmrd/IsmrmrdDataset.m b/matlab/+ismrmrd/IsmrmrdDataset.m
index 0326fd2..e3332a3 100644
--- a/matlab/+ismrmrd/IsmrmrdDataset.m
+++ b/matlab/+ismrmrd/IsmrmrdDataset.m
@@ -159,60 +159,77 @@ classdef IsmrmrdDataset
end
- function acq = readAcquisition(obj, nacq)
+ function block = readAcquisition(obj, start, stop)
+ if nargin == 1
+ % Read all the acquisitions
+ start = 1;
+ stop = -1;
+ elseif nargin == 2
+ % Read a single acquisition
+ stop = start;
+ end
% Check if the Data exists
- lapl_id=H5P.create('H5P_LINK_ACCESS');
- if (H5L.exists(obj.fid, obj.datapath, lapl_id) == 0)
+ lapl=H5P.create('H5P_LINK_ACCESS');
+ if (H5L.exists(obj.fid, obj.datapath, lapl) == 0)
error([obj.datapath ' does not exist in the HDF5 dataset.']);
end
% Open the data
- dset_id = H5D.open(obj.fid, obj.datapath);
+ dset = H5D.open(obj.fid, obj.datapath);
% Open the data space
- file_space_id = H5D.get_space(dset_id);
-
- % Initialize the return object
- acq = ismrmrd.Acquisition;
+ space = H5D.get_space(dset);
+
+ % Get the size
+ H5S.get_simple_extent_dims(space);
+ [~,dims,~] = H5S.get_simple_extent_dims(space);
+ nacq = dims(1);
% Create a mem_space for reading
- dims = [1 1];
- mem_space_id = H5S.create_simple(2,dims,[]);
-
- % Read the desired acquisition
- offset = [nacq-1 0];
- H5S.select_hyperslab(file_space_id,'H5S_SELECT_SET',offset,[1 1],[1 1],[1 1]);
- d = H5D.read(dset_id, obj.htypes.T_Acquisition, ...
- mem_space_id, file_space_id, 'H5P_DEFAULT');
-
- % Set the structure bits
- acq.head = d.head(1);
- acq.traj = d.traj{1};
- t = d.data{1};
- acq.data = reshape( t(1:2:end) + 1j*t(2:2:end) , ...
- [acq.head.number_of_samples, ...
- acq.head.active_channels] );
+ if (stop >= start)
+ offset = [start-1 0];
+ dims = [stop-start+1 1];
+ mem_space = H5S.create_simple(2,dims,[]);
+ else
+ offset = [0 0];
+ dims = [nacq 1];
+ mem_space = H5S.create_simple(2,dims,[]);
+ end
+
+ % Read the desired acquisitions
+ H5S.select_hyperslab(space,'H5S_SELECT_SET',offset,[1 1],[1 1],dims);
+ d = H5D.read(dset, obj.htypes.T_Acquisition, ...
+ mem_space, space, 'H5P_DEFAULT');
+
+ % Pack'em
+ block = ismrmrd.Acquisition(d.head, d.traj, d.data);
+ %block.head = d.head;
+ %block.traj = d.traj;
+ %block.dataFromFloat(d.data);
% Clean up
- H5S.close(mem_space_id);
- H5S.close(file_space_id);
- H5D.close(dset_id);
+ H5S.close(mem_space);
+ H5S.close(space);
+ H5D.close(dset);
end
function appendAcquisition(obj, acq)
% Append an acquisition
% TODO: Check the type of the input
-
+
+ % The number of acquisitions that we are going to append
+ N = acq.getNumberOfAcquisitions();
+
% Check if the Data exists
% if it does not exist, create it
- % if it does exist increase it's size by one
+ % if it does exist increase it's size
lapl_id=H5P.create('H5P_LINK_ACCESS');
if (H5L.exists(obj.fid, obj.datapath, lapl_id) == 0)
% Data does not exist
% create with rank 2, unlimited, and set the chunk size
- dims = [1 1];
+ dims = [N 1];
maxdims = [H5ML.get_constant_value('H5S_UNLIMITED') 1];
file_space_id = H5S.create_simple(2, dims, maxdims);
@@ -232,39 +249,33 @@ classdef IsmrmrdDataset
% Open the data space
file_space_id = H5D.get_space(data_id);
- % Get the size, increment by one
+ % Get the size, increment by N
H5S.get_simple_extent_dims(file_space_id);
[~,dims,~] = H5S.get_simple_extent_dims(file_space_id);
- dims = [dims(1)+1, 1];
+ dims = [dims(1)+N, 1];
H5D.set_extent (data_id, dims);
H5S.close(file_space_id);
end
H5P.close(lapl_id);
- % Get the file space (room for one more acq)
+ % Get the file space
file_space_id = H5D.get_space(data_id);
[~,dims,~] = H5S.get_simple_extent_dims(file_space_id);
- % Select the last block
- offset = [dims(1)-1 0];
- H5S.select_hyperslab(file_space_id,'H5S_SELECT_SET',offset,[],[],[]);
+ % Select the last N block
+ offset = [dims(1)-N 0];
+ H5S.select_hyperslab(file_space_id,'H5S_SELECT_SET',offset,[1 1],[1 1],[N 1]);
% Mem space
- mem_space_id = H5S.create_simple(2,[1 1],[]);
+ mem_space_id = H5S.create_simple(2,[N 1],[]);
% Pack the acquisition into the correct struct for writing
- swarn = warning('query','MATLAB:structOnObject');
- warning('off', 'MATLAB:structOnObject')
- d.head(1) = struct(acq.head);
- d.head(1).idx = struct(acq.head.idx);
- warning(swarn.state, 'MATLAB:structOnObject')
- d.traj{1} = acq.traj;
- t = zeros(2*length(acq.data(:)),1,'single');
- t(1:2:end) = real(acq.data(:));
- t(2:2:end) = imag(acq.data(:));
- d.data{1} = t;
-
+ d = struct();
+ d.head = acq.head;
+ d.traj = acq.traj;
+ d.data = acq.dataToFloat();
+
% Write
H5D.write(data_id, obj.htypes.T_Acquisition, ...
mem_space_id, file_space_id, 'H5P_DEFAULT', d);
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-science/packages/ismrmrd.git
More information about the debian-science-commits
mailing list