bufr2synop 0.24.0
bufr2tac_temp.c
Go to the documentation of this file.
1/***************************************************************************
2 * Copyright (C) 2013-2018 by Guillermo Ballester Valor *
3 * gbv@ogimet.com *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
20/*!
21 \file bufr2tac_temp.c
22 \brief file with the code to parse a sequence as a FM-35 TEMP, FM-36 TEMP SHIP, FM-37 TEMP DROP, FM-38 TEMP MOBIL
23 */
24#include "bufr2tac.h"
25
26
27/*!
28 \fn char *guess_WMO_region_temp(struct synop_chunks *syn)
29 \brief Try to find WMO region if it is not already set and WMO Block and number index are known
30 \param syn pointer to the struct \ref synop_chunks with all known data for a synop
31
32 It returns a pointer to the string with WMO region
33*/
35{
36 if ( t->a.s1.A1[0] )
37 {
38 return t->a.s1.A1;
39 }
40
41 if ( t->a.s1.II[0] == 0 || t->a.s1.iii[0] == 0 )
42 {
43 return t->a.s1.A1;
44 }
45
46 if ( guess_WMO_region ( t->a.s1.A1, t->a.s1.Reg, t->a.s1.II, t->a.s1.iii ) != NULL )
47 {
48 // copy the results in part A to parts A,B and C
49 strcpy ( t->b.s1.A1, t->a.s1.A1 );
50 strcpy ( t->c.s1.A1, t->a.s1.A1 );
51 strcpy ( t->d.s1.A1, t->a.s1.A1 );
52 strcpy ( t->b.s1.Reg, t->a.s1.Reg );
53 strcpy ( t->c.s1.Reg, t->a.s1.Reg );
54 strcpy ( t->d.s1.Reg, t->a.s1.Reg );
55 return t->a.s1.A1;
56 }
57 else
58 {
59 return NULL;
60 }
61}
62
63
64
65/*!
66 \fn int parse_subset_as_temp(struct metreport *m, char *type, struct bufr_subset_sequence_data *sq, char *err)
67 \brief parses a subset sequence as an Land fixed TEMP FM-35, TEMP SHIP FM-36, TEMP DROP FM-37 or TEMP MOBIL FM-38 report
68 \param m pointer to a struct \ref metreport where set some results
69 \param type strint with MiMiMjMj to choose the type of temp, temp ship, temp drop or temp mobil)
70 \param sq pointer to a struct \ref bufr_subset_sequence_data with the parsed sequence on input
71 \param err string with detected errors, if any
72
73 It return 0 if all is OK. Otherwise returns 1 and it also fills the \a err string
74*/
75int parse_subset_as_temp ( struct metreport *m, struct bufr2tac_subset_state *s, struct bufr_subset_sequence_data *sq, char *err )
76{
77 size_t is;
78 char aux[32];
79 struct temp_chunks *t;
80 struct met_datetime dtm;
81 struct temp_raw_data *r;
83
84 if ( sq == NULL )
85 {
86 return 1;
87 }
88
89 t = &m->temp;
90
91 // clean data
93
94 // allocate memory for array of points in raw form
95 if ( ( r = calloc ( 1, sizeof ( struct temp_raw_data ) ) ) == NULL )
96 {
97 sprintf ( err,"bufr2tac: parse_subset_as_temp(): Cannot allocate memory for raw data" );
98 return 1;
99 }
100
101 if ( ( w = calloc ( 1, sizeof ( struct temp_raw_wind_shear_data ) ) ) == NULL )
102 {
103 sprintf ( err,"bufr2tac: parse_subset_as_temp(): Cannot allocate memory for raw data" );
104 free ( ( void * ) ( r ) );
105 return 1;
106 }
107
108 // set pointers
109 s->r = r;
110 s->w = w;
111
112 // reject if still not coded type
113 if ( strcmp ( s->type_report,"TTXX" ) == 0 && 0 )
114 {
115 // FIXME
116 sprintf ( err,"bufr2tac: parse_subset_as_temp(): '%s' reports still not decoded in this software", s->type_report );
117 free ( ( void * ) ( r ) );
118 free ( ( void * ) ( w ) );
119 return 1;
120 }
121
122 // Set the part. We are sure of this
123 strcpy ( t->a.s1.MjMj, "AA" );
124 strcpy ( t->b.s1.MjMj, "BB" );
125 strcpy ( t->c.s1.MjMj, "CC" );
126 strcpy ( t->d.s1.MjMj, "DD" );
127
128 /**** First pass, sequential analysis *****/
129 for ( is = 0; is < sq->nd; is++ )
130 {
131 s->i = is;
132 s->ival = ( int ) sq->sequence[is].val;
133 s->val = sq->sequence[is].val;
134 s->a = &sq->sequence[is];
135 if ( is > 0 )
136 {
137 s->a1 = &sq->sequence[is - 1];
138 }
139
140 // check if is a significance qualifier
141 if ( sq->sequence[is].desc.x == 8 )
142 {
143 temp_parse_x08 ( t, s );
144 }
145
146 switch ( sq->sequence[is].desc.x )
147 {
148 case 1: //localization descriptors
149 if ( temp_parse_x01 ( t, s ) )
150 {
151 free ( ( void * ) ( r ) );
152 free ( ( void * ) ( w ) );
153 return 1;
154 }
155 break;
156
157 case 2: //Type of station descriptors
158 if ( temp_parse_x02 ( t, s ) )
159 {
160 free ( ( void * ) ( r ) );
161 free ( ( void * ) ( w ) );
162 return 1;
163 }
164 break;
165
166 case 4: //Date and time descriptors
167 if ( temp_parse_x04 ( t, s ) )
168 {
169 free ( ( void * ) ( r ) );
170 free ( ( void * ) ( w ) );
171 return 1;
172 }
173 break;
174
175 case 5: // Horizontal position. Latitude
176 if ( temp_parse_x05 ( t, s ) )
177 {
178 free ( ( void * ) ( r ) );
179 free ( ( void * ) ( w ) );
180 return 1;
181 }
182 break;
183
184 case 6: // Horizontal position. Longitude
185 if ( temp_parse_x06 ( t, s ) )
186 {
187 free ( ( void * ) ( r ) );
188 free ( ( void * ) ( w ) );
189 return 1;
190 }
191 break;
192
193 case 7: // Vertical position
194 if ( temp_parse_x07 ( t, s ) )
195 {
196 free ( ( void * ) ( r ) );
197 free ( ( void * ) ( w ) );
198 return 1;
199 }
200 break;
201
202 case 10: // Air Pressure descriptors
203 if ( temp_parse_x10 ( t, s ) )
204 {
205 free ( ( void * ) ( r ) );
206 free ( ( void * ) ( w ) );
207 return 1;
208 }
209 break;
210
211 case 11: // wind data
212 if ( temp_parse_x11 ( t, s ) )
213 {
214 free ( ( void * ) ( r ) );
215 free ( ( void * ) ( w ) );
216 return 1;
217 }
218 break;
219
220 case 12: //Temperature descriptors
221 if ( temp_parse_x12 ( t, s ) )
222 {
223 free ( ( void * ) ( r ) );
224 free ( ( void * ) ( w ) );
225 return 1;
226 }
227 break;
228
229 case 20: // Cloud data
230 if ( temp_parse_x20 ( t, s ) )
231 {
232 free ( ( void * ) ( r ) );
233 free ( ( void * ) ( w ) );
234 return 1;
235 }
236 break;
237
238 case 22: // Oceanographic data
239 if ( temp_parse_x22 ( t, s ) )
240 {
241 free ( ( void * ) ( r ) );
242 free ( ( void * ) ( w ) );
243 return 1;
244 }
245 break;
246
247 case 31: // Replicators
248 if ( temp_parse_x31 ( t, s ) )
249 {
250 free ( ( void * ) ( r ) );
251 free ( ( void * ) ( w ) );
252 return 1;
253 }
254 break;
255
256 case 33: // Quality data
257 if ( temp_parse_x33 ( t, s ) )
258 {
259 free ( ( void * ) ( r ) );
260 free ( ( void * ) ( w ) );
261 return 1;
262 }
263 break;
264
265 default:
266 break;
267 }
268 }
269
270 /* Check about needed descriptors */
271 if ( ( ( s->mask & SUBSET_MASK_HAVE_LATITUDE ) == 0 ) ||
272 ( ( s->mask & SUBSET_MASK_HAVE_LONGITUDE ) == 0 ) ||
273 ( ( s->mask & SUBSET_MASK_HAVE_YEAR ) == 0 ) ||
274 ( ( s->mask & SUBSET_MASK_HAVE_MONTH ) == 0 ) ||
275 ( ( s->mask & SUBSET_MASK_HAVE_DAY ) == 0 ) ||
276 ( ( s->mask & SUBSET_MASK_HAVE_HOUR ) == 0 ) ||
277 ( ( s->mask & SUBSET_MASK_HAVE_MINUTE ) == 0 )
278 )
279 {
280 sprintf ( err,"bufr2tac: parse_subset_as_temp(): lack of mandatory descriptor in sequence" );
281 free ( ( void * ) ( r ) );
282 free ( ( void * ) ( w ) );
283 return 1;
284 }
285
286 // copy WIGOS ID
287 memcpy(&m->g.wid, &m->temp.wid, sizeof (struct wigos_id) );
288
289 /* Guess the type of TEMP report according with data parsed */
290 if ( t->a.s1.II[0] )
291 {
292 // it seems this is a TEMP report
293 strcpy ( t->a.s1.MiMi, "TT" );
294 strcpy ( t->b.s1.MiMi, "TT" );
295 strcpy ( t->c.s1.MiMi, "TT" );
296 strcpy ( t->d.s1.MiMi, "TT" );
297 }
298 else if ( t->a.s1.h0h0h0h0[0] )
299 {
300 // it seems this is a TEMP MOBIL report
301 strcpy ( t->a.s1.MiMi, "II" );
302 strcpy ( t->b.s1.MiMi, "II" );
303 strcpy ( t->c.s1.MiMi, "II" );
304 strcpy ( t->d.s1.MiMi, "II" );
305 }
306 else if ( t->a.s1.D_D[0] )
307 {
308 // it seems this is a TEMP SHIP report
309 strcpy ( t->a.s1.MiMi, "UU" );
310 strcpy ( t->b.s1.MiMi, "UU" );
311 strcpy ( t->c.s1.MiMi, "UU" );
312 strcpy ( t->d.s1.MiMi, "UU" );
313 }
314 else if ( t->a.s1.Ula[0] )
315 {
316 // it seems this is a TEMP DROP report
317 strcpy ( t->a.s1.MiMi, "XX" );
318 strcpy ( t->b.s1.MiMi, "XX" );
319 strcpy ( t->c.s1.MiMi, "XX" );
320 strcpy ( t->d.s1.MiMi, "XX" );
321 }
322 else
323 {
324 sprintf ( err,"bufr2tac: parse_subset_as_temp(): Unknown type TEMP report" );
325 free ( ( void * ) ( r ) );
326 free ( ( void * ) ( w ) );
327 return 1;
328 }
329 sprintf ( m->type, "%s%s" , t->a.s1.MiMi, t->a.s1.MjMj );
330 sprintf ( m->type2, "%s%s" , t->b.s1.MiMi, t->b.s1.MjMj );
331 sprintf ( m->type3, "%s%s" , t->c.s1.MiMi, t->c.s1.MjMj );
332 sprintf ( m->type4, "%s%s" , t->d.s1.MiMi, t->d.s1.MjMj );
333
334 /****** Second pass. Global results and consistence analysis ************/
335 sprintf ( aux,"%s%s%s%s%s%s", t->a.e.YYYY, t->a.e.MM, t->a.e.DD, t->a.e.HH, t->a.e.mm, t->a.e.ss );
336 YYYYMMDDHHmm_to_met_datetime ( &dtm, aux );
337 round_met_datetime_to_hour ( &m->t, &dtm );
338 memcpy ( &m->temp.t, &m->t, sizeof ( struct met_datetime ) );
339
340 met_datetime_to_YYGG ( t->a.s1.YYGG, &dtm );
341 strcpy ( t->b.s1.YYGG, t->a.s1.YYGG );
342 strcpy ( t->c.s1.YYGG, t->a.s1.YYGG );
343 strcpy ( t->d.s1.YYGG, t->a.s1.YYGG );
344
345 if ( strlen ( t->a.s1.II ) )
346 {
347 strcpy ( m->g.index, t->a.s1.II );
348 strcat ( m->g.index, t->a.s1.iii );
349 }
350 else if ( strlen ( t->a.s1.D_D ) )
351 {
352 strcpy ( m->g.index, t->a.s1.D_D );
353 }
354 else if ( strlen ( t->a.s1.IIIII ) )
355 {
356 strcpy ( m->g.index, t->a.s1.IIIII );
357 }
358
360 {
361 m->g.lat = s->lat;
362 }
364 {
365 m->g.lon = s->lon;
366 }
368 {
369 m->g.alt = s->alt;
370 }
371 if ( s->mask & SUBSET_MASK_HAVE_NAME )
372 {
373 strcpy ( m->g.name, s->name );
374 }
376 {
377 strcpy ( m->g.country, s->country );
378 }
379
380 //print_temp_raw_data ( r );
381 //print_temp_raw_wind_shear_data ( w );
382
383 // Finally parse raw data to fill all needed points for a TEMP
384 if ( parse_temp_raw_data ( t, r ) )
385 {
386 sprintf ( err,"bufr2tac: parse_temp_raw_data(): Too much significant points" );
387 free ( ( void * ) ( r ) );
388 free ( ( void * ) ( w ) );
389 return 1;
390 }
392
393 // Free memory
394 free ( ( void * ) ( r ) );
395 free ( ( void * ) ( w ) );
396 return 0;
397}
398
399/*!
400 \fn int parse_temp_raw_data ( struct temp_chunks *t, struct temp_raw_data *r )
401 \brief parse a struct \ref temp_raw_data to fill chunks in a struct \ref temp_chunks
402*/
404{
405 int ix, is_over_100;
406 size_t i, j, isa = 0, isc = 0, ita = 0, itc = 0; // level counters
407 size_t iwxa = 0, iwxc = 0, itb = 0, itd = 0;
408 size_t iwd = 0, iwb = 0;
409 size_t isav = 0, iscv = 0; // valid data counters for standard levels
410 struct temp_raw_point_data *d;
411
412 if ( t == NULL || r == NULL )
413 {
414 return 1;
415 }
416
417 if ( r->n == 0 )
418 {
419 return 1;
420 }
421
422 // Some default
423 t->a.s1.id[0] = '/';
424 t->c.s1.id[0] = '/';
425 for ( i = 0; i < r->n; i++ )
426 {
427 d = & ( r->raw[i] ); // to make code easy
428
429 if ( d->p < 10000.0 ) // to select which part
430 {
431 is_over_100 = 1;
432 }
433 else
434 {
435 is_over_100 = 0;
436 }
437
438 // Surface data
440 {
441 pascal_to_pnpnpn ( t->a.s2.lev0.PnPnPn, d->p ); //PoPoPo
442 kelvin_to_TTTa ( t->a.s2.lev0.TnTnTan, d->T ); // TnTnTan
443 dewpoint_depression_to_DnDn ( t->a.s2.lev0.DnDn, d->T , d->Td ); // DnDn
444 wind_to_dndnfnfnfn ( t->a.s2.lev0.dndnfnfnfn, d->dd, d->ff ); // dndnfnfnfn
445 }
446
447 // standard level
449 {
450 ix = ( int ) ( d->p * 0.01 + 0.5 ); // hPa
451 ix = ( ix / 10 ) % 100; // coded
452 if ( is_over_100 )
453 {
454 sprintf ( t->c.s2.std[isc].PnPn, "%02d", ix ); // PnPn
455 }
456 else
457 {
458 sprintf ( t->a.s2.std[isa].PnPn, "%02d", ix ); // PnPn
459 }
460
461 ix = ( int ) ( d->h + 0.5 );
462 if ( d->p <= 50000.0 )
463 {
464 if ( is_over_100 )
465 {
466 sprintf ( t->c.s2.std[isc].hnhnhn, "%03d", ( ( ix + 5 ) / 10 ) % 1000 );
467 }
468 else
469 {
470 sprintf ( t->a.s2.std[isa].hnhnhn, "%03d", ( ( ix + 5 ) / 10 ) % 1000 );
471 }
472 }
473 else
474 {
475 if ( is_over_100 )
476 {
477 sprintf ( t->c.s2.std[isc].hnhnhn, "%03d", ix % 1000 );
478 }
479 else if ( ix >= 0 )
480 {
481 sprintf ( t->a.s2.std[isa].hnhnhn, "%03d", ix % 1000 );
482 }
483 else
484 {
485 sprintf ( t->a.s2.std[isa].hnhnhn, "%03d", ( -ix + 500 ) % 1000 );
486 }
487 }
488 if ( is_over_100 )
489 {
490 kelvin_to_TTTa ( t->c.s2.std[isc].TnTnTan, d->T ); // TnTnTan
491 dewpoint_depression_to_DnDn ( t->c.s2.std[isc].DnDn, d->T, d->Td ); // DnDn
492 wind_to_dndnfnfnfn ( t->c.s2.std[isc].dndnfnfnfn, d->dd, d->ff ); // dndnfnfnfn
493 // Now update Id
494 if ( d->ff != MISSING_REAL && d->dd != MISSING_REAL )
495 {
496 t->c.s1.id[0] = t->c.s2.std[isc].PnPn[0];
497 }
498 if ( isc < TEMP_NSTAND_MAX )
499 {
500 isc += 1;
501 t->c.s2.n = isc;
502 }
503 else
504 return 1;
505
506 if ( d->T != MISSING_REAL || d->Td != MISSING_REAL ||
507 d->ff != MISSING_REAL || d->dd != MISSING_REAL )
508 {
509 // data present
510 iscv += 1;
511 }
512 }
513 else
514 {
515 kelvin_to_TTTa ( t->a.s2.std[isa].TnTnTan, d->T ); // TnTnTan
516 dewpoint_depression_to_DnDn ( t->a.s2.std[isa].DnDn, d->T , d->Td ); // DnDn
517 wind_to_dndnfnfnfn ( t->a.s2.std[isa].dndnfnfnfn, d->dd, d->ff ); // dndnfnfnfn
518 // Now update Id
519 if ( d->ff != MISSING_REAL && d->dd != MISSING_REAL )
520 {
521 t->a.s1.id[0] = t->a.s2.std[isa].PnPn[0];
522 }
523 if ( isa < TEMP_NSTAND_MAX )
524 {
525 isa += 1;
526 t->a.s2.n = isa;
527 }
528 else
529 return 1;
530
531 if ( d->T != MISSING_REAL || d->Td != MISSING_REAL ||
532 d->ff != MISSING_REAL || d->dd != MISSING_REAL )
533 {
534 // data present
535 isav += 1;
536 }
537 }
538 }
539
540 // Tropopause level
542 {
543 if ( is_over_100 )
544 {
545 ix = ( int ) ( d->p * 0.1 + 0.5 );
546 sprintf ( t->c.s3.trop[itc].PnPnPn, "%03d", ix % 1000 ); // PnPnPn
547 kelvin_to_TTTa ( t->c.s3.trop[itc].TnTnTan, d->T ); // TnTnTan
548 dewpoint_depression_to_DnDn ( t->c.s3.trop[itc].DnDn, d->T , d->Td ); // DnDn
549 wind_to_dndnfnfnfn ( t->c.s3.trop[itc].dndnfnfnfn, d->dd, d->ff ); // dndnfnfnfn
550 if ( ix && itc < TEMP_NTROP_MAX )
551 {
552 itc += 1;
553 t->c.s3.n = itc;
554 }
555 else
556 return 1;
557 }
558 else
559 {
560 ix = ( int ) ( d->p * 0.01 + 0.5 );
561 sprintf ( t->a.s3.trop[ita].PnPnPn, "%03d", ix % 1000 ); // PnPnPn.
562 kelvin_to_TTTa ( t->a.s3.trop[ita].TnTnTan, d->T ); // TnTnTan
563 dewpoint_depression_to_DnDn ( t->a.s3.trop[ita].DnDn, d->T , d->Td ); // DnDn
564 wind_to_dndnfnfnfn ( t->a.s3.trop[ita].dndnfnfnfn, d->dd, d->ff ); // dndnfnfnfn
565 if ( ix && ita < TEMP_NTROP_MAX )
566 {
567 ita += 1;
568 t->a.s3.n = ita;
569 }
570 else
571 return 1;
572 }
573 }
574
575 // Max wind level
577 {
578 if ( is_over_100 )
579 {
580 ix = ( int ) ( d->p * 0.1 + 0.5 );
581 sprintf ( t->c.s4.windx[iwxc].PmPmPm, "%03d", ix % 1000 ); // PnPnPn
582 wind_to_dndnfnfnfn ( t->c.s4.windx[iwxc].dmdmfmfmfm, d->dd, d->ff ); // dndnfnfnfn
583 // check if more wind data
584 for ( j = i + 1; j < r->n ; j++ )
585 {
586 if ( r->raw[j].ff != MISSING_REAL )
587 {
588 t->c.s4.windx[iwxc].no_last_wind = 1;
589 break;
590 }
591 }
592 if ( ix && iwxc < TEMP_NMAXWIND_MAX )
593 {
594 iwxc += 1;
595 t->c.s4.n = iwxc;
596 }
597 else
598 return 1;
599 }
600 else
601 {
602 ix = ( int ) ( d->p * 0.01 + 0.5 );
603 sprintf ( t->a.s4.windx[iwxa].PmPmPm, "%03d", ix % 1000 ); // PnPnPn.
604 wind_to_dndnfnfnfn ( t->a.s4.windx[iwxa].dmdmfmfmfm, d->dd, d->ff ); // dndnfnfnfn
605 for ( j = i + 1; j < r->n ; j++ )
606 {
607 if ( r->raw[j].ff != MISSING_REAL )
608 {
609 t->a.s4.windx[iwxa].no_last_wind = 1;
610 break;
611 }
612 }
613 if ( ix && iwxa < TEMP_NMAXWIND_MAX )
614 {
615 iwxa += 1;
616 t->a.s4.n = iwxa;
617 }
618 else
619 return 1;
620 }
621 }
622
623 // Significant TH points
625 {
626 if ( is_over_100 )
627 {
628 sprintf ( t->d.s5.th[itd].nini, "%d%d", ( ( int ) itd ) %9 + 1, ( ( int ) itd ) %9 + 1 );
629 ix = ( int ) ( d->p * 0.1 + 0.5 );
630 sprintf ( t->d.s5.th[itd].PnPnPn, "%03d", ix ); // PnPnPn
631 kelvin_to_TTTa ( t->d.s5.th[itd].TnTnTan, d->T ); // TnTnTan
632 dewpoint_depression_to_DnDn ( t->d.s5.th[itd].DnDn, d->T , d->Td ); // DnDn
633 if ( ix && itd < TEMP_NMAX_POINTS )
634 {
635 itd += 1;
636 t->d.s5.n = itd;
637 }
638 else
639 return 1;
640 }
641 else
642 {
644 {
645 strcpy ( t->b.s5.th[itb].nini, "00" ); // case of surface level
646 }
647 else
648 {
649 sprintf ( t->b.s5.th[itb].nini, "%d%d", ( ( int ) itb - 1 ) %9 + 1, ( ( int ) itb - 1 ) %9 + 1 );
650 }
651 ix = ( int ) ( d->p * 0.01 + 0.5 );
652 sprintf ( t->b.s5.th[itb].PnPnPn, "%03d", ix % 1000 ); // PnPnPn.
653 kelvin_to_TTTa ( t->b.s5.th[itb].TnTnTan, d->T ); // TnTnTan
654 dewpoint_depression_to_DnDn ( t->b.s5.th[itb].DnDn, d->T , d->Td ); // DnDn
655 if ( ix && itb < TEMP_NMAX_POINTS )
656 {
657 itb += 1;
658 t->b.s5.n = itb;
659 }
660 else
661 return 1;
662 }
663 }
664
665 // Significant wind points
667 {
668 if ( is_over_100 )
669 {
670 sprintf ( t->d.s6.wd[iwd].nini, "%d%d", ( ( int ) iwd ) %9 + 1, ( ( int ) iwd ) %9 + 1 );
671 ix = ( int ) ( d->p * 0.1 + 0.5 );
672 sprintf ( t->d.s6.wd[iwd].PnPnPn, "%03d", ix ); // PnPnPn
673 wind_to_dndnfnfnfn ( t->d.s6.wd[iwd].dndnfnfnfn, d->dd, d->ff ); // dndnfnfnfn
674 if ( ix && iwd < TEMP_NMAX_POINTS )
675 {
676 iwd += 1;
677 t->d.s6.n = iwd;
678 }
679 else
680 return 1;
681
682 }
683 else
684 {
686 {
687 strcpy ( t->b.s6.wd[iwb].nini, "00" ); // case of surface level
688 }
689 else
690 {
691 sprintf ( t->b.s6.wd[iwb].nini, "%d%d", ( ( int ) iwb - 1 ) %9 + 1, ( ( int ) iwb - 1 ) %9 + 1 );
692 }
693 ix = ( int ) ( d->p * 0.01 + 0.5 );
694 sprintf ( t->b.s6.wd[iwb].PnPnPn, "%03d", ix % 1000 ); // PnPnPn.
695 wind_to_dndnfnfnfn ( t->b.s6.wd[iwb].dndnfnfnfn, d->dd, d->ff ); // dndnfnfnfn
696 if ( ix && iwb < TEMP_NMAX_POINTS )
697 {
698 iwb += 1;
699 t->b.s6.n = iwb;
700 //printf("%lu\n", t->b.s6.n);
701 }
702 else
703 return 1;
704 }
705 }
706 }
707
708 // Now we set some bit masks
709 if ( isav )
710 {
711 t->a.mask |= TEMP_SEC_2;
712 }
713 if ( iscv )
714 {
715 t->c.mask |= TEMP_SEC_2;
716 }
717 if ( ita )
718 {
719 t->a.mask |= TEMP_SEC_3;
720 }
721 if ( itc )
722 {
723 t->c.mask |= TEMP_SEC_3;
724 }
725 if ( iwxa )
726 {
727 t->a.mask |= TEMP_SEC_4;
728 }
729 if ( iwxc )
730 {
731 t->c.mask |= TEMP_SEC_4;
732 }
733 if ( itb )
734 {
735 t->b.mask |= TEMP_SEC_5;
736 }
737 if ( itd )
738 {
739 t->d.mask |= TEMP_SEC_5;
740 }
741 if ( iwb )
742 {
743 t->b.mask |= TEMP_SEC_6;
744 }
745 if ( iwd )
746 {
747 t->d.mask |= TEMP_SEC_6;
748 }
749
750 return 0;
751}
752
753/*!
754 \fn int parse_temp_raw_wind_shear_data (struct temp_chunks *t, struct temp_raw_wind_shear_data *w )
755
756*/
758{
759 size_t i, j;
760 int ix, is_over_100;
761 char aux[16];
762
764
765 if ( t == NULL || w == NULL )
766 {
767 return 1;
768 }
769
770 if ( w->n == 0 )
771 {
772 return 1;
773 }
774
775 for ( i = 0; i < w->n; i++ )
776 {
777 d = & ( w->raw[i] ); // to make code easy
778
779 if ( d->p < 10000.0 ) // to select which part
780 {
781 is_over_100 = 1;
782 }
783 else
784 {
785 is_over_100 = 0;
786 }
787
788 // set pnpnpn on aux
789 if ( is_over_100 )
790 {
791 if ( t ->c.s4.n == 0 )
792 {
793 continue;
794 }
795
796 ix = ( int ) ( d->p * 0.1 + 0.5 );
797 sprintf ( aux, "%03d", ix % 1000 ); // PnPnPn
798
799 // checks for a significant wind level in section 4 with same pnpnpn
800 for ( j = 0 ; j < t->c.s4.n ; j++ )
801 {
802 if ( strcmp ( t->c.s4.windx[j].PmPmPm , aux ) == 0 )
803 {
804 if ( d->ws_blw != MISSING_REAL )
805 {
806 sprintf ( t->c.s4.windx[j].vbvb, "%02.0lf", d->ws_blw );
807 }
808 if ( d->ws_abv != MISSING_REAL )
809 {
810 sprintf ( t->c.s4.windx[j].vava, "%02.0lf", d->ws_abv );
811 }
812 break;
813 }
814 }
815 }
816 else
817 {
818 if ( t ->a.s4.n == 0 )
819 {
820 continue;
821 }
822 ix = ( int ) ( d->p * 0.01 + 0.5 );
823 sprintf ( aux, "%03d", ix % 1000 ); // PnPnPn.
824 // checks for a significant wind level in section 4 with same pnpnpn
825 for ( j = 0 ; j < t->a.s4.n ; j++ )
826 {
827 if ( strcmp ( t->a.s4.windx[j].PmPmPm , aux ) == 0 )
828 {
829 //printf("%s %s\n", aux, t->a.s4.windx[j].PmPmPm);
830 //printf("%.1lf %.1lf\n", d->ws_blw, d->ws_abv);
831 if ( d->ws_blw != MISSING_REAL )
832 {
833 sprintf ( t->a.s4.windx[j].vbvb, "%02.0lf", d->ws_blw );
834 }
835 if ( d->ws_abv != MISSING_REAL )
836 {
837 sprintf ( t->a.s4.windx[j].vava, "%02.0lf", d->ws_abv );
838 }
839 break;
840 }
841 }
842 }
843 }
844
845 return 0;
846}
Include header file for binary bufr2tac.
#define SUBSET_MASK_HAVE_MONTH
Bit mask to mark a struct bufr_subset_sequence_data having observation month.
Definition: bufr2tac.h:146
char * met_datetime_to_YYGG(char *target, struct met_datetime *t)
Get YYGG from a struct met_datetime.
int temp_parse_x33(struct temp_chunks *t, struct bufr2tac_subset_state *s)
Parse a expanded descriptor with X = 33.
Definition: bufr2tac_x33.c:100
#define SUBSET_MASK_HAVE_COUNTRY
Bit mask to mark a struct bufr_subset_sequence_data having country name.
Definition: bufr2tac.h:134
char * dewpoint_depression_to_DnDn(char *target, double T, double Td)
Set DnDn (dewpoint depression)
Definition: bufr2tac_x12.c:179
void bufr2tac_clean_temp_chunks(struct temp_chunks *t)
cleans a buoy_chunks struct
int temp_parse_x11(struct temp_chunks *t, struct bufr2tac_subset_state *s)
Parse a expanded descriptor with X = 11.
Definition: bufr2tac_x11.c:500
int temp_parse_x05(struct temp_chunks *t, struct bufr2tac_subset_state *s)
Definition: bufr2tac_x05.c:204
char * guess_WMO_region(char *A1, char *Reg, const char *II, const char *iii)
get WMO region A1 and Reg items from II and iii (WMO index)
#define SUBSET_MASK_HAVE_MINUTE
Bit mask to mark a struct bufr_subset_sequence_data having observation minute.
Definition: bufr2tac.h:164
char * kelvin_to_TTTa(char *target, double T)
Set temperature TTTa.
Definition: bufr2tac_x12.c:147
#define SUBSET_MASK_HAVE_NAME
Bit mask to mark a struct bufr_subset_sequence_data having station name.
Definition: bufr2tac.h:128
#define bufr_subset_sequence_data
To use bufrdeco library with legacy old code using ECMWF library which is not used currently.
Definition: bufr2tac.h:220
char * wind_to_dndnfnfnfn(char *target, double dd, double ff)
Definition: bufr2tac_x11.c:93
char * pascal_to_pnpnpn(char *target, double P)
Definition: bufr2tac_x10.c:47
#define SUBSET_MASK_HAVE_ALTITUDE
Bit mask to mark a struct bufr_subset_sequence_data having altitude.
Definition: bufr2tac.h:122
int temp_parse_x07(struct temp_chunks *t, struct bufr2tac_subset_state *s)
Definition: bufr2tac_x07.c:258
int temp_parse_x04(struct temp_chunks *t, struct bufr2tac_subset_state *s)
Parse a expanded descriptor with X = 04.
Definition: bufr2tac_x04.c:575
int temp_parse_x20(struct temp_chunks *t, struct bufr2tac_subset_state *s)
Parse a expanded descriptor with X = 20.
int temp_parse_x12(struct temp_chunks *t, struct bufr2tac_subset_state *s)
Parse a expanded descriptor with X = 12.
Definition: bufr2tac_x12.c:751
#define SUBSET_MASK_HAVE_YEAR
Bit mask to mark a struct bufr_subset_sequence_data having observation year.
Definition: bufr2tac.h:140
int YYYYMMDDHHmm_to_met_datetime(struct met_datetime *t, const char *source)
Parse the string YYYYMMDDHHmm[ss] and set a struct met_datetime.
int temp_parse_x31(struct temp_chunks *t, struct bufr2tac_subset_state *s)
Parse a expanded descriptor with X = 31.
Definition: bufr2tac_x31.c:120
int round_met_datetime_to_hour(struct met_datetime *target, struct met_datetime *source)
int temp_parse_x01(struct temp_chunks *t, struct bufr2tac_subset_state *s)
Parse a expanded descriptor with X = 01.
Definition: bufr2tac_x01.c:415
int temp_parse_x22(struct temp_chunks *t, struct bufr2tac_subset_state *s)
Parse a expanded descriptor with X = 22.
Definition: bufr2tac_x22.c:289
int temp_parse_x02(struct temp_chunks *t, struct bufr2tac_subset_state *s)
Parse a expanded descriptor with X = 02.
Definition: bufr2tac_x02.c:187
#define SUBSET_MASK_HAVE_LONGITUDE
Bit mask to mark a struct bufr_subset_sequence_data having longitude.
Definition: bufr2tac.h:116
int temp_parse_x06(struct temp_chunks *t, struct bufr2tac_subset_state *s)
Definition: bufr2tac_x06.c:200
#define SUBSET_MASK_HAVE_LATITUDE
Bit mask to mark a struct bufr_subset_sequence_data having latitude.
Definition: bufr2tac.h:110
int temp_parse_x08(struct temp_chunks *t, struct bufr2tac_subset_state *s)
Parse a expanded descriptor with X = 08.
Definition: bufr2tac_x08.c:421
int temp_parse_x10(struct temp_chunks *t, struct bufr2tac_subset_state *s)
Parse a expanded descriptor with X = 10.
Definition: bufr2tac_x10.c:297
#define SUBSET_MASK_HAVE_DAY
Bit mask to mark a struct bufr_subset_sequence_data having observation day in a month.
Definition: bufr2tac.h:152
#define SUBSET_MASK_HAVE_HOUR
Bit mask to mark a struct bufr_subset_sequence_data having observation hour.
Definition: bufr2tac.h:158
int parse_temp_raw_data(struct temp_chunks *t, struct temp_raw_data *r)
parse a struct temp_raw_data to fill chunks in a struct temp_chunks
int parse_subset_as_temp(struct metreport *m, struct bufr2tac_subset_state *s, struct bufr_subset_sequence_data *sq, char *err)
Definition: bufr2tac_temp.c:75
int parse_temp_raw_wind_shear_data(struct temp_chunks *t, struct temp_raw_wind_shear_data *w)
char * guess_WMO_region_temp(struct temp_chunks *t)
Definition: bufr2tac_temp.c:34
#define MISSING_REAL
The missing default value for real values.
Definition: bufrdeco.h:78
#define TEMP_POINT_MASK_SIGNIFICANT_TEMPERATURE_LEVEL
Definition: mettemp.h:176
#define TEMP_SEC_6
mask bit meaning sec 6 of a part of TEMP report parsed with success
Definition: mettemp.h:89
#define TEMP_NTROP_MAX
Maximum number of standard levels in any part of a TEMP report.
Definition: mettemp.h:125
#define TEMP_POINT_MASK_MAXIMUM_WIND_LEVEL
Definition: mettemp.h:175
#define TEMP_SEC_4
mask bit meaning sec 4 of a part of TEMP report parsed with success
Definition: mettemp.h:77
#define TEMP_SEC_5
mask bit meaning sec 5 of a part of TEMP report parsed with success
Definition: mettemp.h:83
#define TEMP_POINT_MASK_TROPOPAUSE_LEVEL
Definition: mettemp.h:174
#define TEMP_SEC_2
mask bit meaning sec 2 of a part of TEMP report parsed with success
Definition: mettemp.h:65
#define TEMP_POINT_MASK_SIGNIFICANT_WIND_LEVEL
Definition: mettemp.h:178
#define TEMP_POINT_MASK_SURFACE
Definition: mettemp.h:172
#define TEMP_NMAX_POINTS
maximum number of significant points
Definition: mettemp.h:138
#define TEMP_POINT_MASK_SIGNIFICANT_HUMIDITY_LEVEL
Definition: mettemp.h:177
#define TEMP_SEC_3
mask bit meaning sec 3 of a part of TEMP report parsed with success
Definition: mettemp.h:71
#define TEMP_NSTAND_MAX
Maximum number of standard levels in any part of a TEMP report.
Definition: mettemp.h:119
#define TEMP_NMAXWIND_MAX
Maximum number of mwx wind level in any part of a TEMP report.
Definition: mettemp.h:132
#define TEMP_POINT_MASK_STANDARD_LEVEL
Definition: mettemp.h:173
stores information needed to parse a sequential list of expanded descriptors for a subset
Definition: bufr2tac.h:246
struct temp_raw_wind_shear_data * w
Definition: bufr2tac.h:286
struct bufr_atom_data * a1
Definition: bufr2tac.h:250
struct bufr_atom_data * a
Definition: bufr2tac.h:249
char type_report[16]
Definition: bufr2tac.h:247
struct temp_raw_data * r
Definition: bufr2tac.h:285
stores date and time reference of a report, commonly the observation time
Definition: metcommon.h:60
double lat
Definition: bufr2tac.h:299
double lon
Definition: bufr2tac.h:300
double alt
Definition: bufr2tac.h:301
struct wigos_id wid
Definition: bufr2tac.h:295
char index[16]
Definition: bufr2tac.h:296
char name[80]
Definition: bufr2tac.h:297
char country[80]
Definition: bufr2tac.h:298
all the information for a meteorological report in WMO text format from a BUFR file
Definition: bufr2tac.h:309
char type4[8]
Definition: bufr2tac.h:326
struct temp_chunks temp
Definition: bufr2tac.h:318
char type[8]
Definition: bufr2tac.h:320
char type3[8]
Definition: bufr2tac.h:324
char type2[8]
Definition: bufr2tac.h:322
struct met_datetime t
Definition: bufr2tac.h:314
struct met_geo g
Definition: bufr2tac.h:315
char ss[4]
Definition: metcommon.h:38
char mm[4]
Definition: metcommon.h:37
char HH[4]
Definition: metcommon.h:36
char DD[4]
Definition: metcommon.h:35
char MM[4]
Definition: metcommon.h:34
char YYYY[6]
Definition: metcommon.h:33
struct temp_main_level_data lev0
Definition: mettemp.h:365
size_t n
Definition: mettemp.h:364
struct temp_std_level_data std[TEMP_NSTAND_MAX]
Definition: mettemp.h:366
int mask
Definition: mettemp.h:453
struct temp_ac_sec3 s3
Definition: mettemp.h:457
struct temp_acd_sec1 s1
Definition: mettemp.h:455
struct report_date_ext e
Definition: mettemp.h:454
struct temp_ac_sec4 s4
Definition: mettemp.h:458
struct temp_a_sec2 s2
Definition: mettemp.h:456
struct temp_main_level_data trop[TEMP_NTROP_MAX]
Definition: mettemp.h:386
size_t n
Definition: mettemp.h:385
struct temp_max_wind_data windx[TEMP_NMAXWIND_MAX]
Definition: mettemp.h:396
size_t n
Definition: mettemp.h:395
char Reg[4]
Definition: mettemp.h:319
char MiMi[4]
Definition: mettemp.h:310
char h0h0h0h0[6]
Definition: mettemp.h:327
char A1[2]
Definition: mettemp.h:312
char YYGG[8]
Definition: mettemp.h:315
char II[4]
Definition: mettemp.h:317
char D_D[10]
Definition: mettemp.h:314
char id[2]
Definition: mettemp.h:316
char MjMj[4]
Definition: mettemp.h:311
char IIIII[10]
Definition: mettemp.h:320
char Ula[2]
Definition: mettemp.h:325
char iii[4]
Definition: mettemp.h:318
char Reg[4]
Definition: mettemp.h:346
char A1[2]
Definition: mettemp.h:339
char YYGG[8]
Definition: mettemp.h:342
char MjMj[4]
Definition: mettemp.h:338
char MiMi[4]
Definition: mettemp.h:337
struct temp_b_sec1 s1
Definition: mettemp.h:470
struct temp_bd_sec5 s5
Definition: mettemp.h:471
int mask
Definition: mettemp.h:468
struct temp_bd_sec6 s6
Definition: mettemp.h:472
size_t n
Definition: mettemp.h:420
struct temp_th_point th[TEMP_NMAX_POINTS]
Definition: mettemp.h:421
size_t n
Definition: mettemp.h:430
struct temp_wind_point wd[TEMP_NMAX_POINTS]
Definition: mettemp.h:431
size_t n
Definition: mettemp.h:375
struct temp_std_level_data std[TEMP_NSTAND_MAX]
Definition: mettemp.h:376
struct temp_c_sec2 s2
Definition: mettemp.h:486
struct temp_ac_sec4 s4
Definition: mettemp.h:488
int mask
Definition: mettemp.h:483
struct temp_ac_sec3 s3
Definition: mettemp.h:487
struct temp_acd_sec1 s1
Definition: mettemp.h:485
Store the whole TEMP report.
Definition: mettemp.h:511
struct temp_c c
Definition: mettemp.h:517
struct met_datetime t
Definition: mettemp.h:513
struct temp_d d
Definition: mettemp.h:518
struct temp_b b
Definition: mettemp.h:516
struct wigos_id wid
Definition: mettemp.h:514
struct temp_a a
Definition: mettemp.h:515
struct temp_bd_sec6 s6
Definition: mettemp.h:502
int mask
Definition: mettemp.h:498
struct temp_acd_sec1 s1
Definition: mettemp.h:500
struct temp_bd_sec5 s5
Definition: mettemp.h:501
char dndnfnfnfn[8]
Definition: mettemp.h:252
char PmPmPm[4]
Definition: mettemp.h:275
char dmdmfmfmfm[8]
Definition: mettemp.h:276
Stores the array of all data profile points as it in bufr sequence.
Definition: mettemp.h:213
struct temp_raw_point_data raw[TEMP_NMAX_POINTS *4]
Definition: mettemp.h:215
size_t n
Definition: mettemp.h:214
Stores data of a sounding profile in raw format, as given in bufr.
Definition: mettemp.h:195
array of Wind shear data points at a pressure level
Definition: mettemp.h:238
struct temp_raw_wind_shear_point raw[TEMP_NMAX_POINTS]
Definition: mettemp.h:240
Wind shear data point at a pressure level.
Definition: mettemp.h:223
char dndnfnfnfn[8]
Definition: mettemp.h:265
char nini[4]
Definition: mettemp.h:287
char TnTnTan[4]
Definition: mettemp.h:289
char PnPnPn[4]
Definition: mettemp.h:288
char DnDn[4]
Definition: mettemp.h:290
char PnPnPn[4]
Definition: mettemp.h:300
char dndnfnfnfn[8]
Definition: mettemp.h:301
char nini[4]
Definition: mettemp.h:299
WIGOS station identifier.
Definition: metcommon.h:46