[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