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

Last change on this file since 325 was 325, checked in by pinsard, 16 years ago

modification of some headers (+some corrections) to prepare usage of the new idldoc

  • Property svn:keywords set to Id
File size: 8.3 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, TIMEVAR = timevar, CALLER = caller, ERR = err, _EXTRA = ex
55;
56  compile_opt idl2, strictarrsubs
57;
58  @cm_4cal                      ;   needed for key_caltype
59;
60  inq = ncdf_inquire(cdfid)
61;----------------------------------------------------
62;`find the variable containing the time axis
63;----------------------------------------------------
64; we get its name through the keyword timevar
65  IF keyword_set(timevar) THEN BEGIN
66    timeid = ncdf_varid(cdfid, timevar)
67    IF timeid EQ -1 THEN BEGIN   ;   the variable is not found
68      CASE caller OF
69        'read_ncdf':err = 'No variable ' + timevar + 'found in '+filename+'. Use the TIMESTEP keyword'
70        'scanfile':err = 'No variable ' + timevar + 'found in '+filename+'. We create a fake calendar'
71      ENDCASE
72      return, -1
73    ENDIF
74    timeinq = ncdf_varinq(cdfid, timeid)
75    inq.recdim = timeinq.dim[0]
76    ncdf_diminq, cdfid, inq.recdim, timedimname, jpt
77  ENDIF ELSE BEGIN
78; we try to find the time axis automatically
79; we look for the infinite dimension
80    IF inq.recdim EQ -1 THEN BEGIN
81      CASE caller OF
82        'read_ncdf':err = 'the file '+filename+' as no infinite dimension. !C Use TIMESTEP or TIMEVAR keyword'
83        'scanfile':err = 'the file '+filename+' as no infinite dimension. We create a fake calendar'
84      ENDCASE
85      return, -1
86    ENDIF
87    ncdf_diminq, cdfid, inq.recdim, timedimname, jpt
88; we look for the variable containing the time axis
89; we look for the first variable having for only dimension inq.recdim
90    timeid = 0
91    REPEAT BEGIN                ; As long as we have not find a variable having only one dimension: the infinite one
92      timeinq = ncdf_varinq(cdfid, timeid) ; that the variable contain.
93      timeid = timeid+1
94    ENDREP UNTIL (n_elements(timeinq.dim) EQ 1 AND timeinq.dim[0] EQ inq.recdim) $
95       OR timeid EQ inq.nvars+1
96    IF timeid EQ inq.nvars+1 THEN BEGIN
97      CASE caller OF
98        'read_ncdf':err = 'the file '+filename+' as no time axis variable. !C Use the TIMESTEP keyword'
99        'scanfile':err = 'the file '+fullname+' has no time axis.!C we create a fake calendar ...'
100      ENDCASE
101      return, -jpt
102    ENDIF
103    timeid = timeid-1
104  ENDELSE
105;----------------------------------------------------
106; look for attribute units and calendar to know how to compte the calendar
107;----------------------------------------------------
108; no attribute for time variable...
109  IF timeinq.natts EQ 0 then begin
110    CASE caller OF
111      'read_ncdf':err = 'the variable '+timeinq.name+' has no attribute.!C Use the TIMESTEP keyword'
112      'scanfile':err = 'the variable '+timeinq.name+' has no attribute.!C we create a fake calendar ...'
113    ENDCASE
114    return, -jpt
115  ENDIF
116; get attributes names
117  attnames = strarr(timeinq.natts)
118  for attiq = 0, timeinq.natts-1 do attnames[attiq] = strlowcase(ncdf_attname(cdfid, timeid, attiq))
119; do we find units attribute?
120  IF (where(attnames EQ 'units'))[0] EQ -1 then BEGIN
121    CASE caller OF
122      'read_ncdf':err = 'Attribute ''units'' not found for the variable '+timeinq.name+' !C Use the TIMESTEP keyword'
123      'scanfile':err = 'Attribute ''units'' not found for the variable '+timeinq.name+'!C we create a fake calendar ...'
124    ENDCASE
125    return, -jpt
126  ENDIF
127; Is attribute "calendar" existing?
128; If no, we suppose that the calendar is gregorian calendar
129;
130  if (where(attnames EQ 'calendar'))[0] NE -1 then BEGIN
131    ncdf_attget, cdfid, timeid, 'calendar', value
132    value = strlowcase(strtrim(value, 2))
133; unpade cm_4cal variable key_caltype (used by julday and caldat)
134    CASE value OF
135      'noleap':key_caltype = 'noleap'
136      '360d':key_caltype = '360d'
137      'greg':IF n_elements(key_caltype) EQ 0 THEN key_caltype = 'greg'
138      ELSE:BEGIN
139;            notused = report('Unknown calendar: '+value+', we use greg calendar.')
140        key_caltype = 'greg'
141      END
142    ENDCASE
143  ENDIF ELSE BEGIN
144;        notused = report('Unknown calendar, we use '+key_caltype+' calendar.')
145    IF n_elements(key_caltype) EQ 0 THEN key_caltype = 'greg'
146  ENDELSE
147;----------------------------------------------------
148; decode units attribute
149;----------------------------------------------------
150  ncdf_attget, cdfid, timeid, 'units', value
151;
152; time_counter:units = "seconds since 0001-01-01 00:00:00" ;
153; time_counter:units = "hours since 0001-01-01 00:00:00" ;
154; time_counter:units = "days since 1979-01-01 00:00:00" ;
155; time_counter:units = "months since 1979-01-01 00:00:00" ;
156; time_counter:units = "years since 1979-01-01 00:00:00" ;
157;
158; we decript the "units" attribute to find the time origin
159  value = strtrim(strcompress(string(value)), 2)
160  words = str_sep(value, ' ')
161  units = words[0]
162  units = strlowcase(units)
163  IF strpos(units, 's', strlen(units)-1) NE -1 THEN units = strmid(units, 0, strlen(units)-1)
164  IF strpos(units, 'julian_') NE -1 THEN units = strmid(units, 7)
165  IF units NE 'second' AND units NE 'hour' AND units NE 'day' $
166     AND units NE 'month' AND units NE 'year' THEN BEGIN
167    CASE caller OF
168      'read_ncdf':err = 'time units does not start with seconds/hours/days/months/years !C Use the TIMESTEP keyword'
169      'scanfile':err = 'time units does not start with seconds/hours/days/months/years !C we create a fake calendar ...'
170    ENDCASE
171    return, -jpt
172  ENDIF
173  IF stregex(value, '[^ ]* since ([0-9]){1,4}-([0-9]){1,2}-([0-9]){1,2}.*', /boolean) EQ 0 THEN BEGIN
174    CASE caller OF
175      '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'
176      '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 ...'
177    ENDCASE
178    return, -jpt
179  ENDIF
180  start = str_sep(words[2], '-')
181;----------------------------------------------------
182; compute time axis
183;----------------------------------------------------
184  ncdf_varget, cdfid, timeid, time
185  time = double(time)
186  case units of
187    'second':time = julday(start[1], start[2], start[0], 0, 0, 0)+time/86400.d
188    'hour':time = julday(start[1], start[2], start[0], 0, 0, 0)+time/24.d
189    'day':time = julday(start[1], start[2], start[0], 0, 0, 0)+time
190    'month':BEGIN
191      if total(fix(time) NE time) NE 0 then $ ; we switch to days with 30d/m
192         time = julday(start[1], start[2], start[0])+round(time*30) $
193      ELSE for t = 0, n_elements(time)-1 DO $
194         time[t] = julday(start[1]+time[t], start[2], start[0])
195    END
196    'year':BEGIN
197      if total(fix(time) NE time) NE 0 then $ ; we switch to days with 365d/y
198         time = julday(start[1], start[2], start[0])+round(time*365) $
199      ELSE for t = 0, n_elements(time)-1 do $
200         time[t] = julday(start[1], start[2], start[0]+time[t])
201    END
202  ENDCASE
203  time = double(time)
204;
205  return, time
206END
Note: See TracBrowser for help on using the repository browser.