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
RevLine 
[150]1;+
2; @file_comments
[2]3;
[150]4;
5; @categories
6;
7;
8; @param NAMEFILE
9;
10;
[219]11; @keyword GRID
[150]12;
[219]13;
[150]14; @keyword _EXTRA
[219]15; Used to pass your keywords
[150]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;
[2]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
[69]49;       dont les noms sont 'x','lon...','xi_...' et 'y','lat...' ou
50;       'eta_...' ou bien en majuscule.
[2]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;
[69]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.
[2]70;
71;------------------------------------------------------------
[69]72FUNCTION scanfile, namefile, GRID = GRID, _extra = ex
[114]73;
74  compile_opt idl2, strictarrsubs
75;
[2]76@common
77;------------------------------------------------------------
[219]78  res = -1
79;------------------------------------------------------------
[69]80; filename
[2]81;------------------------------------------------------------
[69]82  fullname = isafile(filename = namefile, IODIRECTORY = iodir, _extra = ex)
[2]83;------------------------------------------------------------
[69]84; open file
[2]85;------------------------------------------------------------
[69]86  cdfid = ncdf_open(fullname)
[2]87;------------------------------------------------------------
[69]88; What contains the file?
[2]89;------------------------------------------------------------
[219]90  infile = ncdf_inquire(cdfid)  ;
[2]91;------------------------------------------------------------
[69]92; name of all dimensions
[2]93;------------------------------------------------------------
[219]94  namedim = strarr(infile.ndims)
95  for dimiq = 0, infile.ndims-1 do begin
[69]96    ncdf_diminq, cdfid, dimiq, tmpname, value
97    namedim[dimiq] = strlowcase(tmpname)
[49]98  ENDFOR
[219]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
[69]153;------------------------------------------------------------
154; name of all variables
155;------------------------------------------------------------
156; we keep only the variables containing at least x, y and time dimension (if existing...)
[219]157  namevar = strarr(infile.nvars)
158  for varid = 0, infile.nvars-1 do begin
[69]159    invar = ncdf_varinq(cdfid, varid) ; what contains the variable?
[172]160    if (inter(invar.dim, dimidx))[0] NE -1 AND $
161       (inter(invar.dim, dimidy))[0] NE -1 AND $
[219]162       ((where(invar.dim EQ infile.recdim))[0] NE -1 OR infile.recdim EQ -1) $
[69]163    THEN namevar[varid] = invar.name
[49]164  ENDFOR
165  namevar = namevar[where(namevar NE '')]
[2]166;------------------------------------------------------------
[172]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;------------------------------------------------------------
[69]209; time axis
[2]210;------------------------------------------------------------
[69]211  date0fk = date2jul(19000101)
[219]212  IF infile.recdim EQ -1 THEN BEGIN
[69]213    jpt = 1
214    time = date0fk
215    fakecal = 1
216  ENDIF ELSE BEGIN
[219]217    ncdf_diminq, cdfid, infile.recdim, timedimname, jpt
[69]218; we look for the variable containing the time axis
[219]219; we look for the first variable having for only dimension infile.recdim
[69]220    varid = 0
221    repeat BEGIN
[219]222      IF varid LT infile.nvars THEN BEGIN
[167]223        invar = ncdf_varinq(cdfid, varid)
224        varid = varid+1       
225      ENDIF ELSE varid = 0
[219]226    endrep until (n_elements(invar.dim) EQ 1 AND invar.dim[0] EQ infile.recdim) OR (varid EQ 0)
[69]227    varid = varid-1
[49]228;
[69]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
[181]233        time = date0fk + lindgen(1>jpt)
[69]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
[181]238        time = date0fk + lindgen(1>jpt)
[69]239      END
240      ELSE:BEGIN
[49]241;
[69]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
[167]247          dummy = report('Attribut ''units'' not found for the variable '+invar.name+'!C we create a fake calendar ...')
[69]248          fakecal = 1
[181]249          time = date0fk + lindgen(1>jpt)
[69]250        ENDIF ELSE BEGIN
[150]251; we read the time axis
[69]252          ncdf_varget, cdfid, varid, time
253          time = double(time)
254          ncdf_attget, cdfid, varid, 'units', value
[2]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" ;
[69]260          value = strtrim(strcompress(string(value)), 2)
261          mots = str_sep(value, ' ')
262          unite = mots[0]
[198]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)
[172]266          err = 0
[198]267          IF unite NE 'second' AND unite NE 'hour' AND unite NE 'day' $
268             AND unite NE 'month' AND unite NE 'year' THEN BEGIN
[172]269            dummy = report('time units does not start with seconds/hours/days/months/years')
270            err = 1
271          ENDIF
[199]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}.*')
[198]274            err = 1
275          ENDIF
[172]276          IF err GT 0 THEN BEGIN
277            fakecal = 1
[181]278            time = date0fk + lindgen(1>jpt)
[172]279          ENDIF ELSE BEGIN
280            debut = str_sep(mots[2], '-')
[2]281;
[49]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
[2]285;
[172]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
[49]294;            notused = report('Unknown calendar: '+value+', we use greg calendar.')
[172]295                  key_caltype = 'greg'
296                END
297              ENDCASE
298            ENDIF ELSE BEGIN
[49]299;        notused = report('Unknown calendar, we use '+key_caltype+' calendar.')
[172]300              IF n_elements(key_caltype) EQ 0 THEN key_caltype = 'greg'
301            ENDELSE
[49]302;
[167]303; BEWARE we have to get back the calendar attribute and ajust time by consequence...
[2]304;
305;
[167]306; We pass time in IDL julian days
[2]307;
[172]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
[69]325;
326; high frequency calendar: more than one element per day
[172]327            IF max(histogram([long(time-time[0])])) GT 1 THEN fakecal = 1 ELSE fakecal = 0
328            date0fk = date2jul(19000101)
[181]329            IF keyword_set(fakecal) THEN time = date0fk+lindgen(1>jpt) $
[172]330            ELSE time = long(time)
[69]331;
[172]332          ENDELSE
[69]333        ENDELSE
334      END
335    ENDCASE
336  ENDELSE
[2]337;------------------------------------------------------------
[69]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}
[2]343end
Note: See TracBrowser for help on using the repository browser.