function datasetId = h5datacreate(h5file,varname,varargin)
%H5datacreate Create HDF5 dataset.
%
% H5DATACREATE(HFILE,VARNAME,parameter,value,...) creates a dataset
% named VARNAME. HFILE may be either a path to the HDF5 file or a file
% ID to an already opened file.
%
% If VARNAME is a full pathname, all
% intermediate groups are created if they don't already exist.
%
% parameter
% 'size' - size of the dataset
% 'chunk_size' - size of the chunks of the dataset
% 'compression' - 0-9 compression level
% 'type' - type of the dataset to create. This can be a string
% such as 'double', in which case the datatype maps to
% 'H5T_NATIVE_DOUBLE', or it can be a derived HDF5
% datatype.
% 'max_size' - the maximum size of the dataset to create
%
%
% Example: create a 10x20 single precision dataset named 'DS1'.
% h5filecreate('myfile.h5');
% h5datacreate('myfile.h5','DS1','type','single','size',[10 20]);
%
% Example: create a 4x1 string dataset where each string has length
% 8 and is null-terminated.
% mytype = H5T.copy('H5T_C_S1');
% H5T.set_size(mytype,8);
% H5T.set_strpad(mytype,'H5T_STR_NULLTERM');
% h5datacreate('myfile.h5','/path/to/DS2','type',mytype,'size',4);
%
% Credit where credit is due: Philip Top at LLNL
%
% See also h5filecreate.
% Copyright 2010 The MathWorks, Inc.
p = inputParser;
p.addParamValue('size',0,@isnumeric);
p.addParamValue('chunk_size',0,@isnumeric);
p.addParamValue('compression',0,@isnumeric);
p.addParamValue('type',H5T.copy('H5T_NATIVE_DOUBLE'),@(x)ischar(x) || isa(x,'H5ML.id'));
p.addParamValue('max_size',0,@isnumeric);
p.parse(varargin{:});
params = p.Results;
params = validate_params(h5file,varname,params);
flags = 'H5F_ACC_RDWR';
fapl = 'H5P_DEFAULT';
if ischar(h5file)
file_id = H5F.open(h5file,flags,fapl);
else
file_id=h5file;
end
params = set_dataspace_id (params);
params = set_datatype_id (params);
params = set_dcpl(params);
datasetId = set_data_id(file_id,varname,params);
H5S.close(params.dataspaceId);
H5T.close(params.datatypeId);
H5P.close(params.dcpl);
if ischar(h5file)
H5F.close(file_id);
end
%==========================================================================
function params = set_dcpl(params)
% Setup the dataset creation property list.
params.dcpl = H5P.create('H5P_DATASET_CREATE'); % create property list
if (~isequal(params.chunk_size,0))
% set chunk size
H5P.set_chunk(params.dcpl,fliplr(params.chunk_size));
end
if (params.compression~=0)
% set gzip compression level
H5P.set_deflate(params.dcpl,params.compression);
end
return
%==========================================================================
% SET_DATASET_ID
%
% Setup the dataet ID. We need to check as to whether or not the dataset
% already exists.
function datasetID = set_data_id(fid,dataname,params)
v = version('-release');
switch(v)
case { '2007b', '2008a', '2008b' }
% Give it our best shot.
datasetID = H5D.create(fid,dataname,...
params.datatypeId, params.dataspaceId, ...
params.dcpl);
otherwise
% create any intermediate groups along the way.
params.lcpl = H5P.create('H5P_LINK_CREATE');
H5P.set_create_intermediate_group(params.lcpl,1);
dapl = 'H5P_DEFAULT';
% need to use the 1.8.x version of H5D.create for this.
datasetID = H5D.create(fid,dataname,...
params.datatypeId, params.dataspaceId, ...
params.lcpl,params.dcpl,dapl);
end
return
%===============================================================================
% SET_DATASPACE_ID
%
% Setup the dataspace ID.
function params = set_dataspace_id (params)
params.dataspaceId=H5S.create('H5S_SIMPLE');
H5S.set_extent_simple(params.dataspaceId,length(params.size),...
fliplr(params.size),fliplr(params.max_size));
return
%===============================================================================
% SET_DATATYPE_ID
%
% We need to choose an appropriate HDF5 datatype
function params = set_datatype_id (params)
if ischar(params.type)
switch params.type
case 'double'
params.datatypeId = H5T.copy('H5T_NATIVE_DOUBLE');
case {'single','float'}
params.datatypeId = H5T.copy('H5T_NATIVE_FLOAT');
case 'int64'
params.datatypeId = H5T.copy('H5T_NATIVE_LLONG');
case 'uint64'
params.datatypeId = H5T.copy('H5T_NATIVE_ULLONG');
case {'int32','int'}
params.datatypeId = H5T.copy('H5T_NATIVE_INT');
case {'uint32','uint'}
params.datatypeId = H5T.copy('H5T_NATIVE_UINT');
case {'int16','short'}
params.datatypeId = H5T.copy('H5T_NATIVE_SHORT');
case 'uint16'
params.datatypeId = H5T.copy('H5T_NATIVE_USHORT');
case 'int8'
params.datatypeId = H5T.copy('H5T_NATIVE_SCHAR');
case 'uint8'
params.datatypeId = H5T.copy('H5T_NATIVE_UCHAR');
case 'complex'
% special case for complex data. We'll actually create 3
% datasets. One to hold the real data, one to hold the
% complex data, and one to hold references to both.
params.datatypeId = H5T.copy('H5T_STD_REF_OBJ');
otherwise
error('hdf5tools:H5DATACREATE:unsupportedDatatype', ...
'''%s'' is not a supported H5DATACREATE datatype.\n', params.type );
end
return
end
if isa(params.type,'H5ML.id')
params.datatypeId = H5T.copy(params.type);
return
end
%--------------------------------------------------------------------------
function params = validate_params(hfile,varname,params)
if (params.size == 0 )
error('hdf5tools:h5datacreate:zeroSize', ...
'Size must be specified and be greater than zero.');
end
if ~ischar(hfile)
if ~isequal(class(hfile),'H5ML.id')
error('hdf5tools:H%DATACREATE:badDatatype', ...
'Filename input argument must have datatype char.' );
end
end
if ~ischar(varname)
error('hdf5tools:H5DATACREATE:badDatatype', ...
'VARNAME input argument must have datatype char.' );
end
if (~isequal(params.chunk_size,0))
if (numel(params.chunk_size)~=numel(params.size))
error('dataset size and chunk size have different dimensions');
end
end
if (~isequal(params.max_size,0))
if (numel(params.max_size)~=numel(params.size))
error('dataset max size and initial size have different dimensions');
elseif (any(isinf(params.max_size)))
mxs=cell(size(params.max_size));
for kk=1:length(params.max_size)
if (isinf(params.max_size(kk)))
mxs{kk}='H5S_UNLIMITED';
else
mxs{kk}=params.max_size(kk);
end
end
end
else
params.max_size=params.size;
end
if ((params.compression<0)||(params.compression>9))
error('invalid compression level');
else
if (params.compression>0)
if (isequal(params.chunk_size,0))
params.chunk_size=params.size;
end
end
end
return