]> Pileus Git - ~andy/rsl/blob - doc/users_guide.html
RSL v1.43
[~andy/rsl] / doc / users_guide.html
1 <!doctype html public "-//w3c//dtd html 4.0 transitional//en">
2 <html>
3 <head>
4    <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
5    <meta name="GENERATOR" content="Mozilla/4.5 [en] (X11; U; Linux 2.0.32 i686) [Netscape]">
6 </head>
7 <body>
8 <a href="index.html"><img SRC="rsl.gif" height=100 width=100></a>
9 <hr>
10 <br>&nbsp;
11 <br>&nbsp;
12 <h1>
13 Users Guide to RSL.</h1>
14
15 <h2>
16 What is RSL good for?</h2>
17 The best feature of RSL is the ability to ingest many different RADAR data
18 file formats with a single library call. It can, also, read compressed
19 files -- compressed with GZIP or the older COMPRESS. The routine is called
20 <a href="RSL_anyformat_to_radar.html">RSL_anyformat_to_radar</a>.
21 You give it a filename and it will return a pointer to a C structure called
22 <a href="RSL_radar_struct.html">Radar</a>.
23 The structure Radar contains all the information found in the input file.
24 The structure is intended to represent a superset of all RADAR data formats.
25 <p>Below, is a table listing the input/output routines supplied in RSL.
26 You will notice that there are only two output routines. RSL, by design,
27 is not a format converter, but, a library to facilitate reading and manipulation
28 of RADAR data. Output for UF and HDF are supplied because of the popularity
29 of those two formats.
30 <br>&nbsp;
31 <table BORDER CELLPADDING=0 >
32 <tr>
33 <td>
34 <h4>
35 Data format</h4>
36 </td>
37
38 <td>
39 <h4>
40 Input routine</h4>
41 </td>
42
43 <td>
44 <h4>
45 Output routine</h4>
46 </td>
47 </tr>
48
49 <tr>
50 <td>HDF 1B-51 and 1C-51</td>
51
52 <td><a href="RSL_hdf_to_radar.html">RSL_hdf_to_radar</a></td>
53
54 <td><a href="RSL_radar_to_hdf.html">RSL_radar_to_hdf</a></td>
55 </tr>
56
57 <tr>
58 <td>Lassen (Darwin)</td>
59
60 <td><a href="RSL_lassen_to_radar.html">RSL_lassen_to_radar</a></td>
61
62 <td>None</td>
63 </tr>
64
65 <tr>
66 <td>WSR-88d (Nexrad)</td>
67
68 <td><a href="RSL_wsr88d_to_radar.html">RSL_wsr88d_to_radar</a></td>
69
70 <td>None</td>
71 </tr>
72
73 <tr>
74 <td>UF (Universal Format from NCAR)</td>
75
76 <td><a href="RSL_uf_to_radar.html">RSL_uf_to_radar</a></td>
77
78 <td><a href="RSL_radar_to_uf.html">RSL_radar_to_uf</a></td>
79 </tr>
80
81 <tr>
82 <td>SIGMET (Version 1)</td>
83
84 <td><a href="RSL_nsig_to_radar.html">RSL_nsig_to_radar</a></td>
85
86 <td>None</td>
87 </tr>
88
89 <tr>
90 <td>SIGMET (Version 2)</td>
91
92 <td><a href="RSL_nsig_to_radar.html">RSL_nsig2_to_radar</a></td>
93
94 <td>None</td>
95 </tr>
96
97 <tr>
98 <td>McGill&nbsp;</td>
99
100 <td><a href="RSL_mcgill_to_radar.html">RSL_mcgill_to_radar</a></td>
101
102 <td>None</td>
103 </tr>
104
105 <tr>
106 <td>TOGA&nbsp;</td>
107
108 <td><a href="RSL_toga_to_radar.html">RSL_toga_to_radar</a></td>
109
110 <td>None</td>
111 </tr>
112
113 <tr>
114 <td>RAPIC (Berrimah)&nbsp;</td>
115
116 <td><a href="RSL_rapic_to_radar.html">RSL_rapic_to_radar</a></td>
117
118 <td>None</td>
119 </tr>
120
121 <tr>
122 <td>RADTEC (SPANDAR)</td>
123
124 <td><a href="RSL_radtec_to_radar.html">RSL_radtec_to_radar</a></td>
125
126 <td>None</td>
127 </tr>
128
129 </tr>
130 </table>
131 RSL is designed to provide you with a uniform data structure so that you
132 can design RADAR independent science applications. You no longer need to
133 wrestle over the input data format and have a different version of your
134 algorithm for each different RADAR format you may need to analyze.
135 <p>This paper presents RSL from a science application developer's point
136 of view. It will present some of the more useful routines and which fields
137 in the <a href="RSL_radar_struct.html">Radar</a> structure that will be
138 important to you and it will attempt to cover some of the programming pitfalls
139 associated with RSL usage. One of the most difficult hurdles to overcome
140 is that RSL makes extensive use of pointer syntax. You will find yourself
141 becoming expert with C pointers. However, the design of RSL makes it possible
142 to use C pointers painlessly.
143 <h2>
144 Ok, I have some data, how do I look at it?</h2>
145 Let's first make some images. To do that you need only 3 RSL functions:
146 <p><tt><a href="RSL_anyformat_to_radar.html">RSL_anyformat_to_radar</a></tt>
147 <br><tt><a href="RSL_load_color_table.html">RSL_load_refl_color_table</a></tt>
148 <br><tt><a href="RSL_volume_to.html">RSL_volume_to_gif</a></tt>
149 <p>The C program you need is incredibly short. It illustrates how to ingest
150 radar data and create a GIF image of the DZ (reflectivity) field:
151 <pre>#include "rsl.h"
152 void main(int argc, char **argv)
153 {
154 &nbsp; Radar *radar;
155 &nbsp; radar = RSL_anyformat_to_radar("radar.dat", NULL);
156 &nbsp; RSL_load_refl_color_table();
157 &nbsp; RSL_volume_to_gif(radar->v[DZ_INDEX], "dz_sweep", 400, 400, 200.0);
158 }</pre>
159 The line:
160 <p><tt>#include "rsl.h"</tt>
161 <p>is required when using the RSL. It defines important constants and declares
162 all the RSL functions that your application may need.
163 <p>The line:
164 <pre>Radar *radar;</pre>
165 declares the radar pointer. Only a pointer to a radar should be declared,
166 because, the ingest routines allocate all the space to hold all the appropriate
167 substructures: <a href="RSL_volume_struct.html">Volume</a>, <a href="RSL_sweep_struct.html">Sweep</a>,
168 <a href="RSL_ray_struct.html">Ray</a>,
169 and <a href="RSL_range_struct.html">Range</a>.
170 <p>The line:
171 <pre>radar = RSL_anyformat_to_radar("radar.dat", NULL);</pre>
172 performs the actual ingest of data. The input file is called <tt>radar.dat</tt>.
173 <a href="RSL_anyformat_to_radar.html">RSL_anyformat_to_radar
174 </a>automatically
175 determines the type of radar data being read. It can handle *.gz or *.Z
176 files transparently. Reading gzip or compress files is faster, especially
177 over NFS.&nbsp;&nbsp; Generally, reading compressed radar files is faster
178 because of how UNIX pipes are implemented and that the compression is nearly
179 90%.&nbsp;&nbsp; The second argument, NULL, is optional. A second argument
180 is needed only when reading WSR-88D data. The WSR-88D site information
181 is provided in the first physical file on the 8mm tape, but, it is used
182 to fill lat/lon and other radar-site specific information when reading
183 the 2<sup>nd</sup> through last physical files on the tape.
184 <p>Note: <a href="RSL_anyformat_to_radar.html">RSL_anyformat_to_radar</a>
185 can't handle every radar format for which there is an RSL ingest routine.
186 But, it does a good job at recognizing most formats. Currently, TOGA and
187 MCGILL files cannot be automatically detected. In those cases, use: <a href="RSL_toga_to_radar.html">RSL_toga_to_radar</a>
188 and <a href="RSL_mcgill_to_radar.html">RSL_mcgill_to_radar</a>.
189 <p>While basic image generation is provided in RSL, it is never intended
190 to be anything more than a diagnostic tool. Several assumptions are made,
191 but, the image generation functions provided are useful. This is what the
192 last two lines illustrate. First you must define a color table. That is
193 done with:
194 <pre>RSL_load_refl_color_table();</pre>
195 then, to generate disk files, gif images, you must call one of the image
196 generation functions, as in:
197 <pre>RSL_volume_to_gif(radar->v[DZ_INDEX], "dz_sweep", 400, 400, 200.0);</pre>
198 This routine will generate several images, one for each sweep, mapping
199 the image to a 400 x 400 km grid, using a 1 x 1 km spacing, by collecting
200 data out to 200 km.
201 <p>Making images of velocity data, <tt>VR_INDEX</tt>, involves two more
202 steps that are not very obvious. Because of the limited range of the values
203 presented in velocity data, you must re-bin the data. Do that with any
204 one of the following:
205 <pre><a href="RSL_rebin_velocity.html">RSL_rebin_velocity_sweep</a>,
206 <a href="RSL_rebin_velocity.html">RSL_rebin_velocity_volume</a></pre>
207 The second step is that you must call:
208 <pre><a href="RSL_load_color_table.html">RSL_load_vel_color_table()</a>;</pre>
209 The nyquist velocity is used to determine the limits of the re-binning.
210 <i>These
211 functions modify the data in a sweep, or volume.</i> So, it is wise to
212 make copies of the sweep, or volume, if you plan on using the data later
213 in your application. Normally, though, making velocity images is the last
214 step of a program, therefore, you don't need to copy the velocity volume
215 as your program will be exiting shortly. RSL provides a number of color
216 table manipulation functions. You are not limited by the default settings
217 for DZ, VR, and SW color tables. You can specify any color table mapping
218 you wish.
219 <h2>
220 Whoopty doo, I really wanted to examine the values.</h2>
221 In order to get to values in the <a href="RSL_radar_struct.html">Radar</a>
222 structure, you have to trickle down all the substructues. The structures,
223 in order of nesting are: <a href="RSL_radar_struct.html">Radar</a>, <a href="RSL_volume_struct.html">Volume</a>,
224 <a href="RSL_sweep_struct.html">Sweep</a>,
225 <a href="RSL_ray_struct.html">Ray</a>,
226 <a href="RSL_range_struct.html">Range</a>.
227 Each of these structures is presented in that order. You will notice a
228 common organization across all of the structures -- each structure contains
229 a header and contains an array of pointers to the next substructure.
230 <h4>
231 The Radar structure</h4>
232 Ok, make the call to <tt><a href="RSL_anyformat_to_radar.html">RSL_anyformat_to_radar</a></tt>
233 as above, so that you get a pointer to a radar. The structure <tt><a href="RSL_radar_struct.html">Radar</a></tt>
234 is the most general structure in RSL. Radar is composed of two parts:
235 <ul>
236 <li>
237 Radar header.</li>
238
239 <li>
240 Array of pointers to <a href="RSL_volume_struct.html">Volume</a>s.</li>
241 </ul>
242 The radar header, will be presented and described fully later, but, it
243 contains general information about the entire structure. To access the
244 radar header use the syntax:
245 <pre>Radar *radar;
246 radar->h.<i>member</i>;</pre>
247 The array of pointers to <a href="RSL_volume_struct.html">Volume</a>s contains
248 either pointers to <a href="RSL_volume_struct.html">Volume</a>s of data
249 or NULL. The number of possible <a href="RSL_volume_struct.html">Volume</a>s
250 in the radar is specified by radar->h.nvolumes. This number represents
251 the length of the array of pointers to <a href="RSL_volume_struct.html">Volume</a>s
252 and not the number of actual (non-NULL) volumes in the radar. The index
253 of this array of pointers to <a href="RSL_volume_struct.html">Volume</a>s
254 is the field type index. There are MAX_RADAR_VOLUMES (currently set to
255 19) field types defined in RSL. Each field type index has a specific value.
256 That value is illustrated in the table below. RSL ingest routines guarentee
257 that the length of the array of pointers to <a href="RSL_volume_struct.html">Volume</a>s,
258 <tt>radar->v</tt>,
259 is exactly the maximum number of field types, MAX_RADAR_VOLUMES. This is
260 done so that you can check for the existance of a field type with the syntax:
261 <pre>if (radar->v[XZ_INDEX]) /* XZ exists */</pre>
262 Normally, <tt>radar->h.nvolumes</tt> is set to the length of the array
263 of pointers to <a href="RSL_volume_struct.html">Volume</a>s, <tt>radar->v</tt>.
264 Because C array indexes start at 0, you should use a test similiar to:
265 ivol &lt; radar->h.nvolumes. The maximum value for <tt>radar->h.nvolumes</tt>
266 is MAX_RADAR_VOLUMES which is a constant in RSL. The value for <tt>radar->h.nvolumes</tt>
267 could be less though. But, you can rest assured that you can test for the
268 existance of a field type simply by using the hard coded index name as
269 specified in the table below.
270 <p>There are basically two methods for indexing the array of pointers to
271 <a href="RSL_volume_struct.html">Volume</a>s:
272 <ul>
273 <li>
274 Use the index name, eg. CZ_INDEX or its value.</li>
275
276 <li>
277 Use a variable that ranges from 0 to <tt>radar->h.nvolumes</tt>-1.</li>
278 </ul>
279 Here are two coding examples that demonstrate how to access the array of
280 pointers to volumes.
281 <p>Example 1:
282 <pre>Radar *radar;
283 Volume *volume;
284
285 volume = radar->v[CZ_INDEX];
286 if (volume != NULL) {
287 &nbsp;&nbsp; /* Do something with volume. */
288 }</pre>
289 Example 2:
290 <pre>Radar *radar;
291 Volume *volume;
292 int i;
293
294 for (i=0; i&lt;radar->h.nvolumes) {
295 &nbsp;&nbsp; volume = radar->v[i];
296 &nbsp;&nbsp; if (volume == NULL) continue; /* skip this NULL volume */
297 &nbsp;&nbsp; /* Do something with volume. */
298 }</pre>
299 It is very important that you check for the volume pointer being NULL.
300 It is very common that <tt>radar->h.nvolumes</tt> is larger than the number
301 of non-NULL volumes present in radar. By default, <tt>radar->h.nvolumes</tt>
302 is the length of array of pointers to <a href="RSL_volume_struct.html">Volume</a>s.
303 The volumes are also known as field types. There are several field types
304 and a <a href="RSL_volume_struct.html">Volume</a> can be only one field
305 type. The entire list of field types is presented in the table below. To
306 reference a particular field, you use a simple syntax:
307 <p><tt>radar->v[DZ_INDEX]</tt>
308 <br><tt>radar->v[VR_INDEX]</tt>
309 <p>Each field type encountered has a specific index within the <tt>radar->v</tt>
310 array of pointers to <a href="RSL_volume_struct.html">Volume</a>s. The
311 field type indexes are hard-coded and are defined to be specific numbers
312 starting at 0. Hard-coded field type indexes simplifies the syntax for
313 accessing volumes. When there is no volume for a particular field type,
314 the volume pointer is NULL. This is ok, as NULL is a perfectly acceptable,
315 albeit useless, volume. Here is a table of all the field type indexes used
316 in RSL.
317 <br>&nbsp;
318 <table BORDER CELLPADDING=0 >
319 <tr>
320 <td>
321 <h4>
322 INDEX NAME</h4>
323 </td>
324
325 <td>
326 <h4>
327 Value</h4>
328 </td>
329
330 <td>
331 <h4>
332 Description</h4>
333 </td>
334 </tr>
335
336 <tr>
337 <td>DZ_INDEX</td>
338
339 <td>0</td>
340
341 <td>Reflectivity (dBZ)</td>
342 </tr>
343
344 <tr>
345 <td>VR_INDEX</td>
346
347 <td>1</td>
348
349 <td>Radial Velocity (m/s)</td>
350 </tr>
351
352 <tr>
353 <td>SW_INDEX</td>
354
355 <td>2</td>
356
357 <td>Spectral Width (m<sup><font size=-2>2</font></sup>/s<sup><font size=-2>2</font></sup>)</td>
358 </tr>
359
360 <tr>
361 <td>CZ_INDEX</td>
362
363 <td>3</td>
364
365 <td>QC Reflectivity (dBZ)</td>
366 </tr>
367
368 <tr>
369 <td>ZT_INDEX</td>
370
371 <td>4</td>
372
373 <td>Total Reflectivity (dBZ)</td>
374 </tr>
375
376 <tr>
377 <td>DR_INDEX</td>
378
379 <td>5</td>
380
381 <td>Differential reflectivity</td>
382 </tr>
383
384 <tr>
385 <td>LR_INDEX</td>
386
387 <td>6</td>
388
389 <td>Another differential refl.</td>
390 </tr>
391
392 <tr>
393 <td>ZD_INDEX</td>
394
395 <td>7</td>
396
397 <td>Reflectivity Depolarization Ratio&nbsp;
398 <p>ZDR = 10log(ZH/ZV) (dB)</td>
399 </tr>
400
401 <tr>
402 <td>DM_INDEX</td>
403
404 <td>8</td>
405
406 <td>Received power (dBm)</td>
407 </tr>
408
409 <tr>
410 <td>RH_INDEX</td>
411
412 <td>9</td>
413
414 <td>Rho: Correlation coefficient</td>
415 </tr>
416
417 <tr>
418 <td>PH_INDEX</td>
419
420 <td>10</td>
421
422 <td>Phi (MCTEX parameter)</td>
423 </tr>
424
425 <tr>
426 <td>XZ_INDEX</td>
427
428 <td>11</td>
429
430 <td>X-band reflectivity</td>
431 </tr>
432
433 <tr>
434 <td>CR_INDEX</td>
435
436 <td>12</td>
437
438 <td>Corrected DR reflectivity (differential).</td>
439 </tr>
440
441 <tr>
442 <td>MZ_INDEX</td>
443
444 <td>13</td>
445
446 <td>DZ mask volume for HDF 1C-51 product.</td>
447 </tr>
448
449 <tr>
450 <td>MR_INDEX</td>
451
452 <td>14</td>
453
454 <td>DR mask volume for HDF 1C-51 product.</td>
455 </tr>
456
457 <tr>
458 <td>ZE_INDEX</td>
459
460 <td>15</td>
461
462 <td>Edited reflectivity.</td>
463 </tr>
464
465 <tr>
466 <td>VE_INDEX</td>
467
468 <td>16</td>
469
470 <td>Edited velocity.</td>
471 </tr>
472
473 <tr>
474 <td>KD_INDEX</td>
475
476 <td>17</td>
477
478 <td>KDP (unknown) for MCTEX data.</td>
479 </tr>
480
481 <tr>
482 <td>TI_INDEX</td>
483
484 <td>18</td>
485
486 <td>TIME (unknown) for MCTEX data.</td>
487 </tr>
488 </table>
489
490 <h4>
491 The Volume structure</h4>
492 The Volume structure represents the RADAR data for one, and only one, field
493 type. Upon ingest, the data for each field type is separated and placed
494 into separate volumes. This makes it convenient to manipulate volumes based
495 on their field type.
496 <p>The organization of the Volume structure closely resembles the organization
497 of the Radar structure. It, too, is compose of two parts:
498 <ul>
499 <li>
500 Volume header.</li>
501
502 <li>
503 Array of pointers to <a href="RSL_sweep_struct.html">Sweep</a>s.</li>
504 </ul>
505 To access elements in the Volume header, you use the syntax:
506 <pre>Volume *volume;
507 volume->h.<i>member</i>;</pre>
508 You can find a description of each volume header member later. The array
509 of pointers to <a href="RSL_sweep_struct.html">Sweep</a>s contains either
510 pointers to <a href="RSL_sweep_struct.html">Sweep</a>s of data or NULL.
511 The number of possible <a href="RSL_sweep_struct.html">Sweep</a>s in the
512 Volume is specified by <tt>volume->h.nsweeps</tt>. This number represents
513 the length of the array of pointers to <a href="RSL_sweep_struct.html">Sweep</a>s
514 and not the number of actual (non-NULL) sweeps in the volume.
515 <p>There are two methods to accessing sweeps:
516 <ul>
517 <li>
518 Use a loop index that ranges from 0 to <tt>volume->h.nsweeps-1</tt>.</li>
519
520 <li>
521 Use <a href="RSL_get_sweep.html">RSL_get_sweep</a> or other similiar RSL
522 sweep retieval functions.</li>
523 </ul>
524 Here are two coding examples that demonstrate how to access the array of
525 pointers to sweeps.
526 <p>Example 1:
527 <pre>Volume *volume;
528 Sweep *sweep;
529 int i;
530
531 /* Assume a non-NULL volume at this point. */
532 for (i=0; i&lt;volume->h.nsweeps; i++) {
533 &nbsp;&nbsp; sweep = volume->sweep[i];
534 &nbsp;&nbsp; if (sweep == NULL) continue; /* Skip NULL sweeps. */
535 &nbsp;&nbsp; /* Do something with this sweep. */
536 &nbsp;&nbsp; printf("Sweep %d elevation is %f\n", i, sweep->h.elev);
537 }</pre>
538 Example 2:
539 <pre>Volume *volume;
540 Sweep *sweep;
541 float elev;
542
543 /* No assumption about volume, it *can* be NULL! */
544 /* That's because RSL_get_sweep checks it. */
545 elev = 2.0;
546 sweep = RSL_get_sweep(volume, elev);
547 if (sweep != NULL)
548 &nbsp;&nbsp; printf("Sweep %d elevation is %f\n", i, sweep->h.elev);</pre>
549 Again, it is very important to check for NULL sweeps. By default volume->h.nsweeps
550 is the length of the array of pointers to <a href="RSL_sweep_struct.html">Sweep</a>s.
551 <h4>
552 The Sweep structure</h4>
553 The Sweep represents the data collected for one field type during one 360<sup>o</sup>
554 revolution of the RADAR. Like the Radar and Volume structures, the Sweep
555 organization is composed of two parts:
556 <ul>
557 <li>
558 Sweep header.</li>
559
560 <li>
561 Array of pointers to <a href="RSL_ray_struct.html">Ray</a>s.</li>
562 </ul>
563 To access elements in the Sweep header, you use the syntax:
564 <pre>Sweep *sweep;
565 sweep->h.<i>member</i>;</pre>
566 A description of each member of the Sweep header is presented later. The
567 array of pointers to <a href="RSL_ray_struct.html">Ray</a>s contains either
568 pointers to <a href="RSL_ray_struct.html">Ray</a>s of data or NULL. The
569 number of possible <a href="RSL_ray_struct.html">Ray</a>s in the Sweep
570 is specified by <tt>sweep->h.nrays</tt>. This number represents the length
571 of the array of pointers to <a href="RSL_ray_struct.html">Ray</a>s and
572 not the number of actual (non-NULL) rays in the Sweep.
573 <p>There are two methods to accessing rays:
574 <ul>
575 <li>
576 Use a loop index that ranges from 0 to <tt>sweep->h.nrays-1</tt>.</li>
577
578 <li>
579 Use <a href="RSL_get_ray.html">RSL_get_ray</a> or other similiar RSL ray
580 retieval functions.</li>
581 </ul>
582 Here are two coding examples illustrating how to access the array of pointers
583 to <a href="RSL_ray_struct.html">Ray</a>s.
584 <p>Example 1:
585 <pre>Sweep *sweep;
586 Ray *ray;
587 int i;
588
589 /* Assume a non-NULL sweep at this point. */
590 for (i=0; i&lt;sweep->h.nrays; i++) {
591 &nbsp;&nbsp; ray = sweep->ray[i];
592 &nbsp;&nbsp; if (ray == NULL) continue; /* Skip NULL rays. */
593 &nbsp;&nbsp; /* Do something with this ray. */
594 &nbsp;&nbsp; printf("Ray %d azimuth is %f\n", i, ray->h.azimuth);
595 }</pre>
596 Example 2:
597 <pre>Volume *volume;
598 Ray *ray;
599 float elev, azimuth;
600
601 /* No assumption about volume, it *can* be NULL! */
602 /* That's because RSL_get_ray checks it. */
603 elev = 2.0;
604 azimuth = 30.2;
605 ray = RSL_get_ray(volume, elev, azimuth);
606 if (ray != NULL)
607 &nbsp;&nbsp; printf("Ray %d elevation is %f, azimuth is %f\n", i, ray->h.elev, ray->h.azimuth);</pre>
608 You never know when you'll encounter NULL rays, so, make sure you test
609 for it. By default, sweep->h.nrays is the length of the array of pointers
610 to <a href="RSL_ray_struct.html">Ray</a>s which may or may not be the number
611 of non-NULL Rays present.
612 <h4>
613 The Ray structure</h4>
614 A ray of RADAR measurements represents data collected from close to the
615 RADAR to some maximum physical range. The <a href="RSL_ray_struct.html">Ray</a>,
616 too, is composed of two parts:
617 <ul>
618 <li>
619 Ray header.</li>
620
621 <li>
622 Array of field type measurements. These are not pointers. It is an array
623 of values.</li>
624 </ul>
625 We're getting close to the data, now. The ray header contains the largest
626 collection of members and describe all characteristics of the ray. To access
627 elements in the Ray header, you use the syntax:
628 <pre>Ray *ray;
629 ray->h.<i>member</i>;</pre>
630 A description of each member of the Ray header is described later. The
631 array of field type measurements contains the data, finally. The data type
632 for the data is <a href="RSL_range_struct.html">Range</a>. The <a href="RSL_range_struct.html">Range</a>
633 data type must be converted to float by using the function that is in ray
634 header: <tt>ray->h.f(r)</tt>, where <tt>r</tt> is of type <a href="RSL_range_struct.html">Range</a>.
635 These conversion functions are in the headers for the volume and sweep.
636 They are there only as a convenience to the application developer. The
637 number of data values in the Rays is specified by <tt>ray->h.nbins</tt>.
638 This number represents the length of the array of <a href="RSL_range_struct.html">Range</a>
639 values. There is no abiguity here, the number of data values (<a href="RSL_range_struct.html">Range</a>
640 values) exactly matches <tt>ray->h.nbins</tt>.
641 <p>There are two methods to accessing the data:
642 <ul>
643 <li>
644 Use a loop index that ranges from 0 to <tt>ray->h.nbins-1 </tt>calling
645 the <tt>ray->h.f</tt> function.</li>
646
647 <li>
648 Use <a href="RSL_get_value.html">RSL_get_value</a> or other similiar RSL
649 get value functions.</li>
650 </ul>
651 Here are two coding examples illustrating how to access the array of <a href="RSL_range_struct.html">Range</a>
652 values..
653 <p>Example 1:
654 <pre>Ray *ray;
655 int i;
656 float x;
657
658 /* Assume a non-NULL ray at this point. */
659 for (i=0; i&lt;ray->h.nbins; i++) {
660 &nbsp;&nbsp; x = ray->h.f(ray->range[i]);
661 &nbsp;&nbsp; /* Do something with this floating point value 'x'. */
662 &nbsp;&nbsp; printf("BIN %d value is %f\n", i, x);
663 }</pre>
664 Example 2:
665 <pre>Volume *volume;
666 float x;
667 float elev, azimuth, range;
668
669 /* No assumption about volume, it *can* be NULL! */
670 /* That's because RSL_get_value checks it. */
671 elev = 2.0;
672 azimuth = 30.2;
673 range = 87.3; /* KM */
674 x = RSL_get_value(volume, elev, azimuth, range);</pre>
675
676 <h2>
677 No assumptions as to the validity of the data.</h2>
678 The RSL does not modify the data in any way. It merely, loads the data
679 into the Radar structure. For instance, during the MCTEX experiment, the
680 azimuth values were incorrect for the first four tapes. They remain incorrect.
681 It is up to you to write a conversion procedure that corrects the problem.
682 <h2>
683 Pitfalls when using RSL in an application.</h2>
684 Here are some common mistakes made and things you should observe.
685 <ol>
686 <li>
687 Not checking for NULL. It is very important to check for NULL pointers.
688 In the RSL context, NULL is a perfectly valid ray, sweep or volume. Blindly
689 assuming that a volume, sweep, or ray exists is asking for trouble. When
690 using an RSL interface routine, a routine that is prefixed with <b>RSL_</b>,
691 you don't have to worry too much about passing null pointers. RSL routines
692 check their arguments.</li>
693
694 <li>
695 Not checking for NULL, when passing a volume, sweep, or ray pointer into
696 a routine. Check for NULL immediately.</li>
697
698 <li>
699 Not using the value for <tt>radar->h.nvolumes</tt>, <tt>volume->h.nsweeps</tt>,
700 <tt>sweep->h.nray</tt>.
701 They represent the maximum index possible and not the actual number of
702 non-NULL structures. Remember a NULL sweep, in RSL, is a valid sweep; you
703 just can't do anything with it. If you want to know how many non-NULL volumes
704 you have, you'll have to count them yourself. Do that by looping from 0
705 to <tt>radar->h.nvolumes - 1</tt>.</li>
706
707 <li>
708 Not using the value for <tt>radar->h.nvolumes</tt>, <tt>volume->h.nsweeps</tt>,
709 <tt>sweep->h.nrays</tt>,
710 and <tt>ray->h.nbins</tt> for the current object. Never assume that the
711 values are constant throughout the radar structure. They constantly change.
712 For instance, the number of bins may decrease as the sweep elevation increases.</li>
713
714 <li>
715 Not converting the data in the <a href="RSL_radar_struct.html">Radar</a>,
716 <a href="RSL_volume_struct.html">Volume</a>,
717 <a href="RSL_sweep_struct.html">Sweep</a>,
718 <a href="RSL_ray_struct.html">Ray</a>,
719 (really the Ray) to floating point before comparing with anything, including
720 comparing it with BADVAL, RFVAL, APFLAG, NOECHO. Do this conversion with
721 the <tt>h.f(c)</tt>, where <tt>c</tt> is <tt>ray->range[i]</tt> and is
722 of type <a href="RSL_range_struct.html">Range</a>. For example:</li>
723
724 <br>&nbsp;
725 <p>&nbsp;
726 <p><tt>x = ray->h.f(ray->range[ibin]);</tt>
727 <li>
728 Not converting a floating point number to internal storage with <tt>h.invf(x)</tt>,
729 where <tt>x</tt> is of type float, before filling the range array. For
730 example:</li>
731
732 <br>&nbsp;
733 <p>&nbsp;
734 <p><tt>ray->range[ibin] = ray->h.invf(x);</tt>
735 <li>
736 Forgetting to load a color table before calling an image generation function.
737 If you don't load a color table, your images will be black.</li>
738
739 <li>
740 Not rebinning the velocity data before making velocity images. The default
741 color table is setup to cover the range of -nyquist to +nyquist.</li>
742 </ol>
743
744 </body>
745 </html>