File: bufr_read_temp.c

package info (click to toggle)
eccodes 2.20.0-1
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 400,332 kB
  • sloc: ansic: 167,977; makefile: 21,348; sh: 10,719; f90: 5,927; python: 4,831; perl: 3,031; javascript: 1,427; yacc: 818; lex: 356; awk: 66
file content (157 lines) | stat: -rw-r--r-- 5,603 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
/*
 * (C) Copyright 2005- ECMWF.
 *
 * This software is licensed under the terms of the Apache Licence Version 2.0
 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
 *
 * In applying this licence, ECMWF does not waive the privileges and immunities granted to it by
 * virtue of its status as an intergovernmental organisation nor does it submit to any jurisdiction.
 */

/*
 * C Implementation: bufr_read_temp
 *
 * Description: how to read temperature significant levels from TEMP BUFR messages.
 */

/*
 * Please note that TEMP reports can be encoded in various ways in BUFR. Therefore the code
 * below might not work directly for other types of TEMP messages than the one used in the
 * example. It is advised to use bufr_dump to understand the structure of the messages.
 */

#include "eccodes.h"

static void free_memory(double* sigt_pres, double* sigt_geo, double* sigt_t, double* sigt_td)
{
    free(sigt_pres);
    free(sigt_geo);
    free(sigt_t);
    free(sigt_td);
}

int main(int argc, char* argv[])
{
    FILE* in = NULL;

    /* Message handle. Required in all the eccodes calls acting on a message.*/
    codes_handle* h = NULL;

    double *sigt_pres = NULL, *sigt_geo = NULL, *sigt_t = NULL;
    double* sigt_td = NULL;
    size_t sigt_len = 0, len = 0, i = 0;
    int err            = 0;
    int cnt            = 0;
    const char* infile = "../../data/bufr/temp_101.bufr";
    char key_name[128];

    in = fopen(infile, "rb");
    if (!in) {
        fprintf(stderr, "Error: unable to open file %s\n", infile);
        return 1;
    }

    /* Loop over the messages in the bufr file */
    while ((h = codes_handle_new_from_file(NULL, in, PRODUCT_BUFR, &err)) != NULL || err != CODES_SUCCESS) {
        if (h == NULL) {
            fprintf(stderr, "Error: unable to create handle for message %d\n", cnt);
            cnt++;
            continue;
        }

        printf("message: %d\n", cnt);

        /* We need to instruct ecCodes to expand the descriptors
           i.e. unpack the data values */
        CODES_CHECK(codes_set_long(h, "unpack", 1), 0);

        /* In what follows we rely on the fact that for
         * temperature significant levels the value of key
         * verticalSoundingSignificance is 4 (see flag table 8001 for details).
         *
         * In our BUFR message verticalSoundingSignificance is always followed by
         *    geopotential, airTemperature, dewpointTemperature,
         *    windDirection, windSpeed and pressure.
         * So in order to access any of these keys we need to use the
         * condition: verticalSoundingSignificance=4.
         */

        /* Get the number of the temperature significant levels.*/

        /* We find out the number of temperature significant levels by
         * counting how many pressure values we have on these levels.*/

        sprintf(key_name, "/verticalSoundingSignificance=4/pressure");
        CODES_CHECK(codes_get_size(h, key_name, &sigt_len), 0);

        printf("Number of T significant levels: %lu\n", sigt_len);

        /* Allocate memory for the values to be read. Each
         * parameter must have the same number of values. */
        sigt_pres = (double*)malloc(sigt_len * sizeof(double));
        sigt_geo  = (double*)malloc(sigt_len * sizeof(double));
        sigt_t    = (double*)malloc(sigt_len * sizeof(double));
        sigt_td   = (double*)malloc(sigt_len * sizeof(double));

        /* Get pressure */
        sprintf(key_name, "/verticalSoundingSignificance=4/pressure");
        len = sigt_len;
        CODES_CHECK(codes_get_double_array(h, key_name, sigt_pres, &len), 0);

        /* Get geopotential */
        sprintf(key_name, "/verticalSoundingSignificance=4/nonCoordinateGeopotential");

        /* Check the size */
        CODES_CHECK(codes_get_size(h, key_name, &len), 0);
        if (len != sigt_len) {
            fprintf(stderr, "Error: inconsistent number of geopotential values found!\n");
            free_memory(sigt_pres, sigt_geo, sigt_t, sigt_td);
            return 1;
        }

        /* Get the values */
        CODES_CHECK(codes_get_double_array(h, key_name, sigt_geo, &len), 0);

        /* Get temperature */
        if (len != sigt_len) { /* Check the size */
            fprintf(stderr, "Error: inconsistent number of temperature values found!\n");
            free_memory(sigt_pres, sigt_geo, sigt_t, sigt_td);
            return 1;
        }

        /* Get the values */
        sprintf(key_name, "/verticalSoundingSignificance=4/airTemperature");
        CODES_CHECK(codes_get_double_array(h, key_name, sigt_t, &len), 0);

        /* Get dew point */
        if (len != sigt_len) { /* Check the size */
            fprintf(stderr, "Error: inconsistent number of dewpoint temperature values found!\n");
            free_memory(sigt_pres, sigt_geo, sigt_t, sigt_td);
            return 1;
        }

        /* Get the values */
        sprintf(key_name, "/verticalSoundingSignificance=4/dewpointTemperature");
        CODES_CHECK(codes_get_double_array(h, key_name, sigt_td, &len), 0);

        /* Print the values */
        printf("lev  pres    geo    t    td\n");
        printf("-------------------------------\n");

        for (i = 0; i < sigt_len; i++) {
            printf("%3lu %6.0f %6.0f %.1f %.1f\n",
                   i + 1, sigt_pres[i], sigt_geo[i], sigt_t[i], sigt_td[i]);
        }

        /* Delete handle */
        codes_handle_delete(h);

        /* Release memory */
        free_memory(sigt_pres, sigt_geo, sigt_t, sigt_td);

        cnt++;
    }

    fclose(in);
    return 0;
}