Files
2026-08-07 15:56:42 +09:00

279 lines
7.1 KiB
Matlab

% mdaload.m - MATLAB/Octave routine for loading MDA files
% Copyright (c) 2016 UChicago Argonne, LLC,
% as Operator of Argonne National Laboratory.
% This file is distributed subject to a Software License Agreement
% found in file LICENSE that is included with this distribution.
% Written by Dohn A. Arms, Argonne National Laboratory
% Send comments to dohnarms@anl.gov
% 1.0 -- July 2016
% Initial version
function mda = mdaload(filename)
[fileID,errmsg] = fopen( filename,'r','b');
if fileID < 0
error( errmsg)
end
mda.version = float32grab(fileID);
ver = round(mda.version*100.0);
if ver ~= 140 && ver ~= 130 && ver ~= 120
error('Incorrect MDA version')
end
mda.scan_number = int32grab(fileID);
mda.data_rank = int16grab(fileID);
if mda.data_rank < 1
error('Internal inconsistency')
end
[mda.dimensions,cnt] = fread(fileID,mda.data_rank,'int32=>int32');
if (cnt ~= mda.data_rank) || any(mda.dimensions < 1)
error('Internal inconsistency')
end
mda.regular = int16grab(fileID);
extra_offset = int32grab(fileID);
mda.scan = scangrab( fileID,mda.data_rank);
if extra_offset > 0
fseek( fileID, extra_offset, 'bof');
mda.extra = extragrab(fileID);
else
mda.extra = [];
end
fclose(fileID);
end
function scan = scangrab(fileID,data_rank)
scan.scan_rank = int16grab(fileID);
if scan.scan_rank ~= data_rank
error('Internal inconsistency')
end
scan.requested_points = int32grab(fileID);
if scan.requested_points < 1
error('Internal inconsistency')
end
scan.last_point = int32grab(fileID);
if (scan.last_point < 0) || (scan.last_point > scan.requested_points)
error('Internal inconsistency')
end
if scan.scan_rank > 1
[offsets,cnt] = fread(fileID,scan.requested_points,'int32=>int32');
if (cnt ~= scan.requested_points) || any(offsets(1:scan.last_point) == 0) || any(offsets < 0)
error('Internal inconsistency')
end
end
scan.name = strgrab(fileID);
scan.time = strgrab(fileID);
scan.number_positioners = int16grab(fileID);
if scan.number_positioners < 0
error('Internal inconsistency')
end
scan.number_detectors = int16grab(fileID);
if scan.number_detectors < 0
error('Internal inconsistency')
end
scan.number_triggers = int16grab(fileID);
if scan.number_triggers < 0
error('Internal inconsistency')
end
if scan.number_positioners > 0
for i = 1:scan.number_positioners
scan.positioners(i) = posgrab(fileID);
end
else
scan.positioners = [];
end
if scan.number_detectors > 0
for i = 1:scan.number_detectors
scan.detectors(i) = detgrab(fileID);
end
else
scan.detectors = [];
end
if scan.number_triggers > 0
for i = 1:scan.number_triggers
scan.triggers(i) = triggrab(fileID);
end
else
scan.triggers = [];
end
[scan.positioners_data,cnt] = fread(fileID, [scan.requested_points,scan.number_positioners],'float64=>float64');
if cnt ~= scan.requested_points*int32(scan.number_positioners)
error('Internal inconsistency')
end
[scan.detectors_data,cnt] = fread(fileID, [scan.requested_points,scan.number_detectors],'float32=>float32');
if cnt ~= scan.requested_points*int32(scan.number_detectors)
error('Internal inconsistency')
end
if scan.last_point < scan.requested_points
scan.positioners_data(scan.last_point+1:end,:) = [];
scan.detectors_data(scan.last_point+1:end,:) = [];
end
if scan.scan_rank > 1
for i = 1:scan.last_point
if fseek( fileID, offsets(i), 'bof') == -1
error('Premature end of file');
end
scan.sub_scans(i) = scangrab(fileID,scan.scan_rank-1);
end
else
scan.subscans = [];
end
end
function pos = posgrab(fileID)
pos.number = int16grab(fileID);
pos.name = strgrab(fileID);
pos.description = strgrab(fileID);
pos.step_mode = strgrab(fileID);
pos.unit = strgrab(fileID);
pos.readback_name = strgrab(fileID);
pos.readback_description = strgrab(fileID);
pos.readback_unit = strgrab(fileID);
end
function det = detgrab(fileID)
det.number = int16grab(fileID);
det.name = strgrab(fileID);
det.description = strgrab(fileID);
det.unit = strgrab(fileID);
end
function trig = triggrab(fileID)
trig.number = int16grab(fileID);
trig.name = strgrab(fileID);
trig.command = float32grab(fileID);
end
function extra = extragrab(fileID)
extra.number_pvs = int16grab(fileID);
for i = 1:extra.number_pvs
extra.pvs(i) = pvgrab(fileID);
end
end
function pv = pvgrab(fileID)
pv.name = strgrab(fileID);
pv.descr = strgrab(fileID);
type = int16grab(fileID);
switch type
case 0
pv.type = 'char';
case 29
pv.type = 'int16';
case 30
pv.type = 'float32';
case 32
pv.type = 'int8';
case 33
pv.type = 'int32';
case 34
pv.type = 'float64';
otherwise
error('Internal inconsistency')
end
if type > 0
pv.count = int16grab(fileID);
if pv.count < 1
error('Internal inconsistency')
end
pv.unit = strgrab(fileID);
else
pv.count = 1;
pv.unit = '';
end
switch type
case 0
pv.values = strgrab(fileID);
pv.count = length(pv.values);
case 29
[pv.values,cnt] = fread(fileID,pv.count,'int16=>int16');
if cnt ~= pv.count
error('Internal inconsistency')
end
if mod(pv.count,2) == 1
[~,cnt] = fread(fileID,1,'int16=>int16');
if cnt ~= 1
error('Internal inconsistency')
end
end
case 30
[pv.values,cnt] = fread(fileID,pv.count,'float32=>float32');
if cnt ~= pv.count
error('Internal inconsistency')
end
case 32
[pv.values,cnt] = fread(fileID,pv.count,'int8=>int8');
if cnt ~= pv.count
error('Internal inconsistency')
end
len = mod(pv.count,4);
if len > 0
[~,cnt] = fread(fileID,4-len,'int8=>int8');
if cnt ~= 4-len
error('Internal inconsistency')
end
end
case 33
[pv.values,cnt] = fread(fileID,pv.count,'int32=>int32');
if cnt ~= pv.count
error('Internal inconsistency')
end
case 34
[pv.values,cnt] = fread(fileID,pv.count,'float64=>float64');
if cnt ~= pv.count
error('Internal inconsistency')
end
end
end
function val = int32grab(fileID)
[val,cnt] = fread(fileID,1,'int32=>int32');
if cnt ~= 1
error('Premature end of file');
end
end
function val = int16grab(fileID)
[val,cnt] = fread(fileID,1,'int32=>int16');
if cnt ~= 1
error('Premature end of file');
end
end
function val = float32grab(fileID)
[val,cnt] = fread(fileID,1,'float32=>float32');
if cnt ~= 1
error('Premature end of file');
end
end
function str = strgrab(fileID)
[len1,cnt]=fread(fileID,1,'int32=>int16');
if cnt ~= 1
error('Premature end of file');
end
if len1 > 0
[len2,cnt]=fread(fileID,1,'int32=>int16');
if cnt ~= 1
error('Premature end of file');
end
[str,cnt]=fread(fileID,[1,len2],'char=>char');
if cnt ~= len2
error('Premature end of file');
end
m = mod(len2,4);
if m > 0
[~,cnt]=fread(fileID,4-m,'char=>char');
if cnt ~= 4-m
error('Premature end of file');
end
end
else
str='';
end
end