source: trunk/SRC/ReadWrite/ncdf_gettime.pro @ 344

Last change on this file since 344 was 344, checked in by smasson, 16 years ago

small improvements

  • Property svn:keywords set to Id
File size: 7.8 KB
Line 
1;+
2;
3; @file_comments
4; get the time axis from a netcdf_file and transforms it in
5; Julian days of IDL.
6;
7; @categories
8; Read NetCDF file
9;
10; @param filename {in}{required}{type=scalar string}
11; the name of the ncdf_file
12;
13; @param cdfid {in}{required}{type=scalar}
14; the ID of the ncdf_file, which is already open
15;
16; @keyword TIMEVAR {type=string}
17; It define the name of the variable that
18; contains the time axis. This keyword can be useful if there
19; is no unlimited dimension or if the time axis selected by default
20; (the first 1D array with unlimited dimension) is not the good one.
21;
22; @keyword CALLER {required}{type=scalar}
23; Used to specify the error messages. Give the name of the calling
24; procedure. It can be only 'read_ncdf' or 'scanfile'.
25;
26; @keyword ERR
27; Set this keyword to a named variable in which the value of the error
28; message will be returned
29;
30; @keyword _EXTRA
31; _EXTRA to be able to call ncdf_getmask with _extra keyword
32;
33; @returns
34; a double 1D array of IDL Julian days
35; In case of error return -1 if the time dimension was not found
36;               or return -jpt if it as been found that the time dimension size is jpt
37;
38; @restrictions
39; the calendar variable must have the units attribute
40; following the syntax bellow:
41;
42; time_counter:units = "seconds since 0001-01-01 00:00:00" ;
43; time_counter:units = "hours since 0001-01-01 00:00:00" ;
44; time_counter:units = "days since 1979-01-01 00:00:00" ;
45; time_counter:units = "months since 1979-01-01 00:00:00" ;
46; time_counter:units = "years since 1979-01-01 00:00:00" ;
47;
48; @history
49; August 2007: Sebastien Masson (smasson\@lodyc.jussieu.fr)
50;
51; @version
52; $Id$
53;-
54FUNCTION ncdf_gettime, filename, cdfid $
55                     , TIMEVAR=timevar, CALLER=caller, ERR=err, _EXTRA=ex
56;
57  compile_opt idl2, strictarrsubs
58;
59  @cm_4cal                      ;   needed for key_caltype
60;
61  inq = ncdf_inquire(cdfid)
62;----------------------------------------------------
63;`find the variable containing the time axis
64;----------------------------------------------------
65; we get its name through the keyword timevar
66  IF keyword_set(timevar) THEN BEGIN
67    timeid = ncdf_varid(cdfid, timevar)
68    IF timeid EQ -1 THEN BEGIN   ;   the variable is not found
69      CASE caller OF
70        'read_ncdf':err = 'No variable ' + timevar + 'found in '+filename+'. Use the TIMESTEP keyword'
71        'scanfile':err = 'No variable ' + timevar + 'found in '+filename+'. We create a fake calendar'
72      ENDCASE
73      return, -1
74    ENDIF
75    timeinq = ncdf_varinq(cdfid, timeid)
76    inq.recdim = timeinq.dim[0]
77    ncdf_diminq, cdfid, inq.recdim, timedimname, jpt
78  ENDIF ELSE BEGIN
79; we try to find the time axis automatically
80; we look for the infinite dimension
81    IF inq.recdim EQ -1 THEN BEGIN
82      CASE caller OF
83        'read_ncdf':err = 'the file '+filename+' as no infinite dimension. !C Use TIMESTEP or TIMEVAR keyword'
84        'scanfile':err = 'the file '+filename+' as no infinite dimension. We create a fake calendar'
85      ENDCASE
86      return, -1
87    ENDIF
88    ncdf_diminq, cdfid, inq.recdim, timedimname, jpt
89; we look for the variable containing the time axis
90; we look for the first variable having for only dimension inq.recdim
91    timeid = 0
92    REPEAT BEGIN                ; As long as we have not find a variable having only one dimension: the infinite one
93      timeinq = ncdf_varinq(cdfid, timeid) ; that the variable contain.
94      timeid = timeid+1
95    ENDREP UNTIL (n_elements(timeinq.dim) EQ 1 AND timeinq.dim[0] EQ inq.recdim) $
96       OR timeid EQ inq.nvars+1
97    IF timeid EQ inq.nvars+1 THEN BEGIN
98      CASE caller OF
99        'read_ncdf':err = 'the file '+filename+' as no time axis variable. !C Use the TIMESTEP keyword'
100        'scanfile':err = 'the file '+fullname+' has no time axis.!C we create a fake calendar ...'
101      ENDCASE
102      return, -jpt
103    ENDIF
104    timeid = timeid-1
105  ENDELSE
106;----------------------------------------------------
107; look for attribute units and calendar to know how to compte the calendar
108;----------------------------------------------------
109; no attribute for time variable...
110  IF timeinq.natts EQ 0 then begin
111    CASE caller OF
112      'read_ncdf':err = 'the variable '+timeinq.name+' has no attribute.!C Use the TIMESTEP keyword'
113      'scanfile':err = 'the variable '+timeinq.name+' has no attribute.!C we create a fake calendar ...'
114    ENDCASE
115    return, -jpt
116  ENDIF
117; get attributes names
118  attnames = strarr(timeinq.natts)
119  for attiq = 0, timeinq.natts-1 do attnames[attiq] = strlowcase(ncdf_attname(cdfid, timeid, attiq))
120; do we find units attribute?
121  IF (where(attnames EQ 'units'))[0] EQ -1 then BEGIN
122    CASE caller OF
123      'read_ncdf':err = 'Attribute ''units'' not found for the variable '+timeinq.name+' !C Use the TIMESTEP keyword'
124      'scanfile':err = 'Attribute ''units'' not found for the variable '+timeinq.name+'!C we create a fake calendar ...'
125    ENDCASE
126    return, -jpt
127  ENDIF
128; Is attribute "calendar" existing?
129; If no, we suppose that the calendar is gregorian calendar
130;
131  ncdf_getatt, cdfid, timeid, calendar = calendar, units = value
132  CASE calendar OF
133    'noleap':key_caltype = 'noleap'
134    '360d':key_caltype = '360d'
135    'greg':key_caltype = 'greg'
136  ENDCASE
137;----------------------------------------------------
138; decode units attribute
139;----------------------------------------------------
140;
141; time_counter:units = "seconds since 0001-01-01 00:00:00" ;
142; time_counter:units = "hours since 0001-01-01 00:00:00" ;
143; time_counter:units = "days since 1979-01-01 00:00:00" ;
144; time_counter:units = "months since 1979-01-01 00:00:00" ;
145; time_counter:units = "years since 1979-01-01 00:00:00" ;
146;
147; we decript the "units" attribute to find the time origin
148  value = strtrim(strcompress(string(value)), 2)
149  words = str_sep(value, ' ')
150  units = words[0]
151  units = strlowcase(units)
152  IF strpos(units, 's', strlen(units)-1) NE -1 THEN units = strmid(units, 0, strlen(units)-1)
153  IF strpos(units, 'julian_') NE -1 THEN units = strmid(units, 7)
154  IF units NE 'second' AND units NE 'hour' AND units NE 'day' $
155     AND units NE 'month' AND units NE 'year' THEN BEGIN
156    CASE caller OF
157      'read_ncdf':err = 'time units does not start with seconds/hours/days/months/years !C Use the TIMESTEP keyword'
158      'scanfile':err = 'time units does not start with seconds/hours/days/months/years !C we create a fake calendar ...'
159    ENDCASE
160    return, -jpt
161  ENDIF
162  IF stregex(value, '[^ ]* since ([0-9]){1,4}-([0-9]){1,2}-([0-9]){1,2}.*', /boolean) EQ 0 THEN BEGIN
163    CASE caller OF
164      'read_ncdf':err = 'attribute units of time has not the good format: [^ ]* since ([0-9]){1,4}-([0-9]){1,2}-([0-9]){1,2}.*!C Use the TIMESTEP keyword'
165      'scanfile':err = 'attribute units of time has not the good format: [^ ]* since ([0-9]){1,4}-([0-9]){1,2}-([0-9]){1,2}.*!C we create a fake calendar ...'
166    ENDCASE
167    return, -jpt
168  ENDIF
169  start = str_sep(words[2], '-')
170;----------------------------------------------------
171; compute time axis
172;----------------------------------------------------
173  ncdf_varget, cdfid, timeid, time
174  time = double(time)
175  case units of
176    'second':time = julday(start[1], start[2], start[0], 0, 0, 0)+time/86400.d
177    'hour':time = julday(start[1], start[2], start[0], 0, 0, 0)+time/24.d
178    'day':time = julday(start[1], start[2], start[0], 0, 0, 0)+time
179    'month':BEGIN
180      if total(fix(time) NE time) NE 0 then $ ; we switch to days with 30d/m
181         time = julday(start[1], start[2], start[0])+round(time*30) $
182      ELSE for t = 0, n_elements(time)-1 DO $
183         time[t] = julday(start[1]+time[t], start[2], start[0])
184    END
185    'year':BEGIN
186      if total(fix(time) NE time) NE 0 then $ ; we switch to days with 365d/y
187         time = julday(start[1], start[2], start[0])+round(time*365) $
188      ELSE for t = 0, n_elements(time)-1 do $
189         time[t] = julday(start[1], start[2], start[0]+time[t])
190    END
191  ENDCASE
192  time = double(time)
193;
194  return, time
195END
Note: See TracBrowser for help on using the repository browser.