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

Last change on this file since 389 was 389, checked in by smasson, 15 years ago

small improvements

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