source: trunk/SRC/ReadWrite/read_grads.pro @ 121

Last change on this file since 121 was 121, checked in by pinsard, 18 years ago

correction of some *.pro using aspell list; introduction of default idldoc syntax

  • Property svn:executable set to *
File size: 11.5 KB
Line 
1;------------------------------------------------------------
2;------------------------------------------------------------
3;------------------------------------------------------------
4;+
5; @file_comments reading grads file (except "data type station" or "grib")
6; from the grads control file even if there is multiple data files.
7;
8; @categories reading function
9;
10;       @param var {in}{required} the variable name
11;       @param date1 {in}{required} date of the beginning (yyyymmdd if TIMESTEP is not activate)
12;       @param date2 {in}{optional} last date. Optionnal, if not scpecified date2=date1
13;     
14; @keyword FILENAME the grads control file name: 'xxxx.ctl'
15;
16; @file_comments keyword GLAMBOUNDARY (via computegrid.pro) a 2 elements vector,
17;       {lon1,lon2], giving the longitude boundaries that should be
18;       used to visualize the data.
19;         lon2 > lon1
20;         lon2 - lon1 eq 360
21;       key_shift will be automatically defined according to
22;       GLAMBOUNDARY.
23;
24;       @keyword /TIMESTEP to specify that the dates are time steps instead of
25;       true calendar.
26;
27;        @file_comments keyword IODIRECTORY a string giving the name of iodirectory (see
28;       isafile.pro for all possibilities). default value is common
29;       variable iodir
30;
31; @file_comments
32;---------------
33; NOT yet available
34;---------------
35;
36;       @hidden BOX a 4 or 6 elements 1d array, [lon1,lon2,lat1,lat2, depth1,
37;       depth2], that specifies the area where data must be read
38;
39;       @hidden EVERYTHING
40;
41;       @hidden NOSTRUCTURE
42;       
43; @returns an array
44;
45; @uses common
46;
47; @restriction define all the grid parameters (defined in common.pro)
48; associated to the data.
49;
50; @restrictions this function call the procedure scanfile that use the
51; unix commands grep and sed
52;
53; @examples
54;    IDL> a=read_grads('sst',19900101,19900131,filename='outputs.ctl')
55;    IDL> plt, a
56;
57; @history Sebastien Masson (smasson\@lodyc.jussieu.fr)
58;
59;-
60;------------------------------------------------------------
61;------------------------------------------------------------
62;------------------------------------------------------------
63
64FUNCTION read_grads, var, date1, date2, FILENAME = filename, BOX=box, TIMESTEP = timestep, EVERYTHING = everything, NOSTRUCT = nostruct, _EXTRA = ex
65;---------------------------------------------------------
66;
67  compile_opt idl2, strictarrsubs
68;
69@cm_4mesh
70@cm_4data
71@cm_4cal
72  IF NOT keyword_set(key_forgetold) THEN BEGIN
73@updatenew
74  ENDIF
75;------------------------------------------------------------
76; we find the filename.
77;------------------------------------------------------------
78   filename = isafile(FILENAME = filename, IODIRECTORY = iodir, _EXTRA = ex)
79   if size(filename, /type) NE 7 then $
80    return, report('read_ncdf cancelled')
81;------------------------------------------------------------
82; we scan the control file called filename
83;------------------------------------------------------------
84   scanctl, filename, filesname, jpt1file, varsname, varslev, swapbytes, bigendian, littleendian, f77sequential, fileheader, theader, xyheader, VARFMT = varfmt, _EXTRA = ex
85   if n_elements(varfmt) EQ 0 then varfmt = 'float'
86;------------------------
87;------------------------
88; check date1 and date2 and found the starting index "t1" and the
89; ending index "t2" that corresponds to the time series specified by
90; date1 and date2 for the time axis defined in the .ctl file.
91;------------------------
92;------------------------
93   if n_elements(date1) EQ 0 then begin
94      t0 = 0
95      t1 = 0
96   ENDIF
97   if n_elements(date2) EQ 0 then date2 = date1
98   if keyword_set(timestep) then BEGIN
99      if date1 GT date2 then begin
100         print, 'date2 must be larger than date1'
101         return, -1
102      endif
103      t1 = 0 > long(date1) < (jpt-1)
104      t2 = t1 > long(date2) < (jpt-1)
105   ENDIF ELSE BEGIN
106      jdate1 = date2jul(date1, /grads) < time[jpt-1]
107      jdate2 = time[0] > date2jul(date2, /grads)
108      if jdate1 GT jdate2 then begin
109         print, 'date2 must be larger than date1'
110         return, -1
111      endif
112      t1 = (where(time GE jdate1))[0]
113      tmp = where(time LE jdate2, t2)
114      t2 = t2-1
115   ENDELSE
116   if t2 LT t1 then begin
117      print, 'There is no date between date1 and date2'
118      return, -1
119   endif
120   jpt2read = t2-t1+1
121;------------------------
122;------------------------
123; index of the variable
124;------------------------
125;------------------------
126   varid = where(strlowcase(varsname) EQ strlowcase(var))
127   varid = varid[0]
128   if varid EQ -1 then begin
129      print, var+' not found in the variable liste of '+filename
130      return,  -1
131   ENDIF
132   varname = var
133   if varslev[varid] EQ 1 then res = fltarr(jpi, jpj, jpt2read, /nozero) $
134   ELSE res = fltarr(jpi, jpj, varslev[varid], jpt2read, /nozero)
135;------------------------
136;------------------------
137; find the first file to be read according to the lile list,, the
138; number of time step in each file and t1 and t2
139;------------------------
140;------------------------
141   indf2read = t1/jpt1file
142   startread = t1-indf2read*jpt1file
143   alreadyread = 0
144readagain:
145   jpt2read1file = min([jpt1file-startread, jpt2read])
146   f2read = filesname[indf2read]
147;------------------------
148;------------------------
149; opening
150;------------------------
151;------------------------;
152; check the existance of the file
153   f2read = isafile(filename = f2read, iodirectory = iodir, _EXTRA = ex)
154; if the file is stored on tape
155   if !version.os_family EQ 'unix' then spawn, 'file '+f2read+' > /dev/null'
156; open the file
157   openr, unit, f2read, /get_lun, error=err $
158    , swap_if_little_endian = bigendian $
159    , swap_if_big_endian = littleendian $
160    , swap_endian = swapbytes
161   if err ne 0 then begin
162      print,!err_string
163      return, -1
164   endif
165;------------------------
166   case varfmt of
167      'byte':fmtsz = 1l
168      'uint':fmtsz = 2l
169      'int':fmtsz = 2l
170      'long':fmtsz = 4l
171      'float':fmtsz = 4l
172   endcase
173;------------------------
174; check its size
175   addf77sec = long(4*2*f77sequential)
176   xyblocsize = xyheader + addf77sec*(xyheader NE 0) + jpi*jpj*fmtsz +addf77sec
177   nxybloc = long(total(varslev))
178   filesize = (fileheader + addf77sec*(fileheader NE 0)) $
179    +(theader+addf77sec*(theader NE 0) + nxybloc*xyblocsize)*jpt1file
180   infof2read=fstat(unit)
181   if infof2read.size NE filesize then begin
182      print, 'According to '+filename+' the file size must be '+strtrim(filesize, 1)+' instead of '+strtrim(infof2read.size, 1)
183      print, 'jpi: '+strtrim(jpi, 2)
184      print, 'jpj: '+strtrim(jpj, 2)
185      print, 'jpt: '+strtrim(jpt, 2)
186      print, 'format size in byte: '+strtrim(fmtsz, 2)
187      print, 'number of xy arrays: '+strtrim(nxybloc, 2)
188      return, -1
189   endif
190;------------------------
191;------------------------
192; reading
193;------------------------
194;------------------------;
195;------------------------;
196; loop on the time steps to be read in one file
197   for i = 0, jpt2read1file-1 do begin
198; computing the offset
199      offset = (fileheader + addf77sec*(fileheader NE 0)) $
200       +(theader+addf77sec*(theader NE 0) + nxybloc*xyblocsize)*(startread+i) $
201       +theader+addf77sec*(theader NE 0)
202      if varid NE 0 THEN $
203       offset = offset + long(total(varslev[0:varid-1]))*xyblocsize
204; if there is only one level
205      IF varslev[varid] EQ 1 then begin
206         case varfmt of
207            'byte':a=assoc(unit, bytarr(jpi,jpj,/nozero), offset+4*f77sequential)
208            'uint':a=assoc(unit,uintarr(jpi,jpj,/nozero), offset+4*f77sequential)
209            'int':a=assoc(unit,  intarr(jpi,jpj,/nozero), offset+4*f77sequential)
210            'long':a=assoc(unit, lonarr(jpi,jpj,/nozero), offset+4*f77sequential)
211            'float':a=assoc(unit,fltarr(jpi,jpj,/nozero), offset+4*f77sequential)
212         endcase
213         res[*, *, i+alreadyread]=a[0]
214      ENDIF ELSE BEGIN ; more than 1 level to be read
215         if f77sequential then BEGIN ; sequential access
216            case varfmt of
217               'byte':a=assoc(unit, bytarr(jpi*jpj+8, varslev[varid],/nozero), offset)
218               'uint':a=assoc(unit,uintarr(jpi*jpj+4, varslev[varid],/nozero), offset)
219               'int':a=assoc(unit,  intarr(jpi*jpj+4, varslev[varid],/nozero), offset)
220               'long':a=assoc(unit, lonarr(jpi*jpj+2, varslev[varid],/nozero), offset)
221               'float':a=assoc(unit,fltarr(jpi*jpj+2, varslev[varid],/nozero), offset)
222            endcase
223            tmp = a[0]
224            case varfmt OF ; we cut the headers and tailers of f77 write
225               'byte': tmp = tmp[4:jpi*jpj+3, *]
226               'uint': tmp = tmp[2:jpi*jpj+1, *]
227               'int':  tmp = tmp[2:jpi*jpj+1, *]
228               'long': tmp = tmp[1:jpi*jpj+0, *]
229               'float':tmp = tmp[1:jpi*jpj+0, *]
230            endcase
231            if keyword_set(key_zreverse) then res[*, *, *, i+alreadyread]=reverse(reform(tmp,  jpi, jpj, varslev[varid], /over), 3) ELSE res[*, *, *, i+alreadyread]=reform(tmp,  jpi, jpj, varslev[varid], /over)
232         ENDIF ELSE BEGIN  ; direct acces
233            case varfmt of
234               'byte':a=assoc(unit, bytarr(jpi,jpj,varslev[varid],/nozero),offset)
235               'uint':a=assoc(unit,uintarr(jpi,jpj,varslev[varid],/nozero),offset)
236               'int':a=assoc(unit,  intarr(jpi,jpj,varslev[varid],/nozero),offset)
237               'long':a=assoc(unit, lonarr(jpi,jpj,varslev[varid],/nozero),offset)
238               'float':a=assoc(unit,fltarr(jpi,jpj,varslev[varid],/nozero),offset)
239            endcase
240            if keyword_set(key_zreverse) then res[*, *, *, i+alreadyread]=reverse(a[0], 3) ELSE res[*, *, *, i+alreadyread]=a[0]
241         ENDELSE
242      ENDELSE
243   endfor
244;------------------------
245; close the file
246   free_lun,unit
247   close,unit
248;------------------------
249;------------------------
250; do we need to read a new file to complete the time series ?
251;------------------------
252;------------------------
253   if jpt2read1file NE jpt2read then BEGIN
254      indf2read = indf2read+1
255      startread = 0
256      alreadyread = alreadyread+jpt2read1file
257      jpt2read = jpt2read-jpt2read1file
258      GOTO, readagain
259   ENDIF
260;------------------------
261;------------------------
262; post processing
263;------------------------
264;------------------------
265   if keyword_set(key_yreverse) then res = reverse(res, 2)
266   if keyword_set(key_shift) then begin
267      case (size(res))[0] of
268         2:res = shift(res, key_shift, 0)
269         3:res = shift(res, key_shift, 0, 0)
270         4:res = shift(res, key_shift, 0, 0, 0)
271      endcase
272   endif
273;------------------------
274;   mask
275;   IF varslev[varid] EQ 1 then begin
276;      if abs(valmask) LE 1e5 then notgood = where(res[*, *, 0] EQ valmask) $
277;      ELSE notgood = where(abs(res[*, *, 0]) GE abs(valmask)/10)
278;      if notgood[0] NE -1 then tmask[notgood] = 0b
279;   ENDIF ELSE BEGIN
280;      if abs(valmask) LE 1e5 then notgood = where(res[*, *, *, 0] EQ valmask) $
281;      ELSE notgood = where(abs(res[*, *, *, 0]) GE abs(valmask)/10)
282;      if notgood[0] NE -1 then tmask[notgood] = 0b
283;   ENDELSE
284   if abs(valmask) LE 1e5 then notgood = where(res EQ valmask) $
285   ELSE notgood = where(abs(res) GE abs(valmask)/10)
286   if notgood[0] NE -1 THEN res[notgood] = !values.f_nan
287;   valmask = 1e20
288;   if abs(valmask) LE 1e5 then notgood = where(res EQ valmask) $
289;   ELSE notgood = where(abs(res) GE abs(valmask)/10)
290;   if notgood[0] NE -1 THEN res[notgood] = 1e20
291;   valmask = 1e20
292   triangles_list = triangule()
293;------------------------
294; subdomain extration
295
296;------------------------
297; time aguments
298;------------------------
299   time = time[t1:t2]
300   jpt = t2-t1+1
301   if keyword_set(timestep) then vardate = strtrim(time[0], 2) $
302   ELSE vardate = date2string(vairdate(time[0]))
303;------------------------
304   @updateold
305;------------------------
306
307   return, res
308end
Note: See TracBrowser for help on using the repository browser.