Skip to content

Commit 3b5eff7

Browse files
committed
Extend limited reader in H5headerNew to handle filtered data
Test file added to test dataset collection and is checked with other HDF5 files by integration tests. Note: old API handled this case without issue, so no changes needed there. Fixes #1556.
1 parent cd207a9 commit 3b5eff7

2 files changed

Lines changed: 59 additions & 6 deletions

File tree

cdm/core/src/main/java/ucar/nc2/internal/iosp/hdf5/H5headerNew.java

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 1998-2018 University Corporation for Atmospheric Research/Unidata
2+
* Copyright (c) 1998-2026 University Corporation for Atmospheric Research/Unidata
33
* See LICENSE for license information.
44
*/
55

@@ -25,6 +25,7 @@
2525
import ucar.ma2.ArrayStructure;
2626
import ucar.ma2.ArrayStructureBB;
2727
import ucar.ma2.DataType;
28+
import ucar.ma2.Index;
2829
import ucar.ma2.IndexIterator;
2930
import ucar.ma2.InvalidRangeException;
3031
import ucar.ma2.Section;
@@ -59,6 +60,7 @@
5960
import ucar.nc2.write.NetcdfFileFormat;
6061
import ucar.nc2.iosp.IospHelper;
6162
import ucar.nc2.iosp.Layout;
63+
import ucar.nc2.iosp.LayoutBB;
6264
import ucar.nc2.iosp.LayoutRegular;
6365
import ucar.nc2.iosp.hdf5.DataBTree;
6466
import ucar.nc2.iosp.hdf5.H5headerIF;
@@ -1957,6 +1959,29 @@ Object getFillValueNonDefault() {
19571959
Array readArray() throws IOException {
19581960
int[] shape = mds.dimLength;
19591961
DataType dataType = typeInfo.dataType;
1962+
1963+
if (useFillValue) {
1964+
Object pa = IospHelper.makePrimitiveArray((int) Index.computeSize(shape), dataType, getFillValue());
1965+
if (dataType == DataType.CHAR)
1966+
pa = IospHelper.convertByteToChar((byte[]) pa);
1967+
return Array.factory(dataType, shape, pa);
1968+
}
1969+
1970+
// filtered, must read and decode by chunk
1971+
if (mfp != null) {
1972+
ByteOrder bo = (typeInfo.endian == 0) ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN;
1973+
LayoutBB layoutBB;
1974+
try {
1975+
layoutBB = new H5tiledLayoutBB(this, shape, dataType.getSize(), new Section(shape), getRandomAccessFile(),
1976+
mfp.getFilters(), bo);
1977+
} catch (InvalidRangeException e) {
1978+
// should not happen because we passed in the full shape
1979+
throw new IllegalStateException();
1980+
}
1981+
Object data = IospHelper.readDataFill(layoutBB, dataType, getFillValue());
1982+
return Array.factory(dataType, shape, data);
1983+
}
1984+
19601985
Layout layout;
19611986
try {
19621987
if (isChunked) {
@@ -1977,6 +2002,15 @@ Array readArray() throws IOException {
19772002
String readString() throws IOException {
19782003
int[] shape = new int[] {mdt.byteSize};
19792004
DataType dataType = typeInfo.dataType;
2005+
2006+
if (useFillValue) {
2007+
Object pa = IospHelper.makePrimitiveArray((int) Index.computeSize(shape), dataType, getFillValue());
2008+
if (dataType == DataType.CHAR)
2009+
pa = IospHelper.convertByteToChar((byte[]) pa);
2010+
Array dataArray = Array.factory(dataType, shape, pa);
2011+
return (dataArray instanceof ArrayChar.D1) ? ((ArrayChar) dataArray).getString() : "";
2012+
}
2013+
19802014
Layout layout;
19812015
try {
19822016
if (isChunked) {

cdm/core/src/main/java/ucar/nc2/internal/iosp/hdf5/H5tiledLayoutBB.java

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
/*
2-
* Copyright (c) 1998-2018 John Caron and University Corporation for Atmospheric Research/Unidata
2+
* Copyright (c) 1998-2026 John Caron and University Corporation for Atmospheric Research/Unidata
33
* See LICENSE for license information.
44
*/
5+
56
package ucar.nc2.internal.iosp.hdf5;
67

78
import com.google.common.primitives.Ints;
@@ -71,9 +72,27 @@ public class H5tiledLayoutBB implements LayoutBB {
7172
*/
7273
public H5tiledLayoutBB(Variable v2, Section wantSection, RandomAccessFile raf, H5objects.Filter[] filterProps,
7374
ByteOrder byteOrder) throws InvalidRangeException, IOException {
74-
wantSection = Section.fill(wantSection, v2.getShape());
75+
this((H5headerNew.Vinfo) v2.getSPobject(), v2.getShape(), v2.getElementSize(), wantSection, raf, filterProps,
76+
byteOrder);
77+
}
78+
79+
/**
80+
* This constructor can be used when the Variable is not yet built.
81+
*
82+
* @param vinfo the data object
83+
* @param varShape the variable's shape
84+
* @param elemSize the variable's element size in bytes
85+
* @param wantSection the wanted section of data, contains a List of Range objects. must be complete
86+
* @param raf the RandomAccessFile
87+
* @param filterProps set of filter properties from which filter object will be created
88+
* @throws InvalidRangeException if section invalid for this variable
89+
* @throws IOException on io error
90+
*/
91+
H5tiledLayoutBB(H5headerNew.Vinfo vinfo, int[] varShape, int elemSize, Section wantSection, RandomAccessFile raf,
92+
H5objects.Filter[] filterProps, ByteOrder byteOrder) throws InvalidRangeException, IOException {
93+
94+
wantSection = Section.fill(wantSection, varShape);
7595

76-
H5headerNew.Vinfo vinfo = (H5headerNew.Vinfo) v2.getSPobject();
7796
assert vinfo.isChunked;
7897
assert vinfo.btree != null;
7998

@@ -82,7 +101,7 @@ public H5tiledLayoutBB(Variable v2, Section wantSection, RandomAccessFile raf, H
82101
for (int i = 0; i < filterProps.length; i++) {
83102
// add var info to filter props
84103
Map<String, Object> props = filterProps[i].getProperties();
85-
props.put(Filters.Keys.ELEM_SIZE, v2.getElementSize());
104+
props.put(Filters.Keys.ELEM_SIZE, elemSize);
86105
// try to get filter by name or id, throw if not recognized filter
87106
try {
88107
filters[i] = Filters.getFilter(props);
@@ -95,7 +114,7 @@ public H5tiledLayoutBB(Variable v2, Section wantSection, RandomAccessFile raf, H
95114
// we have to translate the want section into the same rank as the storageSize, in order to be able to call
96115
// Section.intersect(). It appears that storageSize (actually msl.chunkSize) may have an extra dimension, relative
97116
// to the Variable.
98-
DataType dtype = v2.getDataType();
117+
DataType dtype = vinfo.getNCDataType();
99118
if ((dtype == DataType.CHAR) && (wantSection.getRank() < vinfo.storageSize.length)) {
100119
this.want = Section.builder().appendRanges(wantSection.getRanges()).appendRange(1).build();
101120
} else {

0 commit comments

Comments
 (0)