Re: problem using NCVIEW

Hi,

We had a problem with ncview 1.93b and reported it to the author, David Pierce. Not sure if it's the same segfault, but if you're compiling it yourself, try replacing a file with the one I attached. I don't think the patch was released yet from the official website.

Remik

Suraj Polade wrote:
Dear
      All,
I am using ncview for displaying the nc file, my operating system is Fedora Core-6 some file are geting display properaly but for some file it is showing the segmentation foult, can some one help me regarding this

Suraj D Polade
M.Tech (Atmospheric Sciences)
University of Pune
PM&A Devision
IITM Pune-411008


--
Remik Ziemlinski                        Raytheon Company
NOAA/Geophysical Fluid Dynamics Lab.    Remik.Ziemlinski at noaa d0t gov
P.O. Box 308                            1.609.452.6500 ext. 6977
Princeton, NJ 08542 USA                 1.609.987.5063 fax

#include <stdio.h>
#include <math.h>
#include "udunits.h"
#include "utCalendar_cal.h"

/* define DEBUG */

/*                                         J   F   M   A   M   J   J   A   S   
O   N   D    */
static long days_per_month_reg_year[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 
31, 30, 31 };
static utUnit udu_origin_zero;
static double udu_sec_since_ref_date( double val, utUnit *dataunits, int *yr0, 
int *mon0, 
                int *day0, int *hr0, int *min0, float *sec0 );
static int utCalendar_noleap_inner( double val, utUnit *dataunits, int *year, 
int *month, int *day, int *hour, 
                                int *minute, float *second, int days_per_year, 
long *days_per_month );
static int utCalendar_360( double val, utUnit *dataunits, int *year, int 
*month, int *day, int *hour, 
                                int *minute, float *second );
static int utCalendar_noleap( double val, utUnit *dataunits, int *year, int 
*month, int *day, int *hour, 
                                int *minute, float *second );

/******************************************************************************/
/* This extends the standard utCalendar call by recognizing CF-1.0 compliant
 * calendar names.
 * Here are some check values:
 *
 *   Units string               calendar        input val        Output date    
note
 * ---------------              --------        ----------       -----------    
----
 * days since 0001-01-01        standard        146000 (400x365) 0400-09-23     
400*365 days leaves us 100 leap days short of 1 Jan
 * days since 1001-01-01        standard        146000 (400x365) 1400-09-23     
Advance by 1000 yrs leaves same deficit as above
 * days since 1601-01-01        standard        146000 (400x365) 2000-09-26     
NOW have 3 less leap days than prev, since udunits 
 *                                                                              
switches to Gregorian calendar after 1582
 * days since 1001-01-01        standard        -146000          0601-04-11     
works with neg vals too; 400*365 leaves us in day #101
 * days since 2001-01-01        standard        -146000          1601-04-08     
Gregorian calendar, vs. Julian in prev line
 *
 * days since 1001-07-15        standard        146000           1401-04-06     
Offset can be other than first day of year; fall 100 
 *                                                                              
days short of going exactly 400 yrs, due to lack of leap days
 *
 * days since 0001-01-01        noleap          146000           0401-01-01     
No leap days, 400*365 = 400 yrs exactly
 * days since 1601-01-01        noleap          146000           2001-01-01     
"noleap" calendar doesn't change behavior around 1582
 * days since 2001-01-01        noleap          -146000          1601-01-01     
works with neg values too
 * days since 1001-01-01        noleap          -146000          0601-01-01     
neg values don't care before/after 1582 either
 */
int utCalendar_cal( double val, utUnit *dataunits, int *year, int *month, int 
*day, int *hour, 
                                int *minute, float *second, char *calendar ) 
{
        int err;
        static int have_shown_warning = 0;
        static int have_initted = 0;

#ifdef DEBUG
        printf( "entering utCalendar_cal\n" );
        printf( "Input value: %lf  Input calendar: %s\n", val, calendar );
#endif

        if( have_initted == 0 ) {
#ifdef DEBUG
                printf( "utCalendar_cal: initting\n" );
#endif
                
/*-------------------------------------------------------------------------------------------
                 * The idea of this snippet is to "trick" the udunits library 
into telling us the year, month,
                 * and date that the user specified in the units string.  This 
prevents us from having to 
                 * reinvent the wheel by parsing the units string ourselves.  
See further comments
                 * in routine udu_sec_since_ref_date
                 
*------------------------------------------------------------------------------------------*/
                err = utScan( "seconds since 1234-05-06 00:00", 
&udu_origin_zero );  /* YYYY-MM-DD used here is irrelevant */
                if( err == 0 ) {
                        udu_origin_zero.origin = 0.0;   /* override specified 
YYYY-MM-DD to set to same date as lib uses internally */
                        }
                else
                        {
                        fprintf( stderr, "Error, could not decode internal date 
string for reference date!\n" );
                        return(-1);
                        }
                have_initted = 1;
                }

        if( (calendar == NULL) || (strncasecmp(calendar,"standard",8)==0) || 
(strncasecmp(calendar,"gregorian",9)==0) ) {
#ifdef DEBUG
                printf( "utCalendar_cal: using standard calendar\n" );
#endif
                return( utCalendar( val, dataunits, year, month, day, hour, 
minute, second ));
                }
        else if( (strncasecmp(calendar,"365_day",7)==0) || 
(strncasecmp(calendar,"noleap",6)==0) ) {
#ifdef DEBUG
                printf( "utCalendar_cal: using 365-day calendar\n" );
#endif
                return( utCalendar_noleap( val, dataunits, year, month, day, 
hour, minute, second ));
                }
        else if( strncasecmp(calendar,"360_day",7)==0) {
#ifdef DEBUG
                printf( "utCalendar_cal: using 360-day calendar\n" );
#endif
                return( utCalendar_360( val, dataunits, year, month, day, hour, 
minute, second ));
                }
        else if( strncasecmp(calendar,"proleptic_gregorian",19)==0) {
                if( ! have_shown_warning ) {
                        have_shown_warning = 1;
                        fprintf( stderr, "sorry, proleptic_gregorian calendar 
not implemented yet; using standard calendar\n" );
                }
                return( utCalendar( val, dataunits, year, month, day, hour, 
minute, second ));
                }
        else if( strncasecmp(calendar,"julian",6)==0) {
                if( ! have_shown_warning ) {
                        have_shown_warning = 1;
                        fprintf( stderr, "sorry, julian calendar not 
implemented yet; using standard calendar\n" );
                }
                return( utCalendar( val, dataunits, year, month, day, hour, 
minute, second ));
                }
        else
                {
                if( ! have_shown_warning ) {
                        fprintf( stderr, "WARNING: unknown calendar: \"%s\". 
Using standard calendar instead!\n", calendar );
                        have_shown_warning = 1;
                }
                        return( utCalendar( val, dataunits, year, month, day, 
hour, minute, second ));
                }
}

/******************************************************************************/
double udu_sec_since_ref_date( double val, utUnit *dataunits, int *yr0, int 
*mon0, 
                int *day0, int *hr0, int *min0, float *sec0 )
{
        double retval;
        int err;

        /*---------------------------------------------------------------------
         * Use a bit of a trick to get the year, month, and day that the
         * original user specified in the units string and was subsequently
         * parsed by the udunits library.  We make use of the fact that the
         * udunits offset is set to some specific date -- it doesn't matter
         * which.  But everything is referenced to this date.  So we make
         * a time units, and SET ITS ORIGIN TO ZERO, so that it is "as if"
         * we specified the date relative to udunit's internal reference
         * date (currently, 2001-01-01).  We then convert the origin of the
         * user-specified units, which is the number of seconds since the
         * udunits reference date, into a calendar date.  Voila!  We then
         * have the year, month, day, etc. that the user specified.
         *--------------------------------------------------------------------*/
        err = utCalendar( dataunits->origin, &udu_origin_zero, yr0,
                mon0, day0, hr0, min0, sec0 );  /* note: all these yr0 etc 
values are RETURNED */

        retval = val * dataunits->factor;

        return( retval );
}

/*************************************************************************************/
/* A calendar with no leap days; days per month and year are passed in, not 
assumed!  
 * Can pass in days_per_year=365 and days_per_month={30,28,31,30, etc} for a 
"noleap" calendar,
 * or days_per_year=360 and days_per_month={30,30,30,...} for a "360 day" 
calendar
 */
int utCalendar_noleap_inner( double val, utUnit *dataunits, int *year, int 
*month, int *day, int *hour, 
                                int *minute, float *second, int days_per_year, 
long *days_per_month )
{
        int yr0, mon0, day0, hr0, min0;
        float sec0;
        double ss, ss_extra;
        long dy, ds, sec_per_day, sec_per_hour, sec_per_min, ss_i, nny;
        long ndays, nhrs, nmin;

        sec_per_day   = 86400;
        sec_per_hour  = 3600;
        sec_per_min   = 60;

        /* 
-------------------------------------------------------------------------------------
         * Get both the REFERENCE TIME that the netCDF file specifies for the 
units string
         * (yr0, mon0, day0, etc) and the number of seconds since that 
reference date.  I.e.,
         * if the units string is "days since 1979-01-01", then the reference 
date is 1 Jan 1979
         * and 'ss' is the number of seconds since that date that we want to 
turn into a calendar
         * date, given the specified calendar.
         
*--------------------------------------------------------------------------------------*/
        ss = udu_sec_since_ref_date( val, dataunits, &yr0, &mon0, &day0, &hr0, 
&min0, &sec0 );
#ifdef DEBUG
        printf( "converting time %lf seconds since %04d-%02d-%02d %02d:%02d\n", 
ss, yr0, mon0, day0, hr0, min0 ); 
#endif

        
/*--------------------------------------------------------------------------
         * If we have a date before our reference date (indicated by a negative 
ss),
         * then wind back the reference date to to be before the target
         * date.  This avoids having to muck around with negative offsets.
         
*------------------------------------------------------------------------*/
        if( ss < 0 ) {
                nny = -ss / (sec_per_day*days_per_year) + 1;
                yr0 -= nny;
                ss  += nny * sec_per_day*days_per_year;
                }

        /*-------------------------------------------------------------------
         * We now have seconds since (ss) yr0, mon0, day0, hr0, min0, sec0.
         * Try to turn this into integer days since reference date and seconds
         * extra, avoiding problems with roundoff and limited precision.  Not
         * an exact science.  We use days since (ds) instead of sticking 
         * strictly with seconds since (ss) becuase we can overflow longs in
         * fairly routine circumstances, if tring to put a century or so of
         * seconds into a long.
         *-------------------------------------------------------------------*/
        ds = (long)((ss + .01)/(double)sec_per_day);
        ss_extra = ss - ((double)ds)*((double)sec_per_day);  /* need to be 
careful of overflow here */
        if( ss_extra < 0. )
                ss_extra = 0;

#ifdef DEBUG
        printf( "# of days since ref date: %ld   # of extra seconds after days 
taken out: %lf\n", ds, ss_extra );
#endif

        /*--------------------------------------
         * Easier to do things relative to 1 Jan 
         *-------------------------------------*/
        if( (min0 != 0) || (hr0 != 0) || (day0 != 1) || (mon0 != 1)) {

                ss_extra += min0 * sec_per_min;
                min0 = 0;

                ss_extra += hr0 * sec_per_hour;
                hr0 = 0;

                ds += (day0-1);
                day0 = 1;

                while( mon0 > 1 ) {
                        ds += days_per_month[ mon0-2 ]; /*  -2 cuz -1 for prev 
month, -1 for 0 offset */
                        mon0--;
                        }
                }

        dy = ds / days_per_year;
        *year = yr0 + dy;
        ds = ds - dy*days_per_year;

        *month = 1;
        while( ds > days_per_month[(*month) - 1] - 1 ) {
                ds -= days_per_month[(*month) - 1];
                (*month)++;
                }

        *day = ds + 1;

        nhrs = ss_extra / sec_per_hour;
        *hour = nhrs;
        ss_extra -= nhrs * sec_per_hour;

        nmin = ss_extra / sec_per_min;
        *minute = nmin;
        ss_extra -= nmin * sec_per_min;

        *second = ss_extra;

        return(0);
}

/******************************************************************************/
int utCalendar_360( double val, utUnit *dataunits, int *year, int *month, int 
*day, int *hour, 
                                int *minute, float *second )
{
        long days_per_year;

        days_per_year = 360L;
        long days_per_month_360[] = { 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 
30, 30 };

        return( utCalendar_noleap_inner( val, dataunits, year, month, day, 
hour, minute, second,
                days_per_year, days_per_month_360 ));
}

/******************************************************************************/
int utCalendar_noleap( double val, utUnit *dataunits, int *year, int *month, 
int *day, int *hour, 
                                int *minute, float *second )
{
        long days_per_year;

        days_per_year = 365L;

        return( utCalendar_noleap_inner( val, dataunits, year, month, day, 
hour, minute, second,
                days_per_year, days_per_month_reg_year ));
}


  • 2007 messages navigation, sorted by:
    1. Thread
    2. Subject
    3. Author
    4. Date
    5. ↑ Table Of Contents
  • Search the netcdfgroup archives: