source: trunk/SRC/ToBeReviewed/WIDGET/AUTOUR_de_XXX/scanfile.pro @ 219

Last change on this file since 219 was 219, checked in by smasson, 17 years ago

get back to changeset:217

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 13.6 KB
Line 
1;+
2; @file_comments
3;
4;
5; @categories
6;
7;
8; @param NAMEFILE
9;
10;
11; @keyword GRID
12;
13;
14; @keyword _EXTRA
15; Used to pass your keywords
16;
17; @returns
18;
19;
20; @uses
21;
22;
23; @restrictions
24;
25;
26; @examples
27;
28;
29; @history
30;
31;
32; @version
33; $Id$
34;
35; @todo
36; seb : I don't know what to do with that...
37;
38;-
39;
40;  liste des presupposes:
41;       1) le fichier a lire est un fichier netcdf
42;       2) le nom de ce fichier finit
43;       par U.nc, V.nc, W.nc, T.nc ou F.nc, la lettre avant le
44;       nc designant la grille a laquelle se rapporte la champ.
45;       Si tel n''est pas la cas, le fichier est attribue a la grille
46;       T.
47;       3) ce fichier contient une dimension infinie qui doit etre
48;       celle qui se rapporte au temps et au mois 2 autres dimensions
49;       dont les noms sont 'x','lon...','xi_...' et 'y','lat...' ou
50;       'eta_...' ou bien en majuscule.
51;       4) il doit exiter ds ce fichier une unique variable n''ayant
52;       qu''une dimension et etant la dimension temporelle. cette
53;       variable sera prise comme axe des temps. Rq: si plusieurs
54;       variables verifient ces criteres on considere la premiere
55;       variable
56;       5) Cette variable axe des temps doit contenir l''attribut
57;       'units'qui doit etre ecrit suivant la syntaxe:
58;               "seconds since 0001-01-01 00:00:00"
59;               "hours since 0001-01-01 00:00:00"
60;               "days since 1979-01-01 00:59:59"
61;               "months since 1979-01-01 00:59:59"
62;               "years since 1979-01-01 00:59:59"
63;
64; je crois que c''est tout!
65;
66;        GRID='[UTVWF]' to specify the type of grid. Defaut is (1)
67;        based on the name of the file if the file ends by
68;        GRID[._][TUVFW].NC (not case sensible) or (2) T if case (1)
69;        is not found.
70;
71;------------------------------------------------------------
72FUNCTION scanfile, namefile, GRID = GRID, _extra = ex
73;
74  compile_opt idl2, strictarrsubs
75;
76@common
77;------------------------------------------------------------
78  res = -1
79;------------------------------------------------------------
80; filename
81;------------------------------------------------------------
82  fullname = isafile(filename = namefile, IODIRECTORY = iodir, _extra = ex)
83;------------------------------------------------------------
84; open file
85;------------------------------------------------------------
86  cdfid = ncdf_open(fullname)
87;------------------------------------------------------------
88; What contains the file?
89;------------------------------------------------------------
90  infile = ncdf_inquire(cdfid)  ;
91;------------------------------------------------------------
92; name of all dimensions
93;------------------------------------------------------------
94  namedim = strarr(infile.ndims)
95  for dimiq = 0, infile.ndims-1 do begin
96    ncdf_diminq, cdfid, dimiq, tmpname, value
97    namedim[dimiq] = strlowcase(tmpname)
98  ENDFOR
99; roms file?
100  dimidx = where(namedim EQ 'xi_rho' OR namedim EQ 'xi_u' OR namedim EQ 'xi_v' OR namedim EQ 'xi_psi')
101  IF dimidx[0] EQ -1 THEN BEGIN
102; we are looking for a x dimension with a name matching one of the following regular expression:
103    testname = ['longitude', 'lon', 'x', 'longitude*', 'lon*', 'x*', '*longitude*', '*lon*', '*x*']
104    cnt = -1
105    ii = 0
106    WHILE cnt NE 1 AND ii LT n_elements(testname) DO BEGIN
107      dimidx = where(strmatch(namedim, testname[ii]) EQ 1, cnt)
108      ii = ii+1
109    ENDWHILE
110    CASE cnt OF
111      0:begin
112        dummy = report(['none of the dimensions name matches one of the following regular expression:' $
113                        , '''longitude'', ''lon'', ''x'', ''longitude*'', ''lon*'', ''x*'', ''*longitude*'', ''*lon*'', ''*x*''' $
114                        , ' => we cannot find the x dimension'])
115        stop
116      END
117      1:dimidx = dimidx[0]
118      ELSE:begin
119        dummy = report(['several (and not one unique) dimensions name matches the following regular expression:' $
120                        , '''longitude'', ''lon'', ''x'', ''longitude*'', ''lon*'', ''x*'', ''*longitude*'', ''*lon*'', ''*x*''' $
121                        , ' => we cannot find the x dimension'])
122        stop
123      ENDELSE
124    ENDCASE
125  ENDIF
126; roms file?
127  dimidy = where(namedim EQ 'eta_rho' OR namedim EQ 'eta_u' OR namedim EQ 'eta_v' OR namedim EQ 'eta_psi')
128  IF dimidy[0] EQ -1 THEN BEGIN
129; we are looking for a y dimension with a name matching one of the following regular expression:
130    testname = ['latitude', 'lat', 'y', 'latitude*', 'lat*', 'y*', 'eta_*', '*latitude*', '*lat*', '*y*']
131    cnt = -1
132    ii = 0
133    WHILE cnt NE 1 AND ii LT n_elements(testname) DO BEGIN
134      dimidy = where(strmatch(namedim, testname[ii]) EQ 1, cnt)
135      ii = ii+1
136    ENDWHILE
137    CASE cnt OF
138      0:begin
139        dummy = report(['none of the dimensions name matches one of the following regular expression:' $
140                        , '''latitude'', ''lat'', ''y'', ''latitude*'', ''lat*'', ''y*'', ''eta_*'', ''*latitude*'', ''*lat*'', ''*y*''' $
141                        , ' => we cannot find the y dimension'])
142        stop
143      END
144      1:dimidy = dimidy[0]
145      ELSE:begin
146        dummy = report(['several (and not one unique) dimensions name matches the following regular expression:' $
147                        , '''latitude'', ''lat'', ''y'', ''latitude*'', ''lat*'', ''y*'', ''eta_*'', ''*latitude*'', ''*lat*'', ''*y*''' $
148                        , ' => we cannot find the x dimension'])
149        stop
150      ENDELSE
151    ENDCASE
152  ENDIF
153;------------------------------------------------------------
154; name of all variables
155;------------------------------------------------------------
156; we keep only the variables containing at least x, y and time dimension (if existing...)
157  namevar = strarr(infile.nvars)
158  for varid = 0, infile.nvars-1 do begin
159    invar = ncdf_varinq(cdfid, varid) ; what contains the variable?
160    if (inter(invar.dim, dimidx))[0] NE -1 AND $
161       (inter(invar.dim, dimidy))[0] NE -1 AND $
162       ((where(invar.dim EQ infile.recdim))[0] NE -1 OR infile.recdim EQ -1) $
163    THEN namevar[varid] = invar.name
164  ENDFOR
165  namevar = namevar[where(namevar NE '')]
166;------------------------------------------------------------
167; find vargrid for each selected variable...
168;------------------------------------------------------------
169  listgrid = strarr(n_elements(namevar))
170; default definitions
171  IF keyword_set(grid) THEN vargrid = strupcase(grid) ELSE vargrid = 'T'
172; look for values of vargrid for each variable
173  IF finite(glamu[0]) EQ 1 AND NOT keyword_set(grid) THEN BEGIN
174; for each variable, look if we in one of the case corresponding to ROMS conventions?
175    FOR i = 0, n_elements(namevar)-1 do begin
176      invar = ncdf_varinq(cdfid, namevar[i])
177      tmpnm = namedim[invar.dim]
178; are we in one of the case corresponding to ROMS conventions?
179      CASE 1 OF
180        tmpnm[2 <(invar.ndims-1)] EQ 's_w':vargrid = 'W'
181        tmpnm[0] EQ 'xi_rho' AND tmpnm[1] EQ 'eta_rho':listgrid[i] = 'T'
182        tmpnm[0] EQ 'xi_u'   AND tmpnm[1] EQ 'eta_u'  :listgrid[i] = 'U'
183        tmpnm[0] EQ 'xi_v'   AND tmpnm[1] EQ 'eta_v'  :listgrid[i] = 'V'
184        tmpnm[0] EQ 'xi_psi' AND tmpnm[1] EQ 'eta_psi':listgrid[i] = 'F'
185        tmpnm[0] EQ 'xi_rho' AND tmpnm[1] EQ 'eta_v'  :listgrid[i] = 'V'
186        tmpnm[0] EQ 'xi_u'   AND tmpnm[1] EQ 'eta_rho':listgrid[i] = 'U'
187        tmpnm[0] EQ 'xi_u'   AND tmpnm[1] EQ 'eta_v'  :listgrid[i] = 'F'
188        ELSE:
189      ENDCASE
190    ENDFOR
191    empty = where(listgrid EQ '')
192    IF empty[0] NE -1 THEN BEGIN   
193; could we define the grid type from the file name??
194      pattern = ['GRID.', 'GRID_', 'GRID', 'UPID_', '30ID_']
195      gdtype = ['T', 'U', 'V', 'W', 'F']
196      fnametest = strupcase(fullname)
197      FOR i = 0, n_elements(pattern)-1 DO BEGIN
198        FOR j = 0, n_elements(gdtype)-1 DO BEGIN
199          substr = pattern[i]+gdtype[j]
200          pos = strpos(fnametest, substr)
201          IF pos NE -1 THEN $
202             vargrid = strmid(fnametest, pos+strlen(substr)-1, 1)
203        ENDFOR
204      ENDFOR
205      listgrid[empty] = vargrid
206    ENDIF
207  ENDIF ELSE listgrid[*] = vargrid
208;------------------------------------------------------------
209; time axis
210;------------------------------------------------------------
211  date0fk = date2jul(19000101)
212  IF infile.recdim EQ -1 THEN BEGIN
213    jpt = 1
214    time = date0fk
215    fakecal = 1
216  ENDIF ELSE BEGIN
217    ncdf_diminq, cdfid, infile.recdim, timedimname, jpt
218; we look for the variable containing the time axis
219; we look for the first variable having for only dimension infile.recdim
220    varid = 0
221    repeat BEGIN
222      IF varid LT infile.nvars THEN BEGIN
223        invar = ncdf_varinq(cdfid, varid)
224        varid = varid+1       
225      ENDIF ELSE varid = 0
226    endrep until (n_elements(invar.dim) EQ 1 AND invar.dim[0] EQ infile.recdim) OR (varid EQ 0)
227    varid = varid-1
228;
229    CASE 1 OF
230      varid EQ -1:BEGIN
231        dummy = report('the file '+fullname+' has no time axis.!C we create a fake calendar ...')
232        fakecal = 1
233        time = date0fk + lindgen(1>jpt)
234      END
235      invar.natts EQ 0:BEGIN
236        dummy = report('the variable '+invar.name+' has no attribut.!C we create a fake calendar ...')
237        fakecal = 1
238        time = date0fk + lindgen(1>jpt)
239      END
240      ELSE:BEGIN
241;
242; we want to know which attributes are attached to the time variable...
243;
244        attnames = strarr(invar.natts)
245        for attiq = 0, invar.natts-1 do attnames[attiq] = ncdf_attname(cdfid, varid, attiq)
246        if (where(attnames EQ 'units'))[0] EQ -1 then BEGIN
247          dummy = report('Attribut ''units'' not found for the variable '+invar.name+'!C we create a fake calendar ...')
248          fakecal = 1
249          time = date0fk + lindgen(1>jpt)
250        ENDIF ELSE BEGIN
251; we read the time axis
252          ncdf_varget, cdfid, varid, time
253          time = double(time)
254          ncdf_attget, cdfid, varid, 'units', value
255; time_counter:units = "seconds since 0001-01-01 00:00:00" ;
256; time_counter:units = "hours since 0001-01-01 00:00:00" ;
257; time_counter:units = "days since 1979-01-01 00:00:00" ;
258; time_counter:units = "months since 1979-01-01 00:00:00" ;
259; time_counter:units = "years since 1979-01-01 00:00:00" ;
260          value = strtrim(strcompress(string(value)), 2)
261          mots = str_sep(value, ' ')
262          unite = mots[0]
263          unite = strlowcase(unite)
264          IF strpos(unite, 's', strlen(unite)-1) NE -1 THEN unite = strmid(unite, 0, strlen(unite)-1)
265          IF strpos(unite, 'julian_') NE -1 THEN unite = strmid(unite, 7)
266          err = 0
267          IF unite NE 'second' AND unite NE 'hour' AND unite NE 'day' $
268             AND unite NE 'month' AND unite NE 'year' THEN BEGIN
269            dummy = report('time units does not start with seconds/hours/days/months/years')
270            err = 1
271          ENDIF
272          IF stregex(value, '[^ ]* since ([0-9]){1,4}-([0-9]){1,2}-([0-9]){1,2}.*', /boolean) EQ 0 THEN BEGIN
273            dummy = report('attribut units of time has not the good format: [^ ]* since ([0-9]){1,4}-([0-9]){1,2}-([0-9]){1,2}.*')
274            err = 1
275          ENDIF
276          IF err GT 0 THEN BEGIN
277            fakecal = 1
278            time = date0fk + lindgen(1>jpt)
279          ENDIF ELSE BEGIN
280            debut = str_sep(mots[2], '-')
281;
282; now we try to find the attribut called calendar...
283; the the attribute "calendar" exists?
284; If no, we suppose that the calendar is gregorian calendar
285;
286            if (where(attnames EQ 'calendar'))[0] NE -1 then BEGIN
287              ncdf_attget, cdfid, varid, 'calendar', value
288              value = string(value)
289              CASE value OF
290                'noleap':key_caltype = 'noleap'
291                '360d':key_caltype = '360d'
292                'greg':IF n_elements(key_caltype) EQ 0 THEN key_caltype = 'greg'
293                ELSE:BEGIN
294;            notused = report('Unknown calendar: '+value+', we use greg calendar.')
295                  key_caltype = 'greg'
296                END
297              ENDCASE
298            ENDIF ELSE BEGIN
299;        notused = report('Unknown calendar, we use '+key_caltype+' calendar.')
300              IF n_elements(key_caltype) EQ 0 THEN key_caltype = 'greg'
301            ENDELSE
302;
303; BEWARE we have to get back the calendar attribute and ajust time by consequence...
304;
305;
306; We pass time in IDL julian days
307;
308            case unite of
309              'second':time = julday(debut[1], debut[2], debut[0])+time/86400.d
310              'hour':time = julday(debut[1], debut[2], debut[0])+time/24.d
311              'day':time = julday(debut[1], debut[2], debut[0])+time
312              'month':BEGIN
313                if total(fix(time) NE time) NE 0 then $ ; we switch to days with 30d/m
314                   time = julday(debut[1], debut[2], debut[0])+round(time*30) $
315                ELSE for t = 0, n_elements(time)-1 DO $
316                   time[t] = julday(debut[1]+time[t], debut[2], debut[0])
317              END
318              'year':BEGIN
319                if total(fix(time) NE time) NE 0 then $ ; we switch to days with 365d/y
320                   time = julday(debut[1], debut[2], debut[0])+round(time*365) $
321                ELSE for t = 0, n_elements(time)-1 do $
322                   time[t] = julday(debut[1], debut[2], debut[0]+time[t])
323              END
324            ENDCASE
325;
326; high frequency calendar: more than one element per day
327            IF max(histogram([long(time-time[0])])) GT 1 THEN fakecal = 1 ELSE fakecal = 0
328            date0fk = date2jul(19000101)
329            IF keyword_set(fakecal) THEN time = date0fk+lindgen(1>jpt) $
330            ELSE time = long(time)
331;
332          ENDELSE
333        ENDELSE
334      END
335    ENDCASE
336  ENDELSE
337;------------------------------------------------------------
338  ncdf_close, cdfid
339;------------------------------------------------------------
340  return, {filename:fullname, time_counter:time, listvar:namevar $
341           , listgrid:strupcase(listgrid), caltype:key_caltype $
342           , fakecal:date0fk*fakecal}
343end
Note: See TracBrowser for help on using the repository browser.