source: trunk/SRC/Interpolation/extrapolate.pro @ 271

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

bugfix for interpolation from ORCA2 without mask

  • Property svn:keywords set to Id
File size: 6.3 KB
Line 
1;+
2;
3; @file_comments
4; extrapolate data (zinput) where maskinput equal 0 by filling step by
5; step the coastline points with the mean value of the 8 neighbourgs
6; (weighted by their mask value).
7;
8; @categories
9; Interpolation
10;
11; @param zinput {in}{required}{type=2d array}
12; data to be extrapolate
13;
14; @param maskinput {in}{required}{type=2d array or -1}
15; a 2D array, the land-sea mask of the output data (1 on ocean, 0 on land)
16; put -1 if input data are not masked
17;
18; @param nb_iteration {in}{optional}{type=integer}{default=large enough to fill everything}
19; Maximum number of iterations done in the extrapolation process. If there
20; is no more masked values we exit extrapolate before reaching nb_iteration
21;
22; @keyword X_PERIODIC {type=scalar, 0 or 1}{default=0}
23; put 1 to specify that the data are periodic along x axis
24;
25; @keyword MINVAL {type=scalar}{default=not used}
26; to specify a minimum value to the extrapolated values
27;
28; @keyword MAXVAL {type=scalar}{default=not used}
29; to specify a maximum value to the extrapolated values
30;
31; @keyword GE0 {type=scalar 0 or 1}{default=0}
32; put 1 to force the extrapolated values to be larger than 0, same as using minval=0.
33;
34; @keyword
35; _EXTRA to be able to call extrapolate with _extra keyword
36;
37; @returns
38; the extrapolated 2d array
39;
40; @examples
41; IDL> a=extrapolate(dist(jpi,jpj),tmask[*,*,0],/x_periodic)
42; IDL> tvplus, a
43; IDL> tvplus, a*(1-tmask[*,*,0])
44; get the coastline:
45; IDL> a=extrapolate(tmask[*,*,0],tmask[*,*,0],1,/x_periodic)
46; IDL> tvplus, a-tmask[*,*,0]
47;
48; @history
49;  Originaly written by G. Roulet
50;  Sebastien Masson (smasson\@lodyc.jussieu.fr)
51;
52; @version
53; $Id$
54;
55;-
56;
57FUNCTION extrapolate, zinput, maskinput, nb_iteration, X_PERIODIC = x_periodic $
58                      , MINVAL = minval, MAXVAL = maxval, GE0 = ge0, _EXTRA = ex
59;
60  compile_opt idl2, strictarrsubs
61;
62; check the number of iteration used in the extrapolation.
63  szin = size(zinput)
64  IF szin[0] NE 2 THEN return, -1. ELSE szin = szin[1:2]
65  nx = szin[0]
66  ny = szin[1]
67  IF n_elements(nb_iteration) EQ 0 THEN nb_iteration = max(szin)
68  IF nb_iteration EQ 0 THEN return, zinput
69; take care of the boundary conditions...
70;
71; for the x direction, we put 2 additional columns at the left and
72; right side of the array.
73; for the y direction, we put 2 additional lines at the bottom and
74; top side of the array.
75; These changes allow us to use shift function without taking care of
76; the x and y periodicity.
77;
78  ztmp = bytarr(nx+2, ny+2)
79  IF n_elements(maskinput) EQ 1 AND maskinput[0] EQ -1 THEN maskinput = replicate(1b, nx, ny)
80  IF n_elements(maskinput) NE nx*ny THEN BEGIN
81    ras = report('input grid mask do not have the good size')
82    return, -1
83  ENDIF
84  ztmp[1:nx, 1:ny] = byte(maskinput)
85  msk = temporary(ztmp)
86;
87  ztmp = replicate(1.e20, nx+2, ny+2)
88  ztmp[1:nx, 1:ny] = zinput
89  if keyword_set(x_periodic) then begin
90    ztmp[0, 1:ny] = zinput[nx-1, *]
91    ztmp[nx+1, 1:ny] = zinput[0, *]
92  ENDIF
93; remove NaN points if there is some...
94  nan = where(finite(ztmp) EQ 0, cnt_nan)
95  IF cnt_nan NE 0 THEN ztmp[temporary(nan)] = 1.e20
96  z = temporary(ztmp)
97  nx2 = nx+2
98  ny2 = ny+2
99;---------------------------------------------------------------
100;---------------------------------------------------------------
101; extrapolation
102;---------------------------------------------------------------
103  sqrtinv = 1./sqrt(2)
104;
105  cnt = 1
106; When we look for the coastline, we don't want to select the
107; borderlines of the array. -> we force the value of the mask for
108; those lines.
109  msk[0, *] = 1b
110  msk[nx+1, *] = 1b
111  msk[*, 0] = 1b
112  msk[*, ny+1] = 1b
113; find the land points
114  land = where(msk EQ 0, cnt_land)
115;---------------------------------------------------------------
116  WHILE cnt LE nb_iteration AND cnt_land NE 0 DO BEGIN
117;---------------------------------------------------------------
118; find the coastline points...
119;---------------------------------------------------------------
120; Once the land points list has been found, we change back the
121; mask values for the boundary conditions.
122    msk[0, *] = 0b
123    msk[nx+1, *] = 0b
124    msk[*, 0] = 0b
125    msk[*, ny+1] = 0b
126    if keyword_set(x_periodic) then begin
127      msk[0, *] = msk[nx, *]
128      msk[nx+1, *] = msk[1, *]
129    endif
130;
131; we compute the weighted number of sea neighbourgs.
132; those 4 neighbours have a weight of 1:
133;    *
134;   *+*
135;    *
136;
137; those 4 neighbours have a weight of 1/sqrt(2):
138;
139;    * *
140;     +
141;    * *
142;
143; As we make sure that none of the land points are located on the
144; border of the array, we can compute the weight without shift
145; (faster).
146;
147    weight = msk[land+1]+msk[land-1]+msk[land+nx2]+msk[land-nx2] $
148             +sqrtinv*(msk[land+nx2+1]+msk[land+nx2-1] $
149                       +msk[land-nx2+1]+msk[land-nx2-1])
150; list all the points that have sea neighbourgs
151    ok = where(weight GT 0)
152; the coastline points
153    coast = land[ok]
154; their weighted number of sea neighbourgs.
155    weight = weight[temporary(ok)]
156;---------------------------------------------------------------
157; fill the coastline points
158;---------------------------------------------------------------
159    z = temporary(z)*msk
160;
161    zcoast = z[1+coast]+z[-1+coast]+z[nx2+coast]+z[-nx2+coast] $
162             +1./sqrt(2)*(z[nx2+1+coast]+z[nx2-1+coast] $
163                          +z[-nx2+1+coast]+z[-nx2-1+coast])
164;
165    IF keyword_set(ge0) THEN zcoast = 0. > temporary(zcoast)
166    IF n_elements(minval) NE 0 THEN zcoast = minval > temporary(zcoast)
167    IF n_elements(maxval) NE 0 THEN zcoast = temporary(zcoast) < maxval
168    z[coast] = temporary(zcoast)/temporary(weight)
169; we update the boundary conditions of z
170    if keyword_set(x_periodic) then begin
171      z[0, *] = z[nx, *]
172      z[nx+1, *] = z[1, *]
173    endif
174;---------------------------------------------------------------
175; we update the mask
176;---------------------------------------------------------------
177    msk[temporary(coast)] = 1
178;
179    cnt = cnt + 1
180; When we look for the coast line, we don't want to select the
181; borderlines of the array. -> we force the value of the mask for
182; those lines.
183    msk[0, *] = 1b
184    msk[nx+1, *] = 1b
185    msk[*, 0] = 1b
186    msk[*, ny+1] = 1b
187; find the land points
188    land = where(msk EQ 0, cnt_land)
189;
190  ENDWHILE
191;---------------------------------------------------------------
192; we return the original size of the array
193;---------------------------------------------------------------
194;
195  return, z[1:nx, 1:ny]
196END
Note: See TracBrowser for help on using the repository browser.