netCDF-SDK¶
This document describes how to read and write NC and NC2 files with C.
Contents¶
The following files must be installed with your application. The files can
be copied from a current UniPlot installation (R2018 or later). A 32bit and
a 64 bit version is available. The file license.txt
can be found in the
UniPlot\samples\SDK\netCDF
directory.
rs_updf_nc.dll
rs_updf.dll
rs_xlib.dll
zlib.dll
license.txt
Other files from the UniPlot\samples\SDK\netCDF
directory:
ncread.c - A simple example how to read data.
ncwrite.c - A simple example how to write data.
win32\rs_updf_nc.lib - The 32-Bit Import-Library.
x64\rs_updf_nc.lib - The 64-Bit Import-Library.
up-nc.h - The Header file.
map-data.nc2 - Simple example file.
Some Notes¶
The UniPlot-netCDF-SDK uses the netCDF 2.4 API.
http://www.unidata.ucar.edu/software/netcdf/old_docs/really_old/guide_toc.html
The netCDF data files used with UniPlot can have three different formats:
The original netCDF format as described in the link above. File size is limited to 2 GBytes. The first three characters in the file are “CDF”.
A modified form of the original netCDF format with Intel byte order (Little Endian). These files cannot be read with the standard netCDF library. The file size is limited to 2 GBytes. The first three characters in the file are “CDH”.
A UniPlot format that uses only the API of the netCDF library. The format supports compression and fast delete/add channel and attributes. The first three characters in the file are “UPD”. These files are similar to a file system. The data is saved in sectors.
The file size is limited to 1 TB. Each channel can contain up to 2^31-1 data points.
If you use a Microsoft C-Compiler you can compile the examples with:
cl ncread.c x64\rs_updf_nc.lib
The path for your C-Compiler must be set.
Start the program with:
ncread map-data.nc2
The example prints the first 10 data points of each channel. More test files can be created using UniPlot.
Instead of using the Import-Library
rs_updf_nc.lib
, you can load the functions dynamically usingLoadLibrary
, (LoadLibraryEx
,GetModuleHandle
) andGetProcAddress
.For some data file formats, for example INCA-MDF, UniPlot saves the data in the netCDF file with a delay. The file contains the complete structure with all attributes and channels. The channel data is saved in the netCDF file, when the channel data is accessed.
To check if the data is already saved in the netCDF file read the value of the channel attribute
_nc_dl_loaded
. If the attribute has the value 1 the data is valid.
Examples¶
1/*
2 compile: cl ncwrite.c rs_updf_nc.lib
3*/
4
5#include <stdlib.h>
6#include <stdio.h>
7#include "up-nc.h"
8
9int error(char *msg)
10{
11 fprintf(stderr, "%s", msg);
12 exit(1);
13}
14
15void main(int argc, char *argv[])
16{
17 test();
18 exit(0);
19}
20
21int test()
22{
23 int ncid;
24 double *p;
25 int dimid;
26 int i, varid, start, count, len;
27 double scale = 1.0, offset = 0.0;
28
29 ncid = nccreate("test1.nc2");
30 if (ncid == -1) {
31 error("cannot open output file");
32 }
33
34 ncredef(ncid);
35
36 // Globale Attributes
37
38 varid = -1;
39 ncattput(ncid, varid, "Origin", NC_CHAR, 1, "");
40 ncattput(ncid, varid, "Source", NC_CHAR, 1, "");
41 len = strlen("enorise GmbH (www.uniplot.com)")+1;
42 ncattput(ncid, varid, "Creator", NC_CHAR, len, "enorise GmbH (www.uniplot.com)");
43 ncattput(ncid, varid, "Date", NC_CHAR, strlen("15 Nov 2013")+1, "15 Nov 2013");
44 ncattput(ncid, varid, "Time", NC_CHAR, strlen("09:24:20")+1, "09:24:20");
45
46 // Dimensions
47 dimid = ncdimdef(ncid, "n", 100);
48
49 // Kanäle und Kanal-Attribute
50 varid = ncvardef(ncid, "var1", NC_DOUBLE, 1, &dimid);
51 ncattput(ncid, varid, "units", NC_CHAR, strlen("1/min")+1, "1/min");
52
53 ncattput(ncid, varid, "scale_factor", NC_DOUBLE, 1, &scale);
54 ncattput(ncid, varid, "add_offset", NC_DOUBLE, 1, &offset);
55
56 ncendef(ncid);
57
58 // Write the channel data
59
60 p = (double*) malloc(100*sizeof(double));
61 for (i = 0; i < 100; i++) p[i] = (double) i;
62 start = 0;
63 count = 100;
64 ncvarput(ncid, varid, &start, &count, p);
65 free(p);
66 ncclose(ncid);
67 return 0;
68}
Writing a string channel
1// compile: cl test_nc_string.c rs_updf_nc.lib
2
3#include <stdlib.h>
4#include <stdio.h>
5#include "up-nc.h"
6
7#define MIN(a,b) (((a)<(b))?(a):(b))
8
9void main()
10{
11 int ncid, varid, n1, len1, start[2], count[2], dimids[2];
12 char *s;
13
14 ncid = nccreate("d:\\test2.nc2");
15
16 // Number of Points 10,000
17 n1 = ncdimdef(ncid, "n", 10000);
18
19 // Legth of the longest string, e. g. 32
20 len1 = ncdimdef(ncid, "len", 32);
21
22 dimids[0] = n1;
23 dimids[1] = len1;
24 varid = ncvardef(ncid, "StringChannel", NC_CHAR, 2, dimids);
25 ncendef(ncid);
26
27 start[0] = 0;
28 start[1] = 0;
29 count[0] = 1;
30 count[1] = 5;
31 ncvarput(ncid, varid, start, count, "Hello");
32
33 s = "This is a long string";
34 start[0] = 10;
35 start[1] = 0;
36 count[0] = 1;
37 count[1] = MIN(32, strlen(s));
38 ncvarput(ncid, varid, start, count, s);
39
40 ncclose(ncid);
41}
Read file:
1/*
2 compile:
3
4 cl ncread.c rs_updf_nc.lib
5
6 See also
7
8 * readme.txt
9
10 * http://www.unidata.ucar.edu/software/netcdf/old_docs/really_old/guide_toc.html
11
12*/
13
14#include <stdlib.h>
15#include <stdio.h>
16#include "up-nc.h"
17
18int error(char *msg)
19{
20 fprintf(stderr, "%s", msg);
21 exit(0);
22}
23
24int att_print(int ncid, int varid, int attnum)
25{
26 char name[MAX_NC_NAME+1];
27 int i, data_type, len;
28 double *dVal;
29 float *fVal;
30 int *iVal;
31 short *sVal;
32 char *cVal;
33
34 ncattname(ncid, varid, attnum, name);
35 ncattinq(ncid, varid, name, &data_type, &len);
36 switch (data_type) {
37 case NC_CHAR:
38 cVal = (char*) malloc(len * sizeof(char));
39 ncattget(ncid, varid, name, cVal);
40 printf("%s = ", name);
41 for (i = 0; i < len; i++) {
42 printf("%c", cVal[i]);
43 }
44 printf("\n");
45 free(cVal);
46 break;
47
48 case NC_BYTE:
49 cVal = (char*) malloc(len * sizeof(char));
50 ncattget(ncid, varid, name, cVal);
51 printf("%s = ", name);
52 for (i = 0; i < len; i++) {
53 printf("%d ", cVal[i]);
54 }
55 printf("\n");
56 free(cVal);
57 break;
58
59 case NC_SHORT:
60 sVal = (short*) malloc(len * sizeof(short));
61 ncattget(ncid, varid, name, sVal);
62 printf("%s = ", name);
63 for (i = 0; i < len; i++) {
64 printf("%d ", sVal[i]);
65 }
66 printf("\n");
67 free(sVal);
68 break;
69
70 case NC_LONG:
71 iVal = (int*) malloc(len * sizeof(int));
72 ncattget(ncid, varid, name, iVal);
73 printf("%s = ", name);
74 for (i = 0; i < len; i++) {
75 printf("%d ", iVal[i]);
76 }
77 printf("\n");
78 free(iVal);
79 break;
80
81 case NC_FLOAT:
82 fVal = (float*) malloc(len * sizeof(float));
83 ncattget(ncid, varid, name, fVal);
84 printf("%s = ", name);
85 for (i = 0; i < len; i++) {
86 printf("%f ", fVal[i]);
87 }
88 printf("\n");
89 free(fVal);
90 break;
91
92 case NC_DOUBLE:
93 dVal = (double*) malloc(len * sizeof(double));
94 ncattget(ncid, varid, name, dVal);
95 printf("%s = ", name);
96 for (i = 0; i < len; i++) {
97 printf("%lf ", dVal[i]);
98 }
99 printf("\n");
100 free(dVal);
101 break;
102 }
103 return 0;
104}
105
106void main(int argc, char *argv[])
107{
108 int ncid;
109 int nvars, ngatts, data_type, ndims, natts, length, length2;
110 int dimids[MAX_NC_DIMS];
111 int i, j;
112 char name[136];
113 double *vals;
114 float *fvals;
115 char *cvals;
116 unsigned char *bvals;
117 short *svals;
118 int *ivals;
119 int ret, start;
120 int st[2], le[2];
121
122 int max_len = 10;
123
124 if (argc != 2) {
125 error("usage: ncread nc-file-name");
126 }
127
128 ncid = ncopen(argv[1], 0);
129 if (ncid == -1) {
130 error("cannot open input file");
131 }
132 ncinquire(ncid, 0, &nvars, &ngatts, 0);
133
134 printf("ngatts=%d\n", ngatts);
135 for (i = 0; i < ngatts; i++) {
136 att_print(ncid, -1, i);
137 }
138
139 printf("\nnvars=%d\n", nvars);
140
141 for (i = 0; i < nvars; i++) {
142 ncvarinq(ncid, i, name, &data_type, &ndims, dimids, &natts);
143
144 printf("%s\n", name);
145
146 printf("natts=%d\n", natts);
147 for (j = 0; j < natts; j++) {
148 att_print(ncid, i, j);
149 }
150
151 if (ndims != 1 && data_type != NC_CHAR) {
152 printf("Variable %s wird im Beispielprog. ignoriert wg. Anzahl Dimensionen != 1", name);
153 continue;
154 }
155 switch (data_type) {
156 case NC_CHAR:
157 if (ndims != 2) {
158 printf("Variable %s wird im Beispielprog. ignoriert wg. Anzahl Dimensionen != 2", name);
159 continue;
160 }
161 ncdiminq(ncid, dimids[0], 0, &length);
162 ncdiminq(ncid, dimids[1], 0, &length2);
163 cvals = (char*) malloc(length2 * sizeof(char));
164 if (cvals == 0) {
165 error("out of memory");
166 }
167 printf("len=%d\n", length);
168 for (j = 0; j < min(max_len, length); j++) {
169 st[0] = j;
170 st[1] = 0;
171 le[0] = 1;
172 le[1] = length2;
173 ret = ncvarget(ncid, i, st, le, cvals);
174 printf("%s\n", cvals);
175 }
176 free(cvals);
177 break;
178
179 case NC_BYTE:
180 ncdiminq(ncid, dimids[0], 0, &length);
181 bvals = (unsigned char*) malloc(length * sizeof(unsigned char));
182 if (bvals == 0) {
183 error("out of memory");
184 }
185 start = 0;
186 ret = ncvarget(ncid, i, &start, &length, bvals);
187 printf("len=%d\n", length);
188 for (j = 0; j < min(max_len, length); j++) {
189 printf("%f\n", bvals[j]);
190 }
191 free(bvals);
192 break;
193
194 case NC_SHORT:
195 ncdiminq(ncid, dimids[0], 0, &length);
196 svals = (short*) malloc(length * sizeof(short));
197 if (svals == 0) {
198 error("out of memory");
199 }
200 start = 0;
201 ret = ncvarget(ncid, i, &start, &length, svals);
202 printf("len=%d\n", length);
203 for (j = 0; j < min(max_len, length); j++) {
204 printf("%f\n", svals[j]);
205 }
206 free(svals);
207 break;
208
209 case NC_LONG:
210 ncdiminq(ncid, dimids[0], 0, &length);
211 ivals = (int*) malloc(length * sizeof(int));
212 if (ivals == 0) {
213 error("out of memory");
214 }
215 start = 0;
216 ret = ncvarget(ncid, i, &start, &length, ivals);
217 printf("len=%d\n", length);
218 for (j = 0; j < min(max_len, length); j++) {
219 printf("%f\n", ivals[j]);
220 }
221 free(ivals);
222 break;
223
224 case NC_FLOAT:
225 ncdiminq(ncid, dimids[0], 0, &length);
226 fvals = (float*) malloc(length * sizeof(float));
227 if (fvals == 0) {
228 error("out of memory");
229 }
230 start = 0;
231 ret = ncvarget(ncid, i, &start, &length, fvals);
232 printf("len=%d\n", length);
233 for (j = 0; j < min(max_len, length); j++) {
234 printf("%f\n", fvals[j]);
235 }
236 free(fvals);
237 break;
238
239 case NC_DOUBLE:
240 ncdiminq(ncid, dimids[0], 0, &length);
241 vals = (double*) malloc(length * sizeof(double));
242 if (vals == 0) {
243 error("out of memory");
244 }
245 start = 0;
246 ret = ncvarget(ncid, i, &start, &length, vals);
247 printf("len=%d\n", length);
248 for (j = 0; j < min(max_len, length); j++) {
249 printf("%lf\n", vals[j]);
250 }
251 free(vals);
252 break;
253 }
254 }
255
256 ncclose(ncid);
257}
Conventions¶
Valid characters for attribute and channel names are:
_[a-z][A-Z][0-9]
, A name should not start with an alphanumeric character. The name length is limited to 128 characters. The following 10 special characters are also allowed in names:. - + $ # ~ ! ^ & %
.Attribute and channel names should not start with an underscore
_
or the characters nc_`. These names are reserved for internal purposes (e. g. for the attributesnc_min
,nc_monotone
,_FillValue
,_nc_dl_loadinfo
, etc.).Channel names must be unique. The number of channels is limited to 20,000 per file.
Missing Values: For
NC_DOUBLE
- andNC_FLOAT
channels the value1e10
should be used as a missing value. For integer channels the attriubtemissing_value
should be added to the channel.For time channels the channel data type NC_DOUBLE` (8 Bytes) should be used.
Time/Date channels should be saved in the Microsoft Excel Format with the datatype
NC_DOUBLE
:uniplot_time = unix_time / 86400 + 25569 The Unix time are the seconds since 1.1.1970 00:00:00. The Excel time are the days since December 31, 1899. 86400: seconds in a day (24*60*60) 25569: days beween 1899-12-31 and 1970-01-01
The attribute
datatype
should be saved with the Time/Date channel with one of the following values: “date”, “time” or “datetime”.A string channel is a matrix of type
NC_CHAR
. The second dimention is the number of characters of the longest string. All other stings will be padded with NULL, see example below.The following attributes should be saved in the file as global attributes:
Attribute-Name
Datatype
Description
Origin
NC_CHAR
Name of the original data file, e.g.
c:\test-data\test.mdf4
. Can be empty.Source
NC_CHAR
Create of the import filter, e. g.
enorise GmbH (www.uniplot.com)
Creator
NC_CHAR
Name of the import filter followed by a version number, e. g.
MDF 4.1
Date
NC_CHAR
Date as a string, e. g.
14 Nov 2013
Time
NC_CHAR
Time as a string, e. g.
12:11:31,345
In addition, the file can also contain other arbitrary attributes. For example, the project number, engine information,etc.
The formula interpreter can access global attributes. example: The air pressure (barom) during the measurement could be specified as a channel or, if it was constant during the measurement, as a global attribute
barom = 1013.4
In this case another addtribute should define the unit:
barom.units = "mbar"
From UniPlot 2014, the attribute can be defined as following:
barom = "1013.4 mbar"
Channels should have the following attributes:
Attribute-Name
Datatype
Description
title
NC_CHAR
Channel title.
long_name
NC_CHAR
A long descriptive name. This could be used for labeling plots, for example.:
zlrsb_w\ETKC:1 [s]
units
NC_CHAR
A character string that specifies the units used for the variable’s data, e. g.
Nm
.scale_factor
NC_DOUBLE
If present for a variable, the data are to be multiplied by this factor after the data are read by the application that accesses the data. Normally 1.
add_offset
NC_DOUBLE
If present for a variable, this number is to be added to the data after it is read by the application that accesses the data. Normally the value 0.
The following attributes are optional.
Attribute-Name
Datatype
Description
missing_value
As channel
The data type of the attribute
missing_value
is the data type of the channel. Only required for integer channels, or if the data type isNC_FLOAT
orNC_DOUBLE
and the value 1e10 is not intended to be used.Type
NC_CHAR
Value is “Time Channel” or “Data Channel”.
datatype
NC_CHAR
For Time/Date channel, values: “date” or “time” or “datetime”
C_format
NC_CHAR
Format string to display the values in the data browser, e. g.
%.2lf
for two decimal places or%.6lf
for 6 decimal places. see printf.Description
NC_CHAR
Description string.
Comment
NC_CHAR
Comment string.
In addition, the channel can also contain other attributes.
See also¶
History¶
Version |
Description |
---|---|
1.4 (28.01.2019) |
zlib.dll added to the list of DLLs. |
1.4 (01.11.2017) |
Correction. The two import libraries could only be used with R2015.x. The new libraries are for R2016 and higher. |
1.3 (09 Jan 2015) |
Description modified. |
1.2 (21 Nov 2013) |
Description modified. |
1.1 (25 Mar 2011) |
Writing added. |
1.0 (21 Mar 2011) |
First version. |
Contact¶
If you have any questions please contact us:
id-1961936