Files
hdf5/java/jtest/TestH5Dffm.java
Allen Byrne b754dcb8f2 Move Java wrappers to FFM using jextract and java 25 (#5957)
FFM build requires Java 25, Jextract 25.
Generates FFM bindings during configure.
JNI is default when the requirements are not met or can be forced.
Presets added for maven and FFM - JNI is default selection.
Enhanced Maven options will work with either JNI or FFM
New Workflows for testing and maven uploads.
Extensive documentation changes for java.
2025-11-04 14:03:06 -06:00

1158 lines
48 KiB
Java

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Copyright by The HDF Group. *
* All rights reserved. *
* *
* This file is part of HDF5. The full HDF5 copyright notice, including *
* terms governing use, modification, and redistribution, is contained in *
* the LICENSE file, which can be found at the root of the source code *
* distribution tree, or in https://www.hdfgroup.org/licenses. *
* If you do not have access to either file, you may request a copy from *
* help@hdfgroup.org. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
package jtest;
import static org.junit.Assert.*;
import static jtest.FfmTestSupport.*;
import java.io.File;
import java.lang.foreign.Arena;
import java.lang.foreign.MemorySegment;
import java.lang.foreign.ValueLayout;
import org.hdfgroup.javahdf5.hdf5_h;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestName;
/**
* FFM-only tests for HDF5 Dataset (H5D) operations.
*
* This test class uses direct FFM bindings without the hdf.hdf5lib wrapper layer.
*/
public class TestH5Dffm {
@Rule
public TestName testname = new TestName();
private static final String H5_FILE = "testDffm.h5";
private static final String DATASET_NAME = "dset";
private static final int DIM_X = 4;
private static final int DIM_Y = 6;
private static final int RANK = 2;
long H5fid = hdf5_h.H5I_INVALID_HID();
long H5dsid = hdf5_h.H5I_INVALID_HID();
long H5did = hdf5_h.H5I_INVALID_HID();
private void deleteFile(String filename)
{
File file = new File(filename);
if (file.exists()) {
try {
file.delete();
}
catch (SecurityException e) {
// Ignore
}
}
}
@Before
public void createH5file()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Create file
MemorySegment fileNameSegment = stringToSegment(arena, H5_FILE);
H5fid = hdf5_h.H5Fcreate(fileNameSegment, hdf5_h.H5F_ACC_TRUNC(), hdf5_h.H5P_DEFAULT(),
hdf5_h.H5P_DEFAULT());
assertTrue("H5Fcreate failed", isValidId(H5fid));
// Create dataspace
long[] dims = {DIM_X, DIM_Y};
MemorySegment dimsSegment = allocateLongArray(arena, RANK);
copyToSegment(dimsSegment, dims);
H5dsid = hdf5_h.H5Screate_simple(RANK, dimsSegment, MemorySegment.NULL);
assertTrue("H5Screate_simple failed", isValidId(H5dsid));
// Create dataset
MemorySegment dsetNameSegment = stringToSegment(arena, DATASET_NAME);
H5did = hdf5_h.H5Dcreate2(H5fid, dsetNameSegment, hdf5_h.H5T_NATIVE_INT_g(), H5dsid,
hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT());
assertTrue("H5Dcreate2 failed", isValidId(H5did));
int flushResult = hdf5_h.H5Fflush(H5fid, hdf5_h.H5F_SCOPE_LOCAL());
assertTrue("H5Fflush failed", isSuccess(flushResult));
}
}
@After
public void deleteH5file()
{
closeQuietly(H5did, hdf5_h::H5Dclose);
closeQuietly(H5dsid, hdf5_h::H5Sclose);
closeQuietly(H5fid, hdf5_h::H5Fclose);
H5did = hdf5_h.H5I_INVALID_HID();
H5dsid = hdf5_h.H5I_INVALID_HID();
H5fid = hdf5_h.H5I_INVALID_HID();
deleteFile(H5_FILE);
System.out.println();
}
@Test
public void testH5Dopen()
{
long did = hdf5_h.H5I_INVALID_HID();
try (Arena arena = Arena.ofConfined()) {
MemorySegment dsetNameSegment = stringToSegment(arena, DATASET_NAME);
did = hdf5_h.H5Dopen2(H5fid, dsetNameSegment, hdf5_h.H5P_DEFAULT());
assertTrue("H5Dopen2 failed", isValidId(did));
}
finally {
closeQuietly(did, hdf5_h::H5Dclose);
}
}
@Test
public void testH5Dget_space()
{
long sid = hdf5_h.H5I_INVALID_HID();
try {
sid = hdf5_h.H5Dget_space(H5did);
assertTrue("H5Dget_space failed", isValidId(sid));
// Verify dimensions
try (Arena arena = Arena.ofConfined()) {
MemorySegment dimsSegment = allocateLongArray(arena, RANK);
int ndims = hdf5_h.H5Sget_simple_extent_dims(sid, dimsSegment, MemorySegment.NULL);
assertEquals("Rank should match", RANK, ndims);
long[] dims = new long[RANK];
copyFromSegment(dimsSegment, dims);
assertEquals("Dimension 0 should match", DIM_X, dims[0]);
assertEquals("Dimension 1 should match", DIM_Y, dims[1]);
}
}
finally {
closeQuietly(sid, hdf5_h::H5Sclose);
}
}
@Test
public void testH5Dget_type()
{
long tid = hdf5_h.H5I_INVALID_HID();
try {
tid = hdf5_h.H5Dget_type(H5did);
assertTrue("H5Dget_type failed", isValidId(tid));
}
finally {
closeQuietly(tid, hdf5_h::H5Tclose);
}
}
@Test
public void testH5Dget_create_plist()
{
long plist = hdf5_h.H5I_INVALID_HID();
try {
plist = hdf5_h.H5Dget_create_plist(H5did);
assertTrue("H5Dget_create_plist failed", isValidId(plist));
}
finally {
closeQuietly(plist, hdf5_h::H5Pclose);
}
}
@Test
public void testH5Dget_access_plist()
{
long plist = hdf5_h.H5I_INVALID_HID();
try {
plist = hdf5_h.H5Dget_access_plist(H5did);
assertTrue("H5Dget_access_plist failed", isValidId(plist));
}
finally {
closeQuietly(plist, hdf5_h::H5Pclose);
}
}
@Test
public void testH5Dwrite_read()
{
int[] writeData = new int[DIM_X * DIM_Y];
int[] readData = new int[DIM_X * DIM_Y];
// Initialize write data
for (int i = 0; i < writeData.length; i++) {
writeData[i] = i;
}
try (Arena arena = Arena.ofConfined()) {
// Allocate memory for write
MemorySegment writeSegment = allocateIntArray(arena, writeData.length);
copyToSegment(writeSegment, writeData);
// Write data
int writeResult = hdf5_h.H5Dwrite(H5did, hdf5_h.H5T_NATIVE_INT_g(), hdf5_h.H5S_ALL(),
hdf5_h.H5S_ALL(), hdf5_h.H5P_DEFAULT(), writeSegment);
assertTrue("H5Dwrite failed", isSuccess(writeResult));
// Allocate memory for read
MemorySegment readSegment = allocateIntArray(arena, readData.length);
// Read data
int readResult = hdf5_h.H5Dread(H5did, hdf5_h.H5T_NATIVE_INT_g(), hdf5_h.H5S_ALL(),
hdf5_h.H5S_ALL(), hdf5_h.H5P_DEFAULT(), readSegment);
assertTrue("H5Dread failed", isSuccess(readResult));
// Copy back to Java array
copyFromSegment(readSegment, readData);
// Verify data
assertArrayEquals("Data should match", writeData, readData);
}
}
@Test
public void testH5Dget_storage_size()
{
// Write some data first to allocate storage
int[] writeData = new int[DIM_X * DIM_Y];
for (int i = 0; i < writeData.length; i++) {
writeData[i] = i;
}
try (Arena arena = Arena.ofConfined()) {
MemorySegment writeSegment = allocateIntArray(arena, writeData.length);
copyToSegment(writeSegment, writeData);
int writeResult = hdf5_h.H5Dwrite(H5did, hdf5_h.H5T_NATIVE_INT_g(), hdf5_h.H5S_ALL(),
hdf5_h.H5S_ALL(), hdf5_h.H5P_DEFAULT(), writeSegment);
assertTrue("H5Dwrite failed", isSuccess(writeResult));
// Flush to ensure storage is allocated
hdf5_h.H5Fflush(H5fid, hdf5_h.H5F_SCOPE_LOCAL());
// Get storage size
long storageSize = hdf5_h.H5Dget_storage_size(H5did);
assertTrue("Storage size should be > 0", storageSize > 0);
}
}
@Test
public void testH5Dcreate_anon()
{
long anon_did = hdf5_h.H5I_INVALID_HID();
try {
// Create anonymous dataset
anon_did = hdf5_h.H5Dcreate_anon(H5fid, hdf5_h.H5T_NATIVE_INT_g(), H5dsid, hdf5_h.H5P_DEFAULT(),
hdf5_h.H5P_DEFAULT());
assertTrue("H5Dcreate_anon failed", isValidId(anon_did));
// Write some data to verify it works
int[] writeData = {1, 2, 3, 4};
try (Arena arena = Arena.ofConfined()) {
MemorySegment writeSegment = allocateIntArray(arena, writeData.length);
copyToSegment(writeSegment, writeData);
int writeResult = hdf5_h.H5Dwrite(anon_did, hdf5_h.H5T_NATIVE_INT_g(), hdf5_h.H5S_ALL(),
hdf5_h.H5S_ALL(), hdf5_h.H5P_DEFAULT(), writeSegment);
assertTrue("H5Dwrite to anonymous dataset failed", isSuccess(writeResult));
}
}
finally {
closeQuietly(anon_did, hdf5_h::H5Dclose);
}
}
@Test
public void testH5Dget_offset()
{
// Write some data first to ensure storage is allocated
int[] writeData = new int[DIM_X * DIM_Y];
for (int i = 0; i < writeData.length; i++) {
writeData[i] = i;
}
try (Arena arena = Arena.ofConfined()) {
MemorySegment writeSegment = allocateIntArray(arena, writeData.length);
copyToSegment(writeSegment, writeData);
int writeResult = hdf5_h.H5Dwrite(H5did, hdf5_h.H5T_NATIVE_INT_g(), hdf5_h.H5S_ALL(),
hdf5_h.H5S_ALL(), hdf5_h.H5P_DEFAULT(), writeSegment);
assertTrue("H5Dwrite failed", isSuccess(writeResult));
// Flush to ensure storage is allocated
hdf5_h.H5Fflush(H5fid, hdf5_h.H5F_SCOPE_LOCAL());
// Get dataset offset
long offset = hdf5_h.H5Dget_offset(H5did);
// For contiguous datasets, offset should be > 0
// For other layouts, it might return HADDR_UNDEF
// We just verify the call succeeds
assertTrue("H5Dget_offset should return valid value", offset >= 0 || offset == -1);
}
}
@Test
public void testH5Dwrite_readCompound()
{
long compound_tid = hdf5_h.H5I_INVALID_HID();
long compound_did = hdf5_h.H5I_INVALID_HID();
long compound_sid = hdf5_h.H5I_INVALID_HID();
try (Arena arena = Arena.ofConfined()) {
// Create compound type with int and double
// Note: double needs 8-byte alignment, so we pad the int to 8 bytes
int doubleOffset = 8; // Start double at 8-byte boundary
int compoundSize = 16; // 8 bytes for int (padded) + 8 bytes for double
compound_tid = hdf5_h.H5Tcreate(hdf5_h.H5T_COMPOUND(), compoundSize);
assertTrue("H5Tcreate compound failed", isValidId(compound_tid));
// Insert members with proper alignment
MemorySegment intNameSegment = stringToSegment(arena, "int_field");
int result = hdf5_h.H5Tinsert(compound_tid, intNameSegment, 0, hdf5_h.H5T_NATIVE_INT_g());
assertTrue("H5Tinsert int field failed", isSuccess(result));
MemorySegment doubleNameSegment = stringToSegment(arena, "double_field");
result =
hdf5_h.H5Tinsert(compound_tid, doubleNameSegment, doubleOffset, hdf5_h.H5T_NATIVE_DOUBLE_g());
assertTrue("H5Tinsert double field failed", isSuccess(result));
// Create dataspace for 4 compound elements
int nElements = 4;
long[] dims = {nElements};
MemorySegment dimsSegment = allocateLongArray(arena, 1);
copyToSegment(dimsSegment, dims);
compound_sid = hdf5_h.H5Screate_simple(1, dimsSegment, MemorySegment.NULL);
assertTrue("H5Screate_simple failed", isValidId(compound_sid));
// Create dataset
MemorySegment compoundDsetSegment = stringToSegment(arena, "compound_dset");
compound_did =
hdf5_h.H5Dcreate2(H5fid, compoundDsetSegment, compound_tid, compound_sid,
hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT());
assertTrue("H5Dcreate2 compound dataset failed", isValidId(compound_did));
// Write compound data with proper 8-byte alignment
MemorySegment writeSegment = arena.allocate(compoundSize * nElements, 8); // 8-byte aligned
for (int i = 0; i < nElements; i++) {
long offset = i * compoundSize;
writeSegment.set(ValueLayout.JAVA_INT, offset, i);
writeSegment.set(ValueLayout.JAVA_DOUBLE, offset + doubleOffset, i * 1.5);
}
int writeResult = hdf5_h.H5Dwrite(compound_did, compound_tid, hdf5_h.H5S_ALL(), hdf5_h.H5S_ALL(),
hdf5_h.H5P_DEFAULT(), writeSegment);
assertTrue("H5Dwrite compound failed", isSuccess(writeResult));
// Read compound data
MemorySegment readSegment = arena.allocate(compoundSize * nElements, 8); // 8-byte aligned
int readResult = hdf5_h.H5Dread(compound_did, compound_tid, hdf5_h.H5S_ALL(), hdf5_h.H5S_ALL(),
hdf5_h.H5P_DEFAULT(), readSegment);
assertTrue("H5Dread compound failed", isSuccess(readResult));
// Verify data
for (int i = 0; i < nElements; i++) {
long offset = i * compoundSize;
int intValue = readSegment.get(ValueLayout.JAVA_INT, offset);
double doubleValue = readSegment.get(ValueLayout.JAVA_DOUBLE, offset + doubleOffset);
assertEquals("Int field should match", i, intValue);
assertEquals("Double field should match", i * 1.5, doubleValue, 0.0001);
}
}
finally {
closeQuietly(compound_did, hdf5_h::H5Dclose);
closeQuietly(compound_sid, hdf5_h::H5Sclose);
closeQuietly(compound_tid, hdf5_h::H5Tclose);
}
}
@Test
public void testH5DArraywr()
{
long array_tid = hdf5_h.H5I_INVALID_HID();
long array_did = hdf5_h.H5I_INVALID_HID();
long array_sid = hdf5_h.H5I_INVALID_HID();
try (Arena arena = Arena.ofConfined()) {
// Create array datatype: int[3][2]
int arrayRank = 2;
long[] arrayDims = {3, 2};
MemorySegment arrayDimsSegment = allocateLongArray(arena, arrayRank);
copyToSegment(arrayDimsSegment, arrayDims);
array_tid = hdf5_h.H5Tarray_create2(hdf5_h.H5T_NATIVE_INT_g(), arrayRank, arrayDimsSegment);
assertTrue("H5Tarray_create2 failed", isValidId(array_tid));
// Create dataspace for 2 array elements
int nElements = 2;
long[] dims = {nElements};
MemorySegment dimsSegment = allocateLongArray(arena, 1);
copyToSegment(dimsSegment, dims);
array_sid = hdf5_h.H5Screate_simple(1, dimsSegment, MemorySegment.NULL);
assertTrue("H5Screate_simple failed", isValidId(array_sid));
// Create dataset
MemorySegment arrayDsetSegment = stringToSegment(arena, "array_dset");
array_did = hdf5_h.H5Dcreate2(H5fid, arrayDsetSegment, array_tid, array_sid, hdf5_h.H5P_DEFAULT(),
hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT());
assertTrue("H5Dcreate2 array dataset failed", isValidId(array_did));
// Write array data: 2 elements, each is int[3][2]
int arraySize = 3 * 2;
int totalSize = nElements * arraySize;
int[] writeData = new int[totalSize];
for (int i = 0; i < totalSize; i++) {
writeData[i] = i;
}
MemorySegment writeSegment = allocateIntArray(arena, totalSize);
copyToSegment(writeSegment, writeData);
int writeResult = hdf5_h.H5Dwrite(array_did, array_tid, hdf5_h.H5S_ALL(), hdf5_h.H5S_ALL(),
hdf5_h.H5P_DEFAULT(), writeSegment);
assertTrue("H5Dwrite array failed", isSuccess(writeResult));
// Read array data
int[] readData = new int[totalSize];
MemorySegment readSegment = allocateIntArray(arena, totalSize);
int readResult = hdf5_h.H5Dread(array_did, array_tid, hdf5_h.H5S_ALL(), hdf5_h.H5S_ALL(),
hdf5_h.H5P_DEFAULT(), readSegment);
assertTrue("H5Dread array failed", isSuccess(readResult));
copyFromSegment(readSegment, readData);
// Verify data
assertArrayEquals("Array data should match", writeData, readData);
}
finally {
closeQuietly(array_did, hdf5_h::H5Dclose);
closeQuietly(array_sid, hdf5_h::H5Sclose);
closeQuietly(array_tid, hdf5_h::H5Tclose);
}
}
@Test
public void testH5Dvlen_write_read()
{
long vlen_tid = hdf5_h.H5I_INVALID_HID();
long vlen_did = hdf5_h.H5I_INVALID_HID();
long vlen_sid = hdf5_h.H5I_INVALID_HID();
try (Arena arena = Arena.ofConfined()) {
// Create variable-length datatype
vlen_tid = hdf5_h.H5Tvlen_create(hdf5_h.H5T_NATIVE_INT_g());
assertTrue("H5Tvlen_create failed", isValidId(vlen_tid));
// Create dataspace for 2 VL elements
int nElements = 2;
long[] dims = {nElements};
MemorySegment dimsSegment = allocateLongArray(arena, 1);
copyToSegment(dimsSegment, dims);
vlen_sid = hdf5_h.H5Screate_simple(1, dimsSegment, MemorySegment.NULL);
assertTrue("H5Screate_simple failed", isValidId(vlen_sid));
// Create dataset
MemorySegment vlenDsetSegment = stringToSegment(arena, "vlen_dset");
vlen_did = hdf5_h.H5Dcreate2(H5fid, vlenDsetSegment, vlen_tid, vlen_sid, hdf5_h.H5P_DEFAULT(),
hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT());
assertTrue("H5Dcreate2 vlen dataset failed", isValidId(vlen_did));
// Note: Full VL write/read requires hvl_t struct manipulation which is complex in FFM
// This test verifies the dataset creation and basic API calls work
// Full VL data I/O would need hvl_t struct support from FfmTestSupport
// Verify we can get the datatype back
long retrieved_tid = hdf5_h.H5Dget_type(vlen_did);
assertTrue("H5Dget_type should succeed", isValidId(retrieved_tid));
// Verify it's a variable-length type
int tclass = hdf5_h.H5Tget_class(retrieved_tid);
assertEquals("Type class should be VLEN", hdf5_h.H5T_VLEN(), tclass);
closeQuietly(retrieved_tid, hdf5_h::H5Tclose);
}
finally {
closeQuietly(vlen_did, hdf5_h::H5Dclose);
closeQuietly(vlen_sid, hdf5_h::H5Sclose);
closeQuietly(vlen_tid, hdf5_h::H5Tclose);
}
}
@Test
public void testH5Dclose()
{
long did = hdf5_h.H5I_INVALID_HID();
try (Arena arena = Arena.ofConfined()) {
MemorySegment dsetNameSegment = stringToSegment(arena, DATASET_NAME);
did = hdf5_h.H5Dopen2(H5fid, dsetNameSegment, hdf5_h.H5P_DEFAULT());
assertTrue("H5Dopen2 failed", isValidId(did));
int result = hdf5_h.H5Dclose(did);
assertTrue("H5Dclose failed", isSuccess(result));
did = hdf5_h.H5I_INVALID_HID();
}
}
@Test
public void testH5Dget_num_chunks_rw()
{
System.out.print(testname.getMethodName());
long chunked_dcpl = hdf5_h.H5I_INVALID_HID();
long chunked_sid = hdf5_h.H5I_INVALID_HID();
long chunked_did = hdf5_h.H5I_INVALID_HID();
try (Arena arena = Arena.ofConfined()) {
// Create chunked dataset creation property list
chunked_dcpl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_DATASET_CREATE_ID_g());
assertTrue("H5Pcreate failed", isValidId(chunked_dcpl));
// Set chunk dimensions: 2x3 chunks
long[] chunkDims = {2, 3};
MemorySegment chunkDimsSegment = allocateLongArray(arena, RANK);
copyToSegment(chunkDimsSegment, chunkDims);
int result = hdf5_h.H5Pset_chunk(chunked_dcpl, RANK, chunkDimsSegment);
assertTrue("H5Pset_chunk failed", isSuccess(result));
// Create dataspace for chunked dataset: 4x6
long[] dims = {4, 6};
MemorySegment dimsSegment = allocateLongArray(arena, RANK);
copyToSegment(dimsSegment, dims);
chunked_sid = hdf5_h.H5Screate_simple(RANK, dimsSegment, MemorySegment.NULL);
assertTrue("H5Screate_simple failed", isValidId(chunked_sid));
// Create chunked dataset
MemorySegment dsetNameSegment = stringToSegment(arena, "chunked_dset");
chunked_did = hdf5_h.H5Dcreate2(H5fid, dsetNameSegment, hdf5_h.H5T_NATIVE_INT_g(), chunked_sid,
hdf5_h.H5P_DEFAULT(), chunked_dcpl, hdf5_h.H5P_DEFAULT());
assertTrue("H5Dcreate2 failed", isValidId(chunked_did));
// Write data to create chunks
int[] writeData = new int[DIM_X * DIM_Y];
for (int i = 0; i < writeData.length; i++) {
writeData[i] = i;
}
MemorySegment writeSegment = allocateIntArray(arena, writeData.length);
copyToSegment(writeSegment, writeData);
result = hdf5_h.H5Dwrite(chunked_did, hdf5_h.H5T_NATIVE_INT_g(), hdf5_h.H5S_ALL(),
hdf5_h.H5S_ALL(), hdf5_h.H5P_DEFAULT(), writeSegment);
assertTrue("H5Dwrite failed", isSuccess(result));
// Get number of chunks (should be 4 chunks: (4/2) * (6/3) = 2 * 2 = 4)
MemorySegment nchunksSegment = allocateLong(arena);
result = hdf5_h.H5Dget_num_chunks(chunked_did, chunked_sid, nchunksSegment);
assertTrue("H5Dget_num_chunks failed", isSuccess(result));
long nchunks = getLong(nchunksSegment);
assertEquals("Should have 4 chunks", 4L, nchunks);
}
finally {
closeQuietly(chunked_did, hdf5_h::H5Dclose);
closeQuietly(chunked_sid, hdf5_h::H5Sclose);
closeQuietly(chunked_dcpl, hdf5_h::H5Pclose);
}
}
@Test
public void testH5Dget_chunk_storage_size()
{
System.out.print(testname.getMethodName());
long chunked_dcpl = hdf5_h.H5I_INVALID_HID();
long chunked_sid = hdf5_h.H5I_INVALID_HID();
long chunked_did = hdf5_h.H5I_INVALID_HID();
try (Arena arena = Arena.ofConfined()) {
// Create chunked dataset creation property list
chunked_dcpl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_DATASET_CREATE_ID_g());
assertTrue("H5Pcreate failed", isValidId(chunked_dcpl));
// Set chunk dimensions: 2x3 chunks
long[] chunkDims = {2, 3};
MemorySegment chunkDimsSegment = allocateLongArray(arena, RANK);
copyToSegment(chunkDimsSegment, chunkDims);
int result = hdf5_h.H5Pset_chunk(chunked_dcpl, RANK, chunkDimsSegment);
assertTrue("H5Pset_chunk failed", isSuccess(result));
// Create dataspace for chunked dataset: 4x6
long[] dims = {4, 6};
MemorySegment dimsSegment = allocateLongArray(arena, RANK);
copyToSegment(dimsSegment, dims);
chunked_sid = hdf5_h.H5Screate_simple(RANK, dimsSegment, MemorySegment.NULL);
assertTrue("H5Screate_simple failed", isValidId(chunked_sid));
// Create chunked dataset
MemorySegment dsetNameSegment = stringToSegment(arena, "chunked_dset2");
chunked_did = hdf5_h.H5Dcreate2(H5fid, dsetNameSegment, hdf5_h.H5T_NATIVE_INT_g(), chunked_sid,
hdf5_h.H5P_DEFAULT(), chunked_dcpl, hdf5_h.H5P_DEFAULT());
assertTrue("H5Dcreate2 failed", isValidId(chunked_did));
// Write data to fill first chunk
int[] writeData = new int[DIM_X * DIM_Y];
for (int i = 0; i < writeData.length; i++) {
writeData[i] = i;
}
MemorySegment writeSegment = allocateIntArray(arena, writeData.length);
copyToSegment(writeSegment, writeData);
result = hdf5_h.H5Dwrite(chunked_did, hdf5_h.H5T_NATIVE_INT_g(), hdf5_h.H5S_ALL(),
hdf5_h.H5S_ALL(), hdf5_h.H5P_DEFAULT(), writeSegment);
assertTrue("H5Dwrite failed", isSuccess(result));
// Get chunk storage size for first chunk (offset [0,0])
long[] offset = {0, 0};
MemorySegment offsetSegment = allocateLongArray(arena, RANK);
copyToSegment(offsetSegment, offset);
MemorySegment sizeSegment = allocateLong(arena);
result = hdf5_h.H5Dget_chunk_storage_size(chunked_did, offsetSegment, sizeSegment);
assertTrue("H5Dget_chunk_storage_size failed", isSuccess(result));
long chunkSize = getLong(sizeSegment);
assertTrue("Chunk size should be > 0", chunkSize > 0);
}
finally {
closeQuietly(chunked_did, hdf5_h::H5Dclose);
closeQuietly(chunked_sid, hdf5_h::H5Sclose);
closeQuietly(chunked_dcpl, hdf5_h::H5Pclose);
}
}
@Test
public void testH5Dset_extent()
{
System.out.print(testname.getMethodName());
long chunked_dcpl = hdf5_h.H5I_INVALID_HID();
long chunked_sid = hdf5_h.H5I_INVALID_HID();
long chunked_did = hdf5_h.H5I_INVALID_HID();
try (Arena arena = Arena.ofConfined()) {
// Create chunked dataset creation property list
chunked_dcpl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_DATASET_CREATE_ID_g());
assertTrue("H5Pcreate failed", isValidId(chunked_dcpl));
// Set chunk dimensions: 2x3 chunks
long[] chunkDims = {2, 3};
MemorySegment chunkDimsSegment = allocateLongArray(arena, RANK);
copyToSegment(chunkDimsSegment, chunkDims);
int result = hdf5_h.H5Pset_chunk(chunked_dcpl, RANK, chunkDimsSegment);
assertTrue("H5Pset_chunk failed", isSuccess(result));
// Create dataspace with unlimited max dimensions
long[] dims = {4, 6};
long[] maxDims = {-1, -1}; // H5S_UNLIMITED for both dimensions
MemorySegment dimsSegment = allocateLongArray(arena, RANK);
MemorySegment maxDimsSegment = allocateLongArray(arena, RANK);
copyToSegment(dimsSegment, dims);
copyToSegment(maxDimsSegment, maxDims);
chunked_sid = hdf5_h.H5Screate_simple(RANK, dimsSegment, maxDimsSegment);
assertTrue("H5Screate_simple failed", isValidId(chunked_sid));
// Create extensible chunked dataset
MemorySegment dsetNameSegment = stringToSegment(arena, "extensible_dset");
chunked_did = hdf5_h.H5Dcreate2(H5fid, dsetNameSegment, hdf5_h.H5T_NATIVE_INT_g(), chunked_sid,
hdf5_h.H5P_DEFAULT(), chunked_dcpl, hdf5_h.H5P_DEFAULT());
assertTrue("H5Dcreate2 failed", isValidId(chunked_did));
// Extend dataset to 8x12
long[] newDims = {8, 12};
MemorySegment newDimsSegment = allocateLongArray(arena, RANK);
copyToSegment(newDimsSegment, newDims);
result = hdf5_h.H5Dset_extent(chunked_did, newDimsSegment);
assertTrue("H5Dset_extent failed", isSuccess(result));
// Verify new dimensions
long space_id = hdf5_h.H5Dget_space(chunked_did);
assertTrue("H5Dget_space failed", isValidId(space_id));
MemorySegment verifyDimsSegment = allocateLongArray(arena, RANK);
int ndims = hdf5_h.H5Sget_simple_extent_dims(space_id, verifyDimsSegment, MemorySegment.NULL);
assertEquals("Rank should be 2", RANK, ndims);
long[] verifyDims = new long[RANK];
copyFromSegment(verifyDimsSegment, verifyDims);
assertEquals("First dimension should be 8", 8, verifyDims[0]);
assertEquals("Second dimension should be 12", 12, verifyDims[1]);
closeQuietly(space_id, hdf5_h::H5Sclose);
}
finally {
closeQuietly(chunked_did, hdf5_h::H5Dclose);
closeQuietly(chunked_sid, hdf5_h::H5Sclose);
closeQuietly(chunked_dcpl, hdf5_h::H5Pclose);
}
}
@Test
public void testH5DArrayenum_rw()
{
long enum_tid = hdf5_h.H5I_INVALID_HID();
long array_tid = hdf5_h.H5I_INVALID_HID();
long array_did = hdf5_h.H5I_INVALID_HID();
long array_sid = hdf5_h.H5I_INVALID_HID();
try (Arena arena = Arena.ofConfined()) {
// Create enum type
enum_tid = hdf5_h.H5Tenum_create(hdf5_h.H5T_NATIVE_INT_g());
assertTrue("H5Tenum_create failed", isValidId(enum_tid));
// Insert enum values
MemorySegment redSegment = stringToSegment(arena, "RED");
MemorySegment redValueSegment = allocateInt(arena);
setInt(redValueSegment, 0);
int result = hdf5_h.H5Tenum_insert(enum_tid, redSegment, redValueSegment);
assertTrue("H5Tenum_insert RED failed", isSuccess(result));
MemorySegment greenSegment = stringToSegment(arena, "GREEN");
MemorySegment greenValueSegment = allocateInt(arena);
setInt(greenValueSegment, 1);
result = hdf5_h.H5Tenum_insert(enum_tid, greenSegment, greenValueSegment);
assertTrue("H5Tenum_insert GREEN failed", isSuccess(result));
MemorySegment blueSegment = stringToSegment(arena, "BLUE");
MemorySegment blueValueSegment = allocateInt(arena);
setInt(blueValueSegment, 2);
result = hdf5_h.H5Tenum_insert(enum_tid, blueSegment, blueValueSegment);
assertTrue("H5Tenum_insert BLUE failed", isSuccess(result));
// Create array of enum: [3]
long[] arrayDims = {3};
MemorySegment arrayDimsSegment = allocateLongArray(arena, 1);
copyToSegment(arrayDimsSegment, arrayDims);
array_tid = hdf5_h.H5Tarray_create2(enum_tid, 1, arrayDimsSegment);
assertTrue("H5Tarray_create2 failed", isValidId(array_tid));
// Create dataspace for 2 array elements
long[] dims = {2};
MemorySegment dimsSegment = allocateLongArray(arena, 1);
copyToSegment(dimsSegment, dims);
array_sid = hdf5_h.H5Screate_simple(1, dimsSegment, MemorySegment.NULL);
assertTrue("H5Screate_simple failed", isValidId(array_sid));
// Create dataset
MemorySegment arrayEnumDsetSegment = stringToSegment(arena, "array_enum_dset");
array_did = hdf5_h.H5Dcreate2(H5fid, arrayEnumDsetSegment, array_tid, array_sid,
hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT());
assertTrue("H5Dcreate2 array enum failed", isValidId(array_did));
// Write array of enum data: [[0,1,2], [2,1,0]]
int[] writeData = {0, 1, 2, 2, 1, 0};
MemorySegment writeSegment = allocateIntArray(arena, writeData.length);
copyToSegment(writeSegment, writeData);
result = hdf5_h.H5Dwrite(array_did, array_tid, hdf5_h.H5S_ALL(), hdf5_h.H5S_ALL(),
hdf5_h.H5P_DEFAULT(), writeSegment);
assertTrue("H5Dwrite array enum failed", isSuccess(result));
// Read array of enum data
int[] readData = new int[writeData.length];
MemorySegment readSegment = allocateIntArray(arena, readData.length);
result = hdf5_h.H5Dread(array_did, array_tid, hdf5_h.H5S_ALL(), hdf5_h.H5S_ALL(),
hdf5_h.H5P_DEFAULT(), readSegment);
assertTrue("H5Dread array enum failed", isSuccess(result));
copyFromSegment(readSegment, readData);
// Verify data
assertArrayEquals("Array enum data should match", writeData, readData);
}
finally {
closeQuietly(array_did, hdf5_h::H5Dclose);
closeQuietly(array_sid, hdf5_h::H5Sclose);
closeQuietly(array_tid, hdf5_h::H5Tclose);
closeQuietly(enum_tid, hdf5_h::H5Tclose);
}
}
@Test
public void testH5Dfill()
{
try (Arena arena = Arena.ofConfined()) {
// Create a buffer and fill it with a value
int fillValue = 42;
MemorySegment fillSegment = allocateInt(arena);
setInt(fillSegment, fillValue);
MemorySegment bufferSegment = allocateIntArray(arena, DIM_X * DIM_Y);
int result = hdf5_h.H5Dfill(fillSegment, hdf5_h.H5T_NATIVE_INT_g(), bufferSegment,
hdf5_h.H5T_NATIVE_INT_g(), H5dsid);
assertTrue("H5Dfill failed", isSuccess(result));
// Verify buffer is filled
int[] buffer = new int[DIM_X * DIM_Y];
copyFromSegment(bufferSegment, buffer);
for (int value : buffer) {
assertEquals("All values should be fill value", fillValue, value);
}
}
}
@Test
public void testH5Dget_chunk_info()
{
System.out.print(testname.getMethodName());
long chunked_dcpl = hdf5_h.H5I_INVALID_HID();
long chunked_sid = hdf5_h.H5I_INVALID_HID();
long chunked_did = hdf5_h.H5I_INVALID_HID();
try (Arena arena = Arena.ofConfined()) {
// Create chunked dataset creation property list
chunked_dcpl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_DATASET_CREATE_ID_g());
assertTrue("H5Pcreate failed", isValidId(chunked_dcpl));
// Set chunk dimensions: 2x3 chunks
long[] chunkDims = {2, 3};
MemorySegment chunkDimsSegment = allocateLongArray(arena, RANK);
copyToSegment(chunkDimsSegment, chunkDims);
int result = hdf5_h.H5Pset_chunk(chunked_dcpl, RANK, chunkDimsSegment);
assertTrue("H5Pset_chunk failed", isSuccess(result));
// Create dataspace for chunked dataset: 4x6
long[] dims = {4, 6};
MemorySegment dimsSegment = allocateLongArray(arena, RANK);
copyToSegment(dimsSegment, dims);
chunked_sid = hdf5_h.H5Screate_simple(RANK, dimsSegment, MemorySegment.NULL);
assertTrue("H5Screate_simple failed", isValidId(chunked_sid));
// Create chunked dataset
MemorySegment dsetNameSegment = stringToSegment(arena, "chunked_info");
chunked_did = hdf5_h.H5Dcreate2(H5fid, dsetNameSegment, hdf5_h.H5T_NATIVE_INT_g(), chunked_sid,
hdf5_h.H5P_DEFAULT(), chunked_dcpl, hdf5_h.H5P_DEFAULT());
assertTrue("H5Dcreate2 failed", isValidId(chunked_did));
// Write data to create chunks
int[] writeData = new int[DIM_X * DIM_Y];
for (int i = 0; i < writeData.length; i++) {
writeData[i] = i;
}
MemorySegment writeSegment = allocateIntArray(arena, writeData.length);
copyToSegment(writeSegment, writeData);
result = hdf5_h.H5Dwrite(chunked_did, hdf5_h.H5T_NATIVE_INT_g(), hdf5_h.H5S_ALL(),
hdf5_h.H5S_ALL(), hdf5_h.H5P_DEFAULT(), writeSegment);
assertTrue("H5Dwrite failed", isSuccess(result));
// Get chunk info for first chunk (index 0)
MemorySegment offsetSegment = allocateLongArray(arena, RANK);
MemorySegment filterMaskSegment = allocateInt(arena);
MemorySegment addrSegment = allocateLong(arena);
MemorySegment sizeSegment = allocateLong(arena);
result = hdf5_h.H5Dget_chunk_info(chunked_did, chunked_sid, 0, offsetSegment, filterMaskSegment,
addrSegment, sizeSegment);
assertTrue("H5Dget_chunk_info failed", isSuccess(result));
// Verify we got valid chunk information
long chunkSize = getLong(sizeSegment);
assertTrue("Chunk size should be > 0", chunkSize > 0);
long[] offset = new long[RANK];
copyFromSegment(offsetSegment, offset);
// First chunk should start at [0, 0]
assertEquals("First chunk offset[0] should be 0", 0L, offset[0]);
assertEquals("First chunk offset[1] should be 0", 0L, offset[1]);
}
finally {
closeQuietly(chunked_did, hdf5_h::H5Dclose);
closeQuietly(chunked_sid, hdf5_h::H5Sclose);
closeQuietly(chunked_dcpl, hdf5_h::H5Pclose);
}
}
@Test
public void testH5Dget_chunk_info_by_coord()
{
System.out.print(testname.getMethodName());
long chunked_dcpl = hdf5_h.H5I_INVALID_HID();
long chunked_sid = hdf5_h.H5I_INVALID_HID();
long chunked_did = hdf5_h.H5I_INVALID_HID();
try (Arena arena = Arena.ofConfined()) {
// Create chunked dataset creation property list
chunked_dcpl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_DATASET_CREATE_ID_g());
assertTrue("H5Pcreate failed", isValidId(chunked_dcpl));
// Set chunk dimensions: 2x3 chunks
long[] chunkDims = {2, 3};
MemorySegment chunkDimsSegment = allocateLongArray(arena, RANK);
copyToSegment(chunkDimsSegment, chunkDims);
int result = hdf5_h.H5Pset_chunk(chunked_dcpl, RANK, chunkDimsSegment);
assertTrue("H5Pset_chunk failed", isSuccess(result));
// Create dataspace for chunked dataset: 4x6
long[] dims = {4, 6};
MemorySegment dimsSegment = allocateLongArray(arena, RANK);
copyToSegment(dimsSegment, dims);
chunked_sid = hdf5_h.H5Screate_simple(RANK, dimsSegment, MemorySegment.NULL);
assertTrue("H5Screate_simple failed", isValidId(chunked_sid));
// Create chunked dataset
MemorySegment dsetNameSegment = stringToSegment(arena, "chunked_by_coord");
chunked_did = hdf5_h.H5Dcreate2(H5fid, dsetNameSegment, hdf5_h.H5T_NATIVE_INT_g(), chunked_sid,
hdf5_h.H5P_DEFAULT(), chunked_dcpl, hdf5_h.H5P_DEFAULT());
assertTrue("H5Dcreate2 failed", isValidId(chunked_did));
// Write data to create chunks
int[] writeData = new int[DIM_X * DIM_Y];
for (int i = 0; i < writeData.length; i++) {
writeData[i] = i;
}
MemorySegment writeSegment = allocateIntArray(arena, writeData.length);
copyToSegment(writeSegment, writeData);
result = hdf5_h.H5Dwrite(chunked_did, hdf5_h.H5T_NATIVE_INT_g(), hdf5_h.H5S_ALL(),
hdf5_h.H5S_ALL(), hdf5_h.H5P_DEFAULT(), writeSegment);
assertTrue("H5Dwrite failed", isSuccess(result));
// Get chunk info for chunk at coordinates [2, 3]
long[] offset = {2, 3};
MemorySegment offsetSegment = allocateLongArray(arena, RANK);
copyToSegment(offsetSegment, offset);
MemorySegment filterMaskSegment = allocateInt(arena);
MemorySegment addrSegment = allocateLong(arena);
MemorySegment sizeSegment = allocateLong(arena);
result = hdf5_h.H5Dget_chunk_info_by_coord(chunked_did, offsetSegment, filterMaskSegment,
addrSegment, sizeSegment);
assertTrue("H5Dget_chunk_info_by_coord failed", isSuccess(result));
// Verify we got valid chunk information
long chunkSize = getLong(sizeSegment);
assertTrue("Chunk size should be > 0", chunkSize > 0);
}
finally {
closeQuietly(chunked_did, hdf5_h::H5Dclose);
closeQuietly(chunked_sid, hdf5_h::H5Sclose);
closeQuietly(chunked_dcpl, hdf5_h::H5Pclose);
}
}
@Test
public void testH5Drefresh()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Refresh the dataset metadata
int result = hdf5_h.H5Drefresh(H5did);
assertTrue("H5Drefresh failed", isSuccess(result));
// Verify dataset is still valid after refresh
long type_id = hdf5_h.H5Dget_type(H5did);
assertTrue("H5Dget_type should succeed after refresh", isValidId(type_id));
hdf5_h.H5Tclose(type_id);
}
}
@Test
public void testH5Dvlen_get_buf_size()
{
System.out.print(testname.getMethodName());
long vlen_tid = hdf5_h.H5I_INVALID_HID();
long vlen_sid = hdf5_h.H5I_INVALID_HID();
long vlen_did = hdf5_h.H5I_INVALID_HID();
try (Arena arena = Arena.ofConfined()) {
// Create variable-length integer datatype
vlen_tid = hdf5_h.H5Tvlen_create(hdf5_h.H5T_NATIVE_INT_g());
assertTrue("H5Tvlen_create failed", isValidId(vlen_tid));
// Create simple 1D dataspace
long[] dims = {3};
MemorySegment dimsSegment = allocateLongArray(arena, 1);
dimsSegment.setAtIndex(ValueLayout.JAVA_LONG, 0, dims[0]);
vlen_sid = hdf5_h.H5Screate_simple(1, dimsSegment, MemorySegment.NULL);
assertTrue("H5Screate_simple failed", isValidId(vlen_sid));
// Create dataset
MemorySegment dsetName = stringToSegment(arena, "vlen_bufsize");
vlen_did = hdf5_h.H5Dcreate2(H5fid, dsetName, vlen_tid, vlen_sid, hdf5_h.H5P_DEFAULT(),
hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT());
assertTrue("H5Dcreate2 failed", isValidId(vlen_did));
// Note: In FFM, we can test that the function exists and returns successfully
// Full VL data writing/reading is complex in FFM and tested separately
MemorySegment sizeSegment = allocateLong(arena);
int result = hdf5_h.H5Dvlen_get_buf_size(vlen_did, vlen_tid, vlen_sid, sizeSegment);
assertTrue("H5Dvlen_get_buf_size should succeed", isSuccess(result));
long bufSize = getLong(sizeSegment);
assertEquals("Buffer size should be 0 for empty VL dataset", 0L, bufSize);
}
finally {
closeQuietly(vlen_did, hdf5_h::H5Dclose);
closeQuietly(vlen_sid, hdf5_h::H5Sclose);
closeQuietly(vlen_tid, hdf5_h::H5Tclose);
}
}
@Test
public void testH5Dget_space_type()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
MemorySegment dsetname = stringToSegment(arena, "/dset");
long did = hdf5_h.H5Dopen2(H5fid, dsetname, hdf5_h.H5P_DEFAULT());
assertTrue("H5Dopen2 failed", isValidId(did));
// Get dataspace
long sid = hdf5_h.H5Dget_space(did);
assertTrue("H5Dget_space failed", isValidId(sid));
// Get datatype
long tid = hdf5_h.H5Dget_type(did);
assertTrue("H5Dget_type failed", isValidId(tid));
hdf5_h.H5Tclose(tid);
hdf5_h.H5Sclose(sid);
hdf5_h.H5Dclose(did);
}
}
@Test
public void testH5Dget_space_status()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
MemorySegment dsetname = stringToSegment(arena, "/dset");
long did = hdf5_h.H5Dopen2(H5fid, dsetname, hdf5_h.H5P_DEFAULT());
assertTrue("H5Dopen2 failed", isValidId(did));
MemorySegment status = allocateIntArray(arena, 1);
int result = hdf5_h.H5Dget_space_status(did, status);
assertTrue("H5Dget_space_status failed", isSuccess(result));
int statusValue = getInt(status);
assertTrue("Status should be valid", statusValue >= 0);
hdf5_h.H5Dclose(did);
}
}
@Test
public void testH5Dget_chunk_index_type()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Create chunked dataset
long[] dims = {10, 10};
long[] chunk_dims = {5, 5};
MemorySegment dimsSegment = allocateLongArray(arena, 2);
MemorySegment chunkSegment = allocateLongArray(arena, 2);
copyToSegment(dimsSegment, dims);
copyToSegment(chunkSegment, chunk_dims);
long sid = hdf5_h.H5Screate_simple(2, dimsSegment, MemorySegment.NULL);
assertTrue("H5Screate_simple failed", isValidId(sid));
long dcpl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_DATASET_CREATE_ID_g());
hdf5_h.H5Pset_chunk(dcpl, 2, chunkSegment);
MemorySegment dsetname = stringToSegment(arena, "/chunked_ds");
long did = hdf5_h.H5Dcreate2(H5fid, dsetname, hdf5_h.H5T_NATIVE_INT_g(), sid,
hdf5_h.H5P_DEFAULT(), dcpl, hdf5_h.H5P_DEFAULT());
assertTrue("H5Dcreate2 failed", isValidId(did));
// Get chunk index type
MemorySegment indexType = allocateIntArray(arena, 1);
int result = hdf5_h.H5Dget_chunk_index_type(did, indexType);
assertTrue("H5Dget_chunk_index_type failed", isSuccess(result));
hdf5_h.H5Dclose(did);
hdf5_h.H5Pclose(dcpl);
hdf5_h.H5Sclose(sid);
}
}
@Test
public void testH5Dget_num_chunks()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Open existing dataset
MemorySegment dsetname = stringToSegment(arena, "/dset");
long did = hdf5_h.H5Dopen2(H5fid, dsetname, hdf5_h.H5P_DEFAULT());
assertTrue("H5Dopen2 failed", isValidId(did));
long sid = hdf5_h.H5Dget_space(did);
MemorySegment numChunks = allocateLongArray(arena, 1);
int result = hdf5_h.H5Dget_num_chunks(did, sid, numChunks);
// This may fail if dataset is not chunked, which is okay
if (isSuccess(result)) {
long count = getLong(numChunks);
assertTrue("Chunk count should be >= 0", count >= 0);
}
hdf5_h.H5Sclose(sid);
hdf5_h.H5Dclose(did);
}
}
@Test
public void testH5Dflush_refresh()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
MemorySegment dsetname = stringToSegment(arena, "/dset");
long did = hdf5_h.H5Dopen2(H5fid, dsetname, hdf5_h.H5P_DEFAULT());
assertTrue("H5Dopen2 failed", isValidId(did));
// Flush dataset
int result = hdf5_h.H5Dflush(did);
assertTrue("H5Dflush failed", isSuccess(result));
// Refresh dataset
result = hdf5_h.H5Drefresh(did);
assertTrue("H5Drefresh failed", isSuccess(result));
hdf5_h.H5Dclose(did);
}
}
}