OB.DAAC Logo
NASA Logo
Ocean Color Science Software

ocssw V2022
nc_init_compress.c
Go to the documentation of this file.
1 #include <netcdf.h>
2 #include <stdlib.h>
3 #include <stdint.h>
4 #include <math.h>
5 #include <stdio.h>
6 #include <nc4utils.h>
7 
8 #define DEFAULT_CHUNK_SIZE 1000
9 
24 void nc_init_compress(int32_t nc_id, int32_t var_id, int32_t *dimids, int32_t rank,
25  size_t *chunksize, int deflate_level) {
26  int i, status;
27 
28  // if deflate level below 0 then don't deflate
29  if (deflate_level < 1)
30  return;
31 
32  size_t dimlength, newchunk;
33  /*
34  * vary chunk size based on dimensions
35  * looking to keep the chunks around 32Kb, hopefully no larger than 200Kb
36  */
37  for (i = 0; i < rank; i++) {
38  status = nc_inq_dimlen(nc_id, dimids[i], &dimlength);
39  // Try to keep as few chunks as possible per scan line
40  if (chunksize[i] == 0) { // only do if chunksize isn't set by user
41  if (dimlength < 1000) {
42  chunksize[i] = floor(dimlength / 3) + 1;
43  } else {
44  newchunk = floor(dimlength / 100) + 1;
45  if (newchunk > 1500) {
46  newchunk = floor(dimlength / 250) + 1;
47  if (newchunk > 40)
48  newchunk = 40;
49  }
50  chunksize[i] = newchunk;
51  }
52  }
53  }
54 
55  // /* decide whether it is worth compression - dims must be larger than chunks */
56  // for (i = 0; i < rank; i++) {
57  // status = nc_inq_dimlen(nc_id, dimids[i], &dimlength);
58  // if (dimlength < chunksize[i]) {
59  // do_deflate = 0;
60  // break;
61  // }
62  // }
63 
64  /* Set compression */
65  /* First set chunking */
66  status = nc_def_var_chunking(nc_id, var_id, NC_CHUNKED, chunksize);
67  if (status != NC_NOERR) {
68  printf("-E- %s %d: %s \n", __FILE__, __LINE__,
69  nc_strerror(status));
70  exit(EXIT_FAILURE);
71  }
72  /* Now we can set compression */
73  status = nc_def_var_deflate(nc_id, var_id, NC_SHUFFLE, 9,
74  deflate_level);
75  if (status != NC_NOERR) {
76  printf("-E- %s %d: %s \n", __FILE__, __LINE__,
77  nc_strerror(status));
78  exit(EXIT_FAILURE);
79  }
80 }
81 
94 int nc_init_compress2(int32_t nc_id, char *varnam, int32_t var_id, int32_t *dimids, int32_t rank,
95  size_t *chunksize, int type_size, int deflate_level) {
96  int d, status;
97 
98  size_t dimlength;
99 
100  /* Pick a chunk length for each dimension, if one has not already
101  * been picked above. */
102  for (d = 0; d < rank; d++)
103  if (!chunksize[d]) {
104  size_t suggested_size;
105  status = nc_inq_dimlen(nc_id, dimids[d], &dimlength);
106  suggested_size = (pow((double) DEFAULT_CHUNK_SIZE / (dimlength * type_size),
107  1 / (double) (rank)) * dimlength - .5);
108  if (suggested_size > dimlength)
109  suggested_size = dimlength;
110  chunksize[d] = suggested_size ? suggested_size : 1;
111  // LOG((4, "nc_def_var_nc4: name %s dim %d DEFAULT_CHUNK_SIZE %d num_values %f type_size %d "
112  // "chunksize %ld", varnam, d, DEFAULT_CHUNK_SIZE, dimlength, type_size, chunksize[d]));
113  }
114 
115  /* But did this add up to a chunk that is too big? */
116  status = check_chunksizes(type_size, rank, chunksize);
117  if (status) {
118  /* Other error? */
119  if (status != NC_EBADCHUNK)
120  return status;
121 
122  /* Chunk is too big! Reduce each dimension by half and try again. */
123  for (; status == NC_EBADCHUNK; status = check_chunksizes(type_size, rank, chunksize))
124  for (d = 0; d < rank; d++)
125  chunksize[d] = chunksize[d] / 2 ? chunksize[d] / 2 : 1;
126  }
127 
128  /* Do we have any big data overhangs? They can be dangerous to
129  * babies, the elderly, or confused campers who have had too much
130  * beer. */
131 #define NC_ALLOWED_OVERHANG .1
132  for (d = 0; d < rank; d++)
133  for (; dimlength % chunksize[d] > dimlength * NC_ALLOWED_OVERHANG;)
134  chunksize[d] -= dimlength * NC_ALLOWED_OVERHANG;
135 
136  /* First set chunking */
137  status = nc_def_var_chunking(nc_id, var_id, NC_CHUNKED, chunksize);
138  if (status != NC_NOERR) {
139  printf("-E- %s %d: %s \n", __FILE__, __LINE__,
140  nc_strerror(status));
141  exit(1);
142  }
143  //do_deflate = chunksize[0] + rank + deflate_level;
144  /* Set compression */
145  if (deflate_level > 0) {
146  /* Now we can set compression */
147  status = nc_def_var_deflate(nc_id, var_id, NC_SHUFFLE, deflate_level,
148  deflate_level);
149  if (status != NC_NOERR) {
150  printf("-E- %s %d: %s \n", __FILE__, __LINE__,
151  nc_strerror(status));
152  exit(1);
153  }
154  }
155  return 0;
156 }
157 
158 /* Check a set of chunksizes to see if they specify a chunk that is too big. */
159 int check_chunksizes(size_t type_len, int32_t ndims, const size_t *chunksizes) {
160  double dprod;
161  int d;
162 
163  dprod = (double) type_len;
164  for (d = 0; d < ndims; d++) {
165  if (chunksizes[d] < 1)
166  return NC_EINVAL;
167  dprod *= (double) chunksizes[d];
168  }
169 
170  if (dprod > (double) NC_MAX_UINT)
171  return NC_EBADCHUNK;
172 
173  return NC_NOERR;
174 }
int status
Definition: l1_czcs_hdf.c:32
void nc_init_compress(int32_t nc_id, int32_t var_id, int32_t *dimids, int32_t rank, size_t *chunksize, int deflate_level)
#define DEFAULT_CHUNK_SIZE
#define NC_ALLOWED_OVERHANG
int nc_init_compress2(int32_t nc_id, char *varnam, int32_t var_id, int32_t *dimids, int32_t rank, size_t *chunksize, int type_size, int deflate_level)
int check_chunksizes(size_t type_len, int32_t ndims, const size_t *chunksizes)
integer, parameter double
Extra metadata that will be written to the HDF4 file l2prod rank
int i
Definition: decode_rs.h:71