VIRCAM Pipeline  1.3.4
vircam_nebuliser.c
1 /* $Id: vircam_nebuliser.c,v 1.1 2013-10-15 16:30:37 jim Exp $
2  *
3  * This file is part of the VIRCAM Pipeline
4  * Copyright (C) 2005 Cambridge Astronomy Survey Unit
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19  */
20 
21 /*
22  * $Author: jim $
23  * $Date: 2013-10-15 16:30:37 $
24  * $Revision: 1.1 $
25  * $Name: not supported by cvs2svn $
26  */
27 
28 /* Includes */
29 
30 #ifdef HAVE_CONFIG_H
31 #include <config.h>
32 #endif
33 
34 #include <cpl.h>
35 #include "vircam_mods.h"
36 #include "vircam_utils.h"
37 #include "vircam_fits.h"
38 #include "vircam_stats.h"
39 
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <string.h>
43 #include <math.h>
44 
45 #define MEDIANCALC 1
46 #define MEANCALC 2
47 
48 static float sum;
49 static float sumw;
50 static int naver;
51 static float nextw;
52 static float lastw;
53 static float nextval;
54 static float lastval;
55 static short int nextc;
56 static short int lastc;
57 
58 static void twodfilt(float *data, unsigned char *bpm, int nx, int ny,
59  int medfilt, int linfilt, int niter, int axis,
60  int twod, int takeout_sky, int inorm, int wantback,
61  float signeg, float sigpos, float **backmap);
62 static void bfilt_1d(float *data, unsigned char *bpm, int nx, int ny,
63  int filt, int stat, int axis);
64 static void bfilt_2d(float *data, unsigned char *bpmcopy, int nx, int ny,
65  int filt, int stat);
66 static void docols_2(float *data, unsigned char *bpm, float *dbuf,
67  unsigned char *bbuf, int nx, int ny, int filter,
68  int stat);
69 static void dorows_2(float *data, unsigned char *bpm, float *dbuf,
70  unsigned char *bbuf, int nx, int ny, int filter,
71  int stat);
72 extern void dostat(float *data, unsigned char *bpm, unsigned char *goodval,
73  int npts, int nfilt, int whichstat);
74 static void wraparound(float *data, unsigned char *bpm, int npts, int nfilt,
75  int whichstat, float **ybuf, unsigned char **ybbuf,
76  int *nbuf);
77 static void medavg(float *array, unsigned char *bpm, int *ipoint, int npix,
78  int whichstat, int newl, float *outval,
79  unsigned char *outbp);
80 static void quickie(float *array, unsigned char *iarray, int *iarray2,
81  int lll, int narray);
82 static void sortm(float *a1, unsigned char *a2, int *a3, int n);
83 static void plugholes(float *data, unsigned char *bpm, int nx);
84 
87 /*---------------------------------------------------------------------------*/
143 /*---------------------------------------------------------------------------*/
144 
145 extern int vircam_nebuliser(vir_fits *infile, vir_fits *inconf, int medfilt,
146  int linfilt, int niter, int axis, int twod,
147  int takeout_sky, int norm, int wantback,
148  float signeg, float sigpos, vir_fits **backmap,
149  int *status) {
150  cpl_image *im;
151  int nx,ny,i;
152  float *data,*backdata,*bdata;
153  int *cdata,npts;
154  unsigned char *bpm;
155  const char *fctid = "vircam_nebuliser";
156 
157  /* Inherited status */
158 
159  *backmap = NULL;
160  if (*status != VIR_OK)
161  return(*status);
162 
163  /* Get the data array of the input file */
164 
165  im = vircam_fits_get_image(infile);
166  nx = cpl_image_get_size_x(im);
167  ny = cpl_image_get_size_y(im);
168  data = cpl_image_get_data_float(im);
169 
170  /* Do we have a confidence map? If so then use it to create a bpm.
171  If not, then create a bpm with all zeros */
172 
173  npts = nx*ny;
174  bpm = cpl_calloc(npts,sizeof(unsigned char));
175  if (inconf != NULL) {
176  im = vircam_fits_get_image(inconf);
177  if (cpl_image_get_size_x(im) != nx || cpl_image_get_size_y(im) != ny) {
178  cpl_msg_error(fctid,"Image and conf map dimensions don't match");
179  FATAL_ERROR
180  }
181  cdata = cpl_image_get_data(im);
182  for (i = 0; i < npts; i++)
183  bpm[i] = (cdata[i] == 0);
184  }
185 
186  /* Ok do the filtering now */
187 
188  twodfilt(data,bpm,nx,ny,medfilt,linfilt,niter,axis,twod,takeout_sky,norm,
189  wantback,signeg,sigpos,&backdata);
190 
191  /* Write a header item to the data header to show that the nebulisation
192  has been successful */
193 
194  cpl_propertylist_append_bool(vircam_fits_get_ehu(infile),
195  "ESO DRS NEBULISED",1);
196  cpl_propertylist_set_comment(vircam_fits_get_ehu(infile),
197  "ESO DRS NEBULISED",
198  "Nebuliser has been used on this image");
199 
200  /* Now if we have a background image, then create the fits structure
201  for it as a copy of the input image */
202 
203  if (wantback) {
204  *backmap = vircam_fits_duplicate(infile);
205  im = vircam_fits_get_image(*backmap);
206  bdata = cpl_image_get_data_float(im);
207  memmove(bdata,backdata,npts*sizeof(float));
208  freespace(backdata);
209  }
210 
211  /* Tidy and exit */
212 
213  freespace(bpm);
214  GOOD_STATUS
215 }
216 
217 static void twodfilt(float *data, unsigned char *bpm, int nx, int ny,
218  int medfilt, int linfilt, int niter, int axis,
219  int twod, int takeout_sky, int inorm, int wantback,
220  float signeg, float sigpos, float **backmap) {
221  int i,iter,nter,nmask;
222  long nn;
223  float *buffer,*orig,*orig_sm,*work,medsky,sigsky,rescale,lthr,hthr;
224  float diff;
225  unsigned char *bpmcopy;
226 
227  /* Get some workspace. One holds a copy of the original data. The
228  others are for work */
229 
230  nn = nx*ny;
231  buffer = cpl_malloc(3*nn*sizeof(*buffer));
232  orig = buffer;
233  orig_sm = orig + nn;
234  work = orig_sm + nn;
235  memmove((char *)orig,(char *)data,nn*sizeof(*data));
236  memmove((char *)orig_sm,(char *)data,nn*sizeof(*data));
237  memmove((char *)work,(char *)data,nn*sizeof(*data));
238 
239  /* Copy the bad pixel mask, so that the pre-existing bad pixels are
240  now flagged with 1. */
241 
242  bpmcopy = cpl_calloc(nn,sizeof(*bpmcopy));
243  for (i = 0; i < nn; i++)
244  bpmcopy[i] = (bpm[i] ? 1 : 0);
245 
246  /* Do gentle smooth on the original data */
247 
248  if (niter > 1 && medfilt > 10) {
249  bfilt_1d(orig_sm,bpmcopy,nx,ny,5,MEDIANCALC,axis);
250  bfilt_1d(orig_sm,bpmcopy,nx,ny,3,MEANCALC,axis);
251  }
252 
253  /* Now do an iteration loop */
254 
255  for (iter = 1; iter <= niter; iter++) {
256  if (iter > 1)
257  memmove((char *)data,(char *)orig,nn*sizeof(*data));
258 
259  /* Filter the original input data, using the latest interation
260  on the pixel mask */
261 
262  if (! twod)
263  bfilt_1d(data,bpmcopy,nx,ny,medfilt,MEDIANCALC,axis);
264  else
265  bfilt_2d(data,bpmcopy,nx,ny,medfilt,MEDIANCALC);
266  if (iter == niter)
267  break;
268 
269  /* Look at the difference between the smoothed map and the (possibly
270  gently smoothed) original data */
271 
272  for (i = 0; i < nn; i++)
273  work[i] = orig_sm[i] - data[i];
274 
275  /* What is the median level and RMS of the residual map? We may need
276  to iterate on this */
277 
278  vircam_qmedsig(work,bpmcopy,nn,3.0,3,-1000.0,65535.0,&medsky,&sigsky);
279  rescale = 2.0;
280  nter = 0;
281  while (sigsky < 2.5 && nter < 16) {
282  nter++;
283  for (i = 0; i < nn; i++)
284  work[i] *= rescale;
285  vircam_qmedsig(work,bpmcopy,nn,3.0,3,-1000.0,65535.0,&medsky,
286  &sigsky);
287  }
288  if (nter > 0) {
289  rescale = (float)pow(2.0,(double)nter);
290  for (i = 0; i < nn; i++)
291  work[i] /= rescale;
292  medsky /= rescale;
293  sigsky /= rescale;
294  }
295  lthr = -signeg*sigsky;
296  hthr = sigpos*sigsky;
297 
298  /* Clip out discordant points */
299 
300  nmask = 0;
301  for (i = 0; i < nn; i++) {
302  if (bpmcopy[i] == 1)
303  continue;
304  diff = work[i] - medsky;
305  if (diff > hthr || diff < lthr) {
306  bpmcopy[i] = 2;
307  nmask++;
308  } else {
309  bpmcopy[i] = 0;
310  }
311  }
312  }
313 
314  /* Now do the linear filter */
315 
316  if (! twod)
317  bfilt_1d(data,bpm,nx,ny,linfilt,MEANCALC,axis);
318  else
319  bfilt_2d(data,bpm,nx,ny,linfilt,MEANCALC);
320 
321  /* Get the sky level if you want to keep it */
322 
323  if (! takeout_sky)
324  vircam_qmedsig(orig,bpmcopy,nn,3.0,3,-1000.0,65535.0,&medsky,&sigsky);
325  else
326  medsky = 0.0;
327 
328  /* Do we want a background map */
329 
330  if (wantback) {
331  *backmap = cpl_malloc(nn*sizeof(**backmap));
332  for (i = 0; i < nn; i++)
333  (*backmap)[i] = data[i];
334  } else {
335  *backmap = NULL;
336  }
337 
338  /* How do we want to normalise? */
339 
340  if (inorm == 0) {
341  for (i = 0; i < nn; i++)
342  data[i] = orig[i] - data[i] + medsky;
343  } else {
344  for (i = 0; i < nn; i++)
345  data[i] = orig[i]/max(1.0,data[i]);
346  }
347 
348  /* Tidy and exit */
349 
350  freespace(buffer);
351  freespace(bpmcopy);
352 }
353 
354 static void bfilt_1d(float *data, unsigned char *bpm, int nx, int ny,
355  int filt, int stat, int axis) {
356 
357  float *dbuf;
358  unsigned char *bbuf;
359  int nbuf;
360 
361  /* Get some workspace */
362 
363  nbuf = max(nx,ny);
364  dbuf = cpl_malloc(nbuf*sizeof(*dbuf));
365  bbuf = cpl_malloc(nbuf*sizeof(*bbuf));
366 
367  /* Order the reset correction so that the first smoothing is done
368  across the axis of the anomaly */
369 
370  if (axis == 1) {
371  dorows_2(data,bpm,dbuf,bbuf,nx,ny,filt,stat);
372  docols_2(data,bpm,dbuf,bbuf,nx,ny,filt,stat);
373  } else {
374  docols_2(data,bpm,dbuf,bbuf,nx,ny,filt,stat);
375  dorows_2(data,bpm,dbuf,bbuf,nx,ny,filt,stat);
376  }
377 
378  /* Ditch workspace */
379 
380  freespace(dbuf);
381  freespace(bbuf);
382 }
383 
384 static void bfilt_2d(float *data, unsigned char *bpmcopy, int nx, int ny,
385  int filt, int stat) {
386  float *dbuf,*outmap,value,*om;
387  unsigned char *outbpm,*ob;
388  int nbuf,j,i,nf2,nalloc,jj,ii,ind,ind1,j1old,j2old,i1old,i2old;
389 
390  /* Filter halfwidth */
391 
392  nf2 = filt/2;
393 
394  /* Get some workspace */
395 
396  nalloc = (2*filt+1)*(2*filt+1);
397  dbuf = cpl_malloc(nalloc*sizeof(*dbuf));
398  outmap = cpl_malloc(nx*ny*sizeof(*outmap));
399  outbpm = cpl_malloc(nx*ny*sizeof(*outbpm));
400 
401  /* Loop for each input pixel */
402 
403  for (j = 0; j < ny; j++) {
404  for (i = 0; i < nx; i++) {
405  nbuf = 0;
406  for (jj = j - nf2; jj <= j + nf2; jj++) {
407  if (jj < 0 || jj >= ny)
408  continue;
409  ind1 = jj*nx;
410  for (ii = i - nf2; ii <= i + nf2; ii++) {
411  if (ii < 0 || ii >= nx)
412  continue;
413  ind = ind1 + ii;
414  if (bpmcopy[ind])
415  continue;
416  dbuf[nbuf++] = data[ind];
417  }
418  }
419 
420  /* If we don't have enough, try and increase the window size.
421  This will only affect the edges */
422 
423  if (nbuf < filt/4) {
424  j1old = j - nf2;
425  j2old = j + nf2;
426  i1old = i - nf2;
427  i2old = i + nf2;
428  for (jj = j - filt; jj <= j + filt; jj++) {
429  if (jj < 0 || jj >= ny || (jj >= j1old && jj <= j2old))
430  continue;
431  ind1 = jj*nx;
432  for (ii = i - filt; ii <= i + filt; ii++) {
433  if (ii < 0 || ii >= nx || (ii >= i1old && ii <= i2old))
434  continue;
435  ind = ind1 + ii;
436  if (bpmcopy[ind])
437  continue;
438  dbuf[nbuf++] = data[ind];
439  }
440  }
441  }
442 
443  /* Right, assuming we have enough entries, then get a median */
444 
445  ind = j*nx + i;
446  if (nbuf > filt/4) {
447  if (stat == MEDIANCALC)
448  value = vircam_med(dbuf,NULL,(long)nbuf);
449  else
450  value = vircam_mean(dbuf,NULL,(long)nbuf);
451  outmap[ind] = value;
452  outbpm[ind] = 0;
453  } else {
454  outmap[ind] = -1000.0;
455  outbpm[ind] = 1;
456  }
457  }
458  }
459 
460  /* Right, fill in the holes and then transfer the filtered data to
461  the input array */
462 
463  for (j = 0; j < ny; j++) {
464  om = outmap + j*nx;
465  ob = outbpm + j*nx;
466  plugholes(om,ob,nx);
467  for (i = 0; i < nx; i++)
468  data[j*nx+i] = om[i];
469  }
470 
471  /* Tidy up and get out of here */
472 
473  freespace(outmap);
474  freespace(outbpm);
475  freespace(dbuf);
476  return;
477 }
478 
479 static void docols_2(float *data, unsigned char *bpm, float *dbuf,
480  unsigned char *bbuf, int nx, int ny, int filter,
481  int stat) {
482 
483  int j,k,indx,nn;
484  unsigned char *goodval,*b;
485  float *t;
486 
487  if (filter <= 0)
488  return;
489 
490  goodval = cpl_malloc(ny*sizeof(*goodval));
491  t = cpl_malloc(ny*sizeof(*t));
492  b = cpl_malloc(ny*sizeof(*b));
493  for (k = 0; k < nx; k++) {
494  memset((char *)goodval,0,ny);
495  nn = 0;
496  for (j = 0; j < ny; j++) {
497  indx = j*nx + k;
498  if (bpm[indx] == 0) {
499  dbuf[nn] = data[indx];
500  bbuf[nn++] = 0;
501  }
502  }
503  dostat(dbuf,bbuf,goodval,nn,filter,stat);
504  nn = 0;
505  for (j = 0; j < ny; j++) {
506  indx = j*nx + k;
507  if (bpm[indx] == 0) {
508  t[j] = dbuf[nn++];
509  b[j] = 0;
510  } else {
511  t[j] = -999.0;
512  b[j] = 1;
513  }
514  }
515  plugholes(t,b,ny);
516  nn = 0;
517  for (j = 0; j < ny; j++) {
518  indx = j*nx + k;
519  data[indx] = t[j];
520  }
521  }
522  freespace(goodval);
523  freespace(t);
524  freespace(b);
525 }
526 
527 static void dorows_2(float *data, unsigned char *bpm, float *dbuf,
528  unsigned char *bbuf, int nx, int ny, int filter,
529  int stat) {
530 
531  int j,k,indx,nn;
532  unsigned char *goodval,*b;
533  float *t;
534 
535  if (filter <= 0)
536  return;
537 
538  goodval = cpl_malloc(nx*sizeof(*goodval));
539  t = cpl_malloc(nx*sizeof(*t));
540  b = cpl_malloc(nx*sizeof(*b));
541  for (k = 0; k < ny; k++) {
542  memset((char *)goodval,0,nx);
543  nn = 0;
544  for (j = 0; j < nx; j++) {
545  indx = k*nx + j;
546  if (bpm[indx])
547  continue;
548  dbuf[nn] = data[indx];
549  bbuf[nn++] = 0;
550  }
551  dostat(dbuf,bbuf,goodval,nn,filter,stat);
552  nn = 0;
553  for (j = 0; j < nx; j++) {
554  indx = k*nx + j;
555  if (bpm[indx] == 0) {
556  t[j] = dbuf[nn++];
557  b[j] = 0;
558  } else {
559  t[j] = -999.0;
560  b[j] = 1;
561  }
562  }
563  plugholes(t,b,nx);
564  for (j = 0; j < nx; j++) {
565  indx = k*nx + j;
566  data[indx] = t[j];
567  }
568  }
569  freespace(goodval);
570  freespace(t);
571  freespace(b);
572 }
573 
574 extern void dostat(float *data, unsigned char *bpm, unsigned char *goodval,
575  int npts, int nfilt, int whichstat) {
576  int nbuf,jl,jh,j,*ipoint,ifree,i;
577  unsigned char *ybbuf,*barray,bval;
578  float *ybuf,*darray,val;
579 
580  /* Check to make sure there are some points in the array... */
581 
582  if (npts < nfilt || npts < 10)
583  return;
584 
585  /* Check to make sure the filter size is odd */
586 
587  if ((nfilt/2)*2 == nfilt)
588  nfilt++;
589 
590  /* Do the wrap around and load the data into an oversized array*/
591 
592  wraparound(data,bpm,npts,nfilt,whichstat,&ybuf,&ybbuf,&nbuf);
593 
594  /* Start doing the filtering...*/
595 
596  darray = cpl_malloc(nfilt*sizeof(*darray));
597  barray = cpl_malloc(nfilt*sizeof(*barray));
598  ipoint = cpl_malloc(nfilt*sizeof(*ipoint));
599  memmove((char *)darray,(char *)ybuf,nfilt*sizeof(*ybuf));
600  memmove((char *)barray,(char *)ybbuf,nfilt*sizeof(*ybbuf));
601  for (j = 0; j < nfilt; j++)
602  ipoint[j] = j;
603  ifree = 0;
604  medavg(darray,barray,ipoint,nfilt,whichstat,-1,&val,&bval);
605  if (! bval)
606  data[0] = val;
607  goodval[0] = bval;
608  jl = nfilt;
609  jh = nfilt + npts - 2;
610  for (j = jl; j <= jh; j++) {
611  for (i = 0; i < nfilt; i++) {
612  if (ipoint[i] == 0) {
613  ifree = i;
614  ipoint[i] = nfilt - 1;
615  lastval = darray[ifree];
616  lastw = 0.0;
617  lastc = 0;
618  if (barray[ifree] == 0) {
619  lastw = 1.0;
620  lastc = 1;
621  }
622  darray[ifree] = ybuf[j];
623  barray[ifree] = ybbuf[j];
624  nextval = darray[ifree];
625  nextw = 0.0;
626  nextc = 0;
627  if (barray[ifree] == 0) {
628  nextw = 1.0;
629  nextc = 1;
630  }
631  } else
632  ipoint[i]--;
633  }
634  medavg(darray,barray,ipoint,nfilt,whichstat,ifree,&val,&bval);
635  if (! bval)
636  data[j-jl+1] = val;
637  goodval[j-jl+1] = bval;
638  }
639 
640  /* Ditch workspace */
641 
642  freespace(darray);
643  freespace(barray);
644  freespace(ipoint);
645  freespace(ybuf);
646  freespace(ybbuf);
647 }
648 
649 static void wraparound(float *data, unsigned char *bpm, int npts, int nfilt,
650  int whichstat, float **ybuf, unsigned char **ybbuf,
651  int *nbuf) {
652 
653  float *darray,xmns,xmnf;
654  int i1,ilow,i,*ipoint;
655  unsigned char *barray,bxmns,bxmnf;
656 
657  /* Do some padding at the edges */
658 
659  i1 = nfilt/2;
660  ilow = max(3,nfilt/4);
661  ilow = (ilow/2)*2 + 1;
662 
663  /* Get some workspace */
664 
665  darray = cpl_malloc(nfilt*sizeof(*darray));
666  barray = cpl_malloc(nfilt*sizeof(*barray));
667  ipoint = cpl_calloc(nfilt,sizeof(*ipoint));
668  *nbuf = npts + 2*i1;
669  *ybuf = cpl_malloc(*nbuf*sizeof(float));
670  *ybbuf = cpl_malloc(*nbuf*sizeof(unsigned char));
671 
672  /* Do the wrap around.*/
673 
674  memmove((char *)darray,(char *)data,ilow*sizeof(*data));
675  memmove((char *)barray,(char *)bpm,ilow*sizeof(*bpm));
676  medavg(darray,barray,ipoint,ilow,whichstat,-1,&xmns,&bxmns);
677  memmove((char *)darray,(char *)(data+npts-ilow),ilow*sizeof(*data));
678  memmove((char *)barray,(char *)(bpm+npts-ilow),ilow*sizeof(*bpm));
679  medavg(darray,barray,ipoint,ilow,whichstat,-1,&xmnf,&bxmnf);
680  for (i=0; i < i1; i++) {
681  if (! bxmns) {
682  (*ybuf)[i] = 2.0*xmns - data[i1+ilow-i-1];
683  (*ybbuf)[i] = bpm[i1+ilow-i-1];
684  } else {
685  (*ybuf)[i] = data[i1+ilow-i-1];
686  (*ybbuf)[i] = 1;
687  }
688  if (! bxmnf) {
689  (*ybuf)[npts+i1+i] = 2.0*xmnf - data[npts-i-ilow-1];
690  (*ybbuf)[npts+i1+i] = bpm[npts-i-ilow-1];
691  } else {
692  (*ybuf)[npts+i1+i] = data[npts-i-ilow-1];
693  (*ybbuf)[npts+i1+i] = 1;
694  }
695  }
696 
697  /* Now place the full line into the buffer */
698 
699  memmove((char *)(*ybuf+i1),data,npts*sizeof(*data));
700  memmove((char *)(*ybbuf+i1),bpm,npts*sizeof(*bpm));
701 
702  /* Free workspace */
703 
704  freespace(darray);
705  freespace(barray);
706  freespace(ipoint);
707 }
708 
709 static void medavg(float *array, unsigned char *bpm, int *ipoint, int npix,
710  int whichstat, int newl, float *outval,
711  unsigned char *outbp) {
712 
713  float *buf = NULL;
714  int m,i;
715 
716  /* If there is a new element and that new element is bad, then
717  the buffer is already sorted from last time (just one element
718  sorter */
719 
720  m = 0;
721  if (whichstat == MEDIANCALC) {
722  if (newl == -1)
723  sortm(array,bpm,ipoint,npix);
724  else
725  quickie(array,bpm,ipoint,newl,npix);
726 
727  /* Get some workspace */
728 
729  buf = cpl_malloc(npix*sizeof(*buf));
730 
731  /* Now put everything that's good in the buffer */
732 
733  m = 0;
734  for (i = 0; i < npix; i++) {
735  if (bpm[i] == 0) {
736  buf[m] = array[i];
737  m++;
738  }
739  }
740  } else if (whichstat == MEANCALC) {
741  if (newl == -1) {
742  sum = 0.0;
743  sumw = 0.0;
744  naver = 0;
745  for (i = 0; i < npix; i++) {
746  if (bpm[i] == 0) {
747  sum += array[i];
748  sumw += 1.0;
749  naver += 1;
750  }
751  }
752  m = naver;
753  } else {
754  sum += (nextw*nextval - lastw*lastval);
755  sumw += (nextw - lastw);
756  naver += (nextc - lastc);
757  m = naver;
758  }
759  }
760 
761  /* If they were all bad, then send a null result back */
762 
763  if (m == 0) {
764  *outval = 0.0;
765  *outbp = 1;
766  if (whichstat == MEDIANCALC)
767  freespace(buf);
768 
769  /* Otherwise calculate the relevant stat */
770 
771  } else {
772  if (whichstat == MEDIANCALC) {
773  *outval = buf[m/2];
774  freespace(buf);
775  } else if (whichstat == MEANCALC)
776  *outval = sum/sumw;
777  *outbp = 0;
778  }
779 }
780 
781 static void quickie(float *array, unsigned char *iarray, int *iarray2,
782  int lll, int narray) {
783 
784  float test;
785  int i,j,npt,it2;
786  unsigned char it;
787 
788  test = array[lll];
789  it = iarray[lll];
790  it2 = iarray2[lll];
791  j = -1;
792  for (i = 0; i < narray; i++) {
793  if (i != lll && test <= array[i]) {
794  j = i;
795  break;
796  }
797  }
798  if (j == -1)
799  j = narray;
800  if (j - 1 == lll)
801  return;
802 
803  if (j - lll < 0) {
804  npt = lll - j;
805  for (i = 0; i < npt; i++) {
806  array[lll-i] = array[lll-i-1];
807  iarray[lll-i] = iarray[lll-i-1];
808  iarray2[lll-i] = iarray2[lll-i-1];
809  }
810  array[j] = test;
811  iarray[j] = it;
812  iarray2[j] = it2;
813  } else {
814  j--;
815  npt = j - lll;
816  if (npt != 0) {
817  for (i = 0; i < npt; i++) {
818  array[lll+i] = array[lll+i+1];
819  iarray[lll+i] = iarray[lll+i+1];
820  iarray2[lll+i] = iarray2[lll+i+1];
821  }
822  }
823  array[j] = test;
824  iarray[j] = it;
825  iarray2[j] = it2;
826  }
827 }
828 
829 static void sortm(float *a1, unsigned char *a2, int *a3, int n) {
830  int iii,ii,i,ifin,j,b3;
831  unsigned char b2;
832  float b1;
833 
834  iii = 4;
835  while (iii < n)
836  iii *= 2;
837  iii = min(n,(3*iii)/4 - 1);
838 
839  while (iii > 1) {
840  iii /= 2;
841  ifin = n - iii;
842  for (ii = 0; ii < ifin; ii++) {
843  i = ii;
844  j = i + iii;
845  if (a1[i] > a1[j]) {
846  b1 = a1[j];
847  b2 = a2[j];
848  b3 = a3[j];
849  while (1) {
850  a1[j] = a1[i];
851  a2[j] = a2[i];
852  a3[j] = a3[i];
853  j = i;
854  i = i - iii;
855  if (i < 0 || a1[i] <= b1)
856  break;
857  }
858  a1[j] = b1;
859  a2[j] = b2;
860  a3[j] = b3;
861  }
862  }
863  }
864 }
865 
866 static void plugholes(float *data, unsigned char *bpm, int nx) {
867  int i,ifirst,ilast,i1,i2,j;
868  float nc,d1,d2,t1,t2,slope;
869 
870  /* First of all, find the first good value in the array */
871 
872  i = 0;
873  while (i < nx && bpm[i] != 0)
874  i++;
875  ifirst = i;
876 
877  /* If all the values in the array are bad, then do nothing */
878 
879  if (ifirst == nx)
880  return;
881 
882  /* Find the last good value in the array */
883 
884  i = nx - 1;
885  while (i >= 0 && bpm[i] != 0)
886  i--;
887  ilast = i;
888 
889  /* Right, now start from the first good value and fill in any holes in the
890  middle part of the array */
891 
892  i = ifirst;
893  while (i <= ilast) {
894  if (bpm[i] == 0) {
895  i++;
896  continue;
897  }
898  i1 = i - 1;
899  while (bpm[i] != 0)
900  i++;
901  i2 = i;
902  nc = (float)(i2 - i1 + 1);
903  d1 = data[i1];
904  d2 = data[i2];
905  for (j = i1+1; j <= i2-1; j++) {
906  t1 = 1.0 - (float)(j - i1)/nc;
907  t2 = 1.0 - t1;
908  data[j] = t1*d1 + t2*d2;
909  }
910  }
911 
912  /* Now the left bit... */
913 
914  if (ifirst > 0) {
915  slope = data[ifirst+1] - data[ifirst];
916  for (j = 0; j < ifirst; j++)
917  data[j] = slope*(float)(j - ifirst) + data[ifirst];
918  }
919 
920  /* Now the right bit... */
921 
922  if (ilast < nx - 1) {
923  slope = data[ilast] - data[ilast-1];
924  for (j = ilast; j < nx; j++)
925  data[j] = slope*(float)(j - ilast) + data[ilast];
926  }
927 }
928 
931 /*
932 
933 $Log: not supported by cvs2svn $
934 
935 */
void vircam_qmedsig(float *data, unsigned char *bpm, long npts, float thresh, int niter, float lowv, float highv, float *median, float *sigma)
Definition: vircam_stats.c:542
float vircam_mean(float *data, unsigned char *bpm, long npts)
Definition: vircam_stats.c:246
int vircam_nebuliser(vir_fits *infile, vir_fits *inconf, int medfilt, int linfilt, int niter, int axis, int twod, int takeout_sky, int norm, int wantback, float signeg, float sigpos, vir_fits **backmap, int *status)
Remove small scale background variations.
cpl_image * vircam_fits_get_image(vir_fits *p)
Definition: vircam_fits.c:349
vir_fits * vircam_fits_duplicate(vir_fits *in)
Definition: vircam_fits.c:159
float vircam_med(float *data, unsigned char *bpm, long npts)
Definition: vircam_stats.c:89
cpl_propertylist * vircam_fits_get_ehu(vir_fits *p)
Definition: vircam_fits.c:457