NOTICE: This version of the NSF Unidata web site (archive.unidata.ucar.edu) is no longer being updated.
Current content can be found at unidata.ucar.edu.

To learn about what's going on, see About the Archive Site.

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: