Wiki
Clone wikiUFF / other_formats / USTB HDF5 read_write
HDF5 read/write
Reading from and writting to HDF5 is done through the functions uff.read_object and uff.write_object. For instance the code
#!matlab my_probe = uff.linear_array('N',128,'pitch',300e-6); uff.write_object('./my_uff_file.uff',my_probe,'my_beautiful_probe');
dumps the probe data in a HDF5 file named 'my_uff_file.uff'. Within the file the data is saved in a data structure called 'my_beautiful_probe'. We can check the contents of the file with the function '''uff.index'''
#!matlab uff.index('./my_uff_file.uff','/',true); UFF: Contents of ./my_uff_file.uff at / - /my_beautiful_probe: my_beautiful_probe [uff.linear_array] size(1,1)
To read the data from the UFF file it suffices to
#!matlab my_other_probe=uff.read_object('./my_uff_file.uff','/my_beautiful_probe');
uff.write_object
#!matlab uff.write_object(filename, object, name, location, verbose)
This function checks the object class. In case the object is a numeric value (double, single) or character (char) the function dumps the data in the provided location. In case the object is a uff class then the routine will recursively call itself for each parameter in the ''object'' class. Dependent properties are skipped. The dataset type and size are stored as attributes in the HDF5.
You can find the code of the uff.write_object function below
#!matlab function dumped_objects = write_object(filename,object,name,location,verbose) %% WRITE_OBJECT Writes object into location % % This UFF method writes the object provided into the specified location % of a UFF file. % % WRITE(filename, object, name, location, verbose) % % Parameters: % filename Name and path to the UFF file % object Object to be written into the UFF file % name Name of the object within the file % location Location within the UFF file % verbose Flag to get text messages % % Example: % chdat = uff.channel_data(); % uff.write_object('test.uff',chdat,'channel_data'); % % See also UFF.WRITE, UFF.INDEX if(nargin<1)||isempty(filename) error('Missing UFF filename'); end if(nargin<2)||isempty(object) error('Missing object to write in UFF file'); end if(nargin<3)||isempty(name) error('Missing name for the HDF5 group'); end if(nargin<4) location=[]; end if nargin<5||isempty(verbose) verbose=true; end % check if path to file exists [pathstr,~] = fileparts(filename); if ~exist(pathstr,'file') error(sprintf('UFF: The path %s does not exist.',pathstr)); end % if file doesn't exist -> we write the current version if ~(exist(filename,'file')==2) if verbose fprintf('UFF: creating file %s\n',filename); end attr_details.Name = 'version'; attr_details.AttachedTo = '/'; attr_details.AttachType = 'group'; hdf5write(filename, attr_details, uff.version); end % check if version matches file_version=h5readatt(filename, '/','version'); % read file version file_version=file_version{1}; % from cell to string file_version=file_version(int32(file_version)>0); % removing 0's from 0-terminated strings if ~strcmp(file_version, uff.version) error(sprintf('UFF: Unsupported file version (%s). Current UFF version (%s). The file you want to write to is obsolete, create a new file instead.',file_version,uff.version)); end % check if location exist if ~isempty(uff.index(filename,[location '/' name],false)); choice = tools.dialog_timeout(5,sprintf('UFF: %s already exists in the file. Overwrite? (y/n)',[location '/' name]), ... 'USTB', ... 'Yes','No','No'); if ~strcmp(choice,'Yes') fprintf(1,'%s not written\n',name); return; else fid = H5F.open(filename,'H5F_ACC_RDWR','H5P_DEFAULT'); H5L.delete(fid,[location '/' name],'H5P_DEFAULT'); H5F.close(fid); end end switch class(object) case {'double' 'single'} if isreal(object) h5create(filename,[location '/' name], size(object), 'Datatype', 'single', 'ChunkSize',size(object)); h5write(filename,[location '/' name], single(object)); h5writeatt(filename,[location '/' name],'class',class(object)); h5writeatt(filename,[location '/' name],'name',name); h5writeatt(filename,[location '/' name],'imaginary',0); h5writeatt(filename,[location '/' name],'complex',0); dumped_objects=1; else % real h5create(filename,[location '/' name '/real'], size(object), 'Datatype', 'single', 'ChunkSize',size(object)); h5write(filename,[location '/' name '/real'], single(real(object))); h5writeatt(filename,[location '/' name '/real'],'class',class(object)); h5writeatt(filename,[location '/' name '/real'],'name',name); h5writeatt(filename,[location '/' name '/real'],'imaginary',0); % imag h5create(filename,[location '/' name '/imag'], size(object), 'Datatype', 'single', 'ChunkSize',size(object)); h5write(filename,[location '/' name '/imag'], single(imag(object))); h5writeatt(filename,[location '/' name '/imag'],'class',class(object)); h5writeatt(filename,[location '/' name '/imag'],'name',name); h5writeatt(filename,[location '/' name '/imag'],'imaginary',1); % group attributes h5writeatt(filename,[location '/' name],'class',class(object)); h5writeatt(filename,[location '/' name],'name',name); h5writeatt(filename,[location '/' name],'complex',1); dumped_objects=1; end case 'char' h5create(filename,[location '/' name], size(object), 'Datatype', 'single', 'ChunkSize',size(object)); h5write(filename,[location '/' name], uint16(object)); h5writeatt(filename,[location '/' name],'class',class(object)); h5writeatt(filename,[location '/' name],'name',name); dumped_objects=1; case 'uff.window' h5create(filename,[location '/' name], size(object), 'Datatype', 'single', 'ChunkSize',size(object)); h5write(filename,[location '/' name], single(object)); h5writeatt(filename,[location '/' name],'class',class(object)); h5writeatt(filename,[location '/' name],'name',name); dumped_objects=1; case 'cell' % call write for all members in the cell dumped_objects=0; for n=1:numel(object) dumped_objects=dumped_objects+uff.write_object(filename,object{n}, [name '_' sprintf('%04d',n)],[location '/' name], verbose); end % group attributes if dumped_objects h5writeatt(filename,[location '/' name],'class',class(object)); h5writeatt(filename,[location '/' name],'name',name); h5writeatt(filename,[location '/' name],'array',1); h5writeatt(filename,[location '/' name],'size',size(object)); end otherwise % UFF structures if (findstr('uff.',class(object))) if numel(object)>1 if verbose fprintf('UFF: writting %s [%s] at %s ',name,class(object),location); end % call write for all members in the array dumped_objects=0; previous_msg=''; for n=1:numel(object) dumped_objects=dumped_objects+uff.write_object(filename,object(n), [name '_' sprintf('%04d',n)],[location '/' name],verbose); if verbose previous_msg = tools.text_progress_bar(100*n/numel(object),previous_msg); end end if verbose fprintf('\n'); end % group attributes if dumped_objects h5writeatt(filename,[location '/' name],'class',class(object)); h5writeatt(filename,[location '/' name],'name',name); h5writeatt(filename,[location '/' name],'array',1); h5writeatt(filename,[location '/' name],'size',size(object)); end else % here we process non-array UFF structures switch class(object) case {'uff.channel_data' 'uff.beamformed_data' 'uff.phantom'} if verbose if isempty(location) fprintf('UFF: writting %s [%s] at %s\n',name,class(object),'/'); else fprintf('UFF: writting %s [%s] at %s\n',name,class(object),location); end end end % dump all fields in struct (or properties in class) dumped_objects=0; field_list = fieldnames(object); eval(['mco = ?' class(object) ';']); plist = mco.PropertyList; for f=1:length(field_list) % check if the property is dependent copy=false; for p=1:length(plist) if strcmp(plist(p).Name,field_list{f}) copy=~plist(p).Dependent; continue; end end % if it isn't dependent or empty we write it if copy prop=object.(field_list{f}); if numel(prop) uff.write_object(filename, prop, field_list{f}, [location '/' name], verbose); dumped_objects=dumped_objects+1; end end end if dumped_objects>0 h5writeatt(filename,[location '/' name],'class',class(object)); h5writeatt(filename,[location '/' name],'name',name); h5writeatt(filename,[location '/' name],'size',size(object)); h5writeatt(filename,[location '/' name],'array',0); end end else warning(sprintf('Class %s not supported by UFF; skipping write.',class(object))); end end
uff.read_object
#!matlab object = uff.read_object(filename, location, verbose)
This function checks the location provided, where an attribute should define the class of the saved object. An object of said class is defined, and the contents of the file will be copied to the object instance. If the object class is a numeric value (double, single) or character (char) the function just dumps the data to the new object. If the dumped object was a uff class then the routine will recursively call itself for each parameter in the object class. The dataset type and size are retrieved from attributes in the HDF5 datasets.
You can find the code of the uff.read_object function below
#!matlab function object = read_object(filename, location, verbose) %% READ_OBJECT Reads object from location % % This UFF method delivers the object stored in the specified location % of a UFF file. % % READ_OBJECT(filename, location, verbose) % % Parameters: % filename Name and path to the UFF file % location Location within the UFF file % verbose Flag to get text messages % % Example: % chndata=uff.read_object('test.uff','/channel_data'); % % See also UFF.READ, UFF.WRITE, UFF.INFO flag_v10X=false; if nargin<2||isempty(location) location='/'; end if nargin<3 verbose=true; end % check if path to file exists [pathstr,~] = fileparts(filename); if ~exist(pathstr,'file') error(sprintf('UFF: The path %s does not exist.',pathstr)); end % check if file exists if ~(exist(filename,'file')==2) error(sprintf('UFF: The file %s does not exist.',filename)); end % check if version matches file_version=h5readatt(filename, '/','version'); % read file version file_version=file_version{1}; % from cell to string file_version=file_version(int32(file_version)>0); % removing 0's from 0-terminated strings if ~strcmp(file_version, uff.version) % Flags to enable backcompatibility. if strcmp(file_version, 'v1.0.0')||strcmp(file_version, 'v1.0.1') flag_v10X=true; else error(sprintf('UFF: Unsupported file version (%s). Current UFF version (%s). Please choose a new file instead.',file_version,uff.version)); end end % check if location exist if isempty(uff.index(filename,location,false)); error('UFF: The location does not exists'); end % check if batch reading if nargin<2 || strcmp(location,'/') % we read everything in the main location item=uff.index(filename,'/'); if length(item) object={}; end for n=1:length(item) object{n}=uff.read_object(filename,item{n}.location,verbose); end else % checking name and class try data_name=h5readatt(filename, location ,'name'); class_name=h5readatt(filename, location ,'class'); catch me if isempty(findstr(me.message,'can''t locate attribute:')) me.rethrow; else warning(['UFF: unnamed locations not supported. Skipping ' location '.']); object=[]; return; end end switch class_name case {'double' 'single'} if ~h5readatt(filename, location, 'complex') object=h5read(filename, location); else object=h5read(filename, [ location '/real' ])+... 1i*h5read(filename, [ location '/imag' ]); end case 'char' object=char(h5read(filename, location)); case 'uff.window' object=uff.window(h5read(filename, location )); case 'cell' data_size=h5readatt(filename, location ,'size'); N=prod(data_size); if(N>0) item=uff.index(filename, location ); if length(item)~=N error('Size attribute does not match number of subgroups'); end object={}; for n=1:N object{n}=uff.read_object(filename,item{n}.location,verbose); end reshape(object,data_size.'); end otherwise % rest of UFF structures if (findstr('uff.',class_name)) switch class_name case {'uff.channel_data' 'uff.beamformed_data' 'uff.phantom'} if verbose fprintf('UFF: reading %s [%s]\n',data_name,class_name); end end data_size=h5readatt(filename, location ,'size'); N=prod(data_size); if(N>1) item=uff.index(filename, location ); if length(item)~=N error('Size attribute does not match number of subgroups'); end if verbose fprintf('UFF: reading %s [%s] ',data_name,class_name); end previous_msg = ''; for n=1:N object(n)=uff.read_object(filename,item{n}.location,verbose); if verbose previous_msg = tools.text_progress_bar(100*n/N,previous_msg); end end if verbose fprintf('\n'); end reshape(object,data_size.'); else object=feval(class_name); % add properties prop=uff.index(filename, location); for m=1:length(prop) % exceptions from backcompatibility if flag_v10X&&strcmp(class_name,'uff.apodization')&&strcmp(prop{m}.name,'apex') object.('origo')=uff.read_object(filename,prop{m}.location,verbose); elseif flag_v10X&&strcmp(class_name,'uff.apodization')&&strcmp(prop{m}.name,'scan') object.('focus')=uff.read_object(filename,prop{m}.location,verbose); else object.(prop{m}.name)=uff.read_object(filename,prop{m}.location,verbose); end end end else warning(sprintf('Class %s not supported by UFF; skipping write.',class(value))); object=[]; end end end
Updated