ncsa.hdf.object.h5.H5Datatype Maven / Gradle / Ivy
Show all versions of hdf-java Show documentation
/*****************************************************************************
* Copyright by The HDF Group. *
* Copyright by the Board of Trustees of the University of Illinois. *
* All rights reserved. *
* *
* This file is part of the HDF Java Products distribution. *
* The full copyright notice, including terms governing use, modification, *
* and redistribution, is contained in the files COPYING and Copyright.html. *
* COPYING can be found at the root of the source code distribution tree. *
* Or, see http://hdfgroup.org/products/hdf-java/doc/Copyright.html. *
* If you do not have access to either file, you may request a copy from *
* [email protected]. *
****************************************************************************/
package ncsa.hdf.object.h5;
import ncsa.hdf.hdf5lib.*;
import ncsa.hdf.hdf5lib.exceptions.*;
import ncsa.hdf.object.*;
import java.lang.reflect.Array;
import java.util.*;
/**
* This class defines HDF5 data type characteristics and APIs for a data type.
*
* This class provides several methods to convert an HDF5 dataype identifier to
* a dataype object, and vice versa. A dataype object is described by four basic
* fields: datatype class, size, byte order, and sign, while an HDF5 dataype is
* presented by a datetype identifier.
*
* @version 1.1 9/4/2007
* @author Peter X. Cao
*/
public class H5Datatype extends Datatype
{
/**
* @see ncsa.hdf.object.HObject#serialVersionUID
*/
public static final long serialVersionUID = HObject.serialVersionUID;
/**
* The list of attributes of this data object.
*/
private List attributeList;
/** Flag to indicate if this datatype is a named datatype */
private boolean isNamed=false;
private int nAttributes = -1;
private boolean isVLEN = false;
private String description = null;
/**
* Constrcuts an named HDF5 data type object for a given file, dataset name and group path.
*
* The datatype object represents an existing named datatype in file. For example,
* new H5Datatype(file, "dtype1", "/g0") constructs a datatype object that corresponds to
* the dataset,"dset1", at group "/g0".
*
* @param theFile the file that contains the dataset.
* @param name the name of the dataset such as "dset1".
* @param path the group path to the dataset such as "/g0/".
*/
public H5Datatype(
FileFormat theFile,
String name,
String path)
{
super (theFile, name, path, null);
}
/**
* @deprecated Not for public use in the future.
* Using {@link #H5Datatype(FileFormat, String, String)}
*/
@Deprecated
public H5Datatype(
FileFormat theFile,
String name,
String path,
long[] oid)
{
super (theFile, name, path, oid);
if ((oid == null) && (theFile != null)) {
// retrieve the object ID
try {
byte[] ref_buf = H5.H5Rcreate(theFile.getFID(), this.getFullName(), HDF5Constants.H5R_OBJECT, -1);
this.oid = new long[1];
this.oid[0] = HDFNativeData.byteToLong(ref_buf, 0);
} catch (Exception ex) {}
}
}
/**
* Constructs a Datatype with specified class, size, byte order and sign.
*
* The following is a list of a few example of H5Datatype.
*
* - to create unsigned native integer
* H5Datatype type = new H5Dataype(CLASS_INTEGER, NATIVE, NATIVE, SIGN_NONE);
* - to create 16-bit signed integer with big endian
* H5Datatype type = new H5Dataype(CLASS_INTEGER, 2, ORDER_BE, NATIVE);
* - to create native float
* H5Datatype type = new H5Dataype(CLASS_FLOAT, NATIVE, NATIVE, -1);
* - to create 64-bit double
* H5Datatype type = new H5Dataype(CLASS_FLOAT, 8, NATIVE, -1);
*
* @param tclass the class of the datatype, e.g. CLASS_INTEGER, CLASS_FLOAT and etc.
* @param tsize the size of the datatype in bytes, e.g. for a 32-bit integer, the size is 4.
* @param torder the byte order of the datatype. Valid values are ORDER_LE, ORDER_BE, ORDER_VAX and ORDER_NONE
* @param tsign the sign of the datatype. Valid values are SIGN_NONE, SIGN_2 and MSGN
*/
public H5Datatype(int tclass, int tsize, int torder, int tsign)
{
super(tclass, tsize, torder, tsign);
}
/**
* Constructs a Datatype with a given native datatype identifier.
*
* For example, if the datatype identifier is a 32-bit unsigned integer created
* from HDF5,
*
* int tid = H5.H5Tcopy( HDF5Constants.H5T_NATIVE_UNINT32);
* Datatype dtype = new Datatype(tid);
*
* will construct a datatype equivalent to
* new Datatype(CLASS_INTEGER, 4, NATIVE, SIGN_NONE);
*
* @see #fromNative(int nativeID)
* @param nativeID the native datatype identifier.
*/
public H5Datatype(int nativeID)
{
super(nativeID);
description = getDatatypeDescription(nativeID);
fromNative(nativeID);
}
/*
* (non-Javadoc)
* @see ncsa.hdf.object.DataFormat#hasAttribute()
*/
public boolean hasAttribute ()
{
if (nAttributes < 0) {
int tid = -1;
try
{
tid = H5.H5Topen(getFID(), getPath()+getName());
fromNative(tid);
nAttributes = H5.H5Aget_num_attrs(tid);
isNamed = true;
} catch (Exception ex) { nAttributes = 0;}
finally {
try {H5.H5Tclose(tid);} catch (Exception ex){}
}
}
return (nAttributes>0);
}
/**
* Converts values in an Enumeration Datatype to names.
*
* This method searches the identified enumeration datatype for
* the values appearing in inValues
and returns the
* names corresponding to those values. If a given value is not
* found in the enumeration datatype, the name corresponding to that
* value will be set to null
in the string array that is
* returned.
*
* If the method fails in general, null will be returned instead
* of a String array. An empty inValues
parameter,
* an outNames
array with a different number of entries
* than the inValues
array, or an invalid tid
* would all cause general failure.
*
* @param tid The identifier of the enumeration datatype.
* @param inValues The array of enumerations values to be converted.
* @param outNames The array of names to be populated. If null, the array
* will be created. If outNames
is not null, the
* number of entries must be the same as the number of values in
* inValues
.
* @return The string array of names if successful;
* otherwise return null.
* @throws HDF5Exception If there is an error at the HDF5 library level.
*
*/
public static final String[] convertEnumValueToName(
int tid, Object inValues, String[] outNames) throws HDF5Exception
{
int inSize = 0;
if ( (inValues == null) ||
( (inSize = Array.getLength(inValues)) <=0) ||
( (outNames != null) && (inSize != Array.getLength(outNames))) ) {
return null;
}
int nMembers = H5.H5Tget_nmembers(tid);
if (nMembers <=0 ) {
return null;
}
if (outNames == null) {
outNames = new String[inSize];
} else {
// set values in existing array to null in case no match found
for ( int i = 0; i < inSize; i++ ) {
outNames[i] = null;
}
}
String[] names = new String[nMembers];
int[] values = new int[nMembers];
int[] theValue = {0};
// Loop through the enumeration datatype and extract the names and
// values.
for (int i=0; i
* Using {@link ncsa.hdf.hdf5lib.H5#H5Tget_native_type(int)}
*
* Return the HDF5 memory datatype identifier based on the HDF5 datatype identifier on disk
*
* @param tid the datatype identifieron disk.
* @return the memory datatype identifier if successful, and negative otherwise.
*/
@Deprecated
public static int toNative(int tid)
{
// data type information
int native_type=-1;
try {
native_type = H5.H5Tget_native_type(tid);
} catch (Exception ex) {}
try {
if (H5.H5Tis_variable_str(tid))
H5.H5Tset_size (native_type, HDF5Constants.H5T_VARIABLE);
} catch (Exception ex) {}
return native_type;
}
/*
* (non-Javadoc)
* @see ncsa.hdf.object.Datatype#toNative()
*/
@Override
public int toNative()
{
int tid=-1, tmptid=-1;
if (isNamed) {
try {tid = H5.H5Topen(getFID(), getPath()+getName());}
catch (Exception ex) {;}
}
if (tid >=0 ) {
return tid;
}
// figure the datatype
try {
switch (datatypeClass)
{
case CLASS_ARRAY:
try {
tmptid = baseType.toNative();
tid = H5.H5Tarray_create(tmptid, dims.length, dims, null);
} finally { close(tmptid); }
break;
case CLASS_INTEGER:
case CLASS_ENUM:
if (datatypeSize == 1) {
tid = H5.H5Tcopy(HDF5Constants.H5T_NATIVE_INT8);
} else if (datatypeSize == 2) {
tid = H5.H5Tcopy(HDF5Constants.H5T_NATIVE_INT16);
} else if (datatypeSize == 4) {
tid = H5.H5Tcopy(HDF5Constants.H5T_NATIVE_INT32);
} else if (datatypeSize == 8) {
tid = H5.H5Tcopy(HDF5Constants.H5T_NATIVE_INT64);
} else {
tid = H5.H5Tcopy(HDF5Constants.H5T_NATIVE_INT);
}
if (datatypeOrder == Datatype.ORDER_BE) {
H5.H5Tset_order(tid, HDF5Constants.H5T_ORDER_BE);
} else if (datatypeOrder == Datatype.ORDER_LE) {
H5.H5Tset_order(tid, HDF5Constants.H5T_ORDER_LE);
}
if (datatypeSign == Datatype.SIGN_NONE) {
H5.H5Tset_sign(tid, HDF5Constants.H5T_SGN_NONE);
}
break;
case CLASS_FLOAT:
if (datatypeSize == 8) {
tid = H5.H5Tcopy(HDF5Constants.H5T_NATIVE_DOUBLE);
} else {
tid = H5.H5Tcopy(HDF5Constants.H5T_NATIVE_FLOAT);
}
if (datatypeOrder == Datatype.ORDER_BE) {
H5.H5Tset_order(tid, HDF5Constants.H5T_ORDER_BE);
} else if (datatypeOrder == Datatype.ORDER_LE) {
H5.H5Tset_order(tid, HDF5Constants.H5T_ORDER_LE);
}
break;
case CLASS_CHAR:
if (datatypeSign == Datatype.SIGN_NONE) {
tid = H5.H5Tcopy(HDF5Constants.H5T_NATIVE_UCHAR);
} else {
tid = H5.H5Tcopy(HDF5Constants.H5T_NATIVE_CHAR);
}
break;
case CLASS_STRING:
tid = H5.H5Tcopy(HDF5Constants.H5T_C_S1);
if (isVLEN)
H5.H5Tset_size (tid, HDF5Constants.H5T_VARIABLE);
else
H5.H5Tset_size(tid, datatypeSize);
H5.H5Tset_strpad(tid, HDF5Constants.H5T_STR_NULLPAD);
break;
case CLASS_REFERENCE:
if (datatypeSize > H5.H5Tget_size(HDF5Constants.H5T_STD_REF_OBJ)) {
tid = H5.H5Tcopy(HDF5Constants.H5T_STD_REF_DSETREG);
} else {
tid = H5.H5Tcopy(HDF5Constants.H5T_STD_REF_OBJ);
}
break;
} // switch (tclass)
} catch (Exception ex) { tid = -1;}
// set up enum members
if (datatypeClass == CLASS_ENUM) {
int ptid = tid;
try {
tid = H5.H5Tenum_create(ptid);
String memstr, memname;
int memval=0, idx;
StringTokenizer token;
// using "0" and "1" as default
if (enumMembers == null) {
token = new StringTokenizer("0,1", ",");
} else {
token = new StringTokenizer(enumMembers, ",");
}
while (token.hasMoreTokens()) {
memstr = token.nextToken();
if (memstr != null) {
memstr = memstr.trim();
}
if ((memstr==null) || (memstr.length()<1)) {
continue;
}
idx = memstr.indexOf('=');
if (idx>0) {
memname = memstr.substring(0, idx);
memval = Integer.parseInt(memstr.substring(idx+1));
} else {
memname = memstr;
memval++;
}
H5.H5Tenum_insert(tid, memname, memval);
}
} catch (Exception ex) { tid = -1;}
try { H5.H5Tclose(ptid); } catch (Exception ex) {}
} // if (datatypeClass == CLASS_ENUM) {
return tid;
}
/**
* Allocates an one-dimensional array of byte, short, int, long, float, double,
* or String to store data in memory.
*
* For example,
*
* int tid = H5.H5Tcopy( HDF5Constants.H5T_NATIVE_INT32);
* int[] data =(int[])allocateArray(tid, 100);
*
* returns a 32-bit integer array of size 100.
*
* @param tid the datatype id.
* @param size the total number of data points of the array.
* @return the array object if successful; otherwise, return null.
*/
public static Object allocateArray(int tid, int size) throws OutOfMemoryError
{
Object data = null;
boolean isVL = false;
boolean is_variable_str = false;
boolean is_reg_ref = false;
if (size < 0) {
return null;
}
// Scalar members have dimensionality zero, i.e. size =0
// what can we do about it, set the size to 1
if (size == 0) {
size = 1;
}
// data type information
int tclass=-1, tsize=-1, tsign=-1;
try
{
tclass = H5.H5Tget_class(tid);
tsize = H5.H5Tget_size(tid);
tsign = H5.H5Tget_sign(tid);
} catch (Exception ex) {}
try { is_variable_str = H5.H5Tis_variable_str(tid); } catch (Exception ex) {}
try { isVL = (tclass==HDF5Constants.H5T_VLEN); } catch (Exception ex) {}
try { is_reg_ref = H5.H5Tequal(tid, HDF5Constants.H5T_STD_REF_DSETREG); } catch (Exception ex) {}
if (is_variable_str || isVL || is_reg_ref)
{
data = new String[size];
for (int i=0; i
* It basically just calls H5Tget_size(tid).
*
* @param tid The datatype identifier.
* @return The size of the datatype in bytes.
*
* @see ncsa.hdf.hdf5lib.H5#H5Tget_size(int)
*/
public static final int getDatatypeSize(int tid)
{
// data type information
int tsize=-1;
try {
tsize = H5.H5Tget_size(tid);
} catch (Exception ex) {tsize = -1; }
return tsize;
}
/*
* (non-Javadoc)
* @see ncsa.hdf.object.Datatype#getDatatypeDescription()
*/
@Override
public String getDatatypeDescription()
{
if (description == null) {
int tid = toNative();
description = getDatatypeDescription(tid);
close(tid);
}
return description;
}
/**
* Returns a short description of a given datatype ID.
*
* @param tid the HDF5 datatype identifier
* @return a string describing the data type.
*/
public static final String getDatatypeDescription(int tid)
{
String description = "Unknown";
// data type information
int tclass=-1, tsize=-1, tsign=-1, torder=-1;
try
{
tclass = H5.H5Tget_class(tid);
tsize = H5.H5Tget_size(tid);
tsign = H5.H5Tget_sign(tid);
} catch (Exception ex) {;}
if (tclass == HDF5Constants.H5T_INTEGER)
{
if (tsize == 1)
{
try {
if (H5.H5Tequal(tid, HDF5Constants.H5T_NATIVE_UCHAR)) {
description = "8-bit unsigned character";
} else if (H5.H5Tequal(tid, HDF5Constants.H5T_NATIVE_CHAR)) {
description = "8-bit character";
} else if (tsign == HDF5Constants.H5T_SGN_NONE) {
description = "8-bit unsigned integer";
} else {
description = "8-bit integer";
}
} catch (Exception ex) { description = "Unknown"; }
}
else if (tsize == 2)
{
if (tsign == HDF5Constants.H5T_SGN_NONE) {
description = "16-bit unsigned integer";
} else {
description = "16-bit integer";
}
}
else if (tsize == 4)
{
if (tsign == HDF5Constants.H5T_SGN_NONE) {
description = "32-bit unsigned integer";
} else {
description = "32-bit integer";
}
}
else if (tsize == 8)
{
if (tsign == HDF5Constants.H5T_SGN_NONE) {
description = "64-bit unsigned integer";
} else {
description = "64-bit integer";
}
}
}
else if (tclass == HDF5Constants.H5T_FLOAT)
{
if (tsize == 4)
{
description = "32-bit floating-point";
}
else if (tsize == 8)
{
description = "64-bit floating-point";
}
}
else if (tclass == HDF5Constants.H5T_STRING)
{
try {
if ( H5.H5Tis_variable_str(tid )) {
description = "String, length = variable";
} else {
description = "String, length = "+H5.H5Tget_size(tid);
}
}
catch (Exception ex)
{
description = "String";
}
}
else if (tclass == HDF5Constants.H5T_REFERENCE)
{
boolean is_reg_ref = false;
try {is_reg_ref=H5.H5Tequal(tid, HDF5Constants.H5T_STD_REF_DSETREG);}
catch (Exception ex) {}
if (is_reg_ref) {
description = "Dataset region reference";
} else {
description = "Object reference";
}
}
else if (tclass == HDF5Constants.H5T_BITFIELD)
{
description = "Bitfield";
}
else if (tclass == HDF5Constants.H5T_ENUM)
{
description = "enum";
String enames = " ( ";
int[] evalue= {0};
try {
int n = H5.H5Tget_nmembers(tid );
for (int i=0; i
* @param datatype the datatype ID to be checked.
*
* @return true is the datatype is an unsigned integer; otherwise returns false.
*/
public static final boolean isUnsigned(int datatype)
{
boolean unsigned = false;;
try
{
int tsign = H5.H5Tget_sign(datatype);
if (tsign == HDF5Constants.H5T_SGN_NONE) {
unsigned = true;
}
} catch (Exception ex) {
unsigned = false;
}
return unsigned;
}
/**
* Opens access to a named datatype.
*
* It calls H5.H5Topen(loc, name).
*
* @return the datatype identifier if successful; otherwise returns negative value.
*
* @see ncsa.hdf.hdf5lib.H5#H5Topen(int, String)
*/
@Override
public int open()
{
int tid = -1;
try
{
tid = H5.H5Topen(getFID(), getPath()+getName());
} catch (HDF5Exception ex)
{
tid = -1;
}
return tid;
}
/**
* Closes a datatype identifier.
*
* It calls H5.H5close(tid).
*
* @param tid the datatype ID to close
*/
@Override
public void close(int tid) {
try { H5.H5Tclose(tid); }
catch (HDF5Exception ex) {;}
}
/*
* (non-Javadoc)
* @see ncsa.hdf.object.Datatype#getMetadata()
*/
@Override
public List getMetadata() throws HDF5Exception
{
// load attributes first
if (attributeList == null)
{
int tid = open();
try {
attributeList = H5File.getAttribute(tid);
} catch (Exception ex) {}
finally {
close(tid);
}
} // if (attributeList == null)
return attributeList;
}
/*
* (non-Javadoc)
* @see ncsa.hdf.object.Datatype#writeMetadata(java.lang.Object)
*/
@Override
public void writeMetadata(Object info) throws Exception
{
// only attribute metadata is supported.
if (!(info instanceof Attribute)) {
return;
}
boolean attrExisted = false;
Attribute attr = (Attribute)info;
String name = attr.getName();
if (attributeList == null) {
this.getMetadata();
} else {
attrExisted = attributeList.contains(attr);
}
getFileFormat().writeAttribute(this, attr, attrExisted);
// add the new attribute into attribute list
if (!attrExisted) {
attributeList.add(attr);
nAttributes = attributeList.size();
}
}
/*
* (non-Javadoc)
* @see ncsa.hdf.object.Datatype#removeMetadata(java.lang.Object)
*/
@Override
public void removeMetadata(Object info) throws HDF5Exception
{
// only attribute metadata is supported.
if (!(info instanceof Attribute)) {
return;
}
Attribute attr = (Attribute)info;
int tid = open();
try {
H5.H5Adelete(tid, attr.getName());
List attrList = getMetadata();
attrList.remove(attr);
nAttributes = attributeList.size();
} finally {
close(tid);
}
}
}