001/***************************************************************************** 002 * Copyright by The HDF Group. * 003 * Copyright by the Board of Trustees of the University of Illinois. * 004 * All rights reserved. * 005 * * 006 * This file is part of the HDF Java Products distribution. * 007 * The full copyright notice, including terms governing use, modification, * 008 * and redistribution, is contained in the files COPYING and Copyright.html. * 009 * COPYING can be found at the root of the source code distribution tree. * 010 * Or, see https://support.hdfgroup.org/products/licenses.html * 011 * If you do not have access to either file, you may request a copy from * 012 * help@hdfgroup.org. * 013 ****************************************************************************/ 014 015package hdf.object.h5; 016 017import hdf.hdf5lib.H5; 018import hdf.hdf5lib.HDF5Constants; 019import hdf.hdf5lib.exceptions.HDF5Exception; 020 021/** HDF5 utility class */ 022public final class H5Utils { 023 024 private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(H5Utils.class); 025 026 /** 027 * Set up a hyperslab selection within a dataset. 028 * 029 * @param did 030 * IN dataset ID 031 * @param dsetDims 032 * IN dimensions 033 * @param startDims 034 * IN start dimensions 035 * @param selectedStride 036 * IN selected stride values 037 * @param selectedDims 038 * IN selected dimensions 039 * @param spaceIDs 040 * IN/OUT memory and file space IDs -- spaceIDs[0]=mspace, spaceIDs[1]=fspace 041 * 042 * @return total number of data points selected 043 * 044 * @throws HDF5Exception 045 * If there is an error at the HDF5 library level. 046 */ 047 public static final long selectHyperslab(long did, long[] dsetDims, long[] startDims, long[] selectedStride, 048 long[] selectedDims, long[] spaceIDs) throws HDF5Exception { 049 if (dsetDims == null) { 050 log.debug("selectHyperslab(): dsetDims is null"); 051 return -1; 052 } 053 054 int rank = dsetDims.length; 055 if ((startDims != null) && (startDims.length != rank)) { 056 log.debug("selectHyperslab(): startDims rank didn't match dsetDims rank"); 057 return -1; 058 } 059 if ((selectedStride != null) && (selectedStride.length != rank)) { 060 log.debug("selectHyperslab(): selectedStride rank didn't match startDims rank"); 061 return -1; 062 } 063 if ((selectedDims != null) && (selectedDims.length != rank)) { 064 log.debug("selectHyperslab(): selectedDims rank didn't match startDims rank"); 065 return -1; 066 } 067 068 long lsize = 1; 069 070 boolean isAllSelected = true; 071 for (int i = 0; i < rank; i++) { 072 if (selectedDims != null) { 073 lsize *= selectedDims[i]; 074 if (selectedDims[i] < dsetDims[i]) 075 isAllSelected = false; 076 } 077 } 078 079 log.trace("selectHyperslab(): isAllSelected={}", isAllSelected); 080 081 if (isAllSelected) { 082 spaceIDs[0] = HDF5Constants.H5S_ALL; 083 spaceIDs[1] = HDF5Constants.H5S_ALL; 084 } 085 else { 086 spaceIDs[1] = H5.H5Dget_space(did); 087 088 // When a 1D dataspace is used for a chunked dataset, reading is very slow. 089 // 090 // It is a known problem within the HDF5 library. 091 // mspace = H5.H5Screate_simple(1, lsize, null); 092 spaceIDs[0] = H5.H5Screate_simple(rank, selectedDims, null); 093 H5.H5Sselect_hyperslab(spaceIDs[1], HDF5Constants.H5S_SELECT_SET, startDims, selectedStride, selectedDims, null); 094 } 095 096 return lsize; 097 } 098 099 /** 100 * Get the total number of datapoints for the hyperslab selection within a dataset. 101 * 102 * @param did 103 * IN dataset ID 104 * @param dsetDims 105 * IN dimensions 106 * @param startDims 107 * IN start dimensions 108 * @param selectedStride 109 * IN selected stride values 110 * @param selectedDims 111 * IN selected dimensions 112 * @param spaceIDs 113 * IN/OUT memory and file space IDs -- spaceIDs[0]=mspace, spaceIDs[1]=fspace 114 * 115 * @return total number of data points selected 116 * 117 * @throws HDF5Exception 118 * If there is an error at the HDF5 library level. 119 */ 120 public static final long getTotalSelectedSpacePoints(long did, long[] dsetDims, long[] startDims, 121 long[] selectedStride, long[] selectedDims, long[] spaceIDs) throws HDF5Exception { 122 long totalSelectedSpacePoints = selectHyperslab(did, dsetDims, startDims, selectedStride, selectedDims, spaceIDs); 123 124 log.trace("getTotalSelectedSpacePoints(): selected {} points in dataset's dataspace", totalSelectedSpacePoints); 125 126 if (totalSelectedSpacePoints == 0) { 127 log.debug("getTotalSelectedSpacePoints(): No data to read. Dataset or selected subset is empty."); 128 throw new HDF5Exception("No data to read.\nEither the dataset or the selected subset is empty."); 129 } 130 131 if (totalSelectedSpacePoints < Integer.MIN_VALUE || totalSelectedSpacePoints > Integer.MAX_VALUE) { 132 log.debug("getTotalSelectedSpacePoints(): totalSelectedSpacePoints outside valid Java int range; unsafe cast"); 133 throw new HDF5Exception("Invalid int size"); 134 } 135 136 if (log.isDebugEnabled()) { 137 // check is storage space is allocated 138 try { 139 long ssize = H5.H5Dget_storage_size(did); 140 log.trace("getTotalSelectedSpacePoints(): Storage space allocated = {} bytes", ssize); 141 } 142 catch (Exception ex) { 143 log.debug("getTotalSelectedSpacePoints(): check if storage space is allocated:", ex); 144 } 145 } 146 147 return totalSelectedSpacePoints; 148 } 149 150}