NetCDF 4.10.1
Loading...
Searching...
No Matches
filter_example.c
Go to the documentation of this file.
1/* Copyright 2018, UCAR/Unidata.
2 See COPYRIGHT file for conditions of use. */
40
41#include "config.h"
42#include <stdio.h>
43#include <string.h>
44#include <stdlib.h>
45
46#include <hdf5.h>
47#include "netcdf.h"
48#include "netcdf_filter.h"
49
50/* The HDF assigned id for bzip compression */
51#define BZIP2_ID 307
52/* The compression level used in this example */
53#define BZIP2_LEVEL 9
54
55#define TESTFILE "bzip2.nc"
56
57/* Point at which we give up */
58#define MAXERRS 8
59
60#define NDIMS 4
61#define DIMSIZE 4
62#define CHUNKSIZE 4 /* Note: not the total size of the chunk, but size wrt a dim*/
63
64static size_t dimsize = DIMSIZE;
65static size_t chunksize = CHUNKSIZE;
66static size_t actualdims = NDIMS;
67
68static size_t actualproduct = 1; /* x-product over dim sizes */
69static size_t chunkproduct = 1; /* x-product over chunksizes */
70
71static size_t dims[NDIMS];
72static size_t chunks[NDIMS];
73
74static int nerrs = 0;
75
76static int ncid, varid;
77static int dimids[NDIMS];
78static float* array = NULL;
79static float* expected = NULL;
80static unsigned int filterid = 0;
81static unsigned int* params = NULL;
82
83/* Forward */
84static void init(int argc, char** argv);
85static int test_bzip2(void);
86static int verifychunks(void);
87
88#define ERRR do { \
89fflush(stdout); /* Make sure our stdout is synced with stderr. */ \
90fprintf(stderr, "Sorry! Unexpected result, %s, line: %d\n", \
91 __FILE__, __LINE__); \
92nerrs++;\
93} while (0)
94
95static int
96check(int err,int line)
97{
98 if(err != NC_NOERR) {
99 fprintf(stderr,"fail (%d): %s\n",line,nc_strerror(err));
100 fflush(stderr);
101 exit(1);
102 }
103 return NC_NOERR;
104}
105
106#define CHECK(x) check(x,__LINE__)
107
108/*
109Read the chunking information about the variable
110and verify that it is as expected.
111*/
112
113static int
114verifychunks(void)
115{
116 int i;
117 int store = -1;
118 size_t chunksizes[NDIMS];
119 memset(chunksizes,0,sizeof(chunksizes));
120 CHECK(nc_inq_var_chunking(ncid, varid, &store, chunksizes));
121 /* Storage must be chunked, not contiguous */
122 if(store != NC_CHUNKED) {
123 fprintf(stderr,"bad chunk store\n");
124 return NC_ESTORAGE;
125 }
126 /* Chunk sizes must match our predefined set */
127 for(i=0;i<actualdims;i++) {
128 if(chunksizes[i] != chunks[i]) {
129 fprintf(stderr,"bad chunk size: %d\n",i);
130 return NC_EBADCHUNK;
131 }
132 }
133 return 1;
134}
135
136/*
137Compare the data we wrote against the data we read.
138*/
139
140static int
141compare(void)
142{
143 int errs = 0;
144 int i;
145 printf("data comparison: |array|=%ld\n",(unsigned long)actualproduct);
146 for(i=0;i<actualproduct;i++) {
147 if(expected[i] != array[i]) {
148 printf("mismatch: array[%d]=%f expected[%d]=%f\n",
149 i,array[i],i,expected[i]);
150 errs++;
151 if(errs >= MAXERRS)
152 break;
153 }
154 }
155 if(errs == 0)
156 printf("no data errors\n");
157 if(actualproduct <= 1)
158 return NC_EBADDIM;
159 return (errs == 0 ? NC_NOERR: NC_EINVAL);
160}
161
162/*
163Create the file, write it, then re-read for comparison.
164*/
165static int
166test_bzip2(void)
167{
168 int i;
169 unsigned int level = BZIP2_LEVEL;
170 size_t nparams = 0;
171
172 printf("\n*** Testing API: bzip2 compression.\n");
173
174 /* Clear the data array */
175 memset(array,0,sizeof(float)*actualproduct);
176
177 /* Create a file */
178 CHECK(nc_create(TESTFILE, NC_NETCDF4|NC_CLOBBER, &ncid));
179
180 /* Do not use fill for this file */
181 CHECK(nc_set_fill(ncid, NC_NOFILL, NULL));
182
183 /* Define the dimensions */
184 for(i=0;i<actualdims;i++) {
185 char dimname[1024];
186 snprintf(dimname,sizeof(dimname),"dim%d",i);
187 CHECK(nc_def_dim(ncid, dimname, dims[i], &dimids[i]));
188 }
189
190 /* Define the variable */
191 CHECK(nc_def_var(ncid, "var", NC_FLOAT, actualdims, dimids, &varid));
192
193 /* Set chunking on the variable */
194 CHECK(nc_def_var_chunking(ncid,varid,NC_CHUNKED,chunks));
195
196 /* Verify that chunking succeeded */
197 if(!verifychunks())
198 return NC_EINVAL;
199 /* Set bzip2 compression for the variable: takes one parameter == level */
200 CHECK(nc_def_var_filter(ncid,varid,BZIP2_ID,1,&level));
201
202 /* Read back the compression info and verify it */
203 level = 0;
204 CHECK(nc_inq_var_filter_info(ncid,varid,BZIP2_ID,&nparams,&level));
205 if(nparams != 1 || level != BZIP2_LEVEL) {
206 printf("test_filter: filter def/inq mismatch\n");
207 return NC_EFILTER;
208 }
209 /* Show the level */
210 printf("show parameters for bzip2: level=%u\n",level);
211 /* Show chunking */
212 printf("show chunks:");
213 for(i=0;i<actualdims;i++)
214 printf("%s%ld",(i==0?" chunks=":","),(unsigned long)chunks[i]);
215 printf("\n");
216
217 /* prepare to write */
218 CHECK(nc_enddef(ncid));
219
220 /* Fill in the array */
221 for(i=0;i<actualproduct;i++)
222 expected[i] = (float)i;
223
224 /* write array */
225 CHECK(nc_put_var(ncid,varid,expected));
226
227 /* Close file */
228 CHECK(nc_close(ncid));
229
230 /* Now re-open and verify */
231 printf("\n*** Testing API: bzip2 decompression.\n");
232
233 /* Clear the data array */
234 memset(array,0,sizeof(float)*actualproduct);
235
236 /* Open the file */
237 CHECK(nc_open(TESTFILE, NC_NOWRITE, &ncid));
238
239 /* Get the variable id */
240 CHECK(nc_inq_varid(ncid, "var", &varid));
241
242 /* Check the compression algorithm */
243 filterid = 0;
244 nparams = 0;
245 params = NULL;
246 CHECK(nc_inq_var_filter(ncid,varid,&filterid,&nparams,NULL));
247 if(filterid == 0) CHECK(NC_ENOFILTER); /* Not defined */
248 if(nparams > 0) {
249 params = (unsigned int*)malloc(sizeof(unsigned int)*nparams);
250 if(params == NULL)
251 return NC_ENOMEM;
252 CHECK(nc_inq_var_filter(ncid,varid,&filterid,&nparams,params));
253 }
254 if(filterid != BZIP2_ID) {
255 printf("Bzip2 id mismatch: %d\n",filterid);
256 return NC_EFILTER;
257 }
258 if(nparams != 1 && params != NULL && params[0] != BZIP2_LEVEL) {
259 printf("Compression parameter mismatch\n");
260 return NC_EFILTER;
261 }
262
263 /* Verify chunking */
264 if(!verifychunks())
265 return 0;
266
267 /* Read the data */
268 CHECK(nc_get_var_float(ncid, varid, array));
269
270 /* Close the file */
271 CHECK(nc_close(ncid));
272 return (compare() == NC_NOERR ? 0 : 1);
273}
274
275/**************************************************/
276/* Utilities */
277
278static void
279init(int argc, char** argv)
280{
281 int i;
282 /* Setup various variables */
283 actualproduct = 1;
284 chunkproduct = 1;
285 for(i=0;i<NDIMS;i++) {
286 dims[i] = dimsize;
287 chunks[i] = chunksize;
288 if(i < actualdims) {
289 actualproduct *= dims[i];
290 chunkproduct *= chunks[i];
291 }
292 }
293 /* Allocate max size */
294 array = (float*)calloc(1,sizeof(float)*actualproduct);
295 expected = (float*)calloc(1,sizeof(float)*actualproduct);
296}
297
298/**************************************************/
299int
300main(int argc, char **argv)
301{
302 H5Eprint1(stderr);
303 init(argc,argv);
304 if(test_bzip2() != NC_NOERR) ERRR;
305 exit(nerrs > 0?1:0);
306}
307
#define BZIP2_ID
EXTERNL int nc_close(int ncid)
Close an open netCDF dataset.
Definition dfile.c:1330
EXTERNL int nc_create(const char *path, int cmode, int *ncidp)
Create a new netCDF file.
Definition dfile.c:428
EXTERNL int nc_set_fill(int ncid, int fillmode, int *old_modep)
Change the fill-value mode to improve write performance.
Definition dfile.c:1504
EXTERNL int nc_enddef(int ncid)
Leave define mode.
Definition dfile.c:1057
EXTERNL int nc_open(const char *path, int mode, int *ncidp)
Open an existing netCDF file.
Definition dfile.c:694
EXTERNL int nc_def_dim(int ncid, const char *name, size_t len, int *idp)
Define a new dimension.
Definition ddim.c:121
EXTERNL const char * nc_strerror(int ncerr)
Given an error number, return an error message.
Definition derror.c:87
EXTERNL int nc_inq_varid(int ncid, const char *name, int *varidp)
Find the ID of a variable, from the name.
Definition dvarinq.c:60
EXTERNL int nc_put_var(int ncid, int varid, const void *op)
Write an entire variable with one call.
Definition dvarput.c:922
EXTERNL int nc_inq_var_filter_info(int ncid, int varid, unsigned int id, size_t *nparams, unsigned int *params)
Find the param info about filter (if any) associated with a variable and with specified id.
Definition dfilter.c:98
EXTERNL int nc_inq_var_filter(int ncid, int varid, unsigned int *idp, size_t *nparams, unsigned int *params)
Find the first filter (if any) associated with a variable.
Definition dfilter.c:170
EXTERNL int nc_inq_var_chunking(int ncid, int varid, int *storagep, size_t *chunksizesp)
Get the storage and (for chunked variables) the chunksizes of a variable.
Definition dvarinq.c:466
EXTERNL int nc_def_var(int ncid, const char *name, nc_type xtype, int ndims, const int *dimidsp, int *varidp)
Define a new variable.
Definition dvar.c:216
EXTERNL int nc_def_var_chunking(int ncid, int varid, int storage, const size_t *chunksizesp)
Define storage and, if chunked storage is used, chunking parameters for a variable.
Definition dvar.c:732
Main header file for the C API.
#define NC_NETCDF4
Use netCDF-4/HDF5 format.
Definition netcdf.h:179
#define NC_EFILTER
Filter operation failed.
Definition netcdf.h:562
#define NC_CLOBBER
Destroy existing file.
Definition netcdf.h:138
#define NC_FLOAT
single precision floating point number
Definition netcdf.h:40
#define NC_NOWRITE
Set read-only access for nc_open().
Definition netcdf.h:135
#define NC_ENOMEM
Memory allocation (malloc) failure.
Definition netcdf.h:497
#define NC_CHUNKED
In HDF5 files you can set storage for each variable to be either contiguous or chunked,...
Definition netcdf.h:353
#define NC_ESTORAGE
Can't specify both contiguous and chunking.
Definition netcdf.h:555
#define NC_NOFILL
Argument to nc_set_fill() to turn off filling of data.
Definition netcdf.h:123
#define NC_EINVAL
Invalid Argument.
Definition netcdf.h:427
#define NC_NOERR
No Error.
Definition netcdf.h:417
EXTERNL int nc_def_var_filter(int ncid, int varid, unsigned int id, size_t nparams, const unsigned int *parms)
Define a new variable filter Assumes HDF5 format using unsigned ints.
Definition dfilter.c:129
#define NC_EBADCHUNK
Bad chunksize.
Definition netcdf.h:556
#define NC_ENOFILTER
Filter not defined on variable.
Definition netcdf.h:566
#define NC_EBADDIM
Invalid dimension id or name.
Definition netcdf.h:460