3 This is the TRMM Office Radar Software Library.
4 Copyright (C) 1996, 1997
6 Space Applications Corporation
9 This library is free software; you can redistribute it and/or
10 modify it under the terms of the GNU Library General Public
11 License as published by the Free Software Foundation; either
12 version 2 of the License, or (at your option) any later version.
14 This library is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 Library General Public License for more details.
19 You should have received a copy of the GNU Library General Public
20 License along with this library; if not, write to the Free
21 Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 #ifdef HAVE_LIBTSDISTK
27 /******************************************************************
29 Subroutines to write one VOS from a RSL radar structure into one
32 A 1B-51/1C-51 HDF file contains multiple VOS's recorded by a radar
33 site during a 1-hour time period, and the HDF file is named using
34 the date/hour of the constituent VOS's.
36 All functions defined herein build the components of the TSDIS
37 toolkit 'L1B_1C_GV' structure using the data from a RSL radar
38 structure. These functions are executed via a call from the top-level
39 RSL function 'RSL_radar_to_hdf()', defined in RSL file
42 -----------------------------------------------------------------
43 Libraries required for execution of this code :
44 -ltsdistk : TSDIS toolkit
45 -lmfhdf -ldf -ljpeg -lz : HDF
49 -----------------------------------------------------------------
50 *******************************************************************/
58 #include <sys/types.h>
61 /* TSDIS toolkit function and structure definitions. */
64 /* RSL function and structure definitions. */
66 /* Parameter definitions for 1B-51 and 1C-51 HDF
67 file handling applications using the TSDIS toolkit. */
68 #include "toolkit_1BC-51_appl.h"
71 /*************************************************************/
73 /* Function Prototypes */
75 /*************************************************************/
76 static int julian(int year, int mo, int day);
77 int8 ***parmData1byteBuild(Volume *v, int pindex, VosSize *vs);
78 int16 ***parmData2byteBuild(Radar *radar, PARAMETER_DESCRIPTOR *parmDesc,
79 int vindex, int pindex, VosSize *vs);
80 void cellRangeVectorFill(CELL_RANGE_VECTOR *cellRangeVector,
81 int vindex, int pindex, VosSize *vs);
82 void parmDescFill(PARAMETER_DESCRIPTOR *parmDesc, Radar *radar, int vindex);
83 PARAMETER *parmBuild(Radar *radar, VosSize *vs, int vindex,
85 void rayInfoFill(int32 rayInfoInteger[MAX_SWEEP][MAX_RAY][7],
86 float32 rayInfoFloat[MAX_SWEEP][MAX_RAY][4],
87 Radar *radar, VosSize *vs);
88 void sweepInfoFill(SWEEP_INFO sweepInfo[MAX_SWEEP], Radar *radar, VosSize *vs);
89 void radarDescFill(RADAR_DESCRIPTOR *radarDesc, Radar *radar, int vindex,
91 void sensorFill(SENSORS *sensor, Radar *radar, VosSize *vs, int productID);
92 struct tm *timeUTC(void);
93 void volDesFill(VOLUME_DESCRIPTORS *volDes, Radar_header *h, VosSize *vs);
94 void commentsFill(char *comments, VosSize *vs, Radar *radar,
95 float *qcParm, int productID);
96 L1B_1C_GV *gvl1Build(Radar *radar, float *qcParm, VosSize *vs,
99 extern int nextVolume(Radar *radar, int last_volume);
100 extern int radar_verbose_flag;
101 extern Ray *first_ray_in_volume[MAX_RADAR_VOLUMES];
103 /*************************************************************/
107 /*************************************************************/
108 static int daytab[2][13] = {
109 {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365},
110 {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366}
113 static int julian(int year, int mo, int day)
115 /* Converts a calendar date (month, day, year) to a Julian date.
121 leap = (year%4 == 0 && year%100 != 0) || year%400 == 0;
122 return(day + daytab[leap][mo-1]);
125 /*************************************************************/
127 /* parmData1byteBuild */
129 /*************************************************************/
130 int8 ***parmData1byteBuild(Volume *v, int pindex, VosSize *vs)
131 /* Move all data from one mask volume of the RSL structure into
132 the array parmData1byte[][][] .
135 int sindex, rindex, bindex; /* Indices for rsl arrays. */
136 int tk_sindex, tk_rindex; /* Indices for toolkit arrays. */
141 ncell = vs->rsl.ncell[pindex][0];
142 data1byte = (int8 ***)TKnewParmData1byte(vs->tk.nsweep, vs->rsl.maxNray,
144 /* Move data values from all non-NULL rsl sweeps into the
145 'parmData1byte' array. */
147 for (tk_sindex=0; tk_sindex<vs->tk.nsweep; tk_sindex++)
149 if (vs->tk.ncell[tk_sindex][pindex] == 0)
151 /* No data from this parm in this physical sweep.
152 Fill bins of this 'parmData1byte' sweep with 0 */
153 for (rindex=0; rindex<vs->rsl.maxNray; rindex++)
154 for (bindex=0; bindex<ncell; bindex++)
155 data1byte[tk_sindex][rindex][bindex] = (int8) 0;
160 /* Move data values from all non-NULL rsl rays into the
161 'parmData1byte' array. */
162 for (rindex=0; rindex<v->sweep[sindex]->h.nrays; rindex++)
164 if (v->sweep[sindex]->ray[rindex] == NULL) continue;
166 ray = v->sweep[sindex]->ray[rindex];
167 /* Move the rsl bin values which exist into the 'parmData1byte' ray.*/
168 for (bindex=0; bindex<vs->tk.ncell[tk_sindex][pindex]; bindex++)
170 if (bindex >= ray->h.nbins) /* Short rsl ray? */
171 data1byte[tk_sindex][tk_rindex][bindex] = (int8) 0;
173 data1byte[tk_sindex][tk_rindex][bindex] = (int8) ray->range[bindex];
174 } /* end for (bindex=0... */
175 /* Fill all remaining bins of 'parmData1byte' ray with 0. */
176 for (bindex=vs->tk.ncell[tk_sindex][pindex]; bindex<ncell; bindex++)
177 data1byte[tk_sindex][tk_rindex][bindex] = (int8) 0;
178 } /* end (rindex=0;... */
180 /* Fill bins of all remaining rays of this sweep with 0. */
181 for (rindex=tk_rindex+1; rindex<vs->rsl.maxNray; rindex++)
182 for (bindex=0; bindex<ncell; bindex++)
183 data1byte[tk_sindex][rindex][bindex] = (int8) 0;
184 } /* end for (tk_sindex=0;...*/
189 /*************************************************************/
191 /* parmData2byteBuild */
193 /*************************************************************/
194 int16 ***parmData2byteBuild(Radar *radar, PARAMETER_DESCRIPTOR *parmDesc,
195 int vindex, int pindex, VosSize *vs)
196 /* Move all ray data from one volume of the RSL structure into
197 the array parmData2byte[][][] . Data values placed into
198 parmData2byte[][][] are scaled.
201 int sindex, rindex, bindex; /* Indices for rsl arrays. */
202 int tk_sindex, tk_rindex; /* Indices for toolkit arrays. */
209 ncell = vs->rsl.ncell[pindex][0];
210 data2byte = (int16 ***)TKnewParmData2byte(vs->tk.nsweep, vs->rsl.maxNray, ncell);
211 v = radar->v[vindex];
212 /* Move data values from all non-NULL rsl sweeps into the
213 'parmData2byte' array. */
215 for (tk_sindex=0; tk_sindex<vs->tk.nsweep; tk_sindex++)
217 if (vs->tk.ncell[tk_sindex][pindex] == 0)
219 /* No data from this parm in this physical sweep.
220 Fill bins of this 'parmData2byte' sweeps with NO_VALUE. */
221 for (rindex=0; rindex<vs->rsl.maxNray; rindex++)
222 for (bindex=0; bindex<ncell; bindex++)
223 data2byte[tk_sindex][rindex][bindex] = (int16) NO_VALUE;
228 /* Move data values from all non-NULL rsl rays into the
229 'parmData2byte' array. */
230 for (rindex=0; rindex<v->sweep[sindex]->h.nrays; rindex++)
232 if (v->sweep[sindex]->ray[rindex] == NULL) continue;
234 ray = v->sweep[sindex]->ray[rindex];
235 /* Move the rsl bin values which exist into the 'parmData2byte' ray.*/
236 for (bindex=0; bindex<vs->tk.ncell[tk_sindex][pindex]; bindex++)
238 /* if short rsl ray, fill cell with NO_VALUE */
239 if (bindex >= ray->h.nbins)
241 data2byte[tk_sindex][tk_rindex][bindex] = (int16) NO_VALUE;
244 value = v->h.f(ray->range[bindex]);
245 if (value >= NOECHO) /* Handle anomalous condition flags */
248 data2byte[tk_sindex][tk_rindex][bindex] = (int16) NO_VALUE;
249 else if (value == RFVAL)
250 data2byte[tk_sindex][tk_rindex][bindex] = (int16) RNG_AMBIG_VALUE;
251 else if (value == APFLAG)
252 data2byte[tk_sindex][tk_rindex][bindex] = (int16) AP_VALUE;
254 data2byte[tk_sindex][tk_rindex][bindex] = (int16) NOECHO_VALUE;
256 else /* Valid rsl data */
258 if (vindex == CZ_INDEX) /* Corrected Z data */
260 /* CZ = DZ + dzCal - mask_val * X ... From Ferrier memo. */
261 value = (value + v->h.calibr_const -
262 radar->v[MZ_INDEX]->sweep[sindex]->ray[rindex]->range[bindex] * X);
264 else if (vindex == CD_INDEX) /* Corrected differential Z data */
266 /* CD = ZD - mask_val * X */
268 radar->v[MD_INDEX]->sweep[sindex]->ray[rindex]->range[bindex] * X;
270 /* Apply scale and offset factors, then store value in
271 parmData2byte structure. */
272 data2byte[tk_sindex][tk_rindex][bindex] = (int16)
273 (value * parmDesc->scaleFactor + parmDesc->offsetFactor);
274 } /* end else Valid rsl data */
275 } /* end for (bindex=0;... */
277 /* Fill all remaining bins of 'parmData2byte' ray with NO_VALUE. */
278 for (bindex=vs->tk.ncell[tk_sindex][pindex]; bindex<ncell; bindex++)
279 data2byte[tk_sindex][tk_rindex][bindex] = (int16) NO_VALUE;
280 } /* end (rindex=0;... */
282 /* Fill bins of all remaining rays of this sweep with NO_VALUE. */
283 for (rindex=tk_rindex+1; rindex<vs->rsl.maxNray; rindex++)
284 for (bindex=0; bindex<ncell; bindex++)
285 data2byte[tk_sindex][rindex][bindex] = (int16) NO_VALUE;
286 } /* end for (sindex=0;... */
291 /*************************************************************/
293 /* cellRangeVectorFill */
295 /*************************************************************/
296 void cellRangeVectorFill(CELL_RANGE_VECTOR *cellRangeVector,
297 int vindex, int pindex, VosSize *vs)
299 /* Fill in the cellRangeVector values.
300 cellRangeVector[j] = distance(m) from radar to center of cell[j] .
303 Ray_header *ray_head;
305 cellRangeVector->numOfCells = (int32) vs->rsl.ncell[pindex][0];
306 ray_head = &first_ray_in_volume[vindex]->h;
308 /* Do first cell (m) */
309 cellRangeVector->distanceToCell[0] = (float32) (ray_head->range_bin1 +
310 0.5 * ray_head->gate_size);
312 /* Do remaining cells. Just add gate_size to previous cellRange value. */
313 for (j=1; j<cellRangeVector->numOfCells; j++)
315 cellRangeVector->distanceToCell[j] = (float32)
316 (cellRangeVector->distanceToCell[j-1] + ray_head->gate_size);
320 /*************************************************************/
324 /*************************************************************/
325 void parmDescFill(PARAMETER_DESCRIPTOR *parmDesc, Radar *radar, int vindex)
327 static char *parm_list[20][3] =
329 { "Z", "dBz", "Reflectivity" },
330 { "V", "m/s", "Radial Velocity" },
331 { "SW", "m2/s2", "Spectral Width" },
332 { "QCZ", "dBz", "QC'ed Reflectivity" },
333 { "ZT", "dBz", "Total Reflectivity" },
334 { "DR", "?", "Differential reflectivity" },
335 { "LR", "?", "Differential reflectivity" },
336 { "ZDR", "dB", "Differential Reflectivity" },
337 { "DM", "dBm", "Received power" },
338 { "RH", "-", "Correlation Coefficient" },
339 { "PH", "?", "Phi" },
340 { "XZ", "dBz", "X-band Reflectivity" },
341 { "QCZDR", "dB", "QC'ed Differential Reflectivity" },
342 { "QCMZ", "-", "Z Mask" },
343 { "QCMZDR", "-", "ZDR Mask" },
344 { "ZE", "-", "Edited Reflectivity" },
345 { "VE", "-", "Edited Velocity" },
346 { "--", "-", "*******" },
347 { "--", "-", "*******" },
348 { "--", "-", "*******" }
351 strncpy(parmDesc->parmName, parm_list[vindex][0], 7);
352 strncpy(parmDesc->parmDesc, parm_list[vindex][2], 39);
353 strncpy(parmDesc->parmUnits, parm_list[vindex][1], 7);
354 parmDesc->interPulsePeriod = (int16) 0;
355 parmDesc->transFreq = (int16) 1;
356 /* Receiver Bandwidth (MHz) */
357 parmDesc->receiverBandwidth = (float32) 0.0;
358 /* Pulse width (m) */
359 parmDesc->pulseWidth = (int16) (300.0 *
360 first_ray_in_volume[vindex]->h.pulse_width);
361 parmDesc->polarTransWave = (int16) 0;
362 parmDesc->numOfsamples = (int16) 0;
363 /* No thresholding done in 1B-51, 1C-51 HDF files. */
364 strncpy(parmDesc->thresholdField, "NONE", 8);
365 parmDesc->thresholdValue = (float32) 0.0;
366 parmDesc->offsetFactor = (float32) 0.0;
367 if ((vindex == MZ_INDEX) || (vindex == MD_INDEX))
369 parmDesc->parmDataType = (int16) 1; /* 1_byte mask value. */
370 parmDesc->scaleFactor = (float32) 1.0;
371 parmDesc->deletedOrMissDataFlag = (int32) 0;
373 else /* 2_byte data value. */
375 parmDesc->parmDataType = (int16) 2;
376 parmDesc->scaleFactor = (float32) SCALE_FACTOR;
377 parmDesc->deletedOrMissDataFlag = (int32) NO_VALUE;
381 /*************************************************************/
385 /*************************************************************/
386 PARAMETER *parmBuild(Radar *radar, VosSize *vs, int vindex,
391 /* Allocate memory for a new parameter structure. */
392 parm = (PARAMETER *)TKnewGVL1parm();
394 parmDescFill(&parm->parmDesc, radar, vindex);
395 cellRangeVectorFill(&parm->cellRangeVector, vindex, pindex, vs);
396 if ((vindex == MZ_INDEX) || (vindex == MD_INDEX)) /* Mask? */
397 parm->parmData1byte = (int8 ***)parmData1byteBuild(radar->v[vindex],
400 parm->parmData2byte = (int16 ***)parmData2byteBuild(radar, &parm->parmDesc,
405 /*************************************************************/
409 /*************************************************************/
410 void rayInfoFill(int32 rayInfoInteger[MAX_SWEEP][MAX_RAY][7],
411 float32 rayInfoFloat[MAX_SWEEP][MAX_RAY][4],
412 Radar *radar, VosSize *vs)
413 /* For each ray in the rsl structure, move ray header info into the
414 arrays rayInfoInteger[][][] and rayInfoFloat[][][].
417 int tk_sindex, rindex, tk_rindex;
419 Ray_header *ray_head;
424 /* For each physical sweep...*/
425 for (tk_sindex=0; tk_sindex<vs->tk.nsweep; tk_sindex++)
427 sweep = vs->rsl.sweep[tk_sindex];
429 for (rindex=0; rindex<sweep->h.nrays; rindex++)
431 if (sweep->ray[rindex] == NULL) continue;
433 /*********** Fill in ray info fields. ***************/
434 ray_head = &sweep->ray[rindex]->h;
435 /* No. of sweep which contains this ray. */
436 rayInfoInteger[tk_sindex][tk_rindex][0] = (int32)(tk_sindex + 1);
437 /* Compute Julian Day. Usually do only once per vos. */
438 if (day != ray_head->day)
440 day = ray_head->day; /* Note day & julday are static. */
442 julian(ray_head->year, ray_head->month, ray_head->day);
444 rayInfoInteger[tk_sindex][tk_rindex][1] = (int32) julday;
445 rayInfoInteger[tk_sindex][tk_rindex][2] = (int32) ray_head->hour;
446 rayInfoInteger[tk_sindex][tk_rindex][3] = (int32) ray_head->minute;
447 rayInfoInteger[tk_sindex][tk_rindex][5] = (int32) (1000.0 *
448 modf(ray_head->sec, &second));
449 rayInfoInteger[tk_sindex][tk_rindex][4] = (int32) second;
450 /* Ray status. 0:Normal , 1:Tansition , 2:Bad , 3:Questionable */
451 /* rayInfoInteger[tk_sindex][tk_rindex][6] = (int32) 0; */
453 rayInfoFloat[tk_sindex][tk_rindex][0] = (float32) ray_head->azimuth;
454 rayInfoFloat[tk_sindex][tk_rindex][1] = (float32) ray_head->elev;
455 /* Store num_of_samples here instead of power. */
456 rayInfoFloat[tk_sindex][tk_rindex][2] = (float32) ray_head->pulse_count;
457 /* Store prf here instead of Sweep Rate */
458 rayInfoFloat[tk_sindex][tk_rindex][3] = (float32) ray_head->prf;
459 } /* end (rindex=0;... */
460 } /* end for (tk_sindex=0;...*/
463 /*************************************************************/
467 /*************************************************************/
468 void sweepInfoFill(SWEEP_INFO sweepInfo[MAX_SWEEP], Radar *radar, VosSize *vs)
470 int rindex, tk_sindex;
473 /* For each physical sweep...*/
474 for (tk_sindex=0; tk_sindex<vs->tk.nsweep; tk_sindex++)
476 sweep = vs->rsl.sweep[tk_sindex];
477 /* Fill in sweep info from the 1st non-NULL rsl ray we find. */
478 for (rindex=0; rindex<sweep->h.nrays; rindex++)
480 if (sweep->ray[rindex] == NULL) continue;
481 strncpy(sweepInfo[tk_sindex].radarName, radar->h.radar_name, 8);
482 /* 1st sweep number (for tsdis structures) is 1 */
483 sweepInfo[tk_sindex].sweepNum = (int32) (tk_sindex + 1);
484 /* No. of rays in sweep */
485 sweepInfo[tk_sindex].numRays = (int32) vs->tk.nray[tk_sindex];
486 sweepInfo[tk_sindex].trueStartAngle = (float32)
487 sweep->ray[rindex]->h.azimuth;
488 if (sweep->ray[sweep->h.nrays-1] != NULL)
489 sweepInfo[tk_sindex].trueStopAngle = (float32)
490 sweep->ray[sweep->h.nrays-1]->h.azimuth;
492 sweepInfo[tk_sindex].trueStopAngle = (float32)
493 sweepInfo[tk_sindex].trueStartAngle;
494 /* degrees. Only for PPI scans. */
495 sweepInfo[tk_sindex].fixedAngle = (float32) sweep->h.elev;
496 /* Filter Flag. 0: No filtering, 1: filtered (descr in comment block) */
497 /* sweepInfo[tk_sindex].filterFlag = (int32) 0; */
500 } /* end for (tk_sindex=0;... */
503 /*************************************************************/
507 /*************************************************************/
508 void radarDescFill(RADAR_DESCRIPTOR *radarDesc, Radar *radar, int vindex,
511 strncpy(radarDesc->radarName, radar->h.name, 8);
512 /*radarDesc->radarConstant = (float32) 0.0;
513 radarDesc->nomPeakPower = (float32) 0.0;
514 radarDesc->nomNoisePower = (float32) 0.0;
515 radarDesc->receiverGain = (float32) 0.0;
516 radarDesc->antennaGain = (float32) 0.0;
517 radarDesc->radarSystemGain = (float32) 0.0;
519 radarDesc->horBeamWidth = (float32) first_ray_in_volume[vindex]->h.beam_width;
520 radarDesc->verBeamWidth = (float32) first_ray_in_volume[vindex]->h.beam_width;
521 radarDesc->radarType = (int16) 0; /* 0: Ground-based radar */
522 radarDesc->scanMode = (int16) 1; /* 1: PPI , 3: RHI */
523 /* radar sweep rate (deg/sec) */
524 radarDesc->nomScanRate = (float32)
525 (first_ray_in_volume[vindex]->h.sweep_rate * 6.0);
526 /* Following holds only for PPI scans. ??? */
527 radarDesc->nomStartAngle = (float32)
528 first_ray_in_volume[vindex]->h.azimuth;
529 radarDesc->nomStopAngle = (float32) radarDesc->nomStartAngle;
530 radarDesc->numParmDesc = (int16) vs->tk.nparm;
531 radarDesc->numDesc = (int16) vs->tk.nparm;
532 /* Data compression. Always 0 . Data compression done by HDF.*/
533 radarDesc->dataComp = (int16) 0;
534 /* Data reduction algorithm. */
535 radarDesc->dataReductAlg = (int16) 0; /* 0: No reduction */
536 radarDesc->dataReductParm1 = (float32) 4.0; /* TBD */
537 radarDesc->dataReductParm2 = (float32) 4.0; /* TBD */
538 radarDesc->radarLon = (float32) (radar->h.lond + radar->h.lonm/60.0 +
539 radar->h.lons/3600.0);
540 radarDesc->radarLat = (float32) (radar->h.latd + radar->h.latm/60.0 +
541 radar->h.lats/3600.0);
542 /* altitude above Mean Sea Level (km) */
543 radarDesc->radarAlt = (float32)((float)(radar->h.height) / 1000.0);
544 /* Effective unambiguous velocity (m/s) Leave blank. See range comments
547 if (radar->v[VR_INDEX] != NULL)
548 radarDesc->velocity = (float32)
549 first_ray_in_volume[VR_INDEX]->h.nyq_vel;
551 radarDesc->velocity = (float32)0.0;
553 /* Effective unambiguous range (km). Leave blank. For wsr88d,
554 unambig_range varies with sweep. See range_info_float block. */
556 radarDesc->range = (float32)
557 first_ray_in_volume[vindex]->h.unam_rng;
559 /* No. of transmitted freqs */
560 radarDesc->numTransfreqency = (int16) 1;
561 /* radarDesc->numInterPulsePeriods = (int16) 0; */
563 radarDesc->frequency1 = (float32) first_ray_in_volume[vindex]->h.frequency;
566 /*************************************************************/
570 /*************************************************************/
571 void sensorFill(SENSORS *sensor, Radar *radar, VosSize *vs, int productID)
572 /* Fill the substructures of the sensor data structure using
573 data from the radar structure. */
575 int pindex, tk_sindex, vindex;
577 vindex = nextVolume(radar, -1); /* Find 1st non-NULL rsl volume. */
579 radarDescFill(&sensor->radarDesc, radar, vindex, vs);
580 sweepInfoFill(sensor->sweepInfo, radar, vs);
581 rayInfoFill(sensor->rayInfoInteger, sensor->rayInfoFloat, radar, vs);
583 /* Move data from each of the radar structure volumes into a
584 corresponding L1GV parameter structure. */
585 if (productID == TK_L1B_GV)
587 for (pindex=0; pindex<vs->tk.nparm; pindex++)
589 sensor->parm[pindex] = (PARAMETER *)parmBuild(radar, vs, vindex, pindex);
590 /* Find the next non-NULL volume in radar structure. */
591 vindex = nextVolume(radar, vindex);
592 } /* end for (pindex=0; ... */
596 /* This is a hatchet job to conform with newest toolkit. The toolkit
597 arbitrarily assumes that the mask volume precedes the corresponding
600 for (pindex=0; pindex<vs->tk.nparm/2; pindex++)
602 if (vindex == CZ_INDEX)
603 sensor->parm[pindex] = (PARAMETER *)parmBuild(radar, vs, MZ_INDEX,
605 else if (vindex == CD_INDEX)
606 sensor->parm[pindex*2] = (PARAMETER *)parmBuild(radar, vs, MD_INDEX,
610 sensor->parm[pindex*2+1] = (PARAMETER *)parmBuild(radar, vs, vindex,
612 /* Find the next non-NULL volume in radar structure. */
613 vindex = nextVolume(radar, vindex);
614 } /* end for (pindex=0... */
615 } /* end else 1C-51 */
617 if (radar_verbose_flag)
619 for (pindex=0; pindex<vs->tk.nparm; pindex++)
621 fprintf(stderr, "Toolkit parameter type : %s '%s'\n",
622 sensor->parm[pindex]->parmDesc.parmDesc,
623 sensor->parm[pindex]->parmDesc.parmName);
624 for (tk_sindex=0; tk_sindex<vs->tk.nsweep; tk_sindex++)
625 if (vs->tk.ncell[tk_sindex][pindex] == 0)
626 fprintf(stderr, " tk_sweep[%.2d] elev=%4.1f nrays=%3d cells/ray=%d\n",
627 tk_sindex, sensor->sweepInfo[tk_sindex].fixedAngle,
629 vs->tk.ncell[tk_sindex][pindex]);
631 fprintf(stderr, " tk_sweep[%.2d] elev=%4.1f nrays=%3d cells/ray=%d\n",
632 tk_sindex, sensor->sweepInfo[tk_sindex].fixedAngle,
633 (int)sensor->sweepInfo[tk_sindex].numRays,
634 vs->tk.ncell[tk_sindex][pindex]);
635 } /* end for (pindex=0;... */
636 } /* end if (radar_verbose_flag) */
639 /*************************************************************/
643 /*************************************************************/
644 struct tm *timeUTC(void)
646 /* Find the current time (UTC).
647 If success: return pointer to filled time_t structure.
648 If failure: return NULL.
652 /* Get the current system clock time */
653 time_current = (time_t) time(NULL);
654 if (time_current != -1) /* valid time? */
655 return(gmtime(&time_current)); /* Convert to UTC and return. */
657 return(NULL); /* Couldn't get the current time. */
661 /*************************************************************/
665 /*************************************************************/
666 void volDesFill(VOLUME_DESCRIPTORS *volDes, Radar_header *h, VosSize *vs)
672 /* Version no. of DORADE specifications used. Currently 1 */
673 volDes->verNum = (int16) 1;
674 /* No. of this volume scan in granule */
675 volDes->volNum = (int16) (vs->vos_num + 1);
676 /* Max size of DORADE data record in this VOS. 2bytes x max(ncell) */
678 for (pindex=0; pindex<vs->tk.nparm; pindex++)
679 if (vs->tk.ncell[0][pindex] > max_ncell)
680 max_ncell = vs->tk.ncell[0][pindex];
681 volDes->sizeDataRec = (int32) (2 * max_ncell);
682 strncpy(volDes->projectName, "TRMM GV", 20);
683 volDes->year = (int16) h->year; /* Year of volume scan */
684 volDes->month = (int16) h->month; /* Month of volume scan */
685 volDes->day = (int16) h->day; /* Day ... */
686 volDes->hour = (int16) h->hour; /* Hour ... */
687 volDes->minute = (int16) h->minute; /* Minute ... */
688 volDes->second = (int16) floor((double)h->sec); /* Second ... */
689 /* Flight no. for airborne radar, or IOP no. for ground radar */
690 strncpy(volDes->flightNum, "***", 8);
691 /* Data product generation facility name */
692 strncpy(volDes->facName, "TSDIS", 8);
693 /* Get the current time; ie, the time of creation of this hdf file. */
694 time_utc = timeUTC();
695 if (time_utc != NULL) /* Valid time? */
697 volDes->genYear = (int16) (1900 + time_utc->tm_year);
698 volDes->genMonth = (int16) (time_utc->tm_mon + 1);
699 volDes->genDay = (int16) time_utc->tm_mday;
701 else /* Couldn't get valid time. */
703 volDes->genYear = (int16) 0;
704 volDes->genMonth = (int16) 0;
705 volDes->genDay = (int16) 0;
707 /* No. of sensor descriptors in this volume scan */
708 volDes->numSensorDesc = (int16) 1; /* 1 for ground-based radar */
711 /*************************************************************/
715 /*************************************************************/
716 void commentsFill(char *comments, VosSize *vs, Radar *radar,
717 float *qcParm, int productID)
719 /* Write the following into the comments field of the gvl1
721 1. VOS comment_field header line.
722 2. cell/ray/sweep count.
723 3. 1C-51 QC parameters, if we're writing a 1C-51 HDF file.
726 int pindex, tk_sindex;
728 /* Write out the dimensions of the toolkit structure which contains
730 sprintf(buf, "nSweep=%d\n", vs->tk.nsweep);
731 strcat(comments, buf);
732 for (tk_sindex=0; tk_sindex<vs->tk.nsweep; tk_sindex++)
734 sprintf(buf, "sweep[%.2d]--\n nRay=%d\n", tk_sindex,
735 vs->tk.nray[tk_sindex]);
736 strcat(comments, buf);
737 for (pindex=0; pindex<vs->tk.nparm; pindex++)
739 sprintf(buf, " nCell_parm[%d]=%d\n", pindex,
740 vs->tk.ncell[tk_sindex][pindex]);
741 strcat(comments, buf);
743 strcat(comments, "\n");
744 } /* end for (pindex=0 ... */
746 strcat(comments, "********\n");
747 /* If 1C-51 file, write out the QC parameters. */
748 if (productID == TK_L1C_GV)
750 sprintf(buf, "-hThresh1 %.2f -hThresh2 %.2f -hThresh3 %.2f -zThresh0 %.2f -zThresh1 %.2f -zThresh2 %.2f -zThresh3 %.2f -hFreeze %.2f -dbzNoise %.2f -zCal %.2f\n\n",
751 qcParm[HTHRESH1], qcParm[HTHRESH2], qcParm[HTHRESH3],
752 qcParm[ZTHRESH0], qcParm[ZTHRESH1], qcParm[ZTHRESH2], qcParm[ZTHRESH3],
753 qcParm[HFREEZE], qcParm[DBZNOISE], qcParm[ZCAL]);
754 strcat(comments, buf);
755 } /* end if (productID == TK_L1C_GV) */
758 /*************************************************************/
762 /*************************************************************/
763 L1B_1C_GV *gvl1Build(Radar *radar, float *qcParm, VosSize *vs,
766 /* Build the components of the Toolkit 'L1B_1C_GV' structure using
767 the data from the RSL radar structure.
771 /* Allocate memory for a TSDIS level_1 structure. */
772 gvl1 = (L1B_1C_GV *)TKnewGVL1();
774 /* Fill the structure, using data from the radar structure. */
775 commentsFill(gvl1->comments, vs, radar, qcParm, productID);
776 volDesFill(&gvl1->volDes, &radar->h, vs);
777 sensorFill(&gvl1->sensor, radar, vs, productID);