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