📄 bvqxfile.m
字号:
%function [varargout] = BVQXfile(varargin)
% BVQXfile (Object Class)
%
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Version: v0.7c
% Build: 7100214
% Date: Oct-02 2007, 2:14 PM CEST
% Author: Jochen Weber, Brain Innovation, B.V., Maastricht, NL
% URL / Info: http://wiki.brainvoyager.com/BVQXtools
%
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% This Class creates, reads, and writes BrainVoyagerQX's
% native file formats as MATLAB ojbects.
%
% vmr = BVQXfile('new:vmr'); % create a new VMR
% vmr = BVQXfile('file.vmr'); % load file.vmr
% vmr = BVQXfile('*.vmr' [, titleornumber]); % show file selector
%
% The storage is made in one global variable, bvqxcont, to keep only
% one copy of elements (full call-by-reference implementation), as of
% BVQXtools version v0.7b.
%
% To clear the storage, it is thus required to call one of the clearing
% methods:
%
% object.ClearObject;
% clearbvqxobjects({object, ...});
%
% Properties in the BVQX objects are then accessible like struct fields:
%
% dimx = vmr.DimX;
%
% Methods are equally accessible and, if available, overload properties.
% Some methods work for all (several) object / file types:
%
% bbox = vmr.BoundingBox;
% copied = vmr.CopyObject;
% filename = vmr.FilenameOnDisk;
% filetype = vmr.Filetype;
% firstvolume = vtc.GetVolume(1);
% vmr.ReloadFromDisk;
% vmr.Save;
% vmr.SaveAs(newfilename);
% vmr.SaveAs('*.vmr' [, title]);
%
% Alternatively, you can use the functional form:
%
% Call(vmr, 'MethodName' [, arguments]);
%
% To obtain help on object methods issue the call
%
% object.Help - or -
% object.Help('Method')
%
% Additionally, certain commands / functions can be executed via
%
% BVQXfile(0, command [, arguments]);
%
% where the following commands are supported
%
% BVQXfile(0, 'clearallobjects')
% clear the object storage (like clear in Matlab for objects WS)
%
% BVQXfile(0, 'clearobj', h)
% clear the objects with internal handle(s) h
%
% BVQXfile(0, 'config', globalsettingname [, globalsettingvalue]]);
% BVQXfile(0, 'config' [, type [, settingname [, settingvalue]]]);
% e.g.
% BVQXfile(0, 'config', 'vmr', 'autov16', false|true);
% make global class configuration (on types)
%
% BVQXfile(0, 'copyobject', h)
% make a copy of object with internal handle h
%
% BVQXfile(0, 'extensions')
% return supported extensions (struct with cell array fields)
%
% BVQXfile(0, 'formats')
% return file formats (struct with fields bff, tff, extensions, magic)
%
% BVQXfile(0, 'isobject', var)
% implementation of isBVQXfile function
%
% BVQXfile(0, 'magic')
% return just the file magic array (1xN struct)
%
% BVQXfile(0, 'makeobject', obj_struct)
% return the classified object (struct -> class constructor)
%
% BVQXfile(0, 'methods')
% return a struct with 1x1 struct field for each file type and
% sub fields for each method supported by this type
%
% BVQXfile(0, 'newcont', type)
% return the resulting struct of NewFileCode of Xff files
%
% BVQXfile(0, 'object', h)
% return the occording object with handle h (implements a check)
%
% BVQXfile(0, 'transiosize');
% retrieve current transio size setting for all BFF (struct)
% BVQXfile(0, 'transiosize', tiostruct);
% sets transiosize (see last transiosize command below)
% BVQXfile(0, 'transiosize', 'vtc');
% retrieve current transio size setting for one BFF (see next command)
% BVQXfile(0, 'transiosize', 'vtc', 1048576 [, boolean:updatecache]);
% this sets the minimum number of bytes before , instead of loading
% the data in a property field, creating a @transio object
%
% BVQXfile(0, 'unwindstack');
% perform garbage collection (remove objects with unmatching dbstack)
%
% BVQXfile(0, 'updatecache');
% updates the cache.mat file (with current transiosize settings)
%
% BVQXfile(0, 'updatedisable' [, type]);
% BVQXfile(0, 'updateenable' [, type]);
% BVQXfile(0, 'updatestate' [, type [, truefalse]]);
% BVQXfile(0, 'updatestate' [, truefalsestruct]]);
% disable/enable automatic object updating (on type field)
% for "undatestate" call can work on a 1x1 struct with type fields
%
% Note: the default constructor (BVQXfile without arguments) produces
% a bogus BVQXfile object with content fields
% Extensions, Formats, Magic, Methods
% containing the supported features of the class
% declare global and persistent variables
global bvqxclup;
global bvqxcont;
global bvqxfile_config;
persistent bvqxfile_singleton;
% check for Class initialization -> do it if necessary
if isempty(bvqxfile_singleton) || ...
~isstruct(bvqxfile_singleton) || ...
~bvqxfile_singleton.is_initialized
% initialize global storage
%
% the storage of all objects is handled in a global variable,
% bvqxcont, as of version 0.7a40
%
% this variable is a struct with fields
% .C - object's content
% .F - associated filename
% .L - lookup value (referential integrity check)
% .S - fileformat specification
%
% references will be looked up by object's internal L field
% vs. the content of global variable bvqxclup
bvqxcont = cell2struct(cell(0, 0, 5), {'C', 'F', 'L', 'S', 'U'}, 3);
% configuration override on cache creation
ovrcfg = struct;
% hdr.assumeflipped is used when the HDR is read to determine the
% convention state if the file itself does not contain this
ovrcfg.hdr = struct;
ovrcfg.hdr.assumeflipped = true;
% vmr.autov16 decides whether V16 files are automatically loaded/saved
ovrcfg.vmr = struct;
ovrcfg.vmr.autov16 = true;
% initialize persistent struct
bvqxfile_singleton = struct;
bvqxfile_singleton.is_initialized = false;
bvqxfile_singleton.mlversion = version;
bvqxfile_singleton.mmversion = str2double(bvqxfile_singleton.mlversion(1));
bvqxfile_singleton.version = 'v0.7c;7100214;20071002141448';
% try to use cached info
bvqxfile_singleton.use_info_cache = true;
% on initialization, also init global struct
bvqxfile_config = struct;
% loaded objects of private functions
bvqxfile_config.loadedobjs = struct;
% reloadsame controls whether the same file (name) should be
% opened again on BVQXfile(filename) calls or a handle to the
% already open object should be returned instead
bvqxfile_config.reloadsame = true;
% settings are loaded from cache/BVQXfile.ini and control
% some of the functions (please check the contents of this file
% every now and then)
try
bsi = BVQXinifile([fileparts(mfilename('fullpath')) ...
'/cache/BVQXfile.ini'], 'convert');
bvqxfile_config.settings = bsi.GetComplete;
catch
bvqxfile_config.settings = [];
end
% type later contains one field (1x1 struct) per filetype
bvqxfile_config.type = struct;
% unwindstack controls the "pseudo scope" of objects
% if set to true, BVQXfile will remove objects from the global
% storage, once the function that created the object has
% been completely run
bvqxfile_config.unwindstack = true;
% update later contains one field (1x1 logical) per filetype
% if this field is set to true and a method with filename
% OBJ_Update(obj, F, S, V) exists, the method is called after
% calls to subsasgn(obj, S, V)
bvqxfile_config.update = struct;
% get base folder
bvqxfile_singleton.base_folder = fileparts(mfilename('fullpath'));
% try cache
usecache = bvqxfile_singleton.use_info_cache;
if usecache
cachefile = ...
[bvqxfile_singleton.base_folder filesep 'cache' filesep 'cache.mat'];
if exist(cachefile, 'file') == 2
try
cachemat = load(cachefile);
cache = cachemat.cache;
if isfield(cache, 'file_formats') && ...
isfield(cache, 'ff_methods') && ...
isfield(cache, 'bvqxconfig') && ...
isfield(cache, 'version') && ...
strcmp(cache.version, bvqxfile_singleton.version)
bvqxfile_singleton.file_formats = cache.file_formats;
bvqxfile_singleton.ff_methods = cache.ff_methods;
bvqxfile_config.reloadsame = cache.bvqxconfig.reloadsame;
bvqxfile_config.type = cache.bvqxconfig.type;
bvqxfile_config.update = cache.bvqxconfig.update;
else
usecache = false;
end
bvqxfile_singleton.cachefile = cachefile;
catch
usecache = false;
end
else
usecache = false;
end
end
% otherwise (or failed)
if ~usecache
% get file formats
bvqxfile_singleton.file_formats = bvqxfile_readformats( ...
[bvqxfile_singleton.base_folder filesep 'formats'] ...
);
% override configs
orf = fieldnames(ovrcfg);
for orfc = 1:numel(orf)
orc = ovrcfg.(orf{orfc});
orcf = fieldnames(orc);
for orcfc = 1:numel(orcf)
bvqxfile_config.type.(orf{orfc}).(orcf{orcfc}) = ...
orc.(orcf{orcfc});
end
end
% get file format specific methods
bvqxfile_singleton.ff_methods = ...
bvqxfile_getmethods(bvqxfile_singleton.file_formats.extensions);
% save ?
if bvqxfile_singleton.use_info_cache
cache = struct;
cache.version = bvqxfile_singleton.version;
cache.file_formats = bvqxfile_singleton.file_formats;
cache.ff_methods = bvqxfile_singleton.ff_methods;
cache.bvqxconfig.reloadsame = bvqxfile_config.reloadsame;
cache.bvqxconfig.type = bvqxfile_config.type;
cache.bvqxconfig.update = bvqxfile_config.update;
if bvqxfile_singleton.mmversion < 7
save(cachefile, 'cache');
else
save(cachefile, 'cache', '-v6');
end
end
end
% get extension and magic list
bvqxfile_singleton.bff = bvqxfile_singleton.file_formats.bff;
bvqxfile_singleton.tff = bvqxfile_singleton.file_formats.tff;
bvqxfile_singleton.ext = bvqxfile_singleton.file_formats.extensions;
bvqxfile_singleton.mag = bvqxfile_singleton.file_formats.magic;
% say we are initialized
bvqxfile_singleton.is_initialized = true;
% fill main object
bvqxclup = 1;
bvqxcont(1) = struct( ...
'C', struct( ...
'Extensions', BVQXfile(0, 'extensions'), ...
'Formats', BVQXfile(0, 'formats'), ...
'Magic', BVQXfile(0, 'magic'), ...
'Methods', BVQXfile(0, 'methods')), ...
'F', 'BVQXfile:BVQXfile', ...
'L', 1, ...
'S', struct('Extensions', {{'ROOT'}}, 'FFTYPE', 'ROOT'), ...
'U', {{ }} );
bvqxcont(1).U(:) = [];
end
% single char argument or char + double
if ...
nargin > 0 && ...
nargin < 3 && ...
ischar(varargin{1}) && ...
~isempty(varargin{1}) && ...
numel(varargin{1}) < 256 && ...
(nargin < 2 || ...
(isa(varargin{2}, 'double') && ...
numel(varargin{2}) == 1) || ...
(ischar(varargin{2}) && ...
~isempty(varargin{2})))
% linearize filename
filename = varargin{1}(:)';
[fnparts{1:3}] = fileparts(filename);
% available file extensions
ext = bvqxfile_singleton.ext;
exn = fieldnames(ext);
% check for "*.???"
if ~isempty(fnparts{2}) && ...
any(fnparts{2} == '*')
% how many files
if nargin < 2 || ...
~isa(varargin{2}, 'double') || ...
isnan(varargin{2}) || ...
varargin{2} < 1
numreq = 1;
else
numreq = floor(varargin{2});
end
if nargin > 1 && ...
ischar(varargin{2})
dtitle = varargin(2);
else
dtitle = cell(0, 1);
end
filename = bvqxfile_requestfile(numreq, filename, ext, ...
bvqxfile_singleton.file_formats, dtitle{:});
% any filename(s) returned
if isempty(filename)
varargout(1:nargout) = cell(1, nargout);
return;
elseif ischar(filename)
filename = {filename};
end
nfiles = numel(filename);
% create output object
oo = BVQXfile(0, 'makeobject', struct('L', 1));
ol = true(1, nfiles);
if nfiles > 1
oo(2:nfiles) = oo(1);
end
% try loading objects
for oc = 1:nfiles
try
if bvqxfile_config.reloadsame
oo(oc) = BVQXfile(filename{oc});
else
if ispc
namelup = strcmpi(filename{oc}, {bvqxcont(:).F});
else
namelup = strcmp(filename{oc}, {bvqxcont(:).F});
end
if ~isempty(namelup)
oo(oc) = BVQXfile(0, 'makeobject', ...
struct('L', bvqxclup(namelup(end))));
ol(oc) = false;
else
oo(oc) = BVQXfile(filename{oc});
end
end
catch
error( ...
'BVQXfile:FileReadError', ...
'Error reading file ''%s'': %s.', ...
filename{oc}, lasterr ...
);
end
end
% return objects
varargout{1} = oo;
varargout{2} = ol;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -