stream_ieg.c 33.5 KB
Newer Older
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1
2
3
4
#if defined (HAVE_CONFIG_H)
#  include "config.h"
#endif

5
#include <limits.h>
Thomas Jahns's avatar
Thomas Jahns committed
6
#include <stdbool.h>
Uwe Schulzweida's avatar
Uwe Schulzweida committed
7
#include <stdio.h>
8
#include <stdlib.h>
Uwe Schulzweida's avatar
Uwe Schulzweida committed
9
10
11
12
13
14
15
16
17
#include <string.h>
#include <float.h>
#include <math.h>

#include "dmemory.h"

#include "error.h"
#include "file.h"
#include "cdi.h"
18
#include "cdi_int.h"
Uwe Schulzweida's avatar
Uwe Schulzweida committed
19
20
21
#include "varscan.h"
#include "datetime.h"
#include "ieg.h"
22
#include "stream_ieg.h"
Uwe Schulzweida's avatar
Uwe Schulzweida committed
23
#include "vlist.h"
Uwe Schulzweida's avatar
Uwe Schulzweida committed
24
#include "exse.h"
Uwe Schulzweida's avatar
Uwe Schulzweida committed
25
26
27
28


#if defined (HAVE_LIBIEG)

29
typedef struct {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
30
  int param;
31
  int level;
32
} iegcompvar_t;
33
34


35
36
static
int iegInqDatatype(int prec)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
37
{
38
  return (prec == EXSE_DOUBLE_PRECISION) ? CDI_DATATYPE_FLT64 : CDI_DATATYPE_FLT32;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
39
40
}

41
42
static
int iegDefDatatype(int datatype)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
43
{
44
  if ( datatype == CDI_DATATYPE_CPX32 || datatype == CDI_DATATYPE_CPX64 )
45
    Error("CDI/IEG library does not support complex numbers!");
Uwe Schulzweida's avatar
Uwe Schulzweida committed
46

47
48
  if ( datatype != CDI_DATATYPE_FLT32 && datatype != CDI_DATATYPE_FLT64 )
    datatype = CDI_DATATYPE_FLT32;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
49

50
  return (datatype == CDI_DATATYPE_FLT64) ? EXSE_DOUBLE_PRECISION : EXSE_SINGLE_PRECISION;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
51
52
}

53
/* not used
54
int iegInqRecord(stream_t *streamptr, int *varID, int *levelID)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
55
56
57
{
  int status;
  int fileID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
58
  int icode, ilevel;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
59
60
  int zaxisID = -1;
  int vlistID;
61
  iegrec_t *iegp = (iegrec_t*) streamptr->record->exsep;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
62

Uwe Schulzweida's avatar
Uwe Schulzweida committed
63
64
  vlistID = streamptr->vlistID;
  fileID  = streamptr->fileID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
65
66
67
68
69

  *varID   = -1;
  *levelID = -1;

  status = iegRead(fileID, iegp);
70
  if ( status != 0 ) return 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
71

Uwe Schulzweida's avatar
Uwe Schulzweida committed
72
  icode  = IEG_P_Parameter(iegp->ipdb);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
73
74
75
76
77
  if ( IEG_P_LevelType(iegp->ipdb) == IEG_LTYPE_HYBRID_LAYER )
    ilevel = IEG_P_Level1(iegp->ipdb);
  else
    ilevel = IEG_P_Level2(iegp->ipdb);

Uwe Schulzweida's avatar
Uwe Schulzweida committed
78
  *varID = vlistInqVarID(vlistID, icode);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
79

80
  if ( *varID == CDI_UNDEFID ) Error("Code %d undefined", icode);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
81
82
83
84

  zaxisID = vlistInqVarZaxis(vlistID, *varID);

  *levelID = zaxisInqLevelID(zaxisID, (double) ilevel);
85

86
  return 1;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
87
}
88
*/
Uwe Schulzweida's avatar
Uwe Schulzweida committed
89

90
void iegReadRecord(stream_t *streamptr, double *data, int *nmiss)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
91
{
92
93
94
95
96
97
98
  int vlistID = streamptr->vlistID;
  int fileID  = streamptr->fileID;
  int tsID    = streamptr->curTsID;
  int vrecID  = streamptr->tsteps[tsID].curRecID;
  int recID   = streamptr->tsteps[tsID].recIDs[vrecID];
  int varID   = streamptr->tsteps[tsID].records[recID].varID;
  off_t recpos = streamptr->tsteps[tsID].records[recID].position;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
99
100
101

  fileSetPos(fileID, recpos, SEEK_SET);

102
  void *iegp = streamptr->record->exsep;
103
  int status = iegRead(fileID, iegp);
104
105
  if ( status != 0 )
    Error("Could not read IEG record!");
Uwe Schulzweida's avatar
Uwe Schulzweida committed
106
107
108

  iegInqDataDP(iegp, data);

109
110
111
  double missval = vlistInqVarMissval(vlistID, varID);
  int gridID  = vlistInqVarGrid(vlistID, varID);
  int size    = gridInqSize(gridID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
112

Uwe Schulzweida's avatar
Uwe Schulzweida committed
113
  streamptr->numvals += size;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
114
115

  *nmiss = 0;
116
  for ( int i = 0; i < size; i++ )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
117
118
119
120
121
122
123
    if ( DBL_IS_EQUAL(data[i], missval) || DBL_IS_EQUAL(data[i], (float)missval) )
      {
	data[i] = missval;
	(*nmiss)++;
      }
}

124
static
Uwe Schulzweida's avatar
Uwe Schulzweida committed
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
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
int iegGetZaxisType(int iegleveltype)
{
  int leveltype = 0;

  switch ( iegleveltype )
    {
    case IEG_LTYPE_SURFACE:
      {
	leveltype = ZAXIS_SURFACE;
	break;
      }
    case IEG_LTYPE_99:
    case IEG_LTYPE_ISOBARIC:
      {
	leveltype = ZAXIS_PRESSURE;
	break;
      }
    case IEG_LTYPE_HEIGHT:
      {
	leveltype = ZAXIS_HEIGHT;
	break;
      }
    case IEG_LTYPE_ALTITUDE:
      {
	leveltype = ZAXIS_ALTITUDE;
	break;
      }
    case IEG_LTYPE_HYBRID:
    case IEG_LTYPE_HYBRID_LAYER:
      {
	leveltype = ZAXIS_HYBRID;
	break;
      }
    case IEG_LTYPE_LANDDEPTH:
    case IEG_LTYPE_LANDDEPTH_LAYER:
      {
	leveltype = ZAXIS_DEPTH_BELOW_LAND;
	break;
      }
    case IEG_LTYPE_SEADEPTH:
      {
	leveltype = ZAXIS_DEPTH_BELOW_SEA;
	break;
      }
    default:
      {
	leveltype = ZAXIS_GENERIC;
	break;
      }
    }

176
  return leveltype;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
177
178
179
}


Thomas Jahns's avatar
Thomas Jahns committed
180
static void iegDefTime(int *pdb, int date, int time, int taxisID)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
181
182
{
  int timetype = -1;
183
  if ( taxisID != -1 ) timetype = taxisInqType(taxisID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
184
185
186

  if ( timetype == TAXIS_ABSOLUTE || timetype == TAXIS_RELATIVE )
    {
187
      int year, month, day, hour, minute, second;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
188
189
      cdiDecodeDate(date, &year, &month, &day);
      cdiDecodeTime(time, &hour, &minute, &second);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206

      IEG_P_Year(pdb)     = year;
      IEG_P_Month(pdb)    = month;
      IEG_P_Day(pdb)      = day;
      IEG_P_Hour(pdb)     = hour;
      IEG_P_Minute(pdb)   = minute;

      pdb[15] = 1;
      pdb[16] = 0;
      pdb[17] = 0;
      pdb[18] = 10;
      pdb[36] = 1;
    }

  pdb[5] = 128;
}

Thomas Jahns's avatar
Thomas Jahns committed
207
208
209
210
211
/* find smallest power of 10 in [1000,10000000] that upon
 * multiplication results in fractional part close to zero for all
 * arguments */
static double
calc_resfac(double xfirst, double xlast, double xinc, double yfirst, double ylast, double yinc)
212
{
Thomas Jahns's avatar
Thomas Jahns committed
213
214
215
216
217
218
219
220
221
222
  double resfac = 1000.0;
  enum {
    nPwrOf10 = 5,
    nMultTests = 6,
  };
  static const double scaleFactors[nPwrOf10]
    = { 1000, 10000, 100000, 1000000, 10000000 };
  double vals[nMultTests] = { xfirst, xlast, xinc, yfirst, ylast, yinc };

  for (size_t j = 0; j < nPwrOf10; ++j )
223
    {
Thomas Jahns's avatar
Thomas Jahns committed
224
225
226
      double scaleBy = scaleFactors[j];
      bool fractionalScale = false;
      for (size_t i = 0; i < nMultTests; ++i )
227
        {
Thomas Jahns's avatar
Thomas Jahns committed
228
229
          fractionalScale = fractionalScale
            || fabs(vals[i]*scaleBy - round(vals[i]*scaleBy)) > FLT_EPSILON;
230
        }
Thomas Jahns's avatar
Thomas Jahns committed
231
      if ( !fractionalScale )
232
        {
Thomas Jahns's avatar
Thomas Jahns committed
233
          resfac = scaleBy;
234
235
236
237
          break;
        }
    }

238
  return resfac;
239
240
}

241
static
Uwe Schulzweida's avatar
Uwe Schulzweida committed
242
243
void iegDefGrid(int *gdb, int gridID)
{
244
245
246
  int projID = gridInqProj(gridID);
  if ( projID != CDI_UNDEFID && gridInqProjType(projID) == CDI_PROJ_RLL ) gridID = projID;

247
  int gridtype = gridInqType(gridID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
248

249
250
251
252
253
254
  int projtype = CDI_UNDEFID;
  if ( gridtype == GRID_PROJECTION && gridInqProjType(gridID) == CDI_PROJ_RLL ) projtype = CDI_PROJ_RLL;

  int xsize = gridInqXsize(gridID);
  int ysize = gridInqYsize(gridID);

Uwe Schulzweida's avatar
Uwe Schulzweida committed
255
256
  if ( gridtype == GRID_GENERIC )
    {
257
      if ( (ysize == 32  || ysize == 48 || ysize == 64 ||
258
	    ysize == 96  || ysize == 160) &&
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
	   (xsize == 2*ysize || xsize == 1) )
	{
	  gridtype = GRID_GAUSSIAN;
	  gridChangeType(gridID, gridtype);
	}
      else if ( (xsize == 1 && ysize == 1) || (xsize == 0 && ysize == 0) )
	{
	  gridtype = GRID_LONLAT;
	  gridChangeType(gridID, gridtype);
	}
      else if ( gridInqXvals(gridID, NULL) && gridInqYvals(gridID, NULL) )
	{
	  gridtype = GRID_LONLAT;
	  gridChangeType(gridID, gridtype);
	}
Uwe Schulzweida's avatar
Uwe Schulzweida committed
274
275
276
277
278
279
    }
  else if ( gridtype == GRID_CURVILINEAR )
    {
      gridtype = GRID_LONLAT;
    }

280
  bool lrotated = (projtype == CDI_PROJ_RLL);
281
282

  if ( gridtype == GRID_LONLAT || gridtype == GRID_GAUSSIAN || projtype == CDI_PROJ_RLL )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
283
    {
284
285
      double xfirst = 0, xlast = 0, xinc = 0;
      double yfirst = 0, ylast = 0, yinc = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
286

287
      if ( xsize == 0 ) xsize = 1;
288
289
      else
	{
290
291
	  xfirst = gridInqXval(gridID,       0);
	  xlast  = gridInqXval(gridID, xsize-1);
292
293
294
	  xinc   = gridInqXinc(gridID);
	}

295
      if ( ysize == 0 ) ysize = 1;
296
297
      else
	{
298
299
	  yfirst = gridInqYval(gridID,       0);
	  ylast  = gridInqYval(gridID, ysize-1);
300
301
302
	  yinc   = gridInqYinc(gridID);
	}

303
304
      if ( gridtype == GRID_GAUSSIAN )
	IEG_G_GridType(gdb) = 4;
305
      else if ( lrotated )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
306
307
308
309
	IEG_G_GridType(gdb) = 10;
      else
	IEG_G_GridType(gdb) = 0;

Thomas Jahns's avatar
Thomas Jahns committed
310
311
      double resfac = calc_resfac(xfirst, xlast, xinc, yfirst, ylast, yinc);
      int iresfac = (int)resfac;
312
313
314
315
      if ( iresfac == 1000 ) iresfac = 0;

      IEG_G_ResFac(gdb)   = iresfac;

316
317
      IEG_G_NumLon(gdb)   = xsize;
      IEG_G_NumLat(gdb)   = ysize;
318
319
320
321
322
      IEG_G_FirstLat(gdb) = (int)lround(yfirst*resfac);
      IEG_G_LastLat(gdb)  = (int)lround(ylast*resfac);
      IEG_G_FirstLon(gdb) = (int)lround(xfirst*resfac);
      IEG_G_LastLon(gdb)  = (int)lround(xlast*resfac);
      IEG_G_LonIncr(gdb)  = (int)lround(xinc*resfac);
323
      if ( fabs(xinc*resfac - IEG_G_LonIncr(gdb)) > FLT_EPSILON )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
324
325
	IEG_G_LonIncr(gdb) = 0;

326
      if ( gridtype == GRID_GAUSSIAN )
327
	IEG_G_LatIncr(gdb) = ysize/2;
328
329
      else
	{
330
	  IEG_G_LatIncr(gdb) = (int)lround(yinc*resfac);
331
	  if ( fabs(yinc*resfac - IEG_G_LatIncr(gdb)) > FLT_EPSILON )
332
	    IEG_G_LatIncr(gdb) = 0;
333
334

	  if ( IEG_G_LatIncr(gdb) < 0 ) IEG_G_LatIncr(gdb) = -IEG_G_LatIncr(gdb);
335
	}
Uwe Schulzweida's avatar
Uwe Schulzweida committed
336

337
      if ( IEG_G_NumLon(gdb) > 1 && IEG_G_NumLat(gdb) == 1 )
338
339
	if ( IEG_G_LonIncr(gdb) != 0 && IEG_G_LatIncr(gdb) == 0 ) IEG_G_LatIncr(gdb) = IEG_G_LonIncr(gdb);

340
      if ( IEG_G_NumLon(gdb) == 1 && IEG_G_NumLat(gdb) > 1 )
341
342
	if ( IEG_G_LonIncr(gdb) == 0 && IEG_G_LatIncr(gdb) != 0 ) IEG_G_LonIncr(gdb) = IEG_G_LatIncr(gdb);

343
      IEG_G_ResFlag(gdb) = (IEG_G_LatIncr(gdb) == 0 || IEG_G_LonIncr(gdb) == 0) ? 0 : 128;
344

345
      if ( lrotated )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
346
	{
347
          double xpole = 0, ypole = 0, angle = 0;
348
          gridInqParamRLL(gridID, &xpole, &ypole, &angle);
349
350
351

	  IEG_G_LatSP(gdb) = - (int)lround(ypole * resfac);
	  IEG_G_LonSP(gdb) =   (int)lround((xpole + 180) * resfac);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
352
353
354
355
356
357
358
359
360
	  IEG_G_Size(gdb)  = 42;
	}
      else
	{
	  IEG_G_Size(gdb)  = 32;
	}
    }
  else
    {
361
      Error("Unsupported grid type: %s", gridNamePtr(gridtype));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
362
363
364
365
366
    }

  IEG_G_ScanFlag(gdb) = 64;
}

367
368
369
370
371
372
373
374
static
void pdbDefLevel(int *pdb, int leveltype, int level1, int level2)
{
  IEG_P_LevelType(pdb) = leveltype;
  IEG_P_Level1(pdb)    = level1;
  IEG_P_Level2(pdb)    = level2;
}

375
static
Uwe Schulzweida's avatar
Uwe Schulzweida committed
376
377
378
void iegDefLevel(int *pdb, int *gdb, double *vct, int zaxisID, int levelID)
{
  double level;
379
  int ilevel;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
380

381
  int leveltype = zaxisInqType(zaxisID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
382
383
384

  if ( leveltype == ZAXIS_GENERIC )
    {
385
      Message("Changed zaxis type from %s to %s",
386
	      zaxisNamePtr(leveltype), zaxisNamePtr(ZAXIS_PRESSURE));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
387
388
      leveltype = ZAXIS_PRESSURE;
      zaxisChangeType(zaxisID, leveltype);
389
      zaxisDefUnits(zaxisID, "Pa");
Uwe Schulzweida's avatar
Uwe Schulzweida committed
390
391
392
393
394
395
396
397
    }

  /*  IEG_G_NumVCP(gdb) = 0; */

  switch (leveltype)
    {
    case ZAXIS_SURFACE:
      {
398
        pdbDefLevel(pdb, IEG_LTYPE_SURFACE, 0, (int)zaxisInqLevel(zaxisID, levelID));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
399
400
401
402
403
	break;
      }
    case ZAXIS_HYBRID:
      {
	if ( zaxisInqLbounds(zaxisID, NULL) && zaxisInqUbounds(zaxisID, NULL) )
404
405
          pdbDefLevel(pdb, IEG_LTYPE_HYBRID_LAYER, (int)zaxisInqLbound(zaxisID, levelID),
                      (int)zaxisInqUbound(zaxisID, levelID));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
406
	else
407
          pdbDefLevel(pdb, IEG_LTYPE_HYBRID, 0, (int)zaxisInqLevel(zaxisID, levelID));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
408

409
	int vctsize = zaxisInqVctSize(zaxisID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
410
411
	if ( vctsize > 100 )
	  {
412
            static bool vct_warning = true;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
413
414
415
	    /*	    IEG_G_NumVCP(gdb) = 0; */
	    if ( vct_warning )
	      {
416
		Warning("VCT size of %d is too large (maximum is 100). Set to 0!", vctsize);
417
		vct_warning = false;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
418
419
420
421
422
	      }
	  }
	else
	  {
	    IEG_G_Size(gdb) += (vctsize*4);
423
424
	    memcpy(vct, zaxisInqVctPtr(zaxisID), (size_t)vctsize/2*sizeof(double));
	    memcpy(vct+50, zaxisInqVctPtr(zaxisID)+vctsize/2, (size_t)vctsize/2*sizeof(double));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
425
426
427
428
429
430
	  }
	break;
      }
    case ZAXIS_PRESSURE:
      {
	double dum;
431
	char units[CDI_MAX_NAME];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
432
433

	level = zaxisInqLevel(zaxisID, levelID);
434
	if ( level < 0 ) Warning("pressure level of %f Pa is below 0.", level);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
435
436

	zaxisInqUnits(zaxisID, units);
437
	if ( memcmp(units, "hPa", 3) == 0 || memcmp(units, "mb",2 ) == 0 )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
438
439
440
441
	  level = level*100;

	ilevel = (int) level;
	if ( level < 32768 && (level < 100 || modf(level/100, &dum) > 0) )
442
          pdbDefLevel(pdb, IEG_LTYPE_99, 0, ilevel);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
443
	else
444
445
446
          pdbDefLevel(pdb, IEG_LTYPE_ISOBARIC, 0, ilevel/100);

        break;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
447
448
449
450
      }
    case ZAXIS_HEIGHT:
      {
	level = zaxisInqLevel(zaxisID, levelID);
451
        pdbDefLevel(pdb, IEG_LTYPE_HEIGHT, 0, (int)level);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
452
453
454
455
456
	break;
      }
    case ZAXIS_ALTITUDE:
      {
	level = zaxisInqLevel(zaxisID, levelID);
457
        pdbDefLevel(pdb, IEG_LTYPE_ALTITUDE, 0, (int)level);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
458
459
460
461
462
	break;
      }
    case ZAXIS_DEPTH_BELOW_LAND:
      {
	if ( zaxisInqLbounds(zaxisID, NULL) && zaxisInqUbounds(zaxisID, NULL) )
463
          pdbDefLevel(pdb, IEG_LTYPE_LANDDEPTH_LAYER, (int)zaxisInqLbound(zaxisID, levelID), (int)zaxisInqUbound(zaxisID, levelID));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
464
	else
465
          pdbDefLevel(pdb, IEG_LTYPE_LANDDEPTH, 0, (int)zaxisInqLevel(zaxisID, levelID));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
466
467
468
469
470
471

	break;
      }
    case ZAXIS_DEPTH_BELOW_SEA:
      {
	level = zaxisInqLevel(zaxisID, levelID);
472
        pdbDefLevel(pdb, IEG_LTYPE_SEADEPTH, 0, (int)level);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
473
474
475
476
477
	break;
      }
    case ZAXIS_ISENTROPIC:
      {
	level = zaxisInqLevel(zaxisID, levelID);
478
        pdbDefLevel(pdb, 113, 0, (int)level);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
479
480
481
482
	break;
      }
    default:
      {
483
	Error("Unsupported zaxis type: %s", zaxisNamePtr(leveltype));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
484
485
486
487
488
489
	break;
      }
    }
}


490
void iegCopyRecord(stream_t *streamptr2, stream_t *streamptr1)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
491
{
492
  streamFCopyRecord(streamptr2, streamptr1, "IEG");
Uwe Schulzweida's avatar
Uwe Schulzweida committed
493
494
495
}


496
void iegDefRecord(stream_t *streamptr)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
497
{
498
499
  Record *record = streamptr->record;
  iegrec_t *iegp = (iegrec_t*) record->exsep;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
500

501
502
  int vlistID = streamptr->vlistID;
  int byteorder = streamptr->byteorder;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
503

504
505
  int varID   = record->varID;
  int levelID = record->levelID;
506
  int tsID    = streamptr->curTsID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
507

508
509
  int gridID  = vlistInqVarGrid(vlistID, varID);
  int zaxisID = vlistInqVarZaxis(vlistID, varID);
510

511
  iegInitMem(iegp);
512
  for ( int i = 0; i < 37; i++ ) iegp->ipdb[i] = -1;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
513
514
515

  iegp->byteswap = getByteswap(byteorder);

516
  int param = vlistInqVarParam(vlistID, varID);
517
  int pdis, pcat, pnum;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
518
  cdiDecodeParam(param, &pnum, &pcat, &pdis);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
519
520
  IEG_P_Parameter(iegp->ipdb) = pnum;
  if ( pdis == 255 ) IEG_P_CodeTable(iegp->ipdb) = pcat;
521

522
523
  int date = streamptr->tsteps[tsID].taxis.vdate;
  int time = streamptr->tsteps[tsID].taxis.vtime;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
524
525
526
527
  iegDefTime(iegp->ipdb, date, time, vlistInqTaxis(vlistID));
  iegDefGrid(iegp->igdb, gridID);
  iegDefLevel(iegp->ipdb, iegp->igdb, iegp->vct, zaxisID, levelID);

528
  iegp->dprec = iegDefDatatype(record->prec);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
529
530
531
}


532
void iegWriteRecord(stream_t *streamptr, const double *data)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
533
{
534
535
  Record *record = streamptr->record;
  iegrec_t *iegp = (iegrec_t*) record->exsep;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
536

537
  int fileID = streamptr->fileID;
538
  int gridsize = gridInqSize(record->gridID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
539

540
541
  double refval = data[0];
  for ( int i = 1; i < gridsize; i++ )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
542
543
544
545
546
547
548
549
    if ( data[i] < refval ) refval = data[i];

  iegp->refval = refval;

  iegDefDataDP(iegp, data);
  iegWrite(fileID, iegp);
}

550
static
551
void iegAddRecord(stream_t *streamptr, int param, int *pdb, int *gdb, double *vct,
552
		  size_t recsize, off_t position, int prec)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
553
{
554
555
556
557
  int vlistID = streamptr->vlistID;
  int tsID    = streamptr->curTsID;
  int recID   = recordNewEntry(streamptr, tsID);
  record_t *record = &streamptr->tsteps[tsID].records[recID];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
558

559
  int level1, level2;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
560
561
562
563
564
565
566
567
568
  if ( IEG_P_LevelType(pdb) == IEG_LTYPE_HYBRID_LAYER )
    {
      level1 = IEG_P_Level1(pdb);
      level2 = IEG_P_Level2(pdb);
    }
  else
    {
      level1 = IEG_P_Level2(pdb);
      level2 = 0;
569
      if ( IEG_P_LevelType(pdb) == 100 ) level1 *= 100;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
570
    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
571

572
573
574
575
576
577
  record->size     = recsize;
  record->position = position;
  record->param    = param;
  record->ilevel   = level1;
  record->ilevel2  = level2;
  record->ltype    = IEG_P_LevelType(pdb);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
578

579
580
581
  int gridtype = (IEG_G_GridType(gdb) == 0) ? GRID_LONLAT :
                 (IEG_G_GridType(gdb) == 10) ? GRID_PROJECTION :
                 (IEG_G_GridType(gdb) == 4) ? GRID_GAUSSIAN : GRID_GENERIC;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
582

583
584
  grid_t *grid = (grid_t *)Malloc(sizeof (*grid));
  grid_init(grid);
585
  cdiGridTypeInit(grid, gridtype, IEG_G_NumLon(gdb)*IEG_G_NumLat(gdb));
586
587
588
589
  int xsize = IEG_G_NumLon(gdb);
  int ysize = IEG_G_NumLat(gdb);
  grid->x.size = xsize;
  grid->y.size = ysize;
590
591
592
  grid->x.inc  = 0;
  grid->y.inc  = 0;
  grid->x.flag = 0;
593
594
595
596
597

  int iresfac = IEG_G_ResFac(gdb);
  if ( iresfac == 0 ) iresfac = 1000;
  double resfac = 1./(double) iresfac;

598
599
  /* if ( IEG_G_FirstLon != 0 || IEG_G_LastLon != 0 ) */
  {
600
    if ( xsize > 1 )
601
602
      {
	if ( IEG_G_ResFlag(gdb) && IEG_G_LonIncr(gdb) > 0 )
603
	  grid->x.inc = IEG_G_LonIncr(gdb) * resfac;
604
	else
605
	  grid->x.inc = (IEG_G_LastLon(gdb) - IEG_G_FirstLon(gdb)) * resfac / (xsize - 1);
606
607
608
609

	/* correct xinc if necessary */
	if ( IEG_G_FirstLon(gdb) == 0 && IEG_G_LastLon(gdb) > 354000 )
	  {
610
	    double xinc = 360. / xsize;
611
612
            /* FIXME: why not use grid->x.inc != xinc as condition? */
	    if ( fabs(grid->x.inc-xinc) > 0.0 )
613
	      {
614
615
		grid->x.inc = xinc;
		if ( CDI_Debug ) Message("set xinc to %g", grid->x.inc);
616
617
618
	      }
	  }
      }
619
620
621
    grid->x.first = IEG_G_FirstLon(gdb) * resfac;
    grid->x.last  = IEG_G_LastLon(gdb)  * resfac;
    grid->x.flag  = 2;
622
  }
623
  grid->y.flag = 0;
624
625
  /* if ( IEG_G_FirstLat != 0 || IEG_G_LastLat != 0 ) */
  {
626
    if ( ysize > 1 )
627
628
      {
	if ( IEG_G_ResFlag(gdb) && IEG_G_LatIncr(gdb) > 0 )
629
	  grid->y.inc = IEG_G_LatIncr(gdb) * resfac;
630
	else
631
	  grid->y.inc = (IEG_G_LastLat(gdb) - IEG_G_FirstLat(gdb)) * resfac / (ysize - 1);
632
      }
633
634
635
    grid->y.first = IEG_G_FirstLat(gdb) * resfac;
    grid->y.last  = IEG_G_LastLat(gdb)  * resfac;
    grid->y.flag  = 2;
636
  }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
637

638
  double xpole = 0, ypole = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
639
640
  if ( IEG_G_GridType(gdb) == 10 )
    {
641
642
      xpole =   IEG_G_LonSP(gdb) * resfac - 180;
      ypole = - IEG_G_LatSP(gdb) * resfac;
643
      grid->projtype = CDI_PROJ_RLL;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
644
645
    }

Uwe Schulzweida's avatar
Uwe Schulzweida committed
646
  struct addIfNewRes gridAdded = cdiVlistAddGridIfNew(vlistID, grid, 0);
647
  int gridID = gridAdded.Id;
648
  if ( !gridAdded.isNew ) Free(grid);
649
  else if ( gridtype == GRID_PROJECTION ) gridDefParamRLL(gridID, xpole, ypole, 0);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
650

651
  int leveltype = iegGetZaxisType(IEG_P_LevelType(pdb));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
652
653
654
  if ( leveltype == ZAXIS_HYBRID )
    {
      double tmpvct[100];
655
      size_t vctsize = (size_t)IEG_G_NumVCP(gdb);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
656

657
      for ( size_t i = 0; i < vctsize/2; i++ ) tmpvct[i] = vct[i];
658
      for ( size_t i = 0; i < vctsize/2; i++ ) tmpvct[i+vctsize/2] = vct[i+50];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
659
660
661
662

      varDefVCT(vctsize, tmpvct);
    }

663
  int lbounds = IEG_P_LevelType(pdb) == IEG_LTYPE_HYBRID_LAYER ? 1 : 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
664

665
  int datatype = iegInqDatatype(prec);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
666

667
  int varID;
668
  int levelID = 0;
669
  varAddRecord(recID, param, gridID, leveltype, lbounds, level1, level2, 0, 0,
670
671
	       datatype, &varID, &levelID, TSTEP_INSTANT, 0, 0, -1,
               NULL, NULL, NULL, NULL, NULL, NULL);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
672

673
674
  record->varID   = (short)varID;
  record->levelID = (short)levelID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
675

Uwe Schulzweida's avatar
Uwe Schulzweida committed
676
677
  streamptr->tsteps[tsID].nallrecs++;
  streamptr->nrecs++;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
678
679

  if ( CDI_Debug )
680
    Message("varID = %d gridID = %d levelID = %d", varID, gridID, levelID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
681
682
}

Thomas Jahns's avatar
Thomas Jahns committed
683
#if 0
684
static
685
void iegCmpRecord(stream_t *streamptr, int tsID, int recID, off_t position, int param,
Uwe Schulzweida's avatar
Uwe Schulzweida committed
686
687
688
689
		  int level, int xsize, int ysize)
{
  int varID = 0;
  int levelID = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
690

691
  record_t *record  = &streamptr->tsteps[tsID].records[recID];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
692

Uwe Schulzweida's avatar
Uwe Schulzweida committed
693
  if ( param != (*record).param || level != (*record).ilevel )
694
    Error("inconsistent timestep");
Uwe Schulzweida's avatar
Uwe Schulzweida committed
695
696
697
698
699
700

  (*record).position = position;
  /*
  varID   = (*record).varID;
  levelID = (*record).levelID;

Uwe Schulzweida's avatar
Uwe Schulzweida committed
701
  streamptr->vars[varID].level[levelID] = recID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
702

Uwe Schulzweida's avatar
Uwe Schulzweida committed
703
704
  streamptr->tsteps[tsID].nallrecs++;
  streamptr->nrecs++;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
705
706
  */
  if ( CDI_Debug )
707
    Message("varID = %d levelID = %d", varID, levelID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
708
}
Thomas Jahns's avatar
Thomas Jahns committed
709
#endif
710

711
712
static
void iegDateTime(int *pdb, int *date, int *time)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
713
{
714
715
716
  int ryear   = IEG_P_Year(pdb);
  int rmonth  = IEG_P_Month(pdb);
  int rday    = IEG_P_Day(pdb);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
717

718
719
  int rhour   = IEG_P_Hour(pdb);
  int rminute = IEG_P_Minute(pdb);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
720
721
722

  if ( rminute == -1 ) rminute = 0;

Uwe Schulzweida's avatar
Uwe Schulzweida committed
723
724
  *date = cdiEncodeDate(ryear, rmonth, rday);
  *time = cdiEncodeTime(rhour, rminute, 0);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
725
726
}

727
static
728
729
void iegScanTimestep1(stream_t *streamptr)
{
730
  DateTime datetime0 = { LONG_MIN, LONG_MIN };
Uwe Schulzweida's avatar
Uwe Schulzweida committed
731
  off_t recpos;
732
  iegcompvar_t compVar, compVar0;
733
  iegrec_t *iegp = (iegrec_t*) streamptr->record->exsep;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
734

Uwe Schulzweida's avatar
Uwe Schulzweida committed
735
  streamptr->curTsID = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
736

737
  int tsID = tstepsNewEntry(streamptr);
738
  taxis_t *taxis = &streamptr->tsteps[tsID].taxis;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
739
740

  if ( tsID != 0 )
741
    Error("Internal problem! tstepsNewEntry returns %d", tsID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
742

743
  int fileID = streamptr->fileID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
744

745
  int nrecs = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
746
747
748
  while ( TRUE )
    {
      recpos = fileGetPos(fileID);
749
      int status = iegRead(fileID, iegp);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
750
751
      if ( status != 0 )
	{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
752
	  streamptr->ntsteps = 1;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
753
754
	  break;
	}
755
      size_t recsize = (size_t)(fileGetPos(fileID) - recpos);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
756

757
758
759
760
      int prec   = iegp->dprec;
      int rcode  = IEG_P_Parameter(iegp->ipdb);
      int tabnum = IEG_P_CodeTable(iegp->ipdb);
      int param  = cdiEncodeParam(rcode, tabnum, 255);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
761

762
      int rlevel = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
763
764
765
766
767
      if ( IEG_P_LevelType(iegp->ipdb) == IEG_LTYPE_HYBRID_LAYER )
	rlevel = IEG_P_Level1(iegp->ipdb);
      else
	rlevel = IEG_P_Level2(iegp->ipdb);

768
769
      if ( IEG_P_LevelType(iegp->ipdb) == 100 ) rlevel *= 100;

770
      int vdate = 0, vtime = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
771
772
773
774
775
776
777
778
779
      iegDateTime(iegp->ipdb, &vdate, &vtime);

      if ( nrecs == 0 )
	{
	  datetime0.date = vdate;
	  datetime0.time = vtime;
	}
      else
	{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
780
	  compVar.param = param;
781
          compVar.level = rlevel;
782
          int recID = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
783
784
	  for ( recID = 0; recID < nrecs; recID++ )
	    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
785
	      compVar0.param = streamptr->tsteps[0].records[recID].param;
786
787
	      compVar0.level = streamptr->tsteps[0].records[recID].ilevel;

788
	      if ( memcmp(&compVar0, &compVar, sizeof(iegcompvar_t)) == 0 ) break;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
789
790
	    }
	  if ( recID < nrecs ) break;
791
792
	  DateTime datetime = { .date = vdate, .time = vtime};
	  if ( datetimeCmp(datetime, datetime0) )
793
	    Warning("Inconsistent verification time for param %d level %d", param, rlevel);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
794
795
796
797
798
	}

      nrecs++;

      if ( CDI_Debug )
799
	Message("%4d%8d%4d%8d%8d%6d", nrecs, (int)recpos, param, rlevel, vdate, vtime);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
800

801
      iegAddRecord(streamptr, param, iegp->ipdb, iegp->igdb, iegp->vct, recsize, recpos, prec);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
802
803
    }

Uwe Schulzweida's avatar
Uwe Schulzweida committed
804
  streamptr->rtsteps = 1;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
805

806
  cdi_generate_vars(streamptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
807

808
  int taxisID = taxisCreate(TAXIS_ABSOLUTE);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
809
  taxis->type  = TAXIS_ABSOLUTE;
810
811
  taxis->vdate = (int)datetime0.date;
  taxis->vtime = (int)datetime0.time;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
812

813
  int vlistID = streamptr->vlistID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
814
815
  vlistDefTaxis(vlistID, taxisID);

816
  vlist_check_contents(vlistID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
817

818
  int nrecords = streamptr->tsteps[0].nallrecs;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
819
  if ( nrecords < streamptr->tsteps[0].recordSize )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
820
    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
821
822
      streamptr->tsteps[0].recordSize = nrecords;
      streamptr->tsteps[0].records =
823
	(record_t *) Realloc(streamptr->tsteps[0].records,
824
                             (size_t)nrecords * sizeof (record_t));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
825
826
    }

827
  streamptr->tsteps[0].recIDs = (int *) Malloc((size_t)nrecords * sizeof (int));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
828
  streamptr->tsteps[0].nrecs = nrecords;
829
  for ( int recID = 0; recID < nrecords; recID++ )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
830
    streamptr->tsteps[0].recIDs[recID] = recID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
831

Uwe Schulzweida's avatar
Uwe Schulzweida committed
832
  if ( streamptr->ntsteps == -1 )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
833
    {
834
      tsID = tstepsNewEntry(streamptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
835
      if ( tsID != streamptr->rtsteps )
836
	Error("Internal error. tsID = %d", tsID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
837

Uwe Schulzweida's avatar
Uwe Schulzweida committed
838
839
      streamptr->tsteps[tsID-1].next   = TRUE;
      streamptr->tsteps[tsID].position = recpos;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
840
841
    }

Uwe Schulzweida's avatar
Uwe Schulzweida committed
842
  if ( streamptr->ntsteps == 1 )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
843
844
845
    {
      if ( taxis->vdate == 0 && taxis->vtime == 0 )
	{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
846
	  streamptr->ntsteps = 0;
847
	  for ( int varID = 0; varID < streamptr->nvars; varID++ )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
848
	    {
849
	      vlistDefVarTsteptype(vlistID, varID, TSTEP_CONSTANT);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
850
851
852
853
854
	    }
	}
    }
}

855
static
856
int iegScanTimestep2(stream_t *streamptr)
857
{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
858
  off_t recpos = 0;
859
  iegcompvar_t compVar, compVar0;
860
  iegrec_t *iegp = (iegrec_t*) streamptr->record->exsep;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
861
862

  streamptr->curTsID = 1;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
863

864
865
  int vlistID = streamptr->vlistID;
  int fileID  = streamptr->fileID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
866

867
  int tsID = streamptr->rtsteps;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
868
  if ( tsID != 1 )
869
    Error("Internal problem! unexpected timestep %d", tsID+1);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
870

871
  taxis_t *taxis = &streamptr->tsteps[tsID].taxis;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
872

Uwe Schulzweida's avatar
Uwe Schulzweida committed
873
  fileSetPos(fileID, streamptr->tsteps[tsID].position, SEEK_SET);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
874

875
  cdi_create_records(streamptr, tsID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
876

877
  int nrecords = streamptr->tsteps[0].nallrecs;
878
  streamptr->tsteps[1].recIDs = (int *) Malloc((size_t)nrecords * sizeof(int));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
879
  streamptr->tsteps[1].nrecs = 0;
880
  for ( int recID = 0; recID < nrecords; recID++ )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
881
    streamptr->tsteps[1].recIDs[recID] = -1;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
882

883
  for ( int recID = 0; recID < nrecords; recID++ )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
884
    {
885
      streamptr->tsteps[tsID].records[recID].position =
Uwe Schulzweida's avatar
Uwe Schulzweida committed
886
	streamptr->tsteps[0].records[recID].position;
887
      streamptr->tsteps[tsID].records[recID].size     =
Uwe Schulzweida's avatar
Uwe Schulzweida committed
888
	streamptr->tsteps[0].records[recID].size;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
889
890
    }

891
  for ( int rindex = 0; rindex <= nrecords; rindex++ )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
892
893
    {
      recpos = fileGetPos(fileID);
894
      int status = iegRead(fileID, iegp);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
895
896
      if ( status != 0 )
	{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
897
	  streamptr->ntsteps = 2;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
898
899
	  break;
	}
900
      size_t recsize = (size_t)(fileGetPos(fileID) - recpos);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
901

902
903
904
      int rcode  = IEG_P_Parameter(iegp->ipdb);
      int tabnum = IEG_P_CodeTable(iegp->ipdb);
      int param  = cdiEncodeParam(rcode, tabnum, 255);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
905

906
      int rlevel = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
907
908
909
910
911
      if ( IEG_P_LevelType(iegp->ipdb) == IEG_LTYPE_HYBRID_LAYER )
	rlevel = IEG_P_Level1(iegp->ipdb);
      else
	rlevel = IEG_P_Level2(iegp->ipdb);

912
913
      if ( IEG_P_LevelType(iegp->ipdb) == 100 ) rlevel *= 100;

914
      int vdate = 0, vtime = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
915
916
917
918
919
920
921
922
923
      iegDateTime(iegp->ipdb, &vdate, &vtime);

      if ( rindex == 0 )
	{
	  taxis->type  = TAXIS_ABSOLUTE;
	  taxis->vdate = vdate;
	  taxis->vtime = vtime;
	}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
924
      compVar.param = param;
925
      compVar.level = rlevel;
926
927
      bool nextstep = false;
      int recID = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
928
929
      for ( recID = 0; recID < nrecords; recID++ )
	{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
930
	  compVar0.param = streamptr->tsteps[tsID].records[recID].param;
931
932
	  compVar0.level = streamptr->tsteps[tsID].records[recID].ilevel;

933
	  if ( memcmp(&compVar0, &compVar, sizeof(iegcompvar_t)) == 0 )