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 COPYING file, which can be found * 009 * at the root of the source code distribution tree, * 010 * or in https://www.hdfgroup.org/licenses. * 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 021import org.slf4j.Logger; 022import org.slf4j.LoggerFactory; 023 024/** HDF5 utility class */ 025public final class H5Utils { 026 027 private static final Logger log = LoggerFactory.getLogger(H5Utils.class); 028 029 /** 030 * Set up a hyperslab selection within a dataset. 031 * 032 * @param did 033 * IN dataset ID 034 * @param dsetDims 035 * IN dimensions 036 * @param startDims 037 * IN start dimensions 038 * @param selectedStride 039 * IN selected stride values 040 * @param selectedDims 041 * IN selected dimensions 042 * @param spaceIDs 043 * IN/OUT memory and file space IDs -- spaceIDs[0]=mspace, spaceIDs[1]=fspace 044 * 045 * @return total number of data points selected 046 * 047 * @throws HDF5Exception 048 * If there is an error at the HDF5 library level. 049 */ 050 public static final long selectHyperslab(long did, long[] dsetDims, long[] startDims, 051 long[] selectedStride, long[] selectedDims, long[] spaceIDs) 052 throws HDF5Exception 053 { 054 if (dsetDims == null) { 055 log.debug("selectHyperslab(): dsetDims is null"); 056 return -1; 057 } 058 059 int rank = dsetDims.length; 060 if ((startDims != null) && (startDims.length != rank)) { 061 log.debug("selectHyperslab(): startDims rank didn't match dsetDims rank"); 062 return -1; 063 } 064 if ((selectedStride != null) && (selectedStride.length != rank)) { 065 log.debug("selectHyperslab(): selectedStride rank didn't match startDims rank"); 066 return -1; 067 } 068 if ((selectedDims != null) && (selectedDims.length != rank)) { 069 log.debug("selectHyperslab(): selectedDims rank didn't match startDims rank"); 070 return -1; 071 } 072 073 long lsize = 1; 074 075 boolean isAllSelected = true; 076 for (int i = 0; i < rank; i++) { 077 if (selectedDims != null) { 078 lsize *= selectedDims[i]; 079 if (selectedDims[i] < dsetDims[i]) 080 isAllSelected = false; 081 } 082 } 083 084 log.trace("selectHyperslab(): isAllSelected={}", isAllSelected); 085 086 if (isAllSelected) { 087 spaceIDs[0] = HDF5Constants.H5S_ALL; 088 spaceIDs[1] = HDF5Constants.H5S_ALL; 089 } 090 else { 091 spaceIDs[1] = H5.H5Dget_space(did); 092 093 // When a 1D dataspace is used for a chunked dataset, reading is very slow. 094 // 095 // It is a known problem within the HDF5 library. 096 // mspace = H5.H5Screate_simple(1, lsize, null); 097 spaceIDs[0] = H5.H5Screate_simple(rank, selectedDims, null); 098 H5.H5Sselect_hyperslab(spaceIDs[1], HDF5Constants.H5S_SELECT_SET, startDims, selectedStride, 099 selectedDims, null); 100 } 101 102 return lsize; 103 } 104 105 /** 106 * Get the total number of datapoints for the hyperslab selection within a dataset. 107 * 108 * @param did 109 * IN dataset ID 110 * @param dsetDims 111 * IN dimensions 112 * @param startDims 113 * IN start dimensions 114 * @param selectedStride 115 * IN selected stride values 116 * @param selectedDims 117 * IN selected dimensions 118 * @param spaceIDs 119 * IN/OUT memory and file space IDs -- spaceIDs[0]=mspace, spaceIDs[1]=fspace 120 * 121 * @return total number of data points selected 122 * 123 * @throws HDF5Exception 124 * If there is an error at the HDF5 library level. 125 */ 126 public static final long getTotalSelectedSpacePoints(long did, long[] dsetDims, long[] startDims, 127 long[] selectedStride, long[] selectedDims, 128 long[] spaceIDs) throws HDF5Exception 129 { 130 long totalSelectedSpacePoints = 131 selectHyperslab(did, dsetDims, startDims, selectedStride, selectedDims, spaceIDs); 132 133 log.trace("getTotalSelectedSpacePoints(): selected {} points in dataset's dataspace", 134 totalSelectedSpacePoints); 135 136 if (totalSelectedSpacePoints == 0) { 137 log.debug("getTotalSelectedSpacePoints(): No data to read. Dataset or selected subset is empty."); 138 throw new HDF5Exception("No data to read.\nEither the dataset or the selected subset is empty."); 139 } 140 141 if (totalSelectedSpacePoints < Integer.MIN_VALUE || totalSelectedSpacePoints > Integer.MAX_VALUE) { 142 log.debug( 143 "getTotalSelectedSpacePoints(): totalSelectedSpacePoints outside valid Java int range; unsafe cast"); 144 throw new HDF5Exception("Invalid int size"); 145 } 146 147 if (log.isDebugEnabled()) { 148 // check is storage space is allocated 149 try { 150 long ssize = H5.H5Dget_storage_size(did); 151 log.trace("getTotalSelectedSpacePoints(): Storage space allocated = {} bytes", ssize); 152 } 153 catch (Exception ex) { 154 log.debug("getTotalSelectedSpacePoints(): check if storage space is allocated:", ex); 155 } 156 } 157 158 return totalSelectedSpacePoints; 159 } 160}