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

20040430: UDUNITS question: months since ...



Manuel,

> To: address@hidden
> From: Manuel Fuentes <address@hidden>
> Subject: [Fwd: udunits question]
> Organization: ECMWF
> Keywords: 200404301801.i3UI1XtK021522

The above message contained the following:

> I'm coding some seasonal forecast monthly mean data
> in NetCDF, and I'm facing some problems when ncview
> displays the month of data. I code it as:
> "months since 1975-11-01 00:00:00.0";
> then months are 1, 2, 3, 4, 5 and 6 (I attach how the
> netcdf file looks like: nc.header).
> 
> I've tracked the problem down to udunits  1.12.1.
> I have prepared a test case in C (ud.c). I compile it with:
> cc -g -I/usr/local/apps/udunits/current/include -c ud.c
> cc -g -L/usr/local/apps/udunits/current/lib ud.o -o ud -ludunits -lc -lm
> I'm using udunits 1.12.1.
> 
> I expect it to give consecutive months, but instead it
> repeats December and jumps over February.
> leda:~/src/udunits) ./ud 1
> month: 12, Dec-1975
> leda:~/src/udunits) ./ud 2
> month: 12, Dec-1975
> leda:~/src/udunits) ./ud 3
> month: 1, Jan-1976
> leda:~/src/udunits) ./ud 4
> month: 3, Mar-1976
> leda:~/src/udunits) ./ud 5
> month: 4, Apr-1976
> leda:~/src/udunits) ./ud 6
> month: 5, May-1976
> 
> Do you have any suggestions how could I solve this problem ?

Unfortunately, a "month" is not a very good unit as the amount of time
it represents depends on the month.  Units aren't supposed to vary.  The
"month" unit used by the UDUNITS package is the mean tropical month,
which is a fixed amount of time.  This can lead to the problem you
encounted when such "units" are used too simply.

You can see what the UDUNITS package is doing by changing the statement

    printf("month: %d, %s-%04d\n", month,months[month-1], year );

to something like

    printf("year=%d month=%d day=%d hour=%d minute=%d\n", year, month,
        day, hour, minute);

How you "solve" the "problem" depends on what you want to do with the
time domain.  In general, you'll need to be more sophisticated in your
handling of time (i.e., you'll have to write more code).  This is
unfortunate, but unavoidable.  Sorry.

> Thanks in advance for your help,
> Manuel Fuentes
> Senior Analyst, Data and Services Section
> European Centre for Medium-Range Weather Forecasts  (ECMWF)
> Shinfield Park, Reading, Berks RG2 9AX, England
> 
> 
> --------------040406020507040803020702
> Content-Type: text/plain;
>  name="nc.header"
> Content-Transfer-Encoding: 7bit
> Content-Disposition: inline;
>  filename="nc.header"
> 
> netcdf output {
> dimensions:
>         longitude = 31 ;
>         latitude = 19 ;
>         number = 3 ;
>         fcmonth = 6 ;
> variables:
>         float longitude(longitude) ;
>                 longitude:units = "degrees_east" ;
>                 longitude:long_name = "longitude" ;
>         float latitude(latitude) ;
>                 latitude:units = "degrees_north" ;
>                 latitude:long_name = "latitude" ;
>         int number(number) ;
>                 number:long_name = "ensemble_member" ;
>         int fcmonth(fcmonth) ;
>                 fcmonth:units = "months since 1975-11-01 00:00:00.0" ;
>                 fcmonth:long_name = "Time" ;
>         short z(fcmonth, number, latitude, longitude) ;
>                 z:scale_factor = 0.0647855851250515 ;
>                 z:add_offset = 13909.0965134574 ;
>                 z:_FillValue = -32767s ;
>                 z:units = "m**2 s**-2" ;
>                 z:long_name = "Geopotential" ;
>         char MARS ;
>                 MARS:date = "19751101" ;
>                 MARS:time = "0000" ;
>                 MARS:step = "0" ;
>                 MARS:class = "dm" ;
>                 MARS:levtype = "pl" ;
>                 MARS:levelist = "850" ;
>                 MARS:domain = "g" ;
> 
> // global attributes:
>                 :Conventions = "CF-1.0" ;
>                 :history = "2004-04-30 16:25:00 GMT by mars2netcdf-0.91" ;
> data:
> 
>  longitude = -30, -27.5, -25, -22.5, -20, -17.5, -15, -12.5, -10, -7.5, -5, 
>     -2.5, 0, 2.5, 5, 7.5, 10, 12.5, 15, 17.5, 20, 22.5, 25, 27.5, 30, 32.5, 
>     35, 37.5, 40, 42.5, 45 ;
> 
>  latitude = 75, 72.5, 70, 67.5, 65, 62.5, 60, 57.5, 55, 52.5, 50, 47.5, 45, 
>     42.5, 40, 37.5, 35, 32.5, 30 ;
> 
>  number = 0, 1, 2 ;
> 
>  fcmonth = 1, 2, 3, 4, 5, 6 ;
> 
> 
> 
> --------------040406020507040803020702
> Content-Type: text/plain;
>  name="ud.c"
> Content-Transfer-Encoding: 7bit
> Content-Disposition: inline;
>  filename="ud.c"
> 
> #include <stdio.h>
> #include <stdlib.h>
> #include <udunits.h>
> 
> int main(int argc, char *argv[])
> {
>       utUnit  dataunits;
>       double  newmonth=2.0;
>       int     year, month, day, hour, minute;
>       float   second;
>       static  char *months[12] = { 
> "Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"};
>       char *units = "months since 1975-11-01 00:00:00.0";
>       int i = 0;
> 
>       if(argc==2)
>               newmonth = (double)atof(argv[1]);
> 
>       utInit(NULL);
>       if(utScan(units,&dataunits) != 0)
>       {
>               printf("internal error: udu_fmt_time can't parse data unit 
> string!\n" );
>               printf("problematic units: \"%s\"\n", units );
>               exit( -1 );
>       }
> 
>       if(utCalendar( newmonth, &dataunits, &year, &month, &day, &hour, 
> &minute, &second ) != 0)
>       {
>               printf("internal error: udu_fmt_time can't convert to calendar 
> value!\n");
>               printf("units: >%s<\n", units );
>               exit( -1 );
>       }
>       
>       printf("month: %d, %s-%04d\n", month,months[month-1], year );
>       return 0;
> }

Regards,
Steve Emmerson

> NOTE: All email exchanges with Unidata User Support are recorded in the
> Unidata inquiry tracking system and then made publically 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.