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

Last change on this file since 378 was 371, checked in by pinsard, 16 years ago

improvements of headers (alignments of IDL prompt in examples)

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