[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[ldmMcidas #JRE-535181]: NLDN LDM data decoder



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.