Hi Ken, re: > I'm a researcher at The University of Oklahoma who is interested in > looking at the NLDN data we are currently receiving. I believe McIDAS > and GEMPAK have built in decoders, but I need to see the actual data > values. Yes, the ldm-mcidas package contains a decoder that converts the NLDN data sent in the IDD into McIDAS-compatible (MD) files, and Unidata GEMPAK contains a decoder that converts the same data into GEMPAK-compatible files. > I found some notes on the internet stating there is currently > no decoder to convert to NetCDF format. Is that correct? There is no program available through Unidata that does this decoding. I do not know if someone in the community has created such a routine, however. > I am currently > working on a converter for the binary LDM access, but I have been unable > to correctly decipher the data. I've been following the documentation > located here <http://www.unidata.ucar.edu/data/lightning.html> but the > data files I have do not appear to match this format. Hmm... I updated the contents of the web page you reference to give specific information on the data being sent in the LDM/IDD 'NLDN' datastream. I am surprised by your comment that the information does not correspond to what you have, but I guess that it has mostly to do with the header found at the beginning of each IDD product. > Can you provide some more information or answer a few questions. > > * How many bytes is the file header. I make it out to be 84 bytes. > * How long is each data record? I make them out to be 28 bytes by > looking at patterns in the binary file, but would assume 33 from > the description in the table. > * Is "NLDN" written at the start of each flash? (ASCII?) > * What does the Size notation indicate in the Description table? > I'm assuming char[4] means 4 single character bytes and int[4] > means 1 integer of size 4 bytes. I think that the routine I use in the ldm-mcidas package would answer all of your questions, so I have attached it to this reply. > * What is the fill/padding value used? I am not sure. We skip over the padding value as they contain no useful information. > * Are all the bytes signed or unsigned? We treat them as unsigned. > Any information you can provide me would be very helpful. Please let me know if the source code (nldninput.c) answers your questions. Cheers, Tom **************************************************************************** Unidata User Support UCAR Unidata Program (303) 497-8642 P.O. Box 3000 address@hidden Boulder, CO 80307 ---------------------------------------------------------------------------- Unidata HomePage http://www.unidata.ucar.edu **************************************************************************** Ticket Details =================== Ticket ID: JRE-535181 Department: Support ldm-mcidas Priority: Normal Status: Closed
/* --------------------------------------------------------------------- ** ** Name: ingestnldn.c ** ** Purpose: Read NLDN binary records from LDM feed ** ** History: 19940302 - Adapted from 'ingesttonc.c' written by Ron ** Henderson of SUNY Albany ** ** --------------------------------------------------------------------- */ #include <stdlib.h> #include <stdio.h> #include <string.h> #include <time.h> #include <assert.h> #include <signal.h> #include "ulog.h" #include "cfortran.h" #include "alarm.h" #define INGESTORFLASHLEN 28 static unsigned alarm_timeout = 60; /* seconds; should suffice */ /* * SIGALRM handler. */ static void alarm_handler( sig ) int sig; { assert( SIGALRM == sig ); uerror( "nldninput(): no data read in %u seconds: simulating EOF", alarm_timeout ); } /* * Read a character from a file. * * Returns: * 1 Success * 0 Failure */ static int read_char( file, value ) FILE *file; char *value; { return fread(value, 1, 1, file) == 1; } /* * Read a short from a file. * * Returns: * 1 Success * 0 Failure */ static int read_short( file, value ) FILE *file; short *value; { unsigned char x[2]; /* NB: 16-bits assumed! */ int retcode; int num = 1; if (fread(x, 1, sizeof(x), file) == sizeof(x)) { *value = (x[0] << 8) | x[1]; retcode = 1; } else { retcode = 0; } return retcode; } /* * Read an integer from a file. * * Returns: * 1 Success * 0 Failure */ static int read_int( file, value ) FILE *file; int *value; { unsigned char x[4]; /* NB: 32-bits assumed! */ int retcode; int num = 1; if (fread(x, 1, sizeof(x), file) == sizeof(x)) { *value = (x[0] << 24) | (x[1] << 16) | (x[2] << 8) | x[3]; retcode = 1; } else { retcode = 0; } return retcode; } /* * Read an undetermined 4-byte sequence from a file; determine whether * or not it is a beginning of a header record; eat all header records * if they exist; and return the integer value at the beginning of a * flash record. * * Returns: * 1 Success * 0 Failure */ static int read_begin( file, value ) FILE *file; int *value; { unsigned char x[4]; /* NB: 32-bits assumed! */ int retcode = 0; /* failure default */ int num = 1; if (fread(x, 1, sizeof(x), file) == sizeof(x)) { if (strncmp((const char *)x, "NLDN", 4) != 0) { /* * Not a header record. Just return the data value. */ retcode = 1; } else { /* * Start of header records. Read them and the first data * value. */ int nhead; uinfo("nldninput(): Product header record found"); if (read_int(file, &nhead)) { int nflash; if (read_int(file, &nflash)) { unsigned char headr[280]; /* NB: 32-bits assumed! */ int bufsiz = nhead * INGESTORFLASHLEN - 12; if (fread(&headr[12], 1, bufsiz, file) == bufsiz) { if (nflash != 0) { if (fread(x, 1, sizeof(x), file) == sizeof(x)) retcode = 1; } } } } } if (retcode == 1) *value = (x[0] << 24) | (x[1] << 16) | (x[2] << 8) | x[3]; } return retcode; } /* * Read an NLDN record from a file stream. * * Returns: * INGESTORFLASHLEN -> Success * 0 -> Failure */ static int nldn_read( file, time_sec, time_nsec, lat, lon, sgnl, mult, semimaj, eccent, angle, chisqr ) FILE *file; int *time_sec; int *time_nsec; float *lat; float *lon; float *sgnl; int *mult; float *semimaj; float *eccent; float *angle; float *chisqr; { int iret; int nbytes; short fill_short; char fill_char; int rc = 0; /* failure */ struct { int lat; int lon; short sgnl; char mult; char semimaj; char eccent; char angle; char chisqr; } obs; if ( read_begin(file, time_sec) && /* 32-bits assumed */ read_int(file, time_nsec) && /* 32-bits assumed */ read_int(file, &obs.lat) && read_int(file, &obs.lon) && read_short(file, &fill_short) && read_short(file, &obs.sgnl) && read_short(file, &fill_short) && read_char(file, &obs.mult) && read_char(file, &fill_char) && read_char(file, &obs.semimaj) && read_char(file, &obs.eccent) && read_char(file, &obs.angle) && read_char(file, &obs.chisqr) ) { *lat = obs.lat / 1000.0; *lon = obs.lon / 1000.0; *sgnl = obs.sgnl / 10.0; *mult = obs.mult; *semimaj = obs.semimaj; *eccent = obs.eccent; *angle = obs.angle; *chisqr = obs.chisqr; rc = INGESTORFLASHLEN; } return( rc ); } /* * Return parameters from the input. In order to handle the situation in * which we're being fed by an LDM and the end of the data product is never * seen, we set an alarm prior to the read. * * Returns: * -1 Error: read error or EOF * 0 No data * INGESTORFLASHLEN Number of bytes read */ int nldninput(time_sec, time_nsec, lat, lon, sgnl, mult, semimaj, eccent, angle, chisqr) int *time_sec; int *time_nsec; float *lat; float *lon; float *sgnl; int *mult; float *semimaj; float *eccent; float *angle; float *chisqr; { int rc = -1; /* failure default */ static int alarm_initialized = 0; static Alarm timeout_alarm; if ( !alarm_initialized ) { alarm_init( &timeout_alarm, alarm_timeout, alarm_handler ); alarm_initialized = 1; } alarm_on(&timeout_alarm); /* set alarm */ rc = nldn_read( stdin, time_sec, time_nsec, lat, lon, sgnl, mult, semimaj, eccent, angle, chisqr ); alarm_off( &timeout_alarm ); /* disable alarm */ if ( !rc ) { if ( feof(stdin) ) { uinfo( "nldninput(): EOF on stdin" ); } else if ( ferror(stdin) ) { serror( "nldninput(): NLDN read error" ); } else { uinfo( "nldninput(): No data to read" ); } } return( rc ); } /* * FORTRAN interface to the above function. */ FCALLSCFUN10(INT,nldninput,NLDNIN,nldnin,PINT,PINT,PFLOAT,PFLOAT,PFLOAT,PINT,PFLOAT,PFLOAT,PFLOAT,PFLOAT)
NOTE: All email exchanges with Unidata User Support are recorded in the Unidata inquiry tracking system and then made publicly available through the web. If you do not want to have your interactions made available in this way, you must let us know in each email you send to us.