Radar *RSL_uf_to_radar_fp(FILE *fp) { union { char buf[6]; short sword; int word; } magic; Radar *radar; int nbytes; short sbytes; UF_buffer uf; enum UF_type uf_type; #define NEW_BUFSIZ 16384 radar = NULL; setvbuf(fp,NULL,_IOFBF,(size_t)NEW_BUFSIZ); /* Faster i/o? */ if (fread(magic.buf, sizeof(char), 6, fp) <= 0) return NULL; /* * Check for fortran record length delimeters, NCAR kludge. */ if (strncmp("UF", magic.buf, 2) == 0) uf_type = TRUE_UF; else if (strncmp("UF", &magic.buf[2], 2) == 0) uf_type = TWO_BYTE_UF; else if (strncmp("UF", &magic.buf[4], 2) == 0) uf_type = FOUR_BYTE_UF; else uf_type = NOT_UF; switch (uf_type) { case FOUR_BYTE_UF: if (radar_verbose_flag) fprintf(stderr,"UF file with 4 byte FORTRAN record delimeters.\n"); /* Handle first record specially, since we needed magic information. */ nbytes = magic.word; if (little_endian()) swap_4_bytes(&nbytes); memcpy(uf, &magic.buf[4], 2); (void)fread(&uf[1], sizeof(char), nbytes-2, fp); if (little_endian()) swap_uf_buffer(uf); (void)fread(&nbytes, sizeof(int), 1, fp); if (uf_into_radar(uf, &radar) == UF_DONE) break; /* Now the rest of the file. */ while(fread(&nbytes, sizeof(int), 1, fp) > 0) { if (little_endian()) swap_4_bytes(&nbytes); (void)fread(uf, sizeof(char), nbytes, fp); if (little_endian()) swap_uf_buffer(uf); (void)fread(&nbytes, sizeof(int), 1, fp); if (uf_into_radar(uf, &radar) == UF_DONE) break; } break; case TWO_BYTE_UF: if (radar_verbose_flag) fprintf(stderr,"UF file with 2 byte FORTRAN record delimeters.\n"); /* Handle first record specially, since we needed magic information. */ sbytes = magic.sword; if (little_endian()) swap_2_bytes(&sbytes); memcpy(uf, &magic.buf[2], 4); (void)fread(&uf[2], sizeof(char), sbytes-4, fp); if (little_endian()) swap_uf_buffer(uf); (void)fread(&sbytes, sizeof(short), 1, fp); uf_into_radar(uf, &radar); /* Now the rest of the file. */ while(fread(&sbytes, sizeof(short), 1, fp) > 0) { if (little_endian()) swap_2_bytes(&sbytes); (void)fread(uf, sizeof(char), sbytes, fp); if (little_endian()) swap_uf_buffer(uf); (void)fread(&sbytes, sizeof(short), 1, fp); if (uf_into_radar(uf, &radar) == UF_DONE) break; } break; case TRUE_UF: if (radar_verbose_flag) fprintf(stderr,"UF file with no FORTRAN record delimeters. Good.\n"); /* Handle first record specially, since we needed magic information. */ memcpy(&sbytes, &magic.buf[2], 2); /* Record length is in word #2. */ if (little_endian()) swap_2_bytes(&sbytes); /* # of 2 byte words. */ memcpy(uf, &magic.buf[0], 6); (void)fread(&uf[3], sizeof(short), sbytes-3, fp); if (little_endian()) swap_uf_buffer(uf); uf_into_radar(uf, &radar); /* Now the rest of the file. */ while(fread(uf, sizeof(short), 2, fp) > 0) { memcpy(&sbytes, &uf[1], 2); /* Record length is in word #2. */ if (little_endian()) swap_2_bytes(&sbytes); (void)fread(&uf[2], sizeof(short), sbytes-2, fp); /* Have words 1,2. */ if (little_endian()) swap_uf_buffer(uf); if (uf_into_radar(uf, &radar) == UF_DONE) break; } break; case NOT_UF: return NULL; break; } radar = reset_nsweeps_in_all_volumes(radar); radar = RSL_prune_radar(radar); return radar; }
Radar *RSL_wsr88d_to_radar(char *infile, char *call_or_first_tape_file) /* * Gets all volumes from the nexrad file. Input file is 'infile'. * Site information is extracted from 'call_or_first_tape_file'; this * is typically a disk file called 'nex.file.1'. * * -or- * * Uses the string in 'call_or_first_tape_file' as the 4 character call sign * for the sight. All UPPERCASE characters. Normally, this call sign * is extracted from the file 'nex.file.1'. * * Returns a pointer to a Radar structure; that contains the different * Volumes of data. */ { Radar *radar; Volume *new_volume; Wsr88d_file *wf; Wsr88d_sweep wsr88d_sweep; Wsr88d_file_header wsr88d_file_header; Wsr88d_tape_header wsr88d_tape_header; int n; int nsweep; int i; int iv; int nvolumes; int volume_mask[] = {WSR88D_DZ, WSR88D_VR, WSR88D_SW}; char *field_str[] = {"Reflectivity", "Velocity", "Spectrum width"}; Wsr88d_site_info *sitep; char site_id_str[5]; char *the_file; int expected_msgtype = 0; char version[8]; extern int rsl_qfield[]; /* See RSL_select_fields in volume.c */ extern int *rsl_qsweep; /* See RSL_read_these_sweeps in volume.c */ extern int rsl_qsweep_max; Radar *load_wsr88d_m31_into_radar(Wsr88d_file *wf); sitep = NULL; /* Determine the site quasi automatically. Here is the procedure: * 1. Determine if we have a call sign. * 2. Try reading 'call_or_first_tape_file' from disk. This is done via * wsr88d_read_tape_header. * 3. If no valid site info, abort. */ if (call_or_first_tape_file == NULL) { fprintf(stderr, "wsr88d_to_radar: No valid site ID info provided.\n"); return(NULL); } else if (strlen(call_or_first_tape_file) == 4) sitep = wsr88d_get_site(call_or_first_tape_file); else if (strlen(call_or_first_tape_file) == 0) { fprintf(stderr, "wsr88d_to_radar: No valid site ID info provided.\n"); return(NULL); } if (sitep == NULL) if (wsr88d_read_tape_header(call_or_first_tape_file, &wsr88d_tape_header) > 0) { memcpy(site_id_str, wsr88d_tape_header.site_id, 4); sitep = wsr88d_get_site(site_id_str); } if (sitep == NULL) { fprintf(stderr,"wsr88d_to_radar: No valid site ID info found.\n"); return(NULL); } if (radar_verbose_flag) fprintf(stderr,"SITE: %c%c%c%c\n", sitep->name[0], sitep->name[1], sitep->name[2], sitep->name[3]); memset(&wsr88d_sweep, 0, sizeof(Wsr88d_sweep)); /* Initialize to 0 a * heavily used variable. */ /* 1. Open the input wsr88d file. */ if (infile == NULL) the_file = "stdin"; /* wsr88d.c understands this to * mean read from stdin. */ else the_file = infile; if ((wf = wsr88d_open(the_file)) == NULL) { wsr88d_perror(the_file); return NULL; } /* 2. Read wsr88d headers. */ /* Return # bytes, 0 or neg. on fail. */ n = wsr88d_read_file_header(wf, &wsr88d_file_header); /* * Get the expected digital radar message type based on version string * from the Archive II header. The message type is 31 for Build 10, and 1 * for prior builds. Note that we consider AR2V0001 to be message type 1, * because it has been in the past, but with Build 10 this officially * becomes the version number for Evansville (KVWX), which will use message * type 31. This could be a problem if RSL is used to process KVWX. */ if (n > 0) { strncpy(version, wsr88d_file_header.title.filename, 8); if (strncmp(version,"AR2V0004",8) == 0 || strncmp(version,"AR2V0003",8) ==0 || strncmp(version,"AR2V0002",8) == 0) { expected_msgtype = 31; } else if (strncmp(version,"ARCHIVE2",8) == 0 || strncmp(version,"AR2V0001",8) == 0) { expected_msgtype = 1; } } if (n <= 0 || expected_msgtype == 0) { fprintf(stderr,"RSL_wsr88d_to_radar: "); if (n <= 0) fprintf(stderr,"wsr88d_read_file_header failed\n"); else fprintf(stderr,"Archive II header contains unknown version " ": '%s'\n", version); wsr88d_close(wf); free(radar); return NULL; } if (radar_verbose_flag) print_head(wsr88d_file_header); if (expected_msgtype == 31) { /* Get radar for message type 31. */ nvolumes = 6; radar = load_wsr88d_m31_into_radar(wf); if (radar == NULL) return NULL; } else { /* Get radar for message type 1. */ nvolumes = 3; /* Allocate all Volume pointers. */ radar = RSL_new_radar(MAX_RADAR_VOLUMES); if (radar == NULL) return NULL; /* Clear the sweep pointers. */ clear_sweep(&wsr88d_sweep, 0, MAX_RAYS_IN_SWEEP); /* Allocate a maximum of 30 sweeps for the volume. */ /* Order is important. WSR88D_DZ, WSR88D_VR, WSR88D_SW, is * assigned to the indexes DZ_INDEX, VR_INDEX and SW_INDEX respectively. */ for (iv=0; iv<nvolumes; iv++) if (rsl_qfield[iv]) radar->v[iv] = RSL_new_volume(20); /* LOOP until EOF */ nsweep = 0; for (;(n = wsr88d_read_sweep(wf, &wsr88d_sweep)) > 0; nsweep++) { if (rsl_qsweep != NULL) { if (nsweep > rsl_qsweep_max) break; if (rsl_qsweep[nsweep] == 0) continue; } if (radar_verbose_flag) fprintf(stderr,"Processing for SWEEP # %d\n", nsweep); /* wsr88d_print_sweep_info(&wsr88d_sweep); */ for (iv=0; iv<nvolumes; iv++) { if (rsl_qfield[iv]) { /* Exceeded sweep limit. * Allocate more sweeps. * Copy all previous sweeps. */ if (nsweep >= radar->v[iv]->h.nsweeps) { if (radar_verbose_flag) fprintf(stderr,"Exceeded sweep allocation of %d. " "Adding 20 more.\n", nsweep); new_volume = RSL_new_volume(radar->v[iv]->h.nsweeps+20); new_volume = copy_sweeps_into_volume(new_volume, radar->v[iv]); radar->v[iv] = new_volume; } if (wsr88d_load_sweep_into_volume(wsr88d_sweep, radar->v[iv], nsweep, volume_mask[iv]) != 0) { RSL_free_radar(radar); return NULL; } } } if (nsweep == 0) { /* Get Volume Coverage Pattern number for radar header. */ i=0; while (i < MAX_RAYS_IN_SWEEP && wsr88d_sweep.ray[i] == NULL) i++; if (i < MAX_RAYS_IN_SWEEP) radar->h.vcp = wsr88d_get_volume_coverage( wsr88d_sweep.ray[i]); } free_and_clear_sweep(&wsr88d_sweep, 0, MAX_RAYS_IN_SWEEP); } for (iv=0; iv<nvolumes; iv++) { if (rsl_qfield[iv]) { radar->v[iv]->h.type_str = strdup(field_str[iv]); radar->v[iv]->h.nsweeps = nsweep; } } } wsr88d_close(wf); /* * Here we will assign the Radar_header information. Take most of it * from an existing volume's header. */ radar_load_date_time(radar); /* Magic :-) */ radar->h.number = sitep->number; memcpy(&radar->h.name, sitep->name, sizeof(sitep->name)); memcpy(&radar->h.radar_name, sitep->name, sizeof(sitep->name)); /* Redundant */ memcpy(&radar->h.city, sitep->city, sizeof(sitep->city)); memcpy(&radar->h.state, sitep->state, sizeof(sitep->state)); strcpy(radar->h.radar_type, "wsr88d"); radar->h.latd = sitep->latd; radar->h.latm = sitep->latm; radar->h.lats = sitep->lats; if (radar->h.latd < 0) { /* Degree/min/sec all the same sign */ radar->h.latm *= -1; radar->h.lats *= -1; } radar->h.lond = sitep->lond; radar->h.lonm = sitep->lonm; radar->h.lons = sitep->lons; if (radar->h.lond < 0) { /* Degree/min/sec all the same sign */ radar->h.lonm *= -1; radar->h.lons *= -1; } radar->h.height = sitep->height; radar->h.spulse = sitep->spulse; radar->h.lpulse = sitep->lpulse; radar = RSL_prune_radar(radar); return radar; }
Radar *RSL_wsr88d_to_radar(char *infile, char *call_or_first_tape_file) /* * Gets all volumes from the nexrad file. Input file is 'infile'. * Site information is extracted from 'call_or_first_tape_file'; this * is typically a disk file called 'nex.file.1'. * * -or- * * Uses the string in 'call_or_first_tape_file' as the 4 character call sign * for the sight. All UPPERCASE characters. Normally, this call sign * is extracted from the file 'nex.file.1'. * * Returns a pointer to a Radar structure; that contains the different * Volumes of data. */ { Radar *radar; Volume *new_volume; Wsr88d_file *wf; Wsr88d_sweep wsr88d_sweep; Wsr88d_file_header wsr88d_file_header; Wsr88d_tape_header wsr88d_tape_header; int n; int nsweep; int iv; int nvolumes; int volume_mask[] = {WSR88D_DZ, WSR88D_VR, WSR88D_SW}; char *field_str[] = {"Reflectivity", "Velocity", "Spectrum width"}; Wsr88d_site_info *sitep; char site_id_str[5], failid[]="KFTG"; char *the_file; extern int rsl_qfield[]; /* See RSL_select_fields in volume.c */ extern int *rsl_qsweep; /* See RSL_read_these_sweeps in volume.c */ extern int rsl_qsweep_max; /* initialize site id to a failsafe value */ wsr88d_set_station_id(failid, -9999.0, -9999.0, -9999.0); sitep = NULL; /* Determine the site quasi automatically. Here is the procedure: * 1. Determine if we have a call sign. * 2. Try reading 'call_or_first_tape_file' from disk. This is done via * wsr88d_read_tape_header. * 3. If no valid site info, abort. */ if (call_or_first_tape_file == NULL) { fprintf(stderr, "wsr88d_to_radar: No valid site ID info provided.\n"); return(NULL); } else if (strlen(call_or_first_tape_file) == 4) sitep = wsr88d_get_site(call_or_first_tape_file); else if (strlen(call_or_first_tape_file) < 3) { /*fprintf(stderr, "wsr88d_to_radar: No valid site ID info provided, using default.\n"); strcpy(site_id_str,failid); sitep = wsr88d_get_site(site_id_str); -*enough for now. Message 31 contains ICAO and lat/lon */ /*return(NULL);*/ } if (sitep == NULL) if (wsr88d_read_tape_header(call_or_first_tape_file, &wsr88d_tape_header) > 0) { memcpy(site_id_str, wsr88d_tape_header.site_id, 4); sitep = wsr88d_get_site(site_id_str); } /*if (sitep == NULL) { fprintf(stderr,"wsr88d_to_radar: No valid site ID info found.\n"); return(NULL); } if (radar_verbose_flag) fprintf(stderr,"SITE: %c%c%c%c\n", sitep->name[0], sitep->name[1], sitep->name[2], sitep->name[3]);*/ memset(&wsr88d_sweep, 0, sizeof(Wsr88d_sweep)); /* Initialize to 0 a * heavily used variable. */ /* 1. Open the input wsr88d file. */ if (infile == NULL) the_file = "stdin"; /* wsr88d.c understands this to * mean read from stdin. */ else the_file = infile; if ((wf = wsr88d_open(the_file)) == NULL) { wsr88d_perror(the_file); return NULL; } nvolumes = 3; radar = RSL_new_radar(MAX_RADAR_VOLUMES); /* Allocate all Volume pointers. */ if (radar == NULL) return NULL; /* 2. Read wsr88d headers. */ /* Return # bytes, 0 or neg. on fail. */ n = wsr88d_read_file_header(wf, &wsr88d_file_header); if (n <= 0 || (strncmp(wsr88d_file_header.title.filename, "ARCHIVE2.", 9) != 0 && strncmp(wsr88d_file_header.title.filename, "AR2V000", 7) != 0)) { wsr88d_close(wf); free(radar); return NULL; } if (radar_verbose_flag) print_head(wsr88d_file_header); /* Clear the sweep pointers. */ clear_sweep(&wsr88d_sweep, 0, MAX_RAYS_IN_SWEEP); /* Allocate a maximum of 30 sweeps for the volume. */ /* Order is important. WSR88D_DZ, WSR88D_VR, WSR88D_SW, is * assigned to the indexes DZ_INDEX, VR_INDEX and SW_INDEX respectively. */ for (iv=0; iv<nvolumes; iv++) if (rsl_qfield[iv]) radar->v[iv] = RSL_new_volume(20); /* LOOP until EOF */ nsweep = 0; for (;(n = wsr88d_read_sweep(wf, &wsr88d_sweep)) > 0; nsweep++) { if (rsl_qsweep != NULL) { if (nsweep > rsl_qsweep_max) break; if (rsl_qsweep[nsweep] == 0) continue; } if (radar_verbose_flag) fprintf(stderr,"Processing for SWEEP # %d\n", nsweep); /* wsr88d_print_sweep_info(&wsr88d_sweep); */ for (iv=0; iv<nvolumes; iv++) { if (rsl_qfield[iv]) { if (nsweep >= radar->v[iv]->h.nsweeps) { /* Exceeded sweep limit. * Allocate more sweeps. * Copy all previous sweeps. */ if (radar_verbose_flag) fprintf(stderr,"Exceeded sweep allocation of %d. Adding 20 more.\n", nsweep); new_volume = RSL_new_volume(radar->v[iv]->h.nsweeps+20); new_volume = copy_sweeps_into_volume(new_volume, radar->v[iv]); radar->v[iv] = new_volume; } if (wsr88d_load_sweep_into_volume(wsr88d_sweep, radar->v[iv], nsweep, volume_mask[iv] ) != 0) { RSL_free_radar(radar); return NULL; } } } free_and_clear_sweep(&wsr88d_sweep, 0, MAX_RAYS_IN_SWEEP); } for (iv=0; iv<nvolumes; iv++) { if (rsl_qfield[iv]) { radar->v[iv]->h.type_str = strdup(field_str[iv]); radar->v[iv]->h.nsweeps = nsweep; } } wsr88d_close(wf); /* * Here we will assign the Radar_header information. Take most of it * from an existing volume's header. */ /* set the sitep info from level2 info, message31 if present (TODO) */ if ( sitep == NULL ) { float mess31_lat, mess31_lon, mess31_elev; float dms; wsr88d_get_station_id(site_id_str, &mess31_lat, &mess31_lon, &mess31_elev); sitep = wsr88d_get_site(site_id_str); mess31_lon = mess31_lon * -1.0; if ( sitep == NULL ) { printf("setting site information to ID %s lat %f lon %f elev %f\n", site_id_str, mess31_lat, mess31_lon, mess31_elev); sitep = (Wsr88d_site_info *)malloc(sizeof(Wsr88d_site_info)); sitep->number = -9999; sprintf(sitep->name,"%s\0",site_id_str); sprintf(sitep->city,"--\0"); sprintf(sitep->state,"--\0"); dms = fabs(mess31_lat); sitep->latd = floor(dms); dms = (dms - (float)sitep->latd)*60; sitep->latm = floor(dms); dms = (dms - (float)sitep->latm)*60; sitep->lats = floor(dms); dms = fabs(mess31_lon); sitep->lond = floor(dms); dms = (dms - (float)sitep->lond)*60; sitep->lonm = floor(dms); dms = (dms - (float)sitep->lonm)*60; sitep->lons = floor(dms); if ( mess31_lat < 0 ) { sitep->latd *= -1; sitep->latm *= -1; sitep->lats *= -1; } if ( mess31_lon < 0 ) { sitep->lond *= -1; sitep->lonm *= -1; sitep->lons *= -1; } sitep->height = (int)mess31_elev; sitep->bwidth = -9999; sitep->spulse = 1530; sitep->lpulse = 4630; } } radar_load_date_time(radar); /* Magic :-) */ radar->h.number = sitep->number; memcpy(&radar->h.name, sitep->name, sizeof(sitep->name)); memcpy(&radar->h.radar_name, sitep->name, sizeof(sitep->name)); /* Redundant */ memcpy(&radar->h.city, sitep->city, sizeof(sitep->city)); memcpy(&radar->h.state, sitep->state, sizeof(sitep->state)); strcpy(radar->h.radar_type, "wsr88d"); radar->h.latd = sitep->latd; radar->h.latm = sitep->latm; radar->h.lats = sitep->lats; if (radar->h.latd < 0) { /* Degree/min/sec all the same sign */ radar->h.latm *= -1; radar->h.lats *= -1; } radar->h.lond = sitep->lond; radar->h.lonm = sitep->lonm; radar->h.lons = sitep->lons; if (radar->h.lond < 0) { /* Degree/min/sec all the same sign */ radar->h.lonm *= -1; radar->h.lons *= -1; } radar->h.height = sitep->height; radar->h.spulse = sitep->spulse; radar->h.lpulse = sitep->lpulse; free(sitep); radar = RSL_prune_radar(radar); return radar; }