OB.DAAC Logo
NASA Logo
Ocean Color Science Software

ocssw V2022
fill_smooth.c
Go to the documentation of this file.
1 /* hope we don't need this
2 #include "ancil.h"
3 #include "no2_avg.h"
4  */
5 #include <math.h>
6 #include <stdlib.h>
7 #include <stdio.h>
8 #include "ancil.h"
9 #include "o3_toms.h"
10 
11 int fill_smooth(int16_t *arr, char *arrqc, int32_t npix, int32_t nlin)
12 /*******************************************************************
13 
14  fill_smooth
15 
16  purpose: make the ozone fill seamlessly join to the day's data
17  Don't extend data beyond what was filed already
18 
19  Returns type: 0 if all went well, else 1
20 
21  Parameters: (in calling order)
22  Type Name I/O Description
23  ---- ---- --- -----------
24  int16 * arr I/O input array
25  char * arrqc I QC values assigned in
26  o3_toms: 0 good data, 1 - 19
27  fill data, 20 bad = data = 0
28  int32 npix I # pixels in the input array
29  int32 nlin I # lines in the input array
30 
31  Modification history:
32  Programmer Date Description of change
33  ---------- ---- ---------------------
34  W. Robinson 12 Dec 2013 Original development
35 
36  *******************************************************************/
37  {
38  int32_t ntot, iv;
39  float *lcl_data, *wt;
40  char *lcl_qc;
41  /*
42  * we will apply field_extend to the good data using a distance of 5
43  * pixels and then weight it in to the fill made before
44  */
45  /*
46  * allocate space to work in and transfer the good array values to a float
47  * array and make a qc array for use in field_extend
48  */
49  ntot = npix * nlin;
50  if (((lcl_data = (float *) malloc(ntot * sizeof ( float))) == NULL)
51  || ((lcl_qc = (char *) malloc(ntot * sizeof ( char))) == NULL)
52  || ((wt = (float *) malloc(npix * nlin * sizeof ( float))) == NULL)) {
53  printf("%s, %d E: unable to allocate local data storage\n",
54  __FILE__, __LINE__);
55  return 1;
56  }
57 
58  for (iv = 0; iv < ntot; iv++) {
59  *(lcl_data + iv) = 0.;
60  *(lcl_qc + iv) = 10;
61  if (*(arrqc + iv) == 0) {
62  *(lcl_data + iv) = (float) *(arr + iv);
63  *(lcl_qc + iv) = 0;
64  }
65  }
66  /*
67  * use field_extend to extend the local data and qc
68  */
69  if (field_extend(lcl_data, lcl_qc, npix, nlin, 7, wt) != 0)
70  return 1;
71  /*
72  * Now, go back and update the grid array
73  */
74  for (iv = 0; iv < ntot; iv++) {
75  /* if lcl_qc is 0 or unchanged, leave the input data alone */
76  /* if lcl_qc is 10, no weighting gets applied here either and no change */
77  /* in the field extend region that has fill, we combine the extended
78  field weighted by the weight with the fill field weighted by
79  1 - weight */
80  if ((*(lcl_qc + iv) == 1) && (*(arrqc + iv) != 20)) {
81  *(arr + iv) = *(wt + iv) * *(lcl_data + iv) +
82  (1. - *(wt + iv)) * (float) *(arr + iv);
83  }
84  }
85  /*
86  * free the space allocated for work and return
87  */
88  free(lcl_data);
89  free(lcl_qc);
90  free(wt);
91 
92  return 0;
93 }
94 
95 int field_extend(float *grid, char *flags, int np_grid, int nl_grid,
96  int max_extend, float* weights)
97 /*******************************************************************
98 
99  field_extend
100 
101  purpose: extens a field of data beyond its limits
102 
103  Returns type: int - 0 if good
104 
105  Parameters: (in calling order)
106  Type Name I/O Description
107  ---- ---- --- -----------
108  float * grid I/O earth covering grid containing
109  the data field which will be
110  extended
111  char * flags I/O state of grid points in grid:
112  0 - data there, 1 - fill
113  (extended) data
114  10 - no data
115  On input, expect only 0 or 1
116  int np_grid I # pixels in grid
117  int nl_grid I # lines in grid
118  int max_extend I maximum extent of the field
119  float * weights O array of weights - linearly
120  decreasing from 1 to 0 at
121  max_extend
122 
123  Modification history:
124  Programmer Date Description of change
125  ---------- ---- ---------------------
126  W. Robinson 17-Mar-2008 Original development
127  W. Robinson, SAIC 21 Jun 2013 re-think algorithm some and adopt
128  same flag meaning as elsewhere in no2_avg
129 
130  *******************************************************************/ {
131  float wt_shell, *ker, wt, sum, dist, r1, r2;
132  int ishell, ker_np, ker_nl, ker_cp, ker_cl, ln_grid, px_grid,
133  ker_lin, ker_pix, tl_grid, tp_grid, n_shell;
134  /*
135  * fill the adjacent pixels to those already filled out to the
136  * specified distance of max_extend
137  */
138  printf("%s: extending field with distance of %d\n", __FILE__, max_extend);
139  ishell = 0;
140  do {
141  /* set the shell's weight in units of 1 / ( max_extend + 1 ) */
142  wt_shell = (float) (max_extend - ishell) / (float) (max_extend + 1);
143  /*
144  * new distance scheme with one distance of radius at start and another
145  * at the end just linearly expanding (r2 should be at least larger
146  * than max_extend or else it could have no data to use
147  */
148  r1 = 5.;
149  r2 = max_extend * 2.0;
150  dist = r1 + (float) ishell * (r2 - r1) / (float) max_extend;
151  /*
152  printf( "%s, %d, Shell %d of %d, wt: %f, dist: %f\n", __FILE__, __LINE__,
153  ishell, max_extend, wt_shell, dist );
154  */
155  /*
156  * create an averaging kernel with radius dist and value 1
157  */
158  if (mk_ker(dist, &ker, &ker_np, &ker_nl, &ker_cp, &ker_cl) != 0)
159  return 1;
160  n_shell = 0;
161  /*
162  printf( "wt_shell = %f, dist = %f, ker_np = %d, ker_nl = %d, ker_cp = %d, ker_cl = %d\n", wt_shell, dist, ker_np, ker_nl, ker_cp, ker_cl );
163  */
164  /*
165  * get the kernel weighted average of the original field and assign
166  * the weight
167  */
168  for (ln_grid = 0; ln_grid < nl_grid; ln_grid++) {
169  for (px_grid = 0; px_grid < np_grid; px_grid++) {
170  /*
171  * process at each grid point
172  */
173  if (*(flags + ln_grid * np_grid + px_grid) != 10) {
174  /*
175  * for filled already, just set the weights to 1
176  */
177  if (ishell == 0)
178  *(weights + ln_grid * np_grid + px_grid) = 1.;
179  } else /* for a point to extend into */ {
180  /*
181  * make sure only pixels in the next shell out are considered
182  * (ie, an adjacent pixel has data)
183  */
184  wt = 0.;
185  for (ker_lin = -1; ker_lin < 2; ker_lin++) {
186  tl_grid = ln_grid + ker_lin;
187  if ((tl_grid >= 0) && (tl_grid < nl_grid)) {
188  for (ker_pix = -1; ker_pix < 2; ker_pix++) {
189  tp_grid = px_grid + ker_pix;
190  if (tp_grid < 0)
191  tp_grid = tp_grid + np_grid;
192  else if (tp_grid >= np_grid)
193  tp_grid = tp_grid - np_grid;
194  if (*(flags + tl_grid * np_grid + tp_grid) <= 1)
195  wt = 1.;
196  }
197  }
198  }
199  /*
200  * The following pixels will be in the next shell
201  */
202  if (wt == 1.) {
203  /*
204  * for unfilled, accumulate the weight and sum for the grid point
205  */
206  wt = 0;
207  sum = 0.;
208  for (ker_lin = 0; ker_lin < ker_nl; ker_lin++) {
209  /*
210  * get the grid line at the start kernel line and
211  * only compute if the line is in the grid
212  */
213  tl_grid = ln_grid + ker_lin - ker_cl;
214  if ((tl_grid >= 0) && (tl_grid < nl_grid)) {
215  for (ker_pix = 0; ker_pix < ker_np; ker_pix++) {
216  /* only do where the kernel is > 0 */
217  if (*(ker + ker_lin * ker_np + ker_pix) > 0.) {
218  /*
219  * wrap the pixel around
220  */
221  tp_grid = px_grid + ker_pix - ker_cp;
222  if (tp_grid < 0)
223  tp_grid = tp_grid + np_grid;
224  else if (tp_grid >= np_grid)
225  tp_grid = tp_grid - np_grid;
226  /* */
227  if (*(flags + tl_grid * np_grid + tp_grid) == 0) {
228  wt += *(ker + ker_lin * ker_np + ker_pix);
229  sum += *(grid + tl_grid * np_grid + tp_grid);
230  }
231  }
232  } /* end of kernel pixel loop */
233  }
234  } /* end of kernel line loop */
235  }
236  /*
237  * get the extended value
238  */
239  if (wt > 0.) {
240  *(grid + ln_grid * np_grid + px_grid) = sum / wt;
241  *(flags + ln_grid * np_grid + px_grid) = 2;
242  *(weights + ln_grid * np_grid + px_grid) = wt_shell;
243  n_shell++;
244  }
245  }
246  } /* end grid pixels */
247  } /* end grid lines */
248  free(ker);
249  /*
250  * Note that I set the flags for the new shell to 2 to avoid detecting
251  * the shell as a previous shell. Now the shell is done, set flag 2 -> 1
252  */
253  for (px_grid = 0; px_grid < (np_grid * nl_grid); px_grid++)
254  if (*(flags + px_grid) == 2)
255  *(flags + px_grid) = 1;
256  ishell++;
257  /* printf( "n_shell = %d\n", n_shell ); */
258  } while ((ishell < max_extend) && (n_shell > 0)); /* end shell loop */
259  /*
260  * return the extended field and the weights
261  */
262  return 0;
263 }
264 
265 int mk_ker(float dist, float **ker, int *ker_np, int *ker_nl,
266  int *ker_cp, int *ker_cl)
267 /*******************************************************************
268  mk_ker
269 
270  purpose: create a weighting kernel of a flat value of 1.
271 
272  Returns type: int - 0 if good
273 
274  Parameters: (in calling order)
275  Type Name I/O Description
276  ---- ---- --- -----------
277  float dist I maximum distance of influence
278  of the averaging kernel
279  float ** ker I/O kernel with weights
280  (pass in pointer to space)
281  int * ker_np O # pixels in kernel
282  int * ker_nl O # lines in kernel
283  int * ker_cp O center pixel of kernel
284  int * ker_cl O center line of kernel
285 
286  Modification history:
287  Programmer Date Description of change
288  ---------- ---- ---------------------
289  W. Robinson 17-Mar-2008 Original development
290 
291  *******************************************************************/ {
292  int il, ip, n_out, iret = 0;
293  float rad;
294  /*
295  */
296  n_out = (int) (dist + 1.);
297  *ker_np = 2 * n_out + 1;
298  *ker_nl = *ker_np;
299  *ker_cp = n_out;
300  *ker_cl = *ker_cp;
301  /*
302  * create the kernel array
303  * it will just be a flat weight of 1 and with a circular edge
304  */
305  if ((*ker = (float *) malloc(*ker_np * *ker_nl * sizeof (float))) == NULL) {
306  printf("%s: unable to allocate storage for ker\n", __FILE__);
307  iret = 1;
308  } else {
309  for (il = 0; il < *ker_nl; il++) {
310  for (ip = 0; ip < *ker_np; ip++) {
311  rad = sqrt(pow((float) (*ker_cl - il), 2) +
312  pow((float) (*ker_cp - ip), 2));
313  *(*ker + il * *ker_np + ip) = (rad < dist) ? 1. : 0.;
314  }
315  }
316  }
317  return iret;
318 }
#define NULL
Definition: decode_rs.h:63
int mk_ker(float dist, float **ker, int *ker_np, int *ker_nl, int *ker_cp, int *ker_cl)
Definition: fill_smooth.c:265
int field_extend(float *grid, char *flags, int np_grid, int nl_grid, int max_extend, float *weights)
Definition: fill_smooth.c:95
int nlin
Definition: get_cmp.c:28
int fill_smooth(int16_t *arr, char *arrqc, int32_t npix, int32_t nlin)
Definition: fill_smooth.c:11
flags
Definition: DDAlgorithm.h:22
int npix
Definition: get_cmp.c:27